modules/ip/inet_ntop.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. inet_ntop
  2. inet_ntop4
  3. inet_ntop6

   1 /*      $OpenBSD: inet_ntop.c,v 1.1 1997/03/13 19:07:32 downsj 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 #define __P(a) a
  19 
  20 #if defined(LIBC_SCCS) && !defined(lint)
  21 #if 0
  22 static char rcsid[] = "$From: inet_ntop.c,v 8.7 1996/08/05 08:41:18 vixie Exp $";
  23 #else
  24 static char rcsid[] = "$OpenBSD: inet_ntop.c,v 1.1 1997/03/13 19:07:32 downsj Exp $";
  25 #endif
  26 #endif /* LIBC_SCCS and not lint */
  27 
  28 #include <sys/param.h>
  29 #include <sys/types.h>
  30 #include <sys/socket.h>
  31 #include <netinet/in.h>
  32 #include <arpa/inet.h>
  33 #include <arpa/nameser.h>
  34 
  35 #include <string.h>
  36 #include <errno.h>
  37 #include <stdio.h>
  38 
  39 #include "inet6def.h"
  40 
  41 /*
  42  * WARNING: Don't even consider trying to compile this on a system where
  43  * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
  44  */
  45 
  46 static const char *inet_ntop4 __P((const u_char *src, char *dst, size_t size));
  47 static const char *inet_ntop6 __P((const u_char *src, char *dst, size_t size));
  48 
  49 /* char *
  50  * inet_ntop(af, src, dst, size)
  51  *      convert a network format address to presentation format.
  52  * return:
  53  *      pointer to presentation format address (`dst'), or NULL (see errno).
  54  * author:
  55  *      Paul Vixie, 1996.
  56  */
  57 const char *
  58 inet_ntop(af, src, dst, size)
     /* [<][>][^][v][top][bottom][index][help] */
  59         int af;
  60         const void *src;
  61         char *dst;
  62         size_t size;
  63 {
  64         switch (af) {
  65         case AF_INET:
  66                 return (inet_ntop4(src, dst, size));
  67         case AF_INET6:
  68                 return (inet_ntop6(src, dst, size));
  69         default:
  70                 errno = EAFNOSUPPORT;
  71                 return (NULL);
  72         }
  73         /* NOTREACHED */
  74 }
  75 
  76 /* const char *
  77  * inet_ntop4(src, dst, size)
  78  *      format an IPv4 address, more or less like inet_ntoa()
  79  * return:
  80  *      `dst' (as a const)
  81  * notes:
  82  *      (1) uses no statics
  83  *      (2) takes a u_char* not an in_addr as input
  84  * author:
  85  *      Paul Vixie, 1996.
  86  */
  87 static const char *
  88 inet_ntop4(src, dst, size)
     /* [<][>][^][v][top][bottom][index][help] */
  89         const u_char *src;
  90         char *dst;
  91         size_t size;
  92 {
  93         static const char fmt[] = "%u.%u.%u.%u";
  94         char tmp[sizeof "255.255.255.255"];
  95 
  96         if (sprintf(tmp, fmt, src[0], src[1], src[2], src[3]) > size) {
  97                 errno = ENOSPC;
  98                 return (NULL);
  99         }
 100         strcpy(dst, tmp);
 101         return (dst);
 102 }
 103 
 104 /* const char *
 105  * inet_ntop6(src, dst, size)
 106  *      convert IPv6 binary address into presentation (printable) format
 107  * author:
 108  *      Paul Vixie, 1996.
 109  */
 110 static const char *
 111 inet_ntop6(src, dst, size)
     /* [<][>][^][v][top][bottom][index][help] */
 112         const u_char *src;
 113         char *dst;
 114         size_t size;
 115 {
 116         /*
 117          * Note that int32_t and int16_t need only be "at least" large enough
 118          * to contain a value of the specified size.  On some systems, like
 119          * Crays, there is no such thing as an integer variable with 16 bits.
 120          * Keep this in mind if you think this function should have been coded
 121          * to use pointer overlays.  All the world's not a VAX.
 122          */
 123         char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
 124         struct { int base, len; } best, cur;
 125         u_int words[IN6ADDRSZ / INT16SZ];
 126         int i;
 127 
 128         /*
 129          * Preprocess:
 130          *      Copy the input (bytewise) array into a wordwise array.
 131          *      Find the longest run of 0x00's in src[] for :: shorthanding.
 132          */
 133         memset(words, '\0', sizeof words);
 134         for (i = 0; i < IN6ADDRSZ; i++)
 135                 words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
 136         best.base = -1;
 137         cur.base = -1;
 138         for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
 139                 if (words[i] == 0) {
 140                         if (cur.base == -1)
 141                                 cur.base = i, cur.len = 1;
 142                         else
 143                                 cur.len++;
 144                 } else {
 145                         if (cur.base != -1) {
 146                                 if (best.base == -1 || cur.len > best.len)
 147                                         best = cur;
 148                                 cur.base = -1;
 149                         }
 150                 }
 151         }
 152         if (cur.base != -1) {
 153                 if (best.base == -1 || cur.len > best.len)
 154                         best = cur;
 155         }
 156         if (best.base != -1 && best.len < 2)
 157                 best.base = -1;
 158 
 159         /*
 160          * Format the result.
 161          */
 162         tp = tmp;
 163         for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
 164                 /* Are we inside the best run of 0x00's? */
 165                 if (best.base != -1 && i >= best.base &&
 166                     i < (best.base + best.len)) {
 167                         if (i == best.base)
 168                                 *tp++ = ':';
 169                         continue;
 170                 }
 171                 /* Are we following an initial run of 0x00s or any real hex? */
 172                 if (i != 0)
 173                         *tp++ = ':';
 174                 /* Is this address an encapsulated IPv4? */
 175                 if (i == 6 && best.base == 0 &&
 176                     (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
 177                         if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
 178                                 return (NULL);
 179                         tp += strlen(tp);
 180                         break;
 181                 }
 182                 tp += sprintf(tp, "%x", words[i]);
 183         }
 184         /* Was it a trailing run of 0x00's? */
 185         if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
 186                 *tp++ = ':';
 187         *tp++ = '\0';
 188 
 189         /*
 190          * Check for overflow, copy, and we're done.
 191          */
 192         if ((size_t)(tp - tmp) > size) {
 193                 errno = ENOSPC;
 194                 return (NULL);
 195         }
 196         strcpy(dst, tmp);
 197         return (dst);
 198 }

/* [<][>][^][v][top][bottom][index][help] */