11cb0ef41Sopenharmony_ci/* MIT License 21cb0ef41Sopenharmony_ci * 31cb0ef41Sopenharmony_ci * Copyright (c) 2023 Brad House 41cb0ef41Sopenharmony_ci * 51cb0ef41Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 61cb0ef41Sopenharmony_ci * of this software and associated documentation files (the "Software"), to deal 71cb0ef41Sopenharmony_ci * in the Software without restriction, including without limitation the rights 81cb0ef41Sopenharmony_ci * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 91cb0ef41Sopenharmony_ci * copies of the Software, and to permit persons to whom the Software is 101cb0ef41Sopenharmony_ci * furnished to do so, subject to the following conditions: 111cb0ef41Sopenharmony_ci * 121cb0ef41Sopenharmony_ci * The above copyright notice and this permission notice (including the next 131cb0ef41Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 141cb0ef41Sopenharmony_ci * Software. 151cb0ef41Sopenharmony_ci * 161cb0ef41Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 171cb0ef41Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 181cb0ef41Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 191cb0ef41Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 201cb0ef41Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 211cb0ef41Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 221cb0ef41Sopenharmony_ci * SOFTWARE. 231cb0ef41Sopenharmony_ci * 241cb0ef41Sopenharmony_ci * SPDX-License-Identifier: MIT 251cb0ef41Sopenharmony_ci */ 261cb0ef41Sopenharmony_ci#include "ares_setup.h" 271cb0ef41Sopenharmony_ci#include "ares.h" 281cb0ef41Sopenharmony_ci#include "ares_private.h" 291cb0ef41Sopenharmony_ci#include <limits.h> 301cb0ef41Sopenharmony_ci#ifdef HAVE_STDINT_H 311cb0ef41Sopenharmony_ci# include <stdint.h> 321cb0ef41Sopenharmony_ci#endif 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_cistatic size_t ares_dns_rr_remaining_len(const ares__buf_t *buf, size_t orig_len, 351cb0ef41Sopenharmony_ci size_t rdlength) 361cb0ef41Sopenharmony_ci{ 371cb0ef41Sopenharmony_ci size_t used_len = orig_len - ares__buf_len(buf); 381cb0ef41Sopenharmony_ci if (used_len >= rdlength) { 391cb0ef41Sopenharmony_ci return 0; 401cb0ef41Sopenharmony_ci } 411cb0ef41Sopenharmony_ci return rdlength - used_len; 421cb0ef41Sopenharmony_ci} 431cb0ef41Sopenharmony_ci 441cb0ef41Sopenharmony_cistatic ares_status_t ares_dns_parse_and_set_dns_name(ares__buf_t *buf, 451cb0ef41Sopenharmony_ci ares_bool_t is_hostname, 461cb0ef41Sopenharmony_ci ares_dns_rr_t *rr, 471cb0ef41Sopenharmony_ci ares_dns_rr_key_t key) 481cb0ef41Sopenharmony_ci{ 491cb0ef41Sopenharmony_ci ares_status_t status; 501cb0ef41Sopenharmony_ci char *name = NULL; 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_ci status = ares__dns_name_parse(buf, &name, is_hostname); 531cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 541cb0ef41Sopenharmony_ci return status; 551cb0ef41Sopenharmony_ci } 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_ci status = ares_dns_rr_set_str_own(rr, key, name); 581cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 591cb0ef41Sopenharmony_ci ares_free(name); 601cb0ef41Sopenharmony_ci return status; 611cb0ef41Sopenharmony_ci } 621cb0ef41Sopenharmony_ci return ARES_SUCCESS; 631cb0ef41Sopenharmony_ci} 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_cistatic ares_status_t ares_dns_parse_and_set_dns_str( 661cb0ef41Sopenharmony_ci ares__buf_t *buf, size_t max_len, ares_bool_t allow_multiple, 671cb0ef41Sopenharmony_ci ares_dns_rr_t *rr, ares_dns_rr_key_t key, ares_bool_t blank_allowed) 681cb0ef41Sopenharmony_ci{ 691cb0ef41Sopenharmony_ci ares_status_t status; 701cb0ef41Sopenharmony_ci char *str = NULL; 711cb0ef41Sopenharmony_ci 721cb0ef41Sopenharmony_ci status = ares__buf_parse_dns_str(buf, max_len, &str, allow_multiple); 731cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 741cb0ef41Sopenharmony_ci return status; 751cb0ef41Sopenharmony_ci } 761cb0ef41Sopenharmony_ci 771cb0ef41Sopenharmony_ci if (!blank_allowed && ares_strlen(str) == 0) { 781cb0ef41Sopenharmony_ci ares_free(str); 791cb0ef41Sopenharmony_ci return ARES_EBADRESP; 801cb0ef41Sopenharmony_ci } 811cb0ef41Sopenharmony_ci 821cb0ef41Sopenharmony_ci status = ares_dns_rr_set_str_own(rr, key, str); 831cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 841cb0ef41Sopenharmony_ci ares_free(str); 851cb0ef41Sopenharmony_ci return status; 861cb0ef41Sopenharmony_ci } 871cb0ef41Sopenharmony_ci return ARES_SUCCESS; 881cb0ef41Sopenharmony_ci} 891cb0ef41Sopenharmony_ci 901cb0ef41Sopenharmony_cistatic ares_status_t 911cb0ef41Sopenharmony_ci ares_dns_parse_and_set_dns_binstr(ares__buf_t *buf, size_t max_len, 921cb0ef41Sopenharmony_ci ares_bool_t allow_multiple, 931cb0ef41Sopenharmony_ci ares_dns_rr_t *rr, ares_dns_rr_key_t key) 941cb0ef41Sopenharmony_ci{ 951cb0ef41Sopenharmony_ci ares_status_t status; 961cb0ef41Sopenharmony_ci unsigned char *bin = NULL; 971cb0ef41Sopenharmony_ci size_t bin_len = 0; 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_ci status = 1001cb0ef41Sopenharmony_ci ares__buf_parse_dns_binstr(buf, max_len, &bin, &bin_len, allow_multiple); 1011cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 1021cb0ef41Sopenharmony_ci return status; 1031cb0ef41Sopenharmony_ci } 1041cb0ef41Sopenharmony_ci 1051cb0ef41Sopenharmony_ci status = ares_dns_rr_set_bin_own(rr, key, bin, bin_len); 1061cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 1071cb0ef41Sopenharmony_ci ares_free(bin); 1081cb0ef41Sopenharmony_ci return status; 1091cb0ef41Sopenharmony_ci } 1101cb0ef41Sopenharmony_ci return ARES_SUCCESS; 1111cb0ef41Sopenharmony_ci} 1121cb0ef41Sopenharmony_ci 1131cb0ef41Sopenharmony_cistatic ares_status_t ares_dns_parse_and_set_be32(ares__buf_t *buf, 1141cb0ef41Sopenharmony_ci ares_dns_rr_t *rr, 1151cb0ef41Sopenharmony_ci ares_dns_rr_key_t key) 1161cb0ef41Sopenharmony_ci{ 1171cb0ef41Sopenharmony_ci ares_status_t status; 1181cb0ef41Sopenharmony_ci unsigned int u32; 1191cb0ef41Sopenharmony_ci 1201cb0ef41Sopenharmony_ci status = ares__buf_fetch_be32(buf, &u32); 1211cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 1221cb0ef41Sopenharmony_ci return status; 1231cb0ef41Sopenharmony_ci } 1241cb0ef41Sopenharmony_ci 1251cb0ef41Sopenharmony_ci return ares_dns_rr_set_u32(rr, key, u32); 1261cb0ef41Sopenharmony_ci} 1271cb0ef41Sopenharmony_ci 1281cb0ef41Sopenharmony_cistatic ares_status_t ares_dns_parse_and_set_be16(ares__buf_t *buf, 1291cb0ef41Sopenharmony_ci ares_dns_rr_t *rr, 1301cb0ef41Sopenharmony_ci ares_dns_rr_key_t key) 1311cb0ef41Sopenharmony_ci{ 1321cb0ef41Sopenharmony_ci ares_status_t status; 1331cb0ef41Sopenharmony_ci unsigned short u16; 1341cb0ef41Sopenharmony_ci 1351cb0ef41Sopenharmony_ci status = ares__buf_fetch_be16(buf, &u16); 1361cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 1371cb0ef41Sopenharmony_ci return status; 1381cb0ef41Sopenharmony_ci } 1391cb0ef41Sopenharmony_ci 1401cb0ef41Sopenharmony_ci return ares_dns_rr_set_u16(rr, key, u16); 1411cb0ef41Sopenharmony_ci} 1421cb0ef41Sopenharmony_ci 1431cb0ef41Sopenharmony_cistatic ares_status_t ares_dns_parse_and_set_u8(ares__buf_t *buf, 1441cb0ef41Sopenharmony_ci ares_dns_rr_t *rr, 1451cb0ef41Sopenharmony_ci ares_dns_rr_key_t key) 1461cb0ef41Sopenharmony_ci{ 1471cb0ef41Sopenharmony_ci ares_status_t status; 1481cb0ef41Sopenharmony_ci unsigned char u8; 1491cb0ef41Sopenharmony_ci 1501cb0ef41Sopenharmony_ci status = ares__buf_fetch_bytes(buf, &u8, 1); 1511cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 1521cb0ef41Sopenharmony_ci return status; 1531cb0ef41Sopenharmony_ci } 1541cb0ef41Sopenharmony_ci 1551cb0ef41Sopenharmony_ci return ares_dns_rr_set_u8(rr, key, u8); 1561cb0ef41Sopenharmony_ci} 1571cb0ef41Sopenharmony_ci 1581cb0ef41Sopenharmony_cistatic ares_status_t ares_dns_parse_rr_a(ares__buf_t *buf, ares_dns_rr_t *rr, 1591cb0ef41Sopenharmony_ci size_t rdlength) 1601cb0ef41Sopenharmony_ci{ 1611cb0ef41Sopenharmony_ci struct in_addr addr; 1621cb0ef41Sopenharmony_ci ares_status_t status; 1631cb0ef41Sopenharmony_ci 1641cb0ef41Sopenharmony_ci (void)rdlength; /* Not needed */ 1651cb0ef41Sopenharmony_ci 1661cb0ef41Sopenharmony_ci status = ares__buf_fetch_bytes(buf, (unsigned char *)&addr, sizeof(addr)); 1671cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 1681cb0ef41Sopenharmony_ci return status; 1691cb0ef41Sopenharmony_ci } 1701cb0ef41Sopenharmony_ci 1711cb0ef41Sopenharmony_ci return ares_dns_rr_set_addr(rr, ARES_RR_A_ADDR, &addr); 1721cb0ef41Sopenharmony_ci} 1731cb0ef41Sopenharmony_ci 1741cb0ef41Sopenharmony_cistatic ares_status_t ares_dns_parse_rr_ns(ares__buf_t *buf, ares_dns_rr_t *rr, 1751cb0ef41Sopenharmony_ci size_t rdlength) 1761cb0ef41Sopenharmony_ci{ 1771cb0ef41Sopenharmony_ci (void)rdlength; /* Not needed */ 1781cb0ef41Sopenharmony_ci 1791cb0ef41Sopenharmony_ci return ares_dns_parse_and_set_dns_name(buf, ARES_FALSE, rr, 1801cb0ef41Sopenharmony_ci ARES_RR_NS_NSDNAME); 1811cb0ef41Sopenharmony_ci} 1821cb0ef41Sopenharmony_ci 1831cb0ef41Sopenharmony_cistatic ares_status_t ares_dns_parse_rr_cname(ares__buf_t *buf, 1841cb0ef41Sopenharmony_ci ares_dns_rr_t *rr, size_t rdlength) 1851cb0ef41Sopenharmony_ci{ 1861cb0ef41Sopenharmony_ci (void)rdlength; /* Not needed */ 1871cb0ef41Sopenharmony_ci 1881cb0ef41Sopenharmony_ci return ares_dns_parse_and_set_dns_name(buf, ARES_FALSE, rr, 1891cb0ef41Sopenharmony_ci ARES_RR_CNAME_CNAME); 1901cb0ef41Sopenharmony_ci} 1911cb0ef41Sopenharmony_ci 1921cb0ef41Sopenharmony_cistatic ares_status_t ares_dns_parse_rr_soa(ares__buf_t *buf, ares_dns_rr_t *rr, 1931cb0ef41Sopenharmony_ci size_t rdlength) 1941cb0ef41Sopenharmony_ci{ 1951cb0ef41Sopenharmony_ci ares_status_t status; 1961cb0ef41Sopenharmony_ci 1971cb0ef41Sopenharmony_ci (void)rdlength; /* Not needed */ 1981cb0ef41Sopenharmony_ci 1991cb0ef41Sopenharmony_ci /* MNAME */ 2001cb0ef41Sopenharmony_ci status = 2011cb0ef41Sopenharmony_ci ares_dns_parse_and_set_dns_name(buf, ARES_FALSE, rr, ARES_RR_SOA_MNAME); 2021cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 2031cb0ef41Sopenharmony_ci return status; 2041cb0ef41Sopenharmony_ci } 2051cb0ef41Sopenharmony_ci 2061cb0ef41Sopenharmony_ci /* RNAME */ 2071cb0ef41Sopenharmony_ci status = 2081cb0ef41Sopenharmony_ci ares_dns_parse_and_set_dns_name(buf, ARES_FALSE, rr, ARES_RR_SOA_RNAME); 2091cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 2101cb0ef41Sopenharmony_ci return status; 2111cb0ef41Sopenharmony_ci } 2121cb0ef41Sopenharmony_ci 2131cb0ef41Sopenharmony_ci /* SERIAL */ 2141cb0ef41Sopenharmony_ci status = ares_dns_parse_and_set_be32(buf, rr, ARES_RR_SOA_SERIAL); 2151cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 2161cb0ef41Sopenharmony_ci return status; 2171cb0ef41Sopenharmony_ci } 2181cb0ef41Sopenharmony_ci 2191cb0ef41Sopenharmony_ci /* REFRESH */ 2201cb0ef41Sopenharmony_ci status = ares_dns_parse_and_set_be32(buf, rr, ARES_RR_SOA_REFRESH); 2211cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 2221cb0ef41Sopenharmony_ci return status; 2231cb0ef41Sopenharmony_ci } 2241cb0ef41Sopenharmony_ci 2251cb0ef41Sopenharmony_ci /* RETRY */ 2261cb0ef41Sopenharmony_ci status = ares_dns_parse_and_set_be32(buf, rr, ARES_RR_SOA_RETRY); 2271cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 2281cb0ef41Sopenharmony_ci return status; 2291cb0ef41Sopenharmony_ci } 2301cb0ef41Sopenharmony_ci 2311cb0ef41Sopenharmony_ci /* EXPIRE */ 2321cb0ef41Sopenharmony_ci status = ares_dns_parse_and_set_be32(buf, rr, ARES_RR_SOA_EXPIRE); 2331cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 2341cb0ef41Sopenharmony_ci return status; 2351cb0ef41Sopenharmony_ci } 2361cb0ef41Sopenharmony_ci 2371cb0ef41Sopenharmony_ci /* MINIMUM */ 2381cb0ef41Sopenharmony_ci return ares_dns_parse_and_set_be32(buf, rr, ARES_RR_SOA_MINIMUM); 2391cb0ef41Sopenharmony_ci} 2401cb0ef41Sopenharmony_ci 2411cb0ef41Sopenharmony_cistatic ares_status_t ares_dns_parse_rr_ptr(ares__buf_t *buf, ares_dns_rr_t *rr, 2421cb0ef41Sopenharmony_ci size_t rdlength) 2431cb0ef41Sopenharmony_ci{ 2441cb0ef41Sopenharmony_ci (void)rdlength; /* Not needed */ 2451cb0ef41Sopenharmony_ci 2461cb0ef41Sopenharmony_ci return ares_dns_parse_and_set_dns_name(buf, ARES_FALSE, rr, 2471cb0ef41Sopenharmony_ci ARES_RR_PTR_DNAME); 2481cb0ef41Sopenharmony_ci} 2491cb0ef41Sopenharmony_ci 2501cb0ef41Sopenharmony_cistatic ares_status_t ares_dns_parse_rr_hinfo(ares__buf_t *buf, 2511cb0ef41Sopenharmony_ci ares_dns_rr_t *rr, size_t rdlength) 2521cb0ef41Sopenharmony_ci{ 2531cb0ef41Sopenharmony_ci ares_status_t status; 2541cb0ef41Sopenharmony_ci size_t orig_len = ares__buf_len(buf); 2551cb0ef41Sopenharmony_ci 2561cb0ef41Sopenharmony_ci (void)rdlength; /* Not needed */ 2571cb0ef41Sopenharmony_ci 2581cb0ef41Sopenharmony_ci /* CPU */ 2591cb0ef41Sopenharmony_ci status = ares_dns_parse_and_set_dns_str( 2601cb0ef41Sopenharmony_ci buf, ares_dns_rr_remaining_len(buf, orig_len, rdlength), ARES_FALSE, rr, 2611cb0ef41Sopenharmony_ci ARES_RR_HINFO_CPU, ARES_TRUE); 2621cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 2631cb0ef41Sopenharmony_ci return status; 2641cb0ef41Sopenharmony_ci } 2651cb0ef41Sopenharmony_ci 2661cb0ef41Sopenharmony_ci /* OS */ 2671cb0ef41Sopenharmony_ci status = ares_dns_parse_and_set_dns_str( 2681cb0ef41Sopenharmony_ci buf, ares_dns_rr_remaining_len(buf, orig_len, rdlength), ARES_FALSE, rr, 2691cb0ef41Sopenharmony_ci ARES_RR_HINFO_OS, ARES_TRUE); 2701cb0ef41Sopenharmony_ci 2711cb0ef41Sopenharmony_ci return status; 2721cb0ef41Sopenharmony_ci} 2731cb0ef41Sopenharmony_ci 2741cb0ef41Sopenharmony_cistatic ares_status_t ares_dns_parse_rr_mx(ares__buf_t *buf, ares_dns_rr_t *rr, 2751cb0ef41Sopenharmony_ci size_t rdlength) 2761cb0ef41Sopenharmony_ci{ 2771cb0ef41Sopenharmony_ci ares_status_t status; 2781cb0ef41Sopenharmony_ci 2791cb0ef41Sopenharmony_ci (void)rdlength; /* Not needed */ 2801cb0ef41Sopenharmony_ci 2811cb0ef41Sopenharmony_ci /* PREFERENCE */ 2821cb0ef41Sopenharmony_ci status = ares_dns_parse_and_set_be16(buf, rr, ARES_RR_MX_PREFERENCE); 2831cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 2841cb0ef41Sopenharmony_ci return status; 2851cb0ef41Sopenharmony_ci } 2861cb0ef41Sopenharmony_ci 2871cb0ef41Sopenharmony_ci /* EXCHANGE */ 2881cb0ef41Sopenharmony_ci return ares_dns_parse_and_set_dns_name(buf, ARES_FALSE, rr, 2891cb0ef41Sopenharmony_ci ARES_RR_MX_EXCHANGE); 2901cb0ef41Sopenharmony_ci} 2911cb0ef41Sopenharmony_ci 2921cb0ef41Sopenharmony_cistatic ares_status_t ares_dns_parse_rr_txt(ares__buf_t *buf, ares_dns_rr_t *rr, 2931cb0ef41Sopenharmony_ci size_t rdlength) 2941cb0ef41Sopenharmony_ci{ 2951cb0ef41Sopenharmony_ci return ares_dns_parse_and_set_dns_binstr(buf, rdlength, ARES_TRUE, rr, 2961cb0ef41Sopenharmony_ci ARES_RR_TXT_DATA); 2971cb0ef41Sopenharmony_ci} 2981cb0ef41Sopenharmony_ci 2991cb0ef41Sopenharmony_cistatic ares_status_t ares_dns_parse_rr_aaaa(ares__buf_t *buf, ares_dns_rr_t *rr, 3001cb0ef41Sopenharmony_ci size_t rdlength) 3011cb0ef41Sopenharmony_ci{ 3021cb0ef41Sopenharmony_ci struct ares_in6_addr addr; 3031cb0ef41Sopenharmony_ci ares_status_t status; 3041cb0ef41Sopenharmony_ci 3051cb0ef41Sopenharmony_ci (void)rdlength; /* Not needed */ 3061cb0ef41Sopenharmony_ci 3071cb0ef41Sopenharmony_ci status = ares__buf_fetch_bytes(buf, (unsigned char *)&addr, sizeof(addr)); 3081cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 3091cb0ef41Sopenharmony_ci return status; 3101cb0ef41Sopenharmony_ci } 3111cb0ef41Sopenharmony_ci 3121cb0ef41Sopenharmony_ci return ares_dns_rr_set_addr6(rr, ARES_RR_AAAA_ADDR, &addr); 3131cb0ef41Sopenharmony_ci} 3141cb0ef41Sopenharmony_ci 3151cb0ef41Sopenharmony_cistatic ares_status_t ares_dns_parse_rr_srv(ares__buf_t *buf, ares_dns_rr_t *rr, 3161cb0ef41Sopenharmony_ci size_t rdlength) 3171cb0ef41Sopenharmony_ci{ 3181cb0ef41Sopenharmony_ci ares_status_t status; 3191cb0ef41Sopenharmony_ci 3201cb0ef41Sopenharmony_ci (void)rdlength; /* Not needed */ 3211cb0ef41Sopenharmony_ci 3221cb0ef41Sopenharmony_ci /* PRIORITY */ 3231cb0ef41Sopenharmony_ci status = ares_dns_parse_and_set_be16(buf, rr, ARES_RR_SRV_PRIORITY); 3241cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 3251cb0ef41Sopenharmony_ci return status; 3261cb0ef41Sopenharmony_ci } 3271cb0ef41Sopenharmony_ci 3281cb0ef41Sopenharmony_ci /* WEIGHT */ 3291cb0ef41Sopenharmony_ci status = ares_dns_parse_and_set_be16(buf, rr, ARES_RR_SRV_WEIGHT); 3301cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 3311cb0ef41Sopenharmony_ci return status; 3321cb0ef41Sopenharmony_ci } 3331cb0ef41Sopenharmony_ci 3341cb0ef41Sopenharmony_ci /* PORT */ 3351cb0ef41Sopenharmony_ci status = ares_dns_parse_and_set_be16(buf, rr, ARES_RR_SRV_PORT); 3361cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 3371cb0ef41Sopenharmony_ci return status; 3381cb0ef41Sopenharmony_ci } 3391cb0ef41Sopenharmony_ci 3401cb0ef41Sopenharmony_ci /* TARGET */ 3411cb0ef41Sopenharmony_ci return ares_dns_parse_and_set_dns_name(buf, ARES_FALSE, rr, 3421cb0ef41Sopenharmony_ci ARES_RR_SRV_TARGET); 3431cb0ef41Sopenharmony_ci} 3441cb0ef41Sopenharmony_ci 3451cb0ef41Sopenharmony_cistatic ares_status_t ares_dns_parse_rr_naptr(ares__buf_t *buf, 3461cb0ef41Sopenharmony_ci ares_dns_rr_t *rr, size_t rdlength) 3471cb0ef41Sopenharmony_ci{ 3481cb0ef41Sopenharmony_ci ares_status_t status; 3491cb0ef41Sopenharmony_ci size_t orig_len = ares__buf_len(buf); 3501cb0ef41Sopenharmony_ci 3511cb0ef41Sopenharmony_ci /* ORDER */ 3521cb0ef41Sopenharmony_ci status = ares_dns_parse_and_set_be16(buf, rr, ARES_RR_NAPTR_ORDER); 3531cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 3541cb0ef41Sopenharmony_ci return status; 3551cb0ef41Sopenharmony_ci } 3561cb0ef41Sopenharmony_ci 3571cb0ef41Sopenharmony_ci /* PREFERENCE */ 3581cb0ef41Sopenharmony_ci status = ares_dns_parse_and_set_be16(buf, rr, ARES_RR_NAPTR_PREFERENCE); 3591cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 3601cb0ef41Sopenharmony_ci return status; 3611cb0ef41Sopenharmony_ci } 3621cb0ef41Sopenharmony_ci 3631cb0ef41Sopenharmony_ci /* FLAGS */ 3641cb0ef41Sopenharmony_ci status = ares_dns_parse_and_set_dns_str( 3651cb0ef41Sopenharmony_ci buf, ares_dns_rr_remaining_len(buf, orig_len, rdlength), ARES_FALSE, rr, 3661cb0ef41Sopenharmony_ci ARES_RR_NAPTR_FLAGS, ARES_TRUE); 3671cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 3681cb0ef41Sopenharmony_ci return status; 3691cb0ef41Sopenharmony_ci } 3701cb0ef41Sopenharmony_ci 3711cb0ef41Sopenharmony_ci /* SERVICES */ 3721cb0ef41Sopenharmony_ci status = ares_dns_parse_and_set_dns_str( 3731cb0ef41Sopenharmony_ci buf, ares_dns_rr_remaining_len(buf, orig_len, rdlength), ARES_FALSE, rr, 3741cb0ef41Sopenharmony_ci ARES_RR_NAPTR_SERVICES, ARES_TRUE); 3751cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 3761cb0ef41Sopenharmony_ci return status; 3771cb0ef41Sopenharmony_ci } 3781cb0ef41Sopenharmony_ci 3791cb0ef41Sopenharmony_ci /* REGEXP */ 3801cb0ef41Sopenharmony_ci status = ares_dns_parse_and_set_dns_str( 3811cb0ef41Sopenharmony_ci buf, ares_dns_rr_remaining_len(buf, orig_len, rdlength), ARES_FALSE, rr, 3821cb0ef41Sopenharmony_ci ARES_RR_NAPTR_REGEXP, ARES_TRUE); 3831cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 3841cb0ef41Sopenharmony_ci return status; 3851cb0ef41Sopenharmony_ci } 3861cb0ef41Sopenharmony_ci 3871cb0ef41Sopenharmony_ci /* REPLACEMENT */ 3881cb0ef41Sopenharmony_ci return ares_dns_parse_and_set_dns_name(buf, ARES_FALSE, rr, 3891cb0ef41Sopenharmony_ci ARES_RR_NAPTR_REPLACEMENT); 3901cb0ef41Sopenharmony_ci} 3911cb0ef41Sopenharmony_ci 3921cb0ef41Sopenharmony_cistatic ares_status_t ares_dns_parse_rr_opt(ares__buf_t *buf, ares_dns_rr_t *rr, 3931cb0ef41Sopenharmony_ci size_t rdlength, 3941cb0ef41Sopenharmony_ci unsigned short raw_class, 3951cb0ef41Sopenharmony_ci unsigned int raw_ttl) 3961cb0ef41Sopenharmony_ci{ 3971cb0ef41Sopenharmony_ci ares_status_t status; 3981cb0ef41Sopenharmony_ci size_t orig_len = ares__buf_len(buf); 3991cb0ef41Sopenharmony_ci unsigned short rcode_high; 4001cb0ef41Sopenharmony_ci 4011cb0ef41Sopenharmony_ci status = ares_dns_rr_set_u16(rr, ARES_RR_OPT_UDP_SIZE, raw_class); 4021cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 4031cb0ef41Sopenharmony_ci return status; 4041cb0ef41Sopenharmony_ci } 4051cb0ef41Sopenharmony_ci 4061cb0ef41Sopenharmony_ci /* First 8 bits of TTL are an extended RCODE, and they go in the higher order 4071cb0ef41Sopenharmony_ci * after the original 4-bit rcode */ 4081cb0ef41Sopenharmony_ci rcode_high = (unsigned short)((raw_ttl >> 20) & 0x0FF0); 4091cb0ef41Sopenharmony_ci rr->parent->raw_rcode |= rcode_high; 4101cb0ef41Sopenharmony_ci 4111cb0ef41Sopenharmony_ci status = ares_dns_rr_set_u8(rr, ARES_RR_OPT_VERSION, 4121cb0ef41Sopenharmony_ci (unsigned char)(raw_ttl >> 16) & 0xFF); 4131cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 4141cb0ef41Sopenharmony_ci return status; 4151cb0ef41Sopenharmony_ci } 4161cb0ef41Sopenharmony_ci 4171cb0ef41Sopenharmony_ci status = ares_dns_rr_set_u16(rr, ARES_RR_OPT_FLAGS, 4181cb0ef41Sopenharmony_ci (unsigned short)(raw_ttl & 0xFFFF)); 4191cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 4201cb0ef41Sopenharmony_ci return status; 4211cb0ef41Sopenharmony_ci } 4221cb0ef41Sopenharmony_ci 4231cb0ef41Sopenharmony_ci /* Parse options */ 4241cb0ef41Sopenharmony_ci while (ares_dns_rr_remaining_len(buf, orig_len, rdlength)) { 4251cb0ef41Sopenharmony_ci unsigned short opt = 0; 4261cb0ef41Sopenharmony_ci unsigned short len = 0; 4271cb0ef41Sopenharmony_ci unsigned char *val = NULL; 4281cb0ef41Sopenharmony_ci 4291cb0ef41Sopenharmony_ci /* Fetch be16 option */ 4301cb0ef41Sopenharmony_ci status = ares__buf_fetch_be16(buf, &opt); 4311cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 4321cb0ef41Sopenharmony_ci return status; 4331cb0ef41Sopenharmony_ci } 4341cb0ef41Sopenharmony_ci 4351cb0ef41Sopenharmony_ci /* Fetch be16 length */ 4361cb0ef41Sopenharmony_ci status = ares__buf_fetch_be16(buf, &len); 4371cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 4381cb0ef41Sopenharmony_ci return status; 4391cb0ef41Sopenharmony_ci } 4401cb0ef41Sopenharmony_ci 4411cb0ef41Sopenharmony_ci if (len) { 4421cb0ef41Sopenharmony_ci status = ares__buf_fetch_bytes_dup(buf, len, ARES_TRUE, &val); 4431cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 4441cb0ef41Sopenharmony_ci return status; 4451cb0ef41Sopenharmony_ci } 4461cb0ef41Sopenharmony_ci } 4471cb0ef41Sopenharmony_ci 4481cb0ef41Sopenharmony_ci status = ares_dns_rr_set_opt_own(rr, ARES_RR_OPT_OPTIONS, opt, val, len); 4491cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 4501cb0ef41Sopenharmony_ci return status; 4511cb0ef41Sopenharmony_ci } 4521cb0ef41Sopenharmony_ci } 4531cb0ef41Sopenharmony_ci 4541cb0ef41Sopenharmony_ci return ARES_SUCCESS; 4551cb0ef41Sopenharmony_ci} 4561cb0ef41Sopenharmony_ci 4571cb0ef41Sopenharmony_cistatic ares_status_t ares_dns_parse_rr_tlsa(ares__buf_t *buf, ares_dns_rr_t *rr, 4581cb0ef41Sopenharmony_ci size_t rdlength) 4591cb0ef41Sopenharmony_ci{ 4601cb0ef41Sopenharmony_ci ares_status_t status; 4611cb0ef41Sopenharmony_ci size_t orig_len = ares__buf_len(buf); 4621cb0ef41Sopenharmony_ci size_t len; 4631cb0ef41Sopenharmony_ci unsigned char *data; 4641cb0ef41Sopenharmony_ci 4651cb0ef41Sopenharmony_ci status = ares_dns_parse_and_set_u8(buf, rr, ARES_RR_TLSA_CERT_USAGE); 4661cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 4671cb0ef41Sopenharmony_ci return status; 4681cb0ef41Sopenharmony_ci } 4691cb0ef41Sopenharmony_ci 4701cb0ef41Sopenharmony_ci status = ares_dns_parse_and_set_u8(buf, rr, ARES_RR_TLSA_SELECTOR); 4711cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 4721cb0ef41Sopenharmony_ci return status; 4731cb0ef41Sopenharmony_ci } 4741cb0ef41Sopenharmony_ci 4751cb0ef41Sopenharmony_ci status = ares_dns_parse_and_set_u8(buf, rr, ARES_RR_TLSA_MATCH); 4761cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 4771cb0ef41Sopenharmony_ci return status; 4781cb0ef41Sopenharmony_ci } 4791cb0ef41Sopenharmony_ci 4801cb0ef41Sopenharmony_ci len = ares_dns_rr_remaining_len(buf, orig_len, rdlength); 4811cb0ef41Sopenharmony_ci if (len == 0) { 4821cb0ef41Sopenharmony_ci return ARES_EBADRESP; 4831cb0ef41Sopenharmony_ci } 4841cb0ef41Sopenharmony_ci 4851cb0ef41Sopenharmony_ci status = ares__buf_fetch_bytes_dup(buf, len, ARES_FALSE, &data); 4861cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 4871cb0ef41Sopenharmony_ci return status; 4881cb0ef41Sopenharmony_ci } 4891cb0ef41Sopenharmony_ci 4901cb0ef41Sopenharmony_ci status = ares_dns_rr_set_bin_own(rr, ARES_RR_TLSA_DATA, data, len); 4911cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 4921cb0ef41Sopenharmony_ci ares_free(data); 4931cb0ef41Sopenharmony_ci return status; 4941cb0ef41Sopenharmony_ci } 4951cb0ef41Sopenharmony_ci 4961cb0ef41Sopenharmony_ci return ARES_SUCCESS; 4971cb0ef41Sopenharmony_ci} 4981cb0ef41Sopenharmony_ci 4991cb0ef41Sopenharmony_cistatic ares_status_t ares_dns_parse_rr_svcb(ares__buf_t *buf, ares_dns_rr_t *rr, 5001cb0ef41Sopenharmony_ci size_t rdlength) 5011cb0ef41Sopenharmony_ci{ 5021cb0ef41Sopenharmony_ci ares_status_t status; 5031cb0ef41Sopenharmony_ci size_t orig_len = ares__buf_len(buf); 5041cb0ef41Sopenharmony_ci 5051cb0ef41Sopenharmony_ci status = ares_dns_parse_and_set_be16(buf, rr, ARES_RR_SVCB_PRIORITY); 5061cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 5071cb0ef41Sopenharmony_ci return status; 5081cb0ef41Sopenharmony_ci } 5091cb0ef41Sopenharmony_ci 5101cb0ef41Sopenharmony_ci status = 5111cb0ef41Sopenharmony_ci ares_dns_parse_and_set_dns_name(buf, ARES_FALSE, rr, ARES_RR_SVCB_TARGET); 5121cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 5131cb0ef41Sopenharmony_ci return status; 5141cb0ef41Sopenharmony_ci } 5151cb0ef41Sopenharmony_ci 5161cb0ef41Sopenharmony_ci /* Parse params */ 5171cb0ef41Sopenharmony_ci while (ares_dns_rr_remaining_len(buf, orig_len, rdlength)) { 5181cb0ef41Sopenharmony_ci unsigned short opt = 0; 5191cb0ef41Sopenharmony_ci unsigned short len = 0; 5201cb0ef41Sopenharmony_ci unsigned char *val = NULL; 5211cb0ef41Sopenharmony_ci 5221cb0ef41Sopenharmony_ci /* Fetch be16 option */ 5231cb0ef41Sopenharmony_ci status = ares__buf_fetch_be16(buf, &opt); 5241cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 5251cb0ef41Sopenharmony_ci return status; 5261cb0ef41Sopenharmony_ci } 5271cb0ef41Sopenharmony_ci 5281cb0ef41Sopenharmony_ci /* Fetch be16 length */ 5291cb0ef41Sopenharmony_ci status = ares__buf_fetch_be16(buf, &len); 5301cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 5311cb0ef41Sopenharmony_ci return status; 5321cb0ef41Sopenharmony_ci } 5331cb0ef41Sopenharmony_ci 5341cb0ef41Sopenharmony_ci if (len) { 5351cb0ef41Sopenharmony_ci status = ares__buf_fetch_bytes_dup(buf, len, ARES_TRUE, &val); 5361cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 5371cb0ef41Sopenharmony_ci return status; 5381cb0ef41Sopenharmony_ci } 5391cb0ef41Sopenharmony_ci } 5401cb0ef41Sopenharmony_ci 5411cb0ef41Sopenharmony_ci status = ares_dns_rr_set_opt_own(rr, ARES_RR_SVCB_PARAMS, opt, val, len); 5421cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 5431cb0ef41Sopenharmony_ci return status; 5441cb0ef41Sopenharmony_ci } 5451cb0ef41Sopenharmony_ci } 5461cb0ef41Sopenharmony_ci 5471cb0ef41Sopenharmony_ci return ARES_SUCCESS; 5481cb0ef41Sopenharmony_ci} 5491cb0ef41Sopenharmony_ci 5501cb0ef41Sopenharmony_cistatic ares_status_t ares_dns_parse_rr_https(ares__buf_t *buf, 5511cb0ef41Sopenharmony_ci ares_dns_rr_t *rr, size_t rdlength) 5521cb0ef41Sopenharmony_ci{ 5531cb0ef41Sopenharmony_ci ares_status_t status; 5541cb0ef41Sopenharmony_ci size_t orig_len = ares__buf_len(buf); 5551cb0ef41Sopenharmony_ci 5561cb0ef41Sopenharmony_ci status = ares_dns_parse_and_set_be16(buf, rr, ARES_RR_HTTPS_PRIORITY); 5571cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 5581cb0ef41Sopenharmony_ci return status; 5591cb0ef41Sopenharmony_ci } 5601cb0ef41Sopenharmony_ci 5611cb0ef41Sopenharmony_ci status = 5621cb0ef41Sopenharmony_ci ares_dns_parse_and_set_dns_name(buf, ARES_FALSE, rr, ARES_RR_HTTPS_TARGET); 5631cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 5641cb0ef41Sopenharmony_ci return status; 5651cb0ef41Sopenharmony_ci } 5661cb0ef41Sopenharmony_ci 5671cb0ef41Sopenharmony_ci /* Parse params */ 5681cb0ef41Sopenharmony_ci while (ares_dns_rr_remaining_len(buf, orig_len, rdlength)) { 5691cb0ef41Sopenharmony_ci unsigned short opt = 0; 5701cb0ef41Sopenharmony_ci unsigned short len = 0; 5711cb0ef41Sopenharmony_ci unsigned char *val = NULL; 5721cb0ef41Sopenharmony_ci 5731cb0ef41Sopenharmony_ci /* Fetch be16 option */ 5741cb0ef41Sopenharmony_ci status = ares__buf_fetch_be16(buf, &opt); 5751cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 5761cb0ef41Sopenharmony_ci return status; 5771cb0ef41Sopenharmony_ci } 5781cb0ef41Sopenharmony_ci 5791cb0ef41Sopenharmony_ci /* Fetch be16 length */ 5801cb0ef41Sopenharmony_ci status = ares__buf_fetch_be16(buf, &len); 5811cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 5821cb0ef41Sopenharmony_ci return status; 5831cb0ef41Sopenharmony_ci } 5841cb0ef41Sopenharmony_ci 5851cb0ef41Sopenharmony_ci if (len) { 5861cb0ef41Sopenharmony_ci status = ares__buf_fetch_bytes_dup(buf, len, ARES_TRUE, &val); 5871cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 5881cb0ef41Sopenharmony_ci return status; 5891cb0ef41Sopenharmony_ci } 5901cb0ef41Sopenharmony_ci } 5911cb0ef41Sopenharmony_ci 5921cb0ef41Sopenharmony_ci status = ares_dns_rr_set_opt_own(rr, ARES_RR_HTTPS_PARAMS, opt, val, len); 5931cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 5941cb0ef41Sopenharmony_ci return status; 5951cb0ef41Sopenharmony_ci } 5961cb0ef41Sopenharmony_ci } 5971cb0ef41Sopenharmony_ci 5981cb0ef41Sopenharmony_ci return ARES_SUCCESS; 5991cb0ef41Sopenharmony_ci} 6001cb0ef41Sopenharmony_ci 6011cb0ef41Sopenharmony_cistatic ares_status_t ares_dns_parse_rr_uri(ares__buf_t *buf, ares_dns_rr_t *rr, 6021cb0ef41Sopenharmony_ci size_t rdlength) 6031cb0ef41Sopenharmony_ci{ 6041cb0ef41Sopenharmony_ci char *name = NULL; 6051cb0ef41Sopenharmony_ci ares_status_t status; 6061cb0ef41Sopenharmony_ci size_t orig_len = ares__buf_len(buf); 6071cb0ef41Sopenharmony_ci size_t remaining_len; 6081cb0ef41Sopenharmony_ci 6091cb0ef41Sopenharmony_ci /* PRIORITY */ 6101cb0ef41Sopenharmony_ci status = ares_dns_parse_and_set_be16(buf, rr, ARES_RR_URI_PRIORITY); 6111cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 6121cb0ef41Sopenharmony_ci return status; 6131cb0ef41Sopenharmony_ci } 6141cb0ef41Sopenharmony_ci 6151cb0ef41Sopenharmony_ci /* WEIGHT */ 6161cb0ef41Sopenharmony_ci status = ares_dns_parse_and_set_be16(buf, rr, ARES_RR_URI_WEIGHT); 6171cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 6181cb0ef41Sopenharmony_ci return status; 6191cb0ef41Sopenharmony_ci } 6201cb0ef41Sopenharmony_ci 6211cb0ef41Sopenharmony_ci /* TARGET -- not in string format, rest of buffer, required to be 6221cb0ef41Sopenharmony_ci * non-zero length */ 6231cb0ef41Sopenharmony_ci remaining_len = ares_dns_rr_remaining_len(buf, orig_len, rdlength); 6241cb0ef41Sopenharmony_ci if (remaining_len == 0) { 6251cb0ef41Sopenharmony_ci status = ARES_EBADRESP; 6261cb0ef41Sopenharmony_ci return status; 6271cb0ef41Sopenharmony_ci } 6281cb0ef41Sopenharmony_ci 6291cb0ef41Sopenharmony_ci /* NOTE: Not in DNS string format */ 6301cb0ef41Sopenharmony_ci status = ares__buf_fetch_str_dup(buf, remaining_len, &name); 6311cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 6321cb0ef41Sopenharmony_ci return status; 6331cb0ef41Sopenharmony_ci } 6341cb0ef41Sopenharmony_ci 6351cb0ef41Sopenharmony_ci status = ares_dns_rr_set_str_own(rr, ARES_RR_URI_TARGET, name); 6361cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 6371cb0ef41Sopenharmony_ci ares_free(name); 6381cb0ef41Sopenharmony_ci return status; 6391cb0ef41Sopenharmony_ci } 6401cb0ef41Sopenharmony_ci name = NULL; 6411cb0ef41Sopenharmony_ci 6421cb0ef41Sopenharmony_ci return ARES_SUCCESS; 6431cb0ef41Sopenharmony_ci} 6441cb0ef41Sopenharmony_ci 6451cb0ef41Sopenharmony_cistatic ares_status_t ares_dns_parse_rr_caa(ares__buf_t *buf, ares_dns_rr_t *rr, 6461cb0ef41Sopenharmony_ci size_t rdlength) 6471cb0ef41Sopenharmony_ci{ 6481cb0ef41Sopenharmony_ci unsigned char *data = NULL; 6491cb0ef41Sopenharmony_ci size_t data_len = 0; 6501cb0ef41Sopenharmony_ci ares_status_t status; 6511cb0ef41Sopenharmony_ci size_t orig_len = ares__buf_len(buf); 6521cb0ef41Sopenharmony_ci 6531cb0ef41Sopenharmony_ci /* CRITICAL */ 6541cb0ef41Sopenharmony_ci status = ares_dns_parse_and_set_u8(buf, rr, ARES_RR_CAA_CRITICAL); 6551cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 6561cb0ef41Sopenharmony_ci return status; 6571cb0ef41Sopenharmony_ci } 6581cb0ef41Sopenharmony_ci 6591cb0ef41Sopenharmony_ci /* Tag */ 6601cb0ef41Sopenharmony_ci status = ares_dns_parse_and_set_dns_str( 6611cb0ef41Sopenharmony_ci buf, ares_dns_rr_remaining_len(buf, orig_len, rdlength), ARES_FALSE, rr, 6621cb0ef41Sopenharmony_ci ARES_RR_CAA_TAG, ARES_FALSE); 6631cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 6641cb0ef41Sopenharmony_ci return status; 6651cb0ef41Sopenharmony_ci } 6661cb0ef41Sopenharmony_ci 6671cb0ef41Sopenharmony_ci /* Value - binary! (remaining buffer */ 6681cb0ef41Sopenharmony_ci data_len = ares_dns_rr_remaining_len(buf, orig_len, rdlength); 6691cb0ef41Sopenharmony_ci if (data_len == 0) { 6701cb0ef41Sopenharmony_ci status = ARES_EBADRESP; 6711cb0ef41Sopenharmony_ci return status; 6721cb0ef41Sopenharmony_ci } 6731cb0ef41Sopenharmony_ci status = ares__buf_fetch_bytes_dup(buf, data_len, ARES_TRUE, &data); 6741cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 6751cb0ef41Sopenharmony_ci return status; 6761cb0ef41Sopenharmony_ci } 6771cb0ef41Sopenharmony_ci 6781cb0ef41Sopenharmony_ci status = ares_dns_rr_set_bin_own(rr, ARES_RR_CAA_VALUE, data, data_len); 6791cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 6801cb0ef41Sopenharmony_ci ares_free(data); 6811cb0ef41Sopenharmony_ci return status; 6821cb0ef41Sopenharmony_ci } 6831cb0ef41Sopenharmony_ci data = NULL; 6841cb0ef41Sopenharmony_ci 6851cb0ef41Sopenharmony_ci return ARES_SUCCESS; 6861cb0ef41Sopenharmony_ci} 6871cb0ef41Sopenharmony_ci 6881cb0ef41Sopenharmony_cistatic ares_status_t ares_dns_parse_rr_raw_rr(ares__buf_t *buf, 6891cb0ef41Sopenharmony_ci ares_dns_rr_t *rr, 6901cb0ef41Sopenharmony_ci size_t rdlength, 6911cb0ef41Sopenharmony_ci unsigned short raw_type) 6921cb0ef41Sopenharmony_ci{ 6931cb0ef41Sopenharmony_ci ares_status_t status; 6941cb0ef41Sopenharmony_ci unsigned char *bytes = NULL; 6951cb0ef41Sopenharmony_ci 6961cb0ef41Sopenharmony_ci if (rdlength == 0) { 6971cb0ef41Sopenharmony_ci return ARES_SUCCESS; 6981cb0ef41Sopenharmony_ci } 6991cb0ef41Sopenharmony_ci 7001cb0ef41Sopenharmony_ci status = ares__buf_fetch_bytes_dup(buf, rdlength, ARES_FALSE, &bytes); 7011cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 7021cb0ef41Sopenharmony_ci return status; 7031cb0ef41Sopenharmony_ci } 7041cb0ef41Sopenharmony_ci 7051cb0ef41Sopenharmony_ci /* Can't fail */ 7061cb0ef41Sopenharmony_ci status = ares_dns_rr_set_u16(rr, ARES_RR_RAW_RR_TYPE, raw_type); 7071cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 7081cb0ef41Sopenharmony_ci ares_free(bytes); 7091cb0ef41Sopenharmony_ci return status; 7101cb0ef41Sopenharmony_ci } 7111cb0ef41Sopenharmony_ci 7121cb0ef41Sopenharmony_ci status = ares_dns_rr_set_bin_own(rr, ARES_RR_RAW_RR_DATA, bytes, rdlength); 7131cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 7141cb0ef41Sopenharmony_ci ares_free(bytes); 7151cb0ef41Sopenharmony_ci return status; 7161cb0ef41Sopenharmony_ci } 7171cb0ef41Sopenharmony_ci 7181cb0ef41Sopenharmony_ci return ARES_SUCCESS; 7191cb0ef41Sopenharmony_ci} 7201cb0ef41Sopenharmony_ci 7211cb0ef41Sopenharmony_cistatic ares_status_t ares_dns_parse_header(ares__buf_t *buf, unsigned int flags, 7221cb0ef41Sopenharmony_ci ares_dns_record_t **dnsrec, 7231cb0ef41Sopenharmony_ci unsigned short *qdcount, 7241cb0ef41Sopenharmony_ci unsigned short *ancount, 7251cb0ef41Sopenharmony_ci unsigned short *nscount, 7261cb0ef41Sopenharmony_ci unsigned short *arcount) 7271cb0ef41Sopenharmony_ci{ 7281cb0ef41Sopenharmony_ci ares_status_t status = ARES_EBADRESP; 7291cb0ef41Sopenharmony_ci unsigned short u16; 7301cb0ef41Sopenharmony_ci unsigned short id; 7311cb0ef41Sopenharmony_ci unsigned short dns_flags = 0; 7321cb0ef41Sopenharmony_ci ares_dns_opcode_t opcode; 7331cb0ef41Sopenharmony_ci unsigned short rcode; 7341cb0ef41Sopenharmony_ci 7351cb0ef41Sopenharmony_ci (void)flags; /* currently unused */ 7361cb0ef41Sopenharmony_ci 7371cb0ef41Sopenharmony_ci if (buf == NULL || dnsrec == NULL || qdcount == NULL || ancount == NULL || 7381cb0ef41Sopenharmony_ci nscount == NULL || arcount == NULL) { 7391cb0ef41Sopenharmony_ci return ARES_EFORMERR; 7401cb0ef41Sopenharmony_ci } 7411cb0ef41Sopenharmony_ci 7421cb0ef41Sopenharmony_ci *dnsrec = NULL; 7431cb0ef41Sopenharmony_ci 7441cb0ef41Sopenharmony_ci /* 7451cb0ef41Sopenharmony_ci * RFC 1035 4.1.1. Header section format. 7461cb0ef41Sopenharmony_ci * and Updated by RFC 2065 to add AD and CD bits. 7471cb0ef41Sopenharmony_ci * 1 1 1 1 1 1 7481cb0ef41Sopenharmony_ci * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 7491cb0ef41Sopenharmony_ci * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 7501cb0ef41Sopenharmony_ci * | ID | 7511cb0ef41Sopenharmony_ci * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 7521cb0ef41Sopenharmony_ci * |QR| Opcode |AA|TC|RD|RA| Z|AD|CD| RCODE | 7531cb0ef41Sopenharmony_ci * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 7541cb0ef41Sopenharmony_ci * | QDCOUNT | 7551cb0ef41Sopenharmony_ci * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 7561cb0ef41Sopenharmony_ci * | ANCOUNT | 7571cb0ef41Sopenharmony_ci * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 7581cb0ef41Sopenharmony_ci * | NSCOUNT | 7591cb0ef41Sopenharmony_ci * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 7601cb0ef41Sopenharmony_ci * | ARCOUNT | 7611cb0ef41Sopenharmony_ci * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 7621cb0ef41Sopenharmony_ci */ 7631cb0ef41Sopenharmony_ci 7641cb0ef41Sopenharmony_ci /* ID */ 7651cb0ef41Sopenharmony_ci status = ares__buf_fetch_be16(buf, &id); 7661cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 7671cb0ef41Sopenharmony_ci goto fail; 7681cb0ef41Sopenharmony_ci } 7691cb0ef41Sopenharmony_ci 7701cb0ef41Sopenharmony_ci /* Flags */ 7711cb0ef41Sopenharmony_ci status = ares__buf_fetch_be16(buf, &u16); 7721cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 7731cb0ef41Sopenharmony_ci goto fail; 7741cb0ef41Sopenharmony_ci } 7751cb0ef41Sopenharmony_ci 7761cb0ef41Sopenharmony_ci /* QR */ 7771cb0ef41Sopenharmony_ci if (u16 & 0x8000) { 7781cb0ef41Sopenharmony_ci dns_flags |= ARES_FLAG_QR; 7791cb0ef41Sopenharmony_ci } 7801cb0ef41Sopenharmony_ci 7811cb0ef41Sopenharmony_ci /* OPCODE */ 7821cb0ef41Sopenharmony_ci opcode = (u16 >> 11) & 0xf; 7831cb0ef41Sopenharmony_ci 7841cb0ef41Sopenharmony_ci /* AA */ 7851cb0ef41Sopenharmony_ci if (u16 & 0x400) { 7861cb0ef41Sopenharmony_ci dns_flags |= ARES_FLAG_AA; 7871cb0ef41Sopenharmony_ci } 7881cb0ef41Sopenharmony_ci 7891cb0ef41Sopenharmony_ci /* TC */ 7901cb0ef41Sopenharmony_ci if (u16 & 0x200) { 7911cb0ef41Sopenharmony_ci dns_flags |= ARES_FLAG_TC; 7921cb0ef41Sopenharmony_ci } 7931cb0ef41Sopenharmony_ci 7941cb0ef41Sopenharmony_ci /* RD */ 7951cb0ef41Sopenharmony_ci if (u16 & 0x100) { 7961cb0ef41Sopenharmony_ci dns_flags |= ARES_FLAG_RD; 7971cb0ef41Sopenharmony_ci } 7981cb0ef41Sopenharmony_ci 7991cb0ef41Sopenharmony_ci /* RA */ 8001cb0ef41Sopenharmony_ci if (u16 & 0x80) { 8011cb0ef41Sopenharmony_ci dns_flags |= ARES_FLAG_RA; 8021cb0ef41Sopenharmony_ci } 8031cb0ef41Sopenharmony_ci 8041cb0ef41Sopenharmony_ci /* Z -- unused */ 8051cb0ef41Sopenharmony_ci 8061cb0ef41Sopenharmony_ci /* AD */ 8071cb0ef41Sopenharmony_ci if (u16 & 0x20) { 8081cb0ef41Sopenharmony_ci dns_flags |= ARES_FLAG_AD; 8091cb0ef41Sopenharmony_ci } 8101cb0ef41Sopenharmony_ci 8111cb0ef41Sopenharmony_ci /* CD */ 8121cb0ef41Sopenharmony_ci if (u16 & 0x10) { 8131cb0ef41Sopenharmony_ci dns_flags |= ARES_FLAG_CD; 8141cb0ef41Sopenharmony_ci } 8151cb0ef41Sopenharmony_ci 8161cb0ef41Sopenharmony_ci /* RCODE */ 8171cb0ef41Sopenharmony_ci rcode = u16 & 0xf; 8181cb0ef41Sopenharmony_ci 8191cb0ef41Sopenharmony_ci /* QDCOUNT */ 8201cb0ef41Sopenharmony_ci status = ares__buf_fetch_be16(buf, qdcount); 8211cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 8221cb0ef41Sopenharmony_ci goto fail; 8231cb0ef41Sopenharmony_ci } 8241cb0ef41Sopenharmony_ci 8251cb0ef41Sopenharmony_ci /* ANCOUNT */ 8261cb0ef41Sopenharmony_ci status = ares__buf_fetch_be16(buf, ancount); 8271cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 8281cb0ef41Sopenharmony_ci goto fail; 8291cb0ef41Sopenharmony_ci } 8301cb0ef41Sopenharmony_ci 8311cb0ef41Sopenharmony_ci /* NSCOUNT */ 8321cb0ef41Sopenharmony_ci status = ares__buf_fetch_be16(buf, nscount); 8331cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 8341cb0ef41Sopenharmony_ci goto fail; 8351cb0ef41Sopenharmony_ci } 8361cb0ef41Sopenharmony_ci 8371cb0ef41Sopenharmony_ci /* ARCOUNT */ 8381cb0ef41Sopenharmony_ci status = ares__buf_fetch_be16(buf, arcount); 8391cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 8401cb0ef41Sopenharmony_ci goto fail; 8411cb0ef41Sopenharmony_ci } 8421cb0ef41Sopenharmony_ci 8431cb0ef41Sopenharmony_ci status = ares_dns_record_create(dnsrec, id, dns_flags, opcode, 8441cb0ef41Sopenharmony_ci ARES_RCODE_NOERROR /* Temporary */); 8451cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 8461cb0ef41Sopenharmony_ci goto fail; 8471cb0ef41Sopenharmony_ci } 8481cb0ef41Sopenharmony_ci 8491cb0ef41Sopenharmony_ci (*dnsrec)->raw_rcode = rcode; 8501cb0ef41Sopenharmony_ci 8511cb0ef41Sopenharmony_ci if (*ancount > 0) { 8521cb0ef41Sopenharmony_ci status = 8531cb0ef41Sopenharmony_ci ares_dns_record_rr_prealloc(*dnsrec, ARES_SECTION_ANSWER, *ancount); 8541cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 8551cb0ef41Sopenharmony_ci goto fail; 8561cb0ef41Sopenharmony_ci } 8571cb0ef41Sopenharmony_ci } 8581cb0ef41Sopenharmony_ci 8591cb0ef41Sopenharmony_ci if (*nscount > 0) { 8601cb0ef41Sopenharmony_ci status = 8611cb0ef41Sopenharmony_ci ares_dns_record_rr_prealloc(*dnsrec, ARES_SECTION_AUTHORITY, *nscount); 8621cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 8631cb0ef41Sopenharmony_ci goto fail; 8641cb0ef41Sopenharmony_ci } 8651cb0ef41Sopenharmony_ci } 8661cb0ef41Sopenharmony_ci 8671cb0ef41Sopenharmony_ci if (*arcount > 0) { 8681cb0ef41Sopenharmony_ci status = 8691cb0ef41Sopenharmony_ci ares_dns_record_rr_prealloc(*dnsrec, ARES_SECTION_ADDITIONAL, *arcount); 8701cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 8711cb0ef41Sopenharmony_ci goto fail; 8721cb0ef41Sopenharmony_ci } 8731cb0ef41Sopenharmony_ci } 8741cb0ef41Sopenharmony_ci 8751cb0ef41Sopenharmony_ci return ARES_SUCCESS; 8761cb0ef41Sopenharmony_ci 8771cb0ef41Sopenharmony_cifail: 8781cb0ef41Sopenharmony_ci ares_dns_record_destroy(*dnsrec); 8791cb0ef41Sopenharmony_ci *dnsrec = NULL; 8801cb0ef41Sopenharmony_ci *qdcount = 0; 8811cb0ef41Sopenharmony_ci *ancount = 0; 8821cb0ef41Sopenharmony_ci *nscount = 0; 8831cb0ef41Sopenharmony_ci *arcount = 0; 8841cb0ef41Sopenharmony_ci 8851cb0ef41Sopenharmony_ci return status; 8861cb0ef41Sopenharmony_ci} 8871cb0ef41Sopenharmony_ci 8881cb0ef41Sopenharmony_cistatic ares_status_t 8891cb0ef41Sopenharmony_ci ares_dns_parse_rr_data(ares__buf_t *buf, size_t rdlength, ares_dns_rr_t *rr, 8901cb0ef41Sopenharmony_ci ares_dns_rec_type_t type, unsigned short raw_type, 8911cb0ef41Sopenharmony_ci unsigned short raw_class, unsigned int raw_ttl) 8921cb0ef41Sopenharmony_ci{ 8931cb0ef41Sopenharmony_ci switch (type) { 8941cb0ef41Sopenharmony_ci case ARES_REC_TYPE_A: 8951cb0ef41Sopenharmony_ci return ares_dns_parse_rr_a(buf, rr, rdlength); 8961cb0ef41Sopenharmony_ci case ARES_REC_TYPE_NS: 8971cb0ef41Sopenharmony_ci return ares_dns_parse_rr_ns(buf, rr, rdlength); 8981cb0ef41Sopenharmony_ci case ARES_REC_TYPE_CNAME: 8991cb0ef41Sopenharmony_ci return ares_dns_parse_rr_cname(buf, rr, rdlength); 9001cb0ef41Sopenharmony_ci case ARES_REC_TYPE_SOA: 9011cb0ef41Sopenharmony_ci return ares_dns_parse_rr_soa(buf, rr, rdlength); 9021cb0ef41Sopenharmony_ci case ARES_REC_TYPE_PTR: 9031cb0ef41Sopenharmony_ci return ares_dns_parse_rr_ptr(buf, rr, rdlength); 9041cb0ef41Sopenharmony_ci case ARES_REC_TYPE_HINFO: 9051cb0ef41Sopenharmony_ci return ares_dns_parse_rr_hinfo(buf, rr, rdlength); 9061cb0ef41Sopenharmony_ci case ARES_REC_TYPE_MX: 9071cb0ef41Sopenharmony_ci return ares_dns_parse_rr_mx(buf, rr, rdlength); 9081cb0ef41Sopenharmony_ci case ARES_REC_TYPE_TXT: 9091cb0ef41Sopenharmony_ci return ares_dns_parse_rr_txt(buf, rr, rdlength); 9101cb0ef41Sopenharmony_ci case ARES_REC_TYPE_AAAA: 9111cb0ef41Sopenharmony_ci return ares_dns_parse_rr_aaaa(buf, rr, rdlength); 9121cb0ef41Sopenharmony_ci case ARES_REC_TYPE_SRV: 9131cb0ef41Sopenharmony_ci return ares_dns_parse_rr_srv(buf, rr, rdlength); 9141cb0ef41Sopenharmony_ci case ARES_REC_TYPE_NAPTR: 9151cb0ef41Sopenharmony_ci return ares_dns_parse_rr_naptr(buf, rr, rdlength); 9161cb0ef41Sopenharmony_ci case ARES_REC_TYPE_ANY: 9171cb0ef41Sopenharmony_ci return ARES_EBADRESP; 9181cb0ef41Sopenharmony_ci case ARES_REC_TYPE_OPT: 9191cb0ef41Sopenharmony_ci return ares_dns_parse_rr_opt(buf, rr, rdlength, raw_class, raw_ttl); 9201cb0ef41Sopenharmony_ci case ARES_REC_TYPE_TLSA: 9211cb0ef41Sopenharmony_ci return ares_dns_parse_rr_tlsa(buf, rr, rdlength); 9221cb0ef41Sopenharmony_ci case ARES_REC_TYPE_SVCB: 9231cb0ef41Sopenharmony_ci return ares_dns_parse_rr_svcb(buf, rr, rdlength); 9241cb0ef41Sopenharmony_ci case ARES_REC_TYPE_HTTPS: 9251cb0ef41Sopenharmony_ci return ares_dns_parse_rr_https(buf, rr, rdlength); 9261cb0ef41Sopenharmony_ci case ARES_REC_TYPE_URI: 9271cb0ef41Sopenharmony_ci return ares_dns_parse_rr_uri(buf, rr, rdlength); 9281cb0ef41Sopenharmony_ci case ARES_REC_TYPE_CAA: 9291cb0ef41Sopenharmony_ci return ares_dns_parse_rr_caa(buf, rr, rdlength); 9301cb0ef41Sopenharmony_ci case ARES_REC_TYPE_RAW_RR: 9311cb0ef41Sopenharmony_ci return ares_dns_parse_rr_raw_rr(buf, rr, rdlength, raw_type); 9321cb0ef41Sopenharmony_ci } 9331cb0ef41Sopenharmony_ci return ARES_EFORMERR; 9341cb0ef41Sopenharmony_ci} 9351cb0ef41Sopenharmony_ci 9361cb0ef41Sopenharmony_cistatic ares_status_t ares_dns_parse_qd(ares__buf_t *buf, 9371cb0ef41Sopenharmony_ci ares_dns_record_t *dnsrec) 9381cb0ef41Sopenharmony_ci{ 9391cb0ef41Sopenharmony_ci char *name = NULL; 9401cb0ef41Sopenharmony_ci unsigned short u16; 9411cb0ef41Sopenharmony_ci ares_status_t status; 9421cb0ef41Sopenharmony_ci ares_dns_rec_type_t type; 9431cb0ef41Sopenharmony_ci ares_dns_class_t qclass; 9441cb0ef41Sopenharmony_ci /* The question section is used to carry the "question" in most queries, 9451cb0ef41Sopenharmony_ci * i.e., the parameters that define what is being asked. The section 9461cb0ef41Sopenharmony_ci * contains QDCOUNT (usually 1) entries, each of the following format: 9471cb0ef41Sopenharmony_ci * 1 1 1 1 1 1 9481cb0ef41Sopenharmony_ci * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 9491cb0ef41Sopenharmony_ci * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 9501cb0ef41Sopenharmony_ci * | | 9511cb0ef41Sopenharmony_ci * / QNAME / 9521cb0ef41Sopenharmony_ci * / / 9531cb0ef41Sopenharmony_ci * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 9541cb0ef41Sopenharmony_ci * | QTYPE | 9551cb0ef41Sopenharmony_ci * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 9561cb0ef41Sopenharmony_ci * | QCLASS | 9571cb0ef41Sopenharmony_ci * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 9581cb0ef41Sopenharmony_ci */ 9591cb0ef41Sopenharmony_ci 9601cb0ef41Sopenharmony_ci /* Name */ 9611cb0ef41Sopenharmony_ci status = ares__dns_name_parse(buf, &name, ARES_FALSE); 9621cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 9631cb0ef41Sopenharmony_ci goto done; 9641cb0ef41Sopenharmony_ci } 9651cb0ef41Sopenharmony_ci 9661cb0ef41Sopenharmony_ci /* Type */ 9671cb0ef41Sopenharmony_ci status = ares__buf_fetch_be16(buf, &u16); 9681cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 9691cb0ef41Sopenharmony_ci goto done; 9701cb0ef41Sopenharmony_ci } 9711cb0ef41Sopenharmony_ci type = u16; 9721cb0ef41Sopenharmony_ci 9731cb0ef41Sopenharmony_ci /* Class */ 9741cb0ef41Sopenharmony_ci status = ares__buf_fetch_be16(buf, &u16); 9751cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 9761cb0ef41Sopenharmony_ci goto done; 9771cb0ef41Sopenharmony_ci } 9781cb0ef41Sopenharmony_ci qclass = u16; 9791cb0ef41Sopenharmony_ci 9801cb0ef41Sopenharmony_ci /* Add question */ 9811cb0ef41Sopenharmony_ci status = ares_dns_record_query_add(dnsrec, name, type, qclass); 9821cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 9831cb0ef41Sopenharmony_ci goto done; 9841cb0ef41Sopenharmony_ci } 9851cb0ef41Sopenharmony_ci 9861cb0ef41Sopenharmony_cidone: 9871cb0ef41Sopenharmony_ci ares_free(name); 9881cb0ef41Sopenharmony_ci return status; 9891cb0ef41Sopenharmony_ci} 9901cb0ef41Sopenharmony_ci 9911cb0ef41Sopenharmony_cistatic ares_status_t ares_dns_parse_rr(ares__buf_t *buf, unsigned int flags, 9921cb0ef41Sopenharmony_ci ares_dns_section_t sect, 9931cb0ef41Sopenharmony_ci ares_dns_record_t *dnsrec) 9941cb0ef41Sopenharmony_ci{ 9951cb0ef41Sopenharmony_ci char *name = NULL; 9961cb0ef41Sopenharmony_ci unsigned short u16; 9971cb0ef41Sopenharmony_ci unsigned short raw_type; 9981cb0ef41Sopenharmony_ci ares_status_t status; 9991cb0ef41Sopenharmony_ci ares_dns_rec_type_t type; 10001cb0ef41Sopenharmony_ci ares_dns_class_t qclass; 10011cb0ef41Sopenharmony_ci unsigned int ttl; 10021cb0ef41Sopenharmony_ci size_t rdlength; 10031cb0ef41Sopenharmony_ci ares_dns_rr_t *rr = NULL; 10041cb0ef41Sopenharmony_ci size_t remaining_len = 0; 10051cb0ef41Sopenharmony_ci size_t processed_len = 0; 10061cb0ef41Sopenharmony_ci ares_bool_t namecomp; 10071cb0ef41Sopenharmony_ci 10081cb0ef41Sopenharmony_ci /* All RRs have the same top level format shown below: 10091cb0ef41Sopenharmony_ci * 1 1 1 1 1 1 10101cb0ef41Sopenharmony_ci * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 10111cb0ef41Sopenharmony_ci * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 10121cb0ef41Sopenharmony_ci * | | 10131cb0ef41Sopenharmony_ci * / / 10141cb0ef41Sopenharmony_ci * / NAME / 10151cb0ef41Sopenharmony_ci * | | 10161cb0ef41Sopenharmony_ci * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 10171cb0ef41Sopenharmony_ci * | TYPE | 10181cb0ef41Sopenharmony_ci * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 10191cb0ef41Sopenharmony_ci * | CLASS | 10201cb0ef41Sopenharmony_ci * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 10211cb0ef41Sopenharmony_ci * | TTL | 10221cb0ef41Sopenharmony_ci * | | 10231cb0ef41Sopenharmony_ci * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 10241cb0ef41Sopenharmony_ci * | RDLENGTH | 10251cb0ef41Sopenharmony_ci * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| 10261cb0ef41Sopenharmony_ci * / RDATA / 10271cb0ef41Sopenharmony_ci * / / 10281cb0ef41Sopenharmony_ci * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 10291cb0ef41Sopenharmony_ci */ 10301cb0ef41Sopenharmony_ci 10311cb0ef41Sopenharmony_ci /* Name */ 10321cb0ef41Sopenharmony_ci status = ares__dns_name_parse(buf, &name, ARES_FALSE); 10331cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 10341cb0ef41Sopenharmony_ci goto done; 10351cb0ef41Sopenharmony_ci } 10361cb0ef41Sopenharmony_ci 10371cb0ef41Sopenharmony_ci /* Type */ 10381cb0ef41Sopenharmony_ci status = ares__buf_fetch_be16(buf, &u16); 10391cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 10401cb0ef41Sopenharmony_ci goto done; 10411cb0ef41Sopenharmony_ci } 10421cb0ef41Sopenharmony_ci type = u16; 10431cb0ef41Sopenharmony_ci raw_type = u16; /* Only used for raw rr data */ 10441cb0ef41Sopenharmony_ci 10451cb0ef41Sopenharmony_ci /* Class */ 10461cb0ef41Sopenharmony_ci status = ares__buf_fetch_be16(buf, &u16); 10471cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 10481cb0ef41Sopenharmony_ci goto done; 10491cb0ef41Sopenharmony_ci } 10501cb0ef41Sopenharmony_ci qclass = u16; 10511cb0ef41Sopenharmony_ci 10521cb0ef41Sopenharmony_ci /* TTL */ 10531cb0ef41Sopenharmony_ci status = ares__buf_fetch_be32(buf, &ttl); 10541cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 10551cb0ef41Sopenharmony_ci goto done; 10561cb0ef41Sopenharmony_ci } 10571cb0ef41Sopenharmony_ci 10581cb0ef41Sopenharmony_ci /* Length */ 10591cb0ef41Sopenharmony_ci status = ares__buf_fetch_be16(buf, &u16); 10601cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 10611cb0ef41Sopenharmony_ci goto done; 10621cb0ef41Sopenharmony_ci } 10631cb0ef41Sopenharmony_ci rdlength = u16; 10641cb0ef41Sopenharmony_ci 10651cb0ef41Sopenharmony_ci if (!ares_dns_rec_type_isvalid(type, ARES_FALSE)) { 10661cb0ef41Sopenharmony_ci type = ARES_REC_TYPE_RAW_RR; 10671cb0ef41Sopenharmony_ci } 10681cb0ef41Sopenharmony_ci 10691cb0ef41Sopenharmony_ci namecomp = ares_dns_rec_type_allow_name_compression(type); 10701cb0ef41Sopenharmony_ci if (sect == ARES_SECTION_ANSWER && 10711cb0ef41Sopenharmony_ci (flags & 10721cb0ef41Sopenharmony_ci (namecomp ? ARES_DNS_PARSE_AN_BASE_RAW : ARES_DNS_PARSE_AN_EXT_RAW))) { 10731cb0ef41Sopenharmony_ci type = ARES_REC_TYPE_RAW_RR; 10741cb0ef41Sopenharmony_ci } 10751cb0ef41Sopenharmony_ci if (sect == ARES_SECTION_AUTHORITY && 10761cb0ef41Sopenharmony_ci (flags & 10771cb0ef41Sopenharmony_ci (namecomp ? ARES_DNS_PARSE_NS_BASE_RAW : ARES_DNS_PARSE_NS_EXT_RAW))) { 10781cb0ef41Sopenharmony_ci type = ARES_REC_TYPE_RAW_RR; 10791cb0ef41Sopenharmony_ci } 10801cb0ef41Sopenharmony_ci if (sect == ARES_SECTION_ADDITIONAL && 10811cb0ef41Sopenharmony_ci (flags & 10821cb0ef41Sopenharmony_ci (namecomp ? ARES_DNS_PARSE_AR_BASE_RAW : ARES_DNS_PARSE_AR_EXT_RAW))) { 10831cb0ef41Sopenharmony_ci type = ARES_REC_TYPE_RAW_RR; 10841cb0ef41Sopenharmony_ci } 10851cb0ef41Sopenharmony_ci 10861cb0ef41Sopenharmony_ci /* Pull into another buffer for safety */ 10871cb0ef41Sopenharmony_ci if (rdlength > ares__buf_len(buf)) { 10881cb0ef41Sopenharmony_ci status = ARES_EBADRESP; 10891cb0ef41Sopenharmony_ci goto done; 10901cb0ef41Sopenharmony_ci } 10911cb0ef41Sopenharmony_ci 10921cb0ef41Sopenharmony_ci /* Add the base rr */ 10931cb0ef41Sopenharmony_ci status = 10941cb0ef41Sopenharmony_ci ares_dns_record_rr_add(&rr, dnsrec, sect, name, type, 10951cb0ef41Sopenharmony_ci type == ARES_REC_TYPE_OPT ? ARES_CLASS_IN : qclass, 10961cb0ef41Sopenharmony_ci type == ARES_REC_TYPE_OPT ? 0 : ttl); 10971cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 10981cb0ef41Sopenharmony_ci goto done; 10991cb0ef41Sopenharmony_ci } 11001cb0ef41Sopenharmony_ci 11011cb0ef41Sopenharmony_ci /* Record the current remaining length in the buffer so we can tell how 11021cb0ef41Sopenharmony_ci * much was processed */ 11031cb0ef41Sopenharmony_ci remaining_len = ares__buf_len(buf); 11041cb0ef41Sopenharmony_ci 11051cb0ef41Sopenharmony_ci /* Fill in the data for the rr */ 11061cb0ef41Sopenharmony_ci status = ares_dns_parse_rr_data(buf, rdlength, rr, type, raw_type, 11071cb0ef41Sopenharmony_ci (unsigned short)qclass, ttl); 11081cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 11091cb0ef41Sopenharmony_ci goto done; 11101cb0ef41Sopenharmony_ci } 11111cb0ef41Sopenharmony_ci 11121cb0ef41Sopenharmony_ci /* Determine how many bytes were processed */ 11131cb0ef41Sopenharmony_ci processed_len = remaining_len - ares__buf_len(buf); 11141cb0ef41Sopenharmony_ci 11151cb0ef41Sopenharmony_ci /* If too many bytes were processed, error! */ 11161cb0ef41Sopenharmony_ci if (processed_len > rdlength) { 11171cb0ef41Sopenharmony_ci status = ARES_EBADRESP; 11181cb0ef41Sopenharmony_ci goto done; 11191cb0ef41Sopenharmony_ci } 11201cb0ef41Sopenharmony_ci 11211cb0ef41Sopenharmony_ci /* If too few bytes were processed, consume the unprocessed data for this 11221cb0ef41Sopenharmony_ci * record as the parser may not have wanted/needed to use it */ 11231cb0ef41Sopenharmony_ci if (processed_len < rdlength) { 11241cb0ef41Sopenharmony_ci ares__buf_consume(buf, rdlength - processed_len); 11251cb0ef41Sopenharmony_ci } 11261cb0ef41Sopenharmony_ci 11271cb0ef41Sopenharmony_ci 11281cb0ef41Sopenharmony_cidone: 11291cb0ef41Sopenharmony_ci ares_free(name); 11301cb0ef41Sopenharmony_ci return status; 11311cb0ef41Sopenharmony_ci} 11321cb0ef41Sopenharmony_ci 11331cb0ef41Sopenharmony_cistatic ares_status_t ares_dns_parse_buf(ares__buf_t *buf, unsigned int flags, 11341cb0ef41Sopenharmony_ci ares_dns_record_t **dnsrec) 11351cb0ef41Sopenharmony_ci{ 11361cb0ef41Sopenharmony_ci ares_status_t status; 11371cb0ef41Sopenharmony_ci unsigned short qdcount; 11381cb0ef41Sopenharmony_ci unsigned short ancount; 11391cb0ef41Sopenharmony_ci unsigned short nscount; 11401cb0ef41Sopenharmony_ci unsigned short arcount; 11411cb0ef41Sopenharmony_ci unsigned short i; 11421cb0ef41Sopenharmony_ci 11431cb0ef41Sopenharmony_ci if (buf == NULL || dnsrec == NULL) { 11441cb0ef41Sopenharmony_ci return ARES_EFORMERR; 11451cb0ef41Sopenharmony_ci } 11461cb0ef41Sopenharmony_ci 11471cb0ef41Sopenharmony_ci /* Maximum DNS packet size is 64k, even over TCP */ 11481cb0ef41Sopenharmony_ci if (ares__buf_len(buf) > 0xFFFF) { 11491cb0ef41Sopenharmony_ci return ARES_EFORMERR; 11501cb0ef41Sopenharmony_ci } 11511cb0ef41Sopenharmony_ci 11521cb0ef41Sopenharmony_ci /* All communications inside of the domain protocol are carried in a single 11531cb0ef41Sopenharmony_ci * format called a message. The top level format of message is divided 11541cb0ef41Sopenharmony_ci * into 5 sections (some of which are empty in certain cases) shown below: 11551cb0ef41Sopenharmony_ci * 11561cb0ef41Sopenharmony_ci * +---------------------+ 11571cb0ef41Sopenharmony_ci * | Header | 11581cb0ef41Sopenharmony_ci * +---------------------+ 11591cb0ef41Sopenharmony_ci * | Question | the question for the name server 11601cb0ef41Sopenharmony_ci * +---------------------+ 11611cb0ef41Sopenharmony_ci * | Answer | RRs answering the question 11621cb0ef41Sopenharmony_ci * +---------------------+ 11631cb0ef41Sopenharmony_ci * | Authority | RRs pointing toward an authority 11641cb0ef41Sopenharmony_ci * +---------------------+ 11651cb0ef41Sopenharmony_ci * | Additional | RRs holding additional information 11661cb0ef41Sopenharmony_ci * +---------------------+ 11671cb0ef41Sopenharmony_ci */ 11681cb0ef41Sopenharmony_ci 11691cb0ef41Sopenharmony_ci /* Parse header */ 11701cb0ef41Sopenharmony_ci status = ares_dns_parse_header(buf, flags, dnsrec, &qdcount, &ancount, 11711cb0ef41Sopenharmony_ci &nscount, &arcount); 11721cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 11731cb0ef41Sopenharmony_ci goto fail; 11741cb0ef41Sopenharmony_ci } 11751cb0ef41Sopenharmony_ci 11761cb0ef41Sopenharmony_ci /* Must have questions */ 11771cb0ef41Sopenharmony_ci if (qdcount == 0) { 11781cb0ef41Sopenharmony_ci status = ARES_EBADRESP; 11791cb0ef41Sopenharmony_ci goto fail; 11801cb0ef41Sopenharmony_ci } 11811cb0ef41Sopenharmony_ci 11821cb0ef41Sopenharmony_ci /* XXX: this should be controlled by a flag in case we want to allow 11831cb0ef41Sopenharmony_ci * multiple questions. I think mDNS allows this */ 11841cb0ef41Sopenharmony_ci if (qdcount > 1) { 11851cb0ef41Sopenharmony_ci status = ARES_EBADRESP; 11861cb0ef41Sopenharmony_ci goto fail; 11871cb0ef41Sopenharmony_ci } 11881cb0ef41Sopenharmony_ci 11891cb0ef41Sopenharmony_ci /* Parse questions */ 11901cb0ef41Sopenharmony_ci for (i = 0; i < qdcount; i++) { 11911cb0ef41Sopenharmony_ci status = ares_dns_parse_qd(buf, *dnsrec); 11921cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 11931cb0ef41Sopenharmony_ci goto fail; 11941cb0ef41Sopenharmony_ci } 11951cb0ef41Sopenharmony_ci } 11961cb0ef41Sopenharmony_ci 11971cb0ef41Sopenharmony_ci /* Parse Answers */ 11981cb0ef41Sopenharmony_ci for (i = 0; i < ancount; i++) { 11991cb0ef41Sopenharmony_ci status = ares_dns_parse_rr(buf, flags, ARES_SECTION_ANSWER, *dnsrec); 12001cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 12011cb0ef41Sopenharmony_ci goto fail; 12021cb0ef41Sopenharmony_ci } 12031cb0ef41Sopenharmony_ci } 12041cb0ef41Sopenharmony_ci 12051cb0ef41Sopenharmony_ci /* Parse Authority */ 12061cb0ef41Sopenharmony_ci for (i = 0; i < nscount; i++) { 12071cb0ef41Sopenharmony_ci status = ares_dns_parse_rr(buf, flags, ARES_SECTION_AUTHORITY, *dnsrec); 12081cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 12091cb0ef41Sopenharmony_ci goto fail; 12101cb0ef41Sopenharmony_ci } 12111cb0ef41Sopenharmony_ci } 12121cb0ef41Sopenharmony_ci 12131cb0ef41Sopenharmony_ci /* Parse Additional */ 12141cb0ef41Sopenharmony_ci for (i = 0; i < arcount; i++) { 12151cb0ef41Sopenharmony_ci status = ares_dns_parse_rr(buf, flags, ARES_SECTION_ADDITIONAL, *dnsrec); 12161cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 12171cb0ef41Sopenharmony_ci goto fail; 12181cb0ef41Sopenharmony_ci } 12191cb0ef41Sopenharmony_ci } 12201cb0ef41Sopenharmony_ci 12211cb0ef41Sopenharmony_ci /* Finalize rcode now that if we have OPT it is processed */ 12221cb0ef41Sopenharmony_ci if (!ares_dns_rcode_isvalid((*dnsrec)->raw_rcode)) { 12231cb0ef41Sopenharmony_ci (*dnsrec)->rcode = ARES_RCODE_SERVFAIL; 12241cb0ef41Sopenharmony_ci } else { 12251cb0ef41Sopenharmony_ci (*dnsrec)->rcode = (ares_dns_rcode_t)(*dnsrec)->raw_rcode; 12261cb0ef41Sopenharmony_ci } 12271cb0ef41Sopenharmony_ci 12281cb0ef41Sopenharmony_ci return ARES_SUCCESS; 12291cb0ef41Sopenharmony_ci 12301cb0ef41Sopenharmony_cifail: 12311cb0ef41Sopenharmony_ci ares_dns_record_destroy(*dnsrec); 12321cb0ef41Sopenharmony_ci *dnsrec = NULL; 12331cb0ef41Sopenharmony_ci return status; 12341cb0ef41Sopenharmony_ci} 12351cb0ef41Sopenharmony_ci 12361cb0ef41Sopenharmony_ciares_status_t ares_dns_parse(const unsigned char *buf, size_t buf_len, 12371cb0ef41Sopenharmony_ci unsigned int flags, ares_dns_record_t **dnsrec) 12381cb0ef41Sopenharmony_ci{ 12391cb0ef41Sopenharmony_ci ares__buf_t *parser = NULL; 12401cb0ef41Sopenharmony_ci ares_status_t status; 12411cb0ef41Sopenharmony_ci 12421cb0ef41Sopenharmony_ci if (buf == NULL || buf_len == 0 || dnsrec == NULL) { 12431cb0ef41Sopenharmony_ci return ARES_EFORMERR; 12441cb0ef41Sopenharmony_ci } 12451cb0ef41Sopenharmony_ci 12461cb0ef41Sopenharmony_ci parser = ares__buf_create_const(buf, buf_len); 12471cb0ef41Sopenharmony_ci if (parser == NULL) { 12481cb0ef41Sopenharmony_ci return ARES_ENOMEM; 12491cb0ef41Sopenharmony_ci } 12501cb0ef41Sopenharmony_ci 12511cb0ef41Sopenharmony_ci status = ares_dns_parse_buf(parser, flags, dnsrec); 12521cb0ef41Sopenharmony_ci ares__buf_destroy(parser); 12531cb0ef41Sopenharmony_ci 12541cb0ef41Sopenharmony_ci return status; 12551cb0ef41Sopenharmony_ci} 1256