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 int nSize = (int)iterTag->second.size();
318 if (nSize != 1) {
319 WIFI_LOGE("SetDhcpRange tag %{public}s range size:%{public}d error.", tagName.c_str(), nSize);
320 return DHCP_OPT_FAILED;
321 }
322
323 /* check same network */
324 for (auto iterTagValue : iterTag->second) {
325 if (DhcpFunc::CheckRangeNetwork(ifname, iterTagValue.strStartip, iterTagValue.strEndip) != DHCP_OPT_SUCCESS) {
326 WIFI_LOGE("SetDhcpRange tag CheckRangeNetwork failed, ifname:%{public}s.", ifname.c_str());
327 return DHCP_OPT_FAILED;
328 }
329 }
330
331 /* add dhcp range */
332 auto iterRangeMap = m_mapInfDhcpRange.find(ifname);
333 if (iterRangeMap != m_mapInfDhcpRange.end()) {
334 nSize = (int)iterRangeMap->second.size();
335 if (nSize > 1) {
336 WIFI_LOGE("SetDhcpRange tag failed, %{public}s range size:%{public}d error!", ifname.c_str(), nSize);
337 return DHCP_OPT_FAILED;
338 }
339 if (nSize == 1) {
340 WIFI_LOGW("SetDhcpRange tag %{public}s range size:%{public}d already exist.", ifname.c_str(), nSize);
341 iterRangeMap->second.clear();
342 }
343 WIFI_LOGI("SetDhcpRange tag m_mapInfDhcpRange find ifname:%{public}s, need push_back.", ifname.c_str());
344 for (auto iterTagValue : iterTag->second) {
345 iterRangeMap->second.push_back(iterTagValue);
346 }
347 } else {
348 m_mapInfDhcpRange.emplace(std::make_pair(ifname, iterTag->second));
349 WIFI_LOGI("SetDhcpRange tag no find %{public}s, need emplace %{public}s.", ifname.c_str(), tagName.c_str());
350 }
351
352 /* update or reload interface config file */
353 if (CheckAndUpdateConf(ifname) != DHCP_OPT_SUCCESS) {
354 WIFI_LOGE("SetDhcpRange tag CheckAndUpdateConf failed, ifname:%{public}s.", ifname.c_str());
355 return DHCP_OPT_FAILED;
356 }
357
358 return DHCP_OPT_SUCCESS;
359 }
360
GetLeases(const std::string & ifname,std::vector<std::string> & leases)361 int DhcpServerService::GetLeases(const std::string& ifname, std::vector<std::string> &leases)
362 {
363 if (ifname.empty()) {
364 WIFI_LOGE("DhcpServerService::GetLeases error, ifname is empty!");
365 return DHCP_OPT_ERROR;
366 }
367
368 std::string strFile = DHCP_SERVER_LEASES_FILE + "." + ifname;
369 if (!DhcpFunc::IsExistFile(strFile)) {
370 WIFI_LOGE("GetLeases() failed, dhcp leasefile:%{public}s no exist!", strFile.c_str());
371 return DHCP_OPT_FAILED;
372 }
373
374 leases.clear();
375
376 std::ifstream inFile;
377 inFile.open(strFile);
378 std::string strTemp = "";
379 char tmpLineData[FILE_LINE_MAX_SIZE] = {0};
380 while (inFile.getline(tmpLineData, sizeof(tmpLineData))) {
381 strTemp = tmpLineData;
382 leases.push_back(strTemp);
383 }
384 inFile.close();
385
386 WIFI_LOGI("GetLeases() leases.size:%{public}d.", (int)leases.size());
387 return DHCP_OPT_SUCCESS;
388 }
389
GetDhcpSerProExit(const std::string & ifname,IDhcpResultNotify * pResultNotify)390 int DhcpServerService::GetDhcpSerProExit(const std::string &ifname, IDhcpResultNotify *pResultNotify)
391 {
392 if (ifname.empty()) {
393 WIFI_LOGE("GetDhcpSerProExit() error, ifname is empty!");
394 return DHCP_OPT_FAILED;
395 }
396
397 if (pResultNotify == nullptr) {
398 WIFI_LOGE("GetDhcpSerProExit() error, pResultNotify = nullptr!");
399 return DHCP_OPT_FAILED;
400 }
401
402 auto iterExitNotify = m_mapDhcpSerExitNotify.find(ifname);
403 if (iterExitNotify == m_mapDhcpSerExitNotify.end()) {
404 WIFI_LOGI("GetDhcpSerProExit() SerExitNotify no find ifname:%{public}s, need emplace.", ifname.c_str());
405 m_mapDhcpSerExitNotify.emplace(std::make_pair(ifname, pResultNotify));
406 } else {
407 WIFI_LOGW("GetDhcpSerProExit() SerExitNotify find ifname:%{public}s, not need emplace!", ifname.c_str());
408 }
409
410 if (pDhcpSerProExitThread == nullptr) {
411 pDhcpSerProExitThread = new std::thread(&DhcpServerService::RunDhcpSerProExitThreadFunc, this);
412 if (pDhcpSerProExitThread == nullptr) {
413 WIFI_LOGE("GetDhcpSerProExit() init pDhcpSerProExitThread failed!");
414 return DHCP_OPT_FAILED;
415 }
416 WIFI_LOGI("GetDhcpSerProExit() init pDhcpSerProExitThread success.");
417 }
418
419 return DHCP_OPT_SUCCESS;
420 }
421
ReloadConfig(const std::string & ifname)422 int DhcpServerService::ReloadConfig(const std::string& ifname)
423 {
424 pid_t pidServer = GetDhcpServerPid(ifname);
425 if (pidServer == 0) {
426 WIFI_LOGE("failed to reload config %{public}s", DHCP_SERVER_CONFIG_FILE.c_str());
427 return DHCP_OPT_FAILED;
428 }
429
430 WIFI_LOGI("reload config %{public}s, need restart server:[ %{public}s ], pid:%{public}d.",
431 DHCP_SERVER_CONFIG_FILE.c_str(), DHCP_SERVER_FILE.c_str(), pidServer);
432
433 /* stop dhcp server process */
434 if (StopServer(pidServer) != DHCP_OPT_SUCCESS) {
435 WIFI_LOGE("failed to reload config %{public}s, stop pid:%{public}d error",
436 DHCP_SERVER_CONFIG_FILE.c_str(), pidServer);
437 return DHCP_OPT_FAILED;
438 }
439 SetDhcpServerInfo(ifname, SERVICE_STATUS_STOP, 0);
440
441 sleep(DHCP_NUM_ONE);
442
443 /* restart dhcp server process for load config */
444 if ((pidServer = vfork()) < 0) {
445 WIFI_LOGE("failed to reload config %{public}s, vfork %{public}d error!",
446 DHCP_SERVER_CONFIG_FILE.c_str(), pidServer);
447 return DHCP_OPT_FAILED;
448 }
449 if (pidServer == 0) {
450 /* Child process */
451 std::string localIp, netmask, ipRange;
452 if ((DhcpFunc::GetLocalIp(ifname, localIp, netmask) != DHCP_OPT_SUCCESS) ||
453 (GetUsingIpRange(ifname, ipRange) != DHCP_OPT_SUCCESS)) {
454 return DHCP_OPT_FAILED;
455 }
456 ForkExecProcess(ifname, localIp, netmask, ipRange);
457 } else {
458 /* Parent process */
459 SetDhcpServerInfo(ifname, SERVICE_STATUS_START, pidServer);
460 ForkParentProcess();
461 }
462
463 return DHCP_OPT_SUCCESS;
464 }
465
ForkParentProcess()466 int DhcpServerService::ForkParentProcess()
467 {
468 RegisterSignal();
469 return DHCP_OPT_SUCCESS;
470 }
471
ForkExecProcess(const std::string ifname,const std::string ip,const std::string mask,const std::string pool)472 int DhcpServerService::ForkExecProcess(
473 const std::string ifname, const std::string ip, const std::string mask, const std::string pool)
474 {
475 if (ifname.empty()) {
476 WIFI_LOGE("ForkExecProcess param error, ifname is empty!");
477 return DHCP_OPT_FAILED;
478 }
479 WIFI_LOGI("ForkExecProcess %{public}s %{public}s %{public}s %{public}s %{public}s",
480 DHCP_SERVER_FILE.c_str(), ifname.c_str(), ip.c_str(), mask.c_str(), pool.c_str());
481 char args[DHCP_SER_ARGSNUM][PARAM_MAX_SIZE];
482 char* args2[DHCP_SER_ARGSNUM];
483 if ((memset_s(args, sizeof(args), 0, sizeof(args)) != EOK) ||
484 (memset_s(args2, sizeof(args2), 0, sizeof(args2)) != EOK)) {
485 return DHCP_OPT_FAILED;
486 }
487 int argsIndex = 0;
488 if (strncpy_s(args[argsIndex], PARAM_MAX_SIZE, DHCP_SERVER_FILE.c_str(), DHCP_SERVER_FILE.size()) != EOK) {
489 return DHCP_OPT_FAILED;
490 }
491 std::string strArg = "-i" + ifname;
492 if (strncpy_s(args[++argsIndex], PARAM_MAX_SIZE, strArg.c_str(), strArg.size()) != EOK) {
493 return DHCP_OPT_FAILED;
494 }
495 if (!ip.empty()) {
496 strArg = "-s" + ip;
497 if (strncpy_s(args[++argsIndex], PARAM_MAX_SIZE, strArg.c_str(), strArg.size()) != EOK) {
498 return DHCP_OPT_FAILED;
499 }
500 }
501 if (!mask.empty()) {
502 strArg = "-n" + mask;
503 if (strncpy_s(args[++argsIndex], PARAM_MAX_SIZE, strArg.c_str(), strArg.size()) != EOK) {
504 return DHCP_OPT_FAILED;
505 }
506 }
507 if (!pool.empty()) {
508 strArg = "-P" + pool;
509 if (strncpy_s(args[++argsIndex], PARAM_MAX_SIZE, strArg.c_str(), strArg.size()) != EOK) {
510 return DHCP_OPT_FAILED;
511 }
512 }
513 for (int i = 0; i <= argsIndex; i++) {
514 args2[i] = args[i];
515 }
516 args2[argsIndex + 1] = nullptr;
517 if (execv(args2[0], args2) == -1) {
518 WIFI_LOGE("failed to execv %{public}s %{public}d, err:%{public}s", args2[0], errno, ifname.c_str());
519 }
520 _exit(-1);
521 return DHCP_OPT_SUCCESS;
522 }
523
StopServer(const pid_t & serverPid)524 int DhcpServerService::StopServer(const pid_t &serverPid)
525 {
526 UnregisterSignal();
527 if (kill(serverPid, SIGTERM) == -1) {
528 if (ESRCH == errno) {
529 /* Normal. The subprocess is dead. The SIGCHLD signal triggers the stop hotspot. */
530 WIFI_LOGI("StopServer() kill [%{public}d] success, pro pid no exist, pro:%{public}s.",
531 serverPid, DHCP_SERVER_FILE.c_str());
532 return DHCP_OPT_SUCCESS;
533 }
534 WIFI_LOGE("StopServer() kill [%{public}d] failed, errno:%{public}d!", serverPid, errno);
535 return DHCP_OPT_FAILED;
536 }
537 if (waitpid(serverPid, nullptr, 0) == -1) {
538 WIFI_LOGE("StopServer() waitpid [%{public}d] failed, errno:%{public}d!", serverPid, errno);
539 return DHCP_OPT_FAILED;
540 }
541 WIFI_LOGI("StopServer() waitpid [%{public}d] success, pro:%{public}s!", serverPid, DHCP_SERVER_FILE.c_str());
542 return DHCP_OPT_SUCCESS;
543 }
544
CheckAndUpdateConf(const std::string & ifname)545 int DhcpServerService::CheckAndUpdateConf(const std::string &ifname)
546 {
547 if (ifname.empty()) {
548 WIFI_LOGE("CheckAndUpdateConf error, ifname is empty!");
549 return DHCP_OPT_ERROR;
550 }
551
552 auto iterRangeMap = m_mapInfDhcpRange.find(ifname);
553 if ((iterRangeMap == m_mapInfDhcpRange.end()) || (iterRangeMap->second).empty()) {
554 return DHCP_OPT_SUCCESS;
555 }
556 int nSize = (int)iterRangeMap->second.size();
557 if (nSize > 1) {
558 WIFI_LOGE("CheckAndUpdateConf failed, %{public}s range size:%{public}d error!", ifname.c_str(), nSize);
559 return DHCP_OPT_FAILED;
560 }
561
562 for (auto iterRange : iterRangeMap->second) {
563 if (((iterRange.iptype != 0) && (iterRange.iptype != 1)) || (iterRange.leaseHours <= 0) ||
564 (iterRange.strStartip.size() == 0) || (iterRange.strEndip.size() == 0)) {
565 WIFI_LOGE("CheckAndUpdateConf failed, "
566 "iptype:%{public}d,leaseHours:%{public}d,strStartip:%{private}s,strEndip:%{private}s error!",
567 iterRange.iptype, iterRange.leaseHours, iterRange.strStartip.c_str(), iterRange.strEndip.c_str());
568 return DHCP_OPT_FAILED;
569 }
570 }
571
572 return DHCP_OPT_SUCCESS;
573 }
574
CheckIpAddrRange(const DhcpRange & range)575 bool DhcpServerService::CheckIpAddrRange(const DhcpRange &range)
576 {
577 if (((range.iptype != 0) && (range.iptype != 1)) || range.strStartip.empty() || range.strEndip.empty()) {
578 WIFI_LOGE("CheckIpAddrRange range.iptype:%{public}d,strStartip:%{private}s,strEndip:%{private}s error!",
579 range.iptype, range.strStartip.c_str(), range.strEndip.c_str());
580 return false;
581 }
582
583 if (range.iptype == 0) {
584 uint32_t uStartIp = 0;
585 if (!DhcpFunc::Ip4StrConToInt(range.strStartip, uStartIp)) {
586 WIFI_LOGE("CheckIpAddrRange Ip4StrConToInt failed, range.iptype:%{public}d,strStartip:%{private}s!",
587 range.iptype, range.strStartip.c_str());
588 return false;
589 }
590 uint32_t uEndIp = 0;
591 if (!DhcpFunc::Ip4StrConToInt(range.strEndip, uEndIp)) {
592 WIFI_LOGE("CheckIpAddrRange Ip4StrConToInt failed, range.iptype:%{public}d,strEndip:%{private}s!",
593 range.iptype, range.strEndip.c_str());
594 return false;
595 }
596 /* check ip4 start and end ip */
597 if (uStartIp >= uEndIp) {
598 WIFI_LOGE("CheckIpAddrRange failed, start:%{private}u not less end:%{private}u!", uStartIp, uEndIp);
599 return false;
600 }
601 } else {
602 uint8_t uStartIp6[sizeof(struct in6_addr)] = {0};
603 if (!DhcpFunc::Ip6StrConToChar(range.strStartip, uStartIp6, sizeof(struct in6_addr))) {
604 return false;
605 }
606 uint8_t uEndIp6[sizeof(struct in6_addr)] = {0};
607 if (!DhcpFunc::Ip6StrConToChar(range.strEndip, uEndIp6, sizeof(struct in6_addr))) {
608 return false;
609 }
610 /* check ip6 start and end ip */
611 }
612
613 return true;
614 }
615
AddSpecifiedInterface(const std::string & ifname)616 int DhcpServerService::AddSpecifiedInterface(const std::string& ifname)
617 {
618 if (ifname.empty()) {
619 WIFI_LOGE("AddSpecifiedInterface param error, ifname is empty!");
620 return DHCP_OPT_ERROR;
621 }
622
623 if (m_setInterfaces.find(ifname) == m_setInterfaces.end()) {
624 m_setInterfaces.insert(ifname);
625 WIFI_LOGI("AddSpecifiedInterface started interfaces add %{public}s success.", ifname.c_str());
626 }
627 return DHCP_OPT_SUCCESS;
628 }
629
DelSpecifiedInterface(const std::string & ifname)630 int DhcpServerService::DelSpecifiedInterface(const std::string& ifname)
631 {
632 if (ifname.empty()) {
633 WIFI_LOGE("DelSpecifiedInterface param error, ifname is empty!");
634 return DHCP_OPT_ERROR;
635 }
636
637 auto iterInterfaces = m_setInterfaces.find(ifname);
638 if (iterInterfaces != m_setInterfaces.end()) {
639 m_setInterfaces.erase(iterInterfaces);
640 WIFI_LOGI("DelSpecifiedInterface started interfaces del %{public}s success.", ifname.c_str());
641 }
642 return DHCP_OPT_SUCCESS;
643 }
644
GetUsingIpRange(const std::string ifname,std::string & ipRange)645 int DhcpServerService::GetUsingIpRange(const std::string ifname, std::string& ipRange)
646 {
647 if (ifname.empty()) {
648 WIFI_LOGE("GetUsingIpRange param error, ifname is empty!");
649 return DHCP_OPT_ERROR;
650 }
651
652 auto iterRangeMap = m_mapInfDhcpRange.find(ifname);
653 if (iterRangeMap == m_mapInfDhcpRange.end()) {
654 WIFI_LOGE("GetUsingIpRange failed, inf range map no find %{public}s!", ifname.c_str());
655 return DHCP_OPT_FAILED;
656 }
657 int nSize = (int)iterRangeMap->second.size();
658 if (nSize != 1) {
659 WIFI_LOGE("GetUsingIpRange failed, %{public}s range size:%{public}d error!", ifname.c_str(), nSize);
660 return DHCP_OPT_FAILED;
661 }
662
663 for (auto iterRange : iterRangeMap->second) {
664 if (((iterRange.iptype != 0) && (iterRange.iptype != 1)) || (iterRange.leaseHours <= 0) ||
665 (iterRange.strStartip.size() == 0) || (iterRange.strEndip.size() == 0)) {
666 WIFI_LOGE("GetUsingIpRange type:%{public}d,lease:%{public}d,start:%{private}s,end:%{private}s error!",
667 iterRange.iptype, iterRange.leaseHours, iterRange.strStartip.c_str(), iterRange.strEndip.c_str());
668 return DHCP_OPT_FAILED;
669 }
670 ipRange.clear();
671 ipRange = iterRange.strStartip + "," + iterRange.strEndip;
672 return DHCP_OPT_SUCCESS;
673 }
674 WIFI_LOGE("GetUsingIpRange failed, %{public}s range size:%{public}d", ifname.c_str(), nSize);
675 return DHCP_OPT_FAILED;
676 }
677
CreateDefaultConfigFile(const std::string strFile)678 int DhcpServerService::CreateDefaultConfigFile(const std::string strFile)
679 {
680 if (strFile.empty()) {
681 WIFI_LOGE("CreateDefaultConfigFile param error, strFile is empty!");
682 return DHCP_OPT_ERROR;
683 }
684
685 if (!DhcpFunc::IsExistFile(strFile)) {
686 std::string strData = "leaseTime=" + std::to_string(LEASETIME_DEFAULT * ONE_HOURS_SEC) + "\n";
687 DhcpFunc::CreateFile(strFile, strData);
688 }
689 return DHCP_OPT_SUCCESS;
690 }
691
RunDhcpSerProExitThreadFunc()692 void DhcpServerService::RunDhcpSerProExitThreadFunc()
693 {
694 for (;;) {
695 if (bDhcpSerProExitThread) {
696 WIFI_LOGI("RunDhcpSerProExitThreadFunc() bDhcpSerProExitThread:true, break!");
697 break;
698 }
699 if (m_mapDhcpSerExitNotify.empty()) {
700 sleep(DHCP_NUM_ONE);
701 continue;
702 }
703
704 /* If the dhcp server process exits abnormally, notify other modules. */
705 WIFI_LOGI("RunDhcpSerProExitThreadFunc() other modules have notify reqs, now begin notify...");
706 auto iterNotify = m_mapDhcpSerExitNotify.begin();
707 while (iterNotify != m_mapDhcpSerExitNotify.end()) {
708 std::string ifname = iterNotify->first;
709 if (iterNotify->second == nullptr) {
710 WIFI_LOGE("RunDhcpSerProExitThreadFunc() ifname:%{public}s error, ptr is nullptr!", ifname.c_str());
711 iterNotify = m_mapDhcpSerExitNotify.erase(iterNotify);
712 continue;
713 }
714
715 if (!DhcpServerService::m_mapDhcpServer[ifname].exitSig ||
716 DhcpServerService::m_mapDhcpServer[ifname].normalExit) {
717 WIFI_LOGI("RunDhcpSerProExitThreadFunc() ifname:%{public}s exit status not update", ifname.c_str());
718 ++iterNotify;
719 continue;
720 }
721
722 /* notify other modules */
723 WIFI_LOGI("RunDhcpSerProExitThreadFunc() notify other modules.");
724 iterNotify->second->OnSerExitNotify(ifname);
725 iterNotify = m_mapDhcpSerExitNotify.erase(iterNotify);
726 }
727 WIFI_LOGI("RunDhcpSerProExitThreadFunc() dhcp ser pro exit notify finished.");
728 sleep(DHCP_NUM_ONE);
729 continue;
730 }
731 WIFI_LOGI("RunDhcpSerProExitThreadFunc() end!");
732 }
733
ExitDhcpMgrThreadFunc()734 void DhcpServerService::ExitDhcpMgrThreadFunc()
735 {
736 bDhcpSerProExitThread = true;
737 if (pDhcpSerProExitThread != nullptr) {
738 pDhcpSerProExitThread->join();
739 delete pDhcpSerProExitThread;
740 pDhcpSerProExitThread = nullptr;
741 }
742
743 if (!m_mapDhcpSerExitNotify.empty()) {
744 m_mapDhcpSerExitNotify.clear();
745 }
746 }
747
RegisterSignal() const748 void DhcpServerService::RegisterSignal() const
749 {
750 struct sigaction newAction {};
751
752 if (sigfillset(&newAction.sa_mask) == -1) {
753 WIFI_LOGE("RegisterSignal() failed, sigfillset error:%{public}d!", errno);
754 }
755
756 if (sigdelset(&newAction.sa_mask, SIGCHLD) == -1) {
757 WIFI_LOGE("RegisterSignal() sigdelset SIGCHLD error:%{public}d!", errno);
758 }
759
760 newAction.sa_handler = SigChildHandler;
761 newAction.sa_flags = SA_RESTART;
762 newAction.sa_restorer = nullptr;
763
764 if (sigaction(SIGCHLD, &newAction, nullptr) == -1) {
765 WIFI_LOGE("RegisterSignal() sigaction SIGCHLD error:%{public}d!", errno);
766 }
767 }
768
UnregisterSignal() const769 void DhcpServerService::UnregisterSignal() const
770 {
771 struct sigaction newAction {};
772
773 if (sigemptyset(&newAction.sa_mask) == -1) {
774 WIFI_LOGE("UnregisterSignal() failed, sigemptyset error:%{public}d!", errno);
775 }
776
777 newAction.sa_handler = SIG_DFL;
778 newAction.sa_flags = SA_RESTART;
779 newAction.sa_restorer = nullptr;
780
781 if (sigaction(SIGCHLD, &newAction, nullptr) == -1) {
782 WIFI_LOGE("UnregisterSignal() sigaction SIGCHLD error:%{public}d!", errno);
783 }
784 }
785
SigChildHandler(int signum)786 void DhcpServerService::SigChildHandler(int signum)
787 {
788 if (signum == SIGCHLD) {
789 for (auto &serverItem : DhcpServerService::m_mapDhcpServer) {
790 pid_t pidServer = GetDhcpServerPid(serverItem.first);
791 if (pidServer == 0) {
792 WIFI_LOGE("SigChildHandler failed to get %{public}s pid.", serverItem.first.c_str());
793 continue;
794 }
795 /* Received signal SIGCHLD, wait the dhcp server process pid status. */
796 pid_t childPid = waitpid(pidServer, nullptr, WUNTRACED | WNOHANG);
797 if ((childPid == pidServer) && !serverItem.second.exitSig) {
798 WIFI_LOGW("SigChildHandler dhcp server %{public}s received SIGCHLD.", serverItem.first.c_str());
799 serverItem.second.exitSig = true;
800 }
801 }
802 }
803 }
804
GetDhcpServerPid(const std::string & ifname)805 pid_t DhcpServerService::GetDhcpServerPid(const std::string &ifname)
806 {
807 if (ifname.empty()) {
808 WIFI_LOGE("GetDhcpServerPid error, ifname is empty!");
809 return 0;
810 }
811
812 auto iter = DhcpServerService::m_mapDhcpServer.find(ifname);
813 if (iter == DhcpServerService::m_mapDhcpServer.end()) {
814 WIFI_LOGI("Not get dhcp server ifname:%{public}s, pid:0", ifname.c_str());
815 return 0;
816 }
817
818 WIFI_LOGI("Get dhcp server ifname:%{public}s, pid:%{public}d", ifname.c_str(), (int)iter->second.proPid);
819 return iter->second.proPid;
820 }
821
SetDhcpServerInfo(const std::string & ifname,int status,const pid_t & serverPid)822 int DhcpServerService::SetDhcpServerInfo(const std::string &ifname, int status, const pid_t& serverPid)
823 {
824 if (ifname.empty()) {
825 WIFI_LOGE("SetDhcpServerInfo error, ifname is empty!");
826 return DHCP_OPT_ERROR;
827 }
828 if (status == SERVICE_STATUS_INVALID) {
829 WIFI_LOGE("SetDhcpServerInfo error, status is invalid!");
830 return DHCP_OPT_ERROR;
831 }
832
833 DhcpServerService::m_mapDhcpServer[ifname].proPid = serverPid;
834 if (status == SERVICE_STATUS_START) {
835 DhcpServerService::m_mapDhcpServer[ifname].normalExit = false;
836 DhcpServerService::m_mapDhcpServer[ifname].exitSig = false;
837 } else {
838 DhcpServerService::m_mapDhcpServer[ifname].normalExit = true;
839 }
840 return DHCP_OPT_SUCCESS;
841 }
842 } // namespace Wifi
843 } // namespace OHOS
844