天天看點

ioctl函數操作

第十六章  ioctl操作 傳統上ioctl函數是用于那些普遍使用,但不适合歸入其他類别的任何特性的系統接口。Posix去掉了ioctl,它通過 建立特殊的其功能已被Posix标準化的包裹函數來代替ioctl。這一章介紹和網絡程式設計有關的ioctl操作。   1. ioctl函數 int ioctl(int d, int request, ...);

和網絡有關的ioctl請求有6類: 套接口操作 檔案操作 接口操作 ARP高速緩存操作 路由表操作 流系統

2. 套接口操作

類别 請求 描述 資料類型
套接口 SIOCATMASK 在帶外标志上嗎 int
SIOCSPGRP 設定套接口的程序ID和程序組ID int
SIOCGPGPR 擷取套接口的程序ID和程序組ID int

SIOCATMASK: 如果套接口的讀指針在帶外标志上,則通過第三個參數指向的整數傳回一個非零值,否則傳回零。 3. 檔案操作

類别 請求 描述 資料類型
檔案操作 FIONBIO 設定/清除非阻塞标志 int
FIOASYNC 設定/清除異步I/O标志 int
FIONREAD 擷取接收緩沖區中資料的位元組數 int
FIOSETOWN 設定檔案的程序ID或程序組ID int
FIOGETOWN 擷取檔案的程序ID或程序組ID int

 FIONBIO: 這個請求和用fcntl的F_SETFL指令設定和清除O_NONBLOCK标志效果相同。  4. 接口配置

類别 請求 描述 資料類型
接口 SIOCGIFCONF 擷取所有接口的清單 struct ifconf
SIOCSIFADDR 設定接口位址 struct ifreq
SIOCGIFADDR 擷取接口位址 struct ifreq
SIOCSIFFLAGS 設定接口标志 struct ifreq
SIOCGIFFLAGS 擷取接口标志 struct ifreq
SIOCSIFDSTADDR 設定點對點位址 struct ifreq
SIOCGIFDSTADDR 擷取點對點位址 struct ifreq
SIOCGIFBRDADDR 擷取廣播位址 struct ifreq
SIOCSIFBRDADDR 設定廣播位址 struct ifreq
SIOCGIFNETMASK 擷取子網路遮罩 struct ifreq
SIOCSIFNETMASK 設定子網路遮罩 struct ifreq
SIOCGIFMETRIC 擷取接口的測度(metric) struct ifreq
SIOCSIFMETRIC 設定接口的測度(metric) struct ifreq
SIOCxxx

5. ARP

類别 請求 描述 資料類型
ARP SIOCSARP 建立/修改ARP項 struct arpreq
SIOCGARP 擷取ARP項 struct arpreq
SIOCDARP 删除ARP項 struct arpreq

 6. 路由

類别 請求 描述 資料類型
路由 SIOCADDRT 增加路徑 struct rtentry
SIOCDELRT 删除路徑 struct rtentry

具體到套接字方面的應用可以看下面的講解

NAME

netdevice - 底層通路 Linux 網絡裝置.

總覽 (SYNOPSIS)

#include < sys/ioctl.h>  

#include <net/if.h>

描述 (DESCRIPTION)

本手冊 描述 用于 配置 網絡裝置 的 套接字(socket) 接口.

Linux 支援 一些 配置 網絡裝置 的 标準 ioctl. 他們 用于 任意的 套接字 描述符, 而 無須 了解 其 類型 或 系列. 他們 傳遞 一個 ifreq結構:

struct ifreq
{
    char            ifr_name[IFNAMSIZ];   /* Interface name */
    union {
                    struct sockaddr       ifr_addr;
                    struct sockaddr       ifr_dstaddr;
                    struct sockaddr       ifr_broadaddr;
                    struct sockaddr       ifr_netmask;
                    struct sockaddr       ifr_hwaddr;
                    short                 ifr_flags;
                    int                   ifr_ifindex;
                    int                   ifr_metric;
                    int                   ifr_mtu;
                    struct ifmap          ifr_map;
                    char                  ifr_slave[IFNAMSIZ];
                    char                  ifr_newname[IFNAMSIZ];
                    char *                ifr_data;
    };
}
struct ifconf 
{ 
    int ifc_len;                          /* size of buffer */
    union {            
                    char *                ifc_buf; /* buffer address */ 
                    struct ifreq *ifc_req; /* array of structures */
    };  
};     
      

一般說來, ioctl 通過 把 ifr_name 設定為 接口 的 名字 來 指定 将要 操作 的 裝置. 結構的 其他成員 可以 分享 記憶體.

IOCTLS

如果 某個 ioctl 标記為 特權操作, 那麼 操作時 需要 有效uid 為 0, 或者 擁有  CAP_NET_ADMIN  能力. 否則 将 傳回  EPERM .

SIOCGIFNAME
給定  ifr_ifindex, 傳回  ifr_name 中 的 接口名字. 這是 唯一 傳回  ifr_name 内容 的 ioctl. 
SIOCGIFINDEX
把 接口 的 索引 存入  ifr_ifindex.
SIOCGIFFLAGS,  SIOCSIFFLAGS
讀取 或 設定 裝置的 活動标志字.  ifr_flags 包含 下列值 的 屏蔽位:
裝置标志
IFF_UP 接口正在運作.
IFF_BROADCAST 有效的廣播位址集.
IFF_DEBUG 内部調試标志.
IFF_LOOPBACK 這是自環接口.
IFF_POINTOPOINT 這是點到點的鍊路接口.
IFF_RUNNING 資源已配置設定.
IFF_NOARP 無arp協定, 沒有設定第二層目的位址.
IFF_PROMISC 接口為雜湊(promiscuous)模式.
IFF_NOTRAILERS 避免使用trailer .
IFF_ALLMULTI 接收所有多點傳播(multicast)封包.
IFF_MASTER 主負載平衡群(bundle).
IFF_SLAVE 從負載平衡群(bundle).
IFF_MULTICAST 支援多點傳播(multicast).
IFF_PORTSEL 可以通過ifmap選擇媒體(media)類型.
IFF_AUTOMEDIA 自動選擇媒體.
IFF_DYNAMIC 接口關閉時丢棄位址.
設定 活動标志字 是 特權操作, 但是 任何程序 都可以 讀取 标志字. 
SIOCGIFMETRIC,  SIOCSIFMETRIC
使用  ifr_metric 讀取 或 設定 裝置的 metric 值. 該功能 目前 還沒有 實作. 讀取操作 使  ifr_metric 置 0, 而 設定操作 則 傳回  EOPNOTSUPP. 
SIOCGIFMTU,  SIOCSIFMTU
使用  ifr_mtu 讀取 或 設定 裝置的 MTU(最大傳輸單元). 設定 MTU 是 特權操作. 過小的 MTU 可能 導緻 核心 崩潰. 
SIOCGIFHWADDR,  SIOCSIFHWADDR
使用  ifr_hwaddr 讀取 或 設定 裝置的 硬體位址. 設定 硬體位址 是 特權操作. 
SIOCSIFHWBROADCAST
使用  ifr_hwaddr 讀取 或 設定 裝置的 硬體廣播位址. 這是個 特權操作. 
SIOCGIFMAP,  SIOCSIFMAP
使用  ifr_map 讀取 或 設定 接口的 硬體參數. 設定 這個參數 是 特權操作. 
struct ifmap 
{
    unsigned long   mem_start;
    unsigned long   mem_end;
    unsigned short  base_addr; 
    unsigned char   irq;                  
    unsigned char   dma; 
    unsigned char   port; 
};

      
對 ifmap 結構 的 解釋 取決于 裝置驅動程式 和 體系結構.
SIOCADDMULTI,  SIOCDELMULTI
使用  ifr_hwaddr 在 裝置的 鍊路層 多點傳播過濾器 (multicase filter) 中 添加 或 删除 位址. 這些是 特權操作. 參看  packet(7) . 
SIOCGIFTXQLEN,  SIOCSIFTXQLEN
使用  ifr_qlen 讀取 或 設定 裝置的 傳輸隊列長度. 設定 傳輸隊列長度 是 特權操作.
SIOCSIFNAME
把  ifr_ifindex 中 指定的 接口名字 改成  ifr_newname. 這是個 特權操作.
SIOCGIFCONF
傳回 接口位址(傳輸層) 清單. 出于 相容性, 目前 隻代表 AF_INET 位址. 使用者 傳送 一個  ifconf 結構 作為 ioctl 的 參數. 其中 ifc_req 包含 一個 指針 指向  ifreq 結構數組, 他的 長度 以位元組 為機關 存放在  ifc_len 中. 核心 用 所有 目前的 L3(第三層?) 接口位址 填充 ifreqs, 這些 接口 正在 運作:  ifr_name 存放 接口名字 (eth0:1等),  ifr_addr 存放 位址. 核心 在  ifc_len 中 傳回 實際長度; 如果 他 等于 初始長度, 表示 溢出了, 使用者 應該 換一個 大些的 緩沖區 重試 一下. 沒有 發生 錯誤時 ioctl 傳回 0, 否則 傳回 -1, 溢出 不算 錯誤.

大多數 協定 使用 自己的 ioctl 配置 協定 特定的 接口 操作. 具體 情況參看 協定的 幫助手冊. 要配置 IP 位址 可以 參看 ip(7).

另外, 某些 裝置 有 專用的 ioctl, 這裡 不做 叙述.

注意 (NOTE)

嚴格說來  SIOCGIFCONF  是 專門 針對 IP 的, 它 屬于  ip (7).

注意 (NOTE)

可以 通過  /proc/net/dev  看到 沒有 位址 或 沒有  IFF_RUNNING  标志 的 接口名字.

繼續閱讀