netlink编程小例子

通过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;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值