李柏霖

导航

翼辉系统获取网络信息

实际环境和特殊需求往往会将简单问题复杂化,比如计算机IP地址,对于一个连接中socket,可以直接获得本端和对端的IP、端口信息。

但在一些特殊场合我们可能需要更多的信息,比如系统中有几块网卡,他们的Mac地址是多少,每块网卡分配了几个IP(一个网卡对应多个IP)等等。

这些信息往往需要通过ifconfig指令来获得,对于程序员来说,在代码中调用外部的shell指令可不是个最佳方案,因为没人能保障不同平台、不同版本的ifconfig指令输出的格式是一致的。

ioctl函数没有纳入POXIS规范,各系统对ioctl的实现也不尽相同。

本篇文章中将介绍通过ioctl函数实现上述需求。

#include <sys/ioctl.h>
int ioctl(int fd, int request, … /* void *arg */);
返回:成功返回0,失败返回-1;

ioctl函数的参数只有3个,但却是Unix中少有的几个“家族类”复杂函数,这里摘录一段《Unix网络编程》一书中对ioctl函数的描述:

在传统上ioctl函数是用于那些普遍使用、但不适合归入其他类别的任何特殊的系统接口……网络程序(一般是服务器程序)中ioctl常用于在程序启动时获得主机上所有接口的信息:接口的地址、接口是否支持广播、是否支持多播,等等。

ioctl函数的第一个参数fd,可以表示一个打开的文件(文件句柄)或网络套接字,第二个和第三个参数体现了函数的家族特色,参数二request根据函数功能分类定义了多组宏,而参数三总是一个指针,指针的类型依赖于参数二request。因为ioctl的种类实在太多,这里只列出和本文相关的几个参数定义:

 

1、通过接口名称获取IP地址:

 1 int get_ipstr(const char *ifname, char *ipstr)
 2 {
 3     int ret = -1;
 4     register int fd;
 5     struct ifreq ifr;
 6 
 7     if (ipstr == NULL || ifname == NULL) {
 8         return ret;
 9     }
10 
11     if (strlen(ifname) >= IFNAMSIZ) {
12         ret = -2;
13         return ret;
14     }
15 
16     if ((fd = socket(AF_INET, SOCK_DGRAM, 0 )) > 0) {
17         strcpy(ifr.ifr_name, ifname);
18         if (!(ioctl(fd, SIOCGIFADDR, &ifr))) {
19             ret = 0;
20             strcpy(ipstr, inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
21         }
22     }
23 
24     if (fd > 0) {
25         close(fd);
26     }
27 
28     return ret;
29 }
int get_ipstr(const char *ifname, char *ipstr)

2、打印网络接口信息:

 1 int printf_ifinfo(void)
 2 {
 3     int fd;                             /* 套接字 */
 4     int if_len;                         /* 接口数量 */
 5     struct ifreq buf[IF_NAMESIZE];      /* ifreq结构数组 */
 6     struct ifconf ifc;                  /* ifconf结构 */
 7 
 8     /* 建立IPv4的UDP套接字fd */
 9     if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
10         perror("socket(AF_INET, SOCK_DGRAM, 0)");
11         return -1;
12     }
13 
14     /* 初始化ifconf结构 */
15     ifc.ifc_len = sizeof(buf);
16     ifc.ifc_buf = (caddr_t) buf;
17 
18     /* 获得接口列表 */
19     if (ioctl(fd, SIOCGIFCONF, (char *) &ifc) == -1) {
20         perror("SIOCGIFCONF ioctl");
21         return -2;
22     }
23 
24     /* 计算接口数量 */
25     if_len = ifc.ifc_len / sizeof(struct ifreq);
26     printf("接口数量:%d\n", if_len);
27 
28     /* 遍历每个接口 */
29     while (if_len-- > 0) {
30         /* 打印接口名称 */
31         printf("接口:%s\n", buf[if_len].ifr_name);
32 
33         /* 获得接口标志 */
34         if (!(ioctl(fd, SIOCGIFFLAGS, (char *) &buf[if_len]))) {
35             /* 接口状态 */
36             if (buf[if_len].ifr_flags & IFF_UP)
37             {
38                 printf("接口状态: UP\n");
39             } else {
40                 printf("接口状态: DOWN\n");
41             }
42         } else {
43             char str[256];
44             sprintf(str, "SIOCGIFFLAGS ioctl %s", buf[if_len].ifr_name);
45             perror(str);
46         }
47 
48         /* IP地址 */
49         if (!(ioctl(fd, SIOCGIFADDR, (char *) &buf[if_len]))) {
50             printf("IP地址:%s\n", (char*)inet_ntoa(((struct sockaddr_in*) (&buf[if_len].ifr_addr))->sin_addr));
51         } else {
52             char str[256];
53             sprintf(str, "SIOCGIFADDR ioctl %s", buf[if_len].ifr_name);
54             perror(str);
55         }
56 
57         /* 子网掩码 */
58         if (!(ioctl(fd, SIOCGIFNETMASK, (char *) &buf[if_len]))) {
59             printf("子网掩码:%s\n", (char*)inet_ntoa(((struct sockaddr_in*) (&buf[if_len].ifr_addr))->sin_addr));
60         } else {
61             char str[256];
62             sprintf(str, "SIOCGIFNETMASK ioctl %s", buf[if_len].ifr_name);
63             perror(str);
64         }
65 
66         /* 广播地址 */
67         if (!(ioctl(fd, SIOCGIFBRDADDR, (char *) &buf[if_len]))) {
68             printf("广播地址:%s\n", (char*)inet_ntoa(((struct sockaddr_in*) (&buf[if_len].ifr_addr))->sin_addr));
69         } else {
70             char str[256];
71             sprintf(str, "SIOCGIFBRDADDR ioctl %s", buf[if_len].ifr_name);
72             perror(str);
73         }
74 
75         /*MAC地址 */
76         if (!(ioctl(fd, SIOCGIFHWADDR, (char *) &buf[if_len]))) {
77             printf("MAC地址:%02x:%02x:%02x:%02x:%02x:%02x\n\n",
78                     (unsigned char) buf[if_len].ifr_hwaddr.sa_data[0],
79                     (unsigned char) buf[if_len].ifr_hwaddr.sa_data[1],
80                     (unsigned char) buf[if_len].ifr_hwaddr.sa_data[2],
81                     (unsigned char) buf[if_len].ifr_hwaddr.sa_data[3],
82                     (unsigned char) buf[if_len].ifr_hwaddr.sa_data[4],
83                     (unsigned char) buf[if_len].ifr_hwaddr.sa_data[5]);
84         } else {
85             char str[256];
86             sprintf(str, "SIOCGIFHWADDR ioctl %s", buf[if_len].ifr_name);
87             perror(str);
88         }
89     } //–while end
90 
91     /* 关闭socket */
92     if (fd > 0) {
93         close(fd);
94     }
95 
96     return 0;
97 }
int printf_ifinfo(void)

3、相关数据结构:

 1 /* net/if.h */  
 2 struct ifconf  
 3 {  
 4     int ifc_len;            /* Size of buffer.  */  
 5     union  
 6     {  
 7         __caddr_t ifcu_buf;  
 8         struct ifreq *ifcu_req;  
 9     } ifc_ifcu;  
10 };  
11    
12 struct ifreq  
13 {  
14 # define IFHWADDRLEN    6  
15 # define IFNAMSIZ   IF_NAMESIZE  
16      
17     union  
18     {  
19         char ifrn_name[IFNAMSIZ];   /* Interface name, e.g. "en0".  */  
20     } ifr_ifrn;  
21      
22     union  
23     {  
24         struct sockaddr ifru_addr;  
25         struct sockaddr ifru_dstaddr;  
26         struct sockaddr ifru_broadaddr;  
27         struct sockaddr ifru_netmask;  
28         struct sockaddr ifru_hwaddr;  
29         short int ifru_flags;  
30         int ifru_ivalue;  
31         int ifru_mtu;  
32         struct ifmap ifru_map;  
33         char ifru_slave[IFNAMSIZ];  /* Just fits the size */  
34         char ifru_newname[IFNAMSIZ];  
35         __caddr_t ifru_data;  
36     } ifr_ifru;  
37 };  
/* net/if.h */

4、参考资料:

    1)、https://www.cnblogs.com/lidabo/category/431655.html

    2)、https://blog.csdn.net/pengluer/category_715116.html

    3)、https://blog.csdn.net/PenglueR/article/details/5793862

    4)、https://blog.csdn.net/xiexingshishu/category_9263043.html

    5)、https://www.cnblogs.com/tdyizhen1314/p/4896689.html

 

posted on 2021-08-20 14:58  李柏霖  阅读(188)  评论(0)    收藏  举报