11cb0ef41Sopenharmony_ci/*
21cb0ef41Sopenharmony_ci * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
31cb0ef41Sopenharmony_ci * Copyright (c) 1996-1999 by Internet Software Consortium.
41cb0ef41Sopenharmony_ci *
51cb0ef41Sopenharmony_ci * Permission to use, copy, modify, and distribute this software for any
61cb0ef41Sopenharmony_ci * purpose with or without fee is hereby granted, provided that the above
71cb0ef41Sopenharmony_ci * copyright notice and this permission notice appear in all copies.
81cb0ef41Sopenharmony_ci *
91cb0ef41Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
101cb0ef41Sopenharmony_ci * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
111cb0ef41Sopenharmony_ci * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
121cb0ef41Sopenharmony_ci * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
131cb0ef41Sopenharmony_ci * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
141cb0ef41Sopenharmony_ci * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
151cb0ef41Sopenharmony_ci * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
161cb0ef41Sopenharmony_ci *
171cb0ef41Sopenharmony_ci * SPDX-License-Identifier: MIT
181cb0ef41Sopenharmony_ci */
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_ci#include "ares_setup.h"
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ci#ifdef HAVE_NETINET_IN_H
231cb0ef41Sopenharmony_ci#  include <netinet/in.h>
241cb0ef41Sopenharmony_ci#endif
251cb0ef41Sopenharmony_ci#ifdef HAVE_ARPA_INET_H
261cb0ef41Sopenharmony_ci#  include <arpa/inet.h>
271cb0ef41Sopenharmony_ci#endif
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ci#include "ares_nameser.h"
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_ci#include "ares.h"
321cb0ef41Sopenharmony_ci#include "ares_ipv6.h"
331cb0ef41Sopenharmony_ci#include "ares_private.h"
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ci#ifndef HAVE_INET_NTOP
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_ci/*
381cb0ef41Sopenharmony_ci * WARNING: Don't even consider trying to compile this on a system where
391cb0ef41Sopenharmony_ci * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
401cb0ef41Sopenharmony_ci */
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_cistatic const char *inet_ntop4(const unsigned char *src, char *dst, size_t size);
431cb0ef41Sopenharmony_cistatic const char *inet_ntop6(const unsigned char *src, char *dst, size_t size);
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ci/* char *
461cb0ef41Sopenharmony_ci * inet_ntop(af, src, dst, size)
471cb0ef41Sopenharmony_ci *     convert a network format address to presentation format.
481cb0ef41Sopenharmony_ci * return:
491cb0ef41Sopenharmony_ci *     pointer to presentation format address (`dst'), or NULL (see errno).
501cb0ef41Sopenharmony_ci * note:
511cb0ef41Sopenharmony_ci *     On Windows we store the error in the thread errno, not
521cb0ef41Sopenharmony_ci *     in the winsock error code. This is to avoid losing the
531cb0ef41Sopenharmony_ci *     actual last winsock error. So use macro ERRNO to fetch the
541cb0ef41Sopenharmony_ci *     errno this function sets when returning NULL, not SOCKERRNO.
551cb0ef41Sopenharmony_ci * author:
561cb0ef41Sopenharmony_ci *     Paul Vixie, 1996.
571cb0ef41Sopenharmony_ci */
581cb0ef41Sopenharmony_ciconst char        *ares_inet_ntop(int af, const void *src, char *dst,
591cb0ef41Sopenharmony_ci                                  ares_socklen_t size)
601cb0ef41Sopenharmony_ci{
611cb0ef41Sopenharmony_ci  switch (af) {
621cb0ef41Sopenharmony_ci    case AF_INET:
631cb0ef41Sopenharmony_ci      return (inet_ntop4(src, dst, (size_t)size));
641cb0ef41Sopenharmony_ci    case AF_INET6:
651cb0ef41Sopenharmony_ci      return (inet_ntop6(src, dst, (size_t)size));
661cb0ef41Sopenharmony_ci    default:
671cb0ef41Sopenharmony_ci      SET_ERRNO(EAFNOSUPPORT);
681cb0ef41Sopenharmony_ci      return (NULL);
691cb0ef41Sopenharmony_ci  }
701cb0ef41Sopenharmony_ci  /* NOTREACHED */
711cb0ef41Sopenharmony_ci}
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ci/* const char *
741cb0ef41Sopenharmony_ci * inet_ntop4(src, dst, size)
751cb0ef41Sopenharmony_ci *     format an IPv4 address
761cb0ef41Sopenharmony_ci * return:
771cb0ef41Sopenharmony_ci *     `dst' (as a const)
781cb0ef41Sopenharmony_ci * notes:
791cb0ef41Sopenharmony_ci *     (1) uses no statics
801cb0ef41Sopenharmony_ci *     (2) takes a unsigned char* not an in_addr as input
811cb0ef41Sopenharmony_ci * author:
821cb0ef41Sopenharmony_ci *     Paul Vixie, 1996.
831cb0ef41Sopenharmony_ci */
841cb0ef41Sopenharmony_cistatic const char *inet_ntop4(const unsigned char *src, char *dst, size_t size)
851cb0ef41Sopenharmony_ci{
861cb0ef41Sopenharmony_ci  static const char fmt[] = "%u.%u.%u.%u";
871cb0ef41Sopenharmony_ci  char              tmp[sizeof("255.255.255.255")];
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ci  if ((size_t)snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]) >=
901cb0ef41Sopenharmony_ci      size) {
911cb0ef41Sopenharmony_ci    SET_ERRNO(ENOSPC);
921cb0ef41Sopenharmony_ci    return (NULL);
931cb0ef41Sopenharmony_ci  }
941cb0ef41Sopenharmony_ci  ares_strcpy(dst, tmp, size);
951cb0ef41Sopenharmony_ci  return (dst);
961cb0ef41Sopenharmony_ci}
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_ci/* const char *
991cb0ef41Sopenharmony_ci * inet_ntop6(src, dst, size)
1001cb0ef41Sopenharmony_ci *     convert IPv6 binary address into presentation (printable) format
1011cb0ef41Sopenharmony_ci * author:
1021cb0ef41Sopenharmony_ci *     Paul Vixie, 1996.
1031cb0ef41Sopenharmony_ci */
1041cb0ef41Sopenharmony_cistatic const char *inet_ntop6(const unsigned char *src, char *dst, size_t size)
1051cb0ef41Sopenharmony_ci{
1061cb0ef41Sopenharmony_ci  /*
1071cb0ef41Sopenharmony_ci   * Note that int32_t and int16_t need only be "at least" large enough
1081cb0ef41Sopenharmony_ci   * to contain a value of the specified size.  On some systems, like
1091cb0ef41Sopenharmony_ci   * Crays, there is no such thing as an integer variable with 16 bits.
1101cb0ef41Sopenharmony_ci   * Keep this in mind if you think this function should have been coded
1111cb0ef41Sopenharmony_ci   * to use pointer overlays.  All the world's not a VAX.
1121cb0ef41Sopenharmony_ci   */
1131cb0ef41Sopenharmony_ci  char  tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
1141cb0ef41Sopenharmony_ci  char *tp;
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_ci  struct {
1171cb0ef41Sopenharmony_ci    int base, len;
1181cb0ef41Sopenharmony_ci  } best, cur;
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci  unsigned int words[NS_IN6ADDRSZ / NS_INT16SZ];
1211cb0ef41Sopenharmony_ci  int          i;
1221cb0ef41Sopenharmony_ci
1231cb0ef41Sopenharmony_ci  /*
1241cb0ef41Sopenharmony_ci   * Preprocess:
1251cb0ef41Sopenharmony_ci   *  Copy the input (bytewise) array into a wordwise array.
1261cb0ef41Sopenharmony_ci   *  Find the longest run of 0x00's in src[] for :: shorthanding.
1271cb0ef41Sopenharmony_ci   */
1281cb0ef41Sopenharmony_ci  memset(words, '\0', sizeof(words));
1291cb0ef41Sopenharmony_ci  for (i = 0; i < NS_IN6ADDRSZ; i++) {
1301cb0ef41Sopenharmony_ci    words[i / 2] |= (unsigned int)(src[i] << ((1 - (i % 2)) << 3));
1311cb0ef41Sopenharmony_ci  }
1321cb0ef41Sopenharmony_ci  best.base = -1;
1331cb0ef41Sopenharmony_ci  best.len  = 0;
1341cb0ef41Sopenharmony_ci  cur.base  = -1;
1351cb0ef41Sopenharmony_ci  cur.len   = 0;
1361cb0ef41Sopenharmony_ci  for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
1371cb0ef41Sopenharmony_ci    if (words[i] == 0) {
1381cb0ef41Sopenharmony_ci      if (cur.base == -1) {
1391cb0ef41Sopenharmony_ci        cur.base = i, cur.len = 1;
1401cb0ef41Sopenharmony_ci      } else {
1411cb0ef41Sopenharmony_ci        cur.len++;
1421cb0ef41Sopenharmony_ci      }
1431cb0ef41Sopenharmony_ci    } else {
1441cb0ef41Sopenharmony_ci      if (cur.base != -1) {
1451cb0ef41Sopenharmony_ci        if (best.base == -1 || cur.len > best.len) {
1461cb0ef41Sopenharmony_ci          best = cur;
1471cb0ef41Sopenharmony_ci        }
1481cb0ef41Sopenharmony_ci        cur.base = -1;
1491cb0ef41Sopenharmony_ci      }
1501cb0ef41Sopenharmony_ci    }
1511cb0ef41Sopenharmony_ci  }
1521cb0ef41Sopenharmony_ci  if (cur.base != -1) {
1531cb0ef41Sopenharmony_ci    if (best.base == -1 || cur.len > best.len) {
1541cb0ef41Sopenharmony_ci      best = cur;
1551cb0ef41Sopenharmony_ci    }
1561cb0ef41Sopenharmony_ci  }
1571cb0ef41Sopenharmony_ci  if (best.base != -1 && best.len < 2) {
1581cb0ef41Sopenharmony_ci    best.base = -1;
1591cb0ef41Sopenharmony_ci  }
1601cb0ef41Sopenharmony_ci
1611cb0ef41Sopenharmony_ci  /*
1621cb0ef41Sopenharmony_ci   * Format the result.
1631cb0ef41Sopenharmony_ci   */
1641cb0ef41Sopenharmony_ci  tp = tmp;
1651cb0ef41Sopenharmony_ci  for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
1661cb0ef41Sopenharmony_ci    /* Are we inside the best run of 0x00's? */
1671cb0ef41Sopenharmony_ci    if (best.base != -1 && i >= best.base && i < (best.base + best.len)) {
1681cb0ef41Sopenharmony_ci      if (i == best.base) {
1691cb0ef41Sopenharmony_ci        *tp++ = ':';
1701cb0ef41Sopenharmony_ci      }
1711cb0ef41Sopenharmony_ci      continue;
1721cb0ef41Sopenharmony_ci    }
1731cb0ef41Sopenharmony_ci    /* Are we following an initial run of 0x00s or any real hex? */
1741cb0ef41Sopenharmony_ci    if (i != 0) {
1751cb0ef41Sopenharmony_ci      *tp++ = ':';
1761cb0ef41Sopenharmony_ci    }
1771cb0ef41Sopenharmony_ci    /* Is this address an encapsulated IPv4? */
1781cb0ef41Sopenharmony_ci    if (i == 6 && best.base == 0 &&
1791cb0ef41Sopenharmony_ci        (best.len == 6 || (best.len == 7 && words[7] != 0x0001) ||
1801cb0ef41Sopenharmony_ci         (best.len == 5 && words[5] == 0xffff))) {
1811cb0ef41Sopenharmony_ci      if (!inet_ntop4(src + 12, tp, sizeof(tmp) - (size_t)(tp - tmp))) {
1821cb0ef41Sopenharmony_ci        return (NULL);
1831cb0ef41Sopenharmony_ci      }
1841cb0ef41Sopenharmony_ci      tp += ares_strlen(tp);
1851cb0ef41Sopenharmony_ci      break;
1861cb0ef41Sopenharmony_ci    }
1871cb0ef41Sopenharmony_ci    tp += snprintf(tp, sizeof(tmp) - (size_t)(tp - tmp), "%x", words[i]);
1881cb0ef41Sopenharmony_ci  }
1891cb0ef41Sopenharmony_ci  /* Was it a trailing run of 0x00's? */
1901cb0ef41Sopenharmony_ci  if (best.base != -1 &&
1911cb0ef41Sopenharmony_ci      (best.base + best.len) == (NS_IN6ADDRSZ / NS_INT16SZ)) {
1921cb0ef41Sopenharmony_ci    *tp++ = ':';
1931cb0ef41Sopenharmony_ci  }
1941cb0ef41Sopenharmony_ci  *tp++ = '\0';
1951cb0ef41Sopenharmony_ci
1961cb0ef41Sopenharmony_ci  /*
1971cb0ef41Sopenharmony_ci   * Check for overflow, copy, and we're done.
1981cb0ef41Sopenharmony_ci   */
1991cb0ef41Sopenharmony_ci  if ((size_t)(tp - tmp) > size) {
2001cb0ef41Sopenharmony_ci    SET_ERRNO(ENOSPC);
2011cb0ef41Sopenharmony_ci    return (NULL);
2021cb0ef41Sopenharmony_ci  }
2031cb0ef41Sopenharmony_ci  ares_strcpy(dst, tmp, size);
2041cb0ef41Sopenharmony_ci  return (dst);
2051cb0ef41Sopenharmony_ci}
2061cb0ef41Sopenharmony_ci
2071cb0ef41Sopenharmony_ci#else  /* HAVE_INET_NTOP */
2081cb0ef41Sopenharmony_ci
2091cb0ef41Sopenharmony_ciconst char *ares_inet_ntop(int af, const void *src, char *dst,
2101cb0ef41Sopenharmony_ci                           ares_socklen_t size)
2111cb0ef41Sopenharmony_ci{
2121cb0ef41Sopenharmony_ci  /* just relay this to the underlying function */
2131cb0ef41Sopenharmony_ci  return inet_ntop(af, src, dst, size);
2141cb0ef41Sopenharmony_ci}
2151cb0ef41Sopenharmony_ci
2161cb0ef41Sopenharmony_ci#endif /* HAVE_INET_NTOP */
217