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