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