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