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