git: 9front

Download patch

ref: 98e7f36f706c21d015af5001a643c0bb64a7aa5d
parent: 47d939a26a95b58e189aa1533530920a9fd50c32
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 */
 }
--