diff --git a/musl_src.gni b/musl_src.gni index 549b09b5e7026a19e4336b4428bb19c88db1cc8e..6afa254538179bbbd1c0cd8499c862141d1ff42c 100644 --- a/musl_src.gni +++ b/musl_src.gni @@ -834,6 +834,7 @@ musl_src_file = [ "src/network/recvfrom.c", "src/network/recvmmsg.c", "src/network/recvmsg.c", + "src/network/res_cache.c", "src/network/res_init.c", "src/network/res_mkquery.c", "src/network/res_msend.c", diff --git a/musl_template.gni b/musl_template.gni index 88cf29a113b299b19f6ec954e79c9ecd8dcf54c8..6d5c1e73a501e732b80e628bd28e2804cb7f5628 100644 --- a/musl_template.gni +++ b/musl_template.gni @@ -177,8 +177,12 @@ template("musl_libs") { cflags = cflags_all + defines = [] if ("${target_abi}" != "a7_hard_neon-vfpv4") { - defines = [ "BROKEN_VFP_ASM" ] + defines += [ "BROKEN_VFP_ASM" ] + } + if (is_standard_system) { + defines += [ "OHOS_DNS_PROXY_BY_NETSYS=1" ] } dynamic_list = diff --git a/src/network/freeaddrinfo.c b/src/network/freeaddrinfo.c index 62241c239e27f8e09a4a437a104f595f69c16255..3b6f833752b5aff7f727bb13457da7d594960769 100644 --- a/src/network/freeaddrinfo.c +++ b/src/network/freeaddrinfo.c @@ -6,10 +6,12 @@ void freeaddrinfo(struct addrinfo *p) { + if (!p) { + return; + } size_t cnt; - for (cnt=1; p->ai_next; cnt++, p=p->ai_next); struct aibuf *b = (void *)((char *)p - offsetof(struct aibuf, ai)); - b -= b->slot; + for (cnt=1; p->ai_next; cnt++, p=p->ai_next); LOCK(b->lock); if (!(b->ref -= cnt)) free(b); else UNLOCK(b->lock); diff --git a/src/network/getaddrinfo.c b/src/network/getaddrinfo.c index efaab306828e847deecbb26751dc7cb8a4c90e2e..0d0a6222d7bf29030a39eb5be29c89b68e6ebec9 100644 --- a/src/network/getaddrinfo.c +++ b/src/network/getaddrinfo.c @@ -11,6 +11,13 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const struct addrinfo *restrict hint, struct addrinfo **restrict res) { +#if OHOS_DNS_PROXY_BY_NETSYS + if (dns_get_addr_info_from_netsys_cache(host, serv, hint, res) == 0) { + DNS_CONFIG_PRINT("get from netsys cache OK\n"); + return 0; + } +#endif + struct service ports[MAXSERVS]; struct address addrs[MAXADDRS]; char canon[256], *outcanon; @@ -131,5 +138,8 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru } out[0].ref = nais; *res = &out->ai; +#if OHOS_DNS_PROXY_BY_NETSYS + dns_set_addr_info_to_netsys_cache(host, serv, hint, *res); +#endif return 0; } diff --git a/src/network/lookup.h b/src/network/lookup.h index ef6627256756abc3eb50850183c095e99f7fe430..0cc196492230f74d6a7784c72750093156751ce9 100644 --- a/src/network/lookup.h +++ b/src/network/lookup.h @@ -7,6 +7,19 @@ #include #include +#if OHOS_DNS_PROXY_BY_NETSYS + +#include + +#if DNS_CONFIG_DEBUG +#ifndef DNS_CONFIG_PRINT +#define DNS_CONFIG_PRINT(fmt, ...) printf("DNS " fmt "\n", ##__VA_ARGS__) +#endif +#else +#define DNS_CONFIG_PRINT(fmt, ...) +#endif +#endif + struct aibuf { struct addrinfo ai; union sa { @@ -52,4 +65,62 @@ hidden int __res_msend_rc(int, const unsigned char *const *, const int *, unsign hidden int __dns_parse(const unsigned char *, int, int (*)(void *, int, const void *, int, const void *), void *); +#if OHOS_DNS_PROXY_BY_NETSYS +#define DNS_SO_PATH "libnetsys_client.z.so" +#define MAX_SERVER_NUM 4 +#define MAX_SERVER_LENGTH 50 +#define OHOS_GET_CONFIG_FUNC_NAME "NetSysGetResolvConf" +#define OHOS_GET_CACHE_FUNC_NAME "NetSysGetResolvCache" +#define OHOS_SET_CACHE_FUNC_NAME "NetSysSetResolvCache" +#define MAX_RESULTS 32 +#define MAX_CANON_NAME 256 +#define MACRO_MIN(a, b) ((a) < (b) ? (a) : (b)) + +struct resolv_config { + int32_t error; + int32_t timeout_ms; + uint32_t retry_count; + char nameservers[MAX_SERVER_NUM][MAX_SERVER_LENGTH + 1]; +}; + +typedef union { + struct sockaddr sa; + struct sockaddr_in6 sin6; + struct sockaddr_in sin; +} aligned_sockAddr; + +struct addr_info_wrapper { + uint32_t ai_flags; + uint32_t ai_family; + uint32_t ai_sockType; + uint32_t ai_protocol; + uint32_t ai_addrLen; + aligned_sockAddr ai_addr; + char ai_canonName[MAX_CANON_NAME + 1]; +}; + +struct param_wrapper { + char *host; + char *serv; + struct addrinfo *hint; +}; + +typedef int32_t (*GetConfig)(uint16_t netId, struct resolv_config *config); + +typedef int32_t (*GetCache)(uint16_t netId, struct param_wrapper param, + struct addr_info_wrapper addr_info[static MAX_RESULTS], + uint32_t *num); + +typedef int32_t (*SetCache)(uint16_t netId, struct param_wrapper param, struct addrinfo *res); + +void +dns_set_addr_info_to_netsys_cache(const char *__restrict host, const char *__restrict serv, + const struct addrinfo *__restrict + hint, struct addrinfo *res); + +int dns_get_addr_info_from_netsys_cache(const char *__restrict host, const char *__restrict serv, + const struct addrinfo *__restrict hint, struct addrinfo **__restrict res); + +#endif + #endif diff --git a/src/network/res_cache.c b/src/network/res_cache.c new file mode 100644 index 0000000000000000000000000000000000000000..9e7da348fbab0b7aa49adb59a04903379d1c8a08 --- /dev/null +++ b/src/network/res_cache.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include "lookup.h" +#include + +#if OHOS_DNS_PROXY_BY_NETSYS + +void +dns_set_addr_info_to_netsys_cache(const char *restrict host, const char *restrict serv, const struct addrinfo *restrict +hint, struct addrinfo *res) { + void *handle = dlopen(DNS_SO_PATH, RTLD_LAZY); + if (handle == NULL) { + DNS_CONFIG_PRINT("dns_set_addr_info_to_netsys_cache dlopen err %s\n", dlerror()); + return; + } + + SetCache func = dlsym(handle, OHOS_SET_CACHE_FUNC_NAME); + if (func == NULL) { + DNS_CONFIG_PRINT("dns_set_addr_info_to_netsys_cache dlsym err %s\n", dlerror()); + dlclose(handle); + return; + } + + struct param_wrapper param = {(char *) host, (char *) serv, (struct addrinfo *) hint}; + int ret = func(0, param, res); + dlclose(handle); + if (ret < 0) { + DNS_CONFIG_PRINT("dns_set_addr_info_to_netsys_cache OHOS_SET_CACHE_FUNC_NAME err %d\n", ret); + return; + } + + DNS_CONFIG_PRINT("set to netsys cache OK\n"); +} + +int dns_get_addr_info_from_netsys_cache(const char *restrict host, const char *restrict serv, + const struct addrinfo *restrict hint, struct addrinfo **restrict res) { + void *handle = dlopen(DNS_SO_PATH, RTLD_LAZY); + if (handle == NULL) { + DNS_CONFIG_PRINT("dns_get_addr_info_from_netsys_cache dlopen err %s\n", dlerror()); + return -1; + } + + GetCache func = dlsym(handle, OHOS_GET_CACHE_FUNC_NAME); + if (func == NULL) { + DNS_CONFIG_PRINT("dns_get_addr_info_from_netsys_cache dlsym err %s\n", dlerror()); + dlclose(handle); + return -1; + } + + struct addr_info_wrapper addr_info[MAX_RESULTS] = {0}; + uint32_t num = 0; + struct param_wrapper param = {(char *) host, (char *) serv, (struct addrinfo *) hint}; + int ret = func(0, param, addr_info, &num); + dlclose(handle); + if (ret < 0) { + DNS_CONFIG_PRINT("dns_get_addr_info_from_netsys_cache OHOS_GET_CACHE_FUNC_NAME err %d\n", ret); + return -1; + } + + num = MACRO_MIN(num, MACRO_MIN(MAX_RESULTS, MAXADDRS)); + if (num == 0) { + DNS_CONFIG_PRINT("dns_get_addr_info_from_netsys_cache num is invalid err %u", num); + return -1; + } + + int canon_len = (int) strlen(addr_info[0].ai_canonName); + struct aibuf *out = calloc(1, num * sizeof(*out) + canon_len + 1); + if (!out) { + return -1; + } + char *outcanon = NULL; + if (canon_len) { + outcanon = (char *) &out[num]; + memcpy(outcanon, addr_info[0].ai_canonName, canon_len + 1); + } + + for (int i = 0; i < num; i++) { + out[i].slot = (short) i; + out[i].ai = (struct addrinfo) { + .ai_flags = (int) addr_info[i].ai_flags, + .ai_family = (int) addr_info[i].ai_family, + .ai_socktype = (int) addr_info[i].ai_sockType, + .ai_protocol = (int) addr_info[i].ai_protocol, + .ai_addrlen = (socklen_t) addr_info[i].ai_addrLen, + .ai_addr = (void *) &out[i].sa, + .ai_canonname = outcanon, + }; + memcpy(&out[i].sa, &addr_info[i].ai_addr, addr_info[i].ai_addrLen); + if (i > 0) { + out[i - 1].ai.ai_next = &out[i].ai; + } + } + + out[0].ref = (short) num; + *res = &out->ai; + + DNS_CONFIG_PRINT("dns_get_addr_info_from_netsys_cache end\n"); + return 0; +} + +#endif diff --git a/src/network/resolvconf.c b/src/network/resolvconf.c index ceabf0808450b056708129b5b937e413884c5c8c..73de25fa58787afb802a4d7c64f843c75d3213de 100644 --- a/src/network/resolvconf.c +++ b/src/network/resolvconf.c @@ -5,6 +5,9 @@ #include #include #include +#if OHOS_DNS_PROXY_BY_NETSYS +#include +#endif int __get_resolv_conf(struct resolvconf *conf, char *search, size_t search_sz) { @@ -18,6 +21,57 @@ int __get_resolv_conf(struct resolvconf *conf, char *search, size_t search_sz) conf->attempts = 2; if (search) *search = 0; +#if OHOS_DNS_PROXY_BY_NETSYS + void *handle = dlopen(DNS_SO_PATH, RTLD_LAZY); + if (handle == NULL) { + DNS_CONFIG_PRINT("__get_resolv_conf dlopen err %s\n", dlerror()); + goto etc_resolv_conf; + } + + GetConfig func = dlsym(handle, OHOS_GET_CONFIG_FUNC_NAME); + if (func == NULL) { + DNS_CONFIG_PRINT("__get_resolv_conf dlsym err %s\n", dlerror()); + dlclose(handle); + goto etc_resolv_conf; + } + + struct resolv_config config = {0}; + int ret = func(0, &config); + dlclose(handle); + if (ret < 0) { + DNS_CONFIG_PRINT("__get_resolv_conf OHOS_GET_CONFIG_FUNC_NAME err %d\n", ret); + goto etc_resolv_conf; + } + int32_t timeout_second = config.timeout_ms / 1000; +#endif + +#if OHOS_DNS_PROXY_BY_NETSYS +netsys_conf: + if (timeout_second > 0) { + if (timeout_second >= 60) { + conf->timeout = 60; + } else { + conf->timeout = timeout_second; + } + } + if (config.retry_count > 0) { + if (config.retry_count >= 10) { + conf->attempts = 10; + } else { + conf->attempts = config.retry_count; + } + } + for (int i = 0; i < MAX_SERVER_NUM; ++i) { + if (config.nameservers[i] == NULL || config.nameservers[i][0] == 0 || nns >= MAXNS) { + continue; + } + if (__lookup_ipliteral(conf->ns + nns, config.nameservers[i], AF_UNSPEC) > 0) { + nns++; + } + } + +etc_resolv_conf: +#endif f = __fopen_rb_ca("/etc/resolv.conf", &_f, _buf, sizeof _buf); if (!f) switch (errno) { case ENOENT: