11cb0ef41Sopenharmony_ci/* MIT License
21cb0ef41Sopenharmony_ci *
31cb0ef41Sopenharmony_ci * Copyright (c) Massachusetts Institute of Technology
41cb0ef41Sopenharmony_ci * Copyright (c) Daniel Stenberg
51cb0ef41Sopenharmony_ci *
61cb0ef41Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
71cb0ef41Sopenharmony_ci * of this software and associated documentation files (the "Software"), to deal
81cb0ef41Sopenharmony_ci * in the Software without restriction, including without limitation the rights
91cb0ef41Sopenharmony_ci * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
101cb0ef41Sopenharmony_ci * copies of the Software, and to permit persons to whom the Software is
111cb0ef41Sopenharmony_ci * furnished to do so, subject to the following conditions:
121cb0ef41Sopenharmony_ci *
131cb0ef41Sopenharmony_ci * The above copyright notice and this permission notice (including the next
141cb0ef41Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
151cb0ef41Sopenharmony_ci * Software.
161cb0ef41Sopenharmony_ci *
171cb0ef41Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
181cb0ef41Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
191cb0ef41Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
201cb0ef41Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
211cb0ef41Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
221cb0ef41Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
231cb0ef41Sopenharmony_ci * SOFTWARE.
241cb0ef41Sopenharmony_ci *
251cb0ef41Sopenharmony_ci * SPDX-License-Identifier: MIT
261cb0ef41Sopenharmony_ci */
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ci#include "ares_setup.h"
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ci#ifdef HAVE_NETINET_IN_H
311cb0ef41Sopenharmony_ci#  include <netinet/in.h>
321cb0ef41Sopenharmony_ci#endif
331cb0ef41Sopenharmony_ci#ifdef HAVE_NETDB_H
341cb0ef41Sopenharmony_ci#  include <netdb.h>
351cb0ef41Sopenharmony_ci#endif
361cb0ef41Sopenharmony_ci#ifdef HAVE_ARPA_INET_H
371cb0ef41Sopenharmony_ci#  include <arpa/inet.h>
381cb0ef41Sopenharmony_ci#endif
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ci#if defined(_WIN32) && defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0600
411cb0ef41Sopenharmony_ci#  include <ws2ipdef.h>
421cb0ef41Sopenharmony_ci#endif
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci#if defined(USE_WINSOCK)
451cb0ef41Sopenharmony_ci#  if defined(HAVE_IPHLPAPI_H)
461cb0ef41Sopenharmony_ci#    include <iphlpapi.h>
471cb0ef41Sopenharmony_ci#  endif
481cb0ef41Sopenharmony_ci#  if defined(HAVE_NETIOAPI_H)
491cb0ef41Sopenharmony_ci#    include <netioapi.h>
501cb0ef41Sopenharmony_ci#  endif
511cb0ef41Sopenharmony_ci#endif
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ci#include "ares.h"
541cb0ef41Sopenharmony_ci#include "ares_inet_net_pton.h"
551cb0ef41Sopenharmony_ci#include "ares_private.h"
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ciares_status_t ares_append_ai_node(int aftype, unsigned short port,
581cb0ef41Sopenharmony_ci                                  unsigned int ttl, const void *adata,
591cb0ef41Sopenharmony_ci                                  struct ares_addrinfo_node **nodes)
601cb0ef41Sopenharmony_ci{
611cb0ef41Sopenharmony_ci  struct ares_addrinfo_node *node;
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ci  node = ares__append_addrinfo_node(nodes);
641cb0ef41Sopenharmony_ci  if (!node) {
651cb0ef41Sopenharmony_ci    return ARES_ENOMEM;
661cb0ef41Sopenharmony_ci  }
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ci  memset(node, 0, sizeof(*node));
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci  if (aftype == AF_INET) {
711cb0ef41Sopenharmony_ci    struct sockaddr_in *sin = ares_malloc(sizeof(*sin));
721cb0ef41Sopenharmony_ci    if (!sin) {
731cb0ef41Sopenharmony_ci      return ARES_ENOMEM;
741cb0ef41Sopenharmony_ci    }
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci    memset(sin, 0, sizeof(*sin));
771cb0ef41Sopenharmony_ci    memcpy(&sin->sin_addr.s_addr, adata, sizeof(sin->sin_addr.s_addr));
781cb0ef41Sopenharmony_ci    sin->sin_family = AF_INET;
791cb0ef41Sopenharmony_ci    sin->sin_port   = htons(port);
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ci    node->ai_addr    = (struct sockaddr *)sin;
821cb0ef41Sopenharmony_ci    node->ai_family  = AF_INET;
831cb0ef41Sopenharmony_ci    node->ai_addrlen = sizeof(*sin);
841cb0ef41Sopenharmony_ci    node->ai_addr    = (struct sockaddr *)sin;
851cb0ef41Sopenharmony_ci    node->ai_ttl     = (int)ttl;
861cb0ef41Sopenharmony_ci  }
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_ci  if (aftype == AF_INET6) {
891cb0ef41Sopenharmony_ci    struct sockaddr_in6 *sin6 = ares_malloc(sizeof(*sin6));
901cb0ef41Sopenharmony_ci    if (!sin6) {
911cb0ef41Sopenharmony_ci      return ARES_ENOMEM;
921cb0ef41Sopenharmony_ci    }
931cb0ef41Sopenharmony_ci
941cb0ef41Sopenharmony_ci    memset(sin6, 0, sizeof(*sin6));
951cb0ef41Sopenharmony_ci    memcpy(&sin6->sin6_addr.s6_addr, adata, sizeof(sin6->sin6_addr.s6_addr));
961cb0ef41Sopenharmony_ci    sin6->sin6_family = AF_INET6;
971cb0ef41Sopenharmony_ci    sin6->sin6_port   = htons(port);
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_ci    node->ai_addr    = (struct sockaddr *)sin6;
1001cb0ef41Sopenharmony_ci    node->ai_family  = AF_INET6;
1011cb0ef41Sopenharmony_ci    node->ai_addrlen = sizeof(*sin6);
1021cb0ef41Sopenharmony_ci    node->ai_addr    = (struct sockaddr *)sin6;
1031cb0ef41Sopenharmony_ci    node->ai_ttl     = (int)ttl;
1041cb0ef41Sopenharmony_ci  }
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci  return ARES_SUCCESS;
1071cb0ef41Sopenharmony_ci}
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_cistatic ares_status_t
1101cb0ef41Sopenharmony_ci  ares__default_loopback_addrs(int aftype, unsigned short port,
1111cb0ef41Sopenharmony_ci                               struct ares_addrinfo_node **nodes)
1121cb0ef41Sopenharmony_ci{
1131cb0ef41Sopenharmony_ci  ares_status_t status = ARES_SUCCESS;
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_ci  if (aftype == AF_UNSPEC || aftype == AF_INET6) {
1161cb0ef41Sopenharmony_ci    struct ares_in6_addr addr6;
1171cb0ef41Sopenharmony_ci    ares_inet_pton(AF_INET6, "::1", &addr6);
1181cb0ef41Sopenharmony_ci    status = ares_append_ai_node(AF_INET6, port, 0, &addr6, nodes);
1191cb0ef41Sopenharmony_ci    if (status != ARES_SUCCESS) {
1201cb0ef41Sopenharmony_ci      return status;
1211cb0ef41Sopenharmony_ci    }
1221cb0ef41Sopenharmony_ci  }
1231cb0ef41Sopenharmony_ci
1241cb0ef41Sopenharmony_ci  if (aftype == AF_UNSPEC || aftype == AF_INET) {
1251cb0ef41Sopenharmony_ci    struct in_addr addr4;
1261cb0ef41Sopenharmony_ci    ares_inet_pton(AF_INET, "127.0.0.1", &addr4);
1271cb0ef41Sopenharmony_ci    status = ares_append_ai_node(AF_INET, port, 0, &addr4, nodes);
1281cb0ef41Sopenharmony_ci    if (status != ARES_SUCCESS) {
1291cb0ef41Sopenharmony_ci      return status;
1301cb0ef41Sopenharmony_ci    }
1311cb0ef41Sopenharmony_ci  }
1321cb0ef41Sopenharmony_ci
1331cb0ef41Sopenharmony_ci  return status;
1341cb0ef41Sopenharmony_ci}
1351cb0ef41Sopenharmony_ci
1361cb0ef41Sopenharmony_cistatic ares_status_t
1371cb0ef41Sopenharmony_ci  ares__system_loopback_addrs(int aftype, unsigned short port,
1381cb0ef41Sopenharmony_ci                              struct ares_addrinfo_node **nodes)
1391cb0ef41Sopenharmony_ci{
1401cb0ef41Sopenharmony_ci#if defined(_WIN32) && defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0600 && \
1411cb0ef41Sopenharmony_ci  !defined(__WATCOMC__)
1421cb0ef41Sopenharmony_ci  PMIB_UNICASTIPADDRESS_TABLE table;
1431cb0ef41Sopenharmony_ci  unsigned int                i;
1441cb0ef41Sopenharmony_ci  ares_status_t               status;
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_ci  *nodes = NULL;
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_ci  if (GetUnicastIpAddressTable((ADDRESS_FAMILY)aftype, &table) != NO_ERROR) {
1491cb0ef41Sopenharmony_ci    return ARES_ENOTFOUND;
1501cb0ef41Sopenharmony_ci  }
1511cb0ef41Sopenharmony_ci
1521cb0ef41Sopenharmony_ci  for (i = 0; i < table->NumEntries; i++) {
1531cb0ef41Sopenharmony_ci    if (table->Table[i].InterfaceLuid.Info.IfType !=
1541cb0ef41Sopenharmony_ci        IF_TYPE_SOFTWARE_LOOPBACK) {
1551cb0ef41Sopenharmony_ci      continue;
1561cb0ef41Sopenharmony_ci    }
1571cb0ef41Sopenharmony_ci
1581cb0ef41Sopenharmony_ci    if (table->Table[i].Address.si_family == AF_INET) {
1591cb0ef41Sopenharmony_ci      status =
1601cb0ef41Sopenharmony_ci        ares_append_ai_node(table->Table[i].Address.si_family, port, 0,
1611cb0ef41Sopenharmony_ci                            &table->Table[i].Address.Ipv4.sin_addr, nodes);
1621cb0ef41Sopenharmony_ci    } else if (table->Table[i].Address.si_family == AF_INET6) {
1631cb0ef41Sopenharmony_ci      status =
1641cb0ef41Sopenharmony_ci        ares_append_ai_node(table->Table[i].Address.si_family, port, 0,
1651cb0ef41Sopenharmony_ci                            &table->Table[i].Address.Ipv6.sin6_addr, nodes);
1661cb0ef41Sopenharmony_ci    } else {
1671cb0ef41Sopenharmony_ci      /* Ignore any others */
1681cb0ef41Sopenharmony_ci      continue;
1691cb0ef41Sopenharmony_ci    }
1701cb0ef41Sopenharmony_ci
1711cb0ef41Sopenharmony_ci    if (status != ARES_SUCCESS) {
1721cb0ef41Sopenharmony_ci      goto fail;
1731cb0ef41Sopenharmony_ci    }
1741cb0ef41Sopenharmony_ci  }
1751cb0ef41Sopenharmony_ci
1761cb0ef41Sopenharmony_ci  if (*nodes == NULL) {
1771cb0ef41Sopenharmony_ci    status = ARES_ENOTFOUND;
1781cb0ef41Sopenharmony_ci  }
1791cb0ef41Sopenharmony_ci
1801cb0ef41Sopenharmony_cifail:
1811cb0ef41Sopenharmony_ci  FreeMibTable(table);
1821cb0ef41Sopenharmony_ci
1831cb0ef41Sopenharmony_ci  if (status != ARES_SUCCESS) {
1841cb0ef41Sopenharmony_ci    ares__freeaddrinfo_nodes(*nodes);
1851cb0ef41Sopenharmony_ci    *nodes = NULL;
1861cb0ef41Sopenharmony_ci  }
1871cb0ef41Sopenharmony_ci
1881cb0ef41Sopenharmony_ci  return status;
1891cb0ef41Sopenharmony_ci
1901cb0ef41Sopenharmony_ci#else
1911cb0ef41Sopenharmony_ci  (void)aftype;
1921cb0ef41Sopenharmony_ci  (void)port;
1931cb0ef41Sopenharmony_ci  (void)nodes;
1941cb0ef41Sopenharmony_ci  /* Not supported on any other OS at this time */
1951cb0ef41Sopenharmony_ci  return ARES_ENOTFOUND;
1961cb0ef41Sopenharmony_ci#endif
1971cb0ef41Sopenharmony_ci}
1981cb0ef41Sopenharmony_ci
1991cb0ef41Sopenharmony_ciares_status_t ares__addrinfo_localhost(const char *name, unsigned short port,
2001cb0ef41Sopenharmony_ci                                       const struct ares_addrinfo_hints *hints,
2011cb0ef41Sopenharmony_ci                                       struct ares_addrinfo             *ai)
2021cb0ef41Sopenharmony_ci{
2031cb0ef41Sopenharmony_ci  struct ares_addrinfo_node *nodes = NULL;
2041cb0ef41Sopenharmony_ci  ares_status_t              status;
2051cb0ef41Sopenharmony_ci
2061cb0ef41Sopenharmony_ci  /* Validate family */
2071cb0ef41Sopenharmony_ci  switch (hints->ai_family) {
2081cb0ef41Sopenharmony_ci    case AF_INET:
2091cb0ef41Sopenharmony_ci    case AF_INET6:
2101cb0ef41Sopenharmony_ci    case AF_UNSPEC:
2111cb0ef41Sopenharmony_ci      break;
2121cb0ef41Sopenharmony_ci    default:
2131cb0ef41Sopenharmony_ci      return ARES_EBADFAMILY;
2141cb0ef41Sopenharmony_ci  }
2151cb0ef41Sopenharmony_ci
2161cb0ef41Sopenharmony_ci  ai->name = ares_strdup(name);
2171cb0ef41Sopenharmony_ci  if (!ai->name) {
2181cb0ef41Sopenharmony_ci    goto enomem;
2191cb0ef41Sopenharmony_ci  }
2201cb0ef41Sopenharmony_ci
2211cb0ef41Sopenharmony_ci  status = ares__system_loopback_addrs(hints->ai_family, port, &nodes);
2221cb0ef41Sopenharmony_ci
2231cb0ef41Sopenharmony_ci  if (status == ARES_ENOTFOUND) {
2241cb0ef41Sopenharmony_ci    status = ares__default_loopback_addrs(hints->ai_family, port, &nodes);
2251cb0ef41Sopenharmony_ci  }
2261cb0ef41Sopenharmony_ci
2271cb0ef41Sopenharmony_ci  ares__addrinfo_cat_nodes(&ai->nodes, nodes);
2281cb0ef41Sopenharmony_ci
2291cb0ef41Sopenharmony_ci  return status;
2301cb0ef41Sopenharmony_ci
2311cb0ef41Sopenharmony_cienomem:
2321cb0ef41Sopenharmony_ci  ares__freeaddrinfo_nodes(nodes);
2331cb0ef41Sopenharmony_ci  ares_free(ai->name);
2341cb0ef41Sopenharmony_ci  ai->name = NULL;
2351cb0ef41Sopenharmony_ci  return ARES_ENOMEM;
2361cb0ef41Sopenharmony_ci}
237