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