1518678f8Sopenharmony_ci/* 2518678f8Sopenharmony_ci * Copyright (C) 2021-2022 Huawei Device Co., Ltd. 3518678f8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4518678f8Sopenharmony_ci * you may not use this file except in compliance with the License. 5518678f8Sopenharmony_ci * You may obtain a copy of the License at 6518678f8Sopenharmony_ci * 7518678f8Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8518678f8Sopenharmony_ci * 9518678f8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10518678f8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11518678f8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12518678f8Sopenharmony_ci * See the License for the specific language governing permissions and 13518678f8Sopenharmony_ci * limitations under the License. 14518678f8Sopenharmony_ci */ 15518678f8Sopenharmony_ci 16518678f8Sopenharmony_ci#include "dhcp_argument.h" 17518678f8Sopenharmony_ci#include <map> 18518678f8Sopenharmony_ci#include <getopt.h> 19518678f8Sopenharmony_ci#include <securec.h> 20518678f8Sopenharmony_ci#include <stddef.h> 21518678f8Sopenharmony_ci#include <stdint.h> 22518678f8Sopenharmony_ci#include <stdio.h> 23518678f8Sopenharmony_ci#include <string.h> 24518678f8Sopenharmony_ci#include "address_utils.h" 25518678f8Sopenharmony_ci#include "dhcp_s_define.h" 26518678f8Sopenharmony_ci#include "dhcp_logger.h" 27518678f8Sopenharmony_ci 28518678f8Sopenharmony_ciDEFINE_DHCPLOG_DHCP_LABEL("DhcpArgument"); 29518678f8Sopenharmony_ci 30518678f8Sopenharmony_cistatic std::map<std::string, ArgumentInfo> g_argumentsTable; 31518678f8Sopenharmony_ci 32518678f8Sopenharmony_cistatic int PutIpArgument(const char *argument, const char *val) 33518678f8Sopenharmony_ci{ 34518678f8Sopenharmony_ci if (!ParseIpAddr(val)) { 35518678f8Sopenharmony_ci DHCP_LOGE("%s format error.", argument); 36518678f8Sopenharmony_ci return RET_FAILED; 37518678f8Sopenharmony_ci } 38518678f8Sopenharmony_ci return PutArgument(argument, val); 39518678f8Sopenharmony_ci} 40518678f8Sopenharmony_ci 41518678f8Sopenharmony_cistatic int PutPoolArgument(const char *argument, const char *val) 42518678f8Sopenharmony_ci{ 43518678f8Sopenharmony_ci if (!val) { 44518678f8Sopenharmony_ci return 0; 45518678f8Sopenharmony_ci } 46518678f8Sopenharmony_ci if (strchr(val, ',') == nullptr) { 47518678f8Sopenharmony_ci DHCP_LOGE("too few pool option arguments."); 48518678f8Sopenharmony_ci return RET_FAILED; 49518678f8Sopenharmony_ci } 50518678f8Sopenharmony_ci return PutArgument(argument, val); 51518678f8Sopenharmony_ci} 52518678f8Sopenharmony_ci 53518678f8Sopenharmony_cistatic int ShowVersion(const char *argument, const char *val) 54518678f8Sopenharmony_ci{ 55518678f8Sopenharmony_ci DHCP_LOGI("version:%s\n", DHCPD_VERSION); 56518678f8Sopenharmony_ci return RET_SUCCESS; 57518678f8Sopenharmony_ci} 58518678f8Sopenharmony_ci 59518678f8Sopenharmony_cistatic int DefaultArgument(const char *argument, const char *val) 60518678f8Sopenharmony_ci{ 61518678f8Sopenharmony_ci DHCP_LOGI("Input argument is: [%s], value is [%s]", (argument == nullptr) ? "" : argument, 62518678f8Sopenharmony_ci (val == nullptr) ? "" : val); 63518678f8Sopenharmony_ci return RET_SUCCESS; 64518678f8Sopenharmony_ci} 65518678f8Sopenharmony_ci 66518678f8Sopenharmony_ciconst char *g_optionString = "i:c:d:g:s:n:P:S:Bp:o:lb:rvhD"; 67518678f8Sopenharmony_ci 68518678f8Sopenharmony_cistatic struct option g_longOptions[] = { 69518678f8Sopenharmony_ci {"ifname", REQUIRED_ARG, 0, 'i'}, 70518678f8Sopenharmony_ci {"conf", REQUIRED_ARG, 0, 'c'}, 71518678f8Sopenharmony_ci {"dns", REQUIRED_ARG, 0, 'd'}, 72518678f8Sopenharmony_ci {"gateway", REQUIRED_ARG, 0, 'g'}, 73518678f8Sopenharmony_ci {"server", REQUIRED_ARG, 0, 's'}, 74518678f8Sopenharmony_ci {"netmask", REQUIRED_ARG, 0, 'n'}, 75518678f8Sopenharmony_ci {"pool", REQUIRED_ARG, 0, 'P'}, 76518678f8Sopenharmony_ci {"lease", REQUIRED_ARG, 0, 0}, 77518678f8Sopenharmony_ci {"renewal", REQUIRED_ARG, 0, 0}, 78518678f8Sopenharmony_ci {"rebinding", REQUIRED_ARG, 0, 0}, 79518678f8Sopenharmony_ci {"version", NO_ARG, 0, 'v'}, 80518678f8Sopenharmony_ci {"help", NO_ARG, 0, 'h'}, 81518678f8Sopenharmony_ci {0, 0, 0, 0}, 82518678f8Sopenharmony_ci}; 83518678f8Sopenharmony_ci 84518678f8Sopenharmony_cistatic DhcpUsage usages[] = { 85518678f8Sopenharmony_ci {&g_longOptions[NUM_ZERO], "<interface>", "network interface name.", "--ifname eth0", 1, PutArgument}, 86518678f8Sopenharmony_ci {&g_longOptions[NUM_ONE], "<file>", "configure file name.", "--conf /etc/conf/dhcp_server.conf", 0, PutArgument}, 87518678f8Sopenharmony_ci {&g_longOptions[NUM_TWO], "<dns1>[,dns2][,dns3][...]", "domain name server IP address list.", "", 0, PutArgument}, 88518678f8Sopenharmony_ci {&g_longOptions[NUM_THREE], "<gateway>", "gateway option.", "", 0, PutIpArgument}, 89518678f8Sopenharmony_ci {&g_longOptions[NUM_FOUR], "<server>", "server identifier.", "", 1, PutIpArgument}, 90518678f8Sopenharmony_ci {&g_longOptions[NUM_FIVE], "<netmask>", "default subnet mask.", "", 1, PutIpArgument}, 91518678f8Sopenharmony_ci {&g_longOptions[NUM_SIX], "<beginip>,<endip>", "pool address range.", "", 0, 92518678f8Sopenharmony_ci PutPoolArgument}, 93518678f8Sopenharmony_ci {&g_longOptions[NUM_SEVEN], "<leaseTime>", "set lease time value, the value is in units of seconds.", "", 0, 94518678f8Sopenharmony_ci PutArgument}, 95518678f8Sopenharmony_ci {&g_longOptions[NUM_EIGHT], "<renewalTime>", "set renewal time value, the value is in units of seconds.", "", 0, 96518678f8Sopenharmony_ci PutArgument}, 97518678f8Sopenharmony_ci {&g_longOptions[NUM_NINE], "<rebindingTime>", "set rebinding time value, the value is in units of seconds.", "", 0, 98518678f8Sopenharmony_ci PutArgument}, 99518678f8Sopenharmony_ci {&g_longOptions[NUM_TEN], "", "show version information.", "", 0, ShowVersion}, 100518678f8Sopenharmony_ci {&g_longOptions[NUM_ELEVEN], "", "show help information.", "", 0, DefaultArgument}, 101518678f8Sopenharmony_ci {0, "", "", ""}, 102518678f8Sopenharmony_ci}; 103518678f8Sopenharmony_ci 104518678f8Sopenharmony_ciint HasArgument(const char *argument) 105518678f8Sopenharmony_ci{ 106518678f8Sopenharmony_ci char name[ARGUMENT_NAME_SIZE] = {'\0'}; 107518678f8Sopenharmony_ci if (!argument) { 108518678f8Sopenharmony_ci return 0; 109518678f8Sopenharmony_ci } 110518678f8Sopenharmony_ci size_t ssize = strlen(argument); 111518678f8Sopenharmony_ci if (ssize > ARGUMENT_NAME_SIZE) { 112518678f8Sopenharmony_ci ssize = ARGUMENT_NAME_SIZE; 113518678f8Sopenharmony_ci } 114518678f8Sopenharmony_ci if (memcpy_s(name, ARGUMENT_NAME_SIZE, argument, ssize) != EOK) { 115518678f8Sopenharmony_ci DHCP_LOGE("failed to set argument name."); 116518678f8Sopenharmony_ci return 0; 117518678f8Sopenharmony_ci } 118518678f8Sopenharmony_ci if (g_argumentsTable.empty()) { 119518678f8Sopenharmony_ci return 0; 120518678f8Sopenharmony_ci } 121518678f8Sopenharmony_ci if (g_argumentsTable.count(name) > 0) { 122518678f8Sopenharmony_ci return 1; 123518678f8Sopenharmony_ci } 124518678f8Sopenharmony_ci return 0; 125518678f8Sopenharmony_ci} 126518678f8Sopenharmony_ci 127518678f8Sopenharmony_cistatic void ShowUsage(const DhcpUsage *usage) 128518678f8Sopenharmony_ci{ 129518678f8Sopenharmony_ci if (!usage || !usage->opt) { 130518678f8Sopenharmony_ci return; 131518678f8Sopenharmony_ci } 132518678f8Sopenharmony_ci if (usage->opt->val) { 133518678f8Sopenharmony_ci DHCP_LOGI("-%{public}c,--%{public}s ", (char)usage->opt->val, usage->opt->name); 134518678f8Sopenharmony_ci } else { 135518678f8Sopenharmony_ci DHCP_LOGI(" --%{public}s ", usage->opt->name); 136518678f8Sopenharmony_ci } 137518678f8Sopenharmony_ci if (usage->params[0] == '\0') { 138518678f8Sopenharmony_ci DHCP_LOGI("\t\t%{public}s\n", usage->desc); 139518678f8Sopenharmony_ci } else { 140518678f8Sopenharmony_ci int plen = strlen(usage->params) + strlen(usage->params); 141518678f8Sopenharmony_ci if (plen < USAGE_DESC_MAX_LENGTH) { 142518678f8Sopenharmony_ci DHCP_LOGI("\t\t%{public}s\t\t%{public}s\n", usage->params, usage->desc); 143518678f8Sopenharmony_ci } else { 144518678f8Sopenharmony_ci DHCP_LOGI("\t\t%{public}s\n", usage->params); 145518678f8Sopenharmony_ci DHCP_LOGI("\t\t\t%{public}s\n\n", usage->desc); 146518678f8Sopenharmony_ci } 147518678f8Sopenharmony_ci } 148518678f8Sopenharmony_ci} 149518678f8Sopenharmony_ci 150518678f8Sopenharmony_civoid PrintRequiredArguments(void) 151518678f8Sopenharmony_ci{ 152518678f8Sopenharmony_ci size_t argc = sizeof(usages) / sizeof(DhcpUsage); 153518678f8Sopenharmony_ci DHCP_LOGI("required parameters:"); 154518678f8Sopenharmony_ci int idx = 0; 155518678f8Sopenharmony_ci for (size_t i = 0; i < argc; i++) { 156518678f8Sopenharmony_ci DhcpUsage usage = usages[i]; 157518678f8Sopenharmony_ci if (!usage.opt) { 158518678f8Sopenharmony_ci break; 159518678f8Sopenharmony_ci } 160518678f8Sopenharmony_ci if (usage.required) { 161518678f8Sopenharmony_ci if (idx == 0) { 162518678f8Sopenharmony_ci DHCP_LOGI("\"%{public}s\"", usage.opt->name); 163518678f8Sopenharmony_ci } else { 164518678f8Sopenharmony_ci DHCP_LOGI(", \"%{public}s\"", usage.opt->name); 165518678f8Sopenharmony_ci } 166518678f8Sopenharmony_ci idx++; 167518678f8Sopenharmony_ci } 168518678f8Sopenharmony_ci } 169518678f8Sopenharmony_ci DHCP_LOGI(".\n\n"); 170518678f8Sopenharmony_ci DHCP_LOGI("Usage: dhcp_server [options] \n"); 171518678f8Sopenharmony_ci DHCP_LOGI("e.g: dhcp_server -i eth0 -c /data/service/el1/public/dhcp/dhcp_server.conf \n"); 172518678f8Sopenharmony_ci DHCP_LOGI(" dhcp_server --help \n\n"); 173518678f8Sopenharmony_ci} 174518678f8Sopenharmony_ci 175518678f8Sopenharmony_cistatic void PrintUsage(void) 176518678f8Sopenharmony_ci{ 177518678f8Sopenharmony_ci DHCP_LOGI("Usage: dhcp_server [options] \n\n"); 178518678f8Sopenharmony_ci 179518678f8Sopenharmony_ci size_t argc = sizeof(usages) / sizeof(DhcpUsage); 180518678f8Sopenharmony_ci for (size_t i = 0; i < argc; i++) { 181518678f8Sopenharmony_ci DhcpUsage usage = usages[i]; 182518678f8Sopenharmony_ci if (!usage.opt) { 183518678f8Sopenharmony_ci break; 184518678f8Sopenharmony_ci } 185518678f8Sopenharmony_ci ShowUsage(&usage); 186518678f8Sopenharmony_ci } 187518678f8Sopenharmony_ci DHCP_LOGI("\n"); 188518678f8Sopenharmony_ci} 189518678f8Sopenharmony_ci 190518678f8Sopenharmony_civoid ShowHelp(int argc) 191518678f8Sopenharmony_ci{ 192518678f8Sopenharmony_ci if (argc == NUM_TWO) { 193518678f8Sopenharmony_ci PrintUsage(); 194518678f8Sopenharmony_ci return; 195518678f8Sopenharmony_ci } 196518678f8Sopenharmony_ci} 197518678f8Sopenharmony_ci 198518678f8Sopenharmony_ciint InitArguments(void) 199518678f8Sopenharmony_ci{ 200518678f8Sopenharmony_ci DHCP_LOGI("start InitArguments."); 201518678f8Sopenharmony_ci g_argumentsTable.clear(); 202518678f8Sopenharmony_ci DHCP_LOGI("end InitArguments."); 203518678f8Sopenharmony_ci return RET_SUCCESS; 204518678f8Sopenharmony_ci} 205518678f8Sopenharmony_ci 206518678f8Sopenharmony_ciArgumentInfo *GetArgument(const char *name) 207518678f8Sopenharmony_ci{ 208518678f8Sopenharmony_ci char argName[ARGUMENT_NAME_SIZE] = {'\0'}; 209518678f8Sopenharmony_ci size_t ssize = strlen(name); 210518678f8Sopenharmony_ci if (ssize > ARGUMENT_NAME_SIZE) { 211518678f8Sopenharmony_ci ssize = ARGUMENT_NAME_SIZE; 212518678f8Sopenharmony_ci } 213518678f8Sopenharmony_ci if (memcpy_s(argName, ARGUMENT_NAME_SIZE, name, ssize) != EOK) { 214518678f8Sopenharmony_ci DHCP_LOGE("failed to set argument name."); 215518678f8Sopenharmony_ci return nullptr; 216518678f8Sopenharmony_ci } 217518678f8Sopenharmony_ci if (g_argumentsTable.count(argName) > 0) { 218518678f8Sopenharmony_ci return &g_argumentsTable[argName]; 219518678f8Sopenharmony_ci } 220518678f8Sopenharmony_ci return nullptr; 221518678f8Sopenharmony_ci} 222518678f8Sopenharmony_ci 223518678f8Sopenharmony_ciint PutArgument(const char *argument, const char *val) 224518678f8Sopenharmony_ci{ 225518678f8Sopenharmony_ci DHCP_LOGI("start PutArgument."); 226518678f8Sopenharmony_ci if (!argument) { 227518678f8Sopenharmony_ci return RET_FAILED; 228518678f8Sopenharmony_ci } 229518678f8Sopenharmony_ci if (!val) { 230518678f8Sopenharmony_ci return RET_FAILED; 231518678f8Sopenharmony_ci } 232518678f8Sopenharmony_ci 233518678f8Sopenharmony_ci if (HasArgument(argument)) { 234518678f8Sopenharmony_ci return RET_FAILED; 235518678f8Sopenharmony_ci } 236518678f8Sopenharmony_ci 237518678f8Sopenharmony_ci ArgumentInfo arg; 238518678f8Sopenharmony_ci size_t ssize = strlen(argument); 239518678f8Sopenharmony_ci if (ssize >= ARGUMENT_NAME_SIZE) { 240518678f8Sopenharmony_ci ssize = ARGUMENT_NAME_SIZE -1; 241518678f8Sopenharmony_ci } 242518678f8Sopenharmony_ci size_t vlen = strlen(val); 243518678f8Sopenharmony_ci if (memset_s(arg.name, ARGUMENT_NAME_SIZE, '\0', ARGUMENT_NAME_SIZE) != EOK) { 244518678f8Sopenharmony_ci DHCP_LOGE("failed to reset argument name."); 245518678f8Sopenharmony_ci return RET_ERROR; 246518678f8Sopenharmony_ci } 247518678f8Sopenharmony_ci if (memcpy_s(arg.name, ARGUMENT_NAME_SIZE, argument, ssize) != EOK) { 248518678f8Sopenharmony_ci DHCP_LOGE("failed to set argument name."); 249518678f8Sopenharmony_ci return RET_ERROR; 250518678f8Sopenharmony_ci } 251518678f8Sopenharmony_ci if (vlen >= ARGUMENT_VALUE_SIZE) { 252518678f8Sopenharmony_ci DHCP_LOGE("value string too long."); 253518678f8Sopenharmony_ci return RET_ERROR; 254518678f8Sopenharmony_ci } 255518678f8Sopenharmony_ci if (memset_s(arg.value, ARGUMENT_VALUE_SIZE, '\0', ARGUMENT_NAME_SIZE) != EOK) { 256518678f8Sopenharmony_ci DHCP_LOGE("failed to reset argument value."); 257518678f8Sopenharmony_ci return RET_ERROR; 258518678f8Sopenharmony_ci } 259518678f8Sopenharmony_ci if (memcpy_s(arg.value, ARGUMENT_VALUE_SIZE, val, vlen) != EOK) { 260518678f8Sopenharmony_ci DHCP_LOGE("failed to set argument value."); 261518678f8Sopenharmony_ci return RET_ERROR; 262518678f8Sopenharmony_ci } 263518678f8Sopenharmony_ci g_argumentsTable[std::string(arg.name)] = arg; 264518678f8Sopenharmony_ci return RET_SUCCESS; 265518678f8Sopenharmony_ci} 266518678f8Sopenharmony_ci 267518678f8Sopenharmony_ciint FindIndex(int c) 268518678f8Sopenharmony_ci{ 269518678f8Sopenharmony_ci int size = sizeof(g_longOptions) / sizeof(g_longOptions[0]); 270518678f8Sopenharmony_ci for (int i = 0; i < size; ++i) { 271518678f8Sopenharmony_ci if (g_longOptions[i].val == c) { 272518678f8Sopenharmony_ci return i; 273518678f8Sopenharmony_ci } 274518678f8Sopenharmony_ci } 275518678f8Sopenharmony_ci return -1; 276518678f8Sopenharmony_ci} 277518678f8Sopenharmony_ci 278518678f8Sopenharmony_ciint ParseArguments(const std::string& ifName, const std::string& netMask, const std::string& ipRange, 279518678f8Sopenharmony_ci const std::string& localIp) 280518678f8Sopenharmony_ci{ 281518678f8Sopenharmony_ci DHCP_LOGI("start ParseArguments."); 282518678f8Sopenharmony_ci PutArgument("ifname", ifName.c_str()); 283518678f8Sopenharmony_ci PutIpArgument("server", localIp.c_str()); 284518678f8Sopenharmony_ci PutIpArgument("netmask", netMask.c_str()); 285518678f8Sopenharmony_ci PutPoolArgument("pool", ipRange.c_str()); 286518678f8Sopenharmony_ci return 0; 287518678f8Sopenharmony_ci} 288518678f8Sopenharmony_ci 289518678f8Sopenharmony_civoid FreeArguments(void) 290518678f8Sopenharmony_ci{ 291518678f8Sopenharmony_ci g_argumentsTable.clear(); 292518678f8Sopenharmony_ci} 293