1 /*
2 * Copyright (c) 2022 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 "netsys_client.h"
17
18 #include <errno.h>
19 #include <sys/socket.h>
20 #include <sys/time.h>
21
22 #include "dns_config_client.h"
23 #include "netdb.h"
24 #include "securec.h"
25 #include "stdbool.h"
26 #include "sys/select.h"
27 #include "sys/un.h"
28 #include "unistd.h"
29
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33
34 static volatile uint8_t g_allowInternet = 1;
35
DisallowInternet(void)36 void DisallowInternet(void)
37 {
38 g_allowInternet = 0;
39 }
40
IsAllowInternet(void)41 uint8_t IsAllowInternet(void)
42 {
43 return g_allowInternet;
44 }
45
Min(uint32_t a,uint32_t b)46 static inline uint32_t Min(uint32_t a, uint32_t b)
47 {
48 return a < b ? a : b;
49 }
50
CloseSocketReturn(int sock,int ret)51 static inline int CloseSocketReturn(int sock, int ret)
52 {
53 close(sock);
54 return ret;
55 }
56
MakeDefaultDnsServer(char * server,size_t length)57 void MakeDefaultDnsServer(char *server, size_t length)
58 {
59 int ret = memset_s(server, length, 0, DEFAULT_SERVER_LENTH);
60 if (ret < 0) {
61 DNS_CONFIG_PRINT("MakeDefaultDnsServer memset_s failed");
62 return;
63 }
64
65 ret = sprintf_s(server, length, "%d.%d.%d.%d", DEFAULT_SERVER_NAME, DEFAULT_SERVER_NAME, DEFAULT_SERVER_NAME,
66 DEFAULT_SERVER_NAME);
67 if (ret != 0) {
68 DNS_CONFIG_PRINT("MakeDefaultDnsServer sprintf_s failed");
69 }
70 }
71
NonBlockConnect(int sock,struct sockaddr * addr,socklen_t addrLen)72 static bool NonBlockConnect(int sock, struct sockaddr *addr, socklen_t addrLen)
73 {
74 int ret = connect(sock, addr, addrLen);
75 if (ret >= 0) {
76 return true;
77 }
78 if (errno != EINPROGRESS) {
79 return false;
80 }
81
82 fd_set set = {0};
83 FD_ZERO(&set);
84 FD_SET(sock, &set);
85 struct timeval timeout = {
86 .tv_sec = DEFAULT_CONNECT_TIMEOUT,
87 .tv_usec = 0,
88 };
89
90 ret = select(sock + 1, NULL, &set, NULL, &timeout);
91 if (ret < 0) {
92 DNS_CONFIG_PRINT("select error: %s", strerror(errno));
93 return false;
94 } else if (ret == 0) {
95 DNS_CONFIG_PRINT("timeout!");
96 return false;
97 }
98
99 int err = 0;
100 socklen_t optLen = sizeof(err);
101 ret = getsockopt(sock, SOL_SOCKET, SO_ERROR, (void *)(&err), &optLen);
102 if (ret < 0 || err != 0) {
103 return false;
104 }
105 return true;
106 }
107
CreateConnectionToNetSys(void)108 static int CreateConnectionToNetSys(void)
109 {
110 int32_t sockFd = socket(AF_UNIX, SOCK_STREAM, 0);
111 if (sockFd < 0) {
112 DNS_CONFIG_PRINT("socket failed %d", errno);
113 return -errno;
114 }
115 if (!MakeNonBlock(sockFd)) {
116 DNS_CONFIG_PRINT("MakeNonBlock failed");
117 return CloseSocketReturn(sockFd, -errno);
118 }
119
120 struct sockaddr_un address = {0};
121 address.sun_family = AF_UNIX;
122
123 if (strcpy_s(address.sun_path, sizeof(address.sun_path), DNS_SOCKET_PATH) != 0) {
124 DNS_CONFIG_PRINT("str copy failed ");
125 return CloseSocketReturn(sockFd, -1);
126 }
127
128 if (!NonBlockConnect(sockFd, (struct sockaddr *)&address, sizeof(address))) {
129 return CloseSocketReturn(sockFd, -errno);
130 }
131
132 return sockFd;
133 }
134
MakeKey(const char * hostName,const char * serv,const struct addrinfo * hints,char key[static MAX_KEY_LENGTH])135 static bool MakeKey(const char *hostName, const char *serv, const struct addrinfo *hints,
136 char key[static MAX_KEY_LENGTH])
137 {
138 if (serv && hints) {
139 return sprintf_s(key, MAX_KEY_LENGTH, "%s %s %d %d %d %d", hostName, serv, hints->ai_family, hints->ai_flags,
140 hints->ai_protocol, hints->ai_socktype) > 0;
141 }
142
143 if (hints) {
144 return sprintf_s(key, MAX_KEY_LENGTH, "%s %d %d %d %d", hostName, hints->ai_family, hints->ai_flags,
145 hints->ai_protocol, hints->ai_socktype) > 0;
146 }
147
148 if (serv) {
149 return sprintf_s(key, MAX_KEY_LENGTH, "%s %s", hostName, serv) > 0;
150 }
151
152 return sprintf_s(key, MAX_KEY_LENGTH, "%s", hostName) > 0;
153 }
154
NetSysGetResolvConfInternal(int sockFd,uint16_t netId,struct ResolvConfig * config)155 static int32_t NetSysGetResolvConfInternal(int sockFd, uint16_t netId, struct ResolvConfig *config)
156 {
157 struct RequestInfo info = {
158 .command = GET_CONFIG,
159 .netId = netId,
160 };
161
162 DNS_CONFIG_PRINT("NetSysGetResolvConfInternal begin netid: %d", info.netId);
163 if (!PollSendData(sockFd, (const char *)(&info), sizeof(info))) {
164 DNS_CONFIG_PRINT("send failed %d", errno);
165 return CloseSocketReturn(sockFd, -errno);
166 }
167
168 if (!PollRecvData(sockFd, (char *)(config), sizeof(struct ResolvConfig))) {
169 DNS_CONFIG_PRINT("receive failed %d", errno);
170 return CloseSocketReturn(sockFd, -errno);
171 }
172
173 if (config->error < 0) {
174 DNS_CONFIG_PRINT("get Config error: %d", config->error);
175 return CloseSocketReturn(sockFd, config->error);
176 }
177
178 DNS_CONFIG_PRINT("NetSysGetResolvConfInternal end netid: %d", info.netId);
179 return CloseSocketReturn(sockFd, 0);
180 }
181
NetSysGetResolvConf(uint16_t netId,struct ResolvConfig * config)182 int32_t NetSysGetResolvConf(uint16_t netId, struct ResolvConfig *config)
183 {
184 if (config == NULL) {
185 DNS_CONFIG_PRINT("Invalid Param");
186 return -EINVAL;
187 }
188
189 int sockFd = CreateConnectionToNetSys();
190 if (sockFd < 0) {
191 DNS_CONFIG_PRINT("NetSysGetResolvConf CreateConnectionToNetSys connect to netsys err: %d", errno);
192 return -errno;
193 }
194
195 int32_t err = NetSysGetResolvConfInternal(sockFd, netId, config);
196 if (err < 0) {
197 DNS_CONFIG_PRINT("NetSysGetResolvConf NetSysGetResolvConfInternal err: %d", errno);
198 return err;
199 }
200
201 if (strlen(config->nameservers[0]) == 0) {
202 return -1;
203 }
204 return 0;
205 }
206
NetsysSendKeyForCache(int sockFd,struct ParamWrapper param,struct RequestInfo info)207 static int32_t NetsysSendKeyForCache(int sockFd, struct ParamWrapper param, struct RequestInfo info)
208 {
209 char key[MAX_KEY_LENGTH] = {0};
210 if (!MakeKey(param.host, param.serv, param.hint, key)) {
211 return CloseSocketReturn(sockFd, -1);
212 }
213
214 DNS_CONFIG_PRINT("NetSysSetResolvCacheInternal begin netid: %d", info.netId);
215 if (!PollSendData(sockFd, (const char *)(&info), sizeof(info))) {
216 DNS_CONFIG_PRINT("send failed %d", errno);
217 return CloseSocketReturn(sockFd, -errno);
218 }
219
220 uint32_t nameLen = strlen(key) + 1;
221 if (!PollSendData(sockFd, (const char *)&nameLen, sizeof(nameLen))) {
222 DNS_CONFIG_PRINT("send failed %d", errno);
223 return CloseSocketReturn(sockFd, -errno);
224 }
225
226 if (!PollSendData(sockFd, key, nameLen)) {
227 DNS_CONFIG_PRINT("send failed %d", errno);
228 return CloseSocketReturn(sockFd, -errno);
229 }
230 return 0;
231 };
232
NetSysGetResolvCacheInternal(int sockFd,uint16_t netId,const struct ParamWrapper param,struct AddrInfo addrInfo[static MAX_RESULTS],uint32_t * num)233 static int32_t NetSysGetResolvCacheInternal(int sockFd, uint16_t netId, const struct ParamWrapper param,
234 struct AddrInfo addrInfo[static MAX_RESULTS], uint32_t *num)
235 {
236 struct RequestInfo info = {
237 .command = GET_CACHE,
238 .netId = netId,
239 };
240
241 int32_t res = NetsysSendKeyForCache(sockFd, param, info);
242 if (res < 0) {
243 return res;
244 }
245
246 if (!PollRecvData(sockFd, (char *)num, sizeof(uint32_t))) {
247 DNS_CONFIG_PRINT("read failed %d", errno);
248 return CloseSocketReturn(sockFd, -errno);
249 }
250
251 *num = Min(*num, MAX_RESULTS);
252 if (*num == 0) {
253 return CloseSocketReturn(sockFd, 0);
254 }
255
256 if (!PollRecvData(sockFd, (char *)addrInfo, sizeof(struct AddrInfo) * (*num))) {
257 DNS_CONFIG_PRINT("read failed %d", errno);
258 return CloseSocketReturn(sockFd, -errno);
259 }
260
261 DNS_CONFIG_PRINT("NetSysGetResolvCacheInternal end netid: %d", info.netId);
262 return CloseSocketReturn(sockFd, 0);
263 }
264
NetSysGetResolvCache(uint16_t netId,const struct ParamWrapper param,struct AddrInfo addrInfo[static MAX_RESULTS],uint32_t * num)265 int32_t NetSysGetResolvCache(uint16_t netId, const struct ParamWrapper param,
266 struct AddrInfo addrInfo[static MAX_RESULTS], uint32_t *num)
267 {
268 char *hostName = param.host;
269 if (hostName == NULL || strlen(hostName) == 0 || num == NULL) {
270 DNS_CONFIG_PRINT("Invalid Param");
271 return -EINVAL;
272 }
273
274 int sockFd = CreateConnectionToNetSys();
275 if (sockFd < 0) {
276 DNS_CONFIG_PRINT("NetSysGetResolvCache CreateConnectionToNetSys connect to netsys err: %d", errno);
277 return sockFd;
278 }
279
280 int err = NetSysGetResolvCacheInternal(sockFd, netId, param, addrInfo, num);
281 if (err < 0) {
282 DNS_CONFIG_PRINT("NetSysGetResolvCache NetSysGetResolvCacheInternal err: %d", errno);
283 return err;
284 }
285
286 return 0;
287 }
288
FillAddrInfo(struct AddrInfo addrInfo[static MAX_RESULTS],struct addrinfo * res)289 static int32_t FillAddrInfo(struct AddrInfo addrInfo[static MAX_RESULTS], struct addrinfo *res)
290 {
291 if (memset_s(addrInfo, sizeof(struct AddrInfo) * MAX_RESULTS, 0, sizeof(struct AddrInfo) * MAX_RESULTS) != 0) {
292 return -1;
293 }
294
295 int32_t resNum = 0;
296 for (struct addrinfo *tmp = res; tmp != NULL; tmp = tmp->ai_next) {
297 addrInfo[resNum].aiFlags = tmp->ai_flags;
298 addrInfo[resNum].aiFamily = tmp->ai_family;
299 addrInfo[resNum].aiSockType = tmp->ai_socktype;
300 addrInfo[resNum].aiProtocol = tmp->ai_protocol;
301 addrInfo[resNum].aiAddrLen = tmp->ai_addrlen;
302 if (memcpy_s(&addrInfo[resNum].aiAddr, sizeof(addrInfo[resNum].aiAddr), tmp->ai_addr, tmp->ai_addrlen) != 0) {
303 DNS_CONFIG_PRINT("memcpy_s failed");
304 return -1;
305 }
306 if (strcpy_s(addrInfo[resNum].aiCanonName, sizeof(addrInfo[resNum].aiCanonName), tmp->ai_canonname) != 0) {
307 DNS_CONFIG_PRINT("strcpy_s failed");
308 return -1;
309 }
310
311 ++resNum;
312 if (resNum >= MAX_RESULTS) {
313 break;
314 }
315 }
316
317 return resNum;
318 }
319
NetSysSetResolvCacheInternal(int sockFd,uint16_t netId,const struct ParamWrapper param,struct addrinfo * res)320 static int32_t NetSysSetResolvCacheInternal(int sockFd, uint16_t netId, const struct ParamWrapper param,
321 struct addrinfo *res)
322 {
323 struct RequestInfo info = {
324 .command = SET_CACHE,
325 .netId = netId,
326 };
327
328 int32_t result = NetsysSendKeyForCache(sockFd, param, info);
329 if (result < 0) {
330 return result;
331 }
332
333 struct AddrInfo addrInfo[MAX_RESULTS] = {};
334 int32_t resNum = FillAddrInfo(addrInfo, res);
335 if (resNum < 0) {
336 return CloseSocketReturn(sockFd, -1);
337 }
338
339 if (!PollSendData(sockFd, (char *)&resNum, sizeof(resNum))) {
340 DNS_CONFIG_PRINT("send failed %d", errno);
341 return CloseSocketReturn(sockFd, -errno);
342 }
343
344 if (resNum == 0) {
345 return CloseSocketReturn(sockFd, 0);
346 }
347
348 if (!PollSendData(sockFd, (char *)addrInfo, sizeof(struct AddrInfo) * resNum)) {
349 DNS_CONFIG_PRINT("send failed %d", errno);
350 return CloseSocketReturn(sockFd, -errno);
351 }
352
353 return CloseSocketReturn(sockFd, 0);
354 }
355
NetSysSetResolvCache(uint16_t netId,const struct ParamWrapper param,struct addrinfo * res)356 int32_t NetSysSetResolvCache(uint16_t netId, const struct ParamWrapper param, struct addrinfo *res)
357 {
358 char *hostName = param.host;
359 if (hostName == NULL || strlen(hostName) == 0 || res == NULL) {
360 DNS_CONFIG_PRINT("Invalid Param");
361 return -EINVAL;
362 }
363
364 int sockFd = CreateConnectionToNetSys();
365 if (sockFd < 0) {
366 DNS_CONFIG_PRINT("NetSysSetResolvCache CreateConnectionToNetSys connect to netsys err: %d", errno);
367 return sockFd;
368 }
369
370 int err = NetSysSetResolvCacheInternal(sockFd, netId, param, res);
371 if (err < 0) {
372 DNS_CONFIG_PRINT("NetSysSetResolvCache NetSysSetResolvCacheInternal err: %d", errno);
373 return err;
374 }
375
376 return 0;
377 }
378
379 #ifdef __cplusplus
380 }
381 #endif
382