免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2352 | 回复: 2
打印 上一主题 下一主题

[网络子系统] 如何通过netlink来获取子网卡的状态变化 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2015-08-06 12:24 |只看该作者 |倒序浏览
具体点讲就是: 现在有一个网卡eth0  在网卡上启用了好几个子网卡 eth0:1 eth0:2。 这样就导致了接口的index值可以对应多个ifname, 现在eth0:1 地址发生变化了,那我如何使用netlink 来知道是eth0:1发生变化的呢?

论坛徽章:
0
2 [报告]
发表于 2015-08-16 22:58 |只看该作者
我自己来回答吧,可以参考iproute中关于获取网络接口信息的方法处理。
以下代码是摘自iproute2-4.0源码
int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n,
                   void *arg)
{
        FILE *fp = arg;
        struct ifaddrmsg *ifa = NLMSG_DATA(n);
        int len = n->nlmsg_len;
        int deprecated = 0;
        /* Use local copy of ifa_flags to not interfere with filtering code */
        unsigned int ifa_flags;
        struct rtattr * rta_tb[IFA_MAX+1];
        char abuf[256];
        SPRINT_BUF(b1);

        if (n->nlmsg_type != RTM_NEWADDR && n->nlmsg_type != RTM_DELADDR)        // 判断netlink消息类型
                return 0;
        len -= NLMSG_LENGTH(sizeof(*ifa));
        if (len < 0) {
                fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
                return -1;
        }

        if (filter.flushb && n->nlmsg_type != RTM_NEWADDR)
                return 0;

        parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(ifa),                                //解析消息属性
                     n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)));

        ifa_flags = get_ifa_flags(ifa, rta_tb[IFA_FLAGS]);

        if (!rta_tb[IFA_LOCAL])
                rta_tb[IFA_LOCAL] = rta_tb[IFA_ADDRESS];
        if (!rta_tb[IFA_ADDRESS])
                rta_tb[IFA_ADDRESS] = rta_tb[IFA_LOCAL];
//         针对过滤条件进行筛选
        if (filter.ifindex && filter.ifindex != ifa->ifa_index)
                return 0;
        if ((filter.scope^ifa->ifa_scope)&filter.scopemask)
                return 0;
        if ((filter.flags ^ ifa_flags) & filter.flagmask)
                return 0;
        if (filter.label) {
                SPRINT_BUF(b1);
                const char *label;
                if (rta_tb[IFA_LABEL])
                        label = RTA_DATA(rta_tb[IFA_LABEL]);
                else
                        label = ll_idx_n2a(ifa->ifa_index, b1);
                if (fnmatch(filter.label, label, 0) != 0)
                        return 0;
        }
        if (filter.pfx.family) {
                if (rta_tb[IFA_LOCAL]) {
                        inet_prefix dst;
                        memset(&dst, 0, sizeof(dst));
                        dst.family = ifa->ifa_family;
                        memcpy(&dst.data, RTA_DATA(rta_tb[IFA_LOCAL]), RTA_PAYLOAD(rta_tb[IFA_LOCAL]));
                        if (inet_addr_match(&dst, &filter.pfx, filter.pfx.bitlen))
                                return 0;
                }
        }

        if (filter.family && filter.family != ifa->ifa_family)
                return 0;

        if (filter.flushb) {
                struct nlmsghdr *fn;
                if (NLMSG_ALIGN(filter.flushp) + n->nlmsg_len > filter.flushe) {
                        if (flush_update())
                                return -1;
                }
                fn = (struct nlmsghdr*)(filter.flushb + NLMSG_ALIGN(filter.flushp));
                memcpy(fn, n, n->nlmsg_len);
                fn->nlmsg_type = RTM_DELADDR;
                fn->nlmsg_flags = NLM_F_REQUEST;
                fn->nlmsg_seq = ++rth.seq;
                filter.flushp = (((char*)fn) + n->nlmsg_len) - filter.flushb;
                filter.flushed++;
                if (show_stats < 2)
                        return 0;
        }

        if (n->nlmsg_type == RTM_DELADDR)
                fprintf(fp, "Deleted ");

        if (filter.oneline || filter.flushb)
                fprintf(fp, "%u: %s", ifa->ifa_index, ll_index_to_name(ifa->ifa_index));
        if (ifa->ifa_family == AF_INET)
                fprintf(fp, "    inet ");
        else if (ifa->ifa_family == AF_INET6)
                fprintf(fp, "    inet6 ");
        else if (ifa->ifa_family == AF_DECnet)
                fprintf(fp, "    dnet ");
        else if (ifa->ifa_family == AF_IPX)
                fprintf(fp, "     ipx ");
        else
                fprintf(fp, "    family %d ", ifa->ifa_family);

        if (rta_tb[IFA_LOCAL]) {                                                                //获取本地IP地址信息
                fprintf(fp, "%s", format_host(ifa->ifa_family,
                                              RTA_PAYLOAD(rta_tb[IFA_LOCAL]),
                                              RTA_DATA(rta_tb[IFA_LOCAL]),
                                              abuf, sizeof(abuf)));

                if (rta_tb[IFA_ADDRESS] == NULL ||
                    memcmp(RTA_DATA(rta_tb[IFA_ADDRESS]), RTA_DATA(rta_tb[IFA_LOCAL]),
                           ifa->ifa_family == AF_INET ? 4 : 16) == 0) {
                        fprintf(fp, "/%d ", ifa->ifa_prefixlen);                                //获取本地IP地址的子网掩码长度
                } else {
                        fprintf(fp, " peer %s/%d ",                                                //点对点类型的peer端IP地址及子网掩码长度
                                format_host(ifa->ifa_family,
                                            RTA_PAYLOAD(rta_tb[IFA_ADDRESS]),
                                            RTA_DATA(rta_tb[IFA_ADDRESS]),
                                            abuf, sizeof(abuf)),
                                ifa->ifa_prefixlen);
                }
        }

        if (rta_tb[IFA_BROADCAST]) {                               
                fprintf(fp, "brd %s ",
                        format_host(ifa->ifa_family,
                                    RTA_PAYLOAD(rta_tb[IFA_BROADCAST]),
                                    RTA_DATA(rta_tb[IFA_BROADCAST]),
                                    abuf, sizeof(abuf)));
        }
        if (rta_tb[IFA_ANYCAST]) {
                fprintf(fp, "any %s ",
                        format_host(ifa->ifa_family,
                                    RTA_PAYLOAD(rta_tb[IFA_ANYCAST]),
                                    RTA_DATA(rta_tb[IFA_ANYCAST]),
                                    abuf, sizeof(abuf)));
        }
        fprintf(fp, "scope %s ", rtnl_rtscope_n2a(ifa->ifa_scope, b1, sizeof(b1)));
        if (ifa_flags & IFA_F_SECONDARY) {
                ifa_flags &= ~IFA_F_SECONDARY;
                if (ifa->ifa_family == AF_INET6)
                        fprintf(fp, "temporary ");
                else
                        fprintf(fp, "secondary ");
        }
        if (ifa_flags & IFA_F_TENTATIVE) {
                ifa_flags &= ~IFA_F_TENTATIVE;
                fprintf(fp, "tentative ");
        }
        if (ifa_flags & IFA_F_DEPRECATED) {
                ifa_flags &= ~IFA_F_DEPRECATED;
                deprecated = 1;
                fprintf(fp, "deprecated ");
        }
        if (ifa_flags & IFA_F_HOMEADDRESS) {
                ifa_flags &= ~IFA_F_HOMEADDRESS;
                fprintf(fp, "home ");
        }
        if (ifa_flags & IFA_F_NODAD) {
                ifa_flags &= ~IFA_F_NODAD;
                fprintf(fp, "nodad ");
        }
        if (ifa_flags & IFA_F_MANAGETEMPADDR) {
                ifa_flags &= ~IFA_F_MANAGETEMPADDR;
                fprintf(fp, "mngtmpaddr ");
        }
        if (ifa_flags & IFA_F_NOPREFIXROUTE) {
                ifa_flags &= ~IFA_F_NOPREFIXROUTE;
                fprintf(fp, "noprefixroute ");
        }
        if (!(ifa_flags & IFA_F_PERMANENT)) {
                fprintf(fp, "dynamic ");
        } else
                ifa_flags &= ~IFA_F_PERMANENT;
        if (ifa_flags & IFA_F_DADFAILED) {
                ifa_flags &= ~IFA_F_DADFAILED;
                fprintf(fp, "dadfailed ");
        }
        if (ifa_flags)
                fprintf(fp, "flags %02x ", ifa_flags);
        if (rta_tb[IFA_LABEL])                                                //名字,在ip aliases时代,它是ethx:y的形式,在secondary ip时代,它统一就是ethx
                fprintf(fp, "%s", rta_getattr_str(rta_tb[IFA_LABEL]));
        if (rta_tb[IFA_CACHEINFO]) {
                struct ifa_cacheinfo *ci = RTA_DATA(rta_tb[IFA_CACHEINFO]);
                fprintf(fp, "%s", _SL_);
                fprintf(fp, "       valid_lft ");
                if (ci->ifa_valid == INFINITY_LIFE_TIME)
                        fprintf(fp, "forever");
                else
                        fprintf(fp, "%usec", ci->ifa_valid);
                fprintf(fp, " preferred_lft ");
                if (ci->ifa_prefered == INFINITY_LIFE_TIME)
                        fprintf(fp, "forever");
                else {
                        if (deprecated)
                                fprintf(fp, "%dsec", ci->ifa_prefered);
                        else
                                fprintf(fp, "%usec", ci->ifa_prefered);
                }
        }
        fprintf(fp, "\n");
        fflush(fp);
        return 0;
}

评分

参与人数 1可用积分 +6 收起 理由
Godbach + 6 很给力!

查看全部评分

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
3 [报告]
发表于 2015-08-17 09:58 |只看该作者
回复 2# xlhl3
感谢分享!


   
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP