ioctl和struct ifreq

转自:http://tech.sunplusedu.com/space/post-4064.aspx

 

用ioctl获得本地ip地址时要用到两个结构体ifconf和ifreq,它们对于大多数人
来说都是比较陌生的,这里给大家一种比较简单的理解方法,当然只一种帮助
理解的方法,在描述中可能会有一些地方与真实定义有所出入,仅供参考.

首先先认识一下ifconf和ifreq:

//ifconf通常是用来保存所有接口信息的
//if.h
struct ifconf 
{
    int    ifc_len;            /* size of buffer    */
    union 
    {
        char *ifcu_buf;                        /* input from user->kernel*/
        struct ifreq *ifcu_req;        /* return from kernel->user*/
    } ifc_ifcu;
};
#define    ifc_buf    ifc_ifcu.ifcu_buf        /* buffer address    */
#define    ifc_req    ifc_ifcu.ifcu_req        /* array of structures    */
 
//ifreq用来保存某个接口的信息
//if.h
struct ifreq {
    char ifr_name[IFNAMSIZ];
    union {
        struct sockaddr ifru_addr;
        struct sockaddr ifru_dstaddr;
        struct sockaddr ifru_broadaddr;
        short ifru_flags;
        int ifru_metric;
        caddr_t ifru_data;
    } ifr_ifru;
};
#define ifr_addr ifr_ifru.ifru_addr
#define ifr_dstaddr ifr_ifru.ifru_dstaddr
#define ifr_broadaddr ifr_ifru.ifru_broadaddr

 

上边这两个结构看起来比较复杂,我们现在把它们简单化一些:
比如说现在我们向实现获得本地IP的功能。

我们的做法是:
1. 先通过ioctl获得本地所有接口的信息,并保存在ifconf中
2. 再从ifconf中取出每一个ifreq中表示ip地址的信息

具体使用时我们可以认为ifconf就有两个成员:
ifc_len 和 ifc_buf,

  

ifc_len:表示用来存放所有接口信息的缓冲区长度
ifc_buf:表示存放接口信息的缓冲区

所以我们需要在程序开始时对ifconf的ifc_len和ifc_buf进行初始化
接下来使用ioctl获取所有接口信息,完成后ifc_len存放实际获得的接口信息总长度
并且信息被存放在ifc_buf中。
 

接下来我们只需要从一个一个的接口信息获取ip地址信息即可。

下面有一个简单的参考:

 

[cpp]  view plain copy
  1. #include <stdlib.h>  
  2. #include <string.h>  
  3. #include <sys/socket.h>  
  4. #include <sys/ioctl.h>  
  5. #include <net/if.h>  
  6. #include <stdio.h>  
  7. #include <netinet/in.h>  
  8. #include <arpa/inet.h>  
  9.   
  10. int main()  
  11. {  
  12. int i=0;  
  13. int sockfd;  
  14. struct ifconf ifconf;  
  15. unsigned char buf[512];  
  16. struct ifreq *ifreq;  
  17. //初始化ifconf  
  18. ifconf.ifc_len=512;  
  19. ifconf.ifc_buf=buf;  
  20. if((sockfd=socket(AF_INET,SOCK_DGRAM,0))<0)  
  21. {  
  22. perror("socket");  
  23. exit(1);  
  24. }  
  25. ioctl(sockfd,SIOCGIFCONF,&ifconf);//获取所有接口信息  
  26. //接下来一个一个的获取IP地址  
  27. ifreq=(struct ifreq*)buf;  
  28. for(i=(ifconf.ifc_len/sizeof(struct ifreq));i>0;i--)  
  29. {  
  30. // if(ifreq->ifr_flags == AF_INET){ //for ipv4  
  31. printf("name = %s \n", ifreq->ifr_name);  
  32. printf("local addr = %s \n",inet_ntoa(((struct sockaddr_in*)&(ifreq->ifr_addr))->sin_addr));  
  33. ifreq++;  
  34. // }  
  35. }  
  36. return 0;  
  37. }  

 

 

 
此方法仅供参考,也适用于获取其他信息。
struct ifreq
这个结构定义在/usr/include/net/if.h,用来配置ip地址,激活接口,配置MTU等接口信息的。

 

DE>/* Interface request structure used for socket ioctl's. All interface
   ioctl's must have parameter definitions which begin with ifr_name.
   The remainder may be interface specific. */


struct ifreq
  {
# define IFHWADDRLEN 6
# define IFNAMSIZ IF_NAMESIZE
    union
      {
        char ifrn_name[IFNAMSIZ]; /* Interface name, e.g. "en0". */
      } ifr_ifrn;

    union
      {
        struct sockaddr ifru_addr;
        struct sockaddr ifru_dstaddr;
        struct sockaddr ifru_broadaddr;
        struct sockaddr ifru_netmask;
        struct sockaddr ifru_hwaddr;
        short int ifru_flags;
        int ifru_ivalue;
        int ifru_mtu;
        struct ifmap ifru_map;
        char ifru_slave[IFNAMSIZ]; /* Just fits the size */
        char ifru_newname[IFNAMSIZ];
        __caddr_t ifru_data;
      } ifr_ifru;
  };
# define ifr_name ifr_ifrn.ifrn_name /* interface name */
# define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */
# define ifr_addr ifr_ifru.ifru_addr /* address */
# define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */
# define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */
# define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */
# define ifr_flags ifr_ifru.ifru_flags /* flags */
# define ifr_metric ifr_ifru.ifru_ivalue /* metric */
# define ifr_mtu ifr_ifru.ifru_mtu /* mtu */
# define ifr_map ifr_ifru.ifru_map /* device map */
# define ifr_slave ifr_ifru.ifru_slave /* slave device */
# define ifr_data ifr_ifru.ifru_data /* for use by interface */
# define ifr_ifindex ifr_ifru.ifru_ivalue /* interface index */
# define ifr_bandwidth ifr_ifru.ifru_ivalue /* link bandwidth */
# define ifr_qlen ifr_ifru.ifru_ivalue /* queue length */
# define ifr_newname ifr_ifru.ifru_newname /* New name */
# define _IOT_ifreq _IOT(_IOTS(char),IFNAMSIZ,_IOTS(char),16,0,0)
# define _IOT_ifreq_short _IOT(_IOTS(char),IFNAMSIZ,_IOTS(short),1,0,0)
# define _IOT_ifreq_int _IOT(_IOTS(char),IFNAMSIZ,_IOTS(int),1,0,0)

DE>

 

 

DE>
/* Structure used in SIOCGIFCONF request. Used to retrieve interface
   configuration for machine (useful for programs which must know all
   networks accessible). */


struct ifconf
  {
    int ifc_len; /* Size of buffer. */
    union
      {
        __caddr_t ifcu_buf;
        struct ifreq *ifcu_req;
      } ifc_ifcu;
  };
# define ifc_buf ifc_ifcu.ifcu_buf /* Buffer address. */
# define ifc_req ifc_ifcu.ifcu_req /* Array of structures. */
# define _IOT_ifconf _IOT(_IOTS(struct ifconf),1,0,0,0,0) /* not right */
DE>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值