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