Winpcap网络编程六之Winpcap学习教程,获取已安装设备的高级信息
2014-10-08 20:28
393 查看
上一节我们展示了如何获取适配器的基本信息 (如设备的名称和描述)。
实际上,获取适配器基本信息远远不止这些,让我们先看下pcap_if结构体的内容
一个地址列表
一个掩码列表 (each of which corresponds to an entry in the addresses list).
一个广播地址列表 (each of which corresponds to an entry in the addresses list).
一个目的地址列表 (each of which corresponds to an entry in the addresses list).
一个链接到下一个pcap_addr 的指针
下面的范例使用了ifprint()函数来打印出
pcap_if 结构体中所有的内容。程序对每一个由pcap_findalldevs_ex() 函数返回的pcap_if,都调用ifprint()函数来实现打印。代码如下:
改编版:
需要特别指出的是,如果你用的是VC,那么下面的ipv6信息是无法编译通过的,需要在VS2005以上的环境下才能编译通过。
我用的Eclipse,编译器是mingw,很遗憾,这个也不支持ipv6信息的获取,调试了一段时间后发现无法编译通过。
既然这样的话我们就将 包含ipv6信息的代码去掉来运行。
运行结果:
实际上,获取适配器基本信息远远不止这些,让我们先看下pcap_if结构体的内容
pcap_if * next if not NULL, a pointer to the next element in the list; NULL for the last element of the list char * name a pointer to a string giving a name for the device to pass to pcap_open_live() char * description if not NULL, a pointer to a string giving a human-readable description of the device pcap_addr * addresses a pointer to the first element of a list of addresses for the interface u_int flags PCAP_IF_ interface flags. Currently the only possible flag is PCAP_IF_LOOPBACK, that is set if the interface is a loopback interface.大家可以发现它有一个pcap_addr 的结构体,而这个结构体的组成如下:
pcap_addr * next if not NULL, a pointer to the next element in the list; NULL for the last element of the list sockaddr * addr a pointer to a struct sockaddr containing an address sockaddr * netmask if not NULL, a pointer to a struct sockaddr that contains the netmask corresponding to the address pointed to by addr. sockaddr * broadaddr if not NULL, a pointer to a struct sockaddr that contains the broadcast address corre sponding to the address pointed to by addr; may be null if the interface doesn't support broadcasts sockaddr * dstaddr if not NULL, a pointer to a struct sockaddr that contains the destination address corre sponding to the address pointed to by addr; may be null if the interface isn't a point- to-point interface
一个地址列表
一个掩码列表 (each of which corresponds to an entry in the addresses list).
一个广播地址列表 (each of which corresponds to an entry in the addresses list).
一个目的地址列表 (each of which corresponds to an entry in the addresses list).
一个链接到下一个pcap_addr 的指针
下面的范例使用了ifprint()函数来打印出
pcap_if 结构体中所有的内容。程序对每一个由pcap_findalldevs_ex() 函数返回的pcap_if,都调用ifprint()函数来实现打印。代码如下:
#include "pcap.h" #ifndef WIN32 #include <sys/socket.h> #include <netinet/in.h> #else #include <winsock.h> #endif // 函数原型 void ifprint(pcap_if_t *d); char *iptos(u_long in); char* ip6tos(struct sockaddr *sockaddr, char *address, int addrlen); int main() { pcap_if_t *alldevs; pcap_if_t *d; char errbuf[PCAP_ERRBUF_SIZE+1]; char source[PCAP_ERRBUF_SIZE+1]; printf("Enter the device you want to list:\n" "rpcap:// ==> lists interfaces in the local machine\n" "rpcap://hostname:port ==> lists interfaces in a remote machine\n" " (rpcapd daemon must be up and running\n" " and it must accept 'null' authentication)\n" "file://foldername ==> lists all pcap files in the give folder\n\n" "Enter your choice: "); fgets(source, PCAP_ERRBUF_SIZE, stdin); source[PCAP_ERRBUF_SIZE] = '\0'; /* 获得接口列表 */ if (pcap_findalldevs_ex(source, NULL, &alldevs, errbuf) == -1) { fprintf(stderr,"Error in pcap_findalldevs: %s\n",errbuf); exit(1); } /* 扫描列表并打印每一项 */ for(d=alldevs;d;d=d->next) { ifprint(d); } pcap_freealldevs(alldevs); return 1; } /* 打印所有可用信息 */ 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) { 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: %s\n", ip6tos(a->addr, ip6str, sizeof(ip6str))); break; default: printf("\tAddress Family Name: Unknown\n"); break; } } printf("\n"); } /* 将数字类型的IP地址转换成字符串类型的 */ #define IPTOSBUFFERS 12 char *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); sprintf(output[which], "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); return output[which]; } char* ip6tos(struct sockaddr *sockaddr, char *address, int addrlen) { socklen_t sockaddrlen; #ifdef WIN32 sockaddrlen = sizeof(struct sockaddr_in6); #else sockaddrlen = sizeof(struct sockaddr_storage); #endif if(getnameinfo(sockaddr, sockaddrlen, address, addrlen, NULL, 0, NI_NUMERICHOST) != 0) address = NULL; return address; }
改编版:
#include <stdio.h> #include <stdlib.h> #include <pcap.h> void ifprint(pcap_if_t *d); char *iptos(u_long in); //u_long即为 unsigned long int main(){ pcap_if_t * alldevs; //所有网络适配器 pcap_if_t *d; //选中的网络适配器 char errbuf[PCAP_ERRBUF_SIZE]; //错误缓冲区,大小为256 char source[PCAP_ERRBUF_SIZE]; int i = 0; //适配器计数变量 /** int pcap_findalldevs_ex ( char * source, struct pcap_rmtauth * auth, pcap_if_t ** alldevs, char * errbuf ); PCAP_SRC_IF_STRING代表用户想从一个本地文件开始捕获内容; */ //获取本地适配器列表 if(pcap_findalldevs_ex(PCAP_SRC_IF_STRING,NULL,&alldevs,errbuf) == -1){ //结果为-1代表出现获取适配器列表失败 fprintf(stderr,"Error in pcap_findalldevs_ex:\n",errbuf); //exit(0)代表正常退出,exit(other)为非正常退出,这个值会传给操作系统 exit(1); } //打印设备列表信息 /** d = alldevs 代表赋值第一个设备,d = d->next代表切换到下一个设备 结构体 pcap_if_t: pcap_if * next 指向下一个pcap_if,pcap_if_t和pcap_if 结构是一样的 char * name 代表适配器的名字 char * description 对适配器的描述 pcap_addr * addresses 适配器存储的地址 u_int flags 适配器接口标识符,值为PCAP_IF_LOOPBACK */ for(d = alldevs;d !=NULL;d = d->next){ printf("-----------------------------------------------------------------\nnumber:%d\nname:%s\n",++i,d->name); if(d->description){ //打印适配器的描述信息 printf("description:%s\n",d->description); }else{ //适配器不存在描述信息 printf("description:%s","no description\n"); } //打印本地环回地址 printf("\tLoopback: %s\n",(d->flags & PCAP_IF_LOOPBACK)?"yes":"no"); /** pcap_addr * next 指向下一个地址的指针 sockaddr * addr IP地址 sockaddr * netmask 子网掩码 sockaddr * broadaddr 广播地址 sockaddr * dstaddr 目的地址 */ pcap_addr_t *a; //网络适配器的地址用来存储变量 for(a = d->addresses;a;a = a->next){ //sa_family代表了地址的类型,是IPV4地址类型还是IPV6地址类型 switch (a->addr->sa_family) { case AF_INET: //代表IPV4类型地址 printf("Address Family Name:AF_INET\n"); if(a->addr){ //->的优先级等同于括号,高于强制类型转换,因为addr为sockaddr类型,对其进行操作须转换为sockaddr_in类型 printf("Address:%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: //代表IPV6类型地址 printf("Address Family Name:AF_INET6\n"); printf("this is an IPV6 address\n"); break; default: break; } } } //i为0代表上述循环未进入,即没有找到适配器,可能的原因为Winpcap没有安装导致未扫描到 if(i == 0){ printf("interface not found,please check winpcap installation"); } //释放网络适配器列表 pcap_freealldevs(alldevs); int inum; scanf_s("%d", &inum); return 0; } /* 将数字类型的IP地址转换成字符串类型的 */ #define IPTOSBUFFERS 12 char *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); sprintf_s(output[which], "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); return output[which]; }
需要特别指出的是,如果你用的是VC,那么下面的ipv6信息是无法编译通过的,需要在VS2005以上的环境下才能编译通过。
我用的Eclipse,编译器是mingw,很遗憾,这个也不支持ipv6信息的获取,调试了一段时间后发现无法编译通过。
既然这样的话我们就将 包含ipv6信息的代码去掉来运行。
#include "pcap.h" #ifndef WIN32 #include <sys/socket.h> #include <netinet/in.h> #else #include <winsock.h> #endif // 函数原型 void ifprint(pcap_if_t *d); char *iptos(u_long in); char* ip6tos(struct sockaddr *sockaddr, char *address, int addrlen); int main() { pcap_if_t *alldevs; pcap_if_t *d; char errbuf[PCAP_ERRBUF_SIZE+1]; char source[PCAP_ERRBUF_SIZE+1]; printf("Enter the device you want to list:\n" "rpcap:// ==> lists interfaces in the local machine\n" "rpcap://hostname:port ==> lists interfaces in a remote machine\n" " (rpcapd daemon must be up and running\n" " and it must accept 'null' authentication)\n" "file://foldername ==> lists all pcap files in the give folder\n\n" "Enter your choice: "); fgets(source, PCAP_ERRBUF_SIZE, stdin); source[PCAP_ERRBUF_SIZE] = '\0'; /* 获得接口列表 */ if (pcap_findalldevs_ex(source, NULL, &alldevs, errbuf) == -1) { fprintf(stderr,"Error in pcap_findalldevs: %s\n",errbuf); exit(1); } /* 扫描列表并打印每一项 */ for(d=alldevs;d;d=d->next) { ifprint(d); } pcap_freealldevs(alldevs); return 1; } /* 打印所有可用信息 */ 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) { 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: %s\n", ip6tos(a->addr, ip6str, sizeof(ip6str))); break; */ default: printf("\tAddress Family Name: Unknown\n"); break; } } printf("\n"); } /* 将数字类型的IP地址转换成字符串类型的 */ #define IPTOSBUFFERS 12 char *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); sprintf(output[which], "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); return output[which]; } /* char* ip6tos(struct sockaddr *sockaddr, char *address, int addrlen) { socklen_t sockaddrlen; #ifdef WIN32 sockaddrlen = sizeof(struct sockaddr_in6); #else sockaddrlen = sizeof(struct sockaddr_storage); #endif if(getnameinfo(sockaddr, sockaddrlen, address, addrlen, NULL, 0, NI_NUMERICHOST) != 0) address = NULL; return address; } */
运行结果:
Enter the device you want to list: rpcap:// ==> lists interfaces in the local machine rpcap://hostname:port ==> lists interfaces in a remote machine (rpcapd daemon must be up and running and it must accept 'null' authentication) file://foldername ==> lists all pcap files in the give folder Enter your choice: rpcap://
rpcap://\Device\NPF_{5AC72F8D-019C-4003-B51B-7ABB67AF392A} Description: Network adapter 'Microsoft' on local host Loopback: no Address Family: #23 Address Family Name: Unknown Address Family: #23 Address Family Name: Unknown rpcap://\Device\NPF_{C17EB3F6-1E86-40E5-8790-AC2518B74D05} Description: Network adapter 'Microsoft' on local host Loopback: no Address Family: #23 Address Family Name: Unknown Address Family: #2 Address Family Name: AF_INET Address: 192.168.95.1 Netmask: 255.255.255.0 Broadcast Address: 255.255.255.255 rpcap://\Device\NPF_{33E23A2F-F791-409B-8452-A3FB5A78B73E} Description: Network adapter 'Qualcomm Atheros Ar81xx series PCI-E Ethernet Controller' on local host Loopback: no Address Family: #23 Address Family Name: Unknown Address Family: #23 Address Family Name: Unknown Address Family: #23 Address Family Name: Unknown Address Family: #2 Address Family Name: AF_INET Address: 121.250.216.237 Netmask: 255.255.255.0 Broadcast Address: 255.255.255.255 rpcap://\Device\NPF_{DCCF036F-A9A8-4225-B980-D3A3F0575F5B} Description: Network adapter 'Microsoft' on local host Loopback: no Address Family: #23 Address Family Name: Unknown Address Family: #23 Address Family Name: Unknown rpcap://\Device\NPF_{D62A0060-F424-46FC-83A5-3394081685FD} Description: Network adapter 'Microsoft' on local host Loopback: no Address Family: #23 Address Family Name: Unknown Address Family: #2 Address Family Name: AF_INET Address: 192.168.191.1 Netmask: 255.255.255.0 Broadcast Address: 255.255.255.255 rpcap://\Device\NPF_{B5224A53-8450-4537-AB3B-9869158121CD} Description: Network adapter 'Microsoft' on local host Loopback: no Address Family: #23 Address Family Name: Unknown Address Family: #2 Address Family Name: AF_INET Address: 0.0.0.0 Netmask: 255.0.0.0 Broadcast Address: 255.255.255.255
相关文章推荐
- WinPcap教程:(2)获取已安装设备的高级信息
- winPcap学习笔记2_获取已安装设备的高级信息(转)
- WinPcap学习(三)获取已安装设备的高级信息
- WinPcap之获取已安装设备的高级信息
- WinPcap教程(2):获取设备高级信息
- WinPcap编程【3】获取已安装设备的高级信息
- WinPcap之获取已安装设备的高级信息
- WinPcap教程(2):获取设备高级信息
- Winpcap网络编程五之Winpcap学习教程,获取设备列表
- winPcap_4_获取已安装设备的高级信息
- WinPcap编程【3】获取已安装设备的高级信息
- winpcap编程学习笔记(2) 获取已安装设备的高级信息
- 获取已安装设备的高级信息
- WinPcap笔记(3):获取已安装设备的详细信息
- WinPcap编程入门(2)——获取安装设备的高级信息
- WinPcap基础知识(第二课:获得已安装设备的高级信息)
- 获取已安装设备的高级信息
- 【Windows 8 Store App】学习一:获取设备信息
- android 获取设备上安装的非系统应用信息
- Winpcap网络编程七之Winpcap学习教程,抓包,抓包!