• 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 <errno.h>
17 #include <signal.h>
18 #include <stdint.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include "address_utils.h"
23 #include "dhcp_address_pool.h"
24 #include "dhcp_argument.h"
25 #include "dhcp_config.h"
26 #include "dhcp_define.h"
27 #include "dhcp_ipv4.h"
28 #include "dhcp_logger.h"
29 #include "dhcp_option.h"
30 #include "dhcp_server.h"
31 
32 #undef LOG_TAG
33 #define LOG_TAG "DhcpServerMain"
34 
35 #define DEFAUTL_NET_MASK "255.255.255.0"
36 
37 static DhcpConfig g_dhcpConfig;
38 
39 static PDhcpServerContext g_dhcpServer = 0;
40 
41 enum SignalEvent {
42     EXIT = 0,
43     RELOAD,
44     RESTART,
45 };
46 
47 typedef struct DhcpOptionField {
48     const char *field;
49     int code;
50     const char *explain;
51     const char *format;
52     int supported;
53     int (*parseOption)(DhcpOption *, int, char *);
54 
55 } DhcpOptionField;
56 
LoadLocalConfig(DhcpAddressPool * pool)57 void LoadLocalConfig(DhcpAddressPool *pool)
58 {
59     LOGD("loading local configure ...");
60 }
61 
ReloadLocalConfig(DhcpAddressPool * pool)62 void ReloadLocalConfig(DhcpAddressPool *pool)
63 {
64     LOGD("reloading local configure ...");
65 }
66 
InitNetworkAbout(DhcpConfig * config)67 static int InitNetworkAbout(DhcpConfig *config)
68 {
69     ArgumentInfo *arg = GetArgument("netmask");
70     if (arg) {
71         LOGI("subnet mask:%s", arg->value);
72         uint32_t argNetmask = ParseIpAddr(arg->value);
73         if (argNetmask) {
74             config->netmask = argNetmask;
75         } else {
76             LOGW("error netmask argument.");
77             return RET_FAILED;
78         }
79     } else {
80         if (!config->netmask) {
81             config->netmask = ParseIpAddr(DEFAUTL_NET_MASK);
82         }
83     }
84     arg = GetArgument("gateway");
85     if (arg) {
86         LOGI("gateway:%s", arg->value);
87         uint32_t argGateway = ParseIpAddr(arg->value);
88         if (argGateway) {
89             config->gateway = argGateway;
90         } else {
91             LOGE("error gateway argument.");
92             return RET_FAILED;
93         }
94     } else {
95         config->gateway = config->serverId;
96         LOGW("InitNetworkAbout, set gateway to serverId as default.");
97     }
98     return RET_SUCCESS;
99 }
100 
PareseAddreesRange(DhcpConfig * config)101 static int PareseAddreesRange(DhcpConfig *config)
102 {
103     ArgumentInfo *arg = GetArgument("pool");
104     if (arg) {
105         LOGD("pool info:%s", arg->value);
106         int index = 0;
107         char *src = arg->value;
108         char *delim = ",";
109         char *pSave = NULL;
110         char *poolPartArg;
111         poolPartArg = strtok_r(src, delim, &pSave);
112         while (poolPartArg) {
113             if (index == 0) {
114                 config->pool.beginAddress = ParseIpAddr(poolPartArg);
115                 LOGD("address range begin of: %s", poolPartArg);
116             } else if (index == 1) {
117                 config->pool.endAddress = ParseIpAddr(poolPartArg);
118                 LOGD("address range end of: %s", poolPartArg);
119             }
120             index++;
121             poolPartArg = strtok_r(NULL, delim, &pSave);
122         }
123         if (!config->pool.beginAddress || !config->pool.endAddress) {
124             LOGE("'pool' argument format error.");
125             return RET_FAILED;
126         }
127         return RET_SUCCESS;
128     }
129     LOGW("failed to get 'pool' argument.");
130     return RET_FAILED;
131 }
132 
InitAddressRange(DhcpConfig * config)133 static int InitAddressRange(DhcpConfig *config)
134 {
135     if (HasArgument("pool")) {
136         if (PareseAddreesRange(config) != RET_SUCCESS) {
137             LOGW("dhcp range config error.");
138             return RET_FAILED;
139         }
140     } else {
141         if (!config->pool.beginAddress || !config->pool.endAddress) {
142             config->pool.beginAddress = FirstIpAddress(config->serverId, config->netmask);
143             config->pool.endAddress = LastIpAddress(config->serverId, config->netmask);
144         }
145     }
146     return RET_SUCCESS;
147 }
148 
InitDomainNameServer(DhcpConfig * config)149 static int InitDomainNameServer(DhcpConfig *config)
150 {
151     DhcpOption argOpt = {DOMAIN_NAME_SERVER_OPTION, 0, {0}};
152     ArgumentInfo *arg = GetArgument("dns");
153     if (arg) {
154         char *pSave = NULL;
155         char *pTok = strtok_r(arg->value, ",", &pSave);
156         if ((pTok == NULL) || (strlen(pTok) == 0)) {
157             LOGE("strtok_r pTok NULL or len is 0!");
158             return RET_FAILED;
159         }
160         uint32_t dnsAddress;
161         while (pTok != NULL) {
162             if ((dnsAddress = ParseIpAddr(pTok)) == 0) {
163                 LOGE("ParseIpAddr %s failed, code:%d", pTok, argOpt.code);
164                 return RET_FAILED;
165             }
166             if (AppendAddressOption(&argOpt, dnsAddress) != RET_SUCCESS) {
167                 LOGW("failed to append dns option.");
168             }
169             pTok = strtok_r(NULL, ",", &pSave);
170         }
171     } else {
172         LOGW("%{public}s, set dns to serverId as default.", __func__);
173         uint32_t dnsAddress = config->serverId;
174         if (AppendAddressOption(&argOpt, dnsAddress) != RET_SUCCESS) {
175             LOGW("failed to append dns option.");
176         }
177     }
178 
179     if (GetOption(&config->options, argOpt.code) != NULL) {
180         RemoveOption(&config->options, DOMAIN_NAME_SERVER_OPTION);
181     }
182     PushBackOption(&config->options, &argOpt);
183     return RET_SUCCESS;
184 }
185 
InitServerId(DhcpConfig * config)186 static int InitServerId(DhcpConfig *config)
187 {
188     ArgumentInfo *arg = GetArgument("server");
189     if (arg) {
190         LOGI("server id:%s", arg->value);
191         uint32_t argServerId = ParseIpAddr(arg->value);
192         if (argServerId) {
193             config->serverId = argServerId;
194         } else {
195             LOGE("error server argument.");
196             return RET_FAILED;
197         }
198     } else {
199         if (!config->serverId) {
200             LOGE("failed to get 'server' argument or config item.");
201             return RET_FAILED;
202         }
203     }
204     return RET_SUCCESS;
205 }
206 
InitLeaseTime(DhcpConfig * config)207 static int InitLeaseTime(DhcpConfig *config)
208 {
209     ArgumentInfo *arg = GetArgument("lease");
210     if (arg) {
211         config->leaseTime = atoi(arg->value);
212     } else {
213         if (!config->leaseTime) {
214             config->leaseTime = DHCP_LEASE_TIME;
215         }
216     }
217     return RET_SUCCESS;
218 }
219 
InitRenewalTime(DhcpConfig * config)220 static int InitRenewalTime(DhcpConfig *config)
221 {
222     ArgumentInfo *arg = GetArgument("renewal");
223     if (arg) {
224         config->renewalTime = atoi(arg->value);
225     } else {
226         if (!config->rebindingTime) {
227             config->rebindingTime = DHCP_RENEWAL_TIME;
228         }
229         config->renewalTime = DHCP_RENEWAL_TIME;
230     }
231     return RET_SUCCESS;
232 }
233 
InitRebindingTime(DhcpConfig * config)234 static int InitRebindingTime(DhcpConfig *config)
235 {
236     ArgumentInfo *arg = GetArgument("rebinding");
237     if (arg) {
238         config->rebindingTime = atoi(arg->value);
239     } else {
240         if (!config->rebindingTime) {
241             config->rebindingTime =  DHCP_REBINDING_TIME;
242         }
243     }
244     return RET_SUCCESS;
245 }
InitConfigByArguments(DhcpConfig * config)246 static int InitConfigByArguments(DhcpConfig *config)
247 {
248     if (!config) {
249         LOGE("dhcp configure pointer is null.");
250         return RET_FAILED;
251     }
252     if (InitServerId(config) != RET_SUCCESS) {
253         return RET_FAILED;
254     }
255     if (InitNetworkAbout(config) != RET_SUCCESS) {
256         return RET_FAILED;
257     }
258     if (InitAddressRange(config) != RET_SUCCESS) {
259         return RET_FAILED;
260     }
261     if (InitLeaseTime(config) != RET_SUCCESS) {
262         return RET_FAILED;
263     }
264     if (InitRenewalTime(config) != RET_SUCCESS) {
265         return RET_FAILED;
266     }
267     if (InitRebindingTime(config) != RET_SUCCESS) {
268         return RET_FAILED;
269     }
270     if (InitDomainNameServer(config) != RET_SUCCESS) {
271         return RET_FAILED;
272     }
273     return RET_SUCCESS;
274 }
275 
ServerActionCallback(int state,int code,const char * ifname)276 int ServerActionCallback(int state, int code, const char *ifname)
277 {
278     int ret = 0;
279     switch (state) {
280         case ST_STARTING: {
281             if (code == 0) {
282                 LOGD(" callback[%s] ==> server starting ...", ifname);
283             } else if (code == 1) {
284                 LOGD(" callback[%s] ==> server started.", ifname);
285             } else if (code == NUM_TWO) {
286                 LOGD(" callback[%s] ==> server start failed.", ifname);
287             }
288             break;
289         }
290         case ST_RELOADNG: {
291             LOGD(" callback[%s] ==> reloading ...", ifname);
292             break;
293         }
294         case ST_STOPED: {
295             LOGD(" callback[%s] ==> server stopped.", ifname);
296             break;
297         }
298         default:
299             break;
300     }
301     return ret;
302 }
303 
SignalHandler(int signal)304 static void SignalHandler(int signal)
305 {
306     switch (signal) {
307         case SIGTERM: {
308             exit(0);
309             break;
310         }
311         case SIGUSR1:
312             break;
313         default:
314             break;
315     }
316 }
317 
RegisterSignalHandle(void)318 static int RegisterSignalHandle(void)
319 {
320     if (signal(SIGTERM, SignalHandler) == SIG_ERR) {
321         LOGE("RegisterSignalHandle() failed, signal SIGTERM err:%d!", errno);
322         return RET_FAILED;
323     }
324 
325     if (signal(SIGUSR1, SignalHandler) == SIG_ERR) {
326         LOGE("RegisterSignalHandle() failed, signal SIGUSR1 err:%d!", errno);
327         return RET_FAILED;
328     }
329 
330     return RET_SUCCESS;
331 }
332 
InitializeDhcpConfig(const char * ifname,DhcpConfig * config)333 static int InitializeDhcpConfig(const char *ifname, DhcpConfig *config)
334 {
335     if (!config) {
336         LOGE("dhcp configure pointer is null.");
337         return RET_FAILED;
338     }
339     if (InitOptionList(&config->options) != RET_SUCCESS) {
340         LOGE("failed to initialize options.");
341         return RET_FAILED;
342     }
343     char *configFile = DHCPD_CONFIG_FILE;
344     if (HasArgument("conf")) {
345         ArgumentInfo *configArg = GetArgument("conf");
346         if (configArg) {
347             configFile = configArg->value;
348         } else {
349             LOGE("failed to get config file name.");
350             return RET_FAILED;
351         }
352     }
353     LOGD("load local dhcp config file:%s", configFile);
354     if (LoadConfig(configFile, ifname, config) != RET_SUCCESS) {
355         LOGE("failed to load configure file.");
356         return RET_FAILED;
357     }
358     if (InitConfigByArguments(config) != RET_SUCCESS) {
359         LOGE("failed to parse arguments.");
360         return RET_FAILED;
361     }
362 
363     return RET_SUCCESS;
364 }
365 
FreeLocalConfig(void)366 static void FreeLocalConfig(void)
367 {
368     FreeOptionList(&g_dhcpConfig.options);
369 }
370 
FreeSeverResources(void)371 void FreeSeverResources(void)
372 {
373     FreeArguments();
374     FreeLocalConfig();
375     if (FreeServerContext(&g_dhcpServer) != RET_SUCCESS) {
376         LOGE("Free server context failed!");
377         return;
378     }
379 }
380 
BeforeExit(void)381 static void BeforeExit(void)
382 {
383     if (g_dhcpServer) {
384         LOGD("saving lease recoder...");
385         if (SaveLease(g_dhcpServer) != RET_SUCCESS) {
386             LOGD("failed to save lease recoder.");
387         }
388     }
389     FreeSeverResources();
390 }
391 
main(int argc,char * argv[])392 int main(int argc, char *argv[])
393 {
394     if (argc == 1) {
395         PrintRequiredArguments();
396         return 1;
397     }
398     if (strcmp("-h", argv[argc - 1]) == 0 || strcmp("--help", argv[argc - 1]) == 0) {
399         ShowHelp(argc);
400         return 0;
401     }
402     if (InitArguments() != RET_SUCCESS) {
403         LOGE("failed to init arguments table.");
404         return 1;
405     }
406     int ret = ParseArguments(argc, argv);
407     if (ret != RET_SUCCESS) {
408         FreeArguments();
409         return 1;
410     }
411     ArgumentInfo *ifaceName = GetArgument("ifname");
412     if (!ifaceName || strlen(ifaceName->value) == 0) {
413         printf("missing required parameters:\"ifname\"\n");
414         FreeArguments();
415         return 1;
416     }
417     if (InitializeDhcpConfig(ifaceName->value, &g_dhcpConfig) != RET_SUCCESS) {
418         LOGW("failed to initialize config.");
419     }
420     g_dhcpServer = InitializeServer(&g_dhcpConfig);
421     if (g_dhcpServer == NULL) {
422         LOGE("failed to initialize dhcp server.");
423         FreeArguments();
424         return 1;
425     }
426     if (RegisterSignalHandle() != RET_SUCCESS) {
427         FreeSeverResources();
428         return 1;
429     }
430     if (atexit(BeforeExit) != 0) {
431         LOGW("failed to register exit process function.");
432     }
433     RegisterDhcpCallback(g_dhcpServer, ServerActionCallback);
434     if (StartDhcpServer(g_dhcpServer) != RET_SUCCESS) {
435         FreeSeverResources();
436         return 1;
437     }
438     return 0;
439 }
440