linux下网络程序经常在启动执行后使用ioctl获取主机的全部网络接口信息,
操作:
1.通过ioctl获得本地所有接口信息存放在ifconf结构中
2.从ifcong中获得某个ifreq的接口信息
其中:
ifc_len:存放所有接口信息的缓冲区长度
ifc_buf:存放接口信息的缓冲区
首先对ifconf的ifc_len和ifc_buf初始化
用ioctl获取所有接口信息,之后ifc_len内存放实际获得的接口信息总长度,信息存放在ifc_buf中
实例:
例如接口地址、是否支持广播,是否支持多播等。
函数原型
#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;
}