• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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