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