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 43DEFINE_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 69const uint8_t MAGIC_COOKIE_DATA[MAGIC_COOKIE_LENGTH] = {0x63, 0x82, 0x53, 0x63}; // Vendor Information "Magic Cookie" 70 71enum 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 83struct 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 94enum LooperState { 95 LS_IDLE = 0, 96 LS_STARING, 97 LS_RUNNING, 98 LS_RELOADNG, 99 LS_STOPING, 100 LS_STOPED 101}; 102typedef struct sockaddr_in sockaddr_in; 103int FillReply(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply); 104static int OnReceivedDiscover(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply); 105static int OnReceivedRequest(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply); 106static int OnReceivedDecline(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply); 107static int OnReceivedRelease(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply); 108static int OnReceivedInform(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply); 109static int SendDhcpOffer(PDhcpServerContext ctx, PDhcpMsgInfo reply); 110static int SendDhcpAck(PDhcpServerContext ctx, PDhcpMsgInfo reply); 111static int SendDhcpNak(PDhcpServerContext ctx, PDhcpMsgInfo reply); 112static int ParseMessageOptions(PDhcpMsgInfo msg); 113 114static int ParseReplyOptions(PDhcpMsgInfo reply); 115struct sockaddr_in *BroadcastAddrIn(void); 116 117static struct ServerContext *GetServerInstance(const DhcpServerContext *ctx) 118{ 119 if (!ctx || !ctx->instance) { 120 return nullptr; 121 } 122 return (struct ServerContext *)ctx->instance; 123} 124 125int 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 134typedef struct ifreq ifreq; 135typedef struct sockaddr sockaddr; 136 137int 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 160int 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 204struct 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 215struct 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 224struct 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 234uint32_t SourceIpAddress(void) 235{ 236 uint32_t srcIp = SourceAddrIn()->sin_addr.s_addr; 237 return srcIp; 238} 239struct 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 249struct 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 256int 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 315void 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 341void 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 354static 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 367void 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 380int 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 414static 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 459int 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 475static 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 493static 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 513static 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 563void 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 583static 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 599void 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 624void 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 646static void ExitProcess(void) 647{ 648 DHCP_LOGD("dhcp server stopped."); 649} 650 651int 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 689int 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 701int 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 711int 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 761int 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 799static 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 832static 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 849static 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 863int 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 886static 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 896AddressBinding *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 922int 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 946static 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 983static 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 1030static 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 1043static 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 1085static 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 1142static 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 1185static 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 1214int 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 1231int 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 1251int 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 1270int 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 1290int 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 1310int 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 1330int 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 1346static 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 1398static 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 1439static 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 1491static 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 1508static 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} 1532int 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 1568static 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 1618static 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 1656static 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 1689static 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 1733static 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 1746static 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 1769static 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 1818void 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 1829void 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 1840static 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 1889int 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 1920PDhcpServerContext 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 1966int 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