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 <arpa/inet.h>
17 #include <sys/stat.h>
18 #include <thread>
19 
20 #include "dns_config_client.h"
21 #include "net_handle.h"
22 #include "net_conn_client.h"
23 #include "dns_param_cache.h"
24 #include "netsys_client.h"
25 #include "init_socket.h"
26 #ifdef USE_SELINUX
27 #include "selinux/selinux.h"
28 #endif
29 #include "singleton.h"
30 #include <ipc_skeleton.h>
31 
32 #include "dns_resolv_listen.h"
33 #include "dns_quality_diag.h"
34 #include "fwmark_client.h"
35 
36 namespace OHOS::nmd {
37 static constexpr const uint32_t MAX_LISTEN_NUM = 1024;
DnsResolvListen()38 DnsResolvListen::DnsResolvListen() : serverSockFd_(-1)
39 {
40     NETNATIVE_LOGE("DnsResolvListen start");
41 }
42 
~DnsResolvListen()43 DnsResolvListen::~DnsResolvListen()
44 {
45     NETNATIVE_LOGE("DnsResolvListen end");
46     if (serverSockFd_ > 0) {
47         close(serverSockFd_);
48     }
49 }
50 
ProcGetConfigCommand(int clientSockFd,uint16_t netId,uint32_t uid)51 void DnsResolvListen::ProcGetConfigCommand(int clientSockFd, uint16_t netId, uint32_t uid)
52 {
53     NETNATIVE_LOG_D("DnsResolvListen::ProcGetConfigCommand uid = [%{public}u]", uid);
54     ResolvConfig sendData = {0};
55     std::vector<std::string> servers;
56     std::vector<std::string> domains;
57     uint16_t baseTimeoutMsec = DEFAULT_TIMEOUT;
58     uint8_t retryCount = DEFAULT_RETRY;
59 
60 #ifdef FEATURE_NET_FIREWALL_ENABLE
61     DnsParamCache::GetInstance().SetCallingUid(uid);
62 #endif
63 
64     int status = -1;
65     if (DnsParamCache::GetInstance().IsVpnOpen() && netId == 0) {
66         status = DnsParamCache::GetInstance().GetResolverConfig(static_cast<uint16_t>(netId), uid, servers,
67                                                                 domains, baseTimeoutMsec, retryCount);
68     } else {
69         status = DnsParamCache::GetInstance().GetResolverConfig(static_cast<uint16_t>(netId), servers,
70                                                                 domains, baseTimeoutMsec, retryCount);
71     }
72     DNS_CONFIG_PRINT("GetResolverConfig status: %{public}d", status);
73     if (status < 0) {
74         sendData.error = status;
75     } else {
76         sendData.retryCount = retryCount;
77         sendData.timeoutMs = baseTimeoutMsec;
78         for (size_t i = 0; i < std::min<size_t>(MAX_SERVER_NUM, servers.size()); i++) {
79             if (memcpy_s(sendData.nameservers[i], sizeof(sendData.nameservers[i]), servers[i].c_str(),
80                          servers[i].length()) < 0) {
81                 DNS_CONFIG_PRINT("mem copy failed");
82                 continue;
83             }
84             DNS_CONFIG_PRINT("i = %{public}d sendData.nameservers: %{public}s", i, sendData.nameservers[i]);
85         }
86     }
87     if (!PollSendData(clientSockFd, reinterpret_cast<char *>(&sendData), sizeof(ResolvConfig))) {
88         DNS_CONFIG_PRINT("send failed");
89     }
90     DNS_CONFIG_PRINT("ProcGetConfigCommand end");
91 }
92 
ProcGetKeyForCache(int clientSockFd,char * name)93 int32_t DnsResolvListen::ProcGetKeyForCache(int clientSockFd, char *name)
94 {
95     DNS_CONFIG_PRINT("ProcGetKeyForCache");
96     uint32_t nameLen = 0;
97     if (!PollRecvData(clientSockFd, reinterpret_cast<char *>(&nameLen), sizeof(nameLen))) {
98         DNS_CONFIG_PRINT("read errno %{public}d", errno);
99         close(clientSockFd);
100         return -1;
101     }
102 
103     if (nameLen > MAX_HOST_NAME_LEN) {
104         DNS_CONFIG_PRINT("MAX_HOST_NAME_LEN is %{public}u, but get %{public}u", MAX_HOST_NAME_LEN, nameLen);
105         close(clientSockFd);
106         return -1;
107     }
108 
109     if (!PollRecvData(clientSockFd, name, nameLen)) {
110         DNS_CONFIG_PRINT("read errno %{public}d", errno);
111         close(clientSockFd);
112         return -1;
113     }
114     DNS_CONFIG_PRINT("ProcGetKeyForCache end");
115     return 0;
116 }
117 
ProcGetCacheCommand(int clientSockFd,uint16_t netId)118 void DnsResolvListen::ProcGetCacheCommand(int clientSockFd, uint16_t netId)
119 {
120 #ifdef FEATURE_NET_FIREWALL_ENABLE
121     ProcGetCacheCommand(clientSockFd, netId, 0);
122 }
123 
ProcGetCacheCommand(int clientSockFd,uint16_t netId,uint32_t callingUid)124 void DnsResolvListen::ProcGetCacheCommand(int clientSockFd, uint16_t netId, uint32_t callingUid)
125 {
126 #endif
127     DNS_CONFIG_PRINT("ProcGetCacheCommand");
128     char name[MAX_HOST_NAME_LEN] = {0};
129     int32_t res = ProcGetKeyForCache(clientSockFd, name);
130     if (res < 0) {
131         return;
132     }
133 
134 #ifdef FEATURE_NET_FIREWALL_ENABLE
135     DnsParamCache::GetInstance().SetCallingUid(callingUid);
136 #endif
137     auto cacheRes = DnsParamCache::GetInstance().GetDnsCache(netId, name);
138 
139     uint32_t resNum = std::min<uint32_t>(MAX_RESULTS, static_cast<uint32_t>(cacheRes.size()));
140     if (!PollSendData(clientSockFd, reinterpret_cast<char *>(&resNum), sizeof(resNum))) {
141         DNS_CONFIG_PRINT("send errno %{public}d", errno);
142         close(clientSockFd);
143         return;
144     }
145 
146     if (resNum == 0 || resNum > MAX_RESULTS) {
147         return;
148     }
149 
150     AddrInfo addrInfo[MAX_RESULTS] = {};
151     for (uint32_t i = 0; i < resNum; i++) {
152         if (memcpy_s(reinterpret_cast<char *>(&addrInfo[i]), sizeof(AddrInfo),
153                      reinterpret_cast<char *>(&cacheRes[i]), sizeof(AddrInfo)) != 0) {
154             return;
155         }
156     }
157     if (!PollSendData(clientSockFd, reinterpret_cast<char *>(addrInfo), sizeof(AddrInfo) * resNum)) {
158         DNS_CONFIG_PRINT("send errno %{public}d", errno);
159         close(clientSockFd);
160         return;
161     }
162     DNS_CONFIG_PRINT("ProcGetCacheCommand end");
163 }
164 
ProcSetCacheCommand(int clientSockFd,uint16_t netId)165 void DnsResolvListen::ProcSetCacheCommand(int clientSockFd, uint16_t netId)
166 {
167 #ifdef FEATURE_NET_FIREWALL_ENABLE
168     ProcSetCacheCommand(clientSockFd, netId, 0);
169 }
170 
ProcSetCacheCommand(int clientSockFd,uint16_t netId,uint32_t callingUid)171 void DnsResolvListen::ProcSetCacheCommand(int clientSockFd, uint16_t netId, uint32_t callingUid)
172 {
173 #endif
174     DNS_CONFIG_PRINT("ProcSetCacheCommand");
175     char name[MAX_HOST_NAME_LEN] = {0};
176     int32_t res = ProcGetKeyForCache(clientSockFd, name);
177     if (res < 0) {
178         return;
179     }
180 
181     uint32_t resNum = 0;
182     if (!PollRecvData(clientSockFd, reinterpret_cast<char *>(&resNum), sizeof(resNum))) {
183         DNS_CONFIG_PRINT("read errno %{public}d", errno);
184         close(clientSockFd);
185         return;
186     }
187 
188     resNum = std::min<uint32_t>(MAX_RESULTS, resNum);
189     if (resNum == 0) {
190         return;
191     }
192 
193     AddrInfo addrInfo[MAX_RESULTS] = {};
194     if (!PollRecvData(clientSockFd, reinterpret_cast<char *>(addrInfo), sizeof(AddrInfo) * resNum)) {
195         DNS_CONFIG_PRINT("read errno %{public}d", errno);
196         close(clientSockFd);
197         return;
198     }
199 
200 #ifdef FEATURE_NET_FIREWALL_ENABLE
201     DnsParamCache::GetInstance().SetCallingUid(callingUid);
202 #endif
203     for (size_t i = 0; i < resNum; ++i) {
204         DnsParamCache::GetInstance().SetDnsCache(netId, name, addrInfo[i]);
205     }
206     DnsParamCache::GetInstance().SetCacheDelayed(netId, name);
207     DNS_CONFIG_PRINT("ProcSetCacheCommand end");
208 }
209 
ProcJudgeIpv6Command(int clientSockFd,uint16_t netId)210 void DnsResolvListen::ProcJudgeIpv6Command(int clientSockFd, uint16_t netId)
211 {
212     int enable = DnsParamCache::GetInstance().IsIpv6Enable(netId) ? 1 : 0;
213     if (!PollSendData(clientSockFd, reinterpret_cast<char *>(&enable), sizeof(int))) {
214         DNS_CONFIG_PRINT("send failed");
215     }
216 }
217 
ProcPostDnsThreadResult(int clientSockFd,uint32_t & uid,uint32_t & pid)218 bool DnsResolvListen::ProcPostDnsThreadResult(int clientSockFd, uint32_t &uid, uint32_t &pid)
219 {
220     if (!PollRecvData(clientSockFd, reinterpret_cast<char *>(&uid), sizeof(uint32_t))) {
221         NETNATIVE_LOGE("read1 errno %{public}d", errno);
222         close(clientSockFd);
223         return false;
224     }
225 
226     if (!PollRecvData(clientSockFd, reinterpret_cast<char *>(&pid), sizeof(uint32_t))) {
227         NETNATIVE_LOGE("read2 errno %{public}d", errno);
228         close(clientSockFd);
229         return false;
230     }
231 
232     return true;
233 }
234 
ProcPostDnsResultCommand(int clientSockFd,uint16_t netId)235 void DnsResolvListen::ProcPostDnsResultCommand(int clientSockFd, uint16_t netId)
236 {
237     char name[MAX_HOST_NAME_LEN] = {0};
238     uint32_t netid = netId;
239     uint32_t uid;
240     uint32_t pid;
241 
242     if (!ProcPostDnsThreadResult(clientSockFd, uid, pid)) {
243         return;
244     }
245 
246     int32_t res = ProcGetKeyForCache(clientSockFd, name);
247     if (res < 0) {
248         return;
249     }
250 
251     uint32_t usedtime;
252     if (!PollRecvData(clientSockFd, reinterpret_cast<char *>(&usedtime), sizeof(uint32_t))) {
253         NETNATIVE_LOGE("read3 errno %{public}d", errno);
254         close(clientSockFd);
255         return;
256     }
257 
258     int32_t queryret;
259     if (!PollRecvData(clientSockFd, reinterpret_cast<char *>(&queryret), sizeof(int32_t))) {
260         NETNATIVE_LOGE("read4 errno %{public}d", errno);
261         close(clientSockFd);
262         return;
263     }
264 
265     uint32_t ai_size = MAX_RESULTS;
266     if (!PollRecvData(clientSockFd, reinterpret_cast<char *>(&ai_size), sizeof(ai_size))) {
267         NETNATIVE_LOGE("read5 errno %{public}d", errno);
268         close(clientSockFd);
269         return;
270     }
271 
272     struct QueryParam param;
273     if (!PollRecvData(clientSockFd, reinterpret_cast<char *>(&param), sizeof(struct QueryParam))) {
274         NETNATIVE_LOGE("read6 errno %{public}d", errno);
275         close(clientSockFd);
276         return;
277     }
278 
279     if ((queryret == 0) && (ai_size > 0)) {
280         ai_size = std::min<uint32_t>(MAX_RESULTS, ai_size);
281         AddrInfo addrInfo[MAX_RESULTS] = {};
282         if (!PollRecvData(clientSockFd, reinterpret_cast<char *>(addrInfo), sizeof(AddrInfo) * ai_size)) {
283             NETNATIVE_LOGE("read errno %{public}d", errno);
284             close(clientSockFd);
285             return;
286         }
287         DnsQualityDiag::GetInstance().ReportDnsResult(netid, uid, pid, usedtime, name,
288                                                       ai_size, queryret, param, addrInfo);
289     } else {
290         DnsQualityDiag::GetInstance().ReportDnsResult(netid, uid, pid, usedtime, name, 0, queryret, param, nullptr);
291     }
292 }
293 
ProcGetDefaultNetworkCommand(int clientSockFd,uint16_t netId)294 void DnsResolvListen::ProcGetDefaultNetworkCommand(int clientSockFd, uint16_t netId)
295 {
296     // Todo recv data
297     OHOS::NetManagerStandard::NetHandle netHandle;
298     OHOS::NetManagerStandard::NetConnClient::GetInstance().GetDefaultNet(netHandle);
299     int netid = netHandle.GetNetId();
300     NETNATIVE_LOGE("ProcGetDefaultNetworkCommand %{public}d", netid);
301     if (!PollSendData(clientSockFd, reinterpret_cast<char *>(&netid), sizeof(int))) {
302         NETNATIVE_LOGE("send failed");
303     }
304 }
305 
ProcBindSocketCommand(int clientSockFd,uint16_t netId)306 void DnsResolvListen::ProcBindSocketCommand(int clientSockFd, uint16_t netId)
307 {
308     // Todo recv data
309     int32_t fd = 0;
310     if (!PollRecvData(clientSockFd, reinterpret_cast<char *>(&fd), sizeof(int32_t))) {
311         NETNATIVE_LOGE("read errno %{public}d", errno);
312         close(clientSockFd);
313         return;
314     }
315     NETNATIVE_LOGE("ProcGetDefaultNetworkCommand %{public}d, %{public}d", netId, fd);
316     if (OHOS::nmd::FwmarkClient().BindSocket(fd, netId) != OHOS::NetManagerStandard::NETMANAGER_SUCCESS) {
317         NETNATIVE_LOGE("BindSocket to netid failed");
318     }
319 }
320 
ProcCommand(int clientSockFd)321 void DnsResolvListen::ProcCommand(int clientSockFd)
322 {
323     char buff[sizeof(RequestInfo)] = {0};
324     if (!PollRecvData(clientSockFd, buff, sizeof(buff))) {
325         DNS_CONFIG_PRINT("read errno %{public}d", errno);
326         close(clientSockFd);
327         return;
328     }
329 
330     auto info = reinterpret_cast<RequestInfo *>(buff);
331     auto netId = info->netId;
332     auto uid = info->uid;
333 
334     NETNATIVE_LOG_D("netId = [%{public}u], uid = [%{public}u], command = [%{public}u]",
335                     netId, uid, info->command);
336 
337     switch (info->command) {
338         case GET_CONFIG:
339             ProcGetConfigCommand(clientSockFd, netId, uid);
340             break;
341         case GET_CACHE:
342 #ifdef FEATURE_NET_FIREWALL_ENABLE
343             ProcGetCacheCommand(clientSockFd, netId, uid);
344 #else
345             ProcGetCacheCommand(clientSockFd, netId);
346 #endif
347             break;
348         case SET_CACHE:
349 #ifdef FEATURE_NET_FIREWALL_ENABLE
350             ProcSetCacheCommand(clientSockFd, netId, uid);
351 #else
352             ProcSetCacheCommand(clientSockFd, netId);
353 #endif
354             break;
355         case JUDGE_IPV6:
356             ProcJudgeIpv6Command(clientSockFd, netId);
357             break;
358         case POST_DNS_RESULT:
359             ProcPostDnsResultCommand(clientSockFd, netId);
360             break;
361         case GET_DEFAULT_NETWORK:
362             ProcGetDefaultNetworkCommand(clientSockFd, netId);
363             break;
364         case BIND_SOCKET:
365             ProcBindSocketCommand(clientSockFd, netId);
366             break;
367         default:
368             DNS_CONFIG_PRINT("invalid command %{public}u", info->command);
369             break;
370     }
371 
372     close(clientSockFd);
373 }
374 
StartListen()375 void DnsResolvListen::StartListen()
376 {
377     NETNATIVE_LOGE("Enter StartListen");
378 
379     serverSockFd_ = GetControlSocket(DNS_SOCKET_NAME);
380     if (serverSockFd_ < 0) {
381         NETNATIVE_LOGE("create socket failed %{public}d", errno);
382         return;
383     }
384 
385     // listen
386     if (listen(serverSockFd_, MAX_LISTEN_NUM) < 0) {
387         NETNATIVE_LOGE("listen errno %{public}d", errno);
388         close(serverSockFd_);
389         return;
390     }
391 
392     NETNATIVE_LOGE("begin listen");
393 
394     while (true) {
395         sockaddr_un clientAddr = {0};
396         socklen_t len = sizeof(clientAddr);
397 
398         int clientSockFd = accept(serverSockFd_, (sockaddr *)&clientAddr, &len);
399         if (clientSockFd < 0) {
400             DNS_CONFIG_PRINT("accept errno %{public}d", errno);
401             continue;
402         }
403         if (!MakeNonBlock(clientSockFd)) {
404             DNS_CONFIG_PRINT("MakeNonBlock errno %{public}d", errno);
405             close(clientSockFd);
406             continue;
407         }
408         this->ProcCommand(clientSockFd);
409     }
410 }
411 } // namespace OHOS::nmd
412