diff options
author | Francis Dupont <fdupont@isc.org> | 2016-10-06 10:14:10 +0200 |
---|---|---|
committer | Francis Dupont <fdupont@isc.org> | 2016-10-06 10:14:10 +0200 |
commit | a1eea2a0d14c25d395d45ffb215df3d81a5b1da1 (patch) | |
tree | d663f5dfa97f4757ffd8dd5d1aa67c1d4a4e9fa0 | |
parent | 160842b2a7ecf1851f829b0ee7e1b36a8a3c6650 (diff) | |
parent | a18e41ff5e07727c87f02a8aa88e4e59bfbac5f6 (diff) | |
download | isc-dhcp-a1eea2a0d14c25d395d45ffb215df3d81a5b1da1.tar.gz |
Merged rt43246a (fix --enable-threads)
-rw-r--r-- | client/dhc6.c | 18 | ||||
-rw-r--r-- | client/dhclient.c | 186 | ||||
-rw-r--r-- | includes/dhcpd.h | 3 | ||||
-rw-r--r-- | omapip/isclib.c | 30 | ||||
-rw-r--r-- | relay/dhcrelay.c | 93 | ||||
-rw-r--r-- | server/dhcpd.c | 194 |
6 files changed, 381 insertions, 143 deletions
diff --git a/client/dhc6.c b/client/dhc6.c index c8d16e8a..be604ac9 100644 --- a/client/dhc6.c +++ b/client/dhc6.c @@ -1500,7 +1500,7 @@ start_init6(struct client_state *client) add_timeout(&tv, do_init6, client, NULL, NULL); if (nowait) - go_daemon(); + detach(); } /* @@ -1544,7 +1544,7 @@ start_info_request6(struct client_state *client) add_timeout(&tv, do_info_request6, client, NULL, NULL); if (nowait) - go_daemon(); + detach(); } /* @@ -1871,7 +1871,7 @@ do_init6(void *input) } /* Stop if and only if this is the last client. */ if (stopping_finished()) - exit(2); + finish(2); return; } @@ -2176,7 +2176,7 @@ do_info_request6(void *input) case CHK_TIM_ALLOC_FAILURE: return; case CHK_TIM_MRD_EXCEEDED: - exit(2); + finish(2); case CHK_TIM_SUCCESS: break; } @@ -2418,7 +2418,7 @@ do_release6(void *input) dhc6_lease_destroy(&client->active_lease, MDL); client->active_lease = NULL; if (stopping_finished()) - exit(0); + finish(0); } /* status_log() just puts a status code into displayable form and logs it @@ -4224,7 +4224,7 @@ reply_handler(struct packet *packet, struct client_state *client) client->active_lease = NULL; /* We should never wait for nothing!? */ if (stopping_finished()) - exit(0); + finish(0); return; } @@ -4840,7 +4840,7 @@ start_bound(struct client_state *client) dhcp4o6_start(); #endif - go_daemon(); + detach(); if (client->old_lease != NULL) { dhc6_lease_destroy(&client->old_lease, MDL); @@ -5323,7 +5323,7 @@ dhc6_check_irt(struct client_state *client) #ifdef DHCP4o6 if (!dhcpv4_over_dhcpv6) #endif - exit(0); + finish(0); } oc = lookup_option(&dhcpv6_universe, client->active_lease->options, @@ -5382,7 +5382,7 @@ start_informed(struct client_state *client) dhcp4o6_start(); #endif - go_daemon(); + detach(); if (client->old_lease != NULL) { dhc6_lease_destroy(&client->old_lease, MDL); diff --git a/client/dhclient.c b/client/dhclient.c index f7486c6a..8d717055 100644 --- a/client/dhclient.c +++ b/client/dhclient.c @@ -84,6 +84,7 @@ u_int16_t remote_port = 0; int dhcp4o6_state = -1; /* -1 = stopped, 0 = polling, 1 = started */ #endif int no_daemon = 0; +int dfd[2] = { -1, -1 }; struct string_list *client_env = NULL; int client_env_count = 0; int onetry = 0; @@ -149,6 +150,28 @@ static const char use_noarg[] = "No argument for command: %s"; static const char use_v6command[] = "Command not used for DHCPv4: %s"; #endif +#ifdef DHCPv6 +#ifdef DHCP4o6 +#define DHCLIENT_USAGE0 \ +"[-4|-6] [-SNTPRI1dvrxi] [-nw] -4o6 <port>]\n" \ +" [-p <port>] [-D LL|LLT] \n" +#else /* DHCP4o6 */ +#define DHCLIENT_USAGE0 \ +"[-4|-6] [-SNTPRI1dvrxi] [-nw] [-p <port>] [-D LL|LLT] \n" +#endif +#else /* DHCPv6 */ +#define DHCLIENT_USAGE0 \ +"[-I1dvrxi] [-nw] [-p <port>] [-D LL|LLT] \n" +#endif + +#define DHCLIENT_USAGEC \ +" [-s server-addr] [-cf config-file]\n" \ +" [-df duid-file] [-lf lease-file]\n" \ +" [-pf pid-file] [--no-pid] [-e VAR=val]\n" \ +" [-sf script-file] [interface]*" + +#define DHCLIENT_USAGEH "{--version|--help|-h}" + static void usage(const char *sfmt, const char *sarg) { @@ -163,22 +186,12 @@ usage(const char *sfmt, const char *sarg) log_error(sfmt, sarg); #endif - log_fatal("Usage: %s " -#ifdef DHCPv6 -#ifdef DHCP4o6 - "[-4|-6] [-SNTPRI1dvrxi] [-nw] -4o6 <port>]\n" - " [-p <port>] [-D LL|LLT] \n" -#else /* DHCP4o6 */ - "[-4|-6] [-SNTPRI1dvrxi] [-nw] [-p <port>] [-D LL|LLT] \n" -#endif -#else /* DHCPv6 */ - "[-I1dvrxi] [-nw] [-p <port>] [-D LL|LLT] \n" -#endif /* DHCPv6 */ - " [-s server-addr] [-cf config-file]\n" - " [-df duid-file] [-lf lease-file]\n" - " [-pf pid-file] [--no-pid] [-e VAR=val]\n" - " [-sf script-file] [interface]*", - isc_file_basename(progname)); + log_fatal("Usage: %s %s%s\n %s %s", + isc_file_basename(progname), + DHCLIENT_USAGE0, + DHCLIENT_USAGEC, + isc_file_basename(progname), + DHCLIENT_USAGEH); } int @@ -236,6 +249,69 @@ main(int argc, char **argv) { setlogmask(LOG_UPTO(LOG_INFO)); #endif + /* Parse arguments changing no_daemon */ + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-r")) { + no_daemon = 1; + } else if (!strcmp(argv[i], "-x")) { + no_daemon = 0; + } else if (!strcmp(argv[i], "-d")) { + no_daemon = 1; + } else if (!strcmp(argv[i], "--version")) { + const char vstring[] = "isc-dhclient-"; + IGNORE_RET(write(STDERR_FILENO, vstring, + strlen(vstring))); + IGNORE_RET(write(STDERR_FILENO, + PACKAGE_VERSION, + strlen(PACKAGE_VERSION))); + IGNORE_RET(write(STDERR_FILENO, "\n", 1)); + exit(0); + } else if (!strcmp(argv[i], "--help") || + !strcmp(argv[i], "-h")) { + const char *pname = isc_file_basename(progname); + IGNORE_RET(write(STDERR_FILENO, "Usage: ", 7)); + IGNORE_RET(write(STDERR_FILENO, pname, strlen(pname))); + IGNORE_RET(write(STDERR_FILENO, " ", 1)); + IGNORE_RET(write(STDERR_FILENO, DHCLIENT_USAGE0, + strlen(DHCLIENT_USAGE0))); + IGNORE_RET(write(STDERR_FILENO, DHCLIENT_USAGEC, + strlen(DHCLIENT_USAGEC))); + IGNORE_RET(write(STDERR_FILENO, "\n", 1)); + IGNORE_RET(write(STDERR_FILENO, " ", 7)); + IGNORE_RET(write(STDERR_FILENO, pname, strlen(pname))); + IGNORE_RET(write(STDERR_FILENO, " ", 1)); + IGNORE_RET(write(STDERR_FILENO, DHCLIENT_USAGEH, + strlen(DHCLIENT_USAGEH))); + IGNORE_RET(write(STDERR_FILENO, "\n", 1)); + exit(0); + } + } + /* When not forbidden prepare to become a daemon */ + if (!no_daemon) { + int pid; + + if (pipe(dfd) == -1) + log_fatal("Can't get pipe: %m"); + if ((pid = fork ()) < 0) + log_fatal("Can't fork daemon: %m"); + if (pid != 0) { + /* Parent: wait for the child to start */ + int n; + + (void) close(dfd[1]); + do { + char buf; + + n = read(dfd[0], &buf, 1); + if (n == 1) + _exit((int)buf); + } while (n == -1 && errno == EINTR); + _exit(1); + } + /* Child */ + (void) close(dfd[0]); + } + /* Set up the isc and dns library managers */ status = dhcp_context_create(DHCP_CONTEXT_PRE_DB | DHCP_CONTEXT_POST_DB, NULL, NULL); @@ -260,7 +336,7 @@ main(int argc, char **argv) { for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-r")) { release_mode = 1; - no_daemon = 1; + /* no_daemon = 1; */ #ifdef DHCPv6 } else if (!strcmp(argv[i], "-4")) { if (local_family_set && local_family != AF_INET) @@ -288,7 +364,7 @@ main(int argc, char **argv) { #endif /* DHCPv6 */ } else if (!strcmp(argv[i], "-x")) { /* eXit, no release */ release_mode = 0; - no_daemon = 0; + /* no_daemon = 0; */ exit_mode = 1; } else if (!strcmp(argv[i], "-p")) { if (++i == argc) @@ -297,7 +373,7 @@ main(int argc, char **argv) { log_debug("binding to user-specified port %d", ntohs(local_port)); } else if (!strcmp(argv[i], "-d")) { - no_daemon = 1; + /* no_daemon = 1; */ quiet = 0; } else if (!strcmp(argv[i], "-pf")) { if (++i == argc) @@ -422,15 +498,6 @@ main(int argc, char **argv) { std_dhcid = 1; } else if (!strcmp(argv[i], "-v")) { quiet = 0; - } else if (!strcmp(argv[i], "--version")) { - const char vstring[] = "isc-dhclient-"; - IGNORE_RET(write(STDERR_FILENO, vstring, - strlen(vstring))); - IGNORE_RET(write(STDERR_FILENO, - PACKAGE_VERSION, - strlen(PACKAGE_VERSION))); - IGNORE_RET(write(STDERR_FILENO, "\n", 1)); - exit(0); } else if (argv[i][0] == '-') { usage("Unknown command: %s", argv[i]); } else if (interfaces_requested < 0) { @@ -613,7 +680,7 @@ main(int argc, char **argv) { if (release_mode || (wanted_ia_na > 0) || wanted_ia_ta || wanted_ia_pd || (interfaces_requested != 1)) { - usage("Stateless commnad: %s incompatibile with " + usage("Stateless command: %s incompatibile with " "other commands", "-S"); } #if defined(DHCPv6) && defined(DHCP4o6) @@ -621,7 +688,7 @@ main(int argc, char **argv) { #else run_stateless(exit_mode, 0); #endif - return 0; + finish(0); } /* Discover all the network interfaces. */ @@ -663,7 +730,7 @@ main(int argc, char **argv) { if (!persist) { /* Nothing more to do. */ log_info("No broadcast interfaces found - exiting."); - exit(0); + finish(0); } } else if (!release_mode && !exit_mode) { /* Call the script with the list of interfaces. */ @@ -800,16 +867,16 @@ main(int argc, char **argv) { } if (exit_mode) - return 0; + finish(0); if (release_mode) { #ifndef DHCPv6 - return 0; + finish(0); #else if ((local_family == AF_INET6) || dhcpv4_over_dhcpv6) { if (onetry) - return 0; + finish(0); } else - return 0; + finish(0); #endif /* DHCPv6 */ } @@ -852,7 +919,7 @@ main(int argc, char **argv) { /* If we're not supposed to wait before getting the address, don't. */ if (nowait) - go_daemon(); + detach(); /* If we're not going to daemonize, write the pid file now. */ @@ -963,7 +1030,7 @@ void run_stateless(int exit_mode, u_int16_t port) /* If we're not supposed to wait before getting the address, don't. */ if (nowait) - go_daemon(); + detach(); /* If we're not going to daemonize, write the pid file now. */ @@ -1404,7 +1471,7 @@ void bind_lease (client) if (!quiet) log_info("Unable to obtain a lease on first " "try (declined). Exiting."); - exit(2); + finish(2); } else { state_init(client); return; @@ -1433,7 +1500,7 @@ void bind_lease (client) (long)(client->active->renewal - cur_time)); client->state = S_BOUND; reinitialize_interfaces(); - go_daemon(); + detach(); #if defined (NSUPDATE) if (client->config->do_forward_update) dhclient_schedule_updates(client, &client->active->address, 1); @@ -2373,7 +2440,7 @@ void state_panic (cpp) state_bound (client); } reinitialize_interfaces (); - go_daemon (); + detach (); return; } } @@ -2413,7 +2480,7 @@ void state_panic (cpp) if (!quiet) log_info ("Unable to obtain a lease on first try.%s", " Exiting."); - exit (2); + finish(2); } log_info ("No working leases in persistent database - sleeping."); @@ -2427,7 +2494,7 @@ void state_panic (cpp) tv.tv_usec = ((tv.tv_sec - cur_tv.tv_sec) > 1) ? random() % 1000000 : cur_tv.tv_usec; add_timeout(&tv, state_init, client, 0, 0); - go_daemon (); + detach (); } void send_request (cpp) @@ -4200,10 +4267,20 @@ int dhcp_option_ev_name (buf, buflen, option) return 1; } -void go_daemon () +void finish (char ret) +{ + if (no_daemon || dfd[0] == -1 || dfd[1] == -1) + exit((int)ret); + if (write(dfd[1], &ret, 1) != 1) + log_fatal("write to parent: %m"); + (void) close(dfd[1]); + dfd[0] = dfd[1] = -1; + exit((int)ret); +} + +void detach () { - static int state = 0; - int pid; + char buf = 0; /* Don't become a daemon if the user requested otherwise. */ if (no_daemon) { @@ -4212,18 +4289,18 @@ void go_daemon () } /* Only do it once. */ - if (state) + if (dfd[0] == -1 || dfd[1] == -1) return; - state = 1; + + /* Signal parent we started successfully. */ + if (write(dfd[1], &buf, 1) != 1) + log_fatal("write to parent: %m"); + (void) close(dfd[1]); + dfd[0] = dfd[1] = -1; /* Stop logging to stderr... */ log_perror = 0; - /* Become a daemon... */ - if ((pid = fork ()) < 0) - log_fatal ("Can't fork daemon: %m"); - else if (pid) - exit (0); /* Become session leader and get pid... */ (void) setsid (); @@ -4240,6 +4317,7 @@ void go_daemon () write_client_pid_file (); IGNORE_RET (chdir("/")); + } void write_client_pid_file () @@ -4376,7 +4454,7 @@ void do_release(client) #if defined(DHCPv6) && defined(DHCP4o6) if (dhcpv4_over_dhcpv6) - exit(0); + finish(0); #endif } @@ -4507,7 +4585,7 @@ static void shutdown_exit (void *foo) /* get rid of the pid if we can */ if (no_pid_file == ISC_FALSE) (void) unlink(path_dhclient_pid); - exit (0); + finish(0); } #if defined (NSUPDATE) diff --git a/includes/dhcpd.h b/includes/dhcpd.h index 261714dc..a16b80db 100644 --- a/includes/dhcpd.h +++ b/includes/dhcpd.h @@ -2975,7 +2975,8 @@ void client_envadd (struct client_state *, __attribute__((__format__(__printf__,4,5))); struct client_lease *packet_to_lease (struct packet *, struct client_state *); -void go_daemon (void); +void finish (char); +void detach (void); void write_client_pid_file (void); void client_location_changed (void); void do_release (struct client_state *); diff --git a/omapip/isclib.c b/omapip/isclib.c index 12608a7b..781db848 100644 --- a/omapip/isclib.c +++ b/omapip/isclib.c @@ -185,21 +185,6 @@ dhcp_context_create(int flags, if (result != ISC_R_SUCCESS) goto cleanup; - result = isc_app_ctxstart(dhcp_gbl_ctx.actx); - if (result != ISC_R_SUCCESS) - return (result); - dhcp_gbl_ctx.actx_started = ISC_TRUE; - - /* Not all OSs support suppressing SIGPIPE through socket - * options, so set the sigal action to be ignore. This allows - * broken connections to fail gracefully with EPIPE on writes */ - handle_signal(SIGPIPE, SIG_IGN); - - /* Reset handlers installed by isc_app_ctxstart() - * to default for control-c and kill */ - handle_signal(SIGINT, SIG_DFL); - handle_signal(SIGTERM, SIG_DFL); - result = isc_taskmgr_createinctx(dhcp_gbl_ctx.mctx, dhcp_gbl_ctx.actx, 1, 0, @@ -222,6 +207,21 @@ dhcp_context_create(int flags, result = isc_task_create(dhcp_gbl_ctx.taskmgr, 0, &dhcp_gbl_ctx.task); if (result != ISC_R_SUCCESS) goto cleanup; + + result = isc_app_ctxstart(dhcp_gbl_ctx.actx); + if (result != ISC_R_SUCCESS) + return (result); + dhcp_gbl_ctx.actx_started = ISC_TRUE; + + /* Not all OSs support suppressing SIGPIPE through socket + * options, so set the sigal action to be ignore. This allows + * broken connections to fail gracefully with EPIPE on writes */ + handle_signal(SIGPIPE, SIG_IGN); + + /* Reset handlers installed by isc_app_ctxstart() + * to default for control-c and kill */ + handle_signal(SIGINT, SIG_DFL); + handle_signal(SIGTERM, SIG_DFL); } #if defined (NSUPDATE) diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c index 344cee78..4f604a22 100644 --- a/relay/dhcrelay.c +++ b/relay/dhcrelay.c @@ -77,6 +77,9 @@ int missing_circuit_id = 0; /* Circuit ID option in matching RAI option was missing. */ int max_hop_count = 10; /* Maximum hop count */ +int no_daemon = 0; +int dfd[2] = { -1, -1 }; + #ifdef DHCPv6 /* Force use of DHCPv6 interface-id option. */ isc_boolean_t use_if_id = ISC_FALSE; @@ -164,8 +167,9 @@ char *progname; " [-s <subscriber-id>]\n" \ " -l lower0 [ ... -l lowerN]\n" \ " -u upper0 [ ... -u upperN]\n" \ -" lower (client link): [address%%]interface[#index]\n" \ -" upper (server link): [address%%]interface" +" lower (client link): [address%%]interface[#index]\n" \ +" upper (server link): [address%%]interface\n\n" \ +" %s {--version|--help|-h}" #else #define DHCRELAY_USAGE \ "Usage: %s [-d] [-q] [-a] [-D] [-A <length>] [-c <hops>] [-p <port>]\n" \ @@ -175,7 +179,8 @@ char *progname; " [-iu interface0 [ ... -iu interfaceN]\n" \ " [-id interface0 [ ... -id interfaceN]\n" \ " [-U interface]\n" \ -" server0 [ ... serverN]\n\n" +" server0 [ ... serverN]\n\n" \ +" %s {--version|--help|-h}" #endif /*! @@ -213,6 +218,7 @@ usage(const char *sfmt, const char *sarg) { #ifdef DHCPv6 isc_file_basename(progname), #endif + isc_file_basename(progname), isc_file_basename(progname)); } @@ -223,7 +229,7 @@ main(int argc, char **argv) { struct server_list *sp = NULL; char *service_local = NULL, *service_remote = NULL; u_int16_t port_local = 0, port_remote = 0; - int no_daemon = 0, quiet = 0; + int quiet = 0; int fd; int i; #ifdef DHCPv6 @@ -256,6 +262,51 @@ main(int argc, char **argv) { setlogmask(LOG_UPTO(LOG_INFO)); #endif + /* Parse arguments changing no_daemon */ + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-d")) { + no_daemon = 1; + } else if (!strcmp(argv[i], "--version")) { + log_info("isc-dhcrelay-%s", PACKAGE_VERSION); + exit(0); + } else if (!strcmp(argv[i], "--help") || + !strcmp(argv[i], "-h")) { + log_info(DHCRELAY_USAGE, +#ifdef DHCPv6 + isc_file_basename(progname), +#endif + isc_file_basename(progname), + isc_file_basename(progname)); + exit(0); + } + } + /* When not forbidden prepare to become a daemon */ + if (!no_daemon) { + int pid; + + if (pipe(dfd) == -1) + log_fatal("Can't get pipe: %m"); + if ((pid = fork ()) < 0) + log_fatal("Can't fork daemon: %m"); + if (pid != 0) { + /* Parent: wait for the child to start */ + int n; + + (void) close(dfd[1]); + do { + char buf; + + n = read(dfd[0], &buf, 1); + if (n == 1) + _exit(0); + } while (n == -1 && errno == EINTR); + _exit(1); + } + /* Child */ + (void) close(dfd[0]); + } + + /* Set up the isc and dns library managers */ status = dhcp_context_create(DHCP_CONTEXT_PRE_DB | DHCP_CONTEXT_POST_DB, NULL, NULL); @@ -288,7 +339,7 @@ main(int argc, char **argv) { local_family = AF_INET6; #endif } else if (!strcmp(argv[i], "-d")) { - no_daemon = 1; + /* no_daemon = 1; */ } else if (!strcmp(argv[i], "-q")) { quiet = 1; quiet_interface_discovery = 1; @@ -481,17 +532,6 @@ main(int argc, char **argv) { no_dhcrelay_pid = ISC_TRUE; } else if (!strcmp(argv[i], "--no-pid")) { no_pid_file = ISC_TRUE; - } else if (!strcmp(argv[i], "--version")) { - log_info("isc-dhcrelay-%s", PACKAGE_VERSION); - exit(0); - } else if (!strcmp(argv[i], "--help") || - !strcmp(argv[i], "-h")) { - log_info(DHCRELAY_USAGE, -#ifdef DHCPv6 - isc_file_basename(progname), -#endif - isc_file_basename(progname)); - exit(0); } else if (argv[i][0] == '-') { usage("Unknown command: %s", argv[i]); } else { @@ -647,17 +687,21 @@ main(int argc, char **argv) { /* Become a daemon... */ if (!no_daemon) { - int pid; + char buf = 0; FILE *pf; int pfdesc; log_perror = 0; - if ((pid = fork()) < 0) - log_fatal("Can't fork daemon: %m"); - else if (pid) - exit(0); + /* Signal parent we started successfully. */ + if (dfd[0] != -1 && dfd[1] != -1) { + if (write(dfd[1], &buf, 1) != 1) + log_fatal("write to parent: %m"); + (void) close(dfd[1]); + dfd[0] = dfd[1] = -1; + } + /* Create the pid file. */ if (no_pid_file == ISC_FALSE) { pfdesc = open(path_dhcrelay_pid, O_CREAT | O_TRUNC | O_WRONLY, 0644); @@ -1865,12 +1909,19 @@ parse_allow_deny(struct option_cache **oc, struct parse *p, int i) { isc_result_t dhcp_set_control_state(control_object_state_t oldstate, control_object_state_t newstate) { + char buf = 0; + if (newstate != server_shutdown) return ISC_R_SUCCESS; if (no_pid_file == ISC_FALSE) (void) unlink(path_dhcrelay_pid); + if (!no_daemon && dfd[0] != -1 && dfd[1] != -1) { + IGNORE_RET(write(dfd[1], &buf, 1)); + (void) close(dfd[1]); + dfd[0] = dfd[1] = -1; + } exit(0); } diff --git a/server/dhcpd.c b/server/dhcpd.c index 43642823..a7f0604a 100644 --- a/server/dhcpd.c +++ b/server/dhcpd.c @@ -135,6 +135,44 @@ static void omapi_listener_start (void *foo) #ifndef UNIT_TEST +#define DHCPD_USAGE0 \ +"[-p <UDP port #>] [-f] [-d] [-q] [-t|-T]\n" + +#ifdef DHCPv6 +#ifdef DHCP4o6 +#define DHCPD_USAGE1 \ +" [-4|-6] [-4o6 <port>]\n" \ +" [-cf config-file] [-lf lease-file]\n" +#else /* DHCP4o6 */ +#define DHCPD_USAGE1 \ +" [-4|-6] [-cf config-file] [-lf lease-file]\n" +#endif /* DHCP4o6 */ +#else /* !DHCPv6 */ +#define DHCPD_USAGE1 \ +" [-cf config-file] [-lf lease-file]\n" +#endif /* DHCPv6 */ + +#if defined (PARANOIA) +#define DHCPD_USAGEP \ +" [-user user] [-group group] [-chroot dir]\n" +#else +#define DHCPD_USAGEP "" +#endif /* PARANOIA */ + +#if defined (TRACING) +#define DHCPD_USAGET \ +" [-tf trace-output-file]\n" \ +" [-play trace-input-file]\n" +#else +#define DHCPD_USAGET "" +#endif /* TRACING */ + +#define DHCPD_USAGEC \ +" [-pf pid-file] [--no-pid] [-s server]\n" \ +" [if0 [...ifN]]" + +#define DHCPD_USAGEH "{--version|--help|-h}" + /*! * * \brief Print the generic usage message @@ -164,28 +202,15 @@ usage(const char *sfmt, const char *sarg) { log_error(sfmt, sarg); #endif - log_fatal("Usage: %s [-p <UDP port #>] [-f] [-d] [-q] [-t|-T]\n" -#ifdef DHCPv6 -#ifdef DHCP4o6 - " [-4|-6] [-4o6 <port>]\n" - " [-cf config-file] [-lf lease-file]\n" -#else /* DHCP4o6 */ - " [-4|-6] [-cf config-file] [-lf lease-file]\n" -#endif /* DHCP4o6 */ -#else /* !DHCPv6 */ - " [-cf config-file] [-lf lease-file]\n" -#endif /* DHCPv6 */ -#if defined (PARANOIA) - /* meld into the following string */ - " [-user user] [-group group] [-chroot dir]\n" -#endif /* PARANOIA */ -#if defined (TRACING) - " [-tf trace-output-file]\n" - " [-play trace-input-file]\n" -#endif /* TRACING */ - " [-pf pid-file] [--no-pid] [-s server]\n" - " [if0 [...ifN]]", - isc_file_basename(progname)); + log_fatal("Usage: %s %s%s%s%s%s\n %s %s", + isc_file_basename(progname), + DHCPD_USAGE0, + DHCPD_USAGE1, + DHCPD_USAGEP, + DHCPD_USAGET, + DHCPD_USAGEC, + isc_file_basename(progname), + DHCPD_USAGEH); } /* Note: If we add unit tests to test setup_chroot it will @@ -220,6 +245,7 @@ main(int argc, char **argv) { char pbuf [20]; #ifndef DEBUG int daemon = 1; + int dfd[2] = { -1, -1 }; #endif int quiet = 0; char *server = (char *)0; @@ -269,6 +295,96 @@ main(int argc, char **argv) { else if (fd != -1) close(fd); + /* Parse arguments changing daemon */ + for (i = 1; i < argc; i++) { + if (!strcmp (argv [i], "-f")) { +#ifndef DEBUG + daemon = 0; +#endif + } else if (!strcmp (argv [i], "-d")) { +#ifndef DEBUG + daemon = 0; +#endif + } else if (!strcmp (argv [i], "-t")) { +#ifndef DEBUG + daemon = 0; +#endif + } else if (!strcmp (argv [i], "-T")) { +#ifndef DEBUG + daemon = 0; +#endif + } else if (!strcmp (argv [i], "--version")) { + const char vstring[] = "isc-dhcpd-"; + IGNORE_RET(write(STDERR_FILENO, vstring, + strlen(vstring))); + IGNORE_RET(write(STDERR_FILENO, + PACKAGE_VERSION, + strlen(PACKAGE_VERSION))); + IGNORE_RET(write(STDERR_FILENO, "\n", 1)); + exit (0); + } else if (!strcmp(argv[i], "--help") || + !strcmp(argv[i], "-h")) { + const char *pname = isc_file_basename(progname); + IGNORE_RET(write(STDERR_FILENO, "Usage: ", 7)); + IGNORE_RET(write(STDERR_FILENO, pname, strlen(pname))); + IGNORE_RET(write(STDERR_FILENO, " ", 1)); + IGNORE_RET(write(STDERR_FILENO, DHCPD_USAGE0, + strlen(DHCPD_USAGE0))); + IGNORE_RET(write(STDERR_FILENO, DHCPD_USAGE1, + strlen(DHCPD_USAGE1))); +#if defined (PARANOIA) + IGNORE_RET(write(STDERR_FILENO, DHCPD_USAGEP, + strlen(DHCPD_USAGEP))); +#endif +#if defined (TRACING) + IGNORE_RET(write(STDERR_FILENO, DHCPD_USAGET, + strlen(DHCPD_USAGET))); +#endif + IGNORE_RET(write(STDERR_FILENO, DHCPD_USAGEC, + strlen(DHCPD_USAGEC))); + IGNORE_RET(write(STDERR_FILENO, "\n", 1)); + IGNORE_RET(write(STDERR_FILENO, " ", 7)); + IGNORE_RET(write(STDERR_FILENO, pname, strlen(pname))); + IGNORE_RET(write(STDERR_FILENO, " ", 1)); + IGNORE_RET(write(STDERR_FILENO, DHCPD_USAGEH, + strlen(DHCPD_USAGEH))); + IGNORE_RET(write(STDERR_FILENO, "\n", 1)); + exit(0); +#ifdef TRACING + } else if (!strcmp (argv [i], "-play")) { +#ifndef DEBUG + daemon = 0; +#endif +#endif + } + } + +#ifndef DEBUG + /* When not forbidden prepare to become a daemon */ + if (daemon) { + if (pipe(dfd) == -1) + log_fatal("Can't get pipe: %m"); + if ((pid = fork ()) < 0) + log_fatal("Can't fork daemon: %m"); + if (pid != 0) { + /* Parent: wait for the child to start */ + int n; + + (void) close(dfd[1]); + do { + char buf; + + n = read(dfd[0], &buf, 1); + if (n == 1) + _exit((int)buf); + } while (n == -1 && errno == EINTR); + _exit(1); + } + /* Child */ + (void) close(dfd[0]); + } +#endif + /* Set up the isc and dns library managers */ status = dhcp_context_create(DHCP_CONTEXT_PRE_DB, NULL, NULL); @@ -304,11 +420,11 @@ main(int argc, char **argv) { ntohs (local_port)); } else if (!strcmp (argv [i], "-f")) { #ifndef DEBUG - daemon = 0; + /* daemon = 0; */ #endif } else if (!strcmp (argv [i], "-d")) { #ifndef DEBUG - daemon = 0; + /* daemon = 0; */ #endif log_perror = -1; } else if (!strcmp (argv [i], "-s")) { @@ -349,14 +465,14 @@ main(int argc, char **argv) { } else if (!strcmp (argv [i], "-t")) { /* test configurations only */ #ifndef DEBUG - daemon = 0; + /* daemon = 0; */ #endif cftest = 1; log_perror = -1; } else if (!strcmp (argv [i], "-T")) { /* test configurations and lease file only */ #ifndef DEBUG - daemon = 0; + /* daemon = 0; */ #endif cftest = 1; lftest = 1; @@ -391,15 +507,6 @@ main(int argc, char **argv) { dhcpv4_over_dhcpv6 = 1; #endif /* DHCP4o6 */ #endif /* DHCPv6 */ - } else if (!strcmp (argv [i], "--version")) { - const char vstring[] = "isc-dhcpd-"; - IGNORE_RET(write(STDERR_FILENO, vstring, - strlen(vstring))); - IGNORE_RET(write(STDERR_FILENO, - PACKAGE_VERSION, - strlen(PACKAGE_VERSION))); - IGNORE_RET(write(STDERR_FILENO, "\n", 1)); - exit (0); #if defined (TRACING) } else if (!strcmp (argv [i], "-tf")) { if (++i == argc) @@ -845,14 +952,6 @@ main(int argc, char **argv) { #endif /* DHCPv6 */ #ifndef DEBUG - if (daemon) { - /* First part of becoming a daemon... */ - if ((pid = fork ()) < 0) - log_fatal ("Can't fork daemon: %m"); - else if (pid) - exit (0); - } - /* * Second part of dealing with pid files. Now * that we have forked we can write our pid if @@ -894,6 +993,15 @@ main(int argc, char **argv) { log_perror = 0; if (daemon) { + if (dfd[0] != -1 && dfd[1] != -1) { + char buf = 0; + + if (write(dfd[1], &buf, 1) != 1) + log_fatal("write to parent: %m"); + (void) close(dfd[1]); + dfd[0] = dfd[1] = -1; + } + /* Become session leader and get pid... */ (void) setsid(); |