gonzui


Format: Advanced Search

t2ex/bsd_source/lib/libc/src_bsd/arpa_inet/inet_ntop.cbare sourcepermlink (0.03 seconds)

Search this content:

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