1 /*
2  * Copyright (C) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "dhcp_address_pool.h"
17 #include <map>
18 #include <mutex>
19 #include <securec.h>
20 #include <stdint.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include "address_utils.h"
24 #include "common_util.h"
25 #include "dhcp_logger.h"
26 
27 DEFINE_DHCPLOG_DHCP_LABEL("DhcpServerAddressPool");
28 
29 #define DHCP_POOL_INIT_SIZE 10
30 #define DHCP_RELEASE_REMOVE_MODE 0
31 
32 static int g_releaseRemoveMode = DHCP_RELEASE_REMOVE_MODE;
33 static std::map<std::size_t, AddressBinding> g_bindingRecoders;
34 static std::mutex g_bindingMapMutex;
35 static int g_distributeMode = 0;
36 
37 #define HASH_DEFAULT_VALUE 5381
38 #define HASH_CAL_CODE_CAL 5
39 //Write a HASH FUNCTION FOR uint8_t macAddr[DHCP_HWADDR_LENGTH]
macAddrHash(uint8_t macAddr[DHCP_HWADDR_LENGTH])40 std::size_t macAddrHash(uint8_t macAddr[DHCP_HWADDR_LENGTH])
41 {
42     std::size_t hash = HASH_DEFAULT_VALUE;
43     for (std::size_t i = 0; i < DHCP_HWADDR_LENGTH; ++i) {
44         hash = ((hash << HASH_CAL_CODE_CAL) + hash) ^ static_cast<std::size_t>(macAddr[i]);
45     }
46     return hash;
47 }
48 
49 
GetBindingByMac(uint8_t macAddr[DHCP_HWADDR_LENGTH])50 AddressBinding *GetBindingByMac(uint8_t macAddr[DHCP_HWADDR_LENGTH])
51 {
52     std::size_t hash = macAddrHash(macAddr);
53     std::lock_guard<std::mutex> autoLock(g_bindingMapMutex);
54     if (g_bindingRecoders.count(hash) > 0) {
55         return &g_bindingRecoders[hash];
56     }
57     return nullptr;
58 }
59 
QueryBinding(uint8_t macAddr[DHCP_HWADDR_LENGTH],PDhcpOptionList cliOptins)60 AddressBinding *QueryBinding(uint8_t macAddr[DHCP_HWADDR_LENGTH], PDhcpOptionList cliOptins)
61 {
62     return GetBindingByMac(macAddr);
63 }
64 
AddNewBinding(uint8_t macAddr[DHCP_HWADDR_LENGTH],PDhcpOptionList cliOptins)65 AddressBinding *AddNewBinding(uint8_t macAddr[DHCP_HWADDR_LENGTH], PDhcpOptionList cliOptins)
66 {
67     AddressBinding newBind = {0};
68     newBind.bindingMode = BIND_MODE_DYNAMIC;
69     newBind.bindingStatus = BIND_PENDING;
70     if (memcpy_s(newBind.chaddr, DHCP_HWADDR_LENGTH, macAddr, DHCP_HWADDR_LENGTH) != EOK) {
71         DHCP_LOGE("newBind chaddr memcpy_s failed!");
72         return nullptr;
73     }
74     newBind.bindingTime = Tmspsec();
75     newBind.pendingTime = Tmspsec();
76     newBind.expireIn = newBind.bindingTime + DHCP_LEASE_TIME;
77     newBind.leaseTime = DHCP_LEASE_TIME;
78     {
79         std::lock_guard<std::mutex> autoLock(g_bindingMapMutex);
80         g_bindingRecoders[macAddrHash(macAddr)] = newBind;
81     }
82     return GetBindingByMac(macAddr);
83 }
84 
CheckIpAvailability(DhcpAddressPool * pool,uint8_t macAddr[DHCP_HWADDR_LENGTH],uint32_t distIp)85 int CheckIpAvailability(DhcpAddressPool *pool, uint8_t macAddr[DHCP_HWADDR_LENGTH], uint32_t distIp)
86 {
87     if (!pool) {
88         DHCP_LOGE("pool pointer is null.");
89         return DHCP_FALSE;
90     }
91     if (IsReserved(macAddr)) {
92         DHCP_LOGW("client address(%s) is reserved address.", ParseLogMac(macAddr));
93         return DHCP_FALSE;
94     }
95     AddressBinding *lease = GetLease(pool, distIp);
96     if (lease) {
97         int same = AddrEquels(lease->chaddr, macAddr, MAC_ADDR_LENGTH);
98         if (distIp == pool->serverId || distIp == pool->gateway) {
99             return DHCP_FALSE;
100         }
101         if (lease->bindingMode == BIND_MODE_STATIC && !same) {
102             return DHCP_FALSE;
103         }
104         if (IsReservedIp(pool, distIp) && !same) {
105             return DHCP_FALSE;
106         }
107         if (same) {
108             lease->pendingTime = Tmspsec();
109             lease->bindingTime = lease->pendingTime;
110             return DHCP_TRUE;
111         }
112         if (IsExpire(lease)) {
113             DHCP_LOGD("the binding recoder has expired.");
114             lease->pendingTime = Tmspsec();
115             lease->bindingTime = lease->pendingTime;
116             RemoveBinding(lease->chaddr);
117             if (memcpy_s(lease->chaddr, DHCP_HWADDR_LENGTH, macAddr, MAC_ADDR_LENGTH) != EOK) {
118                 DHCP_LOGD("failed to rewrite client address.");
119             }
120             return DHCP_TRUE;
121         }
122         return DHCP_FALSE;
123     }
124     return DHCP_TRUE;
125 }
126 
CheckRangeAvailability(DhcpAddressPool * pool,uint8_t macAddr[DHCP_HWADDR_LENGTH],uint32_t distIp,int * outOfRange)127 int CheckRangeAvailability(
128     DhcpAddressPool *pool, uint8_t macAddr[DHCP_HWADDR_LENGTH], uint32_t distIp, int *outOfRange)
129 {
130     if (!pool || !pool->addressRange.beginAddress || !pool->addressRange.endAddress) {
131         DHCP_LOGE("pool beginAddress or endAddress pointer is null.");
132         return RET_ERROR;
133     }
134     if (!pool->netmask || IsEmptyHWAddr(macAddr)) {
135         DHCP_LOGE("pool netmask empty hwaddr pointer is null.");
136         return RET_ERROR;
137     }
138     uint32_t beginIp = pool->addressRange.beginAddress;
139     uint32_t endIp = pool->addressRange.endAddress;
140     if (IpInRange(distIp, beginIp, endIp, pool->netmask)) {
141         DHCP_LOGD("distribution IP address");
142         AddressBinding lease = {0};
143         lease.pendingTime = Tmspsec();
144         lease.bindingMode = BIND_PENDING;
145         lease.ipAddress = distIp;
146         lease.bindingTime = lease.pendingTime;
147         lease.leaseTime = pool->leaseTime;
148         if (memcpy_s(lease.chaddr, sizeof(lease.chaddr), macAddr, MAC_ADDR_LENGTH) != EOK) {
149             DHCP_LOGE("failed to set lease chaddr fields");
150             return RET_ERROR;
151         }
152         if (AddLease(pool, &lease) != RET_SUCCESS) {
153             DHCP_LOGE("failed to add lease.");
154             return RET_ERROR;
155         }
156         return RET_SUCCESS;
157     }
158     if (*outOfRange) {
159         DHCP_LOGD("address is out of range");
160         return RET_FAILED;
161     } else {
162         *outOfRange = 1;
163     }
164     return RET_FAILED;
165 }
166 
NextIpOffset(uint32_t netmask)167 uint32_t NextIpOffset(uint32_t netmask)
168 {
169     uint32_t offset = 0;
170     if (g_distributeMode && netmask) {
171         uint32_t total = HostTotal(netmask);
172         if (total) {
173             offset = Tmspusec() % total;
174         }
175         DHCP_LOGD("next ip offset is: %u", offset);
176     }
177     return offset;
178 }
179 
AddressDistribute(DhcpAddressPool * pool,uint8_t macAddr[DHCP_HWADDR_LENGTH])180 uint32_t AddressDistribute(DhcpAddressPool *pool, uint8_t macAddr[DHCP_HWADDR_LENGTH])
181 {
182     if (!pool || !pool->addressRange.beginAddress || !pool->addressRange.endAddress) {
183         return 0;
184     }
185     if (!pool->netmask || IsEmptyHWAddr(macAddr)) {
186         return 0;
187     }
188     if (pool->distribution == 0) {
189         pool->distribution = pool->addressRange.beginAddress;
190     }
191     uint32_t total = HostTotal(pool->netmask);
192     uint32_t distIp = pool->distribution;
193     if (!distIp || distIp < pool->addressRange.beginAddress) {
194         distIp = pool->addressRange.beginAddress;
195     }
196     int distSucess = 0;
197     int outOfRange = 0;
198     for (uint32_t i = 0; i < total; i++) {
199         uint32_t offset = 0;
200         if (i == 0) {
201             offset = NextIpOffset(pool->netmask);
202         }
203         distIp = NextIpAddress(distIp, pool->netmask, offset);
204         if (!CheckIpAvailability(pool, macAddr, distIp)) {
205             continue;
206         }
207         int ret = CheckRangeAvailability(pool, macAddr, distIp, &outOfRange);
208         if (ret == RET_ERROR) {
209             break;
210         }
211         if (ret == RET_SUCCESS) {
212             distSucess = 1;
213             break;
214         }
215     }
216     if (!distSucess || !distIp) {
217         return 0;
218     }
219     pool->distribution = distIp;
220     return pool->distribution;
221 }
222 
InitAddressPool(DhcpAddressPool * pool,const char * ifname,PDhcpOptionList options)223 int InitAddressPool(DhcpAddressPool *pool, const char *ifname, PDhcpOptionList options)
224 {
225     if (!pool) {
226         DHCP_LOGD("address pool pointer is null.");
227         return RET_ERROR;
228     }
229     if (memset_s(pool, sizeof(DhcpAddressPool), 0, sizeof(DhcpAddressPool)) != EOK) {
230         DHCP_LOGD("failed to init dhcp pool.");
231         return RET_ERROR;
232     }
233     if (memset_s(pool->ifname, IFACE_NAME_SIZE, '\0', IFACE_NAME_SIZE) != EOK) {
234         DHCP_LOGD("failed to reset interface name.");
235         return RET_ERROR;
236     }
237     if (strncpy_s(pool->ifname, IFACE_NAME_SIZE, ifname, strlen(ifname)) != EOK) {
238         DHCP_LOGD("failed to set interface name.");
239         return RET_ERROR;
240     }
241     if (InitOptionList(&pool->fixedOptions) != RET_SUCCESS) {
242         DHCP_LOGD("failed to init options field for dhcp pool.");
243         return RET_FAILED;
244     }
245     std::lock_guard<std::mutex> autoLock(g_bindingMapMutex);
246     g_bindingRecoders.clear();
247 
248     pool->distribue = AddressDistribute;
249     pool->binding = QueryBinding;
250     pool->newBinding = AddNewBinding;
251     pool->leaseTable.clear();
252     return RET_SUCCESS;
253 }
254 
FreeAddressPool(DhcpAddressPool * pool)255 void FreeAddressPool(DhcpAddressPool *pool)
256 {
257     if (!pool) {
258         return;
259     }
260 
261     if (pool->fixedOptions.size > 0) {
262         ClearOptions(&pool->fixedOptions);
263     }
264 
265     if (pool) {
266         pool->leaseTable.clear();
267     }
268 
269     if (pool && HasInitialized(&pool->fixedOptions)) {
270         FreeOptionList(&pool->fixedOptions);
271     }
272 }
273 
FindBindingByIp(uint32_t ipAddress)274 AddressBinding *FindBindingByIp(uint32_t ipAddress)
275 {
276     std::lock_guard<std::mutex> autoLock(g_bindingMapMutex);
277     if (g_bindingRecoders.empty()) {
278         return nullptr;
279     }
280     for (auto current: g_bindingRecoders) {
281         AddressBinding *binding = &current.second;
282         if (binding && ipAddress == binding->ipAddress) {
283             return binding;
284         }
285     }
286     return nullptr;
287 }
288 
IsReserved(uint8_t macAddr[DHCP_HWADDR_LENGTH])289 int IsReserved(uint8_t macAddr[DHCP_HWADDR_LENGTH])
290 {
291     std::lock_guard<std::mutex> autoLock(g_bindingMapMutex);
292     if (g_bindingRecoders.count(macAddrHash(macAddr)) > 0) {
293         AddressBinding *binding = &g_bindingRecoders[macAddrHash(macAddr)];
294         if (binding && binding->bindingMode == BIND_MODE_RESERVED) {
295             return DHCP_TRUE;
296         }
297     }
298     return DHCP_FALSE;
299 }
300 
IsReservedIp(DhcpAddressPool * pool,uint32_t ipAddress)301 int IsReservedIp(DhcpAddressPool *pool, uint32_t ipAddress)
302 {
303     if (!pool) {
304         return DHCP_FALSE;
305     }
306     if (!ipAddress) {
307         return DHCP_FALSE;
308     }
309     if (pool->leaseTable.count(ipAddress) >0) {
310         AddressBinding *lease = &pool->leaseTable[ipAddress];
311         if (lease && lease->bindingMode == BIND_MODE_RESERVED) {
312             return DHCP_TRUE;
313         }
314     }
315     return DHCP_FALSE;
316 }
317 
AddBinding(AddressBinding * binding)318 int AddBinding(AddressBinding *binding)
319 {
320     if (!binding) {
321         DHCP_LOGE("binding pointer is null.");
322         return RET_ERROR;
323     }
324     if (IsEmptyHWAddr(binding->chaddr)) {
325         DHCP_LOGE("binding address is empty.");
326         return RET_ERROR;
327     }
328     if (!binding->ipAddress) {
329         DHCP_LOGE("binding ip is empty.");
330         return RET_ERROR;
331     }
332     std::lock_guard<std::mutex> autoLock(g_bindingMapMutex);
333     if (g_bindingRecoders.count(macAddrHash(binding->chaddr)) > 0) {
334         DHCP_LOGW("binding recoder exist.");
335         return RET_FAILED;
336     }
337     g_bindingRecoders[macAddrHash(binding->chaddr)] = *binding;
338     return RET_SUCCESS;
339 }
340 
AddReservedBinding(uint8_t macAddr[DHCP_HWADDR_LENGTH])341 int AddReservedBinding(uint8_t macAddr[DHCP_HWADDR_LENGTH])
342 {
343     AddressBinding *binding = GetBindingByMac(macAddr);
344     if (binding) {
345         binding->bindingMode = BIND_MODE_RESERVED;
346     } else {
347         AddressBinding bind = {0};
348         bind.bindingMode = BIND_MODE_RESERVED;
349         bind.bindingTime = Tmspsec();
350         bind.pendingTime = bind.bindingTime;
351         std::lock_guard<std::mutex> autoLock(g_bindingMapMutex);
352         g_bindingRecoders[macAddrHash(macAddr)] = bind;
353     }
354     return RET_SUCCESS;
355 }
356 
RemoveBinding(uint8_t macAddr[DHCP_HWADDR_LENGTH])357 int RemoveBinding(uint8_t macAddr[DHCP_HWADDR_LENGTH])
358 {
359     std::lock_guard<std::mutex> autoLock(g_bindingMapMutex);
360     if (g_bindingRecoders.count(macAddrHash(macAddr)) > 0) {
361         g_bindingRecoders.erase(macAddrHash(macAddr));
362         return RET_SUCCESS;
363     }
364     return RET_FAILED;
365 }
366 
RemoveReservedBinding(uint8_t macAddr[DHCP_HWADDR_LENGTH])367 int RemoveReservedBinding(uint8_t macAddr[DHCP_HWADDR_LENGTH])
368 {
369     std::lock_guard<std::mutex> autoLock(g_bindingMapMutex);
370     if (g_bindingRecoders.count(macAddrHash(macAddr)) > 0) {
371         AddressBinding *binding = &g_bindingRecoders[macAddrHash(macAddr)];
372         if (binding && binding->bindingMode == BIND_MODE_RESERVED) {
373             g_bindingRecoders.erase(macAddrHash(macAddr));
374             return RET_SUCCESS;
375         }
376     }
377     DHCP_LOGW("binding mode is not 'BIND_MODE_RESERVED'.");
378     return RET_FAILED;
379 }
380 
ReleaseBinding(uint8_t macAddr[DHCP_HWADDR_LENGTH])381 int ReleaseBinding(uint8_t macAddr[DHCP_HWADDR_LENGTH])
382 {
383     std::lock_guard<std::mutex> autoLock(g_bindingMapMutex);
384     if (g_bindingRecoders.count(macAddrHash(macAddr)) > 0) {
385         if (g_releaseRemoveMode) {
386             g_bindingRecoders.erase(macAddrHash(macAddr));
387             return RET_SUCCESS;
388         }
389         AddressBinding *binding = &g_bindingRecoders[macAddrHash(macAddr)];
390         if (binding) {
391             binding->bindingStatus = BIND_RELEASED;
392             return RET_SUCCESS;
393         }
394     }
395     return RET_FAILED;
396 }
397 
AddLease(DhcpAddressPool * pool,AddressBinding * lease)398 int AddLease(DhcpAddressPool *pool, AddressBinding *lease)
399 {
400     if (!pool) {
401         DHCP_LOGE("add lease pool pointer is null.");
402         return RET_ERROR;
403     }
404 
405     if (!lease || !lease->ipAddress || IsEmptyHWAddr(lease->chaddr)) {
406         DHCP_LOGE("add lease pool ipAddress or chaddr pointer is null.");
407         return RET_ERROR;
408     }
409 
410     if (pool->leaseTable.count(lease->ipAddress) > 0) {
411         DHCP_LOGI("update lease info.");
412         pool->leaseTable[lease->ipAddress] = *lease;
413         return RET_SUCCESS;
414     } else {
415         DHCP_LOGI("insert lease info.");
416         pool->leaseTable[lease->ipAddress] = *lease;
417         return RET_SUCCESS;
418     }
419 }
420 
GetLease(DhcpAddressPool * pool,uint32_t ipAddress)421 AddressBinding *GetLease(DhcpAddressPool *pool, uint32_t ipAddress)
422 {
423     if (!ipAddress) {
424         DHCP_LOGE("get lease ipAddress pointer is null.");
425         return nullptr;
426     }
427     if (!pool) {
428         DHCP_LOGE("get lease pool pointer is null.");
429         return nullptr;
430     }
431     uint32_t ipAddr = ipAddress;
432     if (pool->leaseTable.count(ipAddr) > 0) {
433         return &pool->leaseTable[ipAddr];
434     }
435     DHCP_LOGE("get lease address binding pointer is null.");
436     return nullptr;
437 }
438 
UpdateLease(DhcpAddressPool * pool,AddressBinding * lease)439 int UpdateLease(DhcpAddressPool *pool, AddressBinding *lease)
440 {
441     if (!pool) {
442         DHCP_LOGE("update lease pool pointer is null.");
443         return RET_ERROR;
444     }
445 
446     if (!lease || !lease->ipAddress || IsEmptyHWAddr(lease->chaddr)) {
447         DHCP_LOGE("update lease pool ipAddress or chaddr pointer is null.");
448         return RET_ERROR;
449     }
450     if (pool->leaseTable.count(lease->ipAddress) > 0) {
451         pool->leaseTable[lease->ipAddress] = *lease;
452         return RET_SUCCESS;
453     }
454     DHCP_LOGE("update lease address binding pointer is null.");
455     return RET_FAILED;
456 }
457 
RemoveLease(DhcpAddressPool * pool,AddressBinding * lease)458 int RemoveLease(DhcpAddressPool *pool, AddressBinding *lease)
459 {
460     if (!pool) {
461         DHCP_LOGE("remove lease pool pointer is null.");
462         return RET_ERROR;
463     }
464 
465     if (!lease || !lease->ipAddress || IsEmptyHWAddr(lease->chaddr)) {
466         DHCP_LOGE("remove lease pool ipAddress or chaddr pointer is null.");
467         return RET_ERROR;
468     }
469 
470     if (pool->leaseTable.count(lease->ipAddress) > 0) {
471         pool->leaseTable.erase(lease->ipAddress);
472         return RET_SUCCESS;
473     }
474     DHCP_LOGE("remove lease address binding pointer is null.");
475     return RET_FAILED;
476 }
477 
LoadBindingRecoders(DhcpAddressPool * pool)478 int LoadBindingRecoders(DhcpAddressPool *pool)
479 {
480     if (pool == nullptr) {
481         DHCP_LOGE("loadbinding recorder pool pointer is null.");
482         return RET_FAILED;
483     }
484     char filePath[DHCP_LEASE_FILE_LENGTH] = {0};
485     if (snprintf_s(filePath, sizeof(filePath), sizeof(filePath) - 1, "%s.%s", DHCPD_LEASE_FILE, pool->ifname) < 0) {
486         DHCP_LOGE("Failed to get dhcp lease file path!");
487         return RET_FAILED;
488     }
489     FILE *fp = fopen(filePath, "r");
490     if (fp == nullptr) {
491         return RET_FAILED;
492     }
493     uint32_t beginIp = pool->addressRange.beginAddress;
494     uint32_t endIp = pool->addressRange.endAddress;
495     uint32_t netmask = pool->netmask;
496     char line[DHCP_FILE_LINE_LENGTH] = {0};
497     while (fgets(line, DHCP_FILE_LINE_LENGTH, fp) != nullptr) {
498         TrimString(line);
499         if (line[0] == '\0') { /* skip empty line */
500             continue;
501         }
502         AddressBinding bind = {0};
503         if (ParseAddressBinding(&bind, line) != 0) {
504             continue;
505         }
506         if (IpInRange(bind.ipAddress, beginIp, endIp, netmask)) {
507             pool->leaseTable[bind.ipAddress] = bind;
508         }
509     }
510 
511     if (fclose(fp) != 0) {
512         DHCP_LOGE("LoadBindingRecoders fclose fp failed!");
513     }
514     return RET_SUCCESS;
515 }
516 
SaveBindingRecoders(const DhcpAddressPool * pool,int force)517 int SaveBindingRecoders(const DhcpAddressPool *pool, int force)
518 {
519     if (pool == nullptr) {
520         DHCP_LOGE("Save binding record, pool is null");
521         return RET_FAILED;
522     }
523     static uint64_t lastTime = 0;
524     uint64_t currTime = Tmspsec();
525     if (force == 0 && currTime < lastTime + DHCP_REFRESH_LEASE_FILE_INTERVAL) {
526         DHCP_LOGE("Save binding record, time interval is not satisfied.");
527         return RET_WAIT_SAVE;
528     }
529     char filePath[DHCP_LEASE_FILE_LENGTH] = {0};
530     if (snprintf_s(filePath, sizeof(filePath), sizeof(filePath) - 1, "%s.%s", DHCPD_LEASE_FILE, pool->ifname) < 0) {
531         DHCP_LOGE("Failed to set dhcp lease file path!");
532         return RET_FAILED;
533     }
534     char line[DHCP_FILE_LINE_LENGTH] = {0};
535     FILE *fp = fopen(filePath, "w");
536     if (fp == nullptr) {
537         DHCP_LOGE("Save binding records %{private}s failed: %{public}d", filePath, errno);
538         return RET_FAILED;
539     }
540     for (auto index: pool->leaseTable) {
541         AddressBinding *binding = &index.second;
542         if (binding && WriteAddressBinding(binding, line, sizeof(line)) != RET_SUCCESS) {
543             DHCP_LOGE("Failed to convert binding info to string");
544         } else {
545             fprintf(fp, "%s\n", line);
546         }
547     }
548 
549     if (fclose(fp) != 0) {
550         DHCP_LOGE("SaveBindingRecoders fclose fp failed!");
551     }
552     lastTime = currTime;
553     return RET_SUCCESS;
554 }
555 
SetDistributeMode(int mode)556 void SetDistributeMode(int mode)
557 {
558     g_distributeMode = mode;
559 }
GetDistributeMode(void)560 int GetDistributeMode(void)
561 {
562     return g_distributeMode;
563 }
564 
DeleteMacInLease(DhcpAddressPool * pool,AddressBinding * lease)565 int DeleteMacInLease(DhcpAddressPool *pool, AddressBinding *lease)
566 {
567     if ((pool == nullptr) || (lease == nullptr)) {
568         DHCP_LOGE("DeleteMacInLease pointer is null.");
569         return RET_ERROR;
570     }
571     for (auto it = pool->leaseTable.begin(); it != pool->leaseTable.end();) {
572         AddressBinding *binding = &(it->second);
573         if (binding && AddrEquels(binding->chaddr, lease->chaddr, MAC_ADDR_LENGTH)) {
574             it = pool->leaseTable.erase(it);
575         } else {
576             ++it;
577         }
578     }
579     return RET_SUCCESS;
580 }
581