显示适配器详细信息
先贴上代码
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include "pcap.h" 5 #include <winsock2.h> 6 7 typedef struct sockaddr_in sockad; 8 9 /* 从tcptraceroute数字IP地址转换为字符串 */ 10 #define IPTOSBUFFERS 12 11 char *iptos(u_long in) 12 { 13 static char output[IPTOSBUFFERS][3*4+3+1]; 14 static short which; 15 u_char *p; 16 17 p = (u_char *)∈ 18 which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1); 19 sprintf(output[which], "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); 20 return output[which]; 21 } 22 23 /* 给定的接口上打印所有可用的信息 */ 24 void ifprint(pcap_if_t *d) 25 { 26 pcap_addr_t *a; 27 28 /* 名字 */ 29 printf("%s ",d->name); 30 31 /* 描述 */ 32 if (d->description) 33 printf(" 描述: %s ",d->description); 34 35 /* 环回地址*/ 36 printf(" 环回: %s ",(d->flags & PCAP_IF_LOOPBACK)?"yes":"no"); 37 38 /* IP addresses */ 39 for(a=d->addresses;a;a=a->next) { 40 printf(" Address Family: #%d ",a->addr->sa_family); 41 42 switch(a->addr->sa_family) 43 { 44 case AF_INET: 45 printf(" Address Family Name: AF_INET "); 46 if (a->addr) 47 printf(" IP地址: %s ",iptos(((struct sockaddr_in *)a->addr)->sin_addr.s_addr)); 48 if (a->netmask) 49 printf(" 子网掩码: %s ",iptos(((struct sockaddr_in *)a->netmask)->sin_addr.s_addr)); 50 if (a->broadaddr) 51 printf(" 广播地址: %s ",iptos(((struct sockaddr_in *)a->broadaddr)->sin_addr.s_addr)); 52 if (a->dstaddr) 53 printf(" 目标地址: %s ",iptos(((struct sockaddr_in *)a->dstaddr)->sin_addr.s_addr)); 54 break; 55 default: 56 printf(" Address Family Name: Unknown "); 57 break; 58 } 59 } 60 printf(" "); 61 } 62 63 int main() 64 { 65 pcap_if_t *alldevs; 66 pcap_if_t *d; 67 char errbuf[PCAP_ERRBUF_SIZE+1]; 68 69 /* 获取设备列表 */ 70 if (pcap_findalldevs(&alldevs, errbuf) == -1) 71 { 72 fprintf(stderr,"Error in pcap_findalldevs: %s ", errbuf); 73 exit(1); 74 } 75 for(d=alldevs;d;d=d->next) 76 { 77 ifprint(d); 78 } 79 return 0; 80 }
主要思路就是将得到的 pcap_if_t 展开来看,先看一下pcap_if_t 的结构:
有五个属性,名字、描述、pcap_addr类型的地址、flags、与指向下一个元素的指针。主要看看addresses:
pacp_addr 同样有五个属性,ip地址、子网掩码、广播地址、目标地址。
sockaddr定义如下:
struct sockaddr {
unsigned short sa_family; /* address family, AF_xxx */
char sa_data[14]; /* 14 bytes of protocol address */
};
一般sockaddr与sockaddr_in是可以互相转换的:
struct sockaddr_in {
short int sin_family;
unsigned short int sin_port;
struct in_addr sin_addr;
unsigned char sin_zero[8];
};
sin_family:指代协议族,可取值如下
AF_INET 2 IPv4
AF_INET6 23 IPv6
AF_UNSPEC 0 协议无关
sin_port:存储端口号(使用网络字节顺序)
sin_addr:存储IP地址,使用in_addr这个数据结构
sin_zero:是为了让sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节。
而其中IP地址的定义:
union {
struct{ unsigned char s_b1,s_b2, s_b3,s_b4;} S_un_b;
struct{ unsigned short s_w1, s_w2;} S_un_w;
unsigned long S_addr;
} S_un;
} IN_ADDR;
这里先吧sockaddr强制转换成aockaddr_in,然后取其中的sin_addr中的s_addr表示方式,然后将这个 unsigned long转换成可读的ip地址。
u_char是无符号字符类型,最大值是255。
输出结果: