From ebeabb1ba32f14e308ae9aff9a2a7151265259cf Mon Sep 17 00:00:00 2001 From: nectar Date: Mon, 4 Feb 2002 19:12:46 +0000 Subject: Import of ISC BIND 8.3.1-REL. --- contrib/bind/lib/inet/Makefile | 10 +- contrib/bind/lib/inet/inet_addr.c | 13 +- contrib/bind/lib/inet/inet_cidr_ntop.c | 166 +++++++++++++++++--- contrib/bind/lib/inet/inet_cidr_pton.c | 167 +++++++++++++++++--- contrib/bind/lib/inet/inet_data.c | 44 ++++++ contrib/bind/lib/inet/inet_net_ntop.c | 135 +++++++++++++++- contrib/bind/lib/inet/inet_net_pton.c | 272 +++++++++++++++++++++++++++------ contrib/bind/lib/inet/inet_network.c | 9 +- contrib/bind/lib/inet/inet_ntop.c | 7 +- contrib/bind/lib/inet/inet_pton.c | 6 +- contrib/bind/lib/inet/nsap_addr.c | 7 +- 11 files changed, 728 insertions(+), 108 deletions(-) create mode 100644 contrib/bind/lib/inet/inet_data.c (limited to 'contrib/bind/lib/inet') diff --git a/contrib/bind/lib/inet/Makefile b/contrib/bind/lib/inet/Makefile index 1876bb6..a448e61 100644 --- a/contrib/bind/lib/inet/Makefile +++ b/contrib/bind/lib/inet/Makefile @@ -13,7 +13,7 @@ # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS # SOFTWARE. -# $Id: Makefile,v 8.21 2000/12/23 08:02:59 vixie Exp $ +# $Id: Makefile,v 8.23 2001/08/14 05:58:05 marka Exp $ # these are only appropriate for BSD 4.4 or derivatives, and are used in # development. normal builds will be done in the top level directory and @@ -45,12 +45,14 @@ THREADED= threaded SRCS= nsap_addr.c inet_addr.c inet_ntop.c inet_pton.c \ inet_ntoa.c inet_neta.c inet_net_ntop.c inet_net_pton.c \ inet_cidr_ntop.c inet_cidr_pton.c \ - inet_lnaof.c inet_makeaddr.c inet_netof.c inet_network.c + inet_lnaof.c inet_makeaddr.c inet_netof.c inet_network.c \ + inet_data.c OBJS= nsap_addr.${O} inet_addr.${O} inet_ntop.${O} inet_pton.${O} \ inet_ntoa.${O} inet_neta.${O} inet_net_ntop.${O} inet_net_pton.${O} \ inet_cidr_ntop.${O} inet_cidr_pton.${O} \ - inet_lnaof.${O} inet_makeaddr.${O} inet_netof.${O} inet_network.${O} + inet_lnaof.${O} inet_makeaddr.${O} inet_netof.${O} inet_network.${O} \ + inet_data.${O} all: ${LIBBIND} @@ -62,7 +64,7 @@ ${LIBBIND}: ${OBJS} ${RANLIB} ${LIBBIND} .c.${O}: - if test ! -d ${THREADED} ; then mkdir ${THREADED} ; else true ; fi + mkdir ${THREADED} 2> /dev/null || test -d ${THREADED} -a -w ${THREADED} ${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} ${REENTRANT} -c $*.c \ -o ${THREADED}/$*.${O} -${LDS} ${LD} ${LD_LIBFLAGS} ${THREADED}/$*.${O} \ diff --git a/contrib/bind/lib/inet/inet_addr.c b/contrib/bind/lib/inet/inet_addr.c index 3b54aa8..b68190c 100644 --- a/contrib/bind/lib/inet/inet_addr.c +++ b/contrib/bind/lib/inet/inet_addr.c @@ -70,7 +70,7 @@ #if defined(LIBC_SCCS) && !defined(lint) static const char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93"; -static const char rcsid[] = "$Id: inet_addr.c,v 8.11 1999/10/13 16:39:25 vixie Exp $"; +static const char rcsid[] = "$Id: inet_addr.c,v 8.12 2001/05/29 05:48:18 marka Exp $"; #endif /* LIBC_SCCS and not lint */ #include "port_before.h" @@ -121,7 +121,7 @@ inet_aton(const char *cp, struct in_addr *addr) { * Values are specified as for C: * 0x=hex, 0=octal, isdigit=decimal. */ - if (!isdigit(c)) + if (!isdigit((unsigned char)c)) return (0); val = 0; base = 10; digit = 0; if (c == '0') { @@ -134,15 +134,16 @@ inet_aton(const char *cp, struct in_addr *addr) { } } for (;;) { - if (isascii(c) && isdigit(c)) { + if (isascii(c) && isdigit((unsigned char)c)) { if (base == 8 && (c == '8' || c == '9')) return (0); val = (val * base) + (c - '0'); c = *++cp; digit = 1; - } else if (base == 16 && isascii(c) && isxdigit(c)) { + } else if (base == 16 && isascii(c) && + isxdigit((unsigned char)c)) { val = (val << 4) | - (c + 10 - (islower(c) ? 'a' : 'A')); + (c + 10 - (islower((unsigned char)c) ? 'a' : 'A')); c = *++cp; digit = 1; } else @@ -165,7 +166,7 @@ inet_aton(const char *cp, struct in_addr *addr) { /* * Check for trailing characters. */ - if (c != '\0' && (!isascii(c) || !isspace(c))) + if (c != '\0' && (!isascii(c) || !isspace((unsigned char)c))) return (0); /* * Did we get a valid digit? diff --git a/contrib/bind/lib/inet/inet_cidr_ntop.c b/contrib/bind/lib/inet/inet_cidr_ntop.c index 08352ab..0acff76 100644 --- a/contrib/bind/lib/inet/inet_cidr_ntop.c +++ b/contrib/bind/lib/inet/inet_cidr_ntop.c @@ -16,7 +16,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: inet_cidr_ntop.c,v 8.4 1999/10/07 20:44:02 vixie Exp $"; +static const char rcsid[] = "$Id: inet_cidr_ntop.c,v 8.7 2001/09/28 05:19:36 marka Exp $"; #endif #include "port_before.h" @@ -24,6 +24,7 @@ static const char rcsid[] = "$Id: inet_cidr_ntop.c,v 8.4 1999/10/07 20:44:02 vix #include #include #include +#include #include #include @@ -41,6 +42,8 @@ static const char rcsid[] = "$Id: inet_cidr_ntop.c,v 8.4 1999/10/07 20:44:02 vix static char * inet_cidr_ntop_ipv4 __P((const u_char *src, int bits, char *dst, size_t size)); +static char * inet_cidr_ntop_ipv6 __P((const u_char *src, int bits, + char *dst, size_t size)); /* * char * @@ -61,12 +64,34 @@ inet_cidr_ntop(int af, const void *src, int bits, char *dst, size_t size) { switch (af) { case AF_INET: return (inet_cidr_ntop_ipv4(src, bits, dst, size)); + case AF_INET6: + return (inet_cidr_ntop_ipv6(src, bits, dst, size)); default: errno = EAFNOSUPPORT; return (NULL); } } +static int +decoct(const u_char *src, int bytes, char *dst, size_t size) { + char *odst = dst; + char *t; + int b; + + for (b = 1; b <= bytes; b++) { + if (size < sizeof "255.") + return (0); + t = dst; + dst += SPRINTF((dst, "%u", *src++)); + if (b != bytes) { + *dst++ = '.'; + *dst = '\0'; + } + size -= (size_t)(dst - t); + } + return (dst - odst); +} + /* * static char * * inet_cidr_ntop_ipv4(src, bits, dst, size) @@ -83,9 +108,9 @@ inet_cidr_ntop(int af, const void *src, int bits, char *dst, size_t size) { static char * inet_cidr_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size) { char *odst = dst; - char *t; size_t len = 4; - int b, tb; + size_t b; + size_t bytes; if ((bits < -1) || (bits > 32)) { errno = EINVAL; @@ -94,25 +119,21 @@ inet_cidr_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size) { /* Find number of significant bytes in address. */ if (bits == -1) - len = 3; + len = 4; else - for (len = 0,b = 1 ; b < 4; b++) + for (len = 1, b = 1 ; b < 4; b++) if (*(src + b)) - len = b; + len = b + 1; /* Format whole octets plus nonzero trailing octets. */ - tb = (bits <= 0) ? 1 : (bits - 1); - for (b = 0; b <= (tb / 8) || (b <= len); b++) { - if (size < sizeof "255.") - goto emsgsize; - t = dst; - dst += SPRINTF((dst, "%u", *src++)); - if (b + 1 <= (tb / 8) || (b + 1 <= len)) { - *dst++ = '.'; - *dst = '\0'; - } - size -= (size_t)(dst - t); - } + bytes = (((bits <= 0) ? 1 : bits) + 7) / 8; + if (len > bytes) + bytes = len; + b = decoct(src, bytes, dst, size); + if (b == 0) + goto emsgsize; + dst += b; + size -= b; if (bits != -1) { /* Format CIDR /width. */ @@ -127,3 +148,112 @@ inet_cidr_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size) { errno = EMSGSIZE; return (NULL); } + +static char * +inet_cidr_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size) { + /* + * Note that int32_t and int16_t need only be "at least" large enough + * to contain a value of the specified size. On some systems, like + * Crays, there is no such thing as an integer variable with 16 bits. + * Keep this in mind if you think this function should have been coded + * to use pointer overlays. All the world's not a VAX. + */ + char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255/128"]; + char *tp; + struct { int base, len; } best, cur; + u_int words[NS_IN6ADDRSZ / NS_INT16SZ]; + int i; + + if ((bits < -1) || (bits > 128)) { + errno = EINVAL; + return (NULL); + } + + /* + * Preprocess: + * Copy the input (bytewise) array into a wordwise array. + * Find the longest run of 0x00's in src[] for :: shorthanding. + */ + memset(words, '\0', sizeof words); + for (i = 0; i < NS_IN6ADDRSZ; i++) + words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); + best.base = -1; + cur.base = -1; + for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { + if (words[i] == 0) { + if (cur.base == -1) + cur.base = i, cur.len = 1; + else + cur.len++; + } else { + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + cur.base = -1; + } + } + } + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + } + if (best.base != -1 && best.len < 2) + best.base = -1; + + /* + * Format the result. + */ + tp = tmp; + for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { + /* Are we inside the best run of 0x00's? */ + if (best.base != -1 && i >= best.base && + i < (best.base + best.len)) { + if (i == best.base) + *tp++ = ':'; + continue; + } + /* Are we following an initial run of 0x00s or any real hex? */ + if (i != 0) + *tp++ = ':'; + /* Is this address an encapsulated IPv4? */ + if (i == 6 && best.base == 0 && (best.len == 6 || + (best.len == 7 && words[7] != 0x0001) || + (best.len == 5 && words[5] == 0xffff))) { + int n; + + if (src[15] || bits == -1 || bits > 120) + n = 4; + else if (src[14] || bits > 112) + n = 3; + else + n = 2; + n = decoct(src+12, n, tp, sizeof tmp - (tp - tmp)); + if (n == 0) { + errno = EMSGSIZE; + return (NULL); + } + tp += strlen(tp); + break; + } + tp += SPRINTF((tp, "%x", words[i])); + } + + /* Was it a trailing run of 0x00's? */ + if (best.base != -1 && (best.base + best.len) == + (NS_IN6ADDRSZ / NS_INT16SZ)) + *tp++ = ':'; + *tp = '\0'; + + if (bits != -1) + tp += SPRINTF((tp, "/%u", bits)); + + /* + * Check for overflow, copy, and we're done. + */ + if ((size_t)(tp - tmp) > size) { + errno = EMSGSIZE; + return (NULL); + } + strcpy(dst, tmp); + return (dst); +} diff --git a/contrib/bind/lib/inet/inet_cidr_pton.c b/contrib/bind/lib/inet/inet_cidr_pton.c index 9ead90b..b8a7226 100644 --- a/contrib/bind/lib/inet/inet_cidr_pton.c +++ b/contrib/bind/lib/inet/inet_cidr_pton.c @@ -16,7 +16,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: inet_cidr_pton.c,v 8.4 2000/12/23 08:14:53 vixie Exp $"; +static const char rcsid[] = "$Id: inet_cidr_pton.c,v 8.7 2001/09/28 04:21:28 marka Exp $"; #endif #include "port_before.h" @@ -24,6 +24,7 @@ static const char rcsid[] = "$Id: inet_cidr_pton.c,v 8.4 2000/12/23 08:14:53 vix #include #include #include +#include #include #include @@ -42,8 +43,12 @@ static const char rcsid[] = "$Id: inet_cidr_pton.c,v 8.4 2000/12/23 08:14:53 vix #endif static int inet_cidr_pton_ipv4 __P((const char *src, u_char *dst, + int *bits, int ipv6)); +static int inet_cidr_pton_ipv6 __P((const char *src, u_char *dst, int *bits)); +static int getbits(const char *, int ipv6); + /* * int * inet_cidr_pton(af, src, dst, *bits) @@ -65,16 +70,19 @@ int inet_cidr_pton(int af, const char *src, void *dst, int *bits) { switch (af) { case AF_INET: - return (inet_cidr_pton_ipv4(src, dst, bits)); + return (inet_cidr_pton_ipv4(src, dst, bits, 0)); + case AF_INET6: + return (inet_cidr_pton_ipv6(src, dst, bits)); default: errno = EAFNOSUPPORT; return (-1); } } +static const char digits[] = "0123456789"; + static int -inet_cidr_pton_ipv4(const char *src, u_char *dst, int *pbits) { - static const char digits[] = "0123456789"; +inet_cidr_pton_ipv4(const char *src, u_char *dst, int *pbits, int ipv6) { const u_char *odst = dst; int n, ch, tmp, bits; size_t size = 4; @@ -101,30 +109,17 @@ inet_cidr_pton_ipv4(const char *src, u_char *dst, int *pbits) { /* Get the prefix length if any. */ bits = -1; - if (ch == '/' && isascii(src[0]) && isdigit(src[0]) && dst > odst) { - /* CIDR width specifier. Nothing can follow it. */ - ch = *src++; /* Skip over the /. */ - bits = 0; - do { - n = strchr(digits, ch) - digits; - INSIST(n >= 0 && n <= 9); - bits *= 10; - bits += n; - } while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch)); - if (ch != '\0') + if (ch == '/' && dst > odst) { + bits = getbits(src, ipv6); + if (bits == -2) goto enoent; - if (bits > 32) - goto emsgsize; - } - - /* Firey death and destruction unless we prefetched EOS. */ - if (ch != '\0') + } else if (ch != '\0') goto enoent; /* Prefix length can default to /32 only if all four octets spec'd. */ if (bits == -1) { if (dst - odst == 4) - bits = 32; + bits = ipv6 ? 128 : 32; else goto enoent; } @@ -134,7 +129,7 @@ inet_cidr_pton_ipv4(const char *src, u_char *dst, int *pbits) { goto enoent; /* If prefix length overspecifies mantissa, life is bad. */ - if ((bits / 8) > (dst - odst)) + if (((bits - (ipv6 ? 96 : 0)) / 8) > (dst - odst)) goto enoent; /* Extend address to four octets. */ @@ -152,3 +147,129 @@ inet_cidr_pton_ipv4(const char *src, u_char *dst, int *pbits) { errno = EMSGSIZE; return (-1); } + +static int +inet_cidr_pton_ipv6(const char *src, u_char *dst, int *pbits) { + static const char xdigits_l[] = "0123456789abcdef", + xdigits_u[] = "0123456789ABCDEF"; + u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; + const char *xdigits, *curtok; + int ch, saw_xdigit; + u_int val; + int bits; + + memset((tp = tmp), '\0', NS_IN6ADDRSZ); + endp = tp + NS_IN6ADDRSZ; + colonp = NULL; + /* Leading :: requires some special handling. */ + if (*src == ':') + if (*++src != ':') + return (0); + curtok = src; + saw_xdigit = 0; + val = 0; + bits = -1; + while ((ch = *src++) != '\0') { + const char *pch; + + if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) + pch = strchr((xdigits = xdigits_u), ch); + if (pch != NULL) { + val <<= 4; + val |= (pch - xdigits); + if (val > 0xffff) + return (0); + saw_xdigit = 1; + continue; + } + if (ch == ':') { + curtok = src; + if (!saw_xdigit) { + if (colonp) + return (0); + colonp = tp; + continue; + } else if (*src == '\0') { + return (0); + } + if (tp + NS_INT16SZ > endp) + return (0); + *tp++ = (u_char) (val >> 8) & 0xff; + *tp++ = (u_char) val & 0xff; + saw_xdigit = 0; + val = 0; + continue; + } + if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && + inet_cidr_pton_ipv4(curtok, tp, &bits, 1) == 0) { + tp += NS_INADDRSZ; + saw_xdigit = 0; + break; /* '\0' was seen by inet_pton4(). */ + } + if (ch == '/') { + bits = getbits(src, 1); + if (bits == -2) + goto enoent; + break; + } + goto enoent; + } + if (saw_xdigit) { + if (tp + NS_INT16SZ > endp) + goto emsgsize; + *tp++ = (u_char) (val >> 8) & 0xff; + *tp++ = (u_char) val & 0xff; + } + if (colonp != NULL) { + /* + * Since some memmove()'s erroneously fail to handle + * overlapping regions, we'll do the shift by hand. + */ + const int n = tp - colonp; + int i; + + if (tp == endp) + goto enoent; + for (i = 1; i <= n; i++) { + endp[- i] = colonp[n - i]; + colonp[n - i] = 0; + } + tp = endp; + } + + memcpy(dst, tmp, NS_IN6ADDRSZ); + + *pbits = bits; + return (0); + + enoent: + errno = ENOENT; + return (-1); + + emsgsize: + errno = EMSGSIZE; + return (-1); +} + +int +getbits(const char *src, int ipv6) { + int bits = 0; + char *cp, ch; + + if (*src == '\0') /* syntax */ + return (-2); + do { + ch = *src++; + cp = strchr(digits, ch); + if (cp == NULL) /* syntax */ + return (-2); + bits *= 10; + bits += cp - digits; + if (bits == 0 && *src != '\0') /* no leading zeros */ + return (-2); + if (bits > (ipv6 ? 128 : 32)) /* range error */ + return (-2); + } while (*src != '\0'); + + return (bits); +} diff --git a/contrib/bind/lib/inet/inet_data.c b/contrib/bind/lib/inet/inet_data.c new file mode 100644 index 0000000..47b6d9b --- /dev/null +++ b/contrib/bind/lib/inet/inet_data.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 1995-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$Id: inet_data.c,v 1.2 2001/06/20 22:06:36 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "port_after.h" + +const struct in6_addr isc_in6addr_any = IN6ADDR_ANY_INIT; +const struct in6_addr isc_in6addr_loopback = IN6ADDR_LOOPBACK_INIT; diff --git a/contrib/bind/lib/inet/inet_net_ntop.c b/contrib/bind/lib/inet/inet_net_ntop.c index d8b8377..b38a6ca 100644 --- a/contrib/bind/lib/inet/inet_net_ntop.c +++ b/contrib/bind/lib/inet/inet_net_ntop.c @@ -16,7 +16,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: inet_net_ntop.c,v 1.7 2001/01/25 19:55:59 vixie Exp $"; +static const char rcsid[] = "$Id: inet_net_ntop.c,v 1.8 2001/09/27 15:08:36 marka Exp $"; #endif #include "port_before.h" @@ -41,6 +41,8 @@ static const char rcsid[] = "$Id: inet_net_ntop.c,v 1.7 2001/01/25 19:55:59 vixi static char * inet_net_ntop_ipv4 __P((const u_char *src, int bits, char *dst, size_t size)); +static char * inet_net_ntop_ipv6 __P((const u_char *src, int bits, + char *dst, size_t size)); /* * char * @@ -63,6 +65,8 @@ inet_net_ntop(af, src, bits, dst, size) switch (af) { case AF_INET: return (inet_net_ntop_ipv4(src, bits, dst, size)); + case AF_INET6: + return (inet_net_ntop_ipv6(src, bits, dst, size)); default: errno = EAFNOSUPPORT; return (NULL); @@ -98,6 +102,7 @@ inet_net_ntop_ipv4(src, bits, dst, size) errno = EINVAL; return (NULL); } + if (bits == 0) { if (size < sizeof "0") goto emsgsize; @@ -142,3 +147,131 @@ inet_net_ntop_ipv4(src, bits, dst, size) errno = EMSGSIZE; return (NULL); } + +/* + * static char * + * inet_net_ntop_ipv6(src, bits, fakebits, dst, size) + * convert IPv6 network number from network to presentation format. + * generates CIDR style result always. Picks the shortest representation + * unless the IP is really IPv4. + * always prints specified number of bits (bits). + * return: + * pointer to dst, or NULL if an error occurred (check errno). + * note: + * network byte order assumed. this means 192.5.5.240/28 has + * 0x11110000 in its fourth octet. + * author: + * Vadim Kogan (UCB), June 2001 + * Original version (IPv4) by Paul Vixie (ISC), July 1996 + */ + +static char * +inet_net_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size) { + u_int m; + int b; + int p; + int zero_s, zero_l, tmp_zero_s, tmp_zero_l; + int i; + int is_ipv4 = 0; + unsigned char inbuf[16]; + char outbuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")]; + char *cp; + int words; + u_char *s; + + if (bits < 0 || bits > 128) { + errno = EINVAL; + return (NULL); + } + + cp = outbuf; + + if (bits == 0) { + *cp++ = ':'; + *cp++ = ':'; + *cp = '\0'; + } else { + /* Copy src to private buffer. Zero host part. */ + p = (bits + 7) / 8; + memcpy(inbuf, src, p); + memset(inbuf + p, 0, 16 - p); + b = bits % 8; + if (b != 0) { + m = ~0 << (8 - b); + inbuf[p-1] &= m; + } + + s = inbuf; + + /* how many words need to be displayed in output */ + words = (bits + 15) / 16; + if (words == 1) + words = 2; + + /* Find the longest substring of zero's */ + zero_s = zero_l = tmp_zero_s = tmp_zero_l = 0; + for (i = 0; i < (words * 2); i += 2) { + if ((s[i] | s[i+1]) == 0) { + if (tmp_zero_l == 0) + tmp_zero_s = i / 2; + tmp_zero_l++; + } else { + if (tmp_zero_l && zero_l < tmp_zero_l) { + zero_s = tmp_zero_s; + zero_l = tmp_zero_l; + tmp_zero_l = 0; + } + } + } + + if (tmp_zero_l && zero_l < tmp_zero_l) { + zero_s = tmp_zero_s; + zero_l = tmp_zero_l; + } + + if (zero_l != words && zero_s == 0 && ((zero_l == 6) || + ((zero_l == 5 && s[10] == 0xff && s[11] == 0xff) || + ((zero_l == 7 && s[14] != 0 && s[15] != 1))))) + is_ipv4 = 1; + + /* Format whole words. */ + for (p = 0; p < words; p++) { + if (zero_l != 0 && p >= zero_s && p < zero_s + zero_l) { + /* Time to skip some zeros */ + if (p == zero_s) + *cp++ = ':'; + if (p == words - 1) + *cp++ = ':'; + s++; + s++; + continue; + } + + if (is_ipv4 && p > 5 ) { + *cp++ = (p == 6) ? ':' : '.'; + cp += SPRINTF((cp, "%u", *s++)); + /* we can potentially drop the last octet */ + if (p != 7 || bits > 120) { + *cp++ = '.'; + cp += SPRINTF((cp, "%u", *s++)); + } + } else { + if (cp != outbuf) + *cp++ = ':'; + cp += SPRINTF((cp, "%x", *s * 256 + s[1])); + s += 2; + } + } + } + /* Format CIDR /width. */ + SPRINTF((cp, "/%u", bits)); + if (strlen(outbuf) + 1 > size) + goto emsgsize; + strcpy(dst, outbuf); + + return (dst); + +emsgsize: + errno = EMSGSIZE; + return (NULL); +} diff --git a/contrib/bind/lib/inet/inet_net_pton.c b/contrib/bind/lib/inet/inet_net_pton.c index 4d265b2..ff62a8b 100644 --- a/contrib/bind/lib/inet/inet_net_pton.c +++ b/contrib/bind/lib/inet/inet_net_pton.c @@ -16,7 +16,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: inet_net_pton.c,v 1.11 1999/01/08 19:23:44 vixie Exp $"; +static const char rcsid[] = "$Id: inet_net_pton.c,v 1.13 2001/09/27 15:08:38 marka Exp $"; #endif #include "port_before.h" @@ -24,6 +24,7 @@ static const char rcsid[] = "$Id: inet_net_pton.c,v 1.11 1999/01/08 19:23:44 vix #include #include #include +#include #include #include @@ -41,38 +42,6 @@ static const char rcsid[] = "$Id: inet_net_pton.c,v 1.11 1999/01/08 19:23:44 vix # define SPRINTF(x) ((size_t)sprintf x) #endif -static int inet_net_pton_ipv4 __P((const char *src, u_char *dst, - size_t size)); - -/* - * static int - * inet_net_pton(af, src, dst, size) - * convert network number from presentation to network format. - * accepts hex octets, hex strings, decimal octets, and /CIDR. - * "size" is in bytes and describes "dst". - * return: - * number of bits, either imputed classfully or specified with /CIDR, - * or -1 if some failure occurred (check errno). ENOENT means it was - * not a valid network specification. - * author: - * Paul Vixie (ISC), June 1996 - */ -int -inet_net_pton(af, src, dst, size) - int af; - const char *src; - void *dst; - size_t size; -{ - switch (af) { - case AF_INET: - return (inet_net_pton_ipv4(src, dst, size)); - default: - errno = EAFNOSUPPORT; - return (-1); - } -} - /* * static int * inet_net_pton_ipv4(src, dst, size) @@ -90,20 +59,16 @@ inet_net_pton(af, src, dst, size) * Paul Vixie (ISC), June 1996 */ static int -inet_net_pton_ipv4(src, dst, size) - const char *src; - u_char *dst; - size_t size; -{ - static const char - xdigits[] = "0123456789abcdef", - digits[] = "0123456789"; - int n, ch, tmp, dirty, bits; +inet_net_pton_ipv4( const char *src, u_char *dst, size_t size) { + static const char xdigits[] = "0123456789abcdef"; + static const char digits[] = "0123456789"; + int n, ch, tmp = 0, dirty, bits; const u_char *odst = dst; ch = *src++; if (ch == '0' && (src[0] == 'x' || src[0] == 'X') - && isascii(src[1]) && isxdigit(src[1])) { + && isascii((unsigned char)(src[1])) + && isxdigit((unsigned char)(src[1]))) { /* Hexadecimal: Eat nybble string. */ if (size <= 0) goto emsgsize; @@ -158,7 +123,8 @@ inet_net_pton_ipv4(src, dst, size) goto enoent; bits = -1; - if (ch == '/' && isascii(src[0]) && isdigit(src[0]) && dst > odst) { + if (ch == '/' && isascii((unsigned char)(src[0])) && + isdigit((unsigned char)(src[0])) && dst > odst) { /* CIDR width specifier. Nothing can follow it. */ ch = *src++; /* Skip over the /. */ bits = 0; @@ -213,3 +179,221 @@ inet_net_pton_ipv4(src, dst, size) errno = EMSGSIZE; return (-1); } + +static int +getbits(const char *src, int *bitsp) { + static const char digits[] = "0123456789"; + int n; + int val; + char ch; + + val = 0; + n = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + pch = strchr(digits, ch); + if (pch != NULL) { + if (n++ != 0 && val == 0) /* no leading zeros */ + return (0); + val *= 10; + val += (pch - digits); + if (val > 128) /* range */ + return (0); + continue; + } + return (0); + } + if (n == 0) + return (0); + *bitsp = val; + return (1); +} + +static int +getv4(const char *src, u_char *dst, int *bitsp) { + static const char digits[] = "0123456789"; + u_char *odst = dst; + int n; + u_int val; + char ch; + + val = 0; + n = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + pch = strchr(digits, ch); + if (pch != NULL) { + if (n++ != 0 && val == 0) /* no leading zeros */ + return (0); + val *= 10; + val += (pch - digits); + if (val > 255) /* range */ + return (0); + continue; + } + if (ch == '.' || ch == '/') { + if (dst - odst > 3) /* too many octets? */ + return (0); + *dst++ = val; + if (ch == '/') + return (getbits(src, bitsp)); + val = 0; + n = 0; + continue; + } + return (0); + } + if (n == 0) + return (0); + if (dst - odst > 3) /* too many octets? */ + return (0); + *dst++ = val; + return (1); +} + +static int +inet_net_pton_ipv6(const char *src, u_char *dst, size_t size) { + static const char xdigits_l[] = "0123456789abcdef", + xdigits_u[] = "0123456789ABCDEF"; + u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; + const char *xdigits, *curtok; + int ch, saw_xdigit; + u_int val; + int digits; + int bits; + size_t bytes; + int words; + int ipv4; + + memset((tp = tmp), '\0', NS_IN6ADDRSZ); + endp = tp + NS_IN6ADDRSZ; + colonp = NULL; + /* Leading :: requires some special handling. */ + if (*src == ':') + if (*++src != ':') + goto enoent; + curtok = src; + saw_xdigit = 0; + val = 0; + digits = 0; + bits = -1; + ipv4 = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) + pch = strchr((xdigits = xdigits_u), ch); + if (pch != NULL) { + val <<= 4; + val |= (pch - xdigits); + if (++digits > 4) + goto enoent; + saw_xdigit = 1; + continue; + } + if (ch == ':') { + curtok = src; + if (!saw_xdigit) { + if (colonp) + goto enoent; + colonp = tp; + continue; + } else if (*src == '\0') + goto enoent; + if (tp + NS_INT16SZ > endp) + return (0); + *tp++ = (u_char) (val >> 8) & 0xff; + *tp++ = (u_char) val & 0xff; + saw_xdigit = 0; + digits = 0; + val = 0; + continue; + } + if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && + getv4(curtok, tp, &bits) > 0) { + tp += NS_INADDRSZ; + saw_xdigit = 0; + ipv4 = 1; + break; /* '\0' was seen by inet_pton4(). */ + } + if (ch == '/' && getbits(src, &bits) > 0) + break; + goto enoent; + } + if (saw_xdigit) { + if (tp + NS_INT16SZ > endp) + goto enoent; + *tp++ = (u_char) (val >> 8) & 0xff; + *tp++ = (u_char) val & 0xff; + } + if (bits == -1) + bits = 128; + + words = (bits + 15) / 16; + if (words < 2) + words = 2; + if (ipv4) + words = 8; + endp = tmp + 2 * words; + + if (colonp != NULL) { + /* + * Since some memmove()'s erroneously fail to handle + * overlapping regions, we'll do the shift by hand. + */ + const int n = tp - colonp; + int i; + + if (tp == endp) + goto enoent; + for (i = 1; i <= n; i++) { + endp[- i] = colonp[n - i]; + colonp[n - i] = 0; + } + tp = endp; + } + if (tp != endp) + goto enoent; + + bytes = (bits + 7) / 8; + if (bytes > size) + goto emsgsize; + memcpy(dst, tmp, bytes); + return (bits); + + enoent: + errno = ENOENT; + return (-1); + + emsgsize: + errno = EMSGSIZE; + return (-1); +} + +/* + * int + * inet_net_pton(af, src, dst, size) + * convert network number from presentation to network format. + * accepts hex octets, hex strings, decimal octets, and /CIDR. + * "size" is in bytes and describes "dst". + * return: + * number of bits, either imputed classfully or specified with /CIDR, + * or -1 if some failure occurred (check errno). ENOENT means it was + * not a valid network specification. + * author: + * Paul Vixie (ISC), June 1996 + */ +int +inet_net_pton(int af, const char *src, void *dst, size_t size) { + switch (af) { + case AF_INET: + return (inet_net_pton_ipv4(src, dst, size)); + case AF_INET6: + return (inet_net_pton_ipv6(src, dst, size)); + default: + errno = EAFNOSUPPORT; + return (-1); + } +} diff --git a/contrib/bind/lib/inet/inet_network.c b/contrib/bind/lib/inet/inet_network.c index d26369c..9090d13 100644 --- a/contrib/bind/lib/inet/inet_network.c +++ b/contrib/bind/lib/inet/inet_network.c @@ -65,7 +65,7 @@ again: if (*cp == 'x' || *cp == 'X') base = 16, cp++; while ((c = *cp) != 0) { - if (isdigit(c)) { + if (isdigit((unsigned char)c)) { if (base == 8 && (c == '8' || c == '9')) return (INADDR_NONE); val = (val * base) + (c - '0'); @@ -73,8 +73,9 @@ again: digit = 1; continue; } - if (base == 16 && isxdigit(c)) { - val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A')); + if (base == 16 && isxdigit((unsigned char)c)) { + val = (val << 4) + + (c + 10 - (islower((unsigned char)c) ? 'a' : 'A')); cp++; digit = 1; continue; @@ -89,7 +90,7 @@ again: *pp++ = val, cp++; goto again; } - if (*cp && !isspace(*cp)) + if (*cp && !isspace(*cp&0xff)) return (INADDR_NONE); *pp++ = val; n = pp - parts; diff --git a/contrib/bind/lib/inet/inet_ntop.c b/contrib/bind/lib/inet/inet_ntop.c index d588e9f..e05812e 100644 --- a/contrib/bind/lib/inet/inet_ntop.c +++ b/contrib/bind/lib/inet/inet_ntop.c @@ -16,7 +16,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: inet_ntop.c,v 1.10 2001/01/25 20:21:10 vixie Exp $"; +static const char rcsid[] = "$Id: inet_ntop.c,v 1.11 2001/09/27 15:12:57 marka Exp $"; #endif /* LIBC_SCCS and not lint */ #include "port_before.h" @@ -175,8 +175,9 @@ inet_ntop6(src, dst, size) if (i != 0) *tp++ = ':'; /* Is this address an encapsulated IPv4? */ - if (i == 6 && best.base == 0 && - (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { + if (i == 6 && best.base == 0 && (best.len == 6 || + (best.len == 7 && words[7] != 0x0001) || + (best.len == 5 && words[5] == 0xffff))) { if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp))) return (NULL); tp += strlen(tp); diff --git a/contrib/bind/lib/inet/inet_pton.c b/contrib/bind/lib/inet/inet_pton.c index 0a2927d..a6b0a71 100644 --- a/contrib/bind/lib/inet/inet_pton.c +++ b/contrib/bind/lib/inet/inet_pton.c @@ -16,7 +16,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: inet_pton.c,v 1.7 1999/10/13 16:39:28 vixie Exp $"; +static const char rcsid[] = "$Id: inet_pton.c,v 1.8 2001/07/16 03:22:24 marka Exp $"; #endif /* LIBC_SCCS and not lint */ #include "port_before.h" @@ -95,10 +95,12 @@ inet_pton4(src, dst) if ((pch = strchr(digits, ch)) != NULL) { u_int new = *tp * 10 + (pch - digits); + if (saw_digit && *tp == 0) + return (0); if (new > 255) return (0); *tp = new; - if (! saw_digit) { + if (!saw_digit) { if (++octets > 4) return (0); saw_digit = 1; diff --git a/contrib/bind/lib/inet/nsap_addr.c b/contrib/bind/lib/inet/nsap_addr.c index da388dc..7198b9d 100644 --- a/contrib/bind/lib/inet/nsap_addr.c +++ b/contrib/bind/lib/inet/nsap_addr.c @@ -16,7 +16,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: nsap_addr.c,v 8.11 2001/03/26 07:04:30 marka Exp $"; +static const char rcsid[] = "$Id: nsap_addr.c,v 8.12 2001/05/28 07:37:46 marka Exp $"; #endif /* LIBC_SCCS and not lint */ #include "port_before.h" @@ -46,6 +46,7 @@ inet_nsap_addr(const char *ascii, u_char *binary, int maxlen) { if (ascii[0] != '0' || (ascii[1] != 'x' && ascii[1] != 'X')) return (0); + ascii += 2; while ((c = *ascii++) != '\0' && len < (u_int)maxlen) { if (c == '.' || c == '+' || c == '/') @@ -88,8 +89,8 @@ inet_nsap_ntoa(int binlen, const u_char *binary, char *ascii) { start = tmpbuf; } - *ascii = '0'; - *ascii = 'x'; + *ascii++ = '0'; + *ascii++ = 'x'; if (binlen > 255) binlen = 255; -- cgit v1.1