quickjs-tart

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

ares_parse_into_addrinfo.c (5839B)


      1 /* MIT License
      2  *
      3  * Copyright (c) 2019 Andrew Selivanov
      4  * Copyright (c) 2023 Brad House
      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 #include "ares_private.h"
     28 
     29 #ifdef HAVE_NETINET_IN_H
     30 #  include <netinet/in.h>
     31 #endif
     32 #ifdef HAVE_NETDB_H
     33 #  include <netdb.h>
     34 #endif
     35 #ifdef HAVE_ARPA_INET_H
     36 #  include <arpa/inet.h>
     37 #endif
     38 
     39 #ifdef HAVE_STRINGS_H
     40 #  include <strings.h>
     41 #endif
     42 
     43 #ifdef HAVE_LIMITS_H
     44 #  include <limits.h>
     45 #endif
     46 
     47 
     48 ares_status_t ares_parse_into_addrinfo(const ares_dns_record_t *dnsrec,
     49                                        ares_bool_t    cname_only_is_enodata,
     50                                        unsigned short port,
     51                                        struct ares_addrinfo *ai)
     52 {
     53   ares_status_t               status;
     54   size_t                      i;
     55   size_t                      ancount;
     56   const char                 *hostname  = NULL;
     57   ares_bool_t                 got_a     = ARES_FALSE;
     58   ares_bool_t                 got_aaaa  = ARES_FALSE;
     59   ares_bool_t                 got_cname = ARES_FALSE;
     60   struct ares_addrinfo_cname *cnames    = NULL;
     61   struct ares_addrinfo_node  *nodes     = NULL;
     62 
     63   /* Save question hostname */
     64   status = ares_dns_record_query_get(dnsrec, 0, &hostname, NULL, NULL);
     65   if (status != ARES_SUCCESS) {
     66     goto done; /* LCOV_EXCL_LINE: DefensiveCoding */
     67   }
     68 
     69   ancount = ares_dns_record_rr_cnt(dnsrec, ARES_SECTION_ANSWER);
     70   if (ancount == 0) {
     71     status = ARES_ENODATA;
     72     goto done;
     73   }
     74 
     75   for (i = 0; i < ancount; i++) {
     76     ares_dns_rec_type_t  rtype;
     77     const ares_dns_rr_t *rr =
     78       ares_dns_record_rr_get_const(dnsrec, ARES_SECTION_ANSWER, i);
     79 
     80     if (ares_dns_rr_get_class(rr) != ARES_CLASS_IN) {
     81       continue;
     82     }
     83 
     84     rtype = ares_dns_rr_get_type(rr);
     85 
     86     /* Issue #683
     87      * Old code did this hostname sanity check, however it appears this is
     88      * flawed logic.  Other resolvers don't do this sanity check.  Leaving
     89      * this code commented out for future reference.
     90      *
     91      * rname = ares_dns_rr_get_name(rr);
     92      * if ((rtype == ARES_REC_TYPE_A || rtype == ARES_REC_TYPE_AAAA) &&
     93      *     !ares_strcaseeq(rname, hostname)) {
     94      *   continue;
     95      * }
     96      */
     97 
     98     if (rtype == ARES_REC_TYPE_CNAME) {
     99       struct ares_addrinfo_cname *cname;
    100 
    101       got_cname = ARES_TRUE;
    102       /* replace hostname with data from cname
    103        * SA: Seems wrong as it introduces order dependency. */
    104       hostname = ares_dns_rr_get_str(rr, ARES_RR_CNAME_CNAME);
    105 
    106       cname = ares_append_addrinfo_cname(&cnames);
    107       if (cname == NULL) {
    108         status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
    109         goto done;            /* LCOV_EXCL_LINE: OutOfMemory */
    110       }
    111       cname->ttl   = (int)ares_dns_rr_get_ttl(rr);
    112       cname->alias = ares_strdup(ares_dns_rr_get_name(rr));
    113       if (cname->alias == NULL) {
    114         status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
    115         goto done;            /* LCOV_EXCL_LINE: OutOfMemory */
    116       }
    117       cname->name = ares_strdup(hostname);
    118       if (cname->name == NULL) {
    119         status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
    120         goto done;            /* LCOV_EXCL_LINE: OutOfMemory */
    121       }
    122     } else if (rtype == ARES_REC_TYPE_A) {
    123       got_a = ARES_TRUE;
    124       status =
    125         ares_append_ai_node(AF_INET, port, ares_dns_rr_get_ttl(rr),
    126                             ares_dns_rr_get_addr(rr, ARES_RR_A_ADDR), &nodes);
    127       if (status != ARES_SUCCESS) {
    128         goto done; /* LCOV_EXCL_LINE: OutOfMemory */
    129       }
    130     } else if (rtype == ARES_REC_TYPE_AAAA) {
    131       got_aaaa = ARES_TRUE;
    132       status   = ares_append_ai_node(AF_INET6, port, ares_dns_rr_get_ttl(rr),
    133                                      ares_dns_rr_get_addr6(rr, ARES_RR_AAAA_ADDR),
    134                                      &nodes);
    135       if (status != ARES_SUCCESS) {
    136         goto done; /* LCOV_EXCL_LINE: OutOfMemory */
    137       }
    138     } else {
    139       continue;
    140     }
    141   }
    142 
    143   if (!got_a && !got_aaaa &&
    144       (!got_cname || (got_cname && cname_only_is_enodata))) {
    145     status = ARES_ENODATA;
    146     goto done;
    147   }
    148 
    149   /* save the hostname as ai->name */
    150   if (ai->name == NULL || !ares_strcaseeq(ai->name, hostname)) {
    151     ares_free(ai->name);
    152     ai->name = ares_strdup(hostname);
    153     if (ai->name == NULL) {
    154       status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
    155       goto done;            /* LCOV_EXCL_LINE: OutOfMemory */
    156     }
    157   }
    158 
    159   if (got_a || got_aaaa) {
    160     ares_addrinfo_cat_nodes(&ai->nodes, nodes);
    161     nodes = NULL;
    162   }
    163 
    164   if (got_cname) {
    165     ares_addrinfo_cat_cnames(&ai->cnames, cnames);
    166     cnames = NULL;
    167   }
    168 
    169 done:
    170   ares_freeaddrinfo_cnames(cnames);
    171   ares_freeaddrinfo_nodes(nodes);
    172 
    173   /* compatibility */
    174   if (status == ARES_EBADNAME) {
    175     status = ARES_EBADRESP;
    176   }
    177 
    178   return status;
    179 }