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_address_pool.h" 17518678f8Sopenharmony_ci#include <map> 18518678f8Sopenharmony_ci#include <mutex> 19518678f8Sopenharmony_ci#include <securec.h> 20518678f8Sopenharmony_ci#include <stdint.h> 21518678f8Sopenharmony_ci#include <stdio.h> 22518678f8Sopenharmony_ci#include <string.h> 23518678f8Sopenharmony_ci#include "address_utils.h" 24518678f8Sopenharmony_ci#include "common_util.h" 25518678f8Sopenharmony_ci#include "dhcp_logger.h" 26518678f8Sopenharmony_ci 27518678f8Sopenharmony_ciDEFINE_DHCPLOG_DHCP_LABEL("DhcpServerAddressPool"); 28518678f8Sopenharmony_ci 29518678f8Sopenharmony_ci#define DHCP_POOL_INIT_SIZE 10 30518678f8Sopenharmony_ci#define DHCP_RELEASE_REMOVE_MODE 0 31518678f8Sopenharmony_ci 32518678f8Sopenharmony_cistatic int g_releaseRemoveMode = DHCP_RELEASE_REMOVE_MODE; 33518678f8Sopenharmony_cistatic std::map<std::size_t, AddressBinding> g_bindingRecoders; 34518678f8Sopenharmony_cistatic std::mutex g_bindingMapMutex; 35518678f8Sopenharmony_cistatic int g_distributeMode = 0; 36518678f8Sopenharmony_ci 37518678f8Sopenharmony_ci#define HASH_DEFAULT_VALUE 5381 38518678f8Sopenharmony_ci#define HASH_CAL_CODE_CAL 5 39518678f8Sopenharmony_ci//Write a HASH FUNCTION FOR uint8_t macAddr[DHCP_HWADDR_LENGTH] 40518678f8Sopenharmony_cistd::size_t macAddrHash(uint8_t macAddr[DHCP_HWADDR_LENGTH]) 41518678f8Sopenharmony_ci{ 42518678f8Sopenharmony_ci std::size_t hash = HASH_DEFAULT_VALUE; 43518678f8Sopenharmony_ci for (std::size_t i = 0; i < DHCP_HWADDR_LENGTH; ++i) { 44518678f8Sopenharmony_ci hash = ((hash << HASH_CAL_CODE_CAL) + hash) ^ static_cast<std::size_t>(macAddr[i]); 45518678f8Sopenharmony_ci } 46518678f8Sopenharmony_ci return hash; 47518678f8Sopenharmony_ci} 48518678f8Sopenharmony_ci 49518678f8Sopenharmony_ci 50518678f8Sopenharmony_ciAddressBinding *GetBindingByMac(uint8_t macAddr[DHCP_HWADDR_LENGTH]) 51518678f8Sopenharmony_ci{ 52518678f8Sopenharmony_ci std::size_t hash = macAddrHash(macAddr); 53518678f8Sopenharmony_ci std::lock_guard<std::mutex> autoLock(g_bindingMapMutex); 54518678f8Sopenharmony_ci if (g_bindingRecoders.count(hash) > 0) { 55518678f8Sopenharmony_ci return &g_bindingRecoders[hash]; 56518678f8Sopenharmony_ci } 57518678f8Sopenharmony_ci return nullptr; 58518678f8Sopenharmony_ci} 59518678f8Sopenharmony_ci 60518678f8Sopenharmony_ciAddressBinding *QueryBinding(uint8_t macAddr[DHCP_HWADDR_LENGTH], PDhcpOptionList cliOptins) 61518678f8Sopenharmony_ci{ 62518678f8Sopenharmony_ci return GetBindingByMac(macAddr); 63518678f8Sopenharmony_ci} 64518678f8Sopenharmony_ci 65518678f8Sopenharmony_ciAddressBinding *AddNewBinding(uint8_t macAddr[DHCP_HWADDR_LENGTH], PDhcpOptionList cliOptins) 66518678f8Sopenharmony_ci{ 67518678f8Sopenharmony_ci AddressBinding newBind = {0}; 68518678f8Sopenharmony_ci newBind.bindingMode = BIND_MODE_DYNAMIC; 69518678f8Sopenharmony_ci newBind.bindingStatus = BIND_PENDING; 70518678f8Sopenharmony_ci if (memcpy_s(newBind.chaddr, DHCP_HWADDR_LENGTH, macAddr, DHCP_HWADDR_LENGTH) != EOK) { 71518678f8Sopenharmony_ci DHCP_LOGE("newBind chaddr memcpy_s failed!"); 72518678f8Sopenharmony_ci return nullptr; 73518678f8Sopenharmony_ci } 74518678f8Sopenharmony_ci newBind.bindingTime = Tmspsec(); 75518678f8Sopenharmony_ci newBind.pendingTime = Tmspsec(); 76518678f8Sopenharmony_ci newBind.expireIn = newBind.bindingTime + DHCP_LEASE_TIME; 77518678f8Sopenharmony_ci newBind.leaseTime = DHCP_LEASE_TIME; 78518678f8Sopenharmony_ci { 79518678f8Sopenharmony_ci std::lock_guard<std::mutex> autoLock(g_bindingMapMutex); 80518678f8Sopenharmony_ci g_bindingRecoders[macAddrHash(macAddr)] = newBind; 81518678f8Sopenharmony_ci } 82518678f8Sopenharmony_ci return GetBindingByMac(macAddr); 83518678f8Sopenharmony_ci} 84518678f8Sopenharmony_ci 85518678f8Sopenharmony_ciint CheckIpAvailability(DhcpAddressPool *pool, uint8_t macAddr[DHCP_HWADDR_LENGTH], uint32_t distIp) 86518678f8Sopenharmony_ci{ 87518678f8Sopenharmony_ci if (!pool) { 88518678f8Sopenharmony_ci DHCP_LOGE("pool pointer is null."); 89518678f8Sopenharmony_ci return DHCP_FALSE; 90518678f8Sopenharmony_ci } 91518678f8Sopenharmony_ci if (IsReserved(macAddr)) { 92518678f8Sopenharmony_ci DHCP_LOGW("client address(%s) is reserved address.", ParseLogMac(macAddr)); 93518678f8Sopenharmony_ci return DHCP_FALSE; 94518678f8Sopenharmony_ci } 95518678f8Sopenharmony_ci AddressBinding *lease = GetLease(pool, distIp); 96518678f8Sopenharmony_ci if (lease) { 97518678f8Sopenharmony_ci int same = AddrEquels(lease->chaddr, macAddr, MAC_ADDR_LENGTH); 98518678f8Sopenharmony_ci if (distIp == pool->serverId || distIp == pool->gateway) { 99518678f8Sopenharmony_ci return DHCP_FALSE; 100518678f8Sopenharmony_ci } 101518678f8Sopenharmony_ci if (lease->bindingMode == BIND_MODE_STATIC && !same) { 102518678f8Sopenharmony_ci return DHCP_FALSE; 103518678f8Sopenharmony_ci } 104518678f8Sopenharmony_ci if (IsReservedIp(pool, distIp) && !same) { 105518678f8Sopenharmony_ci return DHCP_FALSE; 106518678f8Sopenharmony_ci } 107518678f8Sopenharmony_ci if (same) { 108518678f8Sopenharmony_ci lease->pendingTime = Tmspsec(); 109518678f8Sopenharmony_ci lease->bindingTime = lease->pendingTime; 110518678f8Sopenharmony_ci return DHCP_TRUE; 111518678f8Sopenharmony_ci } 112518678f8Sopenharmony_ci if (IsExpire(lease)) { 113518678f8Sopenharmony_ci DHCP_LOGD("the binding recoder has expired."); 114518678f8Sopenharmony_ci lease->pendingTime = Tmspsec(); 115518678f8Sopenharmony_ci lease->bindingTime = lease->pendingTime; 116518678f8Sopenharmony_ci RemoveBinding(lease->chaddr); 117518678f8Sopenharmony_ci if (memcpy_s(lease->chaddr, DHCP_HWADDR_LENGTH, macAddr, MAC_ADDR_LENGTH) != EOK) { 118518678f8Sopenharmony_ci DHCP_LOGD("failed to rewrite client address."); 119518678f8Sopenharmony_ci } 120518678f8Sopenharmony_ci return DHCP_TRUE; 121518678f8Sopenharmony_ci } 122518678f8Sopenharmony_ci return DHCP_FALSE; 123518678f8Sopenharmony_ci } 124518678f8Sopenharmony_ci return DHCP_TRUE; 125518678f8Sopenharmony_ci} 126518678f8Sopenharmony_ci 127518678f8Sopenharmony_ciint CheckRangeAvailability( 128518678f8Sopenharmony_ci DhcpAddressPool *pool, uint8_t macAddr[DHCP_HWADDR_LENGTH], uint32_t distIp, int *outOfRange) 129518678f8Sopenharmony_ci{ 130518678f8Sopenharmony_ci if (!pool || !pool->addressRange.beginAddress || !pool->addressRange.endAddress) { 131518678f8Sopenharmony_ci DHCP_LOGE("pool beginAddress or endAddress pointer is null."); 132518678f8Sopenharmony_ci return RET_ERROR; 133518678f8Sopenharmony_ci } 134518678f8Sopenharmony_ci if (!pool->netmask || IsEmptyHWAddr(macAddr)) { 135518678f8Sopenharmony_ci DHCP_LOGE("pool netmask empty hwaddr pointer is null."); 136518678f8Sopenharmony_ci return RET_ERROR; 137518678f8Sopenharmony_ci } 138518678f8Sopenharmony_ci uint32_t beginIp = pool->addressRange.beginAddress; 139518678f8Sopenharmony_ci uint32_t endIp = pool->addressRange.endAddress; 140518678f8Sopenharmony_ci if (IpInRange(distIp, beginIp, endIp, pool->netmask)) { 141518678f8Sopenharmony_ci DHCP_LOGD("distribution IP address"); 142518678f8Sopenharmony_ci AddressBinding lease = {0}; 143518678f8Sopenharmony_ci lease.pendingTime = Tmspsec(); 144518678f8Sopenharmony_ci lease.bindingMode = BIND_PENDING; 145518678f8Sopenharmony_ci lease.ipAddress = distIp; 146518678f8Sopenharmony_ci lease.bindingTime = lease.pendingTime; 147518678f8Sopenharmony_ci lease.leaseTime = pool->leaseTime; 148518678f8Sopenharmony_ci if (memcpy_s(lease.chaddr, sizeof(lease.chaddr), macAddr, MAC_ADDR_LENGTH) != EOK) { 149518678f8Sopenharmony_ci DHCP_LOGE("failed to set lease chaddr fields"); 150518678f8Sopenharmony_ci return RET_ERROR; 151518678f8Sopenharmony_ci } 152518678f8Sopenharmony_ci if (AddLease(pool, &lease) != RET_SUCCESS) { 153518678f8Sopenharmony_ci DHCP_LOGE("failed to add lease."); 154518678f8Sopenharmony_ci return RET_ERROR; 155518678f8Sopenharmony_ci } 156518678f8Sopenharmony_ci return RET_SUCCESS; 157518678f8Sopenharmony_ci } 158518678f8Sopenharmony_ci if (*outOfRange) { 159518678f8Sopenharmony_ci DHCP_LOGD("address is out of range"); 160518678f8Sopenharmony_ci return RET_FAILED; 161518678f8Sopenharmony_ci } else { 162518678f8Sopenharmony_ci *outOfRange = 1; 163518678f8Sopenharmony_ci } 164518678f8Sopenharmony_ci return RET_FAILED; 165518678f8Sopenharmony_ci} 166518678f8Sopenharmony_ci 167518678f8Sopenharmony_ciuint32_t NextIpOffset(uint32_t netmask) 168518678f8Sopenharmony_ci{ 169518678f8Sopenharmony_ci uint32_t offset = 0; 170518678f8Sopenharmony_ci if (g_distributeMode && netmask) { 171518678f8Sopenharmony_ci uint32_t total = HostTotal(netmask); 172518678f8Sopenharmony_ci if (total) { 173518678f8Sopenharmony_ci offset = Tmspusec() % total; 174518678f8Sopenharmony_ci } 175518678f8Sopenharmony_ci DHCP_LOGD("next ip offset is: %u", offset); 176518678f8Sopenharmony_ci } 177518678f8Sopenharmony_ci return offset; 178518678f8Sopenharmony_ci} 179518678f8Sopenharmony_ci 180518678f8Sopenharmony_ciuint32_t AddressDistribute(DhcpAddressPool *pool, uint8_t macAddr[DHCP_HWADDR_LENGTH]) 181518678f8Sopenharmony_ci{ 182518678f8Sopenharmony_ci if (!pool || !pool->addressRange.beginAddress || !pool->addressRange.endAddress) { 183518678f8Sopenharmony_ci return 0; 184518678f8Sopenharmony_ci } 185518678f8Sopenharmony_ci if (!pool->netmask || IsEmptyHWAddr(macAddr)) { 186518678f8Sopenharmony_ci return 0; 187518678f8Sopenharmony_ci } 188518678f8Sopenharmony_ci if (pool->distribution == 0) { 189518678f8Sopenharmony_ci pool->distribution = pool->addressRange.beginAddress; 190518678f8Sopenharmony_ci } 191518678f8Sopenharmony_ci uint32_t total = HostTotal(pool->netmask); 192518678f8Sopenharmony_ci uint32_t distIp = pool->distribution; 193518678f8Sopenharmony_ci if (!distIp || distIp < pool->addressRange.beginAddress) { 194518678f8Sopenharmony_ci distIp = pool->addressRange.beginAddress; 195518678f8Sopenharmony_ci } 196518678f8Sopenharmony_ci int distSucess = 0; 197518678f8Sopenharmony_ci int outOfRange = 0; 198518678f8Sopenharmony_ci for (uint32_t i = 0; i < total; i++) { 199518678f8Sopenharmony_ci uint32_t offset = 0; 200518678f8Sopenharmony_ci if (i == 0) { 201518678f8Sopenharmony_ci offset = NextIpOffset(pool->netmask); 202518678f8Sopenharmony_ci } 203518678f8Sopenharmony_ci distIp = NextIpAddress(distIp, pool->netmask, offset); 204518678f8Sopenharmony_ci if (!CheckIpAvailability(pool, macAddr, distIp)) { 205518678f8Sopenharmony_ci continue; 206518678f8Sopenharmony_ci } 207518678f8Sopenharmony_ci int ret = CheckRangeAvailability(pool, macAddr, distIp, &outOfRange); 208518678f8Sopenharmony_ci if (ret == RET_ERROR) { 209518678f8Sopenharmony_ci break; 210518678f8Sopenharmony_ci } 211518678f8Sopenharmony_ci if (ret == RET_SUCCESS) { 212518678f8Sopenharmony_ci distSucess = 1; 213518678f8Sopenharmony_ci break; 214518678f8Sopenharmony_ci } 215518678f8Sopenharmony_ci } 216518678f8Sopenharmony_ci if (!distSucess || !distIp) { 217518678f8Sopenharmony_ci return 0; 218518678f8Sopenharmony_ci } 219518678f8Sopenharmony_ci pool->distribution = distIp; 220518678f8Sopenharmony_ci return pool->distribution; 221518678f8Sopenharmony_ci} 222518678f8Sopenharmony_ci 223518678f8Sopenharmony_ciint InitAddressPool(DhcpAddressPool *pool, const char *ifname, PDhcpOptionList options) 224518678f8Sopenharmony_ci{ 225518678f8Sopenharmony_ci if (!pool) { 226518678f8Sopenharmony_ci DHCP_LOGD("address pool pointer is null."); 227518678f8Sopenharmony_ci return RET_ERROR; 228518678f8Sopenharmony_ci } 229518678f8Sopenharmony_ci if (memset_s(pool, sizeof(DhcpAddressPool), 0, sizeof(DhcpAddressPool)) != EOK) { 230518678f8Sopenharmony_ci DHCP_LOGD("failed to init dhcp pool."); 231518678f8Sopenharmony_ci return RET_ERROR; 232518678f8Sopenharmony_ci } 233518678f8Sopenharmony_ci if (memset_s(pool->ifname, IFACE_NAME_SIZE, '\0', IFACE_NAME_SIZE) != EOK) { 234518678f8Sopenharmony_ci DHCP_LOGD("failed to reset interface name."); 235518678f8Sopenharmony_ci return RET_ERROR; 236518678f8Sopenharmony_ci } 237518678f8Sopenharmony_ci if (strncpy_s(pool->ifname, IFACE_NAME_SIZE, ifname, strlen(ifname)) != EOK) { 238518678f8Sopenharmony_ci DHCP_LOGD("failed to set interface name."); 239518678f8Sopenharmony_ci return RET_ERROR; 240518678f8Sopenharmony_ci } 241518678f8Sopenharmony_ci if (InitOptionList(&pool->fixedOptions) != RET_SUCCESS) { 242518678f8Sopenharmony_ci DHCP_LOGD("failed to init options field for dhcp pool."); 243518678f8Sopenharmony_ci return RET_FAILED; 244518678f8Sopenharmony_ci } 245518678f8Sopenharmony_ci std::lock_guard<std::mutex> autoLock(g_bindingMapMutex); 246518678f8Sopenharmony_ci g_bindingRecoders.clear(); 247518678f8Sopenharmony_ci 248518678f8Sopenharmony_ci pool->distribue = AddressDistribute; 249518678f8Sopenharmony_ci pool->binding = QueryBinding; 250518678f8Sopenharmony_ci pool->newBinding = AddNewBinding; 251518678f8Sopenharmony_ci pool->leaseTable.clear(); 252518678f8Sopenharmony_ci return RET_SUCCESS; 253518678f8Sopenharmony_ci} 254518678f8Sopenharmony_ci 255518678f8Sopenharmony_civoid FreeAddressPool(DhcpAddressPool *pool) 256518678f8Sopenharmony_ci{ 257518678f8Sopenharmony_ci if (!pool) { 258518678f8Sopenharmony_ci return; 259518678f8Sopenharmony_ci } 260518678f8Sopenharmony_ci 261518678f8Sopenharmony_ci if (pool->fixedOptions.size > 0) { 262518678f8Sopenharmony_ci ClearOptions(&pool->fixedOptions); 263518678f8Sopenharmony_ci } 264518678f8Sopenharmony_ci 265518678f8Sopenharmony_ci if (pool) { 266518678f8Sopenharmony_ci pool->leaseTable.clear(); 267518678f8Sopenharmony_ci } 268518678f8Sopenharmony_ci 269518678f8Sopenharmony_ci if (pool && HasInitialized(&pool->fixedOptions)) { 270518678f8Sopenharmony_ci FreeOptionList(&pool->fixedOptions); 271518678f8Sopenharmony_ci } 272518678f8Sopenharmony_ci} 273518678f8Sopenharmony_ci 274518678f8Sopenharmony_ciAddressBinding *FindBindingByIp(uint32_t ipAddress) 275518678f8Sopenharmony_ci{ 276518678f8Sopenharmony_ci std::lock_guard<std::mutex> autoLock(g_bindingMapMutex); 277518678f8Sopenharmony_ci if (g_bindingRecoders.empty()) { 278518678f8Sopenharmony_ci return nullptr; 279518678f8Sopenharmony_ci } 280518678f8Sopenharmony_ci for (auto current: g_bindingRecoders) { 281518678f8Sopenharmony_ci AddressBinding *binding = ¤t.second; 282518678f8Sopenharmony_ci if (binding && ipAddress == binding->ipAddress) { 283518678f8Sopenharmony_ci return binding; 284518678f8Sopenharmony_ci } 285518678f8Sopenharmony_ci } 286518678f8Sopenharmony_ci return nullptr; 287518678f8Sopenharmony_ci} 288518678f8Sopenharmony_ci 289518678f8Sopenharmony_ciint IsReserved(uint8_t macAddr[DHCP_HWADDR_LENGTH]) 290518678f8Sopenharmony_ci{ 291518678f8Sopenharmony_ci std::lock_guard<std::mutex> autoLock(g_bindingMapMutex); 292518678f8Sopenharmony_ci if (g_bindingRecoders.count(macAddrHash(macAddr)) > 0) { 293518678f8Sopenharmony_ci AddressBinding *binding = &g_bindingRecoders[macAddrHash(macAddr)]; 294518678f8Sopenharmony_ci if (binding && binding->bindingMode == BIND_MODE_RESERVED) { 295518678f8Sopenharmony_ci return DHCP_TRUE; 296518678f8Sopenharmony_ci } 297518678f8Sopenharmony_ci } 298518678f8Sopenharmony_ci return DHCP_FALSE; 299518678f8Sopenharmony_ci} 300518678f8Sopenharmony_ci 301518678f8Sopenharmony_ciint IsReservedIp(DhcpAddressPool *pool, uint32_t ipAddress) 302518678f8Sopenharmony_ci{ 303518678f8Sopenharmony_ci if (!pool) { 304518678f8Sopenharmony_ci return DHCP_FALSE; 305518678f8Sopenharmony_ci } 306518678f8Sopenharmony_ci if (!ipAddress) { 307518678f8Sopenharmony_ci return DHCP_FALSE; 308518678f8Sopenharmony_ci } 309518678f8Sopenharmony_ci if (pool->leaseTable.count(ipAddress) >0) { 310518678f8Sopenharmony_ci AddressBinding *lease = &pool->leaseTable[ipAddress]; 311518678f8Sopenharmony_ci if (lease && lease->bindingMode == BIND_MODE_RESERVED) { 312518678f8Sopenharmony_ci return DHCP_TRUE; 313518678f8Sopenharmony_ci } 314518678f8Sopenharmony_ci } 315518678f8Sopenharmony_ci return DHCP_FALSE; 316518678f8Sopenharmony_ci} 317518678f8Sopenharmony_ci 318518678f8Sopenharmony_ciint AddBinding(AddressBinding *binding) 319518678f8Sopenharmony_ci{ 320518678f8Sopenharmony_ci if (!binding) { 321518678f8Sopenharmony_ci DHCP_LOGE("binding pointer is null."); 322518678f8Sopenharmony_ci return RET_ERROR; 323518678f8Sopenharmony_ci } 324518678f8Sopenharmony_ci if (IsEmptyHWAddr(binding->chaddr)) { 325518678f8Sopenharmony_ci DHCP_LOGE("binding address is empty."); 326518678f8Sopenharmony_ci return RET_ERROR; 327518678f8Sopenharmony_ci } 328518678f8Sopenharmony_ci if (!binding->ipAddress) { 329518678f8Sopenharmony_ci DHCP_LOGE("binding ip is empty."); 330518678f8Sopenharmony_ci return RET_ERROR; 331518678f8Sopenharmony_ci } 332518678f8Sopenharmony_ci std::lock_guard<std::mutex> autoLock(g_bindingMapMutex); 333518678f8Sopenharmony_ci if (g_bindingRecoders.count(macAddrHash(binding->chaddr)) > 0) { 334518678f8Sopenharmony_ci DHCP_LOGW("binding recoder exist."); 335518678f8Sopenharmony_ci return RET_FAILED; 336518678f8Sopenharmony_ci } 337518678f8Sopenharmony_ci g_bindingRecoders[macAddrHash(binding->chaddr)] = *binding; 338518678f8Sopenharmony_ci return RET_SUCCESS; 339518678f8Sopenharmony_ci} 340518678f8Sopenharmony_ci 341518678f8Sopenharmony_ciint AddReservedBinding(uint8_t macAddr[DHCP_HWADDR_LENGTH]) 342518678f8Sopenharmony_ci{ 343518678f8Sopenharmony_ci AddressBinding *binding = GetBindingByMac(macAddr); 344518678f8Sopenharmony_ci if (binding) { 345518678f8Sopenharmony_ci binding->bindingMode = BIND_MODE_RESERVED; 346518678f8Sopenharmony_ci } else { 347518678f8Sopenharmony_ci AddressBinding bind = {0}; 348518678f8Sopenharmony_ci bind.bindingMode = BIND_MODE_RESERVED; 349518678f8Sopenharmony_ci bind.bindingTime = Tmspsec(); 350518678f8Sopenharmony_ci bind.pendingTime = bind.bindingTime; 351518678f8Sopenharmony_ci std::lock_guard<std::mutex> autoLock(g_bindingMapMutex); 352518678f8Sopenharmony_ci g_bindingRecoders[macAddrHash(macAddr)] = bind; 353518678f8Sopenharmony_ci } 354518678f8Sopenharmony_ci return RET_SUCCESS; 355518678f8Sopenharmony_ci} 356518678f8Sopenharmony_ci 357518678f8Sopenharmony_ciint RemoveBinding(uint8_t macAddr[DHCP_HWADDR_LENGTH]) 358518678f8Sopenharmony_ci{ 359518678f8Sopenharmony_ci std::lock_guard<std::mutex> autoLock(g_bindingMapMutex); 360518678f8Sopenharmony_ci if (g_bindingRecoders.count(macAddrHash(macAddr)) > 0) { 361518678f8Sopenharmony_ci g_bindingRecoders.erase(macAddrHash(macAddr)); 362518678f8Sopenharmony_ci return RET_SUCCESS; 363518678f8Sopenharmony_ci } 364518678f8Sopenharmony_ci return RET_FAILED; 365518678f8Sopenharmony_ci} 366518678f8Sopenharmony_ci 367518678f8Sopenharmony_ciint RemoveReservedBinding(uint8_t macAddr[DHCP_HWADDR_LENGTH]) 368518678f8Sopenharmony_ci{ 369518678f8Sopenharmony_ci std::lock_guard<std::mutex> autoLock(g_bindingMapMutex); 370518678f8Sopenharmony_ci if (g_bindingRecoders.count(macAddrHash(macAddr)) > 0) { 371518678f8Sopenharmony_ci AddressBinding *binding = &g_bindingRecoders[macAddrHash(macAddr)]; 372518678f8Sopenharmony_ci if (binding && binding->bindingMode == BIND_MODE_RESERVED) { 373518678f8Sopenharmony_ci g_bindingRecoders.erase(macAddrHash(macAddr)); 374518678f8Sopenharmony_ci return RET_SUCCESS; 375518678f8Sopenharmony_ci } 376518678f8Sopenharmony_ci } 377518678f8Sopenharmony_ci DHCP_LOGW("binding mode is not 'BIND_MODE_RESERVED'."); 378518678f8Sopenharmony_ci return RET_FAILED; 379518678f8Sopenharmony_ci} 380518678f8Sopenharmony_ci 381518678f8Sopenharmony_ciint ReleaseBinding(uint8_t macAddr[DHCP_HWADDR_LENGTH]) 382518678f8Sopenharmony_ci{ 383518678f8Sopenharmony_ci std::lock_guard<std::mutex> autoLock(g_bindingMapMutex); 384518678f8Sopenharmony_ci if (g_bindingRecoders.count(macAddrHash(macAddr)) > 0) { 385518678f8Sopenharmony_ci if (g_releaseRemoveMode) { 386518678f8Sopenharmony_ci g_bindingRecoders.erase(macAddrHash(macAddr)); 387518678f8Sopenharmony_ci return RET_SUCCESS; 388518678f8Sopenharmony_ci } 389518678f8Sopenharmony_ci AddressBinding *binding = &g_bindingRecoders[macAddrHash(macAddr)]; 390518678f8Sopenharmony_ci if (binding) { 391518678f8Sopenharmony_ci binding->bindingStatus = BIND_RELEASED; 392518678f8Sopenharmony_ci return RET_SUCCESS; 393518678f8Sopenharmony_ci } 394518678f8Sopenharmony_ci } 395518678f8Sopenharmony_ci return RET_FAILED; 396518678f8Sopenharmony_ci} 397518678f8Sopenharmony_ci 398518678f8Sopenharmony_ciint AddLease(DhcpAddressPool *pool, AddressBinding *lease) 399518678f8Sopenharmony_ci{ 400518678f8Sopenharmony_ci if (!pool) { 401518678f8Sopenharmony_ci DHCP_LOGE("add lease pool pointer is null."); 402518678f8Sopenharmony_ci return RET_ERROR; 403518678f8Sopenharmony_ci } 404518678f8Sopenharmony_ci 405518678f8Sopenharmony_ci if (!lease || !lease->ipAddress || IsEmptyHWAddr(lease->chaddr)) { 406518678f8Sopenharmony_ci DHCP_LOGE("add lease pool ipAddress or chaddr pointer is null."); 407518678f8Sopenharmony_ci return RET_ERROR; 408518678f8Sopenharmony_ci } 409518678f8Sopenharmony_ci 410518678f8Sopenharmony_ci if (pool->leaseTable.count(lease->ipAddress) > 0) { 411518678f8Sopenharmony_ci DHCP_LOGI("update lease info."); 412518678f8Sopenharmony_ci pool->leaseTable[lease->ipAddress] = *lease; 413518678f8Sopenharmony_ci return RET_SUCCESS; 414518678f8Sopenharmony_ci } else { 415518678f8Sopenharmony_ci DHCP_LOGI("insert lease info."); 416518678f8Sopenharmony_ci pool->leaseTable[lease->ipAddress] = *lease; 417518678f8Sopenharmony_ci return RET_SUCCESS; 418518678f8Sopenharmony_ci } 419518678f8Sopenharmony_ci} 420518678f8Sopenharmony_ci 421518678f8Sopenharmony_ciAddressBinding *GetLease(DhcpAddressPool *pool, uint32_t ipAddress) 422518678f8Sopenharmony_ci{ 423518678f8Sopenharmony_ci if (!ipAddress) { 424518678f8Sopenharmony_ci DHCP_LOGE("get lease ipAddress pointer is null."); 425518678f8Sopenharmony_ci return nullptr; 426518678f8Sopenharmony_ci } 427518678f8Sopenharmony_ci if (!pool) { 428518678f8Sopenharmony_ci DHCP_LOGE("get lease pool pointer is null."); 429518678f8Sopenharmony_ci return nullptr; 430518678f8Sopenharmony_ci } 431518678f8Sopenharmony_ci uint32_t ipAddr = ipAddress; 432518678f8Sopenharmony_ci if (pool->leaseTable.count(ipAddr) > 0) { 433518678f8Sopenharmony_ci return &pool->leaseTable[ipAddr]; 434518678f8Sopenharmony_ci } 435518678f8Sopenharmony_ci DHCP_LOGE("get lease address binding pointer is null."); 436518678f8Sopenharmony_ci return nullptr; 437518678f8Sopenharmony_ci} 438518678f8Sopenharmony_ci 439518678f8Sopenharmony_ciint UpdateLease(DhcpAddressPool *pool, AddressBinding *lease) 440518678f8Sopenharmony_ci{ 441518678f8Sopenharmony_ci if (!pool) { 442518678f8Sopenharmony_ci DHCP_LOGE("update lease pool pointer is null."); 443518678f8Sopenharmony_ci return RET_ERROR; 444518678f8Sopenharmony_ci } 445518678f8Sopenharmony_ci 446518678f8Sopenharmony_ci if (!lease || !lease->ipAddress || IsEmptyHWAddr(lease->chaddr)) { 447518678f8Sopenharmony_ci DHCP_LOGE("update lease pool ipAddress or chaddr pointer is null."); 448518678f8Sopenharmony_ci return RET_ERROR; 449518678f8Sopenharmony_ci } 450518678f8Sopenharmony_ci if (pool->leaseTable.count(lease->ipAddress) > 0) { 451518678f8Sopenharmony_ci pool->leaseTable[lease->ipAddress] = *lease; 452518678f8Sopenharmony_ci return RET_SUCCESS; 453518678f8Sopenharmony_ci } 454518678f8Sopenharmony_ci DHCP_LOGE("update lease address binding pointer is null."); 455518678f8Sopenharmony_ci return RET_FAILED; 456518678f8Sopenharmony_ci} 457518678f8Sopenharmony_ci 458518678f8Sopenharmony_ciint RemoveLease(DhcpAddressPool *pool, AddressBinding *lease) 459518678f8Sopenharmony_ci{ 460518678f8Sopenharmony_ci if (!pool) { 461518678f8Sopenharmony_ci DHCP_LOGE("remove lease pool pointer is null."); 462518678f8Sopenharmony_ci return RET_ERROR; 463518678f8Sopenharmony_ci } 464518678f8Sopenharmony_ci 465518678f8Sopenharmony_ci if (!lease || !lease->ipAddress || IsEmptyHWAddr(lease->chaddr)) { 466518678f8Sopenharmony_ci DHCP_LOGE("remove lease pool ipAddress or chaddr pointer is null."); 467518678f8Sopenharmony_ci return RET_ERROR; 468518678f8Sopenharmony_ci } 469518678f8Sopenharmony_ci 470518678f8Sopenharmony_ci if (pool->leaseTable.count(lease->ipAddress) > 0) { 471518678f8Sopenharmony_ci pool->leaseTable.erase(lease->ipAddress); 472518678f8Sopenharmony_ci return RET_SUCCESS; 473518678f8Sopenharmony_ci } 474518678f8Sopenharmony_ci DHCP_LOGE("remove lease address binding pointer is null."); 475518678f8Sopenharmony_ci return RET_FAILED; 476518678f8Sopenharmony_ci} 477518678f8Sopenharmony_ci 478518678f8Sopenharmony_ciint LoadBindingRecoders(DhcpAddressPool *pool) 479518678f8Sopenharmony_ci{ 480518678f8Sopenharmony_ci if (pool == nullptr) { 481518678f8Sopenharmony_ci DHCP_LOGE("loadbinding recorder pool pointer is null."); 482518678f8Sopenharmony_ci return RET_FAILED; 483518678f8Sopenharmony_ci } 484518678f8Sopenharmony_ci char filePath[DHCP_LEASE_FILE_LENGTH] = {0}; 485518678f8Sopenharmony_ci if (snprintf_s(filePath, sizeof(filePath), sizeof(filePath) - 1, "%s.%s", DHCPD_LEASE_FILE, pool->ifname) < 0) { 486518678f8Sopenharmony_ci DHCP_LOGE("Failed to get dhcp lease file path!"); 487518678f8Sopenharmony_ci return RET_FAILED; 488518678f8Sopenharmony_ci } 489518678f8Sopenharmony_ci FILE *fp = fopen(filePath, "r"); 490518678f8Sopenharmony_ci if (fp == nullptr) { 491518678f8Sopenharmony_ci return RET_FAILED; 492518678f8Sopenharmony_ci } 493518678f8Sopenharmony_ci uint32_t beginIp = pool->addressRange.beginAddress; 494518678f8Sopenharmony_ci uint32_t endIp = pool->addressRange.endAddress; 495518678f8Sopenharmony_ci uint32_t netmask = pool->netmask; 496518678f8Sopenharmony_ci char line[DHCP_FILE_LINE_LENGTH] = {0}; 497518678f8Sopenharmony_ci while (fgets(line, DHCP_FILE_LINE_LENGTH, fp) != nullptr) { 498518678f8Sopenharmony_ci TrimString(line); 499518678f8Sopenharmony_ci if (line[0] == '\0') { /* skip empty line */ 500518678f8Sopenharmony_ci continue; 501518678f8Sopenharmony_ci } 502518678f8Sopenharmony_ci AddressBinding bind = {0}; 503518678f8Sopenharmony_ci if (ParseAddressBinding(&bind, line) != 0) { 504518678f8Sopenharmony_ci continue; 505518678f8Sopenharmony_ci } 506518678f8Sopenharmony_ci if (IpInRange(bind.ipAddress, beginIp, endIp, netmask)) { 507518678f8Sopenharmony_ci pool->leaseTable[bind.ipAddress] = bind; 508518678f8Sopenharmony_ci } 509518678f8Sopenharmony_ci } 510518678f8Sopenharmony_ci 511518678f8Sopenharmony_ci if (fclose(fp) != 0) { 512518678f8Sopenharmony_ci DHCP_LOGE("LoadBindingRecoders fclose fp failed!"); 513518678f8Sopenharmony_ci } 514518678f8Sopenharmony_ci return RET_SUCCESS; 515518678f8Sopenharmony_ci} 516518678f8Sopenharmony_ci 517518678f8Sopenharmony_ciint SaveBindingRecoders(const DhcpAddressPool *pool, int force) 518518678f8Sopenharmony_ci{ 519518678f8Sopenharmony_ci if (pool == nullptr) { 520518678f8Sopenharmony_ci DHCP_LOGE("Save binding record, pool is null"); 521518678f8Sopenharmony_ci return RET_FAILED; 522518678f8Sopenharmony_ci } 523518678f8Sopenharmony_ci static uint64_t lastTime = 0; 524518678f8Sopenharmony_ci uint64_t currTime = Tmspsec(); 525518678f8Sopenharmony_ci if (force == 0 && currTime < lastTime + DHCP_REFRESH_LEASE_FILE_INTERVAL) { 526518678f8Sopenharmony_ci DHCP_LOGE("Save binding record, time interval is not satisfied."); 527518678f8Sopenharmony_ci return RET_WAIT_SAVE; 528518678f8Sopenharmony_ci } 529518678f8Sopenharmony_ci char filePath[DHCP_LEASE_FILE_LENGTH] = {0}; 530518678f8Sopenharmony_ci if (snprintf_s(filePath, sizeof(filePath), sizeof(filePath) - 1, "%s.%s", DHCPD_LEASE_FILE, pool->ifname) < 0) { 531518678f8Sopenharmony_ci DHCP_LOGE("Failed to set dhcp lease file path!"); 532518678f8Sopenharmony_ci return RET_FAILED; 533518678f8Sopenharmony_ci } 534518678f8Sopenharmony_ci char line[DHCP_FILE_LINE_LENGTH] = {0}; 535518678f8Sopenharmony_ci FILE *fp = fopen(filePath, "w"); 536518678f8Sopenharmony_ci if (fp == nullptr) { 537518678f8Sopenharmony_ci DHCP_LOGE("Save binding records %{private}s failed: %{public}d", filePath, errno); 538518678f8Sopenharmony_ci return RET_FAILED; 539518678f8Sopenharmony_ci } 540518678f8Sopenharmony_ci for (auto index: pool->leaseTable) { 541518678f8Sopenharmony_ci AddressBinding *binding = &index.second; 542518678f8Sopenharmony_ci if (binding && WriteAddressBinding(binding, line, sizeof(line)) != RET_SUCCESS) { 543518678f8Sopenharmony_ci DHCP_LOGE("Failed to convert binding info to string"); 544518678f8Sopenharmony_ci } else { 545518678f8Sopenharmony_ci fprintf(fp, "%s\n", line); 546518678f8Sopenharmony_ci } 547518678f8Sopenharmony_ci } 548518678f8Sopenharmony_ci 549518678f8Sopenharmony_ci if (fclose(fp) != 0) { 550518678f8Sopenharmony_ci DHCP_LOGE("SaveBindingRecoders fclose fp failed!"); 551518678f8Sopenharmony_ci } 552518678f8Sopenharmony_ci lastTime = currTime; 553518678f8Sopenharmony_ci return RET_SUCCESS; 554518678f8Sopenharmony_ci} 555518678f8Sopenharmony_ci 556518678f8Sopenharmony_civoid SetDistributeMode(int mode) 557518678f8Sopenharmony_ci{ 558518678f8Sopenharmony_ci g_distributeMode = mode; 559518678f8Sopenharmony_ci} 560518678f8Sopenharmony_ciint GetDistributeMode(void) 561518678f8Sopenharmony_ci{ 562518678f8Sopenharmony_ci return g_distributeMode; 563518678f8Sopenharmony_ci} 564518678f8Sopenharmony_ci 565518678f8Sopenharmony_ciint DeleteMacInLease(DhcpAddressPool *pool, AddressBinding *lease) 566518678f8Sopenharmony_ci{ 567518678f8Sopenharmony_ci if ((pool == nullptr) || (lease == nullptr)) { 568518678f8Sopenharmony_ci DHCP_LOGE("DeleteMacInLease pointer is null."); 569518678f8Sopenharmony_ci return RET_ERROR; 570518678f8Sopenharmony_ci } 571518678f8Sopenharmony_ci for (auto it = pool->leaseTable.begin(); it != pool->leaseTable.end();) { 572518678f8Sopenharmony_ci AddressBinding *binding = &(it->second); 573518678f8Sopenharmony_ci if (binding && AddrEquels(binding->chaddr, lease->chaddr, MAC_ADDR_LENGTH)) { 574518678f8Sopenharmony_ci it = pool->leaseTable.erase(it); 575518678f8Sopenharmony_ci } else { 576518678f8Sopenharmony_ci ++it; 577518678f8Sopenharmony_ci } 578518678f8Sopenharmony_ci } 579518678f8Sopenharmony_ci return RET_SUCCESS; 580518678f8Sopenharmony_ci} 581