• 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_client_service_impl.h"
17 
18 #include <sys/types.h>
19 #include <sys/wait.h>
20 #include <unistd.h>
21 #include <vector>
22 
23 #include "dhcp_func.h"
24 #include "securec.h"
25 #include "wifi_logger.h"
26 #include "dhcp_event_subscriber.h"
27 
28 namespace OHOS {
29 namespace Wifi {
30 DEFINE_WIFILOG_DHCP_LABEL("DhcpClientServiceImpl");
31 
32 pthread_mutex_t DhcpClientServiceImpl::m_DhcpResultInfoMutex;
33 std::map<std::string, std::vector<DhcpResult>> DhcpClientServiceImpl::m_mapDhcpResult;
34 std::map<std::string, DhcpServiceInfo> DhcpClientServiceImpl::m_mapDhcpInfo;
DhcpClientServiceImpl()35 DhcpClientServiceImpl::DhcpClientServiceImpl()
36 {
37     pthread_mutex_init(&m_DhcpResultInfoMutex, NULL);
38     isExitDhcpResultHandleThread = false;
39     pDhcpResultHandleThread = nullptr;
40     pDhcpIpv6ClientThread = nullptr;
41 #ifdef OHOS_ARCH_LITE
42     m_mapDhcpRecvMsgThread.clear();
43 #endif
44     if (!m_mapDhcpResultNotify.empty()) {
45         ReleaseResultNotifyMemory();
46         m_mapDhcpResultNotify.clear();
47     }
48     m_mapEventSubscriber.clear();
49     InitDhcpMgrThread();
50     DhcpFunc::CreateDirs(DHCP_WORK_DIR);
51     using namespace std::placeholders;
52     ipv6Client.SetCallback(std::bind(&DhcpClientServiceImpl::OnAddressChangedCallback, this, _1, _2));
53 }
54 
~DhcpClientServiceImpl()55 DhcpClientServiceImpl::~DhcpClientServiceImpl()
56 {
57     std::unique_lock<std::mutex> lock(m_subscriberMutex);
58     if (!m_mapEventSubscriber.empty()) {
59         WIFI_LOGE("DhcpClientServiceImpl destructor mapEventSubscriber is not empty!");
60         if (UnsubscribeAllDhcpEvent() != DHCP_OPT_SUCCESS) {
61             WIFI_LOGE("DhcpClientServiceImpl unregister all dhcp event failed!");
62         }
63     }
64 
65     ExitDhcpMgrThread();
66     pthread_mutex_destroy(&m_DhcpResultInfoMutex);
67 }
68 
ReleaseResultNotifyMemory()69 void DhcpClientServiceImpl::ReleaseResultNotifyMemory()
70 {
71     for (auto& item : m_mapDhcpResultNotify) {
72         auto& secondItem = item.second;
73         for (auto& each : secondItem) {
74             if (each != nullptr) {
75                 delete each;
76                 each = nullptr;
77             }
78         }
79     }
80 }
81 
InitDhcpMgrThread()82 int DhcpClientServiceImpl::InitDhcpMgrThread()
83 {
84     pDhcpResultHandleThread = new std::thread(&DhcpClientServiceImpl::RunDhcpResultHandleThreadFunc, this);
85     if (pDhcpResultHandleThread == nullptr) {
86         WIFI_LOGE("DhcpClientServiceImpl::InitDhcpMgrThread() init pDhcpResultHandleThread failed!");
87         return DHCP_OPT_FAILED;
88     }
89 
90     return DHCP_OPT_SUCCESS;
91 }
92 
ExitDhcpMgrThread()93 void DhcpClientServiceImpl::ExitDhcpMgrThread()
94 {
95     isExitDhcpResultHandleThread = true;
96 
97     if (pDhcpResultHandleThread != nullptr) {
98         pDhcpResultHandleThread->join();
99         delete pDhcpResultHandleThread;
100         pDhcpResultHandleThread = nullptr;
101     }
102     ipv6Client.DhcpIPV6Stop();
103     if (pDhcpIpv6ClientThread != nullptr) {
104         pDhcpIpv6ClientThread->join();
105         delete pDhcpIpv6ClientThread;
106         pDhcpIpv6ClientThread = nullptr;
107     }
108 
109     if (!m_mapDhcpResultNotify.empty()) {
110         WIFI_LOGE("ExitDhcpMgrThread() error, m_mapDhcpResultNotify is not empty!");
111         ReleaseResultNotifyMemory();
112         m_mapDhcpResultNotify.clear();
113     }
114 #ifdef OHOS_ARCH_LITE
115     if (!m_mapDhcpRecvMsgThread.empty()) {
116         WIFI_LOGE("ExitDhcpMgrThread() error, m_mapDhcpRecvMsgThread is not empty!");
117         for (auto &mapThread : m_mapDhcpRecvMsgThread) {
118             int nStatus = GetDhcpStatus(mapThread.first);
119             WIFI_LOGE("ExitDhcpMgrThread() ifname:%{public}s, status:%{public}d!",
120                 (mapThread.first).c_str(), nStatus);
121         }
122     }
123 #endif
124 }
125 
CheckTimeout()126 void DhcpClientServiceImpl::CheckTimeout()
127 {
128     uint32_t tempTime = 0;
129     uint32_t curTime = (uint32_t)time(NULL);
130     for (auto &itemNotify : m_mapDhcpResultNotify) {
131         std::string ifname = itemNotify.first;
132         WIFI_LOGI("CheckTimeout() ifname:%{public}s, notify1 second size:%{public}d.",
133             ifname.c_str(),
134             (int)itemNotify.second.size());
135         auto iterReq = itemNotify.second.begin();
136         while (iterReq != itemNotify.second.end()) {
137             if ((*iterReq == nullptr) || ((*iterReq)->pResultNotify == nullptr)) {
138                 WIFI_LOGE("DhcpClientServiceImpl::CheckTimeout() error, *iterReq or pResultNotify is nullptr!");
139                 return;
140             }
141             tempTime = (*iterReq)->getTimestamp + (*iterReq)->timeouts;
142             if (tempTime <= curTime && ((*iterReq)->status & DHCP_IPV4_GETTED) == 0) {
143                 /* get dhcp result timeout */
144                 WIFI_LOGW("CheckTimeout() ifname:%{public}s get timeout, getTime:%{public}u,timeout:%{public}d, "
145                           "curTime:%{public}u!",
146                     ifname.c_str(),
147                     (*iterReq)->getTimestamp,
148                     (*iterReq)->timeouts,
149                     curTime);
150                 (*iterReq)->pResultNotify->OnFailed(DHCP_OPT_TIMEOUT, ifname, "get dhcp result timeout!");
151                 delete *iterReq;
152                 *iterReq = nullptr;
153                 iterReq = itemNotify.second.erase(iterReq);
154             } else {
155                 ++iterReq;
156             }
157         }
158     }
159 }
160 
DhcpResultHandle(uint32_t & second)161 void DhcpClientServiceImpl::DhcpResultHandle(uint32_t &second)
162 {
163     std::unique_lock<std::mutex> lock(mResultNotifyMutex);
164     if (m_mapDhcpResultNotify.empty()) {
165         second = SLEEP_TIME_200_MS;
166         return;
167     }
168 
169     /* Check timeout */
170     CheckTimeout();
171     auto iterNotify = m_mapDhcpResultNotify.begin();
172     while (iterNotify != m_mapDhcpResultNotify.end()) {
173         /* Check dhcp result notify size */
174         std::string ifname = iterNotify->first;
175         if (iterNotify->second.size() <= 0) {
176             iterNotify = m_mapDhcpResultNotify.erase(iterNotify);
177             WIFI_LOGI("DhcpResultHandle() ifname:%{public}s, dhcp result notify size:0, erase!", ifname.c_str());
178             continue;
179         }
180         /* Check dhcp result */
181         pthread_mutex_lock(&m_DhcpResultInfoMutex);
182         std::map<std::string, std::vector<DhcpResult>>::iterator dhcpRlt =
183             DhcpClientServiceImpl::m_mapDhcpResult.find(ifname);
184         if (dhcpRlt == DhcpClientServiceImpl::m_mapDhcpResult.end()) {
185             WIFI_LOGI("DhcpResultHandle() ifname:%{public}s, dhcp result is getting...", ifname.c_str());
186             ++iterNotify;
187             pthread_mutex_unlock(&m_DhcpResultInfoMutex);
188             continue;
189         }
190         std::vector<DhcpResult> results(dhcpRlt->second);
191         DhcpClientServiceImpl::m_mapDhcpResult.erase(dhcpRlt);
192         pthread_mutex_unlock(&m_DhcpResultInfoMutex);
193         for (auto resRlt : results) {
194             auto dhcpResult = resRlt;
195             bool isOptSuc =  dhcpResult.isOptSuc;
196             auto iterReq = iterNotify->second.begin();
197             while (iterReq != iterNotify->second.end()) {
198                 if ((*iterReq == nullptr) || ((*iterReq)->pResultNotify == nullptr)) {
199                     WIFI_LOGE("DhcpResultHandle() %{public}s iterReq or pResultNotify is nullptr!", ifname.c_str());
200                     second = SLEEP_TIME_500_MS;
201                     return;
202                 }
203 
204                 /* Handle dhcp result notify */
205                 WIFI_LOGI("DhcpResultHandle() ifname:%{public}s, isOptSuc:%{public}d.",
206                     ifname.c_str(), isOptSuc);
207                 if (isOptSuc) {
208                     /* get dhcp result success */
209                     WIFI_LOGI("DhcpResultHandle() ifname:%{public}s get dhcp result success!", ifname.c_str());
210                     (*iterReq)->pResultNotify->OnSuccess(DHCP_OPT_SUCCESS, ifname, dhcpResult);
211                 } else {
212                     /* get dhcp result failed */
213                     WIFI_LOGE("DhcpResultHandle() ifname:%{public}s get dhcp result failed!", ifname.c_str());
214                     (*iterReq)->pResultNotify->OnFailed(DHCP_OPT_FAILED, ifname, "get dhcp result failed!");
215                 }
216                 if (dhcpResult.iptype == 0) {
217                     (*iterReq)->status |= DHCP_IPV4_GETTED;
218                 } else if (dhcpResult.iptype == 1) {
219                     (*iterReq)->status |= DHCP_IPV6_GETTED;
220                 }
221                 ++iterReq;
222             }
223         }
224         ++iterNotify;
225     }
226 
227     WIFI_LOGI("DhcpResultHandle() dhcp result notify finished.");
228     second = SLEEP_TIME_500_MS;
229 }
230 
SubscribeDhcpEvent(const std::string & strAction)231 int DhcpClientServiceImpl::SubscribeDhcpEvent(const std::string &strAction)
232 {
233     if (strAction.empty()) {
234         WIFI_LOGE("SubscribeDhcpEvent error, strAction is empty!");
235         return DHCP_OPT_ERROR;
236     }
237 #ifndef OHOS_ARCH_LITE
238     std::unique_lock<std::mutex> lock(m_subscriberMutex);
239     auto iterSubscriber = m_mapEventSubscriber.find(strAction);
240     if (iterSubscriber == m_mapEventSubscriber.end()) {
241         EventFwk::MatchingSkills matchingSkills;
242         matchingSkills.AddEvent(strAction);
243         EventFwk::CommonEventSubscribeInfo subInfo(matchingSkills);
244         auto dhcpSubscriber = std::make_shared<OHOS::Wifi::DhcpEventSubscriber>(subInfo);
245         m_mapEventSubscriber.emplace(std::make_pair(strAction, dhcpSubscriber));
246     } else {
247         return DHCP_OPT_SUCCESS;
248     }
249     if (m_mapEventSubscriber[strAction] == nullptr) {
250         WIFI_LOGE("SubscribeDhcpEvent mapEventSubscriber %{public}s nullptr!", strAction.c_str());
251         return DHCP_OPT_FAILED;
252     }
253     if (!DhcpFunc::SubscribeDhcpCommonEvent(m_mapEventSubscriber[strAction])) {
254         WIFI_LOGE("SubscribeDhcpEvent SubscribeDhcpCommonEvent %{public}s failed!", strAction.c_str());
255         return DHCP_OPT_FAILED;
256     }
257     WIFI_LOGI("SubscribeDhcpEvent %{public}s success", strAction.c_str());
258 #endif
259     return DHCP_OPT_SUCCESS;
260 }
261 
UnsubscribeDhcpEvent(const std::string & strAction)262 int DhcpClientServiceImpl::UnsubscribeDhcpEvent(const std::string &strAction)
263 {
264     if (strAction.empty()) {
265         WIFI_LOGE("UnsubscribeDhcpEvent error, strAction is empty!");
266         return DHCP_OPT_ERROR;
267     }
268     std::unique_lock<std::mutex> lock(m_subscriberMutex);
269     auto iterSubscriber = m_mapEventSubscriber.find(strAction);
270     if (iterSubscriber == m_mapEventSubscriber.end()) {
271         WIFI_LOGI("UnsubscribeDhcpEvent map no exist %{public}s, no need unsubscriber", strAction.c_str());
272         return DHCP_OPT_SUCCESS;
273     }
274 
275     if (m_mapEventSubscriber[strAction] == nullptr) {
276         WIFI_LOGE("UnsubscribeDhcpEvent mapEventSubscriber %{public}s nullptr!", strAction.c_str());
277         return DHCP_OPT_FAILED;
278     }
279 #ifndef OHOS_ARCH_LITE
280     if (!DhcpFunc::UnsubscribeDhcpCommonEvent(m_mapEventSubscriber[strAction])) {
281         WIFI_LOGE("UnsubscribeDhcpEvent UnsubscribeDhcpCommonEvent %{public}s failed!", strAction.c_str());
282         return DHCP_OPT_FAILED;
283     }
284 #endif
285     m_mapEventSubscriber.erase(iterSubscriber);
286     WIFI_LOGI("UnsubscribeDhcpEvent %{public}s success", strAction.c_str());
287     return DHCP_OPT_SUCCESS;
288 }
289 
UnsubscribeAllDhcpEvent()290 int DhcpClientServiceImpl::UnsubscribeAllDhcpEvent()
291 {
292 #ifndef OHOS_ARCH_LITE
293     for (auto& e : m_mapEventSubscriber) {
294         if (e.second != nullptr) {
295             if (!DhcpFunc::UnsubscribeDhcpCommonEvent(e.second)) {
296                 WIFI_LOGE("UnsubscribeDhcpEvent UnsubscribeDhcpCommonEvent %{public}s failed!", e.first.c_str());
297                 return DHCP_OPT_FAILED;
298             }
299         }
300     }
301 #endif
302     m_mapEventSubscriber.clear();
303     WIFI_LOGI("UnsubscribeDhcpEvent all dhcp event success!");
304     return DHCP_OPT_SUCCESS;
305 }
306 
RunDhcpResultHandleThreadFunc()307 void DhcpClientServiceImpl::RunDhcpResultHandleThreadFunc()
308 {
309     for (; ;) {
310         if (isExitDhcpResultHandleThread) {
311             WIFI_LOGI("RunDhcpResultHandleThreadFunc() isExitDhcpResultHandleThread:1, break!");
312             break;
313         }
314 
315         uint32_t uSleepSec = SLEEP_TIME_500_MS;
316         DhcpResultHandle(uSleepSec);
317         usleep(uSleepSec);
318     }
319 
320     WIFI_LOGI("DhcpClientServiceImpl::RunDhcpResultHandleThreadFunc() end!");
321 }
322 
323 #ifdef OHOS_ARCH_LITE
RunDhcpRecvMsgThreadFunc(const std::string & ifname)324 void DhcpClientServiceImpl::RunDhcpRecvMsgThreadFunc(const std::string &ifname)
325 {
326     if (ifname.empty()) {
327         WIFI_LOGE("DhcpClientServiceImpl::RunDhcpRecvMsgThreadFunc() error, ifname is empty!");
328         return;
329     }
330 
331     struct DhcpPacketResult result;
332     std::string strResultFile = DHCP_WORK_DIR + ifname + DHCP_RESULT_FILETYPE;
333     for (; ;) {
334         /* Check break condition. */
335         pthread_mutex_lock(&m_DhcpResultInfoMutex);
336         auto iter = this->m_mapDhcpInfo.find(ifname);
337         if ((iter != this->m_mapDhcpInfo.end()) && ((iter->second).clientRunStatus) != 1) {
338             pthread_mutex_unlock(&m_DhcpResultInfoMutex);
339             WIFI_LOGI("RunDhcpRecvMsgThreadFunc() Status != 1, need break, ifname:%{public}s.", ifname.c_str());
340             break;
341         }
342         pthread_mutex_unlock(&m_DhcpResultInfoMutex);
343 
344         /* Check dhcp result file is or not exist. */
345         if (!DhcpFunc::IsExistFile(strResultFile)) {
346             usleep(SLEEP_TIME_200_MS);
347             continue;
348         }
349 
350         if (memset_s(&result, sizeof(result), 0, sizeof(result)) != EOK) {
351             return;
352         }
353         int nGetRet = DhcpFunc::GetDhcpPacketResult(strResultFile, result);
354         if (nGetRet == DHCP_OPT_SUCCESS) {
355             /* Get success, add or reload dhcp packet info. */
356             this->DhcpPacketInfoHandle(ifname, result);
357             usleep(SLEEP_TIME_500_MS);
358         } else if (nGetRet == DHCP_OPT_FAILED) {
359             /* Get failed, print dhcp packet info. */
360             this->DhcpPacketInfoHandle(ifname, result, false);
361             usleep(SLEEP_TIME_500_MS);
362         } else {
363             /* Get null, continue get dhcp packet info. */
364             WIFI_LOGI("RunDhcpRecvMsgThreadFunc() GetDhcpPacketResult NULL, ifname:%{public}s.", ifname.c_str());
365             usleep(SLEEP_TIME_200_MS);
366         }
367     }
368 }
369 
DhcpPacketInfoHandle(const std::string & ifname,struct DhcpPacketResult & packetResult,bool success)370 void DhcpClientServiceImpl::DhcpPacketInfoHandle(
371     const std::string &ifname, struct DhcpPacketResult &packetResult, bool success)
372 {
373     if (ifname.empty()) {
374         WIFI_LOGE("DhcpClientServiceImpl::DhcpPacketInfoHandle() error, ifname is empty!");
375         return;
376     }
377 
378     DhcpResult result;
379     if (!success) {
380         PushDhcpResult(ifname, result);
381         return;
382     }
383 
384     /* get success, add or reload dhcp packet info */
385     auto iterInfo = m_mapDhcpInfo.find(ifname);
386     if (iterInfo != m_mapDhcpInfo.end()) {
387         m_mapDhcpInfo[ifname].serverIp = packetResult.strOptServerId;
388     }
389 
390     result.iptype = 0;
391     result.isOptSuc = true;
392     result.strYourCli = packetResult.strYiaddr;
393     result.strServer = packetResult.strOptServerId;
394     result.strSubnet = packetResult.strOptSubnet;
395     result.strDns1 = packetResult.strOptDns1;
396     result.strDns2 = packetResult.strOptDns2;
397     result.strRouter1 = packetResult.strOptRouter1;
398     result.strRouter2 = packetResult.strOptRouter2;
399     result.strVendor = packetResult.strOptVendor;
400     result.uLeaseTime = packetResult.uOptLeasetime;
401     result.uAddTime = packetResult.uAddTime;
402     result.uGetTime = (uint32_t)time(NULL);
403     PushDhcpResult(ifname, result);
404     WIFI_LOGI("DhcpPacketInfoHandle %{public}s, type:%{public}d, opt:%{public}d, cli:%{private}s, server:%{private}s, "
405         "strSubnet:%{private}s, Dns1:%{private}s, Dns2:%{private}s, strRouter1:%{private}s, strRouter2:%{private}s, "
406         "strVendor:%{public}s, uLeaseTime:%{public}u, uAddTime:%{public}u, uGetTime:%{public}u.",
407         ifname.c_str(), result.iptype, result.isOptSuc, result.strYourCli.c_str(), result.strServer.c_str(),
408         result.strSubnet.c_str(), result.strDns1.c_str(), result.strDns2.c_str(), result.strRouter1.c_str(),
409         result.strRouter2.c_str(), result.strVendor.c_str(), result.uLeaseTime, result.uAddTime, result.uGetTime);
410 }
411 #endif
412 
ForkExecChildProcess(const std::string & ifname,bool bIpv6,bool bStart)413 int DhcpClientServiceImpl::ForkExecChildProcess(const std::string &ifname, bool bIpv6, bool bStart)
414 {
415     if (bIpv6) {
416         /* get ipv4 and ipv6 */
417         if (bStart) {
418             const char *args[DHCP_CLI_ARGSNUM] = {DHCP_CLIENT_FILE.c_str(), "start", ifname.c_str(), "-a", nullptr};
419             if (execv(args[0], const_cast<char *const *>(args)) == -1) {
420                 WIFI_LOGE("execv start v4 v6 failed,errno:%{public}d,ifname:%{public}s", errno, ifname.c_str());
421             }
422         } else {
423             const char *args[DHCP_CLI_ARGSNUM] = {DHCP_CLIENT_FILE.c_str(), "stop", ifname.c_str(), "-a", nullptr};
424             if (execv(args[0], const_cast<char *const *>(args)) == -1) {
425                 WIFI_LOGE("execv stop v4 v6 failed,errno:%{public}d,ifname:%{public}s", errno, ifname.c_str());
426             }
427         }
428     } else {
429         /* only get ipv4 */
430         if (bStart) {
431             const char *args[DHCP_CLI_ARGSNUM] = {DHCP_CLIENT_FILE.c_str(), "start", ifname.c_str(), "-4", nullptr};
432             if (execv(args[0], const_cast<char *const *>(args)) == -1) {
433                 WIFI_LOGE("execv start v4 failed,errno:%{public}d,ifname:%{public}s", errno, ifname.c_str());
434             }
435         } else {
436             const char *args[DHCP_CLI_ARGSNUM] = {DHCP_CLIENT_FILE.c_str(), "stop", ifname.c_str(), "-4", nullptr};
437             if (execv(args[0], const_cast<char *const *>(args)) == -1) {
438                 WIFI_LOGE("execv stop v4 failed,errno:%{public}d,ifname:%{public}s", errno, ifname.c_str());
439             }
440         }
441     }
442     _exit(-1);
443 }
444 
DealParentProcessStart(const std::string & ifname,bool bIpv6,pid_t pid)445 int DhcpClientServiceImpl::DealParentProcessStart(const std::string& ifname, bool bIpv6, pid_t pid)
446 {
447     std::string strAction = OHOS::Wifi::COMMON_EVENT_DHCP_GET_IPV4 + "." + ifname;
448 #ifdef OHOS_ARCH_LITE
449     /* check and new receive dhcp packet msg thread */
450     std::unique_lock<std::mutex> lock(mRecvMsgThreadMutex);
451     auto iterRecvMsgThread = m_mapDhcpRecvMsgThread.find(ifname);
452     if (iterRecvMsgThread != m_mapDhcpRecvMsgThread.end()) {
453         WIFI_LOGE("ForkExecParentProcess() RecvMsgThread exist ifname:%{public}s, need erase!", ifname.c_str());
454         return DHCP_OPT_FAILED;
455     }
456     std::thread *pThread = new std::thread(&DhcpClientServiceImpl::RunDhcpRecvMsgThreadFunc, this, ifname);
457     if (pThread == nullptr) {
458         WIFI_LOGE("ForkExecParentProcess() init pThread failed, ifname:%{public}s.", ifname.c_str());
459         return DHCP_OPT_FAILED;
460     }
461     m_mapDhcpRecvMsgThread.emplace(std::make_pair(ifname, pThread));
462 #endif
463     /* normal started, update dhcp client service running status */
464     pthread_mutex_lock(&m_DhcpResultInfoMutex);
465     auto iter = DhcpClientServiceImpl::m_mapDhcpInfo.find(ifname);
466     if (iter != DhcpClientServiceImpl::m_mapDhcpInfo.end()) {
467         DhcpClientServiceImpl::m_mapDhcpInfo[ifname].enableIPv6 = bIpv6;
468         DhcpClientServiceImpl::m_mapDhcpInfo[ifname].clientRunStatus = 1;
469         DhcpClientServiceImpl::m_mapDhcpInfo[ifname].clientProPid = pid;
470     } else {
471         DhcpServiceInfo dhcpInfo;
472         dhcpInfo.enableIPv6 = bIpv6;
473         dhcpInfo.clientRunStatus = 1;
474         dhcpInfo.clientProPid = pid;
475         DhcpClientServiceImpl::m_mapDhcpInfo.emplace(std::make_pair(ifname, dhcpInfo));
476     }
477     /* Subscribe dhcp event. */
478     if (SubscribeDhcpEvent(strAction) != DHCP_OPT_SUCCESS) {
479         pthread_mutex_unlock(&m_DhcpResultInfoMutex);
480         return DHCP_OPT_FAILED;
481     }
482     pthread_mutex_unlock(&m_DhcpResultInfoMutex);
483     return DHCP_OPT_SUCCESS;
484 }
485 
DealParentProcessStop(const std::string & ifname,bool bIpv6,pid_t pid)486 int DhcpClientServiceImpl::DealParentProcessStop(const std::string& ifname, bool bIpv6, pid_t pid)
487 {
488     pthread_mutex_lock(&m_DhcpResultInfoMutex);
489     auto iter = DhcpClientServiceImpl::m_mapDhcpInfo.find(ifname);
490     if (iter != DhcpClientServiceImpl::m_mapDhcpInfo.end()) {
491         /* not start */
492         DhcpClientServiceImpl::m_mapDhcpInfo[ifname].clientRunStatus = 0;
493         DhcpClientServiceImpl::m_mapDhcpInfo[ifname].clientProPid = 0;
494         pthread_mutex_unlock(&m_DhcpResultInfoMutex);
495 #ifdef OHOS_ARCH_LITE
496         std::unique_lock<std::mutex> lock(mRecvMsgThreadMutex);
497         auto iterRecvMsgThreadMap = m_mapDhcpRecvMsgThread.find(ifname);
498         if (iterRecvMsgThreadMap == m_mapDhcpRecvMsgThread.end()) {
499             WIFI_LOGI("ForkExecParentProcess() RecvMsgThread already del ifname:%{public}s.", ifname.c_str());
500             return DHCP_OPT_SUCCESS;
501         }
502         if (iterRecvMsgThreadMap->second != nullptr) {
503             iterRecvMsgThreadMap->second->join();
504             delete iterRecvMsgThreadMap->second;
505             iterRecvMsgThreadMap->second = nullptr;
506             WIFI_LOGI("ForkExecParentProcess() destroy RecvThread success, ifname:%{public}s.", ifname.c_str());
507         }
508         WIFI_LOGI("ForkExecParentProcess() m_mapDhcpRecvMsgThread erase ifname:%{public}s.", ifname.c_str());
509         m_mapDhcpRecvMsgThread.erase(iterRecvMsgThreadMap);
510 #endif
511     } else {
512         pthread_mutex_unlock(&m_DhcpResultInfoMutex);
513     }
514     return DHCP_OPT_SUCCESS;
515 }
516 
ForkExecParentProcess(const std::string & ifname,bool bIpv6,bool bStart,pid_t pid)517 int DhcpClientServiceImpl::ForkExecParentProcess(const std::string &ifname, bool bIpv6, bool bStart, pid_t pid)
518 {
519     if (bStart) {
520         return DealParentProcessStart(ifname, bStart, pid);
521     } else {
522         return DealParentProcessStop(ifname, bStart, pid);
523     }
524 }
525 
GetDhcpClientProPid(const std::string & ifname)526 pid_t DhcpClientServiceImpl::GetDhcpClientProPid(const std::string &ifname)
527 {
528     if (ifname.empty()) {
529         WIFI_LOGE("GetDhcpClientProPid() error, ifname is empty!");
530         return 0;
531     }
532     pthread_mutex_lock(&m_DhcpResultInfoMutex);
533     auto iter = DhcpClientServiceImpl::m_mapDhcpInfo.find(ifname);
534     if (iter == DhcpClientServiceImpl::m_mapDhcpInfo.end()) {
535         pthread_mutex_unlock(&m_DhcpResultInfoMutex);
536         WIFI_LOGI("GetDhcpClientProPid() m_mapDhcpInfo no find ifname:%{public}s.", ifname.c_str());
537         return 0;
538     }
539 
540     std::string pidFile = DHCP_WORK_DIR + ifname + DHCP_CLIENT_PID_FILETYPE;
541     pid_t newPid = DhcpFunc::GetPID(pidFile);
542     if ((newPid > 0) && (newPid != (iter->second).clientProPid)) {
543         WIFI_LOGI("GetDhcpClientProPid() GetPID %{public}s new pid:%{public}d, old pid:%{public}d, need update.",
544             pidFile.c_str(), newPid, (iter->second).clientProPid);
545         DhcpClientServiceImpl::m_mapDhcpInfo[ifname].clientProPid = newPid;
546     }
547     pid_t clientProPid = DhcpClientServiceImpl::m_mapDhcpInfo[ifname].clientProPid;
548     pthread_mutex_unlock(&m_DhcpResultInfoMutex);
549     WIFI_LOGI("GetDhcpClientProPid() m_mapDhcpInfo find ifname:%{public}s, pid:%{public}d.",
550         ifname.c_str(), clientProPid);
551     return clientProPid;
552 }
553 
CheckDhcpClientRunning(const std::string & ifname)554 int DhcpClientServiceImpl::CheckDhcpClientRunning(const std::string &ifname)
555 {
556     if (ifname.empty()) {
557         WIFI_LOGE("CheckDhcpClientRunning param error, ifname is empty!");
558         return DHCP_OPT_ERROR;
559     }
560 
561     std::string pidFile = DHCP_WORK_DIR + ifname + DHCP_CLIENT_PID_FILETYPE;
562     pid_t pid = DhcpFunc::GetPID(pidFile);
563     if (pid <= 0) {
564         return DHCP_OPT_SUCCESS;
565     }
566 
567     int nRet = DhcpFunc::CheckProRunning(pid, DHCP_CLIENT_FILE);
568     if (nRet == -1) {
569         WIFI_LOGE("CheckDhcpClientRunning %{public}s failed, pid:%{public}d", ifname.c_str(), pid);
570         return DHCP_OPT_FAILED;
571     }
572     if (nRet == 0) {
573         WIFI_LOGI("CheckDhcpClientRunning %{public}s, %{public}s is not running, need remove %{public}s",
574             ifname.c_str(), DHCP_CLIENT_FILE.c_str(), pidFile.c_str());
575         DhcpFunc::RemoveFile(pidFile);
576     } else {
577         WIFI_LOGI("CheckDhcpClientRunning %{public}s, %{public}s is running, pid:%{public}d",
578             ifname.c_str(), DHCP_CLIENT_FILE.c_str(), pid);
579         int nStatus = GetDhcpStatus(ifname);
580         if (nStatus == -1) {
581             nStatus = StopDhcpClient(ifname, false);
582             WIFI_LOGI("CheckDhcpClientRunning, NOT find dhcp info, stop dhcp client, nStatus:%{public}d", nStatus);
583         }
584     }
585 
586     WIFI_LOGI("CheckDhcpClientRunning %{public}s finished, pid:%{public}d, pro:%{public}s",
587         ifname.c_str(), pid, DHCP_CLIENT_FILE.c_str());
588     return DHCP_OPT_SUCCESS;
589 }
590 
GetSuccessIpv4Result(const std::vector<std::string> & splits)591 int DhcpClientServiceImpl::GetSuccessIpv4Result(const std::vector<std::string> &splits)
592 {
593     /* Result format - ifname,time,cliIp,lease,servIp,subnet,dns1,dns2,router1,router2,vendor */
594     if ((splits.size() != EVENT_DATA_NUM) || (splits[DHCP_NUM_TWO] == INVALID_STRING)) {
595         WIFI_LOGE("GetSuccessIpv4Result() splits.size:%{public}d cliIp:%{public}s error!", (int)splits.size(),
596             splits[DHCP_NUM_TWO].c_str());
597         return DHCP_OPT_FAILED;
598     }
599 
600     DhcpResult result;
601     result.uAddTime = atoi(splits[DHCP_NUM_ONE].c_str());
602     result.iptype = 0;
603     std::string ifname = splits[DHCP_NUM_ZERO];
604     if (CheckDhcpResultExist(ifname, result)) {
605         WIFI_LOGI("GetSuccessIpv4Result() %{public}s equal new %{public}u, no need update.",
606             ifname.c_str(), result.uAddTime);
607         return DHCP_OPT_SUCCESS;
608     }
609 
610     WIFI_LOGI("GetSuccessIpv4Result() DhcpResult %{public}s no equal new %{public}u, need update...",
611         ifname.c_str(), result.uAddTime);
612 
613     /* Reload dhcp packet info. */
614     auto iterInfo = DhcpClientServiceImpl::m_mapDhcpInfo.find(ifname);
615     if (iterInfo != DhcpClientServiceImpl::m_mapDhcpInfo.end()) {
616         WIFI_LOGI("GetSuccessIpv4Result() m_mapDhcpInfo find ifname:%{public}s.", ifname.c_str());
617         DhcpClientServiceImpl::m_mapDhcpInfo[ifname].serverIp = splits[DHCP_NUM_FOUR];
618     }
619 
620     result.isOptSuc     = true;
621     result.strYourCli   = splits[DHCP_NUM_TWO];
622     result.uLeaseTime   = atoi(splits[DHCP_NUM_THREE].c_str());
623     result.strServer    = splits[DHCP_NUM_FOUR];
624     result.strSubnet    = splits[DHCP_NUM_FIVE];
625     result.strDns1      = splits[DHCP_NUM_SIX];
626     result.strDns2      = splits[DHCP_NUM_SEVEN];
627     result.strRouter1   = splits[DHCP_NUM_EIGHT];
628     result.strRouter2   = splits[DHCP_NUM_NINE];
629     result.strVendor    = splits[DHCP_NUM_TEN];
630     result.uGetTime     = (uint32_t)time(NULL);
631     PushDhcpResult(ifname, result);
632     WIFI_LOGI("GetSuccessIpv4Result() %{public}s, %{public}d, opt:%{public}d, cli:%{private}s, server:%{private}s, "
633         "strSubnet:%{private}s, strDns1:%{private}s, Dns2:%{private}s, strRouter1:%{private}s, Router2:%{private}s, "
634         "strVendor:%{public}s, uLeaseTime:%{public}u, uAddTime:%{public}u, uGetTime:%{public}u.",
635         ifname.c_str(), result.iptype, result.isOptSuc, result.strYourCli.c_str(), result.strServer.c_str(),
636         result.strSubnet.c_str(), result.strDns1.c_str(), result.strDns2.c_str(), result.strRouter1.c_str(),
637         result.strRouter2.c_str(), result.strVendor.c_str(), result.uLeaseTime, result.uAddTime, result.uGetTime);
638     return DHCP_OPT_SUCCESS;
639 }
640 
GetDhcpEventIpv4Result(const int code,const std::vector<std::string> & splits)641 int DhcpClientServiceImpl::GetDhcpEventIpv4Result(const int code, const std::vector<std::string> &splits)
642 {
643     /* Result format - ifname,time,cliIp,lease,servIp,subnet,dns1,dns2,router1,router2,vendor */
644     if (splits.size() != EVENT_DATA_NUM) {
645         WIFI_LOGE("GetDhcpEventIpv4Result() splits.size:%{public}d error!", (int)splits.size());
646         return DHCP_OPT_FAILED;
647     }
648 
649     /* Check field ifname and time. */
650     if (splits[DHCP_NUM_ZERO].empty() || splits[DHCP_NUM_ONE].empty()) {
651         WIFI_LOGE("GetDhcpEventIpv4Result() ifname or time is empty!");
652         return DHCP_OPT_FAILED;
653     }
654 
655     /* Check field cliIp. */
656     if (((code == PUBLISH_CODE_SUCCESS) && (splits[DHCP_NUM_TWO] == INVALID_STRING))
657     || ((code == PUBLISH_CODE_FAILED) && (splits[DHCP_NUM_TWO] != INVALID_STRING))) {
658         WIFI_LOGE("GetDhcpEventIpv4Result() code:%{public}d,%{public}s error!", code, splits[DHCP_NUM_TWO].c_str());
659         return DHCP_OPT_FAILED;
660     }
661 
662     std::string ifname = splits[DHCP_NUM_ZERO];
663     if (code == PUBLISH_CODE_FAILED) {
664         /* Get failed. */
665         DhcpResult result;
666         result.iptype = 0;
667         result.isOptSuc = false;
668         result.uAddTime = atoi(splits[DHCP_NUM_ONE].c_str());
669         PushDhcpResult(ifname, result);
670         WIFI_LOGI("GetDhcpEventIpv4Result() ifname:%{public}s result.isOptSuc:false!", ifname.c_str());
671         return DHCP_OPT_SUCCESS;
672     }
673 
674     /* Get success. */
675     if (GetSuccessIpv4Result(splits) != DHCP_OPT_SUCCESS) {
676         WIFI_LOGE("GetDhcpEventIpv4Result() GetSuccessIpv4Result failed!");
677         return DHCP_OPT_FAILED;
678     }
679     WIFI_LOGI("GetDhcpEventIpv4Result() ifname:%{public}s result.isOptSuc:true!", ifname.c_str());
680     return DHCP_OPT_SUCCESS;
681 }
682 
CheckDhcpResultExist(const std::string & ifname,DhcpResult & result)683 bool DhcpClientServiceImpl::CheckDhcpResultExist(const std::string &ifname, DhcpResult &result)
684 {
685     bool exist = false;
686     pthread_mutex_lock(&m_DhcpResultInfoMutex);
687     auto iterResult = m_mapDhcpResult.find(ifname);
688     if (iterResult != m_mapDhcpResult.end()) {
689         for (int i = 0; i < iterResult->second.size(); i++) {
690             if (iterResult->second[i].iptype != result.iptype) {
691                 continue;
692             }
693             if (iterResult->second[i].uAddTime == result.uAddTime) {
694                 exist = true;
695                 break;
696             }
697         }
698     }
699     pthread_mutex_unlock(&m_DhcpResultInfoMutex);
700     return exist;
701 }
702 
PushDhcpResult(const std::string & ifname,DhcpResult & result)703 void DhcpClientServiceImpl::PushDhcpResult(const std::string &ifname, DhcpResult &result)
704 {
705     pthread_mutex_lock(&m_DhcpResultInfoMutex);
706     auto iterResult = m_mapDhcpResult.find(ifname);
707     if (iterResult != m_mapDhcpResult.end()) {
708         for (int i = 0; i < iterResult->second.size(); i++) {
709             if (iterResult->second[i].iptype != result.iptype) {
710                 continue;
711             }
712             if (iterResult->second[i].iptype == 0) {
713                 if (iterResult->second[i].uAddTime != result.uAddTime) {
714                     iterResult->second[i] = result;
715                 }
716             } else {
717                 iterResult->second[i] = result;
718             }
719             pthread_mutex_unlock(&m_DhcpResultInfoMutex);
720             return;
721         }
722         iterResult->second.push_back(result);
723     } else {
724         std::vector<DhcpResult> results;
725         results.push_back(result);
726         m_mapDhcpResult.emplace(std::make_pair(ifname, results));
727     }
728     pthread_mutex_unlock(&m_DhcpResultInfoMutex);
729 }
730 
DhcpEventResultHandle(const int code,const std::string & data)731 int DhcpClientServiceImpl::DhcpEventResultHandle(const int code, const std::string &data)
732 {
733     if (data.empty()) {
734         WIFI_LOGE("DhcpClientServiceImpl::DhcpEventResultHandle() error, data is empty!");
735         return DHCP_OPT_FAILED;
736     }
737     WIFI_LOGI("Enter DhcpEventResultHandle() code:%{public}d,data:%{private}s.", code, data.c_str());
738 
739     /* Data format - ipv4:ifname,time,cliIp,lease,servIp,subnet,dns1,dns2,router1,router2,vendor */
740     std::string strData(data);
741     std::string strFlag;
742     std::string strResult;
743     if (strData.find(EVENT_DATA_IPV4) != std::string::npos) {
744         strFlag = strData.substr(0, (int)EVENT_DATA_IPV4.size());
745         if (strFlag != EVENT_DATA_IPV4) {
746             WIFI_LOGE("DhcpEventResultHandle() %{public}s ipv4flag:%{public}s error!", data.c_str(), strFlag.c_str());
747             return DHCP_OPT_FAILED;
748         }
749         /* Skip separator ":" */
750         strResult = strData.substr((int)EVENT_DATA_IPV4.size() + 1);
751     } else if (strData.find(EVENT_DATA_IPV6) != std::string::npos) {
752         strFlag = strData.substr(0, (int)EVENT_DATA_IPV6.size());
753         if (strFlag != EVENT_DATA_IPV6) {
754             WIFI_LOGE("DhcpEventResultHandle() %{public}s ipv6flag:%{public}s error!", data.c_str(), strFlag.c_str());
755             return DHCP_OPT_FAILED;
756         }
757         strResult = strData.substr((int)EVENT_DATA_IPV6.size() + 1);
758     } else {
759         WIFI_LOGE("DhcpEventResultHandle() data:%{public}s error, no find ipflag!", data.c_str());
760         return DHCP_OPT_FAILED;
761     }
762     WIFI_LOGI("DhcpEventResultHandle() flag:%{public}s, result:%{private}s.", strFlag.c_str(), strResult.c_str());
763 
764     if (strFlag == EVENT_DATA_IPV4) {
765         std::vector<std::string> vecSplits;
766         if (!DhcpFunc::SplitString(strResult, EVENT_DATA_DELIMITER, EVENT_DATA_NUM, vecSplits)) {
767             WIFI_LOGE("DhcpEventResultHandle() SplitString strResult:%{public}s failed!", strResult.c_str());
768             return DHCP_OPT_FAILED;
769         }
770 
771         if (GetDhcpEventIpv4Result(code, vecSplits) != DHCP_OPT_SUCCESS) {
772             WIFI_LOGE("DhcpEventResultHandle() GetDhcpEventIpv4Result failed!");
773             return DHCP_OPT_FAILED;
774         }
775     }
776 
777     return DHCP_OPT_SUCCESS;
778 }
779 
RunIpv6ThreadFunc()780 void DhcpClientServiceImpl::RunIpv6ThreadFunc()
781 {
782     ipv6Client.DhcpIpv6Start(currIfName.c_str());
783 }
784 
OnAddressChangedCallback(const std::string ifname,DhcpIpv6Info & info)785 void DhcpClientServiceImpl::OnAddressChangedCallback(const std::string ifname, DhcpIpv6Info &info)
786 {
787     if (strlen(info.globalIpv6Addr) == 0 || strlen(info.routeAddr) == 0) {
788         WIFI_LOGE("OnAddressChangedCallback invalid, ipaddr:%{private}s, route:%{private}s",
789             info.globalIpv6Addr, info.routeAddr);
790         return;
791     }
792 
793     DhcpResult result;
794     result.uAddTime = (uint32_t)time(NULL);
795     result.iptype = 1;
796     result.isOptSuc     = true;
797     result.strYourCli   = info.globalIpv6Addr;
798     result.strSubnet    = info.ipv6SubnetAddr;
799     result.strRouter1   = info.routeAddr;
800     result.strDns1      = info.dnsAddr;
801     result.strDns2      = info.dnsAddr2;
802     result.strRouter2   = "*";
803     result.uGetTime     = (uint32_t)time(NULL);
804     PushDhcpResult(ifname, result);
805     WIFI_LOGI("OnAddressChangedCallback %{public}s, %{public}d, opt:%{public}d, cli:%{private}s, server:%{private}s, "
806         "strSubnet:%{private}s, strDns1:%{private}s, Dns2:%{private}s, strRouter1:%{private}s, Router2:%{private}s, "
807         "strVendor:%{public}s, uLeaseTime:%{public}u, uAddTime:%{public}u, uGetTime:%{public}u.",
808         ifname.c_str(), result.iptype, result.isOptSuc, result.strYourCli.c_str(), result.strServer.c_str(),
809         result.strSubnet.c_str(), result.strDns1.c_str(), result.strDns2.c_str(), result.strRouter1.c_str(),
810         result.strRouter2.c_str(), result.strVendor.c_str(), result.uLeaseTime, result.uAddTime, result.uGetTime);
811 }
812 
StartDhcpClient(const std::string & ifname,bool bIpv6)813 int DhcpClientServiceImpl::StartDhcpClient(const std::string &ifname, bool bIpv6)
814 {
815     if (ifname.empty()) {
816         WIFI_LOGE("DhcpClientServiceImpl::StartDhcpClient() error, ifname is empty!");
817         return DHCP_OPT_FAILED;
818     }
819     currIfName = ifname;
820     WIFI_LOGI("enter StartDhcpClient()...ifname:%{public}s, bIpv6:%{public}d.", ifname.c_str(), bIpv6);
821     if (bIpv6) {
822         ipv6Client.Reset();
823         if (!ipv6Client.IsRunning() && pDhcpIpv6ClientThread) {
824             delete pDhcpIpv6ClientThread;
825             pDhcpIpv6ClientThread = NULL;
826         }
827         if (!pDhcpIpv6ClientThread) {
828             pDhcpIpv6ClientThread = new std::thread(&DhcpClientServiceImpl::RunIpv6ThreadFunc, this);
829             if (pDhcpIpv6ClientThread == nullptr) {
830                 WIFI_LOGE("dhcp ipv6 start client thread failed!");
831             }
832         }
833     }
834     /* check config */
835     /* check dhcp client service running status */
836     if (CheckDhcpClientRunning(ifname) != DHCP_OPT_SUCCESS) {
837         WIFI_LOGE("StartDhcpClient CheckDhcpClientRunning ifname:%{public}s failed.", ifname.c_str());
838         return DHCP_OPT_FAILED;
839     }
840     int nStatus = GetDhcpStatus(ifname);
841     if (nStatus == 1) {
842         WIFI_LOGI("StartDhcpClient() running status:%{public}d, service already started, ifname:%{public}s.",
843             nStatus, ifname.c_str());
844         /* reload config */
845         return DHCP_OPT_SUCCESS;
846     }
847 
848     /* start dhcp client service */
849     pid_t pid;
850     if ((pid = vfork()) < 0) {
851         WIFI_LOGE("StartDhcpClient() vfork() failed, pid:%{public}d.", pid);
852         return DHCP_OPT_FAILED;
853     }
854     if (pid == 0) {
855         /* Child process */
856         ForkExecChildProcess(ifname, bIpv6, true);
857     } else {
858         /* Parent process */
859         WIFI_LOGI("StartDhcpClient() vfork %{public}d success, parent:%{public}d, begin waitpid...", pid, getpid());
860         int ret = ForkExecParentProcess(ifname, bIpv6, true, pid);
861         int pidRet = DhcpFunc::WaitProcessExit(pid);
862         if (pidRet == 0) {
863             WIFI_LOGI("StartDhcpClient() waitpid child:%{public}d success.", pid);
864         } else {
865             WIFI_LOGE("StartDhcpClient() waitpid child:%{public}d failed, pidRet:%{public}d!", pid, pidRet);
866         }
867 
868         return ret;
869     }
870 
871     return DHCP_OPT_SUCCESS;
872 }
873 
StopDhcpClient(const std::string & ifname,bool bIpv6)874 int DhcpClientServiceImpl::StopDhcpClient(const std::string &ifname, bool bIpv6)
875 {
876     if (ifname.empty()) {
877         WIFI_LOGE("DhcpClientServiceImpl::StopDhcpClient() error, ifname is empty!");
878         return DHCP_OPT_FAILED;
879     }
880 
881     WIFI_LOGI("enter StopDhcpClient()...ifname:%{public}s, bIpv6:%{public}d.", ifname.c_str(), bIpv6);
882 
883     /* check dhcp client service running status */
884     bool bExecParentProcess = true;
885     int nStatus = GetDhcpStatus(ifname);
886     if (nStatus == 0) {
887         WIFI_LOGI("StopDhcpClient() status:%{public}d, service already stopped, ifname:%{public}s.",
888             nStatus, ifname.c_str());
889         return DHCP_OPT_SUCCESS;
890     } else if (nStatus == -1) {
891         WIFI_LOGI("StopDhcpClient() status:%{public}d, service not start or started, not need ExecParentProcess, "
892                   "ifname:%{public}s.", nStatus, ifname.c_str());
893         bExecParentProcess = false;
894     }
895 
896     /* stop dhcp client service */
897     pid_t pid;
898     if ((pid = vfork()) < 0) {
899         WIFI_LOGE("StopDhcpClient() vfork() failed, pid:%{public}d.", pid);
900         return DHCP_OPT_FAILED;
901     }
902     if (pid == 0) {
903         /* Child process */
904         ForkExecChildProcess(ifname, bIpv6);
905         return DHCP_OPT_SUCCESS;
906     } else {
907         /* Parent process */
908         WIFI_LOGI("StopDhcpClient() vfork %{public}d success, parent:%{public}d, begin waitpid...", pid, getpid());
909         int pidRet = DhcpFunc::WaitProcessExit(pid);
910         if (pidRet == 0) {
911             WIFI_LOGI("StopDhcpClient() waitpid child:%{public}d success.", pid);
912         } else {
913             WIFI_LOGE("StopDhcpClient() waitpid child:%{public}d failed, pidRet:%{public}d!", pid, pidRet);
914         }
915 
916         return bExecParentProcess ? ForkExecParentProcess(ifname, bIpv6) : DHCP_OPT_SUCCESS;
917     }
918 }
919 
GetDhcpStatus(const std::string & ifname)920 int DhcpClientServiceImpl::GetDhcpStatus(const std::string &ifname)
921 {
922     if (ifname.empty()) {
923         WIFI_LOGE("DhcpClientServiceImpl::GetDhcpStatus() error, ifname is empty!");
924         return -1;
925     }
926     pthread_mutex_lock(&m_DhcpResultInfoMutex);
927     auto iter = DhcpClientServiceImpl::m_mapDhcpInfo.find(ifname);
928     if (iter == DhcpClientServiceImpl::m_mapDhcpInfo.end()) {
929         pthread_mutex_unlock(&m_DhcpResultInfoMutex);
930         WIFI_LOGI("DhcpClientServiceImpl::GetDhcpStatus() m_mapDhcpInfo no find ifname:%{public}s.", ifname.c_str());
931         return -1;
932     }
933     int clientRunStatus = (iter->second).clientRunStatus;
934     pthread_mutex_unlock(&m_DhcpResultInfoMutex);
935     WIFI_LOGI("GetDhcpStatus() m_mapDhcpInfo find ifname:%{public}s, clientRunStatus:%{public}d.",
936         ifname.c_str(),
937         clientRunStatus);
938     return clientRunStatus;
939 }
940 
GetDhcpResult(const std::string & ifname,IDhcpResultNotify * pResultNotify,int timeouts)941 int DhcpClientServiceImpl::GetDhcpResult(const std::string &ifname, IDhcpResultNotify *pResultNotify, int timeouts)
942 {
943     if (ifname.empty()) {
944         WIFI_LOGE("DhcpClientServiceImpl::GetDhcpResult() error, ifname is empty!");
945         return DHCP_OPT_FAILED;
946     }
947 
948     if (pResultNotify == nullptr) {
949         WIFI_LOGE("GetDhcpResult() ifname:%{public}s error, pResultNotify is nullptr!", ifname.c_str());
950         return DHCP_OPT_FAILED;
951     }
952 
953     DhcpResultReq *pResultReq = new DhcpResultReq;
954     if (pResultReq == nullptr) {
955         WIFI_LOGE("GetDhcpResult() new failed! ifname:%{public}s.", ifname.c_str());
956         return DHCP_OPT_FAILED;
957     }
958     pResultReq->timeouts = timeouts;
959     pResultReq->getTimestamp = (uint32_t)time(NULL);
960     pResultReq->status = 0;
961     pResultReq->pResultNotify = pResultNotify;
962 
963     std::unique_lock<std::mutex> lock(mResultNotifyMutex);
964     ReleaseResultNotifyMemory();
965     m_mapDhcpResultNotify.clear();
966     std::list<DhcpResultReq *> listDhcpResultReq;
967     listDhcpResultReq.push_back(pResultReq);
968     m_mapDhcpResultNotify.emplace(std::make_pair(ifname, listDhcpResultReq));
969     WIFI_LOGI("GetDhcpResult() ifname:%{public}s,timeouts:%{public}d, result push_back!", ifname.c_str(), timeouts);
970     return DHCP_OPT_SUCCESS;
971 }
972 
RemoveDhcpResult(IDhcpResultNotify * pResultNotify)973 int DhcpClientServiceImpl::RemoveDhcpResult(IDhcpResultNotify *pResultNotify)
974 {
975     if (pResultNotify == nullptr) {
976         WIFI_LOGE("RemoveDhcpResult error, pResultNotify is nullptr!");
977         return DHCP_OPT_FAILED;
978     }
979 
980     std::unique_lock<std::mutex> lock(mResultNotifyMutex);
981     for (auto &itemNotify : m_mapDhcpResultNotify) {
982         auto iterReq = itemNotify.second.begin();
983         while (iterReq != itemNotify.second.end()) {
984             if ((*iterReq == nullptr) || ((*iterReq)->pResultNotify == nullptr)) {
985                 WIFI_LOGE("DhcpClientServiceImpl::RemoveDhcpResult error, *iterReq or pResultNotify is nullptr!");
986                 continue;
987             }
988             if ((*iterReq)->pResultNotify == pResultNotify) {
989                 delete *iterReq;
990                 *iterReq = nullptr;
991                 iterReq = itemNotify.second.erase(iterReq);
992             } else {
993                 ++iterReq;
994             }
995         }
996     }
997     WIFI_LOGI("RemoveDhcpResul success!");
998     return DHCP_OPT_SUCCESS;
999 }
1000 
GetDhcpInfo(const std::string & ifname,DhcpServiceInfo & dhcp)1001 int DhcpClientServiceImpl::GetDhcpInfo(const std::string &ifname, DhcpServiceInfo &dhcp)
1002 {
1003     if (ifname.empty()) {
1004         WIFI_LOGE("DhcpClientServiceImpl::GetDhcpInfo() error, ifname is empty!");
1005         return DHCP_OPT_FAILED;
1006     }
1007     pthread_mutex_lock(&m_DhcpResultInfoMutex);
1008     auto iter = DhcpClientServiceImpl::m_mapDhcpInfo.find(ifname);
1009     if (iter != DhcpClientServiceImpl::m_mapDhcpInfo.end()) {
1010         dhcp = iter->second;
1011     } else {
1012         WIFI_LOGE("GetDhcpInfo() failed, m_mapDhcpInfo no find ifname:%{public}s.", ifname.c_str());
1013     }
1014     pthread_mutex_unlock(&m_DhcpResultInfoMutex);
1015     return DHCP_OPT_SUCCESS;
1016 }
1017 
RenewDhcpClient(const std::string & ifname)1018 int DhcpClientServiceImpl::RenewDhcpClient(const std::string &ifname)
1019 {
1020     WIFI_LOGI("enter DhcpClientServiceImpl::RenewDhcpClient()...ifname:%{public}s.", ifname.c_str());
1021     int nStatus = GetDhcpStatus(ifname);
1022     if (nStatus != 1) {
1023         WIFI_LOGW("RenewDhcpClient() dhcp client service not started, now start ifname:%{public}s.", ifname.c_str());
1024 
1025         /* Start dhcp client service */
1026         pthread_mutex_lock(&m_DhcpResultInfoMutex);
1027         bool enableIPv6 = DhcpClientServiceImpl::m_mapDhcpInfo[ifname].enableIPv6;
1028         pthread_mutex_unlock(&m_DhcpResultInfoMutex);
1029         return StartDhcpClient(ifname, enableIPv6);
1030     }
1031 
1032     /* Send dhcp renew packet : kill -USR2 <pid> */
1033     pid_t pid = GetDhcpClientProPid(ifname);
1034     if (pid <= 0) {
1035         WIFI_LOGW("RenewDhcpClient() dhcp client process pid:%{public}d error, ifname:%{public}s!",
1036             pid, ifname.c_str());
1037         return DHCP_OPT_FAILED;
1038     }
1039 
1040     if (kill(pid, SIGUSR2) == -1) {
1041         WIFI_LOGE("RenewDhcpClient() kill [%{public}d] failed:%{public}d, ifname:%{public}s!",
1042             pid, errno, ifname.c_str());
1043         return DHCP_OPT_FAILED;
1044     }
1045     WIFI_LOGI("RenewDhcpClient() kill [%{public}d] success, ifname:%{public}s.", pid, ifname.c_str());
1046     return DHCP_OPT_SUCCESS;
1047 }
1048 
ReleaseDhcpClient(const std::string & ifname)1049 int DhcpClientServiceImpl::ReleaseDhcpClient(const std::string &ifname)
1050 {
1051     WIFI_LOGI("enter DhcpClientServiceImpl::ReleaseDhcpClient()...ifname:%{public}s.", ifname.c_str());
1052     int nStatus = GetDhcpStatus(ifname);
1053     if (nStatus != 1) {
1054         WIFI_LOGE("ReleaseDhcpClient() failed, dhcp client service not started, ifname:%{public}s!", ifname.c_str());
1055         return DHCP_OPT_FAILED;
1056     }
1057 
1058     /* Send dhcp release packet : kill -USR1 <pid> */
1059     pid_t pid = GetDhcpClientProPid(ifname);
1060     if (pid <= 0) {
1061         WIFI_LOGW("ReleaseDhcpClient() dhcp client process pid:%{public}d error, ifname:%{public}s!",
1062             pid, ifname.c_str());
1063         return DHCP_OPT_FAILED;
1064     }
1065 
1066     if (kill(pid, SIGUSR1) == -1) {
1067         WIFI_LOGE("ReleaseDhcpClient() kill [%{public}d] failed:%{public}d, ifname:%{public}s!",
1068             pid, errno, ifname.c_str());
1069         return DHCP_OPT_FAILED;
1070     }
1071     WIFI_LOGI("ReleaseDhcpClient() kill [%{public}d] success, ifname:%{public}s.", pid, ifname.c_str());
1072     return DHCP_OPT_SUCCESS;
1073 }
1074 }  // namespace Wifi
1075 }  // namespace OHOS
1076