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/ 转载请注明出处

给libpcap增加一个新的捕包方法的更多相关文章

  1. Android开发之清除缓存功能实现方法,可以集成在自己的app中,增加一个新功能。

    作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 Android开发之清除缓存功能实现方法,可以集成在自己的app中,增加一个新功能. 下面是一个效果图 ...

  2. 关于新feature对应的增加一个新的测试单子(QA)和文档单子(Doucmentation)的步骤

    一,增加一个new feature的文档单子. 1.new feature 增加对应的文档单子(公司有一个组是专门写产品说明的)所以增加一个新的功能就要有这个新的功能对应的一个文档(Documenta ...

  3. 使用layui 做后台管理界面,在Tab中的链接点击后添加一个新TAB的解决方法

    给链接或按钮  添加 onclick="self.parent.addTab('百度','http://www.baidu.com','icon-add')" 如: <a h ...

  4. easyui 后台页面,在Tab中的链接点击后添加一个新TAB的解决方法

    1.示例1 新增一个按钮 添加点击事件 onclick="self.parent.addTab('百度','http://www.baidu.com','icon-add')" 如 ...

  5. go CD 用虚拟机快速增加一个新agent

    背景 最近项目在用go CD做持续交付.为了最大化利用硬件,所有的agent都是用的vbox的虚拟机.随着pipelines的增加,就需要增加更多的agent. 步骤 为了快速增加新的agent,最简 ...

  6. (repost)在ARM Linux内核中增加一个新的系统调用

    实验平台内核版本为4.0-rc1,增加一仅仅打印Hello World的syscall,最后我们在用户空间swi验证 实验平台内核版本为4.0-rc1,增加的系统调用仅仅是简单打印一个Hello Wo ...

  7. 给MySQL中某表增加一个新字段,设为主键值为自动增长。

    alter table test_tb  add ID int(10) primary key AUTO_INCREMENT; 设定完成后,原有记录的该字段会增加并自动设上值.以后的值会在已有记录的最 ...

  8. win10 增加一个新磁盘

    1.右键我的电脑,选择管理 可以看到C盘的空间相比较大,拿出来250G的空间做成E盘 2.选择OS(C:),右键,压缩卷,请稍后,点击压缩 3.此刻会看到,有一块黑色区域就是新建的未分配空间,这时我们 ...

  9. 真正解决vbox不能为虚拟电脑打开一个新任务的解决方法

    今天小编电脑上出现了一个问题,如上图,经过了一个朋友的帮助终于问题解决了,解决方法: 在每一个中把 红框中打上勾号即可

随机推荐

  1. ftp常用命令

    ABOR 中断数据连接程序 ACCT <account> 系统特权帐号 ALLO <bytes> 为服务器上的文件存储器分配字节 APPE <filename> 添 ...

  2. C语言-Hello, world

    你好, 世界   --1-- 语言的编写准备 1.1 C语言源文件的编译执行过程 1.2 常见文件的拓展名 1.3 常用的命令行指令 1.4 环境及运行方法 --2--编写代码 2.1练习 --3-- ...

  3. VS2012一打开就停止工作的解决方法

    昨天刚装好VS2012,用得好好的,嘿,今早儿 一打开程序,就告诉我 VS2012停止工作,只有关闭程序或者调试程序. 小主酸菜郁闷不已,必须找到解决方法啊,错误提示如图: 错误原因:        ...

  4. web项目开发规范整理总结

    一.类.函数.变量名命名: 1.定义类时,全部拼音的首字母必须大写:如Person,ClassDemo:(帕斯卡命名法):也可以用带下斜杆的匈牙利命名法进行命名,如    head_navigatio ...

  5. [转]iOS学习笔记(2)--Xcode6.1创建仅xib文件无storyboard的hello world应用

    转载地址:http://www.mamicode.com/info-detail-514151.html 由于Xcode6之后,默认创建storyboard而非xib文件,而作为初学,了解xib的加载 ...

  6. Audio播放音效

    AudioToolbox.framework是一套基于C语言的框架,使用它来播放音效其本质是将短音频注册到系统声音服务(System Sound Service).System Sound Servi ...

  7. centos常用操作

    文件夹赋权chmod -R 777 文件夹 zip压缩和unzip解压缩命令详解以下命令均在/home目录下操作cd /home #进入/home目录1.把/home目录下面的mydata目录压缩为m ...

  8. JavaScript局部变量和全局变量的理解

    原文链接:http://www.cnblogs.com/eric-qin/p/4166552.html JavaScript局部变量和全局变量的理解   1 2 3 4 5 6 7 8 9 10 &l ...

  9. 使用FIR.im发布自己的移动端APP

    一次很偶然的机会知道FIR.im,这家公司主要的产品就是帮助开发者方便便捷地发布iOS或者Android应用的.今天我就聊聊如何在FIR.im中发布自己的APP,然后让加入UUID的设备通过网页直接下 ...

  10. mysql 批量导出建表语句 (视图,函数同理)

    import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream;import ja ...