ISC DHCP  4.3.5
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 */
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 
715  postconf_initialization (quiet);
716 
717 #if defined(DHCPv6) && defined(DHCP4o6)
718  if (dhcpv4_over_dhcpv6) {
719  if ((local_family == AF_INET) && (interfaces != NULL))
720  log_fatal("DHCPv4 server in DHPv4 over DHCPv6 "
721  "mode with config file specified "
722  "interfaces.");
723  }
724 #endif /* DHCPv6 && DHCP4o6 */
725 
726 #if defined (PARANOIA) && !defined (EARLY_CHROOT)
727  if (set_chroot) setup_chroot (set_chroot);
728 #endif /* PARANOIA && !EARLY_CHROOT */
729 
730 #ifdef DHCPv6
731  /* log info about ipv6_ponds with large address ranges */
733 #endif
734 
735  /* test option should cause an early exit */
736  if (cftest && !lftest)
737  exit(0);
738 
739  /*
740  * First part of dealing with pid files. Check to see if
741  * we should continue running or not. We run if:
742  * - we are testing the lease file out
743  * - we don't have a pid file to check
744  * - there is no other process running
745  */
746  if ((lftest == 0) && (no_pid_file == ISC_FALSE)) {
747  /*Read previous pid file. */
748  if ((i = open(path_dhcpd_pid, O_RDONLY)) >= 0) {
749  status = read(i, pbuf, (sizeof pbuf) - 1);
750  close(i);
751  if (status > 0) {
752  pbuf[status] = 0;
753  pid = atoi(pbuf);
754 
755  /*
756  * If there was a previous server process and
757  * it is still running, abort
758  */
759  if (!pid ||
760  (pid != getpid() && kill(pid, 0) == 0))
761  log_fatal("There's already a "
762  "DHCP server running.");
763  }
764  }
765  }
766 
768 
769  /* Start up the database... */
770  db_startup (lftest);
771 
772  if (lftest)
773  exit (0);
774 
775  /* Discover all the network interfaces and initialize them. */
776 #if defined(DHCPv6) && defined(DHCP4o6)
777  if (dhcpv4_over_dhcpv6) {
778  int real_family = local_family;
779  local_family = AF_INET6;
780  /* The DHCPv4 side of DHCPv4-over-DHCPv6 service
781  uses a specific discovery which doesn't register
782  DHCPv6 sockets. */
783  if (real_family == AF_INET)
785  else
787  local_family = real_family;
788  } else
789 #endif /* DHCPv6 && DHCP4o6 */
791 
792 #ifdef DHCPv6
793  /*
794  * Remove addresses from our pools that we should not issue
795  * to clients.
796  *
797  * We currently have no support for this in IPv4. It is not
798  * as important in IPv4, as making pools with ranges that
799  * leave out interfaces and hosts is fairly straightforward
800  * using range notation, but not so handy with CIDR notation.
801  */
802  if (local_family == AF_INET6) {
806  }
807 #endif /* DHCPv6 */
808 
809  /* Make up a seed for the random number generator from current
810  time plus the sum of the last four bytes of each
811  interface's hardware address interpreted as an integer.
812  Not much entropy, but we're booting, so we're not likely to
813  find anything better. */
814  seed = 0;
815  for (ip = interfaces; ip; ip = ip -> next) {
816  int junk;
817  memcpy (&junk,
818  &ip -> hw_address.hbuf [ip -> hw_address.hlen -
819  sizeof seed], sizeof seed);
820  seed += junk;
821  }
822  srandom (seed + cur_time);
823 #if defined (TRACING)
824  trace_seed_stash (trace_srandom, seed + cur_time);
825 #endif
826  postdb_startup ();
827 
828 #ifdef DHCPv6
829  /*
830  * Set server DHCPv6 identifier - we go in order:
831  * dhcp6.server-id in the config file
832  * server-duid from the lease file
833  * server-duid from the config file (the config file is read first
834  * and the lease file overwrites the config file information)
835  * generate a new one from the interface hardware addresses.
836  * In all cases we write it out to the lease file.
837  * See dhcpv6.c for discussion of setting DUID.
838  */
839  if ((set_server_duid_from_option() != ISC_R_SUCCESS) &&
840  (!server_duid_isset()) &&
841  (generate_new_server_duid() != ISC_R_SUCCESS)) {
842  log_fatal("Unable to set server identifier.");
843  }
845 #ifdef DHCP4o6
846  if (dhcpv4_over_dhcpv6)
847  dhcp4o6_setup(dhcp4o6_port);
848 #endif /* DHCP4o6 */
849 #endif /* DHCPv6 */
850 
851 #ifndef DEBUG
852  if (daemon) {
853  /* First part of becoming a daemon... */
854  if ((pid = fork ()) < 0)
855  log_fatal ("Can't fork daemon: %m");
856  else if (pid)
857  exit (0);
858  }
859 
860  /*
861  * Second part of dealing with pid files. Now
862  * that we have forked we can write our pid if
863  * appropriate.
864  */
865  if (no_pid_file == ISC_FALSE) {
866  i = open(path_dhcpd_pid, O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0644);
867  if (i >= 0) {
868  sprintf(pbuf, "%d\n", (int) getpid());
869  IGNORE_RET(write(i, pbuf, strlen(pbuf)));
870  close(i);
871  } else {
872  log_error("Can't create PID file %s: %m.",
874  }
875  }
876 
877 #if defined (PARANOIA)
878  /* change uid to the specified one */
879 
880  if (set_gid) {
881  if (setgroups (0, (void *)0))
882  log_fatal ("setgroups: %m");
883  if (setgid (set_gid))
884  log_fatal ("setgid(%d): %m", (int) set_gid);
885  }
886 
887  if (set_uid) {
888  if (setuid (set_uid))
889  log_fatal ("setuid(%d): %m", (int) set_uid);
890  }
891 #endif /* PARANOIA */
892 
893  /* If we were requested to log to stdout on the command line,
894  keep doing so; otherwise, stop. */
895  if (log_perror == -1)
896  log_perror = 1;
897  else
898  log_perror = 0;
899 
900  if (daemon) {
901  /* Become session leader and get pid... */
902  (void) setsid();
903 
904  /* Close standard I/O descriptors. */
905  (void) close(0);
906  (void) close(1);
907  (void) close(2);
908 
909  /* Reopen them on /dev/null. */
910  (void) open("/dev/null", O_RDWR | O_CLOEXEC);
911  (void) open("/dev/null", O_RDWR | O_CLOEXEC);
912  (void) open("/dev/null", O_RDWR | O_CLOEXEC);
913  log_perror = 0; /* No sense logging to /dev/null. */
914 
915  IGNORE_RET (chdir("/"));
916  }
917 #endif /* !DEBUG */
918 
919 #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \
920  defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
921  dmalloc_cutoff_generation = dmalloc_generation;
922  dmalloc_longterm = dmalloc_outstanding;
923  dmalloc_outstanding = 0;
924 #endif
925 
927  (omapi_object_t *)0, "state", server_running);
928 
929 #if defined(ENABLE_GENTLE_SHUTDOWN)
930  /* no signal handlers until we deal with the side effects */
931  /* install signal handlers */
932  signal(SIGINT, dhcp_signal_handler); /* control-c */
933  signal(SIGTERM, dhcp_signal_handler); /* kill */
934 #endif
935 
936  /* Log that we are about to start working */
937  log_info("Server starting service.");
938 
939 #ifdef HAVE_LIBSYSTEMD
940  /* We are ready to process incomming packets. Let's notify systemd */
941  sd_notifyf(0, "READY=1\n"
942  "STATUS=Dispatching packets...\n"
943  "MAINPID=%lu",
944  (unsigned long) getpid());
945 #endif
946 
947  /*
948  * Receive packets and dispatch them...
949  * dispatch() will never return.
950  */
951  dispatch ();
952 
953  /* Let's return status code */
954  return 0;
955 }
956 #endif /* !UNIT_TEST */
957 
959 {
960  struct option_state *options = NULL;
961  struct data_string db;
962  struct option_cache *oc;
963  char *s;
964  isc_result_t result;
965  int tmp;
966 #if defined (NSUPDATE)
967  struct in_addr local4, *local4_ptr = NULL;
968  struct in6_addr local6, *local6_ptr = NULL;
969 #endif
970 
971  /* Now try to get the lease file name. */
972  option_state_allocate(&options, MDL);
973 
974  execute_statements_in_scope(NULL, NULL, NULL, NULL, NULL,
975  options, &global_scope, root_group,
976  NULL, NULL);
977  memset(&db, 0, sizeof db);
979  if (oc &&
980  evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
981  &global_scope, oc, MDL)) {
982  s = dmalloc(db.len + 1, MDL);
983  if (!s)
984  log_fatal("no memory for lease db filename.");
985  memcpy(s, db.data, db.len);
986  s[db.len] = 0;
987  data_string_forget(&db, MDL);
988  path_dhcpd_db = s;
989  }
990 
992  if (oc &&
993  evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
994  &global_scope, oc, MDL)) {
995  s = dmalloc(db.len + 1, MDL);
996  if (!s)
997  log_fatal("no memory for pid filename.");
998  memcpy(s, db.data, db.len);
999  s[db.len] = 0;
1000  data_string_forget(&db, MDL);
1001  path_dhcpd_pid = s;
1002  }
1003 
1004 #ifdef DHCPv6
1005  if (local_family == AF_INET6) {
1006  /*
1007  * Override lease file name with dhcpv6 lease file name,
1008  * if it was set; then, do the same with the pid file name
1009  */
1010  oc = lookup_option(&server_universe, options,
1012  if (oc &&
1013  evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
1014  &global_scope, oc, MDL)) {
1015  s = dmalloc(db.len + 1, MDL);
1016  if (!s)
1017  log_fatal("no memory for lease db filename.");
1018  memcpy(s, db.data, db.len);
1019  s[db.len] = 0;
1020  data_string_forget(&db, MDL);
1021  path_dhcpd_db = s;
1022  }
1023 
1024  oc = lookup_option(&server_universe, options,
1026  if (oc &&
1027  evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
1028  &global_scope, oc, MDL)) {
1029  s = dmalloc(db.len + 1, MDL);
1030  if (!s)
1031  log_fatal("no memory for pid filename.");
1032  memcpy(s, db.data, db.len);
1033  s[db.len] = 0;
1034  data_string_forget(&db, MDL);
1035  path_dhcpd_pid = s;
1036  }
1037  }
1038 #endif /* DHCPv6 */
1039 
1040  omapi_port = -1;
1041  oc = lookup_option(&server_universe, options, SV_OMAPI_PORT);
1042  if (oc &&
1043  evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
1044  &global_scope, oc, MDL)) {
1045  if (db.len == 2) {
1046  omapi_port = getUShort(db.data);
1047  } else
1048  log_fatal("invalid omapi port data length");
1049  data_string_forget(&db, MDL);
1050  }
1051 
1052  oc = lookup_option(&server_universe, options, SV_OMAPI_KEY);
1053  if (oc &&
1054  evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
1055  &global_scope, oc, MDL)) {
1056  s = dmalloc(db.len + 1, MDL);
1057  if (!s)
1058  log_fatal("no memory for OMAPI key filename.");
1059  memcpy(s, db.data, db.len);
1060  s[db.len] = 0;
1061  data_string_forget(&db, MDL);
1062  result = omapi_auth_key_lookup_name(&omapi_key, s);
1063  dfree(s, MDL);
1064  if (result != ISC_R_SUCCESS)
1065  log_fatal("OMAPI key %s: %s",
1066  s, isc_result_totext (result));
1067  }
1068 
1069  oc = lookup_option(&server_universe, options, SV_LOCAL_PORT);
1070  if (oc &&
1071  evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
1072  &global_scope, oc, MDL)) {
1073  if (db.len == 2) {
1074  local_port = htons(getUShort (db.data));
1075  } else
1076  log_fatal("invalid local port data length");
1077  data_string_forget(&db, MDL);
1078  }
1079 
1080  oc = lookup_option(&server_universe, options, SV_REMOTE_PORT);
1081  if (oc &&
1082  evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
1083  &global_scope, oc, MDL)) {
1084  if (db.len == 2) {
1085  remote_port = htons(getUShort (db.data));
1086  } else
1087  log_fatal("invalid remote port data length");
1088  data_string_forget(&db, MDL);
1089  }
1090 
1091  oc = lookup_option(&server_universe, options,
1093  if (oc &&
1094  evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
1095  &global_scope, oc, MDL)) {
1096  if (db.len == 4) {
1097  memcpy(&limited_broadcast, db.data, 4);
1098  } else
1099  log_fatal("invalid broadcast address data length");
1100  data_string_forget(&db, MDL);
1101  }
1102 
1104  if (oc &&
1105  evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
1106  &global_scope, oc, MDL)) {
1107  if (db.len == 4) {
1108  memcpy(&local_address, db.data, 4);
1109  } else
1110  log_fatal("invalid local address data length");
1111  data_string_forget(&db, MDL);
1112  }
1113 
1115  if (oc) {
1116  if (evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
1117  &global_scope, oc, MDL)) {
1118  if (db.len == 1) {
1119  ddns_update_style = db.data[0];
1120  } else
1121  log_fatal("invalid dns update type");
1122  data_string_forget(&db, MDL);
1123  }
1124  } else {
1126  }
1127 #if defined (NSUPDATE)
1128  /* We no longer support ad_hoc, tell the user */
1130  log_fatal("ddns-update-style ad_hoc no longer supported");
1131  }
1132 
1134  if (oc) {
1135  if (evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
1136  &global_scope, oc, MDL)) {
1137  if (db.len == 4) {
1138  memcpy(&local4, db.data, 4);
1139  local4_ptr = &local4;
1140  }
1141  data_string_forget(&db, MDL);
1142  }
1143  }
1144 
1146  if (oc) {
1147  if (evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
1148  &global_scope, oc, MDL)) {
1149  if (db.len == 16) {
1150  memcpy(&local6, db.data, 16);
1151  local6_ptr = &local6;
1152  }
1153  data_string_forget(&db, MDL);
1154  }
1155  }
1156 
1157  if (dhcp_context_create(DHCP_CONTEXT_POST_DB, local4_ptr, local6_ptr)
1158  != ISC_R_SUCCESS)
1159  log_fatal("Unable to complete ddns initialization");
1160 
1161 #else
1162  /* If we don't have support for updates compiled in tell the user */
1164  log_fatal("Support for ddns-update-style not compiled in");
1165  }
1166 #endif
1167 
1168  if (!quiet) {
1169  log_info ("Config file: %s", path_dhcpd_conf);
1170  log_info ("Database file: %s", path_dhcpd_db);
1171  log_info ("PID file: %s", path_dhcpd_pid);
1172  }
1173 
1175  if (oc) {
1176  if (evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
1177  &global_scope, oc, MDL)) {
1178  if (db.len == 1) {
1179  closelog ();
1180  openlog(isc_file_basename(progname),
1181  DHCP_LOG_OPTIONS, db.data[0]);
1182  /* Log the startup banner into the new
1183  log file. */
1184  /* Don't log to stderr twice. */
1185  tmp = log_perror;
1186  log_perror = 0;
1187  log_info("%s %s", message, PACKAGE_VERSION);
1188  log_info(copyright);
1189  log_info(arr);
1190  log_info(url);
1191  log_perror = tmp;
1192  } else
1193  log_fatal("invalid log facility");
1194  data_string_forget(&db, MDL);
1195  }
1196  }
1197 
1198 #if defined(DELAYED_ACK)
1199  oc = lookup_option(&server_universe, options, SV_DELAYED_ACK);
1200  if (oc &&
1201  evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
1202  &global_scope, oc, MDL)) {
1203  if (db.len == 2) {
1204  max_outstanding_acks = htons(getUShort(db.data));
1205  } else {
1206  log_fatal("invalid max delayed ACK count ");
1207  }
1208  data_string_forget(&db, MDL);
1209  }
1210 
1212  if (oc &&
1213  evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
1214  &global_scope, oc, MDL)) {
1215  u_int32_t timeval;
1216 
1217  if (db.len != 4)
1218  log_fatal("invalid max ack delay configuration");
1219 
1220  timeval = getULong(db.data);
1221  max_ack_delay_secs = timeval / 1000000;
1222  max_ack_delay_usecs = timeval % 1000000;
1223 
1224  data_string_forget(&db, MDL);
1225  }
1226 #endif
1227 
1229  if ((oc != NULL) &&
1230  evaluate_boolean_option_cache(NULL, NULL, NULL, NULL, options, NULL,
1231  &global_scope, oc, MDL)) {
1232  dont_use_fsync = 1;
1233  log_error("Not using fsync() to flush lease writes");
1234  }
1235 
1237  if ((oc != NULL) &&
1238  evaluate_boolean_option_cache(NULL, NULL, NULL, NULL, options, NULL,
1239  &global_scope, oc, MDL)) {
1240  log_info("Setting server-id-check true");
1241  server_id_check = 1;
1242  }
1243 
1245  if ((oc != NULL) &&
1246  evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
1247  &global_scope, oc, MDL)) {
1248  if (db.len == 1) {
1249  prefix_length_mode = db.data[0];
1250  } else {
1251  log_fatal("invalid prefix-len-mode");
1252  }
1253 
1254  data_string_forget(&db, MDL);
1255  }
1256 
1257  // Set global abandon-lease-time option.
1259  if ((oc != NULL) &&
1260  evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
1261  &global_scope, oc, MDL)) {
1262  if (db.len == sizeof (u_int32_t)) {
1264  } else {
1265  log_fatal("invalid abandon-lease-time");
1266  }
1267 
1268  data_string_forget (&db, MDL);
1269  }
1270 
1271 #if defined (BINARY_LEASES)
1272  if (local_family == AF_INET) {
1273  log_info("Source compiled to use binary-leases");
1274  }
1275 #endif
1276 
1277  /* Don't need the options anymore. */
1278  option_state_dereference(&options, MDL);
1279 }
1280 
1281 void postdb_startup (void)
1282 {
1283  /* Initialize the omapi listener state. */
1284  if (omapi_port != -1) {
1285  omapi_listener_start (0);
1286  }
1287 
1288 #if defined (FAILOVER_PROTOCOL)
1289  /* Initialize the failover listener state. */
1291 #endif
1292 
1293  /*
1294  * Begin our lease timeout background task.
1295  */
1297 }
1298 
1299 void lease_pinged (from, packet, length)
1300  struct iaddr from;
1301  u_int8_t *packet;
1302  int length;
1303 {
1304  struct lease *lp;
1305 
1306  /* Don't try to look up a pinged lease if we aren't trying to
1307  ping one - otherwise somebody could easily make us churn by
1308  just forging repeated ICMP EchoReply packets for us to look
1309  up. */
1310  if (!outstanding_pings)
1311  return;
1312 
1313  lp = (struct lease *)0;
1314  if (!find_lease_by_ip_addr (&lp, from, MDL)) {
1315  log_debug ("unexpected ICMP Echo Reply from %s",
1316  piaddr (from));
1317  return;
1318  }
1319 
1320  if (!lp -> state) {
1321 #if defined (FAILOVER_PROTOCOL)
1322  if (!lp -> pool ||
1323  !lp -> pool -> failover_peer)
1324 #endif
1325  log_debug ("ICMP Echo Reply for %s late or spurious.",
1326  piaddr (from));
1327  goto out;
1328  }
1329 
1330  if (lp -> ends > cur_time) {
1331  log_debug ("ICMP Echo reply while lease %s valid.",
1332  piaddr (from));
1333  }
1334 
1335  /* At this point it looks like we pinged a lease and got a
1336  response, which shouldn't have happened. */
1337  data_string_forget (&lp -> state -> parameter_request_list, MDL);
1338  free_lease_state (lp -> state, MDL);
1339  lp -> state = (struct lease_state *)0;
1340 
1341  abandon_lease (lp, "pinged before offer");
1344  out:
1345  lease_dereference (&lp, MDL);
1346 }
1347 
1349  void *vlp;
1350 {
1351  struct lease *lp = vlp;
1352 
1353 #if defined (DEBUG_MEMORY_LEAKAGE)
1354  unsigned long previous_outstanding = dmalloc_outstanding;
1355 #endif
1356 
1358  dhcp_reply (lp);
1359 
1360 #if defined (DEBUG_MEMORY_LEAKAGE)
1361  log_info ("generation %ld: %ld new, %ld outstanding, %ld long-term",
1362  dmalloc_generation,
1363  dmalloc_outstanding - previous_outstanding,
1364  dmalloc_outstanding, dmalloc_longterm);
1365 #endif
1366 #if defined (DEBUG_MEMORY_LEAKAGE)
1367  dmalloc_dump_outstanding ();
1368 #endif
1369 }
1370 
1372 {
1373  struct subnet *subnet;
1374  struct shared_network *share;
1375  isc_result_t status;
1376 
1377  /* Special case for fallback network - not sure why this is
1378  necessary. */
1379  if (!ia) {
1380  const char *fnn = "fallback-net";
1381  status = shared_network_allocate (&ip -> shared_network, MDL);
1382  if (status != ISC_R_SUCCESS)
1383  log_fatal ("No memory for shared subnet: %s",
1384  isc_result_totext (status));
1385  ip -> shared_network -> name = dmalloc (strlen (fnn) + 1, MDL);
1386  if (!ip -> shared_network -> name)
1387  log_fatal("no memory for shared network");
1388  strcpy (ip -> shared_network -> name, fnn);
1389  return 1;
1390  }
1391 
1392  /* If there's a registered subnet for this address,
1393  connect it together... */
1394  subnet = (struct subnet *)0;
1395  if (find_subnet (&subnet, *ia, MDL)) {
1396  /* If this interface has multiple aliases on the same
1397  subnet, ignore all but the first we encounter. */
1398  if (!subnet -> interface) {
1399  interface_reference (&subnet -> interface, ip, MDL);
1400  subnet -> interface_address = *ia;
1401  } else if (subnet -> interface != ip) {
1402  log_error ("Multiple interfaces match the %s: %s %s",
1403  "same subnet",
1404  subnet -> interface -> name, ip -> name);
1405  }
1406  share = subnet -> shared_network;
1407  if (ip -> shared_network &&
1408  ip -> shared_network != share) {
1409  log_fatal ("Interface %s matches multiple shared %s",
1410  ip -> name, "networks");
1411  } else {
1412  if (!ip -> shared_network)
1413  shared_network_reference
1414  (&ip -> shared_network, share, MDL);
1415  }
1416 
1417  if (!share -> interface) {
1418  interface_reference (&share -> interface, ip, MDL);
1419  } else if (share -> interface != ip) {
1420  log_error ("Multiple interfaces match the %s: %s %s",
1421  "same shared network",
1422  share -> interface -> name, ip -> name);
1423  }
1424  subnet_dereference (&subnet, MDL);
1425  }
1426  return 1;
1427 }
1428 
1429 static TIME shutdown_time;
1430 static int omapi_connection_count;
1432 
1433 isc_result_t dhcp_io_shutdown (omapi_object_t *obj, void *foo)
1434 {
1435  /* Shut down all listeners. */
1436  if (shutdown_state == shutdown_listeners &&
1437  obj -> type == omapi_type_listener &&
1438  obj -> inner &&
1439  obj -> inner -> type == omapi_type_protocol_listener) {
1440  omapi_listener_destroy (obj, MDL);
1441  return ISC_R_SUCCESS;
1442  }
1443 
1444  /* Shut down all existing omapi connections. */
1445  if (obj -> type == omapi_type_connection &&
1446  obj -> inner &&
1447  obj -> inner -> type == omapi_type_protocol) {
1448  if (shutdown_state == shutdown_drop_omapi_connections) {
1449  omapi_disconnect (obj, 1);
1450  }
1451  omapi_connection_count++;
1452  if (shutdown_state == shutdown_omapi_connections) {
1453  omapi_disconnect (obj, 0);
1454  return ISC_R_SUCCESS;
1455  }
1456  }
1457 
1458  /* Shutdown all DHCP interfaces. */
1459  if (obj -> type == dhcp_type_interface &&
1460  shutdown_state == shutdown_dhcp) {
1462  return ISC_R_SUCCESS;
1463  }
1464  return ISC_R_SUCCESS;
1465 }
1466 
1467 static isc_result_t dhcp_io_shutdown_countdown (void *vlp)
1468 {
1469 #if defined (FAILOVER_PROTOCOL)
1470  dhcp_failover_state_t *state;
1471  int failover_connection_count = 0;
1472 #endif
1473  struct timeval tv;
1474 
1475  oncemore:
1476  if (shutdown_state == shutdown_listeners ||
1477  shutdown_state == shutdown_omapi_connections ||
1478  shutdown_state == shutdown_drop_omapi_connections ||
1479  shutdown_state == shutdown_dhcp) {
1480  omapi_connection_count = 0;
1482  }
1483 
1484  if ((shutdown_state == shutdown_listeners ||
1485  shutdown_state == shutdown_omapi_connections ||
1486  shutdown_state == shutdown_drop_omapi_connections) &&
1487  omapi_connection_count == 0) {
1488  shutdown_state = shutdown_dhcp;
1489  shutdown_time = cur_time;
1490  goto oncemore;
1491  } else if (shutdown_state == shutdown_listeners &&
1492  cur_time - shutdown_time > 4) {
1493  shutdown_state = shutdown_omapi_connections;
1494  shutdown_time = cur_time;
1495  } else if (shutdown_state == shutdown_omapi_connections &&
1496  cur_time - shutdown_time > 4) {
1497  shutdown_state = shutdown_drop_omapi_connections;
1498  shutdown_time = cur_time;
1499  } else if (shutdown_state == shutdown_drop_omapi_connections &&
1500  cur_time - shutdown_time > 4) {
1501  shutdown_state = shutdown_dhcp;
1502  shutdown_time = cur_time;
1503  goto oncemore;
1504  } else if (shutdown_state == shutdown_dhcp &&
1505  cur_time - shutdown_time > 4) {
1506  shutdown_state = shutdown_done;
1507  shutdown_time = cur_time;
1508  }
1509 
1510 #if defined (FAILOVER_PROTOCOL)
1511  /* Set all failover peers into the shutdown state. */
1512  if (shutdown_state == shutdown_dhcp) {
1513  for (state = failover_states; state; state = state -> next) {
1514  if (state -> me.state == normal) {
1516  failover_connection_count++;
1517  }
1518  if (state -> me.state == shut_down &&
1519  state -> partner.state != partner_down)
1520  failover_connection_count++;
1521  }
1522  }
1523 
1524  if (shutdown_state == shutdown_done) {
1525  for (state = failover_states; state; state = state -> next) {
1526  if (state -> me.state == shut_down) {
1527  if (state -> link_to_peer)
1528  dhcp_failover_link_dereference (&state -> link_to_peer,
1529  MDL);
1531  }
1532  }
1533 #if defined (DEBUG_MEMORY_LEAKAGE) && \
1534  defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1535  free_everything ();
1537 #endif
1538  if (no_pid_file == ISC_FALSE)
1539  (void) unlink(path_dhcpd_pid);
1540  exit (0);
1541  }
1542 #else
1543  if (shutdown_state == shutdown_done) {
1544 #if defined (DEBUG_MEMORY_LEAKAGE) && \
1545  defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1546  free_everything ();
1548 #endif
1549  if (no_pid_file == ISC_FALSE)
1550  (void) unlink(path_dhcpd_pid);
1551  exit (0);
1552  }
1553 #endif
1554  if (shutdown_state == shutdown_dhcp &&
1555 #if defined(FAILOVER_PROTOCOL)
1556  !failover_connection_count &&
1557 #endif
1558  ISC_TRUE) {
1559  shutdown_state = shutdown_done;
1560  shutdown_time = cur_time;
1561  goto oncemore;
1562  }
1563  tv.tv_sec = cur_tv.tv_sec + 1;
1564  tv.tv_usec = cur_tv.tv_usec;
1565  add_timeout (&tv,
1566  (void (*)(void *))dhcp_io_shutdown_countdown, 0, 0, 0);
1567  return ISC_R_SUCCESS;
1568 }
1569 
1571  control_object_state_t newstate)
1572 {
1573  struct timeval tv;
1574 
1575  if (newstate != server_shutdown)
1576  return DHCP_R_INVALIDARG;
1577  /* Re-entry. */
1578  if (shutdown_signal == SIGUSR1)
1579  return ISC_R_SUCCESS;
1580  shutdown_time = cur_time;
1581  shutdown_state = shutdown_listeners;
1582  /* Called by user. */
1583  if (shutdown_signal == 0) {
1584  shutdown_signal = SIGUSR1;
1585  dhcp_io_shutdown_countdown (0);
1586  return ISC_R_SUCCESS;
1587  }
1588  /* Called on signal. */
1589  log_info("Received signal %d, initiating shutdown.", shutdown_signal);
1590  shutdown_signal = SIGUSR1;
1591 
1592  /*
1593  * Prompt the shutdown event onto the timer queue
1594  * and return to the dispatch loop.
1595  */
1596  tv.tv_sec = cur_tv.tv_sec;
1597  tv.tv_usec = cur_tv.tv_usec + 1;
1598  add_timeout(&tv,
1599  (void (*)(void *))dhcp_io_shutdown_countdown, 0, 0, 0);
1600  return ISC_R_SUCCESS;
1601 }
#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: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:1371
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
const char * piaddr(const struct iaddr addr)
Definition: inet.c:579
char name[IFNAMSIZ]
Definition: dhcpd.h:1375
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:1348
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:624
#define PLM_EXACT
Definition: dhcpd.h:859
Definition: dhcpd.h:1044
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: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:1412
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:91
#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:3978
void dispatch(void)
Definition: dispatch.c:109
#define _PATH_DHCPD_DB
Definition: config.h:259
#define DHCP_LOG_OPTIONS
Definition: dhcpd.h:1601
#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
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:127
struct executable_statement * statements
Definition: dhcpd.h:939
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:347
void postconf_initialization(int quiet)
Definition: dhcpd.c:958
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:1593
void mark_phosts_unavailable(void)
Definition: mdb6.c:2342
struct iaddr interface_address
Definition: dhcpd.h:1050
int max_ack_delay_secs
Definition: dhcpd.h:998
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:1570
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: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:2076
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:2438
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:56
struct interface_info * interfaces
Definition: discover.c:42
u_int32_t flags
Definition: dhcpd.h:1389
u_int32_t getULong(const unsigned char *)
struct shared_network * shared_network
Definition: dhcpd.h:1048
void db_startup(int testp)
Definition: dhclient.c:1982
void lease_pinged(struct iaddr from, u_int8_t *packet, int length)
Definition: dhcpd.c:1299
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:1433
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:854
#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:931
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:1350
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_ABANDON_LEASE_TIME
Definition: dhcpd.h:804
#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:96
#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:93
#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:87
void dhcp_reply(struct lease *)
Definition: dhcp.c:3745
char * name
Definition: dhcpd.h:1029
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:2113
int prefix_length_mode
Definition: dhcpd.c:81
isc_result_t omapi_disconnect(omapi_object_t *, int)
Definition: connection.c:456
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:1431
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:262
struct enumeration ddns_styles
Definition: stables.c:347
void discover_interfaces(int state)
Definition: discover.c:556
struct interface_info * interface
Definition: dhcpd.h:1049
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:1390
#define _PATH_DHCPD_CONF
Definition: dhcpd.h:1535
void postdb_startup(void)
Definition: dhcpd.c:1281
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