On Thu, Jun 28, 2012 at 09:55:57AM +0100, Stuart Henderson wrote: [...] > # route add -inet6 ff55::1/96 ::1 > add net ff55::1/96: gateway ::1 > > # route delete -inet6 ff55::1/96 > route: writing to routing socket: No such process > delete net ff55::1/96: not in table > > # route delete -inet6 ff55::/96 > delete net ff55::/96 > > I think the address should be masked in the same way for both v4 and v6. >
$ sudo ./route add -inet6 ff55::1/96 ::1 add net ff55::1/96: gateway ::1 $ sudo ./route delete -inet6 ff55::1/96 delete net ff55::1/96 However, this remains broken (it's broken for v4 as well): $ sudo ./route add -inet6 ff55::1 -prefixlen 96 ::1 add net ff55::1: gateway ::1 $ sudo ./route delete -inet6 ff55::1 -prefixlen 96 route: writing to routing socket: No such process delete net ff55::1: not in table Index: sbin/route/route.8 =================================================================== RCS file: /opt/OpenBSD-CVS/src/sbin/route/route.8,v retrieving revision 1.69 diff -u -r1.69 route.8 --- sbin/route/route.8 3 Sep 2011 22:59:08 -0000 1.69 +++ sbin/route/route.8 28 Jun 2012 21:36:58 -0000 @@ -240,6 +240,13 @@ is the number of bits in the network portion of the address and is less than 32) .It +it is an IPv6 address with a +.Dq / Ns Em XX +suffix (where +.Em XX +is the number of bits in the network portion of the address +and is less than 128) +.It it is the symbolic name of a network. .El .Pp Index: sbin/route/route.c =================================================================== RCS file: /opt/OpenBSD-CVS/src/sbin/route/route.c,v retrieving revision 1.156 diff -u -r1.156 route.c --- sbin/route/route.c 17 Mar 2012 10:16:40 -0000 1.156 +++ sbin/route/route.c 28 Jun 2012 21:36:58 -0000 @@ -93,7 +93,7 @@ void pmsg_addrs(char *, int); void bprintf(FILE *, int, char *); void mask_addr(union sockunion *, union sockunion *, int); -int inet6_makenetandmask(struct sockaddr_in6 *); +int inet6_makenetandmask(struct sockaddr_in6 *, char *); int getaddr(int, char *, struct hostent **); void getmplslabel(char *, int); int rtmsg(int, int, int, u_char); @@ -737,19 +737,23 @@ * XXX the function may need more improvement... */ int -inet6_makenetandmask(struct sockaddr_in6 *sin6) +inet6_makenetandmask(struct sockaddr_in6 *sin6, char *plen) { - char *plen = NULL; struct in6_addr in6; + const char *errstr; + int i, len, q, r; - if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) && - sin6->sin6_scope_id == 0) { - plen = "0"; - } else if ((sin6->sin6_addr.s6_addr[0] & 0xe0) == 0x20) { - /* aggregatable global unicast - RFC2374 */ - memset(&in6, 0, sizeof(in6)); - if (!memcmp(&sin6->sin6_addr.s6_addr[8], &in6.s6_addr[8], 8)) - plen = "64"; + if (NULL==plen) { + if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) && + sin6->sin6_scope_id == 0) { + plen = "0"; + } else if ((sin6->sin6_addr.s6_addr[0] & 0xe0) == 0x20) { + /* aggregatable global unicast - RFC2374 */ + memset(&in6, 0, sizeof(in6)); + if (!memcmp(&sin6->sin6_addr.s6_addr[8], + &in6.s6_addr[8], 8)) + plen = "64"; + } } if (!plen || strcmp(plen, "128") == 0) @@ -757,6 +761,20 @@ else { rtm_addrs |= RTA_NETMASK; prefixlen(plen); + + len = strtonum(plen, 0, 128, &errstr); + if (errstr) + errx(1, "prefixlen %s is %s", s, errstr); + + q = (128-len) >> 3; + r = (128-len) & 7; + i = 15; + + while (q-- > 0) + sin6->sin6_addr.s6_addr[i--] = 0; + if (r > 0) + sin6->sin6_addr.s6_addr[i] &= 0xff << r; + return (0); } } @@ -824,14 +842,25 @@ case AF_INET6: { struct addrinfo hints, *res; + char buf[ + sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255:255:255:255/128") + ]; + char *sep; + + if (strlcpy(buf, s, sizeof buf) >= sizeof buf) { + errx(1, "%s: bad value", s); + } + sep = strchr(buf, '/'); + if (sep != NULL) + *sep++ = '\0'; memset(&hints, 0, sizeof(hints)); hints.ai_family = afamily; /*AF_INET6*/ hints.ai_flags = AI_NUMERICHOST; hints.ai_socktype = SOCK_DGRAM; /*dummy*/ - if (getaddrinfo(s, "0", &hints, &res) != 0) { + if (getaddrinfo(buf, "0", &hints, &res) != 0) { hints.ai_flags = 0; - if (getaddrinfo(s, "0", &hints, &res) != 0) + if (getaddrinfo(buf, "0", &hints, &res) != 0) errx(1, "%s: bad value", s); } if (sizeof(su->sin6) != res->ai_addrlen) @@ -850,7 +879,7 @@ } if (hints.ai_flags == AI_NUMERICHOST) { if (which == RTA_DST) - return (inet6_makenetandmask(&su->sin6)); + return (inet6_makenetandmask(&su->sin6, sep)); return (0); } else return (1);