【VS开发】循序渐进学习使用WINPCAP(一)

时间:2024-09-13 11:34:08

winpcap教程

中文教程

http://www.ferrisxu.com/WinPcap/html/index.html

除此之外,

WinPcap · Developer Resources下载开发包,解压缩之后里面有相应的demo,直接修改即可!

循序渐进学习使用WINPCAP(一)

一些需要知道的细节描述(前言):

这一部分展示了如何使用WINPCAP-API的不同的功能,它作为一个使用指南被划分为一系列的课时来带领读者循序渐进的体会PCAP的程序设计的

魅力:从简单的基本功能(如获取网卡的列表,数据包的捕获等)到统计和收集网络流量等高级功能。

在这里将提供一些简单但完整的代码作为参考:所有的这些原代码都有和它相关的详细信息的连接以便单击这些功能和数据结构时能够即使跳转到相关的文献。

这些例子是用C语言写的,所以在学习之前首先要有一定的C语言的基础,当然PCAP作为一个网络底层的驱动,要想学好它也必须具备一定的网络方面的知识。

(一)得到网络驱动列表

用PCAP写应用程序的第一件事往往就是要获得本地的网卡列表。PCAP提供了pcap_findalldevs()这个函数来实现此功能,这个API返回一个pcap_if结构的连表,连表的每项内容都含有全面的网卡信息:尤其是字段名字和含有名字的描述以及有关驱动器的易读信息。

得到网络驱动列表的程序如下:

#include "pcap.h"

main()

{

  pcap_if_t *alldevs;

  pcap_if_t *d;

  int i=0;

  char errbuf[PCAP_ERRBUF_SIZE];

 

  /* 这个API用来获得网卡 的列表 */

  if (pcap_findalldevs(&alldevs, errbuf) == -1)

  {

    fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);

    exit(1);

  }

 

  /* 显示列表的响应字段的内容 */

  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;

  }

  /* We don't need any more the device list. Free it */

  pcap_freealldevs(alldevs);

}

有关这段程序的一些说明:

首先pcap_findalldevs()同其他的libpca函数一样有一个errbuf参数,当有异常情况发生时,这个参数会被PCAP填充为某个特定的错误字串。

再次,UNIX也同样提供pcap_findalldevs()这个函数,但是请注意并非所有的系统都支持libpcap提供的网络程序接口。所以我门要想写出合适

的程序就必须考虑到这些情况(系统不能够返回一些字段的描述信息),在这种情况下我门应该给出类似"No description available"这样的

提示。

最后结束时别忘了用pcap_freealldevs()释放掉内存资源。

原文如下:

Obtaining the device list

The first thing that usually a WinPcap based application needs is a list of suitable network adapters. Libpcap provides the pcap_findalldevs() function for this purpose: this function returns a linked list of pcap_if structures, each of which contains comprehensive
information about an adapter. In particular the fields name and description contain the name and a human readable description of the device.

The following code retrieves the adapter list and shows it on the screen, printing an error if no adapters are found.

#include "pcap.h"

main()

{

  pcap_if_t *alldevs;

  pcap_if_t *d;

  int i=0;

  char errbuf[PCAP_ERRBUF_SIZE];

 

  /* Retrieve the device list */

  if (pcap_findalldevs(&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;

  }

  /* We don't need any more the device list. Free it */

  pcap_freealldevs(alldevs);

}

Some comments about this code.

First of all, pcap_findalldevs(), like other libpcap functions, has an errbuf parameter. This parameter points to a string filled by libpcap with a description of the error if something goes wrong.

Second, note that pcap_findalldevs() is provided by libpcap under Unix as well, but remember that not all the OSes supported by libpcap provide a description of the network interfaces, therefore if we want to write a portable application, we must consider the
case in which description is null: we print the string "No description available" in that situation.

Note finally that we free the list with pcap_freealldevs() once when we have finished with it.

Let's try to compile and run the code of this first sample. In order to compile it under Unix or Cygwin, simply issue a:

gcc -o testaprog testprog.c -lpcap

On Windows, you will need to create a project, following the instructions in the "Using WinPcap in your programs " section of this manual. However, I suggest you to use the WinPcap developer's pack (available at the WinPcap website, http://winpcap.polito.it/ ),
that provides a lot of properly configured example apps, all the code presented in this tutorial and all the projects, includes and libraries needed to compile and run the samples.

Assuming we have compiled the program, let's try to run it. On my WinXP workstation, the result is

1. {4E273621-5161-46C8-895A-48D0E52A0B83} (Realtek RTL8029(AS) Ethernet Adapter)

2. {5D24AE04-C486-4A96-83FB-8B5EC6C7F430} (3Com EtherLink PCI)

As you can see, the name of the network adapters (that will be passed to libpcap when opening the devices) under Windows are quite unreadable, so the description near them can be very useful to the user.

dahubaobao 2004-11-18 00:54
循序渐进学习使用WINPCAP(二)

在第一章中演示了如何获得已存在适配器的静态信息。实际上WinPcap同样也提供其他的高级信息,特别是 pcap_findalldevs()这个函数返回的每个 pcap_if结构体都同样包含一个pcap_addr结构的列表,他包含:

一个地址列表,一个掩码列表,一个广播地址列表和一个目的地址列表。

下面的例子通过一个ifprint()函数打印出了pcap_if结构的的所有字段信息,该程序对每一个pcap_findalldevs()所返回的pcap_if结构循环调用ifprint()来显示详细的字段信息。

#include "pcap.h"

#ifndef WIN32

#include

#include

#else

#include

#endif

void ifprint(pcap_if_t *d);

char *iptos(u_long in);

int main()

{

pcap_if_t *alldevs;

pcap_if_t *d;

char errbuf[PCAP_ERRBUF_SIZE+1];

/* 获得网卡的列表 */

if (pcap_findalldevs(&alldevs, errbuf) == -1)

{

  fprintf(stderr,"Error in pcap_findalldevs: %s\n",errbuf);

  exit(1);

}

/* 循环调用ifprint() 来显示pcap_if结构的信息*/

for(d=alldevs;d;d=d->next)

{

  ifprint(d);

}

return 1;

}

/* Print all the available information on the given interface */

void ifprint(pcap_if_t *d)

{

pcap_addr_t *a;

/* Name */

printf("%s\n",d->name);

/* Description */

if (d->description)

  printf("\tDescription: %s\n",d->description);

/* Loopback Address*/

printf("\tLoopback: %s\n",(d->flags & PCAP_IF_LOOPBACK)?"yes":"no");

/* IP addresses */

for(a=d->addresses;a;a=a->next) {

  printf("\tAddress Family: #%d\n",a->addr->sa_family);

/*关于 sockaddr_in 结构请参考其他的网络编程书*/

  switch(a->addr->sa_family)

  {

    case AF_INET:

    printf("\tAddress Family Name: AF_INET\n");//打印网络地址类型

    if (a->addr)//打印IP地址

      printf("\tAddress: %s\n",iptos(((struct sockaddr_in *)a->addr)->sin_addr.s_addr));

    if (a->netmask)//打印掩码

      printf("\tNetmask: %s\n",iptos(((struct sockaddr_in *)a->netmask)->sin_addr.s_addr));

    if (a->broadaddr)//打印广播地址

      printf("\tBroadcast Address: %s\n",iptos(((struct sockaddr_in *)a->broadaddr)->sin_addr.s_addr));

    if (a->dstaddr)//目的地址

      printf("\tDestination Address: %s\n",iptos(((struct sockaddr_in *)a->dstaddr)->sin_addr.s_addr));

    break;

    default:

    printf("\tAddress Family Name: Unknown\n");

    break;

  }

}

printf("\n");

}

/* 将一个unsigned long 型的IP转换为字符串类型的IP */

#define IPTOSBUFFERS   12

char *iptos(u_long in)

{

  static char output[IPTOSBUFFERS][3*4+3+1];

  static short which;

  u_char *p;

  p = (u_char *)∈

  which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1);

  sprintf(output[which], "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);

  return output[which];

}