一、struct ifreq结构体
这个结构定义在/usr/include/net/if.h,用来配置和获取ip地址,掩码,MTU等接口信息的。
- /* 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_data;
- } 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_data ifr_ifru.ifru_data /* for use by interface */
- # 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)
二、用法:
通过ioctl()函数调用
下表列出了网络相关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 |
实例一,获取网卡的IP地址:
- #include <string.h>
- #include <sys/socket.h>
- #include <sys/ioctl.h>
- #include <net/if.h>
- #include <stdio.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- int main()
- {
- int inet_sock;
- struct ifreq ifr;
- inet_sock = socket(AF_INET, SOCK_DGRAM, 0);
- strcpy(ifr.ifr_name, "eth0");
- //SIOCGIFADDR标志代表获取接口地址
- if (ioctl(inet_sock, SIOCGIFADDR, &ifr) < 0)
- perror("ioctl");
- printf("%s\n", inet_ntoa(((struct sockaddr_in*)&(ifr.ifr_addr))->sin_addr));
- return 0;
- }
实例二,实现简单ifconfig功能:
- /**
- * \file getifstat.c
- * \author wzj
- * \brief 访问这个struct ifconf 修改,查询状态
- * \version
- * \note
- * \date: 2012年08月11日星期六22:55:25
- */
- #include <net/if.h> /* for ifconf */
- #include <linux/sockios.h> /* for net status mask */
- #include <netinet/in.h> /* for sockaddr_in */
- #include <sys/socket.h>
- #include <sys/types.h>
- #include <sys/ioctl.h>
- #include <stdio.h>
- #define MAX_INTERFACE (16)
- void port_status(unsigned int flags);
- /* set == 0: do clean , set == 1: do set! */
- int set_if_flags(char *pif_name, int sock, int status, int set)
- {
- struct ifreq ifr;
- int ret = 0;
- strncpy(ifr.ifr_name, pif_name, strlen(pif_name) + 1);
- ret = ioctl(sock, SIOCGIFFLAGS, &ifr);
- if(ret)
- return -1;
- /* set or clean */
- if(set)
- ifr.ifr_flags |= status;
- else
- ifr.ifr_flags &= ~status;
- /* set flags */
- ret = ioctl(sock, SIOCSIFFLAGS, &ifr);
- if(ret)
- return -1;
- return 0;
- }
- int get_if_info(int fd)
- {
- struct ifreq buf[MAX_INTERFACE];
- struct ifconf ifc;
- int ret = 0;
- int if_num = 0;
- ifc.ifc_len = sizeof(buf);
- ifc.ifc_buf = (caddr_t) buf;
- ret = ioctl(fd, SIOCGIFCONF, (char*)&ifc);
- if(ret)
- {
- printf("get if config info failed");
- return -1;
- }
- /* 网口总数 ifc.ifc_len 应该是一个出入参数 */
- if_num = ifc.ifc_len/sizeof(struct ifreq);
- printf("interface num is interface = %d\n", if_num);
- while(if_num-- > 0)
- {
- printf("net device: %s\n", buf[if_num].ifr_name);
- /* 获取第n个网口信息 */
- ret = ioctl(fd, SIOCGIFFLAGS, (char*)&buf[if_num]);
- if(ret)
- continue;
- /* 获取网口状态 */
- port_status(buf[if_num].ifr_flags);
- /* 获取当前网卡的ip地址 */
- ret = ioctl(fd, SIOCGIFADDR, (char*)&buf[if_num]);
- if(ret)
- continue;
- printf("IP address is: \n%s\n", inet_ntoa(((struct sockaddr_in *)(&buf[if_num].ifr_addr))->sin_addr));
- /* 获取当前网卡的mac */
- ret = ioctl(fd, SIOCGIFHWADDR, (char*)&buf[if_num]);
- if(ret)
- continue;
- printf("%02x:%02x:%02x:%02x:%02x:%02x\n\n",
- (unsigned char)buf[if_num].ifr_hwaddr.sa_data[0],
- (unsigned char)buf[if_num].ifr_hwaddr.sa_data[1],
- (unsigned char)buf[if_num].ifr_hwaddr.sa_data[2],
- (unsigned char)buf[if_num].ifr_hwaddr.sa_data[3],
- (unsigned char)buf[if_num].ifr_hwaddr.sa_data[4],
- (unsigned char)buf[if_num].ifr_hwaddr.sa_data[5]
- );
- }
- }
- void port_status(unsigned int flags)
- {
- if(flags & IFF_UP)
- {
- printf("is up\n");
- }
- if(flags & IFF_BROADCAST)
- {
- printf("is broadcast\n");
- }
- if(flags & IFF_LOOPBACK)
- {
- printf("is loop back\n");
- }
- if(flags & IFF_POINTOPOINT)
- {
- printf("is point to point\n");
- }
- if(flags & IFF_RUNNING)
- {
- printf("is running\n");
- }
- if(flags & IFF_PROMISC)
- {
- printf("is promisc\n");
- }
- }
- int main()
- {
- int fd;
- fd = socket(AF_INET, SOCK_DGRAM, 0);
- if(fd > 0)
- {
- get_if_info(fd);
- close(fd);
- }
- return 0;
- }
运行结果:
interface num is interface = 2
net device: eth0
is up
is broadcast
is running
IP address is:
192.168.100.200
54:be:f7:33:57:26
net device: lo
is up
is loop back
is running
IP address is:
127.0.0.1
00:00:00:00:00:00