shithub: riscv

Download patch

ref: 0af11f97b582754df36b588e04fd9d9377b50823
parent: 66b9196f77442ba8a2cbb1396c7640fd4176c4eb
author: cinap_lenrek <[email protected]>
date: Mon Feb 11 18:26:57 EST 2019

libip: replace v4parsecidr() with new parseipandmask()

we want to accept V4 subnets in CIDR notation consistently which
means we need to interpret the mask in context of the IP address.
so parseipmask() now has an additional v4 flag argument which
offsets the prefixlength by 96 so a /24 will be interpreted
as a /120.

parseipandmask() is the new function which handles this automatically
depending on the ip address type.

v4parsecidr() is now obsolete.

--- a/sys/include/ip.h
+++ b/sys/include/ip.h
@@ -161,9 +161,9 @@
 int	eipfmt(Fmt*);
 int	isv4(uchar*);
 vlong	parseip(uchar*, char*);
-vlong	parseipmask(uchar*, char*);
+vlong	parseipmask(uchar*, char*, int);
+vlong	parseipandmask(uchar*, uchar*, char*, char*);
 char*	v4parseip(uchar*, char*);
-char*	v4parsecidr(uchar*, uchar*, char*);
 int	parseether(uchar*, char*);
 int	myipaddr(uchar*, char*);
 int	myetheraddr(uchar*, char*);
--- a/sys/man/2/ip
+++ b/sys/man/2/ip
@@ -1,6 +1,6 @@
 .TH IP 2
 .SH NAME
-eipfmt, parseip, parseipmask, v4parseip, v4parsecidr, parseether, myipaddr, myetheraddr, maskip, equivip4, equivip6, defmask, isv4, v4tov6, v6tov4, nhgetv, nhgetl, nhgets, hnputv, hnputl, hnputs, ptclbsum, readipifc \- Internet Protocol addressing
+eipfmt, parseip, parseipmask, parseipandmask, v4parseip, parseether, myipaddr, myetheraddr, maskip, equivip4, equivip6, defmask, isv4, v4tov6, v6tov4, nhgetv, nhgetl, nhgets, hnputv, hnputl, hnputs, ptclbsum, readipifc \- Internet Protocol addressing
 .SH SYNOPSIS
 .B #include <u.h>
 .br
@@ -15,13 +15,13 @@
 vlong	parseip(uchar *ipaddr, char *str)
 .PP
 .B
-vlong	parseipmask(uchar *ipaddr, char *str)
+vlong	parseipmask(uchar *ipaddr, char *str, int v4)
 .PP
 .B
-char*	v4parseip(uchar *ipaddr, char *str)
+vlong	parseipandmask(uchar *ipaddr, uchar *ipmask, char *ipstr, char *maskstr)
 .PP
 .B
-ulong	v4parsecidr(uchar *addr, uchar *mask, char *str)
+char*	v4parseip(uchar *ipaddr, char *str)
 .PP
 .B
 int	parseether(uchar *eaddr, char *str)
@@ -152,14 +152,38 @@
 if the string is a V4 address, the return value
 is an unsigned long integer containing the big-endian V4 address.
 If not, the return value is 6.
+.PP
 .I Parseipmask
 converts a string pointed to by
 .I str
-to a 6-byte IP mask starting at
+to a 16-byte IP mask starting at
 .IR ipaddr .
 It too returns an unsigned long big-endian V4 address or 6.
-Both routines return -1 on errors.
+.I Parseipmask
+accepts a mask in
+.BI / prefixlen
+slash notation. When the
+.IR v4
+argument is non-zero, then
+.I prefixlen
+in range [0..32] is offset by 96 to yield a mask for a V4 address.
 .PP
+.I Parseipandmask
+combines
+.I parseip
+and
+.I parseipmask
+into a single call, interpreting the mask in context of the
+supplied IP address type.
+The returned IP mask is
+.B /128
+when
+.I maskstr
+is
+.BR nil .
+.PP
+All three functions return -1 on errors.
+.PP
 .I V4parseip
 converts a string pointed to by
 .I str
@@ -166,15 +190,6 @@
 to a 4-byte V4 IP address starting at
 .IR ipaddr .
 .PP
-.I V4parsecidr
-converts a string of the form
-addr/mask, pointed to by
-.IR str ,
-to a 4-byte V4 IP address starting at
-.I ipaddr
-and a 4-byte V4 IP mask starting at
-.IR mask .
-.PP
 .I Myipaddr
 returns the first valid IP address in
 the IP stack rooted at
@@ -207,7 +222,7 @@
 .PP
 .I Defmask
 returns the standard class A, B, or C mask for
-.IR ipaddr .
+.I ipaddr .
 .PP
 .I Isv4
 returns non-zero if the V6 address is in the V4 space, that is,
--- a/sys/src/libip/parseip.c
+++ b/sys/src/libip/parseip.c
@@ -122,7 +122,7 @@
  *  style
  */
 vlong
-parseipmask(uchar *to, char *from)
+parseipmask(uchar *to, char *from, int v4)
 {
 	int i, w;
 	vlong x;
@@ -133,6 +133,8 @@
 		i = atoi(from+1);
 		if(i < 0)
 			i = 0;
+		if(i <= 32 && v4)
+			i += 96;
 		if(i > 128)
 			i = 128;
 		w = i;
@@ -141,7 +143,6 @@
 			*p++ = 0xff;
 		if(i > 0)
 			*p = ~((1<<(8-i))-1);
-		x = nhgetl(to+IPv4off);
 		/*
 		 * identify as ipv6 if the mask is inexpressible as a v4 mask
 		 * (because it has too few mask bits).  Arguably, we could
@@ -149,6 +150,7 @@
 		 */
 		if (w < 8*(IPaddrlen-IPv4addrlen))
 			return 6;
+		x = nhgetl(to+IPv4off);
 	} else {
 		/* as a straight v4 bit mask */
 		x = parseip(to, from);
@@ -160,29 +162,15 @@
 	return x;
 }
 
-/*
- *  parse a v4 ip address/mask in cidr format
- */
-char*
-v4parsecidr(uchar *addr, uchar *mask, char *from)
+vlong
+parseipandmask(uchar *ip, uchar *mask, char *ipstr, char *maskstr)
 {
-	int i;
-	char *p;
-	uchar *a;
+	vlong x;
 
-	p = v4parseip(addr, from);
-
-	if(*p == '/'){
-		/* as a number of prefix bits */
-		i = strtoul(p+1, &p, 0);
-		if(i > 32)
-			i = 32;
-		memset(mask, 0, IPv4addrlen);
-		for(a = mask; i >= 8; i -= 8)
-			*a++ = 0xff;
-		if(i > 0)
-			*a = ~((1<<(8-i))-1);
-	} else 
-		memcpy(mask, defmask(addr), IPv4addrlen);
-	return p;
+	x = parseip(ip, ipstr);
+	if(x == -1)
+		return -1;
+	if(maskstr == nil || parseipmask(mask, maskstr, memcmp(ip, v4prefix, IPv4off) == 0) == -1)
+		memset(mask, 0xff, IPaddrlen);
+	return x;
 }
--- a/sys/src/libip/readipifc.c
+++ b/sys/src/libip/readipifc.c
@@ -31,9 +31,7 @@
 		/* allocate new local address */
 		*ll = lifc = mallocz(sizeof(Iplifc), 1);
 		ll = &lifc->next;
-
-		parseip(lifc->ip, f[i]);
-		parseipmask(lifc->mask, f[i+1]);
+		parseipandmask(lifc->ip, lifc->mask, f[i], f[i+1]);
 		parseip(lifc->net, f[i+2]);
 		ifc->pktin = strtoul(f[i+3], nil, 10);
 		ifc->pktout = strtoul(f[i+4], nil, 10);
@@ -129,8 +127,7 @@
 		*ll = lifc = mallocz(sizeof(Iplifc), 1);
 		ll = &lifc->next;
 
-		parseip(lifc->ip, f[0]);
-		parseipmask(lifc->mask, f[1]);
+		parseipandmask(lifc->ip, lifc->mask, f[0], f[1]);
 		parseip(lifc->net, f[2]);
 
 		lifc->validlt = strtoul(f[3], nil, 10);