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_argument.h"
17 #include <map>
18 #include <getopt.h>
19 #include <securec.h>
20 #include <stddef.h>
21 #include <stdint.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include "address_utils.h"
25 #include "dhcp_s_define.h"
26 #include "dhcp_logger.h"
27
28 DEFINE_DHCPLOG_DHCP_LABEL("DhcpArgument");
29
30 static std::map<std::string, ArgumentInfo> g_argumentsTable;
31
PutIpArgument(const char * argument,const char * val)32 static int PutIpArgument(const char *argument, const char *val)
33 {
34 if (!ParseIpAddr(val)) {
35 DHCP_LOGE("%s format error.", argument);
36 return RET_FAILED;
37 }
38 return PutArgument(argument, val);
39 }
40
PutPoolArgument(const char * argument,const char * val)41 static int PutPoolArgument(const char *argument, const char *val)
42 {
43 if (!val) {
44 return 0;
45 }
46 if (strchr(val, ',') == nullptr) {
47 DHCP_LOGE("too few pool option arguments.");
48 return RET_FAILED;
49 }
50 return PutArgument(argument, val);
51 }
52
ShowVersion(const char * argument,const char * val)53 static int ShowVersion(const char *argument, const char *val)
54 {
55 DHCP_LOGI("version:%s\n", DHCPD_VERSION);
56 return RET_SUCCESS;
57 }
58
DefaultArgument(const char * argument,const char * val)59 static int DefaultArgument(const char *argument, const char *val)
60 {
61 DHCP_LOGI("Input argument is: [%s], value is [%s]", (argument == nullptr) ? "" : argument,
62 (val == nullptr) ? "" : val);
63 return RET_SUCCESS;
64 }
65
66 const char *g_optionString = "i:c:d:g:s:n:P:S:Bp:o:lb:rvhD";
67
68 static struct option g_longOptions[] = {
69 {"ifname", REQUIRED_ARG, 0, 'i'},
70 {"conf", REQUIRED_ARG, 0, 'c'},
71 {"dns", REQUIRED_ARG, 0, 'd'},
72 {"gateway", REQUIRED_ARG, 0, 'g'},
73 {"server", REQUIRED_ARG, 0, 's'},
74 {"netmask", REQUIRED_ARG, 0, 'n'},
75 {"pool", REQUIRED_ARG, 0, 'P'},
76 {"lease", REQUIRED_ARG, 0, 0},
77 {"renewal", REQUIRED_ARG, 0, 0},
78 {"rebinding", REQUIRED_ARG, 0, 0},
79 {"version", NO_ARG, 0, 'v'},
80 {"help", NO_ARG, 0, 'h'},
81 {0, 0, 0, 0},
82 };
83
84 static DhcpUsage usages[] = {
85 {&g_longOptions[NUM_ZERO], "<interface>", "network interface name.", "--ifname eth0", 1, PutArgument},
86 {&g_longOptions[NUM_ONE], "<file>", "configure file name.", "--conf /etc/conf/dhcp_server.conf", 0, PutArgument},
87 {&g_longOptions[NUM_TWO], "<dns1>[,dns2][,dns3][...]", "domain name server IP address list.", "", 0, PutArgument},
88 {&g_longOptions[NUM_THREE], "<gateway>", "gateway option.", "", 0, PutIpArgument},
89 {&g_longOptions[NUM_FOUR], "<server>", "server identifier.", "", 1, PutIpArgument},
90 {&g_longOptions[NUM_FIVE], "<netmask>", "default subnet mask.", "", 1, PutIpArgument},
91 {&g_longOptions[NUM_SIX], "<beginip>,<endip>", "pool address range.", "", 0,
92 PutPoolArgument},
93 {&g_longOptions[NUM_SEVEN], "<leaseTime>", "set lease time value, the value is in units of seconds.", "", 0,
94 PutArgument},
95 {&g_longOptions[NUM_EIGHT], "<renewalTime>", "set renewal time value, the value is in units of seconds.", "", 0,
96 PutArgument},
97 {&g_longOptions[NUM_NINE], "<rebindingTime>", "set rebinding time value, the value is in units of seconds.", "", 0,
98 PutArgument},
99 {&g_longOptions[NUM_TEN], "", "show version information.", "", 0, ShowVersion},
100 {&g_longOptions[NUM_ELEVEN], "", "show help information.", "", 0, DefaultArgument},
101 {0, "", "", ""},
102 };
103
HasArgument(const char * argument)104 int HasArgument(const char *argument)
105 {
106 char name[ARGUMENT_NAME_SIZE] = {'\0'};
107 if (!argument) {
108 return 0;
109 }
110 size_t ssize = strlen(argument);
111 if (ssize > ARGUMENT_NAME_SIZE) {
112 ssize = ARGUMENT_NAME_SIZE;
113 }
114 if (memcpy_s(name, ARGUMENT_NAME_SIZE, argument, ssize) != EOK) {
115 DHCP_LOGE("failed to set argument name.");
116 return 0;
117 }
118 if (g_argumentsTable.empty()) {
119 return 0;
120 }
121 if (g_argumentsTable.count(name) > 0) {
122 return 1;
123 }
124 return 0;
125 }
126
ShowUsage(const DhcpUsage * usage)127 static void ShowUsage(const DhcpUsage *usage)
128 {
129 if (!usage || !usage->opt) {
130 return;
131 }
132 if (usage->opt->val) {
133 DHCP_LOGI("-%{public}c,--%{public}s ", (char)usage->opt->val, usage->opt->name);
134 } else {
135 DHCP_LOGI(" --%{public}s ", usage->opt->name);
136 }
137 if (usage->params[0] == '\0') {
138 DHCP_LOGI("\t\t%{public}s\n", usage->desc);
139 } else {
140 int plen = strlen(usage->params) + strlen(usage->params);
141 if (plen < USAGE_DESC_MAX_LENGTH) {
142 DHCP_LOGI("\t\t%{public}s\t\t%{public}s\n", usage->params, usage->desc);
143 } else {
144 DHCP_LOGI("\t\t%{public}s\n", usage->params);
145 DHCP_LOGI("\t\t\t%{public}s\n\n", usage->desc);
146 }
147 }
148 }
149
PrintRequiredArguments(void)150 void PrintRequiredArguments(void)
151 {
152 size_t argc = sizeof(usages) / sizeof(DhcpUsage);
153 DHCP_LOGI("required parameters:");
154 int idx = 0;
155 for (size_t i = 0; i < argc; i++) {
156 DhcpUsage usage = usages[i];
157 if (!usage.opt) {
158 break;
159 }
160 if (usage.required) {
161 if (idx == 0) {
162 DHCP_LOGI("\"%{public}s\"", usage.opt->name);
163 } else {
164 DHCP_LOGI(", \"%{public}s\"", usage.opt->name);
165 }
166 idx++;
167 }
168 }
169 DHCP_LOGI(".\n\n");
170 DHCP_LOGI("Usage: dhcp_server [options] \n");
171 DHCP_LOGI("e.g: dhcp_server -i eth0 -c /data/service/el1/public/dhcp/dhcp_server.conf \n");
172 DHCP_LOGI(" dhcp_server --help \n\n");
173 }
174
PrintUsage(void)175 static void PrintUsage(void)
176 {
177 DHCP_LOGI("Usage: dhcp_server [options] \n\n");
178
179 size_t argc = sizeof(usages) / sizeof(DhcpUsage);
180 for (size_t i = 0; i < argc; i++) {
181 DhcpUsage usage = usages[i];
182 if (!usage.opt) {
183 break;
184 }
185 ShowUsage(&usage);
186 }
187 DHCP_LOGI("\n");
188 }
189
ShowHelp(int argc)190 void ShowHelp(int argc)
191 {
192 if (argc == NUM_TWO) {
193 PrintUsage();
194 return;
195 }
196 }
197
InitArguments(void)198 int InitArguments(void)
199 {
200 DHCP_LOGI("start InitArguments.");
201 g_argumentsTable.clear();
202 DHCP_LOGI("end InitArguments.");
203 return RET_SUCCESS;
204 }
205
GetArgument(const char * name)206 ArgumentInfo *GetArgument(const char *name)
207 {
208 char argName[ARGUMENT_NAME_SIZE] = {'\0'};
209 size_t ssize = strlen(name);
210 if (ssize > ARGUMENT_NAME_SIZE) {
211 ssize = ARGUMENT_NAME_SIZE;
212 }
213 if (memcpy_s(argName, ARGUMENT_NAME_SIZE, name, ssize) != EOK) {
214 DHCP_LOGE("failed to set argument name.");
215 return nullptr;
216 }
217 if (g_argumentsTable.count(argName) > 0) {
218 return &g_argumentsTable[argName];
219 }
220 return nullptr;
221 }
222
PutArgument(const char * argument,const char * val)223 int PutArgument(const char *argument, const char *val)
224 {
225 DHCP_LOGI("start PutArgument.");
226 if (!argument) {
227 return RET_FAILED;
228 }
229 if (!val) {
230 return RET_FAILED;
231 }
232
233 if (HasArgument(argument)) {
234 return RET_FAILED;
235 }
236
237 ArgumentInfo arg;
238 size_t ssize = strlen(argument);
239 if (ssize >= ARGUMENT_NAME_SIZE) {
240 ssize = ARGUMENT_NAME_SIZE -1;
241 }
242 size_t vlen = strlen(val);
243 if (memset_s(arg.name, ARGUMENT_NAME_SIZE, '\0', ARGUMENT_NAME_SIZE) != EOK) {
244 DHCP_LOGE("failed to reset argument name.");
245 return RET_ERROR;
246 }
247 if (memcpy_s(arg.name, ARGUMENT_NAME_SIZE, argument, ssize) != EOK) {
248 DHCP_LOGE("failed to set argument name.");
249 return RET_ERROR;
250 }
251 if (vlen >= ARGUMENT_VALUE_SIZE) {
252 DHCP_LOGE("value string too long.");
253 return RET_ERROR;
254 }
255 if (memset_s(arg.value, ARGUMENT_VALUE_SIZE, '\0', ARGUMENT_NAME_SIZE) != EOK) {
256 DHCP_LOGE("failed to reset argument value.");
257 return RET_ERROR;
258 }
259 if (memcpy_s(arg.value, ARGUMENT_VALUE_SIZE, val, vlen) != EOK) {
260 DHCP_LOGE("failed to set argument value.");
261 return RET_ERROR;
262 }
263 g_argumentsTable[std::string(arg.name)] = arg;
264 return RET_SUCCESS;
265 }
266
FindIndex(int c)267 int FindIndex(int c)
268 {
269 int size = sizeof(g_longOptions) / sizeof(g_longOptions[0]);
270 for (int i = 0; i < size; ++i) {
271 if (g_longOptions[i].val == c) {
272 return i;
273 }
274 }
275 return -1;
276 }
277
ParseArguments(const std::string & ifName,const std::string & netMask,const std::string & ipRange,const std::string & localIp)278 int ParseArguments(const std::string& ifName, const std::string& netMask, const std::string& ipRange,
279 const std::string& localIp)
280 {
281 DHCP_LOGI("start ParseArguments.");
282 PutArgument("ifname", ifName.c_str());
283 PutIpArgument("server", localIp.c_str());
284 PutIpArgument("netmask", netMask.c_str());
285 PutPoolArgument("pool", ipRange.c_str());
286 return 0;
287 }
288
FreeArguments(void)289 void FreeArguments(void)
290 {
291 g_argumentsTable.clear();
292 }
293