最近打算寫一個簡單路由器,裏面有用到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這個函數還有不少其它的功能,有興趣的朋友能夠問度娘,這裏就不加詳述了!路由