| libpcap 是一个开发sniffer的工具包。pcap:packet capture! libpcap使用总结! libpcap 是一个开发sniffer的工具包。pcap:packet capture!
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 linux int 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 2 libpcap dump文件的主版本号; #define PCAP_VERSION_MINOR 4 libpcap 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_int32 32bit 的整形; typedef u_int bpf_u_int32 32bit 的无类型整形; typedef pcap pcap_t Descriptor of an open capture instance(一个打开的捕获实例的描述符?)这个结构对用户是不透明的。 typedef pcap_dumper pcap_dumper_t libpcap保存文件的描述符。 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 sort. For the purpose of this example, lets pretend that my program wants a user to press a key on the keyboard. Every time they press a key, I want to call a function which then will determine that to do. The function I am utilizing is a callback function. pcap_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 using libpcap for compiling BPF code. pcap_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 by pcap_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 text. pcap_setnonblock() puts a capture descriptor, opened with pcap_open_live(), into ``non-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 on ``savefiles''. If there is an error, -1 is returned and errbuf is filled in with an appropriate error message; otherwise, 0 is returned. In ``non-blocking'' mode, an attempt to read from the capture descriptor with pcap_dispatch() will, if no packets are currently available to be read, return 0 immediately rather than blocking waiting for packets to arrive. pcap_loop() and pcap_next() will not work in ``non-blocking'' mode. libpcap文件选读: ethernet.c:定义了三个内联函数: static inline int xdtoi(int):该函数将十六进值数转化为整数; static inline int skip_space(FILE *):该函数定义了在一个文件中含有空格时,返回第一个不是'\n'的字符。 static inline int skip_line(FILE *): struct pcap_etherent { u_char addr[6]; char name[122]; }; ethertype.h定义了各个协议的值。如#define ETHERTYPE_IP 0x0800 /* IP protocol */
|