• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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