ルーティングテーブルに次のエントリがあります。
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情報を正しく取得できましたが、ルーティングテーブルに/ 64と表示されていても、RTA_NETMASKは常に0を返します。
正しいネットマスクエントリを取得するにはどうすればよいですか。
コード:
/* 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ですが、理由がわかりません。