|
|
通过以前的学习我门已经熟悉了从网卡上捕获数据包,现在我门将学习如何处理数据包。WINPCAP为我们提供了很多API来将流经网络的数据包保存到一个堆文件并读取堆的内容。这一节将讲述如何使用所有的这些API。 这种文件的格式很简单,但包含了所捕获的数据报的二进制内容,这种文件格式也是很多网络工具的标准如WinDump, Ethereal 还有 Snort等.
关于如何将数据包保存到文件:
首先我们看看如何以LIBPCAP的格式写数据包。 下面的例子演示了如何从指定的接口上捕获数据包并将它们存储到一个指定的文件。
#include "pcap.h"
/* 定义处理数据的函数原形 */ void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data);
main(int argc, char **argv) { pcap_if_t *alldevs; pcap_if_t *d; int inum; int i=0; pcap_t *adhandle;//定义文件句柄 char errbuf[PCAP_ERRBUF_SIZE]; pcap_dumper_t *dumpfile;
/* 检查命令行参数 是否带有文件名*/ if(argc != 2){
printf("usage: %s filename", argv[0]); return -1;
} /* 获得驱动列表 */ if (pcap_findalldevs(&alldevs, errbuf) == -1) { fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf); exit(1); } /* 打印 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; } /* 跳转到指定的网卡 */ for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++); /* Open the adapter */ if ( (adhandle = pcap_open_live(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. 1, // promiscuous mode 1000, // read timeout errbuf // error buffer ) ) == NULL) { fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n"); /* Free the device list */ pcap_freealldevs(alldevs); return -1; }
/* 打开文件 */ dumpfile = pcap_dump_open(adhandle, argv[1]); if(dumpfile==NULL){ fprintf(stderr,"\nError opening output file\n"); return -1; } printf("\nlistening on %s...\n", d->description); /* At this point, we don’t need any more the device list. Free it */ pcap_freealldevs(alldevs); /* 循环捕获数据并调用packet_handler函数把数据存储到堆文件 */ pcap_loop(adhandle, 0, packet_handler, (unsigned char *)dumpfile);
return 0; }
/* Callback function invoked by libpcap for every incoming packet */
void packet_handler(u_char *dumpfile, const struct pcap_pkthdr *header, const u_char *pkt_data) { /* 此函数功能将数据报存储到堆文件 */ pcap_dump(dumpfile, header, pkt_data); }
正如你看到的那样该程序的结构非常类似与以前的例子,区别是: 一旦打开网卡就调用pcap_dump_open()来打开一个文件,该调用将文件和某个网卡相关联。 packet_handler()内部通过调用pcap_dump()来将捕获的数据报存储到文件。pcap_dump()的参数和 packet_handler()一样,所以用起来比较方便。
从文件读数据包:
下面我们来看如何从文件读取数据内容。下面的代码打开了 一个堆文件并打印了其中的每个包内容。 pcap_open_offline()用来打开一个堆文件,之后用pcap_loop()来循环从文件中读取数据。你能发现读取脱机的数据几乎和实时的从网卡上读取一摸一样。
|