/* * `from' may contain an address followed by other characters, * at least in /boot, so we permit whitespace (and more) after the address. * we do ensure that "delete" cannot be parsed as "de::". * * some callers don't check the return value for errors, so * set `to' to something distinctive in the case of a parse error. */ vlong parseip(uchar *to, char *from) { int i, elipsis = 0, v4 = 1; ulong x; char *p, *op; memset(to, 0, IPaddrlen); p = from; for(i = 0; i < IPaddrlen && ipcharok(*p); i+=2){ op = p; x = strtoul(p, &p, 16); if(*p == '.' || (*p == 0 && i == 0)){ /* ends with v4? */ if(i > IPaddrlen-4){ memset(to, 0, IPaddrlen); return -1; /* parse error */ } p = v4parseip(to+i, op); i += 4; break; } /* v6: at most 4 hex digits, followed by colon or delim */ if(x != (ushort)x || *p != ':' && !delimchar(*p)) { memset(to, 0, IPaddrlen); return -1; /* parse error */ } to[i] = x>>8; to[i+1] = x; if(*p == ':'){ v4 = 0; if(*++p == ':'){ /* :: is elided zero short(s) */ if (elipsis) { memset(to, 0, IPaddrlen); return -1; /* second :: */ } elipsis = i+2; p++; } } else if (p == op) /* strtoul made no progress? */ break; } if (p == from || !delimchar(*p)) { memset(to, 0, IPaddrlen); return -1; /* parse error */ } if(i < IPaddrlen){ memmove(&to[elipsis+IPaddrlen-i], &to[elipsis], i-elipsis); memset(&to[elipsis], 0, IPaddrlen-i); } if(v4){ to[10] = to[11] = 0xff; return nhgetl(to + IPv4off); } else return 6; }
int _inet_pton(int af, const char *src, void *dst) { int i, elipsis = 0; unsigned char *to; unsigned long x; const char *p, *op; if(af == AF_INET) return _inet_aton(src, (struct in_addr*)dst); if(af != AF_INET6){ errno = EAFNOSUPPORT; return -1; } to = ((struct in6_addr*)dst)->s6_addr; memset(to, 0, 16); p = src; for(i = 0; i < 16 && ipcharok(*p); i+=2){ op = p; x = strtoul(p, (char**)&p, 16); if(x != (unsigned short)x || *p != ':' && !delimchar(*p)) return 0; /* parse error */ to[i] = x>>8; to[i+1] = x; if(*p == ':'){ if(*++p == ':'){ /* :: is elided zero short(s) */ if (elipsis) return 0; /* second :: */ elipsis = i+2; p++; } } else if (p == op) /* strtoul made no progress? */ break; } if (p == src || !delimchar(*p)) return 0; /* parse error */ if(i < 16){ memmove(&to[elipsis+16-i], &to[elipsis], i-elipsis); memset(&to[elipsis], 0, 16-i); } return 1; }