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