2023年7月23日发(作者:)
【转】libpcap库函数介绍(附源代码)libpcap的英⽂意思是 Packet Capture library,即数据包捕获函数库。该库提供的C函数接⼝可⽤于需要捕获经过⽹络接⼝(只要经过该接⼝,⽬标地址不⼀定为本机)数据包的系统开发上。由 Berkeley⼤学Lawrence Berkeley National Laboratory研究院的VanJacobson、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结构指针。fname参数指定打开 的⽂件名。如果返回NULL,则可调⽤pcap_geterr()函数获取错误消 息。char *pcap_lookupdev(char *errbuf) ⽤于返回可被pcap_open_live()或pcap_lookupnet()函数调⽤的⽹络 设备名指针。如果函数出错,则返回NULL,同时errbuf中存放相关的 错误消息。int pcap_lookupnet(char *device, bpf_u_int32 *netp, bpf_u_int32 *maskp, char *errbuf) 获得指定⽹络设备的⽹络号和掩码。netp参数和maskp参数都是 bpf_u_int32指针。如果函数出错,则返回-1,同时errbuf中存放相 关的错误消息。
int pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 捕获并处理数据包。cnt参数指定函数返回前所处理数据包的最⼤值。 cnt=-1表⽰在⼀个缓冲区中处理所有的数据包。cnt=0表⽰处理所有 数据包,直到产⽣以下错误之⼀:读取到EOF;超时读取。callback 参数指定⼀个带有三个参数的回调函数,这三个参数为:⼀个从 pcap_dispatch()函数传递过来的u_char指针,⼀个pcap_pkthdr结构 的指针,和⼀个数据包⼤⼩的u_char指针。如果成功则返回读取到的 字节数。读取到EOF时则返回零值。出错时则返回-1,此时可调⽤ pcap_perror()或pcap_geterr()函数获取错误消息。int pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 功能基本与pcap_dispatch()函数相同,只不过此函数在cnt个数据包 被处理或出现错误时才返回,但读取超时不会返回。⽽如果为 pcap_open_live()函数指定了⼀个⾮零值的超时设置,然后调⽤ pcap_dispatch()函数,则当超时发⽣时pcap_dispatch()函数会返回。 cnt参数为负值时pcap_loop()函数将始终循环运⾏,除⾮出现错误。void pcap_dump(u_char *user, struct pcap_pkthdr *h, u_char *sp) 向调⽤pcap_dump_open()函数打开的⽂件输出⼀个数据包。该函数可 作为pcap_dispatch()函数的回调函数。int pcap_compile(pcap_t *p, struct bpf_program *fp, char *str, int optimize, bpf_u_int32 netmask) 将str参数指定的字符串编译到过滤程序中。fp是⼀个bpf_program结 构的指针,在pcap_compile()函数中被赋值。optimize参数控制结果 代码的优化。netmask参数指定本地⽹络的⽹络掩码。
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指针。int pcap_datalink(pcap_t *p) 返回数据链路层类型,例如DLT_EN10MB。int pcap_snapshot(pcap_t *p) 返回pcap_open_live被调⽤后的snapshot参数值。int pcap_is_swapped(pcap_t *p) 返回当前系统主机字节与被打开⽂件的字节顺序是否不同。int pcap_major_version(pcap_t *p) 返回写⼊被打开⽂件所使⽤的pcap函数的主版本号。int pcap_minor_version(pcap_t *p) 返回写⼊被打开⽂件所使⽤的pcap函数的辅版本号。int pcap_stats(pcap_t *p, struct pcap_stat *ps) 向pcap_stat结构赋值。成功时返回0。这些数值包括了从开始 捕获数据以来⾄今共捕获到的数据包统计。如果出错或不⽀持 数据包统计,则返回-1,且可调⽤pcap_perror()或 pcap_geterr()函数来获取错误消息。FILE *pcap_file(pcap_t *p) 返回被打开⽂件的⽂件名。int pcap_fileno(pcap_t *p) 返回被打开⽂件的⽂件描述字号码。void pcap_perror(pcap_t *p, char *prefix) 在标准输出设备上显⽰最后⼀个pcap库错误消息。以prefix参 数指定的字符串为消息头。char *pcap_geterr(pcap_t *p) 返回最后⼀个pcap库错误消息。char *pcap_strerror(int error) 如果strerror()函数不可⽤,则可调⽤pcap_strerror函数替代。void pcap_close(pcap_t *p) 关闭p参数相应的⽂件,并释放资源。void pcap_dump_close(pcap_dumper_t *p) 关闭相应的被打开⽂件。
ling:libpcap的数据类型定义:struct pcap_addr:⽹卡地址描述{pcap_addr * next;sockaddr * addr;sockaddr * netmask;sockaddr *broadaddr;sockaddr *dstaddr;};pcap_addr * next;如果⾮空,指向链表中⼀个元素的指针;空表⽰链表中的最后⼀个元素。sockaddr * addr;指向包含⼀个地址的sockaddr的结构的指针。sockaddr * netmask;如果⾮空,指向包含相对于addr指向的地址的⼀个⽹络掩码的结构。sockaddr * broadaddr;如果⾮空,指向包含相对于addr指向的地址的⼀个⼴播地址,如果⽹络不⽀持⼴播可能为空。sockaddr * dstaddr;如果⾮空,指向⼀个相对于addr指向的源地址的⽬的地址,如果⽹络不⽀持点对点通讯,则为空。struct pcap_file_header {bpf_u_int32 magic;u_short version_major;u_short version_minor;bpf_int32 thiszone; /* gmt to local correction
/bpf_u_int32 sigfigs; / accuracy of timestamps
/bpf_u_int32 snaplen; / max length saved portion of each pkt
/bpf_u_int32 linktype; / data link type (LINKTYPE_*) */};bpf_u_int32 magic;u_short version_major;Libpcap的主版本号。u_shart version_minor;Libpcap的从版本号。bpf_u_int32 sigfigs;时间戳描述。bpf_u_int32 snaplen;保存的每个pkt的分⽚号的最⼤值。bpf_u_int32 linktype;数据链的类型。细节说明:libpcap dump⽂件头;libpcap dump⽂件中的第⼀个记录包含了⼀些标志的保存值,这些标志在打印阶段⽤到。这⼉的很多域都是32位的int,所以compilers不⽤进⾏转化;这些⽂件需要具有跨层次的可交换性。⽆论如何不要改变结构的层次(包括仅仅改变这个结构中域的长度);struct pcap_if { /⽹卡数据链的⼀个元素/struct pcap_if *next;char
name; / name to hand to “pcap_open_live()” */char
description; / textual description of interface, or NULL */struct pcap_addr
addresses;u_int flags; / PCAP_IF_ interface flags */};pcap_if *next;如果⾮空,指向链的下⼀个元素。如果为空是链的最后⼀个元素。char * name;指向⼀个字符串,该字符串是传给pcap_open_live()函数的设备名;char * description;如果⾮空,指向⼀个对设备的⼈性化的描述字符串。pcap_addr *addresses;指向⽹卡地址链中的第⼀个元素。u_int flags;PCAP_IF_ ⽹卡的标志。现在唯⼀可⽤的标识是PCAP_IF_LOOKBACK,它被⽤来标识⽹卡是不是lookback⽹卡。struct pcap_pkthdr { /dump ⽂件中的数据包头/struct timeval ts; /* time stamp
/bpf_u_int32 caplen; / length of portion present
/bpf_u_int32 len; / length this packet (off wire) */};timeval ts;数据报时间戳;bpf_u_int32 caplen;当前分⽚的长度;dpf_u_int32 len;这个数据报的长度;细节描述:在dump⽂件中的每个数据报都有这样⼀个报头。它⽤来处理不同数据报⽹卡的不同报头问题。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 */};u_int ps_recv;接受数据报的数⽬;u_int ps_drop;被驱动程序丢弃的数据报的数⽬;u_int ps_ifdrop;被⽹卡丢弃的数据报的数⽬;struct pcap_sf { //pacap的savefile结构 定义FILE *rfile; //该指针指向savefile⽂件int swapped; //?int hdrsize; //头⼤⼩吗?int version_major;//主版本号int version_minor;//从版本号u_char
base;//?};struct pcap_md { //?struct pcap_stat stat;/XXX/int use_bpf; / using kernel filter
/u_long TotPkts; / can’t oflow for 79 hrs on ether
/u_long TotAccepted; / count accepted by filter
/u_long TotDrops; / count of dropped packets
/long TotMissed; / missed by i/f during this run
/long OrigMissed; / missed by i/f before this run
/#ifdef linuxint sock_packet; / using Linux 2.0 compatible interface
/int timeout; / timeout specified to pcap_open_live
/int clear_promisc; / must clear promiscuous mode when we close
/int cooked; / using SOCK_DGRAM rather than SOCK_RAW
/int lo_ifindex; / interface index of the loopback device */char
device; / device name */struct pcap
next; / list of open promiscuous sock_packet pcaps */#endif};struct pcap { //这个结构很重要int fd;int snapshot;int linktype;int tzoff; /* timezone offset
/int offset; / offset for proper alignment */ struct pcap_sf sf; struct pcap_md md; /* * Read buffer. */ int bufsize; u_char *buffer; u_char *bp; int cc; /* * Place holder for pcap_next(). */ u_char *pkt;
/* * Placeholder for filter code if bpf not in kernel. */ struct bpf_program fcode; char errbuf[PCAP_ERRBUF_SIZE];};lipcap的声明:#define PCAP_VERSION_MAJOR 2libpcap dump⽂件的主版本号;#define PCAP_VERSION_MINOR 4libpcap dump⽂件的从版本号;#define PCAP_ERRBUF_SIZE 256⽤来存放libpcap出错信息的缓冲区的⼤⼩;#define PCAP_IF_LOOPBACK 0x00000001⽹卡是回环⽹卡;#define MODE_CAPT 0抓报模式,在调⽤pcap_setmode()时使⽤;#define MODE_STAT 1静态模式,在调⽤pcap_setmode()时使⽤;libpcap的类型定义:typedef int bpf_int3232bit 的整形;typedef u_int bpf_u_int3232bit 的⽆类型整形;typedef pcap pcap_tDescriptor of an open capture instance(⼀个打开的捕获实例的描述符?)这个结构对⽤户是不透明的。typedef pcap_dumper pcap_dumper_tlibpcap保存⽂件的描述符。typedef pcap_if pcap_if_t⽹卡链表的⼀个元素;typedef pcap_addr pcap_addr_t⽹卡地址的表⽰;libpcap函数描述:char *pcap_lookupdev(char * errbuf);描述: 这个函数⽤于获取⼀个合适的⽹卡描述,以供pcap_open_liver函数和pcap_lookupnet函数使⽤。如果找不到⽹卡或者所有⽹卡为off,则返回null。如果⼀个系统中有多个⽹卡,那么该函数返回找到的第⼀个on的⽹卡。最后才是回环接⼝。回环⽹卡⼀直被忽略;参数:char * errbuf 存放pcap_lookupdev函数的出错信息,只有在pcap_lookup失败是才有值。返回值: 如果函数执⾏成功,则返回⼀个⽤于描述系统上的⼀个⽹卡的描述符的指针。如果失败,返回null,errbuf中存放出错信息。int pcap_lookupnet(char * device, bpf_u_int32 * netp, bpf_u_int32 * maskp,char * errbuf);描述:该函数⽤于监测⽹卡所在⽹络的⽹络地址和⼦⽹掩码。参数:char *devic:⽹卡的描述符指针,由pcap_looupdev函数获取;bpf_u_int32 *netp:存放⽹络地址;bpf_u_int32 *maskp:存放⼦⽹掩码;char * errbuf: 存放出错信息;返回值:如果函数执⾏成功,则返回值为0,否则返回值为-1,并在errbuf中存放出错信息。pcap_t *pcap_open_live(char * device, int snaplen,int promisc, int to_ms, char * ebuf);描述:该函数⽤于打开⽹卡⽤于捕获数据报。单词live的意思就是表⽰⼀个运⾏的⽹卡(相对于offline⽽⾔)被打开了,如同⼀个保存有被抓数据报的 ⽂件被打开⼀样。在捕获数据报之前这个函数必须被执⾏。所有的其他的⽤于处理数据报捕获的函数⽤到的捕获数据报的描述符由该函数产⽣。查看 pcap_open_offlin()函数的定义,了解如何打开⼀个预先保存的包含数据报的⽂件的细节。参数:char *device:⽹卡的描述符指针,由pcap_looupdev函数获取;int snaplen:规定捕获的每个数据报的最⼤字节数;int promisc:1为混杂模式;0为⾮混杂模式;int to_ms:规定读超时的微秒(milliseconds)数;char *ebuf:存放错误信息,只有在pcap_open_live失败时才被设置;返回值:如果函数成功执⾏,则返回⼀个指向数据报捕获的指针;如果错误,返回null,ebuf存放出错信息;int pcap_compile(pcap_t * p, struct bpf_ program *fp, char * str,int optimize, bpf_u_int32 netmask);描述:该函数⽤于将str指定的规则整合到fp过滤程序中去,并⽣成过滤程序⼊⼝地址,⽤于过滤选择期望的数据报;参数:pcap_t *p:pcap_open_live返回的数据报捕获的指针;struct bpf_program *fp:指向⼀个⼦函数⽤于过滤,在pcap_compile()函数中被赋值;char *str:该字符串规定过滤规则;int optimize:规定了在结果代码上的选择是否被执⾏;bpf_u_int32 netmask:该⽹卡的⼦⽹掩码,可以通过pcap_lookupnet()获取;返回值:如果成功执⾏,返回0,否则返回-1;int pcap_loop(pcap_t * p, int cnt, pcap_handler callback,u_char * user);描述:该函数⽤于读取和处理数据报。既可以⽤来处理事先捕获的保存在⽂件中的数据报,也可以⽤来处理实时捕获的数据报;这个函数类似于pcap_dispatch函数,除了它继续读取数据报直⾄完成cnt个报的处理,或者⽂件处理完(在offline情况下),或者有错误发⽣为⽌。它不会在实时读超时时返回(⽽如果为pcap_open_live()函数指定了⼀个⾮零值的超时设置,然后调⽤pcap_dispatch()函数,则当超时发⽣时pcap_dispatch()函数会返回。)注意第三个参数,callback是pcap_handler类型的变量。这是⼀个⽤户提供的有着三个参数的⼦函数。定义为:void user_routine(u_char *user, struct pcap_pkthdr *phrd, u_char *pdata)这三个参数中,user,是传递给pcap_dispatch()的那个参数;phdr,是个pcap_pkthdr类型的指针,是savefile中的数据报的头指针,pdata,指向数据报数据;这个函数允许⽤户定义⼦集的数据报过滤程序;参数:pcap_t * p:pcap_open_live返回的数据报捕获的指针;int cnt:规定了函数返回前应处理的数据报数⽬;pcap_handler callback:指向⼀个⽤户⾃定义的函数,在处理每个报后⾃动调⽤该函数进⾏再处理;u_char *user:该指针⽤于传递给callback.(不知道有什么⽤?)返回值:如果函数成功执⾏(包括读⽂件时读到EOF),则返回0.否则返回-1,那么错误信息将由函数pcap_geterr或pcap_perror给出;补充:callback函数:The concept behind a callback function is fairly simple. Suppose I have a program that is waiting for an event of some the purpose of this example, lets pretend that my program wants a user to press a key on the keyboard. Every time theypress a key, I want to call a function which then will determine that to do. The function I am utilizing is a callback _open_dead()is used for creating a pcap_t structure to use when calling the other functions in libpcap. It is typically used when just usinglibpcap for compiling BPF _dump_open()is called to open a
savefile'' for writing. The name "-" in a synonym for stdout. NULL is returned on failure. p is a pcap struct as returned bypcap_open_offline() or pcap_open_live(). fname specifies the name of the file to open. If NULL is returned, pcap_geterr() can be used to get the error _setnonblock() puts a capture descriptor, opened with pcap_open_live(), intonon-blocking’’ mode, or takes it out of
non-blocking''mode, depending on whether the nonblock argument is non-zero or zero. It has no effect onsavefiles’’. If there is an error, -1 is returnedand errbuf is filled in with an appropriate error message; otherwise, 0 is returned. In
non-blocking'' mode, an attempt to read from thecapture descriptor with pcap_dispatch() will, if no packets are currently available to be read, return 0 immediately rather than blocking waiting for packets toarrive. pcap_loop() and pcap_next() will not work innon-blocking’’ p⽂件选读:ethernet.c:定义了三个内联函数:static inline int xdtoi(int):该函数将⼗六进值数转化为整数;static inline int skip_space(FILE *):该函数定义了在⼀个⽂件中含有空格时,返回第⼀个不是’'的字符。static inline int skip_line(FILE
):struct pcap_etherent {u_char addr[6];char name[122];};ethertype.h定义了各个协议的值。如#define ETHERTYPE_IP 0x0800 / IP protocol */#include
DEBUGint main(){bpf_u_int32 localnet,netmask;struct bpf_program fcode;pcap_handler printer; pcap_dumper_t*p; char ebuf[PCAP_ERRBUF_SIZE]; char * device; u_char * pcap_userdata; pcap_t * pd; int dev_flag=1; int cap_len=CAP_LEN; int i; device=pcap_lookupdev(ebuf); if (device == NULL) exit(printf("%s n", ebuf)); #ifdef _DEBUG_ printf("device is %s /n",device); #endif pd=pcap_open_live(device,cap_len,dev_flag,1000,ebuf); if(pd == NULL) exit(printf("%s/n",ebuf)); i=pcap_snapshot(pd); if(cap_len < i) {printf(“snaplen raised from %d to %d /n”, cap_len, i);cap_len=i;}if(pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) {localnet=0;netmask=0;printf("%s/n", ebuf);}if (pcap_compile(pd, &fcode, “”, 1, netmask) < 0)exit(printf(“Error %s/n”,“pcap_compile”));if (pcap_setfilter(pd,&fcode) < 0)exit(printf(“Error %s/n”,“pcap_setfilter”)); p=pcap_dump_open(pd,FILENAME); if(p == NULL)exit(printf(“Error:%s/n”,“pcap_dump_open”));printer=pcap_dump;pcap_userdata=(u_char *)p; if(pcap_loop(pd, -1, printer, pcap_userdata) < 0)exit(printf(“Error, %s/n”,“pcap_loop”)); pcap_close(pd); exit(0);}
发布者:admin,转转请注明出处:http://www.yc00.com/news/1690106503a306299.html
评论列表(0条)