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 <cerrno>
18 #include <securec.h>
19 #include <cstdio>
20 #include <cstdlib>
21 #include <string.h>
22 #include <sys/time.h>
23 #include "address_utils.h"
24 #include "common_util.h"
25 #include "dhcp_define.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
ProcessFile(FILE * fp,const char * ifname,DhcpConfig * dhcpConfig,const char * configFile)216 static int ProcessFile(FILE *fp, const char *ifname, DhcpConfig *dhcpConfig, const char *configFile)
217 {
218 int bComm = 1;
219 int bValid = 1;
220 char strLine[FILE_LINE_LEN_MAX] = {0};
221 while (fgets(strLine, FILE_LINE_LEN_MAX, fp) != nullptr) {
222 DHCP_LOGI("fgets strLine = %{public}s", strLine);
223 if ((strchr(strLine, '#') != nullptr) || (strchr(strLine, '=') == nullptr) ||
224 !RemoveSpaceCharacters(strLine, FILE_LINE_LEN_MAX)) {
225 if (memset_s(strLine, FILE_LINE_LEN_MAX, 0, FILE_LINE_LEN_MAX) != EOK) {
226 break;
227 }
228 continue;
229 }
230 if (memcmp(strLine, "interface", strlen("interface")) == 0) {
231 bComm = 0;
232 bValid = 0;
233 if ((ifname == nullptr) || (strlen(ifname) == 0) || (strstr(strLine, ifname) != nullptr)) {
234 DHCP_LOGI("%s %s find ifname:%s", configFile, strLine, ((ifname == nullptr) ? "" : ifname));
235 bValid = 1;
236 } else {
237 DHCP_LOGI("%s %s no find ifname:%s", configFile, strLine, ifname);
238 }
239 }
240 if (bValid && SetDhcpConfig(dhcpConfig, strLine, bComm) != RET_SUCCESS) {
241 DHCP_LOGE("set dhcp config %s %s failed", configFile, strLine);
242
243 return RET_FAILED;
244 }
245 if (memset_s(strLine, FILE_LINE_LEN_MAX, 0, FILE_LINE_LEN_MAX) != EOK) {
246 break;
247 }
248 }
249 return RET_SUCCESS;
250 }
251
ParseConfigFile(const char * configFile,const char * ifname,DhcpConfig * dhcpConfig)252 static int ParseConfigFile(const char *configFile, const char *ifname, DhcpConfig *dhcpConfig)
253 {
254 if ((configFile == nullptr) || (strlen(configFile) == 0) || (dhcpConfig == nullptr)) {
255 DHCP_LOGE("ParseConfigFile param configFile or dhcpConfig is nullptr or len = 0!");
256 return RET_FAILED;
257 }
258 char *realPaths = realpath(configFile, nullptr);
259 if (realPaths == nullptr) {
260 DHCP_LOGE("realpath failed, error: ");
261 return RET_FAILED;
262 }
263 FILE *fp = fopen(realPaths, "r");
264 if (fp == nullptr) {
265 DHCP_LOGE("fopen %{public}s failed, err:%{public}d", configFile, errno);
266 free(realPaths);
267 return RET_FAILED;
268 }
269 if (ProcessFile(fp, ifname, dhcpConfig, realPaths) != RET_SUCCESS) {
270 (void)fclose(fp);
271 free(realPaths);
272 return RET_FAILED;
273 }
274 if (fclose(fp) != 0) {
275 DHCP_LOGE("ParseConfigFile fclose fp failed!");
276 }
277 free(realPaths);
278 return RET_SUCCESS;
279 }
280
CheckDhcpConfig(DhcpConfig * config)281 static int CheckDhcpConfig(DhcpConfig *config)
282 {
283 if (config == nullptr) {
284 DHCP_LOGE("CheckDhcpConfig param config is null");
285 return DHCP_FALSE;
286 }
287 if ((strlen(config->ifname) > 0) && ((config->serverId == 0))) {
288 DHCP_LOGE("failed to config serverId or netmask");
289 return DHCP_FALSE;
290 }
291
292 if (config->renewalTime == 0) {
293 config->renewalTime = config->leaseTime * DHCP_RENEWAL_MULTIPLE;
294 }
295 if (config->rebindingTime == 0) {
296 config->rebindingTime = config->leaseTime * DHCP_REBIND_MULTIPLE;
297 }
298 return DHCP_TRUE;
299 }
300
LoadConfig(const char * configFile,const char * ifname,DhcpConfig * config)301 int LoadConfig(const char *configFile, const char *ifname, DhcpConfig *config)
302 {
303 if ((configFile == nullptr) || (strlen(configFile) == 0) || (ifname == nullptr) || (strlen(ifname) == 0) ||
304 (config == nullptr)) {
305 DHCP_LOGE("LoadConfig param configFile or ifname or config is nullptr or len = 0!");
306 return RET_FAILED;
307 }
308
309 /* Default config. */
310 config->leaseTime = DHCP_LEASE_TIME;
311 config->distribution = 1;
312 config->broadcast = 1;
313
314 /* Set file config. */
315 if (ParseConfigFile(configFile, ifname, config) != RET_SUCCESS) {
316 DHCP_LOGE("parse config file %{public}s error!", configFile);
317 return RET_FAILED;
318 }
319 DHCP_LOGI("parse config file %{public}s success", configFile);
320
321 if (!CheckDhcpConfig(config)) {
322 DHCP_LOGE("check dhcp config failed");
323 return RET_FAILED;
324 }
325
326 if ((strlen(config->ifname) == 0) && SetIfnameInfo(config, ifname) != RET_SUCCESS) {
327 DHCP_LOGE("set ifname %s error!", ifname);
328 return RET_FAILED;
329 }
330 return RET_SUCCESS;
331 }
332