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 34static const char copyright[] = 35"Copyright 2004-2022 Internet Systems Consortium."; 36static const char arr [] = "All rights reserved."; 37static const char message [] = "Internet Systems Consortium DHCP Server"; 38static 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 */ 61uid_t set_uid = 0; 62gid_t set_gid = 0; 63#endif /* PARANOIA */ 64 65struct class unknown_class; 66struct class known_class; 67 68struct iaddr server_identifier; 69int 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. */ 75char std_nsupdate [] = " \n\ 76option server.ddns-hostname = \n\ 77 pick (option fqdn.hostname, option host-name, config-option host-name); \n\ 78option server.ddns-domainname = config-option domain-name; \n\ 79option server.ddns-rev-domainname = \"in-addr.arpa.\";"; 80 81/* Stores configured DDNS conflict detection flags */ 82u_int16_t ddns_conflict_mask; 83#endif /* NSUPDATE */ 84 85int ddns_update_style; 86int dont_use_fsync = 0; /* 0 = default, use fsync, 1 = don't use fsync */ 87int server_id_check = 0; /* 0 = default, don't check server id, 1 = do check */ 88 89#ifdef DHCPv6 90int prefix_length_mode = PLM_PREFER; 91int do_release_on_roam = 0; /* 0 = default, do not release v6 leases on roam */ 92#endif 93 94#ifdef EUI_64 95int persist_eui64 = 1; /* 1 = write EUI64 leases to disk, 0 = don't */ 96#endif 97 98int authoring_byte_order = 0; /* 0 = not set */ 99int lease_id_format = TOKEN_OCTAL; /* octal by default */ 100u_int32_t abandon_lease_time = DEFAULT_ABANDON_LEASE_TIME; 101 102const char *path_dhcpd_conf = _PATH_DHCPD_CONF; 103const char *path_dhcpd_db = _PATH_DHCPD_DB; 104const char *path_dhcpd_pid = _PATH_DHCPD_PID; 105/* False (default) => we write and use a pid file */ 106isc_boolean_t no_pid_file = ISC_FALSE; 107 108int dhcp_max_agent_option_packet_length = DHCP_MTU_MAX; 109 110static omapi_auth_key_t *omapi_key = (omapi_auth_key_t *)0; 111int omapi_port; 112 113#if defined (TRACING) 114trace_type_t *trace_srandom; 115#endif 116 117extern uint16_t local_port; 118extern uint16_t remote_port; 119libdhcp_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 134char *progname; 135 136static isc_result_t verify_addr (omapi_object_t *l, omapi_addr_t *addr) { 137 return ISC_R_SUCCESS; 138} 139 140static 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 146static 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 $"); 230static char use_noarg[] = "No argument for command: %s "; 231 232static void 233usage(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 */ 262static 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 276int 277main(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 1121void 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 1526void 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 1544void 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 1593void 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 1616int 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 1674static TIME shutdown_time; 1675static int omapi_connection_count; 1676enum dhcp_shutdown_state shutdown_state; 1677 1678isc_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 1712static 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 1815isc_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