11cb0ef41Sopenharmony_ci/* MIT License 21cb0ef41Sopenharmony_ci * 31cb0ef41Sopenharmony_ci * Copyright (c) 1998 Massachusetts Institute of Technology 41cb0ef41Sopenharmony_ci * Copyright (c) 2007 Daniel Stenberg 51cb0ef41Sopenharmony_ci * 61cb0ef41Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 71cb0ef41Sopenharmony_ci * of this software and associated documentation files (the "Software"), to deal 81cb0ef41Sopenharmony_ci * in the Software without restriction, including without limitation the rights 91cb0ef41Sopenharmony_ci * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 101cb0ef41Sopenharmony_ci * copies of the Software, and to permit persons to whom the Software is 111cb0ef41Sopenharmony_ci * furnished to do so, subject to the following conditions: 121cb0ef41Sopenharmony_ci * 131cb0ef41Sopenharmony_ci * The above copyright notice and this permission notice (including the next 141cb0ef41Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 151cb0ef41Sopenharmony_ci * Software. 161cb0ef41Sopenharmony_ci * 171cb0ef41Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 181cb0ef41Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 191cb0ef41Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 201cb0ef41Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 211cb0ef41Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 221cb0ef41Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 231cb0ef41Sopenharmony_ci * SOFTWARE. 241cb0ef41Sopenharmony_ci * 251cb0ef41Sopenharmony_ci * SPDX-License-Identifier: MIT 261cb0ef41Sopenharmony_ci */ 271cb0ef41Sopenharmony_ci 281cb0ef41Sopenharmony_ci#include "ares_setup.h" 291cb0ef41Sopenharmony_ci 301cb0ef41Sopenharmony_ci#ifdef HAVE_SYS_PARAM_H 311cb0ef41Sopenharmony_ci# include <sys/param.h> 321cb0ef41Sopenharmony_ci#endif 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_ci#ifdef HAVE_NETINET_IN_H 351cb0ef41Sopenharmony_ci# include <netinet/in.h> 361cb0ef41Sopenharmony_ci#endif 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_ci#ifdef HAVE_NETDB_H 391cb0ef41Sopenharmony_ci# include <netdb.h> 401cb0ef41Sopenharmony_ci#endif 411cb0ef41Sopenharmony_ci 421cb0ef41Sopenharmony_ci#ifdef HAVE_ARPA_INET_H 431cb0ef41Sopenharmony_ci# include <arpa/inet.h> 441cb0ef41Sopenharmony_ci#endif 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_ci#include "ares_nameser.h" 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_ci#if defined(ANDROID) || defined(__ANDROID__) 491cb0ef41Sopenharmony_ci# include <sys/system_properties.h> 501cb0ef41Sopenharmony_ci# include "ares_android.h" 511cb0ef41Sopenharmony_ci/* From the Bionic sources */ 521cb0ef41Sopenharmony_ci# define DNS_PROP_NAME_PREFIX "net.dns" 531cb0ef41Sopenharmony_ci# define MAX_DNS_PROPERTIES 8 541cb0ef41Sopenharmony_ci#endif 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_ci#if defined(CARES_USE_LIBRESOLV) 571cb0ef41Sopenharmony_ci# include <resolv.h> 581cb0ef41Sopenharmony_ci#endif 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_ci#if defined(USE_WINSOCK) && defined(HAVE_IPHLPAPI_H) 611cb0ef41Sopenharmony_ci# include <iphlpapi.h> 621cb0ef41Sopenharmony_ci#endif 631cb0ef41Sopenharmony_ci 641cb0ef41Sopenharmony_ci#include "ares.h" 651cb0ef41Sopenharmony_ci#include "ares_inet_net_pton.h" 661cb0ef41Sopenharmony_ci#include "ares_platform.h" 671cb0ef41Sopenharmony_ci#include "ares_private.h" 681cb0ef41Sopenharmony_ci 691cb0ef41Sopenharmony_cistatic unsigned char ip_natural_mask(const struct ares_addr *addr) 701cb0ef41Sopenharmony_ci{ 711cb0ef41Sopenharmony_ci const unsigned char *ptr = NULL; 721cb0ef41Sopenharmony_ci /* This is an odd one. If a raw ipv4 address is specified, then we take 731cb0ef41Sopenharmony_ci * what is called a natural mask, which means we look at the first octet 741cb0ef41Sopenharmony_ci * of the ip address and for values 0-127 we assume it is a class A (/8), 751cb0ef41Sopenharmony_ci * for values 128-191 we assume it is a class B (/16), and for 192-223 761cb0ef41Sopenharmony_ci * we assume it is a class C (/24). 223-239 is Class D which and 240-255 is 771cb0ef41Sopenharmony_ci * Class E, however, there is no pre-defined mask for this, so we'll use 781cb0ef41Sopenharmony_ci * /24 as well as that's what the old code did. 791cb0ef41Sopenharmony_ci * 801cb0ef41Sopenharmony_ci * For IPv6, we'll use /64. 811cb0ef41Sopenharmony_ci */ 821cb0ef41Sopenharmony_ci 831cb0ef41Sopenharmony_ci if (addr->family == AF_INET6) { 841cb0ef41Sopenharmony_ci return 64; 851cb0ef41Sopenharmony_ci } 861cb0ef41Sopenharmony_ci 871cb0ef41Sopenharmony_ci ptr = (const unsigned char *)&addr->addr.addr4; 881cb0ef41Sopenharmony_ci if (*ptr < 128) { 891cb0ef41Sopenharmony_ci return 8; 901cb0ef41Sopenharmony_ci } 911cb0ef41Sopenharmony_ci 921cb0ef41Sopenharmony_ci if (*ptr < 192) { 931cb0ef41Sopenharmony_ci return 16; 941cb0ef41Sopenharmony_ci } 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_ci return 24; 971cb0ef41Sopenharmony_ci} 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_cistatic ares_bool_t sortlist_append(struct apattern **sortlist, size_t *nsort, 1001cb0ef41Sopenharmony_ci const struct apattern *pat) 1011cb0ef41Sopenharmony_ci{ 1021cb0ef41Sopenharmony_ci struct apattern *newsort; 1031cb0ef41Sopenharmony_ci 1041cb0ef41Sopenharmony_ci newsort = ares_realloc(*sortlist, (*nsort + 1) * sizeof(*newsort)); 1051cb0ef41Sopenharmony_ci if (newsort == NULL) { 1061cb0ef41Sopenharmony_ci return ARES_FALSE; 1071cb0ef41Sopenharmony_ci } 1081cb0ef41Sopenharmony_ci 1091cb0ef41Sopenharmony_ci *sortlist = newsort; 1101cb0ef41Sopenharmony_ci 1111cb0ef41Sopenharmony_ci memcpy(&(*sortlist)[*nsort], pat, sizeof(**sortlist)); 1121cb0ef41Sopenharmony_ci (*nsort)++; 1131cb0ef41Sopenharmony_ci 1141cb0ef41Sopenharmony_ci return ARES_TRUE; 1151cb0ef41Sopenharmony_ci} 1161cb0ef41Sopenharmony_ci 1171cb0ef41Sopenharmony_cistatic ares_status_t parse_sort(ares__buf_t *buf, struct apattern *pat) 1181cb0ef41Sopenharmony_ci{ 1191cb0ef41Sopenharmony_ci ares_status_t status; 1201cb0ef41Sopenharmony_ci const unsigned char ip_charset[] = "ABCDEFabcdef0123456789.:"; 1211cb0ef41Sopenharmony_ci char ipaddr[INET6_ADDRSTRLEN] = ""; 1221cb0ef41Sopenharmony_ci size_t addrlen; 1231cb0ef41Sopenharmony_ci 1241cb0ef41Sopenharmony_ci memset(pat, 0, sizeof(*pat)); 1251cb0ef41Sopenharmony_ci 1261cb0ef41Sopenharmony_ci /* Consume any leading whitespace */ 1271cb0ef41Sopenharmony_ci ares__buf_consume_whitespace(buf, ARES_TRUE); 1281cb0ef41Sopenharmony_ci 1291cb0ef41Sopenharmony_ci /* If no length, just ignore, return ENOTFOUND as an indicator */ 1301cb0ef41Sopenharmony_ci if (ares__buf_len(buf) == 0) { 1311cb0ef41Sopenharmony_ci return ARES_ENOTFOUND; 1321cb0ef41Sopenharmony_ci } 1331cb0ef41Sopenharmony_ci 1341cb0ef41Sopenharmony_ci ares__buf_tag(buf); 1351cb0ef41Sopenharmony_ci 1361cb0ef41Sopenharmony_ci /* Consume ip address */ 1371cb0ef41Sopenharmony_ci if (ares__buf_consume_charset(buf, ip_charset, sizeof(ip_charset)) == 0) { 1381cb0ef41Sopenharmony_ci return ARES_EBADSTR; 1391cb0ef41Sopenharmony_ci } 1401cb0ef41Sopenharmony_ci 1411cb0ef41Sopenharmony_ci /* Fetch ip address */ 1421cb0ef41Sopenharmony_ci status = ares__buf_tag_fetch_string(buf, ipaddr, sizeof(ipaddr)); 1431cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 1441cb0ef41Sopenharmony_ci return status; 1451cb0ef41Sopenharmony_ci } 1461cb0ef41Sopenharmony_ci 1471cb0ef41Sopenharmony_ci /* Parse it to make sure its valid */ 1481cb0ef41Sopenharmony_ci pat->addr.family = AF_UNSPEC; 1491cb0ef41Sopenharmony_ci if (ares_dns_pton(ipaddr, &pat->addr, &addrlen) == NULL) { 1501cb0ef41Sopenharmony_ci return ARES_EBADSTR; 1511cb0ef41Sopenharmony_ci } 1521cb0ef41Sopenharmony_ci 1531cb0ef41Sopenharmony_ci /* See if there is a subnet mask */ 1541cb0ef41Sopenharmony_ci if (ares__buf_begins_with(buf, (const unsigned char *)"/", 1)) { 1551cb0ef41Sopenharmony_ci char maskstr[16]; 1561cb0ef41Sopenharmony_ci const unsigned char ipv4_charset[] = "0123456789."; 1571cb0ef41Sopenharmony_ci 1581cb0ef41Sopenharmony_ci 1591cb0ef41Sopenharmony_ci /* Consume / */ 1601cb0ef41Sopenharmony_ci ares__buf_consume(buf, 1); 1611cb0ef41Sopenharmony_ci 1621cb0ef41Sopenharmony_ci ares__buf_tag(buf); 1631cb0ef41Sopenharmony_ci 1641cb0ef41Sopenharmony_ci /* Consume mask */ 1651cb0ef41Sopenharmony_ci if (ares__buf_consume_charset(buf, ipv4_charset, sizeof(ipv4_charset)) == 1661cb0ef41Sopenharmony_ci 0) { 1671cb0ef41Sopenharmony_ci return ARES_EBADSTR; 1681cb0ef41Sopenharmony_ci } 1691cb0ef41Sopenharmony_ci 1701cb0ef41Sopenharmony_ci /* Fetch mask */ 1711cb0ef41Sopenharmony_ci status = ares__buf_tag_fetch_string(buf, maskstr, sizeof(maskstr)); 1721cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 1731cb0ef41Sopenharmony_ci return status; 1741cb0ef41Sopenharmony_ci } 1751cb0ef41Sopenharmony_ci 1761cb0ef41Sopenharmony_ci if (ares_str_isnum(maskstr)) { 1771cb0ef41Sopenharmony_ci /* Numeric mask */ 1781cb0ef41Sopenharmony_ci int mask = atoi(maskstr); 1791cb0ef41Sopenharmony_ci if (mask < 0 || mask > 128) { 1801cb0ef41Sopenharmony_ci return ARES_EBADSTR; 1811cb0ef41Sopenharmony_ci } 1821cb0ef41Sopenharmony_ci if (pat->addr.family == AF_INET && mask > 32) { 1831cb0ef41Sopenharmony_ci return ARES_EBADSTR; 1841cb0ef41Sopenharmony_ci } 1851cb0ef41Sopenharmony_ci pat->mask = (unsigned char)mask; 1861cb0ef41Sopenharmony_ci } else { 1871cb0ef41Sopenharmony_ci /* Ipv4 subnet style mask */ 1881cb0ef41Sopenharmony_ci struct ares_addr maskaddr; 1891cb0ef41Sopenharmony_ci const unsigned char *ptr; 1901cb0ef41Sopenharmony_ci 1911cb0ef41Sopenharmony_ci memset(&maskaddr, 0, sizeof(maskaddr)); 1921cb0ef41Sopenharmony_ci maskaddr.family = AF_INET; 1931cb0ef41Sopenharmony_ci if (ares_dns_pton(maskstr, &maskaddr, &addrlen) == NULL) { 1941cb0ef41Sopenharmony_ci return ARES_EBADSTR; 1951cb0ef41Sopenharmony_ci } 1961cb0ef41Sopenharmony_ci ptr = (const unsigned char *)&maskaddr.addr.addr4; 1971cb0ef41Sopenharmony_ci pat->mask = (unsigned char)(ares__count_bits_u8(ptr[0]) + 1981cb0ef41Sopenharmony_ci ares__count_bits_u8(ptr[1]) + 1991cb0ef41Sopenharmony_ci ares__count_bits_u8(ptr[2]) + 2001cb0ef41Sopenharmony_ci ares__count_bits_u8(ptr[3])); 2011cb0ef41Sopenharmony_ci } 2021cb0ef41Sopenharmony_ci } else { 2031cb0ef41Sopenharmony_ci pat->mask = ip_natural_mask(&pat->addr); 2041cb0ef41Sopenharmony_ci } 2051cb0ef41Sopenharmony_ci 2061cb0ef41Sopenharmony_ci /* Consume any trailing whitespace */ 2071cb0ef41Sopenharmony_ci ares__buf_consume_whitespace(buf, ARES_TRUE); 2081cb0ef41Sopenharmony_ci 2091cb0ef41Sopenharmony_ci /* If we have any trailing bytes other than whitespace, its a parse failure */ 2101cb0ef41Sopenharmony_ci if (ares__buf_len(buf) != 0) { 2111cb0ef41Sopenharmony_ci return ARES_EBADSTR; 2121cb0ef41Sopenharmony_ci } 2131cb0ef41Sopenharmony_ci 2141cb0ef41Sopenharmony_ci return ARES_SUCCESS; 2151cb0ef41Sopenharmony_ci} 2161cb0ef41Sopenharmony_ci 2171cb0ef41Sopenharmony_ciares_status_t ares__parse_sortlist(struct apattern **sortlist, size_t *nsort, 2181cb0ef41Sopenharmony_ci const char *str) 2191cb0ef41Sopenharmony_ci{ 2201cb0ef41Sopenharmony_ci ares__buf_t *buf = NULL; 2211cb0ef41Sopenharmony_ci ares__llist_t *list = NULL; 2221cb0ef41Sopenharmony_ci ares_status_t status = ARES_SUCCESS; 2231cb0ef41Sopenharmony_ci ares__llist_node_t *node = NULL; 2241cb0ef41Sopenharmony_ci 2251cb0ef41Sopenharmony_ci if (sortlist == NULL || nsort == NULL || str == NULL) { 2261cb0ef41Sopenharmony_ci return ARES_EFORMERR; 2271cb0ef41Sopenharmony_ci } 2281cb0ef41Sopenharmony_ci 2291cb0ef41Sopenharmony_ci if (*sortlist != NULL) { 2301cb0ef41Sopenharmony_ci ares_free(*sortlist); 2311cb0ef41Sopenharmony_ci } 2321cb0ef41Sopenharmony_ci 2331cb0ef41Sopenharmony_ci *sortlist = NULL; 2341cb0ef41Sopenharmony_ci *nsort = 0; 2351cb0ef41Sopenharmony_ci 2361cb0ef41Sopenharmony_ci buf = ares__buf_create_const((const unsigned char *)str, ares_strlen(str)); 2371cb0ef41Sopenharmony_ci if (buf == NULL) { 2381cb0ef41Sopenharmony_ci status = ARES_ENOMEM; 2391cb0ef41Sopenharmony_ci goto done; 2401cb0ef41Sopenharmony_ci } 2411cb0ef41Sopenharmony_ci 2421cb0ef41Sopenharmony_ci /* Split on space or semicolon */ 2431cb0ef41Sopenharmony_ci status = ares__buf_split(buf, (const unsigned char *)" ;", 2, 2441cb0ef41Sopenharmony_ci ARES_BUF_SPLIT_NONE, &list); 2451cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 2461cb0ef41Sopenharmony_ci goto done; 2471cb0ef41Sopenharmony_ci } 2481cb0ef41Sopenharmony_ci 2491cb0ef41Sopenharmony_ci for (node = ares__llist_node_first(list); node != NULL; 2501cb0ef41Sopenharmony_ci node = ares__llist_node_next(node)) { 2511cb0ef41Sopenharmony_ci ares__buf_t *entry = ares__llist_node_val(node); 2521cb0ef41Sopenharmony_ci 2531cb0ef41Sopenharmony_ci struct apattern pat; 2541cb0ef41Sopenharmony_ci 2551cb0ef41Sopenharmony_ci status = parse_sort(entry, &pat); 2561cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS && status != ARES_ENOTFOUND) { 2571cb0ef41Sopenharmony_ci goto done; 2581cb0ef41Sopenharmony_ci } 2591cb0ef41Sopenharmony_ci 2601cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 2611cb0ef41Sopenharmony_ci continue; 2621cb0ef41Sopenharmony_ci } 2631cb0ef41Sopenharmony_ci 2641cb0ef41Sopenharmony_ci if (!sortlist_append(sortlist, nsort, &pat)) { 2651cb0ef41Sopenharmony_ci status = ARES_ENOMEM; 2661cb0ef41Sopenharmony_ci goto done; 2671cb0ef41Sopenharmony_ci } 2681cb0ef41Sopenharmony_ci } 2691cb0ef41Sopenharmony_ci 2701cb0ef41Sopenharmony_ci status = ARES_SUCCESS; 2711cb0ef41Sopenharmony_ci 2721cb0ef41Sopenharmony_cidone: 2731cb0ef41Sopenharmony_ci ares__buf_destroy(buf); 2741cb0ef41Sopenharmony_ci ares__llist_destroy(list); 2751cb0ef41Sopenharmony_ci 2761cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 2771cb0ef41Sopenharmony_ci ares_free(*sortlist); 2781cb0ef41Sopenharmony_ci *sortlist = NULL; 2791cb0ef41Sopenharmony_ci *nsort = 0; 2801cb0ef41Sopenharmony_ci } 2811cb0ef41Sopenharmony_ci 2821cb0ef41Sopenharmony_ci return status; 2831cb0ef41Sopenharmony_ci} 2841cb0ef41Sopenharmony_ci 2851cb0ef41Sopenharmony_cistatic ares_status_t config_search(ares_sysconfig_t *sysconfig, const char *str) 2861cb0ef41Sopenharmony_ci{ 2871cb0ef41Sopenharmony_ci if (sysconfig->domains && sysconfig->ndomains > 0) { 2881cb0ef41Sopenharmony_ci /* if we already have some domains present, free them first */ 2891cb0ef41Sopenharmony_ci ares__strsplit_free(sysconfig->domains, sysconfig->ndomains); 2901cb0ef41Sopenharmony_ci sysconfig->domains = NULL; 2911cb0ef41Sopenharmony_ci sysconfig->ndomains = 0; 2921cb0ef41Sopenharmony_ci } 2931cb0ef41Sopenharmony_ci 2941cb0ef41Sopenharmony_ci sysconfig->domains = ares__strsplit(str, ", ", &sysconfig->ndomains); 2951cb0ef41Sopenharmony_ci if (sysconfig->domains == NULL) { 2961cb0ef41Sopenharmony_ci return ARES_ENOMEM; 2971cb0ef41Sopenharmony_ci } 2981cb0ef41Sopenharmony_ci 2991cb0ef41Sopenharmony_ci return ARES_SUCCESS; 3001cb0ef41Sopenharmony_ci} 3011cb0ef41Sopenharmony_ci 3021cb0ef41Sopenharmony_cistatic ares_status_t config_domain(ares_sysconfig_t *sysconfig, char *str) 3031cb0ef41Sopenharmony_ci{ 3041cb0ef41Sopenharmony_ci char *q; 3051cb0ef41Sopenharmony_ci 3061cb0ef41Sopenharmony_ci /* Set a single search domain. */ 3071cb0ef41Sopenharmony_ci q = str; 3081cb0ef41Sopenharmony_ci while (*q && !ISSPACE(*q)) { 3091cb0ef41Sopenharmony_ci q++; 3101cb0ef41Sopenharmony_ci } 3111cb0ef41Sopenharmony_ci *q = '\0'; 3121cb0ef41Sopenharmony_ci 3131cb0ef41Sopenharmony_ci return config_search(sysconfig, str); 3141cb0ef41Sopenharmony_ci} 3151cb0ef41Sopenharmony_ci 3161cb0ef41Sopenharmony_cistatic ares_status_t config_lookup(ares_sysconfig_t *sysconfig, const char *str, 3171cb0ef41Sopenharmony_ci const char *bindch, const char *altbindch, 3181cb0ef41Sopenharmony_ci const char *filech) 3191cb0ef41Sopenharmony_ci{ 3201cb0ef41Sopenharmony_ci char lookups[3]; 3211cb0ef41Sopenharmony_ci char *l; 3221cb0ef41Sopenharmony_ci const char *p; 3231cb0ef41Sopenharmony_ci ares_bool_t found; 3241cb0ef41Sopenharmony_ci 3251cb0ef41Sopenharmony_ci if (altbindch == NULL) { 3261cb0ef41Sopenharmony_ci altbindch = bindch; 3271cb0ef41Sopenharmony_ci } 3281cb0ef41Sopenharmony_ci 3291cb0ef41Sopenharmony_ci /* Set the lookup order. Only the first letter of each work 3301cb0ef41Sopenharmony_ci * is relevant, and it has to be "b" for DNS or "f" for the 3311cb0ef41Sopenharmony_ci * host file. Ignore everything else. 3321cb0ef41Sopenharmony_ci */ 3331cb0ef41Sopenharmony_ci l = lookups; 3341cb0ef41Sopenharmony_ci p = str; 3351cb0ef41Sopenharmony_ci found = ARES_FALSE; 3361cb0ef41Sopenharmony_ci while (*p) { 3371cb0ef41Sopenharmony_ci if ((*p == *bindch || *p == *altbindch || *p == *filech) && 3381cb0ef41Sopenharmony_ci l < lookups + 2) { 3391cb0ef41Sopenharmony_ci if (*p == *bindch || *p == *altbindch) { 3401cb0ef41Sopenharmony_ci *l++ = 'b'; 3411cb0ef41Sopenharmony_ci } else { 3421cb0ef41Sopenharmony_ci *l++ = 'f'; 3431cb0ef41Sopenharmony_ci } 3441cb0ef41Sopenharmony_ci found = ARES_TRUE; 3451cb0ef41Sopenharmony_ci } 3461cb0ef41Sopenharmony_ci while (*p && !ISSPACE(*p) && (*p != ',')) { 3471cb0ef41Sopenharmony_ci p++; 3481cb0ef41Sopenharmony_ci } 3491cb0ef41Sopenharmony_ci while (*p && (ISSPACE(*p) || (*p == ','))) { 3501cb0ef41Sopenharmony_ci p++; 3511cb0ef41Sopenharmony_ci } 3521cb0ef41Sopenharmony_ci } 3531cb0ef41Sopenharmony_ci if (!found) { 3541cb0ef41Sopenharmony_ci return ARES_ENOTINITIALIZED; 3551cb0ef41Sopenharmony_ci } 3561cb0ef41Sopenharmony_ci *l = '\0'; 3571cb0ef41Sopenharmony_ci 3581cb0ef41Sopenharmony_ci ares_free(sysconfig->lookups); 3591cb0ef41Sopenharmony_ci sysconfig->lookups = ares_strdup(lookups); 3601cb0ef41Sopenharmony_ci if (sysconfig->lookups == NULL) { 3611cb0ef41Sopenharmony_ci return ARES_ENOMEM; 3621cb0ef41Sopenharmony_ci } 3631cb0ef41Sopenharmony_ci return ARES_SUCCESS; 3641cb0ef41Sopenharmony_ci} 3651cb0ef41Sopenharmony_ci 3661cb0ef41Sopenharmony_cistatic const char *try_option(const char *p, const char *q, const char *opt) 3671cb0ef41Sopenharmony_ci{ 3681cb0ef41Sopenharmony_ci size_t len = ares_strlen(opt); 3691cb0ef41Sopenharmony_ci return ((size_t)(q - p) >= len && !strncmp(p, opt, len)) ? &p[len] : NULL; 3701cb0ef41Sopenharmony_ci} 3711cb0ef41Sopenharmony_ci 3721cb0ef41Sopenharmony_cistatic ares_status_t set_options(ares_sysconfig_t *sysconfig, const char *str) 3731cb0ef41Sopenharmony_ci{ 3741cb0ef41Sopenharmony_ci const char *p; 3751cb0ef41Sopenharmony_ci const char *q; 3761cb0ef41Sopenharmony_ci const char *val; 3771cb0ef41Sopenharmony_ci 3781cb0ef41Sopenharmony_ci if (str == NULL) { 3791cb0ef41Sopenharmony_ci return ARES_SUCCESS; 3801cb0ef41Sopenharmony_ci } 3811cb0ef41Sopenharmony_ci 3821cb0ef41Sopenharmony_ci p = str; 3831cb0ef41Sopenharmony_ci while (*p) { 3841cb0ef41Sopenharmony_ci q = p; 3851cb0ef41Sopenharmony_ci while (*q && !ISSPACE(*q)) { 3861cb0ef41Sopenharmony_ci q++; 3871cb0ef41Sopenharmony_ci } 3881cb0ef41Sopenharmony_ci val = try_option(p, q, "ndots:"); 3891cb0ef41Sopenharmony_ci if (val) { 3901cb0ef41Sopenharmony_ci sysconfig->ndots = strtoul(val, NULL, 10); 3911cb0ef41Sopenharmony_ci } 3921cb0ef41Sopenharmony_ci 3931cb0ef41Sopenharmony_ci // Outdated option. 3941cb0ef41Sopenharmony_ci val = try_option(p, q, "retrans:"); 3951cb0ef41Sopenharmony_ci if (val) { 3961cb0ef41Sopenharmony_ci sysconfig->timeout_ms = strtoul(val, NULL, 10); 3971cb0ef41Sopenharmony_ci } 3981cb0ef41Sopenharmony_ci 3991cb0ef41Sopenharmony_ci val = try_option(p, q, "timeout:"); 4001cb0ef41Sopenharmony_ci if (val) { 4011cb0ef41Sopenharmony_ci sysconfig->timeout_ms = strtoul(val, NULL, 10) * 1000; 4021cb0ef41Sopenharmony_ci } 4031cb0ef41Sopenharmony_ci 4041cb0ef41Sopenharmony_ci // Outdated option. 4051cb0ef41Sopenharmony_ci val = try_option(p, q, "retry:"); 4061cb0ef41Sopenharmony_ci if (val) { 4071cb0ef41Sopenharmony_ci sysconfig->tries = strtoul(val, NULL, 10); 4081cb0ef41Sopenharmony_ci } 4091cb0ef41Sopenharmony_ci 4101cb0ef41Sopenharmony_ci val = try_option(p, q, "attempts:"); 4111cb0ef41Sopenharmony_ci if (val) { 4121cb0ef41Sopenharmony_ci sysconfig->tries = strtoul(val, NULL, 10); 4131cb0ef41Sopenharmony_ci } 4141cb0ef41Sopenharmony_ci 4151cb0ef41Sopenharmony_ci val = try_option(p, q, "rotate"); 4161cb0ef41Sopenharmony_ci if (val) { 4171cb0ef41Sopenharmony_ci sysconfig->rotate = ARES_TRUE; 4181cb0ef41Sopenharmony_ci } 4191cb0ef41Sopenharmony_ci 4201cb0ef41Sopenharmony_ci p = q; 4211cb0ef41Sopenharmony_ci while (ISSPACE(*p)) { 4221cb0ef41Sopenharmony_ci p++; 4231cb0ef41Sopenharmony_ci } 4241cb0ef41Sopenharmony_ci } 4251cb0ef41Sopenharmony_ci 4261cb0ef41Sopenharmony_ci return ARES_SUCCESS; 4271cb0ef41Sopenharmony_ci} 4281cb0ef41Sopenharmony_ci 4291cb0ef41Sopenharmony_cistatic char *try_config(char *s, const char *opt, char scc) 4301cb0ef41Sopenharmony_ci{ 4311cb0ef41Sopenharmony_ci size_t len; 4321cb0ef41Sopenharmony_ci char *p; 4331cb0ef41Sopenharmony_ci char *q; 4341cb0ef41Sopenharmony_ci 4351cb0ef41Sopenharmony_ci if (!s || !opt) { 4361cb0ef41Sopenharmony_ci /* no line or no option */ 4371cb0ef41Sopenharmony_ci return NULL; /* LCOV_EXCL_LINE */ 4381cb0ef41Sopenharmony_ci } 4391cb0ef41Sopenharmony_ci 4401cb0ef41Sopenharmony_ci /* Hash '#' character is always used as primary comment char, additionally 4411cb0ef41Sopenharmony_ci a not-NUL secondary comment char will be considered when specified. */ 4421cb0ef41Sopenharmony_ci 4431cb0ef41Sopenharmony_ci /* trim line comment */ 4441cb0ef41Sopenharmony_ci p = s; 4451cb0ef41Sopenharmony_ci if (scc) { 4461cb0ef41Sopenharmony_ci while (*p && (*p != '#') && (*p != scc)) { 4471cb0ef41Sopenharmony_ci p++; 4481cb0ef41Sopenharmony_ci } 4491cb0ef41Sopenharmony_ci } else { 4501cb0ef41Sopenharmony_ci while (*p && (*p != '#')) { 4511cb0ef41Sopenharmony_ci p++; 4521cb0ef41Sopenharmony_ci } 4531cb0ef41Sopenharmony_ci } 4541cb0ef41Sopenharmony_ci *p = '\0'; 4551cb0ef41Sopenharmony_ci 4561cb0ef41Sopenharmony_ci /* trim trailing whitespace */ 4571cb0ef41Sopenharmony_ci q = p - 1; 4581cb0ef41Sopenharmony_ci while ((q >= s) && ISSPACE(*q)) { 4591cb0ef41Sopenharmony_ci q--; 4601cb0ef41Sopenharmony_ci } 4611cb0ef41Sopenharmony_ci *++q = '\0'; 4621cb0ef41Sopenharmony_ci 4631cb0ef41Sopenharmony_ci /* skip leading whitespace */ 4641cb0ef41Sopenharmony_ci p = s; 4651cb0ef41Sopenharmony_ci while (*p && ISSPACE(*p)) { 4661cb0ef41Sopenharmony_ci p++; 4671cb0ef41Sopenharmony_ci } 4681cb0ef41Sopenharmony_ci 4691cb0ef41Sopenharmony_ci if (!*p) { 4701cb0ef41Sopenharmony_ci /* empty line */ 4711cb0ef41Sopenharmony_ci return NULL; 4721cb0ef41Sopenharmony_ci } 4731cb0ef41Sopenharmony_ci 4741cb0ef41Sopenharmony_ci if ((len = ares_strlen(opt)) == 0) { 4751cb0ef41Sopenharmony_ci /* empty option */ 4761cb0ef41Sopenharmony_ci return NULL; /* LCOV_EXCL_LINE */ 4771cb0ef41Sopenharmony_ci } 4781cb0ef41Sopenharmony_ci 4791cb0ef41Sopenharmony_ci if (strncmp(p, opt, len) != 0) { 4801cb0ef41Sopenharmony_ci /* line and option do not match */ 4811cb0ef41Sopenharmony_ci return NULL; 4821cb0ef41Sopenharmony_ci } 4831cb0ef41Sopenharmony_ci 4841cb0ef41Sopenharmony_ci /* skip over given option name */ 4851cb0ef41Sopenharmony_ci p += len; 4861cb0ef41Sopenharmony_ci 4871cb0ef41Sopenharmony_ci if (!*p) { 4881cb0ef41Sopenharmony_ci /* no option value */ 4891cb0ef41Sopenharmony_ci return NULL; /* LCOV_EXCL_LINE */ 4901cb0ef41Sopenharmony_ci } 4911cb0ef41Sopenharmony_ci 4921cb0ef41Sopenharmony_ci if ((opt[len - 1] != ':') && (opt[len - 1] != '=') && !ISSPACE(*p)) { 4931cb0ef41Sopenharmony_ci /* whitespace between option name and value is mandatory 4941cb0ef41Sopenharmony_ci for given option names which do not end with ':' or '=' */ 4951cb0ef41Sopenharmony_ci return NULL; 4961cb0ef41Sopenharmony_ci } 4971cb0ef41Sopenharmony_ci 4981cb0ef41Sopenharmony_ci /* skip over whitespace */ 4991cb0ef41Sopenharmony_ci while (*p && ISSPACE(*p)) { 5001cb0ef41Sopenharmony_ci p++; 5011cb0ef41Sopenharmony_ci } 5021cb0ef41Sopenharmony_ci 5031cb0ef41Sopenharmony_ci if (!*p) { 5041cb0ef41Sopenharmony_ci /* no option value */ 5051cb0ef41Sopenharmony_ci return NULL; 5061cb0ef41Sopenharmony_ci } 5071cb0ef41Sopenharmony_ci 5081cb0ef41Sopenharmony_ci /* return pointer to option value */ 5091cb0ef41Sopenharmony_ci return p; 5101cb0ef41Sopenharmony_ci} 5111cb0ef41Sopenharmony_ci 5121cb0ef41Sopenharmony_ciares_status_t ares__init_by_environment(ares_sysconfig_t *sysconfig) 5131cb0ef41Sopenharmony_ci{ 5141cb0ef41Sopenharmony_ci const char *localdomain; 5151cb0ef41Sopenharmony_ci const char *res_options; 5161cb0ef41Sopenharmony_ci ares_status_t status; 5171cb0ef41Sopenharmony_ci 5181cb0ef41Sopenharmony_ci localdomain = getenv("LOCALDOMAIN"); 5191cb0ef41Sopenharmony_ci if (localdomain) { 5201cb0ef41Sopenharmony_ci char *temp = ares_strdup(localdomain); 5211cb0ef41Sopenharmony_ci if (temp == NULL) { 5221cb0ef41Sopenharmony_ci return ARES_ENOMEM; 5231cb0ef41Sopenharmony_ci } 5241cb0ef41Sopenharmony_ci status = config_domain(sysconfig, temp); 5251cb0ef41Sopenharmony_ci ares_free(temp); 5261cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 5271cb0ef41Sopenharmony_ci return status; 5281cb0ef41Sopenharmony_ci } 5291cb0ef41Sopenharmony_ci } 5301cb0ef41Sopenharmony_ci 5311cb0ef41Sopenharmony_ci res_options = getenv("RES_OPTIONS"); 5321cb0ef41Sopenharmony_ci if (res_options) { 5331cb0ef41Sopenharmony_ci status = set_options(sysconfig, res_options); 5341cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 5351cb0ef41Sopenharmony_ci return status; 5361cb0ef41Sopenharmony_ci } 5371cb0ef41Sopenharmony_ci } 5381cb0ef41Sopenharmony_ci 5391cb0ef41Sopenharmony_ci return ARES_SUCCESS; 5401cb0ef41Sopenharmony_ci} 5411cb0ef41Sopenharmony_ci 5421cb0ef41Sopenharmony_ciares_status_t ares__init_sysconfig_files(const ares_channel_t *channel, 5431cb0ef41Sopenharmony_ci ares_sysconfig_t *sysconfig) 5441cb0ef41Sopenharmony_ci{ 5451cb0ef41Sopenharmony_ci char *p; 5461cb0ef41Sopenharmony_ci FILE *fp = NULL; 5471cb0ef41Sopenharmony_ci char *line = NULL; 5481cb0ef41Sopenharmony_ci size_t linesize = 0; 5491cb0ef41Sopenharmony_ci int error; 5501cb0ef41Sopenharmony_ci const char *resolvconf_path; 5511cb0ef41Sopenharmony_ci ares_status_t status = ARES_SUCCESS; 5521cb0ef41Sopenharmony_ci 5531cb0ef41Sopenharmony_ci /* Support path for resolvconf filename set by ares_init_options */ 5541cb0ef41Sopenharmony_ci if (channel->resolvconf_path) { 5551cb0ef41Sopenharmony_ci resolvconf_path = channel->resolvconf_path; 5561cb0ef41Sopenharmony_ci } else { 5571cb0ef41Sopenharmony_ci resolvconf_path = PATH_RESOLV_CONF; 5581cb0ef41Sopenharmony_ci } 5591cb0ef41Sopenharmony_ci 5601cb0ef41Sopenharmony_ci fp = fopen(resolvconf_path, "r"); 5611cb0ef41Sopenharmony_ci if (fp) { 5621cb0ef41Sopenharmony_ci while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS) { 5631cb0ef41Sopenharmony_ci if ((p = try_config(line, "domain", ';'))) { 5641cb0ef41Sopenharmony_ci status = config_domain(sysconfig, p); 5651cb0ef41Sopenharmony_ci } else if ((p = try_config(line, "lookup", ';'))) { 5661cb0ef41Sopenharmony_ci status = config_lookup(sysconfig, p, "bind", NULL, "file"); 5671cb0ef41Sopenharmony_ci } else if ((p = try_config(line, "search", ';'))) { 5681cb0ef41Sopenharmony_ci status = config_search(sysconfig, p); 5691cb0ef41Sopenharmony_ci } else if ((p = try_config(line, "nameserver", ';'))) { 5701cb0ef41Sopenharmony_ci status = 5711cb0ef41Sopenharmony_ci ares__sconfig_append_fromstr(&sysconfig->sconfig, p, ARES_TRUE); 5721cb0ef41Sopenharmony_ci } else if ((p = try_config(line, "sortlist", ';'))) { 5731cb0ef41Sopenharmony_ci /* Ignore all failures except ENOMEM. If the sysadmin set a bad 5741cb0ef41Sopenharmony_ci * sortlist, just ignore the sortlist, don't cause an inoperable 5751cb0ef41Sopenharmony_ci * channel */ 5761cb0ef41Sopenharmony_ci status = 5771cb0ef41Sopenharmony_ci ares__parse_sortlist(&sysconfig->sortlist, &sysconfig->nsortlist, p); 5781cb0ef41Sopenharmony_ci if (status != ARES_ENOMEM) { 5791cb0ef41Sopenharmony_ci status = ARES_SUCCESS; 5801cb0ef41Sopenharmony_ci } 5811cb0ef41Sopenharmony_ci } else if ((p = try_config(line, "options", ';'))) { 5821cb0ef41Sopenharmony_ci status = set_options(sysconfig, p); 5831cb0ef41Sopenharmony_ci } else { 5841cb0ef41Sopenharmony_ci status = ARES_SUCCESS; 5851cb0ef41Sopenharmony_ci } 5861cb0ef41Sopenharmony_ci if (status != ARES_SUCCESS) { 5871cb0ef41Sopenharmony_ci fclose(fp); 5881cb0ef41Sopenharmony_ci goto done; 5891cb0ef41Sopenharmony_ci } 5901cb0ef41Sopenharmony_ci } 5911cb0ef41Sopenharmony_ci fclose(fp); 5921cb0ef41Sopenharmony_ci 5931cb0ef41Sopenharmony_ci if (status != ARES_EOF) { 5941cb0ef41Sopenharmony_ci goto done; 5951cb0ef41Sopenharmony_ci } 5961cb0ef41Sopenharmony_ci } else { 5971cb0ef41Sopenharmony_ci error = ERRNO; 5981cb0ef41Sopenharmony_ci switch (error) { 5991cb0ef41Sopenharmony_ci case ENOENT: 6001cb0ef41Sopenharmony_ci case ESRCH: 6011cb0ef41Sopenharmony_ci break; 6021cb0ef41Sopenharmony_ci default: 6031cb0ef41Sopenharmony_ci DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", error, 6041cb0ef41Sopenharmony_ci strerror(error))); 6051cb0ef41Sopenharmony_ci DEBUGF(fprintf(stderr, "Error opening file: %s\n", PATH_RESOLV_CONF)); 6061cb0ef41Sopenharmony_ci status = ARES_EFILE; 6071cb0ef41Sopenharmony_ci goto done; 6081cb0ef41Sopenharmony_ci } 6091cb0ef41Sopenharmony_ci } 6101cb0ef41Sopenharmony_ci 6111cb0ef41Sopenharmony_ci 6121cb0ef41Sopenharmony_ci /* Many systems (Solaris, Linux, BSD's) use nsswitch.conf */ 6131cb0ef41Sopenharmony_ci fp = fopen("/etc/nsswitch.conf", "r"); 6141cb0ef41Sopenharmony_ci if (fp) { 6151cb0ef41Sopenharmony_ci while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS) { 6161cb0ef41Sopenharmony_ci if ((p = try_config(line, "hosts:", '\0'))) { 6171cb0ef41Sopenharmony_ci (void)config_lookup(sysconfig, p, "dns", "resolve", "files"); 6181cb0ef41Sopenharmony_ci } 6191cb0ef41Sopenharmony_ci } 6201cb0ef41Sopenharmony_ci fclose(fp); 6211cb0ef41Sopenharmony_ci if (status != ARES_EOF) { 6221cb0ef41Sopenharmony_ci goto done; 6231cb0ef41Sopenharmony_ci } 6241cb0ef41Sopenharmony_ci } else { 6251cb0ef41Sopenharmony_ci error = ERRNO; 6261cb0ef41Sopenharmony_ci switch (error) { 6271cb0ef41Sopenharmony_ci case ENOENT: 6281cb0ef41Sopenharmony_ci case ESRCH: 6291cb0ef41Sopenharmony_ci break; 6301cb0ef41Sopenharmony_ci default: 6311cb0ef41Sopenharmony_ci DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", error, 6321cb0ef41Sopenharmony_ci strerror(error))); 6331cb0ef41Sopenharmony_ci DEBUGF( 6341cb0ef41Sopenharmony_ci fprintf(stderr, "Error opening file: %s\n", "/etc/nsswitch.conf")); 6351cb0ef41Sopenharmony_ci break; 6361cb0ef41Sopenharmony_ci } 6371cb0ef41Sopenharmony_ci /* ignore error, maybe we will get luck in next if clause */ 6381cb0ef41Sopenharmony_ci } 6391cb0ef41Sopenharmony_ci 6401cb0ef41Sopenharmony_ci 6411cb0ef41Sopenharmony_ci /* Linux / GNU libc 2.x and possibly others have host.conf */ 6421cb0ef41Sopenharmony_ci fp = fopen("/etc/host.conf", "r"); 6431cb0ef41Sopenharmony_ci if (fp) { 6441cb0ef41Sopenharmony_ci while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS) { 6451cb0ef41Sopenharmony_ci if ((p = try_config(line, "order", '\0'))) { 6461cb0ef41Sopenharmony_ci /* ignore errors */ 6471cb0ef41Sopenharmony_ci (void)config_lookup(sysconfig, p, "bind", NULL, "hosts"); 6481cb0ef41Sopenharmony_ci } 6491cb0ef41Sopenharmony_ci } 6501cb0ef41Sopenharmony_ci fclose(fp); 6511cb0ef41Sopenharmony_ci if (status != ARES_EOF) { 6521cb0ef41Sopenharmony_ci goto done; 6531cb0ef41Sopenharmony_ci } 6541cb0ef41Sopenharmony_ci } else { 6551cb0ef41Sopenharmony_ci error = ERRNO; 6561cb0ef41Sopenharmony_ci switch (error) { 6571cb0ef41Sopenharmony_ci case ENOENT: 6581cb0ef41Sopenharmony_ci case ESRCH: 6591cb0ef41Sopenharmony_ci break; 6601cb0ef41Sopenharmony_ci default: 6611cb0ef41Sopenharmony_ci DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", error, 6621cb0ef41Sopenharmony_ci strerror(error))); 6631cb0ef41Sopenharmony_ci DEBUGF(fprintf(stderr, "Error opening file: %s\n", "/etc/host.conf")); 6641cb0ef41Sopenharmony_ci break; 6651cb0ef41Sopenharmony_ci } 6661cb0ef41Sopenharmony_ci 6671cb0ef41Sopenharmony_ci /* ignore error, maybe we will get luck in next if clause */ 6681cb0ef41Sopenharmony_ci } 6691cb0ef41Sopenharmony_ci 6701cb0ef41Sopenharmony_ci 6711cb0ef41Sopenharmony_ci /* Tru64 uses /etc/svc.conf */ 6721cb0ef41Sopenharmony_ci fp = fopen("/etc/svc.conf", "r"); 6731cb0ef41Sopenharmony_ci if (fp) { 6741cb0ef41Sopenharmony_ci while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS) { 6751cb0ef41Sopenharmony_ci if ((p = try_config(line, "hosts=", '\0'))) { 6761cb0ef41Sopenharmony_ci /* ignore errors */ 6771cb0ef41Sopenharmony_ci (void)config_lookup(sysconfig, p, "bind", NULL, "local"); 6781cb0ef41Sopenharmony_ci } 6791cb0ef41Sopenharmony_ci } 6801cb0ef41Sopenharmony_ci fclose(fp); 6811cb0ef41Sopenharmony_ci if (status != ARES_EOF) { 6821cb0ef41Sopenharmony_ci goto done; 6831cb0ef41Sopenharmony_ci } 6841cb0ef41Sopenharmony_ci } else { 6851cb0ef41Sopenharmony_ci error = ERRNO; 6861cb0ef41Sopenharmony_ci switch (error) { 6871cb0ef41Sopenharmony_ci case ENOENT: 6881cb0ef41Sopenharmony_ci case ESRCH: 6891cb0ef41Sopenharmony_ci break; 6901cb0ef41Sopenharmony_ci default: 6911cb0ef41Sopenharmony_ci DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", error, 6921cb0ef41Sopenharmony_ci strerror(error))); 6931cb0ef41Sopenharmony_ci DEBUGF(fprintf(stderr, "Error opening file: %s\n", "/etc/svc.conf")); 6941cb0ef41Sopenharmony_ci break; 6951cb0ef41Sopenharmony_ci } 6961cb0ef41Sopenharmony_ci /* ignore error */ 6971cb0ef41Sopenharmony_ci } 6981cb0ef41Sopenharmony_ci 6991cb0ef41Sopenharmony_ci status = ARES_SUCCESS; 7001cb0ef41Sopenharmony_ci 7011cb0ef41Sopenharmony_cidone: 7021cb0ef41Sopenharmony_ci ares_free(line); 7031cb0ef41Sopenharmony_ci 7041cb0ef41Sopenharmony_ci return status; 7051cb0ef41Sopenharmony_ci} 706