Blame gl/inet_ntop.c

Packit Service 4684c1
/* inet_ntop.c -- convert IPv4 and IPv6 addresses from binary to text form
Packit Service 4684c1
Packit Service 4684c1
   Copyright (C) 2005-2006, 2008-2020 Free Software Foundation, Inc.
Packit Service 4684c1
Packit Service 4684c1
   This program is free software; you can redistribute it and/or modify
Packit Service 4684c1
   it under the terms of the GNU Lesser General Public License as published by
Packit Service 4684c1
   the Free Software Foundation; either version 2.1, or (at your option)
Packit Service 4684c1
   any later version.
Packit Service 4684c1
Packit Service 4684c1
   This program is distributed in the hope that it will be useful,
Packit Service 4684c1
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 4684c1
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 4684c1
   GNU Lesser General Public License for more details.
Packit Service 4684c1
Packit Service 4684c1
   You should have received a copy of the GNU Lesser General Public License
Packit Service 4684c1
   along with this program; if not, see <https://www.gnu.org/licenses/>.  */
Packit Service 4684c1
Packit Service 4684c1
/*
Packit Service 4684c1
 * Copyright (c) 1996-1999 by Internet Software Consortium.
Packit Service 4684c1
 *
Packit Service 4684c1
 * Permission to use, copy, modify, and distribute this software for any
Packit Service 4684c1
 * purpose with or without fee is hereby granted, provided that the above
Packit Service 4684c1
 * copyright notice and this permission notice appear in all copies.
Packit Service 4684c1
 *
Packit Service 4684c1
 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
Packit Service 4684c1
 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
Packit Service 4684c1
 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
Packit Service 4684c1
 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
Packit Service 4684c1
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
Packit Service 4684c1
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
Packit Service 4684c1
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
Packit Service 4684c1
 * SOFTWARE.
Packit Service 4684c1
 */
Packit Service 4684c1
Packit Service 4684c1
#include <config.h>
Packit Service 4684c1
Packit Service 4684c1
/* Specification.  */
Packit Service 4684c1
#include <arpa/inet.h>
Packit Service 4684c1
Packit Service 4684c1
/* Use this to suppress gcc's "...may be used before initialized" warnings.
Packit Service 4684c1
   Beware: The Code argument must not contain commas.  */
Packit Service 4684c1
#ifndef IF_LINT
Packit Service 4684c1
# if defined GCC_LINT || defined lint
Packit Service 4684c1
#  define IF_LINT(Code) Code
Packit Service 4684c1
# else
Packit Service 4684c1
#  define IF_LINT(Code) /* empty */
Packit Service 4684c1
# endif
Packit Service 4684c1
#endif
Packit Service 4684c1
Packit Service 4684c1
#if HAVE_DECL_INET_NTOP
Packit Service 4684c1
Packit Service 4684c1
# undef inet_ntop
Packit Service 4684c1
Packit Service 4684c1
const char *
Packit Service 4684c1
rpl_inet_ntop (int af, const void *restrict src,
Packit Service 4684c1
               char *restrict dst, socklen_t cnt)
Packit Service 4684c1
{
Packit Service 4684c1
  return inet_ntop (af, src, dst, cnt);
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
#else
Packit Service 4684c1
Packit Service 4684c1
# include <stdio.h>
Packit Service 4684c1
# include <string.h>
Packit Service 4684c1
# include <errno.h>
Packit Service 4684c1
Packit Service 4684c1
# define NS_IN6ADDRSZ 16
Packit Service 4684c1
# define NS_INT16SZ 2
Packit Service 4684c1
Packit Service 4684c1
/*
Packit Service 4684c1
 * WARNING: Don't even consider trying to compile this on a system where
Packit Service 4684c1
 * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
Packit Service 4684c1
 */
Packit Service 4684c1
typedef int verify_int_size[4 <= sizeof (int) ? 1 : -1];
Packit Service 4684c1
Packit Service 4684c1
static const char *inet_ntop4 (const unsigned char *src, char *dst, socklen_t size);
Packit Service 4684c1
# if HAVE_IPV6
Packit Service 4684c1
static const char *inet_ntop6 (const unsigned char *src, char *dst, socklen_t size);
Packit Service 4684c1
# endif
Packit Service 4684c1
Packit Service 4684c1
Packit Service 4684c1
/* char *
Packit Service 4684c1
 * inet_ntop(af, src, dst, size)
Packit Service 4684c1
 *      convert a network format address to presentation format.
Packit Service 4684c1
 * return:
Packit Service 4684c1
 *      pointer to presentation format address ('dst'), or NULL (see errno).
Packit Service 4684c1
 * author:
Packit Service 4684c1
 *      Paul Vixie, 1996.
Packit Service 4684c1
 */
Packit Service 4684c1
const char *
Packit Service 4684c1
inet_ntop (int af, const void *restrict src,
Packit Service 4684c1
           char *restrict dst, socklen_t cnt)
Packit Service 4684c1
{
Packit Service 4684c1
  switch (af)
Packit Service 4684c1
    {
Packit Service 4684c1
# if HAVE_IPV4
Packit Service 4684c1
    case AF_INET:
Packit Service 4684c1
      return (inet_ntop4 (src, dst, cnt));
Packit Service 4684c1
# endif
Packit Service 4684c1
Packit Service 4684c1
# if HAVE_IPV6
Packit Service 4684c1
    case AF_INET6:
Packit Service 4684c1
      return (inet_ntop6 (src, dst, cnt));
Packit Service 4684c1
# endif
Packit Service 4684c1
Packit Service 4684c1
    default:
Packit Service 4684c1
      errno = EAFNOSUPPORT;
Packit Service 4684c1
      return (NULL);
Packit Service 4684c1
    }
Packit Service 4684c1
  /* NOTREACHED */
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/* const char *
Packit Service 4684c1
 * inet_ntop4(src, dst, size)
Packit Service 4684c1
 *      format an IPv4 address
Packit Service 4684c1
 * return:
Packit Service 4684c1
 *      'dst' (as a const)
Packit Service 4684c1
 * notes:
Packit Service 4684c1
 *      (1) uses no statics
Packit Service 4684c1
 *      (2) takes a u_char* not an in_addr as input
Packit Service 4684c1
 * author:
Packit Service 4684c1
 *      Paul Vixie, 1996.
Packit Service 4684c1
 */
Packit Service 4684c1
static const char *
Packit Service 4684c1
inet_ntop4 (const unsigned char *src, char *dst, socklen_t size)
Packit Service 4684c1
{
Packit Service 4684c1
  char tmp[sizeof "255.255.255.255"];
Packit Service 4684c1
  int len;
Packit Service 4684c1
Packit Service 4684c1
  len = sprintf (tmp, "%u.%u.%u.%u", src[0], src[1], src[2], src[3]);
Packit Service 4684c1
  if (len < 0)
Packit Service 4684c1
    return NULL;
Packit Service 4684c1
Packit Service 4684c1
  if (len > size)
Packit Service 4684c1
    {
Packit Service 4684c1
      errno = ENOSPC;
Packit Service 4684c1
      return NULL;
Packit Service 4684c1
    }
Packit Service 4684c1
Packit Service 4684c1
  return strcpy (dst, tmp);
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
# if HAVE_IPV6
Packit Service 4684c1
Packit Service 4684c1
/* const char *
Packit Service 4684c1
 * inet_ntop6(src, dst, size)
Packit Service 4684c1
 *      convert IPv6 binary address into presentation (printable) format
Packit Service 4684c1
 * author:
Packit Service 4684c1
 *      Paul Vixie, 1996.
Packit Service 4684c1
 */
Packit Service 4684c1
static const char *
Packit Service 4684c1
inet_ntop6 (const unsigned char *src, char *dst, socklen_t size)
Packit Service 4684c1
{
Packit Service 4684c1
  /*
Packit Service 4684c1
   * Note that int32_t and int16_t need only be "at least" large enough
Packit Service 4684c1
   * to contain a value of the specified size.  On some systems, like
Packit Service 4684c1
   * Crays, there is no such thing as an integer variable with 16 bits.
Packit Service 4684c1
   * Keep this in mind if you think this function should have been coded
Packit Service 4684c1
   * to use pointer overlays.  All the world's not a VAX.
Packit Service 4684c1
   */
Packit Service 4684c1
  char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
Packit Service 4684c1
  struct
Packit Service 4684c1
  {
Packit Service 4684c1
    int base, len;
Packit Service 4684c1
  } best, cur;
Packit Service 4684c1
  unsigned int words[NS_IN6ADDRSZ / NS_INT16SZ];
Packit Service 4684c1
  int i;
Packit Service 4684c1
Packit Service 4684c1
  /*
Packit Service 4684c1
   * Preprocess:
Packit Service 4684c1
   *      Copy the input (bytewise) array into a wordwise array.
Packit Service 4684c1
   *      Find the longest run of 0x00's in src[] for :: shorthanding.
Packit Service 4684c1
   */
Packit Service 4684c1
  memset (words, '\0', sizeof words);
Packit Service 4684c1
  for (i = 0; i < NS_IN6ADDRSZ; i += 2)
Packit Service 4684c1
    words[i / 2] = (src[i] << 8) | src[i + 1];
Packit Service 4684c1
  best.base = -1;
Packit Service 4684c1
  cur.base = -1;
Packit Service 4684c1
  IF_LINT(best.len = 0);
Packit Service 4684c1
  IF_LINT(cur.len = 0);
Packit Service 4684c1
  for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++)
Packit Service 4684c1
    {
Packit Service 4684c1
      if (words[i] == 0)
Packit Service 4684c1
        {
Packit Service 4684c1
          if (cur.base == -1)
Packit Service 4684c1
            cur.base = i, cur.len = 1;
Packit Service 4684c1
          else
Packit Service 4684c1
            cur.len++;
Packit Service 4684c1
        }
Packit Service 4684c1
      else
Packit Service 4684c1
        {
Packit Service 4684c1
          if (cur.base != -1)
Packit Service 4684c1
            {
Packit Service 4684c1
              if (best.base == -1 || cur.len > best.len)
Packit Service 4684c1
                best = cur;
Packit Service 4684c1
              cur.base = -1;
Packit Service 4684c1
            }
Packit Service 4684c1
        }
Packit Service 4684c1
    }
Packit Service 4684c1
  if (cur.base != -1)
Packit Service 4684c1
    {
Packit Service 4684c1
      if (best.base == -1 || cur.len > best.len)
Packit Service 4684c1
        best = cur;
Packit Service 4684c1
    }
Packit Service 4684c1
  if (best.base != -1 && best.len < 2)
Packit Service 4684c1
    best.base = -1;
Packit Service 4684c1
Packit Service 4684c1
  /*
Packit Service 4684c1
   * Format the result.
Packit Service 4684c1
   */
Packit Service 4684c1
  tp = tmp;
Packit Service 4684c1
  for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++)
Packit Service 4684c1
    {
Packit Service 4684c1
      /* Are we inside the best run of 0x00's? */
Packit Service 4684c1
      if (best.base != -1 && i >= best.base && i < (best.base + best.len))
Packit Service 4684c1
        {
Packit Service 4684c1
          if (i == best.base)
Packit Service 4684c1
            *tp++ = ':';
Packit Service 4684c1
          continue;
Packit Service 4684c1
        }
Packit Service 4684c1
      /* Are we following an initial run of 0x00s or any real hex? */
Packit Service 4684c1
      if (i != 0)
Packit Service 4684c1
        *tp++ = ':';
Packit Service 4684c1
      /* Is this address an encapsulated IPv4? */
Packit Service 4684c1
      if (i == 6 && best.base == 0 &&
Packit Service 4684c1
          (best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
Packit Service 4684c1
        {
Packit Service 4684c1
          if (!inet_ntop4 (src + 12, tp, sizeof tmp - (tp - tmp)))
Packit Service 4684c1
            return (NULL);
Packit Service 4684c1
          tp += strlen (tp);
Packit Service 4684c1
          break;
Packit Service 4684c1
        }
Packit Service 4684c1
      {
Packit Service 4684c1
        int len = sprintf (tp, "%x", words[i]);
Packit Service 4684c1
        if (len < 0)
Packit Service 4684c1
          return NULL;
Packit Service 4684c1
        tp += len;
Packit Service 4684c1
      }
Packit Service 4684c1
    }
Packit Service 4684c1
  /* Was it a trailing run of 0x00's? */
Packit Service 4684c1
  if (best.base != -1 && (best.base + best.len) ==
Packit Service 4684c1
      (NS_IN6ADDRSZ / NS_INT16SZ))
Packit Service 4684c1
    *tp++ = ':';
Packit Service 4684c1
  *tp++ = '\0';
Packit Service 4684c1
Packit Service 4684c1
  /*
Packit Service 4684c1
   * Check for overflow, copy, and we're done.
Packit Service 4684c1
   */
Packit Service 4684c1
  if ((socklen_t) (tp - tmp) > size)
Packit Service 4684c1
    {
Packit Service 4684c1
      errno = ENOSPC;
Packit Service 4684c1
      return NULL;
Packit Service 4684c1
    }
Packit Service 4684c1
Packit Service 4684c1
  return strcpy (dst, tmp);
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
# endif
Packit Service 4684c1
Packit Service 4684c1
#endif