SIOCGIFCONF請求爲每個已配置的接口返回其名字以及一個套接口地址結構。我們接着可以發出多個接口類其他請求以設置或獲取每個接口的其他特徵。這些請求的獲取(get)版本(SIOCGxxx)通常由netstat程序發出,設置(set)版本(SIGOCSxxx)通常由ifconfig程序發出。任何用戶都可以獲取接口信息,設置接口信息卻要求有超級用戶權限。
這些請求汲取或返回一個一個ifreq結構中的信息,而這個結構的地址則作爲ioctl調用的第三個參數制定。接口總是以其名標誌,在ifreq結構的ifr_name成員中指定,如le0,lo0,ppp0等。
這些請求中有許多使用套接口地址結構在應用進程和內核之間指定或返回具體接口的IP地址或地址掩碼。對於IPV4,這個地址或掩碼放在一個網際套接口地址結構的sin_addr成員中;對於IPV6,它是一個IPV6套接口地址結構的sin6_addr成員。
SIOCGIFADDR: 在ifr_addr成員中返回單播地址。
SIOCSIFADDR:用ifr_addr成員設置接口地址,這個接口的初始化函數也被調用。
SIOCGIFFLAGS:在ifr_flags成員中返回接口標誌。這些接口標誌的名字格式爲IFF_XXX,在<net/if.h>頭文件中定義。舉例來說,這些標誌指示接口是否處於UP即在工狀態(IFF_UP),是否爲一個點到點接口(IFF_POINTOPOINT),是否支持廣播(IFF_BROADCAST),等等。
SIOCSIFFLAGS:用ifr_flags成員設置接口標誌。
SIOCGIFDSTADDR:在ifr_dstaddr成員中返回點到點地址。
SIOCSIFDSTADDR: 在ifr_dstaddr成員中設置點到點地址
SIOCGIFBRDADDR: 在ifr_broadaddr成員中返回廣播地址。應用進程必須首先獲取接口標誌,然後發出正確的請求;對於廣播接口爲SIOCGIFBRDADDR,對於點到點接口爲SIOCGIFDSTADDR
SIOCSIFBRDADDR:用ifr_broadaddr成員設置廣播地址。
SIOCGIFNETMASK:在ifr_addr成員中返回子網掩碼。
SIOCSIFNETMASK:在ifr_addr成員中設置子網掩碼。
SIOCGIFMETRIC:用ifr_metric成員返回接口測度。接口測度由內核爲每個接口維護,不過使用他的是路由守護進程routed。接口測度被routed加到跳數上。
SIOCSIFMETRIC:用ifr_metric成員設置接口的路由測度。
ARP高速緩存操作
ARP告訴緩存也通過ioctl函數操縱。使用路由域套接口的系統往往改用路由套接口訪問
ARP高速緩存。這些請求使用如下的arpreq結構,定義在<net/if_arp.h>
struct arpreq {
struct sockaddr arp_pa;
struct sockaddr arp_ha;
int arp_flags;
};
#define ATF_INUSE 0x01 //entry in use
#define ATF_COM 0x02 //completed entry (hardware addr valid)
#define ATF_PERM 0x04 // permanent entry
#define ATF_PUBL 0x08 // published entry (respond for other host )
Ioctl的第三個必須指向某個arpreq結構,操縱ARP高速緩存的ioctl請求有以下三個:
SIOCSARP: 把一個新的表項加入ARP告訴緩存中區,或者修改其中已經存在的一個表項,其中arp_pa是一個含有IP地址的網際套接口地址結構,arp_ha則是一個通用套接口地址結構,他的sa_family值爲AF_unspec,sa_data中含有硬件地址(例如6直接的以太網地址)。ATF_PERM和ATF_PUBL這兩個標誌也可以由應用進程指定。另外兩個標誌(ATF_INUSE和ATF_COM)則由內核設置。
SIOCDARP: 從ARP告訴緩存中刪除一個表項。調用者指定要刪除表項的網際地址。
SIOCGARP: 從ARP高速緩存中獲取一個表項。調用者指定網際地址,相應的硬件地址(例外以太網地址)隨標誌一起返回。
只有超級用戶才能增加或刪除表項。這三個請求通常由arp程序發出。
注意ioctl沒有辦法列出ARP高速緩存中的所有表項。當指定-a標誌執行arp命令時,大多
數版本的arp程序通過讀取內核的內存( /dev/kmem )獲得ARP高速緩存的當前內容。
路由表操作
有些系統提供2個用於操縱路由表的ioctl請求。這2個請求要求ioctl的第三個參數是指向
某個rtentry結構的一個指針,該結構定義在<net/route.h>頭文件中。這些請求通常由route
程序發出。只有超級用戶才能發出這些請求。
SIOCADDRT:往路由表中增加一個表項
SIOCDELRT:從路由表中刪除一個表項
Ioctl沒有辦法列出路由表中的所有表項。這個操作通常由netstat程序在指定-r標誌自行四
完成。netstat程序通過讀取內核的內存 (/dev/kmem)獲得整個路由表。用sysctl同樣可
以做到。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
void err_sys(const char *errmsg);
int main(void)
{
int i, sockfd;
struct ifreq ifr;
struct arpreq arpr;
strncpy(ifr.ifr_name, "eth0", sizeof(ifr.ifr_name));
if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
err_sys("socket");
/* get ip address */
if (ioctl(sockfd, SIOCGIFADDR, &ifr) == -1)
err_sys("1-ioctl");
/* get hardware address */
ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) == -1)
err_sys("2-ioctl");
/* output hardware address */
for (i = 0; i < 6; i++) {
unsigned char *mac = (unsigned char *) ifr.ifr_hwaddr.sa_data;
printf("%x", (int) mac[i]);
if (i != 5)
printf("%c", ':');
}
exit(0);
}
void err_sys(const char *errmsg)
{
perror(errmsg);
exit(1);
}