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