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