ISC DHCP 4.4.3-P1
A reference DHCPv4 and DHCPv6 implementation
 
Loading...
Searching...
No Matches
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
35static isc_result_t write_binding_scope(FILE *db_file, struct binding *bnd,
36 char *prepend);
37
38FILE *db_file;
39
40static int counting = 0;
41static int count = 0;
44
45/* Write a single binding scope value in parsable format.
46 */
47
48static isc_result_t
49write_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) {
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 */
176 (fprintf(db_file, "\n rewind binding state %s;",
178 ++errors;
179
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
298int 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,
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
472 errno = 0;
473 fprintf (db_file, "\n dynamic;");
474 if (errno)
475 ++errors;
476 }
477
479 errno = 0;
480 fprintf (db_file, "\n static;");
481 if (errno)
482 ++errors;
483 }
484
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 */
517int
518write_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 */
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) ||
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
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
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
698error_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 */
708int
709write_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 */
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
758error_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)
766int 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
845static 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
878isc_result_t
879write_named_billing_class(const void *key, unsigned len, void *object)
880{
881 const unsigned char *name = key;
882 struct class *class = object;
883
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;
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. */
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;
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
1072void 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
1114#if defined (TRACING)
1115 if (trace_playback ())
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
1133int 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",
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.",
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 * format_lease_id(const unsigned char *s, unsigned len, int format, const char *file, int line)
Definition print.c:1427
char * quotify_string(const char *s, const char *file, int line)
Definition print.c:33
char * quotify_buf(const unsigned char *s, unsigned len, char enclose_char, const char *file, int line)
Definition print.c:71
char * print_hw_addr(int htype, const int hlen, const unsigned char *data) const
Definition print.c:171
const char * print_time(TIME t)
Definition print.c:1312
#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
int commit_leases()
Definition dhclient.c:2234
#define D6O_IA_PD
Definition dhcp6.h:54
#define D6O_IA_TA
Definition dhcp6.h:33
#define D6O_IA_NA
Definition dhcp6.h:32
int write_billing_class(struct class *)
Definition db.c:991
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
int write_group(struct group_object *)
Definition db.c:449
#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
int new_lease_file(int test_mode)
Definition db.c:1133
#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
isc_boolean_t server_duid_isset(void)
int write_leases(void)
Definition mdb.c:2434
const char * dhcp_failover_state_name_print(enum failover_state)
#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
isc_result_t write_named_billing_class(const void *, unsigned, void *)
Definition db.c:879
int db_printable_len(const unsigned char *, unsigned)
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
struct binding * bindings
Definition tree.h:126
enum binding_value::@135246253323115003010247222006030375211205217247 type
union binding_value::value value
char * name
Definition tree.h:119
struct binding * next
Definition tree.h:118
struct binding_value * value
Definition tree.h:120
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
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
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
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 _pair * pair
struct data_string data
Definition tree.h:109
unsigned long intval
Definition tree.h:110