`
wanjianfei
  • 浏览: 306766 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论
阅读更多
今天在阅读WinpcapManual的时候发现一句话:

“Thismeansthatonsharedmedia(likenon-switchedEthernet),WinPcapwillbeabletocapturethepacketsofotherhosts.”

我理解为:如果在通过没有交换功能的集线器连接的网络上,只要把网卡设置为混杂(promiscuous)模式,winpcap能够捕获到其他主机通信的数据包。如果是具有交换功能的集线器连接的网络winpcap还能管用吗?这个在后边的实习中将会进行试验。

试验程序2:

/*
*截获数据包的试验。先打印出所有网络适配器的列表,然后选择
*想在哪个适配器上截获数据包。然后通过pcap_loop()函数将截获
*的数据包传给回调函数packet_handler()处理。

*通过该程序初步了解了使用winpcap截获数据包的步骤以及一些在
*截获数据包时非常重要的函数和结构体。
*2006-1-26
*/

#include<pcap.h>
#include<remote-ext.h>

/*Prototypeofthepackethandler*/
voidpacket_handler(u_char*param,conststructpcap_pkthdr*header,constu_char*pkt_data);

intmain(){
pcap_if_t*alldevs;
pcap_if_t*d;
intinum;
inti=0;
pcap_t*adhandle;
charerrbuf[PCAP_ERRBUF_SIZE];

/*Retrievethedeviceslistonthelocalmachine*/
if(pcap_findalldevs_ex(PCAP_SRC_IF_STRING,NULL,&alldevs,errbuf)==-1)
{
fprintf(stderr,"Errorinpcap_findalldevs:%s\n",errbuf);
exit(1);
}

/*Printthelist*/
for(d=alldevs;d;d=d->next)
{
/*Printname*/
printf("%d.%s",++i,d->name);

/*Printdescription*/
if(d->description)
{
printf("(%s)\n",d->description);
}
else
{
printf("(Nodescriptionavailable)\n");
}
}

if(i==0)
{
printf("\nNointerfacesfound!MakesureWinpcapisinstalled.\n");
return-1;
}

/*Selectanadapter*/
printf("Entertheinterfacenumber(1-%d):",i);
scanf("%d",&inum);

if(inum<1||inum>i)
{
printf("\nInterfacenumberoutofrange.\n");
/*Freethedevicelist*/
pcap_freealldevs(alldevs);
return-1;
}

/*Jumptotheselectedadapter*/
for(d=alldevs,i=0;i<inum-1;d=d->next,++i);

/*Openthedevice*/
if((adhandle=pcap_open(d->name,/*nameofthedevice*/
65536,/*portionofthepackettocapture*/
/*65535guaranteesthatthewholepacketwillbecapturedonallthelinklayers*/
PCAP_OPENFLAG_PROMISCUOUS,/*promiscuousmode*/
1000,/*readtimeout*/
NULL,/*authenticationontheremotemachine*/
errbuf/*errorbuffer*/
))==NULL)
{
fprintf(stderr,"\nnabletoopentheadapter.%sisnotsupportedbyWinpcap\n",d->name);
/*Freethedeviceslist*/
pcap_freealldevs(alldevs);

return-1;
}

printf("\nlisteningon%s...\n",d->description);

/*Atthispoint,wedon'tneedanymorethedevicelist.Freeit*/
pcap_freealldevs(alldevs);
/*startthecapture*/
pcap_loop(adhandle,0,packet_handler,NULL);

return1;
}

/*Callbackfunctioninvokedbylibpcapforeveryincomingpacket*/
voidpacket_handler(u_char*param,conststructpcap_pkthdr*header,constu_char*pkt_data){
structtm*ltime;
chartimestr[16];

/*convertthetimestamptoreadableformat*/
ltime=localtime(&header->ts.tv_sec);
strftime(timestr,sizeof(timestr),"%H:%M:%S",ltime);
printf("%s,%.6dlen:%d\n",timestr,header->ts.tv_usec,header->len);
}

函数1:

pcap_t*pcap_open(constchar*source,

intsnaplen,

intflags,

intread_timeout,

structpcap_rmtauth*auth,

char*errbuf

)

为捕获/发送数据打开一个普通的源。pcap_open()能够替代所有的pcap_open_xxx()函数,它隐藏了不同的pcap_open_xxx()之间的差异,所以程序员不必使用不同的open函数。

source:的是包含要打开的源名称的以’\0’结尾的字符串。源名称得包含新的源规范语法(SourceSpecificationSyntax),并且它不能为NULL。为了方便的使用源语法,请记住:(1)pcap_findalldevs_ex()返回的适配器(网卡)可以直接被pcap_open()使用;(2)万一用户想传递他自己的源字符串给pcap_open(),pcap_createsrcstr()可以创建正确的源标识。

snaplen:需要保留的数据包的长度。对每一个过滤器接收到的数据包,第一个‘snaplen’字节的内容将被保存到缓冲区,并且传递给用户程序。例如,snaplen等于100,那么仅仅每一个数据包的第一个100字节的内容被保存。简言之就是从每一个包的开头到snaplen的那段内容将被保存。

flags:保存一些由于抓包需要的标志。Winpcap定义了三种标志:

lPCAP_OPENFLAG_PROMISCUOUS:1,它定义了适配器(网卡)是否进入混杂模式(promiscuousmode)。

lPCAP_OPENFLAG_DATATX_UDP:2,它定义了数据传输(假如是远程抓包)是否用UDP协议来处理。

lPCAP_OPENFLAG_NOCAPTURE_RPCAP:4,它定义了远程探测器是否捕获它自己产生的数据包。

read_timeout:以毫秒为单位。readtimeout被用来设置在遇到一个数据包的时候读操作不必立即返回,而是等待一段时间,让更多的数据包到来后从OS内核一次读多个数据包。并非所有的平台都支持readtimeout;在不支持readtimeout的平台上它将被忽略。

auth:一个指向’structpcap_rmtauth’的指针,保存当一个用户登录到某个远程机器上时的必要信息。假如不是远程抓包,该指针被设置为NULL。

errbuf:一个指向用户申请的缓冲区的指针,存放当该函数出错时的错误信息。

返回值是一个’pcap_t’指针,它可以作为下一步调用(例如pcap_compile()等)的参数,并且指定了一个已经打开的Winpcap会话。在遇到问题的情况下,它返回NULL并且’errbuf’变量保存了错误信息。

函数2:

intpcap_loop(pcap_t*p,

intcnt,

pcap_handercallback,

u_char*user

)

收集一群数据包。pcap_loop()与pcap_dispatch()类似,但是它会一直保持读数据包的操作直到cnt包被处理或者发生了错误。当有活动的读超时(readtimeout)时它并不返回。然而,对pcap_open_live()指定一个非0的读超时(readtimeout),当发生超时的时候调用pcap_dispatch()来接收并处理到来的所有数据包更好。Cnt指明了返回之前要处理数据包的最大数目。如果cnt为负值,pcap_loop()将一直循环(直到发生错误才停止)。如果出错时返回-1;如果cnt用完时返回0;如果在任何包被处理前调用pcap_breakloop()来中止循环将返回-2。所以,如果程序中使用了pcap_breakloop(),必须准确的来判断返回值是-1还是-2,而不能简单的判断<0。

函数3:

hypedefvoid(*pcap_handler)(u_char*user,

conststructpcap_pkthdr*pkt_header,

constu_char*pkt_data)

接收数据包的回调函数原型。当用户程序使用pcap_dispatch()或者pcap_loop(),数据包以这种回调的方法传给应用程序。用户参数是用户自己定义的包含捕获会话状态的参数,它必须跟pcap_dispatch()和pcap_loop()的参数相一致。pkt_hader是与抓包驱动有关的头。pkt_data指向包里的数据,包括协议头。

结构体1:

structpcap_pkthdr{

structtimevalts;

bpf_u_int32caplen;

bpf_u_int32len;

}

ts:时间戳

cpalen:当前分组的长度

len:数据包的长度

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics