注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

A small step

Judgement Must

 
 
 

日志

 
 
关于我

不要因为急着赶路,让自己的步伐杂乱。远方是既定的目标,但路上才是最重要的经历!

网易考拉推荐

ifreq ifconf -网卡  

2015-05-06 12:50:40|  分类: Linux C |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

struct ifreq

这个结构定义在include/net/if.h,用来配置ip地址,激活接口,配置MTU等接口信息的。其中包含了一个接口的名字和具体内容(是个共用体,有可能是IP地址,广播地址,子网掩码,MAC号,MTU或其他内容)。ifreq包含在ifconf结构中。而ifconf结构通常是用来保存所有接口的信息的。


  1. /* Interface request structure used for socket ioctl's.  All interface 
  2.    ioctl's must have parameter definitions which begin with ifr_name. 
  3.    The remainder may be interface specific.  */  
  4.   
  5. struct ifreq  
  6.   {  
  7. # define IFHWADDRLEN    6  
  8. # define IFNAMSIZ   IF_NAMESIZE  
  9.     union  
  10.       {     
  11.     char ifrn_name[IFNAMSIZ];   /* Interface name, e.g. "en0".  */  
  12.       } ifr_ifrn;  
  13.   
  14.     union  
  15.       {     
  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 int 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.     __caddr_t ifru_data;  
  28.       } ifr_ifru;  
  29.   };    
  30. # define ifr_name   ifr_ifrn.ifrn_name  /* interface name   */  
  31. # define ifr_hwaddr ifr_ifru.ifru_hwaddr    /* MAC address      */  
  32. # define ifr_addr   ifr_ifru.ifru_addr  /* address      */  
  33. # define ifr_dstaddr    ifr_ifru.ifru_dstaddr   /* other end of p-p lnk */  
  34. # define ifr_broadaddr  ifr_ifru.ifru_broadaddr /* broadcast address    */  
  35. # define ifr_netmask    ifr_ifru.ifru_netmask   /* interface net mask   */  
  36. # define ifr_flags  ifr_ifru.ifru_flags /* flags        */  
  37. # define ifr_metric ifr_ifru.ifru_ivalue    /* metric       */  
  38. # define ifr_mtu    ifr_ifru.ifru_mtu   /* mtu          */  
  39. # define ifr_map    ifr_ifru.ifru_map   /* device map       */  
  40. # define ifr_slave  ifr_ifru.ifru_slave /* slave device     */  
  41. # define ifr_data   ifr_ifru.ifru_data  /* for use by interface */  
  42. # define ifr_ifindex    ifr_ifru.ifru_ivalue    /* interface index      */  
  43. # define ifr_bandwidth  ifr_ifru.ifru_ivalue    /* link bandwidth   */  
  44. # define ifr_qlen   ifr_ifru.ifru_ivalue    /* queue length     */  
  45. # define ifr_newname    ifr_ifru.ifru_newname   /* New name     */  
  46. # define _IOT_ifreq _IOT(_IOTS(char),IFNAMSIZ,_IOTS(char),16,0,0)  
  47. # define _IOT_ifreq_short _IOT(_IOTS(char),IFNAMSIZ,_IOTS(short),1,0,0)  
  48. # define _IOT_ifreq_int _IOT(_IOTS(char),IFNAMSIZ,_IOTS(int),1,0,0)  

struct  ifconf

通常是用来保存所有接口信息的


  1. /* Structure used in SIOCGIFCONF request.  Used to retrieve interface 
  2.    configuration for machine (useful for programs which must know all 
  3.    networks accessible).  */  
  4.   
  5. struct ifconf  
  6.   {  
  7.     int ifc_len;            /* Size of buffer.  */  
  8.     union  
  9.       {  
  10.     __caddr_t ifcu_buf;  
  11.     struct ifreq *ifcu_req;  
  12.       } ifc_ifcu;  
  13.   };  
  14. # define ifc_buf    ifc_ifcu.ifcu_buf   /* Buffer address.  */  
  15. # define ifc_req    ifc_ifcu.ifcu_req   /* Array of structures.  */  
  16. # define _IOT_ifconf _I

举例说明:

在Linux系统中,ifconfig命令是通过ioctl接口与内核通信,例如,当系统管理员输入如下命令来改变接口eth0的MTU大小:

    ifconfig eth0 mtu 1250

ifconfig命令首先打开一个socket,然后通过系统管理员输入的参数初始化一个数据结构,并通过ioctl调用将数据传送到内核。SIOCSIFMTU是命令标识符。

    struct ifreq data;
    fd = socket(PF_INETSOCK_DGRAM, 0);
    < ... initialize "data" ...>
    err = ioctl(fd, SIOCSIFMTU, &data);


————————————————————————————————————————————————————————

通过socket,ioctl来获得ip,netmask等信息

int get_nic_IP_Address() //获取各网卡IP地址、子网掩码

{

struct ifreq ifreq;  //声明一个struct ifreq结构体(这个结构体中有很多重要的参数,具体可以参照第二的补充)

int sock;

  int i;

  int tmpint;

  read_dev(); //这个函数的功能是获得网卡名字(保存在下面提到的sys_nic_ip[][]数组中)并计算网卡总数(就是下面的sys_nic_count)

for (i=0;i<sys_nic_count;i++)

{

if((sock=socket(AF_INET,SOCK_STREAM,0))<0)

{  //建立一个套接字

perror("socket");

return ;

}

strcpy(ifreq.ifr_name,sys_nic_name[i]);   //把网卡名字复制到ifreq结构体中的name变量(感觉这个地方是必须的)

if(ioctl(sock,SIOCGIFADDR,&ifreq)<0)  //这里涉及ioctl函数对于网络文件的控制

{

sprintf(sys_nic_ip[i],"Not set");

} else 

{

sprintf(sys_nic_ip[i],"%d.%d.%d.%d",      //把ip地址提取出来,保存(理解一下socketaddr_in和socketaddr的关系)

(unsigned char)ifreq.ifr_addr.sa_data[2],

(unsigned char)ifreq.ifr_addr.sa_data[3],

(unsigned char)ifreq.ifr_addr.sa_data[4],

(unsigned char)ifreq.ifr_addr.sa_data[5]);

    }

if(ioctl(sock,SIOCGIFNETMASK,&ifreq)<0)   //我的理解是这个地方用SIOCGIFNETMASK,那么ifreq中原本是存的ip地址,现在存成了子网掩码了。

{

sprintf(sys_nic_mask[i],"Not set");       //把子网掩码提取出来(但得到的只是超网的划分方式就是/xx)

} else

{

sprintf(sys_nic_mask[i],"%d",

Count((unsigned char)ifreq.ifr_netmask.sa_data[2])+

Count((unsigned char)ifreq.ifr_netmask.sa_data[3])+

Count((unsigned char)ifreq.ifr_netmask.sa_data[4])+

Count((unsigned char)ifreq.ifr_netmask.sa_data[5]));

}

}

}


列出上面最后调用函数(Count())和一些全副变量:

char sys_nic_ip[20][20];//各网卡IP

char sys_nic_mask[20][20];//各网卡子网掩码"/xx"

int countTable[256] =

{

0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 

1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 

1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 

2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 

1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 

2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 

2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 

3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8

};

int Count(int v)

  return countTable[v]; 

}


二。对涉及的知识点进行补充

3.关于socketaddr_in和socketaddr的关系,下面贴出具体的定义:

struct sockaddr_in 

short int sin_family; /* 地址族 */ 

unsigned short int sin_port; /* 端口号 */ 

struct in_addr sin_addr; /* IP地址 */ 

unsigned char sin_zero[8]; /* 填充0 以保持与struct sockaddr同样大小 */ 

};

struct sockaddr 

unsigned short sa_family; /* 地址族, AF_xxx */ 

char sa_data[14]; /* 14 字节的协议地址 */ 

};

比较一下,会发现长度一样,所以这2个可以通用的,不过要进行类型转换,比较一下就得出了为什么上面程序中可以用:

(unsigned char)ifreq.ifr_addr.sa_data[2],这种形式了,还是解释一下吧:

这个ifr_addr是一个struct sockaddr结构体。它其中的sa_date[2]是不是照着上面sockaddr_in中的sin_add(也就是ip地址呢).

  评论这张
 
阅读(20)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018