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

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 1996-2019  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:  * Original code by Paul Vixie. "curlified" by Gisle Vanem.
        !            19:  */
        !            20: 
        !            21: #include "curl_setup.h"
        !            22: 
        !            23: #ifndef HAVE_INET_NTOP
        !            24: 
        !            25: #ifdef HAVE_SYS_PARAM_H
        !            26: #include <sys/param.h>
        !            27: #endif
        !            28: #ifdef HAVE_NETINET_IN_H
        !            29: #include <netinet/in.h>
        !            30: #endif
        !            31: #ifdef HAVE_ARPA_INET_H
        !            32: #include <arpa/inet.h>
        !            33: #endif
        !            34: 
        !            35: #include "inet_ntop.h"
        !            36: #include "curl_printf.h"
        !            37: 
        !            38: #define IN6ADDRSZ       16
        !            39: #define INADDRSZ         4
        !            40: #define INT16SZ          2
        !            41: 
        !            42: /*
        !            43:  * Format an IPv4 address, more or less like inet_ntoa().
        !            44:  *
        !            45:  * Returns `dst' (as a const)
        !            46:  * Note:
        !            47:  *  - uses no statics
        !            48:  *  - takes a unsigned char* not an in_addr as input
        !            49:  */
        !            50: static char *inet_ntop4 (const unsigned char *src, char *dst, size_t size)
        !            51: {
        !            52:   char tmp[sizeof("255.255.255.255")];
        !            53:   size_t len;
        !            54: 
        !            55:   DEBUGASSERT(size >= 16);
        !            56: 
        !            57:   tmp[0] = '\0';
        !            58:   (void)msnprintf(tmp, sizeof(tmp), "%d.%d.%d.%d",
        !            59:                   ((int)((unsigned char)src[0])) & 0xff,
        !            60:                   ((int)((unsigned char)src[1])) & 0xff,
        !            61:                   ((int)((unsigned char)src[2])) & 0xff,
        !            62:                   ((int)((unsigned char)src[3])) & 0xff);
        !            63: 
        !            64:   len = strlen(tmp);
        !            65:   if(len == 0 || len >= size) {
        !            66:     errno = ENOSPC;
        !            67:     return (NULL);
        !            68:   }
        !            69:   strcpy(dst, tmp);
        !            70:   return dst;
        !            71: }
        !            72: 
        !            73: #ifdef ENABLE_IPV6
        !            74: /*
        !            75:  * Convert IPv6 binary address into presentation (printable) format.
        !            76:  */
        !            77: static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size)
        !            78: {
        !            79:   /*
        !            80:    * Note that int32_t and int16_t need only be "at least" large enough
        !            81:    * to contain a value of the specified size.  On some systems, like
        !            82:    * Crays, there is no such thing as an integer variable with 16 bits.
        !            83:    * Keep this in mind if you think this function should have been coded
        !            84:    * to use pointer overlays.  All the world's not a VAX.
        !            85:    */
        !            86:   char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
        !            87:   char *tp;
        !            88:   struct {
        !            89:     long base;
        !            90:     long len;
        !            91:   } best, cur;
        !            92:   unsigned long words[IN6ADDRSZ / INT16SZ];
        !            93:   int i;
        !            94: 
        !            95:   /* Preprocess:
        !            96:    *  Copy the input (bytewise) array into a wordwise array.
        !            97:    *  Find the longest run of 0x00's in src[] for :: shorthanding.
        !            98:    */
        !            99:   memset(words, '\0', sizeof(words));
        !           100:   for(i = 0; i < IN6ADDRSZ; i++)
        !           101:     words[i/2] |= (src[i] << ((1 - (i % 2)) << 3));
        !           102: 
        !           103:   best.base = -1;
        !           104:   cur.base  = -1;
        !           105:   best.len = 0;
        !           106:   cur.len = 0;
        !           107: 
        !           108:   for(i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
        !           109:     if(words[i] == 0) {
        !           110:       if(cur.base == -1)
        !           111:         cur.base = i, cur.len = 1;
        !           112:       else
        !           113:         cur.len++;
        !           114:     }
        !           115:     else if(cur.base != -1) {
        !           116:       if(best.base == -1 || cur.len > best.len)
        !           117:         best = cur;
        !           118:       cur.base = -1;
        !           119:     }
        !           120:   }
        !           121:   if((cur.base != -1) && (best.base == -1 || cur.len > best.len))
        !           122:     best = cur;
        !           123:   if(best.base != -1 && best.len < 2)
        !           124:     best.base = -1;
        !           125:   /* Format the result. */
        !           126:   tp = tmp;
        !           127:   for(i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
        !           128:     /* Are we inside the best run of 0x00's? */
        !           129:     if(best.base != -1 && i >= best.base && i < (best.base + best.len)) {
        !           130:       if(i == best.base)
        !           131:         *tp++ = ':';
        !           132:       continue;
        !           133:     }
        !           134: 
        !           135:     /* Are we following an initial run of 0x00s or any real hex?
        !           136:      */
        !           137:     if(i != 0)
        !           138:       *tp++ = ':';
        !           139: 
        !           140:     /* Is this address an encapsulated IPv4?
        !           141:      */
        !           142:     if(i == 6 && best.base == 0 &&
        !           143:         (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
        !           144:       if(!inet_ntop4(src + 12, tp, sizeof(tmp) - (tp - tmp))) {
        !           145:         errno = ENOSPC;
        !           146:         return (NULL);
        !           147:       }
        !           148:       tp += strlen(tp);
        !           149:       break;
        !           150:     }
        !           151:     tp += msnprintf(tp, 5, "%lx", words[i]);
        !           152:   }
        !           153: 
        !           154:   /* Was it a trailing run of 0x00's?
        !           155:    */
        !           156:   if(best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
        !           157:      *tp++ = ':';
        !           158:   *tp++ = '\0';
        !           159: 
        !           160:   /* Check for overflow, copy, and we're done.
        !           161:    */
        !           162:   if((size_t)(tp - tmp) > size) {
        !           163:     errno = ENOSPC;
        !           164:     return (NULL);
        !           165:   }
        !           166:   strcpy(dst, tmp);
        !           167:   return dst;
        !           168: }
        !           169: #endif  /* ENABLE_IPV6 */
        !           170: 
        !           171: /*
        !           172:  * Convert a network format address to presentation format.
        !           173:  *
        !           174:  * Returns pointer to presentation format address (`buf').
        !           175:  * Returns NULL on error and errno set with the specific
        !           176:  * error, EAFNOSUPPORT or ENOSPC.
        !           177:  *
        !           178:  * On Windows we store the error in the thread errno, not
        !           179:  * in the winsock error code. This is to avoid losing the
        !           180:  * actual last winsock error. So when this function returns
        !           181:  * NULL, check errno not SOCKERRNO.
        !           182:  */
        !           183: char *Curl_inet_ntop(int af, const void *src, char *buf, size_t size)
        !           184: {
        !           185:   switch(af) {
        !           186:   case AF_INET:
        !           187:     return inet_ntop4((const unsigned char *)src, buf, size);
        !           188: #ifdef ENABLE_IPV6
        !           189:   case AF_INET6:
        !           190:     return inet_ntop6((const unsigned char *)src, buf, size);
        !           191: #endif
        !           192:   default:
        !           193:     errno = EAFNOSUPPORT;
        !           194:     return NULL;
        !           195:   }
        !           196: }
        !           197: #endif  /* HAVE_INET_NTOP */

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