diff options
Diffstat (limited to 'relay/dhcrelay.c')
-rw-r--r-- | relay/dhcrelay.c | 83 |
1 files changed, 65 insertions, 18 deletions
diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c index 344cee78..fd838be5 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; @@ -223,7 +226,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 +259,50 @@ 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)); + 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 +335,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 +528,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 +683,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 +1905,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); } |