• 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 <cerrno>
17 #include <csignal>
18 #include <stdint.h>
19 #include <cstdio>
20 #include <cstdlib>
21 #include "dhcp_dhcpd.h"
22 #include "securec.h"
23 #include "address_utils.h"
24 #include "dhcp_address_pool.h"
25 #include "dhcp_argument.h"
26 #include "dhcp_config.h"
27 #include "dhcp_s_define.h"
28 #include "dhcp_logger.h"
29 #include "dhcp_option.h"
30 #include "dhcp_s_server.h"
31 #include "dhcp_common_utils.h"
32 
33 DEFINE_DHCPLOG_DHCP_LABEL("DhcpServerMain");
34 
35 constexpr char DEFAUTL_NET_MASK[] = "255.255.255.0";
36 
37 static DhcpConfig g_dhcpConfig;
38 
39 static PDhcpServerContext g_dhcpServer = 0;
40 static DeviceConnectFun deviceConnectFun;
41 enum SignalEvent {
42     EXIT = 0,
43     RELOAD,
44     RESTART,
45 };
46 
LoadLocalConfig(DhcpAddressPool * pool)47 void LoadLocalConfig(DhcpAddressPool *pool)
48 {
49     DHCP_LOGD("loading local configure ...");
50 }
51 
ReloadLocalConfig(DhcpAddressPool * pool)52 void ReloadLocalConfig(DhcpAddressPool *pool)
53 {
54     DHCP_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         DHCP_LOGI("subnet mask:%s", arg->value);
62         uint32_t argNetmask = ParseIpAddr(arg->value);
63         if (argNetmask) {
64             config->netmask = argNetmask;
65         } else {
66             DHCP_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         DHCP_LOGI("gateway:%s", arg->value);
77         uint32_t argGateway = ParseIpAddr(arg->value);
78         if (argGateway) {
79             config->gateway = argGateway;
80         } else {
81             DHCP_LOGE("error gateway argument.");
82             return RET_FAILED;
83         }
84     } else {
85         config->gateway = config->serverId;
86         DHCP_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         DHCP_LOGD("pool info:%s", arg->value);
96         int index = 0;
97         char *src = arg->value;
98         constexpr const char *delim = ",";
99         char *pSave = nullptr;
100         char *poolPartArg;
101         poolPartArg = strtok_r(src, delim, &pSave);
102         while (poolPartArg) {
103             if (index == 0) {
104                 config->pool.beginAddress = ParseIpAddr(poolPartArg);
105                 DHCP_LOGD("address range begin of: %s", poolPartArg);
106             } else if (index == 1) {
107                 config->pool.endAddress = ParseIpAddr(poolPartArg);
108                 DHCP_LOGD("address range end of: %s", poolPartArg);
109             }
110             index++;
111             poolPartArg = strtok_r(nullptr, delim, &pSave);
112         }
113         if (!config->pool.beginAddress || !config->pool.endAddress) {
114             DHCP_LOGE("'pool' argument format error.");
115             return RET_FAILED;
116         }
117         return RET_SUCCESS;
118     }
119     DHCP_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             DHCP_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 = nullptr;
146         char *pTok = strtok_r(arg->value, ",", &pSave);
147         if ((pTok == nullptr) || (strlen(pTok) == 0)) {
148             DHCP_LOGE("strtok_r pTok nullptr or len is 0!");
149             return RET_FAILED;
150         }
151         while (pTok != nullptr) {
152             if ((dnsAddress = ParseIpAddr(pTok)) == 0) {
153                 DHCP_LOGE("ParseIpAddr %s failed, code:%d", pTok, argOpt.code);
154                 return RET_FAILED;
155             }
156             if (AppendAddressOption(&argOpt, dnsAddress) != RET_SUCCESS) {
157                 DHCP_LOGW("failed to append dns option.");
158             }
159             pTok = strtok_r(nullptr, ",", &pSave);
160         }
161     } else {
162         DHCP_LOGW("%{public}s, set dns to serverId as default.", __func__);
163         dnsAddress = config->serverId;
164         if (AppendAddressOption(&argOpt, dnsAddress) != RET_SUCCESS) {
165             DHCP_LOGW("failed to append dns option.");
166         }
167     }
168 
169     if (GetOption(&config->options, argOpt.code) != nullptr) {
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         DHCP_LOGI("server id:%s", arg->value);
181         uint32_t argServerId = ParseIpAddr(arg->value);
182         if (argServerId) {
183             config->serverId = argServerId;
184         } else {
185             DHCP_LOGE("error server argument.");
186             return RET_FAILED;
187         }
188     } else {
189         if (!config->serverId) {
190             DHCP_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         std::string strValue = arg->value;
202         config->leaseTime = static_cast<uint32_t>(OHOS::DHCP::CheckDataLegal(strValue));
203     } else {
204         if (!config->leaseTime) {
205             config->leaseTime = DHCP_LEASE_TIME;
206         }
207     }
208     return RET_SUCCESS;
209 }
210 
InitRenewalTime(DhcpConfig * config)211 static int InitRenewalTime(DhcpConfig *config)
212 {
213     ArgumentInfo *arg = GetArgument("renewal");
214     if (arg) {
215         std::string strValue = arg->value;
216         config->renewalTime = static_cast<uint32_t>(OHOS::DHCP::CheckDataLegal(strValue));
217     } else {
218         if (!config->rebindingTime) {
219             config->rebindingTime = DHCP_RENEWAL_TIME;
220         }
221         config->renewalTime = DHCP_RENEWAL_TIME;
222     }
223     return RET_SUCCESS;
224 }
225 
InitRebindingTime(DhcpConfig * config)226 static int InitRebindingTime(DhcpConfig *config)
227 {
228     ArgumentInfo *arg = GetArgument("rebinding");
229     if (arg) {
230         std::string strValue = arg->value;
231         config->rebindingTime = static_cast<uint32_t>(OHOS::DHCP::CheckDataLegal(strValue));
232     } else {
233         if (!config->rebindingTime) {
234             config->rebindingTime =  DHCP_REBINDING_TIME;
235         }
236     }
237     return RET_SUCCESS;
238 }
InitConfigByArguments(DhcpConfig * config)239 static int InitConfigByArguments(DhcpConfig *config)
240 {
241     if (!config) {
242         DHCP_LOGE("dhcp configure pointer is null.");
243         return RET_FAILED;
244     }
245     if (InitServerId(config) != RET_SUCCESS) {
246         return RET_FAILED;
247     }
248     if (InitNetworkAbout(config) != RET_SUCCESS) {
249         return RET_FAILED;
250     }
251     if (InitAddressRange(config) != RET_SUCCESS) {
252         return RET_FAILED;
253     }
254     if (InitLeaseTime(config) != RET_SUCCESS) {
255         return RET_FAILED;
256     }
257     if (InitRenewalTime(config) != RET_SUCCESS) {
258         return RET_FAILED;
259     }
260     if (InitRebindingTime(config) != RET_SUCCESS) {
261         return RET_FAILED;
262     }
263     if (InitDomainNameServer(config) != RET_SUCCESS) {
264         return RET_FAILED;
265     }
266     return RET_SUCCESS;
267 }
268 
ServerActionCallback(int state,int code,const char * ifname)269 int ServerActionCallback(int state, int code, const char *ifname)
270 {
271     int ret = 0;
272     switch (state) {
273         case ST_STARTING: {
274             if (code == 0) {
275                 DHCP_LOGD(" callback[%s] ==> server starting ...", ifname);
276             } else if (code == 1) {
277                 DHCP_LOGD(" callback[%s] ==> server started.", ifname);
278             } else if (code == NUM_TWO) {
279                 DHCP_LOGD(" callback[%s] ==> server start failed.", ifname);
280             }
281             break;
282         }
283         case ST_RELOADNG: {
284             DHCP_LOGD(" callback[%s] ==> reloading ...", ifname);
285             break;
286         }
287         case ST_STOPED: {
288             DHCP_LOGD(" callback[%s] ==> server stopped.", ifname);
289             break;
290         }
291         default:
292             break;
293     }
294     return ret;
295 }
296 
InitializeDhcpConfig(const char * ifname,DhcpConfig * config)297 static int InitializeDhcpConfig(const char *ifname, DhcpConfig *config)
298 {
299     if (!config) {
300         DHCP_LOGE("dhcp configure pointer is null.");
301         return RET_FAILED;
302     }
303     if (InitOptionList(&config->options) != RET_SUCCESS) {
304         DHCP_LOGE("failed to initialize options.");
305         return RET_FAILED;
306     }
307     char configFile[ARGUMENT_VALUE_SIZE] = {0};
308     if (memcpy_s(configFile, ARGUMENT_VALUE_SIZE, DHCPD_CONFIG_FILE, strlen(DHCPD_CONFIG_FILE)) != EOK) {
309         DHCP_LOGE("conf memcpy_s failed.");
310         return RET_FAILED;
311     }
312     if (HasArgument("conf")) {
313         ArgumentInfo *configArg = GetArgument("conf");
314         if (configArg) {
315             if (memcpy_s(configFile, ARGUMENT_VALUE_SIZE, configArg->value, strlen(configArg->value)) != EOK) {
316                 DHCP_LOGE("conf memcpy_s failed.");
317                 return RET_FAILED;
318             }
319         } else {
320             DHCP_LOGE("failed to get config file name.");
321             return RET_FAILED;
322         }
323     }
324     DHCP_LOGI("load local dhcp config file:%{public}s", configFile);
325     if (LoadConfig(configFile, ifname, config) != RET_SUCCESS) {
326         DHCP_LOGE("failed to load configure file.");
327         return RET_FAILED;
328     }
329     DHCP_LOGI("init config by argument.");
330     if (InitConfigByArguments(config) != RET_SUCCESS) {
331         DHCP_LOGE("failed to parse arguments.");
332         return RET_FAILED;
333     }
334 
335     return RET_SUCCESS;
336 }
337 
FreeLocalConfig(void)338 static void FreeLocalConfig(void)
339 {
340     FreeOptionList(&g_dhcpConfig.options);
341 }
342 
FreeSeverResources(void)343 void FreeSeverResources(void)
344 {
345     DHCP_LOGI("FreeSeverResources enter");
346     FreeArguments();
347     FreeLocalConfig();
348     if (FreeServerContext(&g_dhcpServer) != RET_SUCCESS) {
349         DHCP_LOGE("Free server context failed!");
350         return;
351     }
352 }
353 
StartDhcpServerMain(const std::string & ifName,const std::string & netMask,const std::string & ipRange,const std::string & localIp)354 int StartDhcpServerMain(const std::string& ifName, const std::string& netMask, const std::string& ipRange,
355     const std::string& localIp)
356 {
357     DHCP_LOGI("StartDhcpServerMain.");
358 
359     if (InitArguments() != RET_SUCCESS) {
360         DHCP_LOGE("failed to init arguments table.");
361         return 1;
362     }
363     int ret = ParseArguments(ifName, netMask, ipRange, localIp);
364     if (ret != RET_SUCCESS) {DHCP_LOGE("error ParseArguments.");
365         FreeArguments();
366         return 1;
367     }
368     ArgumentInfo *ifaceName = GetArgument("ifname");
369     if (!ifaceName || strlen(ifaceName->value) == 0) {
370         printf("missing required parameters:\"ifname\"\n");
371         FreeArguments();
372         return 1;
373     }
374     if (InitializeDhcpConfig(ifaceName->value, &g_dhcpConfig) != RET_SUCCESS) {
375         DHCP_LOGW("failed to initialize config.");
376     }
377     if (strcpy_s(g_dhcpConfig.ifname, IFACE_NAME_SIZE, ifaceName->value) != EOK) {
378         DHCP_LOGE("cpy ifname failed!");
379         return 1;
380     }
381     g_dhcpServer = InitializeServer(&g_dhcpConfig);
382     if (g_dhcpServer == nullptr) {
383         DHCP_LOGE("failed to initialize dhcp server.");
384         FreeSeverResources();
385         return 1;
386     }
387 
388     RegisterDhcpCallback(g_dhcpServer, ServerActionCallback);
389     RegisterDeviceChangedCallback(g_dhcpServer, deviceConnectFun);
390     if (StartDhcpServer(g_dhcpServer) != RET_SUCCESS) {
391         FreeSeverResources();
392         return 1;
393     }
394     return 0;
395 }
396 
StopDhcpServerMain()397 int StopDhcpServerMain()
398 {
399     DHCP_LOGI("StopDhcpServerMain.");
400     if (StopDhcpServer(g_dhcpServer) != RET_SUCCESS) {
401         FreeSeverResources();
402         return 1;
403     }
404     FreeSeverResources();
405     return 0;
406 }
407 
RegisterDeviceConnectCallBack(DeviceConnectFun fun)408 int RegisterDeviceConnectCallBack(DeviceConnectFun fun)
409 {
410     DHCP_LOGI("RegisterDeviceConnectCallBack enter!");
411     deviceConnectFun = fun;
412     return 0;
413 }