本身動手寫路由器之ioctl獲取網絡接口信息

最近打算寫一個簡單路由器,裏面有用到ioctl獲取網絡接口信息,那就先把這部分單獨拿出來講一說吧!網絡

ioctl這個函數,能夠用來對特殊文件的基礎設備參數進行操做,它們能夠完成與打開文件描述符相關聯的控制功能。在程序啓動時得到主機上全部接口的信息: 接口的地址、接口是否支持廣播、是否支持多播等等。成功返回0,出錯則返回-1。socket

本文裏只是單獨對獲取網絡接口信息部分講解。函數

先列出一些本文裏ioctl的相關ioctl 請求的request 參數以及arg 地址必須指向的數據類型:ui

request參數  相關說明 指向數據類型
SIOCGIFCONF 獲取全部接口信息 struct ifconf
SIOCGIFADDR 獲取接口地址 struct ifreq
SIOCGIFFLAGS 獲取接口狀態 struct ifreq
SIOCGIFBRDADDR 獲取廣播地址 struct ifreq
SIOCGIFNETMASK       獲取子網掩碼 struct ifreq

接下來,就開始利用ioctl以及其參數來獲取網絡接口的信息了。spa

直接附上代碼,詳情請看註釋:code

 

複製代碼
 1 int main()
 2 {//想要獲取當前網口網線插入狀態,須要用到ifreq結構體,獲取網卡的信息,而後socket結合網卡驅動的ioctl,就能夠獲得與網線插入狀態相關的數據。
 3     int number;                 
 4     char *tmpbuf;               
 5     struct ifconf ifc;          //用來保存全部接口信息的   
 6     struct ifreq buf[16];       //這個結構定義在net/if.h,用來配置ip地址,激活接口,配置MTU等接口信息
 7     ifc.ifc_len = sizeof(buf);
 8     ifc.ifc_buf = (caddr_t)buf;
 9 
10     int sockfd;
11     if(-1 == socket(AF_PACKET,SOCK_RAW,htons(ETH_P_ALL)))     
12     {
13         perror("socket build !");
14         return 1;
15     } 
16     if(-1 == ioctl(sockfd,SIOCGIFCONF,(char *)&ifc))//SIOCGIFCONF用來獲取全部配置接口的信息,將所獲取的信息保存到ifc裏。
17     {
18         perror("SIOCGIFCONF !");
19         return 1;
20     }
21     
22     number = ifc.ifc_len / sizeof(struct ifreq);
23     printf("the interface number is %d \n",number);
24     int tmp;
25     for(tmp = number;tmp > 0;tmp--)
26     {
27         printf("the interface name is %s\n",buf[tmp].ifr_name);
28 
29         /* 接口的狀態信息獲取 */
30         if(0 == ioctl(sockfd,SIOCGIFFLAGS,(char *)&buf[tmp]))
31         { 
32             if(IFF_UP == buf[tmp].ifr_flags)
33                 printf("UP\n");
34             else 
35                 printf("DOWN");
36         } 
37 
38         /* IP地址的獲取 */
39         if(0 == ioctl(sockfd,SIOCGIFADDR,(char *)&buf[tmp]))
40         {
41             tmpbuf = (char *)inet_ntoa(((struct sockaddr_in*) (&buf[tmp].ifr_addr))->sin_addr);
42             printf("IPAdress :%s \n",tmpbuf);
43         }   
44 
45         /* 子網掩碼的獲取 */
46         if(0 == ioctl(sockfd,SIOCGIFNETMASK,(char *)&buf[tmp]))   
47         {
48             tmpbuf = (char *)inet_ntoa(((struct sockaddr_in*) (&buf[tmp].ifr_addr))->sin_addr);
49             printf("netmask:%s \n",tmpbuf);
50         }  
51 
52         /* 廣播地址的獲取 */
53         if(0 == ioctl(sockfd,SIOCGIFBRDADDR,(char *)&buf[tmp]))
54         {
55             tmpbuf = (char *)inet_ntoa(((struct sockaddr_in*)(&buf[tmp].ifr_addr))->sin_addr);
56             printf("broadcast address:%s \n",tmpbuf);
57         } 
58 
59         /* MAC地址的獲取 */
60         if(0 == ioctl(sockfd,SIOCGIFHWADDR,(char *)&buf[tmp]))
61         {
62  printf("MAC:%02x:%02x:%02x:%02x:%02x:%02x\n\n",
63                     (unsigned char) buf[tmp].ifr_hwaddr.sa_data[0],
64                     (unsigned char) buf[tmp].ifr_hwaddr.sa_data[1],
65                     (unsigned char) buf[tmp].ifr_hwaddr.sa_data[2],
66                     (unsigned char) buf[tmp].ifr_hwaddr.sa_data[3],
67                     (unsigned char) buf[tmp].ifr_hwaddr.sa_data[4],
68                     (unsigned char) buf[tmp].ifr_hwaddr.sa_data[5]);
69         } 
70     }
71 }
複製代碼

 

 

在驅動程序中實現的ioctl函數體內,其實是有一個switch{case}結構的,每個case對應一個命令碼,作出一些相應的操做。blog

下面附上ioctl全參數多對應的命令碼的功能的連接:接口

http://riverzhou2000.blog.163.com/blog/static/105403248201183025729615/ip

ioctl這個函數還有不少其它的功能,有興趣的朋友能夠問度娘,這裏就不加詳述了!路由

相關文章
相關標籤/搜索