quickjs-tart

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

ares_dns_parse.c (37028B)


      1 /* MIT License
      2  *
      3  * Copyright (c) 2023 Brad House
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining a copy
      6  * of this software and associated documentation files (the "Software"), to deal
      7  * in the Software without restriction, including without limitation the rights
      8  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      9  * copies of the Software, and to permit persons to whom the Software is
     10  * furnished to do so, subject to the following conditions:
     11  *
     12  * The above copyright notice and this permission notice (including the next
     13  * paragraph) shall be included in all copies or substantial portions of the
     14  * Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     22  * SOFTWARE.
     23  *
     24  * SPDX-License-Identifier: MIT
     25  */
     26 #include "ares_private.h"
     27 #include <limits.h>
     28 #ifdef HAVE_STDINT_H
     29 #  include <stdint.h>
     30 #endif
     31 
     32 static size_t ares_dns_rr_remaining_len(const ares_buf_t *buf, size_t orig_len,
     33                                         size_t rdlength)
     34 {
     35   size_t used_len = orig_len - ares_buf_len(buf);
     36   if (used_len >= rdlength) {
     37     return 0;
     38   }
     39   return rdlength - used_len;
     40 }
     41 
     42 static ares_status_t ares_dns_parse_and_set_dns_name(ares_buf_t    *buf,
     43                                                      ares_bool_t    is_hostname,
     44                                                      ares_dns_rr_t *rr,
     45                                                      ares_dns_rr_key_t key)
     46 {
     47   ares_status_t status;
     48   char         *name = NULL;
     49 
     50   status = ares_dns_name_parse(buf, &name, is_hostname);
     51   if (status != ARES_SUCCESS) {
     52     return status;
     53   }
     54 
     55   status = ares_dns_rr_set_str_own(rr, key, name);
     56   if (status != ARES_SUCCESS) {
     57     ares_free(name);
     58     return status;
     59   }
     60   return ARES_SUCCESS;
     61 }
     62 
     63 static ares_status_t ares_dns_parse_and_set_dns_str(ares_buf_t       *buf,
     64                                                     size_t            max_len,
     65                                                     ares_dns_rr_t    *rr,
     66                                                     ares_dns_rr_key_t key,
     67                                                     ares_bool_t blank_allowed)
     68 {
     69   ares_status_t status;
     70   char         *str = NULL;
     71 
     72   status = ares_buf_parse_dns_str(buf, max_len, &str);
     73   if (status != ARES_SUCCESS) {
     74     return status;
     75   }
     76 
     77   if (!blank_allowed && ares_strlen(str) == 0) {
     78     ares_free(str);
     79     return ARES_EBADRESP;
     80   }
     81 
     82   status = ares_dns_rr_set_str_own(rr, key, str);
     83   if (status != ARES_SUCCESS) {
     84     ares_free(str);
     85     return status;
     86   }
     87   return ARES_SUCCESS;
     88 }
     89 
     90 static ares_status_t
     91   ares_dns_parse_and_set_dns_abin(ares_buf_t *buf, size_t max_len,
     92                                   ares_dns_rr_t *rr, ares_dns_rr_key_t key,
     93                                   ares_bool_t validate_printable)
     94 {
     95   ares_status_t           status;
     96   ares_dns_multistring_t *strs = NULL;
     97 
     98   status =
     99     ares_dns_multistring_parse_buf(buf, max_len, &strs, validate_printable);
    100   if (status != ARES_SUCCESS) {
    101     return status;
    102   }
    103 
    104   status = ares_dns_rr_set_abin_own(rr, key, strs);
    105   if (status != ARES_SUCCESS) {
    106     ares_dns_multistring_destroy(strs);
    107     return status;
    108   }
    109   return ARES_SUCCESS;
    110 }
    111 
    112 static ares_status_t ares_dns_parse_and_set_be32(ares_buf_t       *buf,
    113                                                  ares_dns_rr_t    *rr,
    114                                                  ares_dns_rr_key_t key)
    115 {
    116   ares_status_t status;
    117   unsigned int  u32;
    118 
    119   status = ares_buf_fetch_be32(buf, &u32);
    120   if (status != ARES_SUCCESS) {
    121     return status;
    122   }
    123 
    124   return ares_dns_rr_set_u32(rr, key, u32);
    125 }
    126 
    127 static ares_status_t ares_dns_parse_and_set_be16(ares_buf_t       *buf,
    128                                                  ares_dns_rr_t    *rr,
    129                                                  ares_dns_rr_key_t key)
    130 {
    131   ares_status_t  status;
    132   unsigned short u16;
    133 
    134   status = ares_buf_fetch_be16(buf, &u16);
    135   if (status != ARES_SUCCESS) {
    136     return status;
    137   }
    138 
    139   return ares_dns_rr_set_u16(rr, key, u16);
    140 }
    141 
    142 static ares_status_t ares_dns_parse_and_set_u8(ares_buf_t       *buf,
    143                                                ares_dns_rr_t    *rr,
    144                                                ares_dns_rr_key_t key)
    145 {
    146   ares_status_t status;
    147   unsigned char u8;
    148 
    149   status = ares_buf_fetch_bytes(buf, &u8, 1);
    150   if (status != ARES_SUCCESS) {
    151     return status;
    152   }
    153 
    154   return ares_dns_rr_set_u8(rr, key, u8);
    155 }
    156 
    157 static ares_status_t ares_dns_parse_rr_a(ares_buf_t *buf, ares_dns_rr_t *rr,
    158                                          size_t rdlength)
    159 {
    160   struct in_addr addr;
    161   ares_status_t  status;
    162 
    163   (void)rdlength; /* Not needed */
    164 
    165   status = ares_buf_fetch_bytes(buf, (unsigned char *)&addr, sizeof(addr));
    166   if (status != ARES_SUCCESS) {
    167     return status;
    168   }
    169 
    170   return ares_dns_rr_set_addr(rr, ARES_RR_A_ADDR, &addr);
    171 }
    172 
    173 static ares_status_t ares_dns_parse_rr_ns(ares_buf_t *buf, ares_dns_rr_t *rr,
    174                                           size_t rdlength)
    175 {
    176   (void)rdlength; /* Not needed */
    177 
    178   return ares_dns_parse_and_set_dns_name(buf, ARES_FALSE, rr,
    179                                          ARES_RR_NS_NSDNAME);
    180 }
    181 
    182 static ares_status_t ares_dns_parse_rr_cname(ares_buf_t *buf, ares_dns_rr_t *rr,
    183                                              size_t rdlength)
    184 {
    185   (void)rdlength; /* Not needed */
    186 
    187   return ares_dns_parse_and_set_dns_name(buf, ARES_FALSE, rr,
    188                                          ARES_RR_CNAME_CNAME);
    189 }
    190 
    191 static ares_status_t ares_dns_parse_rr_soa(ares_buf_t *buf, ares_dns_rr_t *rr,
    192                                            size_t rdlength)
    193 {
    194   ares_status_t status;
    195 
    196   (void)rdlength; /* Not needed */
    197 
    198   /* MNAME */
    199   status =
    200     ares_dns_parse_and_set_dns_name(buf, ARES_FALSE, rr, ARES_RR_SOA_MNAME);
    201   if (status != ARES_SUCCESS) {
    202     return status;
    203   }
    204 
    205   /* RNAME */
    206   status =
    207     ares_dns_parse_and_set_dns_name(buf, ARES_FALSE, rr, ARES_RR_SOA_RNAME);
    208   if (status != ARES_SUCCESS) {
    209     return status;
    210   }
    211 
    212   /* SERIAL */
    213   status = ares_dns_parse_and_set_be32(buf, rr, ARES_RR_SOA_SERIAL);
    214   if (status != ARES_SUCCESS) {
    215     return status;
    216   }
    217 
    218   /* REFRESH */
    219   status = ares_dns_parse_and_set_be32(buf, rr, ARES_RR_SOA_REFRESH);
    220   if (status != ARES_SUCCESS) {
    221     return status;
    222   }
    223 
    224   /* RETRY */
    225   status = ares_dns_parse_and_set_be32(buf, rr, ARES_RR_SOA_RETRY);
    226   if (status != ARES_SUCCESS) {
    227     return status;
    228   }
    229 
    230   /* EXPIRE */
    231   status = ares_dns_parse_and_set_be32(buf, rr, ARES_RR_SOA_EXPIRE);
    232   if (status != ARES_SUCCESS) {
    233     return status;
    234   }
    235 
    236   /* MINIMUM */
    237   return ares_dns_parse_and_set_be32(buf, rr, ARES_RR_SOA_MINIMUM);
    238 }
    239 
    240 static ares_status_t ares_dns_parse_rr_ptr(ares_buf_t *buf, ares_dns_rr_t *rr,
    241                                            size_t rdlength)
    242 {
    243   (void)rdlength; /* Not needed */
    244 
    245   return ares_dns_parse_and_set_dns_name(buf, ARES_FALSE, rr,
    246                                          ARES_RR_PTR_DNAME);
    247 }
    248 
    249 static ares_status_t ares_dns_parse_rr_hinfo(ares_buf_t *buf, ares_dns_rr_t *rr,
    250                                              size_t rdlength)
    251 {
    252   ares_status_t status;
    253   size_t        orig_len = ares_buf_len(buf);
    254 
    255   (void)rdlength; /* Not needed */
    256 
    257   /* CPU */
    258   status = ares_dns_parse_and_set_dns_str(
    259     buf, ares_dns_rr_remaining_len(buf, orig_len, rdlength), rr,
    260     ARES_RR_HINFO_CPU, ARES_TRUE);
    261   if (status != ARES_SUCCESS) {
    262     return status;
    263   }
    264 
    265   /* OS */
    266   status = ares_dns_parse_and_set_dns_str(
    267     buf, ares_dns_rr_remaining_len(buf, orig_len, rdlength), rr,
    268     ARES_RR_HINFO_OS, ARES_TRUE);
    269 
    270   return status;
    271 }
    272 
    273 static ares_status_t ares_dns_parse_rr_mx(ares_buf_t *buf, ares_dns_rr_t *rr,
    274                                           size_t rdlength)
    275 {
    276   ares_status_t status;
    277 
    278   (void)rdlength; /* Not needed */
    279 
    280   /* PREFERENCE */
    281   status = ares_dns_parse_and_set_be16(buf, rr, ARES_RR_MX_PREFERENCE);
    282   if (status != ARES_SUCCESS) {
    283     return status;
    284   }
    285 
    286   /* EXCHANGE */
    287   return ares_dns_parse_and_set_dns_name(buf, ARES_FALSE, rr,
    288                                          ARES_RR_MX_EXCHANGE);
    289 }
    290 
    291 static ares_status_t ares_dns_parse_rr_txt(ares_buf_t *buf, ares_dns_rr_t *rr,
    292                                            size_t rdlength)
    293 {
    294   return ares_dns_parse_and_set_dns_abin(buf, rdlength, rr, ARES_RR_TXT_DATA,
    295                                          ARES_FALSE);
    296 }
    297 
    298 static ares_status_t ares_dns_parse_rr_sig(ares_buf_t *buf, ares_dns_rr_t *rr,
    299                                            size_t rdlength)
    300 {
    301   ares_status_t  status;
    302   size_t         orig_len = ares_buf_len(buf);
    303   size_t         len;
    304   unsigned char *data;
    305 
    306   status = ares_dns_parse_and_set_be16(buf, rr, ARES_RR_SIG_TYPE_COVERED);
    307   if (status != ARES_SUCCESS) {
    308     return status;
    309   }
    310 
    311   status = ares_dns_parse_and_set_u8(buf, rr, ARES_RR_SIG_ALGORITHM);
    312   if (status != ARES_SUCCESS) {
    313     return status;
    314   }
    315 
    316   status = ares_dns_parse_and_set_u8(buf, rr, ARES_RR_SIG_LABELS);
    317   if (status != ARES_SUCCESS) {
    318     return status;
    319   }
    320 
    321   status = ares_dns_parse_and_set_be32(buf, rr, ARES_RR_SIG_ORIGINAL_TTL);
    322   if (status != ARES_SUCCESS) {
    323     return status;
    324   }
    325 
    326   status = ares_dns_parse_and_set_be32(buf, rr, ARES_RR_SIG_EXPIRATION);
    327   if (status != ARES_SUCCESS) {
    328     return status;
    329   }
    330 
    331   status = ares_dns_parse_and_set_be32(buf, rr, ARES_RR_SIG_INCEPTION);
    332   if (status != ARES_SUCCESS) {
    333     return status;
    334   }
    335 
    336   status = ares_dns_parse_and_set_be16(buf, rr, ARES_RR_SIG_KEY_TAG);
    337   if (status != ARES_SUCCESS) {
    338     return status;
    339   }
    340 
    341   status = ares_dns_parse_and_set_dns_name(buf, ARES_FALSE, rr,
    342                                            ARES_RR_SIG_SIGNERS_NAME);
    343   if (status != ARES_SUCCESS) {
    344     return status;
    345   }
    346 
    347   len = ares_dns_rr_remaining_len(buf, orig_len, rdlength);
    348   if (len == 0) {
    349     return ARES_EBADRESP;
    350   }
    351 
    352   status = ares_buf_fetch_bytes_dup(buf, len, ARES_FALSE, &data);
    353   if (status != ARES_SUCCESS) {
    354     return status;
    355   }
    356 
    357   status = ares_dns_rr_set_bin_own(rr, ARES_RR_SIG_SIGNATURE, data, len);
    358   if (status != ARES_SUCCESS) {
    359     ares_free(data);
    360     return status;
    361   }
    362 
    363   return ARES_SUCCESS;
    364 }
    365 
    366 static ares_status_t ares_dns_parse_rr_aaaa(ares_buf_t *buf, ares_dns_rr_t *rr,
    367                                             size_t rdlength)
    368 {
    369   struct ares_in6_addr addr;
    370   ares_status_t        status;
    371 
    372   (void)rdlength; /* Not needed */
    373 
    374   status = ares_buf_fetch_bytes(buf, (unsigned char *)&addr, sizeof(addr));
    375   if (status != ARES_SUCCESS) {
    376     return status;
    377   }
    378 
    379   return ares_dns_rr_set_addr6(rr, ARES_RR_AAAA_ADDR, &addr);
    380 }
    381 
    382 static ares_status_t ares_dns_parse_rr_srv(ares_buf_t *buf, ares_dns_rr_t *rr,
    383                                            size_t rdlength)
    384 {
    385   ares_status_t status;
    386 
    387   (void)rdlength; /* Not needed */
    388 
    389   /* PRIORITY */
    390   status = ares_dns_parse_and_set_be16(buf, rr, ARES_RR_SRV_PRIORITY);
    391   if (status != ARES_SUCCESS) {
    392     return status;
    393   }
    394 
    395   /* WEIGHT */
    396   status = ares_dns_parse_and_set_be16(buf, rr, ARES_RR_SRV_WEIGHT);
    397   if (status != ARES_SUCCESS) {
    398     return status;
    399   }
    400 
    401   /* PORT */
    402   status = ares_dns_parse_and_set_be16(buf, rr, ARES_RR_SRV_PORT);
    403   if (status != ARES_SUCCESS) {
    404     return status;
    405   }
    406 
    407   /* TARGET */
    408   return ares_dns_parse_and_set_dns_name(buf, ARES_FALSE, rr,
    409                                          ARES_RR_SRV_TARGET);
    410 }
    411 
    412 static ares_status_t ares_dns_parse_rr_naptr(ares_buf_t *buf, ares_dns_rr_t *rr,
    413                                              size_t rdlength)
    414 {
    415   ares_status_t status;
    416   size_t        orig_len = ares_buf_len(buf);
    417 
    418   /* ORDER */
    419   status = ares_dns_parse_and_set_be16(buf, rr, ARES_RR_NAPTR_ORDER);
    420   if (status != ARES_SUCCESS) {
    421     return status;
    422   }
    423 
    424   /* PREFERENCE */
    425   status = ares_dns_parse_and_set_be16(buf, rr, ARES_RR_NAPTR_PREFERENCE);
    426   if (status != ARES_SUCCESS) {
    427     return status;
    428   }
    429 
    430   /* FLAGS */
    431   status = ares_dns_parse_and_set_dns_str(
    432     buf, ares_dns_rr_remaining_len(buf, orig_len, rdlength), rr,
    433     ARES_RR_NAPTR_FLAGS, ARES_TRUE);
    434   if (status != ARES_SUCCESS) {
    435     return status;
    436   }
    437 
    438   /* SERVICES */
    439   status = ares_dns_parse_and_set_dns_str(
    440     buf, ares_dns_rr_remaining_len(buf, orig_len, rdlength), rr,
    441     ARES_RR_NAPTR_SERVICES, ARES_TRUE);
    442   if (status != ARES_SUCCESS) {
    443     return status;
    444   }
    445 
    446   /* REGEXP */
    447   status = ares_dns_parse_and_set_dns_str(
    448     buf, ares_dns_rr_remaining_len(buf, orig_len, rdlength), rr,
    449     ARES_RR_NAPTR_REGEXP, ARES_TRUE);
    450   if (status != ARES_SUCCESS) {
    451     return status;
    452   }
    453 
    454   /* REPLACEMENT */
    455   return ares_dns_parse_and_set_dns_name(buf, ARES_FALSE, rr,
    456                                          ARES_RR_NAPTR_REPLACEMENT);
    457 }
    458 
    459 static ares_status_t ares_dns_parse_rr_opt(ares_buf_t *buf, ares_dns_rr_t *rr,
    460                                            size_t         rdlength,
    461                                            unsigned short raw_class,
    462                                            unsigned int   raw_ttl)
    463 {
    464   ares_status_t  status;
    465   size_t         orig_len = ares_buf_len(buf);
    466   unsigned short rcode_high;
    467 
    468   status = ares_dns_rr_set_u16(rr, ARES_RR_OPT_UDP_SIZE, raw_class);
    469   if (status != ARES_SUCCESS) {
    470     return status;
    471   }
    472 
    473   /* First 8 bits of TTL are an extended RCODE, and they go in the higher order
    474    * after the original 4-bit rcode */
    475   rcode_high             = (unsigned short)((raw_ttl >> 20) & 0x0FF0);
    476   rr->parent->raw_rcode |= rcode_high;
    477 
    478   status = ares_dns_rr_set_u8(rr, ARES_RR_OPT_VERSION,
    479                               (unsigned char)(raw_ttl >> 16) & 0xFF);
    480   if (status != ARES_SUCCESS) {
    481     return status;
    482   }
    483 
    484   status = ares_dns_rr_set_u16(rr, ARES_RR_OPT_FLAGS,
    485                                (unsigned short)(raw_ttl & 0xFFFF));
    486   if (status != ARES_SUCCESS) {
    487     return status;
    488   }
    489 
    490   /* Parse options */
    491   while (ares_dns_rr_remaining_len(buf, orig_len, rdlength)) {
    492     unsigned short opt = 0;
    493     unsigned short len = 0;
    494     unsigned char *val = NULL;
    495 
    496     /* Fetch be16 option */
    497     status = ares_buf_fetch_be16(buf, &opt);
    498     if (status != ARES_SUCCESS) {
    499       return status;
    500     }
    501 
    502     /* Fetch be16 length */
    503     status = ares_buf_fetch_be16(buf, &len);
    504     if (status != ARES_SUCCESS) {
    505       return status;
    506     }
    507 
    508     if (len) {
    509       status = ares_buf_fetch_bytes_dup(buf, len, ARES_TRUE, &val);
    510       if (status != ARES_SUCCESS) {
    511         return status;
    512       }
    513     }
    514 
    515     status = ares_dns_rr_set_opt_own(rr, ARES_RR_OPT_OPTIONS, opt, val, len);
    516     if (status != ARES_SUCCESS) {
    517       return status;
    518     }
    519   }
    520 
    521   return ARES_SUCCESS;
    522 }
    523 
    524 static ares_status_t ares_dns_parse_rr_tlsa(ares_buf_t *buf, ares_dns_rr_t *rr,
    525                                             size_t rdlength)
    526 {
    527   ares_status_t  status;
    528   size_t         orig_len = ares_buf_len(buf);
    529   size_t         len;
    530   unsigned char *data;
    531 
    532   status = ares_dns_parse_and_set_u8(buf, rr, ARES_RR_TLSA_CERT_USAGE);
    533   if (status != ARES_SUCCESS) {
    534     return status;
    535   }
    536 
    537   status = ares_dns_parse_and_set_u8(buf, rr, ARES_RR_TLSA_SELECTOR);
    538   if (status != ARES_SUCCESS) {
    539     return status;
    540   }
    541 
    542   status = ares_dns_parse_and_set_u8(buf, rr, ARES_RR_TLSA_MATCH);
    543   if (status != ARES_SUCCESS) {
    544     return status;
    545   }
    546 
    547   len = ares_dns_rr_remaining_len(buf, orig_len, rdlength);
    548   if (len == 0) {
    549     return ARES_EBADRESP;
    550   }
    551 
    552   status = ares_buf_fetch_bytes_dup(buf, len, ARES_FALSE, &data);
    553   if (status != ARES_SUCCESS) {
    554     return status;
    555   }
    556 
    557   status = ares_dns_rr_set_bin_own(rr, ARES_RR_TLSA_DATA, data, len);
    558   if (status != ARES_SUCCESS) {
    559     ares_free(data);
    560     return status;
    561   }
    562 
    563   return ARES_SUCCESS;
    564 }
    565 
    566 static ares_status_t ares_dns_parse_rr_svcb(ares_buf_t *buf, ares_dns_rr_t *rr,
    567                                             size_t rdlength)
    568 {
    569   ares_status_t status;
    570   size_t        orig_len = ares_buf_len(buf);
    571 
    572   status = ares_dns_parse_and_set_be16(buf, rr, ARES_RR_SVCB_PRIORITY);
    573   if (status != ARES_SUCCESS) {
    574     return status;
    575   }
    576 
    577   status =
    578     ares_dns_parse_and_set_dns_name(buf, ARES_FALSE, rr, ARES_RR_SVCB_TARGET);
    579   if (status != ARES_SUCCESS) {
    580     return status;
    581   }
    582 
    583   /* Parse params */
    584   while (ares_dns_rr_remaining_len(buf, orig_len, rdlength)) {
    585     unsigned short opt = 0;
    586     unsigned short len = 0;
    587     unsigned char *val = NULL;
    588 
    589     /* Fetch be16 option */
    590     status = ares_buf_fetch_be16(buf, &opt);
    591     if (status != ARES_SUCCESS) {
    592       return status;
    593     }
    594 
    595     /* Fetch be16 length */
    596     status = ares_buf_fetch_be16(buf, &len);
    597     if (status != ARES_SUCCESS) {
    598       return status;
    599     }
    600 
    601     if (len) {
    602       status = ares_buf_fetch_bytes_dup(buf, len, ARES_TRUE, &val);
    603       if (status != ARES_SUCCESS) {
    604         return status;
    605       }
    606     }
    607 
    608     status = ares_dns_rr_set_opt_own(rr, ARES_RR_SVCB_PARAMS, opt, val, len);
    609     if (status != ARES_SUCCESS) {
    610       return status;
    611     }
    612   }
    613 
    614   return ARES_SUCCESS;
    615 }
    616 
    617 static ares_status_t ares_dns_parse_rr_https(ares_buf_t *buf, ares_dns_rr_t *rr,
    618                                              size_t rdlength)
    619 {
    620   ares_status_t status;
    621   size_t        orig_len = ares_buf_len(buf);
    622 
    623   status = ares_dns_parse_and_set_be16(buf, rr, ARES_RR_HTTPS_PRIORITY);
    624   if (status != ARES_SUCCESS) {
    625     return status;
    626   }
    627 
    628   status =
    629     ares_dns_parse_and_set_dns_name(buf, ARES_FALSE, rr, ARES_RR_HTTPS_TARGET);
    630   if (status != ARES_SUCCESS) {
    631     return status;
    632   }
    633 
    634   /* Parse params */
    635   while (ares_dns_rr_remaining_len(buf, orig_len, rdlength)) {
    636     unsigned short opt = 0;
    637     unsigned short len = 0;
    638     unsigned char *val = NULL;
    639 
    640     /* Fetch be16 option */
    641     status = ares_buf_fetch_be16(buf, &opt);
    642     if (status != ARES_SUCCESS) {
    643       return status;
    644     }
    645 
    646     /* Fetch be16 length */
    647     status = ares_buf_fetch_be16(buf, &len);
    648     if (status != ARES_SUCCESS) {
    649       return status;
    650     }
    651 
    652     if (len) {
    653       status = ares_buf_fetch_bytes_dup(buf, len, ARES_TRUE, &val);
    654       if (status != ARES_SUCCESS) {
    655         return status;
    656       }
    657     }
    658 
    659     status = ares_dns_rr_set_opt_own(rr, ARES_RR_HTTPS_PARAMS, opt, val, len);
    660     if (status != ARES_SUCCESS) {
    661       return status;
    662     }
    663   }
    664 
    665   return ARES_SUCCESS;
    666 }
    667 
    668 static ares_status_t ares_dns_parse_rr_uri(ares_buf_t *buf, ares_dns_rr_t *rr,
    669                                            size_t rdlength)
    670 {
    671   char         *name = NULL;
    672   ares_status_t status;
    673   size_t        orig_len = ares_buf_len(buf);
    674   size_t        remaining_len;
    675 
    676   /* PRIORITY */
    677   status = ares_dns_parse_and_set_be16(buf, rr, ARES_RR_URI_PRIORITY);
    678   if (status != ARES_SUCCESS) {
    679     return status;
    680   }
    681 
    682   /* WEIGHT */
    683   status = ares_dns_parse_and_set_be16(buf, rr, ARES_RR_URI_WEIGHT);
    684   if (status != ARES_SUCCESS) {
    685     return status;
    686   }
    687 
    688   /* TARGET -- not in string format, rest of buffer, required to be
    689    * non-zero length */
    690   remaining_len = ares_dns_rr_remaining_len(buf, orig_len, rdlength);
    691   if (remaining_len == 0) {
    692     status = ARES_EBADRESP;
    693     return status;
    694   }
    695 
    696   /* NOTE: Not in DNS string format */
    697   status = ares_buf_fetch_str_dup(buf, remaining_len, &name);
    698   if (status != ARES_SUCCESS) {
    699     return status;
    700   }
    701 
    702   if (!ares_str_isprint(name, remaining_len)) {
    703     ares_free(name);
    704     return ARES_EBADRESP;
    705   }
    706 
    707   status = ares_dns_rr_set_str_own(rr, ARES_RR_URI_TARGET, name);
    708   if (status != ARES_SUCCESS) {
    709     ares_free(name);
    710     return status;
    711   }
    712   name = NULL;
    713 
    714   return ARES_SUCCESS;
    715 }
    716 
    717 static ares_status_t ares_dns_parse_rr_caa(ares_buf_t *buf, ares_dns_rr_t *rr,
    718                                            size_t rdlength)
    719 {
    720   unsigned char *data     = NULL;
    721   size_t         data_len = 0;
    722   ares_status_t  status;
    723   size_t         orig_len = ares_buf_len(buf);
    724 
    725   /* CRITICAL */
    726   status = ares_dns_parse_and_set_u8(buf, rr, ARES_RR_CAA_CRITICAL);
    727   if (status != ARES_SUCCESS) {
    728     return status;
    729   }
    730 
    731   /* Tag */
    732   status = ares_dns_parse_and_set_dns_str(
    733     buf, ares_dns_rr_remaining_len(buf, orig_len, rdlength), rr,
    734     ARES_RR_CAA_TAG, ARES_FALSE);
    735   if (status != ARES_SUCCESS) {
    736     return status;
    737   }
    738 
    739   /* Value - binary! (remaining buffer */
    740   data_len = ares_dns_rr_remaining_len(buf, orig_len, rdlength);
    741   if (data_len == 0) {
    742     status = ARES_EBADRESP;
    743     return status;
    744   }
    745   status = ares_buf_fetch_bytes_dup(buf, data_len, ARES_TRUE, &data);
    746   if (status != ARES_SUCCESS) {
    747     return status;
    748   }
    749 
    750   status = ares_dns_rr_set_bin_own(rr, ARES_RR_CAA_VALUE, data, data_len);
    751   if (status != ARES_SUCCESS) {
    752     ares_free(data);
    753     return status;
    754   }
    755   data = NULL;
    756 
    757   return ARES_SUCCESS;
    758 }
    759 
    760 static ares_status_t ares_dns_parse_rr_raw_rr(ares_buf_t    *buf,
    761                                               ares_dns_rr_t *rr,
    762                                               size_t         rdlength,
    763                                               unsigned short raw_type)
    764 {
    765   ares_status_t  status;
    766   unsigned char *bytes = NULL;
    767 
    768   if (rdlength == 0) {
    769     return ARES_SUCCESS;
    770   }
    771 
    772   status = ares_buf_fetch_bytes_dup(buf, rdlength, ARES_FALSE, &bytes);
    773   if (status != ARES_SUCCESS) {
    774     return status;
    775   }
    776 
    777   /* Can't fail */
    778   status = ares_dns_rr_set_u16(rr, ARES_RR_RAW_RR_TYPE, raw_type);
    779   if (status != ARES_SUCCESS) {
    780     ares_free(bytes);
    781     return status;
    782   }
    783 
    784   status = ares_dns_rr_set_bin_own(rr, ARES_RR_RAW_RR_DATA, bytes, rdlength);
    785   if (status != ARES_SUCCESS) {
    786     ares_free(bytes);
    787     return status;
    788   }
    789 
    790   return ARES_SUCCESS;
    791 }
    792 
    793 static ares_status_t ares_dns_parse_header(ares_buf_t *buf, unsigned int flags,
    794                                            ares_dns_record_t **dnsrec,
    795                                            unsigned short     *qdcount,
    796                                            unsigned short     *ancount,
    797                                            unsigned short     *nscount,
    798                                            unsigned short     *arcount)
    799 {
    800   ares_status_t     status = ARES_EBADRESP;
    801   unsigned short    u16;
    802   unsigned short    id;
    803   unsigned short    dns_flags = 0;
    804   ares_dns_opcode_t opcode;
    805   unsigned short    rcode;
    806 
    807   (void)flags; /* currently unused */
    808 
    809   if (buf == NULL || dnsrec == NULL || qdcount == NULL || ancount == NULL ||
    810       nscount == NULL || arcount == NULL) {
    811     return ARES_EFORMERR;
    812   }
    813 
    814   *dnsrec = NULL;
    815 
    816   /*
    817    *  RFC 1035 4.1.1. Header section format.
    818    *  and Updated by RFC 2065 to add AD and CD bits.
    819    *                                  1  1  1  1  1  1
    820    *    0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
    821    *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    822    *  |                      ID                       |
    823    *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    824    *  |QR|   Opcode  |AA|TC|RD|RA| Z|AD|CD|   RCODE   |
    825    *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    826    *  |                    QDCOUNT                    |
    827    *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    828    *  |                    ANCOUNT                    |
    829    *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    830    *  |                    NSCOUNT                    |
    831    *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    832    *  |                    ARCOUNT                    |
    833    *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    834    */
    835 
    836   /* ID */
    837   status = ares_buf_fetch_be16(buf, &id);
    838   if (status != ARES_SUCCESS) {
    839     goto fail;
    840   }
    841 
    842   /* Flags */
    843   status = ares_buf_fetch_be16(buf, &u16);
    844   if (status != ARES_SUCCESS) {
    845     goto fail;
    846   }
    847 
    848   /* QR */
    849   if (u16 & 0x8000) {
    850     dns_flags |= ARES_FLAG_QR;
    851   }
    852 
    853   /* OPCODE */
    854   opcode = (u16 >> 11) & 0xf;
    855 
    856   /* AA */
    857   if (u16 & 0x400) {
    858     dns_flags |= ARES_FLAG_AA;
    859   }
    860 
    861   /* TC */
    862   if (u16 & 0x200) {
    863     dns_flags |= ARES_FLAG_TC;
    864   }
    865 
    866   /* RD */
    867   if (u16 & 0x100) {
    868     dns_flags |= ARES_FLAG_RD;
    869   }
    870 
    871   /* RA */
    872   if (u16 & 0x80) {
    873     dns_flags |= ARES_FLAG_RA;
    874   }
    875 
    876   /* Z -- unused */
    877 
    878   /* AD */
    879   if (u16 & 0x20) {
    880     dns_flags |= ARES_FLAG_AD;
    881   }
    882 
    883   /* CD */
    884   if (u16 & 0x10) {
    885     dns_flags |= ARES_FLAG_CD;
    886   }
    887 
    888   /* RCODE */
    889   rcode = u16 & 0xf;
    890 
    891   /* QDCOUNT */
    892   status = ares_buf_fetch_be16(buf, qdcount);
    893   if (status != ARES_SUCCESS) {
    894     goto fail;
    895   }
    896 
    897   /* ANCOUNT */
    898   status = ares_buf_fetch_be16(buf, ancount);
    899   if (status != ARES_SUCCESS) {
    900     goto fail;
    901   }
    902 
    903   /* NSCOUNT */
    904   status = ares_buf_fetch_be16(buf, nscount);
    905   if (status != ARES_SUCCESS) {
    906     goto fail;
    907   }
    908 
    909   /* ARCOUNT */
    910   status = ares_buf_fetch_be16(buf, arcount);
    911   if (status != ARES_SUCCESS) {
    912     goto fail;
    913   }
    914 
    915   status = ares_dns_record_create(dnsrec, id, dns_flags, opcode,
    916                                   ARES_RCODE_NOERROR /* Temporary */);
    917   if (status != ARES_SUCCESS) {
    918     goto fail;
    919   }
    920 
    921   (*dnsrec)->raw_rcode = rcode;
    922 
    923   if (*ancount > 0) {
    924     status =
    925       ares_dns_record_rr_prealloc(*dnsrec, ARES_SECTION_ANSWER, *ancount);
    926     if (status != ARES_SUCCESS) {
    927       goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
    928     }
    929   }
    930 
    931   if (*nscount > 0) {
    932     status =
    933       ares_dns_record_rr_prealloc(*dnsrec, ARES_SECTION_AUTHORITY, *nscount);
    934     if (status != ARES_SUCCESS) {
    935       goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
    936     }
    937   }
    938 
    939   if (*arcount > 0) {
    940     status =
    941       ares_dns_record_rr_prealloc(*dnsrec, ARES_SECTION_ADDITIONAL, *arcount);
    942     if (status != ARES_SUCCESS) {
    943       goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
    944     }
    945   }
    946 
    947   return ARES_SUCCESS;
    948 
    949 fail:
    950   ares_dns_record_destroy(*dnsrec);
    951   *dnsrec  = NULL;
    952   *qdcount = 0;
    953   *ancount = 0;
    954   *nscount = 0;
    955   *arcount = 0;
    956 
    957   return status;
    958 }
    959 
    960 static ares_status_t
    961   ares_dns_parse_rr_data(ares_buf_t *buf, size_t rdlength, ares_dns_rr_t *rr,
    962                          ares_dns_rec_type_t type, unsigned short raw_type,
    963                          unsigned short raw_class, unsigned int raw_ttl)
    964 {
    965   switch (type) {
    966     case ARES_REC_TYPE_A:
    967       return ares_dns_parse_rr_a(buf, rr, rdlength);
    968     case ARES_REC_TYPE_NS:
    969       return ares_dns_parse_rr_ns(buf, rr, rdlength);
    970     case ARES_REC_TYPE_CNAME:
    971       return ares_dns_parse_rr_cname(buf, rr, rdlength);
    972     case ARES_REC_TYPE_SOA:
    973       return ares_dns_parse_rr_soa(buf, rr, rdlength);
    974     case ARES_REC_TYPE_PTR:
    975       return ares_dns_parse_rr_ptr(buf, rr, rdlength);
    976     case ARES_REC_TYPE_HINFO:
    977       return ares_dns_parse_rr_hinfo(buf, rr, rdlength);
    978     case ARES_REC_TYPE_MX:
    979       return ares_dns_parse_rr_mx(buf, rr, rdlength);
    980     case ARES_REC_TYPE_TXT:
    981       return ares_dns_parse_rr_txt(buf, rr, rdlength);
    982     case ARES_REC_TYPE_SIG:
    983       return ares_dns_parse_rr_sig(buf, rr, rdlength);
    984     case ARES_REC_TYPE_AAAA:
    985       return ares_dns_parse_rr_aaaa(buf, rr, rdlength);
    986     case ARES_REC_TYPE_SRV:
    987       return ares_dns_parse_rr_srv(buf, rr, rdlength);
    988     case ARES_REC_TYPE_NAPTR:
    989       return ares_dns_parse_rr_naptr(buf, rr, rdlength);
    990     case ARES_REC_TYPE_ANY:
    991       return ARES_EBADRESP;
    992     case ARES_REC_TYPE_OPT:
    993       return ares_dns_parse_rr_opt(buf, rr, rdlength, raw_class, raw_ttl);
    994     case ARES_REC_TYPE_TLSA:
    995       return ares_dns_parse_rr_tlsa(buf, rr, rdlength);
    996     case ARES_REC_TYPE_SVCB:
    997       return ares_dns_parse_rr_svcb(buf, rr, rdlength);
    998     case ARES_REC_TYPE_HTTPS:
    999       return ares_dns_parse_rr_https(buf, rr, rdlength);
   1000     case ARES_REC_TYPE_URI:
   1001       return ares_dns_parse_rr_uri(buf, rr, rdlength);
   1002     case ARES_REC_TYPE_CAA:
   1003       return ares_dns_parse_rr_caa(buf, rr, rdlength);
   1004     case ARES_REC_TYPE_RAW_RR:
   1005       return ares_dns_parse_rr_raw_rr(buf, rr, rdlength, raw_type);
   1006   }
   1007   return ARES_EFORMERR;
   1008 }
   1009 
   1010 static ares_status_t ares_dns_parse_qd(ares_buf_t        *buf,
   1011                                        ares_dns_record_t *dnsrec)
   1012 {
   1013   char               *name = NULL;
   1014   unsigned short      u16;
   1015   ares_status_t       status;
   1016   ares_dns_rec_type_t type;
   1017   ares_dns_class_t    qclass;
   1018   /* The question section is used to carry the "question" in most queries,
   1019    * i.e., the parameters that define what is being asked.  The section
   1020    * contains QDCOUNT (usually 1) entries, each of the following format:
   1021    *                                 1  1  1  1  1  1
   1022    *   0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
   1023    * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   1024    * |                                               |
   1025    * /                     QNAME                     /
   1026    * /                                               /
   1027    * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   1028    * |                     QTYPE                     |
   1029    * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   1030    * |                     QCLASS                    |
   1031    * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   1032    */
   1033 
   1034   /* Name */
   1035   status = ares_dns_name_parse(buf, &name, ARES_FALSE);
   1036   if (status != ARES_SUCCESS) {
   1037     goto done;
   1038   }
   1039 
   1040   /* Type */
   1041   status = ares_buf_fetch_be16(buf, &u16);
   1042   if (status != ARES_SUCCESS) {
   1043     goto done;
   1044   }
   1045   type = u16;
   1046 
   1047   /* Class */
   1048   status = ares_buf_fetch_be16(buf, &u16);
   1049   if (status != ARES_SUCCESS) {
   1050     goto done;
   1051   }
   1052   qclass = u16;
   1053 
   1054   /* Add question */
   1055   status = ares_dns_record_query_add(dnsrec, name, type, qclass);
   1056   if (status != ARES_SUCCESS) {
   1057     goto done;
   1058   }
   1059 
   1060 done:
   1061   ares_free(name);
   1062   return status;
   1063 }
   1064 
   1065 static ares_status_t ares_dns_parse_rr(ares_buf_t *buf, unsigned int flags,
   1066                                        ares_dns_section_t sect,
   1067                                        ares_dns_record_t *dnsrec)
   1068 {
   1069   char               *name = NULL;
   1070   unsigned short      u16;
   1071   unsigned short      raw_type;
   1072   ares_status_t       status;
   1073   ares_dns_rec_type_t type;
   1074   ares_dns_class_t    qclass;
   1075   unsigned int        ttl;
   1076   size_t              rdlength;
   1077   ares_dns_rr_t      *rr            = NULL;
   1078   size_t              remaining_len = 0;
   1079   size_t              processed_len = 0;
   1080   ares_bool_t         namecomp;
   1081 
   1082   /* All RRs have the same top level format shown below:
   1083    *                                 1  1  1  1  1  1
   1084    *   0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
   1085    * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   1086    * |                                               |
   1087    * /                                               /
   1088    * /                      NAME                     /
   1089    * |                                               |
   1090    * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   1091    * |                      TYPE                     |
   1092    * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   1093    * |                     CLASS                     |
   1094    * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   1095    * |                      TTL                      |
   1096    * |                                               |
   1097    * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   1098    * |                   RDLENGTH                    |
   1099    * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
   1100    * /                     RDATA                     /
   1101    * /                                               /
   1102    * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   1103    */
   1104 
   1105   /* Name */
   1106   status = ares_dns_name_parse(buf, &name, ARES_FALSE);
   1107   if (status != ARES_SUCCESS) {
   1108     goto done;
   1109   }
   1110 
   1111   /* Type */
   1112   status = ares_buf_fetch_be16(buf, &u16);
   1113   if (status != ARES_SUCCESS) {
   1114     goto done;
   1115   }
   1116   type     = u16;
   1117   raw_type = u16; /* Only used for raw rr data */
   1118 
   1119   /* Class */
   1120   status = ares_buf_fetch_be16(buf, &u16);
   1121   if (status != ARES_SUCCESS) {
   1122     goto done;
   1123   }
   1124   qclass = u16;
   1125 
   1126   /* TTL */
   1127   status = ares_buf_fetch_be32(buf, &ttl);
   1128   if (status != ARES_SUCCESS) {
   1129     goto done;
   1130   }
   1131 
   1132   /* Length */
   1133   status = ares_buf_fetch_be16(buf, &u16);
   1134   if (status != ARES_SUCCESS) {
   1135     goto done;
   1136   }
   1137   rdlength = u16;
   1138 
   1139   if (!ares_dns_rec_type_isvalid(type, ARES_FALSE)) {
   1140     type = ARES_REC_TYPE_RAW_RR;
   1141   }
   1142 
   1143   namecomp = ares_dns_rec_allow_name_comp(type);
   1144   if (sect == ARES_SECTION_ANSWER &&
   1145       (flags &
   1146        (namecomp ? ARES_DNS_PARSE_AN_BASE_RAW : ARES_DNS_PARSE_AN_EXT_RAW))) {
   1147     type = ARES_REC_TYPE_RAW_RR;
   1148   }
   1149   if (sect == ARES_SECTION_AUTHORITY &&
   1150       (flags &
   1151        (namecomp ? ARES_DNS_PARSE_NS_BASE_RAW : ARES_DNS_PARSE_NS_EXT_RAW))) {
   1152     type = ARES_REC_TYPE_RAW_RR;
   1153   }
   1154   if (sect == ARES_SECTION_ADDITIONAL &&
   1155       (flags &
   1156        (namecomp ? ARES_DNS_PARSE_AR_BASE_RAW : ARES_DNS_PARSE_AR_EXT_RAW))) {
   1157     type = ARES_REC_TYPE_RAW_RR;
   1158   }
   1159 
   1160   /* Pull into another buffer for safety */
   1161   if (rdlength > ares_buf_len(buf)) {
   1162     status = ARES_EBADRESP;
   1163     goto done;
   1164   }
   1165 
   1166   /* Add the base rr */
   1167   status =
   1168     ares_dns_record_rr_add(&rr, dnsrec, sect, name, type,
   1169                            type == ARES_REC_TYPE_OPT ? ARES_CLASS_IN : qclass,
   1170                            type == ARES_REC_TYPE_OPT ? 0 : ttl);
   1171   if (status != ARES_SUCCESS) {
   1172     goto done;
   1173   }
   1174 
   1175   /* Record the current remaining length in the buffer so we can tell how
   1176    * much was processed */
   1177   remaining_len = ares_buf_len(buf);
   1178 
   1179   /* Fill in the data for the rr */
   1180   status = ares_dns_parse_rr_data(buf, rdlength, rr, type, raw_type,
   1181                                   (unsigned short)qclass, ttl);
   1182   if (status != ARES_SUCCESS) {
   1183     goto done;
   1184   }
   1185 
   1186   /* Determine how many bytes were processed */
   1187   processed_len = remaining_len - ares_buf_len(buf);
   1188 
   1189   /* If too many bytes were processed, error! */
   1190   if (processed_len > rdlength) {
   1191     status = ARES_EBADRESP;
   1192     goto done;
   1193   }
   1194 
   1195   /* If too few bytes were processed, consume the unprocessed data for this
   1196    * record as the parser may not have wanted/needed to use it */
   1197   if (processed_len < rdlength) {
   1198     ares_buf_consume(buf, rdlength - processed_len);
   1199   }
   1200 
   1201 
   1202 done:
   1203   ares_free(name);
   1204   return status;
   1205 }
   1206 
   1207 static ares_status_t ares_dns_parse_buf(ares_buf_t *buf, unsigned int flags,
   1208                                         ares_dns_record_t **dnsrec)
   1209 {
   1210   ares_status_t  status;
   1211   unsigned short qdcount;
   1212   unsigned short ancount;
   1213   unsigned short nscount;
   1214   unsigned short arcount;
   1215   unsigned short i;
   1216 
   1217   if (buf == NULL || dnsrec == NULL) {
   1218     return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */
   1219   }
   1220 
   1221   /* Maximum DNS packet size is 64k, even over TCP */
   1222   if (ares_buf_len(buf) > 0xFFFF) {
   1223     return ARES_EFORMERR;
   1224   }
   1225 
   1226   /* All communications inside of the domain protocol are carried in a single
   1227    * format called a message.  The top level format of message is divided
   1228    * into 5 sections (some of which are empty in certain cases) shown below:
   1229    *
   1230    * +---------------------+
   1231    * |        Header       |
   1232    * +---------------------+
   1233    * |       Question      | the question for the name server
   1234    * +---------------------+
   1235    * |        Answer       | RRs answering the question
   1236    * +---------------------+
   1237    * |      Authority      | RRs pointing toward an authority
   1238    * +---------------------+
   1239    * |      Additional     | RRs holding additional information
   1240    * +---------------------+
   1241    */
   1242 
   1243   /* Parse header */
   1244   status = ares_dns_parse_header(buf, flags, dnsrec, &qdcount, &ancount,
   1245                                  &nscount, &arcount);
   1246   if (status != ARES_SUCCESS) {
   1247     goto fail;
   1248   }
   1249 
   1250   /* Must have questions */
   1251   if (qdcount == 0) {
   1252     status = ARES_EBADRESP;
   1253     goto fail;
   1254   }
   1255 
   1256   /* XXX: this should be controlled by a flag in case we want to allow
   1257    *      multiple questions.  I think mDNS allows this */
   1258   if (qdcount > 1) {
   1259     status = ARES_EBADRESP;
   1260     goto fail;
   1261   }
   1262 
   1263   /* Parse questions */
   1264   for (i = 0; i < qdcount; i++) {
   1265     status = ares_dns_parse_qd(buf, *dnsrec);
   1266     if (status != ARES_SUCCESS) {
   1267       goto fail;
   1268     }
   1269   }
   1270 
   1271   /* Parse Answers */
   1272   for (i = 0; i < ancount; i++) {
   1273     status = ares_dns_parse_rr(buf, flags, ARES_SECTION_ANSWER, *dnsrec);
   1274     if (status != ARES_SUCCESS) {
   1275       goto fail;
   1276     }
   1277   }
   1278 
   1279   /* Parse Authority */
   1280   for (i = 0; i < nscount; i++) {
   1281     status = ares_dns_parse_rr(buf, flags, ARES_SECTION_AUTHORITY, *dnsrec);
   1282     if (status != ARES_SUCCESS) {
   1283       goto fail;
   1284     }
   1285   }
   1286 
   1287   /* Parse Additional */
   1288   for (i = 0; i < arcount; i++) {
   1289     status = ares_dns_parse_rr(buf, flags, ARES_SECTION_ADDITIONAL, *dnsrec);
   1290     if (status != ARES_SUCCESS) {
   1291       goto fail;
   1292     }
   1293   }
   1294 
   1295   /* Finalize rcode now that if we have OPT it is processed */
   1296   if (!ares_dns_rcode_isvalid((*dnsrec)->raw_rcode)) {
   1297     (*dnsrec)->rcode = ARES_RCODE_SERVFAIL;
   1298   } else {
   1299     (*dnsrec)->rcode = (ares_dns_rcode_t)(*dnsrec)->raw_rcode;
   1300   }
   1301 
   1302   return ARES_SUCCESS;
   1303 
   1304 fail:
   1305   ares_dns_record_destroy(*dnsrec);
   1306   *dnsrec = NULL;
   1307   return status;
   1308 }
   1309 
   1310 ares_status_t ares_dns_parse(const unsigned char *buf, size_t buf_len,
   1311                              unsigned int flags, ares_dns_record_t **dnsrec)
   1312 {
   1313   ares_buf_t   *parser = NULL;
   1314   ares_status_t status;
   1315 
   1316   if (buf == NULL || buf_len == 0 || dnsrec == NULL) {
   1317     return ARES_EFORMERR;
   1318   }
   1319 
   1320   parser = ares_buf_create_const(buf, buf_len);
   1321   if (parser == NULL) {
   1322     return ARES_ENOMEM;
   1323   }
   1324 
   1325   status = ares_dns_parse_buf(parser, flags, dnsrec);
   1326   ares_buf_destroy(parser);
   1327 
   1328   return status;
   1329 }