struct ifreq學習和實例


一、struct ifreq結構體

 

這個結構定義在/usr/include/net/if.h,用來配置和獲取ip地址,掩碼,MTU等接口信息的。

 

 

[cpp]  view plain  copy
 
  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)  



二、用法:

 

通過ioctl()函數調用
下表列出了網絡相關ioctl請求的request 參數以及arg 地址必須指向的數據類型:

 

  

類別 Request 說明 數據類型


SIOCATMARK 
SIOCSPGRP 
SIOCGPGRP
是否位於帶外標記 
設置套接口的進程ID 或進程組ID 
獲取套接口的進程ID 或進程組ID
int 
int 
int

FIONBIN 
FIOASYNC 
FIONREAD 
FIOSETOWN 
FIOGETOWN
設置/ 清除非阻塞I/O 標志 
設置/ 清除信號驅動異步I/O 標志 
獲取接收緩存區中的字節數 
設置文件的進程ID 或進程組ID 
獲取文件的進程ID 或進程組ID
int 
int 
int 
int 
int

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
ARP SIOCSARP 
SIOCGARP 
SIOCDARP
創建/ 修改ARP 表項 
獲取ARP 表項 
刪除ARP 表項
struct arpreq 
struct arpreq 
struct arpreq

SIOCADDRT 
SIOCDELRT
增加路徑 
刪除路徑
struct rtentry 
struct rtentry
I_xxx

 

實例一,獲取網卡的IP地址:

 

[cpp]  view plain  copy
 
  1. #include <string.h>  
  2. #include <sys/socket.h>  
  3. #include <sys/ioctl.h>  
  4. #include <net/if.h>  
  5. #include <stdio.h>  
  6. #include <netinet/in.h>  
  7. #include <arpa/inet.h>  
  8. int main()  
  9. {  
  10.         int inet_sock;  
  11.         struct ifreq ifr;  
  12.         inet_sock = socket(AF_INET, SOCK_DGRAM, 0);  
  13.   
  14.         strcpy(ifr.ifr_name, "eth0");  
  15.         //SIOCGIFADDR標志代表獲取接口地址  
  16.         if (ioctl(inet_sock, SIOCGIFADDR, &ifr) <  0)  
  17.                 perror("ioctl");  
  18.         printf("%s\n", inet_ntoa(((struct sockaddr_in*)&(ifr.ifr_addr))->sin_addr));  
  19.         return 0;  
  20. }  

 

實例二,實現簡單ifconfig功能:

 

[cpp]  view plain  copy
 
  1. /** 
  2.  * \file getifstat.c 
  3.  * \author  wzj 
  4.  * \brief 訪問這個struct ifconf 修改,查詢狀態 
  5.  * \version  
  6.  * \note   
  7.  * \date: 2012年08月11日星期六22:55:25 
  8.  */   
  9. #include <net/if.h>       /* for ifconf */  
  10. #include <linux/sockios.h>    /* for net status mask */  
  11. #include <netinet/in.h>       /* for sockaddr_in */  
  12. #include <sys/socket.h>  
  13. #include <sys/types.h>  
  14. #include <sys/ioctl.h>  
  15. #include <stdio.h>  
  16.   
  17. #define MAX_INTERFACE   (16)  
  18.   
  19. void port_status(unsigned int flags);  
  20.   
  21. /* set == 0: do clean , set == 1: do set! */  
  22. int set_if_flags(char *pif_name, int sock, int status, int set)  
  23. {  
  24.     struct ifreq ifr;  
  25.     int ret = 0;  
  26.       
  27.     strncpy(ifr.ifr_name, pif_name, strlen(pif_name) + 1);  
  28.     ret = ioctl(sock, SIOCGIFFLAGS, &ifr);  
  29.     if(ret)  
  30.         return -1;  
  31.     /* set or clean */    
  32.     if(set)  
  33.         ifr.ifr_flags |= status;  
  34.     else   
  35.         ifr.ifr_flags &= ~status;  
  36.     /* set flags */  
  37.     ret = ioctl(sock, SIOCSIFFLAGS, &ifr);  
  38.     if(ret)  
  39.         return -1;  
  40.       
  41.     return 0;  
  42. }  
  43.   
  44. int get_if_info(int fd)  
  45. {  
  46.     struct ifreq buf[MAX_INTERFACE];      
  47.     struct ifconf ifc;  
  48.     int ret = 0;  
  49.     int if_num = 0;  
  50.   
  51.     ifc.ifc_len = sizeof(buf);  
  52.     ifc.ifc_buf = (caddr_t) buf;  
  53.       
  54.     ret = ioctl(fd, SIOCGIFCONF, (char*)&ifc);  
  55.     if(ret)  
  56.     {  
  57.         printf("get if config info failed");  
  58.         return -1;  
  59.     }  
  60.     /* 網口總數 ifc.ifc_len 應該是一個出入參數 */      
  61.     if_num = ifc.ifc_len/sizeof(struct ifreq);  
  62.     printf("interface num is interface = %d\n", if_num);  
  63.     while(if_num-- > 0)  
  64.     {  
  65.         printf("net device: %s\n", buf[if_num].ifr_name);     
  66.         /* 獲取第n個網口信息 */  
  67.         ret = ioctl(fd, SIOCGIFFLAGS, (char*)&buf[if_num]);  
  68.         if(ret)  
  69.             continue;  
  70.   
  71.         /* 獲取網口狀態 */  
  72.         port_status(buf[if_num].ifr_flags);  
  73.           
  74.         /* 獲取當前網卡的ip地址 */  
  75.         ret = ioctl(fd, SIOCGIFADDR, (char*)&buf[if_num]);  
  76.         if(ret)  
  77.             continue;  
  78.         printf("IP address is: \n%s\n", inet_ntoa(((struct sockaddr_in *)(&buf[if_num].ifr_addr))->sin_addr));  
  79.   
  80.         /* 獲取當前網卡的mac */  
  81.         ret = ioctl(fd, SIOCGIFHWADDR, (char*)&buf[if_num]);  
  82.         if(ret)  
  83.             continue;  
  84.   
  85.         printf("%02x:%02x:%02x:%02x:%02x:%02x\n\n",  
  86.             (unsigned char)buf[if_num].ifr_hwaddr.sa_data[0],  
  87.             (unsigned char)buf[if_num].ifr_hwaddr.sa_data[1],  
  88.             (unsigned char)buf[if_num].ifr_hwaddr.sa_data[2],  
  89.             (unsigned char)buf[if_num].ifr_hwaddr.sa_data[3],  
  90.             (unsigned char)buf[if_num].ifr_hwaddr.sa_data[4],  
  91.             (unsigned char)buf[if_num].ifr_hwaddr.sa_data[5]  
  92.             );  
  93.     }  
  94. }  
  95.   
  96. void port_status(unsigned int flags)  
  97. {  
  98.     if(flags & IFF_UP)    
  99.     {  
  100.         printf("is up\n");        
  101.     }  
  102.     if(flags & IFF_BROADCAST)     
  103.     {  
  104.         printf("is broadcast\n");     
  105.     }  
  106.     if(flags & IFF_LOOPBACK)      
  107.     {  
  108.         printf("is loop back\n");     
  109.     }  
  110.     if(flags & IFF_POINTOPOINT)   
  111.     {  
  112.         printf("is point to point\n");    
  113.     }  
  114.     if(flags & IFF_RUNNING)   
  115.     {  
  116.         printf("is running\n");   
  117.     }  
  118.     if(flags & IFF_PROMISC)   
  119.     {  
  120.         printf("is promisc\n");   
  121.     }  
  122. }  
  123.   
  124. int main()  
  125. {  
  126.     int fd;  
  127.   
  128.     fd = socket(AF_INET, SOCK_DGRAM, 0);  
  129.     if(fd > 0)  
  130.     {  
  131.         get_if_info(fd);  
  132.         close(fd);  
  133.     }  
  134.   
  135.     return 0;  
  136. }  


運行結果:

 

interface num is interface = 2
net device: eth0
is up
is broadcast
is running
IP address is: 
192.168.100.200
54:be:f7:33:57:26


net device: lo
is up
is loop back
is running
IP address is: 
127.0.0.1
00:00:00:00:00:00


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM