ioctl获取网络接口信息

来源:互联网 发布:vmware12安装mac 编辑:程序博客网 时间:2024/06/04 18:06
linux下网络程序经常在启动执行后使用ioctl获取主机的全部网络接口信息,

例如接口地址、是否支持广播,是否支持多播等。


函数原型

#include <sys/ioctl.h>int ioctl(int d, int request, ...);返回值:成功返回0,出错返回-1 

常见选项
SIOCGIFCONF 获取所有接口的列表
SIOCGIFBRDADDR 获取广播地址
SIOCGIFMTU  获取mtu


linux下使用ioctl操作网络接口,需要用到两个结构体

ifconf用来保存所有网络接口信息,结构体为:

struct ifconf  {    intifc_len;/* 存放接口信息所需的长度.  */    union      {__caddr_t ifcu_buf;             /* 存放接口信息的地址 */struct ifreq *ifcu_req;      } ifc_ifcu;  };# define ifc_bufifc_ifcu.ifcu_buf# define ifc_reqifc_ifcu.ifcu_req

ifreq用来保存某个接口的信息

struct ifreq  {# define IFHWADDRLEN6# define IFNAMSIZIF_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_nameifr_ifrn.ifrn_name/* interface name */# define ifr_hwaddrifr_ifru.ifru_hwaddr/* MAC address */# define ifr_addrifr_ifru.ifru_addr/* address*/# define ifr_dstaddrifr_ifru.ifru_dstaddr/* other end of p-p lnk*/# define ifr_broadaddrifr_ifru.ifru_broadaddr/* broadcast address*/# define ifr_netmaskifr_ifru.ifru_netmask/* interface net mask*/# define ifr_flagsifr_ifru.ifru_flags/* flags*/# define ifr_metricifr_ifru.ifru_ivalue/* metric*/# define ifr_mtuifr_ifru.ifru_mtu/* mtu*/# define ifr_mapifr_ifru.ifru_map/* device map*/# define ifr_slaveifr_ifru.ifru_slave/* slave device*/# define ifr_dataifr_ifru.ifru_data/* for use by interface*/# define ifr_ifindexifr_ifru.ifru_ivalue    /* interface index      */# define ifr_bandwidthifr_ifru.ifru_ivalue/* link bandwidth*/# define ifr_qlenifr_ifru.ifru_ivalue/* queue length*/# define ifr_newnameifr_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;//获取mtuifrcopy = *ifr;if (ioctl(sockfd, SIOCGIFMTU, &ifrcopy) < 0){perror("ioctl error");exit(-1);}cout << "mtu: " << ifrcopy.ifr_mtu << endl;cout << endl;ifr++;}return 0;}



0 0
原创粉丝点击