• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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