• 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 #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