2012-02-14 2 views
1

C에서 pcap 파일을 구문 분석하려고합니다. libpcap을 사용하고 싶지 않습니다. 하지만 웬일인지, 나는 할 수 없다. 내가 어떻게 이럴 수 있니?코드의 일부 오류 - libpcap

fseek(f,24,0); 
while(count<20)//reading 20 packets 
{ 
    fread(header,sizeof(struct pcap_pkthdr),1,f); 
    //after this I'm printing values header fields 
    fseek(f,ntohl(header->caplen),1); 
    count++; 
} 

출력은 libpcap의 동일하지 않습니다 : 여기 내 시도이다. 그런

답변

4

struct pcap_pkthdr입니다. pcap 파일의 패킷 헤더 형식을 정의하는 구조입니다. libpcap이나 WinPcap을 사용하여 프로그램에 제공되는 패킷 헤더의 형식을 정의하는 구조입니다. libpcap의은 /은 WinPcap 그 헤더를 판독 루틴을 제공하고 필요에 pcap_pkthdr 헤더로 변환하기 때문에

PCAP 파일 패킷 헤더의 포맷을 정의하는 구조

는 PCAP 임의의 파일을 포함에서 NOT이다. struct pcap_pkthdr과 달리, time_ttv_sec 값이 struct timeval 인 시스템 에서조차 pcap 파일의 패킷 헤더에있는 시간 소인은 32 비트 "초"필드와 32 비트 "마이크로 초"필드를 항상 갖습니다.

즉, 상기 구조는 struct pcap_sf_pkthdr 파일의 구조

struct pcap_timeval { 
    bpf_int32 tv_sec;   /* seconds */ 
    bpf_int32 tv_usec;   /* microseconds */ 
}; 


struct pcap_sf_pkthdr { 
    struct pcap_timeval ts;  /* time stamp */ 
    bpf_u_int32 caplen;   /* length of portion present */ 
    bpf_u_int32 len;   /* length this packet (off wire) */ 
}; 

의해 정의된다. 당신이 파일에서 struct pcap_sf_pkthdr을 읽으면

참고 또한이, 당신은 바이트 스왑하는 ts.tv_sec, ts.tv_usec, caplen, 그리고 것 len 파일이 누구의 바이트 순서에있는 컴퓨터에서 다른 컴퓨터에 기록 된 경우 당신이 파일을 읽고 있어요. ntohl()과 같은 간단한 코드가 이 아닌 일 경우 - 예를 들어 파일을 읽는 컴퓨터와 동일한 컴퓨터에 파일을 작성한 경우 바이트 스왑이 필요하지 않습니다.

그 일이 에 될 수 있도록하는 방법

오히려 단지 fseek()으로 스킵보다에게 파일 헤더를 읽어주십시오. 파일 헤더의 "magic number"에 0xa1b2c3d4 값이 있으면 바이트 스와핑을 수행 할 필요가 없습니다. 값이 0xd4c3b2a1이면 파일 머리글 및 struct pcap_sf_pkthdr의 값을 바이트 스왑해야합니다. PowerPC/Power Architecture 시스템이나 MIPS 시스템 또는 IBM 메인 프레임이나 같은 빅 엔디안 시스템에서 실행중인 경우 ntohl()htonl()이 아니며 바이트 스왑 일 것입니다.

모든 캡처 파일이 pcap 파일이 될 수는 없습니다. pcap-NG 파일이라면 완전히 다른 방식으로 읽어야합니다. Libpcap 1.1 및 이후 버전에서는 pcap-NG 파일을 읽는 방법을 알고 있습니다 (libpcap/WinPcap API는 모두 pcap-NG 파일을 처리 할만큼 강력하지는 않지만 예를 들어 하나의 섹션 만 포함하는 pcap-NG 파일을 처리 할 수 ​​있습니다 하나의 네트워크 어댑터의 패킷 만 있고, libpcap 1.1 이상에서 읽을 수 있습니다). 나는 unwind suggest와 마찬가지로, libpcap/WinPcap을 사용하여 캡처 파일을 읽는 것이 좋습니다. 코드를 작성하는 대신 libpcap/WinPcap을 사용하십시오.

+0

이 pcap 파일의 마법 번호를 확인했습니다. 0xa1b2c3d4가 나왔습니다. 그래서 당신의 설명에서 바이트 스왑을 할 필요가 없다는 것을 의미합니다. 그러나 첫 번째 패킷의 caplen 값을 인쇄 할 때 snaplen은 0xffff 인 반면 0x1050d300 인 것으로 나타납니다. 이것이 어떻게 가능한지? 여기서 내가 뭘 잘못하고 있니? – user1192671

+0

* 해당 * 파일의 경우 바이트 스왑 할 필요가 없습니다. 다른 파일의 경우 사용자가해야 할 수도 있습니다. caplen에 관해서, 당신은 * struct * struct pcap_pkthdr보다는 내 예제에 따라'struct pcap_sf_pkthdr'를 읽을 코드를 수정 했습니까? 그렇지 않은 경우 그렇게하십시오. –

+0

예, 내 잘못! 작동했습니다! – user1192671

0

시도 뭔가 :

struct dump_pcap_pkthdr { 
struct   timeval ts; /* time stamp */ 
unsigned int caplen;  /* length of portion present */ 
unsigned int len;  /* length this packet (off wire) */ 
}; 

struct dump_pcap_file_header { 
unsigned int magic; 
unsigned short version_major; 
unsigned short version_minor; 
int    thiszone; /* gmt to local correction */ 
unsigned int sigfigs; /* accuracy of timestamps */ 
unsigned int snaplen; /* max length saved portion of each pkt */ 
unsigned int linktype; /* data link type (LINKTYPE_*) */ 
}; 


static void read_pcap_file(char *file) 
{ 
int fd = -1; 
struct dump_pcap_pkthdr packet_header = {0}; 
struct dump_pcap_file_header pcap_header = {0}; 

fd = open(file, O_RDONLY); 
if(fd < 0) { 
    printf("Fail open file: %s\n", file); 
    return; 
} 

if(read(fd, &pcap_header, sizeof(pcap_header)) != sizeof(pcap_header)) { 
    printf("Failed to read TCPDump Header from file: %s\n", file); 
    return; 
} 

while(1) 
{ 
    r = read(fd, &packet_header, sizeof(packet_header)); 
    if(r != sizeof(packet_header)) 
     break; 

    //print data   

    lseek(fd, packet_header.caplen, SEEK_CUR); 
} 

close(fd); 
} 
+0

내 구현과 동일합니까? – user1192671

+0

위의 코드가 작동하지 않습니다. 첫 번째 루프가 끝난 후 종료됩니다. 나는 lseek (caplen)에 잘못된 것이 있다고 의심합니다. 뭐가 잘못 됐는지 말해 줄래? – user1192671

+0

C 표준 대신 비표준 함수를 사용하는 특별한 이유가 있습니까? – Lundin

1

가 제대로 PCAP 파일 형식의 엔디안 처리되어 있는지 확인합니다.

또한 디스크에서 전체 구조를 직접로드하는 것은 거의 안전하지 않습니다. 컴파일러는 구조 필드간에 패딩을 자유롭게 삽입 할 수 있으므로 디스크의 바이트가 메모리의 바이트와 일치하지 않게됩니다.

공식 라이브러리를 사용하는 것이 좋습니다. 그러면 문제가 이미 해결 될 것이므로.

+0

내가 관찰 한 것으로, 파일 포인터에 caplen을 추가하면 처음으로 종료됩니다. 그래서 내가 그것을 호스트 바이트 순서로 변환해야 할 수도 있습니다 생각. 그래서 나는 ntohl (caplen)을 사용했지만 diffrence는 만들지 않았습니다. – user1192671