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