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