]> git.ipfire.org Git - thirdparty/dhcp.git/blame - server/dhcpd.c
[#189] ISC address updated
[thirdparty/dhcp.git] / server / dhcpd.c
CommitLineData
d7837182
TL
1/* dhcpd.c
2
3 DHCP Server Daemon. */
4
5/*
109fa1d0 6 * Copyright (c) 2004-2020 by Internet Systems Consortium, Inc. ("ISC")
98311e4b 7 * Copyright (c) 1996-2003 by Internet Software Consortium
d7837182 8 *
7512d88b
TM
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/.
d7837182 12 *
98311e4b
DH
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.
d7837182 20 *
98311e4b 21 * Internet Systems Consortium, Inc.
429a56d7
TM
22 * PO Box 360
23 * Newmarket, NH 03857 USA
98311e4b 24 * <info@isc.org>
2c85ac9b 25 * https://www.isc.org/
49733f31 26 *
d7837182
TL
27 */
28
ae566556 29static const char copyright[] =
109fa1d0 30"Copyright 2004-2020 Internet Systems Consortium.";
ae566556
SR
31static const char arr [] = "All rights reserved.";
32static const char message [] = "Internet Systems Consortium DHCP Server";
33static const char url [] =
2c85ac9b 34"For info, please visit https://www.isc.org/software/dhcp/";
d7837182
TL
35
36#include "dhcpd.h"
68e50b9e 37#include <omapip/omapip_p.h>
fe5b0fdd 38#include <syslog.h>
47e8308d 39#include <signal.h>
a546f2a7 40#include <errno.h>
e847f983 41#include <limits.h>
28868515 42#include <sys/types.h>
be62cf06 43#include <sys/time.h>
7acd8753 44#include <isc/file.h>
d7837182 45
63971a83
DH
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 */
905c58b9 51# define group real_group
63971a83
DH
52# include <grp.h>
53# undef group
7a6c9368
SR
54
55/* global values so db.c can look at them */
56uid_t set_uid = 0;
57gid_t set_gid = 0;
63971a83
DH
58#endif /* PARANOIA */
59
bf6f8fce
FD
60struct class unknown_class;
61struct class known_class;
62
3b5a1486
TL
63struct iaddr server_identifier;
64int server_identifier_matched;
65
144cdb49 66#if defined (NSUPDATE)
fafe8463
TL
67
68/* This stuff is always executed to figure the default values for certain
69 ddns variables. */
68f55908 70char std_nsupdate [] = " \n\
d7f6db15 71option server.ddns-hostname = \n\
d9b2a590 72 pick (option fqdn.hostname, option host-name, config-option host-name); \n\
ac9c906a 73option server.ddns-domainname = config-option domain-name; \n\
fafe8463
TL
74option server.ddns-rev-domainname = \"in-addr.arpa.\";";
75
905c58b9
TM
76/* Stores configured DDNS conflict detection flags */
77u_int16_t ddns_conflict_mask;
144cdb49 78#endif /* NSUPDATE */
905c58b9 79
98bf1607 80int ddns_update_style;
cde11a4c 81int dont_use_fsync = 0; /* 0 = default, use fsync, 1 = don't use fsync */
7116a34f 82int server_id_check = 0; /* 0 = default, don't check server id, 1 = do check */
bafa7b74
TM
83
84#ifdef DHCPv6
b53ba157 85int prefix_length_mode = PLM_PREFER;
bafa7b74
TM
86int do_release_on_roam = 0; /* 0 = default, do not release v6 leases on roam */
87#endif
77222488 88
c2e5ee28
TM
89#ifdef EUI_64
90int persist_eui64 = 1; /* 1 = write EUI64 leases to disk, 0 = don't */
91#endif
92
347d4962 93int authoring_byte_order = 0; /* 0 = not set */
cc1bd34e 94int lease_id_format = TOKEN_OCTAL; /* octal by default */
a5252220 95u_int32_t abandon_lease_time = DEFAULT_ABANDON_LEASE_TIME;
347d4962 96
b1b7b521
TL
97const char *path_dhcpd_conf = _PATH_DHCPD_CONF;
98const char *path_dhcpd_db = _PATH_DHCPD_DB;
99const char *path_dhcpd_pid = _PATH_DHCPD_PID;
4a5bfeac
SR
100/* False (default) => we write and use a pid file */
101isc_boolean_t no_pid_file = ISC_FALSE;
d7837182 102
0a347607
TL
103int dhcp_max_agent_option_packet_length = DHCP_MTU_MAX;
104
49146f3c 105static omapi_auth_key_t *omapi_key = (omapi_auth_key_t *)0;
a920d3da
TL
106int omapi_port;
107
108#if defined (TRACING)
109trace_type_t *trace_srandom;
110#endif
49146f3c 111
7acd8753
FD
112char *progname;
113
49146f3c
DN
114static isc_result_t verify_addr (omapi_object_t *l, omapi_addr_t *addr) {
115 return ISC_R_SUCCESS;
116}
117
118static isc_result_t verify_auth (omapi_object_t *p, omapi_auth_key_t *a) {
119 if (a != omapi_key)
98bf1607 120 return DHCP_R_INVALIDKEY;
49146f3c
DN
121 return ISC_R_SUCCESS;
122}
123
d758ad8c
TL
124static void omapi_listener_start (void *foo)
125{
126 omapi_object_t *listener;
127 isc_result_t result;
be62cf06 128 struct timeval tv;
d758ad8c
TL
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));
5d082abd
TM
143 tv.tv_sec = cur_tv.tv_sec + 5;
144 tv.tv_usec = cur_tv.tv_usec;
be62cf06 145 add_timeout (&tv, omapi_listener_start, 0, 0, 0);
d758ad8c
TL
146 }
147 omapi_object_dereference (&listener, MDL);
148}
149
7a6c9368
SR
150#ifndef UNIT_TEST
151
68dfa910
FD
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
b2cb745b
SR
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
0c03eaef 198 * command doesn't include its argument.
b2cb745b
SR
199 *
200 * \param sfmt - The basic string and format for the specific error
0c03eaef 201 * \param sarg - Generally the offending argument from the command line.
b2cb745b
SR
202 *
203 * \return Nothing
204 */
205static char use_noarg[] = "No argument for command: %s ";
206
207static void
208usage(const char *sfmt, const char *sarg) {
209 log_info("%s %s", message, PACKAGE_VERSION);
210 log_info(copyright);
211 log_info(arr);
fc4f62fe 212 log_info(url);
b2cb745b
SR
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
68dfa910
FD
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);
b2cb745b
SR
229}
230
7a6c9368
SR
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
63971a83
DH
235#if defined (PARANOIA)
236/* to be used in one of two possible scenarios */
237static 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
905c58b9 251int
98bd7ca0 252main(int argc, char **argv) {
185d16f9 253 int fd;
c6dff01f 254 int i, status;
d7837182 255 struct servent *ent;
28868515 256 char *s;
1ac5bc1a 257 int cftest = 0;
8f450cac 258 int lftest = 0;
d7837182 259 int pid;
c6dff01f 260 char pbuf [20];
001b9d53 261#ifndef DEBUG
c6dff01f 262 int daemon = 1;
29b23207 263 int dfd[2] = { -1, -1 };
955d158b 264#endif
632d8396 265 int quiet = 0;
e3a84e35 266 char *server = (char *)0;
972bde18 267 isc_result_t result;
b1b7b521 268 unsigned seed;
972bde18 269 struct interface_info *ip;
98bf1607 270#if defined (NSUPDATE)
77222488
TL
271 struct parse *parse;
272 int lose;
98bf1607 273#endif
ab77c8b8
TM
274 int have_dhcpd_conf = 0;
275 int have_dhcpd_db = 0;
276 int have_dhcpd_pid = 0;
c998be87 277#ifdef DHCPv6
98bd7ca0 278 int local_family_set = 0;
785c1a51
FD
279#ifdef DHCP4o6
280 u_int16_t dhcp4o6_port = 0;
281#endif /* DHCP4o6 */
c998be87 282#endif /* DHCPv6 */
662df45a 283#if defined (TRACING)
a920d3da
TL
284 char *traceinfile = (char *)0;
285 char *traceoutfile = (char *)0;
662df45a 286#endif
d7837182 287
63971a83
DH
288#if defined (PARANOIA)
289 char *set_user = 0;
290 char *set_group = 0;
291 char *set_chroot = 0;
63971a83
DH
292#endif /* PARANOIA */
293
7acd8753
FD
294#ifdef OLD_LOG_NAME
295 progname = "dhcpd";
296#else
297 progname = argv[0];
298#endif
299
185d16f9
SK
300 /* Make sure that file descriptors 0 (stdin), 1, (stdout), and
301 2 (stderr) are open. To do this, we assume that when we
20ae1aff 302 open a file the lowest available file descriptor is used. */
509df655 303 fd = open("/dev/null", O_RDWR);
185d16f9 304 if (fd == 0)
509df655 305 fd = open("/dev/null", O_RDWR);
185d16f9 306 if (fd == 1)
509df655 307 fd = open("/dev/null", O_RDWR);
185d16f9
SK
308 if (fd == 2)
309 log_perror = 0; /* No sense logging to /dev/null. */
310 else if (fd != -1)
509df655 311 close(fd);
fb5f8793 312
29b23207
FD
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);
68dfa910
FD
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);
29b23207
FD
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
98bf1607 403 /* Set up the isc and dns library managers */
61ef216b
SR
404 status = dhcp_context_create(DHCP_CONTEXT_PRE_DB,
405 NULL, NULL);
98bf1607
SR
406 if (status != ISC_R_SUCCESS)
407 log_fatal("Can't initialize context: %s",
408 isc_result_totext(status));
409
f3a05d72
TL
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
fafe8463
TL
419 /* Set up the OMAPI wrappers for common objects. */
420 dhcp_db_objects_setup ();
f3a05d72
TL
421 /* Set up the OMAPI wrappers for various server database internal
422 objects. */
f3a05d72
TL
423 dhcp_common_objects_setup ();
424
c6dff01f 425 /* Initially, log errors to stderr as well as to syslogd. */
7acd8753
FD
426 openlog (isc_file_basename(progname),
427 DHCP_LOG_OPTIONS, DHCPD_LOG_FACILITY);
40950384 428
d7837182
TL
429 for (i = 1; i < argc; i++) {
430 if (!strcmp (argv [i], "-p")) {
431 if (++i == argc)
b2cb745b 432 usage(use_noarg, argv[i-1]);
59112e84 433 local_port = validate_port (argv [i]);
8ae2d595 434 log_debug ("binding to user-specified port %d",
a60076f9 435 ntohs (local_port));
c6dff01f
TL
436 } else if (!strcmp (argv [i], "-f")) {
437#ifndef DEBUG
29b23207 438 /* daemon = 0; */
c6dff01f
TL
439#endif
440 } else if (!strcmp (argv [i], "-d")) {
77549355 441#ifndef DEBUG
29b23207 442 /* daemon = 0; */
77549355 443#endif
f5d07a38 444 log_perror = -1;
e3a84e35
TL
445 } else if (!strcmp (argv [i], "-s")) {
446 if (++i == argc)
b2cb745b 447 usage(use_noarg, argv[i-1]);
e3a84e35 448 server = argv [i];
63971a83
DH
449#if defined (PARANOIA)
450 } else if (!strcmp (argv [i], "-user")) {
451 if (++i == argc)
b2cb745b 452 usage(use_noarg, argv[i-1]);
63971a83
DH
453 set_user = argv [i];
454 } else if (!strcmp (argv [i], "-group")) {
455 if (++i == argc)
b2cb745b 456 usage(use_noarg, argv[i-1]);
63971a83
DH
457 set_group = argv [i];
458 } else if (!strcmp (argv [i], "-chroot")) {
459 if (++i == argc)
b2cb745b 460 usage(use_noarg, argv[i-1]);
63971a83
DH
461 set_chroot = argv [i];
462#endif /* PARANOIA */
840bd203
TL
463 } else if (!strcmp (argv [i], "-cf")) {
464 if (++i == argc)
b2cb745b 465 usage(use_noarg, argv[i-1]);
840bd203 466 path_dhcpd_conf = argv [i];
ab77c8b8 467 have_dhcpd_conf = 1;
840bd203
TL
468 } else if (!strcmp (argv [i], "-lf")) {
469 if (++i == argc)
b2cb745b 470 usage(use_noarg, argv[i-1]);
840bd203 471 path_dhcpd_db = argv [i];
ab77c8b8 472 have_dhcpd_db = 1;
23b21725
TL
473 } else if (!strcmp (argv [i], "-pf")) {
474 if (++i == argc)
b2cb745b 475 usage(use_noarg, argv[i-1]);
23b21725 476 path_dhcpd_pid = argv [i];
ab77c8b8 477 have_dhcpd_pid = 1;
4a5bfeac
SR
478 } else if (!strcmp(argv[i], "--no-pid")) {
479 no_pid_file = ISC_TRUE;
40f63fcd
TL
480 } else if (!strcmp (argv [i], "-t")) {
481 /* test configurations only */
482#ifndef DEBUG
29b23207 483 /* daemon = 0; */
40f63fcd
TL
484#endif
485 cftest = 1;
486 log_perror = -1;
8f450cac
TL
487 } else if (!strcmp (argv [i], "-T")) {
488 /* test configurations and lease file only */
489#ifndef DEBUG
29b23207 490 /* daemon = 0; */
8f450cac
TL
491#endif
492 cftest = 1;
493 lftest = 1;
494 log_perror = -1;
deb0cb72 495 } else if (!strcmp (argv [i], "-q")) {
632d8396
TL
496 quiet = 1;
497 quiet_interface_discovery = 1;
75135a3f 498#ifdef DHCPv6
98bd7ca0
DH
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;
785c1a51
FD
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 */
75135a3f 524#endif /* DHCPv6 */
662df45a 525#if defined (TRACING)
a920d3da
TL
526 } else if (!strcmp (argv [i], "-tf")) {
527 if (++i == argc)
b2cb745b 528 usage(use_noarg, argv[i-1]);
a920d3da
TL
529 traceoutfile = argv [i];
530 } else if (!strcmp (argv [i], "-play")) {
531 if (++i == argc)
b2cb745b 532 usage(use_noarg, argv[i-1]);
a920d3da
TL
533 traceinfile = argv [i];
534 trace_replay_init ();
662df45a 535#endif /* TRACING */
d992e204 536 } else if (argv [i][0] == '-') {
b2cb745b 537 usage("Unknown command %s", argv[i]);
d992e204
TL
538 } else {
539 struct interface_info *tmp =
f3a05d72 540 (struct interface_info *)0;
66be0ad1
SR
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]));
f3a05d72
TL
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));
d992e204 550 strcpy (tmp -> name, argv [i]);
f3a05d72
TL
551 if (interfaces) {
552 interface_reference (&tmp -> next,
553 interfaces, MDL);
554 interface_dereference (&interfaces, MDL);
555 }
556 interface_reference (&interfaces, tmp, MDL);
d992e204 557 tmp -> flags = INTERFACE_REQUESTED;
d992e204 558 }
d7837182
TL
559 }
560
785c1a51
FD
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
ab77c8b8 573 if (!have_dhcpd_conf && (s = getenv ("PATH_DHCPD_CONF"))) {
cfa7212d
TL
574 path_dhcpd_conf = s;
575 }
75135a3f
EH
576
577#ifdef DHCPv6
578 if (local_family == AF_INET6) {
579 /* DHCPv6: override DHCPv4 lease and pid filenames */
ab77c8b8 580 if (!have_dhcpd_db) {
75135a3f
EH
581 if ((s = getenv ("PATH_DHCPD6_DB")))
582 path_dhcpd_db = s;
583 else
584 path_dhcpd_db = _PATH_DHCPD6_DB;
585 }
ab77c8b8 586 if (!have_dhcpd_pid) {
75135a3f
EH
587 if ((s = getenv ("PATH_DHCPD6_PID")))
588 path_dhcpd_pid = s;
589 else
590 path_dhcpd_pid = _PATH_DHCPD6_PID;
591 }
592 } else
ab77c8b8 593#endif /* DHCPv6 */
75135a3f 594 {
ab77c8b8 595 if (!have_dhcpd_db && (s = getenv ("PATH_DHCPD_DB"))) {
75135a3f 596 path_dhcpd_db = s;
ab77c8b8 597 have_dhcpd_db = 1;
75135a3f 598 }
ab77c8b8 599 if (!have_dhcpd_pid && (s = getenv ("PATH_DHCPD_PID"))) {
75135a3f 600 path_dhcpd_pid = s;
ab77c8b8 601 have_dhcpd_pid = 1;
75135a3f
EH
602 }
603 }
cfa7212d 604
a546f2a7
EH
605 /*
606 * convert relative path names to absolute, for files that need
607 * to be reopened after chdir() has been called
608 */
ab77c8b8 609 if (have_dhcpd_db && path_dhcpd_db[0] != '/') {
db4e4aa2 610 path_dhcpd_db = absolute_path(path_dhcpd_db);
a546f2a7
EH
611 }
612
632d8396 613 if (!quiet) {
fe5b0fdd 614 log_info("%s %s", message, PACKAGE_VERSION);
8ae2d595
TL
615 log_info (copyright);
616 log_info (arr);
8ae2d595 617 log_info (url);
77222488 618 } else {
77222488
TL
619 log_perror = 0;
620 }
c6dff01f 621
a920d3da
TL
622#if defined (TRACING)
623 trace_init (set_time, MDL);
98311e4b
DH
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 }
a920d3da
TL
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);
158a34fb 635#if defined (NSUPDATE)
7aa153b8 636 trace_ddns_init();
158a34fb 637#endif /* NSUPDATE */
a920d3da
TL
638#endif
639
63971a83
DH
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
d7837182 678 /* Default to the DHCP/BOOTP port. */
a60076f9 679 if (!local_port)
d7837182 680 {
a920d3da 681 if ((s = getenv ("DHCPD_PORT"))) {
59112e84 682 local_port = validate_port (s);
a920d3da
TL
683 log_debug ("binding to environment-specified port %d",
684 ntohs (local_port));
685 } else {
98bd7ca0
DH
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 }
1e39d101 702#ifndef __CYGWIN32__ /* XXX */
a920d3da 703 endservent ();
1e39d101 704#endif
a920d3da 705 }
d7837182 706 }
905c58b9 707
98bd7ca0
DH
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 }
a60076f9 719
e3a84e35 720 if (server) {
2e13ba55
SK
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 }
e3a84e35
TL
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
d7837182 739 /* Get the current time... */
be62cf06 740 gettimeofday(&cur_tv, NULL);
d7837182 741
77222488
TL
742 /* Set up the initial dhcp option universe. */
743 initialize_common_option_spaces ();
744 initialize_server_option_spaces ();
745
fafe8463
TL
746 /* Add the ddns update style enumeration prior to parsing. */
747 add_enumeration (&ddns_styles);
ee5a7404 748 add_enumeration (&syslog_enum);
33692791
DH
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
fafe8463 757
20916cae
TL
758 if (!group_allocate (&root_group, MDL))
759 log_fatal ("Can't allocate root group!");
760 root_group -> authoritative = 0;
77222488 761
a920d3da
TL
762 /* Set up various hooks. */
763 dhcp_interface_setup_hook = dhcpd_interface_setup_hook;
764 bootp_packet_handler = do_packet;
fe5b0fdd 765#ifdef DHCPv6
1a006ff6 766 add_enumeration (&prefix_length_modes);
98bd7ca0 767 dhcpv6_packet_handler = do_packet6;
fe5b0fdd 768#endif /* DHCPv6 */
a920d3da 769
144cdb49 770#if defined (NSUPDATE)
77222488 771 /* Set up the standard name service updater routine. */
c40e954c
EH
772 parse = NULL;
773 status = new_parse(&parse, -1, std_nsupdate, sizeof(std_nsupdate) - 1,
dc66a995 774 "standard name service update routine", 0);
77222488 775 if (status != ISC_R_SUCCESS)
d8e1567c 776 log_fatal ("can't begin parsing name service updater!");
77222488 777
c40e954c
EH
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);
77222488 786 }
144cdb49 787#endif
77222488 788
a920d3da 789 /* Initialize icmp support... */
30a122ee
TL
790 if (!cftest && !lftest)
791 icmp_startup (1, lease_pinged);
a920d3da
TL
792
793#if defined (TRACING)
794 if (traceinfile) {
ab77c8b8 795 if (!have_dhcpd_db) {
a920d3da
TL
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. **");
905c58b9 800 }
a920d3da 801 trace_file_replay (traceinfile);
d758ad8c 802
98311e4b 803#if defined (DEBUG_MEMORY_LEAKAGE) && \
d758ad8c
TL
804 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
805 free_everything ();
905c58b9 806 omapi_print_dmalloc_usage_by_caller ();
d758ad8c
TL
807#endif
808
a920d3da
TL
809 exit (0);
810 }
811#endif
812
98bd7ca0 813#ifdef DHCPv6
1d9774ab 814 /* set up DHCPv6 hashes */
9322442f 815 if (!ia_new_hash(&ia_na_active, DEFAULT_HASH_SIZE, MDL)) {
1d9774ab
FD
816 log_fatal("Out of memory creating hash for active IA_NA.");
817 }
9322442f 818 if (!ia_new_hash(&ia_ta_active, DEFAULT_HASH_SIZE, MDL)) {
1d9774ab
FD
819 log_fatal("Out of memory creating hash for active IA_TA.");
820 }
9322442f 821 if (!ia_new_hash(&ia_pd_active, DEFAULT_HASH_SIZE, MDL)) {
1d9774ab 822 log_fatal("Out of memory creating hash for active IA_PD.");
98bd7ca0
DH
823 }
824#endif /* DHCPv6 */
825
d7837182 826 /* Read the dhcpd.conf file... */
8f450cac 827 if (readconf () != ISC_R_SUCCESS)
8ae2d595 828 log_fatal ("Configuration file errors encountered -- exiting");
d7837182 829
d758ad8c 830 postconf_initialization (quiet);
3956569b 831
6ec59010
TM
832#if defined (FAILOVER_PROTOCOL)
833 dhcp_failover_sanity_check();
834#endif
835
785c1a51
FD
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
63971a83
DH
845#if defined (PARANOIA) && !defined (EARLY_CHROOT)
846 if (set_chroot) setup_chroot (set_chroot);
847#endif /* PARANOIA && !EARLY_CHROOT */
d758ad8c 848
fb98e02e
TM
849#ifdef DHCPv6
850 /* log info about ipv6_ponds with large address ranges */
851 report_jumbo_ranges();
852#endif
853
40f63fcd 854 /* test option should cause an early exit */
c2e5ee28 855 if (cftest && !lftest) {
40f63fcd 856 exit(0);
c2e5ee28 857 }
40f63fcd 858
992dc765
SR
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
a920d3da
TL
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. */
785c1a51
FD
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 */
98bd7ca0
DH
910 discover_interfaces(DISCOVER_SERVER);
911
912#ifdef DHCPv6
913 /*
914 * Remove addresses from our pools that we should not issue
915 * to clients.
c61eba3b 916 *
905c58b9
TM
917 * We currently have no support for this in IPv4. It is not
918 * as important in IPv4, as making pools with ranges that
c61eba3b
SK
919 * leave out interfaces and hosts is fairly straightforward
920 * using range notation, but not so handy with CIDR notation.
98bd7ca0 921 */
c61eba3b
SK
922 if (local_family == AF_INET6) {
923 mark_hosts_unavailable();
80c9fdb0 924 mark_phosts_unavailable();
c61eba3b
SK
925 mark_interfaces_unavailable();
926 }
98bd7ca0
DH
927#endif /* DHCPv6 */
928
a920d3da
TL
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
d758ad8c 946 postdb_startup ();
a920d3da 947
fe5b0fdd 948#ifdef DHCPv6
98bd7ca0 949 /*
90a062fb
SR
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)
785c1a51 955 * generate a new one from the interface hardware addresses.
90a062fb 956 * In all cases we write it out to the lease file.
98bd7ca0
DH
957 * See dhcpv6.c for discussion of setting DUID.
958 */
90a062fb
SR
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.");
98bd7ca0 963 }
90a062fb 964 write_server_duid();
785c1a51
FD
965#ifdef DHCP4o6
966 if (dhcpv4_over_dhcpv6)
967 dhcp4o6_setup(dhcp4o6_port);
968#endif /* DHCP4o6 */
fe5b0fdd 969#endif /* DHCPv6 */
98bd7ca0 970
a920d3da 971#ifndef DEBUG
4a5bfeac 972 /*
992dc765
SR
973 * Second part of dealing with pid files. Now
974 * that we have forked we can write our pid if
975 * appropriate.
4a5bfeac
SR
976 */
977 if (no_pid_file == ISC_FALSE) {
4a5bfeac
SR
978 i = open(path_dhcpd_pid, O_WRONLY|O_CREAT|O_TRUNC, 0644);
979 if (i >= 0) {
980 sprintf(pbuf, "%d\n", (int) getpid());
992dc765 981 IGNORE_RET(write(i, pbuf, strlen(pbuf)));
4a5bfeac
SR
982 close(i);
983 } else {
984 log_error("Can't create PID file %s: %m.",
985 path_dhcpd_pid);
986 }
987 }
182b187e 988
d8c7c34e
SR
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);
905c58b9 997 }
d8c7c34e
SR
998
999 if (set_uid) {
1000 if (setuid (set_uid))
1001 log_fatal ("setuid(%d): %m", (int) set_uid);
1002 }
1003#endif /* PARANOIA */
1004
a920d3da
TL
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) {
29b23207
FD
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
a920d3da 1022 /* Become session leader and get pid... */
dc9d7b08 1023 (void) setsid();
185d16f9
SK
1024
1025 /* Close standard I/O descriptors. */
dc9d7b08
MA
1026 (void) close(0);
1027 (void) close(1);
1028 (void) close(2);
185d16f9
SK
1029
1030 /* Reopen them on /dev/null. */
dc9d7b08
MA
1031 (void) open("/dev/null", O_RDWR);
1032 (void) open("/dev/null", O_RDWR);
1033 (void) open("/dev/null", O_RDWR);
185d16f9 1034 log_perror = 0; /* No sense logging to /dev/null. */
a920d3da 1035
ae566556 1036 IGNORE_RET (chdir("/"));
a920d3da
TL
1037 }
1038#endif /* !DEBUG */
1039
d758ad8c
TL
1040#if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \
1041 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
a920d3da
TL
1042 dmalloc_cutoff_generation = dmalloc_generation;
1043 dmalloc_longterm = dmalloc_outstanding;
1044 dmalloc_outstanding = 0;
1045#endif
1046
d758ad8c
TL
1047 omapi_set_int_value ((omapi_object_t *)dhcp_control_object,
1048 (omapi_object_t *)0, "state", server_running);
1049
e9326fd0
SR
1050#if defined(ENABLE_GENTLE_SHUTDOWN)
1051 /* no signal handlers until we deal with the side effects */
47e8308d
SR
1052 /* install signal handlers */
1053 signal(SIGINT, dhcp_signal_handler); /* control-c */
1054 signal(SIGTERM, dhcp_signal_handler); /* kill */
e9326fd0 1055#endif
47e8308d 1056
f88446f1
SR
1057 /* Log that we are about to start working */
1058 log_info("Server starting service.");
1059
47e8308d
SR
1060 /*
1061 * Receive packets and dispatch them...
0895c955 1062 * dispatch() will never return.
47e8308d 1063 */
a920d3da
TL
1064 dispatch ();
1065
47e8308d 1066 /* Let's return status code */
a920d3da
TL
1067 return 0;
1068}
98bd7ca0 1069#endif /* !UNIT_TEST */
a920d3da
TL
1070
1071void postconf_initialization (int quiet)
1072{
cde11a4c 1073 struct option_state *options = NULL;
a920d3da
TL
1074 struct data_string db;
1075 struct option_cache *oc;
1076 char *s;
1077 isc_result_t result;
a920d3da 1078 int tmp;
61ef216b
SR
1079#if defined (NSUPDATE)
1080 struct in_addr local4, *local4_ptr = NULL;
1081 struct in6_addr local6, *local6_ptr = NULL;
1082#endif
a920d3da 1083
b62e4418 1084 /* Now try to get the lease file name. */
cde11a4c 1085 option_state_allocate(&options, MDL);
b62e4418 1086
a7341359
SR
1087 execute_statements_in_scope(NULL, NULL, NULL, NULL, NULL,
1088 options, &global_scope, root_group,
1089 NULL, NULL);
cde11a4c
SR
1090 memset(&db, 0, sizeof db);
1091 oc = lookup_option(&server_universe, options, SV_LEASE_FILE_NAME);
b62e4418 1092 if (oc &&
cde11a4c
SR
1093 evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
1094 &global_scope, oc, MDL)) {
1095 s = dmalloc(db.len + 1, MDL);
b62e4418 1096 if (!s)
cde11a4c
SR
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);
b62e4418
TL
1101 path_dhcpd_db = s;
1102 }
75135a3f 1103
cde11a4c 1104 oc = lookup_option(&server_universe, options, SV_PID_FILE_NAME);
b62e4418 1105 if (oc &&
cde11a4c
SR
1106 evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
1107 &global_scope, oc, MDL)) {
1108 s = dmalloc(db.len + 1, MDL);
b62e4418 1109 if (!s)
cde11a4c
SR
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);
b62e4418
TL
1114 path_dhcpd_pid = s;
1115 }
1116
75135a3f
EH
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 &&
cde11a4c
SR
1126 evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
1127 &global_scope, oc, MDL)) {
1128 s = dmalloc(db.len + 1, MDL);
75135a3f 1129 if (!s)
cde11a4c
SR
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);
75135a3f
EH
1134 path_dhcpd_db = s;
1135 }
1136
1137 oc = lookup_option(&server_universe, options,
1138 SV_DHCPV6_PID_FILE_NAME);
1139 if (oc &&
cde11a4c
SR
1140 evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
1141 &global_scope, oc, MDL)) {
1142 s = dmalloc(db.len + 1, MDL);
75135a3f 1143 if (!s)
cde11a4c
SR
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);
75135a3f
EH
1148 path_dhcpd_pid = s;
1149 }
a2a0f98c
FD
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
75135a3f
EH
1173 }
1174#endif /* DHCPv6 */
1175
312a6a35 1176 omapi_port = -1;
cde11a4c 1177 oc = lookup_option(&server_universe, options, SV_OMAPI_PORT);
ece9e253 1178 if (oc &&
cde11a4c
SR
1179 evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
1180 &global_scope, oc, MDL)) {
ece9e253 1181 if (db.len == 2) {
cde11a4c 1182 omapi_port = getUShort(db.data);
ece9e253 1183 } else
cde11a4c
SR
1184 log_fatal("invalid omapi port data length");
1185 data_string_forget(&db, MDL);
ece9e253
TL
1186 }
1187
cde11a4c 1188 oc = lookup_option(&server_universe, options, SV_OMAPI_KEY);
49146f3c 1189 if (oc &&
cde11a4c
SR
1190 evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
1191 &global_scope, oc, MDL)) {
1192 s = dmalloc(db.len + 1, MDL);
49146f3c 1193 if (!s)
cde11a4c
SR
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);
49146f3c 1200 if (result != ISC_R_SUCCESS)
cde11a4c
SR
1201 log_fatal("OMAPI key %s: %s",
1202 s, isc_result_totext (result));
49146f3c
DN
1203 }
1204
cde11a4c 1205 oc = lookup_option(&server_universe, options, SV_LOCAL_PORT);
ece9e253 1206 if (oc &&
cde11a4c
SR
1207 evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
1208 &global_scope, oc, MDL)) {
ece9e253 1209 if (db.len == 2) {
cde11a4c 1210 local_port = htons(getUShort (db.data));
ece9e253 1211 } else
cde11a4c
SR
1212 log_fatal("invalid local port data length");
1213 data_string_forget(&db, MDL);
ece9e253
TL
1214 }
1215
cde11a4c 1216 oc = lookup_option(&server_universe, options, SV_REMOTE_PORT);
ece9e253 1217 if (oc &&
cde11a4c
SR
1218 evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
1219 &global_scope, oc, MDL)) {
ece9e253 1220 if (db.len == 2) {
cde11a4c 1221 remote_port = htons(getUShort (db.data));
ece9e253 1222 } else
cde11a4c
SR
1223 log_fatal("invalid remote port data length");
1224 data_string_forget(&db, MDL);
ece9e253
TL
1225 }
1226
cde11a4c
SR
1227 oc = lookup_option(&server_universe, options,
1228 SV_LIMITED_BROADCAST_ADDRESS);
ece9e253 1229 if (oc &&
cde11a4c
SR
1230 evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
1231 &global_scope, oc, MDL)) {
ece9e253 1232 if (db.len == 4) {
cde11a4c 1233 memcpy(&limited_broadcast, db.data, 4);
ece9e253 1234 } else
cde11a4c
SR
1235 log_fatal("invalid broadcast address data length");
1236 data_string_forget(&db, MDL);
ece9e253
TL
1237 }
1238
cde11a4c 1239 oc = lookup_option(&server_universe, options, SV_LOCAL_ADDRESS);
ece9e253 1240 if (oc &&
cde11a4c
SR
1241 evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
1242 &global_scope, oc, MDL)) {
ece9e253 1243 if (db.len == 4) {
cde11a4c 1244 memcpy(&local_address, db.data, 4);
ece9e253 1245 } else
cde11a4c
SR
1246 log_fatal("invalid local address data length");
1247 data_string_forget(&db, MDL);
ece9e253
TL
1248 }
1249
cde11a4c 1250 oc = lookup_option(&server_universe, options, SV_DDNS_UPDATE_STYLE);
fafe8463 1251 if (oc) {
cde11a4c
SR
1252 if (evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
1253 &global_scope, oc, MDL)) {
fafe8463 1254 if (db.len == 1) {
cde11a4c 1255 ddns_update_style = db.data[0];
fafe8463 1256 } else
cde11a4c
SR
1257 log_fatal("invalid dns update type");
1258 data_string_forget(&db, MDL);
fafe8463 1259 }
d7f6db15 1260 } else {
884a458f 1261 ddns_update_style = DDNS_UPDATE_STYLE_NONE;
d7f6db15 1262 }
98bf1607
SR
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 }
61ef216b
SR
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
ca22af89
TM
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 }
905c58b9
TM
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
98bf1607
SR
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
fafe8463 1315
3956569b
TM
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
cde11a4c 1322 oc = lookup_option(&server_universe, options, SV_LOG_FACILITY);
ee5a7404 1323 if (oc) {
cde11a4c
SR
1324 if (evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
1325 &global_scope, oc, MDL)) {
ee5a7404
TL
1326 if (db.len == 1) {
1327 closelog ();
7acd8753
FD
1328 openlog(isc_file_basename(progname),
1329 DHCP_LOG_OPTIONS, db.data[0]);
a920d3da
TL
1330 /* Log the startup banner into the new
1331 log file. */
3956569b
TM
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;
ee5a7404 1340 } else
cde11a4c
SR
1341 log_fatal("invalid log facility");
1342 data_string_forget(&db, MDL);
ee5a7404
TL
1343 }
1344 }
e422b8c7
TM
1345
1346#if defined(DELAYED_ACK)
6368a1bd
DH
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 }
700e3fca
TM
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
ee5a7404 1369
f8cbf390
DH
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 }
e422b8c7 1385#endif
f8cbf390 1386
cde11a4c
SR
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
7116a34f
TM
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
bafa7b74 1403#ifdef DHCPv6
1a006ff6 1404 oc = lookup_option(&server_universe, options, SV_PREFIX_LEN_MODE);
905c58b9 1405 if ((oc != NULL) &&
1a006ff6
TM
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 }
bafa7b74 1416#endif
1a006ff6 1417
a5252220
TM
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
30593241
TM
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
c2e5ee28
TM
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
bafa7b74
TM
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
30593241 1465
3933e2aa
SR
1466#if defined (BINARY_LEASES)
1467 if (local_family == AF_INET) {
1468 log_info("Source compiled to use binary-leases");
1469 }
1470#endif
1471
b62e4418 1472 /* Don't need the options anymore. */
cde11a4c 1473 option_state_dereference(&options, MDL);
d7837182
TL
1474}
1475
d758ad8c
TL
1476void 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
d9b43370
SK
1487
1488 /*
1489 * Begin our lease timeout background task.
1490 */
1491 schedule_all_ipv6_lease_timeouts();
d758ad8c
TL
1492}
1493
9acb0bab
TL
1494void 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
20916cae
TL
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));
9acb0bab
TL
1512 return;
1513 }
1514
1515 if (!lp -> state) {
d8e1567c 1516#if defined (FAILOVER_PROTOCOL)
b73c184a
TL
1517 if (!lp -> pool ||
1518 !lp -> pool -> failover_peer)
d8e1567c 1519#endif
b73c184a
TL
1520 log_debug ("ICMP Echo Reply for %s late or spurious.",
1521 piaddr (from));
20916cae 1522 goto out;
9acb0bab
TL
1523 }
1524
c0a8b011 1525 if (lp -> ends > cur_time) {
b73c184a 1526 log_debug ("ICMP Echo reply while lease %s valid.",
4bd8800e 1527 piaddr (from));
c0a8b011
TL
1528 }
1529
9acb0bab
TL
1530 /* At this point it looks like we pinged a lease and got a
1531 response, which shouldn't have happened. */
4bd8800e
TL
1532 data_string_forget (&lp -> state -> parameter_request_list, MDL);
1533 free_lease_state (lp -> state, MDL);
9acb0bab
TL
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;
20916cae
TL
1539 out:
1540 lease_dereference (&lp, MDL);
9acb0bab
TL
1541}
1542
1543void lease_ping_timeout (vlp)
1544 void *vlp;
1545{
1546 struct lease *lp = vlp;
1547
77222488
TL
1548#if defined (DEBUG_MEMORY_LEAKAGE)
1549 unsigned long previous_outstanding = dmalloc_outstanding;
1550#endif
1551
9acb0bab
TL
1552 --outstanding_pings;
1553 dhcp_reply (lp);
77222488
TL
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
d758ad8c 1561#if defined (DEBUG_MEMORY_LEAKAGE)
77222488
TL
1562 dmalloc_dump_outstanding ();
1563#endif
9acb0bab 1564}
20916cae
TL
1565
1566int 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";
20916cae
TL
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);
88c3ff5d
TM
1581 if (!ip -> shared_network -> name)
1582 log_fatal("no memory for shared network");
20916cae
TL
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) {
d758ad8c 1594 interface_reference (&subnet -> interface, ip, MDL);
20916cae
TL
1595 subnet -> interface_address = *ia;
1596 } else if (subnet -> interface != ip) {
905c58b9 1597 log_error ("Multiple interfaces match the %s: %s %s",
20916cae
TL
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 }
905c58b9 1611
20916cae
TL
1612 if (!share -> interface) {
1613 interface_reference (&share -> interface, ip, MDL);
1614 } else if (share -> interface != ip) {
905c58b9 1615 log_error ("Multiple interfaces match the %s: %s %s",
20916cae
TL
1616 "same shared network",
1617 share -> interface -> name, ip -> name);
1618 }
d758ad8c 1619 subnet_dereference (&subnet, MDL);
20916cae
TL
1620 }
1621 return 1;
1622}
d758ad8c
TL
1623
1624static TIME shutdown_time;
1625static int omapi_connection_count;
1626enum dhcp_shutdown_state shutdown_state;
1627
1628isc_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
1662static isc_result_t dhcp_io_shutdown_countdown (void *vlp)
1663{
d758ad8c 1664#if defined (FAILOVER_PROTOCOL)
66cebfcb 1665 dhcp_failover_state_t *state;
d758ad8c
TL
1666 int failover_connection_count = 0;
1667#endif
be62cf06 1668 struct timeval tv;
d758ad8c
TL
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 }
98311e4b 1728#if defined (DEBUG_MEMORY_LEAKAGE) && \
d758ad8c
TL
1729 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1730 free_everything ();
1731 omapi_print_dmalloc_usage_by_caller ();
1732#endif
f950de77
SR
1733 if (no_pid_file == ISC_FALSE)
1734 (void) unlink(path_dhcpd_pid);
d758ad8c 1735 exit (0);
905c58b9 1736 }
d758ad8c
TL
1737#else
1738 if (shutdown_state == shutdown_done) {
98311e4b
DH
1739#if defined (DEBUG_MEMORY_LEAKAGE) && \
1740 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1741 free_everything ();
905c58b9 1742 omapi_print_dmalloc_usage_by_caller ();
d758ad8c 1743#endif
f950de77
SR
1744 if (no_pid_file == ISC_FALSE)
1745 (void) unlink(path_dhcpd_pid);
d758ad8c
TL
1746 exit (0);
1747 }
1748#endif
1749 if (shutdown_state == shutdown_dhcp &&
33e1cb2b
DH
1750#if defined(FAILOVER_PROTOCOL)
1751 !failover_connection_count &&
1752#endif
1753 ISC_TRUE) {
d758ad8c
TL
1754 shutdown_state = shutdown_done;
1755 shutdown_time = cur_time;
1756 goto oncemore;
1757 }
be62cf06
FD
1758 tv.tv_sec = cur_tv.tv_sec + 1;
1759 tv.tv_usec = cur_tv.tv_usec;
1760 add_timeout (&tv,
d758ad8c
TL
1761 (void (*)(void *))dhcp_io_shutdown_countdown, 0, 0, 0);
1762 return ISC_R_SUCCESS;
1763}
1764
1765isc_result_t dhcp_set_control_state (control_object_state_t oldstate,
1766 control_object_state_t newstate)
1767{
0895c955
SR
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;
d758ad8c
TL
1780 dhcp_io_shutdown_countdown (0);
1781 return ISC_R_SUCCESS;
1782 }
0895c955
SR
1783 /* Called on signal. */
1784 log_info("Received signal %d, initiating shutdown.", shutdown_signal);
1785 shutdown_signal = SIGUSR1;
905c58b9 1786
0895c955
SR
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;
d758ad8c 1796}