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