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