转载请注明出处:windeal专栏

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


ioctl

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

比如我们请求所有网络接口的清单:
  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用来保存某个接口的信息。
  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获取该接口的信息。如:
  1. ioctl(Sock, SIOCGIFNETMASK, &IfReq);//获取网络接口地址掩码
  2.  
该代码需要先对IfReq->ifr_name赋值,然后获取与IfReq->ifr_name向匹配的网络接口 的地址掩码



struct ifconf

结构体struct ifconf通常用来保存所有接口信息
  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地址)



Example:

  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. }


运行结果:
  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的更多相关文章

  1. 自己动手写路由器之ioctl获取网络接口信息

    最近打算写一个简单路由器,里面有用到ioctl获取网络接口信息,那就先把这部分单独拿出来说一说吧! ioctl这个函数,可以用来对特殊文件的基础设备参数进行操作,它们可以完成与打开文件描述符相关联的控 ...

  2. Linux获取网络接口信息

    linux获取网络接口信息需要用到的函数为ioctl(),结构体struct ifreq,struct ifconf 1.ioctl()函数原型及作用 #include <sys/ioctl.h ...

  3. C语言笔记 08_函数指针&回调函数&字符串&结构体&位域

    函数指针 函数指针是指向函数的指针变量. 通常我们说的指针变量是指向一个整型.字符型或数组等变量,而函数指针是指向函数. 函数指针可以像一般函数一样,用于调用函数.传递参数. 函数指针变量的声明: / ...

  4. Go基础3:函数、结构体、方法、接口

    目录 1. 函数 1.1 函数返回值 同一种类型返回值 带变量名的返回值 函数中的参数传递 函数变量 1.2 匿名函数--没有函数名字的函数 在定义时调用匿名函数 将匿名函数赋值给变量 匿名函数用作回 ...

  5. 【AT91SAM3S】SAM3S-EK Demo工程中,LCD驱动程序的加载(函数指针结构体)

    为了调试LCD,在英倍特的板子上烧Atmel的sam3s-ek_demo_1.4_source示例代码.LCD显示正常了,却找不到LCD的驱动究竟在哪. 花了好久,追踪到了这个执行过程. 进入main ...

  6. go 学习 (三):函数 & 指针 & 结构体

    一.函数 函数声明 // 声明语法 func funcName (paramName paramType, ...) (returnType, returnType...) { // do somet ...

  7. struct--------构造函数对结构体初始化的影响

    struct--------构造函数对结构体初始化的影响. 没有构造函数时使用如下: struct ClassBook{  int number;  int age; }; int main() { ...

  8. 【Unity Shader】---常用帮助函数、结构体和全局变量

    [Unity Shader]---常用帮助函数.结构体和全局变量 一.内置包含文件 Unity中有类似于C++的包含文件.cginc,在编写Shader时我们可以使用#include指令把这些文件包含 ...

  9. <algorithm>里的sort函数对结构体排序

    题目描述 每天第一个到机房的人要把门打开,最后一个离开的人要把门关好.现有一堆杂乱的机房签到.签离记录,请根据记录找出当天开门和关门的人. 输入描述: 每天的记录在第一行给出记录的条目数M (M &g ...

随机推荐

  1. TCP/IP 传输原理

    TCP传输原理简单说明 TCP传输需要经过3次握手4次挥手.     三次握手 当客户端向服务端进行连接时,会发送一个SYN报文,请求服务端监听端口,服务端确认请求后,会向客户端发送ACK确认,客户端 ...

  2. 20145327 《Java程序设计》第一周学习总结

    20145327 <Java程序设计>第一周学习总结 教材学习内容总结 Java根据领域不同,区分为Java SE.Java EE与Java ME三大平台.Java SE是各应用平台的基础 ...

  3. Python3.6 安装、后续终端pip 安装模块命令

    1. 下载安装包 https://www.python.org/ftp/python/3.6.4/python-3.6.4-amd64.exe 2. 安装python3.6 增加环境变量(打钩.红框很 ...

  4. Spring IOC 源码解析(持续)

    如何查看源码 Spring源码下载https://github.com/spring-projects/spring-framework/tags?after=v3.1.0.RC1 eclipse关联 ...

  5. mysql索引的建立和使用

    转自[http://www.cnblogs.com/mywebname/articles/555696.html] 一.索引的概念        索引就是加快检索表中数据的方法.数据库的索引类似于书籍 ...

  6. Anaconda 环境中使用pip安装时候出现的一些问题

    author:pprp date:18/8/12 --- 1. AttributeError: Module Pip has no attribute 'main' solution:降低pip的版本 ...

  7. valgrind的memchk和callgrind

    一.安装valgrind 安装valgrind,正常的三部曲configure/make/make install就行. 二.memchk使用 1.执行命令 [root@10g-host4 tools ...

  8. git 提交某个内容

    git add 你所添加的文件或者文件夹 git commit git push

  9. Browserify命令行参数

    –outfile, -o: browserify日志打印到文件 –require, -r: 绑定模块名或文件,用逗号分隔 –entry, -e: 应用程序的入口 –ignore, -i: 省略输出 – ...

  10. 03_MySQL DQL_排序查询

    #进阶3:排序查询/*语法: select 查询列表 from 表名 [where 筛选条件] order by 排序列表 [asc|desc] 特点: 1.asc升序,desc降序, 如果都不写,默 ...