为LIBPCAP库添加接口信息

网络协议 专栏收录该内容
23 篇文章 1 订阅

TCPDUMP的libpcap库在抓包时使用any接口,不能得到接口的信息。查看随数据包一并得到的pcap_pkthdr结构体,包含的信息有限,以下我们在其中增加一个ifindex字段,表示此数据包的接口信息 (文件pcap/pcap.h)。
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抓包流程 

介绍一下pcap库的抓包流程。首先创建PF_PACKET套接口,如果是要抓取any任意接口的数据包,指定类型为SOCK_RAW,抓取原始报文,链接类型设置为DLT_LINUX_SLL。

static int activate_new(pcap_t *handle)
{
    int is_any_device = (strcmp(device, "any") == 0);

    sock_fd = is_any_device ?
        socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL)) :
        socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
	handle->linktype = DLT_LINUX_SLL;
}

接下来设置接收数据包的环形buffer参数。默认情况下libpcap分配2M字节大小的环形buffer:

setsockopt(handle->fd, SOL_PACKET, PACKET_RX_RING, (void *) &req, sizeof(req));


函数pcap_read_linux_mmap_v1负责从环形buffer中读取数据包,交由pcap_handle_packet_mmap函数进行处理(过滤、显示等)。

static int pcap_read_linux_mmap_v1(pcap_t *handle, ...)
{
    while ((pkts < max_packets) || PACKET_COUNT_IS_UNLIMITED(max_packets)) {
        h.raw = pcap_get_ring_frame(handle, TP_STATUS_USER);
        if (!h.raw)
            break;
        ret = pcap_handle_packet_mmap(...);
	}
}

 

PCAP调用接口API

使能pcap实时抓包,device使用any;snaplen使用1600,获取完整的数据包。
    pcap_t *pd = pcap_open_live(device, snaplen, 0, 1000, ebuf);

可使用pcap_snapshot函数获取pcap库支持的最小长度snaplen。如果pcap_open_live设置的snaplen小于此值,pcap自动使用最小值:
    pcap_snapshot(pd);

设置过滤器,例如此处设置为过滤ICMP报文。

    pcap_compile(pd, &fcode, “ICMP”, 1, netmask) < 0);
    pcap_setfilter(pd, &fcode) < 0);

开始抓取1000个报文,pcap为每个数据包使用sll_if_print回调函数打印报文信息:
    printer = sll_if_print;
    pcap_loop(pd, 1000, printer, 0);

    
printer函数指针为pcap_handler类型,定义如下:

typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *, const u_char *);

 

添加接口信息

要添加接口信息,可通过修改pcap_handler的第二个参数pcap_pkthdr结构体,将接口索引值传给回调函数。增加ifindex字段。

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) */

    int ifindex;  //增加的接口索引值。
}; 

最重要的是在pcap库中获取每个数据包的接口索引,在调用callback函数前赋值给pcap_pkthdr的成员ifindex,由抓包流程可知,需要修改函数pcap_handle_packet_mmap。 在此函数中,每个抓取的数据包,在偏移sizeof(struct tpacket_hdr)长度之后,为sockaddr_ll结构信息,其成员sll_ifindex就是需要的接口索引值,赋给ifindex即可。

static int pcap_handle_packet_mmap(pcap_t *handle, pcap_handler callback, ...)
{
    sll = (void *)frame + TPACKET_ALIGN(handlep->tp_hdrlen);

    pcaphdr.ifindex = sll->sll_ifindex;
	
    /* pass the packet to the user */
    callback(user, &pcaphdr, bp);
}

这样,就可在sll_if_print函数中打印ifindex的数值了。


完整的修改文件如下,基于libpcap-1.5.3的patch:

diff -burp libpcap-1.5.3-old/pcap/pcap.h libpcap-1.5.3/pcap/pcap.h
--- libpcap-1.5.3-old/pcap/pcap.h       2013-11-08 07:23:22.000000000 +0800
+++ libpcap-1.5.3/pcap/pcap.h   2018-09-18 14:52:06.337276047 +0800
@@ -163,6 +163,8 @@ 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) */
+
+       int     ifindex;
 };
 
 /*
diff -burp libpcap-1.5.3-old/pcap-linux.c libpcap-1.5.3/pcap-linux.c
--- libpcap-1.5.3-old/pcap-linux.c      2014-01-15 04:40:35.000000000 +0800
+++ libpcap-1.5.3/pcap-linux.c  2018-09-18 14:53:06.837274302 +0800
@@ -1735,6 +1735,7 @@ pcap_read_packet(pcap_t *handle, pcap_ha
 
        pcap_header.caplen      = caplen;
        pcap_header.len         = packet_len;
+       pcap_header.index = from.sll_ifindex;
 
        /*
         * Count the packet.
@@ -4219,6 +4220,7 @@ static int pcap_handle_packet_mmap(
        pcaphdr.ts.tv_usec = tp_usec;
        pcaphdr.caplen = tp_snaplen;
        pcaphdr.len = tp_len;
+       pcaphdr.ifindex = sll->sll_ifindex;
 
        /* if required build in place the sll header*/
        if (handlep->cooked) {

 

完。

 

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值