libpcap开始抓包

下面就开始抓包了

在前面获取了网口之后(或者不需要或者直接设定),需要打开:

pcap_t *
pcap_open_live(const char *source, int snaplen, int promisc, int to_ms, char *errbuf)

这个函数打开设备,然后返回一个pcap_t类型的指针,实际上就是获得用来捕获网络数据包的描述符

source是pcap_lookupdev返回的设备,或者我们直接设定

snaplen是对于每个数据包,捕获的最大字节数

promisc表示是否网口设置为混杂模式,0表示非混杂模式,其他值表示混杂模式

to_ms表示指定了超时的时间,单位毫秒

errbuf在函数出错的时候存放错误信息

 

下面的函数是只要收到一个数据包后就会立即返回

const u_char *
pcap_next(pcap_t *p, struct pcap_pkthdr *h)

参数p就是上面pcap_open_live返回的pcap_t类型的指针

参数h是用来保存收到的第一个数据包的pcap_pkthdr类型的指针,结构体如下:

struct pcap_pkthdr {
    struct timeval ts;    /* time stamp */
    bpf_u_int32 caplen;    /* length of portion present */
    bpf_u_int32 len;    /* length this packet (off wire) */
};

表示捕获到的数据包的一些基本信息,时间戳和长度,这里有两个长度的确有点疑惑,同事有福的解释:

pcap_pkthdr表示的是当前包的信息,caplen表示的是当前包的data的长度,len表示包的原来长度,大多数情况下这两个长度的值是一样的,但是,当来了一个超长包,比如10000bytes,而我们在pcap_open_live中设定的snaplen只有1000, 那么caplen就是1000, len就是10000, 剩下的9000就被libpcap给截断了。这种情况下需要注意的是后续包的处理中如果使用ip头部的iplen做为偏移量来移动指针,那么可能会越界,需要做严格的长度检查。

 

释放网络接口

void
pcap_close(pcap_t *p)

将pcap_t的接口描述符关闭,并释放资源

 

因此,可以写一个,只要抓到一个包就立即返回的例子:

[lihui@master work]$ cat devices.c
#include <stdio.h>
#include <stdlib.h>
#include <pcap.h>

int main(){
    char ebuf[PCAP_ERRBUF_SIZE];
    char *device = NULL;
    int promisc = 1;
    int snaplen = 65535;
    int to_ms = 0;
    device = pcap_lookupdev(ebuf);
    if (device)
        printf(“Now: %s is found!\n”, device);
    else {
        printf(“Error: pcap_lookupdev %s\n”, ebuf);
        exit(1);
    }
    pcap_t* p = pcap_open_live(device, snaplen, promisc, to_ms, ebuf);
    if (!p){
        printf(“Error: pcap_open_live %s\n”, ebuf);
        exit(1);
    }
    struct pcap_pkthdr pkthdr;
    const u_char* pktStr = pcap_next(p, &pkthdr);
    if (!pktStr){
        printf(“Cannot capture pkt!\n”);
        exit(1);
    }
    printf(“Capture packet length:%d\n”, pkthdr.len);
    pcap_close(p);
    return 0;
}

[lihui@master work]$ gcc devices.c -lpcap
[lihui@master work]$ ./a.out
Now: eth0 is found!
Error: pcap_open_live eth0: You don’t have permission to capture on that device (socket: Operation not permitted)
[lihui@master work]$ sudo ./a.out
Now: eth0 is found!
Capture packet length:119

发表评论