在应用层获取系统的网卡或者路由的信息都可以通过ioctl 获取,总结一下使用ioctl 获取网卡信息相关的内容
1.关键数据结构,strucet ifreq 通过ioctl 获取某一个网卡信息的数据结构,struct ifconf 是获取所有可用网卡的数据结构(经实践,
不管网卡link 状态是up or down,只能获取配置了ip地址网卡)
struct ifreq 和 struct ifconf 都是定义在net/if.h 中,具体的定义如下
点击(此处)折叠或打开
-
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 */
-
-
struct ifconf
-
{
-
int ifc_len; /* Size of buffer. */
-
union
-
{
-
__caddr_t ifcu_buf;
-
struct ifreq *ifcu_req;
-
} ifc_ifcu;
-
};
-
# define ifc_buf ifc_ifcu.ifcu_buf /* Buffer address. */
-
# define ifc_req ifc_ifcu.ifcu_req /* Array of structures. */
数据结构就不解释了,头文件中都注释的很清楚
2.例子
-
#include<stdio.h>
-
#include <unistd.h>
-
#include<string.h>
-
#include <sys/socket.h>
-
#include<net/if.h>
-
#include<netinet/in.h>
-
#include<linux/sockios.h>
-
-
-
int main(int argc,char **argv)
-
{
-
struct ifconf ifc;
-
struct ifreq ifr[10];
-
int i;
-
int fd ;
-
int count;
-
-
memset(&ifc,0,sizeof(struct ifconf));
-
-
fd = socket(AF_INET, SOCK_DGRAM, 0);
-
if(fd <0){
-
printf("open socket fail\n");
-
return -1;
-
}
-
-
/*初始化ifconf ,准备去内核获取信息,其中ifc.ifc_len是一个值-结果参数,先传ioctl 返回的时候会修改这个值为实际的长度*/
-
ifc.ifc_len = 1024;
-
ifc.ifc_buf = (void*)ifr;
-
-
-
/*get all accessible interface by SIOCGIFCONF,通过socket 命令字SIOCGIFCONF,获取系统配置了ip地址的接口信息,
-
通过SIOCGIFCONF,只能返回ifr_name,和ifr_addr,如果还需要接口的其他信息,可以用这里获取回来的name ,
-
然后通过对应的socket命令字获取对应的信息*/
-
if(ioctl(fd,SIOCGIFCONF,&ifc)<0){
-
printf("ioctl fail\n");
-
return -1;
-
}
-
-
count = ifc.ifc_len/sizeof(struct ifreq);
-
-
for(i=0;i<count;i++) {
-
struct ifreq *ifrp=&ifc.ifc_req[i];
-
char addr_buf[16];
-
printf("ifname=%s, ",ifrp->ifr_name);
-
inet_ntop(AF_INET, &(((struct sockaddr_in* )&ifrp->ifr_addr)->sin_addr.s_addr),addr_buf,(socklen_t )sizeof(addr_buf));
-
printf("addr=%s, ",addr_buf);
-
-
/*get MTU ,需要mtu的,可以传入赋值了ifr_name的ifreq,来获取,如果不通过*/
-
if (ioctl(fd, SIOCGIFMTU, &ifc.ifc_req[i] ) < 0){
-
printf("ioctl get %s MTU fail\n",ifrp->ifr_name);
-
return -1;
-
}
-
printf("MTU=%d,",ifrp->ifr_mtu);
-
-
/*get MAC,获取mac,传入赋值了ifr_name的ifreq 获取*/
-
if (ioctl(fd, SIOCGIFHWADDR, &ifc.ifc_req[i] ) < 0){
-
printf("ioctl get %s MAC fail\n",ifrp->ifr_name);
-
return -1;
-
}
-
-
printf("MAC =%02x:%02x:%02x:%02x:%02x:%02x",
-
(unsigned char)ifrp->ifr_hwaddr.sa_data[0],
-
(unsigned char)ifrp->ifr_hwaddr.sa_data[1],
-
(unsigned char)ifrp->ifr_hwaddr.sa_data[2],
-
(unsigned char)ifrp->ifr_hwaddr.sa_data[3],
-
(unsigned char)ifrp->ifr_hwaddr.sa_data[4],
-
(unsigned char)ifrp->ifr_hwaddr.sa_data[5]);
-
-
printf("\n");
-
}
-
-
return 0;
-
}
上面的代码可以获取系统中配置了ip的所有网卡的name,addr,mtu,mac
if(ioctl(fd,SIOCGIFCONF,&ifc)<0) ,这样get 只能get 配置了ip地址的网卡,通过ifconf 只能获取到ifreq里面的name 和addr
如果还需要其他信息,可以继续通过ioctl 根据name 获取网卡的其他参数(各种socket的命令字定义在./linux/sockios.h )
如果想获取某一个指定接口的信息,可指定ifreq的ifr_name ,然后ioctl 传入指定了ifr_name的ifreq,获取指定的接口信息
在头文件net/if.h 中还提供了结果if_name和if_index 互相转换的接口,分别是if_nametoindex,if_indextoname等,如果需要可以直接引用
阅读(3424) | 评论(0) | 转发(0) |