ioctl在socket中的一些用法及示例
ioctl在socket中的一些用法及示例
函式 : ioctl(int fd, int request, void * arg)
定義 :
功能 : 控制I/O裝置, 提供了一種獲得裝置資訊和向裝置傳送控制引數的手段.
引數 : int fd 檔案控制代碼. 用於socket時, 是socket套接字.
int request 函式定義的所有操作. 關於socket的操作, 定義在檔案中.
void *arg 指標的型別依賴於request引數.
以下表格從網上收集了request - arg指標型別的對應關係
類別 |
Request |
說明 |
資料型別 |
套 |
SIOCATMARK |
是否位於帶外標記 |
int |
文 |
FIONBIN |
設定/ 清除非阻塞I/O 標誌 |
int |
接 |
SIOCGIFCONF |
獲取所有介面的清單 |
struct ifconf |
ARP |
SIOCSARP |
建立/ 修改ARP 表項 |
struct arpreq |
路 |
SIOCADDRT |
增加路徑 |
struct rtentry |
流 |
I_xxx |
|
|
socket最常用到的結構體: struct ifreq 定義在.(包括struct ifconf/ifr_flags等的定義)
一、獲取
以下例程通過ioctl獲取裝置"eth0"的IP/掩碼/硬體址
- #include "stdio.h"
- #include "stdlib.h"
- #include "string.h"
- #include "net/if.h"
- #include "arpa/inet.h"
- #include "linux/sockios.h"
- int main(int argc,char *argv[])
- {
- struct sockaddr_in *addr;
- struct ifreq ifr;
- char*address;
- int sockfd;
- char *name = "eth0";
- if( strlen(name) >= IFNAMSIZ)
- printf("device name is error.\n"), exit(0);
- strcpy( ifr.ifr_name, name);
- sockfd = socket(AF_INET,SOCK_DGRAM,0);
- //get inet addr
- if( ioctl( sockfd, SIOCGIFADDR, &ifr) == -1)
- printf("ioctl error.\n"), exit(0);
- addr = (struct sockaddr_in *)&(ifr.ifr_addr);
- address = inet_ntoa(addr->sin_addr);
- printf("inet addr: %s\n",address);
- //get Mask
- if( ioctl( sockfd, SIOCGIFNETMASK, &ifr) == -1)
- printf("ioctl error.\n"), exit(0);
- addr = (struct sockaddr_in *)&ifr.ifr_addr;
- address = inet_ntoa(addr->sin_addr);
- printf("Mask: %s\n",address);
- //get HWaddr
- u_int8_t hd[6];
- if(ioctl(sockfd, SIOCGIFHWADDR, &ifr) == -1)
- printf("hwaddr error.\n"), exit(0);
- memcpy( hd, ifr.ifr_hwaddr.sa_data, sizeof(hd));
- printf("HWaddr: %02X:%02X:%02X:%02X:%02X:%02X\n", hd[0], hd[1], hd[2], hd[3], hd[4], hd[5]);
- exit(0);
- }
二、設定
以下例程設定eth0的IP地址.
- #include "stdio.h"
- #include "stdlib.h"
- #include "string.h"
- #include "net/if.h"
- #include "arpa/inet.h"
- #include "linux/sockios.h"
- int main(int argc,char *argv[])
- {
- char *dev = "eth0";
- char *ip = "192.168.1.252";
- struct ifreq ifr;
- if( strlen(dev) >= IFNAMSIZ)
- printf("device name error.\n"), exit(0);
- else
- strcpy( ifr.ifr_name, dev);
- int sockfd = socket(AF_INET,SOCK_DGRAM,0);
- //get inet addr
- if( ioctl( sockfd, SIOCGIFADDR, &ifr) == -1)
- printf("ioctl error.\n"), exit(0);
- struct sockaddr_in *addr = (struct sockaddr_in *)&(ifr.ifr_addr);
- char * address = inet_ntoa(addr->sin_addr);
- printf("current inet addr: %s\n",address);
- //set inet addr
- struct sockaddr_in *p = (struct sockaddr_in *)&(ifr.ifr_addr);
- p->sin_family = AF_INET;
- inet_aton( ip, &(p->sin_addr));
- if( ioctl( sockfd, SIOCSIFADDR, &ifr) == -1)
- printf("ioctl error.\n"), exit(0);
- else
- printf("change inet addr to: %s\n", ip);
- //any OS need active dev.
- /*ifr.ifr_flags |= IFF_UP;
- if( ioctl( sockfd, SIOCSIFFLAGS, &ifr) == -1)
- printf("active fault.\n"), exit(0);
- else
- printf("%s[%s] is working...\n", dev, ip);
- */
- close(sockfd);
- exit(1);
- //end
- }
遮蔽的程式碼用於設定IP後, 啟用新設定. 多數系統不需要這步操作.
而且這步僅作演示. 真實使用的時候, 至少應該
1. 獲取當前ifr.ifr_flags
2. ifr.ifr_flags |= IFF_UP;
以上是ioctl的一些示例, 實戰中靈活使用、舉一反三.