libpcap/capture_pcap_dispatch.c

這裡要使用第二種方式抓封包。

Source Code

//
//  capture_pcap_dispatch.c
//  功能:使用pcap_dispatch抓取封包。
//  Created by 聲華 陳 on 2015/12/29.
//

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

void pcap_callback(u_char *arg, const struct pcap_pkthdr *header, const u_char *content);
int main(int argc, const char * argv[]) {
    char errbuf[PCAP_ERRBUF_SIZE];
    pcap_t *handle = NULL;

    //open interface
    handle = pcap_open_live("en0", 50, 1, 1000, errbuf);
    if(!handle) {
        fprintf(stderr, "pcap_open_live: %s\n", errbuf);
        exit(1);
    }//end if

    //start capture loop
    int ret = pcap_dispatch(handle, -1, pcap_callback, NULL);
    if(ret == -1) {
        fprintf(stderr, "pcap_dispatch: %s\n", pcap_geterr(handle));
    }//end if
    else {
        printf("Captured: %d\n", ret);
    }//end else

    //free
    pcap_close(handle);

    return 0;
}

void pcap_callback(u_char *arg, const struct pcap_pkthdr *header, const u_char *content) {
    static int d = 0;
    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);

    printf("No. %d\n", ++d);

    //print header
    printf("\tTime: %s.%.6d\n", timestr, header->ts.tv_usec);
    printf("\tLength: %d bytes\n", header->len);
    printf("\tCapture 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 pcap_callback

結果

libpcap % ./capture_pcap_dispatch
No. 1
    Time: 15:09:56.880809
    Length: 54 bytes
    Capture length: 50 bytes
2c 44 fd 7d f0 c1 6c 40 08 bc ae 98 08 00 45 00 00 28 7c cf 00 00 40 06 7c 43 ac 10 57 7c 1f 0d 5f 24 c5 ab 01 bb 3e 71 df 7a 7c 3c 6b 97 50 10 10 00 

No. 2
    Time: 15:09:56.945242
    Length: 66 bytes
    Capture length: 50 bytes
6c 40 08 bc ae 98 2c 44 fd 7d f0 c1 08 00 45 00 00 34 35 85 40 00 55 06 6e 81 1f 0d 5f 24 ac 10 57 7c 01 bb c5 ab 7c 3c 6b 97 3e 71 df 7b 80 10 01 36 

Captured: 2

程式會在1秒內抓取封包。

分析

    //open interface
    handle = pcap_open_live("en0", 50, 1, 1000, errbuf);
    if(!handle) {
        fprintf(stderr, "pcap_open_live: %s\n", errbuf);
        exit(1);
    }//end if

一樣要使用pcap_open_live()開啟一個Interface,這裡第二個參數給50,為了要示範切割封包,第四個封包給1000表示1秒。


    //start capture loop
    int ret = pcap_dispatch(handle, -1, pcap_callback, NULL);
    if(ret == -1) {
        fprintf(stderr, "pcap_dispatch: %s\n", pcap_geterr(handle));
    }//end if
    else {
        printf("Captured: %d\n", ret);
    }//end else

這裡第二個參數給-1表示不限制多少封包,當pcap_dispatch()返回時會傳回抓到幾個封包。當有封包經過的時候會呼叫第三個參數所給的callback:pcap_callback(),第四個參數是要傳給pcap_callback()哪個變數。


    //free
    pcap_close(handle);

結束後記得釋放。


    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);

將時間戳struct timeval轉成可辨識的字串。


    //print header
    printf("\tTime: %s.%.6d\n", timestr, header->ts.tv_usec);
    printf("\tLength: %d bytes\n", header->len);
    printf("\tCapture length: %d bytes\n", header->caplen);

在這裡輸出時間、封包大小以及擷取大小。

輸出結果:

    Time: 15:09:56.880809
    Length: 54 bytes
    Capture length: 50 bytes

因為我們在pcap_open_live()的第二個參數給50,所以超過50 bytes的封包只會擷取前50 bytes


    //print packet in hex dump
    for(int i = 0 ; i < header->caplen ; i++) {
        printf("%02x ", content[i]);
    }//end for
    printf("\n\n");

最後將封包以16進位表示法輸出,在這裡要講一下,指標跟陣列是完全不同的東西

結語

這裡展示了抓封包的第二種方式,要選擇哪種抓封包方式就依情況使用。

results matching ""

    No results matching ""