netlink 编程介绍

来源:互联网 发布:凌波微步 软件 编辑:程序博客网 时间:2024/05/21 22:25





引自:http://hi.baidu.com/bingqingwu5799/item/6e266cc653bb2408c710b296

  1. 下面是一个用来获取所有网卡信息的例子.
  2. #i nclude <stdio.h>
    #i nclude <string.h>
    #i nclude <errno.h>
    #i nclude <sys/socket.h>
    #i nclude <sys/types.h>
    #i nclude <unistd.h>
    #i nclude <asm/types.h>
    #i nclude <linux/netlink.h>
    #i nclude <linux/rtnetlink.h>
    #i nclude <linux/netdevice.h>
    #i nclude <net/if_arp.h>
    #i nclude <netinet/if_ether.h>
    #i nclude <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 *pstruIF;
    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"创建SOCKET错误:%s\n", strerror(errno));
    return -1;
    }

    /*
    * 绑定地址
    */

    memset(&struAddr, 0sizeof(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"绑定SOCKET错误:%s\n", strerror(errno));
    return -1;
    }

    /*
    * 发送一个请求
    */

    memset(&struReq, 0sizeof(struReq));
    struReq.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struReq));
    struReq.nh.nlmsg_type = RTM_GETLINK;
    struReq.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
    struReq.ifi.ifi_family = AF_UNSPEC;
    memset(&struAddr, 0sizeof(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"发送数据错误:%s\n", strerror(errno));
    return -1;
    }

    /*
    * 循环接收数据,直到超时
    */

    alarm(30);
    memset(szBuffer, 0sizeof(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"发生错误[%s]\n",
    strerror(-pstruError -> error));
    break;
    }

    /*
    * 下面通过宏获取数据
    */

    pstruIF = NLMSG_DATA(pstruNL);
    fprintf(stderr"获取到设备[%d]信息\n", pstruIF -> ifi_index);
    fprintf(stderr"\t设备类型:");
    switch(pstruIF -> 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;
    }
    fprintf(stderr"\t设备状态:");
    if((pstruIF -> ifi_flags & IFF_UP )== IFF_UP)
    fprintf(stderr" UP");
    if((pstruIF -> ifi_flags & IFF_BROADCAST) == IFF_BROADCAST)
    fprintf(stderr" BROADCAST");
    if((pstruIF -> ifi_flags & IFF_DEBUG) == IFF_DEBUG)
    fprintf(stderr" DEBUG");
    if((pstruIF -> ifi_flags & IFF_LOOPBACK) == IFF_LOOPBACK)
    fprintf(stderr" LOOPBACK");
    if((pstruIF -> ifi_flags & IFF_POINTOPOINT) == IFF_POINTOPOINT)
    fprintf(stderr" POINTOPOINT");
    if((pstruIF -> ifi_flags & IFF_RUNNING) == IFF_RUNNING)
    fprintf(stderr" RUNNING");
    if((pstruIF -> ifi_flags & IFF_NOARP) == IFF_NOARP)
    fprintf(stderr" NOARP");
    if((pstruIF -> ifi_flags & IFF_PROMISC) == IFF_PROMISC)
    fprintf(stderr" PROMISC");
    if((pstruIF -> ifi_flags & IFF_NOTRAILERS) == IFF_NOTRAILERS)
    fprintf(stderr" NOTRAILERS");
    if((pstruIF -> ifi_flags & IFF_ALLMULTI) == IFF_ALLMULTI)
    fprintf(stderr" ALLMULTI");
    if((pstruIF -> ifi_flags & IFF_MASTER) == IFF_MASTER)
    fprintf(stderr" MASTER");
    if((pstruIF -> ifi_flags & IFF_SLAVE) == IFF_SLAVE)
    fprintf(stderr" SLAVE");
    if((pstruIF -> ifi_flags & IFF_MULTICAST) == IFF_MULTICAST)
    fprintf(stderr" MULTICAST");
    if((pstruIF -> ifi_flags & IFF_PORTSEL) == IFF_PORTSEL)
    fprintf(stderr" SLAVE");
    if((pstruIF -> ifi_flags & IFF_AUTOMEDIA) == IFF_AUTOMEDIA)
    fprintf(stderr" AUTOMEDIA");
    if((pstruIF -> ifi_flags & IFF_DYNAMIC) == IFF_DYNAMIC)
    fprintf(stderr" DYNAMIC");
    fprintf(stderr"\n");

    /*
    * 下面通过宏获取属性
    */

    pstruAttr = IFLA_RTA(pstruIF);
    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_MTU:
    fprintf(stderr"\t设备MTU:%d\n",
    *(unsigned int *)RTA_DATA(pstruAttr));
    break;
    case IFLA_QDISC:
    fprintf(stderr"\t设备队列:%s\n",
    (char *)RTA_DATA(pstruAttr));
    break;
    case IFLA_ADDRESS:
    if(pstruIF -> ifi_type == ARPHRD_ETHER)
    {
    pstruEther = (struct ether_addr *)
    RTA_DATA(pstruAttr);
    fprintf(stderr"\tMAC地址:%s\n",
    ether_ntoa(pstruEther));
    }
    break;
    case IFLA_BROADCAST:
    if(pstruIF -> ifi_type == ARPHRD_ETHER)
    {
    pstruEther = (struct ether_addr *)
    RTA_DATA(pstruAttr);
    fprintf(stderr"\t广播MAC地址:%s\n",
    ether_ntoa(pstruEther));
    }
    break;
    case IFLA_STATS:
    pstruInfo = (struct net_device_stats *)
    RTA_DATA(pstruAttr);
    fprintf(stderr"\t接收信息:\n");
    fprintf(stderr"\t\t接收报文:%lu字节:%lu\n",
    pstruInfo -> rx_packets, pstruInfo -> rx_bytes);
    fprintf(stderr"\t\terrors:%ludropped:%lu"
    "multicast:%lucollisions:%lu\n"
    ,
    pstruInfo -> rx_errors, pstruInfo -> rx_dropped,
    pstruInfo -> multicast, pstruInfo -> collisions);
    fprintf(stderr"\t\tlength:%luover:%lucrc:%lu"
    "frame:%lufifo:%lumissed:%lu\n"
    ,
    pstruInfo -> rx_length_errors,
    pstruInfo -> rx_over_errors,
    pstruInfo -> rx_crc_errors,
    pstruInfo -> rx_frame_errors,
    pstruInfo -> rx_fifo_errors,
    pstruInfo -> rx_missed_errors);
    fprintf(stderr"\t发送信息:\n");
    fprintf(stderr"\t\t发送报文:%lu字节:%lu\n",
    pstruInfo -> tx_packets, pstruInfo -> tx_bytes);
    fprintf(stderr"\t\terrors:%ludropped:%lu\n",
    pstruInfo -> tx_errors, pstruInfo -> tx_dropped);
    fprintf(stderr"\t\taborted:%lucarrier:%lufifo:%lu"
    " heartbeat:%luwindow:%lu\n"
    ,
    pstruInfo -> tx_aborted_errors,
    pstruInfo -> tx_carrier_errors,
    pstruInfo -> tx_fifo_errors,
    pstruInfo -> tx_heartbeat_errors,
    pstruInfo -> tx_window_errors);
    break;
    default:
    break;

    }
    /*
    * 继续下一个属性
    */

    pstruAttr = RTA_NEXT(pstruAttr, nAttrLen);
    }
    /*
    * 继续下一个数据
    */

    pstruNL = NLMSG_NEXT(pstruNL, nLen);
    }
    memset(szBuffer, 0sizeof(szBuffer));
    alarm(30);
    }
    return 0;
    }
  3. 下面是我的机器的输出信息
  4. 获取到设备[1]信息
    设备类型:环路设备
    设备状态: UP LOOPBACK RUNNING
    设备名称:lo
    设备MTU:16436
    设备队列:noqueue
    接收信息:
    接收报文:73 字节:5105
    errors:0 dropped:0 multicast:0 collisions:0
    length:0 over:0 crc:0 frame:0 fifo:0 missed:0
    发送信息:
    发送报文:73 字节:5105
    errors:0 dropped:0
    aborted:0 carrier:0 fifo:0 heartbeat:0 window:0
    获取到设备[2]信息
    设备类型:以太网
    设备状态: UP BROADCAST RUNNING MULTICAST
    设备名称:eth0
    MAC地址:0:e0:4c:68:17:e2
    广播MAC地址:ff:ff:ff:ff:ff:ff
    设备MTU:1500
    设备队列:pfifo_fast
    接收信息:
    接收报文:23942563 字节:2498812213
    errors:0 dropped:0 multicast:0 collisions:0
    length:0 over:0 crc:0 frame:0 fifo:0 missed:0
    发送信息:
    发送报文:26027259 字节:782054736
    errors:0 dropped:0
    aborted:0 carrier:0 fifo:0 heartbeat:0 window:0
    获取到设备[3]信息
    设备类型:以太网
    设备状态: UP BROADCAST RUNNING MULTICAST
    设备名称:eth1
    MAC地址:0:11:5b:16:ac:52
    广播MAC地址:ff:ff:ff:ff:ff:ff
    设备MTU:1500
    设备队列:pfifo_fast
    接收信息:
    接收报文:28576652 字节:97399242
    errors:0 dropped:0 multicast:0 collisions:0
    length:0 over:0 crc:0 frame:0 fifo:0 missed:0
    发送信息:
    发送报文:22489921 字节:2255181112
    errors:0 dropped:0
    aborted:0 carrier:0 fifo:0 heartbeat:0 window:0
    获取到设备[4]信息
    设备类型:PPP拨号
    设备状态: UP POINTOPOINT RUNNING NOARP MULTICAST
    设备名称:ppp0
    设备MTU:1492
    设备队列:pfifo_fast
    接收信息:
    接收报文:25021013 字节:3614587231
    errors:0 dropped:0 multicast:0 collisions:0
    length:0 over:0 crc:0 frame:0 fifo:0 missed:0
    发送信息:
    发送报文:22442439 字节:1757067695
    errors:0 dropped:0
    aborted:0 carrier:0 fifo:0 heartbeat:0 window:0
原创粉丝点击