Parse config options with ragel and support a configuration file.
This commit is contained in:
		@@ -5,6 +5,7 @@ cmake_minimum_required (VERSION 2.6)
 | 
				
			|||||||
include_directories("${PROJECT_SOURCE_DIR}")
 | 
					include_directories("${PROJECT_SOURCE_DIR}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set(RAGEL_IFCHD_PARSE ${CMAKE_CURRENT_BINARY_DIR}/ifchd-parse.c)
 | 
					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)
 | 
					find_program(RAGEL ragel)
 | 
				
			||||||
add_custom_command(
 | 
					add_custom_command(
 | 
				
			||||||
@@ -15,8 +16,16 @@ add_custom_command(
 | 
				
			|||||||
  COMMENT "Compiling Ragel state machine: ifchd-parse.rl"
 | 
					  COMMENT "Compiling Ragel state machine: ifchd-parse.rl"
 | 
				
			||||||
  VERBATIM
 | 
					  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")
 | 
					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)
 | 
					target_link_libraries(ndhc ncmlib)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -122,7 +122,7 @@ static struct arp_data garp = {
 | 
				
			|||||||
    .server_replied = false,
 | 
					    .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)
 | 
					static void arp_reply_clear(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,6 +28,7 @@
 | 
				
			|||||||
#ifndef ARP_H_
 | 
					#ifndef ARP_H_
 | 
				
			||||||
#define ARP_H_
 | 
					#define ARP_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
#include <stdint.h>
 | 
					#include <stdint.h>
 | 
				
			||||||
#include <net/if_arp.h>
 | 
					#include <net/if_arp.h>
 | 
				
			||||||
#include "ndhc.h"
 | 
					#include "ndhc.h"
 | 
				
			||||||
@@ -57,7 +58,7 @@ extern int arp_probe_num;
 | 
				
			|||||||
extern int arp_probe_min;
 | 
					extern int arp_probe_min;
 | 
				
			||||||
extern int arp_probe_max;
 | 
					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_reset_send_stats(void);
 | 
				
			||||||
void arp_close_fd(struct client_state_t *cs);
 | 
					void arp_close_fd(struct client_state_t *cs);
 | 
				
			||||||
int arp_check(struct client_state_t *cs, struct dhcpmsg *packet);
 | 
					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/types.h>
 | 
				
			||||||
#include <sys/file.h>
 | 
					#include <sys/file.h>
 | 
				
			||||||
#include <unistd.h>
 | 
					#include <unistd.h>
 | 
				
			||||||
#include <getopt.h>
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <signal.h>
 | 
					#include <signal.h>
 | 
				
			||||||
#include <time.h>
 | 
					#include <time.h>
 | 
				
			||||||
@@ -57,6 +56,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "ndhc.h"
 | 
					#include "ndhc.h"
 | 
				
			||||||
#include "ndhc-defines.h"
 | 
					#include "ndhc-defines.h"
 | 
				
			||||||
 | 
					#include "cfg.h"
 | 
				
			||||||
#include "seccomp.h"
 | 
					#include "seccomp.h"
 | 
				
			||||||
#include "state.h"
 | 
					#include "state.h"
 | 
				
			||||||
#include "options.h"
 | 
					#include "options.h"
 | 
				
			||||||
@@ -94,13 +94,42 @@ struct client_config_t client_config = {
 | 
				
			|||||||
    .foreground = 1,
 | 
					    .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(
 | 
					    printf(
 | 
				
			||||||
"ndhc " NDHC_VERSION ", dhcp client.  Licensed under 2-clause BSD.\n"
 | 
					"ndhc " NDHC_VERSION ", dhcp client.  Licensed under 2-clause BSD.\n"
 | 
				
			||||||
"Copyright (C) 2004-2014 Nicholas J. Kain\n"
 | 
					"Copyright (C) 2004-2014 Nicholas J. Kain\n"
 | 
				
			||||||
"Usage: ndhc [OPTIONS]\n\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"
 | 
					"  -h, --hostname=HOSTNAME         Client hostname\n"
 | 
				
			||||||
"  -V, --vendorid=VENDORID         Client vendor identification string\n"
 | 
					"  -V, --vendorid=VENDORID         Client vendor identification string\n"
 | 
				
			||||||
"  -b, --background                Fork to background if lease cannot be\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"
 | 
					"  -M, --arp-probe-max             Max ms to wait for ARP response\n"
 | 
				
			||||||
"  -t, --gw-metric                 Route metric for default gw (default: 0)\n"
 | 
					"  -t, --gw-metric                 Route metric for default gw (default: 0)\n"
 | 
				
			||||||
"  -R, --resolve-conf=FILE         Path to resolv.conf or equivalent\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"
 | 
					"  -v, --version                   Display version\n"
 | 
				
			||||||
           );
 | 
					           );
 | 
				
			||||||
    exit(EXIT_SUCCESS);
 | 
					    exit(EXIT_SUCCESS);
 | 
				
			||||||
@@ -205,7 +234,7 @@ static int is_string_hwaddr(char *str, size_t slen)
 | 
				
			|||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int get_clientid_string(char *str, size_t slen)
 | 
					int get_clientid_string(char *str, size_t slen)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (!slen)
 | 
					    if (!slen)
 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
@@ -333,9 +362,9 @@ jumpstart:
 | 
				
			|||||||
char state_dir[PATH_MAX] = "/etc/ndhc";
 | 
					char state_dir[PATH_MAX] = "/etc/ndhc";
 | 
				
			||||||
char chroot_dir[PATH_MAX] = "";
 | 
					char chroot_dir[PATH_MAX] = "";
 | 
				
			||||||
char resolv_conf_d[PATH_MAX] = "";
 | 
					char resolv_conf_d[PATH_MAX] = "";
 | 
				
			||||||
static char pidfile[PATH_MAX] = PID_FILE_DEFAULT;
 | 
					char pidfile[PATH_MAX] = PID_FILE_DEFAULT;
 | 
				
			||||||
static uid_t ndhc_uid = 0;
 | 
					uid_t ndhc_uid = 0;
 | 
				
			||||||
static gid_t ndhc_gid = 0;
 | 
					gid_t ndhc_gid = 0;
 | 
				
			||||||
int ifchSock[2];
 | 
					int ifchSock[2];
 | 
				
			||||||
int ifchPipe[2];
 | 
					int ifchPipe[2];
 | 
				
			||||||
int sockdSock[2];
 | 
					int sockdSock[2];
 | 
				
			||||||
@@ -432,176 +461,9 @@ void background(void)
 | 
				
			|||||||
        write_pid(pidfile);
 | 
					        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[])
 | 
					int main(int argc, char *argv[])
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    parse_program_options(argc, argv);
 | 
					    parse_cmdline(argc, argv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    nk_random_u32_init(&cs.rnd32_state);
 | 
					    nk_random_u32_init(&cs.rnd32_state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -74,7 +74,14 @@ extern int sockdPipe[2];
 | 
				
			|||||||
extern char state_dir[PATH_MAX];
 | 
					extern char state_dir[PATH_MAX];
 | 
				
			||||||
extern char chroot_dir[PATH_MAX];
 | 
					extern char chroot_dir[PATH_MAX];
 | 
				
			||||||
extern char resolv_conf_d[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 background(void);
 | 
				
			||||||
 | 
					void print_version(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* NJK_NDHC_NDHC_H_ */
 | 
					#endif /* NJK_NDHC_NDHC_H_ */
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user