您好,欢迎访问三七文档
当前位置:首页 > 电子/通信 > 综合/其它 > 使用Wincap编制一个简单的网络数据包监听与捕获程序
一、实验目的复习计算机网络课程相关知识,采用合适的程序开发语言完成网络程序开发。二、实验环境二、实验内容要求使用Wincap编制一个简单的网络数据包监听与捕获程序,同时,将捕获的数据包进行分析并将分析结果显示在屏幕上。三、实验步骤、记录和结果代码如下:#includepcap.htypedefstruct{intnumber;charname[10];}Protocol;Protocolprotocol[10];/*4字节的IP地址*/typedefstructip_address{u_charbyte1;u_charbyte2;u_charbyte3;u_charbyte4;}ip_address;/*IPv4首部*/typedefstructip_header{u_charver_ihl;//版本(4bits)+首部长度(4bits)u_chartos;//服务类型(Typeofservice)u_shorttlen;//总长(Totallength)u_shortidentification;//标识(Identification)u_shortflags_fo;//标志位(Flags)(3bits)+段偏移量(Fragmentoffset)(13bits)u_charttl;//存活时间(Timetolive)u_charproto;//协议(Protocol)u_shortcrc;//首部校验和(Headerchecksum)ip_addresssaddr;//源地址(Sourceaddress)ip_addressdaddr;//目的地址(Destinationaddress)u_intop_pad;//选项与填充(Option+Padding)}ip_header;/*回调函数原型*/voidpacket_handler(u_char*param,conststructpcap_pkthdr*header,constu_char*pkt_data);微机一台操作系统:WinXP/Linux编程软件:C++intmain(){pcap_if_t*alldevs;pcap_if_t*d;intinum;inti=0;pcap_t*adhandle;charerrbuf[PCAP_ERRBUF_SIZE];u_intnetmask;//charpacket_filter[]=ipandudp;charpacket_filter[]=ip;structbpf_programfcode;protocol[0].number=1;strcpy(protocol[0].name,ICMP);protocol[1].number=2;strcpy(protocol[1].name,IGMP);protocol[2].number=4;strcpy(protocol[2].name,IP);protocol[3].number=6;strcpy(protocol[3].name,TCP);protocol[4].number=8;strcpy(protocol[4].name,EGP);protocol[5].number=9;strcpy(protocol[5].name,IGP);protocol[6].number=17;strcpy(protocol[6].name,UDP);protocol[7].number=41;strcpy(protocol[7].name,IPv6);protocol[8].number=50;strcpy(protocol[8].name,ESP);protocol[9].number=89;strcpy(protocol[9].name,OSPF);/*获得设备列表*/if(pcap_findalldevs_ex(PCAP_SRC_IF_STRING,NULL,&alldevs,errbuf)==-1){fprintf(stderr,Errorinpcap_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);elseprintf((Nodescriptionavailable)\n);}if(i==0){printf(\nNointerfacesfound!MakesureWinPcapisinstalled.\n);return-1;}printf(Entertheinterfacenumber(1-%d):,i);scanf(%d,&inum);if(inum1||inumi){printf(\nInterfacenumberoutofrange.\n);/*释放设备列表*/pcap_freealldevs(alldevs);return-1;}/*跳转到已选设备*/for(d=alldevs,i=0;iinum-1;d=d-next,i++);/*打开适配器*/if((adhandle=pcap_open(d-name,//设备名65536,//要捕捉的数据包的部分//65535保证能捕获到不同数据链路层上的每个数据包的全部内容PCAP_OPENFLAG_PROMISCUOUS,//混杂模式1000,//读取超时时间NULL,//远程机器验证errbuf//错误缓冲池))==NULL){fprintf(stderr,\nUnabletoopentheadapter.%sisnotsupportedbyWinPcap\n);/*释放设备列表*/pcap_freealldevs(alldevs);return-1;}/*检查数据链路层,为了简单,我们只考虑以太网*/if(pcap_datalink(adhandle)!=DLT_EN10MB){fprintf(stderr,\nThisprogramworksonlyonEthernetnetworks.\n);/*释放设备列表*/pcap_freealldevs(alldevs);return-1;}if(d-addresses!=NULL)/*获得接口第一个地址的掩码*/netmask=((structsockaddr_in*)(d-addresses-netmask))-sin_addr.S_un.S_addr;else/*如果接口没有地址,那么我们假设一个C类的掩码*/netmask=0xffffff;//编译过滤器if(pcap_compile(adhandle,&fcode,packet_filter,1,netmask)0){fprintf(stderr,\nUnabletocompilethepacketfilter.Checkthesyntax.\n);/*释放设备列表*/pcap_freealldevs(alldevs);return-1;}//设置过滤器if(pcap_setfilter(adhandle,&fcode)0){fprintf(stderr,\nErrorsettingthefilter.\n);/*释放设备列表*/pcap_freealldevs(alldevs);return-1;}printf(\nlisteningon%s...\n,d-description);/*释放设备列表*/pcap_freealldevs(alldevs);/*开始捕捉*/pcap_loop(adhandle,0,packet_handler,NULL);return0;}/*回调函数,当收到每一个数据包时会被libpcap所调用*/voidpacket_handler(u_char*param,conststructpcap_pkthdr*header,constu_char*pkt_data){structtm*ltime;chartimestr[16];ip_header*ih;u_intip_len;u_shortsport,dport;time_tlocal_tv_sec;/*将时间戳转换成可识别的格式*/local_tv_sec=header-ts.tv_sec;ltime=localtime(&local_tv_sec);strftime(timestr,sizeoftimestr,%H:%M:%S,ltime);/*打印数据包的时间戳和长度*/printf(%s.%.6dlen:%4d,timestr,header-ts.tv_usec,header-len);/*获得IP数据包头部的位置*/ih=(ip_header*)(pkt_data+14);//以太网头部长度/*打印协议类型*/inti;for(i=0;i10;i++){if(protocol[i].number==ih-proto){break;}}if(i=9)printf(%5s,protocol[i].name);elseprintf(%5s,Other);/*打印IP地址*/printf(%d.%d.%d.%d-%d.%d.%d.%d\n,ih-saddr.byte1,ih-saddr.byte2,ih-saddr.byte3,ih-saddr.byte4,ih-daddr.byte1,ih-daddr.byte2,ih-daddr.byte3,ih-daddr.byte4);}程序执行结果如下:上面三张图是程序运行的截图,第一列是数据包的时间戳,第二列是数据包的长度,第三列是数据包的协议类型,第四列是数据包的源IP地址和目的IP地址。四、实验分析程序执行过程:使用pcap_findalldevs_ex函数获取已连接的网络适配器列表。这个函数返回一个pcap_if结构的链表,每个这样的结构都包含了一个适配器的详细信息。其中数据域name表示适配器名称,但难以理解,如rpcap://\Device\NPF_{7CD080C7-2B67-4839-B6F6-1D90273D960A},另一个数据域description表示一个可以让人们理解的描述,如(Networkadapter'RealtekPCIeFEFamilyController'onlocalhost)。使用pcap_open()函数打开适配器,将这个函数的snaplen参数设为65535,这比能遇到的最大的MTU还要大,以保证能收到完整的数据包。另一个参数flag设为PCAP_OPENFLAG_PROMISCUOUS,意为混杂模式,不管这个数据包是不是发给本机的,都会去捕获。参数to_ms指定读取数据的超时时间,这里设置为1000ms,在适配器上进行读取操作都会在to_ms毫秒时间内响应。使用pcap_compile编译过滤器,我们可以创建一个char数组packet_filter[],值为ip赋给函数的第三个参数,过滤出ip数据报。使用pcap_setfilter设置过滤器,当pcap_setfilter()被调用时,这个过滤器将被应用到来自网络的所有数据包,并且,所有的符合要求的数据包将会立即复制给应用程序。使用pcap_loop函数开始捕捉数据包。除此之外,我们还需要编写一个回调函数供libpcap在收到每一个数据包后调用。在这个函数中我们对ip数据报的首部进行处理。得到源ip地址和目的ip地址。同时还将打印出ip数据报的协议类型和打印数据包的时间戳和长度
本文标题:使用Wincap编制一个简单的网络数据包监听与捕获程序
链接地址:https://www.777doc.com/doc-3879559 .html