ISC DHCP  4.4.3-P1
A reference DHCPv4 and DHCPv6 implementation
db.c
Go to the documentation of this file.
1 /* db.c
2 
3  Persistent database management routines for DHCPD... */
4 
5 /*
6  * Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC")
7  * Copyright (c) 1995-2003 by Internet Software Consortium
8  *
9  * This Source Code Form is subject to the terms of the Mozilla Public
10  * License, v. 2.0. If a copy of the MPL was not distributed with this
11  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
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  * PO Box 360
23  * Newmarket, NH 03857 USA
24  * <info@isc.org>
25  * https://www.isc.org/
26  *
27  */
28 
29 #include "dhcpd.h"
30 #include <ctype.h>
31 #include <errno.h>
32 
33 #define LEASE_REWRITE_PERIOD 3600
34 
35 static isc_result_t write_binding_scope(FILE *db_file, struct binding *bnd,
36  char *prepend);
37 
38 FILE *db_file;
39 
40 static int counting = 0;
41 static int count = 0;
44 
45 /* Write a single binding scope value in parsable format.
46  */
47 
48 static isc_result_t
49 write_binding_scope(FILE *db_file, struct binding *bnd, char *prepend) {
50  char *s;
51 
52  if ((db_file == NULL) || (bnd == NULL) || (prepend == NULL))
53  return DHCP_R_INVALIDARG;
54 
55  if (bnd->value->type == binding_data) {
56  if (bnd->value->value.data.data != NULL) {
57  s = quotify_buf(bnd->value->value.data.data,
58  bnd->value->value.data.len, '"', MDL);
59  if (s != NULL) {
60  errno = 0;
61  fprintf(db_file, "%sset %s = %s;",
62  prepend, bnd->name, s);
63  dfree(s, MDL);
64  if (errno)
65  return ISC_R_FAILURE;
66  } else {
67  return ISC_R_FAILURE;
68  }
69  }
70  } else if (bnd->value->type == binding_numeric) {
71  errno = 0;
72  fprintf(db_file, "%sset %s = %%%ld;", prepend,
73  bnd->name, bnd->value->value.intval);
74  if (errno)
75  return ISC_R_FAILURE;
76  } else if (bnd->value->type == binding_boolean) {
77  errno = 0;
78  fprintf(db_file, "%sset %s = %s;", prepend, bnd->name,
79  bnd->value->value.intval ? "true" : "false");
80  if (errno)
81  return ISC_R_FAILURE;
82  } else if (bnd->value->type == binding_dns) {
83  log_error("%s: persistent dns values not supported.",
84  bnd->name);
85  } else if (bnd->value->type == binding_function) {
86  log_error("%s: persistent functions not supported.",
87  bnd->name);
88  } else {
89  log_fatal("%s: unknown binding type %d", bnd->name,
90  bnd->value->type);
91  }
92 
93  return ISC_R_SUCCESS;
94 }
95 
96 /* Write the specified lease to the current lease database file. */
97 
99  struct lease *lease;
100 {
101  int errors = 0;
102  struct binding *b;
103  char *s;
104  const char *tval;
105 
106  /* If the lease file is corrupt, don't try to write any more leases
107  until we've written a good lease file. */
109  if (!new_lease_file (0))
110  return 0;
111 
112  if (counting)
113  ++count;
114  errno = 0;
115  fprintf (db_file, "lease %s {", piaddr (lease -> ip_addr));
116  if (errno) {
117  ++errors;
118  }
119 
120  if (lease->starts &&
121  ((tval = print_time(lease->starts)) == NULL ||
122  fprintf(db_file, "\n starts %s", tval) < 0))
123  ++errors;
124 
125  if (lease->ends &&
126  ((tval = print_time(lease->ends)) == NULL ||
127  fprintf(db_file, "\n ends %s", tval) < 0))
128  ++errors;
129 
130  if (lease->tstp &&
131  ((tval = print_time(lease->tstp)) == NULL ||
132  fprintf(db_file, "\n tstp %s", tval) < 0))
133  ++errors;
134 
135  if (lease->tsfp &&
136  ((tval = print_time(lease->tsfp)) == NULL ||
137  fprintf(db_file, "\n tsfp %s", tval) < 0))
138  ++errors;
139 
140  if (lease->atsfp &&
141  ((tval = print_time(lease->atsfp)) == NULL ||
142  fprintf(db_file, "\n atsfp %s", tval) < 0))
143  ++errors;
144 
145  if (lease->cltt &&
146  ((tval = print_time(lease->cltt)) == NULL ||
147  fprintf(db_file, "\n cltt %s", tval) < 0))
148  ++errors;
149 
150  if (fprintf (db_file, "\n binding state %s;",
151  ((lease -> binding_state > 0 &&
152  lease -> binding_state <= FTS_LAST)
153  ? binding_state_names [lease -> binding_state - 1]
154  : "abandoned")) < 0)
155  ++errors;
156 
157  if (lease -> binding_state != lease -> next_binding_state)
158  if (fprintf (db_file, "\n next binding state %s;",
159  ((lease -> next_binding_state > 0 &&
160  lease -> next_binding_state <= FTS_LAST)
162  [lease -> next_binding_state - 1])
163  : "abandoned")) < 0)
164  ++errors;
165 
166  /*
167  * In this case, if the rewind state is not present in the lease file,
168  * the reader will use the current binding state as the most
169  * conservative (safest) state. So if the in-memory rewind state is
170  * for some reason invalid, the best thing to do is not to write a
171  * state and let the reader take on a safe state.
172  */
174  (lease->rewind_binding_state > 0) &&
176  (fprintf(db_file, "\n rewind binding state %s;",
178  ++errors;
179 
180  if (lease->flags & RESERVED_LEASE)
181  if (fprintf(db_file, "\n reserved;") < 0)
182  ++errors;
183 
184  if (lease->flags & BOOTP_LEASE)
185  if (fprintf(db_file, "\n dynamic-bootp;") < 0)
186  ++errors;
187 
188  /* If this lease is billed to a class and is still valid,
189  write it out. */
190  if (lease -> billing_class && lease -> ends > cur_time) {
191  if (!write_billing_class (lease -> billing_class)) {
192  log_error ("unable to write class %s",
193  lease -> billing_class -> name);
194  ++errors;
195  }
196  }
197 
198  if (lease -> hardware_addr.hlen) {
199  errno = 0;
200  fprintf (db_file, "\n hardware %s %s;",
201  hardware_types [lease -> hardware_addr.hbuf [0]],
202  print_hw_addr (lease -> hardware_addr.hbuf [0],
203  lease -> hardware_addr.hlen - 1,
204  &lease -> hardware_addr.hbuf [1]));
205  if (errno)
206  ++errors;
207  }
208  if (lease -> uid_len) {
210  MDL);
211  if (s) {
212  errno = 0;
213  fprintf (db_file, "\n uid %s;", s);
214  if (errno)
215  ++errors;
216  dfree (s, MDL);
217  } else
218  ++errors;
219  }
220 
221  if (lease->scope != NULL) {
222  for (b = lease->scope->bindings; b; b = b->next) {
223  if (!b->value)
224  continue;
225 
226  if (write_binding_scope(db_file, b, "\n ") != ISC_R_SUCCESS)
227  ++errors;
228  }
229  }
230 
231  if (lease -> agent_options) {
232  struct option_cache *oc;
233  struct data_string ds;
234  pair p;
235 
236  memset (&ds, 0, sizeof ds);
237  for (p = lease -> agent_options -> first; p; p = p -> cdr) {
238  oc = (struct option_cache *)p -> car;
239  if (oc -> data.len) {
240  errno = 0;
241  fprintf (db_file, "\n option agent.%s %s;",
242  oc -> option -> name,
243  pretty_print_option (oc -> option, oc -> data.data,
244  oc -> data.len, 1, 1));
245  if (errno)
246  ++errors;
247  }
248  }
249  }
250  if (lease -> client_hostname &&
251  db_printable((unsigned char *)lease->client_hostname)) {
252  s = quotify_string (lease -> client_hostname, MDL);
253  if (s) {
254  errno = 0;
255  fprintf (db_file, "\n client-hostname \"%s\";", s);
256  if (errno)
257  ++errors;
258  dfree (s, MDL);
259  } else
260  ++errors;
261  }
262  if (lease->on_star.on_expiry) {
263  errno = 0;
264  fprintf (db_file, "\n on expiry%s {",
266  ? " or release" : "");
268  /* XXX */
269  fprintf (db_file, "\n }");
270  if (errno)
271  ++errors;
272  }
273  if (lease->on_star.on_release &&
275  errno = 0;
276  fprintf (db_file, "\n on release {");
278  /* XXX */
279  fprintf (db_file, "\n }");
280  if (errno)
281  ++errors;
282  }
283 
284  errno = 0;
285  fputs ("\n}\n", db_file);
286  if (errno)
287  ++errors;
288 
289  if (errors) {
290  log_info ("write_lease: unable to write lease %s",
291  piaddr (lease -> ip_addr));
293  }
294 
295  return !errors;
296 }
297 
298 int write_host (host)
299  struct host_decl *host;
300 {
301  int errors = 0;
302  int i;
303  struct data_string ip_addrs;
304 
305  /* If the lease file is corrupt, don't try to write any more leases
306  until we've written a good lease file. */
308  if (!new_lease_file (0))
309  return 0;
310 
311  if (!db_printable((unsigned char *)host->name))
312  return 0;
313 
314  if (counting)
315  ++count;
316 
317  errno = 0;
318  fprintf (db_file, "host %s {", host -> name);
319  if (errno)
320  ++errors;
321 
322  if (host -> flags & HOST_DECL_DYNAMIC) {
323  errno = 0;
324  fprintf (db_file, "\n dynamic;");
325  if (errno)
326  ++errors;
327  }
328 
329  if (host -> flags & HOST_DECL_DELETED) {
330  errno = 0;
331  fprintf (db_file, "\n deleted;");
332  if (errno)
333  ++errors;
334  } else {
335  if (host -> interface.hlen) {
336  errno = 0;
337  fprintf (db_file, "\n hardware %s %s;",
338  hardware_types [host -> interface.hbuf [0]],
339  print_hw_addr (host -> interface.hbuf [0],
340  host -> interface.hlen - 1,
341  &host -> interface.hbuf [1]));
342  if (errno)
343  ++errors;
344  }
345  if (host -> client_identifier.len) {
346  int i;
347  errno = 0;
348  if (db_printable_len (host -> client_identifier.data,
349  host -> client_identifier.len)) {
350  fprintf (db_file, "\n uid \"%.*s\";",
351  (int)host -> client_identifier.len,
352  host -> client_identifier.data);
353  if (errno)
354  ++errors;
355  } else {
356  fprintf (db_file,
357  "\n uid %2.2x",
358  host -> client_identifier.data [0]);
359  if (errno)
360  ++errors;
361  for (i = 1;
362  i < host -> client_identifier.len; i++) {
363  errno = 0;
364  fprintf (db_file, ":%2.2x",
365  host ->
366  client_identifier.data [i]);
367  if (errno)
368  ++errors;
369  }
370 
371  errno = 0;
372  fputc (';', db_file);
373  if (errno)
374  ++errors;
375  }
376  }
377 
378  memset (&ip_addrs, 0, sizeof ip_addrs);
379  if (host -> fixed_addr &&
380  evaluate_option_cache (&ip_addrs, (struct packet *)0,
381  (struct lease *)0,
382  (struct client_state *)0,
383  (struct option_state *)0,
384  (struct option_state *)0,
385  &global_scope,
386  host -> fixed_addr, MDL)) {
387 
388  errno = 0;
389  fprintf (db_file, "\n fixed-address ");
390  if (errno)
391  ++errors;
392  for (i = 0; i < ip_addrs.len - 3; i += 4) {
393 
394  errno = 0;
395  fprintf (db_file, "%u.%u.%u.%u%s",
396  ip_addrs.data [i] & 0xff,
397  ip_addrs.data [i + 1] & 0xff,
398  ip_addrs.data [i + 2] & 0xff,
399  ip_addrs.data [i + 3] & 0xff,
400  i + 7 < ip_addrs.len ? "," : "");
401  if (errno)
402  ++errors;
403  }
404 
405  /* We're done with ip_addrs so pitch it */
406  data_string_forget (&ip_addrs, MDL);
407 
408  errno = 0;
409  fputc (';', db_file);
410  if (errno)
411  ++errors;
412 
413  }
414 
415  if (host -> named_group) {
416  errno = 0;
417  fprintf (db_file, "\n group \"%s\";",
418  host -> named_group -> name);
419  if (errno)
420  ++errors;
421  }
422 
423  if (host -> group &&
424  (!host -> named_group ||
425  host -> group != host -> named_group -> group) &&
426  host -> group != root_group) {
427  errno = 0;
429  host -> group -> statements, 8);
430  if (errno)
431  ++errors;
432  }
433  }
434 
435  errno = 0;
436  fputs ("\n}\n", db_file);
437  if (errno)
438  ++errors;
439 
440  if (errors) {
441  log_info ("write_host: unable to write host %s",
442  host -> name);
444  }
445 
446  return !errors;
447 }
448 
450  struct group_object *group;
451 {
452  int errors = 0;
453 
454  /* If the lease file is corrupt, don't try to write any more leases
455  until we've written a good lease file. */
457  if (!new_lease_file (0))
458  return 0;
459 
460  if (!db_printable((unsigned char *)group->name))
461  return 0;
462 
463  if (counting)
464  ++count;
465 
466  errno = 0;
467  fprintf (db_file, "group %s {", group -> name);
468  if (errno)
469  ++errors;
470 
471  if (group -> flags & GROUP_OBJECT_DYNAMIC) {
472  errno = 0;
473  fprintf (db_file, "\n dynamic;");
474  if (errno)
475  ++errors;
476  }
477 
478  if (group -> flags & GROUP_OBJECT_STATIC) {
479  errno = 0;
480  fprintf (db_file, "\n static;");
481  if (errno)
482  ++errors;
483  }
484 
485  if (group -> flags & GROUP_OBJECT_DELETED) {
486  errno = 0;
487  fprintf (db_file, "\n deleted;");
488  if (errno)
489  ++errors;
490  } else {
491  if (group -> group) {
492  errno = 0;
494  group -> group -> statements, 8);
495  if (errno)
496  ++errors;
497  }
498  }
499 
500  errno = 0;
501  fputs ("\n}\n", db_file);
502  if (errno)
503  ++errors;
504 
505  if (errors) {
506  log_info ("write_group: unable to write group %s",
507  group -> name);
509  }
510 
511  return !errors;
512 }
513 
514 /*
515  * Write an IA and the options it has.
516  */
517 int
518 write_ia(const struct ia_xx *ia) {
519  struct iasubopt *iasubopt;
520  struct binding *bnd;
521  int i;
522  char addr_buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff.255.255.255.255")];
523  const char *binding_state;
524  const char *tval;
525  char *s;
526  int fprintf_ret;
527 
528 #ifdef EUI_64
529  /* If we're not writing EUI64 leases to the file, then
530  * we can skip writing this IA provided all of its leases
531  * are EUI64. (Not sure you can ever have a case where
532  * they aren't but doesn't hurt to check) */
533  if (ia->ia_type == D6O_IA_NA && !persist_eui64) {
534  int i;
535  for (i=0; i < ia->num_iasubopt; i++) {
536  if (!ia->iasubopt[i]->ipv6_pool->ipv6_pond->use_eui_64)
537  {
538  break;
539  }
540  }
541 
542  if (i == ia->num_iasubopt) {
543  /* Their all EUI64 so we can skip it */
544  return(1);
545  }
546  }
547 #endif
548 
549  /*
550  * If the lease file is corrupt, don't try to write any more
551  * leases until we've written a good lease file.
552  */
553  if (lease_file_is_corrupt) {
554  if (!new_lease_file(0)) {
555  return 0;
556  }
557  }
558 
559  if (counting) {
560  ++count;
561  }
562 
565  if (s == NULL) {
566  goto error_exit;
567  }
568  switch (ia->ia_type) {
569  case D6O_IA_NA:
570  fprintf_ret = fprintf(db_file, "ia-na %s {\n", s);
571  break;
572  case D6O_IA_TA:
573  fprintf_ret = fprintf(db_file, "ia-ta %s {\n", s);
574  break;
575  case D6O_IA_PD:
576  fprintf_ret = fprintf(db_file, "ia-pd %s {\n", s);
577  break;
578  default:
579  log_error("Unknown ia type %u for %s at %s:%d",
580  (unsigned)ia->ia_type, s, MDL);
581  fprintf_ret = -1;
582  }
583  dfree(s, MDL);
584  if (fprintf_ret < 0) {
585  goto error_exit;
586  }
587  if (ia->cltt != MIN_TIME) {
588  tval = print_time(ia->cltt);
589  if (tval == NULL) {
590  goto error_exit;
591  }
592  if (fprintf(db_file, " cltt %s\n", tval) < 0) {
593  goto error_exit;
594  }
595  }
596  for (i=0; i<ia->num_iasubopt; i++) {
597  iasubopt = ia->iasubopt[i];
598 
599  inet_ntop(AF_INET6, &iasubopt->addr,
600  addr_buf, sizeof(addr_buf));
601  if ((ia->ia_type != D6O_IA_PD) &&
602  (fprintf(db_file, " iaaddr %s {\n", addr_buf) < 0)) {
603  goto error_exit;
604  }
605  if ((ia->ia_type == D6O_IA_PD) &&
606  (fprintf(db_file, " iaprefix %s/%d {\n",
607  addr_buf, (int)iasubopt->plen) < 0)) {
608  goto error_exit;
609  }
610  if ((iasubopt->state <= 0) || (iasubopt->state > FTS_LAST)) {
611  log_fatal("Unknown iasubopt state %d at %s:%d",
612  iasubopt->state, MDL);
613  }
614  binding_state = binding_state_names[iasubopt->state-1];
615  if (fprintf(db_file, " binding state %s;\n",
616  binding_state) < 0) {
617  goto error_exit;
618  }
619  if (fprintf(db_file, " preferred-life %u;\n",
620  (unsigned)iasubopt->prefer) < 0) {
621  goto error_exit;
622  }
623  if (fprintf(db_file, " max-life %u;\n",
624  (unsigned)iasubopt->valid) < 0) {
625  goto error_exit;
626  }
627 
628  /* Note that from here on out, the \n is prepended to the
629  * next write, rather than appended to the current write.
630  */
631  if ((iasubopt->state == FTS_ACTIVE) ||
632  (iasubopt->state == FTS_ABANDONED) ||
635  } else {
637  }
638  if (tval == NULL) {
639  goto error_exit;
640  }
641  if (fprintf(db_file, " ends %s", tval) < 0) {
642  goto error_exit;
643  }
644 
645  /* Write out any binding scopes: note that 'ends' above does
646  * not have \n on the end! We want that.
647  */
648  if (iasubopt->scope != NULL)
649  bnd = iasubopt->scope->bindings;
650  else
651  bnd = NULL;
652 
653  for (; bnd != NULL ; bnd = bnd->next) {
654  if (bnd->value == NULL)
655  continue;
656 
657  /* We don't do a regular error_exit because the
658  * lease db is not corrupt in this case.
659  */
660  if (write_binding_scope(db_file, bnd,
661  "\n ") != ISC_R_SUCCESS)
662  goto error_exit;
663 
664  }
665 
666  if (iasubopt->on_star.on_expiry) {
667  if (fprintf(db_file, "\n on expiry%s {",
670  ? " or release" : "") < 0)
671  goto error_exit;
674  if (fprintf(db_file, "\n }") < 0)
675  goto error_exit;
676  }
677 
678  if (iasubopt->on_star.on_release &&
681  if (fprintf(db_file, "\n on release {") < 0)
682  goto error_exit;
685  if (fprintf(db_file, "\n }") < 0)
686  goto error_exit;
687  }
688 
689  if (fprintf(db_file, "\n }\n") < 0)
690  goto error_exit;
691  }
692  if (fprintf(db_file, "}\n\n") < 0)
693  goto error_exit;
694 
695  fflush(db_file);
696  return 1;
697 
698 error_exit:
699  log_info("write_ia: unable to write ia");
701  return 0;
702 }
703 
704 #ifdef DHCPv6
705 /*
706  * Put a copy of the server DUID in the leases file.
707  */
708 int
709 write_server_duid(void) {
710  struct data_string server_duid;
711  char *s;
712  int fprintf_ret;
713 
714  /*
715  * Only write the DUID if it's been set.
716  */
717  if (!server_duid_isset()) {
718  return 1;
719  }
720 
721  /*
722  * If the lease file is corrupt, don't try to write any more
723  * leases until we've written a good lease file.
724  */
725  if (lease_file_is_corrupt) {
726  if (!new_lease_file(0)) {
727  return 0;
728  }
729  }
730 
731  /*
732  * Get a copy of our server DUID and convert to a quoted string.
733  */
734  memset(&server_duid, 0, sizeof(server_duid));
735  copy_server_duid(&server_duid, MDL);
736  s = format_lease_id(server_duid.data, server_duid.len, lease_id_format,
737  MDL);
738  data_string_forget(&server_duid, MDL);
739  if (s == NULL) {
740  goto error_exit;
741  }
742 
743  /*
744  * Write to the leases file.
745  */
746  fprintf_ret = fprintf(db_file, "server-duid %s;\n\n", s);
747  dfree(s, MDL);
748  if (fprintf_ret < 0) {
749  goto error_exit;
750  }
751 
752  /*
753  * Check if we actually managed to write.
754  */
755  fflush(db_file);
756  return 1;
757 
758 error_exit:
759  log_info("write_server_duid: unable to write server-duid");
761  return 0;
762 }
763 #endif /* DHCPv6 */
764 
765 #if defined (FAILOVER_PROTOCOL)
766 int write_failover_state (dhcp_failover_state_t *state)
767 {
768  int errors = 0;
769  const char *tval;
770 
772  if (!new_lease_file (0))
773  return 0;
774 
775  errno = 0;
776  fprintf (db_file, "\nfailover peer \"%s\" state {", state -> name);
777  if (errno)
778  ++errors;
779 
780  tval = print_time(state->me.stos);
781  if (tval == NULL ||
782  fprintf(db_file, "\n my state %s at %s",
783  (state->me.state == startup) ?
784  dhcp_failover_state_name_print(state->saved_state) :
785  dhcp_failover_state_name_print(state->me.state),
786  tval) < 0)
787  ++errors;
788 
789  tval = print_time(state->partner.stos);
790  if (tval == NULL ||
791  fprintf(db_file, "\n partner state %s at %s",
792  dhcp_failover_state_name_print(state->partner.state),
793  tval) < 0)
794  ++errors;
795 
796  if (state -> i_am == secondary) {
797  errno = 0;
798  fprintf (db_file, "\n mclt %ld;",
799  (unsigned long)state -> mclt);
800  if (errno)
801  ++errors;
802  }
803 
804  errno = 0;
805  fprintf (db_file, "\n}\n");
806  if (errno)
807  ++errors;
808 
809  if (errors) {
810  log_info ("write_failover_state: unable to write state %s",
811  state -> name);
813  return 0;
814  }
815 
816  return 1;
817 
818 }
819 #endif
820 
822  const unsigned char *s;
823 {
824  int i;
825  for (i = 0; s [i]; i++)
826  if (!isascii (s [i]) || !isprint (s [i])
827  || s [i] == '"' || s [i] == '\\')
828  return 0;
829  return 1;
830 }
831 
833  const unsigned char *s;
834  unsigned len;
835 {
836  int i;
837 
838  for (i = 0; i < len; i++)
839  if (!isascii (s [i]) || !isprint (s [i]) ||
840  s [i] == '"' || s [i] == '\\')
841  return 0;
842  return 1;
843 }
844 
845 static int print_hash_string(FILE *fp, struct class *class)
846 {
847  int i;
848 
849  for (i = 0 ; i < class->hash_string.len ; i++)
850  if (!isascii(class->hash_string.data[i]) ||
851  !isprint(class->hash_string.data[i]))
852  break;
853 
854  if (i == class->hash_string.len) {
855  if (fprintf(fp, " \"%.*s\"", (int)class->hash_string.len,
856  class->hash_string.data) <= 0) {
857  log_error("Failure writing hash string: %m");
858  return 0;
859  }
860  } else {
861  if (fprintf(fp, " %2.2x", class->hash_string.data[0]) <= 0) {
862  log_error("Failure writing hash string: %m");
863  return 0;
864  }
865  for (i = 1 ; i < class->hash_string.len ; i++) {
866  if (fprintf(fp, ":%2.2x",
867  class->hash_string.data[i]) <= 0) {
868  log_error("Failure writing hash string: %m");
869  return 0;
870  }
871  }
872  }
873 
874  return 1;
875 }
876 
877 
878 isc_result_t
879 write_named_billing_class(const void *key, unsigned len, void *object)
880 {
881  const unsigned char *name = key;
882  struct class *class = object;
883 
884  if (class->flags & CLASS_DECL_DYNAMIC) {
886  if (class->superclass == 0) {
887  if (fprintf(db_file, "class \"%s\" {\n", name) <= 0)
888  return ISC_R_IOERROR;
889  } else {
890  if (fprintf(db_file, "subclass \"%s\"",
891  class->superclass->name) <= 0)
892  return ISC_R_IOERROR;
893  if (!print_hash_string(db_file, class))
894  return ISC_R_IOERROR;
895  if (fprintf(db_file, " {\n") <= 0)
896  return ISC_R_IOERROR;
897  }
898 
899  if ((class->flags & CLASS_DECL_DELETED) != 0) {
900  if (fprintf(db_file, " deleted;\n") <= 0)
901  return ISC_R_IOERROR;
902  } else {
903  if (fprintf(db_file, " dynamic;\n") <= 0)
904  return ISC_R_IOERROR;
905  }
906 
907  if (class->lease_limit > 0) {
908  if (fprintf(db_file, " lease limit %d;\n",
909  class->lease_limit) <= 0)
910  return ISC_R_IOERROR;
911  }
912 
913  if (class->expr != 0) {
914  if (fprintf(db_file, " match if ") <= 0)
915  return ISC_R_IOERROR;
916 
917  errno = 0;
918  write_expression(db_file, class->expr, 5, 5, 0);
919  if (errno)
920  return ISC_R_IOERROR;
921 
922  if (fprintf(db_file, ";\n") <= 0)
923  return ISC_R_IOERROR;
924  }
925 
926  if (class->submatch != 0) {
927  if (class->spawning) {
928  if (fprintf(db_file, " spawn ") <= 0)
929  return ISC_R_IOERROR;
930  } else {
931  if (fprintf(db_file, " match ") <= 0)
932  return ISC_R_IOERROR;
933  }
934 
935  errno = 0;
937  if (errno)
938  return ISC_R_IOERROR;
939 
940  if (fprintf(db_file, ";\n") <= 0)
941  return ISC_R_IOERROR;
942  }
943 
944  if (class->statements != 0) {
945  errno = 0;
947  if (errno)
948  return ISC_R_IOERROR;
949  }
950 
951  /* XXXJAB this isn't right, but classes read in off the
952  leases file don't get the root group assigned to them
953  (due to clone_group() call). */
954  if (class->group != 0 && class->group->authoritative != 0) {
955  errno = 0;
957  if (errno)
958  return ISC_R_IOERROR;
959  }
960 
961  if (fprintf(db_file, "}\n\n") <= 0)
962  return ISC_R_IOERROR;
963  }
964 
965  if (class->hash != NULL) { /* yep. recursive. god help us. */
966  /* XXX - cannot check error status of this...
967  * foo_hash_foreach returns a count of operations completed.
968  */
969  class_hash_foreach(class->hash, write_named_billing_class);
970  }
971 
972  return ISC_R_SUCCESS;
973 }
974 
976 {
977  struct collection *lp;
978  struct class *cp;
979 
980  for (lp = collections; lp; lp = lp -> next) {
981  for (cp = lp -> classes; cp; cp = cp -> nic) {
982  if (cp -> spawning && cp -> hash) {
983  class_hash_foreach (cp -> hash, write_named_billing_class);
984  }
985  }
986  }
987 }
988 
989 /* Write a spawned class to the database file. */
990 
992  struct class *class;
993 {
994  int errors = 0;
995 
997  if (!new_lease_file (0))
998  return 0;
999 
1000  if (!class -> superclass) {
1001  errno = 0;
1002  fprintf (db_file, "\n billing class \"%s\";", class -> name);
1003  return !errno;
1004  }
1005 
1006  if (fprintf(db_file, "\n billing subclass \"%s\"",
1007  class -> superclass -> name) < 0)
1008  ++errors;
1009 
1010  if (!print_hash_string(db_file, class))
1011  ++errors;
1012 
1013  if (fprintf(db_file, ";") < 0)
1014  ++errors;
1015 
1016  class -> dirty = !errors;
1017  if (errors)
1019 
1020  return !errors;
1021 }
1022 
1023 /* Commit leases after a timeout. */
1024 void commit_leases_timeout (void *foo)
1025 {
1026  commit_leases ();
1027 }
1028 
1029 /* Commit any leases that have been written out... */
1030 
1032 {
1033  /* Commit any outstanding writes to the lease database file.
1034  We need to do this even if we're rewriting the file below,
1035  just in case the rewrite fails. */
1036  if (fflush (db_file) == EOF) {
1037  log_info("commit_leases: unable to commit, fflush(): %m");
1038  return (0);
1039  }
1040  if ((dont_use_fsync == 0) &&
1041  (fsync(fileno (db_file)) < 0)) {
1042  log_info ("commit_leases: unable to commit, fsync(): %m");
1043  return (0);
1044  }
1045 
1046  /* If we haven't rewritten the lease database in over an
1047  hour, rewrite it now. (The length of time should probably
1048  be configurable. */
1049  if (count && cur_time - write_time > LEASE_REWRITE_PERIOD) {
1050  count = 0;
1051  write_time = cur_time;
1052  new_lease_file(0);
1053  }
1054  return (1);
1055 }
1056 
1057 /*
1058  * rewrite the lease file about once an hour
1059  * This is meant as a quick patch for ticket 24887. It allows
1060  * us to rotate the v6 lease file without adding too many fsync()
1061  * calls. In the future wes should revisit this area and add
1062  * something similar to the delayed ack code for v4.
1063  */
1065 {
1066  if ((count != 0) && (cur_time - write_time > LEASE_REWRITE_PERIOD)) {
1067  return (commit_leases());
1068  }
1069  return (1);
1070 }
1071 
1072 void db_startup (int test_mode)
1073 {
1074  const char *current_db_path;
1075  isc_result_t status;
1076 
1077 #if defined (TRACING)
1078  if (!trace_playback ()) {
1079 #endif
1080  /* Unset authoring_byte_order so we'll know if it was specified
1081  in the lease file or not. */
1083 
1084  /* Read in the existing lease file... */
1085  status = read_conf_file (path_dhcpd_db,
1086  (struct group *)0, 0, 1);
1087  if (status != ISC_R_SUCCESS) {
1088  /* XXX ignore status? */
1089  ;
1090  }
1091 
1092 #if defined (TRACING)
1093  }
1094 #endif
1095 
1096 #if defined (TRACING)
1097  /* If we're playing back, there is no lease file, so we can't
1098  append it, so we create one immediately (maybe this isn't
1099  the best solution... */
1100  if (trace_playback ()) {
1101  new_lease_file (0);
1102  }
1103 #endif
1104  /* expire_all_pools will cause writes to the "current" lease file.
1105  * Therefore, in test mode we need to point db_file to a disposable
1106  * file to protect the original lease file. */
1107  current_db_path = (test_mode ? "/dev/null" : path_dhcpd_db);
1108  db_file = fopen (current_db_path, "a");
1109  if (!db_file) {
1110  log_fatal ("Can't open %s for append.", current_db_path);
1111  }
1112 
1113  expire_all_pools ();
1114 #if defined (TRACING)
1115  if (trace_playback ())
1116  write_time = cur_time;
1117  else
1118 #endif
1119  time(&write_time);
1120  new_lease_file (test_mode);
1121 
1122 #if defined(REPORT_HASH_PERFORMANCE)
1123  log_info("Host HW hash: %s", host_hash_report(host_hw_addr_hash));
1124  log_info("Host UID hash: %s", host_hash_report(host_uid_hash));
1125  log_info("Lease IP hash: %s",
1126  lease_ip_hash_report(lease_ip_addr_hash));
1127  log_info("Lease UID hash: %s", lease_id_hash_report(lease_uid_hash));
1128  log_info("Lease HW hash: %s",
1129  lease_id_hash_report(lease_hw_addr_hash));
1130 #endif
1131 }
1132 
1133 int new_lease_file (int test_mode)
1134 {
1135  char newfname [512];
1136  char backfname [512];
1137  TIME t;
1138  int db_fd;
1139  int db_validity;
1140  FILE *new_db_file;
1141 
1142  /* Make a temporary lease file... */
1143  time(&t);
1144 
1145  db_validity = lease_file_is_corrupt;
1146 
1147  /* %Audit% Truncated filename causes panic. %2004.06.17,Safe%
1148  * This should never happen since the path is a configuration
1149  * variable from build-time or command-line. But if it should,
1150  * either by malice or ignorance, we panic, since the potential
1151  * for havoc is high.
1152  */
1153  if (snprintf (newfname, sizeof newfname, "%s.%d",
1154  path_dhcpd_db, (int)t) >= sizeof newfname)
1155  log_fatal("new_lease_file: lease file path too long");
1156 
1157  db_fd = open (newfname, O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, 0664);
1158  if (db_fd < 0) {
1159  log_error ("Can't create new lease file: %m");
1160  return 0;
1161  }
1162 
1163 #if defined (PARANOIA)
1164  /*
1165  * If we are currently root and plan to change the
1166  * uid and gid change the file information so we
1167  * can manipulate it later, after we've changed
1168  * our group and user (that is dropped privileges.)
1169  */
1170  if ((set_uid != 0) && (geteuid() == 0) &&
1171  (set_gid != 0) && (getegid() == 0)) {
1172  if (fchown(db_fd, set_uid, set_gid)) {
1173  log_fatal ("Can't chown new lease file: %m");
1174  }
1175  }
1176 #endif /* PARANOIA */
1177 
1178  if ((new_db_file = fdopen(db_fd, "we")) == NULL) {
1179  log_error("Can't fdopen new lease file: %m");
1180  close(db_fd);
1181  goto fdfail;
1182  }
1183 
1184  /* Close previous database, if any. */
1185  if (db_file)
1186  fclose(db_file);
1187  db_file = new_db_file;
1188 
1189  errno = 0;
1190  fprintf (db_file, "# The format of this file is documented in the %s",
1191  "dhcpd.leases(5) manual page.\n");
1192 
1193  if (errno)
1194  goto fail;
1195 
1196  fprintf (db_file, "# This lease file was written by isc-dhcp-%s\n\n",
1197  PACKAGE_VERSION);
1198  if (errno)
1199  goto fail;
1200 
1201  fprintf (db_file, "# authoring-byte-order entry is generated,"
1202  " DO NOT DELETE\n");
1203  if (errno)
1204  goto fail;
1205 
1206  fprintf (db_file, "authoring-byte-order %s;\n\n",
1208  "little-endian" : "big-endian"));
1209  if (errno)
1210  goto fail;
1211 
1212  /* At this point we have a new lease file that, so far, could not
1213  * be described as either corrupt nor valid.
1214  */
1216 
1217  /* Write out all the leases that we know of... */
1218  counting = 0;
1219  if (!write_leases ())
1220  goto fail;
1221 
1222  if (test_mode) {
1223  log_debug("Lease file test successful,"
1224  " removing temp lease file: %s",
1225  newfname);
1226  (void)unlink (newfname);
1227  return (1);
1228  }
1229 
1230 #if defined (TRACING)
1231  if (!trace_playback ()) {
1232 #endif
1233  /* %Audit% Truncated filename causes panic. %2004.06.17,Safe%
1234  * This should never happen since the path is a configuration
1235  * variable from build-time or command-line. But if it should,
1236  * either by malice or ignorance, we panic, since the potential
1237  * for havoc is too high.
1238  */
1239  if (snprintf (backfname, sizeof backfname, "%s~", path_dhcpd_db)
1240  >= sizeof backfname)
1241  log_fatal("new_lease_file: backup lease file path too long");
1242 
1243  /* Get the old database out of the way... */
1244  if (unlink (backfname) < 0 && errno != ENOENT) {
1245  log_error ("Can't remove old lease database backup %s: %m",
1246  backfname);
1247  goto fail;
1248  }
1249  if (link(path_dhcpd_db, backfname) < 0) {
1250  if (errno == ENOENT) {
1251  log_error("%s is missing - no lease db to backup.",
1252  path_dhcpd_db);
1253  } else {
1254  log_error("Can't backup lease database %s to %s: %m",
1255  path_dhcpd_db, backfname);
1256  goto fail;
1257  }
1258  }
1259 #if defined (TRACING)
1260  }
1261 #endif
1262 
1263  /* Move in the new file... */
1264  if (rename (newfname, path_dhcpd_db) < 0) {
1265  log_error ("Can't install new lease database %s to %s: %m",
1266  newfname, path_dhcpd_db);
1267  goto fail;
1268  }
1269 
1270  counting = 1;
1271  return 1;
1272 
1273  fail:
1274  lease_file_is_corrupt = db_validity;
1275  fdfail:
1276  (void)unlink (newfname);
1277  return 0;
1278 }
1279 
1281 {
1282  if (!write_group (group))
1283  return 0;
1284  if (!commit_leases ())
1285  return 0;
1286  return 1;
1287 }
void data_string_forget(struct data_string *data, const char *file, int line)
Definition: alloc.c:1339
const char * pretty_print_option(struct option *option, const unsigned char *data, unsigned len, int emit_commas, int emit_quotes)
Definition: options.c:1793
struct collection * collections
Definition: parse.c:34
char * quotify_buf(const unsigned char *s, unsigned len, char enclose_char, const char *file, int line)
Definition: print.c:71
char * quotify_string(const char *s, const char *file, int line)
Definition: print.c:33
const char * print_time(TIME t)
Definition: print.c:1312
char * format_lease_id(const unsigned char *s, unsigned len, int format, const char *file, int line)
Definition: print.c:1427
char * print_hw_addr(int htype, const int hlen, const unsigned char *data) const
Definition: print.c:171
#define PACKAGE_VERSION
Definition: config.h:168
#define DHCP_BYTE_ORDER
Definition: config.h:21
int write_group(struct group_object *group)
Definition: db.c:449
int lease_file_is_corrupt
Definition: db.c:43
void commit_leases_timeout(void *foo)
Definition: db.c:1024
int write_ia(const struct ia_xx *ia)
Definition: db.c:518
int write_host(struct host_decl *host)
Definition: db.c:298
void write_billing_classes()
Definition: db.c:975
int commit_leases()
Definition: db.c:1031
int db_printable_len(unsigned char *s, unsigned len) const
Definition: db.c:832
int db_printable(unsigned char *s) const
Definition: db.c:821
FILE * db_file
Definition: db.c:38
int new_lease_file(int test_mode)
Definition: db.c:1133
void db_startup(int test_mode)
Definition: db.c:1072
TIME write_time
Definition: db.c:42
int write_billing_class(struct class *class)
Definition: db.c:991
int commit_leases_timed()
Definition: db.c:1064
int write_lease(struct lease *lease)
Definition: db.c:98
int group_writer(struct group_object *group)
Definition: db.c:1280
#define LEASE_REWRITE_PERIOD
Definition: db.c:33
isc_result_t write_named_billing_class(const void *key, unsigned len, void *object)
Definition: db.c:879
#define D6O_IA_PD
Definition: dhcp6.h:54
#define D6O_IA_TA
Definition: dhcp6.h:33
#define D6O_IA_NA
Definition: dhcp6.h:32
host_hash_t * host_hw_addr_hash
Definition: mdb.c:34
int write_server_duid(void)
int write_failover_state(dhcp_failover_state_t *)
#define HOST_DECL_DYNAMIC
Definition: dhcpd.h:993
#define GROUP_OBJECT_DELETED
Definition: dhcpd.h:956
#define HOST_DECL_DELETED
Definition: dhcpd.h:992
#define MIN_TIME
Definition: dhcpd.h:1632
lease_id_hash_t * lease_hw_addr_hash
Definition: mdb.c:39
time_t TIME
Definition: dhcpd.h:85
int dont_use_fsync
Definition: dhcpd.c:85
void expire_all_pools(void)
Definition: mdb.c:2835
void copy_server_duid(struct data_string *ds, const char *file, int line)
const char * path_dhcpd_db
Definition: dhcpd.c:102
lease_id_hash_t * lease_uid_hash
Definition: mdb.c:37
#define cur_time
Definition: dhcpd.h:2126
host_hash_t * host_uid_hash
Definition: mdb.c:35
int lease_id_format
Definition: dhcpd.c:98
gid_t set_gid
#define FTS_LAST
Definition: dhcpd.h:547
#define GROUP_OBJECT_STATIC
Definition: dhcpd.h:958
#define GROUP_OBJECT_DYNAMIC
Definition: dhcpd.h:957
uid_t set_uid
#define FTS_ACTIVE
Definition: dhcpd.h:538
const char * dhcp_failover_state_name_print(enum failover_state)
isc_boolean_t server_duid_isset(void)
int write_leases(void)
Definition: mdb.c:2434
#define CLASS_DECL_DELETED
Definition: dhcpd.h:1134
isc_result_t read_conf_file(const char *, struct group *, int, int)
Definition: confpars.c:79
#define RESERVED_LEASE
Definition: dhcpd.h:594
const char * binding_state_names[]
Definition: stables.c:161
#define BOOTP_LEASE
Definition: dhcpd.h:593
#define FTS_ABANDONED
Definition: dhcpd.h:541
int numclasseswritten
Definition: mdb.c:68
#define CLASS_DECL_DYNAMIC
Definition: dhcpd.h:1135
int authoring_byte_order
Definition: dhcpd.c:97
lease_ip_hash_t * lease_ip_addr_hash
Definition: mdb.c:38
void write_statements(FILE *file, struct executable_statement *statements, int indent)
Definition: execute.c:759
@ startup
Definition: failover.h:290
struct iaddr ip_addr(struct iaddr subnet, struct iaddr mask, u_int32_t host_address)
Definition: inet.c:63
const char * piaddr(const struct iaddr addr)
Definition: inet.c:579
#define ISC_R_SUCCESS
struct group * root_group
Definition: memory.c:31
#define MDL
Definition: omapip.h:567
void dfree(void *, const char *, int)
Definition: alloc.c:145
int log_error(const char *,...) __attribute__((__format__(__printf__
int int int log_debug(const char *,...) __attribute__((__format__(__printf__
void log_fatal(const char *,...) __attribute__((__format__(__printf__
int int log_info(const char *,...) __attribute__((__format__(__printf__
#define LITTLE_ENDIAN
Definition: osdep.h:39
#define DHCP_R_INVALIDARG
Definition: result.h:49
Definition: tree.h:30
struct binding * bindings
Definition: tree.h:126
union binding_value::value value
enum binding_value::@15 type
Definition: tree.h:117
char * name
Definition: tree.h:119
struct binding * next
Definition: tree.h:118
struct binding_value * value
Definition: tree.h:120
Definition: dhcpd.h:1102
int flags
Definition: dhcpd.h:1139
struct class * nic
Definition: dhcpd.h:1104
struct executable_statement * statements
Definition: dhcpd.h:1132
struct expression * submatch
Definition: dhcpd.h:1126
struct group * group
Definition: dhcpd.h:1129
struct expression * expr
Definition: dhcpd.h:1122
struct class * superclass
Definition: dhcpd.h:1105
class_hash_t * hash
Definition: dhcpd.h:1118
int spawning
Definition: dhcpd.h:1127
struct data_string hash_string
Definition: dhcpd.h:1119
char * name
Definition: dhcpd.h:1106
int lease_limit
Definition: dhcpd.h:1109
const unsigned char * data
Definition: tree.h:78
unsigned len
Definition: tree.h:79
char * name
Definition: dhcpd.h:954
struct group * group
Definition: dhcpd.h:953
int flags
Definition: dhcpd.h:955
Definition: dhcpd.h:962
int authoritative
Definition: dhcpd.h:969
struct executable_statement * statements
Definition: dhcpd.h:970
char * name
Definition: dhcpd.h:978
Definition: dhcpd.h:1681
int num_iasubopt
Definition: dhcpd.h:1685
time_t cltt
Definition: dhcpd.h:1687
struct data_string iaid_duid
Definition: dhcpd.h:1683
struct iasubopt ** iasubopt
Definition: dhcpd.h:1688
u_int16_t ia_type
Definition: dhcpd.h:1684
u_int8_t plen
Definition: dhcpd.h:1649
binding_state_t state
Definition: dhcpd.h:1650
time_t hard_lifetime_end_time
Definition: dhcpd.h:1652
u_int32_t prefer
Definition: dhcpd.h:1654
struct in6_addr addr
Definition: dhcpd.h:1648
u_int32_t valid
Definition: dhcpd.h:1655
struct binding_scope * scope
Definition: dhcpd.h:1651
struct on_star on_star
Definition: dhcpd.h:1677
struct ipv6_pool * ipv6_pool
Definition: dhcpd.h:1657
time_t soft_lifetime_end_time
Definition: dhcpd.h:1653
struct ipv6_pond * ipv6_pond
Definition: dhcpd.h:1731
Definition: dhcpd.h:560
TIME atsfp
Definition: dhcpd.h:639
TIME ends
Definition: dhcpd.h:570
u_int8_t flags
Definition: dhcpd.h:591
TIME starts
Definition: dhcpd.h:570
struct binding_scope * scope
Definition: dhcpd.h:575
char * client_hostname
Definition: dhcpd.h:574
binding_state_t rewind_binding_state
Definition: dhcpd.h:626
unsigned char * uid
Definition: dhcpd.h:585
TIME tstp
Definition: dhcpd.h:637
struct on_star on_star
Definition: dhcpd.h:583
TIME tsfp
Definition: dhcpd.h:638
binding_state_t binding_state
Definition: dhcpd.h:623
unsigned short uid_len
Definition: dhcpd.h:586
TIME cltt
Definition: dhcpd.h:640
struct executable_statement * on_expiry
Definition: dhcpd.h:554
struct executable_statement * on_release
Definition: dhcpd.h:556
struct data_string data
Definition: dhcpd.h:390
Definition: tree.h:345
Definition: dhcpd.h:405
const char * hardware_types[]
Definition: tables.c:716
int trace_playback(void)
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
int write_expression(FILE *file, struct expression *expr, int col, int indent, int firstp)
Definition: tree.c:3298
struct binding_scope * global_scope
Definition: tree.c:38
struct data_string data
Definition: tree.h:109
unsigned long intval
Definition: tree.h:110