struct ifreq学习和实例
一、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
参考转载博客地址:
http://blog.csdn.net/dsg333/article/details/7525634
http://blog.csdn.net/kulung/article/details/6442597
http://blog.csdn.net/joker0910/article/details/7855998