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