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