libpcap可以讀取一些數據供讀取,像是封包掉的資訊。
一樣開啟預設的device,然後隨意抓個封包,timeout訂在5000毫秒,過濾器用"tcp or udp"。
    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, 5000, errbuf);
    if(!handle) {
        fprintf(stderr, "pcap_open_live(): %s\n", errbuf);
        exit(1);
    }//end if
    
    //generate bpf filter
    bpf_u_int32 net, mask;
    struct bpf_program fcode;
    //get network and mask
    if(-1 == pcap_lookupnet(device, &net, &mask, errbuf)) {
        fprintf(stderr, "pcap_lookupnet(): %s\n", errbuf);
        mask = PCAP_NETMASK_UNKNOWN;
    }//end if
    
    //compile filter
    if(-1 == pcap_compile(handle, &fcode, "tcp or udp", 1, mask)) {
        fprintf(stderr, "pcap_compile(): %s\n", pcap_geterr(handle));
        pcap_close(handle);
        exit(1);
    }//end if
    
    //set filter
    if(-1 == pcap_setfilter(handle, &fcode)) {
        fprintf(stderr, "pcap_pcap_setfilter(): %s\n", pcap_geterr(handle));
        pcap_freecode(&fcode);
        pcap_close(handle);
        exit(1);
    }//end if
    
    //free bpf code
    pcap_freecode(&fcode);
    
    //start capture
    int capture = 0;
    pcap_dispatch(handle, -1, pcap_callback, (u_char *)&capture);
其中變數capture是用來記錄目前抓到幾個封包了。
而callback只是單純紀錄抓到幾個封包了,要小心指標轉型。
static void pcap_callback(u_char *arg, const struct pcap_pkthdr *header, const u_char *content) {
    int *capture = (int *)arg;
    (*capture)++;
    return;
}//end pcap_callback
函數
pcap_stats()可以抓取一些數據出來。
    //get stat
    struct pcap_stat ps;
    if(pcap_stats(handle, &ps) != 0) {
        fprintf(stderr, "pcap_stats(): %s\n", pcap_geterr(handle));
    }//end if
    else {
        printf("Receive: %d\n", capture);
        printf("Receive by filter: %d\n", ps.ps_recv);
        printf("Drop by kernel: %d\n", ps.ps_drop);
        printf("Drop by interface: %d\n", ps.ps_ifdrop);
    }//end else
要注意的是成員
ps_recv是原本的封包數量,變數capture則是被過濾後命中條件的封包數量。函數
pcap_stats()原型:int pcap_stats(pcap_t *p, struct pcap_stat *ps);
- 回傳值:成功傳回0,失敗傳回-1,錯誤訊息從pcap_geterr()取得。
 - 參數:p一個libpcap handle。ps數據結果指標。
 - 功能:取得目前數據,不能用在檔案。
 
結構
struct stat宣告:
/*
 * As returned by the pcap_stats()
 */
struct pcap_stat {
 u_int ps_recv;  /* number of packets received */
 u_int ps_drop;  /* number of packets dropped */
 u_int ps_ifdrop; /* drops by interface -- only supported on some platforms */
#ifdef WIN32
 u_int bs_capt;  /* number of packets that reach the application */
#endif /* WIN32 */
};
編譯:
libpcap % gcc -I/usr/local/opt/libpcap/include -Wall -std=gnu99 -L/usr/local/opt/libpcap/lib -lpcap get-stat.c -o get-stat
執行結果:
libpcap % ./get-stat Sniffing: en0 Receive: 343 Receive by filter: 358 Drop by kernel: 0 Drop by interface: 0
在這timeout前總共358個封包接收到,343個封包符合"tcp or udp"條件,0個被丟棄。
Source code on Github
沒有留言:
張貼留言