7.1.3 打开与关闭网络适配器的实例
在下面实例程序中会打开一个网络适配器并捕获相应的数据包,该程序会把通过该适配器的每个数据包的长度打印出来,同时打印每个数据包的捕获时间,完整的代码见[ch7/openadapter工程]。
defne WIN32
defne HAVE_REMOTE
include<stdio.h>
include"pcap.h"
include<winsock.h>
/捕获数据包的回调函数的原型/
void packet_handler(u_char*param,
const struct pcap_pkthdrheader,const u_charpkt_data);
int main()
{
pcap_if_t*alldevs;
pcap_if_t*d;
int inum;
int i=0;
pcap_t*adhandle;
char errbuf[PCAP_ERRBUF_SIZE];
/获取本机的网络设备列表/
if(pcap_fndalldevs_ex(PCAP_SRC_IF_STRING,NULL,
&alldevs,errbuf)==-1)
{
fprintf(stderr,
"Error in pcap_fndalldevs:%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-1;
}
/选择网络设备接口/
printf("Enter the interface number(1-%d):",i);
scanf("%d",&inum);
if(inum<1||inum>i)
{
printf("\nInterface number out of range.\n");
/释放设备列表/
pcap_freealldevs(alldevs);
return-1;
}
/跳转到选中的适配器/
for(d=alldevs,i=0;i<inum-1;d=d->next,i++);
/打开设备/
if((adhandle=pcap_open(
d->name,//设备名
65536,//保证捕获到数据链路层上每个数据包的全部内容
PCAP_OPENFLAG_PROMISCUOUS,//混杂模式
1000,//读取超时时间
NULL,//远程机器验证
errbuf//错误缓冲池
))==NULL)
{
fprintf(stderr,"\nUnable to open the adapter.
%s is not supported by WinPcap\n",d->name);
/释放设备列表/
pcap_freealldevs(alldevs);
return-1;
}
/在选中的设备接口上监听数据/
printf("\nlistening on%s…\n",d->description);
/释放设备列表/
pcap_freealldevs(alldevs);
/开始捕获/
pcap_loop(adhandle,0,packet_handler,NULL);
/关闭设备/
pcap_close(adhandle);
return 0;
}
/每次捕获到数据包时,都会自动调用该回调函数/
void packet_handler(u_char*param,
const struct pcap_pkthdrheader,const u_charpkt_data)
{
struct tm*ltime;
char timestr[16];
time_t local_tv_sec;
/将时间戳转换成可识别的格式,header->ts存储了数据包被捕获的时间/
local_tv_sec=header->ts.tv_sec;
ltime=localtime(&local_tv_sec);
strftime(timestr,sizeof timestr,"%H:%M:%S",ltime);
/打印数据包的捕获时间与数据包的长度/
printf("%s,%.6d len:%d\n",
timestr,header->ts.tv_usec,header->len);
}
在本实例中,将pcap_open函数的snaplen参数值设定为65535,这个值比能遇到的最大的网络最大传输单元MTU(Maximum Transfer Unit)还要大,同时这里还使用了混杂模式,这样,可确保总能收到完整的数据包。实例程序的运行结果如图7-1与图7-2所示。
图 7-1 选择网络设备接口(此处选择2)
图 7-2 打印数据包的捕获时间与长度