首先我们看看如何以LIBPCAP的格式写数据包。
下面的例子演示了如何从指定的接口上捕获数据包并将它们存储到一个指定的文件。
#include \
/* 定义处理数据的函数原形 */
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(\ return -1; }
/* 获得驱动列表 */
if (pcap_findalldevs(&alldevs, errbuf) == -1) {
fprintf(stderr,\ exit(1); }
/* 打印 list */
for(d=alldevs; d; d=d->next) {
printf(\ if (d->description)
printf(\ else
printf(\ }
if(i==0) {
printf(\ return -1; }
printf(\ scanf(\
if(inum < 1 || inum > i) {
printf(\ /* 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,\ /* Free the device list */ pcap_freealldevs(alldevs); return -1; }
/* 打开文件 */
dumpfile = pcap_dump_open(adhandle, argv[1]); if(dumpfile==NULL){
fprintf(stderr,\ return -1; }
printf(\
/* 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()来循环从文件中读取数据。你能发现读取脱机的数据几乎和实时的从网卡上读取一摸一样。
#include
#define LINE_LEN 16
void dispatcher_handler(u_char *, const struct pcap_pkthdr *, const u_char *);
main(int argc, char **argv) {
pcap_t *fp;
char errbuf[PCAP_ERRBUF_SIZE];
if(argc != 2){
printf(\ return -1; }
/* 打开一个存储有数据的堆文件 */
if ( (fp = pcap_open_offline(argv[1], errbuf) ) == NULL) {
fprintf(stderr,\ return -1; }
// 读取数据直到遇到 EOF标志。 pcap_loop(fp, 0, dispatcher_handler, NULL);
return 0; }
void dispatcher_handler(u_char *temp1,
const struct pcap_pkthdr *header, const u_char *pkt_data) {
u_int i=0;
/* print pkt timestamp and pkt len */
printf(\
/* Print the packet */
for (i=1; (i < header->caplen + 1 ) ; i++) {
printf(\ if ( (i % LINE_LEN) == 0) printf(\ }
printf(\ }
下面的代码具有一样的作用,只不过是用pcap_next_ex()来代替pcap_loop()循环读取数据而已。
#include
#define LINE_LEN 16
main(int argc, char **argv) {
pcap_t *fp;
char errbuf[PCAP_ERRBUF_SIZE]; struct pcap_pkthdr *header; u_char *pkt_data; u_int i=0; int res;
if(argc != 2){
printf(\ return -1; }
/* Open a capture file */
if ( (fp = pcap_open_offline(argv[1], errbuf) ) == NULL) {
fprintf(stderr,\ return -1; }
/* Retrieve the packets from the file */
while((res = pcap_next_ex( fp, &header, &pkt_data)) >= 0){ /* print pkt timestamp and pkt len */
printf(\
/* Print the packet */
for (i=1; (i < header->caplen + 1 ) ; i++) {
printf(\ if ( (i % LINE_LEN) == 0) printf(\ }