diff options
author | 2018-11-20 10:28:08 +0000 | |
---|---|---|
committer | 2018-11-20 10:28:08 +0000 | |
commit | 2a5d130b45efb7f17f9817216ed88df96341bd9d (patch) | |
tree | 46231630e601c28336844218bfed669d395d445a /sys | |
parent | The first packet received from each AP in each QoS class would be (diff) | |
download | wireguard-openbsd-2a5d130b45efb7f17f9817216ed88df96341bd9d.tar.xz wireguard-openbsd-2a5d130b45efb7f17f9817216ed88df96341bd9d.zip |
Make rtable_satoplen() a bit more strict when parsing netmasks. Ensure
that the mask is contiguous and not longer then the prefixlen is not
bigger then the maximum. Make the function behave a bit more like the
similar netmask handling code in the old patricia codebase.
Fixes a problem reyk@ reported regarding IPv6 masks and the fact that
sin6_scope_id is after sin6_addr.
OK mpi@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/net/rtable.c | 31 |
1 files changed, 12 insertions, 19 deletions
diff --git a/sys/net/rtable.c b/sys/net/rtable.c index d16fed8f7eb..647ad7f7646 100644 --- a/sys/net/rtable.c +++ b/sys/net/rtable.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtable.c,v 1.65 2018/11/19 10:15:04 claudio Exp $ */ +/* $OpenBSD: rtable.c,v 1.66 2018/11/20 10:28:08 claudio Exp $ */ /* * Copyright (c) 2014-2016 Martin Pieuchot @@ -614,6 +614,8 @@ rtable_delete(unsigned int rtableid, struct sockaddr *dst, addr = satoaddr(ar, dst); plen = rtable_satoplen(dst->sa_family, mask); + if (plen == -1) + return (EINVAL); rtref(rt); /* guarantee rtfree won't do anything under ar_lock */ rw_enter_write(&ar->ar_lock); @@ -744,6 +746,8 @@ rtable_mpath_reprio(unsigned int rtableid, struct sockaddr *dst, addr = satoaddr(ar, dst); plen = rtable_satoplen(dst->sa_family, mask); + if (plen == -1) + return (EINVAL); rw_enter_write(&ar->ar_lock); an = art_lookup(ar, addr, plen, &sr); @@ -884,60 +888,49 @@ rtable_satoplen(sa_family_t af, struct sockaddr *mask) if (ap > ep) return (-1); + /* Trim trailing zeroes. */ + while (ep[-1] == 0 && ap < ep) + ep--; + if (ap == ep) return (0); /* "Beauty" adapted from sbin/route/show.c ... */ while (ap < ep) { - switch (*ap) { + switch (*ap++) { case 0xff: plen += 8; - ap++; break; case 0xfe: plen += 7; - ap++; goto out; case 0xfc: plen += 6; - ap++; goto out; case 0xf8: plen += 5; - ap++; goto out; case 0xf0: plen += 4; - ap++; goto out; case 0xe0: plen += 3; - ap++; goto out; case 0xc0: plen += 2; - ap++; goto out; case 0x80: plen += 1; - ap++; - goto out; - case 0x00: goto out; default: /* Non contiguous mask. */ return (-1); } - } out: -#ifdef DIAGNOSTIC - for (; ap < ep; ap++) { - if (*ap != 0x00) - return (-1); - } -#endif /* DIAGNOSTIC */ + if (plen > dp->dom_maxplen || ap != ep) + return -1; return (plen); } |