通过netlink获取网络接口的名字和网卡地址
#include <stdio.h>
#include <string.h>#include <errno.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <asm/types.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <linux/netdevice.h>
#include <net/if_arp.h>
#include <netinet/if_ether.h>
#include <netinet/ether.h>
int main(){
int nSocket, nLen, nAttrLen;
char szBuffer[4096];
struct {
struct nlmsghdr nh;
struct ifinfomsg ifi;
}struReq;
struct sockaddr_nl struAddr;
struct nlmsghdr *pstruNL;
struct ifinfomsg *pstrIF;
struct rtattr *pstruAttr;
struct net_device_stats *pstruInfo;
struct ether_addr *pstruEther;
/*
*创建一个PF——NETLINK的socket,使用NETLINK——ROUTE协议
*/
nSocket = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
if(nSocket < 0){
fprintf(stderr, "create socket error : %s\n", strerror(errno));
return -1;
}
//绑定地址
memset(&struAddr, 0, sizeof(struAddr));
struAddr.nl_family = AF_NETLINK;
struAddr.nl_pid = getpid();
struAddr.nl_groups = 0;
if(bind(nSocket, (struct sockaddr *)&struAddr, sizeof(struAddr)) < 0){
fprintf(stderr, "bind socket error: %s \n", strerror(errno));
return -1;
}
//发送一个请求
memset(&struReq, 0, sizeof(struReq));
struReq.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struReq));
struReq.nh.nlmsg_type = RTM_GETROUTE;//RTM_GETLINK;
struReq.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
struReq.ifi.ifi_family = AF_UNSPEC;
memset(&struAddr, 0, sizeof(struAddr));
struAddr.nl_family = AF_NETLINK;
struAddr.nl_pid = 0;
struAddr.nl_groups = 0;
if(sendto(nSocket, &struReq, struReq.nh.nlmsg_len, 0,
(struct sockaddr *)&struAddr, sizeof(struAddr)) < 0){
fprintf(stderr, "sendto data error : %s\n", strerror(errno));
return -1;
}
//循环接受数据,直到超时
alarm(30);
memset(szBuffer, 0, sizeof(szBuffer));
while((nLen = recv(nSocket, szBuffer, sizeof(szBuffer), 0))){
alarm(0);
pstruNL = (struct nlmsghdr *)szBuffer;
//判断是否继续有数据
while(NLMSG_OK(pstruNL, nLen)){
//数据已经获取完成
if(pstruNL-> nlmsg_type == NLMSG_DONE)
break;
if(pstruNL->nlmsg_type == NLMSG_ERROR){
//发生一个错误
struct nlmsgerr *pstruError;
pstruError = (struct nlmsgerr *)NLMSG_DATA(pstruNL);
fprintf(stderr, "huan error [%s]\n", strerror(pstruError->error));
break;
}
if(pstruNL->nlmsg_type == RTM_GETLINK){
printf("nlmsg_type == RTM_GETLINK\n");
}else{
printf("nlmsg_type is %d\n", pstruNL->nlmsg_type);
}
//通过宏获取数据
pstrIF = (struct ifinfomsg *)NLMSG_DATA(pstruNL);
fprintf(stderr, "获取设备[%d]信息\n", pstrIF->ifi_index);
fprintf(stderr, "\t设备类型:");
switch(pstrIF->ifi_type){
case ARPHRD_ETHER:
fprintf(stderr, "以太网\n");
break;
case ARPHRD_PPP:
fprintf(stderr, "ppp拨号\n");
break;
case ARPHRD_LOOPBACK:
fprintf(stderr, "环路设备\n");
break;
default:
fprintf(stderr, "未知\n");
break;
}
//通过宏获取属性
pstruAttr = IFLA_RTA(pstrIF);
nAttrLen = NLMSG_PAYLOAD(pstruNL, sizeof(struct ifinfomsg));
while(RTA_OK(pstruAttr, nAttrLen)){
switch(pstruAttr->rta_type){
case IFLA_IFNAME:
fprintf(stderr, "\t设备名称:%s\n", (char *)RTA_DATA(pstruAttr));
break;
case IFLA_ADDRESS:
if(pstrIF->ifi_type == ARPHRD_ETHER){
pstruEther = (struct ether_addr *)RTA_DATA(pstruAttr);
fprintf(stderr, "\t MAC地址:%s\n",ether_ntoa(pstruEther));
break;
}
}
pstruAttr = RTA_NEXT(pstruAttr, nAttrLen);
}
pstruNL = NLMSG_NEXT(pstruNL, nLen);
}
memset(szBuffer, 0, sizeof(szBuffer));
alarm(30);
}
return 0;
}