X-Git-Url: https://git.saurik.com/apple/libc.git/blobdiff_plain/6465356a983ac139f81d3b7913cdb548477c346c..507116e319a1470bb0a5040d4d23e5c76955ef97:/net/inet_ntop.c?ds=inline diff --git a/net/inet_ntop.c b/net/inet_ntop.c index a4c977d..aa6ffe4 100644 --- a/net/inet_ntop.c +++ b/net/inet_ntop.c @@ -1,153 +1,169 @@ +/* + * Copyright (c) 2003,2005,2006,2011,2012 Apple, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ -#include -#include #include -#include +#include +#include +#include #include +#include #include -#include #include +#include #define MAX_V4_ADDR_LEN 16 -#define MAX_V6_ADDR_LEN 64 -static const char *hexchars = "0123456789abcdef"; +const char * inet_ntop6(const struct in6_addr *addr, char *dst, socklen_t size); +const char * inet_ntop4(const struct in_addr *addr, char *dst, socklen_t size); const char * -inet_ntop6(const struct in6_addr *addr, char *dst, socklen_t size) +inet_ntop(int af, const void *addr, char *buf, socklen_t len) { - char hexa[8][5], tmp[MAX_V6_ADDR_LEN]; - int zr[8]; - socklen_t len; - int32_t i, j, k, skip; - uint8_t x8, hx8; - uint16_t x16; - struct in_addr a4; - - if (addr == NULL) - { - errno = EAFNOSUPPORT; - return NULL; - } - - if (dst == NULL) - { - errno = ENOSPC; - return NULL; - } - - memset(tmp, 0, MAX_V6_ADDR_LEN); - - /* check for mapped or compat addresses */ - i = IN6_IS_ADDR_V4MAPPED(addr); - j = IN6_IS_ADDR_V4COMPAT(addr); - if ((i != 0) || (j != 0)) - { - a4.s_addr = addr->__u6_addr.__u6_addr32[3]; - sprintf(tmp, "::%s%s", (i != 0) ? "ffff:" : "", inet_ntoa(a4)); - len = strlen(tmp) + 1; - if (len > size) - { - errno = ENOSPC; - return NULL; - } - - memcpy(dst, tmp, len); - return dst; - } - - k = 0; - for (i = 0; i < 16; i += 2) - { - j = 0; - skip = 1; - - memset(hexa[k], 0, 5); - - x8 = addr->__u6_addr.__u6_addr8[i]; - - hx8 = x8 >> 4; - if (hx8 != 0) - { - skip = 0; - hexa[k][j++] = hexchars[hx8]; - } - - hx8 = x8 & 0x0f; - if ((skip == 0) || ((skip == 1) && (hx8 != 0))) - { - skip = 0; - hexa[k][j++] = hexchars[hx8]; - } - - x8 = addr->__u6_addr.__u6_addr8[i + 1]; + if (addr && af == AF_INET6) return inet_ntop6(addr, buf, len); + if (addr && af == AF_INET) return inet_ntop4(addr, buf, len); - hx8 = x8 >> 4; - if ((skip == 0) || ((skip == 1) && (hx8 != 0))) - { - hexa[k][j++] = hexchars[hx8]; - } - - hx8 = x8 & 0x0f; - hexa[k][j++] = hexchars[hx8]; - - k++; - } - - /* find runs of zeros for :: convention */ - j = 0; - for (i = 7; i >= 0; i--) - { - zr[i] = j; - x16 = addr->__u6_addr.__u6_addr16[i]; - if (x16 == 0) j++; - else j = 0; - zr[i] = j; - } + errno = EAFNOSUPPORT; + return NULL; +} - /* find longest run of zeros */ - k = -1; - j = 0; - for(i = 0; i < 8; i++) - { - if (zr[i] > j) - { - k = i; - j = zr[i]; +/* const char * + * inet_ntop6(src, dst, size) + * convert IPv6 binary address into presentation (printable) format + * author: + * Paul Vixie, 1996. + */ +const char * +inet_ntop6(const struct in6_addr *addr, char *dst, socklen_t size) +{ + const u_char *src = addr->__u6_addr.__u6_addr8; + /* + * 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"], *tp; + struct { int base, len; } best, cur; + u_int words[NS_IN6ADDRSZ / NS_INT16SZ]; + int i; + + /* + * 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; + best.len = 0; + cur.base = -1; + cur.len = 0; + 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; + } } } - - for(i = 0; i < 8; i++) - { - if (i != k) zr[i] = 0; + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; } - - len = 0; - for (i = 0; i < 8; i++) - { - if (zr[i] != 0) - { - /* check for leading zero */ - if (i == 0) tmp[len++] = ':'; - tmp[len++] = ':'; - i += (zr[i] - 1); + 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; } - for (j = 0; hexa[i][j] != '\0'; j++) tmp[len++] = hexa[i][j]; - if (i != 7) tmp[len++] = ':'; + /* 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))) { + struct in_addr ipv4_addr; + memcpy(&ipv4_addr, src+12, sizeof(ipv4_addr)); + if (!inet_ntop4(&ipv4_addr, tp, (socklen_t)sizeof(tmp) - (socklen_t)(tp - tmp))) { + errno = ENOSPC; + return (NULL); + } + tp += strlen(tp); + break; + } + tp += sprintf(tp, "%x", words[i]); } - - /* trailing NULL */ - len++; - - if (len > size) - { + /* Was it a trailing run of 0x00's? */ + if (best.base != -1 && (best.base + best.len) == + (NS_IN6ADDRSZ / NS_INT16SZ)) + *tp++ = ':'; + *tp++ = '\0'; + + /* + * Check for overflow, copy, and we're done. + */ + if ((socklen_t)(tp - tmp) > size) { errno = ENOSPC; - return NULL; + return (NULL); } - - memcpy(dst, tmp, len); - return dst; + strcpy(dst, tmp); + return (dst); } const char * @@ -155,16 +171,15 @@ inet_ntop4(const struct in_addr *addr, char *dst, socklen_t size) { char tmp[MAX_V4_ADDR_LEN], *p; const u_int8_t *ap = (u_int8_t *)&addr->s_addr; - int i, ql, len; + int i; + size_t ql, len; - if (addr == NULL) - { + if (addr == NULL) { errno = EAFNOSUPPORT; return NULL; } - if (dst == NULL) - { + if (dst == NULL) { errno = ENOSPC; return NULL; } @@ -176,8 +191,7 @@ inet_ntop4(const struct in_addr *addr, char *dst, socklen_t size) p = tmp; - for (i = 0; i < 4; i++, ap++) - { + for (i = 0; i < 4; i++, ap++) { snprintf(p, 4, "%d", *ap); ql = strlen(p); len += ql; @@ -185,8 +199,7 @@ inet_ntop4(const struct in_addr *addr, char *dst, socklen_t size) if (i < 3) *p++ = '.'; } - if (len > size) - { + if (len > size) { errno = ENOSPC; return NULL; } @@ -194,13 +207,3 @@ inet_ntop4(const struct in_addr *addr, char *dst, socklen_t size) memcpy(dst, tmp, len); return dst; } - -const char * -inet_ntop(int af, const void *addr, char *buf, socklen_t len) -{ - if (af == AF_INET6) return inet_ntop6(addr, buf, len); - if (af == AF_INET) return inet_ntop4(addr, buf, len); - - errno = EAFNOSUPPORT; - return NULL; -}