Linux 网口热插拔

821586284 2017-11-23 12:41:48 2139

在Linux下监控网卡的连接状态有多种方式,我想要的方式,不是以轮询方式定时查询或主动获取某个值,而是在网卡连接状态变化时我的程序能收到通知。


具体做法如下:

  1. 使用AF_NETLINK socket
  2. 绑定到RTMGRP_LINK组
  3. 等待接收RTM_NEWLINK和RTM_DELLINK类型的message
  4. 解析收到的消息中ifinfomsg结构体的ifi_flags成员是否被设置了IFF_RUNNING1. -

代码如下:

#include <stdio.h>  
#include <stdlib.h>  
#include <unistd.h>  
#include <signal.h>  
#include <errno.h>  
#include <string.h>  
#include <asm/types.h>   
#include <sys/socket.h>  
#include <sys/ioctl.h>   
//#include <net/if.h>   
#include <linux/if.h>   
#include <linux/if_arp.h>   
#include <linux/netlink.h>   
#include <linux/rtnetlink.h>   

#define PRINTF(fmt, ...) printf("%s:%d: " fmt, __FUNCTION__, __LINE&#95;_, ## __VA_ARGS__)  

#define BUF_SIZE 4096   

static int init(struct sockaddr_nl *psa);  
static int deinit();  
static int msg_req();  
static int msg_loop(struct msghdr *pmh);  
static void sig_handler(int sig);  

static int sfd = -1;  

int main (int argc, char *argv[])  
{  
    int ret = 0;  

    char buf[BUF_SIZE];  
    struct iovec iov = {buf, sizeof(buf)};  
    struct sockaddr_nl sa;  
    struct msghdr msg = {(void *)&sa, sizeof(sa), &iov, 1, NULL, 0, 0};  

    ret = init(&sa);  
    if (!ret) {  
        ret = msg_req();  
    }  
    if (!ret) {  
        ret = msg_loop(&msg);  
    }  
    ret = deinit();  

    return ret;  
}  

static int init(struct sockaddr_nl *psa)  
{  
    int ret = 0;  
    struct sigaction sigact;  

    sigact.sa_handler = sig_handler;  
    if (!ret && -1 == sigemptyset(&sigact.sa_mask)) {  
        PRINTF("ERROR! sigemptyset\n");  
        ret = -1;  
    }  
    if (!ret && -1 == sigaction(SIGINT, &sigact, NULL)) {   
        PRINTF("ERROR! sigaction SIGINT\n");  
        ret = -1;  
    }  
    if (!ret && -1 == sigaction(SIGTERM, &sigact, NULL)) {   
        PRINTF("ERROR! sigaction SIGTERM\n");  
        ret = -1;  
    }  

    if (!ret) {  

        sfd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);  
        if (-1 == sfd) {  
            PRINTF("ERROR! socket: %s\n", strerror(errno));  
            ret = -1;  
        }  
    }  

    memset(psa, 0, sizeof(*psa));  
    psa->nl_family = AF_NETLINK;  
    psa->nl_groups = RTMGRP_LINK;   
    if (!ret && bind(sfd, (struct sockaddr *)psa, sizeof(*psa))) {  
        PRINTF("ERROR! bind: %s\n", strerror(errno));  
        ret = -1;  
    }  

    if (0 != ret) {  
        deinit();  
    }  

    return ret;  
}  

static int deinit()  
{  
    int ret = 0;  

    if (-1 != sfd) {  
        if (-1 == close(sfd)) {  
            PRINTF("ERROR! close: %s\n", strerror(errno));  
            ret = -1;  
        }  
        sfd = -1;  
    }  

    return ret;  
}  

static int msg_req()  
{  
    int ret = 0;  
    struct {  
        struct nlmsghdr  nh;  
        struct ifinfomsg ifimsg;  
    } req;  

    memset(&req, 0, sizeof(req));  
    req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));   
    req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;   
    req.nh.nlmsg_type = RTM_GETLINK;   
    req.ifimsg.ifi_family = AF_UNSPEC;   
    req.ifimsg.ifi_index = 0;   
    req.ifimsg.ifi_change = 0xFFFFFFFF;   
    if (-1 == send(sfd, &req, req.nh.nlmsg_len, 0)) {  
        PRINTF("ERROR! send: %s\n", strerror(errno));  
        ret = -1;  
    }  

    return ret;  
}  

static int msg_loop(struct msghdr *pmh)  
{  
    int ret = 0;  
    ssize&#95;t nread = -1;  
    char *buf = (char *)(pmh->msg_iov->iov_base);  
    struct nlmsghdr *nh;  
    struct ifinfomsg *ifimsg;  
    struct rtattr *rta;  
    int attrlen;  

    while (!ret) {  
        nread = recvmsg(sfd, pmh, 0);  
        if (-1 == nread) {  
            PRINTF("ERROR! recvmsg: %s\n", strerror(errno));  
            ret = -1;  
        }  

        for (nh = (struct nlmsghdr *)buf;   
                !ret && NLMSG_OK(nh, nread);   
                nh = NLMSG_NEXT(nh, nread)) {   

            if (NLMSG_DONE == nh->nlmsg_type) {  
                break;  
            }  

            if (NLMSG_ERROR == nh->nlmsg_type) {  

                PRINTF("ERROR! NLMSG_ERROR\n");  
                ret = -1;  
            }  

            if (!ret && (RTM_NEWLINK == nh->nlmsg_type || RTM_DELLINK == nh->nlmsg_type)) {   
                ifimsg = (struct ifinfomsg *)NLMSG_DATA(nh);   
                if (ARPHRD_LOOPBACK != ifimsg->ifi_type) {   

                    attrlen = nh->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifinfomsg));   
                    for (rta = IFLA_RTA(ifimsg);   
                            RTA_OK(rta, attrlen) && rta->rta_type <= IFLA_MAX;   
                            rta = RTA_NEXT(rta, attrlen)) {   
                        if (IFLA_IFNAME == rta->rta_type) {   
                                printf("%s: ", (char*)RTA_DATA(rta));   
                        }  
                    }  

                    if (IFF_RUNNING & ifimsg->ifi_flags)  
                        printf("link up\n");  
                    else  
                        printf("link down\n");  
                }  
            }  
        }  
    }  

    return ret;  
}  

static void sig_handler(int sig)  
{  
    exit(deinit());  
} 
声明:本文内容由易百纳平台入驻作者撰写,文章观点仅代表作者本人,不代表易百纳立场。如有内容侵权或者其他问题,请联系本站进行删除。
红包 点赞 收藏 评论 打赏
评论
0个
内容存在敏感词
手气红包
    易百纳技术社区暂无数据
相关专栏
关于作者
821586284

821586284

暂无个性签名~

原创6
阅读2.1w
收藏0
点赞0
评论0
打赏用户 0
我要创作
分享技术经验,可获取创作收益
分类专栏
置顶时间设置
结束时间
删除原因
  • 广告/SPAM
  • 恶意灌水
  • 违规内容
  • 文不对题
  • 重复发帖
打赏作者
易百纳技术社区
821586284
您的支持将鼓励我继续创作!
打赏金额:
¥1易百纳技术社区
¥5易百纳技术社区
¥10易百纳技术社区
¥50易百纳技术社区
¥100易百纳技术社区
支付方式:
微信支付
支付宝支付
易百纳技术社区微信支付
易百纳技术社区
打赏成功!

感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~

举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

审核成功

发布时间设置
发布时间:
是否关联周任务-专栏模块

审核失败

失败原因
备注
拼手气红包 红包规则
祝福语
恭喜发财,大吉大利!
红包金额
红包最小金额不能低于5元
红包数量
红包数量范围10~50个
余额支付
当前余额:
可前往问答、专栏板块获取收益 去获取
取 消 确 定

小包子的红包

恭喜发财,大吉大利

已领取20/40,共1.6元 红包规则

    易百纳技术社区