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 *>(¶m), 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