我的路由表上有以下条目:
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,但我不明白为什么。