Home | History | Annotate | Line # | Download | only in server
      1 /*	$NetBSD: dhcpd.c,v 1.5 2022/04/03 01:10:59 christos Exp $	*/
      2 
      3 /* dhcpd.c
      4 
      5    DHCP Server Daemon. */
      6 
      7 /*
      8  * Copyright (c) 2004-2022 by Internet Systems Consortium, Inc. ("ISC")
      9  * Copyright (c) 1996-2003 by Internet Software Consortium
     10  *
     11  * This Source Code Form is subject to the terms of the Mozilla Public
     12  * License, v. 2.0. If a copy of the MPL was not distributed with this
     13  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
     16  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     17  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
     18  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     19  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     20  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
     21  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     22  *
     23  *   Internet Systems Consortium, Inc.
     24  *   PO Box 360
     25  *   Newmarket, NH 03857 USA
     26  *   <info (at) isc.org>
     27  *   https://www.isc.org/
     28  *
     29  */
     30 
     31 #include <sys/cdefs.h>
     32 __RCSID("$NetBSD: dhcpd.c,v 1.5 2022/04/03 01:10:59 christos Exp $");
     33 
     34 static const char copyright[] =
     35 "Copyright 2004-2022 Internet Systems Consortium.";
     36 static const char arr [] = "All rights reserved.";
     37 static const char message [] = "Internet Systems Consortium DHCP Server";
     38 static const char url [] =
     39 "For info, please visit https://www.isc.org/software/dhcp/";
     40 
     41 #include "dhcpd.h"
     42 #include <omapip/omapip_p.h>
     43 #include <syslog.h>
     44 #include <signal.h>
     45 #include <errno.h>
     46 #include <limits.h>
     47 #include <sys/types.h>
     48 #include <sys/time.h>
     49 #include <isc/file.h>
     50 
     51 #if defined (PARANOIA)
     52 #  include <sys/types.h>
     53 #  include <unistd.h>
     54 #  include <pwd.h>
     55 /* get around the ISC declaration of group */
     56 #  define group real_group
     57 #    include <grp.h>
     58 #  undef group
     59 
     60 /* global values so db.c can look at them */
     61 uid_t set_uid = 0;
     62 gid_t set_gid = 0;
     63 #endif /* PARANOIA */
     64 
     65 struct class unknown_class;
     66 struct class known_class;
     67 
     68 struct iaddr server_identifier;
     69 int server_identifier_matched;
     70 
     71 #if defined (NSUPDATE)
     72 
     73 /* This stuff is always executed to figure the default values for certain
     74    ddns variables. */
     75 char std_nsupdate [] = "						    \n\
     76 option server.ddns-hostname =						    \n\
     77   pick (option fqdn.hostname, option host-name, config-option host-name);   \n\
     78 option server.ddns-domainname =	config-option domain-name;		    \n\
     79 option server.ddns-rev-domainname = \"in-addr.arpa.\";";
     80 
     81 /* Stores configured DDNS conflict detection flags */
     82 u_int16_t ddns_conflict_mask;
     83 #endif /* NSUPDATE */
     84 
     85 int ddns_update_style;
     86 int dont_use_fsync = 0; /* 0 = default, use fsync, 1 = don't use fsync */
     87 int server_id_check = 0; /* 0 = default, don't check server id, 1 = do check */
     88 
     89 #ifdef DHCPv6
     90 int prefix_length_mode = PLM_PREFER;
     91 int do_release_on_roam = 0; /* 0 = default, do not release v6 leases on roam */
     92 #endif
     93 
     94 #ifdef EUI_64
     95 int persist_eui64 = 1; /* 1 = write EUI64 leases to disk, 0 = don't */
     96 #endif
     97 
     98 int authoring_byte_order = 0; /* 0 = not set */
     99 int lease_id_format = TOKEN_OCTAL; /* octal by default */
    100 u_int32_t abandon_lease_time = DEFAULT_ABANDON_LEASE_TIME;
    101 
    102 const char *path_dhcpd_conf = _PATH_DHCPD_CONF;
    103 const char *path_dhcpd_db = _PATH_DHCPD_DB;
    104 const char *path_dhcpd_pid = _PATH_DHCPD_PID;
    105 /* False (default) => we write and use a pid file */
    106 isc_boolean_t no_pid_file = ISC_FALSE;
    107 
    108 int dhcp_max_agent_option_packet_length = DHCP_MTU_MAX;
    109 
    110 static omapi_auth_key_t *omapi_key = (omapi_auth_key_t *)0;
    111 int omapi_port;
    112 
    113 #if defined (TRACING)
    114 trace_type_t *trace_srandom;
    115 #endif
    116 
    117 extern uint16_t local_port;
    118 extern uint16_t remote_port;
    119 libdhcp_callbacks_t dhcpd_callbacks = {
    120 	&local_port,
    121 	&remote_port,
    122 	classify,
    123 	check_collection,
    124 	dhcp,
    125 #ifdef DHCPv6
    126 	dhcpv6,
    127 #endif /* DHCPv6 */
    128 	bootp,
    129 	find_class,
    130 	parse_allow_deny,
    131 	dhcp_set_control_state,
    132 };
    133 
    134 char *progname;
    135 
    136 static isc_result_t verify_addr (omapi_object_t *l, omapi_addr_t *addr) {
    137 	return ISC_R_SUCCESS;
    138 }
    139 
    140 static isc_result_t verify_auth (omapi_object_t *p, omapi_auth_key_t *a) {
    141 	if (a != omapi_key)
    142 		return DHCP_R_INVALIDKEY;
    143 	return ISC_R_SUCCESS;
    144 }
    145 
    146 static void omapi_listener_start (void *foo)
    147 {
    148 	omapi_object_t *listener;
    149 	isc_result_t result;
    150 	struct timeval tv;
    151 
    152 	listener = (omapi_object_t *)0;
    153 	result = omapi_generic_new (&listener, MDL);
    154 	if (result != ISC_R_SUCCESS)
    155 		log_fatal ("Can't allocate new generic object: %s",
    156 			   isc_result_totext (result));
    157 	result = omapi_protocol_listen (listener,
    158 					(unsigned)omapi_port, 1);
    159 	if (result == ISC_R_SUCCESS && omapi_key)
    160 		result = omapi_protocol_configure_security
    161 			(listener, verify_addr, verify_auth);
    162 	if (result != ISC_R_SUCCESS) {
    163 		log_error ("Can't start OMAPI protocol: %s",
    164 			   isc_result_totext (result));
    165 		tv.tv_sec = cur_tv.tv_sec + 5;
    166 		tv.tv_usec = cur_tv.tv_usec;
    167 		add_timeout (&tv, omapi_listener_start, 0, 0, 0);
    168 	}
    169 	omapi_object_dereference (&listener, MDL);
    170 }
    171 
    172 #ifndef UNIT_TEST
    173 
    174 #define DHCPD_USAGE0 \
    175 "[-p <UDP port #>] [-f] [-d] [-q] [-t|-T]\n"
    176 
    177 #ifdef DHCPv6
    178 #ifdef DHCP4o6
    179 #define DHCPD_USAGE1 \
    180 "             [-4|-6] [-4o6 <port>]\n" \
    181 "             [-cf config-file] [-lf lease-file]\n"
    182 #else /* DHCP4o6 */
    183 #define DHCPD_USAGE1 \
    184 "             [-4|-6] [-cf config-file] [-lf lease-file]\n"
    185 #endif /* DHCP4o6 */
    186 #else /* !DHCPv6 */
    187 #define DHCPD_USAGE1 \
    188 "             [-cf config-file] [-lf lease-file]\n"
    189 #endif /* DHCPv6 */
    190 
    191 #if defined (PARANOIA)
    192 #define DHCPD_USAGEP \
    193 "             [-user user] [-group group] [-chroot dir]\n"
    194 #else
    195 #define DHCPD_USAGEP ""
    196 #endif /* PARANOIA */
    197 
    198 #if defined (TRACING)
    199 #define DHCPD_USAGET \
    200 "             [-tf trace-output-file]\n" \
    201 "             [-play trace-input-file]\n"
    202 #else
    203 #define DHCPD_USAGET ""
    204 #endif /* TRACING */
    205 
    206 #define DHCPD_USAGEC \
    207 "             [-pf pid-file] [--no-pid] [-s server]\n" \
    208 "             [if0 [...ifN]]"
    209 
    210 #define DHCPD_USAGEH "{--version|--help|-h}"
    211 
    212 /*!
    213  *
    214  * \brief Print the generic usage message
    215  *
    216  * If the user has provided an incorrect command line print out
    217  * the description of the command line.  The arguments provide
    218  * a way for the caller to request more specific information about
    219  * the error be printed as well.  Mostly this will be that some
    220  * command doesn't include its argument.
    221  *
    222  * \param sfmt - The basic string and format for the specific error
    223  * \param sarg - Generally the offending argument from the command line.
    224  *
    225  * \return Nothing
    226  */
    227 
    228 #include <sys/cdefs.h>
    229 __RCSID("$NetBSD: dhcpd.c,v 1.5 2022/04/03 01:10:59 christos Exp $");
    230 static char use_noarg[] = "No argument for command: %s ";
    231 
    232 static void
    233 usage(const char *sfmt, const char *sarg) {
    234 	log_info("%s %s", message, PACKAGE_VERSION);
    235 	log_info(copyright);
    236 	log_info(arr);
    237 	log_info(url);
    238 
    239 	/* If desired print out the specific error message */
    240 #ifdef PRINT_SPECIFIC_CL_ERRORS
    241 	if (sfmt != NULL)
    242 		log_error(sfmt, sarg);
    243 #endif
    244 
    245 	log_fatal("Usage: %s %s%s%s%s%s\n       %s %s",
    246 		  isc_file_basename(progname),
    247 		  DHCPD_USAGE0,
    248 		  DHCPD_USAGE1,
    249 		  DHCPD_USAGEP,
    250 		  DHCPD_USAGET,
    251 		  DHCPD_USAGEC,
    252 		  isc_file_basename(progname),
    253 		  DHCPD_USAGEH);
    254 }
    255 
    256 /* Note: If we add unit tests to test setup_chroot it will
    257  * need to be moved to be outside the ifndef UNIT_TEST block.
    258  */
    259 
    260 #if defined (PARANOIA)
    261 /* to be used in one of two possible scenarios */
    262 static void setup_chroot (char *chroot_dir) {
    263   if (geteuid())
    264     log_fatal ("you must be root to use chroot");
    265 
    266   if (chroot(chroot_dir)) {
    267     log_fatal ("chroot(\"%s\"): %m", chroot_dir);
    268   }
    269   if (chdir ("/")) {
    270     /* probably permission denied */
    271     log_fatal ("chdir(\"/\"): %m");
    272   }
    273 }
    274 #endif /* PARANOIA */
    275 
    276 int
    277 main(int argc, char **argv) {
    278 	int fd;
    279 	int i, status;
    280 	struct servent *ent;
    281 	char *s;
    282 	int cftest = 0;
    283 	int lftest = 0;
    284 	int pid;
    285 	char pbuf [20];
    286 #ifndef DEBUG
    287 	int daemon = 1;
    288 	int dfd[2] = { -1, -1 };
    289 #endif
    290 	int quiet = 0;
    291 	char *server = (char *)0;
    292 	isc_result_t result;
    293 	unsigned seed;
    294 	struct interface_info *ip;
    295 #if defined (NSUPDATE)
    296 	struct parse *parse;
    297 	int lose;
    298 #endif
    299 	int have_dhcpd_conf = 0;
    300 	int have_dhcpd_db = 0;
    301 	int have_dhcpd_pid = 0;
    302 #ifdef DHCPv6
    303 	int local_family_set = 0;
    304 #ifdef DHCP4o6
    305 	u_int16_t dhcp4o6_port = 0;
    306 #endif /* DHCP4o6 */
    307 #endif /* DHCPv6 */
    308 #if defined (TRACING)
    309 	char *traceinfile = (char *)0;
    310 	char *traceoutfile = (char *)0;
    311 #endif
    312 
    313 #if defined (PARANOIA)
    314 	char *set_user   = 0;
    315 	char *set_group  = 0;
    316 	char *set_chroot = 0;
    317 #endif /* PARANOIA */
    318 
    319 	libdhcp_callbacks_register(&dhcpd_callbacks);
    320 
    321 #ifdef OLD_LOG_NAME
    322 	progname = "dhcpd";
    323 #else
    324 	progname = argv[0];
    325 #endif
    326 
    327         /* Make sure that file descriptors 0 (stdin), 1, (stdout), and
    328            2 (stderr) are open. To do this, we assume that when we
    329            open a file the lowest available file descriptor is used. */
    330         fd = open("/dev/null", O_RDWR);
    331         if (fd == 0)
    332                 fd = open("/dev/null", O_RDWR);
    333         if (fd == 1)
    334                 fd = open("/dev/null", O_RDWR);
    335         if (fd == 2)
    336                 log_perror = 0; /* No sense logging to /dev/null. */
    337         else if (fd != -1)
    338                 close(fd);
    339 
    340 	/* Parse arguments changing daemon */
    341 	for (i = 1; i < argc; i++) {
    342 		if (!strcmp (argv [i], "-f")) {
    343 #ifndef DEBUG
    344 			daemon = 0;
    345 #endif
    346 		} else if (!strcmp (argv [i], "-d")) {
    347 #ifndef DEBUG
    348 			daemon = 0;
    349 #endif
    350 		} else if (!strcmp (argv [i], "-t")) {
    351 #ifndef DEBUG
    352 			daemon = 0;
    353 #endif
    354 		} else if (!strcmp (argv [i], "-T")) {
    355 #ifndef DEBUG
    356 			daemon = 0;
    357 #endif
    358 		} else if (!strcmp (argv [i], "--version")) {
    359 			const char vstring[] = "isc-dhcpd-";
    360 			IGNORE_RET(write(STDERR_FILENO, vstring,
    361 					 strlen(vstring)));
    362 			IGNORE_RET(write(STDERR_FILENO,
    363 					 PACKAGE_VERSION,
    364 					 strlen(PACKAGE_VERSION)));
    365 			IGNORE_RET(write(STDERR_FILENO, "\n", 1));
    366 			exit (0);
    367 		} else if (!strcmp(argv[i], "--help") ||
    368 			   !strcmp(argv[i], "-h")) {
    369 			const char *pname = isc_file_basename(progname);
    370 			IGNORE_RET(write(STDERR_FILENO, "Usage: ", 7));
    371 			IGNORE_RET(write(STDERR_FILENO, pname, strlen(pname)));
    372 			IGNORE_RET(write(STDERR_FILENO, " ", 1));
    373 			IGNORE_RET(write(STDERR_FILENO, DHCPD_USAGE0,
    374 					 strlen(DHCPD_USAGE0)));
    375 			IGNORE_RET(write(STDERR_FILENO, DHCPD_USAGE1,
    376 					 strlen(DHCPD_USAGE1)));
    377 #if defined (PARANOIA)
    378 			IGNORE_RET(write(STDERR_FILENO, DHCPD_USAGEP,
    379 					 strlen(DHCPD_USAGEP)));
    380 #endif
    381 #if defined (TRACING)
    382 			IGNORE_RET(write(STDERR_FILENO, DHCPD_USAGET,
    383 					 strlen(DHCPD_USAGET)));
    384 #endif
    385 			IGNORE_RET(write(STDERR_FILENO, DHCPD_USAGEC,
    386 					 strlen(DHCPD_USAGEC)));
    387 			IGNORE_RET(write(STDERR_FILENO, "\n", 1));
    388 			IGNORE_RET(write(STDERR_FILENO, "       ", 7));
    389 			IGNORE_RET(write(STDERR_FILENO, pname, strlen(pname)));
    390 			IGNORE_RET(write(STDERR_FILENO, " ", 1));
    391 			IGNORE_RET(write(STDERR_FILENO, DHCPD_USAGEH,
    392 					 strlen(DHCPD_USAGEH)));
    393 			IGNORE_RET(write(STDERR_FILENO, "\n", 1));
    394 			exit(0);
    395 #ifdef TRACING
    396 		} else if (!strcmp (argv [i], "-play")) {
    397 #ifndef DEBUG
    398 			daemon = 0;
    399 #endif
    400 #endif
    401 		}
    402 	}
    403 
    404 #ifndef DEBUG
    405 	/* When not forbidden prepare to become a daemon */
    406 	if (daemon) {
    407 		if (pipe(dfd) == -1)
    408 			log_fatal("Can't get pipe: %m");
    409 		if ((pid = fork ()) < 0)
    410 			log_fatal("Can't fork daemon: %m");
    411 		if (pid != 0) {
    412 			/* Parent: wait for the child to start */
    413 			int n;
    414 
    415 			(void) close(dfd[1]);
    416 			do {
    417 				char buf;
    418 
    419 				n = read(dfd[0], &buf, 1);
    420 				if (n == 1)
    421 					_exit((int)buf);
    422 			} while (n == -1 && errno == EINTR);
    423 			_exit(1);
    424 		}
    425 		/* Child */
    426 		(void) close(dfd[0]);
    427 	}
    428 #endif
    429 
    430 	/* Set up the isc and dns library managers */
    431 	status = dhcp_context_create(DHCP_CONTEXT_PRE_DB,
    432 				     NULL, NULL);
    433 	if (status != ISC_R_SUCCESS)
    434 		log_fatal("Can't initialize context: %s",
    435 			  isc_result_totext(status));
    436 
    437 	/* Set up the client classification system. */
    438 	classification_setup ();
    439 
    440 	/* Initialize the omapi system. */
    441 	result = omapi_init ();
    442 	if (result != ISC_R_SUCCESS)
    443 		log_fatal ("Can't initialize OMAPI: %s",
    444 			   isc_result_totext (result));
    445 
    446 	/* Set up the OMAPI wrappers for common objects. */
    447 	dhcp_db_objects_setup ();
    448 	/* Set up the OMAPI wrappers for various server database internal
    449 	   objects. */
    450 	dhcp_common_objects_setup ();
    451 
    452 	/* Initially, log errors to stderr as well as to syslogd. */
    453 	openlog (isc_file_basename(progname),
    454 		 DHCP_LOG_OPTIONS, DHCPD_LOG_FACILITY);
    455 
    456 	for (i = 1; i < argc; i++) {
    457 		if (!strcmp (argv [i], "-p")) {
    458 			if (++i == argc)
    459 				usage(use_noarg, argv[i-1]);
    460 			local_port = validate_port (argv [i]);
    461 			log_debug ("binding to user-specified port %d",
    462 			       ntohs (local_port));
    463 		} else if (!strcmp (argv [i], "-f")) {
    464 #ifndef DEBUG
    465 			/* daemon = 0; */
    466 #endif
    467 		} else if (!strcmp (argv [i], "-d")) {
    468 #ifndef DEBUG
    469 			/* daemon = 0; */
    470 #endif
    471 			log_perror = -1;
    472 		} else if (!strcmp (argv [i], "-s")) {
    473 			if (++i == argc)
    474 				usage(use_noarg, argv[i-1]);
    475 			server = argv [i];
    476 #if defined (PARANOIA)
    477 		} else if (!strcmp (argv [i], "-user")) {
    478 			if (++i == argc)
    479 				usage(use_noarg, argv[i-1]);
    480 			set_user = argv [i];
    481 		} else if (!strcmp (argv [i], "-group")) {
    482 			if (++i == argc)
    483 				usage(use_noarg, argv[i-1]);
    484 			set_group = argv [i];
    485 		} else if (!strcmp (argv [i], "-chroot")) {
    486 			if (++i == argc)
    487 				usage(use_noarg, argv[i-1]);
    488 			set_chroot = argv [i];
    489 #endif /* PARANOIA */
    490 		} else if (!strcmp (argv [i], "-cf")) {
    491 			if (++i == argc)
    492 				usage(use_noarg, argv[i-1]);
    493 			path_dhcpd_conf = argv [i];
    494 			have_dhcpd_conf = 1;
    495 		} else if (!strcmp (argv [i], "-lf")) {
    496 			if (++i == argc)
    497 				usage(use_noarg, argv[i-1]);
    498 			path_dhcpd_db = argv [i];
    499 			have_dhcpd_db = 1;
    500 		} else if (!strcmp (argv [i], "-pf")) {
    501 			if (++i == argc)
    502 				usage(use_noarg, argv[i-1]);
    503 			path_dhcpd_pid = argv [i];
    504 			have_dhcpd_pid = 1;
    505 		} else if (!strcmp(argv[i], "--no-pid")) {
    506 			no_pid_file = ISC_TRUE;
    507                 } else if (!strcmp (argv [i], "-t")) {
    508 			/* test configurations only */
    509 #ifndef DEBUG
    510 			/* daemon = 0; */
    511 #endif
    512 			cftest = 1;
    513 			log_perror = -1;
    514                 } else if (!strcmp (argv [i], "-T")) {
    515 			/* test configurations and lease file only */
    516 #ifndef DEBUG
    517 			/* daemon = 0; */
    518 #endif
    519 			cftest = 1;
    520 			lftest = 1;
    521 			log_perror = -1;
    522 		} else if (!strcmp (argv [i], "-q")) {
    523 			quiet = 1;
    524 			quiet_interface_discovery = 1;
    525 #ifdef DHCPv6
    526 		} else if (!strcmp(argv[i], "-4")) {
    527 			if (local_family_set && (local_family != AF_INET)) {
    528 				log_fatal("Server cannot run in both IPv4 and "
    529 					  "IPv6 mode at the same time.");
    530 			}
    531 			local_family = AF_INET;
    532 			local_family_set = 1;
    533 		} else if (!strcmp(argv[i], "-6")) {
    534 			if (local_family_set && (local_family != AF_INET6)) {
    535 				log_fatal("Server cannot run in both IPv4 and "
    536 					  "IPv6 mode at the same time.");
    537 			}
    538 			local_family = AF_INET6;
    539 			local_family_set = 1;
    540 #ifdef DHCP4o6
    541 		} else if (!strcmp(argv[i], "-4o6")) {
    542 			if (++i == argc)
    543 				usage(use_noarg, argv[i-1]);
    544 			dhcp4o6_port = validate_port_pair(argv[i]);
    545 
    546 			log_debug("DHCPv4 over DHCPv6 over ::1 port %d and %d",
    547 				  ntohs(dhcp4o6_port),
    548 				  ntohs(dhcp4o6_port) + 1);
    549 			dhcpv4_over_dhcpv6 = 1;
    550 #endif /* DHCP4o6 */
    551 #endif /* DHCPv6 */
    552 #if defined (TRACING)
    553 		} else if (!strcmp (argv [i], "-tf")) {
    554 			if (++i == argc)
    555 				usage(use_noarg, argv[i-1]);
    556 			traceoutfile = argv [i];
    557 		} else if (!strcmp (argv [i], "-play")) {
    558 			if (++i == argc)
    559 				usage(use_noarg, argv[i-1]);
    560 			traceinfile = argv [i];
    561 			trace_replay_init ();
    562 #endif /* TRACING */
    563 		} else if (argv [i][0] == '-') {
    564 			usage("Unknown command %s", argv[i]);
    565 		} else {
    566 			struct interface_info *tmp =
    567 				(struct interface_info *)0;
    568 			if (strlen(argv[i]) >= sizeof(tmp->name))
    569 				log_fatal("%s: interface name too long "
    570 					  "(is %ld)",
    571 					  argv[i], (long)strlen(argv[i]));
    572 			result = interface_allocate (&tmp, MDL);
    573 			if (result != ISC_R_SUCCESS)
    574 				log_fatal ("Insufficient memory to %s %s: %s",
    575 					   "record interface", argv [i],
    576 					   isc_result_totext (result));
    577 			strcpy (tmp -> name, argv [i]);
    578 			if (interfaces) {
    579 				interface_reference (&tmp -> next,
    580 						     interfaces, MDL);
    581 				interface_dereference (&interfaces, MDL);
    582 			}
    583 			interface_reference (&interfaces, tmp, MDL);
    584 			tmp -> flags = INTERFACE_REQUESTED;
    585 		}
    586 	}
    587 
    588 #if defined(DHCPv6) && defined(DHCP4o6)
    589 	if (dhcpv4_over_dhcpv6) {
    590 		if (!local_family_set)
    591 			log_error("please specify the address family "
    592 				  "with DHPv4 over DHCPv6 [-4|-6].");
    593 		if ((local_family == AF_INET) && (interfaces != NULL))
    594 			log_fatal("DHCPv4 server in DHPv4 over DHCPv6 "
    595 				  "mode with command line specified "
    596 				  "interfaces.");
    597 	}
    598 #endif /* DHCPv6 && DHCP4o6 */
    599 
    600 	if (!have_dhcpd_conf && (s = getenv ("PATH_DHCPD_CONF"))) {
    601 		path_dhcpd_conf = s;
    602 	}
    603 
    604 #ifdef DHCPv6
    605         if (local_family == AF_INET6) {
    606                 /* DHCPv6: override DHCPv4 lease and pid filenames */
    607 	        if (!have_dhcpd_db) {
    608                         if ((s = getenv ("PATH_DHCPD6_DB")))
    609 		                path_dhcpd_db = s;
    610                         else
    611 		                path_dhcpd_db = _PATH_DHCPD6_DB;
    612 	        }
    613 	        if (!have_dhcpd_pid) {
    614                         if ((s = getenv ("PATH_DHCPD6_PID")))
    615 		                path_dhcpd_pid = s;
    616                         else
    617 		                path_dhcpd_pid = _PATH_DHCPD6_PID;
    618 	        }
    619         } else
    620 #endif /* DHCPv6 */
    621         {
    622 	        if (!have_dhcpd_db && (s = getenv ("PATH_DHCPD_DB"))) {
    623 		        path_dhcpd_db = s;
    624 			have_dhcpd_db = 1;
    625 	        }
    626 	        if (!have_dhcpd_pid && (s = getenv ("PATH_DHCPD_PID"))) {
    627 		        path_dhcpd_pid = s;
    628 			have_dhcpd_pid = 1;
    629 	        }
    630         }
    631 
    632         /*
    633          * convert relative path names to absolute, for files that need
    634          * to be reopened after chdir() has been called
    635          */
    636         if (have_dhcpd_db && path_dhcpd_db[0] != '/') {
    637                 path_dhcpd_db = absolute_path(path_dhcpd_db);
    638         }
    639 
    640 	if (!quiet) {
    641 		log_info("%s %s", message, PACKAGE_VERSION);
    642 		log_info (copyright);
    643 		log_info (arr);
    644 		log_info (url);
    645 	} else {
    646 		log_perror = 0;
    647 	}
    648 
    649 #ifndef DEBUG
    650 	/*
    651 	 * We need to fork before we call the context create
    652 	 * call that creates the worker threads!
    653 	 */
    654 	if (daemon) {
    655 		/* First part of becoming a daemon... */
    656 		if ((pid = fork ()) < 0)
    657 			log_fatal ("Can't fork daemon: %m");
    658 		else if (pid)
    659 			exit (0);
    660 	}
    661 #endif
    662 
    663 	/* Set up the isc and dns library managers */
    664 	status = dhcp_context_create(DHCP_CONTEXT_PRE_DB, NULL, NULL);
    665 	if (status != ISC_R_SUCCESS)
    666 		log_fatal("Can't initialize context: %s",
    667 		          isc_result_totext(status));
    668 
    669 	/* Set up the client classification system. */
    670 	classification_setup ();
    671 
    672 #if defined (TRACING)
    673 	trace_init (set_time, MDL);
    674 	if (traceoutfile) {
    675 		result = trace_begin (traceoutfile, MDL);
    676 		if (result != ISC_R_SUCCESS)
    677 			log_fatal ("Unable to begin trace: %s",
    678 				isc_result_totext (result));
    679 	}
    680 	interface_trace_setup ();
    681 	parse_trace_setup ();
    682 	trace_srandom = trace_type_register ("random-seed", (void *)0,
    683 					     trace_seed_input,
    684 					     trace_seed_stop, MDL);
    685 #if defined (NSUPDATE)
    686 	trace_ddns_init();
    687 #endif /* NSUPDATE */
    688 #endif
    689 
    690 #if defined (PARANOIA)
    691 	/* get user and group info if those options were given */
    692 	if (set_user) {
    693 		struct passwd *tmp_pwd;
    694 
    695 		if (geteuid())
    696 			log_fatal ("you must be root to set user");
    697 
    698 		if (!(tmp_pwd = getpwnam(set_user)))
    699 			log_fatal ("no such user: %s", set_user);
    700 
    701 		set_uid = tmp_pwd->pw_uid;
    702 
    703 		/* use the user's group as the default gid */
    704 		if (!set_group)
    705 			set_gid = tmp_pwd->pw_gid;
    706 	}
    707 
    708 	if (set_group) {
    709 /* get around the ISC declaration of group */
    710 #define group real_group
    711 		struct group *tmp_grp;
    712 
    713 		if (geteuid())
    714 			log_fatal ("you must be root to set group");
    715 
    716 		if (!(tmp_grp = getgrnam(set_group)))
    717 			log_fatal ("no such group: %s", set_group);
    718 
    719 		set_gid = tmp_grp->gr_gid;
    720 #undef group
    721 	}
    722 
    723 #  if defined (EARLY_CHROOT)
    724 	if (set_chroot) setup_chroot (set_chroot);
    725 #  endif /* EARLY_CHROOT */
    726 #endif /* PARANOIA */
    727 
    728 	/* Default to the DHCP/BOOTP port. */
    729 	if (!local_port)
    730 	{
    731 		if ((s = getenv ("DHCPD_PORT"))) {
    732 			local_port = validate_port (s);
    733 			log_debug ("binding to environment-specified port %d",
    734 				   ntohs (local_port));
    735 		} else {
    736 			if (local_family == AF_INET) {
    737 				ent = getservbyname("dhcp", "udp");
    738 				if (ent == NULL) {
    739 					local_port = htons(67);
    740 				} else {
    741 					local_port = ent->s_port;
    742 				}
    743 			} else {
    744 				/* INSIST(local_family == AF_INET6); */
    745 				ent = getservbyname("dhcpv6-server", "udp");
    746 				if (ent == NULL) {
    747 					local_port = htons(547);
    748 				} else {
    749 					local_port = ent->s_port;
    750 				}
    751 			}
    752 #ifndef __CYGWIN32__ /* XXX */
    753 			endservent ();
    754 #endif
    755 		}
    756 	}
    757 
    758   	if (local_family == AF_INET) {
    759 		remote_port = htons(ntohs(local_port) + 1);
    760 	} else {
    761 		/* INSIST(local_family == AF_INET6); */
    762 		ent = getservbyname("dhcpv6-client", "udp");
    763 		if (ent == NULL) {
    764 			remote_port = htons(546);
    765 		} else {
    766 			remote_port = ent->s_port;
    767 		}
    768 	}
    769 
    770 	if (server) {
    771 		if (local_family != AF_INET) {
    772 			log_fatal("You can only specify address to send "
    773 			          "replies to when running an IPv4 server.");
    774 		}
    775 		if (!inet_aton (server, &limited_broadcast)) {
    776 			struct hostent *he;
    777 			he = gethostbyname (server);
    778 			if (he) {
    779 				memcpy (&limited_broadcast,
    780 					he -> h_addr_list [0],
    781 					sizeof limited_broadcast);
    782 			} else
    783 				limited_broadcast.s_addr = INADDR_BROADCAST;
    784 		}
    785 	} else {
    786 		limited_broadcast.s_addr = INADDR_BROADCAST;
    787 	}
    788 
    789 	/* Get the current time... */
    790 	gettimeofday(&cur_tv, NULL);
    791 
    792 	/* Set up the initial dhcp option universe. */
    793 	initialize_common_option_spaces ();
    794 	initialize_server_option_spaces ();
    795 
    796 	/* Add the ddns update style enumeration prior to parsing. */
    797 	add_enumeration (&ddns_styles);
    798 	add_enumeration (&syslog_enum);
    799 #if defined (LDAP_CONFIGURATION)
    800 	add_enumeration (&ldap_methods);
    801 #if defined (LDAP_USE_SSL)
    802 	add_enumeration (&ldap_ssl_usage_enum);
    803 	add_enumeration (&ldap_tls_reqcert_enum);
    804 	add_enumeration (&ldap_tls_crlcheck_enum);
    805 #endif
    806 #endif
    807 
    808 	if (!group_allocate (&root_group, MDL))
    809 		log_fatal ("Can't allocate root group!");
    810 	root_group -> authoritative = 0;
    811 
    812 	/* Set up various hooks. */
    813 	dhcp_interface_setup_hook = dhcpd_interface_setup_hook;
    814 	bootp_packet_handler = do_packet;
    815 #ifdef DHCPv6
    816 	add_enumeration (&prefix_length_modes);
    817 	dhcpv6_packet_handler = do_packet6;
    818 #endif /* DHCPv6 */
    819 
    820 #if defined (NSUPDATE)
    821 	/* Set up the standard name service updater routine. */
    822 	parse = NULL;
    823 	status = new_parse(&parse, -1, std_nsupdate, sizeof(std_nsupdate) - 1,
    824 			    "standard name service update routine", 0);
    825 	if (status != ISC_R_SUCCESS)
    826 		log_fatal ("can't begin parsing name service updater!");
    827 
    828 	if (parse != NULL) {
    829 		lose = 0;
    830 		if (!(parse_executable_statements(&root_group->statements,
    831 						  parse, &lose, context_any))) {
    832 			end_parse(&parse);
    833 			log_fatal("can't parse standard name service updater!");
    834 		}
    835 		end_parse(&parse);
    836 	}
    837 #endif
    838 
    839 	/* Initialize icmp support... */
    840 	if (!cftest && !lftest)
    841 		icmp_startup (1, lease_pinged);
    842 
    843 #if defined (TRACING)
    844 	if (traceinfile) {
    845 	    if (!have_dhcpd_db) {
    846 		    log_error ("%s", "");
    847 		    log_error ("** You must specify a lease file with -lf.");
    848 		    log_error ("   Dhcpd will not overwrite your default");
    849 		    log_fatal ("   lease file when playing back a trace. **");
    850 	    }
    851 	    trace_file_replay (traceinfile);
    852 
    853 #if defined (DEBUG_MEMORY_LEAKAGE) && \
    854                 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
    855             free_everything ();
    856             omapi_print_dmalloc_usage_by_caller ();
    857 #endif
    858 
    859 	    exit (0);
    860 	}
    861 #endif
    862 
    863 #ifdef DHCPv6
    864 	/* set up DHCPv6 hashes */
    865 	if (!ia_new_hash(&ia_na_active, DEFAULT_HASH_SIZE, MDL)) {
    866 		log_fatal("Out of memory creating hash for active IA_NA.");
    867 	}
    868 	if (!ia_new_hash(&ia_ta_active, DEFAULT_HASH_SIZE, MDL)) {
    869 		log_fatal("Out of memory creating hash for active IA_TA.");
    870 	}
    871 	if (!ia_new_hash(&ia_pd_active, DEFAULT_HASH_SIZE, MDL)) {
    872 		log_fatal("Out of memory creating hash for active IA_PD.");
    873 	}
    874 #endif /* DHCPv6 */
    875 
    876 	/* Read the dhcpd.conf file... */
    877 	if (readconf () != ISC_R_SUCCESS)
    878 		log_fatal ("Configuration file errors encountered -- exiting");
    879 
    880 	postconf_initialization (quiet);
    881 
    882 #if defined (FAILOVER_PROTOCOL)
    883 	dhcp_failover_sanity_check();
    884 #endif
    885 
    886 #if defined(DHCPv6) && defined(DHCP4o6)
    887 	if (dhcpv4_over_dhcpv6) {
    888 		if ((local_family == AF_INET) && (interfaces != NULL))
    889 			log_fatal("DHCPv4 server in DHPv4 over DHCPv6 "
    890 				  "mode with config file specified "
    891 				  "interfaces.");
    892 	}
    893 #endif /* DHCPv6 && DHCP4o6 */
    894 
    895 #if defined (PARANOIA) && !defined (EARLY_CHROOT)
    896 	if (set_chroot) setup_chroot (set_chroot);
    897 #endif /* PARANOIA && !EARLY_CHROOT */
    898 
    899 #ifdef DHCPv6
    900 	/* log info about ipv6_ponds with large address ranges */
    901 	report_jumbo_ranges();
    902 #endif
    903 
    904         /* test option should cause an early exit */
    905 	if (cftest && !lftest) {
    906  		exit(0);
    907 	}
    908 
    909 	/*
    910 	 * First part of dealing with pid files.  Check to see if
    911 	 * we should continue running or not.  We run if:
    912 	 * - we are testing the lease file out
    913 	 * - we don't have a pid file to check
    914 	 * - there is no other process running
    915 	 */
    916 	if ((lftest == 0) && (no_pid_file == ISC_FALSE)) {
    917 		/*Read previous pid file. */
    918 		if ((i = open(path_dhcpd_pid, O_RDONLY)) >= 0) {
    919 			status = read(i, pbuf, (sizeof pbuf) - 1);
    920 			close(i);
    921 			if (status > 0) {
    922 				pbuf[status] = 0;
    923 				pid = atoi(pbuf);
    924 
    925 				/*
    926 				 * If there was a previous server process and
    927 				 * it is still running, abort
    928 				 */
    929 				if (!pid ||
    930 				    (pid != getpid() && kill(pid, 0) == 0))
    931 					log_fatal("There's already a "
    932 						  "DHCP server running.");
    933 			}
    934 		}
    935 	}
    936 
    937 	group_write_hook = group_writer;
    938 
    939 	/* Start up the database... */
    940 	db_startup (lftest);
    941 
    942 	if (lftest)
    943 		exit (0);
    944 
    945 	/* Discover all the network interfaces and initialize them. */
    946 #if defined(DHCPv6) && defined(DHCP4o6)
    947 	if (dhcpv4_over_dhcpv6) {
    948 		int real_family = local_family;
    949 		local_family = AF_INET6;
    950 		/* The DHCPv4 side of DHCPv4-over-DHCPv6 service
    951 		   uses a specific discovery which doesn't register
    952 		   DHCPv6 sockets. */
    953 		if (real_family == AF_INET)
    954 			discover_interfaces(DISCOVER_SERVER46);
    955 		else
    956 			discover_interfaces(DISCOVER_SERVER);
    957 		local_family = real_family;
    958 	} else
    959 #endif /* DHCPv6 && DHCP4o6 */
    960 	discover_interfaces(DISCOVER_SERVER);
    961 
    962 #ifdef DHCPv6
    963 	/*
    964 	 * Remove addresses from our pools that we should not issue
    965 	 * to clients.
    966 	 *
    967 	 * We currently have no support for this in IPv4. It is not
    968 	 * as important in IPv4, as making pools with ranges that
    969 	 * leave out interfaces and hosts is fairly straightforward
    970 	 * using range notation, but not so handy with CIDR notation.
    971 	 */
    972 	if (local_family == AF_INET6) {
    973 		mark_hosts_unavailable();
    974 		mark_phosts_unavailable();
    975 		mark_interfaces_unavailable();
    976 	}
    977 #endif /* DHCPv6 */
    978 
    979 	/* Make up a seed for the random number generator from current
    980 	   time plus the sum of the last four bytes of each
    981 	   interface's hardware address interpreted as an integer.
    982 	   Not much entropy, but we're booting, so we're not likely to
    983 	   find anything better. */
    984 	seed = 0;
    985 	for (ip = interfaces; ip; ip = ip -> next) {
    986 		int junk;
    987 		memcpy (&junk,
    988 			&ip -> hw_address.hbuf [ip -> hw_address.hlen -
    989 					       sizeof seed], sizeof seed);
    990 		seed += junk;
    991 	}
    992 	srandom (seed + cur_time);
    993 #if defined (TRACING)
    994 	trace_seed_stash (trace_srandom, seed + cur_time);
    995 #endif
    996 	postdb_startup ();
    997 
    998 #ifdef DHCPv6
    999 	/*
   1000 	 * Set server DHCPv6 identifier - we go in order:
   1001 	 * dhcp6.server-id in the config file
   1002 	 * server-duid from the lease file
   1003 	 * server-duid from the config file (the config file is read first
   1004 	 * and the lease file overwrites the config file information)
   1005 	 * generate a new one from the interface hardware addresses.
   1006 	 * In all cases we write it out to the lease file.
   1007 	 * See dhcpv6.c for discussion of setting DUID.
   1008 	 */
   1009 	if ((set_server_duid_from_option() != ISC_R_SUCCESS) &&
   1010 	    (!server_duid_isset()) &&
   1011 	    (generate_new_server_duid() != ISC_R_SUCCESS)) {
   1012 		log_fatal("Unable to set server identifier.");
   1013 	}
   1014 	write_server_duid();
   1015 #ifdef DHCP4o6
   1016 	if (dhcpv4_over_dhcpv6)
   1017 		dhcp4o6_setup(dhcp4o6_port);
   1018 #endif /* DHCP4o6 */
   1019 #endif /* DHCPv6 */
   1020 
   1021 #ifndef DEBUG
   1022 	/*
   1023 	 * Second part of dealing with pid files.  Now
   1024 	 * that we have forked we can write our pid if
   1025 	 * appropriate.
   1026 	 */
   1027 	if (no_pid_file == ISC_FALSE) {
   1028 		i = open(path_dhcpd_pid, O_WRONLY|O_CREAT|O_TRUNC, 0644);
   1029 		if (i >= 0) {
   1030 			sprintf(pbuf, "%d\n", (int) getpid());
   1031 			IGNORE_RET(write(i, pbuf, strlen(pbuf)));
   1032 			close(i);
   1033 		} else {
   1034 			log_error("Can't create PID file %s: %m.",
   1035 				  path_dhcpd_pid);
   1036 		}
   1037 	}
   1038 
   1039 #if defined (PARANOIA)
   1040 	/* change uid to the specified one */
   1041 
   1042 	if (set_gid) {
   1043 		if (setgroups (0, (void *)0))
   1044 			log_fatal ("setgroups: %m");
   1045 		if (setgid (set_gid))
   1046 			log_fatal ("setgid(%d): %m", (int) set_gid);
   1047 	}
   1048 
   1049 	if (set_uid) {
   1050 		if (setuid (set_uid))
   1051 			log_fatal ("setuid(%d): %m", (int) set_uid);
   1052 	}
   1053 #endif /* PARANOIA */
   1054 
   1055 	/* If we were requested to log to stdout on the command line,
   1056 	   keep doing so; otherwise, stop. */
   1057 	if (log_perror == -1)
   1058 		log_perror = 1;
   1059 	else
   1060 		log_perror = 0;
   1061 
   1062 	if (daemon) {
   1063 		if (dfd[0] != -1 && dfd[1] != -1) {
   1064 			char buf = 0;
   1065 
   1066 			if (write(dfd[1], &buf, 1) != 1)
   1067 				log_fatal("write to parent: %m");
   1068 			(void) close(dfd[1]);
   1069 			dfd[0] = dfd[1] = -1;
   1070 		}
   1071 
   1072 		/* Become session leader and get pid... */
   1073 		(void) setsid();
   1074 
   1075                 /* Close standard I/O descriptors. */
   1076                 (void) close(0);
   1077                 (void) close(1);
   1078                 (void) close(2);
   1079 
   1080                 /* Reopen them on /dev/null. */
   1081                 (void) open("/dev/null", O_RDWR);
   1082                 (void) open("/dev/null", O_RDWR);
   1083                 (void) open("/dev/null", O_RDWR);
   1084                 log_perror = 0; /* No sense logging to /dev/null. */
   1085 
   1086        		IGNORE_RET (chdir("/"));
   1087 	}
   1088 #endif /* !DEBUG */
   1089 
   1090 #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \
   1091 		defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
   1092 	dmalloc_cutoff_generation = dmalloc_generation;
   1093 	dmalloc_longterm = dmalloc_outstanding;
   1094 	dmalloc_outstanding = 0;
   1095 #endif
   1096 
   1097 	omapi_set_int_value ((omapi_object_t *)dhcp_control_object,
   1098 			     (omapi_object_t *)0, "state", server_running);
   1099 
   1100 #if defined(ENABLE_GENTLE_SHUTDOWN)
   1101 	/* no signal handlers until we deal with the side effects */
   1102         /* install signal handlers */
   1103 	signal(SIGINT, dhcp_signal_handler);   /* control-c */
   1104 	signal(SIGTERM, dhcp_signal_handler);  /* kill */
   1105 #endif
   1106 
   1107 	/* Log that we are about to start working */
   1108 	log_info("Server starting service.");
   1109 
   1110 	/*
   1111 	 * Receive packets and dispatch them...
   1112 	 * dispatch() will never return.
   1113 	 */
   1114 	dispatch ();
   1115 
   1116 	/* Let's return status code */
   1117 	return 0;
   1118 }
   1119 #endif /* !UNIT_TEST */
   1120 
   1121 void postconf_initialization (int quiet)
   1122 {
   1123 	struct option_state *options = NULL;
   1124 	struct data_string db;
   1125 	struct option_cache *oc;
   1126 	char *s;
   1127 	isc_result_t result;
   1128 	int tmp;
   1129 #if defined (NSUPDATE)
   1130 	struct in_addr  local4, *local4_ptr = NULL;
   1131 	struct in6_addr local6, *local6_ptr = NULL;
   1132 #endif
   1133 
   1134 	/* Now try to get the lease file name. */
   1135 	option_state_allocate(&options, MDL);
   1136 
   1137 	execute_statements_in_scope(NULL, NULL, NULL, NULL, NULL,
   1138 				    options, &global_scope, root_group,
   1139 				    NULL, NULL);
   1140 	memset(&db, 0, sizeof db);
   1141 	oc = lookup_option(&server_universe, options, SV_LEASE_FILE_NAME);
   1142 	if (oc &&
   1143 	    evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
   1144 				  &global_scope, oc, MDL)) {
   1145 		s = dmalloc(db.len + 1, MDL);
   1146 		if (!s)
   1147 			log_fatal("no memory for lease db filename.");
   1148 		memcpy(s, db.data, db.len);
   1149 		s[db.len] = 0;
   1150 		data_string_forget(&db, MDL);
   1151 		path_dhcpd_db = s;
   1152 	}
   1153 
   1154 	oc = lookup_option(&server_universe, options, SV_PID_FILE_NAME);
   1155 	if (oc &&
   1156 	    evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
   1157 				  &global_scope, oc, MDL)) {
   1158 		s = dmalloc(db.len + 1, MDL);
   1159 		if (!s)
   1160 			log_fatal("no memory for pid filename.");
   1161 		memcpy(s, db.data, db.len);
   1162 		s[db.len] = 0;
   1163 		data_string_forget(&db, MDL);
   1164 		path_dhcpd_pid = s;
   1165 	}
   1166 
   1167 #ifdef DHCPv6
   1168         if (local_family == AF_INET6) {
   1169                 /*
   1170                  * Override lease file name with dhcpv6 lease file name,
   1171                  * if it was set; then, do the same with the pid file name
   1172                  */
   1173                 oc = lookup_option(&server_universe, options,
   1174                                    SV_DHCPV6_LEASE_FILE_NAME);
   1175                 if (oc &&
   1176                     evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
   1177 					  &global_scope, oc, MDL)) {
   1178                         s = dmalloc(db.len + 1, MDL);
   1179                         if (!s)
   1180                                 log_fatal("no memory for lease db filename.");
   1181                         memcpy(s, db.data, db.len);
   1182                         s[db.len] = 0;
   1183                         data_string_forget(&db, MDL);
   1184                         path_dhcpd_db = s;
   1185                 }
   1186 
   1187                 oc = lookup_option(&server_universe, options,
   1188                                    SV_DHCPV6_PID_FILE_NAME);
   1189                 if (oc &&
   1190                     evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
   1191 					  &global_scope, oc, MDL)) {
   1192                         s = dmalloc(db.len + 1, MDL);
   1193                         if (!s)
   1194                                 log_fatal("no memory for pid filename.");
   1195                         memcpy(s, db.data, db.len);
   1196                         s[db.len] = 0;
   1197                         data_string_forget(&db, MDL);
   1198                         path_dhcpd_pid = s;
   1199                 }
   1200 
   1201 		oc = lookup_option(&server_universe, options,
   1202 				   SV_LOCAL_ADDRESS6);
   1203 		if (oc &&
   1204 		    evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
   1205 					  &global_scope, oc, MDL)) {
   1206 			if (db.len == 16) {
   1207 				memcpy(&local_address6, db.data, 16);
   1208 			} else
   1209 				log_fatal("invalid local address "
   1210 					  "data length");
   1211 			data_string_forget(&db, MDL);
   1212 		}
   1213 
   1214 		oc = lookup_option(&server_universe, options,
   1215 				   SV_BIND_LOCAL_ADDRESS6);
   1216 		if (oc &&
   1217 		    evaluate_boolean_option_cache(NULL, NULL, NULL,
   1218 						  NULL, options, NULL,
   1219 						  &global_scope, oc, MDL)) {
   1220 			bind_local_address6 = 1;
   1221 		}
   1222 
   1223         }
   1224 #endif /* DHCPv6 */
   1225 
   1226 	omapi_port = -1;
   1227 	oc = lookup_option(&server_universe, options, SV_OMAPI_PORT);
   1228 	if (oc &&
   1229 	    evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
   1230 				  &global_scope, oc, MDL)) {
   1231 		if (db.len == 2) {
   1232 			omapi_port = getUShort(db.data);
   1233 		} else
   1234 			log_fatal("invalid omapi port data length");
   1235 		data_string_forget(&db, MDL);
   1236 	}
   1237 
   1238 	oc = lookup_option(&server_universe, options, SV_OMAPI_KEY);
   1239 	if (oc &&
   1240 	    evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
   1241 				  &global_scope, oc, MDL)) {
   1242 		s = dmalloc(db.len + 1, MDL);
   1243 		if (!s)
   1244 			log_fatal("no memory for OMAPI key filename.");
   1245 		memcpy(s, db.data, db.len);
   1246 		s[db.len] = 0;
   1247 		data_string_forget(&db, MDL);
   1248 		result = omapi_auth_key_lookup_name(&omapi_key, s);
   1249 		dfree(s, MDL);
   1250 		if (result != ISC_R_SUCCESS)
   1251 			log_fatal("OMAPI key %s: %s",
   1252 				  s, isc_result_totext (result));
   1253 	}
   1254 
   1255 	oc = lookup_option(&server_universe, options, SV_LOCAL_PORT);
   1256 	if (oc &&
   1257 	    evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
   1258 				  &global_scope, oc, MDL)) {
   1259 		if (db.len == 2) {
   1260 			local_port = htons(getUShort (db.data));
   1261 		} else
   1262 			log_fatal("invalid local port data length");
   1263 		data_string_forget(&db, MDL);
   1264 	}
   1265 
   1266 	oc = lookup_option(&server_universe, options, SV_REMOTE_PORT);
   1267 	if (oc &&
   1268 	    evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
   1269 				  &global_scope, oc, MDL)) {
   1270 		if (db.len == 2) {
   1271 			remote_port = htons(getUShort (db.data));
   1272 		} else
   1273 			log_fatal("invalid remote port data length");
   1274 		data_string_forget(&db, MDL);
   1275 	}
   1276 
   1277 	oc = lookup_option(&server_universe, options,
   1278 			   SV_LIMITED_BROADCAST_ADDRESS);
   1279 	if (oc &&
   1280 	    evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
   1281 				  &global_scope, oc, MDL)) {
   1282 		if (db.len == 4) {
   1283 			memcpy(&limited_broadcast, db.data, 4);
   1284 		} else
   1285 			log_fatal("invalid broadcast address data length");
   1286 		data_string_forget(&db, MDL);
   1287 	}
   1288 
   1289 	oc = lookup_option(&server_universe, options, SV_LOCAL_ADDRESS);
   1290 	if (oc &&
   1291 	    evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
   1292 				  &global_scope, oc, MDL)) {
   1293 		if (db.len == 4) {
   1294 			memcpy(&local_address, db.data, 4);
   1295 		} else
   1296 			log_fatal("invalid local address data length");
   1297 		data_string_forget(&db, MDL);
   1298 	}
   1299 
   1300 	oc = lookup_option(&server_universe, options, SV_DDNS_UPDATE_STYLE);
   1301 	if (oc) {
   1302 		if (evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
   1303 					  &global_scope, oc, MDL)) {
   1304 			if (db.len == 1) {
   1305 				ddns_update_style = db.data[0];
   1306 			} else
   1307 				log_fatal("invalid dns update type");
   1308 			data_string_forget(&db, MDL);
   1309 		}
   1310 	} else {
   1311 		ddns_update_style = DDNS_UPDATE_STYLE_NONE;
   1312 	}
   1313 #if defined (NSUPDATE)
   1314 	/* We no longer support ad_hoc, tell the user */
   1315 	if (ddns_update_style == DDNS_UPDATE_STYLE_AD_HOC) {
   1316 		log_fatal("ddns-update-style ad_hoc no longer supported");
   1317 	}
   1318 
   1319 	oc = lookup_option(&server_universe, options, SV_DDNS_LOCAL_ADDRESS4);
   1320 	if (oc) {
   1321 		if (evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
   1322 					  &global_scope, oc, MDL)) {
   1323 			if (db.len == 4) {
   1324 				memcpy(&local4, db.data, 4);
   1325 				local4_ptr = &local4;
   1326 			}
   1327 			data_string_forget(&db, MDL);
   1328 		}
   1329 	}
   1330 
   1331 	oc = lookup_option(&server_universe, options, SV_DDNS_LOCAL_ADDRESS6);
   1332 	if (oc) {
   1333 		if (evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
   1334 					  &global_scope, oc, MDL)) {
   1335 			if (db.len == 16) {
   1336 				memcpy(&local6, db.data, 16);
   1337 				local6_ptr = &local6;
   1338 			}
   1339 			data_string_forget(&db, MDL);
   1340 		}
   1341 	}
   1342 
   1343 	/* Don't init DNS client if update style is none. This avoids
   1344 	 * listening ports that aren't needed.  We don't use ddns-udpates
   1345 	 * as that has multiple levels of scope. */
   1346 	if (ddns_update_style != DDNS_UPDATE_STYLE_NONE) {
   1347 		if (dhcp_context_create(DHCP_CONTEXT_POST_DB,
   1348 					local4_ptr, local6_ptr)
   1349 			!= ISC_R_SUCCESS) {
   1350 			log_fatal("Unable to complete ddns initialization");
   1351 		}
   1352 	}
   1353 
   1354 	/* Set the conflict detection flag mask based on globally
   1355 	 * defined DDNS configuration params.  This mask should be
   1356 	 * to init ddns_cb::flags before for every DDNS transaction. */
   1357 	ddns_conflict_mask = get_conflict_mask(options);
   1358 
   1359 #else
   1360 	/* If we don't have support for updates compiled in tell the user */
   1361 	if (ddns_update_style != DDNS_UPDATE_STYLE_NONE) {
   1362 		log_fatal("Support for ddns-update-style not compiled in");
   1363 	}
   1364 #endif
   1365 
   1366 	if (!quiet) {
   1367 		log_info ("Config file: %s", path_dhcpd_conf);
   1368 		log_info ("Database file: %s", path_dhcpd_db);
   1369 		log_info ("PID file: %s", path_dhcpd_pid);
   1370 	}
   1371 
   1372 	oc = lookup_option(&server_universe, options, SV_LOG_FACILITY);
   1373 	if (oc) {
   1374 		if (evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
   1375 					  &global_scope, oc, MDL)) {
   1376 			if (db.len == 1) {
   1377 				closelog ();
   1378 				openlog(isc_file_basename(progname),
   1379 					DHCP_LOG_OPTIONS, db.data[0]);
   1380 				/* Log the startup banner into the new
   1381 				   log file. */
   1382 				/* Don't log to stderr twice. */
   1383 				tmp = log_perror;
   1384 				log_perror = 0;
   1385 				log_info("%s %s", message, PACKAGE_VERSION);
   1386 				log_info(copyright);
   1387 				log_info(arr);
   1388 				log_info(url);
   1389 				log_perror = tmp;
   1390 			} else
   1391 				log_fatal("invalid log facility");
   1392 			data_string_forget(&db, MDL);
   1393 		}
   1394 	}
   1395 
   1396 #if defined(DELAYED_ACK)
   1397 	oc = lookup_option(&server_universe, options, SV_DELAYED_ACK);
   1398 	if (oc &&
   1399 	    evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
   1400 				  &global_scope, oc, MDL)) {
   1401 		if (db.len == 2) {
   1402 			max_outstanding_acks = htons(getUShort(db.data));
   1403 		} else {
   1404 			log_fatal("invalid max delayed ACK count ");
   1405 		}
   1406 		data_string_forget(&db, MDL);
   1407 	}
   1408 #if defined(DHCP4o6)
   1409 	/* Delayed acks and DHCPv4-over-DHCPv6 are incompatible */
   1410 	if (dhcpv4_over_dhcpv6) {
   1411 		if (max_outstanding_acks > 0) {
   1412 			log_debug("DHCP4o6 enabled, "
   1413 				  "setting delayed-ack to zero (incompatible)");
   1414 		}
   1415 
   1416 		max_outstanding_acks = 0;
   1417 	}
   1418 #endif
   1419 
   1420 	oc = lookup_option(&server_universe, options, SV_MAX_ACK_DELAY);
   1421 	if (oc &&
   1422 	    evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
   1423 				  &global_scope, oc, MDL)) {
   1424 		u_int32_t timeval;
   1425 
   1426 		if (db.len != 4)
   1427 			log_fatal("invalid max ack delay configuration");
   1428 
   1429 		timeval = getULong(db.data);
   1430 		max_ack_delay_secs  = timeval / 1000000;
   1431 		max_ack_delay_usecs = timeval % 1000000;
   1432 
   1433 		data_string_forget(&db, MDL);
   1434 	}
   1435 #endif
   1436 
   1437 	oc = lookup_option(&server_universe, options, SV_DONT_USE_FSYNC);
   1438 	if ((oc != NULL) &&
   1439 	    evaluate_boolean_option_cache(NULL, NULL, NULL, NULL, options, NULL,
   1440 					  &global_scope, oc, MDL)) {
   1441 		dont_use_fsync = 1;
   1442 		log_error("Not using fsync() to flush lease writes");
   1443 	}
   1444 
   1445        oc = lookup_option(&server_universe, options, SV_SERVER_ID_CHECK);
   1446        if ((oc != NULL) &&
   1447 	   evaluate_boolean_option_cache(NULL, NULL, NULL, NULL, options, NULL,
   1448 					 &global_scope, oc, MDL)) {
   1449 		log_info("Setting server-id-check true");
   1450 		server_id_check = 1;
   1451 	}
   1452 
   1453 #ifdef DHCPv6
   1454 	oc = lookup_option(&server_universe, options, SV_PREFIX_LEN_MODE);
   1455 	if ((oc != NULL) &&
   1456 	    evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
   1457 					  &global_scope, oc, MDL)) {
   1458 		if (db.len == 1) {
   1459 			prefix_length_mode = db.data[0];
   1460 		} else {
   1461 			log_fatal("invalid prefix-len-mode");
   1462 		}
   1463 
   1464 		data_string_forget(&db, MDL);
   1465 	}
   1466 #endif
   1467 
   1468 	// Set global abandon-lease-time option.
   1469 	oc = lookup_option (&server_universe, options, SV_ABANDON_LEASE_TIME);
   1470 	if ((oc != NULL) &&
   1471 	    evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
   1472 				  &global_scope, oc, MDL)) {
   1473 		if (db.len == sizeof (u_int32_t)) {
   1474 			abandon_lease_time = getULong (db.data);
   1475 		} else {
   1476 			log_fatal("invalid abandon-lease-time");
   1477 		}
   1478 
   1479 		data_string_forget (&db, MDL);
   1480         }
   1481 
   1482 #if defined (FAILOVER_PROTOCOL)
   1483        oc = lookup_option(&server_universe, options, SV_CHECK_SECS_BYTE_ORDER);
   1484        if ((oc != NULL) &&
   1485 	   evaluate_boolean_option_cache(NULL, NULL, NULL, NULL, options, NULL,
   1486 					 &global_scope, oc, MDL)) {
   1487 		check_secs_byte_order = 1;
   1488 	}
   1489 #endif
   1490 
   1491 #ifdef EUI_64
   1492        oc = lookup_option(&server_universe, options, SV_PERSIST_EUI_64_LEASES);
   1493        if (oc != NULL) {
   1494 		persist_eui64 = evaluate_boolean_option_cache(NULL, NULL, NULL,
   1495 							      NULL, options,
   1496 							      NULL,
   1497 							      &global_scope,
   1498 							      oc, MDL);
   1499 	}
   1500 
   1501 	if (!persist_eui64) {
   1502 		log_info("EUI64 leases will not be written to lease file");
   1503 	}
   1504 #endif
   1505 
   1506 #ifdef DHCPv6
   1507 	oc = lookup_option(&server_universe, options, SV_RELEASE_ON_ROAM);
   1508 	if (oc != NULL) {
   1509 		do_release_on_roam =
   1510 			evaluate_boolean_option_cache(NULL, NULL, NULL, NULL,
   1511 						      options, NULL,
   1512 						      &global_scope, oc, MDL);
   1513 	}
   1514 #endif
   1515 
   1516 #if defined (BINARY_LEASES)
   1517 	if (local_family == AF_INET) {
   1518 		log_info("Source compiled to use binary-leases");
   1519 	}
   1520 #endif
   1521 
   1522 	/* Don't need the options anymore. */
   1523 	option_state_dereference(&options, MDL);
   1524 }
   1525 
   1526 void postdb_startup (void)
   1527 {
   1528 	/* Initialize the omapi listener state. */
   1529 	if (omapi_port != -1) {
   1530 		omapi_listener_start (0);
   1531 	}
   1532 
   1533 #if defined (FAILOVER_PROTOCOL)
   1534 	/* Initialize the failover listener state. */
   1535 	dhcp_failover_startup ();
   1536 #endif
   1537 
   1538 	/*
   1539 	 * Begin our lease timeout background task.
   1540 	 */
   1541 	schedule_all_ipv6_lease_timeouts();
   1542 }
   1543 
   1544 void lease_pinged (from, packet, length)
   1545 	struct iaddr from;
   1546 	u_int8_t *packet;
   1547 	int length;
   1548 {
   1549 	struct lease *lp;
   1550 
   1551 	/* Don't try to look up a pinged lease if we aren't trying to
   1552 	   ping one - otherwise somebody could easily make us churn by
   1553 	   just forging repeated ICMP EchoReply packets for us to look
   1554 	   up. */
   1555 	if (!outstanding_pings)
   1556 		return;
   1557 
   1558 	lp = (struct lease *)0;
   1559 	if (!find_lease_by_ip_addr (&lp, from, MDL)) {
   1560 		log_debug ("unexpected ICMP Echo Reply from %s",
   1561 			   piaddr (from));
   1562 		return;
   1563 	}
   1564 
   1565 	if (!lp -> state) {
   1566 #if defined (FAILOVER_PROTOCOL)
   1567 		if (!lp -> pool ||
   1568 		    !lp -> pool -> failover_peer)
   1569 #endif
   1570 			log_debug ("ICMP Echo Reply for %s late or spurious.",
   1571 				   piaddr (from));
   1572 		goto out;
   1573 	}
   1574 
   1575 	if (lp -> ends > cur_time) {
   1576 		log_debug ("ICMP Echo reply while lease %s valid.",
   1577 			   piaddr (from));
   1578 	}
   1579 
   1580 	/* At this point it looks like we pinged a lease and got a
   1581 	   response, which shouldn't have happened. */
   1582 	data_string_forget (&lp -> state -> parameter_request_list, MDL);
   1583 	free_lease_state (lp -> state, MDL);
   1584 	lp -> state = (struct lease_state *)0;
   1585 
   1586 	abandon_lease (lp, "pinged before offer");
   1587 	cancel_timeout (lease_ping_timeout, lp);
   1588 	--outstanding_pings;
   1589       out:
   1590 	lease_dereference (&lp, MDL);
   1591 }
   1592 
   1593 void lease_ping_timeout (vlp)
   1594 	void *vlp;
   1595 {
   1596 	struct lease *lp = vlp;
   1597 
   1598 #if defined (DEBUG_MEMORY_LEAKAGE)
   1599 	unsigned long previous_outstanding = dmalloc_outstanding;
   1600 #endif
   1601 
   1602 	--outstanding_pings;
   1603 	dhcp_reply (lp);
   1604 
   1605 #if defined (DEBUG_MEMORY_LEAKAGE)
   1606 	log_info ("generation %ld: %ld new, %ld outstanding, %ld long-term",
   1607 		  dmalloc_generation,
   1608 		  dmalloc_outstanding - previous_outstanding,
   1609 		  dmalloc_outstanding, dmalloc_longterm);
   1610 #endif
   1611 #if defined (DEBUG_MEMORY_LEAKAGE)
   1612 	dmalloc_dump_outstanding ();
   1613 #endif
   1614 }
   1615 
   1616 int dhcpd_interface_setup_hook (struct interface_info *ip, struct iaddr *ia)
   1617 {
   1618 	struct subnet *subnet;
   1619 	struct shared_network *share;
   1620 	isc_result_t status;
   1621 
   1622 	/* Special case for fallback network - not sure why this is
   1623 	   necessary. */
   1624 	if (!ia) {
   1625 		const char *fnn = "fallback-net";
   1626 		status = shared_network_allocate (&ip -> shared_network, MDL);
   1627 		if (status != ISC_R_SUCCESS)
   1628 			log_fatal ("No memory for shared subnet: %s",
   1629 				   isc_result_totext (status));
   1630 		ip -> shared_network -> name = dmalloc (strlen (fnn) + 1, MDL);
   1631 		if (!ip -> shared_network -> name)
   1632 			log_fatal("no memory for shared network");
   1633 		strcpy (ip -> shared_network -> name, fnn);
   1634 		return 1;
   1635 	}
   1636 
   1637 	/* If there's a registered subnet for this address,
   1638 	   connect it together... */
   1639 	subnet = (struct subnet *)0;
   1640 	if (find_subnet (&subnet, *ia, MDL)) {
   1641 		/* If this interface has multiple aliases on the same
   1642 		   subnet, ignore all but the first we encounter. */
   1643 		if (!subnet -> interface) {
   1644 			interface_reference (&subnet -> interface, ip, MDL);
   1645 			subnet -> interface_address = *ia;
   1646 		} else if (subnet -> interface != ip) {
   1647 			log_error ("Multiple interfaces match the %s: %s %s",
   1648 				   "same subnet",
   1649 				   subnet -> interface -> name, ip -> name);
   1650 		}
   1651 		share = subnet -> shared_network;
   1652 		if (ip -> shared_network &&
   1653 		    ip -> shared_network != share) {
   1654 			log_fatal ("Interface %s matches multiple shared %s",
   1655 				   ip -> name, "networks");
   1656 		} else {
   1657 			if (!ip -> shared_network)
   1658 				shared_network_reference
   1659 					(&ip -> shared_network, share, MDL);
   1660 		}
   1661 
   1662 		if (!share -> interface) {
   1663 			interface_reference (&share -> interface, ip, MDL);
   1664 		} else if (share -> interface != ip) {
   1665 			log_error ("Multiple interfaces match the %s: %s %s",
   1666 				   "same shared network",
   1667 				   share -> interface -> name, ip -> name);
   1668 		}
   1669 		subnet_dereference (&subnet, MDL);
   1670 	}
   1671 	return 1;
   1672 }
   1673 
   1674 static TIME shutdown_time;
   1675 static int omapi_connection_count;
   1676 enum dhcp_shutdown_state shutdown_state;
   1677 
   1678 isc_result_t dhcp_io_shutdown (omapi_object_t *obj, void *foo)
   1679 {
   1680 	/* Shut down all listeners. */
   1681 	if (shutdown_state == shutdown_listeners &&
   1682 	    obj -> type == omapi_type_listener &&
   1683 	    obj -> inner &&
   1684 	    obj -> inner -> type == omapi_type_protocol_listener) {
   1685 		omapi_listener_destroy (obj, MDL);
   1686 		return ISC_R_SUCCESS;
   1687 	}
   1688 
   1689 	/* Shut down all existing omapi connections. */
   1690 	if (obj -> type == omapi_type_connection &&
   1691 	    obj -> inner &&
   1692 	    obj -> inner -> type == omapi_type_protocol) {
   1693 		if (shutdown_state == shutdown_drop_omapi_connections) {
   1694 			omapi_disconnect (obj, 1);
   1695 		}
   1696 		omapi_connection_count++;
   1697 		if (shutdown_state == shutdown_omapi_connections) {
   1698 			omapi_disconnect (obj, 0);
   1699 			return ISC_R_SUCCESS;
   1700 		}
   1701 	}
   1702 
   1703 	/* Shutdown all DHCP interfaces. */
   1704 	if (obj -> type == dhcp_type_interface &&
   1705 	    shutdown_state == shutdown_dhcp) {
   1706 		dhcp_interface_remove (obj, (omapi_object_t *)0);
   1707 		return ISC_R_SUCCESS;
   1708 	}
   1709 	return ISC_R_SUCCESS;
   1710 }
   1711 
   1712 static isc_result_t dhcp_io_shutdown_countdown (void *vlp)
   1713 {
   1714 #if defined (FAILOVER_PROTOCOL)
   1715 	dhcp_failover_state_t *state;
   1716 	int failover_connection_count = 0;
   1717 #endif
   1718 	struct timeval tv;
   1719 
   1720       oncemore:
   1721 	if (shutdown_state == shutdown_listeners ||
   1722 	    shutdown_state == shutdown_omapi_connections ||
   1723 	    shutdown_state == shutdown_drop_omapi_connections ||
   1724 	    shutdown_state == shutdown_dhcp) {
   1725 		omapi_connection_count = 0;
   1726 		omapi_io_state_foreach (dhcp_io_shutdown, 0);
   1727 	}
   1728 
   1729 	if ((shutdown_state == shutdown_listeners ||
   1730 	     shutdown_state == shutdown_omapi_connections ||
   1731 	     shutdown_state == shutdown_drop_omapi_connections) &&
   1732 	    omapi_connection_count == 0) {
   1733 		shutdown_state = shutdown_dhcp;
   1734 		shutdown_time = cur_time;
   1735 		goto oncemore;
   1736 	} else if (shutdown_state == shutdown_listeners &&
   1737 		   cur_time - shutdown_time > 4) {
   1738 		shutdown_state = shutdown_omapi_connections;
   1739 		shutdown_time = cur_time;
   1740 	} else if (shutdown_state == shutdown_omapi_connections &&
   1741 		   cur_time - shutdown_time > 4) {
   1742 		shutdown_state = shutdown_drop_omapi_connections;
   1743 		shutdown_time = cur_time;
   1744 	} else if (shutdown_state == shutdown_drop_omapi_connections &&
   1745 		   cur_time - shutdown_time > 4) {
   1746 		shutdown_state = shutdown_dhcp;
   1747 		shutdown_time = cur_time;
   1748 		goto oncemore;
   1749 	} else if (shutdown_state == shutdown_dhcp &&
   1750 		   cur_time - shutdown_time > 4) {
   1751 		shutdown_state = shutdown_done;
   1752 		shutdown_time = cur_time;
   1753 	}
   1754 
   1755 #if defined (FAILOVER_PROTOCOL)
   1756 	/* Set all failover peers into the shutdown state. */
   1757 	if (shutdown_state == shutdown_dhcp) {
   1758 	    for (state = failover_states; state; state = state -> next) {
   1759 		if (state -> me.state == normal) {
   1760 		    dhcp_failover_set_state (state, shut_down);
   1761 		    failover_connection_count++;
   1762 		}
   1763 		if (state -> me.state == shut_down &&
   1764 		    state -> partner.state != partner_down)
   1765 			failover_connection_count++;
   1766 	    }
   1767 	}
   1768 
   1769 	if (shutdown_state == shutdown_done) {
   1770 	    for (state = failover_states; state; state = state -> next) {
   1771 		if (state -> me.state == shut_down) {
   1772 		    if (state -> link_to_peer)
   1773 			dhcp_failover_link_dereference (&state -> link_to_peer,
   1774 							MDL);
   1775 		    dhcp_failover_set_state (state, recover);
   1776 		}
   1777 	    }
   1778 #if defined (DEBUG_MEMORY_LEAKAGE) && \
   1779 		defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
   1780 	    free_everything ();
   1781 	    omapi_print_dmalloc_usage_by_caller ();
   1782 #endif
   1783 	    if (no_pid_file == ISC_FALSE)
   1784 		    (void) unlink(path_dhcpd_pid);
   1785 	    exit (0);
   1786 	}
   1787 #else
   1788 	if (shutdown_state == shutdown_done) {
   1789 #if defined (DEBUG_MEMORY_LEAKAGE) && \
   1790 		defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
   1791 		free_everything ();
   1792 		omapi_print_dmalloc_usage_by_caller ();
   1793 #endif
   1794 		if (no_pid_file == ISC_FALSE)
   1795 			(void) unlink(path_dhcpd_pid);
   1796 		exit (0);
   1797 	}
   1798 #endif
   1799 	if (shutdown_state == shutdown_dhcp &&
   1800 #if defined(FAILOVER_PROTOCOL)
   1801 	    !failover_connection_count &&
   1802 #endif
   1803 	    ISC_TRUE) {
   1804 		shutdown_state = shutdown_done;
   1805 		shutdown_time = cur_time;
   1806 		goto oncemore;
   1807 	}
   1808 	tv.tv_sec = cur_tv.tv_sec + 1;
   1809 	tv.tv_usec = cur_tv.tv_usec;
   1810 	add_timeout (&tv,
   1811 		     (void (*)(void *))dhcp_io_shutdown_countdown, 0, 0, 0);
   1812 	return ISC_R_SUCCESS;
   1813 }
   1814 
   1815 isc_result_t dhcp_set_control_state (control_object_state_t oldstate,
   1816 				     control_object_state_t newstate)
   1817 {
   1818 	struct timeval tv;
   1819 
   1820 	if (newstate != server_shutdown)
   1821 		return DHCP_R_INVALIDARG;
   1822 	/* Re-entry. */
   1823 	if (shutdown_signal == SIGUSR1)
   1824 		return ISC_R_SUCCESS;
   1825 	shutdown_time = cur_time;
   1826 	shutdown_state = shutdown_listeners;
   1827 	/* Called by user. */
   1828 	if (shutdown_signal == 0) {
   1829 		shutdown_signal = SIGUSR1;
   1830 		dhcp_io_shutdown_countdown (0);
   1831 		return ISC_R_SUCCESS;
   1832 	}
   1833 	/* Called on signal. */
   1834 	log_info("Received signal %d, initiating shutdown.", shutdown_signal);
   1835 	shutdown_signal = SIGUSR1;
   1836 
   1837 	/*
   1838 	 * Prompt the shutdown event onto the timer queue
   1839 	 * and return to the dispatch loop.
   1840 	 */
   1841 	tv.tv_sec = cur_tv.tv_sec;
   1842 	tv.tv_usec = cur_tv.tv_usec + 1;
   1843 	add_timeout(&tv,
   1844 		    (void (*)(void *))dhcp_io_shutdown_countdown, 0, 0, 0);
   1845 	return ISC_R_SUCCESS;
   1846 }
   1847