• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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