From a501789e042ae8efa1dcdd9d2ad7cece8b59ad3a Mon Sep 17 00:00:00 2001 From: "Nicholas J. Kain" Date: Mon, 14 Apr 2014 15:06:31 -0400 Subject: [PATCH] Parse config options with ragel and support a configuration file. --- src/CMakeLists.txt | 11 +- src/arp.c | 2 +- src/arp.h | 3 +- src/cfg.h | 7 + src/cfg.rl | 321 +++++++++++++++++++++++++++++++++++++++++++++ src/ndhc.c | 214 ++++++------------------------ src/ndhc.h | 7 + 7 files changed, 386 insertions(+), 179 deletions(-) create mode 100644 src/cfg.h create mode 100644 src/cfg.rl diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2aa267a..5d23868 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -5,6 +5,7 @@ cmake_minimum_required (VERSION 2.6) include_directories("${PROJECT_SOURCE_DIR}") set(RAGEL_IFCHD_PARSE ${CMAKE_CURRENT_BINARY_DIR}/ifchd-parse.c) +set(RAGEL_CFG_PARSE ${CMAKE_CURRENT_BINARY_DIR}/cfg.c) find_program(RAGEL ragel) add_custom_command( @@ -15,8 +16,16 @@ add_custom_command( COMMENT "Compiling Ragel state machine: ifchd-parse.rl" VERBATIM ) +add_custom_command( + OUTPUT ${RAGEL_CFG_PARSE} + COMMAND ${RAGEL} -G2 -o ${RAGEL_CFG_PARSE} cfg.rl + DEPENDS cfg.rl + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Compiling Ragel state machine: cfg.rl" + VERBATIM + ) file(GLOB NDHC_SRCS "*.c") -add_executable(ndhc ${RAGEL_IFCHD_PARSE} ${NDHC_SRCS}) +add_executable(ndhc ${RAGEL_CFG_PARSE} ${RAGEL_IFCHD_PARSE} ${NDHC_SRCS}) target_link_libraries(ndhc ncmlib) diff --git a/src/arp.c b/src/arp.c index a8e206a..600077d 100644 --- a/src/arp.c +++ b/src/arp.c @@ -122,7 +122,7 @@ static struct arp_data garp = { .server_replied = false, }; -void set_arp_relentless_def(void) { garp.relentless_def = true; } +void set_arp_relentless_def(bool v) { garp.relentless_def = v; } static void arp_reply_clear(void) { diff --git a/src/arp.h b/src/arp.h index 34f09c5..0c5dfa4 100644 --- a/src/arp.h +++ b/src/arp.h @@ -28,6 +28,7 @@ #ifndef ARP_H_ #define ARP_H_ +#include #include #include #include "ndhc.h" @@ -57,7 +58,7 @@ extern int arp_probe_num; extern int arp_probe_min; extern int arp_probe_max; -void set_arp_relentless_def(void); +void set_arp_relentless_def(bool v); void arp_reset_send_stats(void); void arp_close_fd(struct client_state_t *cs); int arp_check(struct client_state_t *cs, struct dhcpmsg *packet); diff --git a/src/cfg.h b/src/cfg.h new file mode 100644 index 0000000..334a4e9 --- /dev/null +++ b/src/cfg.h @@ -0,0 +1,7 @@ +#ifndef NDHC_CONFIG_H_ +#define NDHC_CONFIG_H_ + +void parse_cmdline(int argc, char *argv[]); + +#endif /* NDHC_CONFIG_H_ */ + diff --git a/src/cfg.rl b/src/cfg.rl new file mode 100644 index 0000000..0575908 --- /dev/null +++ b/src/cfg.rl @@ -0,0 +1,321 @@ +#include +#include +#include +#include +#include "ndhc-defines.h" +#include "cfg.h" +#include "arp.h" +#include "ndhc.h" +#include "ifchd.h" +#include "sockd.h" +#include "seccomp.h" +#include "nk/log.h" +#include "nk/privilege.h" +#include "nk/copy_cmdarg.h" + +struct cfgparse { + char buf[MAX_BUF]; + size_t buflen; + int ternary; // = 0 nothing, -1 = false, +1 = true + int cs; +}; + +%%{ + machine cfg_actions; + access ccfg.; + + action clear { memset(&ccfg, 0, sizeof ccfg); } + action append { + if (ccfg.buflen < sizeof ccfg.buf - 1) + ccfg.buf[ccfg.buflen++] = *p; + else + suicide("line or option is too long"); + } + action term { + if (ccfg.buflen < sizeof ccfg.buf) + ccfg.buf[ccfg.buflen] = 0; + } + action truval { ccfg.ternary = 1; } + action falsval { ccfg.ternary = -1; } + + action clientid { get_clientid_string(ccfg.buf, ccfg.buflen); } + action background { + switch (ccfg.ternary) { + case 1: + client_config.background_if_no_lease = 1; + gflags_detach = 1; + break; + case -1: + client_config.background_if_no_lease = 0; + gflags_detach = 0; + default: + break; + } + } + action pidfile { + copy_cmdarg(pidfile, ccfg.buf, sizeof pidfile, "pidfile"); + } + action hostname { + copy_cmdarg(client_config.hostname, ccfg.buf, + sizeof client_config.hostname, "hostname"); + } + action interface { + copy_cmdarg(client_config.interface, ccfg.buf, + sizeof client_config.interface, "interface"); + } + action now { + switch (ccfg.ternary) { + case 1: client_config.abort_if_no_lease = 1; break; + case -1: client_config.abort_if_no_lease = 0; default: break; + } + } + action quit { + switch (ccfg.ternary) { + case 1: client_config.quit_after_lease = 1; break; + case -1: client_config.quit_after_lease = 0; default: break; + } + } + action request { set_client_addr(ccfg.buf); } + action vendorid { + copy_cmdarg(client_config.vendor, ccfg.buf, + sizeof client_config.vendor, "vendorid"); + } + action user { + if (nk_uidgidbyname(ccfg.buf, &ndhc_uid, &ndhc_gid)) + suicide("invalid ndhc user '%s' specified", ccfg.buf); + } + action ifch_user { + if (nk_uidgidbyname(ccfg.buf, &ifch_uid, &ifch_gid)) + suicide("invalid ifch user '%s' specified", ccfg.buf); + } + action sockd_user { + if (nk_uidgidbyname(ccfg.buf, &sockd_uid, &sockd_gid)) + suicide("invalid sockd user '%s' specified", ccfg.buf); + } + action chroot { + copy_cmdarg(chroot_dir, ccfg.buf, sizeof chroot_dir, "chroot"); + } + action state_dir { + copy_cmdarg(state_dir, ccfg.buf, sizeof state_dir, "state-dir"); + } + action seccomp_enforce { + switch (ccfg.ternary) { + case 1: seccomp_enforce = true; break; + case -1: seccomp_enforce = false; default: break; + } + } + action relentless_defense { + switch (ccfg.ternary) { + case 1: set_arp_relentless_def(true); break; + case -1: set_arp_relentless_def(false); default: break; + } + } + action arp_probe_wait { + int t = atoi(ccfg.buf); + if (t >= 0) + arp_probe_wait = t; + } + action arp_probe_num { + int t = atoi(ccfg.buf); + if (t >= 0) + arp_probe_num = t; + } + action arp_probe_min { + int t = atoi(ccfg.buf); + arp_probe_min = t; + if (arp_probe_min > arp_probe_max) { + t = arp_probe_max; + arp_probe_max = arp_probe_min; + arp_probe_min = t; + } + } + action arp_probe_max { + int t = atoi(ccfg.buf); + arp_probe_max = t; + if (arp_probe_min > arp_probe_max) { + t = arp_probe_max; + arp_probe_max = arp_probe_min; + arp_probe_min = t; + } + } + action gw_metric { + char *q; + long mt = strtol(ccfg.buf, &q, 10); + if (q == ccfg.buf) + suicide("gw-metric arg '%s' isn't a valid number", ccfg.buf); + if (mt > INT_MAX) + suicide("gw-metric arg '%s' is too large", ccfg.buf); + if (mt < 0) + mt = 0; + client_config.metric = (int)mt; + } + action resolv_conf { + copy_cmdarg(resolv_conf_d, ccfg.buf, sizeof resolv_conf_d, + "resolv-conf"); + } + action dhcp_set_hostname { + switch (ccfg.ternary) { + case 1: allow_hostname = 1; break; + case -1: allow_hostname = 0; default: break; + } + } + action version { print_version(); exit(EXIT_SUCCESS); } + action help { show_usage(); exit(EXIT_SUCCESS); } +}%% + +%%{ + machine file_cfg; + access ccfg.; + include cfg_actions; + + spc = [ \t]; + delim = spc* '=' spc*; + string = [^\n]+ >clear $append %term; + term = '\n'; + value = delim string term; + truval = ('true'|'1') % truval; + falsval = ('false'|'0') % falsval; + boolval = delim (truval|falsval) term; + + blankline = term; + + clientid = 'clientid' value @clientid; + background = 'background' value @background; + pidfile = 'pidfile' value @pidfile; + hostname = 'hostname' value @hostname; + interface = 'interface' value @interface; + now = 'now' boolval @now; + quit = 'quit' boolval @quit; + request = 'request' value @request; + vendorid = 'vendorid' value @vendorid; + user = 'user' value @user; + ifch_user = 'ifch-user' value @ifch_user; + sockd_user = 'sockd-user' value @sockd_user; + chroot = 'chroot' value @chroot; + state_dir = 'state-dir' value @state_dir; + seccomp_enforce = 'seccomp-enforce' boolval @seccomp_enforce; + relentless_defense = 'relentless-defense' boolval @relentless_defense; + arp_probe_wait = 'arp-probe-wait' value @arp_probe_wait; + arp_probe_num = 'arp-probe-num' value @arp_probe_num; + arp_probe_min = 'arp-probe-min' value @arp_probe_min; + arp_probe_max = 'arp-probe-max' value @arp_probe_max; + gw_metric = 'gw-metric' value @gw_metric; + resolv_conf = 'resolv-conf' value @resolv_conf; + dhcp_set_hostname = 'dhcp-set-hostname' boolval @dhcp_set_hostname; + + main := blankline | + clientid | background | pidfile | hostname | interface | now | quit | + request | vendorid | user | ifch_user | sockd_user | chroot | + state_dir | seccomp_enforce | relentless_defense | arp_probe_wait | + arp_probe_num | arp_probe_min | arp_probe_max | gw_metric | + resolv_conf | dhcp_set_hostname + ; +}%% + +%% write data; + +static void parse_cfgfile(const char *fname) +{ + struct cfgparse ccfg; + memset(&ccfg, 0, sizeof ccfg); + FILE *f = fopen(fname, "r"); + if (!f) + suicide("Unable to open config file '%s'.", fname); + char l[MAX_BUF]; + size_t linenum = 0; + while (linenum++, fgets(l, sizeof l, f)) { + size_t llen = strlen(l); + const char *p = l; + const char *pe = l + llen; + %% write init; + %% write exec; + + if (ccfg.cs == file_cfg_error) + suicide("error parsing config file line %zu: malformed", linenum); + if (ccfg.cs < file_cfg_first_final) + suicide("error parsing config file line %zu: incomplete", linenum); + } + fclose(f); +} + +%%{ + machine cmd_cfg; + access ccfg.; + include cfg_actions; + + action cfgfile { parse_cfgfile(ccfg.buf); } + action tbv { ccfg.ternary = 1; } + + string = [^\0]+ >clear $append %term; + argval = 0 string 0; + tbv = 0 % tbv; + + cfgfile = ('-c'|'--config') argval @cfgfile; + clientid = ('-I'|'--clientid') argval @clientid; + background = ('-b'|'--background') tbv @background; + pidfile = ('-p'|'--pidfile') argval @pidfile; + hostname = ('-h'|'--hostname') argval @hostname; + interface = ('-i'|'--interface') argval @interface; + now = ('-n'|'--now') tbv @now; + quit = ('-q'|'--quit') tbv @quit; + request = ('-r'|'--request') argval @request; + vendorid = ('-V'|'--vendorid') argval @vendorid; + user = ('-u'|'--user') argval @user; + ifch_user = ('-U'|'--ifch-user') argval @ifch_user; + sockd_user = ('-D'|'--sockd-user') argval @sockd_user; + chroot = ('-C'|'--chroot') argval @chroot; + state_dir = ('-s'|'--state-dir') argval @state_dir; + seccomp_enforce = ('-S'|'--seccomp-enforce') tbv @seccomp_enforce; + relentless_defense = ('-d'|'--relentless-defense') tbv @relentless_defense; + arp_probe_wait = ('-w'|'--arp-probe-wait') argval @arp_probe_wait; + arp_probe_num = ('-W'|'--arp-probe-num') argval @arp_probe_num; + arp_probe_min = ('-m'|'--arp-probe-min') argval @arp_probe_min; + arp_probe_max = ('-M'|'--arp-probe-max') argval @arp_probe_max; + gw_metric = ('-t'|'--gw-metric') argval @gw_metric; + resolv_conf = ('-R'|'--resolv-conf') argval @resolv_conf; + dhcp_set_hostname = ('-H'|'--dhcp-set-hostname') tbv @dhcp_set_hostname; + version = ('-v'|'--version') 0 @version; + help = ('-?'|'--help') 0 @help; + + main := ( + cfgfile | clientid | background | pidfile | hostname | interface | + now | quit | request | vendorid | user | ifch_user | sockd_user | + chroot | state_dir | seccomp_enforce | relentless_defense | + arp_probe_wait | arp_probe_num | arp_probe_min | arp_probe_max | + gw_metric | resolv_conf | dhcp_set_hostname | version | help + )*; +}%% + +%% write data; + +void parse_cmdline(int argc, char *argv[]) +{ + char argb[8192]; + size_t argbl = 0; + for (size_t i = 1; i < (size_t)argc; ++i) { + ssize_t snl; + if (i > 1) + snl = snprintf(argb + argbl, sizeof argb - argbl, "%c%s", + 0, argv[i]); + else + snl = snprintf(argb + argbl, sizeof argb - argbl, "%s", argv[i]); + if (snl < 0 || (size_t)snl >= sizeof argb) + suicide("error parsing command line option: option too long"); + argbl += snl; + } + struct cfgparse ccfg; + memset(&ccfg, 0, sizeof ccfg); + const char *p = argb; + const char *pe = argb + argbl + 1; + const char *eof = pe; + + %% write init; + %% write exec; + + if (ccfg.cs == cmd_cfg_error) + suicide("error parsing command line option: malformed"); + if (ccfg.cs >= cmd_cfg_first_final) + return; + suicide("error parsing command line option: incomplete"); +} + diff --git a/src/ndhc.c b/src/ndhc.c index bf627e4..6c028a3 100644 --- a/src/ndhc.c +++ b/src/ndhc.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -57,6 +56,7 @@ #include "ndhc.h" #include "ndhc-defines.h" +#include "cfg.h" #include "seccomp.h" #include "state.h" #include "options.h" @@ -94,13 +94,42 @@ struct client_config_t client_config = { .foreground = 1, }; -static void show_usage(void) +void set_client_addr(const char *v) { cs.clientAddr = inet_addr(v); } + +void print_version(void) +{ + printf("ndhc %s, dhcp client.\n", NDHC_VERSION); + printf("Copyright (c) 2004-2014 Nicholas J. Kain\n" + "All rights reserved.\n\n" + "Redistribution and use in source and binary forms, with or without\n" + "modification, are permitted provided that the following conditions are met:\n\n" + "- Redistributions of source code must retain the above copyright notice,\n" + " this list of conditions and the following disclaimer.\n" + "- Redistributions in binary form must reproduce the above copyright notice,\n" + " this list of conditions and the following disclaimer in the documentation\n" + " and/or other materials provided with the distribution.\n\n" + "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n" + "AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n" + "IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n" + "ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\n" + "LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n" + "CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n" + "SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n" + "INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n" + "CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n" + "ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n" + "POSSIBILITY OF SUCH DAMAGE.\n"); + exit(EXIT_SUCCESS); +} + +void show_usage(void) { printf( "ndhc " NDHC_VERSION ", dhcp client. Licensed under 2-clause BSD.\n" "Copyright (C) 2004-2014 Nicholas J. Kain\n" "Usage: ndhc [OPTIONS]\n\n" -" -c, --clientid=CLIENTID Client identifier\n" +" -c, --config=FILE Path to ndhc configuration file\n" +" -I, --clientid=CLIENTID Client identifier\n" " -h, --hostname=HOSTNAME Client hostname\n" " -V, --vendorid=VENDORID Client vendor identification string\n" " -b, --background Fork to background if lease cannot be\n" @@ -127,7 +156,7 @@ static void show_usage(void) " -M, --arp-probe-max Max ms to wait for ARP response\n" " -t, --gw-metric Route metric for default gw (default: 0)\n" " -R, --resolve-conf=FILE Path to resolv.conf or equivalent\n" -" -H, --dhcp-hostname Allow DHCP to set machine hostname\n" +" -H, --dhcp-set-hostname Allow DHCP to set machine hostname\n" " -v, --version Display version\n" ); exit(EXIT_SUCCESS); @@ -205,7 +234,7 @@ static int is_string_hwaddr(char *str, size_t slen) return 0; } -static int get_clientid_string(char *str, size_t slen) +int get_clientid_string(char *str, size_t slen) { if (!slen) return -1; @@ -333,9 +362,9 @@ jumpstart: char state_dir[PATH_MAX] = "/etc/ndhc"; char chroot_dir[PATH_MAX] = ""; char resolv_conf_d[PATH_MAX] = ""; -static char pidfile[PATH_MAX] = PID_FILE_DEFAULT; -static uid_t ndhc_uid = 0; -static gid_t ndhc_gid = 0; +char pidfile[PATH_MAX] = PID_FILE_DEFAULT; +uid_t ndhc_uid = 0; +gid_t ndhc_gid = 0; int ifchSock[2]; int ifchPipe[2]; int sockdSock[2]; @@ -432,176 +461,9 @@ void background(void) write_pid(pidfile); } -static void parse_program_options(int argc, char *argv[]) -{ - static const struct option arg_options[] = { - {"clientid", required_argument, 0, 'c'}, - {"background", no_argument, 0, 'b'}, - {"pidfile", required_argument, 0, 'p'}, - {"hostname", required_argument, 0, 'h'}, - {"interface", required_argument, 0, 'i'}, - {"now", no_argument, 0, 'n'}, - {"quit", no_argument, 0, 'q'}, - {"request", required_argument, 0, 'r'}, - {"vendorid", required_argument, 0, 'V'}, - {"user", required_argument, 0, 'u'}, - {"ifch-user", required_argument, 0, 'U'}, - {"sockd-user", required_argument, 0, 'D'}, - {"chroot", required_argument, 0, 'C'}, - {"state-dir", required_argument, 0, 's'}, - {"seccomp-enforce", no_argument, 0, 'S'}, - {"relentless-defense", no_argument, 0, 'd'}, - {"arp-probe-wait", required_argument, 0, 'w'}, - {"arp-probe-num", required_argument, 0, 'W'}, - {"arp-probe-min", required_argument, 0, 'm'}, - {"arp-probe-max", required_argument, 0, 'M'}, - {"gw-metric", required_argument, 0, 't'}, - {"resolv-conf", required_argument, 0, 'R'}, - {"dhcp-set-hostname", no_argument, 0, 'H'}, - {"version", no_argument, 0, 'v'}, - {"help", no_argument, 0, '?'}, - {0, 0, 0, 0} - }; - - while (1) { - int c; - c = getopt_long(argc, argv, "c:bp:P:h:i:nqr:V:u:U:D:C:s:Sdw:W:m:M:t:R:Hv?", - arg_options, NULL); - if (c < 0) break; - - switch (c) { - case 'c': - get_clientid_string(optarg, strlen(optarg)); - break; - case 'b': - client_config.background_if_no_lease = 1; - gflags_detach = 1; - break; - case 'p': - copy_cmdarg(pidfile, optarg, sizeof pidfile, "pidfile"); - break; - case 'h': - copy_cmdarg(client_config.hostname, optarg, - sizeof client_config.hostname, "hostname"); - break; - case 'i': - copy_cmdarg(client_config.interface, optarg, - sizeof client_config.interface, "interface"); - break; - case 'n': - client_config.abort_if_no_lease = 1; - break; - case 'q': - client_config.quit_after_lease = 1; - break; - case 'r': - cs.clientAddr = inet_addr(optarg); - break; - case 'u': - if (nk_uidgidbyname(optarg, &ndhc_uid, &ndhc_gid)) - suicide("invalid ndhc user '%s' specified", optarg); - break; - case 'U': - if (nk_uidgidbyname(optarg, &ifch_uid, &ifch_gid)) - suicide("invalid ifch user '%s' specified", optarg); - break; - case 'D': - if (nk_uidgidbyname(optarg, &sockd_uid, &sockd_gid)) - suicide("invalid sockd user '%s' specified", optarg); - break; - case 'C': - copy_cmdarg(chroot_dir, optarg, sizeof chroot_dir, "chroot"); - break; - case 's': - copy_cmdarg(state_dir, optarg, sizeof state_dir, "state-dir"); - break; - case 'S': - seccomp_enforce = true; - break; - case 'd': - set_arp_relentless_def(); - break; - case 'w': - case 'W': { - int t = atoi(optarg); - if (t < 0) - break; - if (c == 'w') - arp_probe_wait = t; - else - arp_probe_num = t; - break; - } - case 'm': - case 'M': { - int t = atoi(optarg); - if (c == 'm') - arp_probe_min = t; - else - arp_probe_max = t; - if (arp_probe_min > arp_probe_max) { - t = arp_probe_max; - arp_probe_max = arp_probe_min; - arp_probe_min = t; - } - break; - } - case 'v': - printf("ndhc %s, dhcp client.\n", NDHC_VERSION); - printf("Copyright (c) 2004-2014 Nicholas J. Kain\n" - "All rights reserved.\n\n" - "Redistribution and use in source and binary forms, with or without\n" - "modification, are permitted provided that the following conditions are met:\n\n" - "- Redistributions of source code must retain the above copyright notice,\n" - " this list of conditions and the following disclaimer.\n" - "- Redistributions in binary form must reproduce the above copyright notice,\n" - " this list of conditions and the following disclaimer in the documentation\n" - " and/or other materials provided with the distribution.\n\n" - "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n" - "AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n" - "IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n" - "ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\n" - "LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n" - "CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n" - "SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n" - "INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n" - "CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n" - "ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n" - "POSSIBILITY OF SUCH DAMAGE.\n"); - exit(EXIT_SUCCESS); - break; - case 'V': - copy_cmdarg(client_config.vendor, optarg, - sizeof client_config.vendor, "vendorid"); - break; - case 't': { - char *p; - long mt = strtol(optarg, &p, 10); - if (p == optarg) - suicide("gw-metric arg '%s' isn't a valid number", optarg); - if (mt > INT_MAX) - suicide("gw-metric arg '%s' is too large", optarg); - if (mt < 0) - mt = 0; - client_config.metric = (int)mt; - break; - } - case 'R': - copy_cmdarg(resolv_conf_d, optarg, sizeof resolv_conf_d, - "resolv-conf"); - break; - case 'H': - allow_hostname = 1; - break; - default: - show_usage(); - } - } -} - int main(int argc, char *argv[]) { - parse_program_options(argc, argv); + parse_cmdline(argc, argv); nk_random_u32_init(&cs.rnd32_state); diff --git a/src/ndhc.h b/src/ndhc.h index d5bce91..2d989d2 100644 --- a/src/ndhc.h +++ b/src/ndhc.h @@ -74,7 +74,14 @@ extern int sockdPipe[2]; extern char state_dir[PATH_MAX]; extern char chroot_dir[PATH_MAX]; extern char resolv_conf_d[PATH_MAX]; +extern char pidfile[PATH_MAX]; +extern uid_t ndhc_uid; +extern gid_t ndhc_gid; +void set_client_addr(const char *v); +void show_usage(void); +int get_clientid_string(char *str, size_t slen); void background(void); +void print_version(void); #endif /* NJK_NDHC_NDHC_H_ */