- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我的路由表中有以下条目:
tecik:ihsan $ netstat -rn -f inet6 | grep 2400:3700:61:4::/64
2400:3700:61:4::/64 2400:3700:60:4::2 UG gif104
我通过路由套接字发出了一个 RTM_GET 请求,我设法正确获取了 RTA_DST 信息,但 RTA_NETMASK 总是返回 0,尽管路由表显示它是/64。
如何获取正确的网络掩码条目。
代码:
/* fill in request header */
pid = getpid();
buf = calloc(0, sizeof(char) * buflen);
rtm = (struct rt_msghdr *) buf;
rtm->rtm_version = RTM_VERSION;
rtm->rtm_flags = RTF_UP | RTF_GATEWAY;
rtm->rtm_addrs = RTA_DST | RTA_NETMASK;
rtm->rtm_type = RTM_GET;
rtm->rtm_pid = pid;
rtm->rtm_seq = seq;
/* take the dst AFI and assume the rest are of the same AFI */
if (dst->sa_family == AF_INET6) {
sin6 = (struct sockaddr_in6 *) (rtm + 1);
memcpy(sin6, dst, sizeof(struct sockaddr_in6));
sin6 = (struct sockaddr_in6 *) ((char *) sin6 + alignsa(sizeof(struct sockaddr_in6)));
memcpy(sin6, mask, sizeof(struct sockaddr_in6));
sin6 = (struct sockaddr_in6 *) ((char *) sin6 + alignsa(sizeof(struct sockaddr_in6)));
rtm->rtm_msglen = (char *) sin6 - buf;
}
/* write to routing socket */
write(s, rtm, rtm->rtm_msglen);
/* now read the reply */
do {
n = read(s, rtm, buflen);
} while (rtm->rtm_type != RTM_GET || rtm->rtm_seq != seq || rtm->rtm_pid != pid);
close(s);
/* cycle through all routing replies, checking for expected sockaddr */
rtm = (struct rt_msghdr *) buf;
sin6 = (struct sockaddr_in6 *) (rtm + 1);
for (rtax = 0; rtax < RTAX_MAX; rtax++) {
if (rtm->rtm_addrs & (1 << rtax)) {
sa = (struct sockaddr *) sin6;
if (rtax == RTAX_DST) {
al->rt = malloc(sizeof(char) * MAX_ADDRSTR);
getaddrstr(al->rt, sa);
}
else if (rtax == RTAX_NETMASK) {
sa->sa_family = AF_INET6;
al->rtplen = getcidr(sa);
}
sin6 = (struct sockaddr_in6 *) (char *) sin6 + alignsa(sizeof(struct sockaddr_in6));
}
}
if (al->rtplen == 0)
def = 1;
if (def)
debug("%s has default route, ignoring..", al->ifname);
else
debug("%s has route %s/%u", al->ifname, al->rt, al->rtplen);
free(buf);
alignsa() 是:
size_t
alignsa(size_t s)
{
return (1 + (((s) - 1) | (sizeof(size_t) - 1)));
}
getcidr() 是
/* all zeros netmask */
if (sa->sa_len == 0)
return(plen);
switch (sa->sa_family) {
case AF_INET:
break;
case AF_INET6:
s = (uint8_t *) &((struct sockaddr_in6 *)sa)->sin6_addr;
if (*s == 0)
break;
for (i = 0; ((i < 16) && (*s == 0xff)); i++, s++)
plen += 8;
break;
default:
return(-1);
}
return(plen);
如果我打印出 al->rt 的值,它会显示为 2400:3700:61:4::但 rtplen 始终为 0。
如果我打印出网络掩码的 sockaddr_in6,它的结果完全是 ffff:ffff:ffff:ffff::或/64,所以我认为对于 RTA_NETMASK,sin6_len 是 0,但我不明白为什么。
最佳答案
编辑:这个答案是错误的,因为它只适用于 netlink RTM_GETROUTE。该操作询问路由套接字。
我假设您指的是 RTM_GETROUTE,即使您的主题说的是 RTM_GET。 RTM_GETROUTE 不返回由 netstat -6 -rn 显示的相同信息。该命令可以返回缓存的路由。也许更令人惊讶的是,RTM_GETROUTE 可以在路由缓存中创建路由。
这是来自 iproute2 文档(在我的 Ubuntu 上,它在 man 8 ip-route 中列出):
Note that this operation is not equivalent to ip route show. show
shows existing routes. get resolves them and creates new clones if
necessary. Essentially, get is equivalent to sending a packet along
this path. If the iif argument is not given, the kernel creates a
route to output packets towards the requested destination. This is
equivalent to pinging the destination with a subsequent ip route ls
cache, however, no packets are actually sent. With the iif argument,
the kernel pretends that a packet arrived from this interface and
searches for a path to forward the packet.
在您的情况下,您可以比较 ip -6 route show table all 和 ip -6 route get 2400:3700:60:4::123 的输出.它们可能会略有不同,ip route get 版本的末尾包含单词 cached。
我目前所在的位置没有 IPv6 连接,但这条本地路由说明了我的意思:
thuovila@glx:~$ ip -6 r l table all |grep ff00::/8
ff00::/8 dev eth1 table local metric 256
thuovila@glx:~$ ip r get ff00::/8
ff00:: from :: via ff00:: dev eth1 src fe80::21b:b1ff:fe48:1a75 metric 0 cache
如您所见,缓存的路由不包含目标地址长度(网络掩码)。
为了解决您的问题,(如何获取网络掩码)我建议研究过滤网络链接消息。而不是单个 RTM_GET 请求,您将不得不转储符合您的条件的路由并过滤克隆路由。 iproute2 工具在例如iproute.c具有函数 static int filter_nlmsg
的模块。其中,它包含一行 if (filter.cloned == !(r->rtm_flags&RTM_F_CLONED))
删除克隆(即源自缓存)路由。它由 route_print()
调用以限制显示的路线。在 ip route list 命令中,通过调用 libnetlink 函数 rtnl_dump_filter()
转储路由。
有关如何使用 netlink 的更多提示,请检查 iproute2 的源代码,尤其是 ip/iproute.c 和 lib/libnetlink.c 模块。
关于c - 路由套接字 RTM_GET RTA_NETMASK 与路由表条目不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15126757/
我的路由表中有以下条目: tecik:ihsan $ netstat -rn -f inet6 | grep 2400:3700:61:4::/64 2400:3700:61:4::/64
我是一名优秀的程序员,十分优秀!