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