winPcap编程之获取适配器详细信息(三)

显示适配器详细信息

先贴上代码

 #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "pcap.h"
#include <winsock2.h> typedef struct sockaddr_in sockad; /* 从tcptraceroute数字IP地址转换为字符串 */
#define IPTOSBUFFERS 12
char *iptos(u_long in)
{
static char output[IPTOSBUFFERS][*++];
static short which;
u_char *p; p = (u_char *)&in;
which = (which + == IPTOSBUFFERS ? : which + );
sprintf(output[which], "%d.%d.%d.%d", p[], p[], p[], p[]);
return output[which];
} /* 给定的接口上打印所有可用的信息 */
void ifprint(pcap_if_t *d)
{
pcap_addr_t *a; /* 名字 */
printf("%s\n",d->name); /* 描述 */
if (d->description)
printf("\t描述: %s\n",d->description); /* 环回地址*/
printf("\t环回: %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("\tIP地址: %s\n",iptos(((struct sockaddr_in *)a->addr)->sin_addr.s_addr));
if (a->netmask)
printf("\t子网掩码: %s\n",iptos(((struct sockaddr_in *)a->netmask)->sin_addr.s_addr));
if (a->broadaddr)
printf("\t广播地址: %s\n",iptos(((struct sockaddr_in *)a->broadaddr)->sin_addr.s_addr));
if (a->dstaddr)
printf("\t目标地址: %s\n",iptos(((struct sockaddr_in *)a->dstaddr)->sin_addr.s_addr));
break;
default:
printf("\tAddress Family Name: Unknown\n");
break;
}
}
printf("\n");
} int main()
{
pcap_if_t *alldevs;
pcap_if_t *d;
char errbuf[PCAP_ERRBUF_SIZE+]; /* 获取设备列表 */
if (pcap_findalldevs(&alldevs, errbuf) == -)
{
fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
exit();
}
for(d=alldevs;d;d=d->next)
{
ifprint(d);
}
return ;
}

主要思路就是将得到的 pcap_if_t 展开来看,先看一下pcap_if_t 的结构:

winPcap编程之获取适配器详细信息(三)

有五个属性,名字、描述、pcap_addr类型的地址、flags、与指向下一个元素的指针。主要看看addresses:

winPcap编程之获取适配器详细信息(三)

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地址的定义:

typedef struct in_addr {
  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;
阐述下in_addr的含义,很显然它是一个存储ip地址的共用体有三种表达方式:
第一种用四个字节来表示IP地址的四个数字;
第二种用两个双字节来表示IP地址;
第三种用一个长整型来表示IP地址。

这里先吧sockaddr强制转换成aockaddr_in,然后取其中的sin_addr中的s_addr表示方式,然后将这个 unsigned long转换成可读的ip地址。

u_char是无符号字符类型,最大值是255。

输出结果:

winPcap编程之获取适配器详细信息(三)

上一篇:Java中常用加减密方式


下一篇:JS生成数字加减乘法验证码