libpcap学习笔记

合集下载

libpcap函数

libpcap函数

libpcap函数1)ioctl函数定义ioctl()函数非常庞杂,它可以控制各种文件的属性。

ioctl函数原型为:int ioctl(int handle,int cmd[,int *argdx,int argcx]);2)socket函数定义常用的Socket类型有两种:流式Socket(SOCK_STREAM)和数据包式Socket(SOCK_DGRAM)。

流式是一种面向连接的Socket,针对面向连接的TCP服务应用;数据报式Socket是一种无连接的Socket,针对无连接的UDP服务应用。

Socket函数原型为:int socket(int domain, int type,int protocol);3)recvfrom()函数定义用recvfrom()函数来实现接收数据包,recvfrom()是具备“阻塞式I/O”特性的函数,能够在没有数据包到达的情况下暂时挂起等待,直至接收到数据包后,再激活转入下一步处理。

recvfrom()函数的原型为:int recvfrom(SOCKET s,char FAR *buf,int len,int flags,structsockaddr FAR *from,int *fromlen);本函数从已连接套接口上接收数据,并捕获数据发送源的地址。

对于SOCK_STREAM类型的套接口,最多可以接收缓冲区大小个数据。

如果套接口被设置为线内接收带外数据(选项为 SO_OOBINLINE),且有带外数据未读入,则返回带外数据。

应用程序可通过调用ioctlsocket()的SOCATMARK命令来确定是否有带外数据待读入。

对于SOCK_STREAM类型套接口,忽略from和fromlen参数。

因为面向连接的话不用再指定地址了。

4)一些“字节顺序”转换函数因为网络和主机采用的存储字节时内存顺序安排方式的差异,就存在“字节顺序”的问题。

在网络环境下存储时,高位字节存放在内存的起始位置,而低字节则存放在较高的位置。

网络数据包的获取与libpcap应用

网络数据包的获取与libpcap应用

载波监听
指在以太网中的每个站点都具有同等的权利, 指在以太网中的每个站点都具有同等的权利,在传输自己 的数据时,首先监听信道是否空闲,如果空闲, 的数据时,首先监听信道是否空闲,如果空闲,就传输自 己的数据,如果信道被占用,就等待信道空闲。 己的数据,如果信道被占用,就等待信道空闲。 冲突检测 为了防止发生两个站点同时监测到网络没有被使用时而产 生冲突。以太网采用广播机制 广播机制, 生冲突。以太网采用广播机制,所有与网络连接的工作站 都可以看到网络上传递的数据。 都可以看到网络上传递的数据。
数据包接收过程
二、以太网
以太网最初是由XEROX公司研制 并且在 公司研制,并且在 以太网最初是由 公司研制 并且在1980年由数据 年由数据 设备公司DEC(DIGIAL EQUIPMENT CORPOR ATION)、 设备公司 、 INTEL公司和 公司和XEROX公司共同使之规范成形。后来它被作 公司共同使之规范成形。 公司和 公司共同使之规范成形 802.3标准为电气与电子工程师协会 IEEE)所采纳。 标准为电气与电子工程师协会( 为802.3标准为电气与电子工程师协会(IEEE)所采纳。 以太网是最为流行的网络传输系统之一。 以太网是最为流行的网络传输系统之一。以太网的基本 特征是采用一种称为载波监听多路访问 冲突检测CSMA/CD 载波监听多路访问/冲突检测 特征是采用一种称为载波监听多路访问 冲突检测 (Carrier Sense Multiple Access/ Collision Detection)的 的 共享访问方案。 共享访问方案。
TCP/IP与以太网 TCP/IP与以太网
以太网和TCP/IP可以说是相辅相成的。 可以说是相辅相成的。 以太网和 可以说是相辅相成的 以太网在一二层提供物理上的连线,使用48位的 以太网在一二层提供物理上的连线,使用 位的MAC地址 地址 位的 TCP/IP工作在上层,使用 位的 地址 工作在上层, 位的IP地址 工作在上层 使用32位的 两者间使用ARP和RARP协议进行相互转换。 协议进行相互转换。 两者间使用 和 协议进行相互转换

Libpcap网络抓包(linux C)

Libpcap网络抓包(linux C)

1. 入门使用篇本篇讲述如何抓包最简单的libpcap抓包程序只要有以下几句就可以了char ebuf[PCAP_ERRBUF_SIZE];pcap_t *pd = pcap_open_live("eth0", 68, 0, 1000, ebuf);建立libpcap捕捉句柄,若出错,ebuf返回错误字串.ebuf可以为NULL(以后同)struct bpf_program fcode;pcap_compile(pd, &fcode, NULL, 1, 0);添写过滤规则串fcode,可以为空(即第三个参数,格式在后面讲到)pcap_setfilter(pd, &fcode);给pd 设置上过滤规则pcap_loop(pd, 10, eth_printer, NULL);主循环,开始抓包,共抓10个(由第二个参数指定),抓到包后就进入函数eth_printerpcap_close(pd);结束这个就是最简单的程序了,其中还有个不明,在pcap_loop参数eth_printer的类型是pcap_handler,pcap_handler定义如下: typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,const u_char *);当然要包含#include "pcap.h"编译要加上-lpcap至于怎么得到libpcap,还有安装,我就不费话了本文版权所有:doggy(chaujy@) 欢迎转载2. 使用进阶篇刚才我们对程序的要求是能编译通过,能运行成功现在我们让这个程序实用点吧2.1 其它几个函数介绍这几个函数的特点是简单但无关紧要现在我们隆重退出char * pcap_lookupdev ( char * errbuf );这个函数就是查找本机上的网络接口设备,我机器上就返回"eth0",在pcap_open_live之前用,没什么意思吧,反正我是不爱用它int pcap_lookupnet(char *, bpf_u_int32 *, bpf_u_int32 *, char *);第一个参数就是pcap_lookupdev返回的接口名,二三参数都是32位无符号数, 分别是IP网段和掩码,最后那个参数还是ebufint pcap_datalink(pcap_t *);它返回你的网络类型,如DLT_EN10MB 就是10M以太网int pcap_snapshot(pcap_t *);返回最长抓多少字节,就是我们在pcap_open_live中第二个参数设置的int pcap_stats(pcap_t *, struct pcap_stat *);计数,共抓了多少过滤掉了多少,看看struct pcap_stat的定义就明白了struct pcap_stat {u_int ps_recv; /* number of packets received */u_int ps_drop; /* number of packets dropped */u_int ps_ifdrop; /* drops by interface XXX not yet supported */};int pcap_major_version(pcap_t *);int pcap_minor_version(pcap_t *);版本号,你有用么?我的eth_printer如下void eth_printer(u_char * user, const struct pcap_pkthdr * h, const u_char * p) {printf("I get one packet! ");}简单吧:*)2.2 现在的程序(C++)文件名p.cxx#ifdef __cplusplusextern "C" {#endif#include#ifdef __cplusplus}#endifvoid printer(u_char * user, const struct pcap_pkthdr * h, const u_char * p){printf("I get one packet! ");/* 哈哈,我都想喝一杯庆祝一下了! */}#define DEFAULT_SNAPLEN 68/* 别问我为什么是68,我从tcpdump看来的*/int main(){char ebuf[PCAP_ERRBUF_SIZE];char *device = pcap_lookupdev(ebuf);bpf_u_int32 localnet, netmask;pcap_lookupnet(device, &localnet, &netmask, ebuf);printf("%u.%u.%u.%u", localnet&0xff, localnet>>8&0xff,localnet>>16&0xff, localnet>>24&0xff); /*本地IP网段号*/printf(":%d.%d.%d.%d ", netmask&0xff, netmask>>8&0xff,netmask>>16&0xff, netmask>>24&0xff); /*本地IP掩码*/struct pcap_t *pd = pcap_open_live(device, DEFAUL T_SNAPLEN, 0, 1000, ebuf);if(pcap_datalink(pd) == DLT_EN10MB)printf("10Mb以太网");struct bpf_program fcode;pcap_compile(pd, &fcode, NULL, 1, 0);pcap_setfilter(pd, &fcode);pcap_loop(pd, 10, printer, NULL);struct pcap_stat stat;pcap_stats(pd, &stat);printf("recv %d, drop %d. ", stat.ps_recv, stat.ps_drop);pcap_close(pd);}#gcc p.cxx -lpcap#./a.out166.111.168.0:255.255.252.010Mb以太网I get one packet!I get one packet!I get one packet!I get one packet!I get one packet!I get one packet!I get one packet!I get one packet!I get one packet!I get one packet!recv 10, drop 0.#重要提示: libpcap 程序需要root权限2.3 出错处理象其它库一样,libpcap 也有自己的错误处理机制基本上每个函数都有返回值,出错时返回值<0,另外有如下函数void pcap_perror(pcap_t *, char *);char *pcap_strerror(int);char *pcap_geterr(pcap_t *);前两个和perror() strerror() 用法相同,最后一个也很简单在pcap_t 中有一个成员存了错误字串struct pcap {...char errbuf[PCAP_ERRBUF_SIZE];};所以......于是我们在刚才的程序中加上错误处理先加一个函数#includeint err_quit(const char *fmt, ...){va_list ap;va_start(ap, fmt);vfprintf(stderr, fmt, ap);va_end(ap);exit(-1);}之后处理每个函数的异常,在成功建立捕捉句柄pcap_t *pd前,使用ebuf参数char *device = pcap_lookupdev(ebuf);if(device == NULL)err_quit("%s", ebuf);有了句柄pd后if(pcap_compile(pd, &fcode, NULL, 1, 0) < 0)err_quit("%s", pcap_geterr(pd));注意不是每个函数都是出错返回<0pcap_datalink(pd)和pcap_snapshot(pd)等可不要这么处理2.4 参数初步研究前面使用各函数时,并没有具体说明每个函数的意义,现在来探讨一下pcap_t * pcap_open_live(char *device, int snaplen, int promisc,int to_ms, char *ebuf)device指定设备,snaplen指定最长抓多少字节,ebuf出错信息,前面都说过promisc指出是否设置为混杂模式(不懂?我也不懂,整个网都听还有什么安全性可言) to_ms设置超时时间,单位millisecondsint pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)cnt为要抓的包数,pcap_loop在正常时抓cnt个包后返回,异常时返回值<0user是要传入callback()的数据,例如我们把上面的程序修改几行file://pcap_loop(pd, 10, printer, NULL);pcap_loop(pd, 10, printer, (u_char*)pd);再在printer()内加pcap_stat stat;pcap_stats((pcap_t*)user, &stat);printf("recv %d, drop %d. ", stat.ps_recv, stat.ps_drop);再编译运行后输出为166.111.168.0:255.255.252.010Mb以太网recv 1, drop 0.recv 2, drop 0.recv 3, drop 0.recv 4, drop 0.recv 5, drop 0.recv 6, drop 0.recv 7, drop 0.recv 8, drop 0.recv 9, drop 0.recv 10, drop 0.recv 10, drop 0.int pcap_compile(pcap_t *p, struct bpf_program *program,char *buf, int optimize, bpf_u_int32 mask)该函数用于解析过滤规则串buf,填写bpf_program结构.optimize为1表示对过滤规则进行优化处理netmask指定子网掩码buf的格式比较复杂int pcap_setfilter(pcap_t *handle, struct bpf_program *filter)把pcap_compile()构造的filter设置到handle上。

libpcap原理及优化

libpcap原理及优化
libpcap根据帧大小按顺序读 取缓存区.如果当前帧的数据有 效位被设置,则将该数据包提交 给应用程序处理,在处理完毕以 后,libpcap清除当前帧的有效 位,允许内核再次使用该帧;否 则,libpcap使用poll函数等待数 据包的到达。
相比libpcap1.0之前版本,共享内存缓存队列减少了一次数据包拷贝和调 用recvmsg、退出内核态的系统开销,因此有较大的性能提升
Libpcap原理及优化
Mail : Author : panda-bob
Linux数据包处理流程
具体的Linux数据包处理流程如图 1所示。数据包从网卡经过内核最终 到达用户空间的应用程序,其中经过 三次处理:中断服务、软中断和应用 程序。使用三个缓存:DMA、包队列 和插口。在网卡驱动中存在运行时内 存分配,从内核到用户态时存在一次 内存拷贝。
限制系统数据包的捕获处理能力可能原 因
① 处理流程单一:整个处理流程串行化,其处理能力受限于整个流程的 任何一处“短板”。在多核架构系统中这样的处理方式无法发挥并行 优势,存在极大的资源浪费。
② 高中断服务负荷:由于采用每接收一个数据包就产生一次中断的方式, 当数据包以很高的速率到达时,即使最快的处理器也会被持续的中断 服务请求占用而无法处理数据包,从而导致数据包丢失。
PACKET套接字的两大核心模块
1、BPF(berkeley packet filter)过滤器 BPF根据用户设置的过滤规则计算应该接收的数据包长度值,如果该值比数
据包的长度小,那么数据包将会被截短.特别地,如果该值为0,数据包会被 PACKET套接字丢弃而直接返回协议栈进行网络层的处理.BPF在Linux中,BPF被 用于内核进行数据包过滤,以减小提交给应用程序的数据包的包数和字节数,提 高系统性能。 2、缓存队列(BufferQ)

libpcap主要函数及过程详解

libpcap主要函数及过程详解

libpcap主要函数及过程详解/uid-21556133-id-120228.htmllibpcap(Packet Capture Library),即数据包捕获函数库,是Unix/Linux平台下的⽹络数据包捕获函数库。

它是⼀个独⽴于系统的⽤户层包捕获的API接⼝,为底层⽹络监测提供了⼀个可移植的框架。

⼀、libpcap⼯作原理libpcap主要由两部份组成:⽹络分接头(Network Tap)和数据过滤器(Packet Filter)。

⽹络分接头从⽹络设备驱动程序中收集数据拷贝,过滤器决定是否接收该数据包。

Libpcap利⽤BSD Packet Filter(BPF)算法对⽹卡接收到的链路层数据包进⾏过滤。

BPF算法的基本思想是在有BPF监听的⽹络中,⽹卡驱动将接收到的数据包复制⼀份交给BPF过滤器,过滤器根据⽤户定义的规则决定是否接收此数据包以及需要拷贝该数据包的那些内容,然后将过滤后的数据给与过滤器相关联的上层应⽤程序。

libpcap的包捕获机制就是在数据链路层加⼀个旁路处理。

当⼀个数据包到达⽹络接⼝时,libpcap⾸先利⽤已经创建的Socket从链路层驱动程序中获得该数据包的拷贝,再通过Tap函数将数据包发给BPF过滤器。

BPF过滤器根据⽤户已经定义好的过滤规则对数据包进⾏逐⼀匹配,匹配成功则放⼊内核缓冲区,并传递给⽤户缓冲区,匹配失败则直接丢弃。

如果没有设置过滤规则,所有数据包都将放⼊内核缓冲区,并传递给⽤户层缓冲区。

⼆、libpcap的抓包框架pcap_lookupdev()函数⽤于查找⽹络设备,返回可被pcap_open_live()函数调⽤的⽹络设备名指针。

pcap_open_live()函数⽤于打开⽹络设备,并且返回⽤于捕获⽹络数据包的数据包捕获描述字。

对于此⽹络设备的操作都要基于此⽹络设备描述字。

pcap_lookupnet()函数获得指定⽹络设备的⽹络号和掩码。

pcap_compile()函数⽤于将⽤户制定的过滤策略编译到过滤程序中。

tcpdump原理之利用libpcap实现抓包

tcpdump原理之利用libpcap实现抓包

tcpdump原理之利用libpcap实现抓包tcpdump原理之利用libpcap实现(转载请标明出处,请勿用于商业用途)/linux_embedded/article/details/8826429Linux下赫赫有名的抓吧工具tcpdump,想必使用过的人都十分的清楚。

但是,其实现的原理却很少人提及过,今天就tcpdump的实现原理做简单的介绍。

tcpdump 首先利用libpcap工具,将linux网络栈中的数据包抓取上来,然后,tcpdump在按照用户的需求完成数据包的分析工作。

下面就如何通过libpcap实现数据包的抓取做简单的介绍。

开始:libpcap的使用方式首先,我们需要了解一下pcap 嗅探器使用的一般布局,下面分为几个部分简单介绍。

1.首先我们需要定义我们需要使用的网络接口。

在linux下,我们一般会定义eth0或ethx。

在BSD下,可能是xl1。

我们可以把网络接口定义为字符串,或者可以通过pcap获得可用的网络接口的名字。

2.初始化pcap。

现在,我们可以将我们将要监听的网络设备告诉pcap。

如果有需要的话,我们可以使pcap同时监听多个网络接口。

我们可以通过“文件句柄”来区分不同的网络接口,就像我们打开文件进行文件的读取、写入一样,我们必须定义区分我们的监听“回话”,否则我们没有办法区分不同的监听对象(网络设备)。

3.如果我们仅仅想监听特殊的网络数据(例如,我们想监听TCP 业务,或者我们只想监听端口号为23的业务)。

我们可以自己定义一个监听规则的集合,“编译”它,然后在应用它。

上面三个步骤,连接的十分紧密,那一个步骤都不能丢掉。

规则其实就是定义好的字符串,我们需要将其转化为pcap可以是别的格式(所以我们需要编译)。

“编译器”仅仅通过内置的函数就可以实现上述的格式转换。

然后我们可以告诉pcap执行规则完成数据包的过滤。

4.之后,我们会告诉pcap进入主要的循环执行状态。

Libpcap详细教程

Libpcap详细教程

Libpcap 是 Packet Capture library 的英文缩写,即数据包捕获函数库,该库提供的 C 函数接口用于捕获经过指定网络接口 (通过将网卡设置为混杂模式,可以捕获所有经过该网络接口的数据包 )的数据包。

著名的 TCPDUMP 就是在 Libpcap 的基础上开发而成的, Libpcap 提供的接口函数主要实现和封装了与数据包的采集、构造、发送等有关的功能。

Libpcap 面向上层应用,提供了用户级别的网络数据包捕获接口,在系统部署时充分考虑到应用程序的可以移植性。

Libpcap 主要有如下功能:(1)数据包捕获捕获流经本网卡的所有原始数据包,甚至对交换设备中的数据包也能够进行捕获,本功能是嗅探器的基础。

(2)自定义数据包发送构造任意格式的原始数据包,并发送到目标网络,本功能是新协议验证、甚至攻击验证的基础。

(3)流量采集与统计对所采集到的网络中的流量信息进行按照新规则分类,按指标进行统计,并输出到指定终端。

利用这项功能可以分析目标网络的流量特性。

(4)规则过滤Libpcap 自带规则过滤功能,并提供脚本编程接口,能够按照用户编程的方式对已经采集到的数据包进行过滤,以便提高分析的性能。

Libpcap 的应用范围:由于拥有强大的功能,当前基于 Libpcap 的应用比较广泛,有很多 Unix 上的流量相关的网络系统都是基于 Libpcap 的,它的一些典型应用如下:(1)网络协议分析器Libpcap 应用最多的就是网络协议分析器,也可以称之为网络嗅探。

(2)网络流量发生器网络流量发生器也是 Libpcap 的一大应用,它是基于 Libpcap 的数据构造与发送功能,可以有针对性的构造各种形式的数据包,并执行发送工作,这样的组合便构成了网络流量的产生工具。

(3)网络入侵检测系统网络入侵检测系统(IDS)是发现网络入侵行为的关键,利用 Libpcap 所提供的数据包捕获功能,可以进一步开发出 IDS。

libpcap

libpcap

函数名称:int pcap_setfilter(pcap_t *p, struct bpf_program *fp) 函数功能:指定一个过滤程序。 参数说明:fp参数是bpf_program结构指针,通常取自 pcap_compile()函数调用。出错时返回-1;成功时返回0。 函数名称:u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h) 函数功能:返回指向下一个数据包的u_char指针。
Libpcap库主要函数说明
函数名称:pcap_t *pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) 函数功能:获得用于捕获网络数据包的数据包捕获描述字。 参数说明:device参数为指定打开的网络设备名。snaplen参 数定义捕获数据的最大字节数。promisc指定是否将网络接口 置于混杂模式。to_ms参数指*定超时时间(毫秒)。ebuf参数 则仅在pcap_open_live()函数出错返回NULL时用于传递错误消 息。 函数名称:char *pcap_lookupdev(char *errbuf) 函数功能:用于返回可被pcap_open_live()或pcap_lookupnet() 函数调用的网络设备名指针。参数说明:如果函数出错,则返 回NULL,同时errbuf中存放相关的错误消息。
过滤规则详细说明:
/link?url=OVjyr2tH30n0MnpYM44DlENU7Me2Q5uCwlmj7pkX10m5tFBOBf37y-DPnalckI1pXX9sNm4bvzGma84iSvgngcts3Yzv4_DxtzAFbc r7
开始:pcap应用程序的格式

libpcap简介

libpcap简介

libpcap简介libpcap是unix/linux平台下的网络数据包捕获函数包,大多数网络监控软件都以它为基础。

Libpcap可以在绝大多数类unix平台下工作.Libpcap应用程序框架Libpcap提供了系统独立的用户级别网络数据包捕获接口,并充分考虑到应用程序的可移植性。

Libpcap可以在绝大多数类unix平台下工作,参考资料 A 中是对基于 libpcap 的网络应用程序的一个详细列表。

在windows平台下,一个与libpcap 很类似的函数包 winpcap 提供捕获功能,其官方网站是http://winpcap.polito.it/。

Libpcap 软件包可从 / 下载,然后依此执行下列三条命令即可安装,但如果希望libpcap能在linux上正常工作,则必须使内核支持"packet"协议,也即在编译内核时打开配置选项 CONFIG_PACKET(选项缺省为打开)。

./configure./make./make installlibpcap源代码由20多个C文件构成,但在 Linux系统下并不是所有文件都用到。

可以通过查看命令make的输出了解实际所用的文件。

本文所针对的libpcap版本号为0.8.3,网络类型为常规以太网。

Libpcap应用程序从形式上看很简单.Winpcap是libcap的Windows版本。

一libpcap是一个C语言库,其功能是通过网卡抓取网络以太网中的数据包,在windows系统下有相应的winpcap库。

要想使用这个库自然先要知道它在哪里,怎么安装就不废话了。

在/usr/local/lib下有libpcap.a和libpcao.so,在/usr/local/include下有pcap.h,打开手册的命令是man pcap,而不是man libpcap,如果觉得在字符模式下查看man太麻烦也可以baidu或者google一下"man pcap"会又可读性更高的手册。

libpcap 过滤规则

libpcap 过滤规则

libpcap 过滤规则(最新版)目录1.布局层次结构的定义和重要性2.布局层次结构的基本原则3.如何创建一个有效的布局层次结构4.布局层次结构在实际设计中的应用5.布局层次结构对用户体验的影响正文1.布局层次结构的定义和重要性布局层次结构,也被称为文档对象模型(DOM)层次结构,是在网页设计中用于组织和展示内容的一种方式。

它通过将页面元素按照一定的次序和关系分层排列,使得页面的结构更加清晰,易于阅读和理解。

在网页设计中,布局层次结构对于保证用户体验和搜索引擎优化(SEO)至关重要。

2.布局层次结构的基本原则在创建布局层次结构时,需要遵循以下基本原则:- 保持简单:布局层次结构应当简单明了,避免过多的嵌套关系,以方便用户快速找到所需信息。

- 有明确的导航:布局层次结构应当包含明确的导航元素,如标题、菜单和面包屑导航等,以便用户了解自己在页面中的位置,以及如何访问其他相关内容。

- 保持一致:布局层次结构应当在整站范围内保持一致,以便用户快速适应并找到所需信息。

- 良好的层级关系:布局层次结构应当清晰地呈现页面元素之间的层级关系,便于用户理解页面内容的组织结构。

3.如何创建一个有效的布局层次结构创建有效的布局层次结构需要遵循以下步骤:- 确定页面的主要内容和结构:在设计布局层次结构之前,首先需要明确页面的主要内容和结构,以便更好地组织和展示这些内容。

- 创建页面模板:根据页面内容和结构,创建一个页面模板,用于规范页面元素的排列和显示方式。

- 确定导航元素:在模板中添加导航元素,如标题、菜单和面包屑导航等,以便用户了解自己在页面中的位置,以及如何访问其他相关内容。

- 确定页面元素的层级关系:在模板中明确页面元素的层级关系,如标题、正文、侧边栏等,以便用户快速了解页面内容的组织结构。

- 保持布局层次结构的简单性:在设计布局层次结构时,避免过多的嵌套关系,以保证页面的简洁和易用性。

4.布局层次结构在实际设计中的应用在实际网页设计中,布局层次结构对于保证用户体验和搜索引擎优化(SEO)至关重要。

Linux下Libpcap源码分析及包过滤机制

Linux下Libpcap源码分析及包过滤机制

过滤代码的安装前面我们曾经提到,在内核空间过滤数据包对整个捕获机制的效率是至关重要的。

早期使用 SOCK_PACKET 方式的Linux不支持内核过滤,因此过滤操作只能在用户空间执行(请参阅函数 pcap_read_packet() 代码),在《UNIX 网络编程(第一卷)》(参考资料 B)的第 26 章中对此有明确的描述。

不过现在看起来情况已经发生改变,Linux在 PF_PACKET 类型的 socket 上支持内核过滤。

Linux内核允许我们把一个名为LPF(Linux Packet Filter) 的过滤器直接放到 PF_PACKET 类型 socket 的处理过程中,过滤器在网卡接收中断执行后立即执行。

LSF 基于BPF机制,但两者在实现上有略微的不同。

实际代码如下:/* 在包捕获设备上附加 BPF 代码 [pcap-Linux.c]*/static intpcap_setfilter_Linux(pcap_t *handle, struct bpf_program*filter){#ifdef SO_ATTACH_FILTERstruct sock_fprog fcode;int can_filter_in_kernel;int err = 0;#endif/* 检查句柄和过滤器结构的正确性 */if (!handle)return -1;if (!filter) {strncpy(handle->errbuf, "setfilter: No filter specified",sizeof(handle->errbuf));return -1;}/* 具体描述如下 */if (install_bpf_program(handle, filter) < 0) return -1;/* 缺省情况下在用户空间运行过滤器,但如果在内核安装成功,则值为 1 */handle->e_bpf = 0;/* 尝试在内核安装过滤器 */#ifdef SO_ATTACH_FILTER#ifdef USHRT_MAXif (handle->fcode.bf_len > USHRT_MAX) {/*过滤器代码太长,内核不支持 */fprintf(stderr, "Warning: Filter too complex for kerneln");fcode.filter = NULL;can_filter_in_kernel = 0;} else#endif /* USHRT_MAX */{/* Linux内核设置过滤器时使用的数据结构是 sock_fprog,而不是 BPF 的结构 bpf_program ,因此应做结构之间的转换*/switch (fix_program(handle, &fcode)) {/* 严重错误,直接退出 */case -1:default:return -1;/* 通过检查,但不能工作在内核中 */case 0:can_filter_in_kernel = 0;break;/* BPF 可以在内核中工作 */case 1:can_filter_in_kernel = 1;break;}}/* 如果可以在内核中过滤,则安装过滤器到内核中 */if (can_filter_in_kernel) {if ((err = set_kernel_filter(handle, &fcode)) == 0) {/* 安装成功 !!! */handle->e_bpf = 1;}else if (err == -1) /* 出现非致命性错误 */{if (errno != ENOPROTOOPT && errno != EOPNOTSUPP) { fprintf(stderr, "Warning: Kernel filter failed:%sn",pcap_strerror(errno));}}}/* 如果不能在内核中使用过滤器,则去掉曾经可能在此 socket 上安装的内核过滤器。

libpcap编程-编写自己的网络嗅探程序

libpcap编程-编写自己的网络嗅探程序
一旦我们打开了一个可以捕获数据包的网络接口,我们必须告诉 libpcap 我们想要开始 捕获数据包了。对此,我们有以下选择:
* 函数 const u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h) 将利用由 pcap_open_live 返回的接口描述符 pcap_t,一个指向 pcap_pkthdr 类型的结构体 进行处理后返回第一个到达网络接口的数据包。
******Libpcap*****************************************************************
Libpcap 是一个提供了针对网络数据包捕获系统的高层接口的开源函数库。它是在 1994
年由麦克坎尼(McCanne),莱乐士(Leres)和杰科宾森(Jacobson)创建的。当时他们是美国加洲 柏克利大学劳恩斯国家实验室的研究生,而 Libpcap 正是他们研究和改善 TCP 和英特网网关 功能的一部分成果。Libpcap 作者的主要愿望是开创一个独立平台的应用程序接口(API)以 此消除程序中针对不同操作系统所包含的数据包捕获代码模块,因为通常每一个操作系统商 都会实现他们自己的捕获机制。(也就是解决了移植性的问题,这有利于提高程序员开发的效 率--译者注)
int snaplen, int promisc, int to_ms, char *errbuf) 便可以做到。该函数返回一个 pcap_t 类型的接口描述符,此描述符稍候将会被 libpcap 的其 他函数用到。(与此类似的比如文件描述符--译者注)如果函数调用失败,就返回 NULL. 函数 pcap_open_live()的第一个参数是一个指向包含我们想要打开的网络设备名称的 字符串指针,显然该参数可由 pcap_lookupdev()获得。第二个参数是我们要捕获的数据包的 最大字节数。给这个参数设定一个较小的值在某些情况下也会起到一定作用,比如:我们只 想抓获包头或者是在内存资源紧张的嵌入式系统中的程序编写。通常最大的以太帧大小是 1518 字节。但是其它的链接类型,比如 FDDI 或者是 802.11 有跟大的上限值。65535 这个数 值对于容纳任何网络的任何数据包应该是足够的。 参数 to_ms 定义了在把捕获的数据从内核空间复制到用户空间之前内核应该等待多少个 毫秒。反复地改变缓冲区的内容将严重地消耗昂贵的计算时间。如果我们是在一个繁忙的网 络传输环境中捕获数据包,那么最好是让内核在内核空间和用户空间之间拷贝数据之前先将 数据包聚集,然后一起拷贝。当我们把 to_ms 的值是赋为零时,这将导致读操作将永远进行下 去直到足够的数据包到达网络接口(在拷贝数据之前驱动程序要从网络接口读入数据)。 Libpcap 文档对该参数没有提供任何建议值,不过我们可以通过参考其他的嗅探器程序来获 取一些灵感。Tcpdump 用的是数值 1000,dsniff 用的是数值 512,此外 ettercap 在 linux 或 OpenBSD 操作系统下用数值 0,其他操作系统下用数值 10。

libpcap使用(1)

libpcap使用(1)

libpcap使⽤(1)0x00 Libpcap介绍Libpcap是⼀个开源库,它为⽹络数据包捕获提供了⼀个⾼级接⼝。

Libpcap作者的主要⽬标是创建⼀个独⽴于平台的API,以消除对每个应⽤程序中依赖于系统的数据包捕获模块的需求,因为⼏乎每个操作系统供应商都实现了⾃⼰的捕获机制.libpcap的API被设计⽤来供C和C++使⽤,然后有许多包装器,也可以让 Perl,Python Java C# or Ruby 使⽤。

libpcap能在⼤多数类unix的操作系统上。

还有⼀个名为Winpcap的Windows版本。

如今,libpcap由tcpdump⼩组维护。

0x01 使⽤Libpcap的第⼀步1.我们⾸先需要⼀个⽹络接⼝监听char *pcap_lookupdev(char *errbuf)/*1. 函数返回⼀个指针,该指针指向⼀个字符串,该字符串包含适合包捕获的第⼀个⽹络设备的名称2. errbuf参数是⽤户提供⽤来存储错误信息的*/通常,当最终⽤户没有指定任何⽹络接⼝时,调⽤此函数⽹络接⼝。

使⽤硬编码接⼝名通常是⼀个坏主意,因为它们通常不能跨平台移植。

libpcap实现的许多函数都使⽤errbuf这个参数,⽤来获取错误。

在分配缓冲区时我们必须⼩⼼,因为它必须⾄少能够容纳 PCAP_ERRBUF_SIZE 这么多字节。

我们可以使⽤PCAP_ERRBUF_SIZE这个宏来作为数组的⼤⼩。

2. 打开获取的⽹络接⼝pcap_t *pcap_open_live(const char *device, int snaplen, int promise, int to_ms, char *errbuf)/*参数:1. 该函数的第⼀参数是⼀个字符串,包含要打开⽹络接⼝的名称。

2. 第⼆个参数是要捕获的最⼤字节数。

如果我们只对获取数据头感兴趣或者有限制内存的嵌⼊式编程,那么可以为第⼆个参数设置⼀个较低的值。

3. 第三个参数promise 标志决定了⽹络接⼝是否应该进⼊混杂模式,混杂模式是说⽹卡可以接收不是该⽹卡⽬的地的数据包。

Libpcap库函数详细介绍

Libpcap库函数详细介绍

Libpcap库函数libpcap的英文意思是Packet Capture library,即数据包捕获函数库。

该库提供的C函数接口可用于需要捕获经过网络接口(只要经过该接口,目标地址不一定为本机)数据包的系统开发上。

由Berkeley大学Lawrence Berkeley National Laboratory研究院的Van Jacobson、Craig Leres和Steven McCanne编写。

该函数库支持Linux、Solaris和*BSD系统平台。

主要接口函数说明如下:pcap_t *pcap_open_live(char *device, int snaplen,int promisc, int to_ms, char *ebuf)获得用于捕获网络数据包的数据包捕获描述字。

device参数为指定打开的网络设备名。

snaplen参数定义捕获数据的最大字节数。

promisc指定是否将网络接口置于混杂模式。

to_ms参数指定超时时间(毫秒)。

ebuf参数则仅在pcap_open_live()函数出错返回NULL时用于传递错误消息。

pcap_t *pcap_open_offline(char *fname, char *ebuf)打开以前保存捕获数据包的文件,用于读取。

fname参数指定打开的文件名。

该文件中的数据格式与tcpdump和tcpslice兼容。

"-"为标准输入。

ebuf参数则仅在pcap_open_offline()函数出错返回NULL时用于传递错误消息。

pcap_dumper_t *pcap_dump_open(pcap_t *p, char *fname)打开用于保存捕获数据包的文件,用于写入。

fname参数为"-"时表示标准输出。

出错时返回NULL。

p参数为调用pcap_open_offline()或pcap_open_live()函数后返回的pcap结构指针。

libpcap 过滤规则

libpcap 过滤规则

libpcap 过滤规则
摘要:
1.介绍libpcap
2.libpcap 过滤规则的原理
3.libpcap 过滤规则的语法
4.libpcap 过滤规则的应用示例
5.总结
正文:
1.介绍libpcap
libpcap 是一个用于捕捉网络数据包的库,它支持多种操作系统,如Linux、Windows 和MacOS。

libpcap 提供了一种灵活的方式来捕获和分析网络流量,使得开发人员可以更好地了解网络协议的实现和工作原理。

2.libpcap 过滤规则的原理
在使用libpcap 捕获网络数据包时,可以通过设置过滤规则来仅捕获符合特定条件的数据包。

过滤规则可以帮助我们更有效地分析网络流量,节省系统资源和时间。

libpcap 过滤规则的原理是基于数据包的BPF(Berkeley Packet Filter)表达式,该表达式可以描述数据包的各个方面,如源地址、目标地址、协议类型等。

linux网络libpcap编程指南

linux网络libpcap编程指南
#define TH_OFF(th) (((th)->th_offx2 & 0xf0) >> 4)
u_char th_flags;
#define TH_FIN 0x01
#define TH_SYN 0x02
#define TH_RST 0x04
#define TH_PUSH 0x08
};
再解释一遍:caplen记录的是被打劫银行的损失,len记录的是被打劫银行原有的总资产,因此,len-caplen等于银行没有被打劫的资产.
**********************************
回调函数void got_packet(u_char* args, const pcap_pkthdr* header, const u_char* packet);的三个参数的意义:
#define TH_ACK 0x10
#define TH_URG 0x20
#define TH_ECE 0x40
#define TH_CWR 0x80
#define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)
释放内存: pcap_freealldevs(alldevs);
******************
结构体:
struct pcap_pkthdr {
struct timeval ts; /* time stamp */ // 获取包的时间,timeval记录的是Unix问世到现在的时间,以秒或者微秒为单位..
bpf_u_int32 caplen; /* length of portion present */ // 记录捕获的数据包的长度,由于不能确定截获的是一个完整的数据帧,因此,可以只是截获了帧的一部分,故此,这个值是记录着截获了此帧的多少内容...

第5章 基于Libpcap的网络编程技术

第5章 基于Libpcap的网络编程技术

10
常州大学信息学院
网络编程
Network tap是一个回调函数 (callback function),它实时监视 共享网络中的所有数据包,从网络设 备驱动程序中搜集数据拷贝并转发给 包过滤器。 Packet Filter Filter决定是否接收该数 据包,以及接收该数据包的哪些部分。
11
常州大学信息学院
5
常州大学信息学院
网络编程
包过滤机制实际上是针对数据包的布 尔值操作函数,如果函数最终返回 true, 则通过过滤,反之则被丢弃。形式上包过 滤由一个或多个谓词判断的并操作(AND) 和或操作(OR)构成,每一个谓词判断基 本上对应了数据包的协议类型或某个特定 值,例如,只需要 TCP 类型且目的端口为 110 的数据包。
23
常州大学信息学院
网络编程
int pcap_setfilter(pcap_t *p, struct bpf_program *fp) 该函数用于设置由pcap_compile()函数 解析完毕的过滤规则。 fp参数是bpf_program结构指针,通 常取自pcap_compile()函数调用。出错时返 回-1;成功时返回0。
Libpcap 程序的第一步通常是在系统中找 到合适的网络接口设备。在Linux 中最常见的 接口设备名 eth0 和 lo。 Libpcap 调用 pcap_lookupdev() 函数获 得可用网络接口的设备名。 char *pcap_lookupdev(char *errbuf), 该函数用于返回可被pcap_open_live()或 pcap_lookupnet()函数调用的网络设备名(一 个字符串指针)。如果函数出错,则返回 NULL,同时errbuf中存放相关的错误消息。

libpcap接收数据包(三)

libpcap接收数据包(三)

libpcap接收数据包(三)本文以应用程序的api调用为主线,分析libpcap和pfring源码,当然还有内核PF_RING的源码在以后也会分析,以后可能我会分析从网卡驱动一直分析到应用层,争取把这些都讲清楚。

Linux开源就是好,呵呵,闲话少说,继续分析,首先分析pcap_next函数吧,搞过winp cap的都知道这个是数据包的函数,一次只读一个数据包。

constu_char * pcap_next(pcap_t *p, struct pcap_pkthdr *h){struct oneshot_userdata s;const u_char *pkt;s.hdr = h;s.pkt =&pkt;s.pd = p;if (pcap_dispatch(p,1, p->oneshot_callback, (u_char *)&s) < = 0)return (0);return (pkt);}一看这个函数这么短,大家肯定很开心,呵呵,首先要关注的当然是结构体oneshot_userdata,搜了下,发现在pcap-int.h中定义如下:/** User data structure forthe one-shot callback used for pcap _next()* and pcap_next_ex().*/structoneshot_userdata {struct pcap_pkthdr *hdr;const u_char **pkt;pcap_t *pd;};紧接着就是调用pcap_dispatch函数,这个函数呆会也要讲解的,和pcap_loop 一样,也是用来读取数据包的。

下面看看p->oneshot _callback,这个回调函数在哪里定义的呢?还是整个文件搜索。

发现在我们以前分析过的函数pcap_create_common函数中的initialize_ ops中定义了,所有开始的初始化定义的回调函数是有用的,定义如下:p->oneshot_callback = pcap_oneshot;这就告诉我们,这个回调函数实际上调用的是pcap_oneshot函数;再继续找pcap_oneshot函数吧,定义如下:pcap_oneshot(u_char*user, const struct pcap_pkthdr *h, con st u_ch ar *pkt){struct oneshot_userdata *sp = (structoneshot_userdata *)us er;*sp->hdr = *h;*sp->pkt =pkt;}从这里可以看到pcap_oneshot就是pcap_dispatch调用的函数,而user就是pcap_dispatch最后一个参数传过来的。

黑马程序员:网络编程高级应用—— libpcap 详解

黑马程序员:网络编程高级应用—— libpcap 详解

[C/C++]网络编程高级应用——libpcap 详解概述libpcap 是一个网络数据包捕获函数库,功能非常强大,Linux 下著名的tcpdump 就是以它为基础的。

libpcap主要的作用1)捕获各种数据包,列如:网络流量统计。

2)过滤网络数据包,列如:过滤掉本地上的一些数据,类似防火墙。

3)分析网络数据包,列如:分析网络协议,数据的采集。

4)存储网络数据包,列如:保存捕获的数据以为将来进行分析。

libpcap 的安装libpcap 的抓包框架pcap_lookupdev():函数用于查找网络设备,返回可被pcap_open_live() 函数调用的网络设备名指针。

pcap_lookupnet():函数获得指定网络设备的网络号和掩码。

pcap_open_live():函数用于打开网络设备,并且返回用于捕获网络数据包的数据包捕获描述字。

对于此网络pcap_compile():函数用于将用户制定的过滤策略编译到过滤程序中。

pcap_setfilter():函数用于设置过滤器。

pcap_loop():函数pcap_dispatch() 函数用于捕获数据包,捕获后还可以进行处理,此外pcap_next() 和pc 包。

pcap_close():函数用于关闭网络设备,释放资源。

利用libpcap 函数库开发应用程序的基本步骤:1、打开网络设备2、设置过滤规则3、捕获数据4、关闭网络设备抓包详细步骤首先要使用libpcap,我们必须包含pcap.h 头文件,可以在/usr/local/include/pcap/pcap.h 找到,其中包含了1、获取网络接口设备名char *pcap_lookupdev(char *errbuf);功能:得到可用的网络设备名指针参数:errbuf:存放出错信息字符串,里面有个宏定义:PCAP_ERRBUF_SIZE,为错误缓冲区大小返回值:成功返回设备名指针(第一个合适的网络接口的字符串指针);失败返回 NULL,同时,errbuf 存放出错信息字符串。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

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是.pcap文件中包的头部1.入门使用篇本篇讲述如何抓包最简单的libpcap抓包程序只要有以下几句就可以了char ebuf[PCAP_ERRBUF_SIZE];pcap_t *pd = pcap_open_live("eth0", 68, 0, 1000, ebuf);建立libpcap捕捉句柄,若出错,ebuf返回错误字串.ebuf可以为NULL(以后同)struct bpf_program fcode;pcap_compile(pd, &fcode, NULL, 1, 0);添写过滤规则串fcode,可以为空(即第三个参数,格式在后面讲到)pcap_setfilter(pd, &fcode);给 pd 设置上过滤规则pcap_loop(pd, 10, eth_printer, NULL);主循环,开始抓包,共抓10个(由第二个参数指定),抓到包后就进入函数 eth_printerpcap_close(pd);结束这个就是最简单的程序了,其中还有个不明,在pcap_loop参数 eth_printer的类型是pcap_handler,pcap_handler定义如下:typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,const u_char *);当然要包含#include "pcap.h"编译要加上 -lpcap至于怎么得到libpcap,还有安装,我就不费话了本文版权所有:doggy(chaujy@) 欢迎转载2.使用进阶篇刚才我们对程序的要求是能编译通过,能运行成功现在我们让这个程序实用点吧2.1 其它几个函数介绍这几个函数的特点是简单但无关紧要现在我们隆重退出char * pcap_lookupdev ( char * errbuf );这个函数就是查找本机上的网络接口设备,我机器上就返回"eth0",在pcap_open_live之前用,没什么意思吧,反正我是不爱用它int pcap_lookupnet(char *, bpf_u_int32 *, bpf_u_int32 *, char *);第一个参数就是pcap_lookupdev返回的接口名,二三参数都是32位无符号数, 分别是IP网段和掩码,最后那个参数还是ebufint pcap_datalink(pcap_t *);它返回你的网络类型,如 DLT_EN10MB 就是10M以太网让人ft氖钦庑┏A慷ㄒ宀辉趐cap.h中,在哪?自己找找吧;-)int pcap_snapshot(pcap_t *);返回最长抓多少字节,就是我们在pcap_open_live中第二个参数设置的int pcap_stats(pcap_t *, struct pcap_stat *);计数,共抓了多少过滤掉了多少,看看struct pcap_stat的定义就明白了struct pcap_stat {u_int ps_recv; /* number of packets received */u_int ps_drop; /* number of packets dropped */u_int ps_ifdrop; /* drops by interface XXX not yet supported */};int pcap_major_version(pcap_t *);int pcap_minor_version(pcap_t *);版本号,你有用么?我的eth_printer如下void eth_printer(u_char * user, const struct pcap_pkthdr * h, const u_char * p) {printf("I get one packet! ");}简单吧 :*)2.使用进阶篇刚才我们对程序的要求是能编译通过,能运行成功现在我们让这个程序实用点吧2.1 其它几个函数介绍这几个函数的特点是简单但无关紧要现在我们隆重退出char * pcap_lookupdev ( char * errbuf );这个函数就是查找本机上的网络接口设备,我机器上就返回"eth0",在pcap_open_live之前用,没什么意思吧,反正我是不爱用它int pcap_lookupnet(char *, bpf_u_int32 *, bpf_u_int32 *, char *);第一个参数就是pcap_lookupdev返回的接口名,二三参数都是32位无符号数,分别是IP网段和掩码,最后那个参数还是ebufint pcap_datalink(pcap_t *);它返回你的网络类型,如 DLT_EN10MB 就是10M以太网让人ft的是这些常量定义不在pcap.h中,在哪?自己找找吧;-)int pcap_snapshot(pcap_t *);返回最长抓多少字节,就是我们在pcap_open_live中第二个参数设置的int pcap_stats(pcap_t *, struct pcap_stat *);计数,共抓了多少过滤掉了多少,看看struct pcap_stat的定义就明白了struct pcap_stat {u_int ps_recv; /* number of packets received */u_int ps_drop; /* number of packets dropped */u_int ps_ifdrop; /* drops by interface XXX not yet supported */};int pcap_major_version(pcap_t *);int pcap_minor_version(pcap_t *);版本号2.2 现在的程序(C++)文件名p.cxx#ifdef __cplusplusextern "C" {#endif#include#ifdef __cplusplus}#endifvoid printer(u_char * user, const struct pcap_pkthdr * h, const u_char * p) {printf("I get one packet! ");/* 哈哈,我都想喝一杯庆祝一下了! */}#define DEFAULT_SNAPLEN 68/* 别问我为什么是68,我从tcpdump看来的 */int main(){char ebuf[PCAP_ERRBUF_SIZE];char *device = pcap_lookupdev(ebuf);bpf_u_int32 localnet, netmask;pcap_lookupnet(device, &localnet, &netmask, ebuf);printf("%u.%u.%u.%u", localnet&0xff, localnet>>8&0xff,localnet>>16&0xff, localnet>>24&0xff);printf(":%d.%d.%d.%d ", netmask&0xff, netmask>>8&0xff,netmask>>16&0xff, netmask>>24&0xff);struct pcap_t *pd = pcap_open_live(device, DEFAULT_SNAPLEN, 0, 1000, ebuf);if(pcap_datalink(pd) == DLT_EN10MB)printf("10Mb以太网 ");struct bpf_program fcode;pcap_compile(pd, &fcode, NULL, 1, 0);pcap_setfilter(pd, &fcode);pcap_loop(pd, 10, printer, NULL);struct pcap_stat stat;pcap_stats(pd, &stat);printf("recv %d, drop %d. ", stat.ps_recv, stat.ps_drop);pcap_close(pd);}#gcc p.cxx -lpcap#./a.out166.111.168.0:255.255.252.010Mb以太网I get one packet!I get one packet!I get one packet!I get one packet!I get one packet!I get one packet!I get one packet!I get one packet!I get one packet!I get one packet!recv 10, drop 0.#重要提示: libpcap 程序需要root权限2.3 出错处理象其它库一样,libpcap 也有自己的错误处理机制基本上每个函数都有返回值,出错时返回值<0,另外有如下函数void pcap_perror(pcap_t *, char *);char *pcap_strerror(int);char *pcap_geterr(pcap_t *);前两个和 perror() strerror() 用法相同,最后一个也很简单在 pcap_t 中有一个成员存了错误字串struct pcap {...char errbuf[PCAP_ERRBUF_SIZE];};所以......于是我们在刚才的程序中加上错误处理先加一个函数#includeint err_quit(const char *fmt, ...){va_list ap;va_start(ap, fmt);vfprintf(stderr, fmt, ap);va_end(ap);exit(-1);}之后处理每个函数的异常,在成功建立捕捉句柄pcap_t *pd前,使用ebuf参数char *device = pcap_lookupdev(ebuf);if(device == NULL)err_quit("%s", ebuf);有了句柄pd后if(pcap_compile(pd, &fcode, NULL, 1, 0) < 0)err_quit("%s", pcap_geterr(pd));注意不是每个函数都是出错返回<0pcap_datalink(pd)和pcap_snapshot(pd)等可不要这么处理2.4 参数初步研究前面使用各函数时,并没有具体说明每个函数的意义,现在来探讨一下pcap_t * pcap_open_live(char *device, int snaplen, int promisc,int to_ms, char *ebuf)device指定设备,snaplen指定最长抓多少字节,ebuf出错信息,前面都说过promisc指出是否设置为混杂模式(不懂?我也不懂,整个网都听还有什么安全性可言)to_ms设置超时时间,单位millisecondsint pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)cnt为要抓的包数,pcap_loop在正常时抓cnt个包后返回,异常时返回值<0 user是要传入callback()的数据,例如我们把上面的程序修改几行file://pcap_loop(pd, 10, printer, NULL);pcap_loop(pd, 10, printer, (u_char*)pd);再在printer()内加pcap_stat stat;pcap_stats((pcap_t*)user, &stat);printf("recv %d, drop %d. ", stat.ps_recv, stat.ps_drop);再编译运行后输出为166.111.168.0:255.255.252.010Mb以太网recv 1, drop 0.recv 2, drop 0.recv 3, drop 0.recv 4, drop 0.recv 5, drop 0.recv 6, drop 0.recv 7, drop 0.recv 8, drop 0.recv 9, drop 0.recv 10, drop 0.recv 10, drop 0.int pcap_compile(pcap_t *p, struct bpf_program *program,char *buf, int optimize, bpf_u_int32 mask)该函数用于解析过滤规则串buf,填写bpf_program结构. optimize为1表示对过滤规则进行优化处理netmask指定子网掩码buf的格式比较复杂int pcap_setfilter(pcap_t *handle, struct bpf_program *filter) 把pcap_compile()构造的filter设置到handle上。

相关文档
最新文档