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