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