转载:PCAP研究
Version 1.0
2008年4月
本文基于pcap0.9.8版本,该版本发布于September 25,2007。RHEL AS4Update3附带的版本是0.8.3(tcpdump--version)。
一、 pcap简介
封装了OS提供的底层抓包技术,对外提供一些统一的抓包(及发送)接口。实现这些功能的其他技术包括:BPF(Berkeley PacketFilter),DLPI(Data Link ProviderInterface),NIT
二、 pcap Linux安装
参考《INSTALL.txt》。
进入pcap源码目录,执行./configure,这将检测系统环境,并生成Makefile文件;执行make;执行makeinstall,这将安装开发头文件、库、手册等;注意这不会安装动态库。
三、 pcap 开发介绍
2.1 API介绍
本部分介绍API,并对主要的API进行详细的说明。
pcap_open_live,打开由dev指定的设备,
pcap_open_dead,只是建立一个pcap_t结构体,用处不大;
pcap_open_offline,打开一个tcpdump/libpcap
pcap_dump_open
pcap_setnonblock
pcap_getnonblock
pcap_findalldevs,获取设备列表
pcap_freealldevs,关闭查询的设备
pcap_lookupdev,获得设备信息,如eth0,只是获得找到的第一个设备
pcap_lookupnet,获得IP/Mask信息
pcap_dispatch,抓包引擎,需循环调用
pcap_loop,抓包引擎,与pcap_dispatch的不同处在于它少一个超时返回参数;
pcap_dump
pcap_compile,编译过滤语法
pcap_setfilter,绑定过滤器
pcap_freecode
pcap_next,轮询方式抓包
pcap_datalink
pcap_snapshot
pcap_is_swapped
pcap_major_version
pcap_minor_version
pcap_stats,获取当前捕获的统计信息
pcap_file
pcap_fileno
pcap_perror
pcap_geterr
pcap_strerror
pcap_close,关闭设备
pcap_dump_close
pcap_sendpacket,发送一个原始数据包
说明:
1,
2,
2.2使用pcap的一般步骤
Ø
Ø
Ø
2.3回调函数定义
typedef void (*pcap_handler)(u_char *, const structpcap_pkthdr *, const u_char *);
2.4设置过滤条件
首先使用pcap_compile编译一个filter字符串,然后使用pcap_setfilter将编译结果绑定到一个设备;
2.5 错误返回
存在两种获取错误原因的方式,一是通过函数参数的errbuf;如果函数没有该参数,则使用pcap_geterr获得,函数执行错误时会将错误信息写入结构体中的预分配的errbuf(其中一些是基于errno),该函数返回该errbuf的地址;
四、 pcap Linux实现
4.1函数
本部分介绍某些关键函数的实现:
1,
2,
3,
a)
b)
c)
d)
4,
5,
6,
a)
7,
8,
9,
10,
11,
a)
b)
12,
13,
14,
15,
16,
4.1数据结构
本部分为pcap的关键数据结构:
struct pcap_if {
};
struct pcap_pkthdr {
};
len可能大于caplen
pcap_t,摘出了Linux相关部分:
struct pcap {
#ifdef PCAP_FDDIPAD
#endif
};
五、 一些问题
1,c代码与c++代码风格比较
1,
2,
六、 一些测试数据
1,基于Winpcap,使用filter;
程序执行环境:Windows XPsp2,无线网卡;
测试方式:向10.130.24.158拷贝一个超过1G的文件,检查程序的性能情况;
测试数据:
| 描述 | CPU(%) | 程序消耗(%) | 其他 |
1 | 不设置filter,抓取所有数据 | 65~85 | 20 | |
2 | 设置filter(udp)使得不抓取数据 | 15~25 | 0 | |
3 | 设置filter(tcp)抓取所有数据 | 65~80 | 20 | |
2,Winpcap的发送速度
说明:本次测试只测试了发送函数的执行耗时,未检查接受端的情况,即不能保证数据真的通过网卡发出。
测试方式:每次发送300B大小的数据包,每循环执行100000或500000次发送,记录每循环的耗时,取多次循环的折中值;另外24.158机器上安装有两块千兆网卡,一块接在千兆交换机上,另一块接在百兆交换机上。
1,
每循环执行100000次pcap_sendpacket发送,耗时约6秒,流量约40Mb/s,且100Mb网络稍快于1000Mb网络;
使用pcap_sendqueue_transmit,积累到100个数据包时发送一次;千兆网络每循环耗时0.7秒,流量342Mb/s,百兆网络每循环耗时2.6秒,流量92Mb/s。
结论:pcap_sendqueue_transmit比pcap_sendpacket发送速度快得多。
2,
本部分测试用户buffer、系统buffer、每次发送数量对pcap_sendqueue_transmit的发送速度的影响;本测试每循环发送500000个包,每个包300B;
关于pcap_sendqueue_alloc的说明:该函数用于分配一块用户空间存储,应设置得足够大以容纳数据;测试发现它会影响到程序占用的内存,但对发送速度没有影响。
用户buffer
每次发包数 | 50 | 100 | 1200 | 1 |
1000Mb网络(秒) | 3 | 4 | 3 | 32 |
100Mb网络(秒) | 13 | 13 | 13 | 30 |
设置用户buffer为8M,系统buffer
每次发包数 | | 100 | 1200 | |
1000Mb网络(秒) | | 2.7 | 3 | |
100Mb网络(秒) | | 13 | 13.3 | |
设置用户buffer为64M,系统buffer
每次发包数 | | 100 | 1200 | |
1000Mb网络(秒) | | 2.7 | 3 | |
100Mb网络(秒) | | 13 | 13.4 | |
设置用户buffer为1M,系统buffer
每次发包数 | | 100 | 1200 | |
1000Mb网络(秒) | | 2.7 | 3 | |
100Mb网络(秒) | | 13 | 13.4 | |
设置用户buffer为1M,系统buffer
每次发包数 | | 100 | 1200 | |
1000Mb网络(秒) | | 3.7 | 3.1 | |
100Mb网络(秒) | | 13 | 13.3 | |
设置用户buffer为8M,系统buffer
每次发包数 | | 100 | 1200 | 12000 |
1000Mb网络(秒) | | 3.7 | 3 | 2.9 |
100Mb网络(秒) | | 13 | 13.4 | 13.6 |
设置用户buffer为8M,系统buffer
每次发包数 | | 100 | 1200 | |
1000Mb网络(秒) | | 2.7 | 3 | |
100Mb网络(秒) | | 13 | 13.4 | |
七、 相关资料
参考资料
《pcap编程深入解析.doc》
Linux pcap man手册(manpcap)