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.
This commit is contained in:
cinap_lenrek 2019-02-11 23:26:57 +01:00
parent 66b9196f77
commit 0af11f97b5
4 changed files with 49 additions and 49 deletions

View file

@ -161,9 +161,9 @@ void maskip(uchar*, uchar*, uchar*);
int eipfmt(Fmt*); int eipfmt(Fmt*);
int isv4(uchar*); int isv4(uchar*);
vlong parseip(uchar*, char*); vlong parseip(uchar*, char*);
vlong parseipmask(uchar*, char*); vlong parseipmask(uchar*, char*, int);
vlong parseipandmask(uchar*, uchar*, char*, char*);
char* v4parseip(uchar*, char*); char* v4parseip(uchar*, char*);
char* v4parsecidr(uchar*, uchar*, char*);
int parseether(uchar*, char*); int parseether(uchar*, char*);
int myipaddr(uchar*, char*); int myipaddr(uchar*, char*);
int myetheraddr(uchar*, char*); int myetheraddr(uchar*, char*);

View file

@ -1,6 +1,6 @@
.TH IP 2 .TH IP 2
.SH NAME .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 .SH SYNOPSIS
.B #include <u.h> .B #include <u.h>
.br .br
@ -15,15 +15,15 @@ int eipfmt(Fmt*)
vlong parseip(uchar *ipaddr, char *str) vlong parseip(uchar *ipaddr, char *str)
.PP .PP
.B .B
vlong parseipmask(uchar *ipaddr, char *str) vlong parseipmask(uchar *ipaddr, char *str, int v4)
.PP
.B
vlong parseipandmask(uchar *ipaddr, uchar *ipmask, char *ipstr, char *maskstr)
.PP .PP
.B .B
char* v4parseip(uchar *ipaddr, char *str) char* v4parseip(uchar *ipaddr, char *str)
.PP .PP
.B .B
ulong v4parsecidr(uchar *addr, uchar *mask, char *str)
.PP
.B
int parseether(uchar *eaddr, char *str) int parseether(uchar *eaddr, char *str)
.PP .PP
.B .B
@ -152,13 +152,37 @@ As a concession to backwards compatibility,
if the string is a V4 address, the return value if the string is a V4 address, the return value
is an unsigned long integer containing the big-endian V4 address. is an unsigned long integer containing the big-endian V4 address.
If not, the return value is 6. If not, the return value is 6.
.PP
.I Parseipmask .I Parseipmask
converts a string pointed to by converts a string pointed to by
.I str .I str
to a 6-byte IP mask starting at to a 16-byte IP mask starting at
.IR ipaddr . .IR ipaddr .
It too returns an unsigned long big-endian V4 address or 6. 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 .PP
.I V4parseip .I V4parseip
converts a string pointed to by converts a string pointed to by
@ -166,15 +190,6 @@ converts a string pointed to by
to a 4-byte V4 IP address starting at to a 4-byte V4 IP address starting at
.IR ipaddr . .IR ipaddr .
.PP .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 .I Myipaddr
returns the first valid IP address in returns the first valid IP address in
the IP stack rooted at the IP stack rooted at
@ -207,7 +222,7 @@ operates on v6 addresses.
.PP .PP
.I Defmask .I Defmask
returns the standard class A, B, or C mask for returns the standard class A, B, or C mask for
.IR ipaddr . .I ipaddr .
.PP .PP
.I Isv4 .I Isv4
returns non-zero if the V6 address is in the V4 space, that is, returns non-zero if the V6 address is in the V4 space, that is,

View file

@ -122,7 +122,7 @@ parseip(uchar *to, char *from)
* style * style
*/ */
vlong vlong
parseipmask(uchar *to, char *from) parseipmask(uchar *to, char *from, int v4)
{ {
int i, w; int i, w;
vlong x; vlong x;
@ -133,6 +133,8 @@ parseipmask(uchar *to, char *from)
i = atoi(from+1); i = atoi(from+1);
if(i < 0) if(i < 0)
i = 0; i = 0;
if(i <= 32 && v4)
i += 96;
if(i > 128) if(i > 128)
i = 128; i = 128;
w = i; w = i;
@ -141,7 +143,6 @@ parseipmask(uchar *to, char *from)
*p++ = 0xff; *p++ = 0xff;
if(i > 0) if(i > 0)
*p = ~((1<<(8-i))-1); *p = ~((1<<(8-i))-1);
x = nhgetl(to+IPv4off);
/* /*
* identify as ipv6 if the mask is inexpressible as a v4 mask * identify as ipv6 if the mask is inexpressible as a v4 mask
* (because it has too few mask bits). Arguably, we could * (because it has too few mask bits). Arguably, we could
@ -149,6 +150,7 @@ parseipmask(uchar *to, char *from)
*/ */
if (w < 8*(IPaddrlen-IPv4addrlen)) if (w < 8*(IPaddrlen-IPv4addrlen))
return 6; return 6;
x = nhgetl(to+IPv4off);
} else { } else {
/* as a straight v4 bit mask */ /* as a straight v4 bit mask */
x = parseip(to, from); x = parseip(to, from);
@ -160,29 +162,15 @@ parseipmask(uchar *to, char *from)
return x; return x;
} }
/* vlong
* parse a v4 ip address/mask in cidr format parseipandmask(uchar *ip, uchar *mask, char *ipstr, char *maskstr)
*/
char*
v4parsecidr(uchar *addr, uchar *mask, char *from)
{ {
int i; vlong x;
char *p;
uchar *a;
p = v4parseip(addr, from); x = parseip(ip, ipstr);
if(x == -1)
if(*p == '/'){ return -1;
/* as a number of prefix bits */ if(maskstr == nil || parseipmask(mask, maskstr, memcmp(ip, v4prefix, IPv4off) == 0) == -1)
i = strtoul(p+1, &p, 0); memset(mask, 0xff, IPaddrlen);
if(i > 32) return x;
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;
} }

View file

@ -31,9 +31,7 @@ _readoldipifc(char *buf, Ipifc **l, int index)
/* allocate new local address */ /* allocate new local address */
*ll = lifc = mallocz(sizeof(Iplifc), 1); *ll = lifc = mallocz(sizeof(Iplifc), 1);
ll = &lifc->next; ll = &lifc->next;
parseipandmask(lifc->ip, lifc->mask, f[i], f[i+1]);
parseip(lifc->ip, f[i]);
parseipmask(lifc->mask, f[i+1]);
parseip(lifc->net, f[i+2]); parseip(lifc->net, f[i+2]);
ifc->pktin = strtoul(f[i+3], nil, 10); ifc->pktin = strtoul(f[i+3], nil, 10);
ifc->pktout = strtoul(f[i+4], nil, 10); ifc->pktout = strtoul(f[i+4], nil, 10);
@ -129,8 +127,7 @@ lose:
*ll = lifc = mallocz(sizeof(Iplifc), 1); *ll = lifc = mallocz(sizeof(Iplifc), 1);
ll = &lifc->next; ll = &lifc->next;
parseip(lifc->ip, f[0]); parseipandmask(lifc->ip, lifc->mask, f[0], f[1]);
parseipmask(lifc->mask, f[1]);
parseip(lifc->net, f[2]); parseip(lifc->net, f[2]);
lifc->validlt = strtoul(f[3], nil, 10); lifc->validlt = strtoul(f[3], nil, 10);