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_binding.h"
17 #include <securec.h>
18 #include <stdint.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <time.h>
22 #include "address_utils.h"
23 #include "common_util.h"
24 #include "dhcp_s_define.h"
25 #include "dhcp_logger.h"
26
27 DEFINE_DHCPLOG_DHCP_LABEL("DhcpServerBinding");
28
29 #define PENDING_INTERVAL_MAX_TIME 1200
30 #define PENDING_INTERVAL_LEVEL0 3
31 #define PENDING_INTERVAL_LEVEL1 10
32 #define PENDING_INTERVAL_LEVEL2 30
33 #define PENDING_MIN_WAITING_TIMES 1
34 #define PENDING_INTERVAL_LEVEL1_TIMES 2
35 #define PENDING_INTERVAL_LEVEL2_TIMES 5
36
NextPendingInterval(uint64_t pendingInterval)37 uint64_t NextPendingInterval(uint64_t pendingInterval)
38 {
39 uint64_t next = pendingInterval;
40 if (next < PENDING_INTERVAL_LEVEL0) {
41 next += PENDING_MIN_WAITING_TIMES;
42 } else if (next < PENDING_INTERVAL_LEVEL1) {
43 next += PENDING_INTERVAL_LEVEL1_TIMES;
44 } else if (next < PENDING_INTERVAL_LEVEL2) {
45 next += PENDING_INTERVAL_LEVEL2_TIMES;
46 } else {
47 next = PENDING_INTERVAL_MAX_TIME;
48 }
49 return next;
50 }
51
IsExpire(AddressBinding * binding)52 int IsExpire(AddressBinding *binding)
53 {
54 if (!binding) {
55 DHCP_LOGE("binding is null.");
56 return DHCP_FALSE;
57 }
58 uint64_t leaseTime = binding->leaseTime;
59 if (!leaseTime) {
60 leaseTime = DHCP_LEASE_TIME;
61 }
62 uint64_t expireIn = binding->expireIn;
63 if (binding->bindingStatus == BIND_PENDING) {
64 expireIn = binding->pendingTime + leaseTime;
65 } else if (binding->bindingStatus == BIND_ASSOCIATED) {
66 expireIn = binding->bindingTime + leaseTime;
67 }
68 uint64_t curr = Tmspsec();
69 if (curr > expireIn) {
70 binding->bindingStatus = BIND_EXPIRED;
71 return DHCP_TRUE;
72 }
73 return DHCP_FALSE;
74 }
75
76 #define BINDING_MAC_ADDR_POS 0
77 #define BINDING_IP_ADDR_POS 1
78 #define BINDING_LEASE_TIME_POS 2
79 #define BINDING_BINDING_TIME_POS 3
80 #define BINDING_PENDING_TIME_POS 4
81 #define BINDING_PENDING_INTERVAL_POS 5
82 #define BINDING_BINDING_MODE_POS 6
83 #define BINDING_BINDING_STATUS_POS 7
84 #define BINDING_STRING_SIZE 8
85
WriteAddressBinding(const AddressBinding * binding,char * out,uint32_t size)86 int WriteAddressBinding(const AddressBinding *binding, char *out, uint32_t size)
87 {
88 if (!binding || !out) {
89 return RET_FAILED;
90 }
91 const char *mac = ParseStrMac(binding->chaddr, sizeof(binding->chaddr));
92 const char *ip = ParseStrIp(binding->ipAddress);
93 if (mac == nullptr || ip == nullptr) {
94 return RET_FAILED;
95 }
96 if (snprintf_s(out, size, size - 1, "%s %s %llu %llu %llu %llu %d %d", mac, ip, binding->leaseTime,
97 binding->bindingTime, binding->pendingTime, binding->pendingInterval, binding->bindingMode,
98 binding->bindingStatus) < 0) {
99 return RET_FAILED;
100 }
101 return RET_SUCCESS;
102 }
103
ReleaseStrings(char ** strs)104 static void ReleaseStrings(char **strs)
105 {
106 if (strs == nullptr) {
107 return;
108 }
109 int i = 0;
110 while (strs[i] != nullptr) {
111 free(strs[i]);
112 strs[i] = nullptr;
113 ++i;
114 }
115 free(strs);
116 strs = nullptr;
117 return;
118 }
119
SplitString(const char * buf,const char * split)120 static char **SplitString(const char *buf, const char *split)
121 {
122 const char *pos = buf;
123 const char *p = nullptr;
124 size_t len = strlen(split);
125 int num = 0;
126 while ((p = strstr(pos, split)) != nullptr) {
127 if (p != pos) {
128 ++num;
129 }
130 pos = p + len;
131 }
132 if (*pos != '\0') {
133 ++num;
134 }
135 if (num == 0) {
136 return nullptr;
137 }
138 char **strs = (char **)calloc(num + 1, sizeof(char *));
139 if (strs == nullptr) {
140 return nullptr;
141 }
142 pos = buf;
143 num = 0;
144 while ((p = strstr(pos, split)) != nullptr) {
145 if (p != pos) {
146 size_t strLen = p - pos + 1;
147 strs[num] = (char *)calloc(strLen, sizeof(char));
148 if (strs[num] == nullptr || strncpy_s(strs[num], strLen, pos, p - pos) != EOK) {
149 ReleaseStrings(strs);
150 return nullptr;
151 }
152 ++num;
153 }
154 pos = p + len;
155 }
156 if (*pos != '\0') {
157 size_t strLen = strlen(pos) + 1;
158 strs[num] = (char *)calloc(strLen, sizeof(char));
159 if (strs[num] == nullptr || strncpy_s(strs[num], strLen, pos, strlen(pos)) != EOK) {
160 ReleaseStrings(strs);
161 return nullptr;
162 }
163 }
164 return strs;
165 }
166
ParseAddressBinding(AddressBinding * binding,const char * buf)167 int ParseAddressBinding(AddressBinding *binding, const char *buf)
168 {
169 uint64_t curr = Tmspsec();
170 char **strs = SplitString(buf, " ");
171 if (strs == nullptr) {
172 return -1;
173 }
174 int num = 0;
175 while (strs[num] != nullptr) {
176 ++num;
177 }
178 int ret = -1;
179 do {
180 if (num < BINDING_STRING_SIZE) {
181 break;
182 }
183 ParseMacAddress(strs[BINDING_MAC_ADDR_POS], binding->chaddr);
184 binding->ipAddress = ParseIpAddr(strs[BINDING_IP_ADDR_POS]);
185 binding->leaseTime = atol(strs[BINDING_LEASE_TIME_POS]);
186 binding->bindingTime = atol(strs[BINDING_BINDING_TIME_POS]);
187 binding->pendingTime = atol(strs[BINDING_PENDING_TIME_POS]);
188 if (binding->bindingTime && binding->bindingTime < binding->pendingTime) {
189 break;
190 }
191 if (binding->pendingTime > curr) { /* if pending time over than current system time */
192 binding->bindingTime = binding->bindingTime - binding->pendingTime + curr;
193 binding->pendingTime = curr;
194 }
195 binding->pendingInterval = atol(strs[BINDING_PENDING_INTERVAL_POS]);
196 binding->bindingMode = atoi(strs[BINDING_BINDING_MODE_POS]);
197 binding->bindingStatus = atoi(strs[BINDING_BINDING_STATUS_POS]);
198 if (binding->bindingStatus == BIND_ASSOCIATED) {
199 binding->expireIn = binding->bindingTime + binding->leaseTime;
200 }
201 ret += 1; /* set ret = 0 */
202 } while (0);
203 ReleaseStrings(strs);
204 return ret;
205 }
206