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 <dlfcn.h>
22 #include "lookup.h"
23
24 #if OHOS_DNS_PROXY_BY_NETSYS
25
26 #include "atomic.h"
27
28 #define GETADDRINFO_PRINT_DEBUG(...)
29 #define MAX_SOCKET_ADDR_LEN sizeof(aligned_sockAddr)
30
load_cache_getter(void)31 static GetCache load_cache_getter(void)
32 {
33 static GetCache cache_getter = NULL;
34 resolve_dns_sym((void **) &cache_getter, OHOS_GET_CACHE_FUNC_NAME);
35 return cache_getter;
36 }
37
load_cache_setter(void)38 static SetCache load_cache_setter(void)
39 {
40 static SetCache cache_setter = NULL;
41 resolve_dns_sym((void **) &cache_setter, OHOS_SET_CACHE_FUNC_NAME);
42 return cache_setter;
43 }
44
load_result_poster(void)45 static PostDnsResult load_result_poster(void)
46 {
47 static PostDnsResult result_poster = NULL;
48 resolve_dns_sym((void **) &result_poster, OHOS_POST_DNS_RESULT_FUNC_NAME);
49 return result_poster;
50 }
51
52 void
dns_set_addr_info_to_netsys_cache2(const int netid,const char * restrict host,const char * restrict serv,const struct addrinfo * restrict hint,struct addrinfo * res)53 dns_set_addr_info_to_netsys_cache2(const int netid, const char *restrict host, const char *restrict serv,
54 const struct addrinfo *restrict hint, struct addrinfo *res)
55 {
56 SetCache func = load_cache_setter();
57 if (!func) {
58 DNS_CONFIG_PRINT("%s: loading %s failed", __func__, OHOS_SET_CACHE_FUNC_NAME);
59 return;
60 }
61
62 struct param_wrapper param = {(char *) host, (char *) serv, (struct addrinfo *) hint};
63 int ret = func(netid, param, res);
64 if (ret < 0) {
65 GETADDRINFO_PRINT_DEBUG("dns_set_addr_info_to_netsys_cache OHOS_SET_CACHE_FUNC_NAME err %d\n", ret);
66 return;
67 }
68
69 GETADDRINFO_PRINT_DEBUG("set to netsys cache OK\n");
70 }
71
dns_set_addr_info_to_netsys_cache(const char * restrict host,const char * restrict serv,const struct addrinfo * restrict hint,struct addrinfo * res)72 void dns_set_addr_info_to_netsys_cache(const char *restrict host, const char *restrict serv,
73 const struct addrinfo *restrict hint, struct addrinfo *res)
74 {
75 dns_set_addr_info_to_netsys_cache2(0, host, serv, hint, res);
76 }
77
dns_get_addr_info_from_netsys_cache2(const int netid,const char * restrict host,const char * restrict serv,const struct addrinfo * restrict hint,struct addrinfo ** restrict res)78 int dns_get_addr_info_from_netsys_cache2(const int netid, const char *restrict host, const char *restrict serv,
79 const struct addrinfo *restrict hint, struct addrinfo **restrict res)
80 {
81 GetCache func = load_cache_getter();
82 if (!func) {
83 DNS_CONFIG_PRINT("%s: loading %s failed", __func__, OHOS_GET_CACHE_FUNC_NAME);
84 return -1;
85 }
86
87 struct addr_info_wrapper addr_info[MAX_RESULTS] = {0};
88 uint32_t num = 0;
89 struct param_wrapper param = {(char *) host, (char *) serv, (struct addrinfo *) hint};
90 int ret = func(netid, param, addr_info, &num);
91 if (ret < 0) {
92 GETADDRINFO_PRINT_DEBUG("dns_get_addr_info_from_netsys_cache OHOS_GET_CACHE_FUNC_NAME err %d\n", ret);
93 return -1;
94 }
95
96 num = MACRO_MIN(num, MACRO_MIN(MAX_RESULTS, MAXADDRS));
97 if (num == 0) {
98 GETADDRINFO_PRINT_DEBUG("dns_get_addr_info_from_netsys_cache num is invalid err %u", num);
99 return -1;
100 }
101
102 int canon_len = (int) strlen(addr_info[0].ai_canonName);
103 struct aibuf *out = calloc(1, num * sizeof(*out) + canon_len + 1);
104 if (!out) {
105 return -1;
106 }
107 char *outcanon = NULL;
108 if (canon_len) {
109 outcanon = (char *) &out[num];
110 memcpy(outcanon, addr_info[0].ai_canonName, canon_len + 1);
111 }
112
113 for (int i = 0; i < num; i++) {
114 out[i].slot = (short) i;
115 if (addr_info[i].ai_addrLen > MAX_SOCKET_ADDR_LEN) {
116 #ifndef __LITEOS__
117 MUSL_LOGE("%{public}s: %{public}d: ai_addrLen illegal, len = %{public}d",
118 __func__, __LINE__, addr_info[i].ai_addrLen);
119 #endif
120 addr_info[i].ai_addrLen = ((addr_info[i].ai_family == AF_INET)
121 ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6));
122 }
123 out[i].ai = (struct addrinfo) {
124 .ai_flags = (int) addr_info[i].ai_flags,
125 .ai_family = (int) addr_info[i].ai_family,
126 .ai_socktype = (int) addr_info[i].ai_sockType,
127 .ai_protocol = (int) addr_info[i].ai_protocol,
128 .ai_addrlen = (socklen_t) addr_info[i].ai_addrLen,
129 .ai_addr = (void *) &out[i].sa,
130 .ai_canonname = outcanon,
131 };
132 memcpy(&out[i].sa, &addr_info[i].ai_addr, addr_info[i].ai_addrLen);
133 if (i > 0) {
134 out[i - 1].ai.ai_next = &out[i].ai;
135 }
136 }
137
138 out[0].ref = (short) num;
139 *res = &out->ai;
140
141 GETADDRINFO_PRINT_DEBUG("dns_get_addr_info_from_netsys_cache end\n");
142 return 0;
143 }
144
dns_get_addr_info_from_netsys_cache(const char * restrict host,const char * restrict serv,const struct addrinfo * restrict hint,struct addrinfo ** restrict res)145 int dns_get_addr_info_from_netsys_cache(const char *restrict host, const char *restrict serv,
146 const struct addrinfo *restrict hint, struct addrinfo **restrict res)
147 {
148 return dns_get_addr_info_from_netsys_cache2(0, host, serv, hint, res);
149 }
150
dns_post_result_to_netsys_cache(int netid,char * name,int usedtime,int queryret,struct addrinfo * res,struct queryparam * param)151 int dns_post_result_to_netsys_cache(int netid, char* name, int usedtime, int queryret,
152 struct addrinfo *res, struct queryparam *param)
153 {
154 PostDnsResult func = load_result_poster();
155 if (!func) {
156 GETADDRINFO_PRINT_DEBUG("%s: loading %s failed", __func__, OHOS_POST_DNS_RESULT_FUNC_NAME);
157 return -1;
158 }
159
160 int ret = func(netid, name, usedtime, queryret, res, param);
161 if (ret < 0) {
162 GETADDRINFO_PRINT_DEBUG("dns_set_result_to_netsys_cache OHOS_POST_DNS_RESULT_FUNC_NAME err %d\n", ret);
163 return -1;
164 }
165
166 GETADDRINFO_PRINT_DEBUG("dns_post_result_to_netsys_cache OK\n");
167 return 0;
168 }
169
dns_get_default_network(int * currentnetid)170 int dns_get_default_network(int *currentnetid)
171 {
172 void *handle = dlopen(DNS_SO_PATH, RTLD_LAZY);
173 if (handle == NULL) {
174 GETADDRINFO_PRINT_DEBUG("dns_get_addr_info_from_netsys_cache dlopen err %s\n", dlerror());
175 return -1;
176 }
177
178 GetDefaultNet func = dlsym(handle, OHOS_GET_DEFAULT_NET_FUNC_NAME);
179 if (func == NULL) {
180 GETADDRINFO_PRINT_DEBUG("dns_get_addr_info_from_netsys_cache dlsym err %s\n", dlerror());
181 dlclose(handle);
182 return -1;
183 }
184
185 int ret = func(0, currentnetid);
186 dlclose(handle);
187
188 if (ret < 0) {
189 GETADDRINFO_PRINT_DEBUG("dns_get_addr_info_from_netsys_cache OHOS_GET_DEFAULT_NET_FUNC_NAME err %d\n", ret);
190 return -1;
191 }
192
193 GETADDRINFO_PRINT_DEBUG("dns_post_result_to_netsys_cache OK %d\n", currentnetid);
194 return 0;
195 }
196
197 #endif
198