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