linux下网络程序经常在启动执行后使用ioctl获取主机的全部网络接口信息,
例如接口地址、是否支持广播,是否支持多播等。
函数原型
#include <sys/ioctl.h> int ioctl(int d, int request, ...); 返回值:成功返回0,出错返回-1
常见选项
SIOCGIFCONF 获取所有接口的列表
SIOCGIFBRDADDR 获取广播地址
SIOCGIFMTU 获取mtu
linux下使用ioctl操作网络接口,需要用到两个结构体
ifconf用来保存所有网络接口信息,结构体为:
struct ifconf { int ifc_len; /* 存放接口信息所需的长度. */ union { __caddr_t ifcu_buf; /* 存放接口信息的地址 */ struct ifreq *ifcu_req; } ifc_ifcu; }; # define ifc_buf ifc_ifcu.ifcu_buf # define ifc_req ifc_ifcu.ifcu_req
ifreq用来保存某个接口的信息
struct ifreq { # define IFHWADDRLEN 6 # define IFNAMSIZ IF_NAMESIZE union { char ifrn_name[IFNAMSIZ]; /* 接口名字, e.g. "en0".*/ } ifr_ifrn; union { struct sockaddr ifru_addr; /* 接口的IP地址 */ struct sockaddr ifru_dstaddr; struct sockaddr ifru_broadaddr; /* 接口的广播地址 */ struct sockaddr ifru_netmask; /* 接口的子网掩码 */ struct sockaddr ifru_hwaddr; /* 接口的mac地址 */ 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)
操作:
1.通过ioctl获得本地所有接口信息存放在ifconf结构中
2.从ifcong中获得某个ifreq的接口信息
其中:
ifc_len:存放所有接口信息的缓冲区长度
ifc_buf:存放接口信息的缓冲区
首先对ifconf的ifc_len和ifc_buf初始化
用ioctl获取所有接口信息,之后ifc_len内存放实际获得的接口信息总长度,信息存放在ifc_buf中
实例:
#include <net/if.h> #include <unistd.h> #include <sys/ioctl.h> #include <netinet/in.h> #include <stdlib.h> #include <stdio.h> #include <iostream> #include <sys/socket.h> #include <arpa/inet.h> using namespace std; int main() { //得到套接字描述符 int sockfd; if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("socket error"); exit(-1); } struct ifconf ifc; caddr_t buf; int len = 100; //初始化ifconf结构 ifc.ifc_len = 1024; if ((buf = (caddr_t)malloc(1024)) == NULL) { cout << "malloc error" << endl; exit(-1); } ifc.ifc_buf = buf; //获取所有接口信息 if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) { perror("ioctl error"); exit(-1); } //遍历每一个ifreq结构 struct ifreq *ifr; struct ifreq ifrcopy; ifr = (struct ifreq*)buf; for(int i = (ifc.ifc_len/sizeof(struct ifreq)); i>0; i--) { //接口名 cout << "interface name: "<< ifr->ifr_name << endl; //ipv4地址 cout << "inet addr: " << inet_ntoa(((struct sockaddr_in*)&(ifr->ifr_addr))->sin_addr) << endl; //获取广播地址 ifrcopy = *ifr; if (ioctl(sockfd, SIOCGIFBRDADDR, &ifrcopy) < 0) { perror("ioctl error"); exit(-1); } cout << "broad addr: " << inet_ntoa(((struct sockaddr_in*)&(ifrcopy.ifr_addr))->sin_addr) << endl; //获取mtu ifrcopy = *ifr; if (ioctl(sockfd, SIOCGIFMTU, &ifrcopy) < 0) { perror("ioctl error"); exit(-1); } cout << "mtu: " << ifrcopy.ifr_mtu << endl; cout << endl; ifr++; } return 0; }
ioctl获取网络接口信息
时间: 2024-10-27 12:19:52