Annotation of embedaddon/ntp/lib/isc/inet_ntop.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
! 3: * Copyright (C) 1996-2001 Internet Software Consortium.
! 4: *
! 5: * Permission to use, copy, modify, and/or distribute this software for any
! 6: * purpose with or without fee is hereby granted, provided that the above
! 7: * copyright notice and this permission notice appear in all copies.
! 8: *
! 9: * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
! 10: * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
! 11: * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
! 12: * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
! 13: * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
! 14: * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
! 15: * PERFORMANCE OF THIS SOFTWARE.
! 16: */
! 17:
! 18: /*! \file */
! 19:
! 20: #if defined(LIBC_SCCS) && !defined(lint)
! 21: static char rcsid[] =
! 22: "$Id: inet_ntop.c,v 1.19 2007/06/19 23:47:17 tbox Exp $";
! 23: #endif /* LIBC_SCCS and not lint */
! 24:
! 25: #include <config.h>
! 26:
! 27: #include <errno.h>
! 28: #include <stdio.h>
! 29: #include <string.h>
! 30:
! 31: #include <isc/net.h>
! 32: #include <isc/print.h>
! 33:
! 34: #include "ntp_sprintf.h" /* NTP local change, helps SunOS 4 */
! 35:
! 36: #define NS_INT16SZ 2
! 37: #define NS_IN6ADDRSZ 16
! 38:
! 39: /*
! 40: * WARNING: Don't even consider trying to compile this on a system where
! 41: * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
! 42: */
! 43:
! 44: static const char *inet_ntop4(const unsigned char *src, char *dst,
! 45: size_t size);
! 46:
! 47: #ifdef AF_INET6
! 48: static const char *inet_ntop6(const unsigned char *src, char *dst,
! 49: size_t size);
! 50: #endif
! 51:
! 52: /*! char *
! 53: * isc_net_ntop(af, src, dst, size)
! 54: * convert a network format address to presentation format.
! 55: * \return
! 56: * pointer to presentation format address (`dst'), or NULL (see errno).
! 57: * \author
! 58: * Paul Vixie, 1996.
! 59: */
! 60: const char *
! 61: isc_net_ntop(int af, const void *src, char *dst, size_t size)
! 62: {
! 63: switch (af) {
! 64: case AF_INET:
! 65: return (inet_ntop4(src, dst, size));
! 66: #ifdef AF_INET6
! 67: case AF_INET6:
! 68: return (inet_ntop6(src, dst, size));
! 69: #endif
! 70: default:
! 71: errno = EAFNOSUPPORT;
! 72: return (NULL);
! 73: }
! 74: /* NOTREACHED */
! 75: }
! 76:
! 77: /*! const char *
! 78: * inet_ntop4(src, dst, size)
! 79: * format an IPv4 address
! 80: * \return
! 81: * `dst' (as a const)
! 82: * \note
! 83: * (1) uses no statics
! 84: * \note
! 85: * (2) takes a unsigned char* not an in_addr as input
! 86: * \author
! 87: * Paul Vixie, 1996.
! 88: */
! 89: static const char *
! 90: inet_ntop4(const unsigned char *src, char *dst, size_t size)
! 91: {
! 92: static const char *fmt = "%u.%u.%u.%u";
! 93: char tmp[sizeof("255.255.255.255")];
! 94:
! 95: /* NTP local change to use SNPRINTF() macro for SunOS4 compat */
! 96: if (SNPRINTF((tmp, sizeof(tmp), fmt, src[0], src[1], src[2],
! 97: src[3])) >= size)
! 98: {
! 99: errno = ENOSPC;
! 100: return (NULL);
! 101: }
! 102: strcpy(dst, tmp);
! 103:
! 104: return (dst);
! 105: }
! 106:
! 107: /*! const char *
! 108: * isc_inet_ntop6(src, dst, size)
! 109: * convert IPv6 binary address into presentation (printable) format
! 110: * \author
! 111: * Paul Vixie, 1996.
! 112: */
! 113: #ifdef AF_INET6
! 114: static const char *
! 115: inet_ntop6(const unsigned char *src, char *dst, size_t size)
! 116: {
! 117: /*
! 118: * Note that int32_t and int16_t need only be "at least" large enough
! 119: * to contain a value of the specified size. On some systems, like
! 120: * Crays, there is no such thing as an integer variable with 16 bits.
! 121: * Keep this in mind if you think this function should have been coded
! 122: * to use pointer overlays. All the world's not a VAX.
! 123: */
! 124: char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")], *tp;
! 125: struct { int base, len; } best, cur;
! 126: unsigned int words[NS_IN6ADDRSZ / NS_INT16SZ];
! 127: int i;
! 128:
! 129: /*
! 130: * Preprocess:
! 131: * Copy the input (bytewise) array into a wordwise array.
! 132: * Find the longest run of 0x00's in src[] for :: shorthanding.
! 133: */
! 134: memset(words, '\0', sizeof(words));
! 135: for (i = 0; i < NS_IN6ADDRSZ; i++)
! 136: words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
! 137: best.base = -1;
! 138: cur.base = -1;
! 139: for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
! 140: if (words[i] == 0) {
! 141: if (cur.base == -1)
! 142: cur.base = i, cur.len = 1;
! 143: else
! 144: cur.len++;
! 145: } else {
! 146: if (cur.base != -1) {
! 147: if (best.base == -1 || cur.len > best.len)
! 148: best = cur;
! 149: cur.base = -1;
! 150: }
! 151: }
! 152: }
! 153: if (cur.base != -1) {
! 154: if (best.base == -1 || cur.len > best.len)
! 155: best = cur;
! 156: }
! 157: if (best.base != -1 && best.len < 2)
! 158: best.base = -1;
! 159:
! 160: /*
! 161: * Format the result.
! 162: */
! 163: tp = tmp;
! 164: for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
! 165: /* Are we inside the best run of 0x00's? */
! 166: if (best.base != -1 && i >= best.base &&
! 167: i < (best.base + best.len)) {
! 168: if (i == best.base)
! 169: *tp++ = ':';
! 170: continue;
! 171: }
! 172: /* Are we following an initial run of 0x00s or any real hex? */
! 173: if (i != 0)
! 174: *tp++ = ':';
! 175: /* Is this address an encapsulated IPv4? */
! 176: if (i == 6 && best.base == 0 &&
! 177: (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
! 178: if (!inet_ntop4(src+12, tp,
! 179: sizeof(tmp) - (tp - tmp)))
! 180: return (NULL);
! 181: tp += strlen(tp);
! 182: break;
! 183: }
! 184: tp += SPRINTF((tp, "%x", words[i])); /* NTP local change */
! 185: }
! 186: /* Was it a trailing run of 0x00's? */
! 187: if (best.base != -1 && (best.base + best.len) ==
! 188: (NS_IN6ADDRSZ / NS_INT16SZ))
! 189: *tp++ = ':';
! 190: *tp++ = '\0';
! 191:
! 192: /*
! 193: * Check for overflow, copy, and we're done.
! 194: */
! 195: if ((size_t)(tp - tmp) > size) {
! 196: errno = ENOSPC;
! 197: return (NULL);
! 198: }
! 199: strcpy(dst, tmp);
! 200: return (dst);
! 201: }
! 202: #endif /* AF_INET6 */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>