Annotation of embedaddon/ntp/lib/isc/inet_ntop.c, revision 1.1.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>