Return to inet_ntop.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / ntp / lib / isc |
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 */