ISC DHCP  4.3.3
A reference DHCPv4 and DHCPv6 implementation
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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) 2012-2015 by Internet Systems Consortium, Inc. ("ISC")
7  * Copyright (c) 2004-2010 by Internet Systems Consortium, Inc. ("ISC")
8  * Copyright (c) 1995-2003 by Internet Software Consortium
9  *
10  * Permission to use, copy, modify, and distribute this software for any
11  * purpose with or without fee is hereby granted, provided that the above
12  * copyright notice and this permission notice appear in all copies.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
15  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
17  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
20  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21  *
22  * Internet Systems Consortium, Inc.
23  * 950 Charter Street
24  * Redwood City, CA 94063
25  * <info@isc.org>
26  * https://www.isc.org/
27  *
28  */
29 
30 #include "dhcpd.h"
31 #include <ctype.h>
32 #include <errno.h>
33 
34 #define LEASE_REWRITE_PERIOD 3600
35 
36 static isc_result_t write_binding_scope(FILE *db_file, struct binding *bnd,
37  char *prepend);
38 
39 FILE *db_file;
40 
41 static int counting = 0;
42 static int count = 0;
45 
46 /* Write a single binding scope value in parsable format.
47  */
48 
49 static isc_result_t
50 write_binding_scope(FILE *db_file, struct binding *bnd, char *prepend) {
51  char *s;
52 
53  if ((db_file == NULL) || (bnd == NULL) || (prepend == NULL))
54  return DHCP_R_INVALIDARG;
55 
56  if (bnd->value->type == binding_data) {
57  if (bnd->value->value.data.data != NULL) {
58  s = quotify_buf(bnd->value->value.data.data,
59  bnd->value->value.data.len, MDL);
60  if (s != NULL) {
61  errno = 0;
62  fprintf(db_file, "%sset %s = \"%s\";",
63  prepend, bnd->name, s);
64  dfree(s, MDL);
65  if (errno)
66  return ISC_R_FAILURE;
67  } else {
68  return ISC_R_FAILURE;
69  }
70  }
71  } else if (bnd->value->type == binding_numeric) {
72  errno = 0;
73  fprintf(db_file, "%sset %s = %%%ld;", prepend,
74  bnd->name, bnd->value->value.intval);
75  if (errno)
76  return ISC_R_FAILURE;
77  } else if (bnd->value->type == binding_boolean) {
78  errno = 0;
79  fprintf(db_file, "%sset %s = %s;", prepend, bnd->name,
80  bnd->value->value.intval ? "true" : "false");
81  if (errno)
82  return ISC_R_FAILURE;
83  } else if (bnd->value->type == binding_dns) {
84  log_error("%s: persistent dns values not supported.",
85  bnd->name);
86  } else if (bnd->value->type == binding_function) {
87  log_error("%s: persistent functions not supported.",
88  bnd->name);
89  } else {
90  log_fatal("%s: unknown binding type %d", bnd->name,
91  bnd->value->type);
92  }
93 
94  return ISC_R_SUCCESS;
95 }
96 
97 /* Write the specified lease to the current lease database file. */
98 
100  struct lease *lease;
101 {
102  int errors = 0;
103  struct binding *b;
104  char *s;
105  const char *tval;
106 
107  /* If the lease file is corrupt, don't try to write any more leases
108  until we've written a good lease file. */
110  if (!new_lease_file ())
111  return 0;
112 
113  if (counting)
114  ++count;
115  errno = 0;
116  fprintf (db_file, "lease %s {", piaddr (lease -> ip_addr));
117  if (errno) {
118  ++errors;
119  }
120 
121  if (lease->starts &&
122  ((tval = print_time(lease->starts)) == NULL ||
123  fprintf(db_file, "\n starts %s", tval) < 0))
124  ++errors;
125 
126  if (lease->ends &&
127  ((tval = print_time(lease->ends)) == NULL ||
128  fprintf(db_file, "\n ends %s", tval) < 0))
129  ++errors;
130 
131  if (lease->tstp &&
132  ((tval = print_time(lease->tstp)) == NULL ||
133  fprintf(db_file, "\n tstp %s", tval) < 0))
134  ++errors;
135 
136  if (lease->tsfp &&
137  ((tval = print_time(lease->tsfp)) == NULL ||
138  fprintf(db_file, "\n tsfp %s", tval) < 0))
139  ++errors;
140 
141  if (lease->atsfp &&
142  ((tval = print_time(lease->atsfp)) == NULL ||
143  fprintf(db_file, "\n atsfp %s", tval) < 0))
144  ++errors;
145 
146  if (lease->cltt &&
147  ((tval = print_time(lease->cltt)) == NULL ||
148  fprintf(db_file, "\n cltt %s", tval) < 0))
149  ++errors;
150 
151  if (fprintf (db_file, "\n binding state %s;",
152  ((lease -> binding_state > 0 &&
153  lease -> binding_state <= FTS_LAST)
154  ? binding_state_names [lease -> binding_state - 1]
155  : "abandoned")) < 0)
156  ++errors;
157 
158  if (lease -> binding_state != lease -> next_binding_state)
159  if (fprintf (db_file, "\n next binding state %s;",
160  ((lease -> next_binding_state > 0 &&
161  lease -> next_binding_state <= FTS_LAST)
163  [lease -> next_binding_state - 1])
164  : "abandoned")) < 0)
165  ++errors;
166 
167  /*
168  * In this case, if the rewind state is not present in the lease file,
169  * the reader will use the current binding state as the most
170  * conservative (safest) state. So if the in-memory rewind state is
171  * for some reason invalid, the best thing to do is not to write a
172  * state and let the reader take on a safe state.
173  */
174  if ((lease->binding_state != lease->rewind_binding_state) &&
175  (lease->rewind_binding_state > 0) &&
176  (lease->rewind_binding_state <= FTS_LAST) &&
177  (fprintf(db_file, "\n rewind binding state %s;",
178  binding_state_names[lease->rewind_binding_state-1])) < 0)
179  ++errors;
180 
181  if (lease->flags & RESERVED_LEASE)
182  if (fprintf(db_file, "\n reserved;") < 0)
183  ++errors;
184 
185  if (lease->flags & BOOTP_LEASE)
186  if (fprintf(db_file, "\n dynamic-bootp;") < 0)
187  ++errors;
188 
189  /* If this lease is billed to a class and is still valid,
190  write it out. */
191  if (lease -> billing_class && lease -> ends > cur_time) {
192  if (!write_billing_class (lease -> billing_class)) {
193  log_error ("unable to write class %s",
194  lease -> billing_class -> name);
195  ++errors;
196  }
197  }
198 
199  if (lease -> hardware_addr.hlen) {
200  errno = 0;
201  fprintf (db_file, "\n hardware %s %s;",
202  hardware_types [lease -> hardware_addr.hbuf [0]],
203  print_hw_addr (lease -> hardware_addr.hbuf [0],
204  lease -> hardware_addr.hlen - 1,
205  &lease -> hardware_addr.hbuf [1]));
206  if (errno)
207  ++errors;
208  }
209  if (lease -> uid_len) {
210  s = quotify_buf (lease -> uid, lease -> uid_len, 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 {",
265  lease->on_star.on_expiry == lease->on_star.on_release
266  ? " or release" : "");
267  write_statements (db_file, lease->on_star.on_expiry, 4);
268  /* XXX */
269  fprintf (db_file, "\n }");
270  if (errno)
271  ++errors;
272  }
273  if (lease->on_star.on_release &&
274  lease->on_star.on_release != lease->on_star.on_expiry) {
275  errno = 0;
276  fprintf (db_file, "\n on release {");
277  write_statements (db_file, lease->on_star.on_release, 4);
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 ())
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  errno = 0;
406  fputc (';', db_file);
407  if (errno)
408  ++errors;
409  data_string_forget (&ip_addrs, MDL);
410  }
411 
412  if (host -> named_group) {
413  errno = 0;
414  fprintf (db_file, "\n group \"%s\";",
415  host -> named_group -> name);
416  if (errno)
417  ++errors;
418  }
419 
420  if (host -> group &&
421  (!host -> named_group ||
422  host -> group != host -> named_group -> group) &&
423  host -> group != root_group) {
424  errno = 0;
426  host -> group -> statements, 8);
427  if (errno)
428  ++errors;
429  }
430  }
431 
432  errno = 0;
433  fputs ("\n}\n", db_file);
434  if (errno)
435  ++errors;
436 
437  if (errors) {
438  log_info ("write_host: unable to write host %s",
439  host -> name);
441  }
442 
443  return !errors;
444 }
445 
447  struct group_object *group;
448 {
449  int errors = 0;
450 
451  /* If the lease file is corrupt, don't try to write any more leases
452  until we've written a good lease file. */
454  if (!new_lease_file ())
455  return 0;
456 
457  if (!db_printable((unsigned char *)group->name))
458  return 0;
459 
460  if (counting)
461  ++count;
462 
463  errno = 0;
464  fprintf (db_file, "group %s {", group -> name);
465  if (errno)
466  ++errors;
467 
468  if (group -> flags & GROUP_OBJECT_DYNAMIC) {
469  errno = 0;
470  fprintf (db_file, "\n dynamic;");
471  if (errno)
472  ++errors;
473  }
474 
475  if (group -> flags & GROUP_OBJECT_STATIC) {
476  errno = 0;
477  fprintf (db_file, "\n static;");
478  if (errno)
479  ++errors;
480  }
481 
482  if (group -> flags & GROUP_OBJECT_DELETED) {
483  errno = 0;
484  fprintf (db_file, "\n deleted;");
485  if (errno)
486  ++errors;
487  } else {
488  if (group -> group) {
489  errno = 0;
491  group -> group -> statements, 8);
492  if (errno)
493  ++errors;
494  }
495  }
496 
497  errno = 0;
498  fputs ("\n}\n", db_file);
499  if (errno)
500  ++errors;
501 
502  if (errors) {
503  log_info ("write_group: unable to write group %s",
504  group -> name);
506  }
507 
508  return !errors;
509 }
510 
511 /*
512  * Write an IA and the options it has.
513  */
514 int
515 write_ia(const struct ia_xx *ia) {
516  struct iasubopt *iasubopt;
517  struct binding *bnd;
518  int i;
519  char addr_buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff.255.255.255.255")];
520  const char *binding_state;
521  const char *tval;
522  char *s;
523  int fprintf_ret;
524 
525  /*
526  * If the lease file is corrupt, don't try to write any more
527  * leases until we've written a good lease file.
528  */
529  if (lease_file_is_corrupt) {
530  if (!new_lease_file()) {
531  return 0;
532  }
533  }
534 
535  if (counting) {
536  ++count;
537  }
538 
539 
540  s = quotify_buf(ia->iaid_duid.data, ia->iaid_duid.len, MDL);
541  if (s == NULL) {
542  goto error_exit;
543  }
544  switch (ia->ia_type) {
545  case D6O_IA_NA:
546  fprintf_ret = fprintf(db_file, "ia-na \"%s\" {\n", s);
547  break;
548  case D6O_IA_TA:
549  fprintf_ret = fprintf(db_file, "ia-ta \"%s\" {\n", s);
550  break;
551  case D6O_IA_PD:
552  fprintf_ret = fprintf(db_file, "ia-pd \"%s\" {\n", s);
553  break;
554  default:
555  log_error("Unknown ia type %u for \"%s\" at %s:%d",
556  (unsigned)ia->ia_type, s, MDL);
557  fprintf_ret = -1;
558  }
559  dfree(s, MDL);
560  if (fprintf_ret < 0) {
561  goto error_exit;
562  }
563  if (ia->cltt != MIN_TIME) {
564  tval = print_time(ia->cltt);
565  if (tval == NULL) {
566  goto error_exit;
567  }
568  if (fprintf(db_file, " cltt %s\n", tval) < 0) {
569  goto error_exit;
570  }
571  }
572  for (i=0; i<ia->num_iasubopt; i++) {
573  iasubopt = ia->iasubopt[i];
574 
575  inet_ntop(AF_INET6, &iasubopt->addr,
576  addr_buf, sizeof(addr_buf));
577  if ((ia->ia_type != D6O_IA_PD) &&
578  (fprintf(db_file, " iaaddr %s {\n", addr_buf) < 0)) {
579  goto error_exit;
580  }
581  if ((ia->ia_type == D6O_IA_PD) &&
582  (fprintf(db_file, " iaprefix %s/%d {\n",
583  addr_buf, (int)iasubopt->plen) < 0)) {
584  goto error_exit;
585  }
586  if ((iasubopt->state <= 0) || (iasubopt->state > FTS_LAST)) {
587  log_fatal("Unknown iasubopt state %d at %s:%d",
588  iasubopt->state, MDL);
589  }
590  binding_state = binding_state_names[iasubopt->state-1];
591  if (fprintf(db_file, " binding state %s;\n",
592  binding_state) < 0) {
593  goto error_exit;
594  }
595  if (fprintf(db_file, " preferred-life %u;\n",
596  (unsigned)iasubopt->prefer) < 0) {
597  goto error_exit;
598  }
599  if (fprintf(db_file, " max-life %u;\n",
600  (unsigned)iasubopt->valid) < 0) {
601  goto error_exit;
602  }
603 
604  /* Note that from here on out, the \n is prepended to the
605  * next write, rather than appended to the current write.
606  */
607  if ((iasubopt->state == FTS_ACTIVE) ||
608  (iasubopt->state == FTS_ABANDONED) ||
609  (iasubopt->hard_lifetime_end_time != 0)) {
610  tval = print_time(iasubopt->hard_lifetime_end_time);
611  } else {
612  tval = print_time(iasubopt->soft_lifetime_end_time);
613  }
614  if (tval == NULL) {
615  goto error_exit;
616  }
617  if (fprintf(db_file, " ends %s", tval) < 0) {
618  goto error_exit;
619  }
620 
621  /* Write out any binding scopes: note that 'ends' above does
622  * not have \n on the end! We want that.
623  */
624  if (iasubopt->scope != NULL)
625  bnd = iasubopt->scope->bindings;
626  else
627  bnd = NULL;
628 
629  for (; bnd != NULL ; bnd = bnd->next) {
630  if (bnd->value == NULL)
631  continue;
632 
633  /* We don't do a regular error_exit because the
634  * lease db is not corrupt in this case.
635  */
636  if (write_binding_scope(db_file, bnd,
637  "\n ") != ISC_R_SUCCESS)
638  goto error_exit;
639 
640  }
641 
642  if (iasubopt->on_star.on_expiry) {
643  if (fprintf(db_file, "\n on expiry%s {",
644  iasubopt->on_star.on_expiry ==
645  iasubopt->on_star.on_release
646  ? " or release" : "") < 0)
647  goto error_exit;
649  iasubopt->on_star.on_expiry, 6);
650  if (fprintf(db_file, "\n }") < 0)
651  goto error_exit;
652  }
653 
654  if (iasubopt->on_star.on_release &&
655  iasubopt->on_star.on_release !=
656  iasubopt->on_star.on_expiry) {
657  if (fprintf(db_file, "\n on release {") < 0)
658  goto error_exit;
660  iasubopt->on_star.on_release, 6);
661  if (fprintf(db_file, "\n }") < 0)
662  goto error_exit;
663  }
664 
665  if (fprintf(db_file, "\n }\n") < 0)
666  goto error_exit;
667  }
668  if (fprintf(db_file, "}\n\n") < 0)
669  goto error_exit;
670 
671  fflush(db_file);
672  return 1;
673 
674 error_exit:
675  log_info("write_ia: unable to write ia");
677  return 0;
678 }
679 
680 #ifdef DHCPv6
681 /*
682  * Put a copy of the server DUID in the leases file.
683  */
684 int
685 write_server_duid(void) {
686  struct data_string server_duid;
687  char *s;
688  int fprintf_ret;
689 
690  /*
691  * Only write the DUID if it's been set.
692  */
693  if (!server_duid_isset()) {
694  return 1;
695  }
696 
697  /*
698  * If the lease file is corrupt, don't try to write any more
699  * leases until we've written a good lease file.
700  */
701  if (lease_file_is_corrupt) {
702  if (!new_lease_file()) {
703  return 0;
704  }
705  }
706 
707  /*
708  * Get a copy of our server DUID and convert to a quoted string.
709  */
710  memset(&server_duid, 0, sizeof(server_duid));
711  copy_server_duid(&server_duid, MDL);
712  s = quotify_buf(server_duid.data, server_duid.len, MDL);
713  data_string_forget(&server_duid, MDL);
714  if (s == NULL) {
715  goto error_exit;
716  }
717 
718  /*
719  * Write to the leases file.
720  */
721  fprintf_ret = fprintf(db_file, "server-duid \"%s\";\n\n", s);
722  dfree(s, MDL);
723  if (fprintf_ret < 0) {
724  goto error_exit;
725  }
726 
727  /*
728  * Check if we actually managed to write.
729  */
730  fflush(db_file);
731  return 1;
732 
733 error_exit:
734  log_info("write_server_duid: unable to write server-duid");
736  return 0;
737 }
738 #endif /* DHCPv6 */
739 
740 #if defined (FAILOVER_PROTOCOL)
741 int write_failover_state (dhcp_failover_state_t *state)
742 {
743  int errors = 0;
744  const char *tval;
745 
747  if (!new_lease_file ())
748  return 0;
749 
750  errno = 0;
751  fprintf (db_file, "\nfailover peer \"%s\" state {", state -> name);
752  if (errno)
753  ++errors;
754 
755  tval = print_time(state->me.stos);
756  if (tval == NULL ||
757  fprintf(db_file, "\n my state %s at %s",
758  (state->me.state == startup) ?
759  dhcp_failover_state_name_print(state->saved_state) :
760  dhcp_failover_state_name_print(state->me.state),
761  tval) < 0)
762  ++errors;
763 
764  tval = print_time(state->partner.stos);
765  if (tval == NULL ||
766  fprintf(db_file, "\n partner state %s at %s",
767  dhcp_failover_state_name_print(state->partner.state),
768  tval) < 0)
769  ++errors;
770 
771  if (state -> i_am == secondary) {
772  errno = 0;
773  fprintf (db_file, "\n mclt %ld;",
774  (unsigned long)state -> mclt);
775  if (errno)
776  ++errors;
777  }
778 
779  errno = 0;
780  fprintf (db_file, "\n}\n");
781  if (errno)
782  ++errors;
783 
784  if (errors) {
785  log_info ("write_failover_state: unable to write state %s",
786  state -> name);
788  return 0;
789  }
790 
791  return 1;
792 
793 }
794 #endif
795 
797  const unsigned char *s;
798 {
799  int i;
800  for (i = 0; s [i]; i++)
801  if (!isascii (s [i]) || !isprint (s [i])
802  || s [i] == '"' || s [i] == '\\')
803  return 0;
804  return 1;
805 }
806 
808  const unsigned char *s;
809  unsigned len;
810 {
811  int i;
812 
813  for (i = 0; i < len; i++)
814  if (!isascii (s [i]) || !isprint (s [i]) ||
815  s [i] == '"' || s [i] == '\\')
816  return 0;
817  return 1;
818 }
819 
820 static int print_hash_string(FILE *fp, struct class *class)
821 {
822  int i;
823 
824  for (i = 0 ; i < class->hash_string.len ; i++)
825  if (!isascii(class->hash_string.data[i]) ||
826  !isprint(class->hash_string.data[i]))
827  break;
828 
829  if (i == class->hash_string.len) {
830  if (fprintf(fp, " \"%.*s\"", (int)class->hash_string.len,
831  class->hash_string.data) <= 0) {
832  log_error("Failure writing hash string: %m");
833  return 0;
834  }
835  } else {
836  if (fprintf(fp, " %2.2x", class->hash_string.data[0]) <= 0) {
837  log_error("Failure writing hash string: %m");
838  return 0;
839  }
840  for (i = 1 ; i < class->hash_string.len ; i++) {
841  if (fprintf(fp, ":%2.2x",
842  class->hash_string.data[i]) <= 0) {
843  log_error("Failure writing hash string: %m");
844  return 0;
845  }
846  }
847  }
848 
849  return 1;
850 }
851 
852 
853 isc_result_t
854 write_named_billing_class(const void *key, unsigned len, void *object)
855 {
856  const unsigned char *name = key;
857  struct class *class = object;
858 
859  if (class->flags & CLASS_DECL_DYNAMIC) {
861  if (class->superclass == 0) {
862  if (fprintf(db_file, "class \"%s\" {\n", name) <= 0)
863  return ISC_R_IOERROR;
864  } else {
865  if (fprintf(db_file, "subclass \"%s\"",
866  class->superclass->name) <= 0)
867  return ISC_R_IOERROR;
868  if (!print_hash_string(db_file, class))
869  return ISC_R_IOERROR;
870  if (fprintf(db_file, " {\n") <= 0)
871  return ISC_R_IOERROR;
872  }
873 
874  if ((class->flags & CLASS_DECL_DELETED) != 0) {
875  if (fprintf(db_file, " deleted;\n") <= 0)
876  return ISC_R_IOERROR;
877  } else {
878  if (fprintf(db_file, " dynamic;\n") <= 0)
879  return ISC_R_IOERROR;
880  }
881 
882  if (class->lease_limit > 0) {
883  if (fprintf(db_file, " lease limit %d;\n",
884  class->lease_limit) <= 0)
885  return ISC_R_IOERROR;
886  }
887 
888  if (class->expr != 0) {
889  if (fprintf(db_file, " match if ") <= 0)
890  return ISC_R_IOERROR;
891 
892  errno = 0;
893  write_expression(db_file, class->expr, 5, 5, 0);
894  if (errno)
895  return ISC_R_IOERROR;
896 
897  if (fprintf(db_file, ";\n") <= 0)
898  return ISC_R_IOERROR;
899  }
900 
901  if (class->submatch != 0) {
902  if (class->spawning) {
903  if (fprintf(db_file, " spawn ") <= 0)
904  return ISC_R_IOERROR;
905  } else {
906  if (fprintf(db_file, " match ") <= 0)
907  return ISC_R_IOERROR;
908  }
909 
910  errno = 0;
912  if (errno)
913  return ISC_R_IOERROR;
914 
915  if (fprintf(db_file, ";\n") <= 0)
916  return ISC_R_IOERROR;
917  }
918 
919  if (class->statements != 0) {
920  errno = 0;
922  if (errno)
923  return ISC_R_IOERROR;
924  }
925 
926  /* XXXJAB this isn't right, but classes read in off the
927  leases file don't get the root group assigned to them
928  (due to clone_group() call). */
929  if (class->group != 0 && class->group->authoritative != 0) {
930  errno = 0;
932  if (errno)
933  return ISC_R_IOERROR;
934  }
935 
936  if (fprintf(db_file, "}\n\n") <= 0)
937  return ISC_R_IOERROR;
938  }
939 
940  if (class->hash != NULL) { /* yep. recursive. god help us. */
941  /* XXX - cannot check error status of this...
942  * foo_hash_foreach returns a count of operations completed.
943  */
944  class_hash_foreach(class->hash, write_named_billing_class);
945  }
946 
947  return ISC_R_SUCCESS;
948 }
949 
951 {
952  struct collection *lp;
953  struct class *cp;
954 
955  for (lp = collections; lp; lp = lp -> next) {
956  for (cp = lp -> classes; cp; cp = cp -> nic) {
957  if (cp -> spawning && cp -> hash) {
958  class_hash_foreach (cp -> hash, write_named_billing_class);
959  }
960  }
961  }
962 }
963 
964 /* Write a spawned class to the database file. */
965 
967  struct class *class;
968 {
969  int errors = 0;
970 
972  if (!new_lease_file ())
973  return 0;
974 
975  if (!class -> superclass) {
976  errno = 0;
977  fprintf (db_file, "\n billing class \"%s\";", class -> name);
978  return !errno;
979  }
980 
981  if (fprintf(db_file, "\n billing subclass \"%s\"",
982  class -> superclass -> name) < 0)
983  ++errors;
984 
985  if (!print_hash_string(db_file, class))
986  ++errors;
987 
988  if (fprintf(db_file, ";") < 0)
989  ++errors;
990 
991  class -> dirty = !errors;
992  if (errors)
994 
995  return !errors;
996 }
997 
998 /* Commit leases after a timeout. */
999 void commit_leases_timeout (void *foo)
1000 {
1001  commit_leases ();
1002 }
1003 
1004 /* Commit any leases that have been written out... */
1005 
1007 {
1008  /* Commit any outstanding writes to the lease database file.
1009  We need to do this even if we're rewriting the file below,
1010  just in case the rewrite fails. */
1011  if (fflush (db_file) == EOF) {
1012  log_info("commit_leases: unable to commit, fflush(): %m");
1013  return (0);
1014  }
1015  if ((dont_use_fsync == 0) &&
1016  (fsync(fileno (db_file)) < 0)) {
1017  log_info ("commit_leases: unable to commit, fsync(): %m");
1018  return (0);
1019  }
1020 
1021  /* If we haven't rewritten the lease database in over an
1022  hour, rewrite it now. (The length of time should probably
1023  be configurable. */
1024  if (count && cur_time - write_time > LEASE_REWRITE_PERIOD) {
1025  count = 0;
1026  write_time = cur_time;
1027  new_lease_file();
1028  }
1029  return (1);
1030 }
1031 
1032 /*
1033  * rewrite the lease file about once an hour
1034  * This is meant as a quick patch for ticket 24887. It allows
1035  * us to rotate the v6 lease file without adding too many fsync()
1036  * calls. In the future wes should revisit this area and add
1037  * something similar to the delayed ack code for v4.
1038  */
1040 {
1041  if ((count != 0) && (cur_time - write_time > LEASE_REWRITE_PERIOD)) {
1042  return (commit_leases());
1043  }
1044  return (1);
1045 }
1046 
1047 void db_startup (testp)
1048  int testp;
1049 {
1050  isc_result_t status;
1051 
1052 #if defined (TRACING)
1053  if (!trace_playback ()) {
1054 #endif
1055  /* Read in the existing lease file... */
1056  status = read_conf_file (path_dhcpd_db,
1057  (struct group *)0, 0, 1);
1058  if (status != ISC_R_SUCCESS) {
1059  /* XXX ignore status? */
1060  ;
1061  }
1062 
1063 #if defined (TRACING)
1064  }
1065 #endif
1066 
1067 #if defined (TRACING)
1068  /* If we're playing back, there is no lease file, so we can't
1069  append it, so we create one immediately (maybe this isn't
1070  the best solution... */
1071  if (trace_playback ()) {
1072  new_lease_file ();
1073  }
1074 #endif
1075  if (!testp) {
1076  db_file = fopen (path_dhcpd_db, "ae");
1077  if (!db_file)
1078  log_fatal ("Can't open %s for append.", path_dhcpd_db);
1079  expire_all_pools ();
1080 #if defined (TRACING)
1081  if (trace_playback ())
1082  write_time = cur_time;
1083  else
1084 #endif
1085  time(&write_time);
1086  new_lease_file ();
1087  }
1088 
1089 #if defined(REPORT_HASH_PERFORMANCE)
1090  log_info("Host HW hash: %s", host_hash_report(host_hw_addr_hash));
1091  log_info("Host UID hash: %s", host_hash_report(host_uid_hash));
1092  log_info("Lease IP hash: %s",
1093  lease_ip_hash_report(lease_ip_addr_hash));
1094  log_info("Lease UID hash: %s", lease_id_hash_report(lease_uid_hash));
1095  log_info("Lease HW hash: %s",
1096  lease_id_hash_report(lease_hw_addr_hash));
1097 #endif
1098 }
1099 
1101 {
1102  char newfname [512];
1103  char backfname [512];
1104  TIME t;
1105  int db_fd;
1106  int db_validity;
1107  FILE *new_db_file;
1108 
1109  /* Make a temporary lease file... */
1110  time(&t);
1111 
1112  db_validity = lease_file_is_corrupt;
1113 
1114  /* %Audit% Truncated filename causes panic. %2004.06.17,Safe%
1115  * This should never happen since the path is a configuration
1116  * variable from build-time or command-line. But if it should,
1117  * either by malice or ignorance, we panic, since the potential
1118  * for havoc is high.
1119  */
1120  if (snprintf (newfname, sizeof newfname, "%s.%d",
1121  path_dhcpd_db, (int)t) >= sizeof newfname)
1122  log_fatal("new_lease_file: lease file path too long");
1123 
1124  db_fd = open (newfname, O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, 0664);
1125  if (db_fd < 0) {
1126  log_error ("Can't create new lease file: %m");
1127  return 0;
1128  }
1129 
1130 #if defined (PARANOIA)
1131  /*
1132  * If we are currently root and plan to change the
1133  * uid and gid change the file information so we
1134  * can manipulate it later, after we've changed
1135  * our group and user (that is dropped privileges.)
1136  */
1137  if ((set_uid != 0) && (geteuid() == 0) &&
1138  (set_gid != 0) && (getegid() == 0)) {
1139  if (fchown(db_fd, set_uid, set_gid)) {
1140  log_fatal ("Can't chown new lease file: %m");
1141  }
1142  }
1143 #endif /* PARANOIA */
1144 
1145  if ((new_db_file = fdopen(db_fd, "we")) == NULL) {
1146  log_error("Can't fdopen new lease file: %m");
1147  close(db_fd);
1148  goto fdfail;
1149  }
1150 
1151  /* Close previous database, if any. */
1152  if (db_file)
1153  fclose(db_file);
1154  db_file = new_db_file;
1155 
1156  errno = 0;
1157  fprintf (db_file, "# The format of this file is documented in the %s",
1158  "dhcpd.leases(5) manual page.\n");
1159  if (errno)
1160  goto fail;
1161 
1162  fprintf (db_file, "# This lease file was written by isc-dhcp-%s\n\n",
1163  PACKAGE_VERSION);
1164  if (errno)
1165  goto fail;
1166 
1167  /* At this point we have a new lease file that, so far, could not
1168  * be described as either corrupt nor valid.
1169  */
1171 
1172  /* Write out all the leases that we know of... */
1173  counting = 0;
1174  if (!write_leases ())
1175  goto fail;
1176 
1177 #if defined (TRACING)
1178  if (!trace_playback ()) {
1179 #endif
1180  /* %Audit% Truncated filename causes panic. %2004.06.17,Safe%
1181  * This should never happen since the path is a configuration
1182  * variable from build-time or command-line. But if it should,
1183  * either by malice or ignorance, we panic, since the potential
1184  * for havoc is too high.
1185  */
1186  if (snprintf (backfname, sizeof backfname, "%s~", path_dhcpd_db)
1187  >= sizeof backfname)
1188  log_fatal("new_lease_file: backup lease file path too long");
1189 
1190  /* Get the old database out of the way... */
1191  if (unlink (backfname) < 0 && errno != ENOENT) {
1192  log_error ("Can't remove old lease database backup %s: %m",
1193  backfname);
1194  goto fail;
1195  }
1196  if (link(path_dhcpd_db, backfname) < 0) {
1197  if (errno == ENOENT) {
1198  log_error("%s is missing - no lease db to backup.",
1199  path_dhcpd_db);
1200  } else {
1201  log_error("Can't backup lease database %s to %s: %m",
1202  path_dhcpd_db, backfname);
1203  goto fail;
1204  }
1205  }
1206 #if defined (TRACING)
1207  }
1208 #endif
1209 
1210  /* Move in the new file... */
1211  if (rename (newfname, path_dhcpd_db) < 0) {
1212  log_error ("Can't install new lease database %s to %s: %m",
1213  newfname, path_dhcpd_db);
1214  goto fail;
1215  }
1216 
1217  counting = 1;
1218  return 1;
1219 
1220  fail:
1221  lease_file_is_corrupt = db_validity;
1222  fdfail:
1223  (void)unlink (newfname);
1224  return 0;
1225 }
1226 
1228 {
1229  if (!write_group (group))
1230  return 0;
1231  if (!commit_leases ())
1232  return 0;
1233  return 1;
1234 }
#define FTS_ABANDONED
Definition: dhcpd.h:531
#define FTS_LAST
Definition: dhcpd.h:537
#define GROUP_OBJECT_DYNAMIC
Definition: dhcpd.h:913
int trace_playback(void)
struct class * nic
Definition: dhcpd.h:1060
Definition: tree.h:31
lease_id_hash_t * lease_uid_hash
Definition: mdb.c:38
struct binding_scope * global_scope
Definition: tree.c:39
const char * hardware_types[]
Definition: tables.c:659
int write_failover_state(dhcp_failover_state_t *)
void write_billing_classes()
Definition: db.c:950
int group_writer(struct group_object *group)
Definition: db.c:1227
Definition: dhcpd.h:550
unsigned len
Definition: tree.h:80
const char * piaddr(const struct iaddr addr)
Definition: inet.c:581
Definition: dhcpd.h:1620
int write_ia(const struct ia_xx *ia)
Definition: db.c:515
void expire_all_pools(void)
Definition: mdb.c:2791
isc_boolean_t server_duid_isset(void)
struct class * superclass
Definition: dhcpd.h:1061
struct iaddr ip_addr(struct iaddr subnet, struct iaddr mask, u_int32_t host_address)
Definition: inet.c:65
#define MDL
Definition: omapip.h:568
#define HOST_DECL_DYNAMIC
Definition: dhcpd.h:949
FILE * db_file
Definition: db.c:39
#define DHCP_R_INVALIDARG
Definition: result.h:48
class_hash_t * hash
Definition: dhcpd.h:1074
#define CLASS_DECL_DELETED
Definition: dhcpd.h:1090
host_hash_t * host_uid_hash
Definition: mdb.c:36
struct data_string data
Definition: tree.h:110
struct binding * next
Definition: tree.h:119
struct executable_statement * on_release
Definition: dhcpd.h:546
int commit_leases_timed()
Definition: db.c:1039
void data_string_forget(struct data_string *data, const char *file, int line)
Definition: alloc.c:1340
int write_lease(struct lease *lease)
Definition: db.c:99
const char * pretty_print_option(struct option *option, const unsigned char *data, unsigned len, int emit_commas, int emit_quotes)
Definition: options.c:1676
struct group * root_group
Definition: memory.c:31
enum binding_value::@15 type
struct data_string hash_string
Definition: dhcpd.h:1075
const char * path_dhcpd_db
Definition: dhcpd.c:89
u_int32_t valid
Definition: dhcpd.h:1596
int log_error(const char *,...) __attribute__((__format__(__printf__
struct collection * collections
Definition: dhcpd.h:3135
#define HOST_DECL_DELETED
Definition: dhcpd.h:948
lease_id_hash_t * lease_hw_addr_hash
Definition: mdb.c:40
time_t cltt
Definition: dhcpd.h:1626
void commit_leases_timeout(void *foo)
Definition: db.c:999
struct on_star on_star
Definition: dhcpd.h:1617
struct binding_scope * scope
Definition: dhcpd.h:1592
void copy_server_duid(struct data_string *ds, const char *file, int line)
int lease_file_is_corrupt
Definition: db.c:44
char * name
Definition: dhcpd.h:1062
int write_host(struct host_decl *host)
Definition: db.c:298
void log_fatal(const char *,...) __attribute__((__format__(__printf__
#define D6O_IA_TA
Definition: dhcp6.h:34
struct executable_statement * statements
Definition: dhcpd.h:926
#define CLASS_DECL_DYNAMIC
Definition: dhcpd.h:1091
int commit_leases()
Definition: db.c:1006
time_t hard_lifetime_end_time
Definition: dhcpd.h:1593
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
Definition: tree.h:346
char * name
Definition: tree.h:120
#define MIN_TIME
Definition: dhcpd.h:1573
uid_t set_uid
gid_t set_gid
#define LEASE_REWRITE_PERIOD
Definition: db.c:34
int write_billing_class(struct class *class)
Definition: db.c:966
struct expression * expr
Definition: dhcpd.h:1078
Definition: dhcpd.h:405
int write_server_duid(void)
host_hash_t * host_hw_addr_hash
Definition: mdb.c:35
u_int8_t plen
Definition: dhcpd.h:1590
struct data_string iaid_duid
Definition: dhcpd.h:1622
int authoritative
Definition: dhcpd.h:925
#define cur_time
Definition: dhcpd.h:2041
const char * dhcp_failover_state_name_print(enum failover_state)
struct expression * submatch
Definition: dhcpd.h:1082
void dfree(void *, const char *, int)
Definition: alloc.c:131
u_int32_t prefer
Definition: dhcpd.h:1595
int lease_limit
Definition: dhcpd.h:1065
int num_iasubopt
Definition: dhcpd.h:1624
int int log_info(const char *,...) __attribute__((__format__(__printf__
u_int16_t ia_type
Definition: dhcpd.h:1623
void write_statements(FILE *file, struct executable_statement *statements, int indent)
Definition: execute.c:752
#define GROUP_OBJECT_DELETED
Definition: dhcpd.h:912
binding_state_t state
Definition: dhcpd.h:1591
int write_leases(void)
Definition: mdb.c:2386
isc_result_t write_named_billing_class(const void *key, unsigned len, void *object)
Definition: db.c:854
union binding_value::value value
int db_printable(unsigned char *s) const
Definition: db.c:796
Definition: dhcpd.h:918
struct binding * bindings
Definition: tree.h:127
#define RESERVED_LEASE
Definition: dhcpd.h:584
struct executable_statement * statements
Definition: dhcpd.h:1088
#define D6O_IA_NA
Definition: dhcp6.h:33
const char int
Definition: omapip.h:443
struct binding_value * value
Definition: tree.h:121
int write_group(struct group_object *group)
Definition: db.c:446
int dont_use_fsync
Definition: dhcpd.c:84
time_t TIME
Definition: dhcpd.h:85
time_t soft_lifetime_end_time
Definition: dhcpd.h:1594
int flags
Definition: dhcpd.h:1095
struct data_string data
Definition: dhcpd.h:390
Definition: tree.h:118
#define PACKAGE_VERSION
Definition: config.h:168
#define D6O_IA_PD
Definition: dhcp6.h:55
struct iasubopt ** iasubopt
Definition: dhcpd.h:1627
int numclasseswritten
Definition: mdb.c:69
const char * binding_state_names[]
Definition: stables.c:161
struct executable_statement * on_expiry
Definition: dhcpd.h:544
int write_expression(FILE *file, struct expression *expr, int col, int indent, int firstp)
Definition: tree.c:3287
#define BOOTP_LEASE
Definition: dhcpd.h:583
void db_startup(int testp)
Definition: db.c:1047
unsigned long intval
Definition: tree.h:111
isc_result_t read_conf_file(const char *, struct group *, int, int)
Definition: confpars.c:72
struct in6_addr addr
Definition: dhcpd.h:1589
Definition: dhcpd.h:1058
const unsigned char * data
Definition: tree.h:79
TIME write_time
Definition: db.c:43
int new_lease_file()
Definition: db.c:1100
lease_ip_hash_t * lease_ip_addr_hash
Definition: mdb.c:39
#define GROUP_OBJECT_STATIC
Definition: dhcpd.h:914
int spawning
Definition: dhcpd.h:1083
struct group * group
Definition: dhcpd.h:1085
int db_printable_len(unsigned char *s, unsigned len) const
Definition: db.c:807
#define FTS_ACTIVE
Definition: dhcpd.h:528