]> git.ipfire.org Git - thirdparty/dhcp.git/blob - server/dhcpd.c
[master] Corrected several potential null references identified by static analysis
[thirdparty/dhcp.git] / server / dhcpd.c
1 /* dhcpd.c
2
3 DHCP Server Daemon. */
4
5 /*
6 * Copyright (c) 2004-2015 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1996-2003 by Internet Software Consortium
8 *
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
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-2015 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 #ifndef UNIT_TEST
61 static void usage(void);
62 #endif
63
64 struct iaddr server_identifier;
65 int server_identifier_matched;
66
67 #if defined (NSUPDATE)
68
69 /* This stuff is always executed to figure the default values for certain
70 ddns variables. */
71 char std_nsupdate [] = " \n\
72 option server.ddns-hostname = \n\
73 pick (option fqdn.hostname, option host-name, config-option host-name); \n\
74 option server.ddns-domainname = config-option domain-name; \n\
75 option server.ddns-rev-domainname = \"in-addr.arpa.\";";
76
77 #endif /* NSUPDATE */
78 int ddns_update_style;
79 int dont_use_fsync = 0; /* 0 = default, use fsync, 1 = don't use fsync */
80 int server_id_check = 0; /* 0 = default, don't check server id, 1 = do check */
81 int prefix_length_mode = PLM_EXACT;
82
83 const char *path_dhcpd_conf = _PATH_DHCPD_CONF;
84 const char *path_dhcpd_db = _PATH_DHCPD_DB;
85 const char *path_dhcpd_pid = _PATH_DHCPD_PID;
86 /* False (default) => we write and use a pid file */
87 isc_boolean_t no_pid_file = ISC_FALSE;
88
89 int dhcp_max_agent_option_packet_length = DHCP_MTU_MAX;
90
91 static omapi_auth_key_t *omapi_key = (omapi_auth_key_t *)0;
92 int omapi_port;
93
94 #if defined (TRACING)
95 trace_type_t *trace_srandom;
96 #endif
97
98 char *progname;
99
100 static isc_result_t verify_addr (omapi_object_t *l, omapi_addr_t *addr) {
101 return ISC_R_SUCCESS;
102 }
103
104 static isc_result_t verify_auth (omapi_object_t *p, omapi_auth_key_t *a) {
105 if (a != omapi_key)
106 return DHCP_R_INVALIDKEY;
107 return ISC_R_SUCCESS;
108 }
109
110 static void omapi_listener_start (void *foo)
111 {
112 omapi_object_t *listener;
113 isc_result_t result;
114 struct timeval tv;
115
116 listener = (omapi_object_t *)0;
117 result = omapi_generic_new (&listener, MDL);
118 if (result != ISC_R_SUCCESS)
119 log_fatal ("Can't allocate new generic object: %s",
120 isc_result_totext (result));
121 result = omapi_protocol_listen (listener,
122 (unsigned)omapi_port, 1);
123 if (result == ISC_R_SUCCESS && omapi_key)
124 result = omapi_protocol_configure_security
125 (listener, verify_addr, verify_auth);
126 if (result != ISC_R_SUCCESS) {
127 log_error ("Can't start OMAPI protocol: %s",
128 isc_result_totext (result));
129 tv.tv_sec = cur_tv.tv_sec + 5;
130 tv.tv_usec = cur_tv.tv_usec;
131 add_timeout (&tv, omapi_listener_start, 0, 0, 0);
132 }
133 omapi_object_dereference (&listener, MDL);
134 }
135
136 #ifndef UNIT_TEST
137
138 /* Note: If we add unit tests to test setup_chroot it will
139 * need to be moved to be outside the ifndef UNIT_TEST block.
140 */
141
142 #if defined (PARANOIA)
143 /* to be used in one of two possible scenarios */
144 static void setup_chroot (char *chroot_dir) {
145 if (geteuid())
146 log_fatal ("you must be root to use chroot");
147
148 if (chroot(chroot_dir)) {
149 log_fatal ("chroot(\"%s\"): %m", chroot_dir);
150 }
151 if (chdir ("/")) {
152 /* probably permission denied */
153 log_fatal ("chdir(\"/\"): %m");
154 }
155 }
156 #endif /* PARANOIA */
157
158 int
159 main(int argc, char **argv) {
160 int fd;
161 int i, status;
162 struct servent *ent;
163 char *s;
164 int cftest = 0;
165 int lftest = 0;
166 int pid;
167 char pbuf [20];
168 #ifndef DEBUG
169 int daemon = 1;
170 #endif
171 int quiet = 0;
172 char *server = (char *)0;
173 isc_result_t result;
174 unsigned seed;
175 struct interface_info *ip;
176 #if defined (NSUPDATE)
177 struct parse *parse;
178 int lose;
179 #endif
180 int no_dhcpd_conf = 0;
181 int no_dhcpd_db = 0;
182 int no_dhcpd_pid = 0;
183 #ifdef DHCPv6
184 int local_family_set = 0;
185 #endif /* DHCPv6 */
186 #if defined (TRACING)
187 char *traceinfile = (char *)0;
188 char *traceoutfile = (char *)0;
189 #endif
190
191 #if defined (PARANOIA)
192 char *set_user = 0;
193 char *set_group = 0;
194 char *set_chroot = 0;
195 #endif /* PARANOIA */
196
197 #ifdef OLD_LOG_NAME
198 progname = "dhcpd";
199 #else
200 progname = argv[0];
201 #endif
202
203 /* Make sure that file descriptors 0 (stdin), 1, (stdout), and
204 2 (stderr) are open. To do this, we assume that when we
205 open a file the lowest available file descriptor is used. */
206 fd = open("/dev/null", O_RDWR);
207 if (fd == 0)
208 fd = open("/dev/null", O_RDWR);
209 if (fd == 1)
210 fd = open("/dev/null", O_RDWR);
211 if (fd == 2)
212 log_perror = 0; /* No sense logging to /dev/null. */
213 else if (fd != -1)
214 close(fd);
215
216 /* Set up the isc and dns library managers */
217 status = dhcp_context_create(DHCP_CONTEXT_PRE_DB,
218 NULL, NULL);
219 if (status != ISC_R_SUCCESS)
220 log_fatal("Can't initialize context: %s",
221 isc_result_totext(status));
222
223 /* Set up the client classification system. */
224 classification_setup ();
225
226 /* Initialize the omapi system. */
227 result = omapi_init ();
228 if (result != ISC_R_SUCCESS)
229 log_fatal ("Can't initialize OMAPI: %s",
230 isc_result_totext (result));
231
232 /* Set up the OMAPI wrappers for common objects. */
233 dhcp_db_objects_setup ();
234 /* Set up the OMAPI wrappers for various server database internal
235 objects. */
236 dhcp_common_objects_setup ();
237
238 /* Initially, log errors to stderr as well as to syslogd. */
239 openlog (isc_file_basename(progname),
240 DHCP_LOG_OPTIONS, DHCPD_LOG_FACILITY);
241
242 for (i = 1; i < argc; i++) {
243 if (!strcmp (argv [i], "-p")) {
244 if (++i == argc)
245 usage ();
246 local_port = validate_port (argv [i]);
247 log_debug ("binding to user-specified port %d",
248 ntohs (local_port));
249 } else if (!strcmp (argv [i], "-f")) {
250 #ifndef DEBUG
251 daemon = 0;
252 #endif
253 } else if (!strcmp (argv [i], "-d")) {
254 #ifndef DEBUG
255 daemon = 0;
256 #endif
257 log_perror = -1;
258 } else if (!strcmp (argv [i], "-s")) {
259 if (++i == argc)
260 usage ();
261 server = argv [i];
262 #if defined (PARANOIA)
263 } else if (!strcmp (argv [i], "-user")) {
264 if (++i == argc)
265 usage ();
266 set_user = argv [i];
267 } else if (!strcmp (argv [i], "-group")) {
268 if (++i == argc)
269 usage ();
270 set_group = argv [i];
271 } else if (!strcmp (argv [i], "-chroot")) {
272 if (++i == argc)
273 usage ();
274 set_chroot = argv [i];
275 #endif /* PARANOIA */
276 } else if (!strcmp (argv [i], "-cf")) {
277 if (++i == argc)
278 usage ();
279 path_dhcpd_conf = argv [i];
280 no_dhcpd_conf = 1;
281 } else if (!strcmp (argv [i], "-lf")) {
282 if (++i == argc)
283 usage ();
284 path_dhcpd_db = argv [i];
285 no_dhcpd_db = 1;
286 } else if (!strcmp (argv [i], "-pf")) {
287 if (++i == argc)
288 usage ();
289 path_dhcpd_pid = argv [i];
290 no_dhcpd_pid = 1;
291 } else if (!strcmp(argv[i], "--no-pid")) {
292 no_pid_file = ISC_TRUE;
293 } else if (!strcmp (argv [i], "-t")) {
294 /* test configurations only */
295 #ifndef DEBUG
296 daemon = 0;
297 #endif
298 cftest = 1;
299 log_perror = -1;
300 } else if (!strcmp (argv [i], "-T")) {
301 /* test configurations and lease file only */
302 #ifndef DEBUG
303 daemon = 0;
304 #endif
305 cftest = 1;
306 lftest = 1;
307 log_perror = -1;
308 } else if (!strcmp (argv [i], "-q")) {
309 quiet = 1;
310 quiet_interface_discovery = 1;
311 #ifdef DHCPv6
312 } else if (!strcmp(argv[i], "-4")) {
313 if (local_family_set && (local_family != AF_INET)) {
314 log_fatal("Server cannot run in both IPv4 and "
315 "IPv6 mode at the same time.");
316 }
317 local_family = AF_INET;
318 local_family_set = 1;
319 } else if (!strcmp(argv[i], "-6")) {
320 if (local_family_set && (local_family != AF_INET6)) {
321 log_fatal("Server cannot run in both IPv4 and "
322 "IPv6 mode at the same time.");
323 }
324 local_family = AF_INET6;
325 local_family_set = 1;
326 #endif /* DHCPv6 */
327 } else if (!strcmp (argv [i], "--version")) {
328 const char vstring[] = "isc-dhcpd-";
329 IGNORE_RET(write(STDERR_FILENO, vstring,
330 strlen(vstring)));
331 IGNORE_RET(write(STDERR_FILENO,
332 PACKAGE_VERSION,
333 strlen(PACKAGE_VERSION)));
334 IGNORE_RET(write(STDERR_FILENO, "\n", 1));
335 exit (0);
336 #if defined (TRACING)
337 } else if (!strcmp (argv [i], "-tf")) {
338 if (++i == argc)
339 usage ();
340 traceoutfile = argv [i];
341 } else if (!strcmp (argv [i], "-play")) {
342 if (++i == argc)
343 usage ();
344 traceinfile = argv [i];
345 trace_replay_init ();
346 #endif /* TRACING */
347 } else if (argv [i][0] == '-') {
348 usage ();
349 } else {
350 struct interface_info *tmp =
351 (struct interface_info *)0;
352 if (strlen(argv[i]) >= sizeof(tmp->name))
353 log_fatal("%s: interface name too long "
354 "(is %ld)",
355 argv[i], (long)strlen(argv[i]));
356 result = interface_allocate (&tmp, MDL);
357 if (result != ISC_R_SUCCESS)
358 log_fatal ("Insufficient memory to %s %s: %s",
359 "record interface", argv [i],
360 isc_result_totext (result));
361 strcpy (tmp -> name, argv [i]);
362 if (interfaces) {
363 interface_reference (&tmp -> next,
364 interfaces, MDL);
365 interface_dereference (&interfaces, MDL);
366 }
367 interface_reference (&interfaces, tmp, MDL);
368 tmp -> flags = INTERFACE_REQUESTED;
369 }
370 }
371
372 if (!no_dhcpd_conf && (s = getenv ("PATH_DHCPD_CONF"))) {
373 path_dhcpd_conf = s;
374 }
375
376 #ifdef DHCPv6
377 if (local_family == AF_INET6) {
378 /* DHCPv6: override DHCPv4 lease and pid filenames */
379 if (!no_dhcpd_db) {
380 if ((s = getenv ("PATH_DHCPD6_DB")))
381 path_dhcpd_db = s;
382 else
383 path_dhcpd_db = _PATH_DHCPD6_DB;
384 }
385 if (!no_dhcpd_pid) {
386 if ((s = getenv ("PATH_DHCPD6_PID")))
387 path_dhcpd_pid = s;
388 else
389 path_dhcpd_pid = _PATH_DHCPD6_PID;
390 }
391 } else
392 #else /* !DHCPv6 */
393 {
394 if (!no_dhcpd_db && (s = getenv ("PATH_DHCPD_DB"))) {
395 path_dhcpd_db = s;
396 }
397 if (!no_dhcpd_pid && (s = getenv ("PATH_DHCPD_PID"))) {
398 path_dhcpd_pid = s;
399 }
400 }
401 #endif /* DHCPv6 */
402
403 /*
404 * convert relative path names to absolute, for files that need
405 * to be reopened after chdir() has been called
406 */
407 if (path_dhcpd_db[0] != '/') {
408 const char *path = path_dhcpd_db;
409 path_dhcpd_db = realpath(path_dhcpd_db, NULL);
410 if (path_dhcpd_db == NULL)
411 log_fatal("Failed to get realpath for %s: %s", path,
412 strerror(errno));
413 }
414
415 if (!quiet) {
416 log_info("%s %s", message, PACKAGE_VERSION);
417 log_info (copyright);
418 log_info (arr);
419 log_info (url);
420 } else {
421 log_perror = 0;
422 }
423
424 #if defined (TRACING)
425 trace_init (set_time, MDL);
426 if (traceoutfile) {
427 result = trace_begin (traceoutfile, MDL);
428 if (result != ISC_R_SUCCESS)
429 log_fatal ("Unable to begin trace: %s",
430 isc_result_totext (result));
431 }
432 interface_trace_setup ();
433 parse_trace_setup ();
434 trace_srandom = trace_type_register ("random-seed", (void *)0,
435 trace_seed_input,
436 trace_seed_stop, MDL);
437 #if defined (NSUPDATE)
438 trace_ddns_init();
439 #endif /* NSUPDATE */
440 #endif
441
442 #if defined (PARANOIA)
443 /* get user and group info if those options were given */
444 if (set_user) {
445 struct passwd *tmp_pwd;
446
447 if (geteuid())
448 log_fatal ("you must be root to set user");
449
450 if (!(tmp_pwd = getpwnam(set_user)))
451 log_fatal ("no such user: %s", set_user);
452
453 set_uid = tmp_pwd->pw_uid;
454
455 /* use the user's group as the default gid */
456 if (!set_group)
457 set_gid = tmp_pwd->pw_gid;
458 }
459
460 if (set_group) {
461 /* get around the ISC declaration of group */
462 #define group real_group
463 struct group *tmp_grp;
464
465 if (geteuid())
466 log_fatal ("you must be root to set group");
467
468 if (!(tmp_grp = getgrnam(set_group)))
469 log_fatal ("no such group: %s", set_group);
470
471 set_gid = tmp_grp->gr_gid;
472 #undef group
473 }
474
475 # if defined (EARLY_CHROOT)
476 if (set_chroot) setup_chroot (set_chroot);
477 # endif /* EARLY_CHROOT */
478 #endif /* PARANOIA */
479
480 /* Default to the DHCP/BOOTP port. */
481 if (!local_port)
482 {
483 if ((s = getenv ("DHCPD_PORT"))) {
484 local_port = validate_port (s);
485 log_debug ("binding to environment-specified port %d",
486 ntohs (local_port));
487 } else {
488 if (local_family == AF_INET) {
489 ent = getservbyname("dhcp", "udp");
490 if (ent == NULL) {
491 local_port = htons(67);
492 } else {
493 local_port = ent->s_port;
494 }
495 } else {
496 /* INSIST(local_family == AF_INET6); */
497 ent = getservbyname("dhcpv6-server", "udp");
498 if (ent == NULL) {
499 local_port = htons(547);
500 } else {
501 local_port = ent->s_port;
502 }
503 }
504 #ifndef __CYGWIN32__ /* XXX */
505 endservent ();
506 #endif
507 }
508 }
509
510 if (local_family == AF_INET) {
511 remote_port = htons(ntohs(local_port) + 1);
512 } else {
513 /* INSIST(local_family == AF_INET6); */
514 ent = getservbyname("dhcpv6-client", "udp");
515 if (ent == NULL) {
516 remote_port = htons(546);
517 } else {
518 remote_port = ent->s_port;
519 }
520 }
521
522 if (server) {
523 if (local_family != AF_INET) {
524 log_fatal("You can only specify address to send "
525 "replies to when running an IPv4 server.");
526 }
527 if (!inet_aton (server, &limited_broadcast)) {
528 struct hostent *he;
529 he = gethostbyname (server);
530 if (he) {
531 memcpy (&limited_broadcast,
532 he -> h_addr_list [0],
533 sizeof limited_broadcast);
534 } else
535 limited_broadcast.s_addr = INADDR_BROADCAST;
536 }
537 } else {
538 limited_broadcast.s_addr = INADDR_BROADCAST;
539 }
540
541 /* Get the current time... */
542 gettimeofday(&cur_tv, NULL);
543
544 /* Set up the initial dhcp option universe. */
545 initialize_common_option_spaces ();
546 initialize_server_option_spaces ();
547
548 /* Add the ddns update style enumeration prior to parsing. */
549 add_enumeration (&ddns_styles);
550 add_enumeration (&syslog_enum);
551 #if defined (LDAP_CONFIGURATION)
552 add_enumeration (&ldap_methods);
553 #if defined (LDAP_USE_SSL)
554 add_enumeration (&ldap_ssl_usage_enum);
555 add_enumeration (&ldap_tls_reqcert_enum);
556 add_enumeration (&ldap_tls_crlcheck_enum);
557 #endif
558 #endif
559
560 if (!group_allocate (&root_group, MDL))
561 log_fatal ("Can't allocate root group!");
562 root_group -> authoritative = 0;
563
564 /* Set up various hooks. */
565 dhcp_interface_setup_hook = dhcpd_interface_setup_hook;
566 bootp_packet_handler = do_packet;
567 #ifdef DHCPv6
568 add_enumeration (&prefix_length_modes);
569 dhcpv6_packet_handler = do_packet6;
570 #endif /* DHCPv6 */
571
572 #if defined (NSUPDATE)
573 /* Set up the standard name service updater routine. */
574 parse = NULL;
575 status = new_parse(&parse, -1, std_nsupdate, sizeof(std_nsupdate) - 1,
576 "standard name service update routine", 0);
577 if (status != ISC_R_SUCCESS)
578 log_fatal ("can't begin parsing name service updater!");
579
580 if (parse != NULL) {
581 lose = 0;
582 if (!(parse_executable_statements(&root_group->statements,
583 parse, &lose, context_any))) {
584 end_parse(&parse);
585 log_fatal("can't parse standard name service updater!");
586 }
587 end_parse(&parse);
588 }
589 #endif
590
591 /* Initialize icmp support... */
592 if (!cftest && !lftest)
593 icmp_startup (1, lease_pinged);
594
595 #if defined (TRACING)
596 if (traceinfile) {
597 if (!no_dhcpd_db) {
598 log_error ("%s", "");
599 log_error ("** You must specify a lease file with -lf.");
600 log_error (" Dhcpd will not overwrite your default");
601 log_fatal (" lease file when playing back a trace. **");
602 }
603 trace_file_replay (traceinfile);
604
605 #if defined (DEBUG_MEMORY_LEAKAGE) && \
606 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
607 free_everything ();
608 omapi_print_dmalloc_usage_by_caller ();
609 #endif
610
611 exit (0);
612 }
613 #endif
614
615 #ifdef DHCPv6
616 /* set up DHCPv6 hashes */
617 if (!ia_new_hash(&ia_na_active, DEFAULT_HASH_SIZE, MDL)) {
618 log_fatal("Out of memory creating hash for active IA_NA.");
619 }
620 if (!ia_new_hash(&ia_ta_active, DEFAULT_HASH_SIZE, MDL)) {
621 log_fatal("Out of memory creating hash for active IA_TA.");
622 }
623 if (!ia_new_hash(&ia_pd_active, DEFAULT_HASH_SIZE, MDL)) {
624 log_fatal("Out of memory creating hash for active IA_PD.");
625 }
626 #endif /* DHCPv6 */
627
628 /* Read the dhcpd.conf file... */
629 if (readconf () != ISC_R_SUCCESS)
630 log_fatal ("Configuration file errors encountered -- exiting");
631
632 postconf_initialization (quiet);
633
634 #if defined (PARANOIA) && !defined (EARLY_CHROOT)
635 if (set_chroot) setup_chroot (set_chroot);
636 #endif /* PARANOIA && !EARLY_CHROOT */
637
638 #ifdef DHCPv6
639 /* log info about ipv6_ponds with large address ranges */
640 report_jumbo_ranges();
641 #endif
642
643 /* test option should cause an early exit */
644 if (cftest && !lftest)
645 exit(0);
646
647 /*
648 * First part of dealing with pid files. Check to see if
649 * we should continue running or not. We run if:
650 * - we are testing the lease file out
651 * - we don't have a pid file to check
652 * - there is no other process running
653 */
654 if ((lftest == 0) && (no_pid_file == ISC_FALSE)) {
655 /*Read previous pid file. */
656 if ((i = open(path_dhcpd_pid, O_RDONLY)) >= 0) {
657 status = read(i, pbuf, (sizeof pbuf) - 1);
658 close(i);
659 if (status > 0) {
660 pbuf[status] = 0;
661 pid = atoi(pbuf);
662
663 /*
664 * If there was a previous server process and
665 * it is still running, abort
666 */
667 if (!pid ||
668 (pid != getpid() && kill(pid, 0) == 0))
669 log_fatal("There's already a "
670 "DHCP server running.");
671 }
672 }
673 }
674
675 group_write_hook = group_writer;
676
677 /* Start up the database... */
678 db_startup (lftest);
679
680 if (lftest)
681 exit (0);
682
683 /* Discover all the network interfaces and initialize them. */
684 discover_interfaces(DISCOVER_SERVER);
685
686 #ifdef DHCPv6
687 /*
688 * Remove addresses from our pools that we should not issue
689 * to clients.
690 *
691 * We currently have no support for this in IPv4. It is not
692 * as important in IPv4, as making pools with ranges that
693 * leave out interfaces and hosts is fairly straightforward
694 * using range notation, but not so handy with CIDR notation.
695 */
696 if (local_family == AF_INET6) {
697 mark_hosts_unavailable();
698 mark_phosts_unavailable();
699 mark_interfaces_unavailable();
700 }
701 #endif /* DHCPv6 */
702
703 /* Make up a seed for the random number generator from current
704 time plus the sum of the last four bytes of each
705 interface's hardware address interpreted as an integer.
706 Not much entropy, but we're booting, so we're not likely to
707 find anything better. */
708 seed = 0;
709 for (ip = interfaces; ip; ip = ip -> next) {
710 int junk;
711 memcpy (&junk,
712 &ip -> hw_address.hbuf [ip -> hw_address.hlen -
713 sizeof seed], sizeof seed);
714 seed += junk;
715 }
716 srandom (seed + cur_time);
717 #if defined (TRACING)
718 trace_seed_stash (trace_srandom, seed + cur_time);
719 #endif
720 postdb_startup ();
721
722 #ifdef DHCPv6
723 /*
724 * Set server DHCPv6 identifier - we go in order:
725 * dhcp6.server-id in the config file
726 * server-duid from the lease file
727 * server-duid from the config file (the config file is read first
728 * and the lease file overwrites the config file information)
729 * genrate a new one
730 * In all cases we write it out to the lease file.
731 * See dhcpv6.c for discussion of setting DUID.
732 */
733 if ((set_server_duid_from_option() != ISC_R_SUCCESS) &&
734 (!server_duid_isset()) &&
735 (generate_new_server_duid() != ISC_R_SUCCESS)) {
736 log_fatal("Unable to set server identifier.");
737 }
738 write_server_duid();
739 #endif /* DHCPv6 */
740
741 #ifndef DEBUG
742 if (daemon) {
743 /* First part of becoming a daemon... */
744 if ((pid = fork ()) < 0)
745 log_fatal ("Can't fork daemon: %m");
746 else if (pid)
747 exit (0);
748 }
749
750 /*
751 * Second part of dealing with pid files. Now
752 * that we have forked we can write our pid if
753 * appropriate.
754 */
755 if (no_pid_file == ISC_FALSE) {
756 i = open(path_dhcpd_pid, O_WRONLY|O_CREAT|O_TRUNC, 0644);
757 if (i >= 0) {
758 sprintf(pbuf, "%d\n", (int) getpid());
759 IGNORE_RET(write(i, pbuf, strlen(pbuf)));
760 close(i);
761 } else {
762 log_error("Can't create PID file %s: %m.",
763 path_dhcpd_pid);
764 }
765 }
766
767 #if defined (PARANOIA)
768 /* change uid to the specified one */
769
770 if (set_gid) {
771 if (setgroups (0, (void *)0))
772 log_fatal ("setgroups: %m");
773 if (setgid (set_gid))
774 log_fatal ("setgid(%d): %m", (int) set_gid);
775 }
776
777 if (set_uid) {
778 if (setuid (set_uid))
779 log_fatal ("setuid(%d): %m", (int) set_uid);
780 }
781 #endif /* PARANOIA */
782
783 /* If we were requested to log to stdout on the command line,
784 keep doing so; otherwise, stop. */
785 if (log_perror == -1)
786 log_perror = 1;
787 else
788 log_perror = 0;
789
790 if (daemon) {
791 /* Become session leader and get pid... */
792 (void) setsid();
793
794 /* Close standard I/O descriptors. */
795 (void) close(0);
796 (void) close(1);
797 (void) close(2);
798
799 /* Reopen them on /dev/null. */
800 (void) open("/dev/null", O_RDWR);
801 (void) open("/dev/null", O_RDWR);
802 (void) open("/dev/null", O_RDWR);
803 log_perror = 0; /* No sense logging to /dev/null. */
804
805 IGNORE_RET (chdir("/"));
806 }
807 #endif /* !DEBUG */
808
809 #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \
810 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
811 dmalloc_cutoff_generation = dmalloc_generation;
812 dmalloc_longterm = dmalloc_outstanding;
813 dmalloc_outstanding = 0;
814 #endif
815
816 omapi_set_int_value ((omapi_object_t *)dhcp_control_object,
817 (omapi_object_t *)0, "state", server_running);
818
819 #if defined(ENABLE_GENTLE_SHUTDOWN)
820 /* no signal handlers until we deal with the side effects */
821 /* install signal handlers */
822 signal(SIGINT, dhcp_signal_handler); /* control-c */
823 signal(SIGTERM, dhcp_signal_handler); /* kill */
824 #endif
825
826 /* Log that we are about to start working */
827 log_info("Server starting service.");
828
829 /*
830 * Receive packets and dispatch them...
831 * dispatch() will never return.
832 */
833 dispatch ();
834
835 /* Let's return status code */
836 return 0;
837 }
838 #endif /* !UNIT_TEST */
839
840 void postconf_initialization (int quiet)
841 {
842 struct option_state *options = NULL;
843 struct data_string db;
844 struct option_cache *oc;
845 char *s;
846 isc_result_t result;
847 int tmp;
848 #if defined (NSUPDATE)
849 struct in_addr local4, *local4_ptr = NULL;
850 struct in6_addr local6, *local6_ptr = NULL;
851 #endif
852
853 /* Now try to get the lease file name. */
854 option_state_allocate(&options, MDL);
855
856 execute_statements_in_scope(NULL, NULL, NULL, NULL, NULL,
857 options, &global_scope, root_group,
858 NULL, NULL);
859 memset(&db, 0, sizeof db);
860 oc = lookup_option(&server_universe, options, SV_LEASE_FILE_NAME);
861 if (oc &&
862 evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
863 &global_scope, oc, MDL)) {
864 s = dmalloc(db.len + 1, MDL);
865 if (!s)
866 log_fatal("no memory for lease db filename.");
867 memcpy(s, db.data, db.len);
868 s[db.len] = 0;
869 data_string_forget(&db, MDL);
870 path_dhcpd_db = s;
871 }
872
873 oc = lookup_option(&server_universe, options, SV_PID_FILE_NAME);
874 if (oc &&
875 evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
876 &global_scope, oc, MDL)) {
877 s = dmalloc(db.len + 1, MDL);
878 if (!s)
879 log_fatal("no memory for pid filename.");
880 memcpy(s, db.data, db.len);
881 s[db.len] = 0;
882 data_string_forget(&db, MDL);
883 path_dhcpd_pid = s;
884 }
885
886 #ifdef DHCPv6
887 if (local_family == AF_INET6) {
888 /*
889 * Override lease file name with dhcpv6 lease file name,
890 * if it was set; then, do the same with the pid file name
891 */
892 oc = lookup_option(&server_universe, options,
893 SV_DHCPV6_LEASE_FILE_NAME);
894 if (oc &&
895 evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
896 &global_scope, oc, MDL)) {
897 s = dmalloc(db.len + 1, MDL);
898 if (!s)
899 log_fatal("no memory for lease db filename.");
900 memcpy(s, db.data, db.len);
901 s[db.len] = 0;
902 data_string_forget(&db, MDL);
903 path_dhcpd_db = s;
904 }
905
906 oc = lookup_option(&server_universe, options,
907 SV_DHCPV6_PID_FILE_NAME);
908 if (oc &&
909 evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
910 &global_scope, oc, MDL)) {
911 s = dmalloc(db.len + 1, MDL);
912 if (!s)
913 log_fatal("no memory for pid filename.");
914 memcpy(s, db.data, db.len);
915 s[db.len] = 0;
916 data_string_forget(&db, MDL);
917 path_dhcpd_pid = s;
918 }
919 }
920 #endif /* DHCPv6 */
921
922 omapi_port = -1;
923 oc = lookup_option(&server_universe, options, SV_OMAPI_PORT);
924 if (oc &&
925 evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
926 &global_scope, oc, MDL)) {
927 if (db.len == 2) {
928 omapi_port = getUShort(db.data);
929 } else
930 log_fatal("invalid omapi port data length");
931 data_string_forget(&db, MDL);
932 }
933
934 oc = lookup_option(&server_universe, options, SV_OMAPI_KEY);
935 if (oc &&
936 evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
937 &global_scope, oc, MDL)) {
938 s = dmalloc(db.len + 1, MDL);
939 if (!s)
940 log_fatal("no memory for OMAPI key filename.");
941 memcpy(s, db.data, db.len);
942 s[db.len] = 0;
943 data_string_forget(&db, MDL);
944 result = omapi_auth_key_lookup_name(&omapi_key, s);
945 dfree(s, MDL);
946 if (result != ISC_R_SUCCESS)
947 log_fatal("OMAPI key %s: %s",
948 s, isc_result_totext (result));
949 }
950
951 oc = lookup_option(&server_universe, options, SV_LOCAL_PORT);
952 if (oc &&
953 evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
954 &global_scope, oc, MDL)) {
955 if (db.len == 2) {
956 local_port = htons(getUShort (db.data));
957 } else
958 log_fatal("invalid local port data length");
959 data_string_forget(&db, MDL);
960 }
961
962 oc = lookup_option(&server_universe, options, SV_REMOTE_PORT);
963 if (oc &&
964 evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
965 &global_scope, oc, MDL)) {
966 if (db.len == 2) {
967 remote_port = htons(getUShort (db.data));
968 } else
969 log_fatal("invalid remote port data length");
970 data_string_forget(&db, MDL);
971 }
972
973 oc = lookup_option(&server_universe, options,
974 SV_LIMITED_BROADCAST_ADDRESS);
975 if (oc &&
976 evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
977 &global_scope, oc, MDL)) {
978 if (db.len == 4) {
979 memcpy(&limited_broadcast, db.data, 4);
980 } else
981 log_fatal("invalid broadcast address data length");
982 data_string_forget(&db, MDL);
983 }
984
985 oc = lookup_option(&server_universe, options, SV_LOCAL_ADDRESS);
986 if (oc &&
987 evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
988 &global_scope, oc, MDL)) {
989 if (db.len == 4) {
990 memcpy(&local_address, db.data, 4);
991 } else
992 log_fatal("invalid local address data length");
993 data_string_forget(&db, MDL);
994 }
995
996 oc = lookup_option(&server_universe, options, SV_DDNS_UPDATE_STYLE);
997 if (oc) {
998 if (evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
999 &global_scope, oc, MDL)) {
1000 if (db.len == 1) {
1001 ddns_update_style = db.data[0];
1002 } else
1003 log_fatal("invalid dns update type");
1004 data_string_forget(&db, MDL);
1005 }
1006 } else {
1007 ddns_update_style = DDNS_UPDATE_STYLE_NONE;
1008 }
1009 #if defined (NSUPDATE)
1010 /* We no longer support ad_hoc, tell the user */
1011 if (ddns_update_style == DDNS_UPDATE_STYLE_AD_HOC) {
1012 log_fatal("ddns-update-style ad_hoc no longer supported");
1013 }
1014
1015 oc = lookup_option(&server_universe, options, SV_DDNS_LOCAL_ADDRESS4);
1016 if (oc) {
1017 if (evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
1018 &global_scope, oc, MDL)) {
1019 if (db.len == 4) {
1020 memcpy(&local4, db.data, 4);
1021 local4_ptr = &local4;
1022 }
1023 data_string_forget(&db, MDL);
1024 }
1025 }
1026
1027 oc = lookup_option(&server_universe, options, SV_DDNS_LOCAL_ADDRESS6);
1028 if (oc) {
1029 if (evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
1030 &global_scope, oc, MDL)) {
1031 if (db.len == 16) {
1032 memcpy(&local6, db.data, 16);
1033 local6_ptr = &local6;
1034 }
1035 data_string_forget(&db, MDL);
1036 }
1037 }
1038
1039 if (dhcp_context_create(DHCP_CONTEXT_POST_DB, local4_ptr, local6_ptr)
1040 != ISC_R_SUCCESS)
1041 log_fatal("Unable to complete ddns initialization");
1042
1043 #else
1044 /* If we don't have support for updates compiled in tell the user */
1045 if (ddns_update_style != DDNS_UPDATE_STYLE_NONE) {
1046 log_fatal("Support for ddns-update-style not compiled in");
1047 }
1048 #endif
1049
1050 if (!quiet) {
1051 log_info ("Config file: %s", path_dhcpd_conf);
1052 log_info ("Database file: %s", path_dhcpd_db);
1053 log_info ("PID file: %s", path_dhcpd_pid);
1054 }
1055
1056 oc = lookup_option(&server_universe, options, SV_LOG_FACILITY);
1057 if (oc) {
1058 if (evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
1059 &global_scope, oc, MDL)) {
1060 if (db.len == 1) {
1061 closelog ();
1062 openlog(isc_file_basename(progname),
1063 DHCP_LOG_OPTIONS, db.data[0]);
1064 /* Log the startup banner into the new
1065 log file. */
1066 /* Don't log to stderr twice. */
1067 tmp = log_perror;
1068 log_perror = 0;
1069 log_info("%s %s", message, PACKAGE_VERSION);
1070 log_info(copyright);
1071 log_info(arr);
1072 log_info(url);
1073 log_perror = tmp;
1074 } else
1075 log_fatal("invalid log facility");
1076 data_string_forget(&db, MDL);
1077 }
1078 }
1079
1080 #if defined(DELAYED_ACK)
1081 oc = lookup_option(&server_universe, options, SV_DELAYED_ACK);
1082 if (oc &&
1083 evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
1084 &global_scope, oc, MDL)) {
1085 if (db.len == 2) {
1086 max_outstanding_acks = htons(getUShort(db.data));
1087 } else {
1088 log_fatal("invalid max delayed ACK count ");
1089 }
1090 data_string_forget(&db, MDL);
1091 }
1092
1093 oc = lookup_option(&server_universe, options, SV_MAX_ACK_DELAY);
1094 if (oc &&
1095 evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
1096 &global_scope, oc, MDL)) {
1097 u_int32_t timeval;
1098
1099 if (db.len != 4)
1100 log_fatal("invalid max ack delay configuration");
1101
1102 timeval = getULong(db.data);
1103 max_ack_delay_secs = timeval / 1000000;
1104 max_ack_delay_usecs = timeval % 1000000;
1105
1106 data_string_forget(&db, MDL);
1107 }
1108 #endif
1109
1110 oc = lookup_option(&server_universe, options, SV_DONT_USE_FSYNC);
1111 if ((oc != NULL) &&
1112 evaluate_boolean_option_cache(NULL, NULL, NULL, NULL, options, NULL,
1113 &global_scope, oc, MDL)) {
1114 dont_use_fsync = 1;
1115 log_error("Not using fsync() to flush lease writes");
1116 }
1117
1118 oc = lookup_option(&server_universe, options, SV_SERVER_ID_CHECK);
1119 if ((oc != NULL) &&
1120 evaluate_boolean_option_cache(NULL, NULL, NULL, NULL, options, NULL,
1121 &global_scope, oc, MDL)) {
1122 log_info("Setting server-id-check true");
1123 server_id_check = 1;
1124 }
1125
1126 oc = lookup_option(&server_universe, options, SV_PREFIX_LEN_MODE);
1127 if ((oc != NULL) &&
1128 evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
1129 &global_scope, oc, MDL)) {
1130 if (db.len == 1) {
1131 prefix_length_mode = db.data[0];
1132 } else {
1133 log_fatal("invalid prefix-len-mode");
1134 }
1135
1136 data_string_forget(&db, MDL);
1137 }
1138
1139 #if defined (BINARY_LEASES)
1140 if (local_family == AF_INET) {
1141 log_info("Source compiled to use binary-leases");
1142 }
1143 #endif
1144
1145 /* Don't need the options anymore. */
1146 option_state_dereference(&options, MDL);
1147 }
1148
1149 void postdb_startup (void)
1150 {
1151 /* Initialize the omapi listener state. */
1152 if (omapi_port != -1) {
1153 omapi_listener_start (0);
1154 }
1155
1156 #if defined (FAILOVER_PROTOCOL)
1157 /* Initialize the failover listener state. */
1158 dhcp_failover_startup ();
1159 #endif
1160
1161 /*
1162 * Begin our lease timeout background task.
1163 */
1164 schedule_all_ipv6_lease_timeouts();
1165 }
1166
1167 /* Print usage message. */
1168 #ifndef UNIT_TEST
1169 static void
1170 usage(void) {
1171 log_info("%s %s", message, PACKAGE_VERSION);
1172 log_info(copyright);
1173 log_info(arr);
1174
1175 log_fatal("Usage: %s [-p <UDP port #>] [-f] [-d] [-q] [-t|-T]\n"
1176 #ifdef DHCPv6
1177 " [-4|-6] [-cf config-file] [-lf lease-file]\n"
1178 #else /* !DHCPv6 */
1179 " [-cf config-file] [-lf lease-file]\n"
1180 #endif /* DHCPv6 */
1181 #if defined (PARANOIA)
1182 /* meld into the following string */
1183 " [-user user] [-group group] [-chroot dir]\n"
1184 #endif /* PARANOIA */
1185 #if defined (TRACING)
1186 " [-tf trace-output-file]\n"
1187 " [-play trace-input-file]\n"
1188 #endif /* TRACING */
1189 " [-pf pid-file] [--no-pid] [-s server]\n"
1190 " [if0 [...ifN]]",
1191 isc_file_basename(progname));
1192 }
1193 #endif
1194
1195 void lease_pinged (from, packet, length)
1196 struct iaddr from;
1197 u_int8_t *packet;
1198 int length;
1199 {
1200 struct lease *lp;
1201
1202 /* Don't try to look up a pinged lease if we aren't trying to
1203 ping one - otherwise somebody could easily make us churn by
1204 just forging repeated ICMP EchoReply packets for us to look
1205 up. */
1206 if (!outstanding_pings)
1207 return;
1208
1209 lp = (struct lease *)0;
1210 if (!find_lease_by_ip_addr (&lp, from, MDL)) {
1211 log_debug ("unexpected ICMP Echo Reply from %s",
1212 piaddr (from));
1213 return;
1214 }
1215
1216 if (!lp -> state) {
1217 #if defined (FAILOVER_PROTOCOL)
1218 if (!lp -> pool ||
1219 !lp -> pool -> failover_peer)
1220 #endif
1221 log_debug ("ICMP Echo Reply for %s late or spurious.",
1222 piaddr (from));
1223 goto out;
1224 }
1225
1226 if (lp -> ends > cur_time) {
1227 log_debug ("ICMP Echo reply while lease %s valid.",
1228 piaddr (from));
1229 }
1230
1231 /* At this point it looks like we pinged a lease and got a
1232 response, which shouldn't have happened. */
1233 data_string_forget (&lp -> state -> parameter_request_list, MDL);
1234 free_lease_state (lp -> state, MDL);
1235 lp -> state = (struct lease_state *)0;
1236
1237 abandon_lease (lp, "pinged before offer");
1238 cancel_timeout (lease_ping_timeout, lp);
1239 --outstanding_pings;
1240 out:
1241 lease_dereference (&lp, MDL);
1242 }
1243
1244 void lease_ping_timeout (vlp)
1245 void *vlp;
1246 {
1247 struct lease *lp = vlp;
1248
1249 #if defined (DEBUG_MEMORY_LEAKAGE)
1250 unsigned long previous_outstanding = dmalloc_outstanding;
1251 #endif
1252
1253 --outstanding_pings;
1254 dhcp_reply (lp);
1255
1256 #if defined (DEBUG_MEMORY_LEAKAGE)
1257 log_info ("generation %ld: %ld new, %ld outstanding, %ld long-term",
1258 dmalloc_generation,
1259 dmalloc_outstanding - previous_outstanding,
1260 dmalloc_outstanding, dmalloc_longterm);
1261 #endif
1262 #if defined (DEBUG_MEMORY_LEAKAGE)
1263 dmalloc_dump_outstanding ();
1264 #endif
1265 }
1266
1267 int dhcpd_interface_setup_hook (struct interface_info *ip, struct iaddr *ia)
1268 {
1269 struct subnet *subnet;
1270 struct shared_network *share;
1271 isc_result_t status;
1272
1273 /* Special case for fallback network - not sure why this is
1274 necessary. */
1275 if (!ia) {
1276 const char *fnn = "fallback-net";
1277 status = shared_network_allocate (&ip -> shared_network, MDL);
1278 if (status != ISC_R_SUCCESS)
1279 log_fatal ("No memory for shared subnet: %s",
1280 isc_result_totext (status));
1281 ip -> shared_network -> name = dmalloc (strlen (fnn) + 1, MDL);
1282 if (!ip -> shared_network -> name)
1283 log_fatal("no memory for shared network");
1284 strcpy (ip -> shared_network -> name, fnn);
1285 return 1;
1286 }
1287
1288 /* If there's a registered subnet for this address,
1289 connect it together... */
1290 subnet = (struct subnet *)0;
1291 if (find_subnet (&subnet, *ia, MDL)) {
1292 /* If this interface has multiple aliases on the same
1293 subnet, ignore all but the first we encounter. */
1294 if (!subnet -> interface) {
1295 interface_reference (&subnet -> interface, ip, MDL);
1296 subnet -> interface_address = *ia;
1297 } else if (subnet -> interface != ip) {
1298 log_error ("Multiple interfaces match the %s: %s %s",
1299 "same subnet",
1300 subnet -> interface -> name, ip -> name);
1301 }
1302 share = subnet -> shared_network;
1303 if (ip -> shared_network &&
1304 ip -> shared_network != share) {
1305 log_fatal ("Interface %s matches multiple shared %s",
1306 ip -> name, "networks");
1307 } else {
1308 if (!ip -> shared_network)
1309 shared_network_reference
1310 (&ip -> shared_network, share, MDL);
1311 }
1312
1313 if (!share -> interface) {
1314 interface_reference (&share -> interface, ip, MDL);
1315 } else if (share -> interface != ip) {
1316 log_error ("Multiple interfaces match the %s: %s %s",
1317 "same shared network",
1318 share -> interface -> name, ip -> name);
1319 }
1320 subnet_dereference (&subnet, MDL);
1321 }
1322 return 1;
1323 }
1324
1325 static TIME shutdown_time;
1326 static int omapi_connection_count;
1327 enum dhcp_shutdown_state shutdown_state;
1328
1329 isc_result_t dhcp_io_shutdown (omapi_object_t *obj, void *foo)
1330 {
1331 /* Shut down all listeners. */
1332 if (shutdown_state == shutdown_listeners &&
1333 obj -> type == omapi_type_listener &&
1334 obj -> inner &&
1335 obj -> inner -> type == omapi_type_protocol_listener) {
1336 omapi_listener_destroy (obj, MDL);
1337 return ISC_R_SUCCESS;
1338 }
1339
1340 /* Shut down all existing omapi connections. */
1341 if (obj -> type == omapi_type_connection &&
1342 obj -> inner &&
1343 obj -> inner -> type == omapi_type_protocol) {
1344 if (shutdown_state == shutdown_drop_omapi_connections) {
1345 omapi_disconnect (obj, 1);
1346 }
1347 omapi_connection_count++;
1348 if (shutdown_state == shutdown_omapi_connections) {
1349 omapi_disconnect (obj, 0);
1350 return ISC_R_SUCCESS;
1351 }
1352 }
1353
1354 /* Shutdown all DHCP interfaces. */
1355 if (obj -> type == dhcp_type_interface &&
1356 shutdown_state == shutdown_dhcp) {
1357 dhcp_interface_remove (obj, (omapi_object_t *)0);
1358 return ISC_R_SUCCESS;
1359 }
1360 return ISC_R_SUCCESS;
1361 }
1362
1363 static isc_result_t dhcp_io_shutdown_countdown (void *vlp)
1364 {
1365 #if defined (FAILOVER_PROTOCOL)
1366 dhcp_failover_state_t *state;
1367 int failover_connection_count = 0;
1368 #endif
1369 struct timeval tv;
1370
1371 oncemore:
1372 if (shutdown_state == shutdown_listeners ||
1373 shutdown_state == shutdown_omapi_connections ||
1374 shutdown_state == shutdown_drop_omapi_connections ||
1375 shutdown_state == shutdown_dhcp) {
1376 omapi_connection_count = 0;
1377 omapi_io_state_foreach (dhcp_io_shutdown, 0);
1378 }
1379
1380 if ((shutdown_state == shutdown_listeners ||
1381 shutdown_state == shutdown_omapi_connections ||
1382 shutdown_state == shutdown_drop_omapi_connections) &&
1383 omapi_connection_count == 0) {
1384 shutdown_state = shutdown_dhcp;
1385 shutdown_time = cur_time;
1386 goto oncemore;
1387 } else if (shutdown_state == shutdown_listeners &&
1388 cur_time - shutdown_time > 4) {
1389 shutdown_state = shutdown_omapi_connections;
1390 shutdown_time = cur_time;
1391 } else if (shutdown_state == shutdown_omapi_connections &&
1392 cur_time - shutdown_time > 4) {
1393 shutdown_state = shutdown_drop_omapi_connections;
1394 shutdown_time = cur_time;
1395 } else if (shutdown_state == shutdown_drop_omapi_connections &&
1396 cur_time - shutdown_time > 4) {
1397 shutdown_state = shutdown_dhcp;
1398 shutdown_time = cur_time;
1399 goto oncemore;
1400 } else if (shutdown_state == shutdown_dhcp &&
1401 cur_time - shutdown_time > 4) {
1402 shutdown_state = shutdown_done;
1403 shutdown_time = cur_time;
1404 }
1405
1406 #if defined (FAILOVER_PROTOCOL)
1407 /* Set all failover peers into the shutdown state. */
1408 if (shutdown_state == shutdown_dhcp) {
1409 for (state = failover_states; state; state = state -> next) {
1410 if (state -> me.state == normal) {
1411 dhcp_failover_set_state (state, shut_down);
1412 failover_connection_count++;
1413 }
1414 if (state -> me.state == shut_down &&
1415 state -> partner.state != partner_down)
1416 failover_connection_count++;
1417 }
1418 }
1419
1420 if (shutdown_state == shutdown_done) {
1421 for (state = failover_states; state; state = state -> next) {
1422 if (state -> me.state == shut_down) {
1423 if (state -> link_to_peer)
1424 dhcp_failover_link_dereference (&state -> link_to_peer,
1425 MDL);
1426 dhcp_failover_set_state (state, recover);
1427 }
1428 }
1429 #if defined (DEBUG_MEMORY_LEAKAGE) && \
1430 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1431 free_everything ();
1432 omapi_print_dmalloc_usage_by_caller ();
1433 #endif
1434 if (no_pid_file == ISC_FALSE)
1435 (void) unlink(path_dhcpd_pid);
1436 exit (0);
1437 }
1438 #else
1439 if (shutdown_state == shutdown_done) {
1440 #if defined (DEBUG_MEMORY_LEAKAGE) && \
1441 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1442 free_everything ();
1443 omapi_print_dmalloc_usage_by_caller ();
1444 #endif
1445 if (no_pid_file == ISC_FALSE)
1446 (void) unlink(path_dhcpd_pid);
1447 exit (0);
1448 }
1449 #endif
1450 if (shutdown_state == shutdown_dhcp &&
1451 #if defined(FAILOVER_PROTOCOL)
1452 !failover_connection_count &&
1453 #endif
1454 ISC_TRUE) {
1455 shutdown_state = shutdown_done;
1456 shutdown_time = cur_time;
1457 goto oncemore;
1458 }
1459 tv.tv_sec = cur_tv.tv_sec + 1;
1460 tv.tv_usec = cur_tv.tv_usec;
1461 add_timeout (&tv,
1462 (void (*)(void *))dhcp_io_shutdown_countdown, 0, 0, 0);
1463 return ISC_R_SUCCESS;
1464 }
1465
1466 isc_result_t dhcp_set_control_state (control_object_state_t oldstate,
1467 control_object_state_t newstate)
1468 {
1469 struct timeval tv;
1470
1471 if (newstate != server_shutdown)
1472 return DHCP_R_INVALIDARG;
1473 /* Re-entry. */
1474 if (shutdown_signal == SIGUSR1)
1475 return ISC_R_SUCCESS;
1476 shutdown_time = cur_time;
1477 shutdown_state = shutdown_listeners;
1478 /* Called by user. */
1479 if (shutdown_signal == 0) {
1480 shutdown_signal = SIGUSR1;
1481 dhcp_io_shutdown_countdown (0);
1482 return ISC_R_SUCCESS;
1483 }
1484 /* Called on signal. */
1485 log_info("Received signal %d, initiating shutdown.", shutdown_signal);
1486 shutdown_signal = SIGUSR1;
1487
1488 /*
1489 * Prompt the shutdown event onto the timer queue
1490 * and return to the dispatch loop.
1491 */
1492 tv.tv_sec = cur_tv.tv_sec;
1493 tv.tv_usec = cur_tv.tv_usec + 1;
1494 add_timeout(&tv,
1495 (void (*)(void *))dhcp_io_shutdown_countdown, 0, 0, 0);
1496 return ISC_R_SUCCESS;
1497 }