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