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