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