winpcap学习笔记--(Opening an adapter and capturing the packets)

来源:互联网 发布:淘宝切片上传有空隙 编辑:程序博客网 时间:2024/06/08 06:59
#define WIN32#define HAVE_REMOTE#include <stdlib.h>#include <pcap.h>#include <stdio.h>//// NOTE: remember to include WPCAP and HAVE_REMOTE among your// preprocessor definitions.//#pragma comment(lib,"wpcap.lib")#pragma comment(lib,"packet.lib")//#pragma comment(lib,"wsock32.lib")void packet_handler(u_char *param,const struct pcap_pkthdr *header, const u_char *pkt_data);char *iptos(u_long in);//char 和 unsigned char的区别/*char 和 unsigned char是无符号的两者都作为字符用的话是没有区别的,但当整数用时有区别: char 整数范围为-128到127( 0x80__0x7F),  而unsigned char 整数范围为0到255( 0__0xFF )多数情况下,char ,signed char 、unsigned char 类型的数据具有相同的特性然而当你把一个单字节的数赋给一个大整型 数域时,便会看到它们在符号扩展上的差异。另一个区别表现在当把一个介于128和255之间的数赋给signed char 变量时编译器必须先进行数值转化,同样还会出现警告。若使用十六进制进行赋值使用unsigned char 要方便一些.根据编译器具体实现情况不同,char要么和signed char等同,要么和unsigned char等同.*/void ifprint(pcap_if_t *d){  pcap_addr_t *a;  char ip6str[128];  /* 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) {  //这儿为什么要for?  /*  因为一个d->addresses里面可能有多个版本的协议!!如现在就有IPV4和IPV6  IPV4是第二个,第一个是IPV6  */    printf("\tAddress Family: #%d\n",a->addr->sa_family);      switch(a->addr->sa_family)    {      case AF_INET:        printf("\tAddress Family Name: AF_INET\n");        if (a->addr)          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;      case AF_INET6:        printf("\tAddress Family Name: AF_INET6\n");        if (a->addr)          printf("\tAddress: IPV6\n");       break;      default:        printf("\tAddress Family Name: Unknown\n");        break;    }  }  printf("\n");}#define IPTOSBUFFERS    12char *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);    _snprintf_s(output[which], sizeof(output[which]), sizeof(output[which]),"%d.%d.%d.%d", p[0], p[1], p[2], p[3]);    return output[which];}int main(){pcap_if_t *alldevs;pcap_if_t *d;int inum;int i=0;//pcap_t结构体/*Descriptor of an open capture instance. This structure is opaque to the user, that handles its content through the functions provided by wpcap.dll.源文件中:typedef struct pcap pcap_t;*/pcap_t *adhandle;char errbuf[PCAP_ERRBUF_SIZE];if(pcap_findalldevs_ex(PCAP_SRC_IF_STRING,NULL,&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\n",++i,d->name);/*Print Description of the device*///ifprint(d);printf("\tDescription:%s\n",d->description);printf("\n");}if(i==0){printf("\nNo interfaces found!\n");return -1;}printf("Enter the interface number (1-%d):",i);scanf_s("%d",&inum);//scanf_s的用法/*ANSI C中没有scanf_s(),只有scanf(),scanf()在读取时不检查边界,所以可能会造成内存泄露。所以vc++2005/2008中提供了scanf_s(),在最新的VS2013中也提供了scanf_s()。在调用时,必须提供一个数字以表明最多读取多少位字符。scanf_s的百度百科:http://baike.baidu.com/view/3529726.htm?fr=aladdin*/if(inum < 1 || inum > i){printf("\nInterface number out of range.All the device will be released\n");/*Free the device list*/pcap_freealldevs(alldevs);return -1;}/*Jump to the selected adapter */for(d=alldevs, i=0; i<inum-1 ;d=d->next,i++){}/*Open the device*/if( (adhandle=pcap_open(d->name,//name of device65536,//portion of the packet to capturePCAP_OPENFLAG_PROMISCUOUS,//promiscuous mode1000,//read time//3秒抓一次包NULL,//authentication on the remote machineerrbuf//error buffer) ) == NULL){fprintf(stderr,"\nUnable to open the adapter,%s\n",d->name);/*Free the device list*/pcap_freealldevs(alldevs);return -1;}printf("\nlistening on %s...\n",d->description);/*don't forget free the device list*/pcap_freealldevs(alldevs);/*start the capture*///pcap_loop参数/*int pcap_loop(pcap_t * p,int cnt,//抓几个包,非正整数就会一直抓下去,除非出错pcap_handler callback,//回调函数u_char * user )*///packet_handler/*When pcap_dispatch() or pcap_loop() are called by the user, the packets are passed to the application by means of this callback. user is a user-defined parameter that contains the state of the capture session, it corresponds to the user parameter of pcap_dispatch() and pcap_loop(). pkt_header is the header associated by the capture driver to the packet. It is NOT a protocol header. pkt_data points to the data of the packet, including the protocol headers.*/pcap_loop(adhandle, 0, packet_handler, NULL);return 0;}/*Callback function invoked by libpcap for every incoming packet*///Some basic structure//pcap_pkthdr/*struct pcap_pkthdr{struct timeval ts//time stamp bpf_u_int32 caplen//length of portion present bpf_u_int32 len//length this packet (off wire) }Header of a packet in the dump file.Each packet in the dump file is prepended with this generic header. This gets around the problem of different headers for different packet interfaces.*///bpf_u_int32 /*32-bit unsigned integersourcefile:typedef u_int bpf_u_int32; *///timeval/*struct timeval {long tv_sec; // secondslong tv_usec; // and microseconds};*/void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data){struct tm ltime;//http://baike.baidu.com/link?url=W-8_745SPVzWNFrZ2YfQBVYl_zPJpsdY-O14PvsFmfYRFGs-9-06CadT8x0aL5xDQ-mEF73DDqAwHqfF69ZKV_char timestr[16];time_t local_tv_sec;/* *unused variable */(VOID)(param);(VOID)(pkt_data);/*convert the timestamp to readable format*/local_tv_sec = header->ts.tv_sec;// 转换为tm结构localtime_s(<ime,&local_tv_sec);strftime( timestr,sizeof timestr, "%H:%M:%S", <ime);printf("%s,%.6d len:%d\n",timestr, header->ts.tv_sec, header->len);}

0 0
原创粉丝点击