Annotation of embedaddon/rsync/lib/inet_ntop.c, revision 1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>