获取网络接口信息——ioctl()函数与结构体struct ifreq、 struct ifconf

2023-12-26 05:58

本文主要是介绍获取网络接口信息——ioctl()函数与结构体struct ifreq、 struct ifconf,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

http://blog.csdn.net/windeal3203/article/details/39320605

Linux 下 可以使用ioctl()函数 以及 结构体 struct ifreq  结构体struct ifconf来获取网络接口的各种信息。


ioctl

首先看ioctl()用法
ioctl()原型如下:
   
#include <sys/ioctl.h>
int ioctl(int fd, int request, ...);
参数:
     fd     : 文件描述符
request:  表示要请求的信息。如IP地址、网络掩码等
       ...            后面的可变参数根据request而定

比如我们请求所有网络接口的清单:
[cpp]  view plain copy
  1. struct ifconf IoCtlReq;  
  2. ...  
  3. ioctl( Sock, SIOCGIFCONF, &IoCtlReq )  

其中 IoCtlReq 是一个

与接口相关的request如下表所示( 来源: < http://baike.baidu.com/view/1081282.htm?fr=aladdin > ):
SIOCGIFCONF
SIOCSIFADDR
SIOCGIFADDR
SIOCSIFFLAGS
SIOCGIFFLAGS
SIOCSIFDSTADDR
SIOCGIFDSTADDR
SIOCGIFBRDADDR
SIOCSIFBRDADDR
SIOCGIFNETMASK
SIOCSIFNETMASK
SIOCGIFMETRIC
SIOCSIFMETRIC
SIOCGIFMTU
SIOCxxx
获取所有接口的清单
设置接口地址
获取接口地址
设置接口标志
获取接口标志
设置点到点地址
获取点到点地址
获取广播地址
设置广播地址
获取子网掩码
设置子网掩码
获取接口的测度
设置接口的测度
获取接口MTU
(还有很多取决于系统的实现)
struct ifconf
struct ifreq
struct ifreq
struct ifreq
struct ifreq
struct ifreq
struct ifreq
struct ifreq
struct ifreq
struct ifreq
struct ifreq
struct ifreq
struct ifreq
struct ifreq


关于ioctl的详细解释清查阅本博其它博文

struct ifreq

结构体 struct ifreq用来保存某个接口的信息。
[cpp]  view plain copy
  1. // if.h  
  2. /* 
  3.  * Interface request structure used for socket 
  4.  * ioctl's.  All interface ioctl's must have parameter 
  5.  * definitions which begin with ifr_name.  The 
  6.  * remainder may be interface specific. 
  7.  */  
  8. struct ifreq {  
  9. #define IFHWADDRLEN 6  
  10.     union  
  11.     {  
  12.         char    ifrn_name[IFNAMSIZ];        /* if name, e.g. "en0" */  
  13.     } ifr_ifrn;  
  14.       
  15.     union {  
  16.         struct  sockaddr ifru_addr;  
  17.         struct  sockaddr ifru_dstaddr;  
  18.         struct  sockaddr ifru_broadaddr;  
  19.         struct  sockaddr ifru_netmask;  
  20.         struct  sockaddr ifru_hwaddr;  
  21.         short   ifru_flags;  
  22.         int ifru_ivalue;  
  23.         int ifru_mtu;  
  24.         struct  ifmap ifru_map;  
  25.         char    ifru_slave[IFNAMSIZ];   /* Just fits the size */  
  26.         char    ifru_newname[IFNAMSIZ];  
  27.         void __user *   ifru_data;  
  28.         struct  if_settings ifru_settings;  
  29.     } ifr_ifru;  
  30. };  
  31. #define ifr_name    ifr_ifrn.ifrn_name  /* interface name   */  
  32. #define ifr_hwaddr  ifr_ifru.ifru_hwaddr    /* MAC address      */  
  33. #define ifr_addr    ifr_ifru.ifru_addr  /* address      */  
  34. #define ifr_dstaddr ifr_ifru.ifru_dstaddr   /* other end of p-p lnk */  
  35. #define ifr_broadaddr   ifr_ifru.ifru_broadaddr /* broadcast address    */  
  36. #define ifr_netmask ifr_ifru.ifru_netmask   /* interface net mask   */  
  37. #define ifr_flags   ifr_ifru.ifru_flags /* flags        */  
  38. #define ifr_metric  ifr_ifru.ifru_ivalue    /* metric       */  
  39. #define ifr_mtu     ifr_ifru.ifru_mtu   /* mtu          */  
  40. #define ifr_map     ifr_ifru.ifru_map   /* device map       */  
  41. #define ifr_slave   ifr_ifru.ifru_slave /* slave device     */  
  42. #define ifr_data    ifr_ifru.ifru_data  /* for use by interface */  
  43. #define ifr_ifindex ifr_ifru.ifru_ivalue    /* interface index  */  
  44. #define ifr_bandwidth   ifr_ifru.ifru_ivalue    /* link bandwidth   */  
  45. #define ifr_qlen    ifr_ifru.ifru_ivalue    /* Queue length     */  
  46. #define ifr_newname ifr_ifru.ifru_newname   /* New name     */  
  47. #define ifr_settings    ifr_ifru.ifru_settings  /* Device/proto settings*/  



ifr_name 标识了某一接口。
可以通过ioctl获取该接口的信息。如:
   
ioctl(Sock, SIOCGIFNETMASK, &IfReq);//获取网络接口地址掩码
该代码需要先对IfReq->ifr_name赋值,然后获取与 IfReq->ifr_name向匹配的网络接口 的地址掩码



struct ifconf

结构体struct ifconf通常用来保存所有接口信息
[cpp]  view plain copy
  1. // if.h  
  2. /* 
  3.  * Structure used in SIOCGIFCONF request. 
  4.  * Used to retrieve interface configuration 
  5.  * for machine (useful for programs which 
  6.  * must know all networks accessible). 
  7.  */  
  8. struct ifconf  {  
  9.     int ifc_len;            /* size of buffer   */  
  10.     union {  
  11.         char __user *ifcu_buf;  
  12.         struct ifreq __user *ifcu_req;  
  13.     } ifc_ifcu;  
  14. };  
  15. #define ifc_buf ifc_ifcu.ifcu_buf       /* buffer address   */  
  16. #define ifc_req ifc_ifcu.ifcu_req       /* array of structures  */  


该结构体可以用来获取所哟网络接口的名字和信息(不是全部信息,是ip地址)
(图片来自: http://tech.sunplusedu.com/space/post-4064.aspx



Example:

[cpp]  view plain copy
  1. #include <sys/types.h>    
  2. #include <sys/ioctl.h>    
  3. #include <sys/socket.h>    
  4. #include <net/if.h>    
  5. #include <stdio.h>    
  6. #include <stdlib.h>    
  7. #include <unistd.h>    
  8. #include <netdb.h>    
  9. #include <string.h>    
  10. #include <fcntl.h>    
  11. #include <string.h>    
  12. #include <errno.h>  
  13. typedef uint32_t uint32;   
  14. #define MAX_IF 10  
  15. int   
  16. main()  
  17. {  
  18.     struct ifreq ifVec[MAX_IF];//用来保存所有接口  
  19.       
  20.     int sock = -1;  
  21.     if ( (sock = socket( AF_INET, SOCK_DGRAM, 0 )) < 0 )  
  22.         fprintf(stderr, "Error:%d, cannot open RAM;\n");  
  23.       
  24.     // get if vector  
  25.     struct ifconf ioIfConf;  
  26.         ioIfConf.ifc_buf = (void *)ifVec;  
  27.         ioIfConf.ifc_len = sizeof(ifVec);  
  28.      printf("Len:%d\n", ioIfConf.ifc_len);       
  29.           
  30.     if (ioctl(sock, SIOCGIFCONF, &ioIfConf) < 0 )//获取所有网络接口信息  
  31.         fprintf(stderr, "Error:%d   ioctl IFCONF\n");  
  32.       
  33.      printf("Len:%d\n", ioIfConf.ifc_len);// 和前面到len对比,发现ioctl修改里len到大小       
  34.     //循环打印每个网络接口到信息  
  35.     {  
  36.         struct ifreq *ifPt;  
  37.         struct ifreq *ifEndPt;  
  38.         ifPt = ifVec;  
  39.         ifEndPt = (void *)((char *)ifVec + ioIfConf.ifc_len);  
  40.         for (ifPt = ifVec; ifPt < ifEndPt; ifPt++)  
  41.         {  
  42.             struct ifreq ifReq;  
  43.             if ( ifPt->ifr_addr.sa_family != AF_INET ) {  
  44.                         continue;  
  45.                     }  
  46.               
  47.             // Temp keepers of interface params...  
  48.             uint32 u32_addr, u32_mask;  
  49.               
  50.             /*  打印ip地址  */  
  51.             char ipDotBuf[16], subnetDotBuf[16], maskDotBuf[16]; // 保存点分十进制到ip地址  
  52.             u32_addr = ((struct sockaddr_in *)&ifPt->ifr_addr)->sin_addr.s_addr;  
  53.             inet_ntop(AF_INET, &u32_addr, ipDotBuf, (socklen_t )sizeof(ipDotBuf));   
  54.             printf("IP Address: %s\n", ipDotBuf);  
  55.               
  56.             /*    打印地址掩码    */  
  57.             bzero(&ifReq,sizeof(struct ifreq));    
  58.             memcpy(ifReq.ifr_name, ifPt->ifr_name, sizeof(ifReq.ifr_name));    
  59.             if (ioctl(sock, SIOCGIFNETMASK, &ifReq ) < 0){  
  60.                 fprintf(stderr, "Error: %d, cannot get mask\n", errno);  
  61.             }  
  62.             else{  
  63.                 u32_mask = ((struct sockaddr_in *)&ifReq.ifr_addr)->sin_addr.s_addr;  
  64.                 inet_ntop(AF_INET, &u32_mask, maskDotBuf, (socklen_t )sizeof(maskDotBuf));  
  65.                 printf("Mask: %s\n", maskDotBuf);  
  66.             }     
  67.             /*    打印MTU    */  
  68.             bzero(&ifReq,sizeof(struct ifreq));    
  69.             memcpy(ifReq.ifr_name, ifPt->ifr_name, sizeof(ifReq.ifr_name));    
  70.             if (ioctl(sock, SIOCGIFMTU, &ifReq ) < 0){  
  71.                 fprintf(stderr, "Error: %d, cannot get MTU\n", errno);  
  72.             }  
  73.             else{  
  74.                 printf("SIOCGIFMTU:%d\n", ifReq.ifr_mtu);   
  75.             }  
  76.                /*    其他信息的打印方式与掩码和MTU相同    */  
  77.         }  
  78.     }  
  79.       
  80.       
  81.       
  82. }  



运行结果:
[cpp]  view plain copy
  1. windeal@ubuntu:~/Windeal/apue$ ./exe   
  2. Len:320  
  3. Len:64  
  4. IP Address: 127.0.0.1  
  5. Mask: 255.0.0.0  
  6. SIOCGIFMTU:16436  
  7. IP Address: 172.17.92.198  
  8. Mask: 255.255.254.0  
  9. SIOCGIFMTU:1500  
  10. windeal@ubuntu:~/Windeal/apue$   

这篇关于获取网络接口信息——ioctl()函数与结构体struct ifreq、 struct ifconf的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/538325

相关文章

Java中switch-case结构的使用方法举例详解

《Java中switch-case结构的使用方法举例详解》:本文主要介绍Java中switch-case结构使用的相关资料,switch-case结构是Java中处理多个分支条件的一种有效方式,它... 目录前言一、switch-case结构的基本语法二、使用示例三、注意事项四、总结前言对于Java初学者

结构体和联合体的区别及说明

《结构体和联合体的区别及说明》文章主要介绍了C语言中的结构体和联合体,结构体是一种自定义的复合数据类型,可以包含多个成员,每个成员可以是不同的数据类型,联合体是一种特殊的数据结构,可以在内存中共享同一... 目录结构体和联合体的区别1. 结构体(Struct)2. 联合体(Union)3. 联合体与结构体的

python获取当前文件和目录路径的方法详解

《python获取当前文件和目录路径的方法详解》:本文主要介绍Python中获取当前文件路径和目录的方法,包括使用__file__关键字、os.path.abspath、os.path.realp... 目录1、获取当前文件路径2、获取当前文件所在目录3、os.path.abspath和os.path.re

Java子线程无法获取Attributes的解决方法(最新推荐)

《Java子线程无法获取Attributes的解决方法(最新推荐)》在Java多线程编程中,子线程无法直接获取主线程设置的Attributes是一个常见问题,本文探讨了这一问题的原因,并提供了两种解决... 目录一、问题原因二、解决方案1. 直接传递数据2. 使用ThreadLocal(适用于线程独立数据)

使用Python检查CPU型号并弹出警告信息

《使用Python检查CPU型号并弹出警告信息》本教程将指导你如何编写一个Python程序,该程序能够在启动时检查计算机的CPU型号,如果检测到CPU型号包含“I3”,则会弹出一个警告窗口,感兴趣的小... 目录教程目标方法一所需库步骤一:安装所需库步骤二:编写python程序步骤三:运行程序注意事项方法二

C++11的函数包装器std::function使用示例

《C++11的函数包装器std::function使用示例》C++11引入的std::function是最常用的函数包装器,它可以存储任何可调用对象并提供统一的调用接口,以下是关于函数包装器的详细讲解... 目录一、std::function 的基本用法1. 基本语法二、如何使用 std::function

PostgreSQL如何查询表结构和索引信息

《PostgreSQL如何查询表结构和索引信息》文章介绍了在PostgreSQL中查询表结构和索引信息的几种方法,包括使用`d`元命令、系统数据字典查询以及使用可视化工具DBeaver... 目录前言使用\d元命令查看表字段信息和索引信息通过系统数据字典查询表结构通过系统数据字典查询索引信息查询所有的表名可

hdu1171(母函数或多重背包)

题意:把物品分成两份,使得价值最接近 可以用背包,或者是母函数来解,母函数(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v) 其中指数为价值,每一项的数目为(该物品数+1)个 代码如下: #include<iostream>#include<algorithm>

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

业务中14个需要进行A/B测试的时刻[信息图]

在本指南中,我们将全面了解有关 A/B测试 的所有内容。 我们将介绍不同类型的A/B测试,如何有效地规划和启动测试,如何评估测试是否成功,您应该关注哪些指标,多年来我们发现的常见错误等等。 什么是A/B测试? A/B测试(有时称为“分割测试”)是一种实验类型,其中您创建两种或多种内容变体——如登录页面、电子邮件或广告——并将它们显示给不同的受众群体,以查看哪一种效果最好。 本质上,A/B测