shithub: front

Download patch

ref: 1a919327313d87ca7797928b3cbad80cb40d5167
parent: 248634879a9b78f08ddaeda9c7a50ba413fd4804
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Mon Dec 23 11:12:35 EST 2024

ip/dhcpd: impvoe validip(), make validipmask() reject ipv6 masks

Because isv4() is never true for IPnoaddr,
we can skip the check.

Make validipmask() ensure that the top IPv4off
bytes are all 0xff, then check that the low
4 bytes are a valid mask (must be a power
of two minus one).

--- a/sys/src/cmd/ip/dhcpd/dat.h
+++ b/sys/src/cmd/ip/dhcpd/dat.h
@@ -49,8 +49,6 @@
 
 
 /* from dhcp.c */
-extern int	validip(uchar*);
-extern int	validipmask(uchar*);
 extern void	fatal(char*, ...);
 extern void	warning(char*, ...);
 #pragma	varargck argpos	fatal 1
@@ -58,6 +56,8 @@
 extern int	minlease;
 
 /* from db.c */
+extern int	validip(uchar*);
+extern int	validipmask(uchar*);
 extern char*	toid(uchar*, int);
 extern void	initbinding(uchar*, int);
 extern Binding*	iptobinding(uchar*, int);
--- a/sys/src/cmd/ip/dhcpd/db.c
+++ b/sys/src/cmd/ip/dhcpd/db.c
@@ -412,3 +412,22 @@
 	close(fd);
 	return 0;
 }
+
+int
+validip(uchar *ip)
+{
+	if(ipcmp(ip, v4prefix) == 0)
+		return 0;
+	return isv4(ip);
+}
+
+int
+validipmask(uchar *mask)
+{
+	unsigned x;
+
+	if(memcmp(mask, IPallbits, IPv4off) != 0)
+		return 0;
+	x = ~(mask[IPv4off+0] << 24 | mask[IPv4off+1] << 16 | mask[IPv4off+2] << 8 | mask[IPv4off+3]);
+	return ((x + 1U) & x) == 0;
+}
--- a/sys/src/cmd/ip/dhcpd/dhcpd.c
+++ b/sys/src/cmd/ip/dhcpd/dhcpd.c
@@ -191,7 +191,6 @@
 void	sendoffer(Req*, uchar*, int);
 void	stringopt(Req*, int, char*);
 void	termopt(Req*);
-int	validip(uchar*);
 void	vectoropt(Req*, int, uchar*, int);
 
 void
@@ -1387,26 +1386,6 @@
 	if(p == nil || *p == 0)
 		return "unknown";
 	return p;
-}
-
-extern int
-validip(uchar *ip)
-{
-	if(ipcmp(ip, IPnoaddr) == 0)
-		return 0;
-	if(ipcmp(ip, v4prefix) == 0)
-		return 0;
-	return isv4(ip);
-}
-
-extern int
-validipmask(uchar *ip)
-{
-	if(ipcmp(ip, IPnoaddr) == 0)
-		return 0;
-	if(ipcmp(ip, v4prefix) == 0)
-		return 0;
-	return 1;
 }
 
 void
--- a/sys/src/cmd/ip/dhcpd/dhcpleases.c
+++ b/sys/src/cmd/ip/dhcpd/dhcpleases.c
@@ -35,7 +35,9 @@
 	b.lease = b.offer = 0;
 	now = time(0);
 	for(i = 0; i < nall; i++){
-		if(parseip(b.ip, all[i].name) == -1 || syncbinding(&b, 0) < 0)
+		if(parseip(b.ip, all[i].name) == -1
+		|| !validip(b.ip)
+		|| syncbinding(&b, 0) < 0)
 			continue;
 		if(b.lease > now)
 			print("%I leased by %s until %s", b.ip, b.boundto,
--- a/sys/src/cmd/ip/dhcpd/ndb.c
+++ b/sys/src/cmd/ip/dhcpd/ndb.c
@@ -57,19 +57,19 @@
 }
 
 static void
-setipaddr(uchar *addr, char *ip)
+setipaddr(uchar *ip, char *s)
 {
-	if(ipcmp(addr, IPnoaddr) == 0)
-		if(parseip(addr, ip) == -1
-		|| !validip(addr))
-			ipmove(addr, IPnoaddr);	/* invalid */
+	if(ipcmp(ip, IPnoaddr) == 0)
+		if(parseip(ip, s) == -1
+		|| !validip(ip))
+			ipmove(ip, IPnoaddr);	/* invalid */
 }
 
 static void
-setipmask(uchar *mask, char *ip)
+setipmask(uchar *mask, char *s)
 {
 	if(ipcmp(mask, IPnoaddr) == 0)
-		if(parseipmask(mask, ip, 1) == -1
+		if(parseipmask(mask, s, 1) == -1
 		|| !validipmask(mask))
 			ipmove(mask, IPnoaddr);	/* invalid */
 }
--