• 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 
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