2013-07-14 2 views
4

У меня есть файл nanosecond libpcap (nanosec.pcap) и наносекундная метка времени (например, 2.123456789), которая может быть отображена с помощью Wireshark. Теперь я хотел бы открыть файл nanosecond libpcap с использованием языка C и иметь исходный код следующим образом. Когда я пытаюсь открыть файл nanosec.pcap с помощью pcap_open_offine(), он вернет ошибку «неизвестный формат файла». Кроме того, изменив магическое число в заголовке nanosec.pcap на значение normal pcap (0x1A2B3C4D), и я получил ошибку сегментации от терминала (Ubuntu). Любой эксперт здесь мог бы советовать, как я могу отобразить наносекундную часть метки времени, используя libpcap? Заранее спасибо! Ниже приводится код:Чтение файла nanosecond pcap с использованием libpcap

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

#include <netinet/in.h> 
#include <netinet/ip.h> 
#include <net/if.h> 
#include <netinet/if_ether.h> 

#include <pcap.h> 

struct UDP_hdr { 
u_short uh_sport;  /* source port */ 
u_short uh_dport;  /* destination port */ 
u_short uh_ulen;  /* datagram length */ 
u_short uh_sum;   /* datagram checksum */ 
}; 


/* Some helper functions, which we define at the end of this file. */ 

/* Returns a string representation of a timestamp. */ 
const char *timestamp_string(struct timeval ts); 

/* Report a problem with dumping the packet with the given timestamp. */ 
void problem_pkt(struct timeval ts, const char *reason); 

/* Report the specific problem of a packet being too short. */ 
void too_short(struct timeval ts, const char *truncated_hdr); 

void dump_UDP_packet(const unsigned char *packet, struct timeval ts, 
     unsigned int capture_len) 
{ 
struct ip *ip; 
struct UDP_hdr *udp; 
unsigned int IP_header_length; 

/* For simplicity, we assume Ethernet encapsulation. */ 

if (capture_len < sizeof(struct ether_header)) 
    { 
    /* We didn't even capture a full Ethernet header, so we 
    * can't analyze this any further. 
    */ 
    too_short(ts, "Ethernet header"); 
    return; 
    } 

/* Skip over the Ethernet header. */ 
packet += sizeof(struct ether_header); 
capture_len -= sizeof(struct ether_header); 

if (capture_len < sizeof(struct ip)) 
    { /* Didn't capture a full IP header */ 
    too_short(ts, "IP header"); 
    return; 
    } 

ip = (struct ip*) packet; 
IP_header_length = ip->ip_hl * 4; /* ip_hl is in 4-byte words */ 

if (capture_len < IP_header_length) 
    { /* didn't capture the full IP header including options */ 
    too_short(ts, "IP header with options"); 
    return; 
    } 

if (ip->ip_p != IPPROTO_UDP) 
    { 
    problem_pkt(ts, "non-UDP packet"); 
    return; 
    } 

/* Skip over the IP header to get to the UDP header. */ 
packet += IP_header_length; 
capture_len -= IP_header_length; 

if (capture_len < sizeof(struct UDP_hdr)) 
    { 
    too_short(ts, "UDP header"); 
    return; 
    } 

udp = (struct UDP_hdr*) packet; 

printf("%s UDP src_port=%d dst_port=%d length=%d\n", 
    timestamp_string(ts), 
    ntohs(udp->uh_sport), 
    ntohs(udp->uh_dport), 
    ntohs(udp->uh_ulen)); 
} 


int main(int argc, char *argv[]) 
{ 
pcap_t *pcap; 
const unsigned char *packet; 
char errbuf[PCAP_ERRBUF_SIZE]; 
struct pcap_pkthdr header; 

/* Skip over the program name. */ 
++argv; --argc; 

/* We expect exactly one argument, the name of the file to dump. */ 
if (argc != 1) 
    { 
    fprintf(stderr, "program requires one argument, the trace file to dump\n"); 
    exit(1); 
    } 

pcap = pcap_open_offline(argv[0], errbuf); 
if (pcap == NULL) 
    { 
    fprintf(stderr, "error reading pcap file: %s\n", errbuf); 
    exit(1); 
    } 

/* Now just loop through extracting packets as long as we have 
* some to read. 
*/ 
while ((packet = pcap_next(pcap, &header)) != NULL) 
    dump_UDP_packet(packet, header.ts, header.caplen); 

// terminate 
return 0; 
} 


/* Note, this routine returns a pointer into a static buffer, and 
* so each call overwrites the value returned by the previous call. 
*/ 
const char *timestamp_string(struct timeval ts) 
{ 
static char timestamp_string_buf[256]; 

sprintf(timestamp_string_buf, "%d.%09d", 
    (int) ts.tv_sec, (int) ts.tv_usec); 

return timestamp_string_buf; 
} 

void problem_pkt(struct timeval ts, const char *reason) 
{ 
fprintf(stderr, "%s: %s\n", timestamp_string(ts), reason); 
} 

void too_short(struct timeval ts, const char *truncated_hdr) 
{ 
fprintf(stderr, "packet with timestamp %s is truncated and lacks a full %s\n", 
    timestamp_string(ts), truncated_hdr); 
} 

ответ

7

Любой специалист здесь мог посоветовать, как я мог бы отобразить наносекунд часть временной метки с помощью Libpcap?

Использование топ-оф-Гит стволу версия Libpcap, открыть файл захвата с

pcap_open_offline_with_tstamp_precision(pathname, PCAP_TSTAMP_PRECISION_NANO, errbuf); 

и лечить struct timeval в pcap_pkthdr структуре как секунды и наносекунды, а не секунды и микросекунды (т. е. ваша программа обрабатывает tv_usec как наносекунды, а не микросекунды - немного запутывает, но я не уверен, что есть менее уродливое решение).

+0

Вы имеете в виду libpcap-master на https://github.com/the-tcpdump-group/libpcap? я дам ему попробовать – CheeHow

+0

Это или тот, который вы получаете от 'git clone git: // bpf.tcpdump.org/libpcap', согласно [веб-сайту tcpdump] (http://www.tcpdump.org/# источник). –

+0

Привет, господин Гай, без везения, я снова получил ошибку сегментации (ядро сбрасывал), используя этот метод. как обрабатывать timeval как наносекунду? изменить на tv_nsec? Я установил libpcap-master и даже не могу запустить код. любезно совет. – CheeHow