1/*
2 * Copyright (c) 2022-2024 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
21#include "app_net_client.h"
22#include "dns_config_client.h"
23#include "hilog/log_c.h"
24#include <netdb.h>
25#include <securec.h>
26#include <stdbool.h>
27#include <sys/select.h>
28#include <sys/un.h>
29#include <unistd.h>
30
31#undef LOG_TAG
32#ifndef NETMGRNATIVE_LOG_TAG
33#define LOG_TAG "NetsysNativeService"
34#else
35#define LOG_TAG NETMGRNATIVE_LOG_TAG
36#endif
37
38#ifdef __cplusplus
39extern "C" {
40#endif
41
42static volatile uint8_t g_allowInternet = 1;
43
44void DisallowInternet(void)
45{
46    g_allowInternet = 0;
47}
48
49uint8_t IsAllowInternet(void)
50{
51    return g_allowInternet;
52}
53
54static inline uint32_t Min(uint32_t a, uint32_t b)
55{
56    return a < b ? a : b;
57}
58
59static inline int CloseSocketReturn(int sock, int ret)
60{
61    close(sock);
62    return ret;
63}
64
65void MakeDefaultDnsServer(char *server, size_t length)
66{
67    int ret = memset_s(server, length, 0, DEFAULT_SERVER_LENTH);
68    if (ret < 0) {
69        DNS_CONFIG_PRINT("MakeDefaultDnsServer memset_s failed");
70        return;
71    }
72
73    ret = sprintf_s(server, length, "%d.%d.%d.%d", DEFAULT_SERVER_NAME, DEFAULT_SERVER_NAME, DEFAULT_SERVER_NAME,
74                    DEFAULT_SERVER_NAME);
75    if (ret != 0) {
76        DNS_CONFIG_PRINT("MakeDefaultDnsServer sprintf_s failed");
77    }
78}
79
80static bool NonBlockConnect(int sock, struct sockaddr *addr, socklen_t addrLen)
81{
82    int ret = connect(sock, addr, addrLen);
83    if (ret >= 0) {
84        return true;
85    }
86    if (errno != EINPROGRESS) {
87        return false;
88    }
89
90    fd_set set = {0};
91    FD_ZERO(&set);
92    FD_SET(sock, &set);
93    struct timeval timeout = {
94        .tv_sec = DEFAULT_CONNECT_TIMEOUT,
95        .tv_usec = 0,
96    };
97
98    ret = select(sock + 1, NULL, &set, NULL, &timeout);
99    if (ret < 0) {
100        DNS_CONFIG_PRINT("select error: %s", strerror(errno));
101        return false;
102    } else if (ret == 0) {
103        DNS_CONFIG_PRINT("timeout!");
104        return false;
105    }
106
107    int err = 0;
108    socklen_t optLen = sizeof(err);
109    ret = getsockopt(sock, SOL_SOCKET, SO_ERROR, (void *)(&err), &optLen);
110    if (ret < 0 || err != 0) {
111        return false;
112    }
113    return true;
114}
115
116static int CreateConnectionToNetSys(void)
117{
118    int32_t sockFd = socket(AF_UNIX, SOCK_STREAM, 0);
119    if (sockFd < 0) {
120        DNS_CONFIG_PRINT("socket failed %d", errno);
121        return -errno;
122    }
123    if (!MakeNonBlock(sockFd)) {
124        DNS_CONFIG_PRINT("MakeNonBlock failed");
125        return CloseSocketReturn(sockFd, -errno);
126    }
127
128    struct sockaddr_un address = {0};
129    address.sun_family = AF_UNIX;
130
131    if (strcpy_s(address.sun_path, sizeof(address.sun_path), DNS_SOCKET_PATH) != 0) {
132        DNS_CONFIG_PRINT("str copy failed ");
133        return CloseSocketReturn(sockFd, -1);
134    }
135
136    if (!NonBlockConnect(sockFd, (struct sockaddr *)&address, sizeof(address))) {
137        return CloseSocketReturn(sockFd, -errno);
138    }
139
140    return sockFd;
141}
142
143static bool MakeKey(const char *hostName, const char *serv, const struct addrinfo *hints,
144                    char key[static MAX_KEY_LENGTH])
145{
146    if (serv && hints) {
147        return sprintf_s(key, MAX_KEY_LENGTH, "%s %s %d %d %d %d", hostName, serv, hints->ai_family, hints->ai_flags,
148                         hints->ai_protocol, hints->ai_socktype) > 0;
149    }
150
151    if (hints) {
152        return sprintf_s(key, MAX_KEY_LENGTH, "%s %d %d %d %d", hostName, hints->ai_family, hints->ai_flags,
153                         hints->ai_protocol, hints->ai_socktype) > 0;
154    }
155
156    if (serv) {
157        return sprintf_s(key, MAX_KEY_LENGTH, "%s %s", hostName, serv) > 0;
158    }
159
160    return sprintf_s(key, MAX_KEY_LENGTH, "%s", hostName) > 0;
161}
162
163static int32_t NetSysGetResolvConfInternal(int sockFd, uint16_t netId, struct ResolvConfig *config)
164{
165    struct RequestInfo info = {
166        .uid = getuid(),
167        .command = GET_CONFIG,
168        .netId = netId,
169    };
170    if (netId == 0 && GetNetForApp() > 0) {
171        info.netId = (uint32_t)GetNetForApp();
172    }
173    DNS_CONFIG_PRINT("NetSysGetResolvConfInternal begin netid: %d", info.netId);
174    if (!PollSendData(sockFd, (const char *)(&info), sizeof(info))) {
175        HILOG_ERROR(LOG_CORE, "send failed %{public}d", errno);
176        return CloseSocketReturn(sockFd, -errno);
177    }
178
179    if (!PollRecvData(sockFd, (char *)(config), sizeof(struct ResolvConfig))) {
180        HILOG_ERROR(LOG_CORE, "receive failed %{public}d", errno);
181        return CloseSocketReturn(sockFd, -errno);
182    }
183
184    if (config->error < 0) {
185        HILOG_ERROR(LOG_CORE, "get Config error: %{public}d", config->error);
186        return CloseSocketReturn(sockFd, config->error);
187    }
188
189    DNS_CONFIG_PRINT("NetSysGetResolvConfInternal end netid: %d", info.netId);
190    return CloseSocketReturn(sockFd, 0);
191}
192
193int32_t NetSysGetResolvConf(uint16_t netId, struct ResolvConfig *config)
194{
195    if (config == NULL) {
196        DNS_CONFIG_PRINT("Invalid Param");
197        return -EINVAL;
198    }
199
200    int sockFd = CreateConnectionToNetSys();
201    if (sockFd < 0) {
202        DNS_CONFIG_PRINT("NetSysGetResolvConf CreateConnectionToNetSys connect to netsys err: %d", errno);
203        return -errno;
204    }
205
206    int32_t err = NetSysGetResolvConfInternal(sockFd, netId, config);
207    if (err < 0) {
208        DNS_CONFIG_PRINT("NetSysGetResolvConf NetSysGetResolvConfInternal err: %d", errno);
209        return err;
210    }
211
212    if (strlen(config->nameservers[0]) == 0) {
213        return -1;
214    }
215    return 0;
216}
217
218static int32_t NetsysSendKeyForCache(int sockFd, struct ParamWrapper param, struct RequestInfo info)
219{
220    char key[MAX_KEY_LENGTH] = {0};
221    if (!MakeKey(param.host, param.serv, param.hint, key)) {
222        return CloseSocketReturn(sockFd, -1);
223    }
224
225    DNS_CONFIG_PRINT("NetSysSetResolvCacheInternal begin netid: %d", info.netId);
226    if (!PollSendData(sockFd, (const char *)(&info), sizeof(info))) {
227        DNS_CONFIG_PRINT("send failed %d", errno);
228        return CloseSocketReturn(sockFd, -errno);
229    }
230
231    uint32_t nameLen = strlen(key) + 1;
232    if (!PollSendData(sockFd, (const char *)&nameLen, sizeof(nameLen))) {
233        DNS_CONFIG_PRINT("send failed %d", errno);
234        return CloseSocketReturn(sockFd, -errno);
235    }
236
237    if (!PollSendData(sockFd, key, nameLen)) {
238        DNS_CONFIG_PRINT("send failed %d", errno);
239        return CloseSocketReturn(sockFd, -errno);
240    }
241    return 0;
242};
243
244static int32_t NetSysGetResolvCacheInternal(int sockFd, uint16_t netId, const struct ParamWrapper param,
245                                            struct AddrInfo addrInfo[static MAX_RESULTS], uint32_t *num)
246{
247    struct RequestInfo info = {
248        .uid = getuid(),
249        .command = GET_CACHE,
250        .netId = netId,
251    };
252    if (netId == 0 && GetNetForApp() > 0) {
253        info.netId = (uint32_t)GetNetForApp();
254    }
255    int32_t res = NetsysSendKeyForCache(sockFd, param, info);
256    if (res < 0) {
257        return res;
258    }
259
260    if (!PollRecvData(sockFd, (char *)num, sizeof(uint32_t))) {
261        DNS_CONFIG_PRINT("read failed %d", errno);
262        return CloseSocketReturn(sockFd, -errno);
263    }
264
265    *num = Min(*num, MAX_RESULTS);
266    if (*num == 0) {
267        return CloseSocketReturn(sockFd, 0);
268    }
269
270    if (!PollRecvData(sockFd, (char *)addrInfo, sizeof(struct AddrInfo) * (*num))) {
271        DNS_CONFIG_PRINT("read failed %d", errno);
272        return CloseSocketReturn(sockFd, -errno);
273    }
274
275    DNS_CONFIG_PRINT("NetSysGetResolvCacheInternal end netid: %d", info.netId);
276    return CloseSocketReturn(sockFd, 0);
277}
278
279int32_t NetSysGetResolvCache(uint16_t netId, const struct ParamWrapper param,
280                             struct AddrInfo addrInfo[static MAX_RESULTS], uint32_t *num)
281{
282    char *hostName = param.host;
283    if (hostName == NULL || strlen(hostName) == 0 || num == NULL) {
284        DNS_CONFIG_PRINT("Invalid Param");
285        return -EINVAL;
286    }
287
288    int sockFd = CreateConnectionToNetSys();
289    if (sockFd < 0) {
290        DNS_CONFIG_PRINT("NetSysGetResolvCache CreateConnectionToNetSys connect to netsys err: %d", errno);
291        return sockFd;
292    }
293
294    int err = NetSysGetResolvCacheInternal(sockFd, netId, param, addrInfo, num);
295    if (err < 0) {
296        DNS_CONFIG_PRINT("NetSysGetResolvCache NetSysGetResolvCacheInternal err: %d", errno);
297        return err;
298    }
299
300    return 0;
301}
302
303static int32_t FillAddrInfo(struct AddrInfo addrInfo[static MAX_RESULTS], struct addrinfo *res)
304{
305    if (memset_s(addrInfo, sizeof(struct AddrInfo) * MAX_RESULTS, 0, sizeof(struct AddrInfo) * MAX_RESULTS) != 0) {
306        return -1;
307    }
308
309    int32_t resNum = 0;
310    for (struct addrinfo *tmp = res; tmp != NULL; tmp = tmp->ai_next) {
311        addrInfo[resNum].aiFlags = tmp->ai_flags;
312        addrInfo[resNum].aiFamily = tmp->ai_family;
313        addrInfo[resNum].aiSockType = (uint32_t)(tmp->ai_socktype);
314        addrInfo[resNum].aiProtocol = tmp->ai_protocol;
315        addrInfo[resNum].aiAddrLen = tmp->ai_addrlen;
316        if (memcpy_s(&addrInfo[resNum].aiAddr, sizeof(addrInfo[resNum].aiAddr), tmp->ai_addr, tmp->ai_addrlen) != 0) {
317            DNS_CONFIG_PRINT("memcpy_s failed");
318            return -1;
319        }
320        if (strcpy_s(addrInfo[resNum].aiCanonName, sizeof(addrInfo[resNum].aiCanonName), tmp->ai_canonname) != 0) {
321            DNS_CONFIG_PRINT("strcpy_s failed");
322            return -1;
323        }
324
325        ++resNum;
326        if (resNum >= MAX_RESULTS) {
327            break;
328        }
329    }
330
331    return resNum;
332}
333
334static int32_t FillQueryParam(struct queryparam *orig, struct QueryParam *dest)
335{
336    dest->type = orig->qp_type;
337    dest->netId = orig->qp_netid;
338    dest->mark = orig->qp_mark;
339    dest->flags = orig->qp_flag;
340    dest->qHook = NULL;
341    return 0;
342}
343
344static int32_t NetSysSetResolvCacheInternal(int sockFd, uint16_t netId, const struct ParamWrapper param,
345                                            struct addrinfo *res)
346{
347    struct RequestInfo info = {
348        .uid = getuid(),
349        .command = SET_CACHE,
350        .netId = netId,
351    };
352    if (netId == 0 && GetNetForApp() > 0) {
353        info.netId = (uint32_t)GetNetForApp();
354    }
355    int32_t result = NetsysSendKeyForCache(sockFd, param, info);
356    if (result < 0) {
357        return result;
358    }
359
360    struct AddrInfo addrInfo[MAX_RESULTS] = {};
361    int32_t resNum = FillAddrInfo(addrInfo, res);
362    if (resNum < 0) {
363        return CloseSocketReturn(sockFd, -1);
364    }
365
366    if (!PollSendData(sockFd, (char *)&resNum, sizeof(resNum))) {
367        DNS_CONFIG_PRINT("send failed %d", errno);
368        return CloseSocketReturn(sockFd, -errno);
369    }
370
371    if (resNum == 0) {
372        return CloseSocketReturn(sockFd, 0);
373    }
374
375    if (!PollSendData(sockFd, (char *)addrInfo, sizeof(struct AddrInfo) * resNum)) {
376        DNS_CONFIG_PRINT("send failed %d", errno);
377        return CloseSocketReturn(sockFd, -errno);
378    }
379
380    return CloseSocketReturn(sockFd, 0);
381}
382
383int32_t NetSysSetResolvCache(uint16_t netId, const struct ParamWrapper param, struct addrinfo *res)
384{
385    char *hostName = param.host;
386    if (hostName == NULL || strlen(hostName) == 0 || res == NULL) {
387        DNS_CONFIG_PRINT("Invalid Param");
388        return -EINVAL;
389    }
390
391    int sockFd = CreateConnectionToNetSys();
392    if (sockFd < 0) {
393        DNS_CONFIG_PRINT("NetSysSetResolvCache CreateConnectionToNetSys connect to netsys err: %d", errno);
394        return sockFd;
395    }
396
397    int err = NetSysSetResolvCacheInternal(sockFd, netId, param, res);
398    if (err < 0) {
399        DNS_CONFIG_PRINT("NetSysSetResolvCache NetSysSetResolvCacheInternal err: %d", errno);
400        return err;
401    }
402
403    return 0;
404}
405
406static int32_t NetSysIsIpv6EnableInternal(int sockFd, uint16_t netId, int *enable)
407{
408    struct RequestInfo info = {
409        .uid = getuid(),
410        .command = JUDGE_IPV6,
411        .netId = netId,
412    };
413    if (!PollSendData(sockFd, (const char *)(&info), sizeof(info))) {
414        DNS_CONFIG_PRINT("send failed %d", errno);
415        return CloseSocketReturn(sockFd, -errno);
416    }
417
418    if (!PollRecvData(sockFd, (char *)enable, sizeof(int))) {
419        DNS_CONFIG_PRINT("read failed %d", errno);
420        return CloseSocketReturn(sockFd, -errno);
421    }
422
423    return CloseSocketReturn(sockFd, 0);
424}
425
426int NetSysIsIpv6Enable(uint16_t netId)
427{
428    int sockFd = CreateConnectionToNetSys();
429    if (sockFd < 0) {
430        DNS_CONFIG_PRINT("NetSysIsIpv6Enable CreateConnectionToNetSys connect to netsys err: %d", errno);
431        return sockFd;
432    }
433    int enable = 0;
434    int err = NetSysIsIpv6EnableInternal(sockFd, netId, &enable);
435    if (err < 0) {
436        return 0;
437    }
438
439    return enable;
440}
441
442static int32_t NetSysPostDnsResultPollSendData(int sockFd, int queryret, int32_t resNum, struct QueryParam *param,
443                                               struct AddrInfo addrInfo[static MAX_RESULTS])
444{
445    if (!PollSendData(sockFd, (char *)&queryret, sizeof(int))) {
446        DNS_CONFIG_PRINT("send failed %d", errno);
447        return CloseSocketReturn(sockFd, -errno);
448    }
449
450    if (!PollSendData(sockFd, (char *)&resNum, sizeof(int32_t))) {
451        DNS_CONFIG_PRINT("send failed %d", errno);
452        return CloseSocketReturn(sockFd, -errno);
453    }
454
455    if (!PollSendData(sockFd, (char *)param, sizeof(struct QueryParam))) {
456        DNS_CONFIG_PRINT("send failed %d", errno);
457        return CloseSocketReturn(sockFd, -errno);
458    }
459
460    if (resNum > 0) {
461        if (!PollSendData(sockFd, (char *)addrInfo, sizeof(struct AddrInfo) * resNum)) {
462            DNS_CONFIG_PRINT("send failed %d", errno);
463            return CloseSocketReturn(sockFd, -errno);
464        }
465    }
466    return CloseSocketReturn(sockFd, 0);
467}
468
469static int32_t NetSysPostDnsResultInternal(int sockFd, uint16_t netId, char* name, int usedtime, int queryret,
470                                           struct addrinfo *res, struct queryparam *param)
471{
472    struct RequestInfo info = {
473        .uid = getuid(),
474        .command = POST_DNS_RESULT,
475        .netId = netId,
476    };
477
478    int32_t uid = (int32_t)(getuid());
479    int32_t pid = getpid();
480    uint32_t nameLen = strlen(name) + 1;
481    NETSYS_CLIENT_PRINT("NetSysPostDnsResultInternal uid %d, pid %d, netid %d pkg", uid, pid, netId);
482
483    struct AddrInfo addrInfo[MAX_RESULTS] = {};
484    struct QueryParam netparam = {};
485    int32_t resNum = 0;
486    if (queryret == 0) {
487        resNum = FillAddrInfo(addrInfo, res);
488    }
489    if (resNum < 0) {
490        return CloseSocketReturn(sockFd, -1);
491    }
492    FillQueryParam(param, &netparam);
493
494    if (!PollSendData(sockFd, (const char *)(&info), sizeof(info))) {
495        DNS_CONFIG_PRINT("send failed %d", errno);
496        return CloseSocketReturn(sockFd, -errno);
497    }
498
499    if (!PollSendData(sockFd, (char *)&uid, sizeof(int32_t))) {
500        DNS_CONFIG_PRINT("send failed %d", errno);
501        return CloseSocketReturn(sockFd, -errno);
502    }
503
504    if (!PollSendData(sockFd, (char *)&pid, sizeof(int32_t))) {
505        DNS_CONFIG_PRINT("send failed %d", errno);
506        return CloseSocketReturn(sockFd, -errno);
507    }
508
509    if (!PollSendData(sockFd, (char *)&nameLen, sizeof(uint32_t))) {
510        DNS_CONFIG_PRINT("send failed %d", errno);
511        return CloseSocketReturn(sockFd, -errno);
512    }
513
514    if (!PollSendData(sockFd, name, (sizeof(char) * nameLen))) {
515        DNS_CONFIG_PRINT("send failed %d", errno);
516        return CloseSocketReturn(sockFd, -errno);
517    }
518
519    if (!PollSendData(sockFd, (char *)&usedtime, sizeof(int))) {
520        DNS_CONFIG_PRINT("send failed %d", errno);
521        return CloseSocketReturn(sockFd, -errno);
522    }
523
524    return NetSysPostDnsResultPollSendData(sockFd, queryret, resNum, &netparam, addrInfo);
525}
526
527int32_t NetSysPostDnsResult(int netid, char* name, int usedtime, int queryret,
528                            struct addrinfo *res, struct queryparam *param)
529{
530    if (name == NULL) {
531        return -1;
532    }
533
534    int sockFd = CreateConnectionToNetSys();
535    if (sockFd < 0) {
536        DNS_CONFIG_PRINT("NetSysPostDnsResult CreateConnectionToNetSys connect to netsys err: %d", errno);
537        return sockFd;
538    }
539    int err = NetSysPostDnsResultInternal(sockFd, netid, name, usedtime, queryret, res, param);
540    if (err < 0) {
541        return -1;
542    }
543
544    return 0;
545}
546
547static int32_t NetSysGetDefaultNetworkInternal(int sockFd, uint16_t netId, int32_t *currentNetId)
548{
549    struct RequestInfo info = {
550        .uid = getuid(),
551        .command = GET_DEFAULT_NETWORK,
552        .netId = netId,
553    };
554    if (!PollSendData(sockFd, (const char *)(&info), sizeof(info))) {
555        DNS_CONFIG_PRINT("send failed %d", errno);
556        return CloseSocketReturn(sockFd, -errno);
557    }
558
559    if (!PollRecvData(sockFd, (char *)currentNetId, sizeof(int))) {
560        DNS_CONFIG_PRINT("read failed %d", errno);
561        return CloseSocketReturn(sockFd, -errno);
562    }
563    DNS_CONFIG_PRINT("currentNetId %d", *currentNetId);
564    return CloseSocketReturn(sockFd, 0);
565}
566
567int32_t NetSysGetDefaultNetwork(uint16_t netId, int32_t* currentNetId)
568{
569    int sockFd = CreateConnectionToNetSys();
570    int err = NetSysGetDefaultNetworkInternal(sockFd, netId, currentNetId);
571    if (err < 0) {
572        return -1;
573    }
574
575    return 0;
576}
577
578static int32_t NetSysBindSocketInternal(int sockFd, uint16_t netId, int32_t fd)
579{
580    struct RequestInfo info = {
581        .uid = getuid(),
582        .command = BIND_SOCKET,
583        .netId = netId,
584    };
585    if (!PollSendData(sockFd, (const char *)(&info), sizeof(info))) {
586        DNS_CONFIG_PRINT("send failed %d", errno);
587        return CloseSocketReturn(sockFd, -errno);
588    }
589
590    if (!PollSendData(sockFd, (const char *)(&fd), sizeof(int32_t))) {
591        DNS_CONFIG_PRINT("send failed %d", errno);
592        return CloseSocketReturn(sockFd, -errno);
593    }
594
595    return CloseSocketReturn(sockFd, 0);
596}
597
598int32_t NetSysBindSocket(int32_t fd, uint32_t netId)
599{
600    int sockFd = CreateConnectionToNetSys();
601    DNS_CONFIG_PRINT("NetSysBindSocket %d", fd);
602    int err = NetSysBindSocketInternal(sockFd, netId, fd);
603    if (err < 0) {
604        return -1;
605    }
606
607    return 0;
608}
609
610#ifdef __cplusplus
611}
612#endif
613