iplib: Allow v4parsecidr() to take longer masks
authorBarret Rhoden <brho@cs.berkeley.edu>
Thu, 22 Dec 2016 17:03:24 +0000 (12:03 -0500)
committerBarret Rhoden <brho@cs.berkeley.edu>
Tue, 10 Jan 2017 00:01:40 +0000 (19:01 -0500)
v4parsecidr() takes a string of the form IP/MASK, and converts it to a v4
address and v4mask.  If you gave it a /mask string that you got from %M,
you'd have something like /122 for a v4 /26 (6 bits unmasked).  v4parsecidr
would take the first 32 bits (all 1s) and make a mask from that.  We want
the last 32 bits (including the 0s).

It's quite possible for the user to give us a mask that doesn't make sense
for V4 (like /44).  In that case, they can just do their own thing.  This
will work for sane v4 masks, even if they are in v6 form.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
user/iplib/parseip.c

index 9a2905f..973cd0d 100644 (file)
@@ -195,8 +195,10 @@ char *v4parsecidr(uint8_t *addr, uint8_t *mask, char *from)
        if (*p == '/') {
                /* as a number of prefix bits */
                i = strtoul(p + 1, &p, 0);
-               if (i > 32)
-                       i = 32;
+               /* We might have been passed a v6 mask - the signal for that will be
+                * having more than 32 bits. */
+               if (i >= 32)
+                       i -= 128 - 32;
                memset(mask, 0, IPv4addrlen);
                for (a = mask; i >= 8; i -= 8)
                        *a++ = 0xff;