Hi, <rant> so route(8) drives me crazy. For some reason I always put -prefixlen before the address when adding IPv6 routes and route(8) happily accepts that:
$ sudo route add -inet6 -prefixlen 32 2001:db8:: ::1 -blackhole add net 2001:db8::: gateway ::1 $ route -n show -inet6 | fgrep 2001:db8 2001:db8::/64 ::1 UGBS 0 0 - 8 lo0 Where is my /32 blackhole route?! Even this is valid syntax: $ sudo route add -inet -prefixlen 24 10.10.10.0/23 -prefixlen 22 \ 127.0.0.1 -blackhole add net 10.10.10.0/23: gateway 127.0.0.1 $ route -n show -inet | fgrep 10.10 10.10.8/22 127.0.0.1 UGBS 0 0 33196 8 lo0 Here it tells me it added a /23 route when in fact it added a /22 route. argharghargh! One can argue that this is (subtly) documented in the man page. Looking at the option / argument parser in int newroute(int argc, char **argv) I decided that I'm not capable of fixing this and went for the low hanging fruit. </rant> With the following patch this is valid syntax: $ sudo route add -inet6 2001:db8::/32 ::1 -blackhole add net 2001:db8::/32: gateway ::1 $ route -n get -inet6 2001:db8::/32 route to: 2001:db8:: destination: 2001:db8:: mask: ffff:ffff:: gateway: ::1 interface: lo0 if address: ::1 priority: 8 (static) flags: <UP,GATEWAY,DONE,STATIC,BLACKHOLE> use mtu expire 0 0 0 $ sudo route delete -inet6 2001:db8::/32 delete net 2001:db8::/32 I kept the inet6_makenetandmask() call but in my understanding of the code it's not necessary in the else block. Is it correct to remove that call? + else { + inet6_makenetandmask(&su->sin6); + return prefixlen(sep); + } Btw. the strlcpy / strchr dance is from inet_net_pton which I'm not calling because it can't handle scoped addresses according to inet(3). Thanks, Florian 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 27 Jun 2012 22:19:50 -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 27 Jun 2012 22:10:52 -0000 @@ -824,14 +824,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 +861,12 @@ } if (hints.ai_flags == AI_NUMERICHOST) { if (which == RTA_DST) - return (inet6_makenetandmask(&su->sin6)); + if (sep == NULL) + return (inet6_makenetandmask(&su->sin6)); + else { + inet6_makenetandmask(&su->sin6); + return prefixlen(sep); + } return (0); } else return (1);