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