xref: /netbsd/external/mpl/dhcp/dist/server/dhcpd.c (revision 13df4856)
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 
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 
verify_addr(omapi_object_t * l,omapi_addr_t * addr)136 static isc_result_t verify_addr (omapi_object_t *l, omapi_addr_t *addr) {
137 	return ISC_R_SUCCESS;
138 }
139 
verify_auth(omapi_object_t * p,omapi_auth_key_t * a)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 
omapi_listener_start(void * foo)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
usage(const char * sfmt,const char * sarg)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 */
setup_chroot(char * chroot_dir)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
main(int argc,char ** argv)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 
postconf_initialization(int quiet)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 
postdb_startup(void)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 
lease_pinged(from,packet,length)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 
lease_ping_timeout(vlp)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 
dhcpd_interface_setup_hook(struct interface_info * ip,struct iaddr * ia)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 
dhcp_io_shutdown(omapi_object_t * obj,void * foo)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 
dhcp_io_shutdown_countdown(void * vlp)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 
dhcp_set_control_state(control_object_state_t oldstate,control_object_state_t newstate)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