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 #include "dhcp_client_state_machine.h"
16
17 #include <cstdio>
18 #include <cstdlib>
19 #include <string.h>
20 #include <unistd.h>
21 #include <fcntl.h>
22 #include <sys/time.h>
23 #include <cerrno>
24 #include <csignal>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <sys/socket.h>
28 #include <sys/file.h>
29 #include <netinet/in.h>
30 #include <arpa/inet.h>
31 #include <netinet/if_ether.h>
32 #include <net/if_arp.h>
33 #include <memory>
34 #include <string>
35
36 #include "securec.h"
37 #include "dhcp_common_utils.h"
38 #include "dhcp_result.h"
39 #include "dhcp_result_store_manager.h"
40 #include "dhcp_options.h"
41 #include "dhcp_socket.h"
42 #include "dhcp_function.h"
43 #include "dhcp_logger.h"
44 #include "dhcp_thread.h"
45 #include "dhcp_define.h"
46
47 #ifdef INIT_LIB_ENABLE
48 #include "parameter.h"
49 #endif
50 #ifndef FALLTHROUGH_INTENDED
51 #define FALLTHROUGH_INTENDED [[clang::fallthrough]] //NOLINT
52 #endif
53 DEFINE_DHCPLOG_DHCP_LABEL("DhcpIpv4");
54
55 namespace OHOS {
56 namespace DHCP {
57 constexpr uint32_t FAST_ARP_DETECTION_TIME_MS = 50;
58 constexpr uint32_t SLOW_ARP_DETECTION_TIME_MS = 80;
59 constexpr uint32_t SLOW_ARP_TOTAL_TIME_MS = 4 * 1000;
60 constexpr uint32_t SLOW_ARP_TOTAL_TIME_S = 4;
61 constexpr uint32_t SLOW_ARP_DETECTION_TRY_CNT = 2;
62 constexpr int DHCP_IP_TYPE_A = 128;
63 constexpr int DHCP_IP_TYPE_B = 192;
64 constexpr int DHCP_IP_TYPE_C = 224;
65 constexpr uint32_t DEFAULT_TIMEROUT_ETH0 = 72 * 1000; // 72s
DhcpClientStateMachine(std::string ifname)66 DhcpClientStateMachine::DhcpClientStateMachine(std::string ifname) :
67 m_dhcp4State(DHCP_STATE_INIT),
68 m_sockFd(-1),
69 m_resendTimer(0),
70 m_sentPacketNum(0),
71 m_timeoutTimestamp(0),
72 m_renewalTimestamp(0),
73 m_renewalTimestampBoot(0),
74 m_leaseTime(0),
75 m_renewalSec(0),
76 m_rebindSec(0),
77 m_requestedIp4(0),
78 m_serverIp4(0),
79 m_socketMode(SOCKET_MODE_INVALID),
80 m_transID(0),
81 m_ifName(ifname),
82 ipv4Thread_(nullptr),
83 m_slowArpDetecting(false),
84 firstSendPacketTime_(0),
85 slowArpTimeoutTimerId_(0)
86 {
87 #ifndef OHOS_ARCH_LITE
88 m_slowArpTaskId =0 ;
89 getIpTimerId = 0;
90 renewDelayTimerId = 0;
91 rebindDelayTimerId = 0;
92 remainingDelayTimerId = 0;
93 timeOut_ = DhcpTimer::DEFAULT_TIMEROUT;
94 if (ifname == "eth0") {
95 timeOut_ = DEFAULT_TIMEROUT_ETH0;
96 }
97 #endif
98 m_cltCnf.ifaceIndex = 0;
99 threadExit_ = true;
100 m_conflictCount = 0;
101 m_cltCnf.ifaceIpv4 = 0;
102 m_cltCnf.getMode = DHCP_IP_TYPE_NONE;
103 m_cltCnf.isIpv6 = false;
104 m_slowArpCallback = [this](bool isReachable) { this->SlowArpDetectCallback(isReachable); };
105 DHCP_LOGI("DhcpClientStateMachine()");
106 ipv4Thread_ = std::make_unique<DhcpThread>("InnerIpv4Thread");
107 }
108
~DhcpClientStateMachine()109 DhcpClientStateMachine::~DhcpClientStateMachine()
110 {
111 DHCP_LOGI("~DhcpClientStateMachine()");
112 if (ipv4Thread_) {
113 DHCP_LOGI("~DhcpClientStateMachine ipv4Thread_ reset!");
114 ipv4Thread_.reset();
115 }
116 }
117
InitSignalHandle()118 int DhcpClientStateMachine::InitSignalHandle()
119 {
120 if (socketpair(AF_UNIX, SOCK_STREAM, 0, m_sigSockFds) != 0) {
121 DHCP_LOGE("InitSignalHandle socketpair m_sigSockFds failed, error:%{public}d", errno);
122 return DHCP_OPT_FAILED;
123 }
124 DHCP_LOGI("InitSignalHandle socketpair 0:%{public}d 1:%{public}d", m_sigSockFds[0], m_sigSockFds[1]);
125 return DHCP_OPT_SUCCESS;
126 }
127
CloseSignalHandle()128 int DhcpClientStateMachine::CloseSignalHandle()
129 {
130 for (int i = 0; i < NUMBER_TWO; i++) {
131 DHCP_LOGI("CloseSignalHandle m_sigSockFds, i:%{public}d %{public}d", i, m_sigSockFds[i]);
132 close(m_sigSockFds[i]);
133 }
134 return DHCP_OPT_SUCCESS;
135 }
136
RunGetIPThreadFunc(const DhcpClientStateMachine & instance)137 void DhcpClientStateMachine::RunGetIPThreadFunc(const DhcpClientStateMachine &instance)
138 {
139 DHCP_LOGI("RunGetIPThreadFunc begin.");
140 if ((m_cltCnf.getMode == DHCP_IP_TYPE_ALL) || (m_cltCnf.getMode == DHCP_IP_TYPE_V4)) {
141 threadExit_ = false;
142 StartIpv4(); // Handle dhcp v4.
143 }
144 return;
145 }
146
InitConfig(const std::string & ifname,bool isIpv6)147 int DhcpClientStateMachine::InitConfig(const std::string &ifname, bool isIpv6)
148 {
149 if (InitSpecifiedClientCfg(ifname, isIpv6) != DHCP_OPT_SUCCESS) {
150 DHCP_LOGE("InitConfig InitSpecifiedClientCfg failed!");
151 return DHCP_OPT_FAILED;
152 }
153 if (GetClientNetworkInfo() != DHCP_OPT_SUCCESS) {
154 DHCP_LOGE("InitConfig GetClientNetworkInfo failed!");
155 return DHCP_OPT_FAILED;
156 }
157 m_slowArpDetecting = false;
158 return DHCP_OPT_SUCCESS;
159 }
160
StartIpv4Type(const std::string & ifname,bool isIpv6,ActionMode action)161 int DhcpClientStateMachine::StartIpv4Type(const std::string &ifname, bool isIpv6, ActionMode action)
162 {
163 DHCP_LOGI("StartIpv4Type ifname:%{public}s isIpv6:%{public}d threadExit:%{public}d action:%{public}d",
164 ifname.c_str(), isIpv6, threadExit_.load(), action);
165 m_ifName = ifname;
166 m_action = action;
167 #ifndef OHOS_ARCH_LITE
168 StopTimer(getIpTimerId);
169 StartTimer(TIMER_GET_IP, getIpTimerId, timeOut_, true);
170 #endif
171 if (InitConfig(ifname, isIpv6) != DHCP_OPT_SUCCESS) {
172 DHCP_LOGE("StartIpv4Type InitConfig failed!");
173 return DHCP_OPT_FAILED;
174 }
175 if ((m_action == ACTION_START_NEW) || (m_action == ACTION_START_OLD)) {
176 InitStartIpv4Thread(ifname, isIpv6);
177 } else {
178 DHCP_LOGI("StartIpv4Type not supported m_action:%{public}d", m_action);
179 }
180 return DHCP_OPT_SUCCESS;
181 }
182
183
InitStartIpv4Thread(const std::string & ifname,bool isIpv6)184 int DhcpClientStateMachine::InitStartIpv4Thread(const std::string &ifname, bool isIpv6)
185 {
186 DHCP_LOGI("InitStartIpv4Thread, ifname:%{public}s, isIpv6:%{public}d, threadExit:%{public}d", ifname.c_str(),
187 isIpv6, threadExit_.load());
188 if (!threadExit_.load()) {
189 DHCP_LOGI("InitStartIpv4Thread ipv4Thread is run!");
190 return DHCP_OPT_FAILED;
191 }
192
193 if (!ipv4Thread_) {
194 DHCP_LOGI("InitStartIpv4Thread make_unique ipv4Thread_");
195 ipv4Thread_ = std::make_unique<DhcpThread>("InnerIpv4Thread");
196 }
197 std::function<void()> func = [this]() { RunGetIPThreadFunc(std::ref(*this)); };
198 int delayTime = 0;
199 bool result = ipv4Thread_->PostAsyncTask(func, delayTime);
200 if (!result) {
201 DHCP_LOGE("InitStartIpv4Thread ipv4Thread_ RunGetIPThreadFunc failed!");
202 return DHCP_OPT_FAILED;
203 }
204 DHCP_LOGE("InitStartIpv4Thread ipv4Thread_ RunGetIPThreadFunc ok");
205 return DHCP_OPT_SUCCESS;
206 }
207
InitSpecifiedClientCfg(const std::string & ifname,bool isIpv6)208 int DhcpClientStateMachine::InitSpecifiedClientCfg(const std::string &ifname, bool isIpv6)
209 {
210 if ((strncpy_s(m_cltCnf.workDir, sizeof(m_cltCnf.workDir), WORKDIR, DIR_MAX_LEN - 1) != EOK) ||
211 (strncpy_s(m_cltCnf.ifaceName, sizeof(m_cltCnf.ifaceName), ifname.c_str(), ifname.size()) != EOK)) {
212 return DHCP_OPT_FAILED;
213 }
214
215 if (strlen(m_cltCnf.workDir) == 0) {
216 DHCP_LOGE("InitSpecifiedClientCfg() m_cltCnf.workDir:%{public}s error!", m_cltCnf.workDir);
217 return DHCP_OPT_FAILED;
218 }
219
220 if (CreateDirs(m_cltCnf.workDir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != DHCP_OPT_SUCCESS) {
221 DHCP_LOGE("InitSpecifiedClientCfg() CreateDirs %{public}s failed!", m_cltCnf.workDir);
222 return DHCP_OPT_FAILED;
223 }
224
225 if (snprintf_s(m_cltCnf.confFile, DIR_MAX_LEN, DIR_MAX_LEN - 1, "%s%s", m_cltCnf.workDir, DHCPC_CONF) < 0) {
226 return DHCP_OPT_FAILED;
227 }
228
229 if (snprintf_s(m_cltCnf.resultFile, DIR_MAX_LEN, DIR_MAX_LEN - 1, "%s%s.result",
230 m_cltCnf.workDir, m_cltCnf.ifaceName) < 0) {
231 return DHCP_OPT_FAILED;
232 }
233
234 if (snprintf_s(m_cltCnf.leaseFile, DIR_MAX_LEN, DIR_MAX_LEN - 1, "%sdhcp_client_service-%s.lease",
235 m_cltCnf.workDir, m_cltCnf.ifaceName) < 0) {
236 return DHCP_OPT_FAILED;
237 }
238
239 if (snprintf_s(m_cltCnf.result6File, DIR_MAX_LEN, DIR_MAX_LEN - 1, "%sdhcp_client_service-6-%s.lease",
240 m_cltCnf.workDir, m_cltCnf.ifaceName) < 0) {
241 return DHCP_OPT_FAILED;
242 }
243 m_cltCnf.getMode = DHCP_IP_TYPE_ALL;
244 m_cltCnf.isIpv6 = isIpv6;
245 isIpv6 ? m_cltCnf.getMode = DHCP_IP_TYPE_ALL : m_cltCnf.getMode = DHCP_IP_TYPE_V4;
246
247 DHCP_LOGD("InitSpecifiedClientCfg: ifaceName:%{public}s, workDir:%{public}s, confFile:%{public}s,"
248 "leaseFile:%{public}s,resultFile:%{public}s,result6File:%{public}s,getMode:%{public}d", m_cltCnf.ifaceName,
249 m_cltCnf.workDir, m_cltCnf.confFile, m_cltCnf.leaseFile,m_cltCnf.resultFile, m_cltCnf.result6File,
250 m_cltCnf.getMode);
251 return DHCP_OPT_SUCCESS;
252 }
253
GetClientNetworkInfo(void)254 int DhcpClientStateMachine::GetClientNetworkInfo(void)
255 {
256 if (GetLocalInterface(m_cltCnf.ifaceName, &m_cltCnf.ifaceIndex, m_cltCnf.ifaceMac, NULL) != DHCP_OPT_SUCCESS) {
257 DHCP_LOGE("GetClientNetworkInfo() GetLocalInterface failed, ifaceName:%{public}s.", m_cltCnf.ifaceName);
258 return DHCP_OPT_FAILED;
259 }
260
261 char macAddr[MAC_ADDR_LEN * MAC_ADDR_CHAR_NUM];
262 if (memset_s(macAddr, sizeof(macAddr), 0, sizeof(macAddr)) != EOK) {
263 DHCP_LOGE("GetClientNetworkInfo() memset_s failed!");
264 return DHCP_OPT_FAILED;
265 }
266 if (!MacChConToMacStr(m_cltCnf.ifaceMac, MAC_ADDR_LEN, macAddr, sizeof(macAddr))) {
267 DHCP_LOGE("MacChConToMacStr() failed!");
268 return DHCP_OPT_FAILED;
269 }
270 DHCP_LOGI("GetClientNetworkInfo() m_cltCnf.ifaceName:%{public}s -> ifaceIndex:%{public}d,ifaceMac:%{private}s.",
271 m_cltCnf.ifaceName, m_cltCnf.ifaceIndex, macAddr);
272
273 if (GetLocalIp(m_cltCnf.ifaceName, &m_cltCnf.ifaceIpv4) != DHCP_OPT_SUCCESS) {
274 DHCP_LOGE("GetClientNetworkInfo() failed, m_cltCnf.ifaceName:%{public}s.", m_cltCnf.ifaceName);
275 return DHCP_OPT_FAILED;
276 }
277 std::string cIp = Ip4IntConvertToStr(m_cltCnf.ifaceIpv4, true);
278 if (cIp.empty()) {
279 DHCP_LOGE("GetClientNetworkInfo() Ip4IntConvertToStr m_cltCnf.ifaceIpv4 failed!");
280 return DHCP_OPT_FAILED;
281 }
282 DHCP_LOGI("GetClientNetworkInfo() GetLocalIp ifaceName:%{public}s -> ifaceIpv4:%{private}u - %{private}s.",
283 m_cltCnf.ifaceName, m_cltCnf.ifaceIpv4, cIp.c_str());
284 return DHCP_OPT_SUCCESS;
285 }
286
StartIpv4()287 void DhcpClientStateMachine::StartIpv4()
288 {
289 int nRet;
290 fd_set readfds;
291 struct timeval timeout;
292 timeout.tv_sec = 0;
293 timeout.tv_usec = SELECT_TIMEOUT_US;
294 int sockFdRaw = -1;
295 int sockFdkernel = -1;
296 if ((m_action != ACTION_RENEW_T1) && (m_action != ACTION_RENEW_T2) && (m_action != ACTION_RENEW_T3)) {
297 DhcpInit();
298 }
299 firstSendPacketTime_ = 0;
300 if (!InitSocketFd(sockFdRaw, sockFdkernel)) {
301 threadExit_ = true;
302 return;
303 }
304 DHCP_LOGI("StartIpv4 m_dhcp4State:%{public}d m_action:%{public}d", m_dhcp4State, m_action);
305 for (; ;) {
306 if (threadExit_.load()) {
307 DHCP_LOGI("StartIpv4 send packet timed out, now break!");
308 break;
309 }
310 int sockFd = (m_socketMode == SOCKET_MODE_RAW) ? sockFdRaw : sockFdkernel;
311 FD_ZERO(&readfds);
312 FD_SET(sockFd, &readfds);
313 time_t curTimestamp = time(NULL);
314 if (curTimestamp == static_cast<time_t>(-1)) {
315 DHCP_LOGI("StartIpv4, time return failed");
316 }
317 if (m_timeoutTimestamp - curTimestamp <= 0) {
318 DHCP_LOGI("StartIpv4 already timed out, need send or resend packet...");
319 DhcpRequestHandle(curTimestamp);
320 continue;
321 }
322 nRet = select(sockFd + 1, &readfds, NULL, NULL, &timeout);
323 if ((nRet == -1) && (errno == EINTR)) {
324 DHCP_LOGI("StartIpv4 select err:%{public}d, a signal was caught!", errno);
325 continue;
326 }
327 if (FD_ISSET(sockFd, &readfds)) {
328 DhcpResponseHandle(curTimestamp, sockFd);
329 }
330 }
331 close(sockFdRaw);
332 close(sockFdkernel);
333 DHCP_LOGI("StartIpv4 exit");
334 }
335
ExitIpv4(void)336 int DhcpClientStateMachine::ExitIpv4(void)
337 {
338 if (threadExit_.load()) {
339 CloseSignalHandle();
340 }
341 DHCP_LOGI("ExitIpv4 threadExit:%{public}d", threadExit_.load());
342 return DHCP_OPT_SUCCESS;
343 }
344
StopIpv4(void)345 int DhcpClientStateMachine::StopIpv4(void)
346 {
347 DHCP_LOGI("StopIpv4 threadExit:%{public}d", threadExit_.load());
348 if (!threadExit_.load()) {
349 threadExit_ = true;
350 m_slowArpDetecting = false;
351 m_conflictCount = 0;
352 #ifndef OHOS_ARCH_LITE
353 StopTimer(getIpTimerId);
354 StopTimer(slowArpTimeoutTimerId_);
355 DHCP_LOGI("UnRegister slowArpTask: %{public}u", m_slowArpTaskId);
356 DhcpTimer::GetInstance()->UnRegister(m_slowArpTaskId);
357 m_slowArpTaskId = 0;
358 #endif
359 }
360 return DHCP_OPT_SUCCESS;
361 }
362
GetAction(void)363 ActionMode DhcpClientStateMachine::GetAction(void)
364 {
365 return m_action;
366 }
367
DhcpInit(void)368 void DhcpClientStateMachine::DhcpInit(void)
369 {
370 DHCP_LOGI("DhcpInit m_dhcp4State:%{public}d", m_dhcp4State);
371 /* Init dhcp ipv4 state. */
372 m_dhcp4State = DHCP_STATE_INIT;
373 m_resendTimer = 0;
374 m_sentPacketNum = 0;
375 m_timeoutTimestamp = 0;
376 m_conflictCount = 0;
377 SetSocketMode(SOCKET_MODE_RAW);
378
379 std::string arpIgnore = "/proc/sys/net/ipv4/conf/" + m_ifName + "/arp_ignore";
380 ModifyKernelFile(arpIgnore, "2");
381 std::string arpAnnounce = "/proc/sys/net/ipv4/conf/" + m_ifName + "/arp_announce";
382 ModifyKernelFile(arpAnnounce, "2");
383
384 time_t t = time(NULL);
385 if (t == (time_t)-1) {
386 return;
387 }
388 Reboot(t);
389 }
390
ModifyKernelFile(const std::string & filePath,const char * num)391 void DhcpClientStateMachine::ModifyKernelFile(const std::string &filePath, const char* num)
392 {
393 if (!IsValidPath(filePath)) {
394 DHCP_LOGE("invalid path:%{public}s", filePath.c_str());
395 return;
396 }
397 FILE* file = fopen(filePath.c_str(), "w");
398 if (file == nullptr) {
399 DHCP_LOGI("Failed to open file");
400 return;
401 }
402 if (fwrite(num, 1, 1, file) != 1) {
403 DHCP_LOGI("Failed to write file");
404 (void)fclose(file);
405 return;
406 }
407 (void)fflush(file);
408 (void)fsync(fileno(file));
409 (void)fclose(file);
410 }
411
InitSocketFd(int & sockFdRaw,int & sockFdkernel)412 bool DhcpClientStateMachine::InitSocketFd(int &sockFdRaw, int &sockFdkernel)
413 {
414 if (CreateRawSocket(&sockFdRaw) != SOCKET_OPT_SUCCESS) {
415 DHCP_LOGE("InitSocketFd CreateRawSocket failed, fd:%{public}d,index:%{public}d failed!",
416 sockFdRaw, m_cltCnf.ifaceIndex);
417 return false;
418 }
419 if (BindRawSocket(sockFdRaw, m_cltCnf.ifaceIndex, NULL) != SOCKET_OPT_SUCCESS) {
420 DHCP_LOGE("InitSocketFd BindRawSocket failed, fd:%{public}d,index:%{public}d failed!",
421 sockFdRaw, m_cltCnf.ifaceIndex);
422 return false;
423 }
424
425 if (CreateKernelSocket(&sockFdkernel) != SOCKET_OPT_SUCCESS) {
426 DHCP_LOGE("InitSocketFd CreateKernelSocket failed, fd:%{public}d,index:%{public}d failed!",
427 sockFdkernel, m_cltCnf.ifaceIndex);
428 close(sockFdRaw);
429 return false;
430 }
431 if (BindKernelSocket(sockFdkernel, m_cltCnf.ifaceName, INADDR_ANY, BOOTP_CLIENT, true) != SOCKET_OPT_SUCCESS) {
432 DHCP_LOGE("InitSocketFd BindKernelSocket failed, fd:%{public}d,ifname:%{public}s failed!",
433 sockFdkernel, m_cltCnf.ifaceName);
434 close(sockFdRaw);
435 return false;
436 }
437
438 DHCP_LOGI("InitSocketFd success, sockFdRaw:%{public}d sockFdkernel:%{public}d ifname:%{public}s!",
439 sockFdRaw, sockFdkernel, m_cltCnf.ifaceName);
440 return true;
441 }
442
GetPacketReadSockFd(void)443 int DhcpClientStateMachine::GetPacketReadSockFd(void)
444 {
445 return m_sockFd;
446 }
447
GetSigReadSockFd(void)448 int DhcpClientStateMachine::GetSigReadSockFd(void)
449 {
450 return m_sigSockFds[0];
451 }
452
GetDhcpTransID(void)453 uint32_t DhcpClientStateMachine::GetDhcpTransID(void)
454 {
455 return m_transID;
456 }
457
SetSocketMode(uint32_t mode)458 void DhcpClientStateMachine::SetSocketMode(uint32_t mode)
459 {
460 m_socketMode = mode;
461 DHCP_LOGI("SetSocketMode() the socket mode %{public}s.", (mode == SOCKET_MODE_RAW) ? "raw"
462 : ((mode == SOCKET_MODE_KERNEL) ? "kernel" : "not valid"));
463 }
464
ExecDhcpRenew(void)465 int DhcpClientStateMachine::ExecDhcpRenew(void)
466 {
467 DHCP_LOGI("ExecDhcpRenew m_dhcp4State:%{public}d", m_dhcp4State);
468 /* Set socket mode and dhcp ipv4 state, make sure dhcp packets can be sent normally. */
469 switch (m_dhcp4State) {
470 case DHCP_STATE_INIT:
471 FALLTHROUGH_INTENDED;
472 case DHCP_STATE_SELECTING:
473 DHCP_LOGI("ExecDhcpRenew() dhcp ipv4 old state:%{public}d, no need change state.", m_dhcp4State);
474 break;
475 case DHCP_STATE_REQUESTING:
476 FALLTHROUGH_INTENDED;
477 case DHCP_STATE_RELEASED:
478 FALLTHROUGH_INTENDED;
479 case DHCP_STATE_RENEWED:
480 DHCP_LOGI("ExecDhcpRenew() dhcp ipv4 old state:%{public}d, init state:INIT.", m_dhcp4State);
481 /* Init socket mode and dhcp ipv4 state. */
482 m_dhcp4State = DHCP_STATE_INIT;
483 SetSocketMode(SOCKET_MODE_RAW);
484 break;
485 case DHCP_STATE_BOUND:
486 FALLTHROUGH_INTENDED;
487 case DHCP_STATE_RENEWING:
488 FALLTHROUGH_INTENDED;
489 case DHCP_STATE_REBINDING:
490 DHCP_LOGI("ExecDhcpRenew() dhcp ipv4 old state:%{public}d, set state:RENEWED.", m_dhcp4State);
491 /* Set dhcp ipv4 state, send request packet. */
492 m_dhcp4State = DHCP_STATE_RENEWED;
493 break;
494 default:
495 break;
496 }
497
498 /* Start record again, go back to init state. */
499 m_sentPacketNum = 0;
500 m_timeoutTimestamp = 0;
501 DHCP_LOGI("ExecDhcpRenew() a dhcp renew is executed...");
502 return DHCP_OPT_SUCCESS;
503 }
504
ExecDhcpRelease(void)505 int DhcpClientStateMachine::ExecDhcpRelease(void)
506 {
507 /* Ensure that we've received dhcp ack packet completely. */
508 if ((m_dhcp4State == DHCP_STATE_BOUND) || (m_dhcp4State == DHCP_STATE_RENEWING) ||
509 (m_dhcp4State == DHCP_STATE_REBINDING)) {
510 /* Unicast dhcp release packet. */
511 DhcpRelease(m_requestedIp4, m_serverIp4);
512 }
513
514 m_dhcp4State = DHCP_STATE_RELEASED;
515 SetSocketMode(SOCKET_MODE_INVALID);
516
517 /* Ensure that the function select() is always blocked and don't need to receive ip from dhcp server. */
518 m_timeoutTimestamp = SIGNED_INTEGER_MAX;
519
520 DHCP_LOGI("ExecDhcpRelease() enter released state...");
521 return DHCP_OPT_SUCCESS;
522 }
523
AddParamaterRequestList(struct DhcpPacket * packet)524 void DhcpClientStateMachine::AddParamaterRequestList(struct DhcpPacket *packet)
525 {
526 int end = GetEndOptionIndex(packet->options);
527 int i;
528 int len = 0;
529 const uint8_t arrReqCode[DHCP_REQ_CODE_NUM] = {
530 SUBNET_MASK_OPTION,
531 ROUTER_OPTION,
532 DOMAIN_NAME_SERVER_OPTION,
533 DOMAIN_NAME_OPTION,
534 INTERFACE_MTU_OPTION,
535 BROADCAST_ADDRESS_OPTION,
536 IP_ADDRESS_LEASE_TIME_OPTION,
537 RENEWAL_TIME_VALUE_OPTION,
538 REBINDING_TIME_VALUE_OPTION,
539 VENDOR_SPECIFIC_INFO_OPTION,
540 CAPTIVE_PORTAL_OPTION,
541 IPV6_ONLY_PREFERRED_OPTION
542 };
543
544 packet->options[end + DHCP_OPT_CODE_INDEX] = PARAMETER_REQUEST_LIST_OPTION;
545 for (i = 0; i < DHCP_REQ_CODE_NUM; i++) {
546 if ((arrReqCode[i] > PAD_OPTION) && (arrReqCode[i] < END_OPTION)) {
547 packet->options[end + DHCP_OPT_DATA_INDEX + len++] = arrReqCode[i];
548 }
549 }
550 packet->options[end + DHCP_OPT_LEN_INDEX] = len;
551 packet->options[end + DHCP_OPT_DATA_INDEX + len] = END_OPTION;
552 }
553
GetRandomId(void)554 uint32_t DhcpClientStateMachine::GetRandomId(void)
555 {
556 static bool bSranded = false;
557 if (!bSranded) {
558 unsigned int uSeed = 0;
559 int nFd = -1;
560 if ((nFd = open("/dev/urandom", 0)) == -1) {
561 DHCP_LOGE("GetRandomId() open /dev/urandom failed, error:%{public}d!", errno);
562 uSeed = time(NULL);
563 } else {
564 if (read(nFd, &uSeed, sizeof(uSeed)) == -1) {
565 DHCP_LOGE("GetRandomId() read /dev/urandom failed, error:%{public}d!", errno);
566 uSeed = time(NULL);
567 }
568 DHCP_LOGI("GetRandomId() read /dev/urandom uSeed:%{public}u.", uSeed);
569 close(nFd);
570 }
571 srandom(uSeed);
572 bSranded = true;
573 }
574 return random();
575 }
576
InitSelecting(time_t timestamp)577 void DhcpClientStateMachine::InitSelecting(time_t timestamp)
578 {
579 if (m_sentPacketNum > TIMEOUT_TIMES_MAX) {
580 // Send packet timed out, now exit process.
581 DHCP_LOGI("InitSelecting() send packet timed out %{public}u times, now exit process!", m_sentPacketNum);
582 m_timeoutTimestamp = timestamp + TIMEOUT_MORE_WAIT_SEC;
583 m_sentPacketNum = 0;
584 return;
585 }
586
587 if (m_sentPacketNum == 0) {
588 m_transID = GetRandomId();
589 }
590
591 /* Broadcast dhcp discover packet. */
592 DhcpDiscover(m_transID, m_requestedIp4);
593 m_dhcp4State = DHCP_STATE_SELECTING;
594
595 uint32_t uTimeoutSec = TIMEOUT_WAIT_SEC << (m_sentPacketNum > MAX_WAIT_TIMES ? MAX_WAIT_TIMES : m_sentPacketNum);
596 if ((uTimeoutSec > DHCP_FAILE_TIMEOUT_THR) && (m_action != ACTION_RENEW_T3)) {
597 TryCachedIp();
598 }
599 m_timeoutTimestamp = timestamp + static_cast<int64_t>(uTimeoutSec);
600 DHCP_LOGI("InitSelecting() DhcpDiscover m_sentPacketNum:%{public}u,timeoutSec:%{public}u,"
601 "timestamp:%{public}" PRId64,
602 m_sentPacketNum,
603 uTimeoutSec,
604 m_timeoutTimestamp);
605 m_sentPacketNum++;
606 }
607
AddParamaterRebootList(struct DhcpPacket * packet)608 void DhcpClientStateMachine::AddParamaterRebootList(struct DhcpPacket *packet)
609 {
610 int end = GetEndOptionIndex(packet->options);
611 int i;
612 int len = 0;
613 const uint8_t arrReqCode[DHCP_REQ_CODE_NUM] = {
614 SUBNET_MASK_OPTION,
615 ROUTER_OPTION,
616 DOMAIN_NAME_SERVER_OPTION,
617 DOMAIN_NAME_OPTION,
618 INTERFACE_MTU_OPTION,
619 BROADCAST_ADDRESS_OPTION,
620 IP_ADDRESS_LEASE_TIME_OPTION,
621 RENEWAL_TIME_VALUE_OPTION,
622 REBINDING_TIME_VALUE_OPTION,
623 VENDOR_SPECIFIC_INFO_OPTION,
624 CAPTIVE_PORTAL_OPTION,
625 IPV6_ONLY_PREFERRED_OPTION
626 };
627
628 packet->options[end + DHCP_OPT_CODE_INDEX] = PARAMETER_REQUEST_LIST_OPTION;
629 for (i = 0; i < DHCP_REQ_CODE_NUM; i++) {
630 if ((arrReqCode[i] > PAD_OPTION) && (arrReqCode[i] < END_OPTION)) {
631 packet->options[end + DHCP_OPT_DATA_INDEX + len++] = arrReqCode[i];
632 }
633 }
634 packet->options[end + DHCP_OPT_LEN_INDEX] = len;
635 packet->options[end + DHCP_OPT_DATA_INDEX + len] = END_OPTION;
636 }
637
DhcpReboot(uint32_t transid,uint32_t reqip)638 int DhcpClientStateMachine::DhcpReboot(uint32_t transid, uint32_t reqip)
639 {
640 DHCP_LOGI("DhcpReboot send request, transid:%{public}u, clientip:%{public}s", transid,
641 IntIpv4ToAnonymizeStr(reqip).c_str());
642 struct DhcpPacket packet;
643 if (memset_s(&packet, sizeof(struct DhcpPacket), 0, sizeof(struct DhcpPacket)) != EOK) {
644 DHCP_LOGE("DhcpReboot() memset_s failed!");
645 return -1;
646 }
647
648 /* Get packet header and common info. */
649 if (GetPacketHeaderInfo(&packet, DHCP_REQUEST) != DHCP_OPT_SUCCESS) {
650 DHCP_LOGE("DhcpReboot() GetPacketHeaderInfo failed!");
651 return -1;
652 }
653
654 if (memcpy_s(packet.chaddr, sizeof(packet.chaddr), m_cltCnf.ifaceMac, MAC_ADDR_LEN) != EOK) {
655 DHCP_LOGE("DhcpReboot() failed, memcpy_s error!");
656 return -1;
657 }
658 packet.xid = transid;
659 /* Set Reboot Request seconds elapsed. */
660 SetSecondsElapsed(&packet);
661 AddClientIdToOpts(&packet); // 61
662 AddOptValueToOpts(packet.options, REQUESTED_IP_ADDRESS_OPTION, reqip); //50
663 AddOptValueToOpts(packet.options, MAXIMUM_DHCP_MESSAGE_SIZE_OPTION, MAX_MSG_SIZE); //57
664 AddHostNameToOpts(&packet); // 60 12
665 AddParamaterRebootList(&packet); // 55
666 DHCP_LOGI("DhcpReboot begin broadcast dhcp request packet");
667 return SendToDhcpPacket(&packet, INADDR_ANY, INADDR_BROADCAST, m_cltCnf.ifaceIndex, (uint8_t *)MAC_BCAST_ADDR);
668 }
669
SendReboot(uint32_t targetIp,time_t timestamp)670 void DhcpClientStateMachine::SendReboot(uint32_t targetIp, time_t timestamp)
671 {
672 if (m_sentPacketNum >= NUMBER_TWO) {
673 m_dhcp4State = DHCP_STATE_INIT;
674 SetSocketMode(SOCKET_MODE_RAW);
675 m_sentPacketNum = 0;
676 m_timeoutTimestamp = timestamp;
677 return;
678 }
679
680 uint32_t uTimeoutSec = TIMEOUT_WAIT_SEC << (m_sentPacketNum > MAX_WAIT_TIMES ? MAX_WAIT_TIMES : m_sentPacketNum);
681 m_timeoutTimestamp = timestamp + static_cast<int64_t>(uTimeoutSec);
682 m_requestedIp4 = targetIp;
683 DhcpReboot(m_transID, m_requestedIp4);
684 DHCP_LOGI("SendReboot() SendReboot m_sentPacketNum:%{public}u,timeoutSec:%{public}u,"
685 "timeoutTimestamp:%{public}" PRId64,
686 m_sentPacketNum,
687 uTimeoutSec,
688 m_timeoutTimestamp);
689 m_sentPacketNum++;
690 }
691
Reboot(time_t timestamp)692 void DhcpClientStateMachine::Reboot(time_t timestamp)
693 {
694 if (strncmp(m_cltCnf.ifaceName, "wlan", NUMBER_FOUR) != 0) {
695 DHCP_LOGI("ifaceName is not wlan, not Reboot");
696 return;
697 }
698
699 if (m_routerCfg.bssid.empty()) {
700 DHCP_LOGE("m_routerCfg.bssid is empty, no need reboot");
701 return;
702 }
703
704 IpInfoCached ipInfoCached;
705 if (GetCachedDhcpResult(m_routerCfg.bssid, ipInfoCached) != 0) {
706 DHCP_LOGE("not find cache ip for m_routerCfg.bssid");
707 return;
708 }
709 if (static_cast<int64_t>(timestamp) > ipInfoCached.absoluteLeasetime) {
710 DHCP_LOGE("Lease has expired, need get new ip");
711 return;
712 }
713
714 uint32_t lastAssignedIpv4Addr = 0;
715 if (!Ip4StrConToInt(ipInfoCached.ipResult.strYiaddr, &lastAssignedIpv4Addr, false)) {
716 DHCP_LOGE("lastAssignedIpv4Addr get failed");
717 return;
718 }
719
720 if (lastAssignedIpv4Addr != 0) {
721 m_transID = GetRandomId();
722 m_dhcp4State = DHCP_STATE_INITREBOOT;
723 m_sentPacketNum = 0;
724 SendReboot(lastAssignedIpv4Addr, timestamp);
725 }
726 }
727
Requesting(time_t timestamp)728 void DhcpClientStateMachine::Requesting(time_t timestamp)
729 {
730 if (m_sentPacketNum > TIMEOUT_TIMES_MAX) {
731 /* Send packet timed out, now enter init state. */
732 m_dhcp4State = DHCP_STATE_INIT;
733 SetSocketMode(SOCKET_MODE_RAW);
734 m_sentPacketNum = 0;
735 m_timeoutTimestamp = timestamp;
736 return;
737 }
738
739 if (m_dhcp4State == DHCP_STATE_RENEWED) {
740 /* Unicast dhcp request packet in the renew state. */
741 DhcpRenew(m_transID, m_requestedIp4, m_serverIp4);
742 } else {
743 /* Broadcast dhcp request packet in the requesting state. */
744 DhcpRequest(m_transID, m_requestedIp4, m_serverIp4);
745 }
746
747 uint32_t uTimeoutSec = TIMEOUT_WAIT_SEC << (m_sentPacketNum > MAX_WAIT_TIMES ? MAX_WAIT_TIMES : m_sentPacketNum);
748 if (uTimeoutSec > DHCP_FAILE_TIMEOUT_THR) {
749 TryCachedIp();
750 }
751 m_timeoutTimestamp = timestamp + static_cast<int64_t>(uTimeoutSec);
752 DHCP_LOGI("Requesting() DhcpRequest m_sentPacketNum:%{public}u,timeoutSec:%{public}u,"
753 "timeoutTimestamp:%{public}" PRId64,
754 m_sentPacketNum,
755 uTimeoutSec,
756 m_timeoutTimestamp);
757
758 m_sentPacketNum++;
759 }
760
Renewing(time_t timestamp)761 void DhcpClientStateMachine::Renewing(time_t timestamp)
762 {
763 if (m_dhcp4State == DHCP_STATE_RENEWING) {
764 DhcpRenew(m_transID, m_requestedIp4, m_serverIp4);
765 }
766 uint32_t uTimeoutSec = TIMEOUT_WAIT_SEC << (m_sentPacketNum > MAX_WAIT_TIMES ? MAX_WAIT_TIMES : m_sentPacketNum);
767 m_timeoutTimestamp = timestamp + static_cast<int64_t>(uTimeoutSec);
768 m_sentPacketNum++;
769 DHCP_LOGI("Renewing sentPacketNum:%{public}u timeoutSec:%{public}u timeoutTimestamp:%{public}" PRId64
770 "state:%{public}u",
771 m_sentPacketNum, uTimeoutSec, m_timeoutTimestamp, m_dhcp4State);
772 }
773
Rebinding(time_t timestamp)774 void DhcpClientStateMachine::Rebinding(time_t timestamp)
775 {
776 if (m_dhcp4State == DHCP_STATE_REBINDING) {
777 DhcpRenew(m_transID, m_requestedIp4, 0);
778 }
779 uint32_t uTimeoutSec = TIMEOUT_WAIT_SEC << (m_sentPacketNum > MAX_WAIT_TIMES ? MAX_WAIT_TIMES : m_sentPacketNum);
780 m_timeoutTimestamp = timestamp + static_cast<int64_t>(uTimeoutSec);
781 m_sentPacketNum++;
782 DHCP_LOGI("Rebinding sentPacketNum:%{public}u timeoutSec:%{public}u timeoutTimestamp:%{public}" PRId64
783 "state:%{public}u",
784 m_sentPacketNum, uTimeoutSec, m_timeoutTimestamp, m_dhcp4State);
785 }
786
Declining(time_t timestamp)787 void DhcpClientStateMachine::Declining(time_t timestamp)
788 {
789 DHCP_LOGI("Declining() m_conflictCount is :%{public}u", m_conflictCount);
790 if (++m_conflictCount > MAX_CONFLICTS_COUNT) {
791 if (PublishDhcpResultEvent(m_cltCnf.ifaceName, PUBLISH_CODE_SUCCESS, &m_dhcpIpResult) != DHCP_OPT_SUCCESS) {
792 PublishDhcpResultEvent(m_cltCnf.ifaceName, PUBLISH_CODE_FAILED, &m_dhcpIpResult);
793 DHCP_LOGE("Declining publish dhcp result failed!");
794 }
795 SaveIpInfoInLocalFile(m_dhcpIpResult);
796 StopIpv4();
797 m_dhcp4State = DHCP_STATE_BOUND;
798 m_sentPacketNum = 0;
799 m_resendTimer = 0;
800 m_timeoutTimestamp = timestamp;
801 return;
802 }
803 m_timeoutTimestamp = timestamp + TIMEOUT_WAIT_SEC;
804 DhcpDecline(m_transID, m_requestedIp4, m_serverIp4);
805 m_dhcp4State = DHCP_STATE_INIT;
806 m_sentPacketNum = 0;
807 }
808
DhcpRequestHandle(time_t timestamp)809 void DhcpClientStateMachine::DhcpRequestHandle(time_t timestamp)
810 {
811 DHCP_LOGI("DhcpRequestHandle state:%{public}d[init-0 selecting-1 requesting-2 bound-3 renewing-4 rebinding-5 "
812 "initreboot-6 released-7 renewed-8 fastarp-9 slowarp-10 decline-11]", m_dhcp4State);
813 switch (m_dhcp4State) {
814 case DHCP_STATE_INIT:
815 FALLTHROUGH_INTENDED;
816 case DHCP_STATE_SELECTING:
817 InitSelecting(timestamp);
818 break;
819 case DHCP_STATE_REQUESTING:
820 FALLTHROUGH_INTENDED;
821 case DHCP_STATE_RENEWED:
822 Requesting(timestamp);
823 break;
824 case DHCP_STATE_BOUND:
825 /* Now the renewal time run out, ready to enter renewing state. */
826 m_dhcp4State = DHCP_STATE_RENEWING;
827 FALLTHROUGH_INTENDED;
828 case DHCP_STATE_RENEWING:
829 Renewing(timestamp);
830 break;
831 case DHCP_STATE_REBINDING:
832 Rebinding(timestamp);
833 break;
834 case DHCP_STATE_INITREBOOT:
835 SendReboot(m_requestedIp4, timestamp);
836 break;
837 case DHCP_STATE_RELEASED:
838 /* Ensure that the function select() is always blocked and don't need to receive ip from dhcp server. */
839 DHCP_LOGI("DhcpRequestHandle() DHCP_STATE_RELEASED-7 m_timeoutTimestamp:%{public}" PRId64,
840 m_timeoutTimestamp);
841 m_timeoutTimestamp = SIGNED_INTEGER_MAX;
842 break;
843 case DHCP_STATE_FAST_ARP:
844 FastArpDetect();
845 break;
846 case DHCP_STATE_SLOW_ARP:
847 SlowArpDetect(timestamp);
848 break;
849 case DHCP_STATE_DECLINE:
850 Declining(timestamp);
851 break;
852 default:
853 break;
854 }
855 }
DhcpOfferPacketHandle(uint8_t type,const struct DhcpPacket * packet,time_t timestamp)856 void DhcpClientStateMachine::DhcpOfferPacketHandle(uint8_t type, const struct DhcpPacket *packet, time_t timestamp)
857 {
858 if (type != DHCP_OFFER) {
859 DHCP_LOGE("DhcpOfferPacketHandle() type:%{public}d error!", type);
860 return;
861 }
862
863 if (packet == NULL) {
864 DHCP_LOGE("DhcpOfferPacketHandle() type:%{public}d error, packet == NULL!", type);
865 return;
866 }
867
868 uint32_t u32Data = 0;
869 if (!GetDhcpOptionUint32(packet, SERVER_IDENTIFIER_OPTION, &u32Data)) {
870 DHCP_LOGE("DhcpOfferPacketHandle() type:%{public}d GetDhcpOptionUint32 SERVER_IDENTIFIER_OPTION failed!",
871 type);
872 return;
873 }
874
875 m_transID = packet->xid;
876 m_requestedIp4 = packet->yiaddr;
877 m_serverIp4 = htonl(u32Data);
878
879 std::string pReqIp = Ip4IntConvertToStr(m_requestedIp4, false);
880 if (pReqIp.length() > 0) {
881 DHCP_LOGI(
882 "DhcpOfferPacketHandle() receive DHCP_OFFER, xid:%{public}u, requestIp: host %{private}u->%{private}s.",
883 m_transID,
884 ntohl(m_requestedIp4),
885 pReqIp.c_str());
886 }
887 std::string pSerIp = Ip4IntConvertToStr(m_serverIp4, false);
888 if (pSerIp.length() > 0) {
889 DHCP_LOGI("DhcpOfferPacketHandle() receive DHCP_OFFER, serverIp: host %{private}u->%{private}s.",
890 ntohl(m_serverIp4),
891 pSerIp.c_str());
892 }
893
894 /* Receive dhcp offer packet finished, next send dhcp request packet. */
895 m_dhcp4State = DHCP_STATE_REQUESTING;
896 m_sentPacketNum = 0;
897 m_timeoutTimestamp = timestamp;
898 }
899
ParseNetworkServerIdInfo(const struct DhcpPacket * packet,struct DhcpIpResult * result)900 void DhcpClientStateMachine::ParseNetworkServerIdInfo(const struct DhcpPacket *packet, struct DhcpIpResult *result)
901 {
902 if ((packet == nullptr) || (result == nullptr)) {
903 DHCP_LOGE("ParseNetworkServerIdInfo packet == nullptr or result == nullptr!");
904 return;
905 }
906 uint32_t u32Data = 0;
907 if (!GetDhcpOptionUint32(packet, SERVER_IDENTIFIER_OPTION, &u32Data)) {
908 DHCP_LOGE("ParseNetworkServerIdInfo SERVER_IDENTIFIER_OPTION failed!");
909 } else {
910 m_serverIp4 = htonl(u32Data);
911 std::string pSerIp = Ip4IntConvertToStr(m_serverIp4, false);
912 if (pSerIp.length() > 0) {
913 DHCP_LOGI("ParseNetworkServerIdInfo recv DHCP_ACK 54, serid: %{private}u->%{private}s.",
914 u32Data, pSerIp.c_str());
915 if (strncpy_s(result->strOptServerId, INET_ADDRSTRLEN, pSerIp.c_str(), INET_ADDRSTRLEN - 1) != EOK) {
916 return;
917 }
918 }
919 }
920 }
921
SetIpv4DefaultDns(struct DhcpIpResult * result)922 void DhcpClientStateMachine::SetIpv4DefaultDns(struct DhcpIpResult *result)
923 {
924 if (result == nullptr) {
925 DHCP_LOGE("SetIpv4DefaultDns result == nullptr!");
926 return;
927 }
928 if (strncpy_s(result->strOptDns1, INET_ADDRSTRLEN, DEFAULT_IPV4_DNS_PRI, INET_ADDRSTRLEN - 1) != EOK) {
929 DHCP_LOGE("SetIpv4DefaultDns strncpy_s defult strOptDns1 Failed.");
930 return;
931 }
932 if (strncpy_s(result->strOptDns2, INET_ADDRSTRLEN, DEFAULT_IPV4_DNS_SEC, INET_ADDRSTRLEN - 1) != EOK) {
933 DHCP_LOGE("SetIpv4DefaultDns strncpy_s defult strOptDns2 Failed.");
934 return;
935 }
936 result->dnsAddr.clear();
937 result->dnsAddr.push_back(DEFAULT_IPV4_DNS_PRI);
938 result->dnsAddr.push_back(DEFAULT_IPV4_DNS_SEC);
939 DHCP_LOGI("SetIpv4DefaultDns make defult dns!");
940 }
941
ParseNetworkDnsInfo(const struct DhcpPacket * packet,struct DhcpIpResult * result)942 void DhcpClientStateMachine::ParseNetworkDnsInfo(const struct DhcpPacket *packet, struct DhcpIpResult *result)
943 {
944 if ((packet == nullptr) || (result == nullptr)) {
945 DHCP_LOGE("ParseNetworkDnsInfo error, packet == nullptr or result == nullptr!");
946 return;
947 }
948 size_t len = 0;
949 const uint8_t *p = GetDhcpOption(packet, DOMAIN_NAME_SERVER_OPTION, &len);
950 if (p == nullptr) {
951 DHCP_LOGE("ParseNetworkDnsInfo nullptr!");
952 SetIpv4DefaultDns(result);
953 return;
954 }
955 uint32_t uData = 0;
956 int count = 0;
957 if ((len < (ssize_t)sizeof(uData)) || (len % (ssize_t)sizeof(uData) != 0)) {
958 DHCP_LOGE("ParseNetworkDnsInfo failed, len:%{public}zu is not %{public}zu * n, code:%{public}d!",
959 len, sizeof(uData), DOMAIN_NAME_SERVER_OPTION);
960 SetIpv4DefaultDns(result);
961 return;
962 }
963 DHCP_LOGI("ParseNetworkDnsInfo len:%{public}zu count:%{public}d", len, count);
964 while (len >= (ssize_t)sizeof(uData)) {
965 uData = 0;
966 if (memcpy_s(&uData, sizeof(uData), p, sizeof(uData)) != EOK) {
967 DHCP_LOGE("ParseNetworkDnsInfo memcpy_s failed!");
968 continue;
969 }
970 if (uData > 0) {
971 ParseNetworkDnsValue(result, uData, len, count);
972 }
973 p += sizeof(uData);
974 len -= sizeof(uData);
975 }
976 return;
977 }
978
ParseNetworkDnsValue(struct DhcpIpResult * result,uint32_t uData,size_t & len,int & count)979 void DhcpClientStateMachine::ParseNetworkDnsValue(struct DhcpIpResult *result, uint32_t uData, size_t &len, int &count)
980 {
981 if (result == nullptr) {
982 DHCP_LOGE("ParseNetworkDnsValue error, result == nullptr!");
983 return;
984 }
985 uint32_t u32Data = ntohl(uData);
986 std::string pDnsIp = Ip4IntConvertToStr(u32Data, true);
987 if (pDnsIp.length() > 0) {
988 count++;
989 result->dnsAddr.push_back(pDnsIp);
990 DHCP_LOGI("ParseNetworkDnsInfo recv DHCP_ACK 6, dns:%{private}u->%{private}s len:%{public}zu %{public}d",
991 u32Data, pDnsIp.c_str(), len, count);
992 if (count == DHCP_DNS_FIRST) {
993 if (strncpy_s(result->strOptDns1, INET_ADDRSTRLEN, pDnsIp.c_str(), INET_ADDRSTRLEN - 1) != EOK) {
994 DHCP_LOGE("ParseNetworkDnsInfo strncpy_s strOptDns1 Failed.");
995 return;
996 }
997 } else if (count == DHCP_DNS_SECOND) {
998 if (strncpy_s(result->strOptDns2, INET_ADDRSTRLEN, pDnsIp.c_str(), INET_ADDRSTRLEN - 1) != EOK) {
999 DHCP_LOGE("ParseNetworkDnsInfo strncpy_s strOptDns2 Failed.");
1000 return;
1001 }
1002 }
1003 } else {
1004 DHCP_LOGI("ParseNetworkDnsInfo pDnsIp is nullptr, len:%{public}zu %{public}d ", len, count);
1005 }
1006 }
1007
SetDefaultNetMask(struct DhcpIpResult * result)1008 void DhcpClientStateMachine::SetDefaultNetMask(struct DhcpIpResult *result)
1009 {
1010 if (result == nullptr) {
1011 DHCP_LOGE("SetDefaultNetMask result is nullptr!");
1012 return;
1013 }
1014 std::string strYiaddr = result->strYiaddr;
1015 std::string strNetmask = result->strOptSubnet;
1016 size_t pos = strYiaddr.find(".");
1017 std::string yiaddrTmp = strYiaddr.substr(0, pos);
1018 int firstByte = static_cast<int>(CheckDataLegal(yiaddrTmp, DECIMAL_NOTATION));
1019 if ((!strYiaddr.empty()) && strNetmask.empty()) {
1020 if (firstByte < DHCP_IP_TYPE_A) {
1021 if (strncpy_s(result->strOptSubnet, INET_ADDRSTRLEN, "255.0.0.0", INET_ADDRSTRLEN - 1) != EOK) {
1022 DHCP_LOGE("SetDefaultNetMask strncpy_s failed!");
1023 return;
1024 }
1025 } else if (firstByte < DHCP_IP_TYPE_B) {
1026 if (strncpy_s(result->strOptSubnet, INET_ADDRSTRLEN, "255.255.0.0", INET_ADDRSTRLEN - 1) != EOK) {
1027 DHCP_LOGE("SetDefaultNetMask strncpy_s failed!");
1028 return;
1029 }
1030 } else if (firstByte < DHCP_IP_TYPE_C) {
1031 if (strncpy_s(result->strOptSubnet, INET_ADDRSTRLEN, "255.255.255.0", INET_ADDRSTRLEN - 1) != EOK) {
1032 DHCP_LOGE("SetDefaultNetMask strncpy_s failed!");
1033 return;
1034 }
1035 } else {
1036 if (strncpy_s(result->strOptSubnet, INET_ADDRSTRLEN, "255.255.255.255", INET_ADDRSTRLEN - 1) != EOK) {
1037 DHCP_LOGE("SetDefaultNetMask strncpy_s failed!");
1038 return;
1039 }
1040 }
1041 }
1042 }
1043
ParseNetworkInfo(const struct DhcpPacket * packet,struct DhcpIpResult * result)1044 void DhcpClientStateMachine::ParseNetworkInfo(const struct DhcpPacket *packet, struct DhcpIpResult *result)
1045 {
1046 if ((packet == NULL) || (result == NULL)) {
1047 DHCP_LOGE("ParseNetworkInfo() error, packet == NULL or result == NULL!");
1048 return;
1049 }
1050
1051 std::string pReqIp = Ip4IntConvertToStr(m_requestedIp4, false);
1052 if (pReqIp.length() > 0) {
1053 DHCP_LOGI("ParseNetworkInfo() recv DHCP_ACK yiaddr: %{private}u->%{public}s.",
1054 ntohl(m_requestedIp4), Ipv4Anonymize(pReqIp).c_str());
1055 if (strncpy_s(result->strYiaddr, INET_ADDRSTRLEN, pReqIp.c_str(), INET_ADDRSTRLEN - 1) != EOK) {
1056 DHCP_LOGI("ParseNetworkInfo() strncpy_s failed!");
1057 return;
1058 }
1059 }
1060
1061 uint32_t u32Data = 0;
1062 if (GetDhcpOptionUint32(packet, SUBNET_MASK_OPTION, &u32Data)) {
1063 std::string pSubIp = Ip4IntConvertToStr(u32Data, true);
1064 if (pSubIp.length() > 0) {
1065 DHCP_LOGI("ParseNetworkInfo() recv DHCP_ACK 1, subnetmask: %{private}u->%{private}s.",
1066 u32Data, pSubIp.c_str());
1067 if (strncpy_s(result->strOptSubnet, INET_ADDRSTRLEN, pSubIp.c_str(), INET_ADDRSTRLEN - 1) != EOK) {
1068 DHCP_LOGE("strncpy_s strOptSubnet failed!");
1069 SetDefaultNetMask(result);
1070 return;
1071 }
1072 } else {
1073 DHCP_LOGE("Ip4IntConvertToStr() failed!");
1074 SetDefaultNetMask(result);
1075 }
1076 } else {
1077 DHCP_LOGE("GetDhcpOptionUint32() failed!");
1078 SetDefaultNetMask(result);
1079 }
1080
1081 u32Data = 0;
1082 uint32_t u32Data2 = 0;
1083 if (GetDhcpOptionUint32n(packet, ROUTER_OPTION, &u32Data, &u32Data2)) {
1084 std::string pRouterIp = Ip4IntConvertToStr(u32Data, true);
1085 if (pRouterIp.length() > 0) {
1086 DHCP_LOGI("ParseNetworkInfo() recv DHCP_ACK 3, router1: %{private}u->%{private}s.",
1087 u32Data, pRouterIp.c_str());
1088 if (strncpy_s(result->strOptRouter1, INET_ADDRSTRLEN, pRouterIp.c_str(), INET_ADDRSTRLEN - 1) != EOK) {
1089 return;
1090 }
1091 }
1092 pRouterIp = Ip4IntConvertToStr(u32Data2, true);
1093 if ((u32Data2 > 0) && (pRouterIp.length() > 0)) {
1094 DHCP_LOGI("ParseNetworkInfo() recv DHCP_ACK 3, router2: %{private}u->%{private}s.",
1095 u32Data2, pRouterIp.c_str());
1096 if (strncpy_s(result->strOptRouter2, INET_ADDRSTRLEN, pRouterIp.c_str(), INET_ADDRSTRLEN - 1) != EOK) {
1097 return;
1098 }
1099 }
1100 }
1101 }
1102
FormatString(struct DhcpIpResult * result)1103 void DhcpClientStateMachine::FormatString(struct DhcpIpResult *result)
1104 {
1105 if (result == nullptr) {
1106 DHCP_LOGE("FormatString error, result == nullptr!");
1107 return;
1108 }
1109
1110 if (strlen(result->strYiaddr) == 0) {
1111 if (strncpy_s(result->strYiaddr, INET_ADDRSTRLEN, "*", INET_ADDRSTRLEN - 1) != EOK) {
1112 DHCP_LOGE("FormatString strncpy_s strYiaddr failed!");
1113 return;
1114 }
1115 }
1116 if (strlen(result->strOptServerId) == 0) {
1117 if (strncpy_s(result->strOptServerId, INET_ADDRSTRLEN, "*", INET_ADDRSTRLEN - 1) != EOK) {
1118 DHCP_LOGE("FormatString strncpy_s strOptServerId failed!");
1119 return;
1120 }
1121 }
1122 if (strlen(result->strOptSubnet) == 0) {
1123 if (strncpy_s(result->strOptSubnet, INET_ADDRSTRLEN, "*", INET_ADDRSTRLEN - 1) != EOK) {
1124 DHCP_LOGE("FormatString strncpy_s strOptSubnet failed!");
1125 return;
1126 }
1127 }
1128 if (strlen(result->strOptDns1) == 0) {
1129 if (strncpy_s(result->strOptDns1, INET_ADDRSTRLEN, "*", INET_ADDRSTRLEN - 1) != EOK) {
1130 DHCP_LOGE("FormatString strncpy_s strOptDns1 failed!");
1131 return;
1132 }
1133 }
1134 if (strlen(result->strOptDns2) == 0) {
1135 if (strncpy_s(result->strOptDns2, INET_ADDRSTRLEN, "*", INET_ADDRSTRLEN - 1) != EOK) {
1136 DHCP_LOGE("FormatString strncpy_s strOptDns2 failed!");
1137 return;
1138 }
1139 }
1140 if (strlen(result->strOptRouter1) == 0) {
1141 if (strncpy_s(result->strOptRouter1, INET_ADDRSTRLEN, "*", INET_ADDRSTRLEN - 1) != EOK) {
1142 DHCP_LOGE("FormatString strncpy_s strOptRouter1 failed!");
1143 return;
1144 }
1145 }
1146 if (strlen(result->strOptRouter2) == 0) {
1147 if (strncpy_s(result->strOptRouter2, INET_ADDRSTRLEN, "*", INET_ADDRSTRLEN - 1) != EOK) {
1148 DHCP_LOGE("FormatString strncpy_s strOptRouter2 failed!");
1149 return;
1150 }
1151 }
1152 if (strlen(result->strOptVendor) == 0) {
1153 if (strncpy_s(result->strOptVendor, DHCP_FILE_MAX_BYTES, "*", DHCP_FILE_MAX_BYTES - 1) != EOK) {
1154 DHCP_LOGE("FormatString strncpy_s strOptVendor failed!");
1155 return;
1156 }
1157 }
1158 }
1159
GetDHCPServerHostName(const struct DhcpPacket * packet,struct DhcpIpResult * result)1160 int DhcpClientStateMachine::GetDHCPServerHostName(const struct DhcpPacket *packet, struct DhcpIpResult *result)
1161 {
1162 if ((packet == NULL) || (result == NULL)) {
1163 DHCP_LOGE("GetDHCPServerHostName() error, packet == NULL or result == NULL!");
1164 return DHCP_OPT_FAILED;
1165 }
1166 const uint8_t *p = packet->sname;
1167 char *pSname = NULL;
1168 if (p == NULL || *p == '\0') {
1169 DHCP_LOGW("GetDHCPServerHostName() recv DHCP_ACK sname, pSname is NULL!");
1170 } else {
1171 pSname = (char*)p;
1172 DHCP_LOGI("GetDHCPServerHostName() recv DHCP_ACK sname, original pSname is %{public}s.", pSname);
1173 const char *pHostName = "hostname:";
1174 if (strncpy_s(result->strOptVendor, DHCP_FILE_MAX_BYTES, pHostName, DHCP_FILE_MAX_BYTES - 1) != EOK) {
1175 DHCP_LOGE("GetDHCPServerHostName() error, strncpy_s pHostName failed!");
1176 pHostName = NULL;
1177 return DHCP_OPT_FAILED;
1178 } else {
1179 DHCP_LOGI("GetDHCPServerHostName() recv DHCP_ACK sname, save ""hostname:"" only, \
1180 result->strOptVendor is %{public}s.", result->strOptVendor);
1181 if (strncat_s(result->strOptVendor, DHCP_FILE_MAX_BYTES,
1182 pSname, DHCP_FILE_MAX_BYTES - strlen(pHostName) - 1) != EOK) {
1183 DHCP_LOGE("GetDHCPServerHostName() error, strncat_s pSname failed!");
1184 pHostName = NULL;
1185 return DHCP_OPT_FAILED;
1186 } else {
1187 DHCP_LOGI("GetDHCPServerHostName() recv DHCP_ACK sname, add pSname, \
1188 result->strOptVendor is %{public}s.", result->strOptVendor);
1189 }
1190 pHostName = NULL;
1191 }
1192 }
1193 return DHCP_OPT_SUCCESS;
1194 }
1195
ParseNetworkVendorInfo(const struct DhcpPacket * packet,struct DhcpIpResult * result)1196 int DhcpClientStateMachine::ParseNetworkVendorInfo(const struct DhcpPacket *packet, struct DhcpIpResult *result)
1197 {
1198 if ((packet == NULL) || (result == NULL)) {
1199 DHCP_LOGE("ParseNetworkVendorInfo() error, packet == NULL or result == NULL!");
1200 return DHCP_OPT_FAILED;
1201 }
1202
1203 char *pVendor = GetDhcpOptionString(packet, VENDOR_SPECIFIC_INFO_OPTION);
1204 if (pVendor == NULL) {
1205 DHCP_LOGW("ParseNetworkVendorInfo() recv DHCP_ACK 43, pVendor is NULL!");
1206 if (GetDHCPServerHostName(packet, result) != DHCP_OPT_SUCCESS) {
1207 DHCP_LOGE("GetDHCPServerHostName() error, GetDHCPServerHostName failed!");
1208 return DHCP_OPT_FAILED;
1209 }
1210 /* Get option43 success. */
1211 } else {
1212 DHCP_LOGI("ParseNetworkVendorInfo() recv DHCP_ACK 43, pVendor is %{public}s.", pVendor);
1213 if (strncpy_s(result->strOptVendor, DHCP_FILE_MAX_BYTES, pVendor, DHCP_FILE_MAX_BYTES - 1) != EOK) {
1214 DHCP_LOGE("ParseNetworkVendorInfo() error, strncpy_s pVendor failed!");
1215 free(pVendor);
1216 pVendor = NULL;
1217 return DHCP_OPT_FAILED;
1218 }
1219 free(pVendor);
1220 pVendor = NULL;
1221 }
1222 return DHCP_OPT_SUCCESS;
1223 }
1224
DhcpAckOrNakPacketHandle(uint8_t type,struct DhcpPacket * packet,time_t timestamp)1225 void DhcpClientStateMachine::DhcpAckOrNakPacketHandle(uint8_t type, struct DhcpPacket *packet, time_t timestamp)
1226 {
1227 if ((type != DHCP_ACK) && (type != DHCP_NAK)) {
1228 DHCP_LOGI("DhcpAckOrNakPacketHandle type:%{public}d error!", type);
1229 if (m_dhcp4State == DHCP_STATE_INITREBOOT) {
1230 m_dhcp4State = DHCP_STATE_INIT;
1231 m_timeoutTimestamp = timestamp;
1232 }
1233 return;
1234 }
1235 if (packet == NULL) {
1236 DHCP_LOGE("DhcpAckOrNakPacketHandle type:%{public}d error, packet == NULL!", type);
1237 return;
1238 }
1239
1240 m_dhcpIpResult.dnsAddr.clear();
1241 std::vector<std::string>().swap(m_dhcpIpResult.dnsAddr);
1242 m_dhcpIpResult.ifname.clear();
1243 if (memset_s(&m_dhcpIpResult, sizeof(struct DhcpIpResult), 0, sizeof(struct DhcpIpResult)) != EOK) {
1244 DHCP_LOGE("DhcpAckOrNakPacketHandle error, memset_s failed!");
1245 return;
1246 }
1247 if (type == DHCP_NAK) {
1248 ParseDhcpNakPacket(packet, timestamp);
1249 return;
1250 }
1251
1252 ParseDhcpAckPacket(packet, timestamp);
1253 if (SetLocalInterface(m_cltCnf.ifaceName,
1254 inet_addr(m_dhcpIpResult.strYiaddr), inet_addr(m_dhcpIpResult.strOptSubnet)) != DHCP_OPT_SUCCESS) {
1255 DHCP_LOGE("DhcpAckOrNakPacketHandle error, SetLocalInterface yiaddr:%{public}s failed!",
1256 m_dhcpIpResult.strYiaddr);
1257 return;
1258 }
1259 FormatString(&m_dhcpIpResult);
1260 CloseAllRenewTimer();
1261 if (m_dhcp4State == DHCP_STATE_INITREBOOT && m_dhcpIpResult.dnsAddr.empty()) {
1262 IpInfoCached ipCached;
1263 if (GetCachedDhcpResult(m_routerCfg.bssid, ipCached) != 0) {
1264 DHCP_LOGE("DhcpAckOrNakPacketHandle() not find cache ip");
1265 return;
1266 }
1267 DHCP_LOGI("DhcpAckOrNakPacketHandle() use cache DNS addr, size:%{public}zu", ipCached.ipResult.dnsAddr.size());
1268 m_dhcpIpResult.dnsAddr = ipCached.ipResult.dnsAddr;
1269 }
1270 if (m_dhcp4State == DHCP_STATE_REQUESTING || m_dhcp4State == DHCP_STATE_INITREBOOT) {
1271 IpConflictDetect();
1272 } else {
1273 if (PublishDhcpResultEvent(m_cltCnf.ifaceName, PUBLISH_CODE_SUCCESS, &m_dhcpIpResult) != DHCP_OPT_SUCCESS) {
1274 DHCP_LOGE("DhcpAckOrNakPacketHandle PublishDhcpResultEvent result failed!");
1275 return;
1276 }
1277 m_dhcp4State = DHCP_STATE_BOUND;
1278 m_sentPacketNum = 0;
1279 m_resendTimer = 0;
1280 m_timeoutTimestamp = timestamp + static_cast<int64_t>(m_renewalSec);
1281 StopIpv4();
1282 ScheduleLeaseTimers(false);
1283 }
1284 }
1285
ParseDhcpAckPacket(const struct DhcpPacket * packet,time_t timestamp)1286 void DhcpClientStateMachine::ParseDhcpAckPacket(const struct DhcpPacket *packet, time_t timestamp)
1287 {
1288 if (packet == nullptr) {
1289 DHCP_LOGE("ParseDhcpAckPacket error, packet == nullptr!");
1290 return;
1291 }
1292 /* Set default leasetime. */
1293 m_leaseTime = LEASETIME_DEFAULT * ONE_HOURS_SEC;
1294 m_requestedIp4 = packet->yiaddr;
1295 uint32_t u32Data = 0;
1296 if (GetDhcpOptionUint32(packet, IP_ADDRESS_LEASE_TIME_OPTION, &u32Data)) {
1297 m_leaseTime = u32Data;
1298 DHCP_LOGI("ParseDhcpAckPacket recv DHCP_ACK 51, lease:%{public}u.", m_leaseTime);
1299 }
1300 m_renewalSec = m_leaseTime * RENEWAL_SEC_MULTIPLE; /* First renewal seconds. */
1301 m_rebindSec = m_leaseTime * REBIND_SEC_MULTIPLE; /* Second rebind seconds. */
1302 m_renewalTimestamp = static_cast<int64_t>(timestamp); /* Record begin renewing or rebinding timestamp. */
1303 m_renewalTimestampBoot = GetElapsedSecondsSinceBoot();
1304 m_dhcpIpResult.uOptLeasetime = m_leaseTime;
1305 DHCP_LOGI("ParseDhcpAckPacket Last get lease:%{public}u,renewal:%{public}u,rebind:%{public}u.",
1306 m_leaseTime, m_renewalSec, m_rebindSec);
1307 ParseNetworkServerIdInfo(packet, &m_dhcpIpResult); // m_dhcpIpResult.strOptServerId
1308 ParseNetworkInfo(packet, &m_dhcpIpResult); // strYiaddr/strOptSubnet/strOptRouter1/strOptRouter2
1309 ParseNetworkDnsInfo(packet, &m_dhcpIpResult);
1310 ParseNetworkVendorInfo(packet, &m_dhcpIpResult);
1311 }
1312
ParseDhcpNakPacket(const struct DhcpPacket * packet,time_t timestamp)1313 void DhcpClientStateMachine::ParseDhcpNakPacket(const struct DhcpPacket *packet, time_t timestamp)
1314 {
1315 if (packet == NULL) {
1316 DHCP_LOGE("ParseDhcpNakPacket error, packet == NULL!");
1317 return;
1318 }
1319 /* If receive dhcp nak packet, init m_dhcp4State, resend dhcp discover packet. */
1320 DHCP_LOGI("ParseDhcpNakPacket receive DHCP_NAK 53, init m_dhcp4State, resend dhcp discover packet!");
1321 m_dhcp4State = DHCP_STATE_INIT;
1322 SetSocketMode(SOCKET_MODE_RAW);
1323 m_requestedIp4 = 0;
1324 m_sentPacketNum = 0;
1325 m_timeoutTimestamp = timestamp;
1326 /* Avoid excessive network traffic. */
1327 DHCP_LOGI("ParseDhcpNakPacket receive DHCP_NAK 53, avoid excessive network traffic, need sleep!");
1328 if (m_resendTimer == 0) {
1329 m_resendTimer = FIRST_TIMEOUT_SEC;
1330 } else {
1331 sleep(m_resendTimer);
1332 DHCP_LOGI("ParseDhcpNakPacket sleep:%{public}u", m_resendTimer);
1333 m_resendTimer *= DOUBLE_TIME;
1334 if (m_resendTimer > MAX_TIMEOUT_SEC) {
1335 m_resendTimer = MAX_TIMEOUT_SEC;
1336 }
1337 }
1338 }
1339 #ifndef OHOS_ARCH_LITE
GetDhcpOffer(DhcpPacket * packet,int64_t timestamp)1340 void DhcpClientStateMachine::GetDhcpOffer(DhcpPacket *packet, int64_t timestamp)
1341 {
1342 DHCP_LOGI("GetDhcpOffer enter");
1343 if (strncmp(m_cltCnf.ifaceName, "wlan", NUMBER_FOUR) != 0) {
1344 DHCP_LOGI("ifaceName is not wlan, no need deal multi Offer");
1345 return;
1346 }
1347
1348 if (packet == nullptr) {
1349 DHCP_LOGW("GetDhcpOffer() packet is nullptr!");
1350 return;
1351 }
1352 uint8_t u8Message = 0;
1353 if (!GetDhcpOptionUint8(packet, DHCP_MESSAGE_TYPE_OPTION, &u8Message)) {
1354 DHCP_LOGE("GetDhcpOffer GetDhcpOptionUint8 DHCP_MESSAGE_TYPE_OPTION failed!");
1355 return;
1356 }
1357 if (u8Message != DHCP_OFFER) {
1358 DHCP_LOGW("GetDhcpOffer() not offer, type:%{public}d!", u8Message);
1359 return;
1360 }
1361
1362 uint32_t leaseTime = LEASETIME_DEFAULT * ONE_HOURS_SEC;
1363 uint32_t u32Data = 0;
1364 if (GetDhcpOptionUint32(packet, IP_ADDRESS_LEASE_TIME_OPTION, &u32Data)) {
1365 leaseTime = u32Data;
1366 }
1367 m_requestedIp4 = packet->yiaddr;
1368 DhcpIpResult dhcpIpResult;
1369 dhcpIpResult.code = PUBLISH_DHCP_OFFER_REPORT;
1370 dhcpIpResult.ifname = m_cltCnf.ifaceName;
1371 dhcpIpResult.uOptLeasetime = leaseTime;
1372 ParseNetworkServerIdInfo(packet, &dhcpIpResult);
1373 ParseNetworkInfo(packet, &dhcpIpResult);
1374 ParseNetworkDnsInfo(packet, &dhcpIpResult);
1375 ParseNetworkVendorInfo(packet, &dhcpIpResult);
1376 PublishDhcpIpv4Result(dhcpIpResult);
1377 }
1378 #endif
1379
DhcpResponseDataCheck(time_t timestamp,int sockFd,uint8_t & u8Message,struct DhcpPacket & packet)1380 int DhcpClientStateMachine::DhcpResponseDataCheck(time_t timestamp, int sockFd,
1381 uint8_t &u8Message, struct DhcpPacket &packet)
1382 {
1383 int getLen = 0;
1384 getLen = (m_socketMode == SOCKET_MODE_RAW) ? GetDhcpRawPacket(&packet, sockFd)
1385 : GetDhcpKernelPacket(&packet, sockFd);
1386 if (getLen < 0) {
1387 if ((getLen == SOCKET_OPT_ERROR) && (errno != EINTR)) {
1388 DHCP_LOGI(" DhcpResponseHandle get packet read error, reopening socket!");
1389 /* Reopen m_sockFd. */
1390 SetSocketMode(m_socketMode);
1391 }
1392 DHCP_LOGD("DhcpResponseHandle get packet failed, error:%{public}d len:%{public}d", errno, getLen);
1393 if (m_dhcp4State == DHCP_STATE_INITREBOOT) {
1394 m_dhcp4State = DHCP_STATE_INIT;
1395 m_timeoutTimestamp = timestamp;
1396 }
1397 return DHCP_OPT_FAILED;
1398 }
1399 DHCP_LOGI("DhcpResponseHandle get packet success, getLen:%{public}d.", getLen);
1400 /* Check packet data. */
1401 if (packet.xid != m_transID) {
1402 DHCP_LOGW("DhcpResponseHandle get xid:%{public}u and m_transID:%{public}u not same!", packet.xid, m_transID);
1403 return DHCP_OPT_FAILED;
1404 }
1405 #ifndef OHOS_ARCH_LITE
1406 GetDhcpOffer(&packet, timestamp);
1407 #endif
1408 if (!GetDhcpOptionUint8(&packet, DHCP_MESSAGE_TYPE_OPTION, &u8Message)) {
1409 DHCP_LOGE("DhcpResponseHandle GetDhcpOptionUint8 DHCP_MESSAGE_TYPE_OPTION failed!");
1410 return DHCP_OPT_FAILED;
1411 }
1412 return DHCP_OPT_SUCCESS;
1413 }
1414
DhcpResponseHandle(time_t timestamp,int sockFd)1415 void DhcpClientStateMachine::DhcpResponseHandle(time_t timestamp, int sockFd)
1416 {
1417 struct DhcpPacket packet;
1418 uint8_t u8Message = 0;
1419
1420 if (memset_s(&packet, sizeof(packet), 0, sizeof(packet)) != EOK) {
1421 DHCP_LOGE("DhcpResponseHandle memset_s packet failed!");
1422 return;
1423 }
1424 if (DhcpResponseDataCheck(timestamp, sockFd, u8Message, packet) != DHCP_OPT_SUCCESS) {
1425 return;
1426 }
1427 DHCP_LOGI("DhcpResponseHandle m_dhcp4State:%{public}d.", m_dhcp4State);
1428 switch (m_dhcp4State) {
1429 case DHCP_STATE_SELECTING:
1430 DhcpOfferPacketHandle(u8Message, &packet, timestamp);
1431 break;
1432 case DHCP_STATE_REQUESTING:
1433 FALLTHROUGH_INTENDED;
1434 case DHCP_STATE_RENEWING:
1435 FALLTHROUGH_INTENDED;
1436 case DHCP_STATE_REBINDING:
1437 FALLTHROUGH_INTENDED;
1438 case DHCP_STATE_INITREBOOT:
1439 FALLTHROUGH_INTENDED;
1440 case DHCP_STATE_RENEWED:
1441 DhcpAckOrNakPacketHandle(u8Message, &packet, timestamp);
1442 break;
1443 default:
1444 break;
1445 }
1446 }
1447
1448 /* Receive signals. */
SignalReceiver(void)1449 bool DhcpClientStateMachine::SignalReceiver(void)
1450 {
1451 int signum = SIG_INVALID;
1452 if (read(m_sigSockFds[0], &signum, sizeof(signum)) < 0) {
1453 DHCP_LOGE("SignalReceiver read failed, m_sigSockFds[0]:%{public}d read error:%{public}d!", m_sigSockFds[0],
1454 errno);
1455 return false;
1456 }
1457 DHCP_LOGE("SignalReceiver read sigSockFds[0]:%{public}d signum:%{public}d!", m_sigSockFds[0], signum);
1458 return signum == SIG_STOP;
1459 }
1460
1461 /* Set dhcp ipv4 state. */
SetIpv4State(int state)1462 int DhcpClientStateMachine::SetIpv4State(int state)
1463 {
1464 if (state < 0) {
1465 DHCP_LOGE("SetIpv4State() failed, state:%{public}d!", state);
1466 return DHCP_OPT_FAILED;
1467 }
1468 m_dhcp4State = state;
1469 return DHCP_OPT_SUCCESS;
1470 }
1471
PublishDhcpResultEvent(const char * ifname,const int code,struct DhcpIpResult * result)1472 int DhcpClientStateMachine::PublishDhcpResultEvent(const char *ifname, const int code, struct DhcpIpResult *result)
1473 {
1474 if (ifname == nullptr) {
1475 DHCP_LOGE("PublishDhcpResultEvent failed, ifname is nullptr!");
1476 return DHCP_OPT_FAILED;
1477 }
1478 if ((code != PUBLISH_CODE_SUCCESS) && (code != PUBLISH_CODE_FAILED) && (code != PUBLISH_CODE_TIMEOUT)) {
1479 DHCP_LOGE("PublishDhcpResultEvent ifname:%{public}s failed, code:%{public}d error!", ifname, code);
1480 return DHCP_OPT_FAILED;
1481 }
1482 if (result == nullptr) {
1483 DHCP_LOGE("PublishDhcpResultEvent ifname:%{public}s, code:%{public}d failed, result==nullptr!", ifname, code);
1484 return DHCP_OPT_FAILED;
1485 }
1486 result->code = code;
1487 result->uAddTime = (uint32_t)time(NULL);
1488 result->ifname = ifname;
1489 DHCP_LOGI("PublishDhcpResultEvent code:%{public}d ifname:%{public}s uAddTime:%{public}u", result->code,
1490 result->ifname.c_str(), result->uAddTime);
1491 bool ret = PublishDhcpIpv4Result(*result);
1492 if (!ret) {
1493 DHCP_LOGE("PublishDhcpResultEvent failed!");
1494 return DHCP_OPT_FAILED;
1495 }
1496 return DHCP_OPT_SUCCESS;
1497 }
1498
GetPacketHeaderInfo(struct DhcpPacket * packet,uint8_t type)1499 int DhcpClientStateMachine::GetPacketHeaderInfo(struct DhcpPacket *packet, uint8_t type)
1500 {
1501 if (packet == NULL) {
1502 DHCP_LOGE("GetPacketHeaderInfo() failed, packet == NULL!");
1503 return DHCP_OPT_FAILED;
1504 }
1505
1506 switch (type) {
1507 case DHCP_DISCOVER:
1508 FALLTHROUGH_INTENDED;
1509 case DHCP_REQUEST:
1510 FALLTHROUGH_INTENDED;
1511 case DHCP_DECLINE:
1512 FALLTHROUGH_INTENDED;
1513 case DHCP_RELEASE:
1514 FALLTHROUGH_INTENDED;
1515 case DHCP_INFORM:
1516 packet->op = BOOT_REQUEST;
1517 break;
1518 case DHCP_OFFER:
1519 FALLTHROUGH_INTENDED;
1520 case DHCP_ACK:
1521 FALLTHROUGH_INTENDED;
1522 case DHCP_NAK:
1523 packet->op = BOOT_REPLY;
1524 break;
1525 default:
1526 break;
1527 }
1528 packet->htype = ETHERNET_TYPE;
1529 packet->hlen = ETHERNET_LEN;
1530 packet->cookie = htonl(MAGIC_COOKIE);
1531 packet->options[0] = END_OPTION;
1532 AddOptValueToOpts(packet->options, DHCP_MESSAGE_TYPE_OPTION, type);
1533
1534 return DHCP_OPT_SUCCESS;
1535 }
1536
GetPacketCommonInfo(struct DhcpPacket * packet)1537 int DhcpClientStateMachine::GetPacketCommonInfo(struct DhcpPacket *packet)
1538 {
1539 if (packet == NULL) {
1540 DHCP_LOGE("GetPacketCommonInfo() failed, packet == NULL!");
1541 return DHCP_OPT_FAILED;
1542 }
1543
1544 /* Add packet client_cfg info. */
1545 if (memcpy_s(packet->chaddr, sizeof(packet->chaddr), m_cltCnf.ifaceMac, MAC_ADDR_LEN) != EOK) {
1546 DHCP_LOGE("GetPacketCommonInfo() failed, memcpy_s error!");
1547 return DHCP_OPT_FAILED;
1548 }
1549 AddClientIdToOpts(packet); // 61
1550 AddHostNameToOpts(packet); // 60 12
1551 return DHCP_OPT_SUCCESS;
1552 }
1553
AddClientIdToOpts(struct DhcpPacket * packet)1554 int DhcpClientStateMachine::AddClientIdToOpts(struct DhcpPacket *packet)
1555 {
1556 if (packet == nullptr) {
1557 DHCP_LOGE("AddClientIdToOpts failed, packet == nullptr!");
1558 return DHCP_OPT_FAILED;
1559 }
1560 char macAddr[MAC_ADDR_LEN * MAC_ADDR_CHAR_NUM] = {0};
1561 if (!MacChConToMacStr(m_cltCnf.ifaceMac, MAC_ADDR_LEN, macAddr, sizeof(macAddr))) {
1562 DHCP_LOGE("MacChConToMacStr() failed!");
1563 return DHCP_OPT_FAILED;
1564 }
1565
1566 unsigned char optValue[VENDOR_MAX_LEN - DHCP_OPT_CODE_BYTES - DHCP_OPT_LEN_BYTES] = {0};
1567 optValue[DHCP_OPT_CODE_INDEX] = CLIENT_IDENTIFIER_OPTION;
1568 optValue[DHCP_OPT_LEN_INDEX] = MAC_ADDR_LEN + 1;
1569 optValue[DHCP_OPT_DATA_INDEX] = NUMBER_ONE; /* Generate format: 1 + ifaceMac. */
1570 if (memcpy_s(optValue + DHCP_OPT_DATA_INDEX + 1, MAC_ADDR_LEN, m_cltCnf.ifaceMac, MAC_ADDR_LEN) != EOK) {
1571 DHCP_LOGE("AddClientIdToOpts memcpy_s failed!");
1572 return DHCP_OPT_FAILED;
1573 }
1574 int optValueLen = DHCP_OPT_CODE_BYTES + DHCP_OPT_LEN_BYTES + optValue[DHCP_OPT_LEN_INDEX];
1575 DHCP_LOGI("AddClientIdToOpts option=%{public}d len=%{public}d", CLIENT_IDENTIFIER_OPTION, optValueLen);
1576 AddOptStrToOpts(packet->options, optValue, optValueLen);
1577 return DHCP_OPT_SUCCESS;
1578 }
1579
AddHostNameToOpts(struct DhcpPacket * packet)1580 int DhcpClientStateMachine::AddHostNameToOpts(struct DhcpPacket *packet)
1581 {
1582 if (packet == nullptr) {
1583 DHCP_LOGE("AddHostNameToOpts failed, packet == nullptr!");
1584 return DHCP_OPT_FAILED;
1585 }
1586 std::string strProductModel;
1587 #ifdef INIT_LIB_ENABLE
1588 strProductModel = GetProductModelAlias();
1589 DHCP_LOGD("AddHostNameOptions strProductModel:%{public}s", strProductModel.c_str());
1590 #endif
1591 std::string venderName = VENDOR_NAME_PREFIX;
1592 std::string venderClass = venderName + ":" + strProductModel; // xxxx:openharmony:yyyy
1593 AddStrToOpts(packet, VENDOR_CLASS_IDENTIFIER_OPTION, venderClass); // add option 60
1594 AddStrToOpts(packet, HOST_NAME_OPTION, strProductModel); // add option 12
1595 return DHCP_OPT_SUCCESS;
1596 }
1597
AddStrToOpts(struct DhcpPacket * packet,int option,std::string & value)1598 int DhcpClientStateMachine::AddStrToOpts(struct DhcpPacket *packet, int option, std::string &value)
1599 {
1600 if (packet == nullptr) {
1601 DHCP_LOGE("AddStrToOpts failed, packet is nullptr!");
1602 return DHCP_OPT_FAILED;
1603 }
1604 char buf[VENDOR_MAX_LEN - DHCP_OPT_CODE_BYTES - DHCP_OPT_LEN_BYTES] = {0};
1605 int nRes = snprintf_s(buf, VENDOR_MAX_LEN - DHCP_OPT_DATA_INDEX,
1606 VENDOR_MAX_LEN - DHCP_OPT_DATA_INDEX - 1, "%s", value.c_str());
1607 if (nRes < 0) {
1608 DHCP_LOGE("AddStrToOpts buf snprintf_s failed, nRes:%{public}d", nRes);
1609 return DHCP_OPT_FAILED;
1610 }
1611 unsigned char optValue[VENDOR_MAX_LEN] = {0};
1612 optValue[DHCP_OPT_CODE_INDEX] = option;
1613 optValue[DHCP_OPT_LEN_INDEX] = strlen(buf);
1614 if (strncpy_s((char *)optValue + DHCP_OPT_DATA_INDEX, VENDOR_MAX_LEN - DHCP_OPT_DATA_INDEX, buf,
1615 strlen(buf)) != EOK) {
1616 DHCP_LOGE("AddStrToOpts optValue strncpy_s failed!");
1617 return DHCP_OPT_FAILED;
1618 }
1619 int optValueLen = DHCP_OPT_CODE_BYTES + DHCP_OPT_LEN_BYTES + optValue[DHCP_OPT_LEN_INDEX];
1620 DHCP_LOGD("AddStrToOpts option=%{public}d buf=%{public}s len=%{public}d", option, buf, optValueLen);
1621 AddOptStrToOpts(packet->options, optValue, optValueLen);
1622 return DHCP_OPT_SUCCESS;
1623 }
1624
1625 /* Broadcast dhcp discover packet, discover dhcp servers that can provide ip address. */
DhcpDiscover(uint32_t transid,uint32_t requestip)1626 int DhcpClientStateMachine::DhcpDiscover(uint32_t transid, uint32_t requestip)
1627 {
1628 DHCP_LOGI("DhcpDiscover send discover transid:%{public}u reqip:%{public}s", transid,
1629 IntIpv4ToAnonymizeStr(requestip).c_str());
1630 struct DhcpPacket packet;
1631 if (memset_s(&packet, sizeof(struct DhcpPacket), 0, sizeof(struct DhcpPacket)) != EOK) {
1632 return -1;
1633 }
1634
1635 /* Get packet header and common info. */
1636 if ((GetPacketHeaderInfo(&packet, DHCP_DISCOVER) != DHCP_OPT_SUCCESS) ||
1637 (GetPacketCommonInfo(&packet) != DHCP_OPT_SUCCESS)) {
1638 DHCP_LOGE("DhcpDiscover() GetPacketHeaderInfo failed!");
1639 return -1;
1640 }
1641
1642 /* Get packet not common info. */
1643 packet.xid = transid;
1644 /* Set Discover seconds elapsed. */
1645 SetSecondsElapsed(&packet);
1646 AddOptValueToOpts(packet.options, MAXIMUM_DHCP_MESSAGE_SIZE_OPTION, MAX_MSG_SIZE); // 57
1647 AddParamaterRequestList(&packet); // 55
1648 DHCP_LOGI("DhcpDiscover begin broadcast discover packet");
1649 return SendToDhcpPacket(&packet, INADDR_ANY, INADDR_BROADCAST, m_cltCnf.ifaceIndex, (uint8_t *)MAC_BCAST_ADDR);
1650 }
1651
1652 /* Broadcast dhcp request packet, tell dhcp servers that which ip address to choose. */
DhcpRequest(uint32_t transid,uint32_t reqip,uint32_t servip)1653 int DhcpClientStateMachine::DhcpRequest(uint32_t transid, uint32_t reqip, uint32_t servip)
1654 {
1655 DHCP_LOGI("DhcpRequest send request transid:%{public}u reqip:%{public}s servip:%{public}s", transid,
1656 IntIpv4ToAnonymizeStr(reqip).c_str(), IntIpv4ToAnonymizeStr(servip).c_str());
1657 struct DhcpPacket packet;
1658 if (memset_s(&packet, sizeof(struct DhcpPacket), 0, sizeof(struct DhcpPacket)) != EOK) {
1659 return -1;
1660 }
1661
1662 /* Get packet header and common info. */
1663 if ((GetPacketHeaderInfo(&packet, DHCP_REQUEST) != DHCP_OPT_SUCCESS) ||
1664 (GetPacketCommonInfo(&packet) != DHCP_OPT_SUCCESS)) {
1665 return -1;
1666 }
1667
1668 /* Get packet not common info. */
1669 packet.xid = transid;
1670 /* Set Request seconds elapsed. */
1671 SetSecondsElapsed(&packet);
1672 AddOptValueToOpts(packet.options, SERVER_IDENTIFIER_OPTION, servip); // 50
1673 AddOptValueToOpts(packet.options, REQUESTED_IP_ADDRESS_OPTION, reqip); // 54
1674 AddOptValueToOpts(packet.options, MAXIMUM_DHCP_MESSAGE_SIZE_OPTION, MAX_MSG_SIZE); //57
1675 AddParamaterRequestList(&packet); // 55
1676 DHCP_LOGI("DhcpRequest begin broadcast dhcp request packet");
1677 return SendToDhcpPacket(&packet, INADDR_ANY, INADDR_BROADCAST, m_cltCnf.ifaceIndex, (uint8_t *)MAC_BCAST_ADDR);
1678 }
1679
1680 /* Unicast or broadcast dhcp request packet, request to extend the lease from the dhcp server. */
DhcpRenew(uint32_t transid,uint32_t clientip,uint32_t serverip)1681 int DhcpClientStateMachine::DhcpRenew(uint32_t transid, uint32_t clientip, uint32_t serverip)
1682 {
1683 DHCP_LOGI("DhcpRenew send request transid:%{public}u, clientip:%{public}s serverip:%{public}s", transid,
1684 IntIpv4ToAnonymizeStr(clientip).c_str(), IntIpv4ToAnonymizeStr(serverip).c_str());
1685 struct DhcpPacket packet;
1686 if (memset_s(&packet, sizeof(struct DhcpPacket), 0, sizeof(struct DhcpPacket)) != EOK) {
1687 return -1;
1688 }
1689
1690 /* Get packet header and common info. */
1691 if ((GetPacketHeaderInfo(&packet, DHCP_REQUEST) != DHCP_OPT_SUCCESS) ||
1692 (GetPacketCommonInfo(&packet) != DHCP_OPT_SUCCESS)) {
1693 return -1;
1694 }
1695
1696 /* Get packet not common info. */
1697 packet.xid = transid;
1698 /* Set Renew Request seconds elapsed. */
1699 SetSecondsElapsed(&packet);
1700 packet.ciaddr = clientip;
1701 AddParamaterRequestList(&packet);
1702 AddOptValueToOpts(packet.options, MAXIMUM_DHCP_MESSAGE_SIZE_OPTION, MAX_MSG_SIZE); //57
1703
1704 /* Begin broadcast or unicast dhcp request packet. */
1705 if (serverip == 0) {
1706 DHCP_LOGI("DhcpRenew rebind, begin broadcast req packet");
1707 return SendToDhcpPacket(&packet, INADDR_ANY, INADDR_BROADCAST, m_cltCnf.ifaceIndex, (uint8_t *)MAC_BCAST_ADDR);
1708 }
1709 DHCP_LOGI("DhcpRenew send renew, begin unicast request packet");
1710 return SendDhcpPacket(&packet, clientip, serverip);
1711 }
1712
1713 /* Unicast dhcp release packet, releasing an ip address in Use from the dhcp server. */
DhcpRelease(uint32_t clientip,uint32_t serverip)1714 int DhcpClientStateMachine::DhcpRelease(uint32_t clientip, uint32_t serverip)
1715 {
1716 struct DhcpPacket packet;
1717 if (memset_s(&packet, sizeof(struct DhcpPacket), 0, sizeof(struct DhcpPacket)) != EOK) {
1718 return -1;
1719 }
1720
1721 /* Get packet header and common info. */
1722 if ((GetPacketHeaderInfo(&packet, DHCP_RELEASE) != DHCP_OPT_SUCCESS) ||
1723 (GetPacketCommonInfo(&packet) != DHCP_OPT_SUCCESS)) {
1724 return -1;
1725 }
1726
1727 /* Get packet not common info. */
1728 packet.xid = GetRandomId();
1729 AddOptValueToOpts(packet.options, REQUESTED_IP_ADDRESS_OPTION, clientip);
1730 AddOptValueToOpts(packet.options, SERVER_IDENTIFIER_OPTION, serverip);
1731 DHCP_LOGI("DhcpRelease begin unicast release packet, transid:%{public}u clientip:%{public}s serverip:%{public}s",
1732 packet.xid, IntIpv4ToAnonymizeStr(clientip).c_str(), IntIpv4ToAnonymizeStr(serverip).c_str());
1733 return SendDhcpPacket(&packet, clientip, serverip);
1734 }
1735
DhcpDecline(uint32_t transId,uint32_t clientIp,uint32_t serverIp)1736 int DhcpClientStateMachine::DhcpDecline(uint32_t transId, uint32_t clientIp, uint32_t serverIp)
1737 {
1738 DHCP_LOGI("DhcpDecline send decline transid:%{public}u, clientip:%{public}s serverip:%{public}s", transId,
1739 IntIpv4ToAnonymizeStr(clientIp).c_str(), IntIpv4ToAnonymizeStr(serverIp).c_str());
1740 struct DhcpPacket packet;
1741 if (memset_s(&packet, sizeof(struct DhcpPacket), 0, sizeof(struct DhcpPacket)) != EOK) {
1742 return -1;
1743 }
1744
1745 /* Get packet header and common info. */
1746 if (GetPacketHeaderInfo(&packet, DHCP_DECLINE) != DHCP_OPT_SUCCESS) {
1747 return -1;
1748 }
1749
1750 /* Get packet not common info. */
1751 packet.xid = transId;
1752 if (memcpy_s(packet.chaddr, sizeof(packet.chaddr), m_cltCnf.ifaceMac, MAC_ADDR_LEN) != EOK) {
1753 DHCP_LOGE("DhcpDecline, memcpy_s error!");
1754 return -1;
1755 }
1756 AddClientIdToOpts(&packet);
1757 AddOptValueToOpts(packet.options, REQUESTED_IP_ADDRESS_OPTION, clientIp);
1758 AddOptValueToOpts(packet.options, SERVER_IDENTIFIER_OPTION, serverIp);
1759 AddOptValueToOpts(packet.options, REQUESTED_IP_ADDRESS_OPTION, clientIp);
1760 AddOptValueToOpts(packet.options, SERVER_IDENTIFIER_OPTION, serverIp);
1761 DHCP_LOGI("DhcpDecline send decline, transid:%{public}u", transId);
1762 return SendToDhcpPacket(&packet, INADDR_ANY, INADDR_BROADCAST, m_cltCnf.ifaceIndex, (uint8_t *)MAC_BCAST_ADDR);
1763 }
1764
IpConflictDetect()1765 void DhcpClientStateMachine::IpConflictDetect()
1766 {
1767 DHCP_LOGI("IpConflictDetect start");
1768 m_sentPacketNum = 0;
1769 m_timeoutTimestamp = 0;
1770 m_dhcp4State = DHCP_STATE_FAST_ARP;
1771 m_arpDectionTargetIp = Ip4IntConvertToStr(m_requestedIp4, false);
1772 }
1773
FastArpDetect()1774 void DhcpClientStateMachine::FastArpDetect()
1775 {
1776 DHCP_LOGI("FastArpDetect() enter");
1777 if (IsArpReachable(FAST_ARP_DETECTION_TIME_MS, m_arpDectionTargetIp)) {
1778 m_dhcp4State = DHCP_STATE_DECLINE;
1779 SetSocketMode(SOCKET_MODE_RAW);
1780 } else {
1781 if (PublishDhcpResultEvent(m_cltCnf.ifaceName, PUBLISH_CODE_SUCCESS, &m_dhcpIpResult) != DHCP_OPT_SUCCESS) {
1782 PublishDhcpResultEvent(m_cltCnf.ifaceName, PUBLISH_CODE_FAILED, &m_dhcpIpResult);
1783 DHCP_LOGE("FastArpDetect PublishDhcpResultEvent result failed!");
1784 StopIpv4();
1785 return;
1786 }
1787 SaveIpInfoInLocalFile(m_dhcpIpResult);
1788 m_dhcp4State = DHCP_STATE_SLOW_ARP;
1789 m_slowArpDetecting = true;
1790 }
1791 }
1792
SlowArpDetectCallback(bool isReachable)1793 void DhcpClientStateMachine::SlowArpDetectCallback(bool isReachable)
1794 {
1795 DHCP_LOGI("SlowArpDetectCallback() enter");
1796 if (!m_slowArpDetecting) {
1797 DHCP_LOGI("it is not arpchecking");
1798 return;
1799 }
1800 if (isReachable) {
1801 m_dhcp4State = DHCP_STATE_DECLINE;
1802 m_timeoutTimestamp = 0;
1803 SetSocketMode(SOCKET_MODE_RAW);
1804 #ifndef OHOS_ARCH_LITE
1805 StopTimer(slowArpTimeoutTimerId_);
1806 #endif
1807 } else {
1808 m_dhcp4State = DHCP_STATE_BOUND;
1809 m_sentPacketNum = 0;
1810 m_resendTimer = 0;
1811 m_timeoutTimestamp = static_cast<int64_t>(m_renewalSec) + time(NULL);
1812 StopIpv4();
1813 ScheduleLeaseTimers(false);
1814 }
1815 m_slowArpDetecting = false;
1816 #ifndef OHOS_ARCH_LITE
1817 DhcpTimer::GetInstance()->UnRegister(m_slowArpTaskId);
1818 #endif
1819 }
1820
SlowArpTimeoutCallback()1821 void DhcpClientStateMachine::SlowArpTimeoutCallback()
1822 {
1823 DHCP_LOGI("SlowArpTimeoutCallback, enter");
1824 if (!m_slowArpDetecting) {
1825 DHCP_LOGI("SlowArpTimeoutCallback, it is not arpchecking");
1826 return;
1827 }
1828 m_dhcp4State = DHCP_STATE_BOUND;
1829 m_sentPacketNum = 0;
1830 m_resendTimer = 0;
1831 time_t curTimestamp = time(NULL);
1832 if (curTimestamp == static_cast<time_t>(-1)) {
1833 DHCP_LOGI("StartIpv4, time return failed");
1834 }
1835 m_timeoutTimestamp = curTimestamp + static_cast<time_t>(m_renewalSec);
1836 StopIpv4();
1837 ScheduleLeaseTimers(false);
1838 }
1839
SlowArpDetect(time_t timestamp)1840 void DhcpClientStateMachine::SlowArpDetect(time_t timestamp)
1841 {
1842 DHCP_LOGI("SlowArpDetect() enter, %{public}d", m_sentPacketNum);
1843 if (m_sentPacketNum > SLOW_ARP_DETECTION_TRY_CNT) {
1844 m_dhcp4State = DHCP_STATE_BOUND;
1845 m_sentPacketNum = 0;
1846 m_resendTimer = 0;
1847 m_timeoutTimestamp = timestamp + static_cast<int64_t>(m_renewalSec);
1848 StopIpv4();
1849 ScheduleLeaseTimers(false);
1850 } else if (m_sentPacketNum == SLOW_ARP_DETECTION_TRY_CNT) {
1851 m_timeoutTimestamp = SLOW_ARP_TOTAL_TIME_S + SLOW_ARP_TOTAL_TIME_S + timestamp;
1852 #ifndef OHOS_ARCH_LITE
1853 std::function<void()> func = [this]() {
1854 DHCP_LOGI("SlowArpDetectTask enter");
1855 uint32_t tastId = m_slowArpTaskId;
1856 uint32_t timeout = SLOW_ARP_TOTAL_TIME_MS - SLOW_ARP_DETECTION_TIME_MS * SLOW_ARP_DETECTION_TRY_CNT;
1857 bool ret = IsArpReachable(timeout, m_arpDectionTargetIp);
1858 if (tastId != m_slowArpTaskId) {
1859 ret = false;
1860 DHCP_LOGW("tastId != m_slowArpTaskId, %{public}u, %{public}u", tastId, m_slowArpTaskId);
1861 }
1862 m_slowArpCallback(ret);
1863 };
1864 DhcpTimer::GetInstance()->Register(func, m_slowArpTaskId, 0);
1865 StartTimer(TIMER_SLOW_ARP, slowArpTimeoutTimerId_, static_cast<int64_t>(SLOW_ARP_TOTAL_TIME_MS), true);
1866 DHCP_LOGI("Register m_slowArpTaskId is %{public}u", m_slowArpTaskId);
1867 #endif
1868 } else {
1869 if (IsArpReachable(SLOW_ARP_DETECTION_TIME_MS, m_arpDectionTargetIp)) {
1870 m_dhcp4State = DHCP_STATE_DECLINE;
1871 m_slowArpDetecting = false;
1872 SetSocketMode(SOCKET_MODE_RAW);
1873 }
1874 }
1875 m_sentPacketNum++;
1876 }
1877
IsArpReachable(uint32_t timeoutMillis,std::string ipAddress)1878 bool DhcpClientStateMachine::IsArpReachable(uint32_t timeoutMillis, std::string ipAddress)
1879 {
1880 std::string senderIp = "0.0.0.0";
1881 char macAddr[MAC_ADDR_CHAR_NUM * MAC_ADDR_LEN];
1882 if (memset_s(macAddr, sizeof(macAddr), 0, sizeof(macAddr)) != EOK) {
1883 DHCP_LOGI("IsArpReachable memset_s error");
1884 return false;
1885 }
1886 if (!MacChConToMacStr(m_cltCnf.ifaceMac, MAC_ADDR_LEN, macAddr, sizeof(macAddr))) {
1887 DHCP_LOGE("MacChConToMacStr() failed!");
1888 return false;
1889 }
1890 std::string localMac = macAddr;
1891 uint64_t timeCost = 0;
1892 DhcpArpChecker dhcpArpChecker;
1893 dhcpArpChecker.Start(m_ifName, localMac, senderIp, ipAddress);
1894 if (dhcpArpChecker.DoArpCheck(timeoutMillis, false, timeCost)) {
1895 DHCP_LOGI("Arp detection get response");
1896 return true;
1897 }
1898 DHCP_LOGI("Arp detection not get response");
1899 return false;
1900 }
1901
GetCachedDhcpResult(std::string targetBssid,IpInfoCached & ipcached)1902 int32_t DhcpClientStateMachine::GetCachedDhcpResult(std::string targetBssid, IpInfoCached &ipcached)
1903 {
1904 return DhcpResultStoreManager::GetInstance().GetCachedIp(targetBssid, ipcached);
1905 }
1906
SaveIpInfoInLocalFile(const DhcpIpResult ipResult)1907 void DhcpClientStateMachine::SaveIpInfoInLocalFile(const DhcpIpResult ipResult)
1908 {
1909 DHCP_LOGI("SaveIpInfoInLocalFile() enter");
1910 if (strncmp(m_cltCnf.ifaceName, "wlan", NUMBER_FOUR) != 0) {
1911 DHCP_LOGI("ifaceName is not wlan, no need save");
1912 return;
1913 }
1914
1915 if (m_routerCfg.bssid.empty()) {
1916 DHCP_LOGI("m_routerCfg.bssid is empty, no need save");
1917 return;
1918 }
1919 IpInfoCached ipInfoCached;
1920 ipInfoCached.bssid = m_routerCfg.bssid;
1921 ipInfoCached.absoluteLeasetime = static_cast<int64_t>(ipResult.uOptLeasetime) + static_cast<int64_t>(time(NULL));
1922 ipInfoCached.ipResult = ipResult;
1923 DhcpResultStoreManager::GetInstance().SaveIpInfoInLocalFile(ipInfoCached);
1924 }
1925
TryCachedIp()1926 void DhcpClientStateMachine::TryCachedIp()
1927 {
1928 DHCP_LOGI("TryCachedIp() enter, action:%{public}d dhcpState:%{public}d", m_action, m_dhcp4State);
1929 if (m_routerCfg.prohibitUseCacheIp) {
1930 DHCP_LOGW("don not make default IP");
1931 return;
1932 }
1933
1934 if (strncmp(m_cltCnf.ifaceName, "wlan", NUMBER_FOUR) != 0) {
1935 DHCP_LOGW("ifaceName is not wlan, not use cache ip");
1936 return;
1937 }
1938
1939 IpInfoCached ipCached;
1940 if (GetCachedDhcpResult(m_routerCfg.bssid, ipCached) != 0) {
1941 DHCP_LOGE("TryCachedIp() not find cache ip");
1942 return;
1943 }
1944 if (PublishDhcpResultEvent(m_cltCnf.ifaceName, PUBLISH_CODE_SUCCESS, &ipCached.ipResult) != DHCP_OPT_SUCCESS) {
1945 PublishDhcpResultEvent(m_cltCnf.ifaceName, PUBLISH_CODE_FAILED, &ipCached.ipResult);
1946 DHCP_LOGE("TryCachedIp publish dhcp result failed!");
1947 }
1948 StopIpv4();
1949 m_leaseTime = ipCached.ipResult.uOptLeasetime;
1950 m_renewalSec = ipCached.ipResult.uOptLeasetime * RENEWAL_SEC_MULTIPLE;
1951 m_rebindSec = ipCached.ipResult.uOptLeasetime * REBIND_SEC_MULTIPLE;
1952 m_renewalTimestamp = static_cast<int64_t>(ipCached.ipResult.uAddTime);
1953 DHCP_LOGI("TryCachedIp m_leaseTime:%{public}u %{public}u %{public}u", m_leaseTime, m_renewalSec, m_rebindSec);
1954 ScheduleLeaseTimers(true);
1955 }
1956
SetConfiguration(const RouterConfig & routerCfg)1957 void DhcpClientStateMachine::SetConfiguration(const RouterConfig &routerCfg)
1958 {
1959 m_routerCfg = routerCfg;
1960 }
1961
SetSecondsElapsed(struct DhcpPacket * packet)1962 void DhcpClientStateMachine::SetSecondsElapsed(struct DhcpPacket *packet)
1963 {
1964 if (packet == nullptr) {
1965 DHCP_LOGE("packet is nullptr!");
1966 return;
1967 }
1968 int64_t curTimeSeconds = GetElapsedSecondsSinceBoot();
1969 if (firstSendPacketTime_ == 0) {
1970 firstSendPacketTime_ = curTimeSeconds;
1971 }
1972 packet->secs = htons(static_cast<uint16_t>(curTimeSeconds - firstSendPacketTime_));
1973 DHCP_LOGI("SetSecondsElapsed curTimeSeconds:%{public}" PRId64" %{public}" PRId64", secs:%{public}u",
1974 curTimeSeconds, firstSendPacketTime_, static_cast<uint16_t>(curTimeSeconds - firstSendPacketTime_));
1975 }
1976
1977 #ifndef OHOS_ARCH_LITE
GetIpTimerCallback()1978 void DhcpClientStateMachine::GetIpTimerCallback()
1979 {
1980 DHCP_LOGI("GetIpTimerCallback isExit:%{public}d action:%{public}d [%{public}" PRIu64",%{public}" PRIu64","
1981 "%{public}" PRIu64",%{public}" PRIu64"",
1982 threadExit_.load(), m_action, getIpTimerId, renewDelayTimerId, rebindDelayTimerId, remainingDelayTimerId);
1983 if (threadExit_.load()) {
1984 DHCP_LOGE("GetIpTimerCallback return!");
1985 return;
1986 }
1987 StopTimer(getIpTimerId);
1988 StopIpv4();
1989 if (m_action == ACTION_RENEW_T1 || m_action == ACTION_RENEW_T2) {
1990 DHCP_LOGI("GetIpTimerCallback T1 or T2 Timeout!");
1991 } else if (m_action == ACTION_RENEW_T3) {
1992 DHCP_LOGI("GetIpTimerCallback T3 Expired!");
1993 struct DhcpIpResult ipResult;
1994 ipResult.code = PUBLISH_CODE_EXPIRED;
1995 ipResult.ifname = m_cltCnf.ifaceName;
1996 PublishDhcpIpv4Result(ipResult);
1997 } else {
1998 struct DhcpIpResult ipResult;
1999 ipResult.code = PUBLISH_CODE_TIMEOUT;
2000 ipResult.ifname = m_cltCnf.ifaceName;
2001 PublishDhcpIpv4Result(ipResult);
2002 }
2003 }
2004
StartTimer(TimerType type,uint64_t & timerId,int64_t interval,bool once)2005 void DhcpClientStateMachine::StartTimer(TimerType type, uint64_t &timerId, int64_t interval, bool once)
2006 {
2007 DHCP_LOGI("StartTimer timerId:%{public}" PRIu64" type:%{public}u interval:%{public}" PRId64" once:%{public}d",
2008 timerId, type, interval, once);
2009 if (timerId != 0) {
2010 DHCP_LOGE("StartTimer timerId !=0 id:%{public}" PRIu64"", timerId);
2011 return;
2012 }
2013 std::unique_lock<std::mutex> lock(getIpTimerMutex);
2014 std::function<void()> timeCallback = nullptr;
2015 #ifndef OHOS_EUPDATER
2016 std::shared_ptr<OHOS::DHCP::DhcpSysTimer> dhcpSysTimer =
2017 std::make_shared<OHOS::DHCP::DhcpSysTimer>(false, 0, false, false);
2018 if (dhcpSysTimer == nullptr) {
2019 DHCP_LOGE("StartTimer dhcpSysTimer is nullptr");
2020 return;
2021 }
2022 #endif
2023 SetTimerCallback(type, timeCallback);
2024 if (timeCallback != nullptr) {
2025 #ifndef OHOS_EUPDATER
2026 dhcpSysTimer->SetCallbackInfo(timeCallback);
2027 timerId = MiscServices::TimeServiceClient::GetInstance()->CreateTimer(dhcpSysTimer);
2028 int64_t currentTime = MiscServices::TimeServiceClient::GetInstance()->GetBootTimeMs();
2029 MiscServices::TimeServiceClient::GetInstance()->StartTimer(timerId, currentTime + interval);
2030 #else
2031 uint32_t tempTimerId = 0;
2032 DhcpTimer::GetInstance()->Register(timeCallback, tempTimerId, interval, once);
2033 timerId = tempTimerId;
2034 #endif
2035 DHCP_LOGI("StartTimer timerId:%{public}" PRIu64" [%{public}" PRIu64",%{public}" PRIu64",%{public}" PRIu64","
2036 "%{public}" PRIu64"]",
2037 timerId, getIpTimerId, renewDelayTimerId, rebindDelayTimerId, remainingDelayTimerId);
2038 }
2039 }
2040
SetTimerCallback(TimerType type,std::function<void ()> & timeCallback)2041 void DhcpClientStateMachine::SetTimerCallback(TimerType type, std::function<void()> &timeCallback)
2042 {
2043 switch (type) {
2044 case TIMER_GET_IP:
2045 timeCallback = [this] { this->GetIpTimerCallback(); };
2046 break;
2047 case TIMER_RENEW_DELAY:
2048 timeCallback = [this] { this->RenewDelayCallback(); };
2049 break;
2050 case TIMER_REBIND_DELAY:
2051 timeCallback = [this] { this->RebindDelayCallback(); };
2052 break;
2053 case TIMER_REMAINING_DELAY:
2054 timeCallback = [this] { this->RemainingDelayCallback(); };
2055 break;
2056 case TIMER_SLOW_ARP:
2057 timeCallback = [this] { this->SlowArpTimeoutCallback(); };
2058 break;
2059 default:
2060 DHCP_LOGI("SetTimerCallback: invalid type:%{public}d", static_cast<int32_t>(type));
2061 break;
2062 }
2063 }
2064
2065 #ifndef OHOS_EUPDATER
SetTimerName(TimerType type,std::shared_ptr<OHOS::DHCP::DhcpSysTimer> dhcpSysTimer)2066 void DhcpClientStateMachine::SetTimerName(TimerType type, std::shared_ptr<OHOS::DHCP::DhcpSysTimer> dhcpSysTimer)
2067 {
2068 if (dhcpSysTimer == nullptr) {
2069 return;
2070 }
2071
2072 switch (type) {
2073 case TIMER_GET_IP:
2074 dhcpSysTimer->SetName("getIpTimer");
2075 break;
2076 case TIMER_RENEW_DELAY:
2077 dhcpSysTimer->SetName("renewIpTimer");
2078 break;
2079 case TIMER_REBIND_DELAY:
2080 dhcpSysTimer->SetName("rebindIpTimer");
2081 break;
2082 case TIMER_REMAINING_DELAY:
2083 dhcpSysTimer->SetName("remainingIpTimer");
2084 break;
2085 case TIMER_SLOW_ARP:
2086 dhcpSysTimer->SetName("slowArpTimer");
2087 break;
2088 default:
2089 break;
2090 }
2091 }
2092 #endif
2093
StopTimer(uint64_t & timerId)2094 void DhcpClientStateMachine::StopTimer(uint64_t &timerId)
2095 {
2096 uint64_t stopTimerId = timerId;
2097 if (timerId == 0) {
2098 DHCP_LOGE("StopTimer timerId is 0, no unregister timer");
2099 return;
2100 }
2101 std::unique_lock<std::mutex> lock(getIpTimerMutex);
2102 #ifndef OHOS_EUPDATER
2103 MiscServices::TimeServiceClient::GetInstance()->StopTimer(timerId);
2104 MiscServices::TimeServiceClient::GetInstance()->DestroyTimer(timerId);
2105 #else
2106 DhcpTimer::GetInstance()->UnRegister(static_cast<uint32_t>(timerId));
2107 #endif
2108 timerId = 0;
2109 DHCP_LOGI("StopTimer stopTimerId:%{public}" PRIu64" [%{public}" PRIu64",%{public}" PRIu64",%{public}" PRIu64","
2110 "%{public}" PRIu64"]",
2111 stopTimerId, getIpTimerId, renewDelayTimerId, rebindDelayTimerId, remainingDelayTimerId);
2112 }
2113
RenewDelayCallback()2114 void DhcpClientStateMachine::RenewDelayCallback()
2115 {
2116 DHCP_LOGI("RenewDelayCallback timerId:%{public}" PRIu64"", renewDelayTimerId);
2117 StopTimer(renewDelayTimerId);
2118 StopIpv4();
2119 m_action = ACTION_RENEW_T1; // T1 begin renew
2120 InitConfig(m_ifName, m_cltCnf.isIpv6);
2121 StartTimer(TIMER_GET_IP, getIpTimerId, timeOut_, true);
2122 m_dhcp4State = DHCP_STATE_RENEWING;
2123 m_sentPacketNum = 0;
2124 m_timeoutTimestamp = 0;
2125 InitStartIpv4Thread(m_ifName, m_cltCnf.isIpv6);
2126 }
2127
RebindDelayCallback()2128 void DhcpClientStateMachine::RebindDelayCallback()
2129 {
2130 DHCP_LOGI("RebindDelayCallback timerId:%{public}" PRIu64"", rebindDelayTimerId);
2131 StopTimer(rebindDelayTimerId);
2132 StopIpv4();
2133 m_action = ACTION_RENEW_T2; // T2 begin rebind
2134 InitConfig(m_ifName, m_cltCnf.isIpv6);
2135 StartTimer(TIMER_GET_IP, getIpTimerId, timeOut_, true);
2136 m_dhcp4State = DHCP_STATE_REBINDING;
2137 m_sentPacketNum = 0;
2138 m_timeoutTimestamp = 0;
2139 SetSocketMode(SOCKET_MODE_RAW);
2140 InitStartIpv4Thread(m_ifName, m_cltCnf.isIpv6);
2141 }
2142
RemainingDelayCallback()2143 void DhcpClientStateMachine::RemainingDelayCallback()
2144 {
2145 DHCP_LOGI("RemainingDelayCallback timerId:%{public}" PRIu64"", remainingDelayTimerId);
2146 StopTimer(remainingDelayTimerId);
2147 StopIpv4();
2148 m_action = ACTION_RENEW_T3; // T3 expired,
2149 InitConfig(m_ifName, m_cltCnf.isIpv6);
2150 StartTimer(TIMER_GET_IP, getIpTimerId, timeOut_, true);
2151 m_dhcp4State = DHCP_STATE_INIT;
2152 m_sentPacketNum = 0;
2153 m_timeoutTimestamp = 0;
2154 SetSocketMode(SOCKET_MODE_RAW);
2155 InitStartIpv4Thread(m_ifName, m_cltCnf.isIpv6); // int discover
2156 }
2157 #endif
2158
SendStopSignal()2159 int DhcpClientStateMachine::SendStopSignal()
2160 {
2161 DHCP_LOGI("SendStopSignal isExit:%{public}d", threadExit_.load());
2162 if (!threadExit_.load()) {
2163 int signum = SIG_STOP;
2164 if (send(m_sigSockFds[1], &signum, sizeof(signum), MSG_DONTWAIT) < 0) {
2165 DHCP_LOGE("SendStopSignal send SIG_STOP failed.");
2166 return DHCP_OPT_FAILED;
2167 }
2168 DHCP_LOGE("SendStopSignal send SIG_STOP ok, m_sigSockFds[1]:%{public}d", m_sigSockFds[1]);
2169 }
2170 return DHCP_OPT_SUCCESS;
2171 }
2172
CloseAllRenewTimer()2173 void DhcpClientStateMachine::CloseAllRenewTimer()
2174 {
2175 DHCP_LOGI("CloseAllRenewTimer enter!");
2176 #ifndef OHOS_ARCH_LITE
2177 StopTimer(renewDelayTimerId);
2178 StopTimer(rebindDelayTimerId);
2179 StopTimer(remainingDelayTimerId);
2180 #endif
2181 }
2182
ScheduleLeaseTimers(bool isCachedIp)2183 void DhcpClientStateMachine::ScheduleLeaseTimers(bool isCachedIp)
2184 {
2185 DHCP_LOGI("ScheduleLeaseTimers threadExit:%{public}d m_action:%{public}d isCachedIp:%{public}d",
2186 threadExit_.load(), m_action, isCachedIp);
2187 int64_t delay = 0;
2188 if (isCachedIp) {
2189 time_t curTimestamp = time(nullptr);
2190 if (curTimestamp == static_cast<time_t>(-1)) {
2191 DHCP_LOGE("time return failed, errno:%{public}d", errno);
2192 return;
2193 }
2194 delay = (static_cast<int64_t>(curTimestamp) < m_renewalTimestamp) ? 0 : (static_cast<int64_t>(curTimestamp) -
2195 m_renewalTimestamp);
2196 DHCP_LOGI("ScheduleLeaseTimers delay:%{public}" PRId64", curTimestamp:%{public}" PRId64","
2197 "m_renewalTimestamp:%{public}" PRId64, delay, static_cast<int64_t>(curTimestamp), m_renewalTimestamp);
2198 } else {
2199 int64_t curTimestampBoot = GetElapsedSecondsSinceBoot();
2200 delay = (curTimestampBoot < m_renewalTimestampBoot) ? 0 : (curTimestampBoot - m_renewalTimestampBoot);
2201 DHCP_LOGI("ScheduleLeaseTimers delay:%{public}" PRId64", curTimestampBoot:%{public}" PRId64","
2202 "m_renewalTimestampBoot:%{public}" PRId64, delay, curTimestampBoot, m_renewalTimestampBoot);
2203 }
2204
2205 int64_t remainingDelay = ((static_cast<int64_t>(m_leaseTime) < delay) ? (static_cast<int64_t>(m_leaseTime)) :
2206 (static_cast<int64_t>(m_leaseTime) - delay)) * USECOND_CONVERT;
2207 if (IsPcDevice() && m_routerCfg.bSpecificNetwork) {
2208 int64_t renewalSec = remainingDelay * RENEWAL_SEC_MULTIPLE_SPECIFIC_NETWORK;
2209 DHCP_LOGI("SpecifigNetwork, ScheduleLeaseTimers renewalSec:%{public}" PRId64", leaseTime:%{public}d,"
2210 "remainingDelay:%{public}" PRId64, renewalSec, m_leaseTime, remainingDelay);
2211 #ifndef OHOS_ARCH_LITE
2212 StopTimer(renewDelayTimerId);
2213 StopTimer(rebindDelayTimerId);
2214 StopTimer(remainingDelayTimerId);
2215 StartTimer(TIMER_RENEW_DELAY, renewDelayTimerId, renewalSec, true);
2216 StartTimer(TIMER_REMAINING_DELAY, remainingDelayTimerId, remainingDelay, true);
2217 #endif
2218 } else {
2219 int64_t renewalSec = remainingDelay * RENEWAL_SEC_MULTIPLE;
2220 int64_t rebindSec = remainingDelay * REBIND_SEC_MULTIPLE;
2221 DHCP_LOGI("ScheduleLeaseTimers renewalSec:%{public}" PRId64", rebindSec:%{public}" PRId64","
2222 "remainingDelay:%{public}" PRId64, renewalSec, rebindSec, remainingDelay);
2223 #ifndef OHOS_ARCH_LITE
2224 StopTimer(renewDelayTimerId);
2225 StopTimer(rebindDelayTimerId);
2226 StopTimer(remainingDelayTimerId);
2227 StartTimer(TIMER_RENEW_DELAY, renewDelayTimerId, renewalSec, true);
2228 StartTimer(TIMER_REBIND_DELAY, rebindDelayTimerId, rebindSec, true);
2229 StartTimer(TIMER_REMAINING_DELAY, remainingDelayTimerId, remainingDelay, true);
2230 #endif
2231 }
2232 }
2233
IsPcDevice()2234 bool DhcpClientStateMachine::IsPcDevice()
2235 {
2236 const char deviceClass[] = "const.product.devicetype";
2237 constexpr const int32_t SYS_PARAMETER_SIZE = 256;
2238 constexpr const int32_t SYSTEM_PARAMETER_ERROR_CODE = 0;
2239 char param[SYS_PARAMETER_SIZE] = { 0 };
2240 int errorCode = GetParameter(deviceClass, NULL, param, SYS_PARAMETER_SIZE);
2241 if (errorCode <= SYSTEM_PARAMETER_ERROR_CODE) {
2242 DHCP_LOGE("get devicetype fail, errorCode: %{public}d", errorCode);
2243 return false;
2244 }
2245 DHCP_LOGI("devicetype: %{public}s, Code: %{public}d.", param, errorCode);
2246 auto iter = std::string(param).find("2in1");
2247 return iter != std::string::npos;
2248 }
2249
2250 } // namespace DHCP
2251 } // namespace OHOS