使用netlink的ipv6本地地址
Posted
技术标签:
【中文标题】使用netlink的ipv6本地地址【英文标题】:ipv6 local address using netlink 【发布时间】:2016-09-22 13:39:57 【问题描述】:我使用 netlink 编写 C 代码来获取有关 ip 路由表的信息并检测给定接口的新 ip 地址。 使用 IPv4,我可以使用“IFA_LOCAL”过滤本地地址。 但是使用 IPv6,我无法获得本地地址。即使对于本地地址,rta_type 也永远不会等于 'IFA_LOCAL'。
使用的代码如下:
int main(void)
struct
struct nlmsghdr hdr;
struct ifaddrmsg msg;
req;
struct sockaddr_nl addr;
int sock[2];
memset(&addr, 0, sizeof(addr));
memset(&req, 0, sizeof(req));
if ((sock[0] = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1)
CWMP_LOG(ERROR,"couldn't open NETLINK_ROUTE socket");
return -1;
addr.nl_family = AF_NETLINK;
addr.nl_groups = RTMGRP_IPV6_IFADDR;// |RTMGRP_IPV6_IFADDR;
if ((bind(sock[0], (struct sockaddr_in6 *)&addr, sizeof(addr))) == -1)
CWMP_LOG(ERROR,"couldn't bind netlink socket");
return -1;
netlink_event.fd = sock[0];
if ((sock[1] = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) == -1)
CWMP_LOG(ERROR,"couldn't open NETLINK_ROUTE socket");
return -1;
req.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
req.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT;
req.hdr.nlmsg_type = RTM_GETADDR;
req.msg.ifa_family = AF_INET6;
if ((send(sock[1], &req, req.hdr.nlmsg_len, 0)) == -1)
CWMP_LOG(ERROR,"couldn't send netlink socket");
return -1;
struct nlmsghdr *nlh;
char buffer[BUFSIZ];
int msg_size;
memset(&buffer, 0, sizeof(buffer));
nlh = (struct nlmsghdr *)buffer;
if ((msg_size = recv(sock[1], nlh, BUFSIZ, 0)) == -1)
CWMP_LOG(ERROR,"error receiving netlink message");
return;
while (msg_size > sizeof(*nlh))
int len = nlh->nlmsg_len;
int req_len = len - sizeof(*nlh);
if (req_len < 0 || len > msg_size)
CWMP_LOG(ERROR,"error reading netlink message");
return;
if (!NLMSG_OK(nlh, msg_size))
CWMP_LOG(ERROR,"netlink message is not NLMSG_OK");
return;
if (nlh->nlmsg_type == RTM_NEWADDR)
printf("new addr \n");
struct ifaddrmsg *ifa = (struct ifaddrmsg *) NLMSG_DATA(nlh);
struct rtattr *rth = IFA_RTA(ifa);
int rtl = IFA_PAYLOAD(nlh);
char if_name[IFNAMSIZ], if_addr[INET6_ADDRSTRLEN];
char *c;
struct in6_addr *in6p;
memset(&if_name, 0, sizeof(if_name));
memset(&if_addr, 0, sizeof(if_addr));
while (rtl && RTA_OK(rth, rtl))
printf("rth->rta_type %d \n", rth->rta_type);
in6p = (struct in6_addr *)RTA_DATA(rth);
printf("addr1: " NIP6_FMT "\n",NIP6(*in6p));
if (rth->rta_type != IFA_LOCAL)
printf("########NOT IFA_LOCAL ############\n");
rth = RTA_NEXT(rth, rtl);
continue;
printf("======IFA_LOCAL======\n");
rth = RTA_NEXT(rth, rtl);
msg_size -= NLMSG_ALIGN(len);
nlh = (struct nlmsghdr*)((char*)nlh + NLMSG_ALIGN(len));
return 0;
并且执行的痕迹如下: rth->rta_type 6 地址1:0000:0e0e:0000:1c1e:0031:15c7:0031:15c7
##NOT IFA_LOCAL新地址 rth->rta_type 1 addr1: fd59:ca3e:bd63:0000:0222:07ff:fe41:b9d6
##NOT IFA_LOCALrth->rta_type 6 addr1: 0000:068c:0000:1ba4:0030:e60b:0030:e60b
##NOT IFA_LOCAL新地址 rth->rta_type 1 addr1: 2001:1338:000a:0000:0000:0000:0000:0196
##NOT IFA_LOCALrth->rta_type 6 addr1: ffff:ffff:ffff:ffff:0005:a828:0005:a828
##NOT IFA_LOCAL新地址 rth->rta_type 1 地址1:fe80:0000:0000:0000:0222:07ff:fe41:b9d6
##NOT IFA_LOCALrth->rta_type 6 addr1: ffff:ffff:ffff:ffff:0005:a826:0005:a826
##NOT IFA_LOCAL新地址 rth->rta_type 1 地址1:fe80:0000:0000:0000:0222:07ff:fe41:b9d7
##NOT IFA_LOCAL【问题讨论】:
如果您正在寻找链接本地地址,只需用/10
屏蔽地址,然后将其与fe80::/10
进行比较。如果匹配,则它是一个链接本地地址。
这不是我真正想要的。
你在找什么?
如果我给你看一下ipv4结果可能会更清楚:
好的,但也许你可以定义 IFA_LOCAL 的含义。
【参考方案1】:
尝试查找“IFA_ADDRESS”。对于广播接口,IFA_LOCAL 和 IFA_ADDRESS 含义相同。这是来自内核 if_addr.h 的代码 sn-p。
/*
* Important comment:
* IFA_ADDRESS is prefix address, rather than local interface address.
* It makes no difference for normally configured broadcast interfaces,
* but for point-to-point IFA_ADDRESS is DESTINATION address,
* local address is supplied in IFA_LOCAL attribute.
*/
enum
IFA_UNSPEC,
IFA_ADDRESS,
IFA_LOCAL,
IFA_LABEL,
IFA_BROADCAST,
IFA_ANYCAST,
IFA_CACHEINFO,
IFA_MULTICAST,
__IFA_MAX,
;
对于 inet6 RTM_GETADDR 请求,内核以 IFA_ADDRESS (addrconf.c:inet6_fill_ifaddr()) 响应:-
nla_put(skb, IFA_ADDRESS, 16, &ifa->addr)
【讨论】:
以上是关于使用netlink的ipv6本地地址的主要内容,如果未能解决你的问题,请参考以下文章