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