由 pcap_findalldevs_ex() 返回的每一个 pcap_if 结构体,都包含一个 pcap_addr 结构体,这个结构体由如下元素组成:
另外,函数 pcap_findalldevs_ex() 还能 返回远程适配器信息 和 一个位于所给的本地文件夹的pcap文件列表。
下面的范例使用了ifprint()函数来打印出 pcap_if 结构体中所有的内容。程序对每一个由 pcap_findalldevs_ex() 函数返回的pcap_if,都调用ifprint()函数来实现打印。
1 #include "pcap.h" 2 #pragma comment(lib, "wpcap.lib") 3 #pragma comment(lib, "Packet.lib") 4 #pragma comment(lib, "wsock32.lib") 5 6 7 8 #ifndef WIN32 9 #include <sys/socket.h> 10 #include <netinet/in.h> 11 #else 12 #include <winsock.h> 13 #endif 14 15 16 // 函数原型 17 void ifprint(pcap_if_t *d); 18 char *iptos(u_long in); 19 char* ip6tos(struct sockaddr *sockaddr, char *address, int addrlen); 20 21 22 int main() 23 { 24 pcap_if_t *alldevs; 25 pcap_if_t *d; 26 char errbuf[PCAP_ERRBUF_SIZE+1]; 27 char source[PCAP_ERRBUF_SIZE+1]; 28 29 printf("Enter the device you want to list:\n" 30 "rpcap:// ==> lists interfaces in the local machine\n" 31 "rpcap://hostname:port ==> lists interfaces in a remote machine\n" 32 " (rpcapd daemon must be up and running\n" 33 " and it must accept 'null' authentication)\n" 34 "file://foldername ==> lists all pcap files in the give folder\n\n" 35 "Enter your choice: "); 36 37 fgets(source, PCAP_ERRBUF_SIZE, stdin); 38 source[PCAP_ERRBUF_SIZE] = '\0'; 39 40 /* 获得接口列表 */ 41 if (pcap_findalldevs_ex(source, NULL, &alldevs, errbuf) == -1) 42 { 43 fprintf(stderr,"Error in pcap_findalldevs: %s\n",errbuf); 44 exit(1); 45 } 46 47 /* 扫描列表并打印每一项 */ 48 for(d=alldevs;d;d=d->next) 49 { 50 ifprint(d); 51 } 52 53 pcap_freealldevs(alldevs); 54 55 return 1; 56 } 57 58 59 60 /* 打印所有可用信息 */ 61 void ifprint(pcap_if_t *d) 62 { 63 pcap_addr_t *a; 64 char ip6str[128]; 65 66 /* 设备名(Name) */ 67 printf("%s\n",d->name); 68 69 /* 设备描述(Description) */ 70 if (d->description) 71 printf("\tDescription: %s\n",d->description); 72 73 /* Loopback Address*/ 74 printf("\tLoopback: %s\n",(d->flags & PCAP_IF_LOOPBACK)?"yes":"no"); 75 76 /* IP addresses */ 77 for(a=d->addresses;a;a=a->next) { 78 printf("\tAddress Family: #%d\n",a->addr->sa_family); 79 80 switch(a->addr->sa_family) 81 { 82 case AF_INET: 83 printf("\tAddress Family Name: AF_INET\n"); 84 if (a->addr) 85 printf("\tAddress: %s\n",iptos(((struct sockaddr_in *)a->addr)->sin_addr.s_addr)); 86 if (a->netmask) 87 printf("\tNetmask: %s\n",iptos(((struct sockaddr_in *)a->netmask)->sin_addr.s_addr)); 88 if (a->broadaddr) 89 printf("\tBroadcast Address: %s\n",iptos(((struct sockaddr_in *)a->broadaddr)->sin_addr.s_addr)); 90 if (a->dstaddr) 91 printf("\tDestination Address: %s\n",iptos(((struct sockaddr_in *)a->dstaddr)->sin_addr.s_addr)); 92 break; 93 /* 94 case AF_INET6: 95 printf("\tAddress Family Name: AF_INET6\n"); 96 if (a->addr) 97 printf("\tAddress: %s\n", ip6tos(a->addr, ip6str, sizeof(ip6str))); 98 break; 99 */ 100 default: 101 printf("\tAddress Family Name: Unknown\n"); 102 break; 103 } 104 } 105 printf("\n"); 106 } 107 108 109 110 /* 将数字类型的IP地址转换成字符串类型的 */ 111 #define IPTOSBUFFERS 12 112 char *iptos(u_long in) 113 { 114 static char output[IPTOSBUFFERS][3*4+3+1]; 115 static short which; 116 u_char *p; 117 118 p = (u_char *)∈ 119 which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1); 120 sprintf(output[which], "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); 121 return output[which]; 122 } 123 124 125 /* 126 char* ip6tos(struct sockaddr *sockaddr, char *address, int addrlen) 127 { 128 socklen_t sockaddrlen; 129 130 #ifdef WIN32 131 sockaddrlen = sizeof(struct sockaddr_in6); 132 #else 133 sockaddrlen = sizeof(struct sockaddr_storage); 134 #endif 135 136 137 if(getnameinfo(sockaddr, 138 sockaddrlen, 139 address, 140 addrlen, 141 NULL, 142 0, 143 NI_NUMERICHOST) != 0) address = NULL; 144 145 return address; 146 } 147 */
结果:
此处只能显示电脑的ipv4的网卡信息,不知道为什么不能有ipv6的代码时,不能编译通过,不知道是包不支持,还是系统不支持;
int pcap_findalldevs_ex ( char * source, struct pcap_rmtauth * auth, pcap_if_t ** alldevs, char * errbuf )
·该函数请查看前一篇;
struct pcap_rmtauth{ int type //Type of the authentication required. char * username //Zero-terminated string containing the username that has to be used on the remote machine for authentication. char * password //Zero-terminated string containing the password that has to be used on the remote machine for authentication. };
typedef struct pcap_if pcap_if_t;
struct 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. };
typedef struct pcap_addr pcap_addr_t;
struct 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 };
struct sockaddr { unsigned short sa_family; char sa_data[14]; };
·详细的请看前面的socket编程;
struct sockaddr_in{ short sin_family; unsigned short sin_port; struct in_addr sin_addr; char sin_zero[8]; };
The in_addr structure represents a host by its Internet address.
struct in_addr { union { struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b; struct { u_short s_w1,s_w2; } S_un_w; u_long S_addr; } S_un; };
Get a string from a stream.
char *fgets( char *string, int n, FILE *stream ); wchar_t *fgetws( wchar_t *string, int n, FILE *stream );