libpcap中主要函数使用介绍


pcap_compile

使用方法

#include<pcap.h>

int pcap_comile(pcap_t *p,struct bpf_program *fp,const char *str,int optimize, bpf_u_int32 netmask);

参数及函数说明

这个函数将str编译为一个过滤程序(filter program),str的语法在pcap-filter中进行了定义。fp是一个指向bpf_program结构体的指针,其存储了执行函数后的pcap过滤器结构。optimize控制是否对resulting code执行优化(1代表进行优化,0代表不进行优化)。netmask指定包捕获时对应网络的IPv4子网掩码,它仅在检查过滤程序中的IPv4广播地址时才会使用。If the netmask of the network on which packets are being captured isn’t known to the program, or if packets are being captured on the Linux “any” pseudo-interface that can capture on more than one network, a value of PCAP_NETMASK_UNKNOWN can be supplied; tests for IPv4 broadcast addresses will fail to compile, but all other tests in the filter program will be OK

返回值

当函数成功执行时,返回0,否则会返回PCAP_ERROR(-1)。如果返回了PCAP_ERROR,pcap_geterr(3PCAP) or pcap_perror(3PCAP) may be called with p as an argument to fetch or display the error text.

参考


pcap-filter

pcap_compile用于将一个字符串编译成一个filter program。最终获取的filter program可以被用于一些stream of packet,进而判断这些包是提供给pcap_loop(3PCAP),pcap_dispatch(3PCAP),pcap_next(3PCAP)还是pcap_next_ex(3PCAP)。

filter expression由一个或多个primitive组成。Primitives usually consist of an id (name or number) preceded by one or more qualifiers.总共有如下三种qualifier:

  • type:type qualifier表示id name或number所指的类型。可能的类型有host、net、port和portrange。例如,“host foo”、“net 128.3”、“port 20”、“portrange 6000-6008”。如果没有type qualifier,则假定其为host。
  • dir:dir qualifiers specify a particular transfer direction to and/or from id. Possible directions are src, dst, src or dst, src and dst, ra, ta, addr1, addr2, addr3, and addr4. E.g., src foo',dst net 128.3’, src or dst port ftp-data'. If there is no dir qualifier,src or dst’ is assumed. The ra, ta, addr1, addr2, addr3, and addr4 qualifiers are only valid for IEEE 802.11 Wireless LAN link layers.
  • proto:proto qualifiers restrict the match to a particular protocol. Possible protos are: ether, fddi, tr, wlan, ip, ip6, arp, rarp, decnet, tcp and udp. E.g., ether src foo',arp net 128.3’, tcp port 21',udp portrange 7000-7009’, wlan addr2 0:2:3:4:5:6'. If there is no proto qualifier, all protocols consistent with the type are assumed. E.g.,src foo’ means (ip or arp or rarp) src foo' (except the latter is not legal syntax),net bar’ means (ip or arp or rarp) net bar' andport 53’ means `(tcp or udp) port 53’.

[fddi is actually an alias for ether; the parser treats them identically as meaning ``the data link level used on the specified network interface’’. FDDI headers contain Ethernet-like source and destination addresses, and often contain Ethernet-like packet types, so you can filter on these FDDI fields just as with the analogous Ethernet fields. FDDI headers also contain other fields, but you cannot name them explicitly in a filter expression.

Similarly, tr and wlan are aliases for ether; the previous paragraph’s statements about FDDI headers also apply to Token Ring and 802.11 wireless LAN headers. For 802.11 headers, the destination address is the DA field and the source address is the SA field; the BSSID, RA, and TA fields aren’t tested.]

In addition to the above, there are some special `primitive’ keywords that don’t follow the pattern: gateway, broadcast, less, greater and arithmetic expressions. All of these are described below.

More complex filter expressions are built up by using the words and, or and not (or equivalently: &&',||’ and !' respectively) to combine primitives. E.g.,host foo and not port ftp and not port ftp-data’. To save typing, identical qualifier lists can be omitted. E.g., tcp dst port ftp or ftp-data or domain' is exactly the same astcp dst port ftp or tcp dst port ftp-data or tcp dst port domain’.

可使用的primitive有:

  • dst host host:当IPv4/v6的destination field是host时为真,host可以为address或name
  • src host host:当IPv4/v6的source field是host是为真
  • host host:当IPv4/v6的source或destination为host时为真
    Any of the above host expressions can be prepended with the keywords, ip, arp, rarp, or ip6 as in:
    ip host host
    这和如下的形式等同:
    ether proto \ip and host host
    如果host是一个有着多个IPv4地址的name,那么每个地址都会被检查看是否符合匹配
  • ether dst ehost:如果Ethernet的destination地址为ehost时为真。Ehost可以是一个来自于/etc/ethers的name,也可以是数字化表示的MAC地址,形式为"xx:xx:xx:xx:xx:xx", “xx.xx.xx.xx.xx.xx”, “xx-xx-xx-xx-xx-xx”, “xxxx.xxxx.xxxx”, “xxxxxxxxxxxx”, or various mixes of ‘:’, ‘.’, and ‘-’, where each “x” is a hex digit (0-9, a-f, or A-F).
  • ether src ehost:True if the Ethernet source address is ehost.
  • ether host ehost:True if either the Ethernet source or destination address is ehost.
  • gateway host:当包用host作为gateway时为真。例如,Ethernet source或destination address为host但IP source和IP destination都不是host。Host must be a name and must be found both by the machine’s host-name-to-IP-address resolution mechanisms (host name file, DNS, NIS, etc.) and by the machine’s host-name-to-Ethernet-address resolution mechanism (/etc/ethers, etc.). (An equivalent expression is
    ether host ehost and not host host
    which can be used with either names or numbers for host / ehost.) This syntax does not work in IPv6-enabled configuration at this moment.
  • dst net net
  • portrange port1-port2:当包的source或destination port在port1port2之间时为真(port1port2这两个值包含在内)。
    Any of the above port or port range expressions can be prepended with the keywords, tcp or udp, as in:
    tcp src port port
    这种情况下只匹配source port为port的TCP包

参考:

https://www.tcpdump.org/manpages/pcap-filter.7.html


pcap_lookupdev

char *pcap_lookupdev(char *errbuf)

返回第一个合适的,可被pcap_open_live()或pcap_lookupnet()函数调用的网络设备名指针。如果函数出错,则返回NULL,同时errbuf中存放相关的错误消息。


pcap_lookupnet

使用方法

#include<pcap.h>

char errbuf[PCAP_ERRBUF_SIZE];

int pcap_lookupnet(const char *device,bpf_u_int32 *netp, bpf_u_int32 *maskp, char *errbuf);

函数简介及参数

pcap_lookupnet()函数用于获取和网卡device绑定的IPv4 网络号(number)和子网掩码(mask)。netp以及maskp都是bpf_u_int32指针。

网络号和子网掩码都是以网络字节序存放的,比如一个IP为10.108.20.0,那么netp中存放的这个地址就是1338378。转化为二进制表示形式为:

数据的高位------------------>数据的低位
00000000 00010100 01101100 00001010

网络字节序采用大端表示,而主机字节序有用大端表示,也有用小端表示,因此要进行一步转化。

采用小端编址时,上面的数据为:

00001010 01101100 00010100 00000000

返回值

函数执行成功时返回0,执行失败时返回PCAP_ERROR(-1)。如果返回了PCAP_ERROR,此时errbuf会用适当的错误信息进行填充。

参考:

https://www.tcpdump.org/manpages/pcap_lookupnet.3pcap.html


pcap_loop

int pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)

其功能基本与pcap_dispatch()函数相同,但是多了一个cnt参数,这个参数告知pcap_loop应该嗅探到多少个包后返回(一个负值的含义是它应该一直嗅探,直到错误发生)。调用pcap_breakloop()函数也可以终止pcap_loop的执行。

第三个参数是一个回调函数指针,它必须是如下的形式:

void callback(u_char * userarg, const struct pcap_pkthdr * pkthdr, const u_char * packet)

其第一个参数是pcap_loop的最后一个参数,当收到足够数量的包后pcap_loop会调用callback回调函数,同时将pcap_loop的user参数传递给它。第二个参数是收到的数据包的pcap_pkthdr类型的指针,第三个参数是收到的数据包的数据。注意这个函数的返回值为void,因为pcap_loop()不知道如何处理一个回调返回值。


pcap_next

u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h)

第二个参数是保存收到的第一个数据包的pcap_pkthdr类型的指针。同时函数返回指向下一个数据包的u_char指针。


PCAP_NEXT_EX

使用方法

#include<pcap/pcap.h>

int pcap_next_ex(pcap_t *p,struct pcap_pkthdr **pkt_header,const u_char **pkt_data);

const u_char *pcap_next(pcap_t *p,struct pcap_pkthdr *h);

使用简介及参数

pcap_next_ex()读取下一个包并且会返回函数是否执行成功。如果读取包没有发生错误,那么pkt_header所指向的指针会被设定为指向这个包的pcap_pkhdr结构体,同时pkt_data所指向的指针会被设定为指向包中的数据部分。注意,结构体pcap_pkthdr以及包数据并不由调用者进行释放,同时它们也不保证在下次调用pcap_next_ex(), pcap_next(), pcap_loop(3PCAP), or pcap_dispatch(3PCAP)时仍有效,所以使用者在获取到了这个信息后,需要自己将信息进行拷贝。

pcap_next()函数读取下一个包(通过调用pcap_dispath()函数,其中cnt为1)并且返回一个u_char指针指向这个包中的数据部分。包中的数据不由调用者释放,同时它们也不保证在下次调用pcap_next_ex(), pcap_next(), pcap_loop(3PCAP), or pcap_dispatch(3PCAP)时仍有效,所以使用者在获取到了这个信息后,需要自己将信息进行拷贝。h指针指向的pcap_pkhdr数结构is filled with the appropriate values for the packet。

包中的数据字节以一个链路层首部为开始。链路层首部的格式由pcap_datalink(3PCAP)程序指明when handed the pcap_t value also passed to pcap_loop() or pcap_dispatch(). https://www.tcpdump.org/linktypes.html列出了pcap_datalink()可能返回的值并描述了和这些值对应的包的格式。 The value it returns will be valid for all packets received unless and until pcap_set_datalink(3PCAP) is called; after a successful call to pcap_set_datalink(), all subsequent packets will have a link-layer header of the type specified by the link-layer header type value passed to pcap_set_datalink().

Do NOT assume that the packets for a given capture or savefile will have any given link-layer header type, such as DLT_EN10MB for Ethernet. For example, the “any” device on Linux will have a link-layer header type of DLT_LINUX_SLL or DLT_LINUX_SLL2 even if all devices on the system at the time the “any” device is opened have some other data link type, such as DLT_EN10MB for Ethernet.

通过试验,在调用pcap_next_ex()之后系统会分配一部分内存(大概有500KB左右)供其使用,返回的报文内容存放在这部分内存中,不过这只是暂存,不可能将大量的数据内容放在这一部分内容中;通过调试后可以看到,pcap_next_ex()将返回的报文内容线性的存储在这一部分内存中,当数据量占满了这部分内存后,会从开始位置覆盖原有数据,所以如果想要保存报文内容,需要写入本地文件或者另外开辟内存空间存储。

返回值

当函数成功执行时并读取到包信息时,pcap_next_ex()返回1,0 if packets are being read from a live capture and the packet buffer timeout expired, PCAP_ERROR if an error occurred while reading the packet, and PCAP_ERROR_BREAK if packets are being read from a ``savefile’’ and there are no more packets to read from the savefile. If PCAP_ERROR is returned, pcap_geterr(3PCAP) or pcap_perror(3PCAP) may be called with p as an argument to fetch or display the error text.

pcap_next() returns a pointer to the packet data on success, and returns NULL if an error occurred, or if no packets were read from a live capture (if, for example, they were discarded because they didn’t pass the packet filter, or if, on platforms that support a packet buffer timeout that starts before any packets arrive, the timeout expires before any packets arrive, or if the file descriptor for the capture device is in non-blocking mode and no packets were available to be read), or if no more packets are available in a ``savefile.’’ Unfortunately, there is no way to determine whether an error occurred or not.

参考


pcap_open_live

pcap_t *pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)

获得用于捕获网络数据包的数据包捕获句柄。

  • device参数为指定打开的网络设备名(即网卡,在Linux 2.2及以后的版本中这个参数传入"any"或NULL可以被用于在所有接口上获取包)。
  • snaplen参数定义捕获数据的最大字节数(我们可以设置这个值来只抓每个数据包的首部,而不关心具体内容)。如果这个值小于被捕获的数据包的大小,则只显示前snaplen位
  • promisc参数指定是否打开混杂模式。如果打开混杂模式,那么网卡必须也要打开混杂模式,可以使用如下的命令打开eth0混杂模式:
    ifconfig eth0 promisc
  • to_ms参数指定需要等待的毫秒数(0代表不设置超时;在某些平台上,设置这个参数代表着我们可以在这个时间内获取一定的包后一起返回,所以建议使用一个非零值)
  • ,超过这个数值后,pcap_next等函数就会立即返回,0表示一直等待到有数据包到来。这是一个非负值,单位为millisecond。这个参数的含义是让捕捉程序没有必要看到一个数据包就返回,而是设定一个返回时间,这个时间内可能读取很多个数据包,然后一起返回
  • ebuf参数则仅在pcap_open_live()函数出错返回NULL时用于传递错误消息。

混杂模式与非混杂模式的区别:一般来说,非混杂模式的嗅探器中,主机仅嗅探那些跟它直接有关的通信,如发向它的,从它发出的,或经由它路由的等都会被嗅探器捕捉。而在混杂模式中则嗅探传输线路上的所有通信。在非交换式网络中,这将是整个网络的通信。这样做最明显的优点是使更多的包被嗅探到,但是在高负荷的网络中,主机的系统资源将消耗的非常严重。

函数成功执行时返回一个pcap_t*指针,如果函数执行失败,返回NULL。


PCAP_SETFILTER

#include<pcap.h>

int pcap_setfilter(pcap_t *p, struct bpf_program *fp);

参数及使用说明

这个函数用于指定一个过滤程序(filter program)。fp是一个指向bpf_program结构体的指针,通常是调用pcap_compile()函数后返回的值。p通常是pcap_open_live()函数返回的结果。

返回值

函数执行成功时返回0,执行失败时返回PCAP_ERROR。
If PCAP_ERROR is returned, pcap_geterr(3PCAP) or pcap_perror(3PCAP) may be called with p as an argument to fetch or display the error text.

参考


pcap_set_immediate_mode

int pcap_set_immediate_mode(pcap_t *p,int immediate_mode);

pcap_set_immediate_mode将一个没有激活的捕获句柄设定为immediate模式。在immediate模式下,包在它们到达时就被送达而不经过缓存。如果immediate_mode参数非零,那么会将句柄设定为immediate模式,否则不会设定为immediate模式。

当函数执行成功时返回0,当对一个已经激活的句柄调用这个函数时会返回PCAP_ERROR_ACTIVATED

https://www.tcpdump.org/manpages/pcap_set_immediate_mode.3pcap.html


pcap_setnonblock

int pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf);

当参数nonblock为非零值时,函数将一个捕获句柄设置为非阻塞模式,而当参数nonblock为0时取消一个捕获句柄的非阻塞模式。它对于“savefiles”没有影响。

在非阻塞模式下,任何尝试从捕获文件描述符中获取信息的pcap_dispatch、pcap_next_ex以及pcap_loop等函数,在当前没有可读包时,会立即返回0而不是一直阻塞等待新包的到来(如果是阻塞模式那么这些函数会一直阻塞到新包的到来)。(但是实验测试对pcap_next_ex函数,这个函数的设定是无效的,pcap_next_ex仍然会阻塞直到新包的到来)

pcap_loop(3PCAP) will loop forever, consuming CPU time when no packets are currently available; pacp_dispatch() should be used instead. pcap_next(3PCAP) will return NULL if there are no packets currently available to read; this is indistinguishable from an error, so pcap_next_ex() should be used instead.

当首次利用pcap_activate激活一个句柄或使用pcap_open_live打开一个句柄时,这个捕获句柄并未处于非阻塞模式,此时我们需要调用pcap_setnonblock来将它置于非阻塞模式。

当函数执行成功时返回0,失败时返回-1。

pcap_getnonblock()返回当前捕获文件描述符是否位于非阻塞状态,它对于“savefile”总返回0。如果发生了错误,那么那么返回PCAP_ERROR并且将错误信息填充进errbuf。

pcap简单使用和简单解释

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值