Packet Capture Roughly means, to grab a copy of packets off of the wire before they are processed by the operating system.
数据包捕获是指,在操作系统处理数据包之前从网络上获取数据包的副本。
#include
or
#include
获取捕获设备列表,并释放该列表.
#include
char errbuf[PCAP_ERRBUF_SIZE] = { 0 };
int pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf);
void pcap_freealldevs(pcap_if_t *alldevs);
pcap_findalldevs()
构建了一个网络设备列表,可以使用pcap_create()
和 pcap_activate()
或 pcap_open_live()
打开这些设备。
如果pcap_findalldevs()
成功,则alldevsp
指向的指针将设置为指向列表的第一个元素,如果未找到设备,则设置为NULL
(这被视为成功).
列表的每个元素的类型为pcap_if_t
,并具有以下成员:
pcap_open_live()
的设备的名称pcap_addr_t
,并具有以下成员:
struct sockaddr
的指针struct sockaddr
的指针,该结构包含与addr指向的地址对应的网络掩码.struct sockaddr
的指针,该结构包含与addr指向的地址相对应的广播地址;如果设备不支持广播,则可能为空.struct sockaddr
的指针,该结构包含与addr指向的地址相对应的目标地址;如果设备不是点对点接口,则可以为空.CONNECTION_STATUS
的可能值为:
pcap_findalldevs()
成功时返回0,失败时返回PCAP_ERROR
;如前所述,没有发现设备被视为成功,而不是失败,因此在这种情况下将返回0。如果返回PCAP_ERROR
,则errbuf将填充适当的错误消息。errbuf被假定为能够容纳至少PCAP_ ERRBEF_SIZE
个字符。
必须使用pcap_freealldevs()
释放设备列表,这将释放alldevs
指向的列表。
注意,可能存在调用
pcap_findalldevs()
的进程无法打开的网络设备,例如,该进程没有足够的权限打开它们以进行捕获;如果是,这些设备将不会出现在列表中。
打开用于捕获的设备.
#include
char errbuf[PCAP_ERRBUF_SIZE] = { 0 };
pcap_t *pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, char *errbuf);
pcap_open_live()
用于获取数据包捕获句柄,以查看网络上的数据包。
device
是指定要打开的网络设备的字符串(在具有2.2或更高版本内核的Linux系统上,可以使用设备参数“any”或NULL从所有接口捕获数据包)。snaplen
指定要在句柄上设置的快照长度。promisc
指定是否将接口置于混杂模式。如果promisc为非零,将设置混杂模式,否则不会设置。to_ms
将数据包缓冲超时指定为非负值,以毫秒为单位。pcap_open_live()
在成功时返回一个pcap_ t *
,在失败时返回NULL。如果返回NULL,则用适当的错误消息填充errbuf。当pcap_open_live()
成功时,errbuf也可以设置为警告文本;要检测这种情况,调用方应在调用pcap_open_live()
之前将零长度字符串存储在errbuf中,如果errbuf不再是零长度字符串,则向用户显示警告。errbuf被假定为能够容纳至少PCAP_ ERRBEF_SIZE
大小的字符。
查找设备的IPv4网络号和网络掩码
#include
char errbuf[PCAP_ERRBUF_SIZE] = { 0 };
int pcap_lookupnet(const char *device, bpf_u_int32 *netp, bpf_u_int32 *maskp, char *errbuf);
pcap_lookupnet()
用于确定与网络设备设备关联的IPv4网络号和掩码。
netp
和maskp
都是bpf_u_int32 类型的指针。
pcap_lookupnet()
成功时返回0,失败时返回PCAP_ERROR。如果返回PCAP_ERROR,则errbuf将填充适当的错误消息。errbuf被假定为能够容纳至少PCAP_ ERRBEF_SIZE
个字符。
编译一个筛选表达式
#include
int pcap_compile(pcap_t *p, struct bpf_program *fp, const char *str, int optimize, bpf_u_int32 netmask);
pcap_compile()
用于将字符串str编译成过滤程序。
fp
是指向struct bpf_program
的指针,由pcap_compile()
填充。
optimize
控制是否对结果代码执行优化.
netmask
网络掩码指定正在捕获数据包的网络的IPv4网络掩码;仅当在筛选程序中检查IPv4广播地址时使用。
pcap_compile()
成功时返回0,失败时返回PCAP_ERROR
。如果返回了PCAP_ERROR
,则可以使用p作为参数调用pcap_ geterr
或pcap_perror
,以获取或显示错误文本。
包过滤器语法
…
设置过滤器
#include
int pcap_setfilter(pcap_t *p, struct bpf_program *fp);
pcap_setfilter()
用于指定过滤程序。fp
是指向struct bpf_program
的指针,通常是调用pcap_compile()
的结果。
pcap_setfilter()
在成功时返回0,如果在已创建但未激活的捕获句柄上调用,则返回PCAP_ERROR_NOT_ACTIVATED
,或在其他错误上返回PCAP_ERROR
。如果返回了PCAP_ERROR
,则可以使用p作为参数调用pcap_ geterr
或pcap_perror
,以获取或显示错误文本。
从pcap_t
读取下一个数据包
#include
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_pkthdr
结构 ,并将pkt_data
参数指向的指示器设置为指向该数据包中的数据。
结构pcap_pkthdr
和pkt_data
不会被调用方释放,并且不能保证在下一次调用pcap_ next_ex()
、pcap_next()
、pcap_loop()
或pcap_dispatch()
后有效;如果代码需要它们保持有效,则必须复制它们。
pcap_next()
读取下一个数据包(通过使用cnt为1调用pcap_ dispatch()
),并返回指向该数据包中数据的u_char
指针。数据包数据不会被调用方释放,并且不能保证在下一次调用pcap_ next_ex()
、pcap_next()
、pcap_loop()
或pcap_dispatch()
后有效;如果代码需要它们保持有效,则必须复制它们。由h指向的pcap_ pkthdr
被设置为指向数据包的pcap_pkthdr
结构 。
pcap_next_ex()
,如果数据包读取没有问题返回1;如果从实时捕获中读取数据包,并且数据包缓冲超时已过期,则返回0;如果从“保存文件”读取数据包并且没有更多数据包可从保存文件中读取,如果在已创建但未激活的捕获句柄上调用,则返回PCAP_ ERROR_BREAK;如果在已创建但未激活的捕获句柄上调用,则返回PCAP_ERROR_NOT_ACTIVATED;如果在读取数据包时发生错误,则为PCAP_ ERROR。
如果返回了PCAP_ERROR
,则可以使用p作为参数调用pcap_ geterr
或pcap_perror
,以获取或显示错误文本。
pcap_next()
在成功时返回指向分组数据的指针,如果发生错误则返回NULL。
处理实时捕获或保存文件中的数据包
#include
typedef void (*pcap_handler)(u_char *user, const struct pcap_pkthdr *h,const u_char *bytes);
int pcap_loop(pcap_t *p, int cnt,pcap_handler callback, u_char *user);
int pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user);
pcap_dispatch()处理来自实时捕获或“savefile”的数据包,直到处理cnt数据包,在执行实时捕获时达到当前数据包缓冲区的结尾,在读取“savefile”时达到“savefile”的结尾。在某些平台上进行实时捕获时,如果在没有数据包可用时读取超时过期,则pcap_dispatch()将返回0,即使不处于非阻塞模式,因为没有数据包要处理。应用程序应该为这种情况的发生做好准备,但不能依赖于它的发生。
pcap_loop()处理来自实时捕获或“savefile”的数据包,直到cnt数据包被处理、从“”读取时到达“savefile”的结尾、调用pcap_ breakloop或发生错误。当实时数据包缓冲区超时时,它不会返回。cnt的值-1或0相当于无穷大,因此数据包将被处理,直到出现另一个结束条件。
callback指定要用三个参数调用的pcap_handler例程:在用户参数中传递给pcap_loop()或pcap_ dispatch()的u_char指针、指向数据包时间戳和长度的const struct pcapupkthdr指针,char指针(如结构pcap_ pkthdr中给出的。结构pcap_pkthdr和分组数据不会被回调例程释放,并且在回调例程返回后不保证有效;如果代码需要它们在回调后有效,则必须复制它们。
如果cnt已用尽,或者从“保存文件”读取时,没有更多数据包可用,则pcap_loop()返回0。如果在处理任何数据包之前调用PCAP_breakloop()导致循环终止,则返回PCAP_ERROR_BREAK;如果在已创建但未激活的捕获句柄上调用,则返回PCAP_ ERROR_ NOT_ACTIVATED;如果发生另一个错误,则返回PCAP_errors。当实时数据包缓冲区超时发生时,它不返回;相反,它尝试读取更多数据包。