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