libpcap能夠將封包儲存成檔案,可以之後用Wireshark或其他工具再打開。
函數
pcap_dump*
開頭的都是跟檔案處理有關的函數。一樣用預設的device和打開它。
char errbuf[PCAP_ERRBUF_SIZE]; char *device = NULL; //get default interface name device = pcap_lookupdev(errbuf); if(!device) { fprintf(stderr, "pcap_lookupdev(): %s\n", errbuf); exit(1); }//end if printf("Sniffing: %s\n", device); //open interface pcap_t *handle = pcap_open_live(device, 65535, 1, 1, errbuf); if(!handle) { fprintf(stderr, "pcap_open_live(): %s\n", errbuf); exit(1); }//end if
接著根據這個handle資訊再打開一個檔案處理的handle。
//open file handler const char *filename = "saved.pcap"; pcap_dumper_t *dumper = pcap_dump_open(handle, filename); if(!dumper) { fprintf(stderr, "pcap_dump_open(): %s\n", pcap_geterr(handle)); pcap_close(handle); exit(1); }//end if printf("Saving to %s...\n", filename);
結構
pcap_dumper_t *
是檔案處理的handle,函數pcap_dump_open()
負責打開一個檔案處理handle,第二個參數是要輸出的檔名,這邊用"saved.pcap"當作檔名。函數
pcap_dump_open()
原型:pcap_dumper_t *pcap_dump_open(pcap_t *p, const char *fname);
- 返回值:成功傳回一個處理檔案的handle,失敗傳回NULL,錯誤訊息從pcap_geterr()取得。
- 參數:p一個libpcap handle。fname檔案名稱。
- 功能:打開一個可以處理封包檔案的handle。
用函數
pcap_loop()
來抓封包,抓1000個封包以及將處理檔案的handle:變數dumper傳入。//start capture loop if(0 != pcap_loop(handle, 1000, pcap_callback, (u_char *)dumper)) { fprintf(stderr, "pcap_loop(): %s\n", pcap_geterr(handle)); }//end if
接著來看callback部分
static int d = 0; printf("\rNo.%5d captured", ++d); fflush(stdout);
一樣將目前抓到第幾個封包列印出來,這邊用了
\r
,也就是說列印出來後再歸位(carriage return)一次,所以每次列印出來的東西會被下一次列印出來的蓋掉,視覺上就像是在原地遞增數量一樣。(等等看結果就知道了)函數
fflush()
是將某個檔案指標內的buffer給清出來,因為之前的函數printf()
本身有緩衝區(linux通常是4096,Mac OS X通常是8192),如果在緩衝區滿之前、遇到\n
、檔案指標關閉或者程式結束前...等,都不會輸出。\n
也稱為行緩衝,這邊函數printf()
並沒有用到,所以有可能並不會立即更新,所以呼叫函數fflush()
強迫把stdout緩衝區內的資料清出來。接著就把封包直接輸出到檔案內。
//dump to file pcap_dump(arg, header, content);
只要呼叫函數
pcap_dump()
,就可以將封包塞到檔案內。函數
pcap_dump()
原型:void pcap_dump(u_char *user, const pcap_pkthdr *header, const u_char *content);
- 參數:user處理檔案的handle(從pcap_dump_open()取得)。header封包的表頭資訊。content封包的內容。
- 功能:將封包丟到檔案內。
抓完封包後,在關檔前還要處理一些事情。
//flush and close pcap_dump_flush(dumper); pcap_dump_close(dumper); printf("\nDone\n");
函數
pcap_dump_flush()
先將緩衝區內的資料(封包)強迫清空到檔案內,再呼叫函數pcap_dump_close()
關檔,雖然pcap_dump_flush()
不是必要的,但是可以確保封包可以完全清空。函數
pcap_dump_flush()
原型:int pcap_dump_flush(pcap_dumper_t *p);
- 返回值:成功傳回0,失敗傳回-1,錯誤訊息從pcap_geterr()取得。
- 參數:p處理檔案的handle。
- 功能:將處理檔案handle內的封包全部強迫清到檔案內。
函數
pcap_dump_close()
原型:void pcap_dump_close(pcap_dumper_t *p);
- 參數:p處理檔案的handle。
- 功能:釋放處理檔案handle的資源。
最後關掉handle。
//free pcap_close(handle);
編譯:
libpcap % gcc -I/usr/local/opt/libpcap/include -Wall -std=gnu99 -L/usr/local/opt/libpcap/lib -lpcap save-to-file.c -o save-to-file
執行結果(Mac OS X):
libpcap % ./save-to-file Sniffing: en0 Saving to saved.pcap... No. 1000 captured Done
執行結果(CentOS):
[root@tutu libpcap]# ./save-to-file Sniffing: eth0 Saving to saved.pcap... No. 1000 captured Done
結果檔案saved.pcap
剛好一千個封包。
Source code on Github
沒有留言:
張貼留言