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