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_config.h"
17 #include <errno.h>
18 #include <securec.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <time.h>
23 #include "address_utils.h"
24 #include "common_util.h"
25 #include "dhcp_server_ipv4.h"
26 #include "dhcp_logger.h"
27
28 DEFINE_DHCPLOG_DHCP_LABEL("DhcpServerConfig");
29
30 #define FILE_LINE_LEN_MAX 1024
31 #define FILE_LINE_DELIMITER "="
32
SetEnableConfigInfo(DhcpConfig * dhcpConfig,const char * pKey,const char * pValue)33 static int SetEnableConfigInfo(DhcpConfig *dhcpConfig, const char *pKey, const char *pValue)
34 {
35 if ((dhcpConfig == nullptr) || (pKey == nullptr) || (pValue == nullptr)) {
36 DHCP_LOGE("SetEnableConfigInfo param dhcpConfig or pKey or pValue is nullptr!");
37 return RET_FAILED;
38 }
39
40 uint32_t uValue = (uint32_t)atoi(pValue);
41 if ((uValue != 0) && (uValue != 1)) {
42 DHCP_LOGE("enable:%s error", pValue);
43 return RET_FAILED;
44 }
45
46 if (strcmp(pKey, "distribution") == 0) {
47 dhcpConfig->distribution = uValue;
48 } else if (strcmp(pKey, "broadcast") == 0) {
49 dhcpConfig->broadcast = uValue;
50 }
51 return RET_SUCCESS;
52 }
53
SetTimeConfigInfo(DhcpConfig * dhcpConfig,const char * pKey,const char * pValue)54 static int SetTimeConfigInfo(DhcpConfig *dhcpConfig, const char *pKey, const char *pValue)
55 {
56 if ((dhcpConfig == nullptr) || (pKey == nullptr) || (pValue == nullptr)) {
57 DHCP_LOGE("SetTimeConfigInfo param dhcpConfig or pKey or pValue is nullptr!");
58 return RET_FAILED;
59 }
60
61 uint32_t uValue = 0;
62 if ((uValue = (uint32_t)atoi(pValue)) == 0) {
63 DHCP_LOGE("atoi failed, time:%s", pValue);
64 return RET_FAILED;
65 }
66
67 if (strcmp(pKey, "leaseTime") == 0) {
68 dhcpConfig->leaseTime = uValue;
69 } else if (strcmp(pKey, "renewalTime") == 0) {
70 dhcpConfig->renewalTime = uValue;
71 } else if (strcmp(pKey, "rebindingTime") == 0) {
72 dhcpConfig->rebindingTime = uValue;
73 }
74 return RET_SUCCESS;
75 }
76
SetNetConfigInfo(DhcpConfig * dhcpConfig,const char * pKey,const char * pValue,int common)77 static int SetNetConfigInfo(DhcpConfig *dhcpConfig, const char *pKey, const char *pValue, int common)
78 {
79 if ((dhcpConfig == nullptr) || (pKey == nullptr) || (pValue == nullptr)) {
80 DHCP_LOGE("SetNetConfigInfo param dhcpConfig or pKey or pValue is nullptr!");
81 return RET_FAILED;
82 }
83
84 uint32_t uValue = 0;
85 if ((uValue = ParseIpAddr(pValue)) == 0) {
86 DHCP_LOGE("ParseIpAddr failed, ip:%s", pValue);
87 return RET_FAILED;
88 }
89
90 if (((strcmp(pKey, "serverId") == 0) && common) || ((strcmp(pKey, "server") == 0) && !common)) {
91 dhcpConfig->serverId = uValue;
92 } else if (strcmp(pKey, "gateway") == 0) {
93 dhcpConfig->gateway = uValue;
94 } else if (strcmp(pKey, "netmask") == 0) {
95 dhcpConfig->netmask = uValue;
96 }
97 return RET_SUCCESS;
98 }
99
SetIpAddressPool(DhcpConfig * dhcpConfig,const char * pValue)100 static int SetIpAddressPool(DhcpConfig *dhcpConfig, const char *pValue)
101 {
102 if ((dhcpConfig == nullptr) || (pValue == nullptr)) {
103 DHCP_LOGE("SetIpAddressPool param dhcpConfig or pValue is nullptr!");
104 return RET_FAILED;
105 }
106
107 char *pSrc = (char *)pValue;
108 char *pSave = nullptr;
109 char *pTok = strtok_r(pSrc, ",", &pSave);
110 if (((pTok == nullptr) || (strlen(pTok) == 0)) || ((pSave == nullptr) || (strlen(pSave) == 0))) {
111 DHCP_LOGE("strtok_r pTok or pSave nullptr or len is 0!");
112 return RET_FAILED;
113 }
114
115 uint32_t begin;
116 if ((begin = ParseIpAddr(pTok)) == 0) {
117 DHCP_LOGE("ParseIpAddr begin:%s failed!", pTok);
118 return RET_FAILED;
119 }
120 dhcpConfig->pool.beginAddress = begin;
121 uint32_t end;
122 if ((end = ParseIpAddr(pSave)) == 0) {
123 DHCP_LOGE("ParseIpAddr end:%s failed!", pSave);
124 return RET_FAILED;
125 }
126 dhcpConfig->pool.endAddress = end;
127 return RET_SUCCESS;
128 }
129
SetDnsInfo(DhcpConfig * dhcpConfig,const char * pValue)130 static int SetDnsInfo(DhcpConfig *dhcpConfig, const char *pValue)
131 {
132 if ((dhcpConfig == nullptr) || (pValue == nullptr)) {
133 DHCP_LOGE("SetDnsInfo param dhcpConfig or pValue is nullptr!");
134 return RET_FAILED;
135 }
136
137 char *pSrc = (char *)pValue;
138 char *pSave = nullptr;
139 char *pTok = strtok_r(pSrc, ",", &pSave);
140 if ((pTok == nullptr) || (strlen(pTok) == 0)) {
141 DHCP_LOGE("strtok_r pTok nullptr or len is 0!");
142 return RET_FAILED;
143 }
144
145 DhcpOption optDns = {DOMAIN_NAME_SERVER_OPTION, 0, {0}};
146 if (GetOption(&dhcpConfig->options, optDns.code) != nullptr) {
147 RemoveOption(&dhcpConfig->options, optDns.code);
148 }
149
150 uint32_t dnsAddress;
151 while (pTok != nullptr) {
152 if ((dnsAddress = ParseIpAddr(pTok)) == 0) {
153 DHCP_LOGE("ParseIpAddr %s failed, code:%d", pTok, optDns.code);
154 return RET_FAILED;
155 }
156 if (AppendAddressOption(&optDns, dnsAddress) != RET_SUCCESS) {
157 DHCP_LOGW("failed append dns option.");
158 }
159 pTok = strtok_r(nullptr, ",", &pSave);
160 }
161 PushBackOption(&dhcpConfig->options, &optDns);
162 return RET_SUCCESS;
163 }
164
SetIfnameInfo(DhcpConfig * dhcpConfig,const char * pValue)165 static int SetIfnameInfo(DhcpConfig *dhcpConfig, const char *pValue)
166 {
167 if ((dhcpConfig == nullptr) || (pValue == nullptr)) {
168 DHCP_LOGE("SetIfnameInfo dhcpConfig or pValue is nullptr!");
169 return RET_FAILED;
170 }
171 if (strlen(pValue) >= IFACE_NAME_SIZE) {
172 DHCP_LOGE("ifname:%s too long!", pValue);
173 return RET_FAILED;
174 }
175 if (memset_s(dhcpConfig->ifname, IFACE_NAME_SIZE, '\0', IFACE_NAME_SIZE) != EOK ||
176 strncpy_s(dhcpConfig->ifname, IFACE_NAME_SIZE, pValue, strlen(pValue)) != EOK) {
177 return RET_FAILED;
178 }
179 return RET_SUCCESS;
180 }
181
SetDhcpConfig(DhcpConfig * dhcpConfig,const char * strLine,int common)182 static int SetDhcpConfig(DhcpConfig *dhcpConfig, const char *strLine, int common)
183 {
184 if ((strLine == nullptr) || (strlen(strLine) == 0)) {
185 DHCP_LOGE("SetDhcpConfig param strLine is nullptr or len = 0!");
186 return RET_FAILED;
187 }
188
189 char *pSrc = (char *)strLine;
190 char *pSave = nullptr;
191 char *pTok = strtok_r(pSrc, FILE_LINE_DELIMITER, &pSave);
192 if (pTok == nullptr) {
193 DHCP_LOGE("strtok_r pTok nullptr!");
194 return RET_FAILED;
195 }
196 if (strcmp(pTok, "interface") == 0) {
197 return SetIfnameInfo(dhcpConfig, pSave);
198 } else if (strcmp(pTok, "dns") == 0) {
199 return SetDnsInfo(dhcpConfig, pSave);
200 } else if (strcmp(pTok, "pool") == 0) {
201 return SetIpAddressPool(dhcpConfig, pSave);
202 } else if ((((strcmp(pTok, "serverId") == 0) && common) || ((strcmp(pTok, "server") == 0) && !common)) ||
203 (strcmp(pTok, "gateway") == 0) || (strcmp(pTok, "netmask") == 0)) {
204 return SetNetConfigInfo(dhcpConfig, pTok, pSave, common);
205 } else if ((strcmp(pTok, "leaseTime") == 0) || (strcmp(pTok, "renewalTime") == 0) ||
206 (strcmp(pTok, "rebindingTime") == 0)) {
207 return SetTimeConfigInfo(dhcpConfig, pTok, pSave);
208 } else if ((strcmp(pTok, "distribution") == 0) || (strcmp(pTok, "broadcast") == 0)) {
209 return SetEnableConfigInfo(dhcpConfig, pTok, pSave);
210 } else {
211 DHCP_LOGD("invalid key:%s", pTok);
212 return RET_SUCCESS;
213 }
214 }
215
ParseConfigFile(const char * configFile,const char * ifname,DhcpConfig * dhcpConfig)216 static int ParseConfigFile(const char *configFile, const char *ifname, DhcpConfig *dhcpConfig)
217 {
218 if ((configFile == nullptr) || (strlen(configFile) == 0) || (dhcpConfig == nullptr)) {
219 DHCP_LOGE("ParseConfigFile param configFile or dhcpConfig is nullptr or len = 0!");
220 return RET_FAILED;
221 }
222
223 FILE *fp = fopen(configFile, "r");
224 if (fp == nullptr) {
225 DHCP_LOGE("fopen %{public}s failed, err:%{public}d", configFile, errno);
226 return RET_FAILED;
227 }
228
229 int bComm = 1;
230 int bValid = 1;
231 char strLine[FILE_LINE_LEN_MAX] = {0};
232 while (fgets(strLine, FILE_LINE_LEN_MAX, fp) != nullptr) {
233 DHCP_LOGI("fgets strLine = %{public}s", strLine);
234 if ((strchr(strLine, '#') != nullptr) || (strchr(strLine, '=') == nullptr) ||
235 !RemoveSpaceCharacters(strLine, FILE_LINE_LEN_MAX)) {
236 if (memset_s(strLine, FILE_LINE_LEN_MAX, 0, FILE_LINE_LEN_MAX) != EOK) {
237 break;
238 }
239 continue;
240 }
241 if (memcmp(strLine, "interface", strlen("interface")) == 0) {
242 bComm = 0;
243 bValid = 0;
244 if ((ifname == nullptr) || (strlen(ifname) == 0) || (strstr(strLine, ifname) != nullptr)) {
245 DHCP_LOGI("%s %s find ifname:%s", configFile, strLine, ((ifname == nullptr) ? "" : ifname));
246 bValid = 1;
247 } else {
248 DHCP_LOGI("%s %s no find ifname:%s", configFile, strLine, ifname);
249 }
250 }
251 if (bValid && SetDhcpConfig(dhcpConfig, strLine, bComm) != RET_SUCCESS) {
252 DHCP_LOGE("set dhcp config %s %s failed", configFile, strLine);
253 fclose(fp);
254 return RET_FAILED;
255 }
256 if (memset_s(strLine, FILE_LINE_LEN_MAX, 0, FILE_LINE_LEN_MAX) != EOK) {
257 break;
258 }
259 }
260 if (fclose(fp) != 0) {
261 DHCP_LOGE("ParseConfigFile fclose fp failed!");
262 }
263 return RET_SUCCESS;
264 }
265
CheckDhcpConfig(DhcpConfig * config)266 static int CheckDhcpConfig(DhcpConfig *config)
267 {
268 if (config == nullptr) {
269 DHCP_LOGE("CheckDhcpConfig param config is null");
270 return DHCP_FALSE;
271 }
272 if ((strlen(config->ifname) > 0) && ((config->serverId == 0))) {
273 DHCP_LOGE("failed to config serverId or netmask");
274 return DHCP_FALSE;
275 }
276
277 if (config->renewalTime == 0) {
278 config->renewalTime = config->leaseTime * DHCP_RENEWAL_MULTIPLE;
279 }
280 if (config->rebindingTime == 0) {
281 config->rebindingTime = config->leaseTime * DHCP_REBIND_MULTIPLE;
282 }
283 return DHCP_TRUE;
284 }
285
LoadConfig(const char * configFile,const char * ifname,DhcpConfig * config)286 int LoadConfig(const char *configFile, const char *ifname, DhcpConfig *config)
287 {
288 if ((configFile == nullptr) || (strlen(configFile) == 0) || (ifname == nullptr) || (strlen(ifname) == 0) ||
289 (config == nullptr)) {
290 DHCP_LOGE("LoadConfig param configFile or ifname or config is nullptr or len = 0!");
291 return RET_FAILED;
292 }
293
294 /* Default config. */
295 config->leaseTime = DHCP_LEASE_TIME;
296 config->distribution = 1;
297 config->broadcast = 1;
298
299 /* Set file config. */
300 if (ParseConfigFile(configFile, ifname, config) != RET_SUCCESS) {
301 DHCP_LOGE("parse config file %{public}s error!", configFile);
302 return RET_FAILED;
303 }
304 DHCP_LOGI("parse config file %{public}s success", configFile);
305
306 if (!CheckDhcpConfig(config)) {
307 DHCP_LOGE("check dhcp config failed");
308 return RET_FAILED;
309 }
310
311 if ((strlen(config->ifname) == 0) && SetIfnameInfo(config, ifname) != RET_SUCCESS) {
312 DHCP_LOGE("set ifname %s error!", ifname);
313 return RET_FAILED;
314 }
315 return RET_SUCCESS;
316 }
317