2015-11-04 140 views
0

我有了這個代碼是工作的罰款寫一個PCAP文件(只有以太網協議測試)與libpcap的:如何從頭開始編寫pcap文件,去除libpcap函數?

struct ethernet { 
    u_char  mac1[6]; 
    u_char  mac2[6]; 
    u_short  protocol; 
}; 

int main() { 
    pcap_t *pd; 
    pcap_dumper_t *pdumper; 

    pd = pcap_open_dead(DLT_EN10MB, 65535); 
    pdumper = pcap_dump_open(pd, "test.pcap"); 

    struct pcap_pkthdr packet_header; 
    struct timeval ts; 

    packet_header.ts = ts; 
    packet_header.caplen = sizeof(struct ethernet); 
    packet_header.len = sizeof(struct ethernet); 

    struct ethernet ethernet; 

    bzero(ethernet.mac1, 6); 
    bzero(ethernet.mac2, 6); 
    ethernet.protocol = 8977; // randomly choose 
    pcap_dump((u_char*)pdumper, &packet_header, (const u_char*)&ethernet); 
    pcap_close(pd); 
    pcap_dump_close(pdumper); 
    return 0; 
} 

但我想嘗試不使用PCAP功能,所以我開始去除上面使用的功能。

這裏是我找到了來源:

pcap_open_dead功能:http://www.wand.net.nz/trac/libtrace/browser/lib/pcap_open_dead.c?rev=808a478a2459f3cf0e8bf927fcaad371138efb20

pcap_dump_open,pcap_dump及其他:http://www.opensource.apple.com/source/libpcap/libpcap-2.1/libpcap/savefile.c

所以,這裏是我的想法:

的pcap_open_dead功能是怎麼樣無用的,只是實例化一個pcap_t結構(我不想在我的代碼中使用)並用參數填充它的值。

pcap_dump_open返回一個pcap_dumper_t(它看起來就像一個FILE *),只是打開文件並在其中寫入頭文件(如果我們不關心錯誤處理)。順便說一句,似乎它給予「p-> tzoff」作爲sf_write_header的參數,它尚未在我的代碼中初始化(並且它仍在工作)。 關於LINKTYPE,在我們的情況下,它只是等於1

最後,pcap_dump功能採取pcap_dumper_t變量作爲第一個參數,它是隱式轉換爲u_char *則顯式轉換爲FILE *(爲什麼不使用文件*從一開始?) 然後它將一個包頭和一個包數據用fwrite寫入文件中。

因此,這裏是我做過什麼:

FILE *fd = fopen("test.pcap", "w"); 

struct pcap_file_header header; 

header.magic = 0xa1b2cd34; 
header.version_major = 2; 
header.version_minor = 4; 
header.thiszone = 0; 
header.sigfigs = 0; 
header.snaplen = 65535; 
header.linktype = DLT_EN10MB; 

struct pcap_pkthdr packet_header; 
struct timeval ts; 

packet_header.ts = ts; 
packet_header.caplen = sizeof(struct ethernet); 
packet_header.len = sizeof(struct ethernet); 

struct ethernet ethernet; 

bzero(ethernet.mac1, 6); 
bzero(ethernet.mac2, 6); 
ethernet.protocol = 8977; 

fwrite((char*)&header, sizeof(header), 1, fd); 
fwrite((char*)&packet_header, sizeof(struct pcap_pkthdr), 1, fd); 
fwrite((char*)&ethernet, sizeof(struct ethernet), 1, fd); 
close(fd); 

無需使用pcap_t結構,我把snaplen有和LINKTYPE值直接在pcap_file_header結構。

然後我使用fwrite,就像他們在pcap函數中做的那樣。

頭文件是好的,我可以用wireshark打開文件,如果我只是在文件中寫頭。 但是當我添加了2最後的fwrite(寫包頭和包),Wireshark的告訴我:

The capture file appears to be damaged or corrupt. 
(pcap: File has 4195245-byte packet, bigger than maximum of 65535) 

我找不到哪裏是我的錯,我不知道他看到那麼多字節。

編輯

除了使用未初始化的timeval的,我所做的:

packet_header.ts = (struct timeval){0}; 

而且現在的工作,但你怎麼解釋它是使用PCAP功能,當工作? 「ts」仍未初始化。

這個timeval的含義是什麼?將它設置爲零是否有意義?

+1

'ts'未初始化。也許它無意中設置爲0xffffffff,這也是你的結構錯誤的地方。 –

+0

你說得對,現在正在工作,但我正在編輯我的帖子以尋求一些細節 – Charrette

回答

2

struct pcap_pkthdr packet_header;

,因爲它是提供給一個程序這是一個分組報頭的格式。它是而不是必須是數據包標題的格式,因爲它存儲在文件中;它包含一個struct timeval,其大小取決於time_t是32位還是64位。

你需要的是:

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代替。將struct pcap_pkthdr結構寫入文件將在struct timevaltv_sectv_usec字段不是32位的任何系統上生成無效的pcap文件;這在任何64位系統上都可能是這種情況。在這種情況下,您可能會收到錯誤,例如您看到的「已損壞或已損壞」錯誤。

至於時間標記的含義是什麼,在實際的捕獲中,它表示無論捕獲代碼路徑的任何部分被標記的時間,它都表示數據包被看到的時間,這是對時間戳的近似值包到達機器捕獲它。這是一個UN * X時間戳,因此tv_sec是自1970年1月1日00:00:00 UTC以來的秒數,而tv_usec是自第二秒起的一個微秒數。