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