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_ipv4.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
34 #include "securec.h"
35 #include "dhcp_client.h"
36 #include "dhcp_options.h"
37 #include "dhcp_socket.h"
38 #include "dhcp_function.h"
39
40 #undef LOG_TAG
41 #define LOG_TAG "WifiDhcpIpv4"
42
43 struct ArpPacket {
44 struct ethhdr ethh; /* Ethernet header */
45 struct arphdr arph; /* Arp header */
46 u_char sHaddr[6]; /* sender's hardware address */
47 u_char sInaddr[4]; /* sender's IP address */
48 u_char tHaddr[6]; /* target's hardware address */
49 u_char tInaddr[4]; /* target's IP address */
50 u_char pad[18]; /* pad for min. Ethernet payload (60 bytes) */
51 };
52
53 /* static defined */
54 static int g_dhcp4State = DHCP_STATE_INIT;
55 static int g_sockFd = -1;
56 static int g_sigSockFds[NUMBER_TWO];
57 static uint32_t g_sentPacketNum = 0;
58 static uint32_t g_timeoutTimestamp = 0;
59 static uint32_t g_renewalTimestamp = 0;
60 static uint32_t g_leaseTime = 0;
61 static uint32_t g_renewalSec = 0;
62 static uint32_t g_rebindSec = 0;
63 static uint32_t g_requestedIp4 = 0;
64 static uint32_t g_serverIp4 = 0;
65 static uint32_t g_socketMode = SOCKET_MODE_INVALID;
66 static uint32_t g_transID = 0;
67
68 static struct DhcpClientCfg *g_cltCnf;
69
GetPacketReadSockFd(void)70 int GetPacketReadSockFd(void)
71 {
72 return g_sockFd;
73 }
74
GetSigReadSockFd(void)75 int GetSigReadSockFd(void)
76 {
77 return g_sigSockFds[0];
78 }
79
GetDhcpTransID(void)80 uint32_t GetDhcpTransID(void)
81 {
82 return g_transID;
83 }
84
85 /* Send signals. */
SignalHandler(int signum)86 static void SignalHandler(int signum)
87 {
88 switch (signum) {
89 case SIGTERM:
90 /* Send signal SIGTERM. */
91 case SIGUSR1:
92 /* Send signal SIGUSR1. */
93 case SIGUSR2:
94 /* Send signal SIGUSR2. */
95 send(g_sigSockFds[1], &signum, sizeof(signum), MSG_DONTWAIT);
96 break;
97 default:
98 break;
99 }
100 }
101
102 /* Set the socket mode. */
SetSocketMode(uint32_t mode)103 void SetSocketMode(uint32_t mode)
104 {
105 close(g_sockFd);
106 g_sockFd = -1;
107 g_socketMode = mode;
108 LOGI("SetSocketMode() the socket mode %{public}s.", (mode == SOCKET_MODE_RAW) ? "raw"
109 : ((mode == SOCKET_MODE_KERNEL) ? "kernel" : "not valid"));
110 }
111
112 /* Execution dhcp release. */
ExecDhcpRelease(void)113 int ExecDhcpRelease(void)
114 {
115 /* Ensure that we've received dhcp ack packet completely. */
116 if ((g_dhcp4State == DHCP_STATE_BOUND) || (g_dhcp4State == DHCP_STATE_RENEWING) ||
117 (g_dhcp4State == DHCP_STATE_REBINDING)) {
118 /* Unicast dhcp release packet. */
119 DhcpRelease(g_requestedIp4, g_serverIp4);
120 }
121
122 g_dhcp4State = DHCP_STATE_RELEASED;
123 SetSocketMode(SOCKET_MODE_INVALID);
124
125 /* Ensure that the function select() is always blocked and don't need to receive ip from dhcp server. */
126 g_timeoutTimestamp = SIGNED_INTEGER_MAX;
127
128 LOGI("ExecDhcpRelease() enter released state...");
129 return DHCP_OPT_SUCCESS;
130 }
131
132 /* Execution dhcp renew. */
ExecDhcpRenew(void)133 int ExecDhcpRenew(void)
134 {
135 /* Set socket mode and dhcp ipv4 state, make sure dhcp packets can be sent normally. */
136 switch (g_dhcp4State) {
137 case DHCP_STATE_INIT:
138 case DHCP_STATE_SELECTING:
139 LOGI("ExecDhcpRenew() dhcp ipv4 old state:%{public}d, no need change state.", g_dhcp4State);
140 break;
141 case DHCP_STATE_REQUESTING:
142 case DHCP_STATE_RELEASED:
143 case DHCP_STATE_RENEWED:
144 LOGI("ExecDhcpRenew() dhcp ipv4 old state:%{public}d, init state:INIT.", g_dhcp4State);
145 /* Init socket mode and dhcp ipv4 state. */
146 g_dhcp4State = DHCP_STATE_INIT;
147 SetSocketMode(SOCKET_MODE_RAW);
148 break;
149 case DHCP_STATE_BOUND:
150 /* Set socket mode, send unicast packet. */
151 SetSocketMode(SOCKET_MODE_KERNEL);
152 case DHCP_STATE_RENEWING:
153 case DHCP_STATE_REBINDING:
154 LOGI("ExecDhcpRenew() dhcp ipv4 old state:%{public}d, set state:RENEWED.", g_dhcp4State);
155 /* Set dhcp ipv4 state, send request packet. */
156 g_dhcp4State = DHCP_STATE_RENEWED;
157 break;
158 default:
159 break;
160 }
161
162 /* Start record again, go back to init state. */
163 g_sentPacketNum = 0;
164 g_timeoutTimestamp = 0;
165
166 LOGI("ExecDhcpRenew() a dhcp renew is executed...");
167 return DHCP_OPT_SUCCESS;
168 }
169
170 /* Add dhcp option parameter request list. */
AddParamaterRequestList(struct DhcpPacket * packet)171 static void AddParamaterRequestList(struct DhcpPacket *packet)
172 {
173 int end = GetEndOptionIndex(packet->options);
174 int i;
175 int len = 0;
176 uint8_t arrReqCode[DHCP_REQ_CODE_NUM] = {SUBNET_MASK_OPTION,
177 ROUTER_OPTION,
178 DOMAIN_NAME_SERVER_OPTION,
179 HOST_NAME_OPTION,
180 DOMAIN_NAME_OPTION,
181 BROADCAST_ADDRESS_OPTION};
182
183 packet->options[end + DHCP_OPT_CODE_INDEX] = PARAMETER_REQUEST_LIST_OPTION;
184 for (i = 0; i < DHCP_REQ_CODE_NUM; i++) {
185 if ((arrReqCode[i] > PAD_OPTION) && (arrReqCode[i] < END_OPTION)) {
186 packet->options[end + DHCP_OPT_DATA_INDEX + len++] = arrReqCode[i];
187 }
188 }
189 packet->options[end + DHCP_OPT_LEN_INDEX] = len;
190 packet->options[end + DHCP_OPT_DATA_INDEX + len] = END_OPTION;
191 }
192
193 /* Init the socket fd. */
InitSocketFd(void)194 static void InitSocketFd(void)
195 {
196 if (g_sockFd < 0) {
197 if (g_socketMode == SOCKET_MODE_INVALID) {
198 return;
199 }
200
201 bool bInitSuccess = true;
202 if (g_socketMode == SOCKET_MODE_RAW) {
203 if ((CreateRawSocket(&g_sockFd) != SOCKET_OPT_SUCCESS) ||
204 (BindRawSocket(g_sockFd, g_cltCnf->ifaceIndex, NULL) != SOCKET_OPT_SUCCESS)) {
205 LOGE("InitSocketFd() fd:%{public}d,index:%{public}d failed!", g_sockFd, g_cltCnf->ifaceIndex);
206 bInitSuccess = false;
207 }
208 } else {
209 if ((CreateKernelSocket(&g_sockFd) != SOCKET_OPT_SUCCESS) ||
210 (BindKernelSocket(g_sockFd, g_cltCnf->ifaceName, INADDR_ANY, BOOTP_CLIENT, true) !=
211 SOCKET_OPT_SUCCESS)) {
212 LOGE("InitSocketFd() fd:%{public}d,ifname:%{public}s failed!", g_sockFd, g_cltCnf->ifaceName);
213 bInitSuccess = false;
214 }
215 }
216 if (!bInitSuccess || (g_sockFd < 0)) {
217 LOGE("InitSocketFd() %{public}d err:%{public}d, couldn't listen on socket!", g_sockFd, errno);
218 unlink(g_cltCnf->pidFile);
219 unlink(g_cltCnf->resultFile);
220 exit(EXIT_SUCCESS);
221 }
222 }
223 }
224
225 /* Obtains a random number as the trans id. */
GetTransId(void)226 static uint32_t GetTransId(void)
227 {
228 static bool bSranded = false;
229 if (!bSranded) {
230 unsigned int uSeed = 0;
231 int nFd = -1;
232 if ((nFd = open("/dev/urandom", 0)) == -1) {
233 LOGE("GetTransId() open /dev/urandom failed, error:%{public}d!", errno);
234 uSeed = time(NULL);
235 } else {
236 if (read(nFd, &uSeed, sizeof(uSeed)) == -1) {
237 LOGE("GetTransId() read /dev/urandom failed, error:%{public}d!", errno);
238 uSeed = time(NULL);
239 }
240 LOGI("GetTransId() read /dev/urandom uSeed:%{public}u.", uSeed);
241 close(nFd);
242 }
243 srandom(uSeed);
244 bSranded = true;
245 }
246 return random();
247 }
248
InitSelecting(time_t timestamp)249 static void InitSelecting(time_t timestamp)
250 {
251 if (g_sentPacketNum > TIMEOUT_TIMES_MAX) {
252 /* Send packet timed out, now exit process. */
253 LOGW("InitSelecting() send packet timed out %{public}u times, now exit process!", g_sentPacketNum);
254 g_timeoutTimestamp = timestamp + TIMEOUT_MORE_WAIT_SEC;
255 g_sentPacketNum = 0;
256 g_cltCnf->timeoutExit = true;
257 return;
258 }
259
260 if (g_sentPacketNum == 0) {
261 g_transID = GetTransId();
262 }
263
264 /* Broadcast dhcp discover packet. */
265 DhcpDiscover(g_transID, g_requestedIp4);
266 if (g_dhcp4State != DHCP_STATE_SELECTING) {
267 g_dhcp4State = DHCP_STATE_SELECTING;
268 }
269
270 uint32_t uTimeoutSec = TIMEOUT_WAIT_SEC << g_sentPacketNum;
271 g_timeoutTimestamp = timestamp + uTimeoutSec;
272 LOGI("InitSelecting() DhcpDiscover g_sentPacketNum:%{public}u,timeoutSec:%{public}u,timestamp:%{public}u.",
273 g_sentPacketNum,
274 uTimeoutSec,
275 g_timeoutTimestamp);
276
277 g_sentPacketNum++;
278 }
279
ReadLease(void)280 static struct DhcpPacket *ReadLease(void)
281 {
282 if (g_cltCnf->leaseFile[0] == '\0') {
283 return NULL;
284 }
285
286 int fd;
287 struct DhcpPacket *dhcp = NULL;
288 ssize_t rBytes;
289
290 fd = open(g_cltCnf->leaseFile, O_RDONLY);
291 if (fd < 0) {
292 return NULL;
293 }
294
295 dhcp = calloc(1, sizeof(*dhcp));
296 if (dhcp == NULL) {
297 close(fd);
298 return NULL;
299 }
300
301 rBytes = read(fd, (uint8_t *)dhcp, sizeof(*dhcp));
302 close(fd);
303 if (rBytes <= 0 || (size_t)rBytes < offsetof(struct DhcpPacket, options)) {
304 free(dhcp);
305 dhcp = NULL;
306 return NULL;
307 }
308
309 return dhcp;
310 }
311
WriteLease(const struct DhcpPacket * pkt)312 static ssize_t WriteLease(const struct DhcpPacket *pkt)
313 {
314 if (pkt == NULL) {
315 return -1;
316 }
317
318 if (g_cltCnf->leaseFile[0] == '\0') {
319 return -1;
320 }
321
322 int fd;
323 ssize_t wBytes;
324
325 fd = open(g_cltCnf->leaseFile, O_WRONLY | O_CREAT | O_TRUNC, RWMODE);
326 if (fd < 0) {
327 return -1;
328 }
329
330 wBytes = write(fd, (uint8_t *)pkt, sizeof(*pkt));
331 close(fd);
332 return wBytes;
333 }
334
AddParamaterRebootList(struct DhcpPacket * packet)335 static void AddParamaterRebootList(struct DhcpPacket *packet)
336 {
337 int end = GetEndOptionIndex(packet->options);
338 int i;
339 int len = 0;
340 uint8_t arrReqCode[DHCP_REQ_CODE_NUM] = {
341 SUBNET_MASK_OPTION,
342 STATIC_ROUTE_OPTION,
343 ROUTER_OPTION,
344 DOMAIN_NAME_SERVER_OPTION,
345 BROADCAST_ADDRESS_OPTION,
346 IP_ADDRESS_LEASE_TIME_OPTION,
347 RENEWAL_TIME_VALUE_OPTION,
348 REBINDING_TIME_VALUE_OPTION};
349
350 packet->options[end + DHCP_OPT_CODE_INDEX] = PARAMETER_REQUEST_LIST_OPTION;
351 for (i = 0; i < DHCP_REQ_CODE_NUM; i++) {
352 if ((arrReqCode[i] > PAD_OPTION) && (arrReqCode[i] < END_OPTION)) {
353 packet->options[end + DHCP_OPT_DATA_INDEX + len++] = arrReqCode[i];
354 }
355 }
356 packet->options[end + DHCP_OPT_LEN_INDEX] = len;
357 packet->options[end + DHCP_OPT_DATA_INDEX + len] = END_OPTION;
358 }
359
DhcpReboot(uint32_t transid,uint32_t reqip)360 static int DhcpReboot(uint32_t transid, uint32_t reqip)
361 {
362 LOGI("DhcpReboot() enter");
363 struct DhcpPacket packet;
364 if (memset_s(&packet, sizeof(struct DhcpPacket), 0, sizeof(struct DhcpPacket)) != EOK) {
365 return -1;
366 }
367
368 /* Get packet header and common info. */
369 if (GetPacketHeaderInfo(&packet, DHCP_REQUEST) != DHCP_OPT_SUCCESS) {
370 return -1;
371 }
372
373 if (memcpy_s(packet.chaddr, sizeof(packet.chaddr), g_cltCnf->ifaceMac, MAC_ADDR_LEN) != EOK) {
374 LOGE("DhcpReboot() failed, memcpy_s error!");
375 return -1;
376 }
377
378 /* Get packet not common info. */
379 packet.xid = transid;
380 AddOptValueToOpts(packet.options, REQUESTED_IP_ADDRESS_OPTION, reqip);
381 AddOptValueToOpts(packet.options, MAXIMUM_DHCP_MESSAGE_SIZE_OPTION, MAX_MSG_SIZE);
382 AddOptValueToOpts(packet.options, FORCERENEW_NONCE_OPTION, 1);
383 AddParamaterRebootList(&packet);
384
385 /* Begin broadcast dhcp request packet. */
386 char *pReqIp = Ip4IntConToStr(reqip, false);
387 if (pReqIp != NULL) {
388 LOGI("DhcpReboot() broadcast req packet, reqip: host %{private}u->%{private}s.", ntohl(reqip), pReqIp);
389 free(pReqIp);
390 pReqIp = NULL;
391 }
392 return SendToDhcpPacket(&packet, INADDR_ANY, INADDR_BROADCAST, g_cltCnf->ifaceIndex, (uint8_t *)MAC_BCAST_ADDR);
393 }
394
SendReboot(struct DhcpPacket * p,time_t timestamp)395 void SendReboot(struct DhcpPacket *p, time_t timestamp)
396 {
397 if (p == NULL) {
398 return;
399 }
400
401 g_requestedIp4 = p->yiaddr;
402
403 free(p);
404 p = NULL;
405
406 g_transID = GetTransId();
407 g_dhcp4State = DHCP_STATE_INITREBOOT;
408 g_sentPacketNum = 0;
409
410 uint32_t uTimeoutSec = TIMEOUT_WAIT_SEC << g_sentPacketNum;
411 g_timeoutTimestamp = timestamp + uTimeoutSec;
412 DhcpReboot(g_transID, g_requestedIp4);
413 }
414
Reboot(time_t timestamp)415 static void Reboot(time_t timestamp)
416 {
417 struct DhcpPacket *pkt = ReadLease();
418 if (pkt == NULL) {
419 return;
420 }
421
422 uint32_t leaseTime;
423 uint32_t renewalTime;
424 uint32_t rebindTime;
425 uint32_t interval;
426 struct stat st;
427 if (!GetDhcpOptionUint32(pkt, IP_ADDRESS_LEASE_TIME_OPTION, &leaseTime)) {
428 leaseTime = ~0U;
429 }
430
431 if (leaseTime != ~0U && stat(g_cltCnf->leaseFile, &st) == 0) {
432 if (timestamp == (time_t)-1 || timestamp < st.st_mtime || (time_t)leaseTime < timestamp - st.st_mtime) {
433 LOGI("Reboot read lease file leaseTime expire");
434 free(pkt);
435 pkt = NULL;
436 return;
437 } else {
438 interval = timestamp - st.st_mtime;
439 leaseTime -= interval;
440 renewalTime = leaseTime * RENEWAL_SEC_MULTIPLE;
441 rebindTime = leaseTime * REBIND_SEC_MULTIPLE;
442 LOGI("Reboot read lease file leaseTime:%{public}u, renewalTime:%{public}u, rebindTime:%{public}u",
443 leaseTime, renewalTime, rebindTime);
444 }
445 } else {
446 LOGI("Reboot read lease file leaseTime option not found");
447 free(pkt);
448 pkt = NULL;
449 return;
450 }
451
452 g_leaseTime = leaseTime;
453 g_renewalSec = renewalTime;
454 g_rebindSec = rebindTime;
455
456 SendReboot(pkt, timestamp);
457 }
458
Requesting(time_t timestamp)459 static void Requesting(time_t timestamp)
460 {
461 if (g_sentPacketNum > TIMEOUT_TIMES_MAX) {
462 /* Send packet timed out, now enter init state. */
463 g_dhcp4State = DHCP_STATE_INIT;
464 SetSocketMode(SOCKET_MODE_RAW);
465 g_sentPacketNum = 0;
466 g_timeoutTimestamp = timestamp;
467 return;
468 }
469
470 if (g_dhcp4State == DHCP_STATE_RENEWED) {
471 /* Unicast dhcp request packet in the renew state. */
472 DhcpRenew(g_transID, g_requestedIp4, g_serverIp4);
473 } else {
474 /* Broadcast dhcp request packet in the requesting state. */
475 DhcpRequest(g_transID, g_requestedIp4, g_serverIp4);
476 }
477
478 uint32_t uTimeoutSec = TIMEOUT_WAIT_SEC << g_sentPacketNum;
479 g_timeoutTimestamp = timestamp + uTimeoutSec;
480 LOGI("Requesting() DhcpRequest g_sentPacketNum:%{public}u,timeoutSec:%{public}u,g_timeoutTimestamp:%{public}u.",
481 g_sentPacketNum,
482 uTimeoutSec,
483 g_timeoutTimestamp);
484
485 g_sentPacketNum++;
486 }
487
Renewing(time_t timestamp)488 static void Renewing(time_t timestamp)
489 {
490 if ((g_renewalSec + TIME_INTERVAL_MAX) < g_rebindSec) {
491 /* Cur time is between renewal and rebind time, unicast dhcp request packet in the renew state. */
492 DhcpRenew(g_transID, g_requestedIp4, g_serverIp4);
493
494 /* Set a new renewal time. */
495 g_renewalSec += (g_rebindSec - g_renewalSec) / NUMBER_TWO;
496 g_timeoutTimestamp = g_renewalTimestamp + g_renewalSec;
497 LOGI("Renewing() DhcpRenew unicast renewalTime:%{public}u,renewal:%{public}u,timeoutTime:%{public}u, "
498 "rebind:%{public}u.",
499 g_renewalTimestamp,
500 g_renewalSec,
501 g_timeoutTimestamp,
502 g_rebindSec);
503 } else {
504 /* Cur time reaches rebind time, now enter rebinding state. */
505 g_dhcp4State = DHCP_STATE_REBINDING;
506 LOGI("Renewing() cur time reaches rebind time, now enter rebinding state...");
507 g_timeoutTimestamp = timestamp + (g_rebindSec - g_renewalSec);
508 LOGI("Renewing() timestamp:%{public}d,rebind:%{public}u,renewal:%{public}u, timeoutTime:%{public}u.",
509 (int)timestamp, g_rebindSec, g_renewalSec, g_timeoutTimestamp);
510 }
511 }
512
Rebinding(time_t timestamp)513 static void Rebinding(time_t timestamp)
514 {
515 if ((g_rebindSec + TIME_INTERVAL_MAX) < g_leaseTime) {
516 /* Cur time is between rebind and lease time, broadcast dhcp request packet in the rebind state. */
517 DhcpRenew(g_transID, g_requestedIp4, 0);
518
519 /* Set a new rebind time. */
520 g_rebindSec += (g_leaseTime - g_rebindSec) / NUMBER_TWO;
521 g_timeoutTimestamp = g_renewalTimestamp + g_rebindSec;
522 LOGI("Rebinding() DhcpRenew broadcast renewalTime:%{public}u,rebind:%{public}u,timeoutTime:%{public}u, "
523 "lease:%{public}u.",
524 g_renewalTimestamp,
525 g_rebindSec,
526 g_timeoutTimestamp,
527 g_leaseTime);
528 } else {
529 /* Cur time reaches lease time, send packet timed out, now enter init state. */
530 LOGI("Rebinding() 555 cur time reaches lease time, now enter init state...");
531 g_dhcp4State = DHCP_STATE_INIT;
532 SetSocketMode(SOCKET_MODE_RAW);
533 g_sentPacketNum = 0;
534 g_timeoutTimestamp = timestamp;
535 return;
536 }
537 }
538
DhcpRequestHandle(time_t timestamp)539 static void DhcpRequestHandle(time_t timestamp)
540 {
541 switch (g_dhcp4State) {
542 case DHCP_STATE_INIT:
543 case DHCP_STATE_SELECTING:
544 InitSelecting(timestamp);
545 break;
546 case DHCP_STATE_REQUESTING:
547 case DHCP_STATE_RENEWED:
548 Requesting(timestamp);
549 break;
550 case DHCP_STATE_BOUND:
551 /* Now the renewal time run out, ready to enter renewing state. */
552 LOGI("DhcpRequestHandle() 333 the renewal time run out, ready to enter renewing state...");
553 g_dhcp4State = DHCP_STATE_RENEWING;
554 SetSocketMode(SOCKET_MODE_KERNEL);
555 case DHCP_STATE_RENEWING:
556 Renewing(timestamp);
557 break;
558 case DHCP_STATE_REBINDING:
559 Rebinding(timestamp);
560 break;
561 case DHCP_STATE_INITREBOOT:
562 g_dhcp4State = DHCP_STATE_INIT;
563 break;
564 case DHCP_STATE_RELEASED:
565 /* Ensure that the function select() is always blocked and don't need to receive ip from dhcp server. */
566 g_timeoutTimestamp = SIGNED_INTEGER_MAX;
567 break;
568 default:
569 break;
570 }
571 }
572
DhcpOfferPacketHandle(uint8_t type,const struct DhcpPacket * packet,time_t timestamp)573 static void DhcpOfferPacketHandle(uint8_t type, const struct DhcpPacket *packet, time_t timestamp)
574 {
575 if (type != DHCP_OFFER) {
576 LOGE("DhcpOfferPacketHandle() type:%{public}d error!", type);
577 return;
578 }
579
580 if (packet == NULL) {
581 LOGE("DhcpOfferPacketHandle() type:%{public}d error, packet == NULL!", type);
582 return;
583 }
584
585 uint32_t u32Data = 0;
586 if (!GetDhcpOptionUint32(packet, SERVER_IDENTIFIER_OPTION, &u32Data)) {
587 LOGE("DhcpOfferPacketHandle() type:%{public}d GetDhcpOptionUint32 SERVER_IDENTIFIER_OPTION failed!", type);
588 return;
589 }
590
591 g_transID = packet->xid;
592 g_requestedIp4 = packet->yiaddr;
593 g_serverIp4 = htonl(u32Data);
594
595 char *pReqIp = Ip4IntConToStr(g_requestedIp4, false);
596 if (pReqIp != NULL) {
597 LOGI(
598 "DhcpOfferPacketHandle() receive DHCP_OFFER, xid:%{public}u, requestIp: host %{private}u->%{private}s.",
599 g_transID,
600 ntohl(g_requestedIp4),
601 pReqIp);
602 free(pReqIp);
603 pReqIp = NULL;
604 }
605 char *pSerIp = Ip4IntConToStr(g_serverIp4, false);
606 if (pSerIp != NULL) {
607 LOGI("DhcpOfferPacketHandle() receive DHCP_OFFER, serverIp: host %{private}u->%{private}s.",
608 ntohl(g_serverIp4),
609 pSerIp);
610 free(pSerIp);
611 pSerIp = NULL;
612 }
613
614 /* Receive dhcp offer packet finished, next send dhcp request packet. */
615 WriteLease(packet);
616 g_dhcp4State = DHCP_STATE_REQUESTING;
617 g_sentPacketNum = 0;
618 g_timeoutTimestamp = timestamp;
619 }
620
ParseOtherNetworkInfo(const struct DhcpPacket * packet,struct DhcpResult * result)621 static void ParseOtherNetworkInfo(const struct DhcpPacket *packet, struct DhcpResult *result)
622 {
623 if ((packet == NULL) || (result == NULL)) {
624 LOGE("ParseOtherNetworkInfo() error, packet == NULL or result == NULL!");
625 return;
626 }
627
628 uint32_t u32Data = 0;
629 uint32_t u32Data2 = 0;
630 if (GetDhcpOptionUint32n(packet, DOMAIN_NAME_SERVER_OPTION, &u32Data, &u32Data2)) {
631 char *pDnsIp = Ip4IntConToStr(u32Data, true);
632 if (pDnsIp != NULL) {
633 LOGI("ParseOtherNetworkInfo() recv DHCP_ACK 6, dns1: %{private}u->%{private}s.", u32Data, pDnsIp);
634 if (strncpy_s(result->strOptDns1, INET_ADDRSTRLEN, pDnsIp, INET_ADDRSTRLEN - 1) != EOK) {
635 free(pDnsIp);
636 pDnsIp = NULL;
637 return;
638 }
639 free(pDnsIp);
640 pDnsIp = NULL;
641 }
642 if ((u32Data2 > 0) && ((pDnsIp = Ip4IntConToStr(u32Data2, true)) != NULL)) {
643 LOGI("ParseOtherNetworkInfo() recv DHCP_ACK 6, dns2: %{private}u->%{private}s.", u32Data2, pDnsIp);
644 if (strncpy_s(result->strOptDns2, INET_ADDRSTRLEN, pDnsIp, INET_ADDRSTRLEN - 1) != EOK) {
645 LOGE("ParseOtherNetworkInfo() strncpy_s Failed.");
646 }
647 free(pDnsIp);
648 pDnsIp = NULL;
649 return;
650 }
651 }
652 return;
653 }
654
ParseNetworkInfo(const struct DhcpPacket * packet,struct DhcpResult * result)655 static void ParseNetworkInfo(const struct DhcpPacket *packet, struct DhcpResult *result)
656 {
657 if ((packet == NULL) || (result == NULL)) {
658 LOGE("ParseNetworkInfo() error, packet == NULL or result == NULL!");
659 return;
660 }
661
662 char *pReqIp = Ip4IntConToStr(g_requestedIp4, false);
663 if (pReqIp != NULL) {
664 LOGI("ParseNetworkInfo() recv DHCP_ACK yiaddr: %{private}u->%{private}s.", ntohl(g_requestedIp4), pReqIp);
665 if (strncpy_s(result->strYiaddr, INET_ADDRSTRLEN, pReqIp, INET_ADDRSTRLEN - 1) != EOK) {
666 LOGI("ParseNetworkInfo() strncpy_s failed!");
667 free(pReqIp);
668 pReqIp = NULL;
669 return;
670 }
671 free(pReqIp);
672 pReqIp = NULL;
673 }
674
675 uint32_t u32Data = 0;
676 if (GetDhcpOptionUint32(packet, SUBNET_MASK_OPTION, &u32Data)) {
677 char *pSubIp = Ip4IntConToStr(u32Data, true);
678 if (pSubIp != NULL) {
679 LOGI("ParseNetworkInfo() recv DHCP_ACK 1, subnetmask: %{private}u->%{private}s.", u32Data, pSubIp);
680 if (strncpy_s(result->strOptSubnet, INET_ADDRSTRLEN, pSubIp, INET_ADDRSTRLEN - 1) != EOK) {
681 free(pSubIp);
682 pSubIp = NULL;
683 return;
684 }
685 free(pSubIp);
686 pSubIp = NULL;
687 }
688 }
689
690 u32Data = 0;
691 uint32_t u32Data2 = 0;
692 if (GetDhcpOptionUint32n(packet, ROUTER_OPTION, &u32Data, &u32Data2)) {
693 char *pRouterIp = Ip4IntConToStr(u32Data, true);
694 if (pRouterIp != NULL) {
695 LOGI("ParseNetworkInfo() recv DHCP_ACK 3, router1: %{private}u->%{private}s.", u32Data, pRouterIp);
696 if (strncpy_s(result->strOptRouter1, INET_ADDRSTRLEN, pRouterIp, INET_ADDRSTRLEN - 1) != EOK) {
697 free(pRouterIp);
698 pRouterIp = NULL;
699 return;
700 }
701 free(pRouterIp);
702 pRouterIp = NULL;
703 }
704 if ((u32Data2 > 0) && ((pRouterIp = Ip4IntConToStr(u32Data2, true)) != NULL)) {
705 LOGI("ParseNetworkInfo() recv DHCP_ACK 3, router2: %{private}u->%{private}s.", u32Data2, pRouterIp);
706 if (strncpy_s(result->strOptRouter2, INET_ADDRSTRLEN, pRouterIp, INET_ADDRSTRLEN - 1) != EOK) {
707 free(pRouterIp);
708 pRouterIp = NULL;
709 return;
710 }
711 free(pRouterIp);
712 pRouterIp = NULL;
713 }
714 }
715
716 ParseOtherNetworkInfo(packet, result);
717 }
718
FormatString(struct DhcpResult * result)719 static void FormatString(struct DhcpResult *result)
720 {
721 if (result == NULL) {
722 LOGE("FormatString() error, result == NULL!");
723 return;
724 }
725
726 if (strlen(result->strYiaddr) == 0) {
727 if (strncpy_s(result->strYiaddr, INET_ADDRSTRLEN, "*", INET_ADDRSTRLEN - 1) != EOK) {
728 return;
729 }
730 }
731 if (strlen(result->strOptServerId) == 0) {
732 if (strncpy_s(result->strOptServerId, INET_ADDRSTRLEN, "*", INET_ADDRSTRLEN - 1) != EOK) {
733 return;
734 }
735 }
736 if (strlen(result->strOptSubnet) == 0) {
737 if (strncpy_s(result->strOptSubnet, INET_ADDRSTRLEN, "*", INET_ADDRSTRLEN - 1) != EOK) {
738 return;
739 }
740 }
741 if (strlen(result->strOptDns1) == 0) {
742 if (strncpy_s(result->strOptDns1, INET_ADDRSTRLEN, "*", INET_ADDRSTRLEN - 1) != EOK) {
743 return;
744 }
745 }
746 if (strlen(result->strOptDns2) == 0) {
747 if (strncpy_s(result->strOptDns2, INET_ADDRSTRLEN, "*", INET_ADDRSTRLEN - 1) != EOK) {
748 return;
749 }
750 }
751 if (strlen(result->strOptRouter1) == 0) {
752 if (strncpy_s(result->strOptRouter1, INET_ADDRSTRLEN, "*", INET_ADDRSTRLEN - 1) != EOK) {
753 return;
754 }
755 }
756 if (strlen(result->strOptRouter2) == 0) {
757 if (strncpy_s(result->strOptRouter2, INET_ADDRSTRLEN, "*", INET_ADDRSTRLEN - 1) != EOK) {
758 return;
759 }
760 }
761 if (strlen(result->strOptVendor) == 0) {
762 if (strncpy_s(result->strOptVendor, DHCP_FILE_MAX_BYTES, "*", DHCP_FILE_MAX_BYTES - 1) != EOK) {
763 return;
764 }
765 }
766 }
767
WriteDhcpResult(struct DhcpResult * result)768 static int WriteDhcpResult(struct DhcpResult *result)
769 {
770 if (result == NULL) {
771 LOGE("WriteDhcpResult() error, result == NULL!");
772 return DHCP_OPT_FAILED;
773 }
774
775 /* Format dhcp result. */
776 FormatString(result);
777
778 uint32_t curTime = (uint32_t)time(NULL);
779 if ((time_t)curTime == (time_t)-1) {
780 return DHCP_OPT_FAILED;
781 }
782 LOGI("WriteDhcpResult() "
783 "result->strYiaddr:%{private}s,strOptServerId:%{private}s,strOptSubnet:%{private}s,uOptLeasetime:%{public}u,"
784 " curTime:%{public}u.",
785 result->strYiaddr, result->strOptServerId, result->strOptSubnet, result->uOptLeasetime, curTime);
786 FILE *pFile = fopen(g_cltCnf->resultFile, "w+");
787 if (pFile == NULL) {
788 LOGE("WriteDhcpResult fopen %{public}s err:%{public}d!", g_cltCnf->resultFile, errno);
789 return DHCP_OPT_FAILED;
790 }
791
792 /* Lock the writing file. */
793 if (flock(fileno(pFile), LOCK_EX) != 0) {
794 LOGE("WriteDhcpResult() flock file:%{public}s LOCK_EX failed, error:%{public}d!", g_cltCnf->resultFile, errno);
795 fclose(pFile);
796 return DHCP_OPT_FAILED;
797 }
798
799 /* Format: IP4 timestamp cliIp servIp subnet dns1 dns2 router1 router2 vendor lease. */
800 int nBytes = fprintf(pFile,
801 "IP4 %u %s %s %s %s %s %s %s %s %u\n",
802 curTime, result->strYiaddr, result->strOptServerId, result->strOptSubnet, result->strOptDns1,
803 result->strOptDns2, result->strOptRouter1, result->strOptRouter2, result->strOptVendor, result->uOptLeasetime);
804 if (nBytes <= 0) {
805 LOGE("WriteDhcpResult() fprintf %{public}s error:%{public}d!", g_cltCnf->resultFile, errno);
806 fclose(pFile);
807 return DHCP_OPT_FAILED;
808 }
809
810 /* Unlock the writing file. */
811 if (flock(fileno(pFile), LOCK_UN) != 0) {
812 LOGE("WriteDhcpResult() flock file:%{public}s LOCK_UN failed, error:%{public}d!", g_cltCnf->resultFile, errno);
813 fclose(pFile);
814 return DHCP_OPT_FAILED;
815 }
816
817 if (fclose(pFile) != 0) {
818 LOGE("WriteDhcpResult() fclose %{public}s error:%{public}d!", g_cltCnf->resultFile, errno);
819 return DHCP_OPT_FAILED;
820 }
821 LOGI("WriteDhcpResult() fprintf %{public}s success, nBytes:%{public}d.", g_cltCnf->resultFile, nBytes);
822 return DHCP_OPT_SUCCESS;
823 }
824
SyncDhcpResult(const struct DhcpPacket * packet,struct DhcpResult * result)825 static int SyncDhcpResult(const struct DhcpPacket *packet, struct DhcpResult *result)
826 {
827 if ((packet == NULL) || (result == NULL)) {
828 LOGE("SyncDhcpResult() error, packet == NULL or result == NULL!");
829 return DHCP_OPT_FAILED;
830 }
831
832 char *pVendor = GetDhcpOptionString(packet, VENDOR_SPECIFIC_INFO_OPTION);
833 if (pVendor == NULL) {
834 LOGW("SyncDhcpResult() recv DHCP_ACK 43, pVendor is NULL!");
835 } else {
836 LOGI("SyncDhcpResult() recv DHCP_ACK 43, pVendor is %{public}s.", pVendor);
837 if (strncpy_s(result->strOptVendor, DHCP_FILE_MAX_BYTES, pVendor, DHCP_FILE_MAX_BYTES - 1) != EOK) {
838 LOGE("SyncDhcpResult() error, strncpy_s pVendor failed!");
839 free(pVendor);
840 pVendor = NULL;
841 return DHCP_OPT_FAILED;
842 }
843 free(pVendor);
844 pVendor = NULL;
845 }
846
847 /* Set the specified client process interface network info. */
848 if (SetLocalInterface(g_cltCnf->ifaceName, inet_addr(result->strYiaddr), inet_addr(result->strOptSubnet))
849 != DHCP_OPT_SUCCESS) {
850 LOGE("SyncDhcpResult() error, SetLocalInterface yiaddr:%{private}s failed!", result->strYiaddr);
851 return DHCP_OPT_FAILED;
852 }
853
854 /* Write to the file. */
855 if (WriteDhcpResult(result) != DHCP_OPT_SUCCESS) {
856 LOGE("SyncDhcpResult() error, WriteDhcpResult result failed!");
857 return DHCP_OPT_FAILED;
858 }
859
860 /* Publish dhcp success result event. */
861 if (PublishDhcpResultEvent(g_cltCnf->ifaceName, PUBLISH_CODE_SUCCESS, result) != DHCP_OPT_SUCCESS) {
862 LOGE("SyncDhcpResult() error, PublishDhcpResultEvent result failed!");
863 return DHCP_OPT_FAILED;
864 }
865
866 LOGI("SyncDhcpResult() handle dhcp result success, ifaceName:%{public}s.", g_cltCnf->ifaceName);
867 return DHCP_OPT_SUCCESS;
868 }
869
ParseDhcpAckPacket(const struct DhcpPacket * packet,time_t timestamp)870 static void ParseDhcpAckPacket(const struct DhcpPacket *packet, time_t timestamp)
871 {
872 if (packet == NULL) {
873 LOGE("ParseDhcpAckPacket() error, packet == NULL!");
874 return;
875 }
876
877 struct DhcpResult dhcpResult;
878 if (memset_s(&dhcpResult, sizeof(struct DhcpResult), 0, sizeof(struct DhcpResult)) != EOK) {
879 LOGE("ParseDhcpAckPacket() error, memset_s failed!");
880 return;
881 }
882
883 /* Set default leasetime. */
884 g_leaseTime = LEASETIME_DEFAULT * ONE_HOURS_SEC;
885 g_requestedIp4 = packet->yiaddr;
886 uint32_t u32Data = 0;
887 if (GetDhcpOptionUint32(packet, IP_ADDRESS_LEASE_TIME_OPTION, &u32Data)) {
888 g_leaseTime = u32Data;
889 LOGI("ParseDhcpAckPacket() recv DHCP_ACK 51, lease:%{public}u.", g_leaseTime);
890 }
891 g_renewalSec = g_leaseTime * RENEWAL_SEC_MULTIPLE; /* First renewal seconds. */
892 g_rebindSec = g_leaseTime * REBIND_SEC_MULTIPLE; /* Second rebind seconds. */
893 g_renewalTimestamp = timestamp; /* Record begin renewing or rebinding timestamp. */
894 dhcpResult.uOptLeasetime = g_leaseTime;
895 LOGI("Last get lease:%{public}u,renewal:%{public}u,rebind:%{public}u.", g_leaseTime, g_renewalSec, g_rebindSec);
896
897 if (!GetDhcpOptionUint32(packet, SERVER_IDENTIFIER_OPTION, &u32Data)) {
898 LOGE("ParseDhcpAckPacket() GetDhcpOptionUint32 SERVER_IDENTIFIER_OPTION failed!");
899 } else {
900 g_serverIp4 = htonl(u32Data);
901 char *pSerIp = Ip4IntConToStr(g_serverIp4, false);
902 if (pSerIp != NULL) {
903 LOGI("ParseDhcpAckPacket() recv DHCP_ACK 54, serid: %{private}u->%{private}s.", u32Data, pSerIp);
904 if (strncpy_s(dhcpResult.strOptServerId, INET_ADDRSTRLEN, pSerIp, INET_ADDRSTRLEN - 1) != EOK) {
905 free(pSerIp);
906 pSerIp = NULL;
907 return;
908 }
909 free(pSerIp);
910 pSerIp = NULL;
911 }
912 }
913
914 /* Parse the specified client process interface network info. */
915 ParseNetworkInfo(packet, &dhcpResult);
916
917 /* Sync the specified client process interface network info to the file. */
918 if (SyncDhcpResult(packet, &dhcpResult) != DHCP_OPT_SUCCESS) {
919 /* Publish dhcp failed result event. */
920 PublishDhcpResultEvent(g_cltCnf->ifaceName, PUBLISH_CODE_FAILED, NULL);
921 return;
922 }
923
924 /* Receive dhcp ack packet finished, g_leaseTime * T1 later enter renewing state. */
925 g_dhcp4State = DHCP_STATE_BOUND;
926 SetSocketMode(SOCKET_MODE_INVALID);
927 g_timeoutTimestamp = timestamp + g_renewalSec;
928 }
929
DhcpAckOrNakPacketHandle(uint8_t type,struct DhcpPacket * packet,time_t timestamp)930 static void DhcpAckOrNakPacketHandle(uint8_t type, struct DhcpPacket *packet, time_t timestamp)
931 {
932 if ((type != DHCP_ACK) && (type != DHCP_NAK)) {
933 LOGE("DhcpAckOrNakPacketHandle() type:%{public}d error!", type);
934 if (g_dhcp4State == DHCP_STATE_INITREBOOT) {
935 g_dhcp4State = DHCP_STATE_INIT;
936 g_timeoutTimestamp = timestamp;
937 }
938 return;
939 }
940
941 if (packet == NULL) {
942 LOGE("DhcpAckOrNakPacketHandle() type:%{public}d error, packet == NULL!", type);
943 return;
944 }
945
946 if (type == DHCP_NAK) {
947 /* If receive dhcp nak packet, init g_dhcp4State, resend dhcp discover packet. */
948 LOGI("DhcpAckOrNakPacketHandle() receive DHCP_NAK 53, init g_dhcp4State, resend dhcp discover packet!");
949 g_dhcp4State = DHCP_STATE_INIT;
950 SetSocketMode(SOCKET_MODE_RAW);
951 g_requestedIp4 = 0;
952 g_sentPacketNum = 0;
953 g_timeoutTimestamp = timestamp;
954
955 /* Avoid excessive network traffic. */
956 LOGI("DhcpAckOrNakPacketHandle() receive DHCP_NAK 53, avoid excessive network traffic, need sleep!");
957 sleep(NUMBER_THREE);
958 return;
959 }
960
961 LOGI("DhcpAckOrNakPacketHandle() recv DHCP_ACK 53.");
962
963 /* Parse received dhcp ack packet. */
964 ParseDhcpAckPacket(packet, timestamp);
965
966 /* ack packet success. */
967 if (g_dhcp4State == DHCP_STATE_BOUND) {
968 WriteLease(packet);
969 }
970 }
971
DhcpResponseHandle(time_t timestamp)972 static void DhcpResponseHandle(time_t timestamp)
973 {
974 struct DhcpPacket packet;
975 int getLen;
976 uint8_t u8Message = 0;
977
978 if (memset_s(&packet, sizeof(packet), 0, sizeof(packet)) != EOK) {
979 LOGE("DhcpResponseHandle() memset_s packet failed!");
980 return;
981 }
982 getLen = (g_socketMode == SOCKET_MODE_RAW) ? GetDhcpRawPacket(&packet, g_sockFd)
983 : GetDhcpKernelPacket(&packet, g_sockFd);
984 if (getLen < 0) {
985 if ((getLen == SOCKET_OPT_ERROR) && (errno != EINTR)) {
986 LOGE("DhcpResponseHandle() get packet read error, reopening socket!");
987 /* Reopen g_sockFd. */
988 SetSocketMode(g_socketMode);
989 }
990 LOGE("DhcpResponseHandle() get packet failed, error:%{public}d!", errno);
991 if (g_dhcp4State == DHCP_STATE_INITREBOOT) {
992 g_dhcp4State = DHCP_STATE_INIT;
993 g_timeoutTimestamp = timestamp;
994 }
995 return;
996 }
997 LOGI("DhcpResponseHandle() get packet success, getLen:%{public}d.", getLen);
998
999 /* Check packet data. */
1000 if (packet.xid != g_transID) {
1001 LOGW("DhcpResponseHandle() get xid:%{public}u and g_transID:%{public}u not same!", packet.xid, g_transID);
1002 return;
1003 }
1004 if (!GetDhcpOptionUint8(&packet, DHCP_MESSAGE_TYPE_OPTION, &u8Message)) {
1005 LOGE("DhcpResponseHandle() GetDhcpOptionUint8 DHCP_MESSAGE_TYPE_OPTION failed!");
1006 return;
1007 }
1008
1009 switch (g_dhcp4State) {
1010 case DHCP_STATE_SELECTING:
1011 DhcpOfferPacketHandle(u8Message, &packet, timestamp);
1012 break;
1013 case DHCP_STATE_REQUESTING:
1014 case DHCP_STATE_RENEWING:
1015 case DHCP_STATE_REBINDING:
1016 case DHCP_STATE_INITREBOOT:
1017 case DHCP_STATE_RENEWED:
1018 DhcpAckOrNakPacketHandle(u8Message, &packet, timestamp);
1019 break;
1020 case DHCP_STATE_BOUND:
1021 case DHCP_STATE_RELEASED:
1022 LOGW("DhcpResponseHandle() g_dhcp4State is BOUND or RELEASED, ignore all packets!");
1023 break;
1024 default:
1025 break;
1026 }
1027 }
1028
1029 /* Receive signals. */
SignalReceiver(void)1030 static void SignalReceiver(void)
1031 {
1032 int signum;
1033 if (read(g_sigSockFds[0], &signum, sizeof(signum)) < 0) {
1034 LOGE("SignalReceiver() failed, g_sigSockFds[0]:%{public}d read error:%{public}d!", g_sigSockFds[0], errno);
1035 return;
1036 }
1037
1038 switch (signum) {
1039 case SIGTERM:
1040 LOGW("SignalReceiver() SIGTERM!");
1041 SetSocketMode(SOCKET_MODE_INVALID);
1042 unlink(g_cltCnf->pidFile);
1043 unlink(g_cltCnf->resultFile);
1044 exit(EXIT_SUCCESS);
1045 break;
1046 case SIGUSR1:
1047 LOGW("SignalReceiver() SIGUSR1!");
1048 ExecDhcpRelease();
1049 break;
1050 case SIGUSR2:
1051 LOGW("SignalReceiver() SIGUSR2!");
1052 ExecDhcpRenew();
1053 break;
1054 default:
1055 break;
1056 }
1057 }
1058
1059
1060 /* Set dhcp ipv4 state. */
SetIpv4State(int state)1061 int SetIpv4State(int state)
1062 {
1063 if (state < 0) {
1064 LOGE("SetIpv4State() failed, state:%{public}d!", state);
1065 return DHCP_OPT_FAILED;
1066 }
1067
1068 g_dhcp4State = state;
1069 return DHCP_OPT_SUCCESS;
1070 }
1071
1072 /* Init signal handle function. */
InitSignalHandle(void)1073 int InitSignalHandle(void)
1074 {
1075 /* Create signal socket fd. */
1076 if (socketpair(AF_UNIX, SOCK_STREAM, 0, g_sigSockFds) != 0) {
1077 LOGE("InitSignalHandle() failed, socketpair error str:%{public}d!", errno);
1078 return DHCP_OPT_FAILED;
1079 }
1080
1081 /* Register signal handlers. */
1082 if (signal(SIGTERM, SignalHandler) == SIG_ERR) {
1083 LOGE("InitSignalHandle() failed, signal SIGTERM error str:%{public}d!", errno);
1084 return DHCP_OPT_FAILED;
1085 }
1086
1087 if (signal(SIGUSR1, SignalHandler) == SIG_ERR) {
1088 LOGE("InitSignalHandle() failed, signal SIGUSR1 error str:%{public}d!", errno);
1089 return DHCP_OPT_FAILED;
1090 }
1091
1092 if (signal(SIGUSR2, SignalHandler) == SIG_ERR) {
1093 LOGE("InitSignalHandle() failed, signal SIGUSR2 error str:%{public}d!", errno);
1094 return DHCP_OPT_FAILED;
1095 }
1096
1097 return DHCP_OPT_SUCCESS;
1098 }
1099
1100 extern bool PublishDhcpIpv4ResultEvent(const int code, const char *data, const char *ifname);
PublishDhcpResultEvent(const char * ifname,const int code,struct DhcpResult * result)1101 int PublishDhcpResultEvent(const char *ifname, const int code, struct DhcpResult *result)
1102 {
1103 if (ifname == NULL) {
1104 LOGE("PublishDhcpResultEvent() failed, ifname == NULL!");
1105 return DHCP_OPT_FAILED;
1106 }
1107 if ((code != PUBLISH_CODE_SUCCESS) && (code != PUBLISH_CODE_FAILED)) {
1108 LOGE("PublishDhcpResultEvent() ifname:%{public}s failed, code:%{public}d error!", ifname, code);
1109 return DHCP_OPT_FAILED;
1110 }
1111 if ((code == PUBLISH_CODE_SUCCESS) && (result == NULL)) {
1112 LOGE("PublishDhcpResultEvent() ifname:%{public}s,code:%{public}d failed, result == NULL!", ifname, code);
1113 return DHCP_OPT_FAILED;
1114 }
1115
1116 /* Data format - ipv4:ifname,time,cliIp,lease,servIp,subnet,dns1,dns2,router1,router2,vendor */
1117 int nBytes;
1118 uint32_t curTime = (uint32_t)time(NULL);
1119 char strData[STRING_MAX_LEN] = {0};
1120 if (code == PUBLISH_CODE_SUCCESS) {
1121 nBytes = snprintf_s(strData, STRING_MAX_LEN, STRING_MAX_LEN - 1, "ipv4:%s,%u,%s,%u,%s,%s,%s,%s,%s,%s,%s",
1122 ifname, curTime, result->strYiaddr, result->uOptLeasetime, result->strOptServerId, result->strOptSubnet,
1123 result->strOptDns1, result->strOptDns2, result->strOptRouter1, result->strOptRouter2, result->strOptVendor);
1124 } else {
1125 nBytes = snprintf_s(strData, STRING_MAX_LEN, STRING_MAX_LEN - 1, "ipv4:%s,%u,*,*,*,*,*,*,*,*,*",
1126 ifname, curTime);
1127 }
1128 if (nBytes < 0) {
1129 LOGE("PublishDhcpResultEvent() failed, snprintf_s %{public}s error:%{public}d!", ifname, errno);
1130 return DHCP_OPT_FAILED;
1131 }
1132
1133 if (!PublishDhcpIpv4ResultEvent(code, strData, ifname)) {
1134 LOGE("PublishDhcpResultEvent() PublishDhcpIpv4ResultEvent %{public}d %{public}s failed!", code, strData);
1135 return DHCP_OPT_FAILED;
1136 }
1137 LOGI("PublishDhcpResultEvent() PublishDhcpIpv4ResultEvent %{public}d %{private}s success.", code, strData);
1138 return DHCP_OPT_SUCCESS;
1139 }
1140
GetPacketHeaderInfo(struct DhcpPacket * packet,uint8_t type)1141 int GetPacketHeaderInfo(struct DhcpPacket *packet, uint8_t type)
1142 {
1143 if (packet == NULL) {
1144 LOGE("GetPacketHeaderInfo() failed, packet == NULL!");
1145 return DHCP_OPT_FAILED;
1146 }
1147
1148 switch (type) {
1149 case DHCP_DISCOVER:
1150 case DHCP_REQUEST:
1151 case DHCP_DECLINE:
1152 case DHCP_RELEASE:
1153 case DHCP_INFORM:
1154 packet->op = BOOT_REQUEST;
1155 break;
1156 case DHCP_OFFER:
1157 case DHCP_ACK:
1158 case DHCP_NAK:
1159 packet->op = BOOT_REPLY;
1160 break;
1161 default:
1162 break;
1163 }
1164 packet->htype = ETHERNET_TYPE;
1165 packet->hlen = ETHERNET_LEN;
1166 packet->cookie = htonl(MAGIC_COOKIE);
1167 packet->options[0] = END_OPTION;
1168 AddOptValueToOpts(packet->options, DHCP_MESSAGE_TYPE_OPTION, type);
1169
1170 return DHCP_OPT_SUCCESS;
1171 }
1172
GetPacketCommonInfo(struct DhcpPacket * packet)1173 int GetPacketCommonInfo(struct DhcpPacket *packet)
1174 {
1175 if (packet == NULL) {
1176 LOGE("GetPacketCommonInfo() failed, packet == NULL!");
1177 return DHCP_OPT_FAILED;
1178 }
1179
1180 /* Add packet client_cfg info. */
1181 if (memcpy_s(packet->chaddr, sizeof(packet->chaddr), g_cltCnf->ifaceMac, MAC_ADDR_LEN) != EOK) {
1182 LOGE("GetPacketCommonInfo() failed, memcpy_s error!");
1183 return DHCP_OPT_FAILED;
1184 }
1185 int nClientIdLen = DHCP_OPT_CODE_BYTES + DHCP_OPT_LEN_BYTES + g_cltCnf->pOptClientId[DHCP_OPT_LEN_INDEX];
1186 AddOptStrToOpts(packet->options, g_cltCnf->pOptClientId, nClientIdLen);
1187
1188 /* Add packet vendor info, vendor format: pro-version. */
1189 char buf[VENDOR_MAX_LEN - DHCP_OPT_CODE_BYTES - DHCP_OPT_LEN_BYTES] = {0};
1190 unsigned char vendorId[VENDOR_MAX_LEN] = {0};
1191 unsigned char *pVendorId = vendorId;
1192 int nRes = snprintf_s(buf,
1193 VENDOR_MAX_LEN - DHCP_OPT_DATA_INDEX,
1194 VENDOR_MAX_LEN - DHCP_OPT_DATA_INDEX - 1,
1195 "%s-%s",
1196 DHCPC_NAME,
1197 DHCPC_VERSION);
1198 if (nRes < 0) {
1199 LOGE("GetPacketCommonInfo() failed, snprintf_s res:%{public}d error!", nRes);
1200 return DHCP_OPT_FAILED;
1201 }
1202 pVendorId[DHCP_OPT_CODE_INDEX] = VENDOR_SPECIFIC_INFO_OPTION;
1203 pVendorId[DHCP_OPT_LEN_INDEX] = strlen(buf);
1204 if (strncpy_s((char *)pVendorId + DHCP_OPT_DATA_INDEX, VENDOR_MAX_LEN - DHCP_OPT_DATA_INDEX, buf, strlen(buf)) !=
1205 EOK) {
1206 LOGE("GetPacketCommonInfo() failed, strncpy_s error!");
1207 return DHCP_OPT_FAILED;
1208 }
1209 if (strlen((char *)vendorId) > 0) {
1210 int nVendorIdLen = DHCP_OPT_CODE_BYTES + DHCP_OPT_LEN_BYTES + pVendorId[DHCP_OPT_LEN_INDEX];
1211 AddOptStrToOpts(packet->options, vendorId, nVendorIdLen);
1212 }
1213
1214 return DHCP_OPT_SUCCESS;
1215 }
1216
1217 /* Broadcast dhcp discover packet, discover dhcp servers that can provide ip address. */
DhcpDiscover(uint32_t transid,uint32_t requestip)1218 int DhcpDiscover(uint32_t transid, uint32_t requestip)
1219 {
1220 LOGI("DhcpDiscover() enter, transid:%{public}u,requestip:%{private}u.", transid, requestip);
1221
1222 struct DhcpPacket packet;
1223 if (memset_s(&packet, sizeof(struct DhcpPacket), 0, sizeof(struct DhcpPacket)) != EOK) {
1224 return -1;
1225 }
1226
1227 /* Get packet header and common info. */
1228 if ((GetPacketHeaderInfo(&packet, DHCP_DISCOVER) != DHCP_OPT_SUCCESS) ||
1229 (GetPacketCommonInfo(&packet) != DHCP_OPT_SUCCESS)) {
1230 return -1;
1231 }
1232
1233 /* Get packet not common info. */
1234 packet.xid = transid;
1235 if (requestip > 0) {
1236 AddOptValueToOpts(packet.options, REQUESTED_IP_ADDRESS_OPTION, requestip);
1237 }
1238 AddParamaterRequestList(&packet);
1239
1240 /* Begin broadcast dhcp discover packet. */
1241 LOGI("DhcpDiscover() discover, begin broadcast discover packet...");
1242 return SendToDhcpPacket(&packet, INADDR_ANY, INADDR_BROADCAST, g_cltCnf->ifaceIndex, (uint8_t *)MAC_BCAST_ADDR);
1243 }
1244
1245 /* Broadcast dhcp request packet, tell dhcp servers that which ip address to choose. */
DhcpRequest(uint32_t transid,uint32_t reqip,uint32_t servip)1246 int DhcpRequest(uint32_t transid, uint32_t reqip, uint32_t servip)
1247 {
1248 LOGI("DhcpRequest() enter, transid:%{public}u,reqip:%{private}u.", transid, reqip);
1249
1250 struct DhcpPacket packet;
1251 if (memset_s(&packet, sizeof(struct DhcpPacket), 0, sizeof(struct DhcpPacket)) != EOK) {
1252 return -1;
1253 }
1254
1255 /* Get packet header and common info. */
1256 if ((GetPacketHeaderInfo(&packet, DHCP_REQUEST) != DHCP_OPT_SUCCESS) ||
1257 (GetPacketCommonInfo(&packet) != DHCP_OPT_SUCCESS)) {
1258 return -1;
1259 }
1260
1261 /* Get packet not common info. */
1262 packet.xid = transid;
1263 AddOptValueToOpts(packet.options, REQUESTED_IP_ADDRESS_OPTION, reqip);
1264 AddOptValueToOpts(packet.options, SERVER_IDENTIFIER_OPTION, servip);
1265 AddParamaterRequestList(&packet);
1266
1267 /* Begin broadcast dhcp request packet. */
1268 char *pReqIp = Ip4IntConToStr(reqip, false);
1269 if (pReqIp != NULL) {
1270 LOGI("DhcpRequest() broadcast req packet, reqip: host %{private}u->%{private}s.", ntohl(reqip), pReqIp);
1271 free(pReqIp);
1272 pReqIp = NULL;
1273 }
1274 char *pSerIp = Ip4IntConToStr(servip, false);
1275 if (pSerIp != NULL) {
1276 LOGI("DhcpRequest() broadcast req packet, servIp: host %{private}u->%{private}s.", ntohl(servip), pSerIp);
1277 free(pSerIp);
1278 pSerIp = NULL;
1279 }
1280 return SendToDhcpPacket(&packet, INADDR_ANY, INADDR_BROADCAST, g_cltCnf->ifaceIndex, (uint8_t *)MAC_BCAST_ADDR);
1281 }
1282
1283 /* 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)1284 int DhcpRenew(uint32_t transid, uint32_t clientip, uint32_t serverip)
1285 {
1286 LOGI("DhcpRenew() enter, transid:%{public}u,clientip:%{private}u.", transid, clientip);
1287
1288 struct DhcpPacket packet;
1289 if (memset_s(&packet, sizeof(struct DhcpPacket), 0, sizeof(struct DhcpPacket)) != EOK) {
1290 return -1;
1291 }
1292
1293 /* Get packet header and common info. */
1294 if ((GetPacketHeaderInfo(&packet, DHCP_REQUEST) != DHCP_OPT_SUCCESS) ||
1295 (GetPacketCommonInfo(&packet) != DHCP_OPT_SUCCESS)) {
1296 return -1;
1297 }
1298
1299 /* Get packet not common info. */
1300 packet.xid = transid;
1301 packet.ciaddr = clientip;
1302 AddParamaterRequestList(&packet);
1303
1304 /* Begin broadcast or unicast dhcp request packet. */
1305 if (serverip == 0) {
1306 LOGI("DhcpRenew() rebind, begin broadcast req packet");
1307 return SendToDhcpPacket(&packet, INADDR_ANY, INADDR_BROADCAST, g_cltCnf->ifaceIndex, (uint8_t *)MAC_BCAST_ADDR);
1308 }
1309 LOGI("DhcpRenew() renew, begin unicast request packet");
1310 return SendDhcpPacket(&packet, clientip, serverip);
1311 }
1312
1313 /* Unicast dhcp release packet, releasing an ip address in Use from the dhcp server. */
DhcpRelease(uint32_t clientip,uint32_t serverip)1314 int DhcpRelease(uint32_t clientip, uint32_t serverip)
1315 {
1316 LOGI("DhcpRelease() enter, clientip:%{private}u.", clientip);
1317
1318 struct DhcpPacket packet;
1319 if (memset_s(&packet, sizeof(struct DhcpPacket), 0, sizeof(struct DhcpPacket)) != EOK) {
1320 return -1;
1321 }
1322
1323 /* Get packet header and common info. */
1324 if ((GetPacketHeaderInfo(&packet, DHCP_RELEASE) != DHCP_OPT_SUCCESS) ||
1325 (GetPacketCommonInfo(&packet) != DHCP_OPT_SUCCESS)) {
1326 return -1;
1327 }
1328
1329 /* Get packet not common info. */
1330 packet.xid = GetTransId();
1331 AddOptValueToOpts(packet.options, REQUESTED_IP_ADDRESS_OPTION, clientip);
1332 AddOptValueToOpts(packet.options, SERVER_IDENTIFIER_OPTION, serverip);
1333
1334 LOGI("DhcpRelease() release, begin unicast release packet, clientip:%{private}u, serverip:%{private}u", clientip,
1335 serverip);
1336 return SendDhcpPacket(&packet, clientip, serverip);
1337 }
1338
DhcpInit(void)1339 static void DhcpInit(void)
1340 {
1341 g_cltCnf = GetDhcpClientCfg();
1342
1343 /* Init dhcp ipv4 state. */
1344 g_dhcp4State = DHCP_STATE_INIT;
1345 SetSocketMode(SOCKET_MODE_RAW);
1346
1347 InitSocketFd();
1348
1349 time_t t = time(NULL);
1350 if (t == (time_t)-1) {
1351 return;
1352 }
1353 Reboot(t);
1354 }
1355
StartIpv4(void)1356 int StartIpv4(void)
1357 {
1358 int nRet, nMaxFds;
1359 fd_set exceptfds;
1360 struct timeval timeout;
1361 time_t curTimestamp;
1362
1363 DhcpInit();
1364
1365 for (; ;) {
1366 if (g_cltCnf->timeoutExit) {
1367 LOGW("StartIpv4() send packet timed out, now break!");
1368 break;
1369 }
1370
1371 FD_ZERO(&exceptfds);
1372 timeout.tv_sec = g_timeoutTimestamp - time(NULL);
1373 timeout.tv_usec = 0;
1374
1375 InitSocketFd();
1376
1377 if (g_sockFd >= 0) {
1378 FD_SET(g_sockFd, &exceptfds);
1379 }
1380 FD_SET(g_sigSockFds[0], &exceptfds);
1381
1382 if (timeout.tv_sec <= 0) {
1383 LOGI("StartIpv4() already timed out, need send or resend packet...");
1384 nRet = 0;
1385 } else {
1386 LOGI("StartIpv4() waiting on select...");
1387 nMaxFds = (g_sigSockFds[0] > g_sockFd) ? g_sigSockFds[0] : g_sockFd;
1388 nRet = select(nMaxFds + 1, &exceptfds, NULL, NULL, &timeout);
1389 }
1390 if (nRet < 0) {
1391 if ((nRet == -1) && (errno == EINTR)) {
1392 LOGW("StartIpv4() select err:%{public}d, a signal was caught!", errno);
1393 } else {
1394 LOGE("StartIpv4() failed, select maxFds:%{public}d error:%{public}d!", nMaxFds, errno);
1395 }
1396 continue;
1397 }
1398
1399 curTimestamp = time(NULL);
1400 if (nRet == 0) {
1401 DhcpRequestHandle(curTimestamp);
1402 } else if ((g_socketMode != SOCKET_MODE_INVALID) && FD_ISSET(g_sockFd, &exceptfds)) {
1403 DhcpResponseHandle(curTimestamp);
1404 } else if (FD_ISSET(g_sigSockFds[0], &exceptfds)) {
1405 SignalReceiver();
1406 } else {
1407 LOGW("StartIpv4() nRet:%{public}d, g_socketMode:%{public}d, continue select...", nRet, g_socketMode);
1408 }
1409 }
1410 return g_cltCnf->timeoutExit ? StopProcess(g_cltCnf->pidFile) : DHCP_OPT_SUCCESS;
1411 }
1412