网络程序(一般是服务器程序)中ioctl常用于在程序启动时获得主机上所有接口的信息: 接口的地址、接口是否支持广播、是否支持多播等等。
#include <unistd.h> or #include <sys/ioctl.h>
int ioctl(int fd, int request, …/*void *arg */);
返回:成功返回0,出错返回-1;
下表列出了网络相关ioctl 请求的request 参数以及arg 地址必须指向的数据类型:
类别 | Request | 说明 | 数据类型 |
套 接 口 | 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 |
|
|
为这个调用拥有与网络相关的代码,所以文件描述符号fd就是socket()系统调用所返回的,而command参数可以是/usr/include/linux/sockios.h头文件中的任何一个,这些个命令根据它可以解决的问题所涉及的方面被分为多种的类型.
改变路由表(SIOCADDRT, SIOCDELRT)
读取或更新ARP/RARP缓存(SIOCDARP, SIOCSRARP)
一般的和网络有关的函数(SIOCGIFNAME, SIOCSIFADDR等等)
Goodies目录中包含了很多展示ioctl用法的示例程序,看这些程序的时候,注意根据ioctl的命令类型来使用具体的调用参数结构,比如:和路由表相关的IOCTL用RTENTRY结构,rtentry结构是被定义在/usr/include/linux/route.h文件中的,和ARP相关的ioctl调用到的arpreq结构被定义在/usr/include/linux/if_arp.h文件之中。网络接口相关的ioctl命令最具有代表性的特征的是都以S或G开头,其实就是设置或得到数据,getifinfo.c程序用这些命令去读取IP地址信息,硬件地址信息,广播地址信息和与网络接口相关的标志。对于这些ioctl,第三个参数是一个ifreq结构体,这个结构体被定义在/usr/include/linux/if.h头文件中。
根据常规约定,一个用户程序调用一个特定的ioctl命令如下:
ioctl(sockid, SIOCDEVPRIVATE, (char *) &ifr);
这里ifr是一个ifreq结构体变量,它用一个和这个设备联系的接口名称来填充ifr的ifr NAME域,比如前述的无线网卡接口名称为eth1。
ifreq结构体:
/* Interface request structure used for socket ioctl's. All interface
ioctl's must have parameter definitions which begin with ifr_name.
The remainder may be interface specific. */
struct ifreq
{
# define IFHWADDRLEN 6
# define IFNAMSIZ IF_NAMESIZE
union
{
char ifrn_name[IFNAMSIZ]; /* Interface name, e.g. "en0". */
} ifr_ifrn;
union
{
struct sockaddr ifru_addr;
struct sockaddr ifru_dstaddr;
struct sockaddr ifru_broadaddr;
struct sockaddr ifru_netmask;
struct sockaddr ifru_hwaddr;
short int ifru_flags;
int ifru_ivalue;
int ifru_mtu;
struct ifmap ifru_map;
char ifru_slave[IFNAMSIZ]; /* Just fits the size */
char ifru_newname[IFNAMSIZ];
__caddr_t ifru_da
} ifr_ifru;
};
# define ifr_name ifr_ifrn.ifrn_name /* interface name */
# define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */
# define ifr_addr ifr_ifru.ifru_addr /* address */
# define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */
# define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */
# define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */
# define ifr_flags ifr_ifru.ifru_flags /* flags */
# define ifr_metric ifr_ifru.ifru_ivalue /* metric */
# define ifr_mtu ifr_ifru.ifru_mtu /* mtu */
# define ifr_map ifr_ifru.ifru_map /* device map */
# define ifr_slave ifr_ifru.ifru_slave /* slave device */
# define ifr_da
# define ifr_ifindex ifr_ifru.ifru_ivalue /* interface index */
# define ifr_bandwidth ifr_ifru.ifru_ivalue /* link bandwidth */
# define ifr_qlen ifr_ifru.ifru_ivalue /* queue length */
# define ifr_newname ifr_ifru.ifru_newname /* New name */
# define _IOT_ifreq _IOT(_IOTS(char),IFNAMSIZ,_IOTS(char),16,0,0)
# define _IOT_ifreq_short _IOT(_IOTS(char),IFNAMSIZ,_IOTS(short),1,0,0)
# define _IOT_ifreq_int _IOT(_IOTS(char),IFNAMSIZ,_IOTS(int),1,0,0)