zoukankan      html  css  js  c++  java
  • 给libpcap增加一个新的捕包方法

    libpcap是一个网络数据包捕获函数库,功能非常强大,提供了系统独立的用户级别网络数据包捕获接口,Libpcap可以在绝大多数类unix 平台下工作。大多数网络监控软件都以它为基础,著名的tcpdump就是以它为基础的。tcpdump是linux下一个非常重要的网络工具,可以将网络 中传送的数据包的“头”完全截获下来提供分析。它支持针对网络层、协议、主机、网络或端口的过滤,并提供and、or、not等逻辑语句来帮助你去掉无用 的信息。很多时候为了提升捕包性能,我们通常使用修改过的驱动或者专用网卡来收包,这样就导致libpcap无法工作了,但我们又需要tcpdump来进 行调试等工作。这样就需要我们修改libpcap,以支持我们的收包方式。比如pfring就是这样处理的。

    这是本文在我自己搭建博客的地址 欢迎访问  http://www.itblogs.ga/blog/20150404222832/

    为libpcap添加一个捕包方法非常简单,下面代码先实现捕获内存中一个固定包的功能,保证能够工作后,再去支持专有驱动或者专用网卡的收包。以下所涉及的libpcap代码和tcpdump代码,版本分别为libpcap-1.7.2,tcpdump-4.1.1。

    首先添加两个文件,编写收包的代码,可以参考的代码还是挺多的,比如pcap-snoop.c、pcap-can-linux.c等。

    pcap-ring.h

    pcap_t *ring_create(const char *device, char *ebuf, int *is_ours);
    int ring_findalldevs(pcap_if_t **alldevsp, char *errbuf);

    pcap-ring.c

    #ifdef HAVE_CONFIG_H
    # include "config.h"
    #endif
    
    #include <sys/param.h>	/* optionally get BSD define */
    #include <string.h>
    
    #ifdef HAVE_OS_PROTO_H
    # include "os-proto.h"
    #endif
    
    #include "pcap-int.h"
    #include "errno.h"
    
    struct pcap_ring {
    	int pad;
    };
    
    /* 
     * 192.168.19.105 -> 202.106.4.151 
     * DNS 
     * Name: offlintab.firefoxchina.cn 
     * Type: A
     * Class: IN
     */
    char peer0_0[] = {
    		0x8c,0x21,0x0a,0x6d,0x72,0x58,0x00,0x26,0xc7,0x35,0x2f,0x58,0x08,0x00,0x45,0x00
    		,0x00,0x47,0x72,0x51,0x00,0x00,0x40,0x11,0x3b,0x42,0xc0,0xa8,0x13,0x69,0xca,0x6a
    		,0x2e,0x97,0xe5,0x30,0x00,0x35,0x00,0x33,0x5a,0x2e,0x67,0xcb,0x01,0x00,0x00,0x01
    		,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x6f,0x66,0x66,0x6c,0x69,0x6e,0x74,0x61,0x62
    		,0x0c,0x66,0x69,0x72,0x65,0x66,0x6f,0x78,0x63,0x68,0x69,0x6e,0x61,0x02,0x63,0x6e
    		,0x00,0x00,0x01,0x00,0x01
    	};
    
    static int pcap_read_ring(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
    {
    	int wirelen = sizeof(peer0_0);
    	int caplen  = wirelen;
    
    	if (caplen > p->snapshot) {
    		caplen = p->snapshot;
    	}
    
    	memcpy(p->buffer, peer0_0, caplen);
    
    	if (bpf_filter(p->fcode.bf_insns, p->buffer, wirelen, caplen)) {
    		struct pcap_pkthdr h;
    
    		gettimeofday(&h.ts, NULL);
    		h.len    = wirelen;
    		h.caplen = caplen;
    
    		(*callback)(user, &h, p->buffer);
    
    		return 1;
    	}
    
    	return 0;
    }
    
    static int pcap_stats_ring(pcap_t *p, struct pcap_stat *ps)
    {
    	/* not yet implemented */
    	ps->ps_recv = 0;    /* number of packets received */
    	ps->ps_drop = 0;    /* number of packets dropped */
    	ps->ps_ifdrop = 0;  /* drops by interface -- only supported on some platforms */
    	
    	return (0);
    }
    
    static int pcap_getnonblock_ring(pcap_t *p, char *errbuf)
    {
    	return (0);
    }
    
    static int pcap_setnonblock_ring(pcap_t *p, int nonblock, char *errbuf)
    {
    	return (0);
    }
    
    static int pcap_inject_ring(pcap_t *p, const void *buf _U_, size_t size _U_)
    {
    	strlcpy(p->errbuf, "Sending packets isn't supported", PCAP_ERRBUF_SIZE);
    	return (-1);
    }
    
    int pcap_activate_ring(pcap_t *handle)
    {
    	handle->bufsize  = 2048;
    	handle->linktype = DLT_EN10MB;
    	handle->selectable_fd = -1;
    
    	handle->read_op   = pcap_read_ring;
    	handle->stats_op  = pcap_stats_ring;
    	handle->inject_op = pcap_inject_ring;
    	handle->setfilter_op    = install_bpf_program;
    	handle->setdirection_op = NULL;
    	handle->set_datalink_op = NULL;
    	handle->getnonblock_op = pcap_getnonblock_fd; //pcap_getnonblock_ring;
    	handle->setnonblock_op = pcap_setnonblock_fd;//pcap_setnonblock_ring;
    
    	handle->buffer = (u_char *)malloc(handle->bufsize);
    	if (handle->buffer == NULL) {
    		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 
    			"Can't allocate dump buffer: %s", pcap_strerror(errno));
    		pcap_cleanup_live_common(handle);
    
    		return (PCAP_ERROR);
    	}
    
    	return 0;
    }
    
    pcap_t *ring_create(const char *device, char *ebuf, int *is_ours)
    {
    	pcap_t *p;
    
    	if(strncmp(device, "ring", 4) != 0) {
    			*is_ours = 0;
    			return NULL;
    	}
    
    	*is_ours = 1;
    
    	p = pcap_create_common(device, ebuf, sizeof(struct pcap_ring));
    	if (p == NULL) {
    		return (NULL);
    	}
    
    	p->activate_op = pcap_activate_ring;
    
    	return (p);
    }
    
    int ring_findalldevs(pcap_if_t **alldevsp, char *errbuf)
    {
    	return (0);
    }
    
    

     修改pcap.c,支持新的收包方式。

    pcap.c

    #include "pcap-ring.h"

    ... ...

    struct capture_source_type { int (*findalldevs_op)(pcap_if_t **, char *); pcap_t *(*create_op)(const char *, char *, int *); } capture_source_types[] = { #ifdef PCAP_SUPPORT_DBUS ... ... { dbus_findalldevs, dbus_create }, #endif { ring_findalldevs, ring_create }, /* new !!! */ { NULL, NULL } };

    修改  Makefile.in ,将新添加的文件编译进去。

    PSRC =  pcap-@V_PCAP@.c @USB_SRC@ @BT_SRC@ @BT_MONITOR_SRC@ 
    @CAN_SRC@ @NETFILTER_SRC@ @CANUSB_SRC@ @DBUS_SRC@ pcap-ring.c

    接下来可以编译了:

    ./configure

    make

    可以看到libpcap.a了。

    接下编译tcpdump-4.1.1

    ./configure

    make

    运行:

    [root@localhost tcpdump-4.1.1]# ./tcpdump  -i ring1 -c 2
    tcpdump: WARNING: SIOCGIFADDR: ring1: No such device
    tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
    listening on ring1, link-type EN10MB (Ethernet), capture size 65535 bytes
    02:17:45.465535 IP localhost.58672 > dialdns.bta.net.cn.domain: 26571+ A? offlintab.firefoxchina.cn. (43)
    02:17:45.485310 IP localhost.58672 > dialdns.bta.net.cn.domain: 26571+ A? offlintab.firefoxchina.cn. (43)
    2 packets captured
    0 packets received by filter
    0 packets dropped by kernel

    可以看到,tcpdump能拿到包并解析了。

        How to add support for new capture interface.

    原文链接:http://www.itblogs.ga/blog/20150404222832/ 转载请注明出处

       

  • 相关阅读:
    android 7.0带来的
    转 android 侧滑实现
    (转)30道面试题
    【转】关于手机号注册的一些思考
    一个美国人对"智能制造"的思考!
    【转】社区O2O的增量与存量,机会在哪?
    【转】30岁之前打好基础,无惧职场“35岁现象”! | 人力资源心理学
    Linux 复制、移动覆盖文件不提示
    使用DDMS测试安卓手机APP的性能(android)
    【转】测试思考——测试人员需要具备哪些素质?
  • 原文地址:https://www.cnblogs.com/jintianfree/p/4393240.html
Copyright © 2011-2022 走看看