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