• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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