Blame gl/inet_ntop.c

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