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