quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

ares_addrinfo_localhost.c (7100B)


      1 /* MIT License
      2  *
      3  * Copyright (c) Massachusetts Institute of Technology
      4  * Copyright (c) Daniel Stenberg
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a copy
      7  * of this software and associated documentation files (the "Software"), to deal
      8  * in the Software without restriction, including without limitation the rights
      9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     10  * copies of the Software, and to permit persons to whom the Software is
     11  * furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice (including the next
     14  * paragraph) shall be included in all copies or substantial portions of the
     15  * Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     23  * SOFTWARE.
     24  *
     25  * SPDX-License-Identifier: MIT
     26  */
     27 
     28 #include "ares_private.h"
     29 
     30 #ifdef HAVE_NETINET_IN_H
     31 #  include <netinet/in.h>
     32 #endif
     33 #ifdef HAVE_NETDB_H
     34 #  include <netdb.h>
     35 #endif
     36 #ifdef HAVE_ARPA_INET_H
     37 #  include <arpa/inet.h>
     38 #endif
     39 
     40 #if defined(USE_WINSOCK)
     41 #  if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0600
     42 #    include <ws2ipdef.h>
     43 #  endif
     44 #  if defined(HAVE_IPHLPAPI_H)
     45 #    include <iphlpapi.h>
     46 #  endif
     47 #  if defined(HAVE_NETIOAPI_H)
     48 #    include <netioapi.h>
     49 #  endif
     50 #endif
     51 
     52 static ares_bool_t ares_ai_has_family(int aftype,
     53                                       const struct ares_addrinfo_node *nodes)
     54 {
     55   const struct ares_addrinfo_node *node;
     56 
     57   for (node = nodes; node != NULL; node = node->ai_next) {
     58     if (node->ai_family == aftype)
     59       return ARES_TRUE;
     60   }
     61 
     62   return ARES_FALSE;
     63 }
     64 
     65 ares_status_t ares_append_ai_node(int aftype, unsigned short port,
     66                                   unsigned int ttl, const void *adata,
     67                                   struct ares_addrinfo_node **nodes)
     68 {
     69   struct ares_addrinfo_node *node;
     70 
     71   node = ares_append_addrinfo_node(nodes);
     72   if (!node) {
     73     return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
     74   }
     75 
     76   memset(node, 0, sizeof(*node));
     77 
     78   if (aftype == AF_INET) {
     79     struct sockaddr_in *sin = ares_malloc(sizeof(*sin));
     80     if (!sin) {
     81       return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
     82     }
     83 
     84     memset(sin, 0, sizeof(*sin));
     85     memcpy(&sin->sin_addr.s_addr, adata, sizeof(sin->sin_addr.s_addr));
     86     sin->sin_family = AF_INET;
     87     sin->sin_port   = htons(port);
     88 
     89     node->ai_addr    = (struct sockaddr *)sin;
     90     node->ai_family  = AF_INET;
     91     node->ai_addrlen = sizeof(*sin);
     92     node->ai_addr    = (struct sockaddr *)sin;
     93     node->ai_ttl     = (int)ttl;
     94   }
     95 
     96   if (aftype == AF_INET6) {
     97     struct sockaddr_in6 *sin6 = ares_malloc(sizeof(*sin6));
     98     if (!sin6) {
     99       return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
    100     }
    101 
    102     memset(sin6, 0, sizeof(*sin6));
    103     memcpy(&sin6->sin6_addr.s6_addr, adata, sizeof(sin6->sin6_addr.s6_addr));
    104     sin6->sin6_family = AF_INET6;
    105     sin6->sin6_port   = htons(port);
    106 
    107     node->ai_addr    = (struct sockaddr *)sin6;
    108     node->ai_family  = AF_INET6;
    109     node->ai_addrlen = sizeof(*sin6);
    110     node->ai_addr    = (struct sockaddr *)sin6;
    111     node->ai_ttl     = (int)ttl;
    112   }
    113 
    114   return ARES_SUCCESS;
    115 }
    116 
    117 static ares_status_t
    118   ares_default_loopback_addrs(int aftype, unsigned short port,
    119                               struct ares_addrinfo_node **nodes)
    120 {
    121   ares_status_t status = ARES_SUCCESS;
    122 
    123   if ((aftype == AF_UNSPEC || aftype == AF_INET6) &&
    124       !ares_ai_has_family(AF_INET6, *nodes)) {
    125     struct ares_in6_addr addr6;
    126     ares_inet_pton(AF_INET6, "::1", &addr6);
    127     status = ares_append_ai_node(AF_INET6, port, 0, &addr6, nodes);
    128     if (status != ARES_SUCCESS) {
    129       return status; /* LCOV_EXCL_LINE: OutOfMemory */
    130     }
    131   }
    132 
    133   if ((aftype == AF_UNSPEC || aftype == AF_INET) &&
    134       !ares_ai_has_family(AF_INET, *nodes)) {
    135     struct in_addr addr4;
    136     ares_inet_pton(AF_INET, "127.0.0.1", &addr4);
    137     status = ares_append_ai_node(AF_INET, port, 0, &addr4, nodes);
    138     if (status != ARES_SUCCESS) {
    139       return status; /* LCOV_EXCL_LINE: OutOfMemory */
    140     }
    141   }
    142 
    143   return status;
    144 }
    145 
    146 static ares_status_t
    147   ares_system_loopback_addrs(int aftype, unsigned short port,
    148                              struct ares_addrinfo_node **nodes)
    149 {
    150 #if defined(USE_WINSOCK) && defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0600 && \
    151   !defined(__WATCOMC__)
    152   PMIB_UNICASTIPADDRESS_TABLE table;
    153   unsigned int                i;
    154   ares_status_t               status = ARES_ENOTFOUND;
    155 
    156   *nodes = NULL;
    157 
    158   if (GetUnicastIpAddressTable((ADDRESS_FAMILY)aftype, &table) != NO_ERROR) {
    159     return ARES_ENOTFOUND;
    160   }
    161 
    162   for (i = 0; i < table->NumEntries; i++) {
    163     if (table->Table[i].InterfaceLuid.Info.IfType !=
    164         IF_TYPE_SOFTWARE_LOOPBACK) {
    165       continue;
    166     }
    167 
    168     if (table->Table[i].Address.si_family == AF_INET &&
    169         !ares_ai_has_family(AF_INET, *nodes)) {
    170       status =
    171         ares_append_ai_node(table->Table[i].Address.si_family, port, 0,
    172                             &table->Table[i].Address.Ipv4.sin_addr, nodes);
    173     } else if (table->Table[i].Address.si_family == AF_INET6 &&
    174                !ares_ai_has_family(AF_INET6, *nodes)) {
    175       status =
    176         ares_append_ai_node(table->Table[i].Address.si_family, port, 0,
    177                             &table->Table[i].Address.Ipv6.sin6_addr, nodes);
    178     } else {
    179       /* Ignore any others */
    180       continue;
    181     }
    182 
    183     if (status != ARES_SUCCESS) {
    184       goto fail;
    185     }
    186   }
    187 
    188   if (*nodes == NULL) {
    189     status = ARES_ENOTFOUND;
    190   }
    191 
    192 fail:
    193   FreeMibTable(table);
    194 
    195   if (status != ARES_SUCCESS) {
    196     ares_freeaddrinfo_nodes(*nodes);
    197     *nodes = NULL;
    198   }
    199 
    200   return status;
    201 
    202 #else
    203   (void)aftype;
    204   (void)port;
    205   (void)nodes;
    206   /* Not supported on any other OS at this time */
    207   return ARES_ENOTFOUND;
    208 #endif
    209 }
    210 
    211 ares_status_t ares_addrinfo_localhost(const char *name, unsigned short port,
    212                                       const struct ares_addrinfo_hints *hints,
    213                                       struct ares_addrinfo             *ai)
    214 {
    215   ares_status_t status;
    216 
    217   /* Validate family */
    218   switch (hints->ai_family) {
    219     case AF_INET:
    220     case AF_INET6:
    221     case AF_UNSPEC:
    222       break;
    223     default:                  /* LCOV_EXCL_LINE: DefensiveCoding */
    224       return ARES_EBADFAMILY; /* LCOV_EXCL_LINE: DefensiveCoding */
    225   }
    226 
    227   if (ai->name != NULL) {
    228     ares_free(ai->name);
    229   }
    230   ai->name = ares_strdup(name);
    231   if (ai->name == NULL) {
    232     status = ARES_ENOMEM;
    233     goto done; /* LCOV_EXCL_LINE: OutOfMemory */
    234   }
    235 
    236   status = ares_system_loopback_addrs(hints->ai_family, port, &ai->nodes);
    237   if (status != ARES_SUCCESS && status != ARES_ENOTFOUND) {
    238     goto done;
    239   }
    240 
    241   status = ares_default_loopback_addrs(hints->ai_family, port, &ai->nodes);
    242 
    243 done:
    244   return status;
    245 }