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_ipv4.h"
26 #include "dhcp_logger.h"
27
28 #undef LOG_TAG
29 #define LOG_TAG "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 == NULL) || (pKey == NULL) || (pValue == NULL)) {
37 LOGE("SetEnableConfigInfo param dhcpConfig or pKey or pValue is NULL!");
38 return RET_FAILED;
39 }
40
41 uint32_t uValue = (uint32_t)atoi(pValue);
42 if ((uValue != 0) && (uValue != 1)) {
43 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 == NULL) || (pKey == NULL) || (pValue == NULL)) {
58 LOGE("SetTimeConfigInfo param dhcpConfig or pKey or pValue is NULL!");
59 return RET_FAILED;
60 }
61
62 uint32_t uValue = 0;
63 if ((uValue = (uint32_t)atoi(pValue)) == 0) {
64 LOGE("atoi failed, time:%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 == NULL) || (pKey == NULL) || (pValue == NULL)) {
81 LOGE("SetNetConfigInfo param dhcpConfig or pKey or pValue is NULL!");
82 return RET_FAILED;
83 }
84
85 uint32_t uValue = 0;
86 if ((uValue = ParseIpAddr(pValue)) == 0) {
87 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 == NULL) || (pValue == NULL)) {
104 LOGE("SetIpAddressPool param dhcpConfig or pValue is NULL!");
105 return RET_FAILED;
106 }
107
108 char *pSrc = (char *)pValue;
109 char *pSave = NULL;
110 char *pTok = strtok_r(pSrc, ",", &pSave);
111 if (((pTok == NULL) || (strlen(pTok) == 0)) || ((pSave == NULL) || (strlen(pSave) == 0))) {
112 LOGE("strtok_r pTok or pSave NULL or len is 0!");
113 return RET_FAILED;
114 }
115
116 uint32_t begin;
117 if (((begin = ParseIpAddr(pTok)) == 0)) {
118 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 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 == NULL) || (pValue == NULL)) {
134 LOGE("SetDnsInfo param dhcpConfig or pValue is NULL!");
135 return RET_FAILED;
136 }
137
138 char *pSrc = (char *)pValue;
139 char *pSave = NULL;
140 char *pTok = strtok_r(pSrc, ",", &pSave);
141 if ((pTok == NULL) || (strlen(pTok) == 0)) {
142 LOGE("strtok_r pTok NULL 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) != NULL) {
148 RemoveOption(&dhcpConfig->options, optDns.code);
149 }
150
151 uint32_t dnsAddress;
152 while (pTok != NULL) {
153 if ((dnsAddress = ParseIpAddr(pTok)) == 0) {
154 LOGE("ParseIpAddr %s failed, code:%d", pTok, optDns.code);
155 return RET_FAILED;
156 }
157 if (AppendAddressOption(&optDns, dnsAddress) != RET_SUCCESS) {
158 LOGW("failed append dns option.");
159 }
160 pTok = strtok_r(NULL, ",", &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 == NULL) || (pValue == NULL)) {
169 LOGE("SetIfnameInfo dhcpConfig or pValue is NULL!");
170 return RET_FAILED;
171 }
172 if (strlen(pValue) >= IFACE_NAME_SIZE) {
173 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 == NULL) || (strlen(strLine) == 0)) {
186 LOGE("SetDhcpConfig param strLine is NULL or len = 0!");
187 return RET_FAILED;
188 }
189
190 char *pSrc = (char *)strLine;
191 char *pSave = NULL;
192 char *pTok = strtok_r(pSrc, FILE_LINE_DELIMITER, &pSave);
193 if (pTok == NULL) {
194 LOGE("strtok_r pTok NULL!");
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 LOGD("invalid key:%s", pTok);
213 return RET_SUCCESS;
214 }
215 }
216
ParseConfigFile(const char * configFile,const char * ifname,DhcpConfig * dhcpConfig)217 static int ParseConfigFile(const char *configFile, const char *ifname, DhcpConfig *dhcpConfig)
218 {
219 if ((configFile == NULL) || (strlen(configFile) == 0) || (dhcpConfig == NULL)) {
220 LOGE("ParseConfigFile param configFile or dhcpConfig is NULL or len = 0!");
221 return RET_FAILED;
222 }
223
224 FILE *fp = fopen(configFile, "r");
225 if (fp == NULL) {
226 LOGE("fopen %s failed, err:%d", configFile, errno);
227 return RET_FAILED;
228 }
229
230 int bComm = 1;
231 int bValid = 1;
232 char strLine[FILE_LINE_LEN_MAX] = {0};
233 while (fgets(strLine, FILE_LINE_LEN_MAX, fp) != NULL) {
234 if ((strchr(strLine, '#') != NULL) || (strchr(strLine, '=') == NULL) ||
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 == NULL) || (strlen(ifname) == 0) || (strstr(strLine, ifname) != NULL)) {
245 LOGI("%s %s find ifname:%s", configFile, strLine, ((ifname == NULL) ? "" : ifname));
246 bValid = 1;
247 } else {
248 LOGI("%s %s no find ifname:%s", configFile, strLine, ifname);
249 }
250 }
251 if (bValid && SetDhcpConfig(dhcpConfig, strLine, bComm) != RET_SUCCESS) {
252 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 fclose(fp);
261 return RET_SUCCESS;
262 }
263
CheckDhcpConfig(DhcpConfig * config)264 static int CheckDhcpConfig(DhcpConfig *config)
265 {
266 if (config == NULL) {
267 LOGE("CheckDhcpConfig param config is null");
268 return DHCP_FALSE;
269 }
270 if ((strlen(config->ifname) > 0) && ((config->serverId == 0))) {
271 LOGE("failed to config serverId or netmask");
272 return DHCP_FALSE;
273 }
274
275 if (config->renewalTime == 0) {
276 config->renewalTime = config->leaseTime * DHCP_RENEWAL_MULTIPLE;
277 }
278 if (config->rebindingTime == 0) {
279 config->rebindingTime = config->leaseTime * DHCP_REBIND_MULTIPLE;
280 }
281 return DHCP_TRUE;
282 }
283
LoadConfig(const char * configFile,const char * ifname,DhcpConfig * config)284 int LoadConfig(const char *configFile, const char *ifname, DhcpConfig *config)
285 {
286 if ((configFile == NULL) || (strlen(configFile) == 0) || (ifname == NULL) || (strlen(ifname) == 0) ||
287 (config == NULL)) {
288 LOGE("LoadConfig param configFile or ifname or config is NULL or len = 0!");
289 return RET_FAILED;
290 }
291
292 /* Default config. */
293 config->leaseTime = DHCP_LEASE_TIME;
294 config->distribution = 1;
295 config->broadcast = 1;
296
297 /* Set file config. */
298 if (ParseConfigFile(configFile, ifname, config) != RET_SUCCESS) {
299 LOGE("parse config file %s error!", configFile);
300 return RET_FAILED;
301 }
302 LOGI("parse config file %s success", configFile);
303
304 if (!CheckDhcpConfig(config)) {
305 LOGE("check dhcp config failed");
306 return RET_FAILED;
307 }
308
309 if ((strlen(config->ifname) == 0) && SetIfnameInfo(config, ifname) != RET_SUCCESS) {
310 LOGE("set ifname %s error!", ifname);
311 return RET_FAILED;
312 }
313 return RET_SUCCESS;
314 }
315