1 /*
2 * Copyright (C) 2021-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 "dhcp_server_service.h"
17
18 #include <unistd.h>
19
20 #include "dhcp_func.h"
21 #include "wifi_logger.h"
22 #include "securec.h"
23
24 DEFINE_WIFILOG_DHCP_LABEL("DhcpServerService");
25
26 namespace OHOS {
27 namespace Wifi {
28 std::map<std::string, DhcpServerInfo> DhcpServerService::m_mapDhcpServer;
DhcpServerService()29 DhcpServerService::DhcpServerService()
30 {
31 m_setInterfaces.clear();
32 m_mapTagDhcpRange.clear();
33 m_mapInfDhcpRange.clear();
34 m_mapDhcpSerExitNotify.clear();
35 bDhcpSerProExitThread = false;
36 pDhcpSerProExitThread = nullptr;
37
38 DhcpFunc::CreateDirs(DHCP_SERVER_CONFIG_DIR);
39 }
40
~DhcpServerService()41 DhcpServerService::~DhcpServerService()
42 {
43 WIFI_LOGI("StartDhcpServer: ~DhcpServerService");
44 StopDhcpServerOnExit();
45 ExitDhcpMgrThreadFunc();
46 }
47
StartDhcpServer(const std::string & ifname)48 int DhcpServerService::StartDhcpServer(const std::string &ifname)
49 {
50 if (ifname.empty()) {
51 WIFI_LOGE("StartDhcpServer error, ifname is empty!");
52 return DHCP_OPT_FAILED;
53 }
54
55 WIFI_LOGI("StartDhcpServer ifname:%{public}s.", ifname.c_str());
56
57 /* Add the specified interface. */
58 if (AddSpecifiedInterface(ifname) != DHCP_OPT_SUCCESS) {
59 return DHCP_OPT_FAILED;
60 }
61
62 if (CreateDefaultConfigFile(DHCP_SERVER_CONFIG_FILE) != DHCP_OPT_SUCCESS) {
63 return DHCP_OPT_FAILED;
64 }
65
66 if (GetDhcpServerPid(ifname) > 0) {
67 WIFI_LOGI("ifname:%{public}s pro already started, now reload config.", ifname.c_str());
68
69 /* reload dhcp server config */
70 return ReloadConfig(ifname);
71 }
72
73 /* start dhcp server process */
74 pid_t pidServer;
75 if ((pidServer = vfork()) < 0) {
76 WIFI_LOGE("StartDhcpServer() vfork() failed, pidServer:%{public}d!", pidServer);
77 return DHCP_OPT_FAILED;
78 }
79 if (pidServer == 0) {
80 /* Child process */
81 std::string localIp, netmask, ipRange;
82 if ((DhcpFunc::GetLocalIp(ifname, localIp, netmask) != DHCP_OPT_SUCCESS) ||
83 (GetUsingIpRange(ifname, ipRange) != DHCP_OPT_SUCCESS)) {
84 return DHCP_OPT_FAILED;
85 }
86 ForkExecProcess(ifname, localIp, netmask, ipRange);
87 } else {
88 /* Parent process */
89 SetDhcpServerInfo(ifname, SERVICE_STATUS_START, pidServer);
90 ForkParentProcess();
91 }
92
93 return DHCP_OPT_SUCCESS;
94 }
95
StopDhcpServer(const std::string & ifname)96 int DhcpServerService::StopDhcpServer(const std::string &ifname)
97 {
98 if (ifname.empty()) {
99 WIFI_LOGE("StopDhcpServer() error, ifname is empty!");
100 return DHCP_OPT_FAILED;
101 }
102
103 pid_t pidServer = GetDhcpServerPid(ifname);
104 if (pidServer == 0) {
105 WIFI_LOGI("StopDhcpServer() %{public}s, %{public}s already stop.", ifname.c_str(), DHCP_SERVER_FILE.c_str());
106 return DHCP_OPT_SUCCESS;
107 }
108 auto iterRangeMap = m_mapInfDhcpRange.find(ifname);
109 if (iterRangeMap != m_mapInfDhcpRange.end()) {
110 m_mapInfDhcpRange.erase(iterRangeMap);
111 }
112 if (RemoveAllDhcpRange(ifname) != DHCP_OPT_SUCCESS) {
113 return DHCP_OPT_FAILED;
114 }
115 if (StopServer(pidServer) != DHCP_OPT_SUCCESS) {
116 return DHCP_OPT_FAILED;
117 }
118 SetDhcpServerInfo(ifname, SERVICE_STATUS_STOP, 0);
119
120 /* Del the specified interface. */
121 if (DelSpecifiedInterface(ifname) != DHCP_OPT_SUCCESS) {
122 return DHCP_OPT_FAILED;
123 }
124
125 return DHCP_OPT_SUCCESS;
126 }
127
StopDhcpServerOnExit()128 int DhcpServerService::StopDhcpServerOnExit()
129 {
130 for (auto& each: m_setInterfaces) {
131 if (each.empty()) {
132 WIFI_LOGE("StopDhcpServer() on exit error, ifname is empty!");
133 continue;
134 }
135
136 pid_t pidServer = GetDhcpServerPid(each);
137 if (pidServer == 0) {
138 WIFI_LOGI("StopDhcpServer() on exit %{public}s already stop.", each.c_str());
139 continue;
140 }
141 auto iterRangeMap = m_mapInfDhcpRange.find(each);
142 if (iterRangeMap != m_mapInfDhcpRange.end()) {
143 m_mapInfDhcpRange.erase(iterRangeMap);
144 }
145 if (RemoveAllDhcpRange(each) != DHCP_OPT_SUCCESS) {
146 WIFI_LOGE("StopDhcpServer() on exit, RemoveAllDhcpRange %{public}s error.", each.c_str());
147 }
148 if (StopServer(pidServer) != DHCP_OPT_SUCCESS) {
149 WIFI_LOGE("StopDhcpServer() on exit error, StopServer %{public}s already stop.", each.c_str());
150 }
151 SetDhcpServerInfo(each, SERVICE_STATUS_STOP, 0);
152 }
153 m_setInterfaces.clear();
154 return DHCP_OPT_SUCCESS;
155 }
156
GetServerStatus()157 int DhcpServerService::GetServerStatus()
158 {
159 return 0;
160 }
161
PutDhcpRange(const std::string & tagName,const DhcpRange & range)162 int DhcpServerService::PutDhcpRange(const std::string &tagName, const DhcpRange &range)
163 {
164 if (tagName.empty()) {
165 WIFI_LOGE("PutDhcpRange param error, tagName is empty!");
166 return DHCP_OPT_ERROR;
167 }
168 if (!CheckIpAddrRange(range)) {
169 WIFI_LOGE("PutDhcpRange tag:%{public}s check range failed.", tagName.c_str());
170 return DHCP_OPT_FAILED;
171 }
172
173 WIFI_LOGI("PutDhcpRange tag:%{public}s.", tagName.c_str());
174
175 /* add dhcp range */
176 auto iterRangeMap = m_mapTagDhcpRange.find(tagName);
177 if (iterRangeMap != m_mapTagDhcpRange.end()) {
178 int nSize = (int)iterRangeMap->second.size();
179 if (nSize > 1) {
180 WIFI_LOGE("PutDhcpRange failed, %{public}s range size:%{public}d error!", tagName.c_str(), nSize);
181 return DHCP_OPT_FAILED;
182 } else if (nSize == 0) {
183 WIFI_LOGI("PutDhcpRange m_mapTagDhcpRange find tagName:%{public}s, need push_back.", tagName.c_str());
184 iterRangeMap->second.push_back(range);
185 return DHCP_OPT_SUCCESS;
186 } else {
187 for (auto tagRange : iterRangeMap->second) {
188 if ((tagRange.iptype != range.iptype) ||
189 (tagRange.strStartip != range.strStartip) || (tagRange.strEndip != range.strEndip)) {
190 continue;
191 }
192 WIFI_LOGW("PutDhcpRange success, %{public}s range already exist", tagName.c_str());
193 return DHCP_OPT_SUCCESS;
194 }
195 WIFI_LOGE("PutDhcpRange failed, %{public}s range size:%{public}d already exist!", tagName.c_str(), nSize);
196 return DHCP_OPT_FAILED;
197 }
198 } else {
199 std::list<DhcpRange> listDhcpRange;
200 listDhcpRange.push_back(range);
201 m_mapTagDhcpRange.emplace(std::make_pair(tagName, listDhcpRange));
202 WIFI_LOGI("PutDhcpRange m_mapTagDhcpRange no find tagName:%{public}s, need emplace.", tagName.c_str());
203 return DHCP_OPT_SUCCESS;
204 }
205 }
206
RemoveDhcpRange(const std::string & tagName,const DhcpRange & range)207 int DhcpServerService::RemoveDhcpRange(const std::string &tagName, const DhcpRange &range)
208 {
209 if (tagName.empty()) {
210 WIFI_LOGE("RemoveDhcpRange param error, tagName is empty!");
211 return DHCP_OPT_ERROR;
212 }
213
214 /* remove dhcp range */
215 auto iterRangeMap = m_mapTagDhcpRange.find(tagName);
216 if (iterRangeMap != m_mapTagDhcpRange.end()) {
217 auto iterRange = m_mapTagDhcpRange[tagName].begin();
218 while (iterRange != m_mapTagDhcpRange[tagName].end()) {
219 if ((iterRange->iptype == range.iptype) && (iterRange->strStartip == range.strStartip) &&
220 (iterRange->strEndip == range.strEndip)) {
221 m_mapTagDhcpRange[tagName].erase(iterRange++);
222 WIFI_LOGI("RemoveDhcpRange find tagName:%{public}s, "
223 "range.iptype:%{public}d,strStartip:%{private}s,strEndip:%{private}s, erase.",
224 tagName.c_str(),
225 range.iptype,
226 range.strStartip.c_str(),
227 range.strEndip.c_str());
228 return DHCP_OPT_SUCCESS;
229 }
230 iterRange++;
231 }
232 WIFI_LOGE("RemoveDhcpRange find tagName:%{public}s, second no find range, erase failed!", tagName.c_str());
233 } else {
234 WIFI_LOGE("RemoveDhcpRange no find tagName:%{public}s, erase failed!", tagName.c_str());
235 }
236
237 return DHCP_OPT_FAILED;
238 }
239
RemoveAllDhcpRange(const std::string & tagName)240 int DhcpServerService::RemoveAllDhcpRange(const std::string &tagName)
241 {
242 if (tagName.empty()) {
243 WIFI_LOGE("RemoveAllDhcpRange param error, tagName is empty!");
244 return DHCP_OPT_ERROR;
245 }
246
247 /* remove all dhcp range */
248 auto iterRangeMap = m_mapTagDhcpRange.find(tagName);
249 if (iterRangeMap != m_mapTagDhcpRange.end()) {
250 m_mapTagDhcpRange.erase(iterRangeMap);
251 WIFI_LOGI("RemoveAllDhcpRange find tagName:%{public}s, erase success.", tagName.c_str());
252 } else {
253 WIFI_LOGI("RemoveAllDhcpRange no find tagName:%{public}s, not need erase!", tagName.c_str());
254 }
255
256 return DHCP_OPT_SUCCESS;
257 }
258
SetDhcpRange(const std::string & ifname,const DhcpRange & range)259 int DhcpServerService::SetDhcpRange(const std::string &ifname, const DhcpRange &range)
260 {
261 /* put dhcp range */
262 if (PutDhcpRange(ifname, range) != DHCP_OPT_SUCCESS) {
263 WIFI_LOGE("SetDhcpRange PutDhcpRange failed, ifname:%{public}s.", ifname.c_str());
264 return DHCP_OPT_FAILED;
265 }
266
267 /* check same network */
268 if (DhcpFunc::CheckRangeNetwork(ifname, range.strStartip, range.strEndip) != DHCP_OPT_SUCCESS) {
269 WIFI_LOGE("SetDhcpRange CheckRangeNetwork failed, ifname:%{public}s.", ifname.c_str());
270 RemoveDhcpRange(ifname, range);
271 return DHCP_OPT_FAILED;
272 }
273
274 /* add dhcp range */
275 auto iterRangeMap = m_mapInfDhcpRange.find(ifname);
276 if (iterRangeMap != m_mapInfDhcpRange.end()) {
277 int nSize = (int)iterRangeMap->second.size();
278 if (nSize > 1) {
279 WIFI_LOGE("SetDhcpRange failed, %{public}s range size:%{public}d error!", ifname.c_str(), nSize);
280 RemoveDhcpRange(ifname, range);
281 return DHCP_OPT_FAILED;
282 }
283 if (nSize == 1) {
284 WIFI_LOGW("SetDhcpRange %{public}s range size:%{public}d already exist.", ifname.c_str(), nSize);
285 iterRangeMap->second.clear();
286 }
287 WIFI_LOGI("SetDhcpRange m_mapInfDhcpRange find ifname:%{public}s, need push_back.", ifname.c_str());
288 iterRangeMap->second.push_back(range);
289 } else {
290 std::list<DhcpRange> listDhcpRange;
291 listDhcpRange.push_back(range);
292 m_mapInfDhcpRange.emplace(std::make_pair(ifname, listDhcpRange));
293 WIFI_LOGI("SetDhcpRange m_mapInfDhcpRange no find ifname:%{public}s, need emplace.", ifname.c_str());
294 }
295
296 if (CheckAndUpdateConf(ifname) != DHCP_OPT_SUCCESS) {
297 WIFI_LOGE("SetDhcpRange() CheckAndUpdateConf failed, ifname:%{public}s.", ifname.c_str());
298 RemoveDhcpRange(ifname, range);
299 return DHCP_OPT_FAILED;
300 }
301
302 return DHCP_OPT_SUCCESS;
303 }
304
SetDhcpRange(const std::string & ifname,const std::string & tagName)305 int DhcpServerService::SetDhcpRange(const std::string &ifname, const std::string &tagName)
306 {
307 if (ifname.empty() || tagName.empty()) {
308 WIFI_LOGE("SetDhcpRange failed, ifname or tagName is empty!");
309 return DHCP_OPT_FAILED;
310 }
311
312 auto iterTag = m_mapTagDhcpRange.find(tagName);
313 if (iterTag == m_mapTagDhcpRange.end()) {
314 WIFI_LOGE("SetDhcpRange tag m_mapTagDhcpRange no find tagName:%{public}s.", tagName.c_str());
315 return DHCP_OPT_FAILED;
316 }
317
318 int nSize = (int)iterTag->second.size();
319 if (nSize != 1) {
320 WIFI_LOGE("SetDhcpRange tag %{public}s range size:%{public}d error.", tagName.c_str(), nSize);
321 return DHCP_OPT_FAILED;
322 }
323
324 /* check same network */
325 for (auto iterTagValue : iterTag->second) {
326 if (DhcpFunc::CheckRangeNetwork(ifname, iterTagValue.strStartip, iterTagValue.strEndip) != DHCP_OPT_SUCCESS) {
327 WIFI_LOGE("SetDhcpRange tag CheckRangeNetwork failed, ifname:%{public}s.", ifname.c_str());
328 return DHCP_OPT_FAILED;
329 }
330 }
331
332 /* add dhcp range */
333 auto iterRangeMap = m_mapInfDhcpRange.find(ifname);
334 if (iterRangeMap != m_mapInfDhcpRange.end()) {
335 nSize = (int)iterRangeMap->second.size();
336 if (nSize > 1) {
337 WIFI_LOGE("SetDhcpRange tag failed, %{public}s range size:%{public}d error!", ifname.c_str(), nSize);
338 return DHCP_OPT_FAILED;
339 }
340 if (nSize == 1) {
341 WIFI_LOGW("SetDhcpRange tag %{public}s range size:%{public}d already exist.", ifname.c_str(), nSize);
342 iterRangeMap->second.clear();
343 }
344 WIFI_LOGI("SetDhcpRange tag m_mapInfDhcpRange find ifname:%{public}s, need push_back.", ifname.c_str());
345 for (auto iterTagValue : iterTag->second) {
346 iterRangeMap->second.push_back(iterTagValue);
347 }
348 } else {
349 m_mapInfDhcpRange.emplace(std::make_pair(ifname, iterTag->second));
350 WIFI_LOGI("SetDhcpRange tag no find %{public}s, need emplace %{public}s.", ifname.c_str(), tagName.c_str());
351 }
352
353 /* update or reload interface config file */
354 if (CheckAndUpdateConf(ifname) != DHCP_OPT_SUCCESS) {
355 WIFI_LOGE("SetDhcpRange tag CheckAndUpdateConf failed, ifname:%{public}s.", ifname.c_str());
356 return DHCP_OPT_FAILED;
357 }
358
359 return DHCP_OPT_SUCCESS;
360 }
361
GetLeases(const std::string & ifname,std::vector<std::string> & leases)362 int DhcpServerService::GetLeases(const std::string& ifname, std::vector<std::string> &leases)
363 {
364 if (ifname.empty()) {
365 WIFI_LOGE("DhcpServerService::GetLeases error, ifname is empty!");
366 return DHCP_OPT_ERROR;
367 }
368
369 std::string strFile = DHCP_SERVER_LEASES_FILE + "." + ifname;
370 if (!DhcpFunc::IsExistFile(strFile)) {
371 WIFI_LOGE("GetLeases() failed, dhcp leasefile:%{public}s no exist!", strFile.c_str());
372 return DHCP_OPT_FAILED;
373 }
374
375 leases.clear();
376
377 std::ifstream inFile;
378 inFile.open(strFile);
379 std::string strTemp = "";
380 char tmpLineData[FILE_LINE_MAX_SIZE] = {0};
381 while (inFile.getline(tmpLineData, sizeof(tmpLineData))) {
382 strTemp = tmpLineData;
383 leases.push_back(strTemp);
384 }
385 inFile.close();
386
387 WIFI_LOGI("GetLeases() leases.size:%{public}d.", (int)leases.size());
388 return DHCP_OPT_SUCCESS;
389 }
390
GetDhcpSerProExit(const std::string & ifname,IDhcpResultNotify * pResultNotify)391 int DhcpServerService::GetDhcpSerProExit(const std::string &ifname, IDhcpResultNotify *pResultNotify)
392 {
393 if (ifname.empty()) {
394 WIFI_LOGE("GetDhcpSerProExit() error, ifname is empty!");
395 return DHCP_OPT_FAILED;
396 }
397
398 if (pResultNotify == nullptr) {
399 WIFI_LOGE("GetDhcpSerProExit() error, pResultNotify = nullptr!");
400 return DHCP_OPT_FAILED;
401 }
402
403 auto iterExitNotify = m_mapDhcpSerExitNotify.find(ifname);
404 if (iterExitNotify == m_mapDhcpSerExitNotify.end()) {
405 WIFI_LOGI("GetDhcpSerProExit() SerExitNotify no find ifname:%{public}s, need emplace.", ifname.c_str());
406 m_mapDhcpSerExitNotify.emplace(std::make_pair(ifname, pResultNotify));
407 } else {
408 WIFI_LOGW("GetDhcpSerProExit() SerExitNotify find ifname:%{public}s, not need emplace!", ifname.c_str());
409 }
410
411 if (pDhcpSerProExitThread == nullptr) {
412 pDhcpSerProExitThread = new std::thread(&DhcpServerService::RunDhcpSerProExitThreadFunc, this);
413 if (pDhcpSerProExitThread == nullptr) {
414 WIFI_LOGE("GetDhcpSerProExit() init pDhcpSerProExitThread failed!");
415 return DHCP_OPT_FAILED;
416 }
417 WIFI_LOGI("GetDhcpSerProExit() init pDhcpSerProExitThread success.");
418 }
419
420 return DHCP_OPT_SUCCESS;
421 }
422
ReloadConfig(const std::string & ifname)423 int DhcpServerService::ReloadConfig(const std::string& ifname)
424 {
425 pid_t pidServer = GetDhcpServerPid(ifname);
426 if (pidServer == 0) {
427 WIFI_LOGE("failed to reload config %{public}s", DHCP_SERVER_CONFIG_FILE.c_str());
428 return DHCP_OPT_FAILED;
429 }
430
431 WIFI_LOGI("reload config %{public}s, need restart server:[ %{public}s ], pid:%{public}d.",
432 DHCP_SERVER_CONFIG_FILE.c_str(), DHCP_SERVER_FILE.c_str(), pidServer);
433
434 /* stop dhcp server process */
435 if (StopServer(pidServer) != DHCP_OPT_SUCCESS) {
436 WIFI_LOGE("failed to reload config %{public}s, stop pid:%{public}d error",
437 DHCP_SERVER_CONFIG_FILE.c_str(), pidServer);
438 return DHCP_OPT_FAILED;
439 }
440 SetDhcpServerInfo(ifname, SERVICE_STATUS_STOP, 0);
441
442 sleep(DHCP_NUM_ONE);
443
444 /* restart dhcp server process for load config */
445 if ((pidServer = vfork()) < 0) {
446 WIFI_LOGE("failed to reload config %{public}s, vfork %{public}d error!",
447 DHCP_SERVER_CONFIG_FILE.c_str(), pidServer);
448 return DHCP_OPT_FAILED;
449 }
450 if (pidServer == 0) {
451 /* Child process */
452 std::string localIp, netmask, ipRange;
453 if ((DhcpFunc::GetLocalIp(ifname, localIp, netmask) != DHCP_OPT_SUCCESS) ||
454 (GetUsingIpRange(ifname, ipRange) != DHCP_OPT_SUCCESS)) {
455 return DHCP_OPT_FAILED;
456 }
457 ForkExecProcess(ifname, localIp, netmask, ipRange);
458 } else {
459 /* Parent process */
460 SetDhcpServerInfo(ifname, SERVICE_STATUS_START, pidServer);
461 ForkParentProcess();
462 }
463
464 return DHCP_OPT_SUCCESS;
465 }
466
ForkParentProcess()467 int DhcpServerService::ForkParentProcess()
468 {
469 RegisterSignal();
470 return DHCP_OPT_SUCCESS;
471 }
472
ForkExecProcess(const std::string ifname,const std::string ip,const std::string mask,const std::string pool)473 int DhcpServerService::ForkExecProcess(
474 const std::string ifname, const std::string ip, const std::string mask, const std::string pool)
475 {
476 if (ifname.empty()) {
477 WIFI_LOGE("ForkExecProcess param error, ifname is empty!");
478 return DHCP_OPT_FAILED;
479 }
480 WIFI_LOGI("ForkExecProcess %{public}s %{public}s %{public}s %{public}s %{public}s",
481 DHCP_SERVER_FILE.c_str(), ifname.c_str(), ip.c_str(), mask.c_str(), pool.c_str());
482 char args[DHCP_SER_ARGSNUM][PARAM_MAX_SIZE];
483 char* args2[DHCP_SER_ARGSNUM];
484 if ((memset_s(args, sizeof(args), 0, sizeof(args)) != EOK) ||
485 (memset_s(args2, sizeof(args2), 0, sizeof(args2)) != EOK)) {
486 return DHCP_OPT_FAILED;
487 }
488 int argsIndex = 0;
489 if (strncpy_s(args[argsIndex], PARAM_MAX_SIZE, DHCP_SERVER_FILE.c_str(), DHCP_SERVER_FILE.size()) != EOK) {
490 return DHCP_OPT_FAILED;
491 }
492 std::string strArg = "-i" + ifname;
493 if (strncpy_s(args[++argsIndex], PARAM_MAX_SIZE, strArg.c_str(), strArg.size()) != EOK) {
494 return DHCP_OPT_FAILED;
495 }
496 if (!ip.empty()) {
497 strArg = "-s" + ip;
498 if (strncpy_s(args[++argsIndex], PARAM_MAX_SIZE, strArg.c_str(), strArg.size()) != EOK) {
499 return DHCP_OPT_FAILED;
500 }
501 }
502 if (!mask.empty()) {
503 strArg = "-n" + mask;
504 if (strncpy_s(args[++argsIndex], PARAM_MAX_SIZE, strArg.c_str(), strArg.size()) != EOK) {
505 return DHCP_OPT_FAILED;
506 }
507 }
508 if (!pool.empty()) {
509 strArg = "-P" + pool;
510 if (strncpy_s(args[++argsIndex], PARAM_MAX_SIZE, strArg.c_str(), strArg.size()) != EOK) {
511 return DHCP_OPT_FAILED;
512 }
513 }
514 for (int i = 0; i <= argsIndex; i++) {
515 args2[i] = args[i];
516 }
517 args2[argsIndex + 1] = nullptr;
518 if (execv(args2[0], args2) == -1) {
519 WIFI_LOGE("failed to execv %{public}s %{public}d, err:%{public}s", args2[0], errno, ifname.c_str());
520 }
521 _exit(-1);
522 return DHCP_OPT_SUCCESS;
523 }
524
StopServer(const pid_t & serverPid)525 int DhcpServerService::StopServer(const pid_t &serverPid)
526 {
527 UnregisterSignal();
528 if (kill(serverPid, SIGTERM) == -1) {
529 if (ESRCH == errno) {
530 /* Normal. The subprocess is dead. The SIGCHLD signal triggers the stop hotspot. */
531 WIFI_LOGI("StopServer() kill [%{public}d] success, pro pid no exist, pro:%{public}s.",
532 serverPid, DHCP_SERVER_FILE.c_str());
533 return DHCP_OPT_SUCCESS;
534 }
535 WIFI_LOGE("StopServer() kill [%{public}d] failed, errno:%{public}d!", serverPid, errno);
536 return DHCP_OPT_FAILED;
537 }
538 if (waitpid(serverPid, nullptr, 0) == -1) {
539 WIFI_LOGE("StopServer() waitpid [%{public}d] failed, errno:%{public}d!", serverPid, errno);
540 return DHCP_OPT_FAILED;
541 }
542 WIFI_LOGI("StopServer() waitpid [%{public}d] success, pro:%{public}s!", serverPid, DHCP_SERVER_FILE.c_str());
543 return DHCP_OPT_SUCCESS;
544 }
545
CheckAndUpdateConf(const std::string & ifname)546 int DhcpServerService::CheckAndUpdateConf(const std::string &ifname)
547 {
548 if (ifname.empty()) {
549 WIFI_LOGE("CheckAndUpdateConf error, ifname is empty!");
550 return DHCP_OPT_ERROR;
551 }
552
553 auto iterRangeMap = m_mapInfDhcpRange.find(ifname);
554 if ((iterRangeMap == m_mapInfDhcpRange.end()) || (iterRangeMap->second).empty()) {
555 return DHCP_OPT_SUCCESS;
556 }
557 int nSize = (int)iterRangeMap->second.size();
558 if (nSize > 1) {
559 WIFI_LOGE("CheckAndUpdateConf failed, %{public}s range size:%{public}d error!", ifname.c_str(), nSize);
560 return DHCP_OPT_FAILED;
561 }
562
563 for (auto iterRange : iterRangeMap->second) {
564 if (((iterRange.iptype != 0) && (iterRange.iptype != 1)) || (iterRange.leaseHours <= 0) ||
565 (iterRange.strStartip.size() == 0) || (iterRange.strEndip.size() == 0)) {
566 WIFI_LOGE("CheckAndUpdateConf failed, "
567 "iptype:%{public}d,leaseHours:%{public}d,strStartip:%{private}s,strEndip:%{private}s error!",
568 iterRange.iptype, iterRange.leaseHours, iterRange.strStartip.c_str(), iterRange.strEndip.c_str());
569 return DHCP_OPT_FAILED;
570 }
571 }
572
573 return DHCP_OPT_SUCCESS;
574 }
575
CheckIpAddrRange(const DhcpRange & range)576 bool DhcpServerService::CheckIpAddrRange(const DhcpRange &range)
577 {
578 if (((range.iptype != 0) && (range.iptype != 1)) || range.strStartip.empty() || range.strEndip.empty()) {
579 WIFI_LOGE("CheckIpAddrRange range.iptype:%{public}d,strStartip:%{private}s,strEndip:%{private}s error!",
580 range.iptype, range.strStartip.c_str(), range.strEndip.c_str());
581 return false;
582 }
583
584 if (range.iptype == 0) {
585 uint32_t uStartIp = 0;
586 if (!DhcpFunc::Ip4StrConToInt(range.strStartip, uStartIp)) {
587 WIFI_LOGE("CheckIpAddrRange Ip4StrConToInt failed, range.iptype:%{public}d,strStartip:%{private}s!",
588 range.iptype, range.strStartip.c_str());
589 return false;
590 }
591 uint32_t uEndIp = 0;
592 if (!DhcpFunc::Ip4StrConToInt(range.strEndip, uEndIp)) {
593 WIFI_LOGE("CheckIpAddrRange Ip4StrConToInt failed, range.iptype:%{public}d,strEndip:%{private}s!",
594 range.iptype, range.strEndip.c_str());
595 return false;
596 }
597 /* check ip4 start and end ip */
598 if (uStartIp >= uEndIp) {
599 WIFI_LOGE("CheckIpAddrRange failed, start:%{private}u not less end:%{private}u!", uStartIp, uEndIp);
600 return false;
601 }
602 } else {
603 uint8_t uStartIp6[sizeof(struct in6_addr)] = {0};
604 if (!DhcpFunc::Ip6StrConToChar(range.strStartip, uStartIp6, sizeof(struct in6_addr))) {
605 return false;
606 }
607 uint8_t uEndIp6[sizeof(struct in6_addr)] = {0};
608 if (!DhcpFunc::Ip6StrConToChar(range.strEndip, uEndIp6, sizeof(struct in6_addr))) {
609 return false;
610 }
611 /* check ip6 start and end ip */
612 }
613
614 return true;
615 }
616
AddSpecifiedInterface(const std::string & ifname)617 int DhcpServerService::AddSpecifiedInterface(const std::string& ifname)
618 {
619 if (ifname.empty()) {
620 WIFI_LOGE("AddSpecifiedInterface param error, ifname is empty!");
621 return DHCP_OPT_ERROR;
622 }
623
624 if (m_setInterfaces.find(ifname) == m_setInterfaces.end()) {
625 m_setInterfaces.insert(ifname);
626 WIFI_LOGI("AddSpecifiedInterface started interfaces add %{public}s success.", ifname.c_str());
627 }
628 return DHCP_OPT_SUCCESS;
629 }
630
DelSpecifiedInterface(const std::string & ifname)631 int DhcpServerService::DelSpecifiedInterface(const std::string& ifname)
632 {
633 if (ifname.empty()) {
634 WIFI_LOGE("DelSpecifiedInterface param error, ifname is empty!");
635 return DHCP_OPT_ERROR;
636 }
637
638 auto iterInterfaces = m_setInterfaces.find(ifname);
639 if (iterInterfaces != m_setInterfaces.end()) {
640 m_setInterfaces.erase(iterInterfaces);
641 WIFI_LOGI("DelSpecifiedInterface started interfaces del %{public}s success.", ifname.c_str());
642 }
643 return DHCP_OPT_SUCCESS;
644 }
645
GetUsingIpRange(const std::string ifname,std::string & ipRange)646 int DhcpServerService::GetUsingIpRange(const std::string ifname, std::string& ipRange)
647 {
648 if (ifname.empty()) {
649 WIFI_LOGE("GetUsingIpRange param error, ifname is empty!");
650 return DHCP_OPT_ERROR;
651 }
652
653 auto iterRangeMap = m_mapInfDhcpRange.find(ifname);
654 if (iterRangeMap == m_mapInfDhcpRange.end()) {
655 WIFI_LOGE("GetUsingIpRange failed, inf range map no find %{public}s!", ifname.c_str());
656 return DHCP_OPT_FAILED;
657 }
658 int nSize = (int)iterRangeMap->second.size();
659 if (nSize != 1) {
660 WIFI_LOGE("GetUsingIpRange failed, %{public}s range size:%{public}d error!", ifname.c_str(), nSize);
661 return DHCP_OPT_FAILED;
662 }
663
664 for (auto iterRange : iterRangeMap->second) {
665 if (((iterRange.iptype != 0) && (iterRange.iptype != 1)) || (iterRange.leaseHours <= 0) ||
666 (iterRange.strStartip.size() == 0) || (iterRange.strEndip.size() == 0)) {
667 WIFI_LOGE("GetUsingIpRange type:%{public}d,lease:%{public}d,start:%{private}s,end:%{private}s error!",
668 iterRange.iptype, iterRange.leaseHours, iterRange.strStartip.c_str(), iterRange.strEndip.c_str());
669 return DHCP_OPT_FAILED;
670 }
671 ipRange.clear();
672 ipRange = iterRange.strStartip + "," + iterRange.strEndip;
673 return DHCP_OPT_SUCCESS;
674 }
675 WIFI_LOGE("GetUsingIpRange failed, %{public}s range size:%{public}d", ifname.c_str(), nSize);
676 return DHCP_OPT_FAILED;
677 }
678
CreateDefaultConfigFile(const std::string strFile)679 int DhcpServerService::CreateDefaultConfigFile(const std::string strFile)
680 {
681 if (strFile.empty()) {
682 WIFI_LOGE("CreateDefaultConfigFile param error, strFile is empty!");
683 return DHCP_OPT_ERROR;
684 }
685
686 if (!DhcpFunc::IsExistFile(strFile)) {
687 std::string strData = "leaseTime=" + std::to_string(LEASETIME_DEFAULT * ONE_HOURS_SEC) + "\n";
688 DhcpFunc::CreateFile(strFile, strData);
689 }
690 return DHCP_OPT_SUCCESS;
691 }
692
RunDhcpSerProExitThreadFunc()693 void DhcpServerService::RunDhcpSerProExitThreadFunc()
694 {
695 for (;;) {
696 if (bDhcpSerProExitThread) {
697 WIFI_LOGI("RunDhcpSerProExitThreadFunc() bDhcpSerProExitThread:true, break!");
698 break;
699 }
700 if (m_mapDhcpSerExitNotify.empty()) {
701 sleep(DHCP_NUM_ONE);
702 continue;
703 }
704
705 /* If the dhcp server process exits abnormally, notify other modules. */
706 WIFI_LOGI("RunDhcpSerProExitThreadFunc() other modules have notify reqs, now begin notify...");
707 auto iterNotify = m_mapDhcpSerExitNotify.begin();
708 while (iterNotify != m_mapDhcpSerExitNotify.end()) {
709 std::string ifname = iterNotify->first;
710 if (iterNotify->second == nullptr) {
711 WIFI_LOGE("RunDhcpSerProExitThreadFunc() ifname:%{public}s error, ptr is nullptr!", ifname.c_str());
712 iterNotify = m_mapDhcpSerExitNotify.erase(iterNotify);
713 continue;
714 }
715
716 if (!DhcpServerService::m_mapDhcpServer[ifname].exitSig ||
717 DhcpServerService::m_mapDhcpServer[ifname].normalExit) {
718 WIFI_LOGI("RunDhcpSerProExitThreadFunc() ifname:%{public}s exit status not update", ifname.c_str());
719 ++iterNotify;
720 continue;
721 }
722
723 /* notify other modules */
724 WIFI_LOGI("RunDhcpSerProExitThreadFunc() notify other modules.");
725 iterNotify->second->OnSerExitNotify(ifname);
726 iterNotify = m_mapDhcpSerExitNotify.erase(iterNotify);
727 }
728 WIFI_LOGI("RunDhcpSerProExitThreadFunc() dhcp ser pro exit notify finished.");
729 sleep(DHCP_NUM_ONE);
730 continue;
731 }
732 WIFI_LOGI("RunDhcpSerProExitThreadFunc() end!");
733 }
734
ExitDhcpMgrThreadFunc()735 void DhcpServerService::ExitDhcpMgrThreadFunc()
736 {
737 bDhcpSerProExitThread = true;
738 if (pDhcpSerProExitThread != nullptr) {
739 pDhcpSerProExitThread->join();
740 delete pDhcpSerProExitThread;
741 pDhcpSerProExitThread = nullptr;
742 }
743
744 if (!m_mapDhcpSerExitNotify.empty()) {
745 m_mapDhcpSerExitNotify.clear();
746 }
747 }
748
RegisterSignal() const749 void DhcpServerService::RegisterSignal() const
750 {
751 struct sigaction newAction {};
752
753 if (sigfillset(&newAction.sa_mask) == -1) {
754 WIFI_LOGE("RegisterSignal() failed, sigfillset error:%{public}d!", errno);
755 }
756
757 if (sigdelset(&newAction.sa_mask, SIGCHLD) == -1) {
758 WIFI_LOGE("RegisterSignal() sigdelset SIGCHLD error:%{public}d!", errno);
759 }
760
761 newAction.sa_handler = SigChildHandler;
762 newAction.sa_flags = SA_RESTART;
763 newAction.sa_restorer = nullptr;
764
765 if (sigaction(SIGCHLD, &newAction, nullptr) == -1) {
766 WIFI_LOGE("RegisterSignal() sigaction SIGCHLD error:%{public}d!", errno);
767 }
768 }
769
UnregisterSignal() const770 void DhcpServerService::UnregisterSignal() const
771 {
772 struct sigaction newAction {};
773
774 if (sigemptyset(&newAction.sa_mask) == -1) {
775 WIFI_LOGE("UnregisterSignal() failed, sigemptyset error:%{public}d!", errno);
776 }
777
778 newAction.sa_handler = SIG_DFL;
779 newAction.sa_flags = SA_RESTART;
780 newAction.sa_restorer = nullptr;
781
782 if (sigaction(SIGCHLD, &newAction, nullptr) == -1) {
783 WIFI_LOGE("UnregisterSignal() sigaction SIGCHLD error:%{public}d!", errno);
784 }
785 }
786
SigChildHandler(int signum)787 void DhcpServerService::SigChildHandler(int signum)
788 {
789 if (signum == SIGCHLD) {
790 for (auto &serverItem : DhcpServerService::m_mapDhcpServer) {
791 pid_t pidServer = GetDhcpServerPid(serverItem.first);
792 if (pidServer == 0) {
793 WIFI_LOGE("SigChildHandler failed to get %{public}s pid.", serverItem.first.c_str());
794 continue;
795 }
796 /* Received signal SIGCHLD, wait the dhcp server process pid status. */
797 pid_t childPid = waitpid(pidServer, nullptr, WUNTRACED | WNOHANG);
798 if ((childPid == pidServer) && !serverItem.second.exitSig) {
799 WIFI_LOGW("SigChildHandler dhcp server %{public}s received SIGCHLD.", serverItem.first.c_str());
800 serverItem.second.exitSig = true;
801 }
802 }
803 }
804 }
805
GetDhcpServerPid(const std::string & ifname)806 pid_t DhcpServerService::GetDhcpServerPid(const std::string &ifname)
807 {
808 if (ifname.empty()) {
809 WIFI_LOGE("GetDhcpServerPid error, ifname is empty!");
810 return 0;
811 }
812
813 auto iter = DhcpServerService::m_mapDhcpServer.find(ifname);
814 if (iter == DhcpServerService::m_mapDhcpServer.end()) {
815 WIFI_LOGI("Not get dhcp server ifname:%{public}s, pid:0", ifname.c_str());
816 return 0;
817 }
818
819 WIFI_LOGI("Get dhcp server ifname:%{public}s, pid:%{public}d", ifname.c_str(), (int)iter->second.proPid);
820 return iter->second.proPid;
821 }
822
SetDhcpServerInfo(const std::string & ifname,int status,const pid_t & serverPid)823 int DhcpServerService::SetDhcpServerInfo(const std::string &ifname, int status, const pid_t& serverPid)
824 {
825 if (ifname.empty()) {
826 WIFI_LOGE("SetDhcpServerInfo error, ifname is empty!");
827 return DHCP_OPT_ERROR;
828 }
829 if (status == SERVICE_STATUS_INVALID) {
830 WIFI_LOGE("SetDhcpServerInfo error, status is invalid!");
831 return DHCP_OPT_ERROR;
832 }
833
834 DhcpServerService::m_mapDhcpServer[ifname].proPid = serverPid;
835 if (status == SERVICE_STATUS_START) {
836 DhcpServerService::m_mapDhcpServer[ifname].normalExit = false;
837 DhcpServerService::m_mapDhcpServer[ifname].exitSig = false;
838 } else {
839 DhcpServerService::m_mapDhcpServer[ifname].normalExit = true;
840 }
841 return DHCP_OPT_SUCCESS;
842 }
843 } // namespace Wifi
844 } // namespace OHOS
845