Parse config options with ragel and support a configuration file.
This commit is contained in:
parent
51033d3664
commit
a501789e04
@ -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)
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -28,6 +28,7 @@
|
||||
#ifndef ARP_H_
|
||||
#define ARP_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <net/if_arp.h>
|
||||
#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);
|
||||
|
7
src/cfg.h
Normal file
7
src/cfg.h
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef NDHC_CONFIG_H_
|
||||
#define NDHC_CONFIG_H_
|
||||
|
||||
void parse_cmdline(int argc, char *argv[]);
|
||||
|
||||
#endif /* NDHC_CONFIG_H_ */
|
||||
|
321
src/cfg.rl
Normal file
321
src/cfg.rl
Normal file
@ -0,0 +1,321 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#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");
|
||||
}
|
||||
|
214
src/ndhc.c
214
src/ndhc.c
@ -32,7 +32,6 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/file.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
@ -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);
|
||||
|
||||
|
@ -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_ */
|
||||
|
Loading…
Reference in New Issue
Block a user