summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorclaudio <claudio@openbsd.org>2018-11-20 10:28:08 +0000
committerclaudio <claudio@openbsd.org>2018-11-20 10:28:08 +0000
commit2a5d130b45efb7f17f9817216ed88df96341bd9d (patch)
tree46231630e601c28336844218bfed669d395d445a /sys
parentThe first packet received from each AP in each QoS class would be (diff)
downloadwireguard-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.c31
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);
}