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