1 /*
2 * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <stdlib.h>
17 #include <sys/socket.h>
18 #include <netinet/in.h>
19 #include <netdb.h>
20 #include <string.h>
21 #include "lookup.h"
22 #include <dlfcn.h>
23
24 #if OHOS_DNS_PROXY_BY_NETSYS
25
26 #include "atomic.h"
27
load_cache_getter(void)28 static GetCache load_cache_getter(void)
29 {
30 static GetCache cache_getter = NULL;
31 resolve_dns_sym((void **) &cache_getter, OHOS_GET_CACHE_FUNC_NAME);
32 return cache_getter;
33 }
34
load_cache_setter(void)35 static SetCache load_cache_setter(void)
36 {
37 static SetCache cache_setter = NULL;
38 resolve_dns_sym((void **) &cache_setter, OHOS_SET_CACHE_FUNC_NAME);
39 return cache_setter;
40 }
41
42 void
dns_set_addr_info_to_netsys_cache(const char * restrict host,const char * restrict serv,const struct addrinfo * restrict hint,struct addrinfo * res)43 dns_set_addr_info_to_netsys_cache(const char *restrict host, const char *restrict serv, const struct addrinfo *restrict
44 hint, struct addrinfo *res) {
45 SetCache func = load_cache_setter();
46 if (!func) {
47 DNS_CONFIG_PRINT("%s: loading %s failed", __func__, OHOS_SET_CACHE_FUNC_NAME);
48 return;
49 }
50
51 struct param_wrapper param = {(char *) host, (char *) serv, (struct addrinfo *) hint};
52 int ret = func(0, param, res);
53 if (ret < 0) {
54 DNS_CONFIG_PRINT("dns_set_addr_info_to_netsys_cache OHOS_SET_CACHE_FUNC_NAME err %d\n", ret);
55 return;
56 }
57
58 DNS_CONFIG_PRINT("set to netsys cache OK\n");
59 }
60
dns_get_addr_info_from_netsys_cache(const char * restrict host,const char * restrict serv,const struct addrinfo * restrict hint,struct addrinfo ** restrict res)61 int dns_get_addr_info_from_netsys_cache(const char *restrict host, const char *restrict serv,
62 const struct addrinfo *restrict hint, struct addrinfo **restrict res) {
63 GetCache func = load_cache_getter();
64 if (!func) {
65 DNS_CONFIG_PRINT("%s: loading %s failed", __func__, OHOS_GET_CACHE_FUNC_NAME);
66 return -1;
67 }
68
69 struct addr_info_wrapper addr_info[MAX_RESULTS] = {0};
70 uint32_t num = 0;
71 struct param_wrapper param = {(char *) host, (char *) serv, (struct addrinfo *) hint};
72 int ret = func(0, param, addr_info, &num);
73 if (ret < 0) {
74 DNS_CONFIG_PRINT("dns_get_addr_info_from_netsys_cache OHOS_GET_CACHE_FUNC_NAME err %d\n", ret);
75 return -1;
76 }
77
78 num = MACRO_MIN(num, MACRO_MIN(MAX_RESULTS, MAXADDRS));
79 if (num == 0) {
80 DNS_CONFIG_PRINT("dns_get_addr_info_from_netsys_cache num is invalid err %u", num);
81 return -1;
82 }
83
84 int canon_len = (int) strlen(addr_info[0].ai_canonName);
85 struct aibuf *out = calloc(1, num * sizeof(*out) + canon_len + 1);
86 if (!out) {
87 return -1;
88 }
89 char *outcanon = NULL;
90 if (canon_len) {
91 outcanon = (char *) &out[num];
92 memcpy(outcanon, addr_info[0].ai_canonName, canon_len + 1);
93 }
94
95 for (int i = 0; i < num; i++) {
96 out[i].slot = (short) i;
97 out[i].ai = (struct addrinfo) {
98 .ai_flags = (int) addr_info[i].ai_flags,
99 .ai_family = (int) addr_info[i].ai_family,
100 .ai_socktype = (int) addr_info[i].ai_sockType,
101 .ai_protocol = (int) addr_info[i].ai_protocol,
102 .ai_addrlen = (socklen_t) addr_info[i].ai_addrLen,
103 .ai_addr = (void *) &out[i].sa,
104 .ai_canonname = outcanon,
105 };
106 memcpy(&out[i].sa, &addr_info[i].ai_addr, addr_info[i].ai_addrLen);
107 if (i > 0) {
108 out[i - 1].ai.ai_next = &out[i].ai;
109 }
110 }
111
112 out[0].ref = (short) num;
113 *res = &out->ai;
114
115 DNS_CONFIG_PRINT("dns_get_addr_info_from_netsys_cache end\n");
116 return 0;
117 }
118
119 #endif
120