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