• 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 
16 #include "dhcp_server.h"
17 #include <arpa/inet.h>
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <net/if.h>
21 #include <netinet/in.h>
22 #include <securec.h>
23 #include <stdint.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <sys/select.h>
28 #include <sys/socket.h>
29 #include <sys/time.h>
30 #include <sys/types.h>
31 #include <unistd.h>
32 #include "address_utils.h"
33 #include "common_util.h"
34 #include "dhcp_address_pool.h"
35 #include "dhcp_binding.h"
36 #include "dhcp_config.h"
37 #include "dhcp_ipv4.h"
38 #include "dhcp_logger.h"
39 #include "dhcp_option.h"
40 #include "hash_table.h"
41 
42 #undef LOG_TAG
43 #define LOG_TAG "DhcpServer"
44 
45 #ifndef DHCP_SEL_WAIT_TIMEOUTS
46 #define DHCP_SEL_WAIT_TIMEOUTS 1000
47 #endif
48 #define OPT_MESSAGE_TYPE_LEGTH 1
49 #define OPT_HEADER_LENGTH 2
50 #define OPT_TIME_LENGTH 4
51 #define OPT_TYPE_FIELD_LENGTH 1
52 #define OPT_MAC_ADDR_LENGTH 6
53 #define MAGIC_COOKIE_LENGTH 4
54 #define OPT_BROADCAST_FLAG_ENABLE 0
55 
56 #define OFFER_MIN_INTERVAL_TIME 5
57 
58 #define PENDING_DEFAULT_TIMEOUT 1200
59 #define PENDING_DEFAULT_INTERVAL 1
60 #define PENDING_INTERVAL_CHECKING_ENABLE 1
61 #define DHCP_MAGIC_COOKIE 0x63825363
62 #define RECV_BUFFER_SIZE 2048
63 #define ALLOW_NOBINDING_REQUEST 1
64 #define REUSE_ADDRESS_ENABLE 1
65 #define WAIT_STOPED_TIME 5
66 
67 const uint8_t MAGIC_COOKIE_DATA[MAGIC_COOKIE_LENGTH] = {0x63, 0x82, 0x53, 0x63};  // Vendor Information "Magic Cookie"
68 
69 enum AssignedNumbers {
70     ETHERNET = 1,               // Ethernet (10Mb)
71     EXPERIMENTAL_ETHERNET,      // Experimental Ethernet (3Mb)
72     AMATEUR_RADIO_AX_25,        // Amateur Radio AX.25
73     PROTEON_PRONET_TOKEN_RING,  // Proteon ProNET Token Ring
74     CHAOS,
75     IEEE802_NETWORKS,
76     ARCNET,
77     HYPERCHANNEL,
78     LANSTAR
79 };
80 
81 struct ServerContext {
82     int broadCastFlagEnable;
83     DhcpAddressPool addressPool;
84     DhcpServerCallback callback;
85     DhcpConfig config;
86     int serverFd;
87     int looperState;
88     int initialized;
89 };
90 
91 enum LooperState {
92     LS_IDLE = 0,
93     LS_STARING,
94     LS_RUNNING,
95     LS_RELOADNG,
96     LS_STOPING,
97     LS_STOPED
98 };
99 typedef struct sockaddr_in sockaddr_in;
100 int FillReply(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply);
101 static int OnReceivedDiscover(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply);
102 static int OnReceivedRequest(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply);
103 static int OnReceivedDecline(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply);
104 static int OnReceivedRelease(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply);
105 static int OnReceivedInform(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply);
106 static int SendDhcpOffer(PDhcpServerContext ctx, PDhcpMsgInfo reply);
107 static int SendDhcpAck(PDhcpServerContext ctx, PDhcpMsgInfo reply);
108 static int SendDhcpNak(PDhcpServerContext ctx, PDhcpMsgInfo reply);
109 static int ParseMessageOptions(PDhcpMsgInfo msg);
110 
111 static int ParseReplyOptions(PDhcpMsgInfo reply);
112 struct sockaddr_in *BroadcastAddrIn(void);
113 
GetServerInstance(const DhcpServerContext * ctx)114 static struct ServerContext *GetServerInstance(const DhcpServerContext *ctx)
115 {
116     if (!ctx || !ctx->instance) {
117         return NULL;
118     }
119     return (struct ServerContext *)ctx->instance;
120 }
121 
HasFixSocket(int fd)122 int HasFixSocket(int fd)
123 {
124     int flags;
125     if ((flags = fcntl(fd, F_GETFL)) == -1 || fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
126         return DHCP_FALSE;
127     }
128     return DHCP_TRUE;
129 }
130 
131 typedef struct ifreq ifreq;
132 typedef struct sockaddr sockaddr;
133 
BindNetInterface(int fd,const char * ifname)134 int BindNetInterface(int fd, const char *ifname)
135 {
136     if (!fd || !ifname) {
137         return RET_FAILED;
138     }
139     ifreq iface;
140     if (memset_s(&iface, sizeof(iface), 0, sizeof(iface)) != EOK) {
141         return RET_FAILED;
142     }
143     ssize_t ifnameSize = strlen(ifname);
144     if (strncpy_s(iface.ifr_ifrn.ifrn_name, sizeof(iface.ifr_ifrn.ifrn_name), ifname, ifnameSize) != EOK) {
145         return RET_FAILED;
146     };
147     if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, (char *)&iface, sizeof(iface)) == -1) {
148         LOGE("failed to bind network device interface[%s].", ifname);
149         return RET_FAILED;
150     }
151     return RET_SUCCESS;
152 }
153 
InitServer(const char * ifname)154 int InitServer(const char *ifname)
155 {
156     sockaddr_in srvAddrIn = {0};
157     int optval = 1;
158     int optrval = 0;
159     srvAddrIn.sin_family = AF_INET;
160     srvAddrIn.sin_port = htons(DHCP_SERVER_PORT);
161     srvAddrIn.sin_addr.s_addr = INADDR_ANY;
162     int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
163     if (fd == -1) {
164         LOGE("failed to create server socket!");
165         return -1;
166     }
167     if (!HasFixSocket(fd)) {
168         LOGD("failed to fcntl O_NONBLOCK flag!");
169     }
170     if (BindNetInterface(fd, ifname) != RET_SUCCESS) {
171         close(fd);
172         return -1;
173     }
174     socklen_t optlen = sizeof(optrval);
175     if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&optrval, &optlen) == -1) {
176         LOGD("failed to receive buffer size.");
177     } else {
178         LOGD("receive buffer size is %d", optrval);
179     }
180     if (REUSE_ADDRESS_ENABLE && setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(optval)) == -1) {
181         LOGW("failed to setsockopt 'SO_REUSEADDR' for server socket!");
182     }
183     if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval)) == -1) {
184         LOGE("failed to setsockopt 'SO_BROADCAST' for server socket!");
185         close(fd);
186         return -1;
187     }
188     if (bind(fd, (sockaddr *)&srvAddrIn, sizeof(sockaddr)) == -1) {
189         LOGE("failed to bind server!");
190         close(fd);
191         return -1;
192     }
193     return fd;
194 }
195 
BroadcastAddrIn(void)196 struct sockaddr_in *BroadcastAddrIn(void)
197 {
198     static struct sockaddr_in broadcastAddrIn = {0};
199     if (broadcastAddrIn.sin_port == 0) {
200         broadcastAddrIn.sin_port = htons(DHCP_CLIENT_PORT);
201         broadcastAddrIn.sin_family = AF_INET;
202         broadcastAddrIn.sin_addr.s_addr = INADDR_BROADCAST;
203     }
204     return &broadcastAddrIn;
205 }
206 
SourceAddrIn(void)207 struct sockaddr_in *SourceAddrIn(void)
208 {
209     static struct sockaddr_in sourceAddrIn = {0};
210     sourceAddrIn.sin_port = htons(DHCP_CLIENT_PORT);
211     sourceAddrIn.sin_family = AF_INET;
212     sourceAddrIn.sin_addr.s_addr = INADDR_ANY;
213     return &sourceAddrIn;
214 }
215 
ResetSourceAddr(void)216 struct sockaddr_in *ResetSourceAddr(void)
217 {
218     struct sockaddr_in *srcAddr = SourceAddrIn();
219     srcAddr->sin_port = htons(DHCP_CLIENT_PORT);
220     srcAddr->sin_family = AF_INET;
221     srcAddr->sin_addr.s_addr = INADDR_ANY;
222     return srcAddr;
223 }
224 
SourceIpAddress(void)225 uint32_t SourceIpAddress(void)
226 {
227     uint32_t srcIp = SourceAddrIn()->sin_addr.s_addr;
228     return srcIp;
229 }
DestinationAddrIn(void)230 struct sockaddr_in *DestinationAddrIn(void)
231 {
232     static struct sockaddr_in destAddrIn = {0};
233     if (destAddrIn.sin_port == 0) {
234         destAddrIn.sin_port = htons(DHCP_CLIENT_PORT);
235         destAddrIn.sin_family = AF_INET;
236     }
237     return &destAddrIn;
238 }
239 
DestinationAddr(uint32_t ipAddress)240 struct sockaddr_in *DestinationAddr(uint32_t ipAddress)
241 {
242     struct sockaddr_in *destAddr = DestinationAddrIn();
243     destAddr->sin_addr.s_addr = htonl(ipAddress);
244     return destAddr;
245 }
246 
ReceiveDhcpMessage(int sock,PDhcpMsgInfo msgInfo)247 int ReceiveDhcpMessage(int sock, PDhcpMsgInfo msgInfo)
248 {
249     static uint8_t recvBuffer[RECV_BUFFER_SIZE] = {0};
250     struct timeval tmt;
251     fd_set recvFd;
252     FD_ZERO(&recvFd);
253     FD_SET(sock, &recvFd);
254     time_t seconds = DHCP_SEL_WAIT_TIMEOUTS;
255     tmt.tv_sec = seconds;
256     tmt.tv_usec = 0;
257     int ret = select(sock + 1, &recvFd, NULL, NULL, &tmt);
258     if (ret < 0) {
259         LOGE("select error, %d", errno);
260         return ERR_SELECT;
261     }
262     if (ret == 0) {
263         LOGE("select time out.");
264         return RET_SELECT_TIME_OUT;
265     }
266     if (!FD_ISSET(sock, &recvFd)) {
267         LOGE("failed to select isset.");
268         return RET_ERROR;
269     }
270     socklen_t ssize = sizeof(sockaddr_in);
271     struct sockaddr_in *srcAddrIn = ResetSourceAddr();
272     srcAddrIn->sin_addr.s_addr = INADDR_ANY;
273     int rsize = recvfrom(sock, recvBuffer, RECV_BUFFER_SIZE, 0, (struct sockaddr *)srcAddrIn, (socklen_t *)&ssize);
274     if (!rsize) {
275         LOGE("receive error, %d", errno);
276         return RET_FAILED;
277     }
278     if (rsize > (int)sizeof(DhcpMessage) || rsize < DHCP_MSG_HEADER_SIZE) {
279         LOGW("message length error, received %d bytes.", rsize);
280         return RET_FAILED;
281     }
282     msgInfo->length = rsize;
283     if (memcpy_s(&msgInfo->packet, sizeof(DhcpMessage), recvBuffer, rsize) != EOK) {
284         return RET_FAILED;
285     }
286     if (msgInfo->packet.op != BOOTREQUEST) {
287         LOGW("dhcp message type error!");
288         return RET_FAILED;
289     }
290     if (msgInfo->packet.hlen > DHCP_HWADDR_LENGTH) {
291         LOGW("hlen error!");
292         return RET_FAILED;
293     }
294     if (IsEmptyHWAddr(msgInfo->packet.chaddr)) {
295         LOGW("client hardware address error!");
296         return RET_FAILED;
297     }
298     if (IsReserved(msgInfo->packet.chaddr)) {
299         LOGD("ignore client, %s", ParseLogMac(msgInfo->packet.chaddr));
300         return RET_FAILED;
301     }
302     return RET_SUCCESS;
303 }
304 
InitReply(PDhcpServerContext ctx,PDhcpMsgInfo received,PDhcpMsgInfo reply)305 void InitReply(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply)
306 {
307     if (!reply) {
308         LOGE("reply message pointer is null!");
309         return;
310     }
311     reply->packet.op = BOOTREPLY;
312     reply->packet.htype = ETHERNET;
313     reply->packet.hlen = OPT_MAC_ADDR_LENGTH;
314     reply->packet.secs = 0;
315     reply->packet.ciaddr = 0;
316     if (memset_s(reply->packet.sname, sizeof(reply->packet.sname), '\0', sizeof(reply->packet.sname)) != EOK) {
317         LOGE("failed to reset message packet[sname]!");
318         return;
319     };
320     if (memset_s(reply->packet.file, sizeof(reply->packet.file), '\0', sizeof(reply->packet.file)) != EOK) {
321         LOGE("failed to reset message packet[file]!");
322         return;
323     }
324 
325     if (FillReply(ctx, received, reply) != RET_SUCCESS) {
326         LOGW("failed to fill reply message.");
327     }
328 }
329 
OnUpdateServerConfig(PDhcpServerContext ctx)330 void OnUpdateServerConfig(PDhcpServerContext ctx)
331 {
332     LOGD("OnUpdateServerConfig ...");
333     ServerContext *srvIns = GetServerInstance(ctx);
334     if (!srvIns) {
335         LOGE("dhcp server context pointer is null.");
336         return;
337     }
338     if (srvIns->callback) {
339         srvIns->callback(ST_RELOADNG, 0, ctx->ifname);
340     }
341 }
342 
OnServerStoping(PDhcpServerContext ctx)343 static void OnServerStoping(PDhcpServerContext ctx)
344 {
345     LOGD("server stopping ...");
346     ServerContext *srvIns = GetServerInstance(ctx);
347     if (!srvIns) {
348         LOGE("dhcp server context pointer is null.");
349         return;
350     }
351     if (srvIns->callback) {
352         srvIns->callback(ST_STOPING, 0, ctx->ifname);
353     }
354 }
355 
OnServerStoped(PDhcpServerContext ctx,int code)356 void OnServerStoped(PDhcpServerContext ctx, int code)
357 {
358     LOGD("OnServerStoped.");
359     ServerContext *srvIns = GetServerInstance(ctx);
360     if (!srvIns) {
361         LOGE("dhcp server context pointer is null.");
362         return;
363     }
364     if (srvIns->callback) {
365         srvIns->callback(ST_STOPED, code, ctx->ifname);
366     }
367 }
368 
SendDhcpReply(PDhcpServerContext ctx,int replyType,PDhcpMsgInfo reply)369 int SendDhcpReply(PDhcpServerContext ctx, int replyType, PDhcpMsgInfo reply)
370 {
371     if (!reply) {
372         LOGE("reply message pointer is null.");
373         return RET_FAILED;
374     }
375     int sendRet = -1;
376     ServerContext *srvIns = GetServerInstance(ctx);
377     if (!srvIns) {
378         LOGE("dhcp server context pointer is null.");
379         return RET_FAILED;
380     }
381     switch (replyType) {
382         case REPLY_OFFER:
383             LOGD("<== send reply dhcp offer.");
384             sendRet = SendDhcpOffer(ctx, reply);
385             break;
386         case REPLY_ACK:
387             LOGD("<== send reply dhcp ack.");
388             sendRet = SendDhcpAck(ctx, reply);
389             break;
390         case REPLY_NAK:
391             LOGD("<== send reply dhcp nak.");
392             sendRet = SendDhcpNak(ctx, reply);
393             break;
394         default:
395             break;
396     }
397     if (replyType && sendRet != RET_SUCCESS) {
398         return RET_FAILED;
399     }
400     return  RET_SUCCESS;
401 }
402 
MessageProcess(PDhcpServerContext ctx,PDhcpMsgInfo received,PDhcpMsgInfo reply)403 static int MessageProcess(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply)
404 {
405     int replyType = REPLY_NONE;
406     if (!received) {
407         return replyType;
408     }
409     PDhcpOption opt = GetOption(&received->options, DHCP_MESSAGE_TYPE_OPTION);
410     if (!opt) {
411         LOGE("error dhcp message, missing required message type option.");
412         return replyType;
413     }
414     uint8_t messageType = opt->data[0];
415     switch (messageType) {
416         case DHCPDISCOVER: {
417             LOGD("==> Received DHCPDISCOVER message.");
418             replyType = OnReceivedDiscover(ctx, received, reply);
419             break;
420         }
421         case DHCPREQUEST: {
422             LOGD("==> Received DHCPREQUEST message.");
423             replyType = OnReceivedRequest(ctx, received, reply);
424             break;
425         }
426         case DHCPDECLINE: {
427             LOGD("==> Received DHCPDECLINE message.");
428             replyType = OnReceivedDecline(ctx, received, reply);
429             break;
430         }
431         case DHCPRELEASE: {
432             LOGD("==> Received DHCPRELEASE message.");
433             replyType = OnReceivedRelease(ctx, received, reply);
434             break;
435         }
436         case DHCPINFORM: {
437             LOGD("==> Received DHCPINFORM message.");
438             replyType = OnReceivedInform(ctx, received, reply);
439             break;
440         }
441         default:
442             break;
443     }
444     return replyType;
445 }
446 
SaveLease(PDhcpServerContext ctx)447 int SaveLease(PDhcpServerContext ctx)
448 {
449     ServerContext *srvIns = GetServerInstance(ctx);
450     if (!srvIns) {
451         LOGE("dhcp server context pointer is null.");
452         return RET_FAILED;
453     }
454     int saveRet = SaveBindingRecoders(&srvIns->addressPool, 1);
455     if (saveRet == RET_FAILED) {
456         LOGD("failed to save lease recoders. total: %zu", srvIns->addressPool.leaseTable.size);
457     } else if (saveRet == RET_SUCCESS) {
458         LOGD("lease recoders saved.");
459     }
460     return saveRet;
461 }
462 
OnLooperStateChanged(PDhcpServerContext ctx)463 static int OnLooperStateChanged(PDhcpServerContext ctx)
464 {
465     ServerContext *srvIns = GetServerInstance(ctx);
466     if (!srvIns) {
467         LOGE("dhcp server context pointer is null.");
468         return RET_FAILED;
469     }
470 
471     if (srvIns->looperState == LS_RELOADNG) {
472         OnUpdateServerConfig(ctx);
473         srvIns->looperState = LS_RUNNING;
474     } else if (srvIns->looperState == LS_STOPING) {
475         OnServerStoping(ctx);
476         return RET_BREAK;
477     }
478     return RET_SUCCESS;
479 }
480 
ContinueReceive(PDhcpMsgInfo from,int recvRet)481 static int ContinueReceive(PDhcpMsgInfo from, int recvRet)
482 {
483     if (!from) {
484         return DHCP_TRUE;
485     }
486     if (recvRet != RET_SUCCESS) {
487         return DHCP_TRUE;
488     }
489     size_t recLength = from->length;
490     LOGD("received, length:%zu", recLength);
491     if (ParseMessageOptions(from) != 0) {
492         LOGE("invalid dhcp message.");
493         return DHCP_TRUE;
494     }
495     if (!GetOption(&from->options, DHCP_MESSAGE_TYPE_OPTION)) {
496         LOGW("can't found 'message type' option.");
497         return DHCP_TRUE;
498     }
499     return DHCP_FALSE;
500 }
501 
BeginLooper(PDhcpServerContext ctx)502 static int BeginLooper(PDhcpServerContext ctx)
503 {
504     DhcpMsgInfo from = { 0 };
505     DhcpMsgInfo reply = { 0 };
506     ServerContext *srvIns = GetServerInstance(ctx);
507     if (!srvIns) {
508         LOGE("dhcp server context pointer is null.");
509         return RET_FAILED;
510     }
511     ctx->instance->serverFd = InitServer(ctx->ifname);
512     if (ctx->instance->serverFd < 0) {
513         LOGE("failed to initialize server socket.");
514         return RET_FAILED;
515     }
516     InitOptionList(&from.options);
517     InitOptionList(&reply.options);
518     srvIns->looperState = LS_RUNNING;
519     while (srvIns->looperState) {
520         if (OnLooperStateChanged(ctx) != RET_SUCCESS) {
521             break;
522         }
523         ClearOptions(&from.options);
524         ClearOptions(&reply.options);
525         int recvRet = ReceiveDhcpMessage(ctx->instance->serverFd, &from);
526         if (recvRet == RET_ERROR || recvRet == ERR_SELECT) {
527             continue;
528         }
529         if (ContinueReceive(&from, recvRet)) {
530             continue;
531         }
532         InitReply(ctx, &from, &reply);
533         int replyType = MessageProcess(ctx, &from, &reply);
534         if (replyType && SendDhcpReply(ctx, replyType, &reply) != RET_SUCCESS) {
535             LOGE("failed to send reply message.");
536         }
537         if (replyType == REPLY_ACK || replyType == REPLY_OFFER) {
538             int saveRet = SaveBindingRecoders(&srvIns->addressPool, 1);
539             if (saveRet != RET_SUCCESS && saveRet != RET_WAIT_SAVE) {
540                 LOGW("failed to save lease recoders.");
541             }
542         }
543     }
544     FreeOptionList(&from.options);
545     FreeOptionList(&reply.options);
546     LOGD("dhcp server message looper stopped.");
547     close(ctx->instance->serverFd);
548     ctx->instance->serverFd = -1;
549     srvIns->looperState = LS_STOPED;
550     return 0;
551 }
552 
CheckAddressRange(DhcpAddressPool * pool)553 static int CheckAddressRange(DhcpAddressPool *pool)
554 {
555     uint32_t serverNetwork = NetworkAddress(pool->serverId, pool->netmask);
556     uint32_t firstNetwork = NetworkAddress(pool->addressRange.beginAddress, pool->netmask);
557     uint32_t secondNetwork = NetworkAddress(pool->addressRange.endAddress, pool->netmask);
558     if (!serverNetwork || !firstNetwork || !secondNetwork) {
559         LOGE("network config error.");
560         return DHCP_FALSE;
561     }
562     if (serverNetwork != firstNetwork || serverNetwork != secondNetwork) {
563         LOGE("server network and address pool network belong to different networks.");
564         return DHCP_FALSE;
565     }
566     return DHCP_TRUE;
567 }
568 
InitBindingRecoders(DhcpAddressPool * pool)569 void InitBindingRecoders(DhcpAddressPool *pool)
570 {
571     if (!pool) {
572         LOGE("address pool pointer is null.");
573         return;
574     }
575     HashTable *table = &pool->leaseTable;
576     if (!Initialized(table)) {
577         LOGE("pool does not init.");
578         return;
579     }
580     uint32_t realLeaseTotal = 0;
581     for (size_t current = 0; current < table->capacity; ++current) {
582         HashNode *node = table->nodes[current];
583         int invalidBindig;
584         while (node) {
585             HashNode *next = node->next;
586             AddressBinding *binding = (AddressBinding*)node->value;
587             if (binding && !IsEmptyHWAddr(binding->chaddr) && binding->ipAddress) {
588                 AddBinding(binding);
589                 realLeaseTotal++;
590                 invalidBindig = 0;
591             } else {
592                 LOGE("bad binding recoder.");
593                 invalidBindig = 1;
594             }
595             if (!invalidBindig && binding && pool->distribution < binding->ipAddress) {
596                 pool->distribution = binding->ipAddress;
597             }
598             node = next;
599         }
600     }
601     LOGD("lease recoder total: %u", realLeaseTotal);
602 }
603 
InitLeaseFile(DhcpAddressPool * pool)604 void InitLeaseFile(DhcpAddressPool *pool)
605 {
606     const char *leasePath  = GetFilePath(DHCPD_LEASE_FILE);
607     if (!leasePath || strlen(leasePath) == 0) {
608         LOGE("failed to get lease file path.");
609         return;
610     }
611     if (access(leasePath, 0) != 0) {
612         LOGD("lease file path does not exist.");
613         if (!CreatePath(leasePath)) {
614             LOGE("failed to create lease file directory.");
615             return;
616         } else {
617             LOGD("lease file directory created.");
618         }
619     }
620     if (LoadBindingRecoders(pool) != RET_SUCCESS) {
621         LOGW("failed to load lease recoders.");
622     }
623     InitBindingRecoders(pool);
624 }
625 
ExitProcess(void)626 static void ExitProcess(void)
627 {
628     LOGD("dhcp server stopped.");
629 }
630 
StartDhcpServer(PDhcpServerContext ctx)631 int StartDhcpServer(PDhcpServerContext ctx)
632 {
633     LOGD("dhcp server starting ...");
634     if (!ctx) {
635         LOGE("server context pointer is null.");
636         return RET_FAILED;
637     }
638     if (strlen(ctx->ifname) == 0) {
639         LOGE("context interface is null or empty.");
640         return RET_FAILED;
641     }
642     ServerContext *srvIns = GetServerInstance(ctx);
643     if (!srvIns) {
644         LOGE("dhcp server context instance pointer is null.");
645         return RET_FAILED;
646     }
647     if (atexit(ExitProcess) != 0) {
648         LOGW("failed to regiester exit process function.");
649     }
650     if (!srvIns->initialized) {
651         LOGE("dhcp server no initialized.");
652         return RET_FAILED;
653     }
654     LOGD("bind interface: %s", ctx->ifname);
655     LOGI("begin dhcp message looper");
656     if (srvIns->callback) {
657         srvIns->callback(ST_STARTING, 1, ctx->ifname);
658     }
659     int ret = BeginLooper(ctx);
660     if (ret != RET_SUCCESS) {
661         LOGD("failed to start dhcp server.");
662         OnServerStoped(ctx, ret);
663         return RET_FAILED;
664     }
665     OnServerStoped(ctx, ret);
666     return RET_SUCCESS;
667 }
668 
StopDhcpServer(PDhcpServerContext ctx)669 int StopDhcpServer(PDhcpServerContext ctx)
670 {
671     ServerContext *srvIns = GetServerInstance(ctx);
672     if (!srvIns) {
673         return RET_FAILED;
674     }
675     srvIns->looperState = LS_STOPING;
676     return RET_SUCCESS;
677 }
678 
GetServerStatus(PDhcpServerContext ctx)679 int GetServerStatus(PDhcpServerContext ctx)
680 {
681     ServerContext *srvIns = GetServerInstance(ctx);
682     if (!srvIns) {
683         LOGE("dhcp server context pointer is null.");
684         return -1;
685     }
686     return srvIns->looperState;
687 }
688 
FillReply(PDhcpServerContext ctx,PDhcpMsgInfo received,PDhcpMsgInfo reply)689 int FillReply(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply)
690 {
691     if (!received || !reply) {
692         return RET_ERROR;
693     }
694     ServerContext *srvIns = GetServerInstance(ctx);
695     if (!srvIns) {
696         LOGE("dhcp server context pointer is null.");
697         return RET_FAILED;
698     }
699     if (received->packet.ciaddr && received->packet.ciaddr != INADDR_BROADCAST) {
700         reply->packet.ciaddr = received->packet.ciaddr;
701     }
702     if (received->packet.flags) {
703         reply->packet.flags = received->packet.flags;
704     }
705     if (received->packet.xid) {
706         reply->packet.xid = received->packet.xid;
707     }
708     if (received->packet.siaddr && received->packet.siaddr != INADDR_BROADCAST) {
709         reply->packet.siaddr = received->packet.siaddr;
710     } else {
711         reply->packet.siaddr = srvIns->addressPool.serverId;
712     }
713     if (received->packet.giaddr && received->packet.giaddr != INADDR_BROADCAST) {
714         reply->packet.giaddr = received->packet.giaddr;
715     } else {
716         if (srvIns->addressPool.gateway) {
717             reply->packet.giaddr = srvIns->addressPool.gateway;
718         }
719     }
720     if (received->packet.hlen) {
721         reply->packet.hlen = received->packet.hlen;
722         LOGD("fill reply - chaddr:%s", ParseLogMac(received->packet.chaddr));
723         if (memset_s(reply->packet.chaddr, sizeof(reply->packet.chaddr), 0, sizeof(reply->packet.chaddr)) != EOK) {
724             LOGE("failed to reset message packet[chaddr]!");
725             return RET_ERROR;
726         }
727         if (memcpy_s(reply->packet.chaddr, sizeof(reply->packet.chaddr),
728             received->packet.chaddr, sizeof(received->packet.chaddr)) != EOK) {
729             LOGE("failed to copy message packet[chaddr]!");
730             return RET_ERROR;
731         }
732     }
733     if (received->packet.giaddr) {
734         reply->packet.giaddr = received->packet.giaddr;
735     }
736     return 0;
737 }
738 
AppendReplyTimeOptions(PDhcpServerContext ctx,PDhcpOptionList options)739 int AppendReplyTimeOptions(PDhcpServerContext ctx, PDhcpOptionList options)
740 {
741     if (!ctx || !options) {
742         LOGE("server context or options pointer is null.");
743         return RET_FAILED;
744     }
745     ServerContext *srvIns = GetServerInstance(ctx);
746     if (!srvIns) {
747         LOGE("dhcp server context pointer is null.");
748         return RET_FAILED;
749     }
750     uint32_t leaseTime = HostToNetwork(DHCP_LEASE_TIME);
751     if (srvIns->addressPool.leaseTime) {
752         leaseTime = HostToNetwork(srvIns->addressPool.leaseTime);
753     }
754     DhcpOption optLeaseTime = {IP_ADDRESS_LEASE_TIME_OPTION, OPT_TIME_LENGTH, {0}};
755     FillU32Option(&optLeaseTime, leaseTime);
756     PushBackOption(options, &optLeaseTime);
757 
758     uint32_t t1Time = HostToNetwork(DHCP_RENEWAL_TIME);
759     if (srvIns->addressPool.renewalTime) {
760         t1Time = HostToNetwork(srvIns->addressPool.renewalTime);
761     }
762     DhcpOption optRenewTime = {RENEWAL_TIME_VALUE_OPTION, OPT_TIME_LENGTH, {0}};
763     FillU32Option(&optLeaseTime, t1Time);
764     PushBackOption(options, &optRenewTime);
765 
766     uint32_t t2Time = HostToNetwork(DHCP_REBINDING_TIME);
767     if (srvIns->addressPool.rebindingTime) {
768         t2Time = HostToNetwork(srvIns->addressPool.rebindingTime);
769     }
770     DhcpOption optRebindTime = {REBINDING_TIME_VALUE_OPTION, OPT_TIME_LENGTH, {0}};
771     FillU32Option(&optRebindTime, t2Time);
772     PushBackOption(options, &optRebindTime);
773 
774     return RET_SUCCESS;
775 }
776 
Repending(DhcpAddressPool * pool,AddressBinding * binding)777 static int Repending(DhcpAddressPool *pool, AddressBinding *binding)
778 {
779     if (!pool) {
780         return REPLY_NONE;
781     }
782     uint32_t bindingIp = binding->ipAddress;
783     LOGD(" binding found, bindIp:%s", ParseStrIp(bindingIp));
784     binding->pendingInterval = NextPendingInterval(binding->pendingInterval);
785     uint64_t tms = Tmspsec() - binding->pendingTime;
786     if (tms < binding->pendingInterval) {
787         binding->pendingTime = Tmspsec();
788         LOGW("message interval is too short, ignore the message.");
789         return REPLY_NONE;
790     }
791     binding->pendingTime = Tmspsec();
792     binding->pendingInterval = 0;
793     binding->bindingStatus = BIND_PENDING;
794     uint32_t srcIp = SourceIpAddress();
795     if (srcIp && srcIp != INADDR_BROADCAST && bindingIp != INADDR_BROADCAST && srcIp != bindingIp) {
796         LOGW("source ip address and bound ip address inconsistency.");
797         return REPLY_NAK;
798     }
799     if (srcIp && srcIp == bindingIp) {
800         if (!ContainsKey(&pool->leaseTable, (uintptr_t)&srcIp)) {
801             LOGD("can't find lease information.");
802             if (Insert(&pool->leaseTable, (uintptr_t)&srcIp, (uintptr_t)binding) != HASH_INSERTED) {
803                 LOGE("failed to insert lease information.");
804             }
805         } else {
806             if (Insert(&pool->leaseTable, (uintptr_t)&srcIp, (uintptr_t)binding) != HASH_UPDATED) {
807                 LOGE("failed to update lease information.");
808             }
809         }
810     }
811     return REPLY_OFFER;
812 }
813 
Rebinding(DhcpAddressPool * pool,AddressBinding * binding)814 static int Rebinding(DhcpAddressPool *pool, AddressBinding *binding)
815 {
816     uint64_t pendingTime = binding->pendingTime;
817     int replyType = Repending(pool, binding);
818     binding->bindingStatus = BIND_ASSOCIATED;
819     if (!binding->leaseTime) {
820         binding->leaseTime = pool->leaseTime;
821     }
822     binding->bindingTime = Tmspsec();
823     binding->expireIn = binding->bindingTime + binding->leaseTime;
824     binding->pendingTime = pendingTime;
825     if (replyType == REPLY_OFFER) {
826         replyType = REPLY_ACK;
827     }
828     return replyType;
829 }
830 
AddAddressOption(PDhcpMsgInfo reply,uint8_t code,int32_t address)831 static void AddAddressOption(PDhcpMsgInfo reply, uint8_t code, int32_t address)
832 {
833     if (!reply) {
834         return;
835     }
836     DhcpOption optAddress = {0, 0, {0}};
837     optAddress.code = code;
838     if (AppendAddressOption(&optAddress, address) != RET_SUCCESS) {
839         LOGE("failed to append address option.");
840         return;
841     };
842     PushBackOption(&reply->options, &optAddress);
843 }
844 
AddReplyServerIdOption(PDhcpOptionList options,uint32_t serverId)845 int AddReplyServerIdOption(PDhcpOptionList options, uint32_t serverId)
846 {
847     if (!options) {
848         LOGE("option list pointer is null.");
849         return RET_FAILED;
850     }
851     if (!serverId || serverId == INADDR_BROADCAST) {
852         LOGE("servier id error.");
853         return RET_FAILED;
854     }
855     DhcpOption optSrvId = {SERVER_IDENTIFIER_OPTION, 0, {0}};
856     if (AppendAddressOption(&optSrvId, serverId) != RET_SUCCESS) {
857         LOGE("failed to append server id option.");
858         return RET_FAILED;
859     }
860     if (GetOption(options, SERVER_IDENTIFIER_OPTION)) {
861         LOGD("server identifier option exists.");
862         return RET_SUCCESS;
863     }
864     PushBackOption(options, &optSrvId);
865     return RET_SUCCESS;
866 }
867 
AddReplyMessageTypeOption(PDhcpMsgInfo reply,uint8_t replyMessageType)868 static void AddReplyMessageTypeOption(PDhcpMsgInfo reply, uint8_t replyMessageType)
869 {
870     if (!reply) {
871         return;
872     }
873     DhcpOption optMsgType = {DHCP_MESSAGE_TYPE_OPTION, OPT_MESSAGE_TYPE_LEGTH, {replyMessageType, 0}};
874     PushBackOption(&reply->options, &optMsgType);
875 }
876 
877 
GetBinding(DhcpAddressPool * pool,PDhcpMsgInfo received)878 AddressBinding *GetBinding(DhcpAddressPool *pool, PDhcpMsgInfo received)
879 {
880     if (!pool) {
881         return NULL;
882     }
883     if (!received) {
884         return NULL;
885     }
886     AddressBinding *binding = pool->binding(received->packet.chaddr, &received->options);
887     if (!binding) {
888         binding = pool->newBinding(received->packet.chaddr, &received->options);
889         if (binding == NULL) {
890             LOGE("new binding is null");
891             return NULL;
892         }
893         if (pool->leaseTime) {
894             binding->leaseTime = pool->leaseTime;
895         }
896         binding->ipAddress = pool->distribue(pool, received->packet.chaddr);
897         LOGD("new binding ip");
898     } else {
899         LOGD("rebinding ip");
900     }
901     return binding;
902 }
903 
OnReceivedDiscover(PDhcpServerContext ctx,PDhcpMsgInfo received,PDhcpMsgInfo reply)904 static int OnReceivedDiscover(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply)
905 {
906     if (!received || !reply) {
907         return REPLY_NONE;
908     }
909     LOGI("received 'Discover' message from: %s", ParseLogMac(received->packet.chaddr));
910     ServerContext *srvIns = GetServerInstance(ctx);
911     if (!srvIns) {
912         return REPLY_NONE;
913     }
914     uint32_t reqIp = 0;
915     PDhcpOption optReqIp = GetOption(&received->options, REQUESTED_IP_ADDRESS_OPTION);
916     if (optReqIp) {
917         reqIp = ParseIp(optReqIp->data);
918         if (reqIp) {
919             LOGD(" request ip: %s", ParseStrIp(reqIp));
920         }
921     }
922     uint32_t srcIp = SourceIpAddress();
923     if (!srvIns->broadCastFlagEnable) {
924         if (srcIp) {
925             LOGD(" client repending:%s", ParseStrIp(srcIp));
926         } else {
927             srcIp = INADDR_BROADCAST;
928         }
929         DestinationAddr(srcIp);
930     }
931     AddressBinding *binding = GetBinding(&srvIns->addressPool, received);
932     if (!binding) {
933         return REPLY_NONE;
934     }
935     if (!binding->ipAddress) {
936         LOGE("no ip address available.");
937         return REPLY_NONE;
938     }
939     if (reqIp != 0 && reqIp != binding->ipAddress) {
940         LOGE("error request message.");
941         return REPLY_NAK;
942     }
943     AddressBinding *lease = GetLease(&srvIns->addressPool, binding->ipAddress);
944     if (!lease) {
945         LOGD("add lease recoder.");
946         AddLease(&srvIns->addressPool, binding);
947         lease = GetLease(&srvIns->addressPool, binding->ipAddress);
948     }
949     if (!lease) {
950         return REPLY_NONE;
951     }
952     AddReplyMessageTypeOption(reply, DHCPOFFER);
953     reply->packet.yiaddr = lease->ipAddress;
954     return REPLY_OFFER;
955 }
956 
957 
GetRequestIpAddress(PDhcpMsgInfo received)958 static uint32_t GetRequestIpAddress(PDhcpMsgInfo received)
959 {
960     uint32_t reqIp = 0;
961     if (!received) {
962         return reqIp;
963     }
964     PDhcpOption optReqIp = GetOption(&received->options, REQUESTED_IP_ADDRESS_OPTION);
965     if (optReqIp) {
966         reqIp = ParseIp(optReqIp->data);
967     }
968     return reqIp;
969 }
970 
GetYourIpAddress(PDhcpMsgInfo received,uint32_t * yourIpAddr,DhcpAddressPool * pool)971 static int GetYourIpAddress(PDhcpMsgInfo received, uint32_t *yourIpAddr, DhcpAddressPool *pool)
972 {
973     uint32_t cliIp = received->packet.ciaddr;
974     uint32_t srcIp = SourceIpAddress();
975     uint32_t reqIp = GetRequestIpAddress(received);
976     if (cliIp && srcIp && cliIp != srcIp) {
977         LOGE("error dhcp request message, missing required request option.");
978         return RET_FAILED;
979     }
980     if (reqIp && srcIp && reqIp != srcIp) {
981         LOGE("error dhcp request message, request ip error.");
982         return RET_FAILED;
983     }
984     if (cliIp && reqIp && cliIp != reqIp) {
985         LOGE("error dhcp request message, client ip error.");
986         return RET_FAILED;
987     }
988 
989     if (srcIp && srcIp != INADDR_BROADCAST) {
990         *yourIpAddr = srcIp;
991     } else if (cliIp && cliIp != INADDR_BROADCAST) {
992         *yourIpAddr = cliIp;
993     } else if (reqIp && reqIp != INADDR_BROADCAST) {
994         *yourIpAddr = reqIp;
995     }
996 
997     if ((ntohl(*yourIpAddr) < ntohl(pool->addressRange.beginAddress))
998             || (ntohl(*yourIpAddr) > ntohl(pool->addressRange.endAddress))) {
999         return RET_FAILED;
1000     }
1001 
1002     if (srcIp && srcIp != INADDR_BROADCAST) {
1003         DestinationAddr(srcIp);
1004     } else if (srcIp == INADDR_ANY) {
1005         DestinationAddr(INADDR_BROADCAST);
1006     }
1007     return RET_SUCCESS;
1008 }
1009 
NotBindingRequest(DhcpAddressPool * pool,PDhcpMsgInfo received,PDhcpMsgInfo reply)1010 static int NotBindingRequest(DhcpAddressPool *pool, PDhcpMsgInfo received, PDhcpMsgInfo reply)
1011 {
1012     uint32_t yourIpAddr = 0;
1013     if (GetYourIpAddress(received, &yourIpAddr, pool) != RET_SUCCESS) {
1014         return REPLY_NONE;
1015     }
1016     AddressBinding *lease = GetLease(pool, yourIpAddr);
1017     if (!lease) {
1018         if (SourceIpAddress()) {
1019             return REPLY_ACK;
1020         }
1021         return REPLY_NONE;
1022     }
1023     int sameAddr = AddrEquels(lease->chaddr, received->packet.chaddr, MAC_ADDR_LENGTH);
1024     if (lease->bindingStatus == BIND_ASSOCIATED && !sameAddr) {
1025         if (!IsExpire(lease)) {
1026             return REPLY_NAK;
1027         }
1028         RemoveLease(pool, lease);
1029     }
1030     AddressBinding *binding = pool->newBinding(received->packet.chaddr, &received->options);
1031     if (binding == NULL) {
1032         LOGE("Not binding request binding is null.");
1033         return REPLY_NONE;
1034     }
1035     binding->ipAddress = yourIpAddr;
1036     if (pool->leaseTime) {
1037         binding->leaseTime = pool->leaseTime;
1038     }
1039     int replyType = Repending(pool, binding);
1040     if (replyType != REPLY_OFFER) {
1041         return replyType;
1042     }
1043     lease = GetLease(pool, yourIpAddr);
1044     if (!lease) {
1045         LOGD("add new lease recoder.");
1046         AddLease(pool, binding);
1047         lease = GetLease(pool, binding->ipAddress);
1048     }
1049     if (!lease) {
1050         LOGD("failed to get lease.");
1051         return REPLY_NONE;
1052     }
1053     lease->bindingStatus = BIND_ASSOCIATED;
1054     lease->bindingTime = Tmspsec();
1055     lease->expireIn = lease->bindingTime + binding->leaseTime;
1056     reply->packet.yiaddr = lease->ipAddress;
1057     return REPLY_ACK;
1058 }
1059 
ValidateRequestMessage(const PDhcpServerContext ctx,const PDhcpMsgInfo received,PDhcpMsgInfo reply,uint32_t * yourIp)1060 static int ValidateRequestMessage(const PDhcpServerContext ctx, const PDhcpMsgInfo received,
1061     PDhcpMsgInfo reply, uint32_t *yourIp)
1062 {
1063     if (!received || !reply) {
1064         return REPLY_NONE;
1065     }
1066     LOGI("received 'Request' message from: %s.", ParseLogMac(received->packet.chaddr));
1067     uint32_t yourIpAddr = INADDR_BROADCAST;
1068     ServerContext *srvIns = GetServerInstance(ctx);
1069     if (!srvIns) {
1070         return RET_FAILED;
1071     }
1072     if (GetYourIpAddress(received, &yourIpAddr, &srvIns->addressPool) != RET_SUCCESS) {
1073         if (yourIpAddr && yourIpAddr != INADDR_BROADCAST) {
1074             AddressBinding *lease = GetLease(&srvIns->addressPool, yourIpAddr);
1075             if (lease) {
1076                 RemoveLease(&srvIns->addressPool, lease);
1077                 LOGD("lease recoder has been removed.");
1078             } else {
1079                 LOGW("can't found lease recoder.");
1080             }
1081             RemoveBinding(received->packet.chaddr);
1082             return REPLY_NAK;
1083         }
1084         return REPLY_NONE;
1085     }
1086     PDhcpOption optReqSrvId = GetOption(&received->options, SERVER_IDENTIFIER_OPTION);
1087     if (optReqSrvId) {
1088         uint32_t reqSrvId = ParseIp(optReqSrvId->data);
1089         LOGD(" reuquest server id is:%s", ParseStrIp(reqSrvId));
1090         if (reqSrvId != srvIns->addressPool.serverId) {
1091             LOGW("other dhcp server process.");
1092             return REPLY_NONE;
1093         }
1094     } else {
1095         LOGW("request message not specified server identifier option.");
1096     }
1097     *yourIp = yourIpAddr;
1098     return REPLY_ACK;
1099 }
1100 
HasNobindgRequest(PDhcpServerContext ctx,PDhcpMsgInfo received,PDhcpMsgInfo reply)1101 static int HasNobindgRequest(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply)
1102 {
1103     if (!received || !reply) {
1104         LOGE("receive or reply message pointer is null.");
1105         return REPLY_NONE;
1106     }
1107     ServerContext *srvIns = GetServerInstance(ctx);
1108     if (!srvIns) {
1109         LOGE("dhcp server context pointer is null.");
1110         return REPLY_NONE;
1111     }
1112     AddressBinding *binding = srvIns->addressPool.binding(received->packet.chaddr, &received->options);
1113     if (!binding && ALLOW_NOBINDING_REQUEST) {
1114         LOGE("client not binding.");
1115         uint32_t srcIp = SourceIpAddress();
1116         uint32_t reqIp = GetRequestIpAddress(received);
1117         LOGD("allow no binding request mode.");
1118         if (reqIp == 0 && srcIp == 0) {
1119             LOGE("error dhcp message.");
1120             return REPLY_NONE;
1121         }
1122         if (!IpInNetwork(reqIp, srvIns->addressPool.serverId, srvIns->addressPool.netmask)) {
1123             LOGE("error request ip.");
1124             return REPLY_NAK;
1125         }
1126         return NotBindingRequest(&srvIns->addressPool, received, reply);
1127     }
1128     return REPLY_NONE;
1129 }
1130 
OnReceivedRequest(PDhcpServerContext ctx,PDhcpMsgInfo received,PDhcpMsgInfo reply)1131 static int OnReceivedRequest(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply)
1132 {
1133     int ret;
1134     uint32_t yourIpAddr;
1135     if ((ret = ValidateRequestMessage(ctx, received, reply, &yourIpAddr)) != REPLY_ACK) {
1136         return ret;
1137     }
1138     ServerContext *srvIns = GetServerInstance(ctx);
1139     if (srvIns == NULL) {
1140         LOGE("OnReceivedRequest, srvIns is null");
1141         return REPLY_NONE;
1142     }
1143     AddressBinding *binding = srvIns->addressPool.binding(received->packet.chaddr, &received->options);
1144     if (binding == NULL) {
1145         LOGE("OnReceivedRequest, binding is null");
1146         return HasNobindgRequest(ctx, received, reply);
1147     }
1148     Rebinding(&srvIns->addressPool, binding);
1149     AddressBinding *lease = GetLease(&srvIns->addressPool, yourIpAddr);
1150     if (lease) {
1151         int sameAddr = AddrEquels(lease->chaddr, received->packet.chaddr, MAC_ADDR_LENGTH);
1152         if (!sameAddr && !IsExpire(lease)) {
1153             LOGW("invalid request ip address.");
1154             return REPLY_NAK;
1155         }
1156         if (!sameAddr && IsExpire(lease)) {
1157             if (memcpy_s(lease->chaddr, DHCP_HWADDR_LENGTH, binding->chaddr, MAC_ADDR_LENGTH) != EOK) {
1158                 LOGW("failed to update lease client address.");
1159             }
1160         }
1161         lease->bindingStatus = BIND_ASSOCIATED;
1162         lease->bindingTime = binding->bindingTime;
1163         lease->expireIn = binding->expireIn;
1164     } else {
1165         LOGW("can not found lease recoder.");
1166     }
1167     uint32_t bindingIp = binding->ipAddress;
1168     if (bindingIp && yourIpAddr != INADDR_BROADCAST && yourIpAddr != bindingIp) {
1169         LOGE("error request ip binding.");
1170         return REPLY_NAK;
1171     }
1172     AddAddressOption(reply, SUBNET_MASK_OPTION, srvIns->addressPool.netmask);
1173     if (srvIns->addressPool.gateway) {
1174         AddAddressOption(reply, ROUTER_OPTION, srvIns->addressPool.gateway);
1175     }
1176     reply->packet.yiaddr = bindingIp;
1177     return REPLY_ACK;
1178 }
1179 
OnReceivedDecline(PDhcpServerContext ctx,PDhcpMsgInfo received,PDhcpMsgInfo reply)1180 static int OnReceivedDecline(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply)
1181 {
1182     if (!received || !reply) {
1183         return REPLY_NONE;
1184     }
1185     ServerContext *srvIns = GetServerInstance(ctx);
1186     if (!srvIns) {
1187         return REPLY_NONE;
1188     }
1189     LOGI("received 'Decline' message from: %s.", ParseLogMac(received->packet.chaddr));
1190     uint32_t reqIp = 0;
1191     PDhcpOption optReqIp = GetOption(&received->options, REQUESTED_IP_ADDRESS_OPTION);
1192     if (optReqIp) {
1193         reqIp = ParseIp(optReqIp->data);
1194     }
1195     if (!reqIp) {
1196         LOGD("invalid request ip address.");
1197         return REPLY_NONE;
1198     }
1199     AddressBinding* binding = srvIns->addressPool.binding(received->packet.chaddr, &received->options);
1200     if (!binding) {
1201         LOGD("client not binding.");
1202         return REPLY_NONE;
1203     }
1204     if (binding->ipAddress != reqIp) {
1205         LOGD("invalid request ip address.");
1206         return REPLY_NONE;
1207     }
1208     if (ContainsKey(&srvIns->addressPool.leaseTable, (uintptr_t)&binding->ipAddress)) {
1209         AddressBinding *lease = GetBindingByIp(&srvIns->addressPool.leaseTable, binding->ipAddress);
1210         if (lease) {
1211             lease->bindingStatus = BIND_MODE_RESERVED;
1212             lease->expireIn = Tmspsec() + lease->leaseTime;
1213         } else {
1214             LOGE("failed to get lease info.");
1215         }
1216     }
1217     RemoveBinding(received->packet.chaddr);
1218     return REPLY_NONE;
1219 }
1220 
OnReceivedRelease(PDhcpServerContext ctx,PDhcpMsgInfo received,PDhcpMsgInfo reply)1221 static int OnReceivedRelease(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply)
1222 {
1223     if (!received || !reply) {
1224         return REPLY_NONE;
1225     }
1226     LOGI("received 'Release' message from: %s", ParseLogMac(received->packet.chaddr));
1227     if (!ctx || !ctx->instance) {
1228         return RET_FAILED;
1229     }
1230     PDhcpOption optReqIp = GetOption(&received->options, REQUESTED_IP_ADDRESS_OPTION);
1231     if (!optReqIp) {
1232         LOGW("missing required request option.");
1233     }
1234     ServerContext *srvIns = GetServerInstance(ctx);
1235     if (!srvIns) {
1236         LOGE("dhcp server context pointer is null.");
1237         return RET_FAILED;
1238     }
1239     AddressBinding *binding = srvIns->addressPool.binding(received->packet.chaddr, &received->options);
1240     if (!binding) {
1241         LOGD("client not binding.");
1242         return REPLY_NONE;
1243     }
1244     uint32_t bindIp = binding->ipAddress;
1245     uint32_t reqIp = 0;
1246     if (optReqIp) {
1247         reqIp = ParseIp(optReqIp->data);
1248     }
1249     uint32_t srcIp = SourceIpAddress();
1250     if (srcIp != 0 && reqIp != 0 && reqIp != srcIp) {
1251         LOGE("error release message, invalid request ip address.");
1252         return REPLY_NONE;
1253     }
1254     if (bindIp != 0 && reqIp != 0 && reqIp != bindIp) {
1255         LOGE("error release message, invalid request ip address.");
1256         return REPLY_NONE;
1257     }
1258     AddressBinding *lease = GetLease(&srvIns->addressPool, bindIp);
1259     if (lease) {
1260         RemoveLease(&srvIns->addressPool, lease);
1261         LOGD("lease recoder has been removed.");
1262     } else {
1263         LOGW("can't found lease recoder.");
1264     }
1265 
1266     if (ReleaseBinding(received->packet.chaddr) != RET_SUCCESS) {
1267         LOGW("failed to release client[%s] bind.", ParseLogMac(received->packet.chaddr));
1268     }
1269     LOGD("client released.");
1270     return REPLY_NONE;
1271 }
1272 
OnReceivedInform(PDhcpServerContext ctx,PDhcpMsgInfo received,PDhcpMsgInfo reply)1273 static int OnReceivedInform(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply)
1274 {
1275     if (!received || !reply) {
1276         return REPLY_NONE;
1277     }
1278     ServerContext *srvIns = GetServerInstance(ctx);
1279     if (!srvIns) {
1280         LOGE("dhcp server context pointer is null.");
1281         return RET_FAILED;
1282     }
1283     LOGI("received 'Inform' message from: %s", ParseLogMac(received->packet.chaddr));
1284     if (IsEmptyHWAddr(received->packet.chaddr)) {
1285         LOGD("error dhcp 'Inform' message.");
1286     }
1287     return REPLY_ACK;
1288 }
1289 
AppendFixedOptions(PDhcpServerContext ctx,PDhcpMsgInfo reply)1290 static int AppendFixedOptions(PDhcpServerContext ctx, PDhcpMsgInfo reply)
1291 {
1292     ServerContext *srvIns = GetServerInstance(ctx);
1293     if (!srvIns) {
1294         return RET_FAILED;
1295     }
1296     if (!reply) {
1297         return RET_FAILED;
1298     }
1299     if (srvIns->addressPool.fixedOptions.size > 0) {
1300         DhcpOptionNode *pNode = srvIns->addressPool.fixedOptions.first->next;
1301         for (size_t i = 0; pNode != NULL && i < srvIns->addressPool.fixedOptions.size; i++) {
1302             PDhcpOption opt = NULL;
1303             if (pNode->option.code) {
1304                 opt = GetOption(&reply->options, pNode->option.code);
1305             }
1306             if (opt == NULL) {
1307                 PushBackOption(&reply->options, &pNode->option);
1308             }
1309             pNode = pNode->next;
1310         }
1311     }
1312     return RET_SUCCESS;
1313 }
AppendReplyTypeOption(PDhcpMsgInfo reply,int replyType)1314 int AppendReplyTypeOption(PDhcpMsgInfo reply, int replyType)
1315 {
1316     if (!reply) {
1317         return RET_FAILED;
1318     }
1319     if (!replyType) {
1320         return RET_FAILED;
1321     }
1322     uint8_t msgType = 0;
1323     switch (replyType) {
1324         case REPLY_OFFER:
1325             msgType = DHCPOFFER;
1326             break;
1327         case REPLY_ACK:
1328             msgType = DHCPACK;
1329             break;
1330         case REPLY_NAK:
1331             msgType = DHCPNAK;
1332             break;
1333         default:
1334             break;
1335     }
1336     PDhcpOption pOptMsgType = GetOption(&reply->options, DHCP_MESSAGE_TYPE_OPTION);
1337     if (!pOptMsgType) {
1338         LOGD("append message type option for reply message, type:%hhu", msgType);
1339         DhcpOption optMsgType = {DHCP_MESSAGE_TYPE_OPTION, OPT_MESSAGE_TYPE_LEGTH, {msgType, 0}};
1340         PushFrontOption(&reply->options, &optMsgType);
1341     } else {
1342         if (pOptMsgType->data[0] != msgType) {
1343             LOGD("error dhcp nak message type.");
1344             return RET_FAILED;
1345         }
1346     }
1347     return RET_SUCCESS;
1348 }
1349 
SendDhcpOffer(PDhcpServerContext ctx,PDhcpMsgInfo reply)1350 static int SendDhcpOffer(PDhcpServerContext ctx, PDhcpMsgInfo reply)
1351 {
1352     ServerContext *srvIns = GetServerInstance(ctx);
1353     if (!srvIns) {
1354         return RET_FAILED;
1355     }
1356     if (AppendReplyTypeOption(reply, REPLY_OFFER) != RET_SUCCESS) {
1357         return RET_FAILED;
1358     }
1359     if (AppendReplyTimeOptions(ctx, &reply->options) != RET_SUCCESS ||
1360         AddReplyServerIdOption(&reply->options, srvIns->addressPool.serverId) != RET_SUCCESS) {
1361             return RET_FAILED;
1362     }
1363     if (AppendFixedOptions(ctx, reply) != RET_SUCCESS) {
1364         LOGW("failed to append fixed reply options.");
1365     }
1366     if (ParseReplyOptions(reply) != RET_SUCCESS) {
1367         LOGE("failed to parse reply options.");
1368         return RET_FAILED;
1369     }
1370     int ret;
1371     struct sockaddr_in *bcastAddrIn = BroadcastAddrIn();
1372     struct sockaddr_in *destAddrIn = DestinationAddrIn();
1373     if (srvIns->broadCastFlagEnable == 1 && destAddrIn) {
1374         int broadCastFlag = 1;
1375         if (reply->packet.flags && (reply->packet.flags >> (DHCP_MESSAGE_FLAG_LENGTH - 1)) == 0) {
1376             broadCastFlag = 0;
1377         }
1378         if (!broadCastFlag && destAddrIn->sin_addr.s_addr) {
1379             ret = sendto(srvIns->serverFd, &reply->packet, reply->length, 0, (struct sockaddr *)destAddrIn,
1380                 sizeof(*destAddrIn));
1381         } else {
1382             ret = sendto(srvIns->serverFd, &reply->packet, reply->length, 0, (struct sockaddr *)bcastAddrIn,
1383                 sizeof(*bcastAddrIn));
1384         }
1385     } else {
1386         ret = sendto(
1387             srvIns->serverFd, &reply->packet, reply->length, 0, (struct sockaddr *)bcastAddrIn, sizeof(*bcastAddrIn));
1388     }
1389     if (!ret) {
1390         LOGD("failed to send dhcp offer message.");
1391         return RET_FAILED;
1392     }
1393     LOGI(" send reply offer, length:%d", reply->length);
1394     return RET_SUCCESS;
1395 }
1396 
SendDhcpAck(PDhcpServerContext ctx,PDhcpMsgInfo reply)1397 static int SendDhcpAck(PDhcpServerContext ctx, PDhcpMsgInfo reply)
1398 {
1399     if (AppendReplyTypeOption(reply, REPLY_ACK) != RET_SUCCESS) {
1400         return RET_FAILED;
1401     }
1402     if (AppendFixedOptions(ctx, reply) != RET_SUCCESS) {
1403         LOGW("failed to append fixed reply options.");
1404     }
1405     if (!ctx || !ctx->instance) {
1406         LOGE("dhcp server context pointer is null.");
1407         return RET_FAILED;
1408     }
1409     ServerContext *srvIns = GetServerInstance(ctx);
1410 
1411     if (AppendReplyTimeOptions(ctx, &reply->options) != RET_SUCCESS) {
1412         return RET_FAILED;
1413     }
1414     if (AddReplyServerIdOption(&reply->options, srvIns->addressPool.serverId) != RET_SUCCESS) {
1415         return RET_FAILED;
1416     }
1417     if (ParseReplyOptions(reply) != RET_SUCCESS) {
1418         return RET_FAILED;
1419     }
1420     sockaddr_in *destAddrIn = DestinationAddrIn();
1421     int ret = sendto(srvIns->serverFd, &reply->packet, reply->length, 0, (struct sockaddr *)destAddrIn,
1422         sizeof(*destAddrIn));
1423     if (!ret) {
1424         LOGD("failed to send dhcp ack message.");
1425         return RET_FAILED;
1426     }
1427     LOGI(" send reply ack, size:%d", reply->length);
1428     return RET_SUCCESS;
1429 }
1430 
SendDhcpNak(PDhcpServerContext ctx,PDhcpMsgInfo reply)1431 static int SendDhcpNak(PDhcpServerContext ctx, PDhcpMsgInfo reply)
1432 {
1433     if (AppendReplyTypeOption(reply, REPLY_NAK) != RET_SUCCESS) {
1434         return RET_FAILED;
1435     }
1436     ServerContext *srvIns = GetServerInstance(ctx);
1437     if (srvIns == NULL) {
1438         LOGE("SendDhcpNak, srvIns is null");
1439         return RET_FAILED;
1440     }
1441     if (ParseReplyOptions(reply) != RET_SUCCESS) {
1442         return RET_FAILED;
1443     }
1444 
1445     struct sockaddr_in *destAddrIn = DestinationAddrIn();
1446     int ret = sendto(srvIns->serverFd, &reply->packet, reply->length, 0, (struct sockaddr *)destAddrIn,
1447         sizeof(*destAddrIn));
1448     if (!ret) {
1449         LOGD("failed to send dhcp ack message.");
1450         return RET_FAILED;
1451     }
1452     LOGI(" send reply nak, size:%d", reply->length);
1453     return RET_SUCCESS;
1454 }
1455 
ParseMessageOptions(PDhcpMsgInfo msg)1456 static int ParseMessageOptions(PDhcpMsgInfo msg)
1457 {
1458     if (msg->length < (DHCP_MSG_HEADER_SIZE + MAGIC_COOKIE_LENGTH)) {
1459         return RET_FAILED;
1460     }
1461     DhcpOption *current, *end;
1462     current = (DhcpOption *)msg->packet.options;
1463     end = (DhcpOption *)(((uint8_t *)msg->packet.options) + (msg->length - DHCP_MSG_HEADER_SIZE));
1464 
1465     if (memcmp(current, MAGIC_COOKIE_DATA, sizeof(MAGIC_COOKIE_DATA)) != 0) {
1466         LOGD("bad magic cookie.");
1467         return RET_FAILED;
1468     }
1469 
1470     current = (DhcpOption *)(((uint8_t *)current) + MAGIC_COOKIE_LENGTH);
1471     uint8_t *pos = (((uint8_t *)current) + MAGIC_COOKIE_LENGTH);
1472     uint8_t *maxPos = (((uint8_t *)current) + (DHCP_OPTION_SIZE - MAGIC_COOKIE_LENGTH - OPT_HEADER_LENGTH -1));
1473     int optTotal = 0;
1474     while (current < end && current->code != END_OPTION) {
1475         if (((uint8_t *)end) - ((uint8_t *)current) < OPT_HEADER_LENGTH) {
1476             LOGE("current->code out of option range.");
1477             return RET_FAILED;
1478         }
1479         pos += (OPT_HEADER_LENGTH + current->length);
1480         if (pos >= maxPos) {
1481             LOGD("out of option max pos.");
1482             return RET_FAILED;
1483         }
1484         if (PushBackOption(&msg->options, current) != RET_SUCCESS) {
1485             LOGD("failed to PushOption.");
1486         }
1487         current = (DhcpOption *)(((uint8_t *)current) + OPT_HEADER_LENGTH + current->length);
1488         optTotal++;
1489     }
1490     if (current < end && current->code == END_OPTION) {
1491         LOGD("option list size:%zu xid:%u", msg->options.size, msg->packet.xid);
1492         return RET_SUCCESS;
1493     }
1494 
1495     LOGD("option list parse failed.");
1496     return RET_FAILED;
1497 }
1498 
ResetMessageOptions(PDhcpMsgInfo reply)1499 static int ResetMessageOptions(PDhcpMsgInfo reply)
1500 {
1501     if (!reply || reply->options.size == 0) {
1502         LOGE("message pointer is null.");
1503         return RET_ERROR;
1504     }
1505     if (memset_s(reply->packet.options, DHCP_OPTIONS_SIZE, 0, DHCP_OPTIONS_SIZE) != EOK) {
1506         LOGE("failed to reset message options!");
1507         return RET_ERROR;
1508     }
1509     return RET_SUCCESS;
1510 }
1511 
ValidateReplyOptions(PDhcpMsgInfo reply)1512 static int ValidateReplyOptions(PDhcpMsgInfo reply)
1513 {
1514     if (!reply) {
1515         LOGE("reply message pointer is null.");
1516         return RET_FAILED;
1517     }
1518     int ret = RET_FAILED;
1519     if ((ret = ResetMessageOptions(reply)) != RET_SUCCESS) {
1520         return ret;
1521     }
1522     reply->length = DHCP_MSG_HEADER_SIZE;
1523     PDhcpOptionNode pNode = reply->options.first;
1524     if (!pNode) {
1525         return RET_ERROR;
1526     }
1527     PDhcpOption pOptMsgType = GetOption(&reply->options, DHCP_MESSAGE_TYPE_OPTION);
1528     if (!pOptMsgType) {
1529         LOGE("unknown reply message type.");
1530         return ret;
1531     }
1532     return RET_SUCCESS;
1533 }
1534 
ParseReplyOptions(PDhcpMsgInfo reply)1535 static int ParseReplyOptions(PDhcpMsgInfo reply)
1536 {
1537     int ret = RET_FAILED;
1538     if ((ret = ValidateReplyOptions(reply)) != RET_SUCCESS) {
1539         return ret;
1540     }
1541     PDhcpOptionNode pNode = reply->options.first->next;
1542     DhcpOption endOpt = {END_OPTION, 0, {0}};
1543     PushBackOption(&reply->options, &endOpt);
1544     int replyOptsLength = 0;
1545     uint8_t *current = reply->packet.options, olen = MAGIC_COOKIE_LENGTH;
1546     size_t remainingSize = sizeof(reply->packet.options);
1547     uint32_t cookie = htonl(DHCP_MAGIC_COOKIE);
1548     if (memcpy_s(current, remainingSize, &cookie, olen) != EOK) {
1549         LOGE("memcpy cookie out of options buffer!");
1550         return RET_FAILED;
1551     }
1552     replyOptsLength += olen;
1553     remainingSize -= olen;
1554     current += olen;
1555     ret = RET_SUCCESS;
1556     while (pNode && (uint32_t)pNode->option.length < DHCP_OPTION_SIZE) {
1557         if ((uint32_t)pNode->option.code == END_OPTION) {
1558             olen = OPT_HEADER_LENGTH + 1;
1559         } else {
1560             olen = OPT_HEADER_LENGTH + pNode->option.length;
1561         }
1562         if (memcpy_s(current, remainingSize, &pNode->option, olen) != EOK) {
1563             LOGE("memcpy current option out of options buffer!");
1564             ret = RET_FAILED;
1565             break;
1566         }
1567         remainingSize -= olen;
1568         current += olen;
1569         replyOptsLength += olen;
1570         if ((uint32_t)pNode->option.code == END_OPTION) {
1571             break;
1572         }
1573         pNode = pNode->next;
1574         if (replyOptsLength >= DHCP_OPTIONS_SIZE) {
1575             LOGE("current option out of options buffer!");
1576             ret = RET_FAILED;
1577             break;
1578         }
1579     }
1580     reply->length += replyOptsLength;
1581     return ret;
1582 }
1583 
RegisterDhcpCallback(PDhcpServerContext ctx,DhcpServerCallback callback)1584 void RegisterDhcpCallback(PDhcpServerContext ctx, DhcpServerCallback callback)
1585 {
1586     LOGI("register server callback.");
1587     ServerContext *srvIns = GetServerInstance(ctx);
1588     if (!srvIns) {
1589         LOGE("dhcp server context pointer is null.");
1590         return;
1591     }
1592     srvIns->callback = callback;
1593 }
1594 
InitServerContext(DhcpConfig * config,DhcpServerContext * ctx)1595 static int InitServerContext(DhcpConfig *config, DhcpServerContext *ctx)
1596 {
1597     if (!config) {
1598         LOGE("server configure pointer is null.");
1599         return RET_FAILED;
1600     }
1601     ServerContext *srvIns = GetServerInstance(ctx);
1602     if (!srvIns) {
1603         LOGE("dhcp server context pointer is null.");
1604         return RET_FAILED;
1605     }
1606     if (InitAddressPool(&srvIns->addressPool, config->ifname, NULL) != RET_SUCCESS) {
1607         LOGD("failed to init address pool.");
1608         return RET_FAILED;
1609     }
1610     if (memcpy_s(ctx->ifname, sizeof(ctx->ifname), config->ifname, strlen(config->ifname)) != EOK) {
1611         LOGD("failed to set interface name.");
1612         return RET_FAILED;
1613     }
1614     srvIns->serverFd = 0;
1615     srvIns->callback = 0;
1616     srvIns->looperState = LS_IDLE;
1617     srvIns->broadCastFlagEnable = config->broadcast;
1618     srvIns->addressPool.serverId = config->serverId;
1619     srvIns->addressPool.netmask = config->netmask;
1620     srvIns->addressPool.gateway = config->gateway;
1621     if (config->pool.beginAddress && config->pool.endAddress) {
1622         srvIns->addressPool.addressRange.beginAddress = config->pool.beginAddress;
1623         srvIns->addressPool.addressRange.endAddress = config->pool.endAddress;
1624     } else {
1625         srvIns->addressPool.addressRange.beginAddress = FirstIpAddress(config->serverId, config->netmask);
1626         srvIns->addressPool.addressRange.endAddress = LastIpAddress(config->serverId, config->netmask);
1627     }
1628     if (memcpy_s(srvIns->addressPool.ifname, sizeof(srvIns->addressPool.ifname),
1629         config->ifname, strlen(config->ifname)) != EOK) {
1630         LOGD("failed to set interface name.");
1631         return RET_FAILED;
1632     }
1633     if (!CheckAddressRange(&srvIns->addressPool)) {
1634         LOGE("failed to validate address range.");
1635         return RET_FAILED;
1636     }
1637     InitLeaseFile(&srvIns->addressPool);
1638     return RET_SUCCESS;
1639 }
1640 
InitServerFixedOptions(DhcpConfig * config,DhcpServerContext * ctx)1641 int InitServerFixedOptions(DhcpConfig *config, DhcpServerContext *ctx)
1642 {
1643     if (!config) {
1644         LOGE("server configure pointer is null.");
1645         return RET_FAILED;
1646     }
1647     ServerContext *srvIns = GetServerInstance(ctx);
1648     if (!srvIns) {
1649         LOGE("dhcp server context pointer is null.");
1650         return RET_FAILED;
1651     }
1652 
1653     if (!HasInitialized(&config->options)) {
1654         LOGE("dhcp configure has not been initialized.");
1655         return RET_FAILED;
1656     }
1657     if (InitOptionList(&srvIns->addressPool.fixedOptions) != RET_SUCCESS) {
1658         return RET_FAILED;
1659     }
1660     if (config->options.first != NULL && config->options.size > 0) {
1661         DhcpOptionNode *pNode = config->options.first->next;
1662         for (size_t i = 0; pNode != NULL && i < config->options.size; i++) {
1663             PushBackOption(&srvIns->addressPool.fixedOptions, &pNode->option);
1664             LOGD("append fixed option ==> %hhu,%d", pNode->option.code,
1665                 pNode->option.length);
1666             pNode = pNode->next;
1667         }
1668     }
1669     return RET_SUCCESS;
1670 }
1671 
InitializeServer(DhcpConfig * config)1672 PDhcpServerContext InitializeServer(DhcpConfig *config)
1673 {
1674     DhcpServerContext *context = NULL;
1675     if (!config) {
1676         LOGE("dhcp server config pointer is null.");
1677         return NULL;
1678     }
1679     if (strlen(config->ifname) == 0) {
1680         LOGE("can't found interface name config.");
1681         return NULL;
1682     }
1683     if (!config->serverId || !config->netmask) {
1684         LOGE("missing required parameter or config item: \"serverId\", \"netmask\"");
1685         return NULL;
1686     }
1687     if ((context = (DhcpServerContext *)calloc(1, sizeof(DhcpServerContext))) == NULL) {
1688         LOGE("failed to calloc server context.");
1689         return NULL;
1690     }
1691     if ((context->instance = calloc(1, sizeof(ServerContext))) == NULL) {
1692         LOGE("failed to calloc server instance.");
1693         FreeServerContext(&context);
1694         return NULL;
1695     }
1696     if (InitServerContext(config, context) != RET_SUCCESS) {
1697         LOGE("failed initialize dhcp server context.");
1698         FreeServerContext(&context);
1699         return NULL;
1700     }
1701     if (InitServerFixedOptions(config, context) != RET_SUCCESS) {
1702         LOGE("failed initialize dhcp server fixed options.");
1703         FreeServerContext(&context);
1704         return NULL;
1705     }
1706     LOGD("server id: %s", ParseStrIp(config->serverId));
1707     LOGD("netmask: %s", ParseStrIp(config->netmask));
1708     if (config->gateway) {
1709         LOGD("gateway: %s", ParseStrIp(config->gateway));
1710     }
1711     LOGD("address range begin of: %s", ParseStrIp(config->pool.beginAddress));
1712     LOGD("address range end of: %s", ParseStrIp(config->pool.endAddress));
1713     context->instance->initialized = 1;
1714     return context;
1715 }
1716 
FreeServerContext(PDhcpServerContext * ctx)1717 int FreeServerContext(PDhcpServerContext *ctx)
1718 {
1719     if (ctx == NULL || *ctx == NULL) {
1720         LOGE("dhcp server context pointer is null.");
1721         return RET_FAILED;
1722     }
1723     ServerContext *srvIns = GetServerInstance(*ctx);
1724     if (!srvIns) {
1725         LOGE("dhcp server instance pointer is null.");
1726         return RET_FAILED;
1727     }
1728     FreeAddressPool(&srvIns->addressPool);
1729     if ((*ctx)->instance != NULL) {
1730         free((*ctx)->instance);
1731         (*ctx)->instance = NULL;
1732     }
1733     free(*ctx);
1734     *ctx = NULL;
1735     return RET_SUCCESS;
1736 }
1737