summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client/dhc6.c18
-rw-r--r--client/dhclient.c186
-rw-r--r--includes/dhcpd.h3
-rw-r--r--omapip/isclib.c30
-rw-r--r--relay/dhcrelay.c93
-rw-r--r--server/dhcpd.c194
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();