2016年11月5日 星期六

libpcap - Capture using pcap_next_ex(5)


libpcap除了提供callback方式抓封包,也提供一般呼叫函數的方式一次抓一個封包,函數pcap_next_ex()是函數pcap_next()改良版,函數pcap_next()基本上已經棄用了,所以只講函數pcap_next_ex()



一樣使用預設的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);


接著一樣函數pcap_open_live()打開device,這次timeout設定1000毫秒。
//open interface
pcap_t *handle = pcap_open_live(device, 65535, 1, 1000, errbuf);
if(!handle) {
    fprintf(stderr, "pcap_open_live(): %s\n", errbuf);
    exit(1);
}//end if


然後就開始抓封包了。
//start capture
struct pcap_pkthdr *header = NULL;
const u_char *content = NULL;
int ret =
pcap_next_ex(handle, &header, &content);

函數pcap_next_ex()需要宣告一個struct pcap_pkthdr *和一個const u_char *讓它能夠取回封包的訊息,就跟函數pcap_loop()和函數pcap_dispathc()的callback一樣,因為要修改這兩個指標指向的位址,所以要用&的方式傳進去給函數pcap_next_ex()

函數pcap_next_ex()原型:
int pcap_next_ex(pcap_ t *p, struct pcap_pkthdr **pkt_header, const u_char **pkt_data);
  • 返回值:成功傳回1,失敗傳回-1,錯誤訊息從pcap_geterr()取得,timeout傳回0,讀取檔案時已經沒封包傳回-2。
  • 參數:p一個libpcap handle。pkt_header封包的表頭指標。pkt_data封包內容指標。
  • 功能:該函數只會抓取一個封包就馬上返回。

函數pcap_open_live()的第四個參數to_ms在這個函數單純就只是timeout,當達到to_ms時間都沒有封包就傳回0。


有沒有抓到封包要透過傳回值判斷。
if(ret == 1) {
    struct tm *ltime;
    char timestr[16];
    time_t local_tv_sec;
    
    local_tv_sec = header->ts.tv_sec;
    ltime = localtime(&local_tv_sec);
    strftime(timestr, sizeof timestr, "%H:%M:%S", ltime);
    
    //print header
    printf("Time: %s.%.6d\n", timestr, (int)header->ts.tv_usec);
    printf("Length: %d bytes\n", header->len);
    printf("Capture length: %d bytes\n", header->caplen);
    
    //print packet in hex dump
    for(int i = 0 ; i < header->caplen ; i++) {
        printf("%02x ", content[i]);
    }//end for
    printf("\n\n");
}//end if success

當傳回1表示成功讀到一個封包;一樣將header解析出來,封包內容用十六進位顯示。


else if(ret == 0) {
    printf("Timeout\n");
}//end if timeout
else if(ret == -1) {
    fprintf(stderr, "pcap_next_ex(): %s\n", pcap_geterr(handle));
}//end if fail
else if(ret == -2) {
    printf("No more packet from file\n");
}//end if read no more packet

當傳回0表示發生timeout,傳回-1表示發生錯誤,而-2只有當封包來源是檔案時候,讀取結束才會傳回。


程式結束前,記得一樣要關掉handle。
//free
pcap_close(handle);


編譯:
libpcap % gcc -I/usr/local/opt/libpcap/include -Wall -std=gnu99 -L/usr/local/opt/libpcap/lib -lpcap  capture-pcap_next_ex.c -o capture-pcap_next_ex


執行結果(Mac OS X):
libpcap % ./capture-pcap_next_ex 
Sniffing: en0
Time: 15:40:47.137992
Length: 54 bytes
Capture length: 54 bytes
b8 a3 86 a7 be d0 6c 40 08 bc ae 98 08 00 45 00 00 28 50 18 00 00 40 06 61 32 c0 a8 0b 69 40 e9 bc 8b e8 89 01 bb 90 27 bf 38 cc 21 83 81 50 10 10 00 4d 06 00 00 



執行結果(CentOS):
[root@tutu libpcap]# ./capture-pcap_next_ex 
Sniffing: eth0
Time: 15:14:49.557424
Length: 103 bytes
Capture length: 103 bytes
01 00 5e 00 00 fb b8 53 ac 1e 0d 51 08 00 45 00 00 59 1b b7 00 00 ff 11 f2 cd c0 a8 0b 6b e0 00 00 fb 14 e9 14 e9 00 45 28 5d 00 00 00 00 00 02 00 00 00 00 00 00 09 5f 32 33 33 36 33 37 44 45 04 5f 73 75 62 0b 5f 67 6f 6f 67 6c 65 63 61 73 74 04 5f 74 63 70 05 6c 6f 63 61 6c 00 00 0c 00 01 c0 1b 00 0c 00 01



Source code on Github

沒有留言:

張貼留言