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 <arpa/inet.h>
17 #include <sys/stat.h>
18 #include <thread>
19
20 #include "dns_config_client.h"
21 #include "dns_param_cache.h"
22 #include "netsys_client.h"
23 #include "init_socket.h"
24 #ifdef USE_SELINUX
25 #include "selinux.h"
26 #endif
27 #include "singleton.h"
28
29 #include "dns_resolv_listen.h"
30
31 namespace OHOS::nmd {
32 static constexpr const uint32_t MAX_LISTEN_NUM = 1024;
33 namespace {
34 constexpr const char *DNS_RESOLV_THREAD = "DNS_RESOLV_THREAD";
35 } // namespace
DnsResolvListen()36 DnsResolvListen::DnsResolvListen() : serverSockFd_(-1)
37 {
38 NETNATIVE_LOGE("DnsResolvListen start");
39 dnsResolvRunner_ = AppExecFwk::EventRunner::Create(DNS_RESOLV_THREAD);
40 dnsResolvHandler_ = std::make_shared<AppExecFwk::EventHandler>(dnsResolvRunner_);
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,uint32_t netId)51 void DnsResolvListen::ProcGetConfigCommand(int clientSockFd, uint32_t netId)
52 {
53 DNS_CONFIG_PRINT("ProcGetConfigCommand");
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 auto status = DelayedSingleton<DnsParamCache>::GetInstance()->GetResolverConfig(
61 static_cast<uint16_t>(netId), servers, domains, baseTimeoutMsec, retryCount);
62 DNS_CONFIG_PRINT("GetResolverConfig status: %{public}d", status);
63 if (status < 0) {
64 sendData.error = status;
65 } else {
66 sendData.retryCount = retryCount;
67 sendData.timeoutMs = baseTimeoutMsec;
68 for (size_t i = 0; i < std::min<size_t>(MAX_SERVER_NUM, servers.size()); i++) {
69 if (memcpy_s(sendData.nameservers[i], sizeof(sendData.nameservers[i]), servers[i].c_str(),
70 servers[i].length()) < 0) {
71 DNS_CONFIG_PRINT("mem copy failed");
72 continue;
73 }
74 DNS_CONFIG_PRINT("i = %{public}d sendData.nameservers: %{public}s", i, sendData.nameservers[i]);
75 }
76 }
77 if (!PollSendData(clientSockFd, reinterpret_cast<char *>(&sendData), sizeof(ResolvConfig))) {
78 DNS_CONFIG_PRINT("send failed");
79 }
80 DNS_CONFIG_PRINT("ProcGetConfigCommand end");
81 }
82
ProcGetKeyForCache(int clientSockFd,char * name)83 int32_t DnsResolvListen::ProcGetKeyForCache(int clientSockFd, char *name)
84 {
85 DNS_CONFIG_PRINT("ProcGetKeyForCache");
86 uint32_t nameLen = 0;
87 if (!PollRecvData(clientSockFd, reinterpret_cast<char *>(&nameLen), sizeof(nameLen))) {
88 DNS_CONFIG_PRINT("read errno %{public}d", errno);
89 close(clientSockFd);
90 return -1;
91 }
92
93 if (nameLen > MAX_HOST_NAME_LEN) {
94 DNS_CONFIG_PRINT("MAX_HOST_NAME_LEN is %{public}u, but get %{public}u", MAX_HOST_NAME_LEN, nameLen);
95 close(clientSockFd);
96 return -1;
97 }
98
99 if (!PollRecvData(clientSockFd, name, nameLen)) {
100 DNS_CONFIG_PRINT("read errno %{public}d", errno);
101 close(clientSockFd);
102 return -1;
103 }
104 DNS_CONFIG_PRINT("ProcGetKeyForCache end");
105 return 0;
106 }
107
ProcGetCacheCommand(int clientSockFd,uint32_t netId)108 void DnsResolvListen::ProcGetCacheCommand(int clientSockFd, uint32_t netId)
109 {
110 DNS_CONFIG_PRINT("ProcGetCacheCommand");
111 char name[MAX_HOST_NAME_LEN] = {0};
112 int32_t res = ProcGetKeyForCache(clientSockFd, name);
113 if (res < 0) {
114 return;
115 }
116
117 auto cacheRes = DelayedSingleton<DnsParamCache>::GetInstance()->GetDnsCache(netId, name);
118
119 uint32_t resNum = std::min<uint32_t>(MAX_RESULTS, static_cast<uint32_t>(cacheRes.size()));
120 if (!PollSendData(clientSockFd, reinterpret_cast<char *>(&resNum), sizeof(resNum))) {
121 DNS_CONFIG_PRINT("send errno %{public}d", errno);
122 close(clientSockFd);
123 return;
124 }
125
126 if (resNum == 0 || resNum > MAX_RESULTS) {
127 return;
128 }
129
130 AddrInfo addrInfo[MAX_RESULTS] = {};
131 for (uint32_t i = 0; i < resNum; i++) {
132 if (memcpy_s(reinterpret_cast<char *>(&addrInfo[i]), sizeof(AddrInfo),
133 reinterpret_cast<char *>(&cacheRes[i]), sizeof(AddrInfo)) != 0) {
134 return;
135 }
136 }
137 if (!PollSendData(clientSockFd, reinterpret_cast<char *>(addrInfo), sizeof(AddrInfo) * resNum)) {
138 DNS_CONFIG_PRINT("send errno %{public}d", errno);
139 close(clientSockFd);
140 return;
141 }
142 DNS_CONFIG_PRINT("ProcGetCacheCommand end");
143 }
144
ProcSetCacheCommand(int clientSockFd,uint32_t netId)145 void DnsResolvListen::ProcSetCacheCommand(int clientSockFd, uint32_t netId)
146 {
147 DNS_CONFIG_PRINT("ProcSetCacheCommand");
148 char name[MAX_HOST_NAME_LEN] = {0};
149 int32_t res = ProcGetKeyForCache(clientSockFd, name);
150 if (res < 0) {
151 return;
152 }
153
154 uint32_t resNum = 0;
155 if (!PollRecvData(clientSockFd, reinterpret_cast<char *>(&resNum), sizeof(resNum))) {
156 DNS_CONFIG_PRINT("read errno %{public}d", errno);
157 close(clientSockFd);
158 return;
159 }
160
161 resNum = std::min<uint32_t>(MAX_RESULTS, resNum);
162 if (resNum == 0) {
163 return;
164 }
165
166 AddrInfo addrInfo[MAX_RESULTS] = {};
167 if (!PollRecvData(clientSockFd, reinterpret_cast<char *>(addrInfo), sizeof(AddrInfo) * resNum)) {
168 DNS_CONFIG_PRINT("read errno %{public}d", errno);
169 close(clientSockFd);
170 return;
171 }
172
173 for (size_t i = 0; i < resNum; ++i) {
174 DelayedSingleton<DnsParamCache>::GetInstance()->SetDnsCache(netId, name, addrInfo[i]);
175 }
176 DelayedSingleton<DnsParamCache>::GetInstance()->SetCacheDelayed(netId, name);
177 DNS_CONFIG_PRINT("ProcSetCacheCommand end");
178 }
179
ProcCommand(int clientSockFd)180 void DnsResolvListen::ProcCommand(int clientSockFd)
181 {
182 char buff[sizeof(RequestInfo)] = {0};
183 if (!PollRecvData(clientSockFd, buff, sizeof(buff))) {
184 DNS_CONFIG_PRINT("read errno %{public}d", errno);
185 close(clientSockFd);
186 return;
187 }
188
189 auto info = reinterpret_cast<RequestInfo *>(buff);
190 auto netId = info->netId;
191
192 switch (info->command) {
193 case GET_CONFIG:
194 ProcGetConfigCommand(clientSockFd, netId);
195 break;
196 case GET_CACHE:
197 ProcGetCacheCommand(clientSockFd, netId);
198 break;
199 case SET_CACHE:
200 ProcSetCacheCommand(clientSockFd, netId);
201 break;
202 default:
203 DNS_CONFIG_PRINT("invalid command %{public}u", info->command);
204 break;
205 }
206
207 close(clientSockFd);
208 }
209
StartListen()210 void DnsResolvListen::StartListen()
211 {
212 NETNATIVE_LOGE("Enter StartListen");
213
214 serverSockFd_ = GetControlSocket(DNS_SOCKET_NAME);
215 if (serverSockFd_ < 0) {
216 NETNATIVE_LOGE("create socket failed %{public}d", errno);
217 return;
218 }
219
220 // listen
221 if (listen(serverSockFd_, MAX_LISTEN_NUM) < 0) {
222 NETNATIVE_LOGE("listen errno %{public}d", errno);
223 close(serverSockFd_);
224 return;
225 }
226
227 NETNATIVE_LOGE("begin listen");
228
229 while (true) {
230 sockaddr_un clientAddr = {0};
231 socklen_t len = sizeof(clientAddr);
232
233 int clientSockFd = accept(serverSockFd_, (sockaddr *)&clientAddr, &len);
234 if (clientSockFd < 0) {
235 DNS_CONFIG_PRINT("accept errno %{public}d", errno);
236 continue;
237 }
238 if (!MakeNonBlock(clientSockFd)) {
239 DNS_CONFIG_PRINT("MakeNonBlock errno %{public}d", errno);
240 close(clientSockFd);
241 continue;
242 }
243 if (dnsResolvHandler_ != nullptr) {
244 dnsResolvHandler_->PostSyncTask([this, &clientSockFd]() {
245 this->ProcCommand(clientSockFd);
246 });
247 }
248 }
249 }
250 } // namespace OHOS::nmd
251