美文网首页
通过Netlink检测网线插拔

通过Netlink检测网线插拔

作者: 网路元素 | 来源:发表于2019-11-02 07:44 被阅读0次

        最近有个需求需要检测RJ45网卡的网线有没有接上,而最近正在了解Netlink相关资料,刚好也看下通过Netlink可以进行检测,故在此做下粗略笔记:

        1.首先要创建一个Netlink Socket,在用户层使用如下参数来调用socket()函数:

           fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); 

           上面这个函数第一个参数必须是AF_NETLINK或PF_NETLINK,这两个标志在Linux下是一样的,第二个参数可以是SOCK_RAW或SOCK_DGRAM(对应用到TCP或UDP协议),而最后一个参数NETLINK_ROUTE为“路由守护进程”,用于接收来自内核的路由通知事件。

        2.将上面创建的Socket绑定

    addr.nl_family = AF_NETLINK;
    addr.nl_groups = RTNLGRP_LINK; //指定接收路由多播组消息
    bind(fd, (struct sockaddr*)&addr, sizeof(addr));

           上面将创建的socket与相应的协议族和组进行绑定,接下来通过读fd这个socket来获得相应的消息数据struct nlmsghdr,再对该结构体数据进行判断来获得网线是接上或是拔掉,相应的源码如下:

    #include <sys/types.h> 
    #include <sys/socket.h>
    #include <asm/types.h> 
    #include <linux/netlink.h> 
    #include <linux/rtnetlink.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <sys/ioctl.h>
    #include <linux/if.h>
    #include <string.h>

    #define BUFLEN 20480

    int main(int argc, char *argv[])
    {
        int fd, retval;
        char buf[BUFLEN] = {0};

        int len = BUFLEN;
        struct sockaddr_nl addr;
        struct nlmsghdr *nh;
        struct ifinfomsg *ifinfo;
        struct rtattr *attr;

        fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
        setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &len, sizeof(len));
        memset(&addr, 0, sizeof(addr));

        addr.nl_family = AF_NETLINK;
        addr.nl_groups = RTNLGRP_LINK;
        bind(fd, (struct sockaddr*)&addr, sizeof(addr));

        while ((retval = read(fd, buf, BUFLEN)) > 0)
        {
            for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, retval); nh = NLMSG_NEXT(nh, retval))
            {
                if (nh->nlmsg_type == NLMSG_DONE)
                    break;
                else if (nh->nlmsg_type == NLMSG_ERROR)
                    return;
                else if (nh->nlmsg_type != RTM_NEWLINK)
                    continue;

                ifinfo = NLMSG_DATA(nh);
                printf("%u: %s", ifinfo->ifi_index,  (ifinfo->ifi_flags & IFF_LOWER_UP) ? "up" : "down" );

                attr = (struct rtattr*)(((char*)nh) + NLMSG_SPACE(sizeof(*ifinfo)));
                len = nh->nlmsg_len - NLMSG_SPACE(sizeof(*ifinfo));

                for (; RTA_OK(attr, len); attr = RTA_NEXT(attr, len))
                {
                    if (attr->rta_type == IFLA_IFNAME)
                    {
                        printf(" %s", (char*)RTA_DATA(attr));
                        break;
                    }
                }

                printf("\n");
            }
        }
        return 0;
    }

            将上面的代码保存成文件rj45_pulg_check.c,然后执行命令gcc -o rj45_pulg_check rj45_pulg_check.c进行编译,生成rj45_pulg_check文件,执行该文件后再插拔网线,有如下内容输出:

    2: down eth0
    2: up eth0

            注意:上述操作须在网卡驱动加载后进行,并且使用ifconfig里能看到该网卡信息(如没有则执行ifconfig eth0 up),实际上就相当于有没有分配到IP地址(即网络有没有通路)的判断。当我们开关WiFi时也可以检测到。

    参考网址:

    http://blog.csdn.net/sourthstar/article/details/7975999
    http://blog.chinaunix.net/uid-317451-id-92692.html

    相关文章

      网友评论

          本文标题:通过Netlink检测网线插拔

          本文链接:https://www.haomeiwen.com/subject/ehcryctx.html