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);