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