1518678f8Sopenharmony_ci/* 2518678f8Sopenharmony_ci * Copyright (C) 2021-2022 Huawei Device Co., Ltd. 3518678f8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4518678f8Sopenharmony_ci * you may not use this file except in compliance with the License. 5518678f8Sopenharmony_ci * You may obtain a copy of the License at 6518678f8Sopenharmony_ci * 7518678f8Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8518678f8Sopenharmony_ci * 9518678f8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10518678f8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11518678f8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12518678f8Sopenharmony_ci * See the License for the specific language governing permissions and 13518678f8Sopenharmony_ci * limitations under the License. 14518678f8Sopenharmony_ci */ 15518678f8Sopenharmony_ci 16518678f8Sopenharmony_ci#include "dhcp_s_server.h" 17518678f8Sopenharmony_ci#include <arpa/inet.h> 18518678f8Sopenharmony_ci#include <errno.h> 19518678f8Sopenharmony_ci#include <fcntl.h> 20518678f8Sopenharmony_ci#include <net/if.h> 21518678f8Sopenharmony_ci#include <netinet/in.h> 22518678f8Sopenharmony_ci#include <securec.h> 23518678f8Sopenharmony_ci#include <stdint.h> 24518678f8Sopenharmony_ci#include <stdio.h> 25518678f8Sopenharmony_ci#include <stdlib.h> 26518678f8Sopenharmony_ci#include <string.h> 27518678f8Sopenharmony_ci#include <sys/select.h> 28518678f8Sopenharmony_ci#include <sys/socket.h> 29518678f8Sopenharmony_ci#include <sys/time.h> 30518678f8Sopenharmony_ci#include <sys/types.h> 31518678f8Sopenharmony_ci#include <unistd.h> 32518678f8Sopenharmony_ci#include <pthread.h> 33518678f8Sopenharmony_ci#include "address_utils.h" 34518678f8Sopenharmony_ci#include "common_util.h" 35518678f8Sopenharmony_ci#include "dhcp_address_pool.h" 36518678f8Sopenharmony_ci#include "dhcp_binding.h" 37518678f8Sopenharmony_ci#include "dhcp_config.h" 38518678f8Sopenharmony_ci#include "dhcp_server_ipv4.h" 39518678f8Sopenharmony_ci#include "dhcp_logger.h" 40518678f8Sopenharmony_ci#include "dhcp_option.h" 41518678f8Sopenharmony_ci#include "dhcp_common_utils.h" 42518678f8Sopenharmony_ci 43518678f8Sopenharmony_ciDEFINE_DHCPLOG_DHCP_LABEL("DhcpServer"); 44518678f8Sopenharmony_ci 45518678f8Sopenharmony_ci#ifndef DHCP_SEL_WAIT_TIMEOUTS 46518678f8Sopenharmony_ci#define DHCP_SEL_WAIT_TIMEOUTS 1000 47518678f8Sopenharmony_ci#endif 48518678f8Sopenharmony_ci#define OPT_MESSAGE_TYPE_LEGTH 1 49518678f8Sopenharmony_ci#define OPT_HEADER_LENGTH 2 50518678f8Sopenharmony_ci#define OPT_TIME_LENGTH 4 51518678f8Sopenharmony_ci#define OPT_TYPE_FIELD_LENGTH 1 52518678f8Sopenharmony_ci#define OPT_MAC_ADDR_LENGTH 6 53518678f8Sopenharmony_ci#define MAGIC_COOKIE_LENGTH 4 54518678f8Sopenharmony_ci#define OPT_BROADCAST_FLAG_ENABLE 0 55518678f8Sopenharmony_ci#define OFFER_MIN_INTERVAL_TIME 5 56518678f8Sopenharmony_ci 57518678f8Sopenharmony_ci#define PENDING_DEFAULT_TIMEOUT 1200 58518678f8Sopenharmony_ci#define PENDING_DEFAULT_INTERVAL 1 59518678f8Sopenharmony_ci#define PENDING_INTERVAL_CHECKING_ENABLE 1 60518678f8Sopenharmony_ci#define DHCP_MAGIC_COOKIE 0x63825363 61518678f8Sopenharmony_ci#define RECV_BUFFER_SIZE 2048 62518678f8Sopenharmony_ci#define ALLOW_NOBINDING_REQUEST 1 63518678f8Sopenharmony_ci#define REUSE_ADDRESS_ENABLE 1 64518678f8Sopenharmony_ci#define WAIT_STOPED_TIME 5 65518678f8Sopenharmony_ci#define DHCP_SERVER_SLEEP_TIMEOUTS 600000 // 600ms 66518678f8Sopenharmony_ci 67518678f8Sopenharmony_ci#define VNEDOR_OPEN_HARMONY "OPEN_HARMONY" 68518678f8Sopenharmony_ci 69518678f8Sopenharmony_ciconst uint8_t MAGIC_COOKIE_DATA[MAGIC_COOKIE_LENGTH] = {0x63, 0x82, 0x53, 0x63}; // Vendor Information "Magic Cookie" 70518678f8Sopenharmony_ci 71518678f8Sopenharmony_cienum AssignedNumbers { 72518678f8Sopenharmony_ci ETHERNET = 1, // Ethernet (10Mb) 73518678f8Sopenharmony_ci EXPERIMENTAL_ETHERNET, // Experimental Ethernet (3Mb) 74518678f8Sopenharmony_ci AMATEUR_RADIO_AX_25, // Amateur Radio AX.25 75518678f8Sopenharmony_ci PROTEON_PRONET_TOKEN_RING, // Proteon ProNET Token Ring 76518678f8Sopenharmony_ci CHAOS, 77518678f8Sopenharmony_ci IEEE802_NETWORKS, 78518678f8Sopenharmony_ci ARCNET, 79518678f8Sopenharmony_ci HYPERCHANNEL, 80518678f8Sopenharmony_ci LANSTAR 81518678f8Sopenharmony_ci}; 82518678f8Sopenharmony_ci 83518678f8Sopenharmony_cistruct ServerContext { 84518678f8Sopenharmony_ci int broadCastFlagEnable; 85518678f8Sopenharmony_ci DhcpAddressPool addressPool; 86518678f8Sopenharmony_ci DhcpServerCallback callback; 87518678f8Sopenharmony_ci DeviceConnectFun deviceConnectFun; 88518678f8Sopenharmony_ci DhcpConfig config; 89518678f8Sopenharmony_ci int serverFd; 90518678f8Sopenharmony_ci int looperState; 91518678f8Sopenharmony_ci int initialized; 92518678f8Sopenharmony_ci}; 93518678f8Sopenharmony_ci 94518678f8Sopenharmony_cienum LooperState { 95518678f8Sopenharmony_ci LS_IDLE = 0, 96518678f8Sopenharmony_ci LS_STARING, 97518678f8Sopenharmony_ci LS_RUNNING, 98518678f8Sopenharmony_ci LS_RELOADNG, 99518678f8Sopenharmony_ci LS_STOPING, 100518678f8Sopenharmony_ci LS_STOPED 101518678f8Sopenharmony_ci}; 102518678f8Sopenharmony_citypedef struct sockaddr_in sockaddr_in; 103518678f8Sopenharmony_ciint FillReply(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply); 104518678f8Sopenharmony_cistatic int OnReceivedDiscover(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply); 105518678f8Sopenharmony_cistatic int OnReceivedRequest(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply); 106518678f8Sopenharmony_cistatic int OnReceivedDecline(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply); 107518678f8Sopenharmony_cistatic int OnReceivedRelease(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply); 108518678f8Sopenharmony_cistatic int OnReceivedInform(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply); 109518678f8Sopenharmony_cistatic int SendDhcpOffer(PDhcpServerContext ctx, PDhcpMsgInfo reply); 110518678f8Sopenharmony_cistatic int SendDhcpAck(PDhcpServerContext ctx, PDhcpMsgInfo reply); 111518678f8Sopenharmony_cistatic int SendDhcpNak(PDhcpServerContext ctx, PDhcpMsgInfo reply); 112518678f8Sopenharmony_cistatic int ParseMessageOptions(PDhcpMsgInfo msg); 113518678f8Sopenharmony_ci 114518678f8Sopenharmony_cistatic int ParseReplyOptions(PDhcpMsgInfo reply); 115518678f8Sopenharmony_cistruct sockaddr_in *BroadcastAddrIn(void); 116518678f8Sopenharmony_ci 117518678f8Sopenharmony_cistatic struct ServerContext *GetServerInstance(const DhcpServerContext *ctx) 118518678f8Sopenharmony_ci{ 119518678f8Sopenharmony_ci if (!ctx || !ctx->instance) { 120518678f8Sopenharmony_ci return nullptr; 121518678f8Sopenharmony_ci } 122518678f8Sopenharmony_ci return (struct ServerContext *)ctx->instance; 123518678f8Sopenharmony_ci} 124518678f8Sopenharmony_ci 125518678f8Sopenharmony_ciint HasFixSocket(int fd) 126518678f8Sopenharmony_ci{ 127518678f8Sopenharmony_ci int flags; 128518678f8Sopenharmony_ci if ((flags = fcntl(fd, F_GETFL)) == -1 || fcntl(fd, F_SETFL, static_cast<unsigned int>(flags) | O_NONBLOCK) == -1) { 129518678f8Sopenharmony_ci return DHCP_FALSE; 130518678f8Sopenharmony_ci } 131518678f8Sopenharmony_ci return DHCP_TRUE; 132518678f8Sopenharmony_ci} 133518678f8Sopenharmony_ci 134518678f8Sopenharmony_citypedef struct ifreq ifreq; 135518678f8Sopenharmony_citypedef struct sockaddr sockaddr; 136518678f8Sopenharmony_ci 137518678f8Sopenharmony_ciint BindNetInterface(int fd, const char *ifname) 138518678f8Sopenharmony_ci{ 139518678f8Sopenharmony_ci DHCP_LOGI("start %{public}s %{public}d ifname = %{public}s ", __func__, __LINE__, ifname); 140518678f8Sopenharmony_ci if (!fd || !ifname) { 141518678f8Sopenharmony_ci return RET_FAILED; 142518678f8Sopenharmony_ci } 143518678f8Sopenharmony_ci ifreq iface; 144518678f8Sopenharmony_ci if (memset_s(&iface, sizeof(iface), 0, sizeof(iface)) != EOK) { 145518678f8Sopenharmony_ci return RET_FAILED; 146518678f8Sopenharmony_ci } 147518678f8Sopenharmony_ci ssize_t ifnameSize = strlen(ifname); 148518678f8Sopenharmony_ci if (strncpy_s(iface.ifr_ifrn.ifrn_name, sizeof(iface.ifr_ifrn.ifrn_name), ifname, ifnameSize) != EOK) { 149518678f8Sopenharmony_ci DHCP_LOGE("start %{public}s %{public}d copy failed ", __func__, __LINE__); 150518678f8Sopenharmony_ci return RET_FAILED; 151518678f8Sopenharmony_ci }; 152518678f8Sopenharmony_ci if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, (char *)&iface, sizeof(iface)) == -1) { 153518678f8Sopenharmony_ci DHCP_LOGE("failed to bind network device interface[%s].", ifname); 154518678f8Sopenharmony_ci return RET_FAILED; 155518678f8Sopenharmony_ci } 156518678f8Sopenharmony_ci DHCP_LOGI("start %{public}s %{public}d success ", __func__, __LINE__); 157518678f8Sopenharmony_ci return RET_SUCCESS; 158518678f8Sopenharmony_ci} 159518678f8Sopenharmony_ci 160518678f8Sopenharmony_ciint InitServer(const char *ifname) 161518678f8Sopenharmony_ci{ 162518678f8Sopenharmony_ci DHCP_LOGI("start %{public}s %{public}d ifname = %{public}s ", __func__, __LINE__, ifname); 163518678f8Sopenharmony_ci sockaddr_in srvAddrIn = {0}; 164518678f8Sopenharmony_ci int optval = 1; 165518678f8Sopenharmony_ci int optrval = 0; 166518678f8Sopenharmony_ci srvAddrIn.sin_family = AF_INET; 167518678f8Sopenharmony_ci srvAddrIn.sin_port = htons(DHCP_SERVER_PORT); 168518678f8Sopenharmony_ci srvAddrIn.sin_addr.s_addr = INADDR_ANY; 169518678f8Sopenharmony_ci int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); 170518678f8Sopenharmony_ci if (fd == -1) { 171518678f8Sopenharmony_ci DHCP_LOGE("failed to create server socket!"); 172518678f8Sopenharmony_ci return -1; 173518678f8Sopenharmony_ci } 174518678f8Sopenharmony_ci if (!HasFixSocket(fd)) { 175518678f8Sopenharmony_ci DHCP_LOGD("failed to fcntl O_NONBLOCK flag!"); 176518678f8Sopenharmony_ci } 177518678f8Sopenharmony_ci if (BindNetInterface(fd, ifname) != RET_SUCCESS) { 178518678f8Sopenharmony_ci close(fd); 179518678f8Sopenharmony_ci return -1; 180518678f8Sopenharmony_ci } 181518678f8Sopenharmony_ci socklen_t optlen = sizeof(optrval); 182518678f8Sopenharmony_ci if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&optrval, &optlen) == -1) { 183518678f8Sopenharmony_ci DHCP_LOGI("failed to receive buffer size."); 184518678f8Sopenharmony_ci } else { 185518678f8Sopenharmony_ci DHCP_LOGI("receive buffer size is %d", optrval); 186518678f8Sopenharmony_ci } 187518678f8Sopenharmony_ci if (REUSE_ADDRESS_ENABLE && setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(optval)) == -1) { 188518678f8Sopenharmony_ci DHCP_LOGW("failed to setsockopt 'SO_REUSEADDR' for server socket!"); 189518678f8Sopenharmony_ci } 190518678f8Sopenharmony_ci if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval)) == -1) { 191518678f8Sopenharmony_ci DHCP_LOGE("failed to setsockopt 'SO_BROADCAST' for server socket!"); 192518678f8Sopenharmony_ci close(fd); 193518678f8Sopenharmony_ci return -1; 194518678f8Sopenharmony_ci } 195518678f8Sopenharmony_ci if (int ret = bind(fd, (sockaddr *)&srvAddrIn, sizeof(sockaddr)) == -1) { 196518678f8Sopenharmony_ci DHCP_LOGE("failed to bind server %{public}d!", ret); 197518678f8Sopenharmony_ci close(fd); 198518678f8Sopenharmony_ci return -1; 199518678f8Sopenharmony_ci } 200518678f8Sopenharmony_ci DHCP_LOGI("start %{public}s %{public}d SUCCESSs ", __func__, __LINE__); 201518678f8Sopenharmony_ci return fd; 202518678f8Sopenharmony_ci} 203518678f8Sopenharmony_ci 204518678f8Sopenharmony_cistruct sockaddr_in *BroadcastAddrIn(void) 205518678f8Sopenharmony_ci{ 206518678f8Sopenharmony_ci static struct sockaddr_in broadcastAddrIn = {0}; 207518678f8Sopenharmony_ci if (broadcastAddrIn.sin_port == 0) { 208518678f8Sopenharmony_ci broadcastAddrIn.sin_port = htons(DHCP_CLIENT_PORT); 209518678f8Sopenharmony_ci broadcastAddrIn.sin_family = AF_INET; 210518678f8Sopenharmony_ci broadcastAddrIn.sin_addr.s_addr = INADDR_BROADCAST; 211518678f8Sopenharmony_ci } 212518678f8Sopenharmony_ci return &broadcastAddrIn; 213518678f8Sopenharmony_ci} 214518678f8Sopenharmony_ci 215518678f8Sopenharmony_cistruct sockaddr_in *SourceAddrIn(void) 216518678f8Sopenharmony_ci{ 217518678f8Sopenharmony_ci static struct sockaddr_in sourceAddrIn = {0}; 218518678f8Sopenharmony_ci sourceAddrIn.sin_port = htons(DHCP_CLIENT_PORT); 219518678f8Sopenharmony_ci sourceAddrIn.sin_family = AF_INET; 220518678f8Sopenharmony_ci sourceAddrIn.sin_addr.s_addr = INADDR_ANY; 221518678f8Sopenharmony_ci return &sourceAddrIn; 222518678f8Sopenharmony_ci} 223518678f8Sopenharmony_ci 224518678f8Sopenharmony_cistruct sockaddr_in *ResetSourceAddr(void) 225518678f8Sopenharmony_ci{ 226518678f8Sopenharmony_ci DHCP_LOGI("start %{public}s %{public}d", __func__, __LINE__); 227518678f8Sopenharmony_ci struct sockaddr_in *srcAddr = SourceAddrIn(); 228518678f8Sopenharmony_ci srcAddr->sin_port = htons(DHCP_CLIENT_PORT); 229518678f8Sopenharmony_ci srcAddr->sin_family = AF_INET; 230518678f8Sopenharmony_ci srcAddr->sin_addr.s_addr = INADDR_ANY; 231518678f8Sopenharmony_ci return srcAddr; 232518678f8Sopenharmony_ci} 233518678f8Sopenharmony_ci 234518678f8Sopenharmony_ciuint32_t SourceIpAddress(void) 235518678f8Sopenharmony_ci{ 236518678f8Sopenharmony_ci uint32_t srcIp = SourceAddrIn()->sin_addr.s_addr; 237518678f8Sopenharmony_ci return srcIp; 238518678f8Sopenharmony_ci} 239518678f8Sopenharmony_cistruct sockaddr_in *DestinationAddrIn(void) 240518678f8Sopenharmony_ci{ 241518678f8Sopenharmony_ci static struct sockaddr_in destAddrIn = {0}; 242518678f8Sopenharmony_ci if (destAddrIn.sin_port == 0) { 243518678f8Sopenharmony_ci destAddrIn.sin_port = htons(DHCP_CLIENT_PORT); 244518678f8Sopenharmony_ci destAddrIn.sin_family = AF_INET; 245518678f8Sopenharmony_ci } 246518678f8Sopenharmony_ci return &destAddrIn; 247518678f8Sopenharmony_ci} 248518678f8Sopenharmony_ci 249518678f8Sopenharmony_cistruct sockaddr_in *DestinationAddr(uint32_t ipAddress) 250518678f8Sopenharmony_ci{ 251518678f8Sopenharmony_ci struct sockaddr_in *destAddr = DestinationAddrIn(); 252518678f8Sopenharmony_ci destAddr->sin_addr.s_addr = htonl(ipAddress); 253518678f8Sopenharmony_ci return destAddr; 254518678f8Sopenharmony_ci} 255518678f8Sopenharmony_ci 256518678f8Sopenharmony_ciint ReceiveDhcpMessage(int sock, PDhcpMsgInfo msgInfo) 257518678f8Sopenharmony_ci{ 258518678f8Sopenharmony_ci static uint8_t recvBuffer[RECV_BUFFER_SIZE] = {0}; 259518678f8Sopenharmony_ci struct timeval tmt; 260518678f8Sopenharmony_ci fd_set recvFd; 261518678f8Sopenharmony_ci FD_ZERO(&recvFd); 262518678f8Sopenharmony_ci FD_SET(sock, &recvFd); 263518678f8Sopenharmony_ci tmt.tv_sec = 0; 264518678f8Sopenharmony_ci tmt.tv_usec = DHCP_SERVER_SLEEP_TIMEOUTS; // 600ms 265518678f8Sopenharmony_ci int ret = select(sock + 1, &recvFd, nullptr, nullptr, &tmt); 266518678f8Sopenharmony_ci if (ret < 0) { 267518678f8Sopenharmony_ci DHCP_LOGE("select error, %d", errno); 268518678f8Sopenharmony_ci return ERR_SELECT; 269518678f8Sopenharmony_ci } 270518678f8Sopenharmony_ci if (ret == 0) { 271518678f8Sopenharmony_ci return RET_SELECT_TIME_OUT; 272518678f8Sopenharmony_ci } 273518678f8Sopenharmony_ci if (!FD_ISSET(sock, &recvFd)) { 274518678f8Sopenharmony_ci DHCP_LOGE("failed to select isset."); 275518678f8Sopenharmony_ci return RET_ERROR; 276518678f8Sopenharmony_ci } 277518678f8Sopenharmony_ci socklen_t ssize = sizeof(sockaddr_in); 278518678f8Sopenharmony_ci struct sockaddr_in *srcAddrIn = ResetSourceAddr(); 279518678f8Sopenharmony_ci srcAddrIn->sin_addr.s_addr = INADDR_ANY; 280518678f8Sopenharmony_ci DHCP_LOGI("start recv from"); 281518678f8Sopenharmony_ci int rsize = recvfrom(sock, recvBuffer, RECV_BUFFER_SIZE, 0, (struct sockaddr *)srcAddrIn, (socklen_t *)&ssize); 282518678f8Sopenharmony_ci if (!rsize) { 283518678f8Sopenharmony_ci DHCP_LOGE("receive error, %d", errno); 284518678f8Sopenharmony_ci return RET_FAILED; 285518678f8Sopenharmony_ci } 286518678f8Sopenharmony_ci if (rsize > (int)sizeof(DhcpMessage) || rsize < DHCP_MSG_HEADER_SIZE) { 287518678f8Sopenharmony_ci DHCP_LOGW("message length error, received %d bytes.", rsize); 288518678f8Sopenharmony_ci return RET_FAILED; 289518678f8Sopenharmony_ci } 290518678f8Sopenharmony_ci DHCP_LOGI("recv over"); 291518678f8Sopenharmony_ci msgInfo->length = rsize; 292518678f8Sopenharmony_ci if (memcpy_s(&msgInfo->packet, sizeof(DhcpMessage), recvBuffer, rsize) != EOK) { 293518678f8Sopenharmony_ci return RET_FAILED; 294518678f8Sopenharmony_ci } 295518678f8Sopenharmony_ci if (msgInfo->packet.op != BOOTREQUEST) { 296518678f8Sopenharmony_ci DHCP_LOGW("dhcp message type error!"); 297518678f8Sopenharmony_ci return RET_FAILED; 298518678f8Sopenharmony_ci } 299518678f8Sopenharmony_ci if (msgInfo->packet.hlen > DHCP_HWADDR_LENGTH) { 300518678f8Sopenharmony_ci DHCP_LOGW("hlen error!"); 301518678f8Sopenharmony_ci return RET_FAILED; 302518678f8Sopenharmony_ci } 303518678f8Sopenharmony_ci if (IsEmptyHWAddr(msgInfo->packet.chaddr)) { 304518678f8Sopenharmony_ci DHCP_LOGW("client hardware address error!"); 305518678f8Sopenharmony_ci return RET_FAILED; 306518678f8Sopenharmony_ci } 307518678f8Sopenharmony_ci if (IsReserved(msgInfo->packet.chaddr)) { 308518678f8Sopenharmony_ci DHCP_LOGD("ignore client, %s", ParseLogMac(msgInfo->packet.chaddr)); 309518678f8Sopenharmony_ci return RET_FAILED; 310518678f8Sopenharmony_ci } 311518678f8Sopenharmony_ci DHCP_LOGI("start %{public}s %{public}d return success", __func__, __LINE__); 312518678f8Sopenharmony_ci return RET_SUCCESS; 313518678f8Sopenharmony_ci} 314518678f8Sopenharmony_ci 315518678f8Sopenharmony_civoid InitReply(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply) 316518678f8Sopenharmony_ci{ 317518678f8Sopenharmony_ci DHCP_LOGI("start %{public}s %{public}d", __func__, __LINE__); 318518678f8Sopenharmony_ci if (!reply) { 319518678f8Sopenharmony_ci DHCP_LOGE("reply message pointer is null!"); 320518678f8Sopenharmony_ci return; 321518678f8Sopenharmony_ci } 322518678f8Sopenharmony_ci reply->packet.op = BOOTREPLY; 323518678f8Sopenharmony_ci reply->packet.htype = ETHERNET; 324518678f8Sopenharmony_ci reply->packet.hlen = OPT_MAC_ADDR_LENGTH; 325518678f8Sopenharmony_ci reply->packet.secs = 0; 326518678f8Sopenharmony_ci reply->packet.ciaddr = 0; 327518678f8Sopenharmony_ci if (memset_s(reply->packet.sname, sizeof(reply->packet.sname), '\0', sizeof(reply->packet.sname)) != EOK) { 328518678f8Sopenharmony_ci DHCP_LOGE("failed to reset message packet[sname]!"); 329518678f8Sopenharmony_ci return; 330518678f8Sopenharmony_ci }; 331518678f8Sopenharmony_ci if (memset_s(reply->packet.file, sizeof(reply->packet.file), '\0', sizeof(reply->packet.file)) != EOK) { 332518678f8Sopenharmony_ci DHCP_LOGE("failed to reset message packet[file]!"); 333518678f8Sopenharmony_ci return; 334518678f8Sopenharmony_ci } 335518678f8Sopenharmony_ci 336518678f8Sopenharmony_ci if (FillReply(ctx, received, reply) != RET_SUCCESS) { 337518678f8Sopenharmony_ci DHCP_LOGW("failed to fill reply message."); 338518678f8Sopenharmony_ci } 339518678f8Sopenharmony_ci} 340518678f8Sopenharmony_ci 341518678f8Sopenharmony_civoid OnUpdateServerConfig(PDhcpServerContext ctx) 342518678f8Sopenharmony_ci{ 343518678f8Sopenharmony_ci DHCP_LOGI("start %{public}s %{public}d", __func__, __LINE__); 344518678f8Sopenharmony_ci ServerContext *srvIns = GetServerInstance(ctx); 345518678f8Sopenharmony_ci if (!srvIns) { 346518678f8Sopenharmony_ci DHCP_LOGE("dhcp server context pointer is null."); 347518678f8Sopenharmony_ci return; 348518678f8Sopenharmony_ci } 349518678f8Sopenharmony_ci if (srvIns->callback) { 350518678f8Sopenharmony_ci srvIns->callback(ST_RELOADNG, 0, ctx->ifname); 351518678f8Sopenharmony_ci } 352518678f8Sopenharmony_ci} 353518678f8Sopenharmony_ci 354518678f8Sopenharmony_cistatic void OnServerStoping(PDhcpServerContext ctx) 355518678f8Sopenharmony_ci{ 356518678f8Sopenharmony_ci DHCP_LOGI("start %{public}s %{public}d", __func__, __LINE__); 357518678f8Sopenharmony_ci ServerContext *srvIns = GetServerInstance(ctx); 358518678f8Sopenharmony_ci if (!srvIns) { 359518678f8Sopenharmony_ci DHCP_LOGE("dhcp server context pointer is null."); 360518678f8Sopenharmony_ci return; 361518678f8Sopenharmony_ci } 362518678f8Sopenharmony_ci if (srvIns->callback) { 363518678f8Sopenharmony_ci srvIns->callback(ST_STOPING, 0, ctx->ifname); 364518678f8Sopenharmony_ci } 365518678f8Sopenharmony_ci} 366518678f8Sopenharmony_ci 367518678f8Sopenharmony_civoid OnServerStoped(PDhcpServerContext ctx, int code) 368518678f8Sopenharmony_ci{ 369518678f8Sopenharmony_ci DHCP_LOGI("OnServerStoped."); 370518678f8Sopenharmony_ci ServerContext *srvIns = GetServerInstance(ctx); 371518678f8Sopenharmony_ci if (!srvIns) { 372518678f8Sopenharmony_ci DHCP_LOGE("dhcp server context pointer is null."); 373518678f8Sopenharmony_ci return; 374518678f8Sopenharmony_ci } 375518678f8Sopenharmony_ci if (srvIns->callback) { 376518678f8Sopenharmony_ci srvIns->callback(ST_STOPED, code, ctx->ifname); 377518678f8Sopenharmony_ci } 378518678f8Sopenharmony_ci} 379518678f8Sopenharmony_ci 380518678f8Sopenharmony_ciint SendDhcpReply(PDhcpServerContext ctx, int replyType, PDhcpMsgInfo reply) 381518678f8Sopenharmony_ci{ 382518678f8Sopenharmony_ci if (!reply) { 383518678f8Sopenharmony_ci DHCP_LOGE("reply message pointer is null."); 384518678f8Sopenharmony_ci return RET_FAILED; 385518678f8Sopenharmony_ci } 386518678f8Sopenharmony_ci int sendRet = -1; 387518678f8Sopenharmony_ci ServerContext *srvIns = GetServerInstance(ctx); 388518678f8Sopenharmony_ci if (!srvIns) { 389518678f8Sopenharmony_ci DHCP_LOGE("dhcp server context pointer is null."); 390518678f8Sopenharmony_ci return RET_FAILED; 391518678f8Sopenharmony_ci } 392518678f8Sopenharmony_ci switch (replyType) { 393518678f8Sopenharmony_ci case REPLY_OFFER: 394518678f8Sopenharmony_ci DHCP_LOGD("<== send reply dhcp offer."); 395518678f8Sopenharmony_ci sendRet = SendDhcpOffer(ctx, reply); 396518678f8Sopenharmony_ci break; 397518678f8Sopenharmony_ci case REPLY_ACK: 398518678f8Sopenharmony_ci DHCP_LOGD("<== send reply dhcp ack."); 399518678f8Sopenharmony_ci sendRet = SendDhcpAck(ctx, reply); 400518678f8Sopenharmony_ci break; 401518678f8Sopenharmony_ci case REPLY_NAK: 402518678f8Sopenharmony_ci DHCP_LOGD("<== send reply dhcp nak."); 403518678f8Sopenharmony_ci sendRet = SendDhcpNak(ctx, reply); 404518678f8Sopenharmony_ci break; 405518678f8Sopenharmony_ci default: 406518678f8Sopenharmony_ci break; 407518678f8Sopenharmony_ci } 408518678f8Sopenharmony_ci if (replyType && sendRet != RET_SUCCESS) { 409518678f8Sopenharmony_ci return RET_FAILED; 410518678f8Sopenharmony_ci } 411518678f8Sopenharmony_ci return RET_SUCCESS; 412518678f8Sopenharmony_ci} 413518678f8Sopenharmony_ci 414518678f8Sopenharmony_cistatic int MessageProcess(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply) 415518678f8Sopenharmony_ci{ 416518678f8Sopenharmony_ci DHCP_LOGI("start %{public}s %{public}d", __func__, __LINE__); 417518678f8Sopenharmony_ci int replyType = REPLY_NONE; 418518678f8Sopenharmony_ci if (!received) { 419518678f8Sopenharmony_ci return replyType; 420518678f8Sopenharmony_ci } 421518678f8Sopenharmony_ci PDhcpOption opt = GetOption(&received->options, DHCP_MESSAGE_TYPE_OPTION); 422518678f8Sopenharmony_ci if (!opt) { 423518678f8Sopenharmony_ci DHCP_LOGE("error dhcp message, missing required message type option."); 424518678f8Sopenharmony_ci return replyType; 425518678f8Sopenharmony_ci } 426518678f8Sopenharmony_ci uint8_t messageType = opt->data[0]; 427518678f8Sopenharmony_ci switch (messageType) { 428518678f8Sopenharmony_ci case DHCPDISCOVER: { 429518678f8Sopenharmony_ci DHCP_LOGD("==> Received DHCPDISCOVER message."); 430518678f8Sopenharmony_ci replyType = OnReceivedDiscover(ctx, received, reply); 431518678f8Sopenharmony_ci break; 432518678f8Sopenharmony_ci } 433518678f8Sopenharmony_ci case DHCPREQUEST: { 434518678f8Sopenharmony_ci DHCP_LOGD("==> Received DHCPREQUEST message."); 435518678f8Sopenharmony_ci replyType = OnReceivedRequest(ctx, received, reply); 436518678f8Sopenharmony_ci break; 437518678f8Sopenharmony_ci } 438518678f8Sopenharmony_ci case DHCPDECLINE: { 439518678f8Sopenharmony_ci DHCP_LOGD("==> Received DHCPDECLINE message."); 440518678f8Sopenharmony_ci replyType = OnReceivedDecline(ctx, received, reply); 441518678f8Sopenharmony_ci break; 442518678f8Sopenharmony_ci } 443518678f8Sopenharmony_ci case DHCPRELEASE: { 444518678f8Sopenharmony_ci DHCP_LOGD("==> Received DHCPRELEASE message."); 445518678f8Sopenharmony_ci replyType = OnReceivedRelease(ctx, received, reply); 446518678f8Sopenharmony_ci break; 447518678f8Sopenharmony_ci } 448518678f8Sopenharmony_ci case DHCPINFORM: { 449518678f8Sopenharmony_ci DHCP_LOGD("==> Received DHCPINFORM message."); 450518678f8Sopenharmony_ci replyType = OnReceivedInform(ctx, received, reply); 451518678f8Sopenharmony_ci break; 452518678f8Sopenharmony_ci } 453518678f8Sopenharmony_ci default: 454518678f8Sopenharmony_ci break; 455518678f8Sopenharmony_ci } 456518678f8Sopenharmony_ci return replyType; 457518678f8Sopenharmony_ci} 458518678f8Sopenharmony_ci 459518678f8Sopenharmony_ciint SaveLease(PDhcpServerContext ctx) 460518678f8Sopenharmony_ci{ 461518678f8Sopenharmony_ci ServerContext *srvIns = GetServerInstance(ctx); 462518678f8Sopenharmony_ci if (!srvIns) { 463518678f8Sopenharmony_ci DHCP_LOGE("dhcp server context pointer is null."); 464518678f8Sopenharmony_ci return RET_FAILED; 465518678f8Sopenharmony_ci } 466518678f8Sopenharmony_ci int saveRet = SaveBindingRecoders(&srvIns->addressPool, 1); 467518678f8Sopenharmony_ci if (saveRet == RET_FAILED) { 468518678f8Sopenharmony_ci DHCP_LOGD("failed to save lease recoders. total: %zu", srvIns->addressPool.leaseTable.size()); 469518678f8Sopenharmony_ci } else if (saveRet == RET_SUCCESS) { 470518678f8Sopenharmony_ci DHCP_LOGD("lease recoders saved."); 471518678f8Sopenharmony_ci } 472518678f8Sopenharmony_ci return saveRet; 473518678f8Sopenharmony_ci} 474518678f8Sopenharmony_ci 475518678f8Sopenharmony_cistatic int OnLooperStateChanged(PDhcpServerContext ctx) 476518678f8Sopenharmony_ci{ 477518678f8Sopenharmony_ci ServerContext *srvIns = GetServerInstance(ctx); 478518678f8Sopenharmony_ci if (!srvIns) { 479518678f8Sopenharmony_ci DHCP_LOGE("dhcp server context pointer is null."); 480518678f8Sopenharmony_ci return RET_FAILED; 481518678f8Sopenharmony_ci } 482518678f8Sopenharmony_ci 483518678f8Sopenharmony_ci if (srvIns->looperState == LS_RELOADNG) { 484518678f8Sopenharmony_ci OnUpdateServerConfig(ctx); 485518678f8Sopenharmony_ci srvIns->looperState = LS_RUNNING; 486518678f8Sopenharmony_ci } else if (srvIns->looperState == LS_STOPING) { 487518678f8Sopenharmony_ci OnServerStoping(ctx); 488518678f8Sopenharmony_ci return RET_BREAK; 489518678f8Sopenharmony_ci } 490518678f8Sopenharmony_ci return RET_SUCCESS; 491518678f8Sopenharmony_ci} 492518678f8Sopenharmony_ci 493518678f8Sopenharmony_cistatic int ContinueReceive(PDhcpMsgInfo from, int recvRet) 494518678f8Sopenharmony_ci{ 495518678f8Sopenharmony_ci if (!from) { 496518678f8Sopenharmony_ci return DHCP_TRUE; 497518678f8Sopenharmony_ci } 498518678f8Sopenharmony_ci if (recvRet != RET_SUCCESS) { 499518678f8Sopenharmony_ci return DHCP_TRUE; 500518678f8Sopenharmony_ci } 501518678f8Sopenharmony_ci DHCP_LOGD("received, length:%{public}d", from->length); 502518678f8Sopenharmony_ci if (ParseMessageOptions(from) != 0) { 503518678f8Sopenharmony_ci DHCP_LOGE("invalid dhcp message."); 504518678f8Sopenharmony_ci return DHCP_TRUE; 505518678f8Sopenharmony_ci } 506518678f8Sopenharmony_ci if (!GetOption(&from->options, DHCP_MESSAGE_TYPE_OPTION)) { 507518678f8Sopenharmony_ci DHCP_LOGW("can't found 'message type' option."); 508518678f8Sopenharmony_ci return DHCP_TRUE; 509518678f8Sopenharmony_ci } 510518678f8Sopenharmony_ci return DHCP_FALSE; 511518678f8Sopenharmony_ci} 512518678f8Sopenharmony_ci 513518678f8Sopenharmony_cistatic void *BeginLooper(void *argc) __attribute__((no_sanitize("cfi"))) 514518678f8Sopenharmony_ci{ 515518678f8Sopenharmony_ci PDhcpServerContext ctx = (PDhcpServerContext)argc; 516518678f8Sopenharmony_ci DHCP_LOGI("start %{public}s %{public}d", __func__, __LINE__); 517518678f8Sopenharmony_ci DhcpMsgInfo from; 518518678f8Sopenharmony_ci DhcpMsgInfo reply; 519518678f8Sopenharmony_ci ServerContext *srvIns = GetServerInstance(ctx); 520518678f8Sopenharmony_ci if (!srvIns) { 521518678f8Sopenharmony_ci DHCP_LOGE("dhcp server context pointer is null."); 522518678f8Sopenharmony_ci return nullptr; 523518678f8Sopenharmony_ci } 524518678f8Sopenharmony_ci ctx->instance->serverFd = InitServer(ctx->ifname); 525518678f8Sopenharmony_ci if (ctx->instance->serverFd < 0) { 526518678f8Sopenharmony_ci DHCP_LOGE("failed to initialize server socket."); 527518678f8Sopenharmony_ci return nullptr; 528518678f8Sopenharmony_ci } 529518678f8Sopenharmony_ci InitOptionList(&from.options); 530518678f8Sopenharmony_ci InitOptionList(&reply.options); 531518678f8Sopenharmony_ci srvIns->looperState = LS_RUNNING; 532518678f8Sopenharmony_ci while (srvIns->looperState) { 533518678f8Sopenharmony_ci if (OnLooperStateChanged(ctx) != RET_SUCCESS) { 534518678f8Sopenharmony_ci DHCP_LOGI("OnLooperStateChanged break, looperState:%{public}d", srvIns->looperState); 535518678f8Sopenharmony_ci break; 536518678f8Sopenharmony_ci } 537518678f8Sopenharmony_ci ClearOptions(&from.options); 538518678f8Sopenharmony_ci ClearOptions(&reply.options); 539518678f8Sopenharmony_ci int recvRet = ReceiveDhcpMessage(ctx->instance->serverFd, &from); 540518678f8Sopenharmony_ci if (recvRet == RET_ERROR || recvRet == ERR_SELECT) { 541518678f8Sopenharmony_ci DHCP_LOGI("ReceiveDhcpMessage"); 542518678f8Sopenharmony_ci continue; 543518678f8Sopenharmony_ci } 544518678f8Sopenharmony_ci if (ContinueReceive(&from, recvRet)) { 545518678f8Sopenharmony_ci continue; 546518678f8Sopenharmony_ci } 547518678f8Sopenharmony_ci InitReply(ctx, &from, &reply); 548518678f8Sopenharmony_ci int replyType = MessageProcess(ctx, &from, &reply); 549518678f8Sopenharmony_ci if (replyType && SendDhcpReply(ctx, replyType, &reply) != RET_SUCCESS) { 550518678f8Sopenharmony_ci DHCP_LOGE("failed to send reply message."); 551518678f8Sopenharmony_ci } 552518678f8Sopenharmony_ci NotifyConnetDeviceChanged(replyType, ctx); 553518678f8Sopenharmony_ci } 554518678f8Sopenharmony_ci FreeOptionList(&from.options); 555518678f8Sopenharmony_ci FreeOptionList(&reply.options); 556518678f8Sopenharmony_ci DHCP_LOGI("dhcp server message looper stopped."); 557518678f8Sopenharmony_ci close(ctx->instance->serverFd); 558518678f8Sopenharmony_ci ctx->instance->serverFd = -1; 559518678f8Sopenharmony_ci srvIns->looperState = LS_STOPED; 560518678f8Sopenharmony_ci return nullptr; 561518678f8Sopenharmony_ci} 562518678f8Sopenharmony_ci 563518678f8Sopenharmony_civoid NotifyConnetDeviceChanged(int replyType, PDhcpServerContext ctx) 564518678f8Sopenharmony_ci{ 565518678f8Sopenharmony_ci DHCP_LOGI("NotifyConnetDeviceChanged replyType:%{public}d", replyType); 566518678f8Sopenharmony_ci if (replyType == REPLY_ACK || replyType == REPLY_OFFER) { 567518678f8Sopenharmony_ci ServerContext *srvIns = GetServerInstance(ctx); 568518678f8Sopenharmony_ci if (srvIns == nullptr) { 569518678f8Sopenharmony_ci DHCP_LOGE("NotifyConnetDeviceChanged srvIns is nullptr"); 570518678f8Sopenharmony_ci return; 571518678f8Sopenharmony_ci } 572518678f8Sopenharmony_ci int saveRet = SaveBindingRecoders(&srvIns->addressPool, 1); 573518678f8Sopenharmony_ci if (saveRet != RET_SUCCESS && saveRet != RET_WAIT_SAVE) { 574518678f8Sopenharmony_ci DHCP_LOGW("SaveBindingRecoders failed to save lease recoders."); 575518678f8Sopenharmony_ci } 576518678f8Sopenharmony_ci if (replyType == REPLY_ACK && srvIns->deviceConnectFun != nullptr) { 577518678f8Sopenharmony_ci DHCP_LOGI("NotifyConnetDeviceChanged deviceConnectFun"); 578518678f8Sopenharmony_ci srvIns->deviceConnectFun(ctx->ifname); 579518678f8Sopenharmony_ci } 580518678f8Sopenharmony_ci } 581518678f8Sopenharmony_ci} 582518678f8Sopenharmony_ci 583518678f8Sopenharmony_cistatic int CheckAddressRange(DhcpAddressPool *pool) 584518678f8Sopenharmony_ci{ 585518678f8Sopenharmony_ci uint32_t serverNetwork = NetworkAddress(pool->serverId, pool->netmask); 586518678f8Sopenharmony_ci uint32_t firstNetwork = NetworkAddress(pool->addressRange.beginAddress, pool->netmask); 587518678f8Sopenharmony_ci uint32_t secondNetwork = NetworkAddress(pool->addressRange.endAddress, pool->netmask); 588518678f8Sopenharmony_ci if (!serverNetwork || !firstNetwork || !secondNetwork) { 589518678f8Sopenharmony_ci DHCP_LOGE("network config error."); 590518678f8Sopenharmony_ci return DHCP_FALSE; 591518678f8Sopenharmony_ci } 592518678f8Sopenharmony_ci if (serverNetwork != firstNetwork || serverNetwork != secondNetwork) { 593518678f8Sopenharmony_ci DHCP_LOGE("server network and address pool network belong to different networks."); 594518678f8Sopenharmony_ci return DHCP_FALSE; 595518678f8Sopenharmony_ci } 596518678f8Sopenharmony_ci return DHCP_TRUE; 597518678f8Sopenharmony_ci} 598518678f8Sopenharmony_ci 599518678f8Sopenharmony_civoid InitBindingRecoders(DhcpAddressPool *pool) 600518678f8Sopenharmony_ci{ 601518678f8Sopenharmony_ci if (!pool) { 602518678f8Sopenharmony_ci DHCP_LOGE("address pool pointer is null."); 603518678f8Sopenharmony_ci return; 604518678f8Sopenharmony_ci } 605518678f8Sopenharmony_ci uint32_t realLeaseTotal = 0; 606518678f8Sopenharmony_ci for (auto current: pool->leaseTable) { 607518678f8Sopenharmony_ci int invalidBindig; 608518678f8Sopenharmony_ci AddressBinding *binding = ¤t.second; 609518678f8Sopenharmony_ci if (binding && !IsEmptyHWAddr(binding->chaddr) && binding->ipAddress) { 610518678f8Sopenharmony_ci AddBinding(binding); 611518678f8Sopenharmony_ci realLeaseTotal++; 612518678f8Sopenharmony_ci invalidBindig = 0; 613518678f8Sopenharmony_ci } else { 614518678f8Sopenharmony_ci DHCP_LOGE("bad binding recoder."); 615518678f8Sopenharmony_ci invalidBindig = 1; 616518678f8Sopenharmony_ci } 617518678f8Sopenharmony_ci if (!invalidBindig && binding && pool->distribution < binding->ipAddress) { 618518678f8Sopenharmony_ci pool->distribution = binding->ipAddress; 619518678f8Sopenharmony_ci } 620518678f8Sopenharmony_ci } 621518678f8Sopenharmony_ci DHCP_LOGD("lease recoder total: %u", realLeaseTotal); 622518678f8Sopenharmony_ci} 623518678f8Sopenharmony_ci 624518678f8Sopenharmony_civoid InitLeaseFile(DhcpAddressPool *pool) 625518678f8Sopenharmony_ci{ 626518678f8Sopenharmony_ci const char *leasePath = GetFilePath(DHCPD_LEASE_FILE); 627518678f8Sopenharmony_ci if (!leasePath || strlen(leasePath) == 0) { 628518678f8Sopenharmony_ci DHCP_LOGE("failed to get lease file path."); 629518678f8Sopenharmony_ci return; 630518678f8Sopenharmony_ci } 631518678f8Sopenharmony_ci if (access(leasePath, 0) != 0) { 632518678f8Sopenharmony_ci DHCP_LOGD("lease file path does not exist."); 633518678f8Sopenharmony_ci if (!CreatePath(leasePath)) { 634518678f8Sopenharmony_ci DHCP_LOGE("failed to create lease file directory."); 635518678f8Sopenharmony_ci return; 636518678f8Sopenharmony_ci } else { 637518678f8Sopenharmony_ci DHCP_LOGD("lease file directory created."); 638518678f8Sopenharmony_ci } 639518678f8Sopenharmony_ci } 640518678f8Sopenharmony_ci if (LoadBindingRecoders(pool) != RET_SUCCESS) { 641518678f8Sopenharmony_ci DHCP_LOGW("failed to load lease recoders."); 642518678f8Sopenharmony_ci } 643518678f8Sopenharmony_ci InitBindingRecoders(pool); 644518678f8Sopenharmony_ci} 645518678f8Sopenharmony_ci 646518678f8Sopenharmony_cistatic void ExitProcess(void) 647518678f8Sopenharmony_ci{ 648518678f8Sopenharmony_ci DHCP_LOGD("dhcp server stopped."); 649518678f8Sopenharmony_ci} 650518678f8Sopenharmony_ci 651518678f8Sopenharmony_ciint StartDhcpServer(PDhcpServerContext ctx) 652518678f8Sopenharmony_ci{ 653518678f8Sopenharmony_ci DHCP_LOGI("%{public}s %{public}d start", __func__, __LINE__); 654518678f8Sopenharmony_ci if (!ctx) { 655518678f8Sopenharmony_ci DHCP_LOGE("server context pointer is null."); 656518678f8Sopenharmony_ci return RET_FAILED; 657518678f8Sopenharmony_ci } 658518678f8Sopenharmony_ci if (strlen(ctx->ifname) == 0) { 659518678f8Sopenharmony_ci DHCP_LOGE("context interface is null or empty."); 660518678f8Sopenharmony_ci return RET_FAILED; 661518678f8Sopenharmony_ci } 662518678f8Sopenharmony_ci ServerContext *srvIns = GetServerInstance(ctx); 663518678f8Sopenharmony_ci if (!srvIns) { 664518678f8Sopenharmony_ci DHCP_LOGE("dhcp server context instance pointer is null."); 665518678f8Sopenharmony_ci return RET_FAILED; 666518678f8Sopenharmony_ci } 667518678f8Sopenharmony_ci if (atexit(ExitProcess) != 0) { 668518678f8Sopenharmony_ci DHCP_LOGW("failed to regiester exit process function."); 669518678f8Sopenharmony_ci } 670518678f8Sopenharmony_ci if (!srvIns->initialized) { 671518678f8Sopenharmony_ci DHCP_LOGE("dhcp server no initialized."); 672518678f8Sopenharmony_ci return RET_FAILED; 673518678f8Sopenharmony_ci } 674518678f8Sopenharmony_ci DHCP_LOGD("bind interface: %{public}s, begin dhcp message looper", ctx->ifname); 675518678f8Sopenharmony_ci if (srvIns->callback) { 676518678f8Sopenharmony_ci srvIns->callback(ST_STARTING, 1, ctx->ifname); 677518678f8Sopenharmony_ci } 678518678f8Sopenharmony_ci pthread_t threadId; 679518678f8Sopenharmony_ci int ret = pthread_create(&threadId, nullptr, BeginLooper, ctx); 680518678f8Sopenharmony_ci if (ret != RET_SUCCESS) { 681518678f8Sopenharmony_ci DHCP_LOGI("failed to start dhcp server."); 682518678f8Sopenharmony_ci OnServerStoped(ctx, ret); 683518678f8Sopenharmony_ci return RET_FAILED; 684518678f8Sopenharmony_ci } 685518678f8Sopenharmony_ci OnServerStoped(ctx, ret); 686518678f8Sopenharmony_ci return RET_SUCCESS; 687518678f8Sopenharmony_ci} 688518678f8Sopenharmony_ci 689518678f8Sopenharmony_ciint StopDhcpServer(PDhcpServerContext ctx) 690518678f8Sopenharmony_ci{ 691518678f8Sopenharmony_ci ServerContext *srvIns = GetServerInstance(ctx); 692518678f8Sopenharmony_ci if (!srvIns) { 693518678f8Sopenharmony_ci DHCP_LOGE("StopDhcpServer GetServerInstance failed!"); 694518678f8Sopenharmony_ci return RET_FAILED; 695518678f8Sopenharmony_ci } 696518678f8Sopenharmony_ci srvIns->looperState = LS_STOPING; 697518678f8Sopenharmony_ci DHCP_LOGI("StopDhcpServer looperState LS_STOPING!"); 698518678f8Sopenharmony_ci return RET_SUCCESS; 699518678f8Sopenharmony_ci} 700518678f8Sopenharmony_ci 701518678f8Sopenharmony_ciint GetServerStatus(PDhcpServerContext ctx) 702518678f8Sopenharmony_ci{ 703518678f8Sopenharmony_ci ServerContext *srvIns = GetServerInstance(ctx); 704518678f8Sopenharmony_ci if (!srvIns) { 705518678f8Sopenharmony_ci DHCP_LOGE("dhcp server context pointer is null."); 706518678f8Sopenharmony_ci return -1; 707518678f8Sopenharmony_ci } 708518678f8Sopenharmony_ci return srvIns->looperState; 709518678f8Sopenharmony_ci} 710518678f8Sopenharmony_ci 711518678f8Sopenharmony_ciint FillReply(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply) 712518678f8Sopenharmony_ci{ 713518678f8Sopenharmony_ci if (!received || !reply) { 714518678f8Sopenharmony_ci return RET_ERROR; 715518678f8Sopenharmony_ci } 716518678f8Sopenharmony_ci ServerContext *srvIns = GetServerInstance(ctx); 717518678f8Sopenharmony_ci if (!srvIns) { 718518678f8Sopenharmony_ci DHCP_LOGE("dhcp server context pointer is null."); 719518678f8Sopenharmony_ci return RET_FAILED; 720518678f8Sopenharmony_ci } 721518678f8Sopenharmony_ci if (received->packet.ciaddr && received->packet.ciaddr != INADDR_BROADCAST) { 722518678f8Sopenharmony_ci reply->packet.ciaddr = received->packet.ciaddr; 723518678f8Sopenharmony_ci } 724518678f8Sopenharmony_ci if (received->packet.flags) { 725518678f8Sopenharmony_ci reply->packet.flags = received->packet.flags; 726518678f8Sopenharmony_ci } 727518678f8Sopenharmony_ci if (received->packet.xid) { 728518678f8Sopenharmony_ci reply->packet.xid = received->packet.xid; 729518678f8Sopenharmony_ci } 730518678f8Sopenharmony_ci if (received->packet.siaddr && received->packet.siaddr != INADDR_BROADCAST) { 731518678f8Sopenharmony_ci reply->packet.siaddr = received->packet.siaddr; 732518678f8Sopenharmony_ci } else { 733518678f8Sopenharmony_ci reply->packet.siaddr = srvIns->addressPool.serverId; 734518678f8Sopenharmony_ci } 735518678f8Sopenharmony_ci if (received->packet.giaddr && received->packet.giaddr != INADDR_BROADCAST) { 736518678f8Sopenharmony_ci reply->packet.giaddr = received->packet.giaddr; 737518678f8Sopenharmony_ci } else { 738518678f8Sopenharmony_ci if (srvIns->addressPool.gateway) { 739518678f8Sopenharmony_ci reply->packet.giaddr = srvIns->addressPool.gateway; 740518678f8Sopenharmony_ci } 741518678f8Sopenharmony_ci } 742518678f8Sopenharmony_ci if (received->packet.hlen) { 743518678f8Sopenharmony_ci reply->packet.hlen = received->packet.hlen; 744518678f8Sopenharmony_ci DHCP_LOGD("fill reply - chaddr:%s", ParseLogMac(received->packet.chaddr)); 745518678f8Sopenharmony_ci if (memset_s(reply->packet.chaddr, sizeof(reply->packet.chaddr), 0, sizeof(reply->packet.chaddr)) != EOK) { 746518678f8Sopenharmony_ci DHCP_LOGE("failed to reset message packet[chaddr]!"); 747518678f8Sopenharmony_ci return RET_ERROR; 748518678f8Sopenharmony_ci } 749518678f8Sopenharmony_ci if (memcpy_s(reply->packet.chaddr, sizeof(reply->packet.chaddr), 750518678f8Sopenharmony_ci received->packet.chaddr, sizeof(received->packet.chaddr)) != EOK) { 751518678f8Sopenharmony_ci DHCP_LOGE("failed to copy message packet[chaddr]!"); 752518678f8Sopenharmony_ci return RET_ERROR; 753518678f8Sopenharmony_ci } 754518678f8Sopenharmony_ci } 755518678f8Sopenharmony_ci if (received->packet.giaddr) { 756518678f8Sopenharmony_ci reply->packet.giaddr = received->packet.giaddr; 757518678f8Sopenharmony_ci } 758518678f8Sopenharmony_ci return 0; 759518678f8Sopenharmony_ci} 760518678f8Sopenharmony_ci 761518678f8Sopenharmony_ciint AppendReplyTimeOptions(PDhcpServerContext ctx, PDhcpOptionList options) 762518678f8Sopenharmony_ci{ 763518678f8Sopenharmony_ci if (!ctx || !options) { 764518678f8Sopenharmony_ci DHCP_LOGE("server context or options pointer is null."); 765518678f8Sopenharmony_ci return RET_FAILED; 766518678f8Sopenharmony_ci } 767518678f8Sopenharmony_ci ServerContext *srvIns = GetServerInstance(ctx); 768518678f8Sopenharmony_ci if (!srvIns) { 769518678f8Sopenharmony_ci DHCP_LOGE("dhcp server context pointer is null."); 770518678f8Sopenharmony_ci return RET_FAILED; 771518678f8Sopenharmony_ci } 772518678f8Sopenharmony_ci uint32_t leaseTime = HostToNetwork(DHCP_LEASE_TIME); 773518678f8Sopenharmony_ci if (srvIns->addressPool.leaseTime) { 774518678f8Sopenharmony_ci leaseTime = HostToNetwork(srvIns->addressPool.leaseTime); 775518678f8Sopenharmony_ci } 776518678f8Sopenharmony_ci DhcpOption optLeaseTime = {IP_ADDRESS_LEASE_TIME_OPTION, OPT_TIME_LENGTH, {0}}; 777518678f8Sopenharmony_ci FillU32Option(&optLeaseTime, leaseTime); 778518678f8Sopenharmony_ci PushBackOption(options, &optLeaseTime); 779518678f8Sopenharmony_ci 780518678f8Sopenharmony_ci uint32_t t1Time = HostToNetwork(DHCP_RENEWAL_TIME); 781518678f8Sopenharmony_ci if (srvIns->addressPool.renewalTime) { 782518678f8Sopenharmony_ci t1Time = HostToNetwork(srvIns->addressPool.renewalTime); 783518678f8Sopenharmony_ci } 784518678f8Sopenharmony_ci DhcpOption optRenewTime = {RENEWAL_TIME_VALUE_OPTION, OPT_TIME_LENGTH, {0}}; 785518678f8Sopenharmony_ci FillU32Option(&optRenewTime, t1Time); 786518678f8Sopenharmony_ci PushBackOption(options, &optRenewTime); 787518678f8Sopenharmony_ci 788518678f8Sopenharmony_ci uint32_t t2Time = HostToNetwork(DHCP_REBINDING_TIME); 789518678f8Sopenharmony_ci if (srvIns->addressPool.rebindingTime) { 790518678f8Sopenharmony_ci t2Time = HostToNetwork(srvIns->addressPool.rebindingTime); 791518678f8Sopenharmony_ci } 792518678f8Sopenharmony_ci DhcpOption optRebindTime = {REBINDING_TIME_VALUE_OPTION, OPT_TIME_LENGTH, {0}}; 793518678f8Sopenharmony_ci FillU32Option(&optRebindTime, t2Time); 794518678f8Sopenharmony_ci PushBackOption(options, &optRebindTime); 795518678f8Sopenharmony_ci 796518678f8Sopenharmony_ci return RET_SUCCESS; 797518678f8Sopenharmony_ci} 798518678f8Sopenharmony_ci 799518678f8Sopenharmony_cistatic int Repending(DhcpAddressPool *pool, AddressBinding *binding) 800518678f8Sopenharmony_ci{ 801518678f8Sopenharmony_ci if (!pool) { 802518678f8Sopenharmony_ci return REPLY_NONE; 803518678f8Sopenharmony_ci } 804518678f8Sopenharmony_ci uint32_t bindingIp = binding->ipAddress; 805518678f8Sopenharmony_ci DHCP_LOGD(" binding found, bindIp:%s", ParseStrIp(bindingIp)); 806518678f8Sopenharmony_ci binding->pendingInterval = NextPendingInterval(binding->pendingInterval); 807518678f8Sopenharmony_ci uint64_t tms = Tmspsec() - binding->pendingTime; 808518678f8Sopenharmony_ci if (tms < binding->pendingInterval) { 809518678f8Sopenharmony_ci binding->pendingTime = Tmspsec(); 810518678f8Sopenharmony_ci DHCP_LOGW("message interval is too short, ignore the message."); 811518678f8Sopenharmony_ci return REPLY_NONE; 812518678f8Sopenharmony_ci } 813518678f8Sopenharmony_ci binding->pendingTime = Tmspsec(); 814518678f8Sopenharmony_ci binding->pendingInterval = 0; 815518678f8Sopenharmony_ci binding->bindingStatus = BIND_PENDING; 816518678f8Sopenharmony_ci uint32_t srcIp = SourceIpAddress(); 817518678f8Sopenharmony_ci if (srcIp && srcIp != INADDR_BROADCAST && bindingIp != INADDR_BROADCAST && srcIp != bindingIp) { 818518678f8Sopenharmony_ci DHCP_LOGW("source ip address and bound ip address inconsistency."); 819518678f8Sopenharmony_ci return REPLY_NAK; 820518678f8Sopenharmony_ci } 821518678f8Sopenharmony_ci if (srcIp && srcIp == bindingIp) { 822518678f8Sopenharmony_ci if (pool->leaseTable.count(srcIp) == 0) { 823518678f8Sopenharmony_ci DHCP_LOGD("can't find lease information."); 824518678f8Sopenharmony_ci pool->leaseTable[srcIp] = *binding; 825518678f8Sopenharmony_ci } else { 826518678f8Sopenharmony_ci pool->leaseTable[srcIp] = *binding; 827518678f8Sopenharmony_ci } 828518678f8Sopenharmony_ci } 829518678f8Sopenharmony_ci return REPLY_OFFER; 830518678f8Sopenharmony_ci} 831518678f8Sopenharmony_ci 832518678f8Sopenharmony_cistatic int Rebinding(DhcpAddressPool *pool, AddressBinding *binding) 833518678f8Sopenharmony_ci{ 834518678f8Sopenharmony_ci uint64_t pendingTime = binding->pendingTime; 835518678f8Sopenharmony_ci int replyType = Repending(pool, binding); 836518678f8Sopenharmony_ci binding->bindingStatus = BIND_ASSOCIATED; 837518678f8Sopenharmony_ci if (!binding->leaseTime) { 838518678f8Sopenharmony_ci binding->leaseTime = pool->leaseTime; 839518678f8Sopenharmony_ci } 840518678f8Sopenharmony_ci binding->bindingTime = Tmspsec(); 841518678f8Sopenharmony_ci binding->expireIn = binding->bindingTime + binding->leaseTime; 842518678f8Sopenharmony_ci binding->pendingTime = pendingTime; 843518678f8Sopenharmony_ci if (replyType == REPLY_OFFER) { 844518678f8Sopenharmony_ci replyType = REPLY_ACK; 845518678f8Sopenharmony_ci } 846518678f8Sopenharmony_ci return replyType; 847518678f8Sopenharmony_ci} 848518678f8Sopenharmony_ci 849518678f8Sopenharmony_cistatic void AddAddressOption(PDhcpMsgInfo reply, uint8_t code, int32_t address) 850518678f8Sopenharmony_ci{ 851518678f8Sopenharmony_ci if (!reply) { 852518678f8Sopenharmony_ci return; 853518678f8Sopenharmony_ci } 854518678f8Sopenharmony_ci DhcpOption optAddress = {0, 0, {0}}; 855518678f8Sopenharmony_ci optAddress.code = code; 856518678f8Sopenharmony_ci if (AppendAddressOption(&optAddress, address) != RET_SUCCESS) { 857518678f8Sopenharmony_ci DHCP_LOGE("failed to append address option."); 858518678f8Sopenharmony_ci return; 859518678f8Sopenharmony_ci }; 860518678f8Sopenharmony_ci PushBackOption(&reply->options, &optAddress); 861518678f8Sopenharmony_ci} 862518678f8Sopenharmony_ci 863518678f8Sopenharmony_ciint AddReplyServerIdOption(PDhcpOptionList options, uint32_t serverId) 864518678f8Sopenharmony_ci{ 865518678f8Sopenharmony_ci if (!options) { 866518678f8Sopenharmony_ci DHCP_LOGE("option list pointer is null."); 867518678f8Sopenharmony_ci return RET_FAILED; 868518678f8Sopenharmony_ci } 869518678f8Sopenharmony_ci if (!serverId || serverId == INADDR_BROADCAST) { 870518678f8Sopenharmony_ci DHCP_LOGE("servier id error."); 871518678f8Sopenharmony_ci return RET_FAILED; 872518678f8Sopenharmony_ci } 873518678f8Sopenharmony_ci DhcpOption optSrvId = {SERVER_IDENTIFIER_OPTION, 0, {0}}; 874518678f8Sopenharmony_ci if (AppendAddressOption(&optSrvId, serverId) != RET_SUCCESS) { 875518678f8Sopenharmony_ci DHCP_LOGE("failed to append server id option."); 876518678f8Sopenharmony_ci return RET_FAILED; 877518678f8Sopenharmony_ci } 878518678f8Sopenharmony_ci if (GetOption(options, SERVER_IDENTIFIER_OPTION)) { 879518678f8Sopenharmony_ci DHCP_LOGD("server identifier option exists."); 880518678f8Sopenharmony_ci return RET_SUCCESS; 881518678f8Sopenharmony_ci } 882518678f8Sopenharmony_ci PushBackOption(options, &optSrvId); 883518678f8Sopenharmony_ci return RET_SUCCESS; 884518678f8Sopenharmony_ci} 885518678f8Sopenharmony_ci 886518678f8Sopenharmony_cistatic void AddReplyMessageTypeOption(PDhcpMsgInfo reply, uint8_t replyMessageType) 887518678f8Sopenharmony_ci{ 888518678f8Sopenharmony_ci if (!reply) { 889518678f8Sopenharmony_ci return; 890518678f8Sopenharmony_ci } 891518678f8Sopenharmony_ci DhcpOption optMsgType = {DHCP_MESSAGE_TYPE_OPTION, OPT_MESSAGE_TYPE_LEGTH, {replyMessageType, 0}}; 892518678f8Sopenharmony_ci PushBackOption(&reply->options, &optMsgType); 893518678f8Sopenharmony_ci} 894518678f8Sopenharmony_ci 895518678f8Sopenharmony_ci 896518678f8Sopenharmony_ciAddressBinding *GetBinding(DhcpAddressPool *pool, PDhcpMsgInfo received) 897518678f8Sopenharmony_ci{ 898518678f8Sopenharmony_ci if (!pool) { 899518678f8Sopenharmony_ci return nullptr; 900518678f8Sopenharmony_ci } 901518678f8Sopenharmony_ci if (!received) { 902518678f8Sopenharmony_ci return nullptr; 903518678f8Sopenharmony_ci } 904518678f8Sopenharmony_ci AddressBinding *binding = pool->binding(received->packet.chaddr, &received->options); 905518678f8Sopenharmony_ci if (!binding) { 906518678f8Sopenharmony_ci binding = pool->newBinding(received->packet.chaddr, &received->options); 907518678f8Sopenharmony_ci if (binding == nullptr) { 908518678f8Sopenharmony_ci DHCP_LOGE("new binding is null"); 909518678f8Sopenharmony_ci return nullptr; 910518678f8Sopenharmony_ci } 911518678f8Sopenharmony_ci if (pool->leaseTime) { 912518678f8Sopenharmony_ci binding->leaseTime = pool->leaseTime; 913518678f8Sopenharmony_ci } 914518678f8Sopenharmony_ci binding->ipAddress = pool->distribue(pool, received->packet.chaddr); 915518678f8Sopenharmony_ci DHCP_LOGI("new binding ip"); 916518678f8Sopenharmony_ci } else { 917518678f8Sopenharmony_ci DHCP_LOGI("rebinding ip"); 918518678f8Sopenharmony_ci } 919518678f8Sopenharmony_ci return binding; 920518678f8Sopenharmony_ci} 921518678f8Sopenharmony_ci 922518678f8Sopenharmony_ciint ReplyCommontOption(PDhcpServerContext ctx, PDhcpMsgInfo reply) 923518678f8Sopenharmony_ci{ 924518678f8Sopenharmony_ci if (!reply) { 925518678f8Sopenharmony_ci DHCP_LOGE("reply is nullptr!"); 926518678f8Sopenharmony_ci return REPLY_NONE; 927518678f8Sopenharmony_ci } 928518678f8Sopenharmony_ci ServerContext *srvIns = GetServerInstance(ctx); 929518678f8Sopenharmony_ci if (!srvIns) { 930518678f8Sopenharmony_ci DHCP_LOGE("srvIns is nullptr!"); 931518678f8Sopenharmony_ci return REPLY_NONE; 932518678f8Sopenharmony_ci } 933518678f8Sopenharmony_ci AddAddressOption(reply, SUBNET_MASK_OPTION, srvIns->addressPool.netmask); 934518678f8Sopenharmony_ci if (srvIns->addressPool.gateway) { 935518678f8Sopenharmony_ci AddAddressOption(reply, ROUTER_OPTION, srvIns->addressPool.gateway); 936518678f8Sopenharmony_ci } 937518678f8Sopenharmony_ci DhcpOption optVendorInfo = {VENDOR_SPECIFIC_INFO_OPTION, static_cast<uint8_t>(strlen(VNEDOR_OPEN_HARMONY)), 938518678f8Sopenharmony_ci VNEDOR_OPEN_HARMONY}; 939518678f8Sopenharmony_ci PushBackOption(&reply->options, &optVendorInfo); 940518678f8Sopenharmony_ci uint32_t netAddress = reply->packet.yiaddr & srvIns->addressPool.netmask; 941518678f8Sopenharmony_ci uint32_t boastAddress = (~srvIns->addressPool.netmask) | netAddress; 942518678f8Sopenharmony_ci AddAddressOption(reply, BROADCAST_ADDRESS_OPTION, boastAddress); 943518678f8Sopenharmony_ci return REPLY_OFFER; 944518678f8Sopenharmony_ci} 945518678f8Sopenharmony_ci 946518678f8Sopenharmony_cistatic int DiscoverReplyLeaseMessage(PDhcpServerContext ctx, PDhcpMsgInfo reply, ServerContext *srvIns, 947518678f8Sopenharmony_ci AddressBinding *binding) 948518678f8Sopenharmony_ci{ 949518678f8Sopenharmony_ci if (!ctx) { 950518678f8Sopenharmony_ci DHCP_LOGE("ctx pointer is null."); 951518678f8Sopenharmony_ci return REPLY_NONE; 952518678f8Sopenharmony_ci } 953518678f8Sopenharmony_ci if (!reply) { 954518678f8Sopenharmony_ci DHCP_LOGE("reply message pointer is null."); 955518678f8Sopenharmony_ci return REPLY_NONE; 956518678f8Sopenharmony_ci } 957518678f8Sopenharmony_ci if (!srvIns) { 958518678f8Sopenharmony_ci DHCP_LOGE("get server instance is nullptr!"); 959518678f8Sopenharmony_ci return REPLY_NONE; 960518678f8Sopenharmony_ci } 961518678f8Sopenharmony_ci if (!binding) { 962518678f8Sopenharmony_ci DHCP_LOGI("Discover binding is null, reply none"); 963518678f8Sopenharmony_ci return REPLY_NONE; 964518678f8Sopenharmony_ci } 965518678f8Sopenharmony_ci AddressBinding *lease = GetLease(&srvIns->addressPool, binding->ipAddress); 966518678f8Sopenharmony_ci if (!lease) { 967518678f8Sopenharmony_ci DHCP_LOGI("Discover add lease, binging ip:%{public}s mac:%{public}s", 968518678f8Sopenharmony_ci OHOS::DHCP::IntIpv4ToAnonymizeStr(binding->ipAddress).c_str(), ParseLogMac(binding->chaddr)); 969518678f8Sopenharmony_ci AddLease(&srvIns->addressPool, binding); 970518678f8Sopenharmony_ci lease = GetLease(&srvIns->addressPool, binding->ipAddress); 971518678f8Sopenharmony_ci } 972518678f8Sopenharmony_ci if (!lease) { 973518678f8Sopenharmony_ci DHCP_LOGI("Discover lease is null, reply none"); 974518678f8Sopenharmony_ci return REPLY_NONE; 975518678f8Sopenharmony_ci } 976518678f8Sopenharmony_ci AddReplyMessageTypeOption(reply, DHCPOFFER); 977518678f8Sopenharmony_ci reply->packet.yiaddr = lease->ipAddress; 978518678f8Sopenharmony_ci ReplyCommontOption(ctx, reply); 979518678f8Sopenharmony_ci DHCP_LOGI("Discover reply offer"); 980518678f8Sopenharmony_ci return REPLY_OFFER; 981518678f8Sopenharmony_ci} 982518678f8Sopenharmony_ci 983518678f8Sopenharmony_cistatic int OnReceivedDiscover(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply) 984518678f8Sopenharmony_ci{ 985518678f8Sopenharmony_ci if (!received || !reply) { 986518678f8Sopenharmony_ci DHCP_LOGE("receive or reply message pointer is null."); 987518678f8Sopenharmony_ci return REPLY_NONE; 988518678f8Sopenharmony_ci } 989518678f8Sopenharmony_ci DHCP_LOGI("received 'Discover' message from:%{public}s", ParseLogMac(received->packet.chaddr)); 990518678f8Sopenharmony_ci ServerContext *srvIns = GetServerInstance(ctx); 991518678f8Sopenharmony_ci if (!srvIns) { 992518678f8Sopenharmony_ci DHCP_LOGE("get server instance is nullptr!"); 993518678f8Sopenharmony_ci return REPLY_NONE; 994518678f8Sopenharmony_ci } 995518678f8Sopenharmony_ci uint32_t reqIp = 0; 996518678f8Sopenharmony_ci PDhcpOption optReqIp = GetOption(&received->options, REQUESTED_IP_ADDRESS_OPTION); 997518678f8Sopenharmony_ci if (optReqIp) { 998518678f8Sopenharmony_ci reqIp = ParseIp(optReqIp->data); 999518678f8Sopenharmony_ci if (reqIp) { 1000518678f8Sopenharmony_ci DHCP_LOGI("Discover request ip:%{public}s", OHOS::DHCP::IntIpv4ToAnonymizeStr(reqIp).c_str()); 1001518678f8Sopenharmony_ci } 1002518678f8Sopenharmony_ci } 1003518678f8Sopenharmony_ci uint32_t srcIp = SourceIpAddress(); 1004518678f8Sopenharmony_ci if (!srvIns->broadCastFlagEnable) { 1005518678f8Sopenharmony_ci if (srcIp) { 1006518678f8Sopenharmony_ci DHCP_LOGI("Discover client repending:%{public}s", OHOS::DHCP::IntIpv4ToAnonymizeStr(srcIp).c_str()); 1007518678f8Sopenharmony_ci } else { 1008518678f8Sopenharmony_ci srcIp = INADDR_BROADCAST; 1009518678f8Sopenharmony_ci } 1010518678f8Sopenharmony_ci DestinationAddr(srcIp); 1011518678f8Sopenharmony_ci } 1012518678f8Sopenharmony_ci AddressBinding *binding = GetBinding(&srvIns->addressPool, received); 1013518678f8Sopenharmony_ci if (!binding) { 1014518678f8Sopenharmony_ci DHCP_LOGI("Discover binding is null, reply none"); 1015518678f8Sopenharmony_ci return REPLY_NONE; 1016518678f8Sopenharmony_ci } 1017518678f8Sopenharmony_ci if (!binding->ipAddress) { 1018518678f8Sopenharmony_ci DHCP_LOGI("Discover binding ipAddress is null, reply none"); 1019518678f8Sopenharmony_ci return REPLY_NONE; 1020518678f8Sopenharmony_ci } 1021518678f8Sopenharmony_ci if (reqIp != 0 && reqIp != binding->ipAddress) { 1022518678f8Sopenharmony_ci DHCP_LOGW("Discover package reqIp:%{public}s, binging ip:%{public}s", 1023518678f8Sopenharmony_ci OHOS::DHCP::IntIpv4ToAnonymizeStr(reqIp).c_str(), 1024518678f8Sopenharmony_ci OHOS::DHCP::IntIpv4ToAnonymizeStr(binding->ipAddress).c_str()); 1025518678f8Sopenharmony_ci } 1026518678f8Sopenharmony_ci DeleteMacInLease(&srvIns->addressPool, binding); 1027518678f8Sopenharmony_ci return DiscoverReplyLeaseMessage(ctx, reply, srvIns, binding); 1028518678f8Sopenharmony_ci} 1029518678f8Sopenharmony_ci 1030518678f8Sopenharmony_cistatic uint32_t GetRequestIpAddress(PDhcpMsgInfo received) 1031518678f8Sopenharmony_ci{ 1032518678f8Sopenharmony_ci uint32_t reqIp = 0; 1033518678f8Sopenharmony_ci if (!received) { 1034518678f8Sopenharmony_ci return reqIp; 1035518678f8Sopenharmony_ci } 1036518678f8Sopenharmony_ci PDhcpOption optReqIp = GetOption(&received->options, REQUESTED_IP_ADDRESS_OPTION); 1037518678f8Sopenharmony_ci if (optReqIp) { 1038518678f8Sopenharmony_ci reqIp = ParseIp(optReqIp->data); 1039518678f8Sopenharmony_ci } 1040518678f8Sopenharmony_ci return reqIp; 1041518678f8Sopenharmony_ci} 1042518678f8Sopenharmony_ci 1043518678f8Sopenharmony_cistatic int GetYourIpAddress(PDhcpMsgInfo received, uint32_t *yourIpAddr, DhcpAddressPool *pool) 1044518678f8Sopenharmony_ci{ 1045518678f8Sopenharmony_ci uint32_t cliIp = received->packet.ciaddr; 1046518678f8Sopenharmony_ci uint32_t srcIp = SourceIpAddress(); 1047518678f8Sopenharmony_ci uint32_t reqIp = GetRequestIpAddress(received); 1048518678f8Sopenharmony_ci DHCP_LOGI("cliIp:%{public}s srcIp:%{public}s reqIp:%{public}s", 1049518678f8Sopenharmony_ci OHOS::DHCP::IntIpv4ToAnonymizeStr(cliIp).c_str(), OHOS::DHCP::IntIpv4ToAnonymizeStr(srcIp).c_str(), 1050518678f8Sopenharmony_ci OHOS::DHCP::IntIpv4ToAnonymizeStr(reqIp).c_str()); 1051518678f8Sopenharmony_ci if (cliIp && srcIp && cliIp != srcIp) { 1052518678f8Sopenharmony_ci DHCP_LOGE("error dhcp request message, missing required request option."); 1053518678f8Sopenharmony_ci return RET_FAILED; 1054518678f8Sopenharmony_ci } 1055518678f8Sopenharmony_ci if (reqIp && srcIp && reqIp != srcIp) { 1056518678f8Sopenharmony_ci DHCP_LOGE("error dhcp request message, request ip error."); 1057518678f8Sopenharmony_ci return RET_FAILED; 1058518678f8Sopenharmony_ci } 1059518678f8Sopenharmony_ci if (cliIp && reqIp && cliIp != reqIp) { 1060518678f8Sopenharmony_ci DHCP_LOGE("error dhcp request message, client ip error."); 1061518678f8Sopenharmony_ci return RET_FAILED; 1062518678f8Sopenharmony_ci } 1063518678f8Sopenharmony_ci 1064518678f8Sopenharmony_ci if (srcIp && srcIp != INADDR_BROADCAST) { 1065518678f8Sopenharmony_ci *yourIpAddr = srcIp; 1066518678f8Sopenharmony_ci } else if (cliIp && cliIp != INADDR_BROADCAST) { 1067518678f8Sopenharmony_ci *yourIpAddr = cliIp; 1068518678f8Sopenharmony_ci } else if (reqIp && reqIp != INADDR_BROADCAST) { 1069518678f8Sopenharmony_ci *yourIpAddr = reqIp; 1070518678f8Sopenharmony_ci } 1071518678f8Sopenharmony_ci 1072518678f8Sopenharmony_ci if ((ntohl(*yourIpAddr) < ntohl(pool->addressRange.beginAddress)) 1073518678f8Sopenharmony_ci || (ntohl(*yourIpAddr) > ntohl(pool->addressRange.endAddress))) { 1074518678f8Sopenharmony_ci return RET_FAILED; 1075518678f8Sopenharmony_ci } 1076518678f8Sopenharmony_ci 1077518678f8Sopenharmony_ci if (srcIp && srcIp != INADDR_BROADCAST) { 1078518678f8Sopenharmony_ci DestinationAddr(srcIp); 1079518678f8Sopenharmony_ci } else if (srcIp == INADDR_ANY) { 1080518678f8Sopenharmony_ci DestinationAddr(INADDR_BROADCAST); 1081518678f8Sopenharmony_ci } 1082518678f8Sopenharmony_ci return RET_SUCCESS; 1083518678f8Sopenharmony_ci} 1084518678f8Sopenharmony_ci 1085518678f8Sopenharmony_cistatic int NotBindingRequest(DhcpAddressPool *pool, PDhcpMsgInfo received, PDhcpMsgInfo reply) 1086518678f8Sopenharmony_ci{ 1087518678f8Sopenharmony_ci uint32_t yourIpAddr = 0; 1088518678f8Sopenharmony_ci if (GetYourIpAddress(received, &yourIpAddr, pool) != RET_SUCCESS) { 1089518678f8Sopenharmony_ci DHCP_LOGI("GetYourIpAddress REPLY_NONE"); 1090518678f8Sopenharmony_ci return REPLY_NONE; 1091518678f8Sopenharmony_ci } 1092518678f8Sopenharmony_ci AddressBinding *lease = GetLease(pool, yourIpAddr); 1093518678f8Sopenharmony_ci if (!lease) { 1094518678f8Sopenharmony_ci if (SourceIpAddress()) { 1095518678f8Sopenharmony_ci DHCP_LOGI("SourceIpAddress True REPLY_ACK"); 1096518678f8Sopenharmony_ci return REPLY_ACK; 1097518678f8Sopenharmony_ci } 1098518678f8Sopenharmony_ci DHCP_LOGI("SourceIpAddress REPLY_NAK"); 1099518678f8Sopenharmony_ci return REPLY_NAK; 1100518678f8Sopenharmony_ci } 1101518678f8Sopenharmony_ci int sameAddr = AddrEquels(lease->chaddr, received->packet.chaddr, MAC_ADDR_LENGTH); 1102518678f8Sopenharmony_ci if (lease->bindingStatus == BIND_ASSOCIATED && !sameAddr) { 1103518678f8Sopenharmony_ci if (!IsExpire(lease)) { 1104518678f8Sopenharmony_ci DHCP_LOGI("Not IsExpire REPLY_NAK"); 1105518678f8Sopenharmony_ci return REPLY_NAK; 1106518678f8Sopenharmony_ci } 1107518678f8Sopenharmony_ci DHCP_LOGI("RemoveLease lease"); 1108518678f8Sopenharmony_ci RemoveLease(pool, lease); 1109518678f8Sopenharmony_ci } 1110518678f8Sopenharmony_ci AddressBinding *binding = pool->newBinding(received->packet.chaddr, &received->options); 1111518678f8Sopenharmony_ci if (binding == nullptr) { 1112518678f8Sopenharmony_ci DHCP_LOGE("Not binding request binding is null."); 1113518678f8Sopenharmony_ci return REPLY_NONE; 1114518678f8Sopenharmony_ci } 1115518678f8Sopenharmony_ci binding->ipAddress = yourIpAddr; 1116518678f8Sopenharmony_ci if (pool->leaseTime) { 1117518678f8Sopenharmony_ci binding->leaseTime = pool->leaseTime; 1118518678f8Sopenharmony_ci } 1119518678f8Sopenharmony_ci int replyType = Repending(pool, binding); 1120518678f8Sopenharmony_ci if (replyType != REPLY_OFFER) { 1121518678f8Sopenharmony_ci DHCP_LOGI("replyType != REPLY_OFFER"); 1122518678f8Sopenharmony_ci return replyType; 1123518678f8Sopenharmony_ci } 1124518678f8Sopenharmony_ci lease = GetLease(pool, yourIpAddr); 1125518678f8Sopenharmony_ci if (!lease) { 1126518678f8Sopenharmony_ci DHCP_LOGI("add new lease recoder."); 1127518678f8Sopenharmony_ci AddLease(pool, binding); 1128518678f8Sopenharmony_ci lease = GetLease(pool, binding->ipAddress); 1129518678f8Sopenharmony_ci } 1130518678f8Sopenharmony_ci if (!lease) { 1131518678f8Sopenharmony_ci DHCP_LOGI("failed to get lease."); 1132518678f8Sopenharmony_ci return REPLY_NONE; 1133518678f8Sopenharmony_ci } 1134518678f8Sopenharmony_ci lease->bindingStatus = BIND_ASSOCIATED; 1135518678f8Sopenharmony_ci lease->bindingTime = Tmspsec(); 1136518678f8Sopenharmony_ci lease->expireIn = lease->bindingTime + binding->leaseTime; 1137518678f8Sopenharmony_ci reply->packet.yiaddr = lease->ipAddress; 1138518678f8Sopenharmony_ci DHCP_LOGI("NotBindingRequest REPLY_ACK"); 1139518678f8Sopenharmony_ci return REPLY_ACK; 1140518678f8Sopenharmony_ci} 1141518678f8Sopenharmony_ci 1142518678f8Sopenharmony_cistatic int ValidateRequestMessage(const PDhcpServerContext ctx, const PDhcpMsgInfo received, 1143518678f8Sopenharmony_ci PDhcpMsgInfo reply, uint32_t *yourIp) 1144518678f8Sopenharmony_ci{ 1145518678f8Sopenharmony_ci if (!received || !reply) { 1146518678f8Sopenharmony_ci DHCP_LOGE("receive or reply message pointer is null."); 1147518678f8Sopenharmony_ci return REPLY_NONE; 1148518678f8Sopenharmony_ci } 1149518678f8Sopenharmony_ci DHCP_LOGI("received 'Request' message from:%{public}s", ParseLogMac(received->packet.chaddr)); 1150518678f8Sopenharmony_ci uint32_t yourIpAddr = INADDR_BROADCAST; 1151518678f8Sopenharmony_ci ServerContext *srvIns = GetServerInstance(ctx); 1152518678f8Sopenharmony_ci if (!srvIns) { 1153518678f8Sopenharmony_ci DHCP_LOGI("get server instance failed!"); 1154518678f8Sopenharmony_ci return RET_FAILED; 1155518678f8Sopenharmony_ci } 1156518678f8Sopenharmony_ci if (GetYourIpAddress(received, &yourIpAddr, &srvIns->addressPool) != RET_SUCCESS) { 1157518678f8Sopenharmony_ci if (yourIpAddr && yourIpAddr != INADDR_BROADCAST) { 1158518678f8Sopenharmony_ci AddressBinding *lease = GetLease(&srvIns->addressPool, yourIpAddr); 1159518678f8Sopenharmony_ci if (lease) { 1160518678f8Sopenharmony_ci RemoveLease(&srvIns->addressPool, lease); 1161518678f8Sopenharmony_ci DHCP_LOGD("lease recoder has been removed."); 1162518678f8Sopenharmony_ci } else { 1163518678f8Sopenharmony_ci DHCP_LOGW("can't found lease recoder."); 1164518678f8Sopenharmony_ci } 1165518678f8Sopenharmony_ci RemoveBinding(received->packet.chaddr); 1166518678f8Sopenharmony_ci return REPLY_NAK; 1167518678f8Sopenharmony_ci } 1168518678f8Sopenharmony_ci return REPLY_NONE; 1169518678f8Sopenharmony_ci } 1170518678f8Sopenharmony_ci PDhcpOption optReqSrvId = GetOption(&received->options, SERVER_IDENTIFIER_OPTION); 1171518678f8Sopenharmony_ci if (optReqSrvId) { 1172518678f8Sopenharmony_ci uint32_t reqSrvId = ParseIp(optReqSrvId->data); 1173518678f8Sopenharmony_ci DHCP_LOGD(" reuquest server id is:%s", ParseStrIp(reqSrvId)); 1174518678f8Sopenharmony_ci if (reqSrvId != srvIns->addressPool.serverId) { 1175518678f8Sopenharmony_ci DHCP_LOGW("other dhcp server process."); 1176518678f8Sopenharmony_ci return REPLY_NONE; 1177518678f8Sopenharmony_ci } 1178518678f8Sopenharmony_ci } else { 1179518678f8Sopenharmony_ci DHCP_LOGW("request message not specified server identifier option."); 1180518678f8Sopenharmony_ci } 1181518678f8Sopenharmony_ci *yourIp = yourIpAddr; 1182518678f8Sopenharmony_ci return REPLY_ACK; 1183518678f8Sopenharmony_ci} 1184518678f8Sopenharmony_ci 1185518678f8Sopenharmony_cistatic int HasNobindgRequest(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply) 1186518678f8Sopenharmony_ci{ 1187518678f8Sopenharmony_ci if (!received || !reply) { 1188518678f8Sopenharmony_ci DHCP_LOGE("receive or reply message pointer is null."); 1189518678f8Sopenharmony_ci return REPLY_NONE; 1190518678f8Sopenharmony_ci } 1191518678f8Sopenharmony_ci ServerContext *srvIns = GetServerInstance(ctx); 1192518678f8Sopenharmony_ci if (!srvIns) { 1193518678f8Sopenharmony_ci DHCP_LOGE("dhcp server context pointer is null."); 1194518678f8Sopenharmony_ci return REPLY_NONE; 1195518678f8Sopenharmony_ci } 1196518678f8Sopenharmony_ci AddressBinding *binding = srvIns->addressPool.binding(received->packet.chaddr, &received->options); 1197518678f8Sopenharmony_ci if (!binding && ALLOW_NOBINDING_REQUEST) { 1198518678f8Sopenharmony_ci uint32_t srcIp = SourceIpAddress(); 1199518678f8Sopenharmony_ci uint32_t reqIp = GetRequestIpAddress(received); 1200518678f8Sopenharmony_ci DHCP_LOGD("allow no binding request mode."); 1201518678f8Sopenharmony_ci if (reqIp == 0 && srcIp == 0) { 1202518678f8Sopenharmony_ci DHCP_LOGE("error dhcp message."); 1203518678f8Sopenharmony_ci return REPLY_NONE; 1204518678f8Sopenharmony_ci } 1205518678f8Sopenharmony_ci if (!IpInNetwork(reqIp, srvIns->addressPool.serverId, srvIns->addressPool.netmask)) { 1206518678f8Sopenharmony_ci DHCP_LOGE("error request ip."); 1207518678f8Sopenharmony_ci return REPLY_NAK; 1208518678f8Sopenharmony_ci } 1209518678f8Sopenharmony_ci return NotBindingRequest(&srvIns->addressPool, received, reply); 1210518678f8Sopenharmony_ci } 1211518678f8Sopenharmony_ci return REPLY_NONE; 1212518678f8Sopenharmony_ci} 1213518678f8Sopenharmony_ci 1214518678f8Sopenharmony_ciint GetVendorIdentifierOption(PDhcpMsgInfo received) 1215518678f8Sopenharmony_ci{ 1216518678f8Sopenharmony_ci PDhcpOption optVendorIdentifier = GetOption(&received->options, VENDOR_CLASS_IDENTIFIER_OPTION); 1217518678f8Sopenharmony_ci if (optVendorIdentifier) { 1218518678f8Sopenharmony_ci char strVendorIdentifier[DEVICE_NAME_STRING_LENGTH] = {0}; 1219518678f8Sopenharmony_ci if (memcpy_s(strVendorIdentifier, DEVICE_NAME_STRING_LENGTH, (char*)optVendorIdentifier->data, 1220518678f8Sopenharmony_ci optVendorIdentifier->length) != EOK) { 1221518678f8Sopenharmony_ci DHCP_LOGE("GetVendorIdentifierOption strClientIdentifier memcpy_s failed!"); 1222518678f8Sopenharmony_ci return REPLY_NONE; 1223518678f8Sopenharmony_ci } 1224518678f8Sopenharmony_ci DHCP_LOGD("GetVendorIdentifierOption strClientIdentifier:%{public}s", strVendorIdentifier); 1225518678f8Sopenharmony_ci } else { 1226518678f8Sopenharmony_ci DHCP_LOGD("GetVendorIdentifierOption pClientIdentifier is null"); 1227518678f8Sopenharmony_ci } 1228518678f8Sopenharmony_ci return REPLY_NAK; 1229518678f8Sopenharmony_ci} 1230518678f8Sopenharmony_ci 1231518678f8Sopenharmony_ciint GetHostNameOption(PDhcpMsgInfo received, AddressBinding *bindin) 1232518678f8Sopenharmony_ci{ 1233518678f8Sopenharmony_ci if (!bindin) { 1234518678f8Sopenharmony_ci DHCP_LOGE("GetHostNameOption bindin is nullptr!"); 1235518678f8Sopenharmony_ci return REPLY_NONE; 1236518678f8Sopenharmony_ci } 1237518678f8Sopenharmony_ci PDhcpOption optHostName = GetOption(&received->options, HOST_NAME_OPTION); 1238518678f8Sopenharmony_ci if (optHostName) { 1239518678f8Sopenharmony_ci if (memcpy_s(bindin->deviceName, DEVICE_NAME_STRING_LENGTH, (char*)optHostName->data, 1240518678f8Sopenharmony_ci optHostName->length) != EOK) { 1241518678f8Sopenharmony_ci DHCP_LOGE("GetHostNameOption pHost memcpy_s failed!"); 1242518678f8Sopenharmony_ci return REPLY_NONE; 1243518678f8Sopenharmony_ci } 1244518678f8Sopenharmony_ci DHCP_LOGI("GetHostNameOption deviceName:%{public}s", bindin->deviceName); 1245518678f8Sopenharmony_ci } else { 1246518678f8Sopenharmony_ci DHCP_LOGD("GetHostNameOption pHost is null"); 1247518678f8Sopenharmony_ci } 1248518678f8Sopenharmony_ci return REPLY_NAK; 1249518678f8Sopenharmony_ci} 1250518678f8Sopenharmony_ci 1251518678f8Sopenharmony_ciint GetUserClassOption(PDhcpMsgInfo received, AddressBinding *bindin) 1252518678f8Sopenharmony_ci{ 1253518678f8Sopenharmony_ci if (!bindin) { 1254518678f8Sopenharmony_ci DHCP_LOGE("GetUserClassOption bindin is nullptr!"); 1255518678f8Sopenharmony_ci return REPLY_NONE; 1256518678f8Sopenharmony_ci } 1257518678f8Sopenharmony_ci PDhcpOption option = GetOption(&received->options, USER_CLASS_OPTION); 1258518678f8Sopenharmony_ci if (option) { 1259518678f8Sopenharmony_ci if (memcpy_s(bindin->userClass, DEVICE_NAME_STRING_LENGTH, (char*)option->data, option->length) != EOK) { 1260518678f8Sopenharmony_ci DHCP_LOGE("GetUserClassOption memcpy_s failed!"); 1261518678f8Sopenharmony_ci return REPLY_NONE; 1262518678f8Sopenharmony_ci } 1263518678f8Sopenharmony_ci DHCP_LOGD("GetUserClassOption userClass:%{public}s", bindin->userClass); 1264518678f8Sopenharmony_ci } else { 1265518678f8Sopenharmony_ci DHCP_LOGD("GetUserClassOption pHost is null"); 1266518678f8Sopenharmony_ci } 1267518678f8Sopenharmony_ci return REPLY_ACK; 1268518678f8Sopenharmony_ci} 1269518678f8Sopenharmony_ci 1270518678f8Sopenharmony_ciint GetRapidCommitOption(PDhcpMsgInfo received, AddressBinding *bindin) 1271518678f8Sopenharmony_ci{ 1272518678f8Sopenharmony_ci if (!bindin) { 1273518678f8Sopenharmony_ci DHCP_LOGE("GetRapidCommitOption bindin is nullptr!"); 1274518678f8Sopenharmony_ci return REPLY_NONE; 1275518678f8Sopenharmony_ci } 1276518678f8Sopenharmony_ci PDhcpOption option = GetOption(&received->options, RAPID_COMMIT_OPTION); 1277518678f8Sopenharmony_ci if (option) { 1278518678f8Sopenharmony_ci char value[DEVICE_NAME_STRING_LENGTH] = {0}; 1279518678f8Sopenharmony_ci if (memcpy_s(value, DEVICE_NAME_STRING_LENGTH, (char*)option->data, option->length) != EOK) { 1280518678f8Sopenharmony_ci DHCP_LOGE("GetRapidCommitOption memcpy_s failed!"); 1281518678f8Sopenharmony_ci return REPLY_NONE; 1282518678f8Sopenharmony_ci } 1283518678f8Sopenharmony_ci DHCP_LOGD("GetRapidCommitOption value:%{public}s", value); 1284518678f8Sopenharmony_ci } else { 1285518678f8Sopenharmony_ci DHCP_LOGD("GetRapidCommitOption pHost is null"); 1286518678f8Sopenharmony_ci } 1287518678f8Sopenharmony_ci return REPLY_ACK; 1288518678f8Sopenharmony_ci} 1289518678f8Sopenharmony_ci 1290518678f8Sopenharmony_ciint GetOnlyIpv6Option(PDhcpMsgInfo received, AddressBinding *bindin) 1291518678f8Sopenharmony_ci{ 1292518678f8Sopenharmony_ci if (!bindin) { 1293518678f8Sopenharmony_ci DHCP_LOGE("GetOnlyIpv6Option bindin is nullptr!"); 1294518678f8Sopenharmony_ci return REPLY_NONE; 1295518678f8Sopenharmony_ci } 1296518678f8Sopenharmony_ci PDhcpOption option = GetOption(&received->options, IPV6_ONLY_PREFERRED_OPTION); 1297518678f8Sopenharmony_ci if (option) { 1298518678f8Sopenharmony_ci char value[DEVICE_NAME_STRING_LENGTH] = {0}; 1299518678f8Sopenharmony_ci if (memcpy_s(value, DEVICE_NAME_STRING_LENGTH, (char*)option->data, option->length) != EOK) { 1300518678f8Sopenharmony_ci DHCP_LOGE("GetOnlyIpv6Option memcpy_s failed!"); 1301518678f8Sopenharmony_ci return REPLY_NONE; 1302518678f8Sopenharmony_ci } 1303518678f8Sopenharmony_ci DHCP_LOGD("GetOnlyIpv6Option value:%{public}s", value); 1304518678f8Sopenharmony_ci } else { 1305518678f8Sopenharmony_ci DHCP_LOGD("GetOnlyIpv6Option pHost is null"); 1306518678f8Sopenharmony_ci } 1307518678f8Sopenharmony_ci return REPLY_ACK; 1308518678f8Sopenharmony_ci} 1309518678f8Sopenharmony_ci 1310518678f8Sopenharmony_ciint GetPortalUrlOption(PDhcpMsgInfo received, AddressBinding *bindin) 1311518678f8Sopenharmony_ci{ 1312518678f8Sopenharmony_ci if (!bindin) { 1313518678f8Sopenharmony_ci DHCP_LOGE("GetPortalUrlOption bindin is nullptr!"); 1314518678f8Sopenharmony_ci return REPLY_NONE; 1315518678f8Sopenharmony_ci } 1316518678f8Sopenharmony_ci PDhcpOption option = GetOption(&received->options, IPV6_ONLY_PREFERRED_OPTION); 1317518678f8Sopenharmony_ci if (option) { 1318518678f8Sopenharmony_ci char value[DEVICE_NAME_STRING_LENGTH] = {0}; 1319518678f8Sopenharmony_ci if (memcpy_s(value, DEVICE_NAME_STRING_LENGTH, (char*)option->data, option->length) != EOK) { 1320518678f8Sopenharmony_ci DHCP_LOGE("GetPortalUrlOption memcpy_s failed!"); 1321518678f8Sopenharmony_ci return REPLY_NONE; 1322518678f8Sopenharmony_ci } 1323518678f8Sopenharmony_ci DHCP_LOGD("GetPortalUrlOption value:%{public}s", value); 1324518678f8Sopenharmony_ci } else { 1325518678f8Sopenharmony_ci DHCP_LOGD("GetPortalUrlOption pHost is null"); 1326518678f8Sopenharmony_ci } 1327518678f8Sopenharmony_ci return REPLY_ACK; 1328518678f8Sopenharmony_ci} 1329518678f8Sopenharmony_ci 1330518678f8Sopenharmony_ciint ParseDhcpOption(PDhcpMsgInfo received, AddressBinding *bindin) 1331518678f8Sopenharmony_ci{ 1332518678f8Sopenharmony_ci if (!bindin) { 1333518678f8Sopenharmony_ci DHCP_LOGE("ParseDhcpOption bindin is nullptr!"); 1334518678f8Sopenharmony_ci return REPLY_NONE; 1335518678f8Sopenharmony_ci } 1336518678f8Sopenharmony_ci DHCP_LOGE("enter ParseDhcpOption"); 1337518678f8Sopenharmony_ci GetHostNameOption(received, bindin); 1338518678f8Sopenharmony_ci GetVendorIdentifierOption(received); 1339518678f8Sopenharmony_ci GetUserClassOption(received, bindin); 1340518678f8Sopenharmony_ci GetRapidCommitOption(received, bindin); 1341518678f8Sopenharmony_ci GetOnlyIpv6Option(received, bindin); 1342518678f8Sopenharmony_ci GetPortalUrlOption(received, bindin); 1343518678f8Sopenharmony_ci return REPLY_ACK; 1344518678f8Sopenharmony_ci} 1345518678f8Sopenharmony_ci 1346518678f8Sopenharmony_cistatic int OnReceivedRequest(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply) 1347518678f8Sopenharmony_ci{ 1348518678f8Sopenharmony_ci int ret; 1349518678f8Sopenharmony_ci uint32_t yourIpAddr; 1350518678f8Sopenharmony_ci if ((ret = ValidateRequestMessage(ctx, received, reply, &yourIpAddr)) != REPLY_ACK) { 1351518678f8Sopenharmony_ci DHCP_LOGE("Request validateRequestMessage ret:%{public}d", ret); 1352518678f8Sopenharmony_ci return ret; 1353518678f8Sopenharmony_ci } 1354518678f8Sopenharmony_ci ServerContext *srvIns = GetServerInstance(ctx); 1355518678f8Sopenharmony_ci if (srvIns == nullptr) { 1356518678f8Sopenharmony_ci DHCP_LOGE("OnReceivedRequest, srvIns is null"); 1357518678f8Sopenharmony_ci return REPLY_NONE; 1358518678f8Sopenharmony_ci } 1359518678f8Sopenharmony_ci AddressBinding *binding = srvIns->addressPool.binding(received->packet.chaddr, &received->options); 1360518678f8Sopenharmony_ci if (binding == nullptr) { 1361518678f8Sopenharmony_ci DHCP_LOGI("Request enter HasNobindgRequest!"); 1362518678f8Sopenharmony_ci return HasNobindgRequest(ctx, received, reply); 1363518678f8Sopenharmony_ci } 1364518678f8Sopenharmony_ci Rebinding(&srvIns->addressPool, binding); 1365518678f8Sopenharmony_ci AddressBinding *lease = GetLease(&srvIns->addressPool, yourIpAddr); 1366518678f8Sopenharmony_ci if (lease) { 1367518678f8Sopenharmony_ci ParseDhcpOption(received, lease); 1368518678f8Sopenharmony_ci DHCP_LOGI("request in lease, yourIpAddr:%{public}s, mac:%{public}s", 1369518678f8Sopenharmony_ci OHOS::DHCP::IntIpv4ToAnonymizeStr(yourIpAddr).c_str(), ParseLogMac(lease->chaddr)); 1370518678f8Sopenharmony_ci int sameAddr = AddrEquels(lease->chaddr, received->packet.chaddr, MAC_ADDR_LENGTH); 1371518678f8Sopenharmony_ci if (!sameAddr && !IsExpire(lease)) { 1372518678f8Sopenharmony_ci DHCP_LOGW("invalid request ip address, reply nak, sameAddr:%{public}d", sameAddr); 1373518678f8Sopenharmony_ci return REPLY_NAK; 1374518678f8Sopenharmony_ci } 1375518678f8Sopenharmony_ci if (!sameAddr && IsExpire(lease)) { 1376518678f8Sopenharmony_ci if (memcpy_s(lease->chaddr, DHCP_HWADDR_LENGTH, binding->chaddr, MAC_ADDR_LENGTH) != EOK) { 1377518678f8Sopenharmony_ci DHCP_LOGW("failed to update lease client address, sameAddr:%{public}d", sameAddr); 1378518678f8Sopenharmony_ci } 1379518678f8Sopenharmony_ci } 1380518678f8Sopenharmony_ci lease->bindingStatus = BIND_ASSOCIATED; 1381518678f8Sopenharmony_ci lease->bindingTime = binding->bindingTime; 1382518678f8Sopenharmony_ci lease->expireIn = binding->expireIn; 1383518678f8Sopenharmony_ci DHCP_LOGI("Request found lease recoder, sameAddr:%{public}d", sameAddr); 1384518678f8Sopenharmony_ci } else { 1385518678f8Sopenharmony_ci DHCP_LOGW("Request can not found lease recoder."); 1386518678f8Sopenharmony_ci } 1387518678f8Sopenharmony_ci uint32_t bindingIp = binding->ipAddress; 1388518678f8Sopenharmony_ci if (bindingIp && yourIpAddr != INADDR_BROADCAST && yourIpAddr != bindingIp) { 1389518678f8Sopenharmony_ci DHCP_LOGE("error request ip binding. reply nak"); 1390518678f8Sopenharmony_ci return REPLY_NAK; 1391518678f8Sopenharmony_ci } 1392518678f8Sopenharmony_ci reply->packet.yiaddr = bindingIp; 1393518678f8Sopenharmony_ci ReplyCommontOption(ctx, reply); 1394518678f8Sopenharmony_ci DHCP_LOGI("Request reply ack!"); 1395518678f8Sopenharmony_ci return REPLY_ACK; 1396518678f8Sopenharmony_ci} 1397518678f8Sopenharmony_ci 1398518678f8Sopenharmony_cistatic int OnReceivedDecline(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply) 1399518678f8Sopenharmony_ci{ 1400518678f8Sopenharmony_ci if (!received || !reply) { 1401518678f8Sopenharmony_ci return REPLY_NONE; 1402518678f8Sopenharmony_ci } 1403518678f8Sopenharmony_ci ServerContext *srvIns = GetServerInstance(ctx); 1404518678f8Sopenharmony_ci if (!srvIns) { 1405518678f8Sopenharmony_ci return REPLY_NONE; 1406518678f8Sopenharmony_ci } 1407518678f8Sopenharmony_ci DHCP_LOGI("received 'Decline' message from: %s.", ParseLogMac(received->packet.chaddr)); 1408518678f8Sopenharmony_ci uint32_t reqIp = 0; 1409518678f8Sopenharmony_ci PDhcpOption optReqIp = GetOption(&received->options, REQUESTED_IP_ADDRESS_OPTION); 1410518678f8Sopenharmony_ci if (optReqIp) { 1411518678f8Sopenharmony_ci reqIp = ParseIp(optReqIp->data); 1412518678f8Sopenharmony_ci } 1413518678f8Sopenharmony_ci if (!reqIp) { 1414518678f8Sopenharmony_ci DHCP_LOGD("invalid request ip address."); 1415518678f8Sopenharmony_ci return REPLY_NONE; 1416518678f8Sopenharmony_ci } 1417518678f8Sopenharmony_ci AddressBinding* binding = srvIns->addressPool.binding(received->packet.chaddr, &received->options); 1418518678f8Sopenharmony_ci if (!binding) { 1419518678f8Sopenharmony_ci DHCP_LOGD("client not binding."); 1420518678f8Sopenharmony_ci return REPLY_NONE; 1421518678f8Sopenharmony_ci } 1422518678f8Sopenharmony_ci if (binding->ipAddress != reqIp) { 1423518678f8Sopenharmony_ci DHCP_LOGD("invalid request ip address."); 1424518678f8Sopenharmony_ci return REPLY_NONE; 1425518678f8Sopenharmony_ci } 1426518678f8Sopenharmony_ci if (srvIns->addressPool.leaseTable.count(reqIp) > 0) { 1427518678f8Sopenharmony_ci AddressBinding *lease = &srvIns->addressPool.leaseTable[reqIp]; 1428518678f8Sopenharmony_ci if (lease) { 1429518678f8Sopenharmony_ci lease->bindingStatus = BIND_MODE_RESERVED; 1430518678f8Sopenharmony_ci lease->expireIn = Tmspsec() + lease->leaseTime; 1431518678f8Sopenharmony_ci } else { 1432518678f8Sopenharmony_ci DHCP_LOGE("failed to get lease info."); 1433518678f8Sopenharmony_ci } 1434518678f8Sopenharmony_ci } 1435518678f8Sopenharmony_ci RemoveBinding(received->packet.chaddr); 1436518678f8Sopenharmony_ci return REPLY_NONE; 1437518678f8Sopenharmony_ci} 1438518678f8Sopenharmony_ci 1439518678f8Sopenharmony_cistatic int OnReceivedRelease(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply) 1440518678f8Sopenharmony_ci{ 1441518678f8Sopenharmony_ci if (!received || !reply) { 1442518678f8Sopenharmony_ci return REPLY_NONE; 1443518678f8Sopenharmony_ci } 1444518678f8Sopenharmony_ci DHCP_LOGI("received 'Release' message from: %s", ParseLogMac(received->packet.chaddr)); 1445518678f8Sopenharmony_ci if (!ctx || !ctx->instance) { 1446518678f8Sopenharmony_ci return RET_FAILED; 1447518678f8Sopenharmony_ci } 1448518678f8Sopenharmony_ci PDhcpOption optReqIp = GetOption(&received->options, REQUESTED_IP_ADDRESS_OPTION); 1449518678f8Sopenharmony_ci if (!optReqIp) { 1450518678f8Sopenharmony_ci DHCP_LOGW("missing required request option."); 1451518678f8Sopenharmony_ci } 1452518678f8Sopenharmony_ci ServerContext *srvIns = GetServerInstance(ctx); 1453518678f8Sopenharmony_ci if (!srvIns) { 1454518678f8Sopenharmony_ci DHCP_LOGE("dhcp server context pointer is null."); 1455518678f8Sopenharmony_ci return RET_FAILED; 1456518678f8Sopenharmony_ci } 1457518678f8Sopenharmony_ci AddressBinding *binding = srvIns->addressPool.binding(received->packet.chaddr, &received->options); 1458518678f8Sopenharmony_ci if (!binding) { 1459518678f8Sopenharmony_ci DHCP_LOGD("client not binding."); 1460518678f8Sopenharmony_ci return REPLY_NONE; 1461518678f8Sopenharmony_ci } 1462518678f8Sopenharmony_ci uint32_t bindIp = binding->ipAddress; 1463518678f8Sopenharmony_ci uint32_t reqIp = 0; 1464518678f8Sopenharmony_ci if (optReqIp) { 1465518678f8Sopenharmony_ci reqIp = ParseIp(optReqIp->data); 1466518678f8Sopenharmony_ci } 1467518678f8Sopenharmony_ci uint32_t srcIp = SourceIpAddress(); 1468518678f8Sopenharmony_ci if (srcIp != 0 && reqIp != 0 && reqIp != srcIp) { 1469518678f8Sopenharmony_ci DHCP_LOGE("error release message, invalid request ip address."); 1470518678f8Sopenharmony_ci return REPLY_NONE; 1471518678f8Sopenharmony_ci } 1472518678f8Sopenharmony_ci if (bindIp != 0 && reqIp != 0 && reqIp != bindIp) { 1473518678f8Sopenharmony_ci DHCP_LOGE("error release message, invalid request ip address."); 1474518678f8Sopenharmony_ci return REPLY_NONE; 1475518678f8Sopenharmony_ci } 1476518678f8Sopenharmony_ci AddressBinding *lease = GetLease(&srvIns->addressPool, bindIp); 1477518678f8Sopenharmony_ci if (lease) { 1478518678f8Sopenharmony_ci RemoveLease(&srvIns->addressPool, lease); 1479518678f8Sopenharmony_ci DHCP_LOGD("lease recoder has been removed."); 1480518678f8Sopenharmony_ci } else { 1481518678f8Sopenharmony_ci DHCP_LOGW("can't found lease recoder."); 1482518678f8Sopenharmony_ci } 1483518678f8Sopenharmony_ci 1484518678f8Sopenharmony_ci if (ReleaseBinding(received->packet.chaddr) != RET_SUCCESS) { 1485518678f8Sopenharmony_ci DHCP_LOGW("failed to release client[%s] bind.", ParseLogMac(received->packet.chaddr)); 1486518678f8Sopenharmony_ci } 1487518678f8Sopenharmony_ci DHCP_LOGD("client released."); 1488518678f8Sopenharmony_ci return REPLY_NONE; 1489518678f8Sopenharmony_ci} 1490518678f8Sopenharmony_ci 1491518678f8Sopenharmony_cistatic int OnReceivedInform(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply) 1492518678f8Sopenharmony_ci{ 1493518678f8Sopenharmony_ci if (!received || !reply) { 1494518678f8Sopenharmony_ci return REPLY_NONE; 1495518678f8Sopenharmony_ci } 1496518678f8Sopenharmony_ci ServerContext *srvIns = GetServerInstance(ctx); 1497518678f8Sopenharmony_ci if (!srvIns) { 1498518678f8Sopenharmony_ci DHCP_LOGE("dhcp server context pointer is null."); 1499518678f8Sopenharmony_ci return RET_FAILED; 1500518678f8Sopenharmony_ci } 1501518678f8Sopenharmony_ci DHCP_LOGI("received 'Inform' message from: %s", ParseLogMac(received->packet.chaddr)); 1502518678f8Sopenharmony_ci if (IsEmptyHWAddr(received->packet.chaddr)) { 1503518678f8Sopenharmony_ci DHCP_LOGD("error dhcp 'Inform' message."); 1504518678f8Sopenharmony_ci } 1505518678f8Sopenharmony_ci return REPLY_ACK; 1506518678f8Sopenharmony_ci} 1507518678f8Sopenharmony_ci 1508518678f8Sopenharmony_cistatic int AppendFixedOptions(PDhcpServerContext ctx, PDhcpMsgInfo reply) 1509518678f8Sopenharmony_ci{ 1510518678f8Sopenharmony_ci ServerContext *srvIns = GetServerInstance(ctx); 1511518678f8Sopenharmony_ci if (!srvIns) { 1512518678f8Sopenharmony_ci return RET_FAILED; 1513518678f8Sopenharmony_ci } 1514518678f8Sopenharmony_ci if (!reply) { 1515518678f8Sopenharmony_ci return RET_FAILED; 1516518678f8Sopenharmony_ci } 1517518678f8Sopenharmony_ci if (srvIns->addressPool.fixedOptions.size > 0) { 1518518678f8Sopenharmony_ci DhcpOptionNode *pNode = srvIns->addressPool.fixedOptions.first->next; 1519518678f8Sopenharmony_ci for (size_t i = 0; pNode != nullptr && i < srvIns->addressPool.fixedOptions.size; i++) { 1520518678f8Sopenharmony_ci PDhcpOption opt = nullptr; 1521518678f8Sopenharmony_ci if (pNode->option.code) { 1522518678f8Sopenharmony_ci opt = GetOption(&reply->options, pNode->option.code); 1523518678f8Sopenharmony_ci } 1524518678f8Sopenharmony_ci if (opt == nullptr) { 1525518678f8Sopenharmony_ci PushBackOption(&reply->options, &pNode->option); 1526518678f8Sopenharmony_ci } 1527518678f8Sopenharmony_ci pNode = pNode->next; 1528518678f8Sopenharmony_ci } 1529518678f8Sopenharmony_ci } 1530518678f8Sopenharmony_ci return RET_SUCCESS; 1531518678f8Sopenharmony_ci} 1532518678f8Sopenharmony_ciint AppendReplyTypeOption(PDhcpMsgInfo reply, int replyType) 1533518678f8Sopenharmony_ci{ 1534518678f8Sopenharmony_ci if (!reply) { 1535518678f8Sopenharmony_ci return RET_FAILED; 1536518678f8Sopenharmony_ci } 1537518678f8Sopenharmony_ci if (!replyType) { 1538518678f8Sopenharmony_ci return RET_FAILED; 1539518678f8Sopenharmony_ci } 1540518678f8Sopenharmony_ci uint8_t msgType = 0; 1541518678f8Sopenharmony_ci switch (replyType) { 1542518678f8Sopenharmony_ci case REPLY_OFFER: 1543518678f8Sopenharmony_ci msgType = DHCPOFFER; 1544518678f8Sopenharmony_ci break; 1545518678f8Sopenharmony_ci case REPLY_ACK: 1546518678f8Sopenharmony_ci msgType = DHCPACK; 1547518678f8Sopenharmony_ci break; 1548518678f8Sopenharmony_ci case REPLY_NAK: 1549518678f8Sopenharmony_ci msgType = DHCPNAK; 1550518678f8Sopenharmony_ci break; 1551518678f8Sopenharmony_ci default: 1552518678f8Sopenharmony_ci break; 1553518678f8Sopenharmony_ci } 1554518678f8Sopenharmony_ci PDhcpOption pOptMsgType = GetOption(&reply->options, DHCP_MESSAGE_TYPE_OPTION); 1555518678f8Sopenharmony_ci if (!pOptMsgType) { 1556518678f8Sopenharmony_ci DHCP_LOGD("append message type option for reply message, type:%hhu", msgType); 1557518678f8Sopenharmony_ci DhcpOption optMsgType = {DHCP_MESSAGE_TYPE_OPTION, OPT_MESSAGE_TYPE_LEGTH, {msgType, 0}}; 1558518678f8Sopenharmony_ci PushFrontOption(&reply->options, &optMsgType); 1559518678f8Sopenharmony_ci } else { 1560518678f8Sopenharmony_ci if (pOptMsgType->data[0] != msgType) { 1561518678f8Sopenharmony_ci DHCP_LOGD("error dhcp nak message type."); 1562518678f8Sopenharmony_ci return RET_FAILED; 1563518678f8Sopenharmony_ci } 1564518678f8Sopenharmony_ci } 1565518678f8Sopenharmony_ci return RET_SUCCESS; 1566518678f8Sopenharmony_ci} 1567518678f8Sopenharmony_ci 1568518678f8Sopenharmony_cistatic int SendDhcpOffer(PDhcpServerContext ctx, PDhcpMsgInfo reply) 1569518678f8Sopenharmony_ci{ 1570518678f8Sopenharmony_ci ServerContext *srvIns = GetServerInstance(ctx); 1571518678f8Sopenharmony_ci if (!srvIns) { 1572518678f8Sopenharmony_ci DHCP_LOGE("failed to get server instance"); 1573518678f8Sopenharmony_ci return RET_FAILED; 1574518678f8Sopenharmony_ci } 1575518678f8Sopenharmony_ci if (AppendReplyTypeOption(reply, REPLY_OFFER) != RET_SUCCESS) { 1576518678f8Sopenharmony_ci DHCP_LOGE("failed to append reply type options"); 1577518678f8Sopenharmony_ci return RET_FAILED; 1578518678f8Sopenharmony_ci } 1579518678f8Sopenharmony_ci if (AppendReplyTimeOptions(ctx, &reply->options) != RET_SUCCESS || 1580518678f8Sopenharmony_ci AddReplyServerIdOption(&reply->options, srvIns->addressPool.serverId) != RET_SUCCESS) { 1581518678f8Sopenharmony_ci DHCP_LOGE("failed to append reply time options"); 1582518678f8Sopenharmony_ci return RET_FAILED; 1583518678f8Sopenharmony_ci } 1584518678f8Sopenharmony_ci if (AppendFixedOptions(ctx, reply) != RET_SUCCESS) { 1585518678f8Sopenharmony_ci DHCP_LOGW("failed to append fixed reply options."); 1586518678f8Sopenharmony_ci } 1587518678f8Sopenharmony_ci if (ParseReplyOptions(reply) != RET_SUCCESS) { 1588518678f8Sopenharmony_ci DHCP_LOGE("failed to parse reply options."); 1589518678f8Sopenharmony_ci return RET_FAILED; 1590518678f8Sopenharmony_ci } 1591518678f8Sopenharmony_ci int ret; 1592518678f8Sopenharmony_ci struct sockaddr_in *bcastAddrIn = BroadcastAddrIn(); 1593518678f8Sopenharmony_ci struct sockaddr_in *destAddrIn = DestinationAddrIn(); 1594518678f8Sopenharmony_ci if (srvIns->broadCastFlagEnable == 1 && destAddrIn) { 1595518678f8Sopenharmony_ci int broadCastFlag = 1; 1596518678f8Sopenharmony_ci if (reply->packet.flags && (reply->packet.flags >> (DHCP_MESSAGE_FLAG_LENGTH - 1)) == 0) { 1597518678f8Sopenharmony_ci broadCastFlag = 0; 1598518678f8Sopenharmony_ci } 1599518678f8Sopenharmony_ci if (!broadCastFlag && destAddrIn->sin_addr.s_addr) { 1600518678f8Sopenharmony_ci ret = sendto(srvIns->serverFd, &reply->packet, reply->length, 0, (struct sockaddr *)destAddrIn, 1601518678f8Sopenharmony_ci sizeof(*destAddrIn)); 1602518678f8Sopenharmony_ci } else { 1603518678f8Sopenharmony_ci ret = sendto(srvIns->serverFd, &reply->packet, reply->length, 0, (struct sockaddr *)bcastAddrIn, 1604518678f8Sopenharmony_ci sizeof(*bcastAddrIn)); 1605518678f8Sopenharmony_ci } 1606518678f8Sopenharmony_ci } else { 1607518678f8Sopenharmony_ci ret = sendto( 1608518678f8Sopenharmony_ci srvIns->serverFd, &reply->packet, reply->length, 0, (struct sockaddr *)bcastAddrIn, sizeof(*bcastAddrIn)); 1609518678f8Sopenharmony_ci } 1610518678f8Sopenharmony_ci if (!ret) { 1611518678f8Sopenharmony_ci DHCP_LOGD("failed to send dhcp offer message."); 1612518678f8Sopenharmony_ci return RET_FAILED; 1613518678f8Sopenharmony_ci } 1614518678f8Sopenharmony_ci DHCP_LOGI("send reply offer, length:%d", reply->length); 1615518678f8Sopenharmony_ci return RET_SUCCESS; 1616518678f8Sopenharmony_ci} 1617518678f8Sopenharmony_ci 1618518678f8Sopenharmony_cistatic int SendDhcpAck(PDhcpServerContext ctx, PDhcpMsgInfo reply) 1619518678f8Sopenharmony_ci{ 1620518678f8Sopenharmony_ci if (AppendReplyTypeOption(reply, REPLY_ACK) != RET_SUCCESS) { 1621518678f8Sopenharmony_ci DHCP_LOGE("failed to append reply type options"); 1622518678f8Sopenharmony_ci return RET_FAILED; 1623518678f8Sopenharmony_ci } 1624518678f8Sopenharmony_ci if (AppendFixedOptions(ctx, reply) != RET_SUCCESS) { 1625518678f8Sopenharmony_ci DHCP_LOGW("failed to append fixed reply options."); 1626518678f8Sopenharmony_ci } 1627518678f8Sopenharmony_ci if (!ctx || !ctx->instance) { 1628518678f8Sopenharmony_ci DHCP_LOGE("dhcp server context pointer is null."); 1629518678f8Sopenharmony_ci return RET_FAILED; 1630518678f8Sopenharmony_ci } 1631518678f8Sopenharmony_ci ServerContext *srvIns = GetServerInstance(ctx); 1632518678f8Sopenharmony_ci 1633518678f8Sopenharmony_ci if (AppendReplyTimeOptions(ctx, &reply->options) != RET_SUCCESS) { 1634518678f8Sopenharmony_ci DHCP_LOGE("failed to append reply time options"); 1635518678f8Sopenharmony_ci return RET_FAILED; 1636518678f8Sopenharmony_ci } 1637518678f8Sopenharmony_ci if (AddReplyServerIdOption(&reply->options, srvIns->addressPool.serverId) != RET_SUCCESS) { 1638518678f8Sopenharmony_ci DHCP_LOGE("failed to add reply server options"); 1639518678f8Sopenharmony_ci return RET_FAILED; 1640518678f8Sopenharmony_ci } 1641518678f8Sopenharmony_ci if (ParseReplyOptions(reply) != RET_SUCCESS) { 1642518678f8Sopenharmony_ci DHCP_LOGE("failed to parse reply options"); 1643518678f8Sopenharmony_ci return RET_FAILED; 1644518678f8Sopenharmony_ci } 1645518678f8Sopenharmony_ci sockaddr_in *destAddrIn = DestinationAddrIn(); 1646518678f8Sopenharmony_ci int ret = sendto(srvIns->serverFd, &reply->packet, reply->length, 0, (struct sockaddr *)destAddrIn, 1647518678f8Sopenharmony_ci sizeof(*destAddrIn)); 1648518678f8Sopenharmony_ci if (!ret) { 1649518678f8Sopenharmony_ci DHCP_LOGD("failed to send dhcp ack message."); 1650518678f8Sopenharmony_ci return RET_FAILED; 1651518678f8Sopenharmony_ci } 1652518678f8Sopenharmony_ci DHCP_LOGI("send reply ack, size:%d", reply->length); 1653518678f8Sopenharmony_ci return RET_SUCCESS; 1654518678f8Sopenharmony_ci} 1655518678f8Sopenharmony_ci 1656518678f8Sopenharmony_cistatic int SendDhcpNak(PDhcpServerContext ctx, PDhcpMsgInfo reply) 1657518678f8Sopenharmony_ci{ 1658518678f8Sopenharmony_ci if (AppendReplyTypeOption(reply, REPLY_NAK) != RET_SUCCESS) { 1659518678f8Sopenharmony_ci DHCP_LOGE("failed to append reply type options"); 1660518678f8Sopenharmony_ci return RET_FAILED; 1661518678f8Sopenharmony_ci } 1662518678f8Sopenharmony_ci ServerContext *srvIns = GetServerInstance(ctx); 1663518678f8Sopenharmony_ci if (srvIns == nullptr) { 1664518678f8Sopenharmony_ci DHCP_LOGE("SendDhcpNak, srvIns is null"); 1665518678f8Sopenharmony_ci return RET_FAILED; 1666518678f8Sopenharmony_ci } 1667518678f8Sopenharmony_ci if (AddReplyServerIdOption(&reply->options, srvIns->addressPool.serverId) != RET_SUCCESS) { 1668518678f8Sopenharmony_ci DHCP_LOGE("SendDhcpNak serverId fail!"); 1669518678f8Sopenharmony_ci return RET_FAILED; 1670518678f8Sopenharmony_ci } 1671518678f8Sopenharmony_ci DhcpOption optVendorInfo = {MESSAGE_OPTION, static_cast<uint8_t>(strlen("wrong network")), "wrong network"}; 1672518678f8Sopenharmony_ci PushBackOption(&reply->options, &optVendorInfo); 1673518678f8Sopenharmony_ci if (ParseReplyOptions(reply) != RET_SUCCESS) { 1674518678f8Sopenharmony_ci DHCP_LOGE("failed to parse reply options"); 1675518678f8Sopenharmony_ci return RET_FAILED; 1676518678f8Sopenharmony_ci } 1677518678f8Sopenharmony_ci 1678518678f8Sopenharmony_ci struct sockaddr_in *destAddrIn = BroadcastAddrIn(); 1679518678f8Sopenharmony_ci int ret = sendto(srvIns->serverFd, &reply->packet, reply->length, 0, (struct sockaddr *)destAddrIn, 1680518678f8Sopenharmony_ci sizeof(*destAddrIn)); 1681518678f8Sopenharmony_ci if (!ret) { 1682518678f8Sopenharmony_ci DHCP_LOGD("failed to send dhcp ack message."); 1683518678f8Sopenharmony_ci return RET_FAILED; 1684518678f8Sopenharmony_ci } 1685518678f8Sopenharmony_ci DHCP_LOGI("send reply nak, size:%d", reply->length); 1686518678f8Sopenharmony_ci return RET_SUCCESS; 1687518678f8Sopenharmony_ci} 1688518678f8Sopenharmony_ci 1689518678f8Sopenharmony_cistatic int ParseMessageOptions(PDhcpMsgInfo msg) 1690518678f8Sopenharmony_ci{ 1691518678f8Sopenharmony_ci DHCP_LOGI("start %{public}s %{public}d", __func__, __LINE__); 1692518678f8Sopenharmony_ci if (msg->length < (DHCP_MSG_HEADER_SIZE + MAGIC_COOKIE_LENGTH)) { 1693518678f8Sopenharmony_ci return RET_FAILED; 1694518678f8Sopenharmony_ci } 1695518678f8Sopenharmony_ci DhcpOption *current, *end; 1696518678f8Sopenharmony_ci current = (DhcpOption *)msg->packet.options; 1697518678f8Sopenharmony_ci end = (DhcpOption *)(((uint8_t *)msg->packet.options) + (msg->length - DHCP_MSG_HEADER_SIZE)); 1698518678f8Sopenharmony_ci 1699518678f8Sopenharmony_ci if (memcmp(current, MAGIC_COOKIE_DATA, sizeof(MAGIC_COOKIE_DATA)) != 0) { 1700518678f8Sopenharmony_ci DHCP_LOGD("bad magic cookie."); 1701518678f8Sopenharmony_ci return RET_FAILED; 1702518678f8Sopenharmony_ci } 1703518678f8Sopenharmony_ci 1704518678f8Sopenharmony_ci current = (DhcpOption *)(((uint8_t *)current) + MAGIC_COOKIE_LENGTH); 1705518678f8Sopenharmony_ci uint8_t *pos = (((uint8_t *)current) + MAGIC_COOKIE_LENGTH); 1706518678f8Sopenharmony_ci uint8_t *maxPos = (((uint8_t *)current) + (DHCP_OPTION_SIZE - MAGIC_COOKIE_LENGTH - OPT_HEADER_LENGTH -1)); 1707518678f8Sopenharmony_ci int optTotal = 0; 1708518678f8Sopenharmony_ci while (current < end && current->code != END_OPTION) { 1709518678f8Sopenharmony_ci if (((uint8_t *)end) - ((uint8_t *)current) < OPT_HEADER_LENGTH) { 1710518678f8Sopenharmony_ci DHCP_LOGE("current->code out of option range."); 1711518678f8Sopenharmony_ci return RET_FAILED; 1712518678f8Sopenharmony_ci } 1713518678f8Sopenharmony_ci pos += (OPT_HEADER_LENGTH + current->length); 1714518678f8Sopenharmony_ci if (pos >= maxPos) { 1715518678f8Sopenharmony_ci DHCP_LOGD("out of option max pos."); 1716518678f8Sopenharmony_ci return RET_FAILED; 1717518678f8Sopenharmony_ci } 1718518678f8Sopenharmony_ci if (PushBackOption(&msg->options, current) != RET_SUCCESS) { 1719518678f8Sopenharmony_ci DHCP_LOGD("failed to PushOption."); 1720518678f8Sopenharmony_ci } 1721518678f8Sopenharmony_ci current = (DhcpOption *)(((uint8_t *)current) + OPT_HEADER_LENGTH + current->length); 1722518678f8Sopenharmony_ci optTotal++; 1723518678f8Sopenharmony_ci } 1724518678f8Sopenharmony_ci if (current < end && current->code == END_OPTION) { 1725518678f8Sopenharmony_ci DHCP_LOGD("option list size:%zu xid:%u", msg->options.size, msg->packet.xid); 1726518678f8Sopenharmony_ci return RET_SUCCESS; 1727518678f8Sopenharmony_ci } 1728518678f8Sopenharmony_ci 1729518678f8Sopenharmony_ci DHCP_LOGD("option list parse failed."); 1730518678f8Sopenharmony_ci return RET_FAILED; 1731518678f8Sopenharmony_ci} 1732518678f8Sopenharmony_ci 1733518678f8Sopenharmony_cistatic int ResetMessageOptions(PDhcpMsgInfo reply) 1734518678f8Sopenharmony_ci{ 1735518678f8Sopenharmony_ci if (!reply || reply->options.size == 0) { 1736518678f8Sopenharmony_ci DHCP_LOGE("message pointer is null."); 1737518678f8Sopenharmony_ci return RET_ERROR; 1738518678f8Sopenharmony_ci } 1739518678f8Sopenharmony_ci if (memset_s(reply->packet.options, DHCP_OPTIONS_SIZE, 0, DHCP_OPTIONS_SIZE) != EOK) { 1740518678f8Sopenharmony_ci DHCP_LOGE("failed to reset message options!"); 1741518678f8Sopenharmony_ci return RET_ERROR; 1742518678f8Sopenharmony_ci } 1743518678f8Sopenharmony_ci return RET_SUCCESS; 1744518678f8Sopenharmony_ci} 1745518678f8Sopenharmony_ci 1746518678f8Sopenharmony_cistatic int ValidateReplyOptions(PDhcpMsgInfo reply) 1747518678f8Sopenharmony_ci{ 1748518678f8Sopenharmony_ci if (!reply) { 1749518678f8Sopenharmony_ci DHCP_LOGE("reply message pointer is null."); 1750518678f8Sopenharmony_ci return RET_FAILED; 1751518678f8Sopenharmony_ci } 1752518678f8Sopenharmony_ci int ret = RET_FAILED; 1753518678f8Sopenharmony_ci if ((ret = ResetMessageOptions(reply)) != RET_SUCCESS) { 1754518678f8Sopenharmony_ci return ret; 1755518678f8Sopenharmony_ci } 1756518678f8Sopenharmony_ci reply->length = DHCP_MSG_HEADER_SIZE; 1757518678f8Sopenharmony_ci PDhcpOptionNode pNode = reply->options.first; 1758518678f8Sopenharmony_ci if (!pNode) { 1759518678f8Sopenharmony_ci return RET_ERROR; 1760518678f8Sopenharmony_ci } 1761518678f8Sopenharmony_ci PDhcpOption pOptMsgType = GetOption(&reply->options, DHCP_MESSAGE_TYPE_OPTION); 1762518678f8Sopenharmony_ci if (!pOptMsgType) { 1763518678f8Sopenharmony_ci DHCP_LOGE("unknown reply message type."); 1764518678f8Sopenharmony_ci return ret; 1765518678f8Sopenharmony_ci } 1766518678f8Sopenharmony_ci return RET_SUCCESS; 1767518678f8Sopenharmony_ci} 1768518678f8Sopenharmony_ci 1769518678f8Sopenharmony_cistatic int ParseReplyOptions(PDhcpMsgInfo reply) 1770518678f8Sopenharmony_ci{ 1771518678f8Sopenharmony_ci int ret = RET_FAILED; 1772518678f8Sopenharmony_ci if ((ret = ValidateReplyOptions(reply)) != RET_SUCCESS) { 1773518678f8Sopenharmony_ci return ret; 1774518678f8Sopenharmony_ci } 1775518678f8Sopenharmony_ci PDhcpOptionNode pNode = reply->options.first->next; 1776518678f8Sopenharmony_ci DhcpOption endOpt = {END_OPTION, 0, {0}}; 1777518678f8Sopenharmony_ci PushBackOption(&reply->options, &endOpt); 1778518678f8Sopenharmony_ci int replyOptsLength = 0; 1779518678f8Sopenharmony_ci uint8_t *current = reply->packet.options, olen = MAGIC_COOKIE_LENGTH; 1780518678f8Sopenharmony_ci size_t remainingSize = sizeof(reply->packet.options); 1781518678f8Sopenharmony_ci uint32_t cookie = htonl(DHCP_MAGIC_COOKIE); 1782518678f8Sopenharmony_ci if (memcpy_s(current, remainingSize, &cookie, olen) != EOK) { 1783518678f8Sopenharmony_ci DHCP_LOGE("memcpy cookie out of options buffer!"); 1784518678f8Sopenharmony_ci return RET_FAILED; 1785518678f8Sopenharmony_ci } 1786518678f8Sopenharmony_ci replyOptsLength += olen; 1787518678f8Sopenharmony_ci remainingSize -= olen; 1788518678f8Sopenharmony_ci current += olen; 1789518678f8Sopenharmony_ci ret = RET_SUCCESS; 1790518678f8Sopenharmony_ci while (pNode && (uint32_t)pNode->option.length < DHCP_OPTION_SIZE) { 1791518678f8Sopenharmony_ci if ((uint32_t)pNode->option.code == END_OPTION) { 1792518678f8Sopenharmony_ci olen = OPT_HEADER_LENGTH + 1; 1793518678f8Sopenharmony_ci } else { 1794518678f8Sopenharmony_ci olen = OPT_HEADER_LENGTH + pNode->option.length; 1795518678f8Sopenharmony_ci } 1796518678f8Sopenharmony_ci if (memcpy_s(current, remainingSize, &pNode->option, olen) != EOK) { 1797518678f8Sopenharmony_ci DHCP_LOGE("memcpy current option out of options buffer!"); 1798518678f8Sopenharmony_ci ret = RET_FAILED; 1799518678f8Sopenharmony_ci break; 1800518678f8Sopenharmony_ci } 1801518678f8Sopenharmony_ci remainingSize -= olen; 1802518678f8Sopenharmony_ci current += olen; 1803518678f8Sopenharmony_ci replyOptsLength += olen; 1804518678f8Sopenharmony_ci if ((uint32_t)pNode->option.code == END_OPTION) { 1805518678f8Sopenharmony_ci break; 1806518678f8Sopenharmony_ci } 1807518678f8Sopenharmony_ci pNode = pNode->next; 1808518678f8Sopenharmony_ci if (replyOptsLength >= DHCP_OPTIONS_SIZE) { 1809518678f8Sopenharmony_ci DHCP_LOGE("current option out of options buffer!"); 1810518678f8Sopenharmony_ci ret = RET_FAILED; 1811518678f8Sopenharmony_ci break; 1812518678f8Sopenharmony_ci } 1813518678f8Sopenharmony_ci } 1814518678f8Sopenharmony_ci reply->length += replyOptsLength; 1815518678f8Sopenharmony_ci return ret; 1816518678f8Sopenharmony_ci} 1817518678f8Sopenharmony_ci 1818518678f8Sopenharmony_civoid RegisterDhcpCallback(PDhcpServerContext ctx, DhcpServerCallback callback) 1819518678f8Sopenharmony_ci{ 1820518678f8Sopenharmony_ci DHCP_LOGI("start %{public}s %{public}d.", __func__, __LINE__); 1821518678f8Sopenharmony_ci ServerContext *srvIns = GetServerInstance(ctx); 1822518678f8Sopenharmony_ci if (!srvIns) { 1823518678f8Sopenharmony_ci DHCP_LOGE("dhcp server context pointer is null."); 1824518678f8Sopenharmony_ci return; 1825518678f8Sopenharmony_ci } 1826518678f8Sopenharmony_ci srvIns->callback = callback; 1827518678f8Sopenharmony_ci} 1828518678f8Sopenharmony_ci 1829518678f8Sopenharmony_civoid RegisterDeviceChangedCallback(PDhcpServerContext ctx, DeviceConnectFun func) 1830518678f8Sopenharmony_ci{ 1831518678f8Sopenharmony_ci DHCP_LOGI("start %{public}s %{public}d.", __func__, __LINE__); 1832518678f8Sopenharmony_ci ServerContext *srvIns = GetServerInstance(ctx); 1833518678f8Sopenharmony_ci if (!srvIns) { 1834518678f8Sopenharmony_ci DHCP_LOGE("dhcp server context pointer is null."); 1835518678f8Sopenharmony_ci return; 1836518678f8Sopenharmony_ci } 1837518678f8Sopenharmony_ci srvIns->deviceConnectFun = func; 1838518678f8Sopenharmony_ci} 1839518678f8Sopenharmony_ci 1840518678f8Sopenharmony_cistatic int InitServerContext(DhcpConfig *config, DhcpServerContext *ctx) 1841518678f8Sopenharmony_ci{ 1842518678f8Sopenharmony_ci if (!config) { 1843518678f8Sopenharmony_ci DHCP_LOGE("server configure pointer is null."); 1844518678f8Sopenharmony_ci return RET_FAILED; 1845518678f8Sopenharmony_ci } 1846518678f8Sopenharmony_ci ServerContext *srvIns = GetServerInstance(ctx); 1847518678f8Sopenharmony_ci if (!srvIns) { 1848518678f8Sopenharmony_ci DHCP_LOGE("dhcp server context pointer is null."); 1849518678f8Sopenharmony_ci return RET_FAILED; 1850518678f8Sopenharmony_ci } 1851518678f8Sopenharmony_ci if (InitAddressPool(&srvIns->addressPool, config->ifname, nullptr) != RET_SUCCESS) { 1852518678f8Sopenharmony_ci DHCP_LOGD("failed to init address pool."); 1853518678f8Sopenharmony_ci return RET_FAILED; 1854518678f8Sopenharmony_ci } 1855518678f8Sopenharmony_ci if (memcpy_s(ctx->ifname, sizeof(ctx->ifname), config->ifname, strlen(config->ifname)) != EOK) { 1856518678f8Sopenharmony_ci DHCP_LOGD("failed to set interface name."); 1857518678f8Sopenharmony_ci return RET_FAILED; 1858518678f8Sopenharmony_ci } 1859518678f8Sopenharmony_ci srvIns->serverFd = 0; 1860518678f8Sopenharmony_ci srvIns->callback = 0; 1861518678f8Sopenharmony_ci srvIns->looperState = LS_IDLE; 1862518678f8Sopenharmony_ci srvIns->broadCastFlagEnable = static_cast<int>(config->broadcast); 1863518678f8Sopenharmony_ci srvIns->addressPool.serverId = config->serverId; 1864518678f8Sopenharmony_ci srvIns->addressPool.netmask = config->netmask; 1865518678f8Sopenharmony_ci srvIns->addressPool.gateway = config->gateway; 1866518678f8Sopenharmony_ci if (config->pool.beginAddress && config->pool.endAddress) { 1867518678f8Sopenharmony_ci srvIns->addressPool.addressRange.beginAddress = config->pool.beginAddress; 1868518678f8Sopenharmony_ci srvIns->addressPool.addressRange.endAddress = config->pool.endAddress; 1869518678f8Sopenharmony_ci } else { 1870518678f8Sopenharmony_ci srvIns->addressPool.addressRange.beginAddress = FirstIpAddress(config->serverId, config->netmask); 1871518678f8Sopenharmony_ci srvIns->addressPool.addressRange.endAddress = LastIpAddress(config->serverId, config->netmask); 1872518678f8Sopenharmony_ci } 1873518678f8Sopenharmony_ci if (memcpy_s(srvIns->addressPool.ifname, sizeof(srvIns->addressPool.ifname), 1874518678f8Sopenharmony_ci config->ifname, strlen(config->ifname)) != EOK) { 1875518678f8Sopenharmony_ci DHCP_LOGD("failed to set interface name."); 1876518678f8Sopenharmony_ci return RET_FAILED; 1877518678f8Sopenharmony_ci } 1878518678f8Sopenharmony_ci if (!CheckAddressRange(&srvIns->addressPool)) { 1879518678f8Sopenharmony_ci DHCP_LOGE("failed to validate address range."); 1880518678f8Sopenharmony_ci return RET_FAILED; 1881518678f8Sopenharmony_ci } 1882518678f8Sopenharmony_ci InitLeaseFile(&srvIns->addressPool); 1883518678f8Sopenharmony_ci srvIns->addressPool.leaseTime = config->leaseTime; 1884518678f8Sopenharmony_ci srvIns->addressPool.renewalTime = config->renewalTime; 1885518678f8Sopenharmony_ci srvIns->addressPool.rebindingTime = config->rebindingTime; 1886518678f8Sopenharmony_ci return RET_SUCCESS; 1887518678f8Sopenharmony_ci} 1888518678f8Sopenharmony_ci 1889518678f8Sopenharmony_ciint InitServerFixedOptions(DhcpConfig *config, DhcpServerContext *ctx) 1890518678f8Sopenharmony_ci{ 1891518678f8Sopenharmony_ci if (!config) { 1892518678f8Sopenharmony_ci DHCP_LOGE("server configure pointer is null."); 1893518678f8Sopenharmony_ci return RET_FAILED; 1894518678f8Sopenharmony_ci } 1895518678f8Sopenharmony_ci ServerContext *srvIns = GetServerInstance(ctx); 1896518678f8Sopenharmony_ci if (!srvIns) { 1897518678f8Sopenharmony_ci DHCP_LOGE("dhcp server context pointer is null."); 1898518678f8Sopenharmony_ci return RET_FAILED; 1899518678f8Sopenharmony_ci } 1900518678f8Sopenharmony_ci 1901518678f8Sopenharmony_ci if (!HasInitialized(&config->options)) { 1902518678f8Sopenharmony_ci DHCP_LOGE("dhcp configure has not been initialized."); 1903518678f8Sopenharmony_ci return RET_FAILED; 1904518678f8Sopenharmony_ci } 1905518678f8Sopenharmony_ci if (InitOptionList(&srvIns->addressPool.fixedOptions) != RET_SUCCESS) { 1906518678f8Sopenharmony_ci return RET_FAILED; 1907518678f8Sopenharmony_ci } 1908518678f8Sopenharmony_ci if (config->options.first != nullptr && config->options.size > 0) { 1909518678f8Sopenharmony_ci DhcpOptionNode *pNode = config->options.first->next; 1910518678f8Sopenharmony_ci for (size_t i = 0; pNode != nullptr && i < config->options.size; i++) { 1911518678f8Sopenharmony_ci PushBackOption(&srvIns->addressPool.fixedOptions, &pNode->option); 1912518678f8Sopenharmony_ci DHCP_LOGD("append fixed option ==> %hhu,%d", pNode->option.code, 1913518678f8Sopenharmony_ci pNode->option.length); 1914518678f8Sopenharmony_ci pNode = pNode->next; 1915518678f8Sopenharmony_ci } 1916518678f8Sopenharmony_ci } 1917518678f8Sopenharmony_ci return RET_SUCCESS; 1918518678f8Sopenharmony_ci} 1919518678f8Sopenharmony_ci 1920518678f8Sopenharmony_ciPDhcpServerContext InitializeServer(DhcpConfig *config) 1921518678f8Sopenharmony_ci{ 1922518678f8Sopenharmony_ci DHCP_LOGI("start %{public}s %{public}d.", __func__, __LINE__); 1923518678f8Sopenharmony_ci DhcpServerContext *context = nullptr; 1924518678f8Sopenharmony_ci if (!config) { 1925518678f8Sopenharmony_ci DHCP_LOGE("dhcp server config pointer is null."); 1926518678f8Sopenharmony_ci return nullptr; 1927518678f8Sopenharmony_ci } 1928518678f8Sopenharmony_ci if (strlen(config->ifname) == 0) { 1929518678f8Sopenharmony_ci DHCP_LOGE("can't found interface name config."); 1930518678f8Sopenharmony_ci return nullptr; 1931518678f8Sopenharmony_ci } 1932518678f8Sopenharmony_ci if (!config->serverId || !config->netmask) { 1933518678f8Sopenharmony_ci DHCP_LOGE("missing required parameter or config item: \"serverId\", \"netmask\""); 1934518678f8Sopenharmony_ci return nullptr; 1935518678f8Sopenharmony_ci } 1936518678f8Sopenharmony_ci if ((context = (DhcpServerContext *)calloc(1, sizeof(DhcpServerContext))) == nullptr) { 1937518678f8Sopenharmony_ci DHCP_LOGE("failed to calloc server context."); 1938518678f8Sopenharmony_ci return nullptr; 1939518678f8Sopenharmony_ci } 1940518678f8Sopenharmony_ci if ((context->instance = (ServerContext *)calloc(1, sizeof(ServerContext))) == nullptr) { 1941518678f8Sopenharmony_ci DHCP_LOGE("failed to calloc server instance."); 1942518678f8Sopenharmony_ci FreeServerContext(&context); 1943518678f8Sopenharmony_ci return nullptr; 1944518678f8Sopenharmony_ci } 1945518678f8Sopenharmony_ci if (InitServerContext(config, context) != RET_SUCCESS) { 1946518678f8Sopenharmony_ci DHCP_LOGE("failed initialize dhcp server context."); 1947518678f8Sopenharmony_ci FreeServerContext(&context); 1948518678f8Sopenharmony_ci return nullptr; 1949518678f8Sopenharmony_ci } 1950518678f8Sopenharmony_ci if (InitServerFixedOptions(config, context) != RET_SUCCESS) { 1951518678f8Sopenharmony_ci DHCP_LOGE("failed initialize dhcp server fixed options."); 1952518678f8Sopenharmony_ci FreeServerContext(&context); 1953518678f8Sopenharmony_ci return nullptr; 1954518678f8Sopenharmony_ci } 1955518678f8Sopenharmony_ci DHCP_LOGI("server id: %{private}s", ParseStrIp(config->serverId)); 1956518678f8Sopenharmony_ci DHCP_LOGI("netmask: %{private}s", ParseStrIp(config->netmask)); 1957518678f8Sopenharmony_ci if (config->gateway) { 1958518678f8Sopenharmony_ci DHCP_LOGI("gateway: %{private}s", ParseStrIp(config->gateway)); 1959518678f8Sopenharmony_ci } 1960518678f8Sopenharmony_ci DHCP_LOGI("address range begin of: %{private}s", ParseStrIp(config->pool.beginAddress)); 1961518678f8Sopenharmony_ci DHCP_LOGI("address range end of: %{private}s", ParseStrIp(config->pool.endAddress)); 1962518678f8Sopenharmony_ci context->instance->initialized = 1; 1963518678f8Sopenharmony_ci return context; 1964518678f8Sopenharmony_ci} 1965518678f8Sopenharmony_ci 1966518678f8Sopenharmony_ciint FreeServerContext(PDhcpServerContext *ctx) 1967518678f8Sopenharmony_ci{ 1968518678f8Sopenharmony_ci if (ctx == nullptr || *ctx == nullptr) { 1969518678f8Sopenharmony_ci DHCP_LOGE("dhcp server context pointer is null."); 1970518678f8Sopenharmony_ci return RET_FAILED; 1971518678f8Sopenharmony_ci } 1972518678f8Sopenharmony_ci ServerContext *srvIns = GetServerInstance(*ctx); 1973518678f8Sopenharmony_ci if (!srvIns) { 1974518678f8Sopenharmony_ci DHCP_LOGE("dhcp server instance pointer is null."); 1975518678f8Sopenharmony_ci return RET_FAILED; 1976518678f8Sopenharmony_ci } 1977518678f8Sopenharmony_ci int times = 5; 1978518678f8Sopenharmony_ci while (srvIns->looperState != LS_STOPED && srvIns->looperState != LS_IDLE) { 1979518678f8Sopenharmony_ci DHCP_LOGE("FreeServerContext wait 300ms."); 1980518678f8Sopenharmony_ci usleep(300000); 1981518678f8Sopenharmony_ci times--; 1982518678f8Sopenharmony_ci if (times <= 0) { 1983518678f8Sopenharmony_ci return RET_FAILED; 1984518678f8Sopenharmony_ci } 1985518678f8Sopenharmony_ci } 1986518678f8Sopenharmony_ci FreeAddressPool(&srvIns->addressPool); 1987518678f8Sopenharmony_ci if ((*ctx)->instance != nullptr) { 1988518678f8Sopenharmony_ci free((*ctx)->instance); 1989518678f8Sopenharmony_ci (*ctx)->instance = nullptr; 1990518678f8Sopenharmony_ci } 1991518678f8Sopenharmony_ci free(*ctx); 1992518678f8Sopenharmony_ci *ctx = nullptr; 1993518678f8Sopenharmony_ci return RET_SUCCESS; 1994518678f8Sopenharmony_ci} 1995