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

Reply via email to