|
|
Winpcap提供(libpcap也提供)的一个强大特性是过滤引擎(filtering engine)。它提供了一个非常有效的接收网络流量的方法,并且它通常与Winpcap提供的抓包机制集成在一起。用于过滤数据包的函数是pcap_complie()和pcap_setfilter()。 pcap_complie()使用一个包含高级布尔表达式的字符串并且产生一个能被过滤引擎集成到数据包驱动中的低级字节码。
pcap_setfilter()把一个过滤器与核心驱动抓包会话关联起来。一旦pcap_setfilter()被调用,相关的过滤器将被应用到所有的来自网络的数据包上,并且所有的一致的数据包将被复制给应用程序。
抓包和过滤
经过前面几天的知识准备,现在我们将把前面的知识综合后应用于一个简单的实际应用程序。下面试验的目的是如何解析和解释被捕获的数据包的协议头。应用程序运行的结果是打印出一组我们的网络上的UDP通信数据。我们之所以选择解析和显示UDP协议是因为它比起其他协议(例如:TCP)更易于理解,对于初学者更适合。
试验代码:
#include <pcap.h> #include <remote-ext.h>
/* 4 bytes IP address */ typedef struct ip_address { u_char byte1; u_char byte2; u_char byte3; u_char byte4; }ip_address;
/* IPv4 header */ typedef struct ip_header { u_char ver_ihl; /* Version (4 bits) + Internet header length (4 bits)*/ u_char tos; /* Type of service */ u_short tlen; /* Total length */ u_short identification; /* Identification */ u_short flags_fo; /* Flags (3 bits) + Fragment offset (13 bits)*/ u_char ttl; /* Time to live */ u_char proto; /* Protocol */ u_short crc; /* Header checksum */ ip_address saddr;/* Source address */ ip_address daddr;/* Destination address */ u_int op_pad; /* Option + Padding */ }ip_header;
/* UDP header */ typedef struct udp_header { u_short sport; /* Source port */ u_short dport; /* Destination port */ u_short len; /* Datagram length */ u_short crc; /* Checksum */ }udp_header;
/* Prototype of the pachet handler */ void packet_handler(u_char* param, const struct pcap_pkthdr* header, const u_char* pkt_data);
int main() { pcap_if_t* alldevs; pcap_if_t* d; int inum; int i = 0; pcap_t* adhandle; char errbuf[PCAP_ERRBUF_SIZE]; u_int netmask; char packet_filter[] = "ip and udp"; struct bpf_program fcode;
/* Retrieve the device list */ if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1) { fprintf(stderr, "Error in pcap_findalldevs: %s\n", errbuf); exit(1); }
/* Print the list*/ for (d = alldevs; d; d = d->next) { printf("%d. %s", ++ i, d->name); if (d->description) { printf(" (%s)\n", d->description); } else { printf(" (No description available)\n"); } }
if (i == 0) { printf("\nNo interfaces found! Make sure Winpcap is installed.\n"); return -1; }
printf("Enter the interface number (1 - %d):", i); scanf("%d", &inum);
if (inum < 1 || inum > i) { printf("\nInterface number out of range.\n"); /* Free the device list */ pcap_freealldevs(alldevs); return -1; }
/* Jump to the selected adapter */ for (d = alldevs; d; d = d->next);
/* Open the adapter */ if ((adhandle = pcap_open(d->name, /*name of the device */ 65536, /* portion of the packet to capture */ /* 65536 grants that the whole packet will be captured on all the MACs */ PCAP_OPENFLAG_PROMISCUOUS, /* promiscuous mode */ 1000, /* read timeout */ NULL, /* remote authentication */ errbuf /* error buffer */ )) == NULL) { fprintf(stderr, "\nUnable to open the adapter. %s is not supported by Winpcap\n"); /* Free the devices list */ pcap_freealldevs(alldevs); return -1; }
/* Check the link layer. We support only Ethernet for simplicity */
|