Home | History | Annotate | Line # | Download | only in import
      1      1.1  christos /* inet_ntop.c -- convert IPv4 and IPv6 addresses from binary to text form
      2      1.1  christos 
      3  1.1.1.2  christos    Copyright (C) 2005-2006, 2008-2022 Free Software Foundation, Inc.
      4      1.1  christos 
      5  1.1.1.2  christos    This file is free software: you can redistribute it and/or modify
      6  1.1.1.2  christos    it under the terms of the GNU Lesser General Public License as
      7  1.1.1.2  christos    published by the Free Software Foundation; either version 2.1 of the
      8  1.1.1.2  christos    License, or (at your option) any later version.
      9      1.1  christos 
     10  1.1.1.2  christos    This file is distributed in the hope that it will be useful,
     11      1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     12      1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13  1.1.1.2  christos    GNU Lesser General Public License for more details.
     14      1.1  christos 
     15  1.1.1.2  christos    You should have received a copy of the GNU Lesser General Public License
     16  1.1.1.2  christos    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
     17      1.1  christos 
     18      1.1  christos /*
     19      1.1  christos  * Copyright (c) 1996-1999 by Internet Software Consortium.
     20      1.1  christos  *
     21      1.1  christos  * Permission to use, copy, modify, and distribute this software for any
     22      1.1  christos  * purpose with or without fee is hereby granted, provided that the above
     23      1.1  christos  * copyright notice and this permission notice appear in all copies.
     24      1.1  christos  *
     25      1.1  christos  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
     26      1.1  christos  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
     27      1.1  christos  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
     28      1.1  christos  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
     29      1.1  christos  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
     30      1.1  christos  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
     31      1.1  christos  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
     32      1.1  christos  * SOFTWARE.
     33      1.1  christos  */
     34      1.1  christos 
     35      1.1  christos #include <config.h>
     36      1.1  christos 
     37      1.1  christos /* Specification.  */
     38      1.1  christos #include <arpa/inet.h>
     39      1.1  christos 
     40      1.1  christos /* Use this to suppress gcc's "...may be used before initialized" warnings.
     41      1.1  christos    Beware: The Code argument must not contain commas.  */
     42      1.1  christos #ifndef IF_LINT
     43      1.1  christos # if defined GCC_LINT || defined lint
     44      1.1  christos #  define IF_LINT(Code) Code
     45      1.1  christos # else
     46      1.1  christos #  define IF_LINT(Code) /* empty */
     47      1.1  christos # endif
     48      1.1  christos #endif
     49      1.1  christos 
     50      1.1  christos #if HAVE_DECL_INET_NTOP
     51      1.1  christos 
     52      1.1  christos # undef inet_ntop
     53      1.1  christos 
     54      1.1  christos const char *
     55      1.1  christos rpl_inet_ntop (int af, const void *restrict src,
     56      1.1  christos                char *restrict dst, socklen_t cnt)
     57      1.1  christos {
     58      1.1  christos   return inet_ntop (af, src, dst, cnt);
     59      1.1  christos }
     60      1.1  christos 
     61      1.1  christos #else
     62      1.1  christos 
     63      1.1  christos # include <stdio.h>
     64      1.1  christos # include <string.h>
     65      1.1  christos # include <errno.h>
     66      1.1  christos 
     67      1.1  christos # define NS_IN6ADDRSZ 16
     68      1.1  christos # define NS_INT16SZ 2
     69      1.1  christos 
     70      1.1  christos /*
     71      1.1  christos  * WARNING: Don't even consider trying to compile this on a system where
     72      1.1  christos  * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
     73      1.1  christos  */
     74      1.1  christos typedef int verify_int_size[4 <= sizeof (int) ? 1 : -1];
     75      1.1  christos 
     76      1.1  christos static const char *inet_ntop4 (const unsigned char *src, char *dst, socklen_t size);
     77      1.1  christos # if HAVE_IPV6
     78      1.1  christos static const char *inet_ntop6 (const unsigned char *src, char *dst, socklen_t size);
     79      1.1  christos # endif
     80      1.1  christos 
     81      1.1  christos 
     82      1.1  christos /* char *
     83      1.1  christos  * inet_ntop(af, src, dst, size)
     84      1.1  christos  *      convert a network format address to presentation format.
     85      1.1  christos  * return:
     86      1.1  christos  *      pointer to presentation format address ('dst'), or NULL (see errno).
     87      1.1  christos  * author:
     88      1.1  christos  *      Paul Vixie, 1996.
     89      1.1  christos  */
     90      1.1  christos const char *
     91      1.1  christos inet_ntop (int af, const void *restrict src,
     92      1.1  christos            char *restrict dst, socklen_t cnt)
     93      1.1  christos {
     94      1.1  christos   switch (af)
     95      1.1  christos     {
     96      1.1  christos # if HAVE_IPV4
     97      1.1  christos     case AF_INET:
     98      1.1  christos       return (inet_ntop4 (src, dst, cnt));
     99      1.1  christos # endif
    100      1.1  christos 
    101      1.1  christos # if HAVE_IPV6
    102      1.1  christos     case AF_INET6:
    103      1.1  christos       return (inet_ntop6 (src, dst, cnt));
    104      1.1  christos # endif
    105      1.1  christos 
    106      1.1  christos     default:
    107      1.1  christos       errno = EAFNOSUPPORT;
    108      1.1  christos       return (NULL);
    109      1.1  christos     }
    110      1.1  christos   /* NOTREACHED */
    111      1.1  christos }
    112      1.1  christos 
    113      1.1  christos /* const char *
    114      1.1  christos  * inet_ntop4(src, dst, size)
    115      1.1  christos  *      format an IPv4 address
    116      1.1  christos  * return:
    117      1.1  christos  *      'dst' (as a const)
    118      1.1  christos  * notes:
    119      1.1  christos  *      (1) uses no statics
    120      1.1  christos  *      (2) takes a u_char* not an in_addr as input
    121      1.1  christos  * author:
    122      1.1  christos  *      Paul Vixie, 1996.
    123      1.1  christos  */
    124      1.1  christos static const char *
    125      1.1  christos inet_ntop4 (const unsigned char *src, char *dst, socklen_t size)
    126      1.1  christos {
    127      1.1  christos   char tmp[sizeof "255.255.255.255"];
    128      1.1  christos   int len;
    129      1.1  christos 
    130      1.1  christos   len = sprintf (tmp, "%u.%u.%u.%u", src[0], src[1], src[2], src[3]);
    131      1.1  christos   if (len < 0)
    132      1.1  christos     return NULL;
    133      1.1  christos 
    134      1.1  christos   if (len > size)
    135      1.1  christos     {
    136      1.1  christos       errno = ENOSPC;
    137      1.1  christos       return NULL;
    138      1.1  christos     }
    139      1.1  christos 
    140      1.1  christos   return strcpy (dst, tmp);
    141      1.1  christos }
    142      1.1  christos 
    143      1.1  christos # if HAVE_IPV6
    144      1.1  christos 
    145      1.1  christos /* const char *
    146      1.1  christos  * inet_ntop6(src, dst, size)
    147      1.1  christos  *      convert IPv6 binary address into presentation (printable) format
    148      1.1  christos  * author:
    149      1.1  christos  *      Paul Vixie, 1996.
    150      1.1  christos  */
    151      1.1  christos static const char *
    152      1.1  christos inet_ntop6 (const unsigned char *src, char *dst, socklen_t size)
    153      1.1  christos {
    154      1.1  christos   /*
    155      1.1  christos    * Note that int32_t and int16_t need only be "at least" large enough
    156      1.1  christos    * to contain a value of the specified size.  On some systems, like
    157      1.1  christos    * Crays, there is no such thing as an integer variable with 16 bits.
    158      1.1  christos    * Keep this in mind if you think this function should have been coded
    159      1.1  christos    * to use pointer overlays.  All the world's not a VAX.
    160      1.1  christos    */
    161      1.1  christos   char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
    162      1.1  christos   struct
    163      1.1  christos   {
    164      1.1  christos     int base, len;
    165      1.1  christos   } best, cur;
    166      1.1  christos   unsigned int words[NS_IN6ADDRSZ / NS_INT16SZ];
    167      1.1  christos   int i;
    168      1.1  christos 
    169      1.1  christos   /*
    170      1.1  christos    * Preprocess:
    171      1.1  christos    *      Copy the input (bytewise) array into a wordwise array.
    172      1.1  christos    *      Find the longest run of 0x00's in src[] for :: shorthanding.
    173      1.1  christos    */
    174      1.1  christos   memset (words, '\0', sizeof words);
    175      1.1  christos   for (i = 0; i < NS_IN6ADDRSZ; i += 2)
    176      1.1  christos     words[i / 2] = (src[i] << 8) | src[i + 1];
    177      1.1  christos   best.base = -1;
    178      1.1  christos   cur.base = -1;
    179      1.1  christos   IF_LINT(best.len = 0);
    180      1.1  christos   IF_LINT(cur.len = 0);
    181      1.1  christos   for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++)
    182      1.1  christos     {
    183      1.1  christos       if (words[i] == 0)
    184      1.1  christos         {
    185      1.1  christos           if (cur.base == -1)
    186      1.1  christos             cur.base = i, cur.len = 1;
    187      1.1  christos           else
    188      1.1  christos             cur.len++;
    189      1.1  christos         }
    190      1.1  christos       else
    191      1.1  christos         {
    192      1.1  christos           if (cur.base != -1)
    193      1.1  christos             {
    194      1.1  christos               if (best.base == -1 || cur.len > best.len)
    195      1.1  christos                 best = cur;
    196      1.1  christos               cur.base = -1;
    197      1.1  christos             }
    198      1.1  christos         }
    199      1.1  christos     }
    200      1.1  christos   if (cur.base != -1)
    201      1.1  christos     {
    202      1.1  christos       if (best.base == -1 || cur.len > best.len)
    203      1.1  christos         best = cur;
    204      1.1  christos     }
    205      1.1  christos   if (best.base != -1 && best.len < 2)
    206      1.1  christos     best.base = -1;
    207      1.1  christos 
    208      1.1  christos   /*
    209      1.1  christos    * Format the result.
    210      1.1  christos    */
    211      1.1  christos   tp = tmp;
    212      1.1  christos   for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++)
    213      1.1  christos     {
    214      1.1  christos       /* Are we inside the best run of 0x00's? */
    215      1.1  christos       if (best.base != -1 && i >= best.base && i < (best.base + best.len))
    216      1.1  christos         {
    217      1.1  christos           if (i == best.base)
    218      1.1  christos             *tp++ = ':';
    219      1.1  christos           continue;
    220      1.1  christos         }
    221      1.1  christos       /* Are we following an initial run of 0x00s or any real hex? */
    222      1.1  christos       if (i != 0)
    223      1.1  christos         *tp++ = ':';
    224      1.1  christos       /* Is this address an encapsulated IPv4? */
    225      1.1  christos       if (i == 6 && best.base == 0 &&
    226      1.1  christos           (best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
    227      1.1  christos         {
    228      1.1  christos           if (!inet_ntop4 (src + 12, tp, sizeof tmp - (tp - tmp)))
    229      1.1  christos             return (NULL);
    230      1.1  christos           tp += strlen (tp);
    231      1.1  christos           break;
    232      1.1  christos         }
    233      1.1  christos       {
    234      1.1  christos         int len = sprintf (tp, "%x", words[i]);
    235      1.1  christos         if (len < 0)
    236      1.1  christos           return NULL;
    237      1.1  christos         tp += len;
    238      1.1  christos       }
    239      1.1  christos     }
    240      1.1  christos   /* Was it a trailing run of 0x00's? */
    241      1.1  christos   if (best.base != -1 && (best.base + best.len) ==
    242      1.1  christos       (NS_IN6ADDRSZ / NS_INT16SZ))
    243      1.1  christos     *tp++ = ':';
    244      1.1  christos   *tp++ = '\0';
    245      1.1  christos 
    246      1.1  christos   /*
    247      1.1  christos    * Check for overflow, copy, and we're done.
    248      1.1  christos    */
    249      1.1  christos   if ((socklen_t) (tp - tmp) > size)
    250      1.1  christos     {
    251      1.1  christos       errno = ENOSPC;
    252      1.1  christos       return NULL;
    253      1.1  christos     }
    254      1.1  christos 
    255      1.1  christos   return strcpy (dst, tmp);
    256      1.1  christos }
    257      1.1  christos 
    258      1.1  christos # endif
    259      1.1  christos 
    260      1.1  christos #endif
    261