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 28DEFINE_DHCPLOG_DHCP_LABEL("DhcpArgument"); 29 30static std::map<std::string, ArgumentInfo> g_argumentsTable; 31 32static 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 41static 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 53static int ShowVersion(const char *argument, const char *val) 54{ 55 DHCP_LOGI("version:%s\n", DHCPD_VERSION); 56 return RET_SUCCESS; 57} 58 59static 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 66const char *g_optionString = "i:c:d:g:s:n:P:S:Bp:o:lb:rvhD"; 67 68static 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 84static 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 104int 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 127static 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 150void 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 175static 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 190void ShowHelp(int argc) 191{ 192 if (argc == NUM_TWO) { 193 PrintUsage(); 194 return; 195 } 196} 197 198int InitArguments(void) 199{ 200 DHCP_LOGI("start InitArguments."); 201 g_argumentsTable.clear(); 202 DHCP_LOGI("end InitArguments."); 203 return RET_SUCCESS; 204} 205 206ArgumentInfo *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 223int 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 267int 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 278int 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 289void FreeArguments(void) 290{ 291 g_argumentsTable.clear(); 292} 293