diff --git a/sys/include/ip.h b/sys/include/ip.h index 56e707729..c2ab8dcf8 100644 --- a/sys/include/ip.h +++ b/sys/include/ip.h @@ -161,9 +161,9 @@ void maskip(uchar*, uchar*, uchar*); 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*); diff --git a/sys/man/2/ip b/sys/man/2/ip index e84b14c08..d2fcab0dd 100644 --- 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 .br @@ -15,15 +15,15 @@ int eipfmt(Fmt*) vlong parseip(uchar *ipaddr, char *str) .PP .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 .B char* v4parseip(uchar *ipaddr, char *str) .PP .B -ulong v4parsecidr(uchar *addr, uchar *mask, char *str) -.PP -.B int parseether(uchar *eaddr, char *str) .PP .B @@ -152,13 +152,37 @@ As a concession to backwards compatibility, 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 @@ -166,15 +190,6 @@ converts a string pointed to by 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 @@ operates on v6 addresses. .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, diff --git a/sys/src/libip/parseip.c b/sys/src/libip/parseip.c index 9f5d5dac7..757716770 100644 --- a/sys/src/libip/parseip.c +++ b/sys/src/libip/parseip.c @@ -122,7 +122,7 @@ parseip(uchar *to, char *from) * style */ vlong -parseipmask(uchar *to, char *from) +parseipmask(uchar *to, char *from, int v4) { int i, w; vlong x; @@ -133,6 +133,8 @@ parseipmask(uchar *to, char *from) 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 @@ parseipmask(uchar *to, char *from) *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 @@ parseipmask(uchar *to, char *from) */ 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 @@ parseipmask(uchar *to, char *from) 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; } diff --git a/sys/src/libip/readipifc.c b/sys/src/libip/readipifc.c index 8169a14eb..70212ef57 100644 --- a/sys/src/libip/readipifc.c +++ b/sys/src/libip/readipifc.c @@ -31,9 +31,7 @@ _readoldipifc(char *buf, Ipifc **l, int index) /* 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 @@ lose: *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);