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 = ¤t.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