Chinaunix首页 | 论坛 | 博客
  • 博客访问: 99106
  • 博文数量: 31
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 295
  • 用 户 组: 普通用户
  • 注册时间: 2016-06-22 11:52
文章分类

全部博文(31)

文章存档

2018年(3)

2017年(11)

2016年(12)

2015年(5)

我的朋友

分类: C/C++

2017-06-24 18:40:35

在应用层获取系统的网卡或者路由的信息都可以通过ioctl 获取,总结一下使用ioctl 获取网卡信息相关的内容

1.关键数据结构,strucet ifreq 通过ioctl 获取某一个网卡信息的数据结构,struct ifconf 是获取所有可用网卡的数据结构(经实践,不管网卡link 状态是up or down,只能获取配置了ip地址网卡)

struct ifreq 和 struct ifconf 都是定义在net/if.h 中,具体的定义如下

 点击(此处)折叠或打开
  1. struct ifreq
  2.   {
  3. # define IFHWADDRLEN 6
  4. # define IFNAMSIZ IF_NAMESIZE
  5.     union
  6.       {
  7.         char ifrn_name[IFNAMSIZ]; /* Interface name, e.g. "en0". */
  8.       } ifr_ifrn;

  9.     union
  10.       {
  11.         struct sockaddr ifru_addr;
  12.         struct sockaddr ifru_dstaddr;
  13.         struct sockaddr ifru_broadaddr;
  14.         struct sockaddr ifru_netmask;
  15.         struct sockaddr ifru_hwaddr;
  16.         short int ifru_flags;
  17.         int ifru_ivalue;
  18.         int ifru_mtu;
  19.         struct ifmap ifru_map;
  20.         char ifru_slave[IFNAMSIZ]; /* Just fits the size */
  21.         char ifru_newname[IFNAMSIZ];
  22.         __caddr_t ifru_data;
  23.       } ifr_ifru;
  24.   };


  25. # define ifr_name ifr_ifrn.ifrn_name /* interface name */
  26. # define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */
  27. # define ifr_addr ifr_ifru.ifru_addr /* address */
  28. # define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */
  29. # define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */
  30. # define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */
  31. # define ifr_flags ifr_ifru.ifru_flags /* flags */
  32. # define ifr_metric ifr_ifru.ifru_ivalue /* metric */
  33. # define ifr_mtu ifr_ifru.ifru_mtu /* mtu */
  34. # define ifr_map ifr_ifru.ifru_map /* device map */
  35. # define ifr_slave ifr_ifru.ifru_slave /* slave device */
  36. # define ifr_data ifr_ifru.ifru_data /* for use by interface */
  37. # define ifr_ifindex ifr_ifru.ifru_ivalue /* interface index */
  38. # define ifr_bandwidth ifr_ifru.ifru_ivalue /* link bandwidth */
  39. # define ifr_qlen ifr_ifru.ifru_ivalue /* queue length */
  40. # define ifr_newname ifr_ifru.ifru_newname /* New name */


点击(此处)折叠或打开

  1. struct ifconf
  2.   {
  3.     int ifc_len; /* Size of buffer. */
  4.     union
  5.       {
  6.         __caddr_t ifcu_buf;
  7.         struct ifreq *ifcu_req;
  8.       } ifc_ifcu;
  9.   };
  10. # define ifc_buf ifc_ifcu.ifcu_buf /* Buffer address. */
  11. # define ifc_req ifc_ifcu.ifcu_req /* Array of structures. */
数据结构就不解释了,头文件中都注释的很清楚

2.例子

点击(此处)折叠或打开

  1. #include<stdio.h>
  2. #include <unistd.h>
  3. #include<string.h>
  4. #include <sys/socket.h>
  5. #include<net/if.h>
  6. #include<netinet/in.h>
  7. #include<linux/sockios.h>


  8. int main(int argc,char **argv)
  9. {
  10.         struct ifconf ifc;
  11.         struct ifreq ifr[10];
  12.         int i;
  13.         int fd ;
  14.         int count;
  15.     
  16.         memset(&ifc,0,sizeof(struct ifconf));

  17.         fd = socket(AF_INET, SOCK_DGRAM, 0);
  18.         if(fd <0){
  19.                 printf("open socket fail\n");
  20.                 return -1;
  21.         }

  22.     /*初始化ifconf ,准备去内核获取信息,其中ifc.ifc_len是一个值-结果参数,先传ioctl 返回的时候会修改这个值为实际的长度*/
  23.         ifc.ifc_len = 1024;
  24.         ifc.ifc_buf = (void*)ifr;  


  25.     /*get all accessible interface by SIOCGIFCONF,通过socket 命令字SIOCGIFCONF,获取系统配置了ip地址的接口信息,
  26.     通过SIOCGIFCONF,只能返回ifr_name,和ifr_addr,如果还需要接口的其他信息,可以用这里获取回来的name ,
  27.     然后通过对应的socket命令字获取对应的信息*/
  28.         if(ioctl(fd,SIOCGIFCONF,&ifc)<0){
  29.                 printf("ioctl fail\n");
  30.                 return -1;
  31.         }
  32.     
  33.         count = ifc.ifc_len/sizeof(struct ifreq);
  34.     
  35.         for(i=0;i<count;i++) {
  36.                 struct ifreq *ifrp=&ifc.ifc_req[i];
  37.                 char addr_buf[16];
  38.                 printf("ifname=%s, ",ifrp->ifr_name);
  39. inet_ntop(AF_INET, &(((struct sockaddr_in* )&ifrp->ifr_addr)->sin_addr.s_addr),addr_buf,(socklen_t )sizeof(addr_buf));
  40.                 printf("addr=%s, ",addr_buf);

  41.                 /*get MTU ,需要mtu的,可以传入赋值了ifr_name的ifreq,来获取,如果不通过*/
  42.                 if (ioctl(fd, SIOCGIFMTU, &ifc.ifc_req[i] ) < 0){
  43.                         printf("ioctl get %s MTU fail\n",ifrp->ifr_name);
  44.                         return -1;
  45.                 }
  46.                 printf("MTU=%d,",ifrp->ifr_mtu);

  47.                 /*get MAC,获取mac,传入赋值了ifr_name的ifreq 获取*/
  48.                 if (ioctl(fd, SIOCGIFHWADDR, &ifc.ifc_req[i] ) < 0){
  49.                         printf("ioctl get %s MAC fail\n",ifrp->ifr_name);
  50.                         return -1;
  51.                 }

  52.                 printf("MAC =%02x:%02x:%02x:%02x:%02x:%02x",
  53.                 (unsigned char)ifrp->ifr_hwaddr.sa_data[0],
  54.                 (unsigned char)ifrp->ifr_hwaddr.sa_data[1],
  55.                 (unsigned char)ifrp->ifr_hwaddr.sa_data[2],
  56.                 (unsigned char)ifrp->ifr_hwaddr.sa_data[3],
  57.                 (unsigned char)ifrp->ifr_hwaddr.sa_data[4],
  58.                 (unsigned char)ifrp->ifr_hwaddr.sa_data[5]);

  59.                 printf("\n");
  60.         }

  61.         return 0;
  62. }


上面的代码可以获取系统中配置了ip的所有网卡的name,addr,mtu,mac 
if(ioctl(fd,SIOCGIFCONF,&ifc)<0) ,
这样get 只能get 配置了ip地址的网卡,通过ifconf 只能获取到ifreq里面的name addr
如果还需要其他信息,可以继续通过ioctl 根据name 获取网卡的其他参数(各种socket的命令字定义在./linux/sockios.h )
如果想获取某一个指定接口的信息,可指定ifreqifr_name ,然后ioctl 传入指定了ifr_name的ifreq,获取指定的接口信息
在头文件net/if.h 中还提供了结果if_name和if_index 互相转换的接口,分别是if_nametoindex,if_indextoname等,如果需要可以直接引用




阅读(665) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~