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>