2012-06-11 3 views
2

RAW 소켓 프로그래밍을 사용하여 NIC에 접근하는 모든 UDP 패킷을 캡처하려고했습니다. 여기에 이상한 문제가 있습니다. 내 프로그램을 실행하는 동안 내 소켓 설명자가 자동으로 변경됩니다. 여기에 코드가 있습니다 :소켓 파일 설명자가 자동으로 변경됩니다.

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <netinet/ip.h> 
#include <netinet/udp.h> 
#include <netinet/tcp.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <errno.h> 
#include <arpa/inet.h> 

int main() { 

int sockfd = socket (PF_INET, SOCK_RAW, IPPROTO_UDP); 
if (sockfd < 0) { 
    perror ("socket failed"); 
    return -1; 
} 

char *buf = malloc (8192); 
memset (buf, 0, 8192); 
if (!buf) { 
    perror ("calloc failed\n"); 
    return -1; 
} 

int ret_recv; 
i: 
while ((ret_recv = recv (sockfd, buf, 8192, 0)) > -1) { 
    printf ("%d\n", ret_recv); 
    struct iphdr *iph = (struct iphdr *) buf; 
    //struct udphdr *udph = (struct udphdr *) (buf + sizeof (struct iphdr)); 
    struct tcphdr *tcph = (struct tcphdr *) (buf + sizeof (struct iphdr)); 
    char ip[4]; 
    printf ("source ip: %s\n", inet_ntop (AF_INET, &iph->saddr, ip, sizeof (struct sockaddr_in))); 
    printf ("dest ip: %s\n", inet_ntop (AF_INET, &iph->daddr, ip, sizeof (struct sockaddr_in))); 
    //printf ("port: %d\n", ntohs (udph->source)); 
    printf ("port: %d\n", ntohs (tcph->source)); 
} 
perror ("recv failed"); 
//goto i; 
return 0; 
} 

내 출력에는 무한 루프의 패킷 정보 인쇄 대신 단지 하나의 정보 패킷 만 인쇄됩니다. 그래서 나는 gdb를 점검했다. 나는 display sockfd을 사용했다. 소켓 호출 후 sockfd의 값은 7이었습니다. 그리고 나서 while 루프 내에서 dest ip의 printf를 실행 한 후 sockfd 값이 808988216으로 변경되었습니다. 따라서 recv가 "잘못된 파일 설명자"오류로 실패했습니다. 실제로 잘못 된 것을 찾을 수 없습니다.

char ip[4]; 
    printf ("source ip: %s\n", inet_ntop (AF_INET, &iph->saddr, ip, sizeof (struct sockaddr_in))); 

버퍼가 IP 주소의 문자열 형식을 보관 유지하는데 충분한 크기가 아닌 :

+1

valgrind를 사용하여 프로그램을 실행 했습니까? 제 생각 엔 당신이 잠시 동안 {{} 내부의 스택을 망가 뜨리고 있습니다. BTW는 ip [4] inet_ntop에서 ip [16] 이상으로 변경합니다. [INET_ADDRSTRLEN] – strkol

+1

메모리 손상이 가장 좋습니다. 포인터 연산을 확인하십시오. –

+0

게시 된 코드는 그대로 있습니다. 나는 이것이 실제 코드가 아닌 것으로 의심한다. (아마 "이것이 될 수 없다"라고 생각하는 것을 생략했을 것이다.) – cnicutar

답변

2

:-) 사전에

덕분에 여기에 버퍼 오버 플로우입니다. 또한 네 번째 인수는 사용 가능한 공간에 대해 inet_ntop()에 거짓말하며 다음과 같아야합니다.

char ip[INET_ADDRSTRLEN]; 
printf ("source ip: %s\n", inet_ntop (AF_INET, &iph->saddr, ip, sizeof ip)); 
관련 문제