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