1.介紹
Linux網絡程序與內核交互的方法是經過ioctl來實現的,ioctl與網絡協議棧進行交互,可獲得網絡接口的信息,網卡設備的映射屬性和配置網絡接口.而且還可以查看,修改,刪除ARP高速緩存的信息,因此,咱們有必要了解一下ioctl函數的具體實現.編程
2.函數說明
SYNOPSIS
#include <sys/ioctl.h>
int ioctl(int d, int request, ...);
DESCRIPTION
The ioctl() function manipulates the underlying device parameters of
special files. In particular, many operating characteristics of char-
acter special files (e.g., terminals) may be controlled with ioctl()
requests. The argument d must be an open file descriptor.
The second argument is a device-dependent request code. The third
argument is an untyped pointer to memory. It’s traditionally char
*argp (from the days before void * was valid C), and will be so named
for this discussion.
An ioctl() request has encoded in it whether the argument is an in
parameter or out parameter, and the size of the argument argp in bytes.
Macros and defines used in specifying an ioctl() request are located in
the file <sys/ioctl.h>.
RETURN VALUE
Usually, on success zero is returned. A few ioctl() requests use the
return value as an output parameter and return a non-negative value on
success. On error, -1 is returned, and errno is set appropriately.
數組
3.參數說明
類別緩存 |
Request網絡 |
說明數據結構 |
數據類型app |
套框架 接異步 口 |
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 |
|
|
4.相關數據結構
- <h2><a name="t4"></a>(1)網絡接口請求結構ifreq</h2>
- struct ifreq {
- #define IFHWADDRLEN 6 //6個字節的硬件地址,即MAC
- union {
- char ifrn_name[IFNAMESIZ];
- }ifr_ifrn;
- union {
- struct sockaddr ifru_addr;
- struct sockaddr ifru_dstaddr;
- struct sockaddr ifru_broadaddr;
- struct sockaddr ifru_netmask;
- struct sockaddr ifru_hwaddr;
- short ifru_flags;
- int ifru_ivalue;
- struct ifmap ifru_map;
- int ifru_mtu;
- char ifru_slave[IFNAMSIZ];
- char ifru_newname[IFNAMSIZE];
- void __user* ifru_data;
- struct if_settings ifru_settings;
- }ifr_ifru;
- }
- #define ifr_name ifr_ifrn.ifrn_name;//接口名稱
- #define ifr_hwaddr ifr_ifru.ifru_hwaddr;//MAC
- #define ifr_addr ifr_ifru.ifru_addr;//本地IP
- #define ifr_dstaddr ifr_ifru.dstaddr;//目標IP
- #define ifr_broadaddr ifr_ifru.broadaddr;//廣播IP
- #define ifr_netmask ifr_ifru.ifru_netmask;//子網掩碼
- #define ifr_flags ifr_ifru.ifru_flags;//標誌
- #define ifr_metric ifr_ifru.ifru_ivalue;//接口側度
- #define ifr_mtu ifr_ifru.ifru_mtu;//最大傳輸單元
- #define ifr_map ifr_ifru.ifru_map;//設備地址映射
- #define ifr_slave ifr_ifru.ifru_slave;//副設備
- #define ifr_data ifr_ifru.ifru_data;//接口使用
- #define ifr_ifrindex ifr_ifru.ifru_ivalue;//網絡接口序號
- #define ifr_bandwidth ifr_ifru.ifru_ivalue;//鏈接帶寬
- #define ifr_qlen ifr_ifru.ifru_ivalue;//傳輸單元長度
- #define ifr_newname ifr_ifru.ifru_newname;//新名稱
- #define ifr_seeting ifr_ifru.ifru_settings;//設備協議設置
- 若是想得到網絡接口的相關信息,就傳入ifreq結構體.
-
- <h2><a name="t5"></a>(2)網卡設備屬性ifmap</h2>
- struct ifmap {
- unsigned long mem_start;
- unsigned long mem_end;
- unsigned short base_addr;
- unsigned char irq;
- unsigned char dma;
- unsigned char port;
- }
-
- <h2><a name="t6"></a>(3)網絡配置接口ifconf</h2>
- struct ifconf {
- int ifc_len;
- union {
- char__user *ifcu_buf;
- struct ifreq__user* ifcu_req;
- }ifc_ifcu;
- };
- #define ifc_buf ifc_ifcu.ifcu_buf;//緩衝區地址
- #define ifc_req ifc_ifcu.ifcu_req;//ifc_req地址
-
- <h2><a name="t7"></a>(4)ARP高速緩存操做arpreq</h2>
- /**
- ARP高速緩存操做,包含IP地址和硬件地址的映射表
- 操做ARP高速緩存的命令字 SIOCDARP,SIOCGARP,SIOCSARP分別是刪除ARP高速緩存的一條記錄,得到ARP高速緩存的一條記錄和修改ARP高速緩存的一條記錄
- struct arpreq{
- struct sockaddr arp_pa;
- struct sockaddr arp_ha;
- int arp_flags;
- struct sockaddr arp_netmask;
- char arp_dev[16];
- }
5. 相關代碼例子
- <pre name="code" class="cpp">#include <sys/types.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <sys/ioctl.h>
- #include <sys/socket.h>
- #include <netdb.h>
- #include <string.h>
- #include <fcntl.h>
- #include <net/if.h>
- #include <string.h>
-
- int main(int argc, char*argv[]) {
- int s,sv6;
- int err;
- s = socket(AF_INET, SOCK_DGRAM, 0);
- if (s < 0) {
- perror("socket error");
- return -1;
- }
-
-
- struct ifreq ifr;
- int ia = sizeof( struct ifreq );
- ia = sizeof(struct sockaddr);
- ia = 1; err = 0;
- bzero(&ifr, sizeof(struct ifreq));
- while (err != -1) {
-
- ifr.ifr_ifindex = ia++;
- err = ioctl(s, SIOCGIFNAME, &ifr);
- if (-1 == err) {
- perror("index error");
- } else {
- char ipbuf[255];
- inet_ntop(AF_INET,
- &((struct sockaddr_in*) &(ifr.ifr_ifru.ifru_addr))->sin_addr,
- ipbuf, sizeof(ipbuf));
- printf("the %dst interface is:%s \t addr:%s\n", ifr.ifr_ifindex,
- ifr.ifr_name, ipbuf);
- }
- }
-
- bzero(&ifr,sizeof(struct ifreq));
- memcpy(ifr.ifr_name, "eth0", 5);
- err = ioctl(s, SIOCGIFFLAGS, &ifr);
- if (!err) {
- printf("SIOCGIFFLAGS:%d\n", ifr.ifr_flags);
- }
-
-
- bzero(&ifr,sizeof(struct ifreq));
- memcpy(ifr.ifr_name, "eth0", 5);
- err = ioctl(s, SIOCGIFMTU, &ifr);
- if (err!=-1) {
- printf("SIOCGIFMTU:%d\n", ifr.ifr_mtu);
- }else
- perror("ioctl:");
-
- bzero(&ifr,sizeof(struct ifreq));
- memcpy(ifr.ifr_name, "eth0", 5);
-
- err = ioctl(s, SIOCGIFHWADDR, &ifr);
- if (-1!=err) {
- unsigned char* hw = ifr.ifr_ifru.ifru_hwaddr.sa_data;
- printf("SIOCGIFHWADDR:%02x:%02x:%02x:%02x:%02x:%02x\n", hw[0], hw[1],
- hw[2], hw[3], hw[4], hw[5]);
- }else
- perror("ioctl:");
-
-
- err = ioctl(s, SIOCGIFMAP, &ifr);
- if (!err) {
- printf(
- "SIOCGIFMAP,mem_start:%d,mem_end:%d,base_addr:%d,ifr_map:%d,dma:%d,port:%d\n",
- ifr.ifr_map.mem_start, ifr.ifr_map.mem_end,
- ifr.ifr_map.base_addr, ifr.ifr_map.irq, ifr.ifr_map.dma,
- ifr.ifr_map.port);
- }
-
- err = ioctl(s, SIOCGIFINDEX, &ifr);
- if (!err) {
- printf("SIOCGIFINDEX:%d\n", ifr.ifr_ifindex);
- }
-
- err = ioctl(s, SIOCGIFTXQLEN, &ifr);
- if (!err) {
- printf("SIOCGIFTXQLEN:%d\n", ifr.ifr_qlen);
- }
-
- bzero(&ifr,sizeof(struct ifreq));
- memcpy(ifr.ifr_name, "eth0", 5);
-
- struct sockaddr_in *sin = (struct sockaddr_in*) &ifr.ifr_addr;
- char ip[16];
- memset(ip, 0, 16);
- err = ioctl(s, SIOCGIFADDR, &ifr);
- if (!err) {
- inet_ntop(AF_INET, &sin->sin_addr.s_addr, ip, 16);
- printf("SIOCGIFADDR:%s\n", ip);
- }
-
-
-
- err = ioctl(s, SIOCGIFDSTADDR, &ifr);
- if (!err) {
- inet_ntop(AF_INET, &sin->sin_addr.s_addr, ip, 16);
- printf("SIOCGIFDSTADDR:%s\n", ip);
- }
-
- bzero(&ifr,sizeof(struct ifreq));
- memcpy(ifr.ifr_name, "eth0", 5);
- err = ioctl(s, SIOCGIFNETMASK, &ifr);
- if (!err) {
- inet_ntop(AF_INET, &sin->sin_addr.s_addr, ip, 16);
- printf("SIOCGIFNETMASK:%s\n", ip);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
- memset(&ifr, 0, sizeof(ifr));
- memcpy(ifr.ifr_name, "eth0", 5);
- ioctl(s, SIOCGIFBRDADDR, &ifr);
- struct sockaddr_in *broadcast = (struct sockaddr_in*) &ifr.ifr_broadaddr;
-
- inet_ntop(AF_INET, &broadcast->sin_addr.s_addr, ip, 16);
- printf("BROADCAST IP:%s\n", ip);
- close(s);
- }
- </pre><br>
- <pre></pre>
- <br>
- <h1><a name="t9"></a>6.內核主要函數調用框架</h1>
- <p></p>
- <p>內核實現ioctl()函數的是sys_ioctl(),在內核中主要調用框架圖以下,它清晰地給咱們展現ioctl的控制傳遞框架,咱們接下來的內容將根據此圖向你們作詳細的解釋:</p>
- <p><img src="http://img.my.csdn.net/uploads/201211/26/1353937655_1774.jpg" alt=""><br>
- </p>
- <p><br>
- </p>
- <h1><a name="t10"></a>7.小結</h1>
- <p> 本文介紹了ioctrl 主要的用法,固然它還有不少用法,之後會繼續追加的,該如函數的用法,主要就是其對應的request列表的用法,便是該函數的第二個參數的用法</p>
- <p><br>
- </p>
- <p>參考: UNIX 網絡編程</p>
- <p><a href="http://blog.163.com/jlz_325/blog/static/19174000920126893245653/">http://blog.163.com/jlz_325/blog/static/19174000920126893245653/</a></p>
- <p><a href="http://www.linuxidc.com/Linux/2007-12/9680.htm">http://www.linuxidc.com/Linux/2007-12/9680.htm</a><br>
- </p>
- <p><a href="http://linux.chinaunix.net/techdoc/develop/2007/09/05/967137.shtml">http://linux.chinaunix.net/techdoc/develop/2007/09/05/967137.shtml</a><br>
- </p>
- <p><br>
- </p>