#include<pcap.h>#include<stdlib.h>typedef struct macaddress{u_char mac1;u_char mac2;u_char mac3;u_char mac4;u_char mac5;u_char mac6;};typedef struct macheader{macaddress dest;macaddress src;u_short type;};//IP地址32位,这里用4个字节来表示。
typedef struct ipaddress{u_char by1;u_char by2;u_char by3;u_char by4;};//IP报文格式typedef struct ipbaowen{u_char ver_ihl;//首部长度和版本号u_char tos;//服务类型u_short tlen;// 报文总长度u_short ident;// 标识u_short flags_fo;// 标志和片偏移u_char ttl;// 生存时间u_char proto;//协议类型#define IP_ICMP 1#define IP_IGMP 2#define IP_TCP 6#define IP_UDP 17#define IP_IGRP 88#define IP_OSPF 89u_short crc;ipaddress saddr;ipaddress daddr;};typedef struct tcpheader{u_short sport;// 源端口u_short dport;// 目的端口u_int th_seq;// 序列号u_int th_ack;// 确认号u_char th_lenand;// 报文长度u_char th_flags;//标志#define TH_FIN 0x01#define TH_SYN 0x02#define TH_RST 0x04#define TH_PSH 0x08#define TH_ACK 0x10#define TH_URG 0x20u_short th_win;//窗口u_short th_sum;//校验和u_short th_urp;//紧急};// UDP格式typedef struct udpheader{u_short sport;// Source port 源端口u_short dport;// Destination port 目的端口u_short uh_len;// Datagram length 用户数据包长度u_short uh_sum;// Checksum 校验和};typedef struct udpnode{ipaddress saddr;ipaddress daddr;u_short sport;u_short dport;u_short length;u_int upnum;u_int downnum;struct udpnode * next;struct udpnode * pre;};typedef struct tcpnode{ipaddress saddr;ipaddress daddr;u_short sport;u_short dport;u_short length;u_int upnum;u_int downnum;struct tcpnode * next;struct tcpnode * pre;};#define tcphashtablelength 10#define udphashtablelength 10udpnode udphashtable[udphashtablelength];tcpnode tcphashtable[tcphashtablelength];void initudp(){for(int i =0; i < udphashtablelength; i++){udphashtable[i].pre = udphashtable + i;udphashtable[i].next = NULL;udphashtable[i].length =0;}}void inittcp(){for(int i =0; i < tcphashtablelength; i++){tcphashtable[i].pre = tcphashtable + i;tcphashtable[i].next = NULL;tcphashtable[i].length =0;}}int hash(int a,int b,int c,int d){return(a %2+ b %3+ c %4+ d %5);}void packet_handler(u_char *param,const struct pcap_pkthdr *header,const u_char *pkt_data); void dispatcher_handler(u_char *,const struct pcap_pkthdr *,const u_char *);void showudphashtable();void showtcphashtable();////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////int main(){FILE * PP;pcap_if_t *alldevs;pcap_if_t *d;int inum;int i =0;pcap_t *adhandle;char errbuf[PCAP_ERRBUF_SIZE];u_int netmask;char packet_filter[]="ip";struct bpf_program fcode;#define LINE_LEN 10pcap_t *fp;char errbuf2[PCAP_ERRBUF_SIZE];char source[PCAP_BUF_SIZE];initudp();//////////////////////////////////inittcp();////////////////////////////////////获取设备列表;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\n",++i, d->name);//设备名printf(" (%s)\n", d->description);//设备描述}printf("适配器总共有%d个\n", i);if(i ==0){printf("\nNo?interfaces?found!?Make?sure?WinPcap?is?installed.\n");return-1;}//输入某个适配器;printf("Enter the device number(1-%d):", i);scanf_s("%d",&inum);if(inum <=0|| inum>i){printf("\ndevice number out of range.\n");pcap_freealldevs(alldevs);return-1;}//使d指向输入的那个;for(d = alldevs, i =0; i< inum -1; d = d->next, i++);//打开指定的适配器;if((adhandle = pcap_open_live(d->name,65536,1,1000, errbuf))== NULL){fprintf(stderr,"\nUnable?to?open?the?adapter.?%s?is?not?supported?by?WinPcap\n");pcap_freealldevs(alldevs);/*?Free?the?device?list?*/return-1;}//检查链路层if(pcap_datalink(adhandle)!= DLT_EN10MB){fprintf(stderr,"\nThis?program?works?only?on?Ethernet?networks.\n");/*?Free?the?device?list?*/pcap_freealldevs(alldevs);return-1;}/* 获得接口第一个地址的掩码 */if(d->addresses != NULL)//netmask =((struct sockaddr_in*)(d->addresses->netmask))->sin_addr.S_un.S_addr; elsenetmask =0xffffff;//编译过滤器if(pcap_compile(adhandle,&fcode, packet_filter,1, netmask)<0){fprintf(stderr,"\nUnable to compile the packet filter. Check the syntax.\n");/*?Free?the?device?list?*/pcap_freealldevs(alldevs);return-1;}//设置过滤器if(pcap_setfilter(adhandle,&fcode)<0){fprintf(stderr,"\nError?setting?the?filter.\n");pcap_freealldevs(alldevs);return-1;}printf("\nlistening on : %s...\n", d->description);pcap_freealldevs(alldevs);pcap_dumper_t * dumpfp;dumpfp = pcap_dump_open(adhandle,"data");char[]="data";//开始抓包////////////////////////////////////////////////////pcap_loop(adhandle,100, packet_handler,(u_char*)dumpfp);pcap_close(adhandle);pcap_dump_close(dumpfp);/* 根据新的WinPcap语法创建源字符串 */if(pcap_createsrcstr(source,// variable that will keep the source string PCAP_SRC_FILE,// we want to open a fileNULL,// remote hostNULL,// port on the remote host,// name of the want to openerrbuf // error buffer)!=0){fprintf(stderr,"/nError creating a source string/n");return-1;}/* 打开捕捉文件 */if((fp = pcap_open(source,// name of the device65536,// portion of the packet to capture// 65536 guarantees that the whole packet will be captured on all the link layers PCAP_OPENFLAG_PROMISCUOUS,// promiscuous mode1000,// read timeoutNULL,// authentication on the remote machineerrbuf2 // error buffer))== NULL){fprintf(stderr,"/nUnable to open the ", source);return-1;}showudphashtable();showtcphashtable();printf("hashtable----show----is----stopped\n");//打开离线pcap文件,将其显示出来;pcap_loop(fp,0, dispatcher_handler, NULL);system("pause");return0;}void showudphashtable(){printf("start to show udphashtable-------->\n");printf("UDP hashtable:\n");int i;for(i =0; i < udphashtablelength; i++){udpnode *s;printf(" key = %d:\n", i);s = udphashtable + i;while((s->next)!= NULL){printf("\n");s = s->next;printf("这是IP:%d.%d.%d.%d 端口:%d------和-----IP:%d.%d.%d.%d端口:%d之间的连接\n",s->saddr.by1,s->saddr.by2,s->saddr.by3,s->saddr.by4,s->sport,s->daddr.by1,s->daddr.by2,s->daddr.by3,s->daddr.by4,s->dport);printf("数据包总长度:%d字节上行数据包数目:%d个下行数据包数目:%d个\n", s->length,s->upnum,s->downnum);}}printf("UDP显示完---------------------------------------------------------------------------------------------------\n");}void showtcphashtable(){printf("begin:\n");printf("TCP hashtable : ");int i;for(i =0; i < tcphashtablelength; i++){tcpnode *s;printf("%d\n", i);s = tcphashtable + i;while((s->next)!= NULL){s = s->next;printf("目的端口%d->源端口%d->数据包总长度%d字节\n",s->dport,s->sport,s->length);}}printf("TCP显示完--------------------------------------------------------------------------------------\n") ;}////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////void dispatcher_handler(u_char *temp1,const struct pcap_pkthdr *header,const u_char*pkt_data){u_int i =0;/* Print the packet */for(i =1; i < header->caplen +1; i++){printf("%x", pkt_data[i -1]);if((i%LINE_LEN)==30) printf("\n");//每30位一组换行一次;}printf("\n");}int compare(udpnode **p, udpnode **pd){int flag =0;if((*pd)->daddr.by1 ==(*p)->daddr.by1) flag +=1;if((*pd)->daddr.by2 ==(*p)->daddr.by2) flag +=1;if((*pd)->daddr.by3 ==(*p)->daddr.by3) flag +=1;if((*pd)->daddr.by4 ==(*p)->daddr.by4) flag +=1;if((*pd)->saddr.by1 ==(*p)->saddr.by1) flag +=1;if((*pd)->saddr.by2 ==(*p)->saddr.by2) flag +=1;if((*pd)->saddr.by3 ==(*p)->saddr.by3) flag +=1;if((*pd)->saddr.by4 ==(*p)->saddr.by4) flag +=1;if((*pd)->sport ==(*p)->sport) flag +=1;if((*pd)->dport ==(*p)->dport) flag +=1;if(flag ==10) flag =2;else flag =0;int f =0;if((*pd)->daddr.by1 ==(*p)->saddr.by1) f +=1;if((*pd)->daddr.by2 ==(*p)->saddr.by2) f +=1;if((*pd)->daddr.by3 ==(*p)->saddr.by3) f +=1;if((*pd)->daddr.by4 ==(*p)->saddr.by4) f +=1;if((*pd)->saddr.by1 ==(*p)->daddr.by1) f +=1;if((*pd)->saddr.by2 ==(*p)->daddr.by2) f +=1;if((*pd)->saddr.by3 ==(*p)->daddr.by3) f +=1;if((*pd)->saddr.by4 ==(*p)->daddr.by4) f +=1;if((*pd)->sport !=(*p)->dport) f +=1;if((*pd)->dport !=(*p)->sport) f +=1;if(f ==10) f =1;else f =0;return(flag + f);}void packet_handler(u_char *dumpfp,const struct pcap_pkthdr *header,const u_char *pkt_data) {macheader *mh;ipbaowen *ih;tcpheader *th;udpheader *uh;u_int iplen =0;u_int key =0;int flag =0;//定义源端口和目的端口;u_short sport =0;u_short dport =0;//Mac帧各个指针找到自己对应的位置;mh =(macheader*)pkt_data;//mac头ih =(ipbaowen*)(pkt_data +14);//ip头iplen =(ih->ver_ihl &0xf)*4;//ip层的长度uh =(udpheader *)((u_char*)ih + iplen);//udp指针th =(tcpheader *)((u_char*)ih + iplen);//tcp指针//边收边存哈希//printf("%d\n", ih->proto);//system("pause");if((ih->proto)==17)//udp报文2{udpnode *p;p =(udpnode*)malloc(sizeof(udpnode));p->downnum =0;p->upnum =1;int a =0, b =0;a =(ih->saddr.by1)+(ih->saddr.by2)+(ih->saddr.by3)+(ih->saddr.by4);b =(ih->daddr.by1)+(ih->daddr.by2)+(ih->daddr.by3)+(ih->daddr.by4);key = hash(a, b, uh->dport, uh->sport);//得到对应的hash值;//printf("%d\n", key);////////////////////////////////////////////////将新来的节点的数据装入结构体;p->daddr.by1 = ih->daddr.by1;p->daddr.by2 = ih->daddr.by2;p->daddr.by3 = ih->daddr.by3;p->daddr.by4 = ih->daddr.by4;p->saddr.by1 = ih->saddr.by1;p->saddr.by2 = ih->saddr.by2;p->saddr.by3 = ih->saddr.by3;p->saddr.by4 = ih->saddr.by4;p->dport = uh->dport;p->sport = uh->sport;p->length = header->caplen;//判断udphashtable表中是否有该节点;udpnode *pd;pd = udphashtable + key;do{flag = compare(&p,&pd);if(flag>0){break;}if((pd->next)== NULL){break;}else{ pd = pd->next;}}while(1);//有该节点则更新信息;if(flag>0){pd->length =(pd->length)+(p->length);if(flag ==1){ pd->downnum =(pd->downnum)+1;}if(flag ==2){ pd->upnum =(pd->upnum)+1;}}//是否插入新的节点,建立新的节点;if(flag ==0){p->next = NULL;p->pre = udphashtable[key].pre;udphashtable[key].pre->next = p;udphashtable[key].pre = p;}}if((ih->proto)==6)//tcpbaowen{tcpnode *q;q =(tcpnode*)malloc(sizeof(tcpnode));int a, b;a =(ih->saddr.by1)+(ih->saddr.by2)+(ih->saddr.by3)+(ih->saddr.by4);b =(ih->daddr.by1)+(ih->daddr.by2)+(ih->daddr.by3)+(ih->saddr.by4);key = hash(a, b, uh->dport, uh->sport);//得到对应的hash值;//将数据包的内容装到结构体中;q->daddr.by1 = ih->daddr.by1;q->daddr.by2 = ih->daddr.by2;q->daddr.by3 = ih->daddr.by3;q->daddr.by4 = ih->daddr.by4;q->saddr.by1 = ih->saddr.by1;q->saddr.by2 = ih->saddr.by2;q->saddr.by3 = ih->saddr.by3;q->saddr.by4 = ih->saddr.by4;q->dport = th->dport;q->sport = th->sport;q->length = header->len;//判断TCPhashtable里是否有该连接//有,则更新节点信息;//如果没有,则建立新的节点q->next = NULL;q->pre = tcphashtable[key].pre;tcphashtable[key].pre->next = q;tcphashtable[key].pre = q;}struct tm*ltime;char timestr[16];time_t aaa;aaa = header->_sec;ltime = localtime(&aaa);strftime(timestr,sizeof timestr,"%H:%M:%S", ltime);printf("时间:%s 长度;%d字节\n", timestr, header->caplen);//打印时间和长度//输出源和目的Mac地址(链路层)printf("目的Mac地址%x:%x:%x:%x:%x:%x\n源Mac地址%x:%x:%x:%x:%x:%x\n",mh->dest.mac1,mh->dest.mac2,mh->dest.mac3,mh->dest.mac4,mh->dest.mac5,mh->dest.mac6,mh->src.mac1,mh->src.mac2,mh->src.mac3,mh->src.mac4,mh->src.mac5,mh->src.mac6);if((mh->type)==8)printf("网际协议IPv4\n");//网络层协议类型printf("首部长度和版本号%d\n", ih->ver_ihl);//首部长度和版本号printf("服务类型%d\n", ih->tos);//服务类型printf("IP报文总长度%d字节\n", ih->tlen);// 报文总长度printf("标志%d\n", ih->ident);// 标识printf("标志和片偏移%d\n", ih->flags_fo);// 生存时间ih->flags_fo, // 标志和片偏移printf("生存时间%d\n", ih->ttl);// 生存时间if((ih->proto)==6) printf("协议类型:TCP\n");//协议类型else if((ih->proto)==17)printf("协议类型:UDP\n");//协议类型else printf("wrong\n");printf("首部校验和%d\n", ih->crc);printf("源IP地址 %d.%d.%d.%d 目的IP %d.%d.%d.%d\n",ih->saddr.by1,ih->saddr.by2,ih->saddr.by3,ih->saddr.by4,ih->daddr.by1,ih->daddr.by2,ih->daddr.by3,ih->daddr.by4);//进入传输层,判断是什么类型的协议th->th_seq = ntohs(th->th_seq);th->th_ack = ntohs(th->th_ack);th->sport = ntohs(th->sport);th->dport = ntohs(th->dport);//tcpif((ih->proto)==6){printf("源端口:%d 目的端口:%d序列号:%d确认号:%d 报头长度%: 标志%d: 窗口%d: 校验和%d: 紧急%d: ",th->sport,th->dport,th->th_seq,th->th_ack,th->th_lenand,th->th_flags,th->th_win,th->th_sum,th->th_urp);}//udpif((ih->proto)==17){printf("源端口:%d目的端口:%d用户数据包长度:%d校验和:%d",uh->sport,uh->dport,uh->uh_len,uh->uh_sum);}if((ih->proto)!=6&&(ih->proto)!=17){printf("不是IPv4协议\n");}printf("\n\n\n");pcap_dump(dumpfp, header, pkt_data);}。