• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #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