## modules/ip/inet_ntop.c

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

## DEFINITIONS

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] */