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@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
34static const char copyright[] =
35"Copyright 2004-2022 Internet Systems Consortium.";
36static const char arr [] = "All rights reserved.";
37static const char message [] = "Internet Systems Consortium DHCP Server";
38static 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 */
61uid_t set_uid = 0;
62gid_t set_gid = 0;
63#endif /* PARANOIA */
64
65struct class unknown_class;
66struct class known_class;
67
68struct iaddr server_identifier;
69int 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. */
75char std_nsupdate [] = "						    \n\
76option server.ddns-hostname =						    \n\
77  pick (option fqdn.hostname, option host-name, config-option host-name);   \n\
78option server.ddns-domainname =	config-option domain-name;		    \n\
79option server.ddns-rev-domainname = \"in-addr.arpa.\";";
80
81/* Stores configured DDNS conflict detection flags */
82u_int16_t ddns_conflict_mask;
83#endif /* NSUPDATE */
84
85int ddns_update_style;
86int dont_use_fsync = 0; /* 0 = default, use fsync, 1 = don't use fsync */
87int server_id_check = 0; /* 0 = default, don't check server id, 1 = do check */
88
89#ifdef DHCPv6
90int prefix_length_mode = PLM_PREFER;
91int do_release_on_roam = 0; /* 0 = default, do not release v6 leases on roam */
92#endif
93
94#ifdef EUI_64
95int persist_eui64 = 1; /* 1 = write EUI64 leases to disk, 0 = don't */
96#endif
97
98int authoring_byte_order = 0; /* 0 = not set */
99int lease_id_format = TOKEN_OCTAL; /* octal by default */
100u_int32_t abandon_lease_time = DEFAULT_ABANDON_LEASE_TIME;
101
102const char *path_dhcpd_conf = _PATH_DHCPD_CONF;
103const char *path_dhcpd_db = _PATH_DHCPD_DB;
104const char *path_dhcpd_pid = _PATH_DHCPD_PID;
105/* False (default) => we write and use a pid file */
106isc_boolean_t no_pid_file = ISC_FALSE;
107
108int dhcp_max_agent_option_packet_length = DHCP_MTU_MAX;
109
110static omapi_auth_key_t *omapi_key = (omapi_auth_key_t *)0;
111int omapi_port;
112
113#if defined (TRACING)
114trace_type_t *trace_srandom;
115#endif
116
117extern uint16_t local_port;
118extern uint16_t remote_port;
119libdhcp_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
134char *progname;
135
136static isc_result_t verify_addr (omapi_object_t *l, omapi_addr_t *addr) {
137	return ISC_R_SUCCESS;
138}
139
140static 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
146static 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 $");
230static char use_noarg[] = "No argument for command: %s ";
231
232static void
233usage(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 */
262static 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
276int
277main(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
1121void 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
1526void 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
1544void 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
1593void 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
1616int 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
1674static TIME shutdown_time;
1675static int omapi_connection_count;
1676enum dhcp_shutdown_state shutdown_state;
1677
1678isc_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
1712static 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
1815isc_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