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