]> git.ipfire.org Git - thirdparty/dhcp.git/blob - server/db.c
Merged rt43285 (make distcheck vs --with-libbind)
[thirdparty/dhcp.git] / server / db.c
1 /* db.c
2
3 Persistent database management routines for DHCPD... */
4
5 /*
6 * Copyright (c) 2004-2016 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1995-2003 by Internet Software Consortium
8 *
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 *
21 * Internet Systems Consortium, Inc.
22 * 950 Charter Street
23 * Redwood City, CA 94063
24 * <info@isc.org>
25 * https://www.isc.org/
26 *
27 */
28
29 #include "dhcpd.h"
30 #include <ctype.h>
31 #include <errno.h>
32
33 #define LEASE_REWRITE_PERIOD 3600
34
35 static isc_result_t write_binding_scope(FILE *db_file, struct binding *bnd,
36 char *prepend);
37
38 FILE *db_file;
39
40 static int counting = 0;
41 static int count = 0;
42 TIME write_time;
43 int lease_file_is_corrupt = 0;
44
45 /* Write a single binding scope value in parsable format.
46 */
47
48 static isc_result_t
49 write_binding_scope(FILE *db_file, struct binding *bnd, char *prepend) {
50 char *s;
51
52 if ((db_file == NULL) || (bnd == NULL) || (prepend == NULL))
53 return DHCP_R_INVALIDARG;
54
55 if (bnd->value->type == binding_data) {
56 if (bnd->value->value.data.data != NULL) {
57 s = quotify_buf(bnd->value->value.data.data,
58 bnd->value->value.data.len, '"', MDL);
59 if (s != NULL) {
60 errno = 0;
61 fprintf(db_file, "%sset %s = %s;",
62 prepend, bnd->name, s);
63 dfree(s, MDL);
64 if (errno)
65 return ISC_R_FAILURE;
66 } else {
67 return ISC_R_FAILURE;
68 }
69 }
70 } else if (bnd->value->type == binding_numeric) {
71 errno = 0;
72 fprintf(db_file, "%sset %s = %%%ld;", prepend,
73 bnd->name, bnd->value->value.intval);
74 if (errno)
75 return ISC_R_FAILURE;
76 } else if (bnd->value->type == binding_boolean) {
77 errno = 0;
78 fprintf(db_file, "%sset %s = %s;", prepend, bnd->name,
79 bnd->value->value.intval ? "true" : "false");
80 if (errno)
81 return ISC_R_FAILURE;
82 } else if (bnd->value->type == binding_dns) {
83 log_error("%s: persistent dns values not supported.",
84 bnd->name);
85 } else if (bnd->value->type == binding_function) {
86 log_error("%s: persistent functions not supported.",
87 bnd->name);
88 } else {
89 log_fatal("%s: unknown binding type %d", bnd->name,
90 bnd->value->type);
91 }
92
93 return ISC_R_SUCCESS;
94 }
95
96 /* Write the specified lease to the current lease database file. */
97
98 int write_lease (lease)
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. */
108 if (lease_file_is_corrupt)
109 if (!new_lease_file ())
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)
161 ? (binding_state_names
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 */
173 if ((lease->binding_state != lease->rewind_binding_state) &&
174 (lease->rewind_binding_state > 0) &&
175 (lease->rewind_binding_state <= FTS_LAST) &&
176 (fprintf(db_file, "\n rewind binding state %s;",
177 binding_state_names[lease->rewind_binding_state-1])) < 0)
178 ++errors;
179
180 if (lease->flags & RESERVED_LEASE)
181 if (fprintf(db_file, "\n reserved;") < 0)
182 ++errors;
183
184 if (lease->flags & BOOTP_LEASE)
185 if (fprintf(db_file, "\n dynamic-bootp;") < 0)
186 ++errors;
187
188 /* If this lease is billed to a class and is still valid,
189 write it out. */
190 if (lease -> billing_class && lease -> ends > cur_time) {
191 if (!write_billing_class (lease -> billing_class)) {
192 log_error ("unable to write class %s",
193 lease -> billing_class -> name);
194 ++errors;
195 }
196 }
197
198 if (lease -> hardware_addr.hlen) {
199 errno = 0;
200 fprintf (db_file, "\n hardware %s %s;",
201 hardware_types [lease -> hardware_addr.hbuf [0]],
202 print_hw_addr (lease -> hardware_addr.hbuf [0],
203 lease -> hardware_addr.hlen - 1,
204 &lease -> hardware_addr.hbuf [1]));
205 if (errno)
206 ++errors;
207 }
208 if (lease -> uid_len) {
209 s = format_lease_id(lease->uid, lease->uid_len, lease_id_format,
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 {",
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));
292 lease_file_is_corrupt = 1;
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. */
307 if (lease_file_is_corrupt)
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 /* 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;
428 write_statements (db_file,
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);
443 lease_file_is_corrupt = 1;
444 }
445
446 return !errors;
447 }
448
449 int write_group (group)
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. */
456 if (lease_file_is_corrupt)
457 if (!new_lease_file ())
458 return 0;
459
460 if (!db_printable((unsigned char *)group->name))
461 return 0;
462
463 if (counting)
464 ++count;
465
466 errno = 0;
467 fprintf (db_file, "group %s {", group -> name);
468 if (errno)
469 ++errors;
470
471 if (group -> flags & GROUP_OBJECT_DYNAMIC) {
472 errno = 0;
473 fprintf (db_file, "\n dynamic;");
474 if (errno)
475 ++errors;
476 }
477
478 if (group -> flags & GROUP_OBJECT_STATIC) {
479 errno = 0;
480 fprintf (db_file, "\n static;");
481 if (errno)
482 ++errors;
483 }
484
485 if (group -> flags & GROUP_OBJECT_DELETED) {
486 errno = 0;
487 fprintf (db_file, "\n deleted;");
488 if (errno)
489 ++errors;
490 } else {
491 if (group -> group) {
492 errno = 0;
493 write_statements (db_file,
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);
508 lease_file_is_corrupt = 1;
509 }
510
511 return !errors;
512 }
513
514 /*
515 * Write an IA and the options it has.
516 */
517 int
518 write_ia(const struct ia_xx *ia) {
519 struct iasubopt *iasubopt;
520 struct binding *bnd;
521 int i;
522 char addr_buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff.255.255.255.255")];
523 const char *binding_state;
524 const char *tval;
525 char *s;
526 int fprintf_ret;
527
528 /*
529 * If the lease file is corrupt, don't try to write any more
530 * leases until we've written a good lease file.
531 */
532 if (lease_file_is_corrupt) {
533 if (!new_lease_file()) {
534 return 0;
535 }
536 }
537
538 if (counting) {
539 ++count;
540 }
541
542 s = format_lease_id(ia->iaid_duid.data, ia->iaid_duid.len,
543 lease_id_format, MDL);
544 if (s == NULL) {
545 goto error_exit;
546 }
547 switch (ia->ia_type) {
548 case D6O_IA_NA:
549 fprintf_ret = fprintf(db_file, "ia-na %s {\n", s);
550 break;
551 case D6O_IA_TA:
552 fprintf_ret = fprintf(db_file, "ia-ta %s {\n", s);
553 break;
554 case D6O_IA_PD:
555 fprintf_ret = fprintf(db_file, "ia-pd %s {\n", s);
556 break;
557 default:
558 log_error("Unknown ia type %u for %s at %s:%d",
559 (unsigned)ia->ia_type, s, MDL);
560 fprintf_ret = -1;
561 }
562 dfree(s, MDL);
563 if (fprintf_ret < 0) {
564 goto error_exit;
565 }
566 if (ia->cltt != MIN_TIME) {
567 tval = print_time(ia->cltt);
568 if (tval == NULL) {
569 goto error_exit;
570 }
571 if (fprintf(db_file, " cltt %s\n", tval) < 0) {
572 goto error_exit;
573 }
574 }
575 for (i=0; i<ia->num_iasubopt; i++) {
576 iasubopt = ia->iasubopt[i];
577
578 inet_ntop(AF_INET6, &iasubopt->addr,
579 addr_buf, sizeof(addr_buf));
580 if ((ia->ia_type != D6O_IA_PD) &&
581 (fprintf(db_file, " iaaddr %s {\n", addr_buf) < 0)) {
582 goto error_exit;
583 }
584 if ((ia->ia_type == D6O_IA_PD) &&
585 (fprintf(db_file, " iaprefix %s/%d {\n",
586 addr_buf, (int)iasubopt->plen) < 0)) {
587 goto error_exit;
588 }
589 if ((iasubopt->state <= 0) || (iasubopt->state > FTS_LAST)) {
590 log_fatal("Unknown iasubopt state %d at %s:%d",
591 iasubopt->state, MDL);
592 }
593 binding_state = binding_state_names[iasubopt->state-1];
594 if (fprintf(db_file, " binding state %s;\n",
595 binding_state) < 0) {
596 goto error_exit;
597 }
598 if (fprintf(db_file, " preferred-life %u;\n",
599 (unsigned)iasubopt->prefer) < 0) {
600 goto error_exit;
601 }
602 if (fprintf(db_file, " max-life %u;\n",
603 (unsigned)iasubopt->valid) < 0) {
604 goto error_exit;
605 }
606
607 /* Note that from here on out, the \n is prepended to the
608 * next write, rather than appended to the current write.
609 */
610 if ((iasubopt->state == FTS_ACTIVE) ||
611 (iasubopt->state == FTS_ABANDONED) ||
612 (iasubopt->hard_lifetime_end_time != 0)) {
613 tval = print_time(iasubopt->hard_lifetime_end_time);
614 } else {
615 tval = print_time(iasubopt->soft_lifetime_end_time);
616 }
617 if (tval == NULL) {
618 goto error_exit;
619 }
620 if (fprintf(db_file, " ends %s", tval) < 0) {
621 goto error_exit;
622 }
623
624 /* Write out any binding scopes: note that 'ends' above does
625 * not have \n on the end! We want that.
626 */
627 if (iasubopt->scope != NULL)
628 bnd = iasubopt->scope->bindings;
629 else
630 bnd = NULL;
631
632 for (; bnd != NULL ; bnd = bnd->next) {
633 if (bnd->value == NULL)
634 continue;
635
636 /* We don't do a regular error_exit because the
637 * lease db is not corrupt in this case.
638 */
639 if (write_binding_scope(db_file, bnd,
640 "\n ") != ISC_R_SUCCESS)
641 goto error_exit;
642
643 }
644
645 if (iasubopt->on_star.on_expiry) {
646 if (fprintf(db_file, "\n on expiry%s {",
647 iasubopt->on_star.on_expiry ==
648 iasubopt->on_star.on_release
649 ? " or release" : "") < 0)
650 goto error_exit;
651 write_statements(db_file,
652 iasubopt->on_star.on_expiry, 6);
653 if (fprintf(db_file, "\n }") < 0)
654 goto error_exit;
655 }
656
657 if (iasubopt->on_star.on_release &&
658 iasubopt->on_star.on_release !=
659 iasubopt->on_star.on_expiry) {
660 if (fprintf(db_file, "\n on release {") < 0)
661 goto error_exit;
662 write_statements(db_file,
663 iasubopt->on_star.on_release, 6);
664 if (fprintf(db_file, "\n }") < 0)
665 goto error_exit;
666 }
667
668 if (fprintf(db_file, "\n }\n") < 0)
669 goto error_exit;
670 }
671 if (fprintf(db_file, "}\n\n") < 0)
672 goto error_exit;
673
674 fflush(db_file);
675 return 1;
676
677 error_exit:
678 log_info("write_ia: unable to write ia");
679 lease_file_is_corrupt = 1;
680 return 0;
681 }
682
683 #ifdef DHCPv6
684 /*
685 * Put a copy of the server DUID in the leases file.
686 */
687 int
688 write_server_duid(void) {
689 struct data_string server_duid;
690 char *s;
691 int fprintf_ret;
692
693 /*
694 * Only write the DUID if it's been set.
695 */
696 if (!server_duid_isset()) {
697 return 1;
698 }
699
700 /*
701 * If the lease file is corrupt, don't try to write any more
702 * leases until we've written a good lease file.
703 */
704 if (lease_file_is_corrupt) {
705 if (!new_lease_file()) {
706 return 0;
707 }
708 }
709
710 /*
711 * Get a copy of our server DUID and convert to a quoted string.
712 */
713 memset(&server_duid, 0, sizeof(server_duid));
714 copy_server_duid(&server_duid, MDL);
715 s = format_lease_id(server_duid.data, server_duid.len, lease_id_format,
716 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");
739 lease_file_is_corrupt = 1;
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
750 if (lease_file_is_corrupt)
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);
791 lease_file_is_corrupt = 1;
792 return 0;
793 }
794
795 return 1;
796
797 }
798 #endif
799
800 int db_printable (s)
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
811 int db_printable_len (s, len)
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) {
864 numclasseswritten++;
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;
915 write_expression(db_file, class->submatch, 5, 5, 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;
925 write_statements(db_file, class->statements, 8);
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;
935 write_statements(db_file, class->group->statements, 8);
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
954 void write_billing_classes ()
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
970 int write_billing_class (class)
971 struct class *class;
972 {
973 int errors = 0;
974
975 if (lease_file_is_corrupt)
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)
997 lease_file_is_corrupt = 1;
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
1010 int commit_leases ()
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 /* If we haven't rewritten the lease database in over an
1026 hour, rewrite it now. (The length of time should probably
1027 be configurable. */
1028 if (count && cur_time - write_time > LEASE_REWRITE_PERIOD) {
1029 count = 0;
1030 write_time = cur_time;
1031 new_lease_file();
1032 }
1033 return (1);
1034 }
1035
1036 /*
1037 * rewrite the lease file about once an hour
1038 * This is meant as a quick patch for ticket 24887. It allows
1039 * us to rotate the v6 lease file without adding too many fsync()
1040 * calls. In the future wes should revisit this area and add
1041 * something similar to the delayed ack code for v4.
1042 */
1043 int commit_leases_timed()
1044 {
1045 if ((count != 0) && (cur_time - write_time > LEASE_REWRITE_PERIOD)) {
1046 return (commit_leases());
1047 }
1048 return (1);
1049 }
1050
1051 void db_startup (testp)
1052 int testp;
1053 {
1054 isc_result_t status;
1055
1056 #if defined (TRACING)
1057 if (!trace_playback ()) {
1058 #endif
1059 /* Unset authoring_byte_order so we'll know if it was specified
1060 in the lease file or not. */
1061 authoring_byte_order = 0;
1062
1063 /* Read in the existing lease file... */
1064 status = read_conf_file (path_dhcpd_db,
1065 (struct group *)0, 0, 1);
1066 if (status != ISC_R_SUCCESS) {
1067 /* XXX ignore status? */
1068 ;
1069 }
1070
1071 #if defined (TRACING)
1072 }
1073 #endif
1074
1075 #if defined (TRACING)
1076 /* If we're playing back, there is no lease file, so we can't
1077 append it, so we create one immediately (maybe this isn't
1078 the best solution... */
1079 if (trace_playback ()) {
1080 new_lease_file ();
1081 }
1082 #endif
1083 if (!testp) {
1084 db_file = fopen (path_dhcpd_db, "a");
1085 if (!db_file)
1086 log_fatal ("Can't open %s for append.", path_dhcpd_db);
1087 expire_all_pools ();
1088 #if defined (TRACING)
1089 if (trace_playback ())
1090 write_time = cur_time;
1091 else
1092 #endif
1093 time(&write_time);
1094 new_lease_file ();
1095 }
1096
1097 #if defined(REPORT_HASH_PERFORMANCE)
1098 log_info("Host HW hash: %s", host_hash_report(host_hw_addr_hash));
1099 log_info("Host UID hash: %s", host_hash_report(host_uid_hash));
1100 log_info("Lease IP hash: %s",
1101 lease_ip_hash_report(lease_ip_addr_hash));
1102 log_info("Lease UID hash: %s", lease_id_hash_report(lease_uid_hash));
1103 log_info("Lease HW hash: %s",
1104 lease_id_hash_report(lease_hw_addr_hash));
1105 #endif
1106 }
1107
1108 int new_lease_file ()
1109 {
1110 char newfname [512];
1111 char backfname [512];
1112 TIME t;
1113 int db_fd;
1114 int db_validity;
1115 FILE *new_db_file;
1116
1117 /* Make a temporary lease file... */
1118 time(&t);
1119
1120 db_validity = lease_file_is_corrupt;
1121
1122 /* %Audit% Truncated filename causes panic. %2004.06.17,Safe%
1123 * This should never happen since the path is a configuration
1124 * variable from build-time or command-line. But if it should,
1125 * either by malice or ignorance, we panic, since the potential
1126 * for havoc is high.
1127 */
1128 if (snprintf (newfname, sizeof newfname, "%s.%d",
1129 path_dhcpd_db, (int)t) >= sizeof newfname)
1130 log_fatal("new_lease_file: lease file path too long");
1131
1132 db_fd = open (newfname, O_WRONLY | O_TRUNC | O_CREAT, 0664);
1133 if (db_fd < 0) {
1134 log_error ("Can't create new lease file: %m");
1135 return 0;
1136 }
1137
1138 #if defined (PARANOIA)
1139 /*
1140 * If we are currently root and plan to change the
1141 * uid and gid change the file information so we
1142 * can manipulate it later, after we've changed
1143 * our group and user (that is dropped privileges.)
1144 */
1145 if ((set_uid != 0) && (geteuid() == 0) &&
1146 (set_gid != 0) && (getegid() == 0)) {
1147 if (fchown(db_fd, set_uid, set_gid)) {
1148 log_fatal ("Can't chown new lease file: %m");
1149 }
1150 }
1151 #endif /* PARANOIA */
1152
1153 if ((new_db_file = fdopen(db_fd, "w")) == NULL) {
1154 log_error("Can't fdopen new lease file: %m");
1155 close(db_fd);
1156 goto fdfail;
1157 }
1158
1159 /* Close previous database, if any. */
1160 if (db_file)
1161 fclose(db_file);
1162 db_file = new_db_file;
1163
1164 errno = 0;
1165 fprintf (db_file, "# The format of this file is documented in the %s",
1166 "dhcpd.leases(5) manual page.\n");
1167
1168 if (errno)
1169 goto fail;
1170
1171 fprintf (db_file, "# This lease file was written by isc-dhcp-%s\n\n",
1172 PACKAGE_VERSION);
1173 if (errno)
1174 goto fail;
1175
1176 fprintf (db_file, "# authoring-byte-order entry is generated,"
1177 " DO NOT DELETE\n");
1178 if (errno)
1179 goto fail;
1180
1181 fprintf (db_file, "authoring-byte-order %s;\n\n",
1182 (DHCP_BYTE_ORDER == LITTLE_ENDIAN ?
1183 "little-endian" : "big-endian"));
1184 if (errno)
1185 goto fail;
1186
1187 /* At this point we have a new lease file that, so far, could not
1188 * be described as either corrupt nor valid.
1189 */
1190 lease_file_is_corrupt = 0;
1191
1192 /* Write out all the leases that we know of... */
1193 counting = 0;
1194 if (!write_leases ())
1195 goto fail;
1196
1197 #if defined (TRACING)
1198 if (!trace_playback ()) {
1199 #endif
1200 /* %Audit% Truncated filename causes panic. %2004.06.17,Safe%
1201 * This should never happen since the path is a configuration
1202 * variable from build-time or command-line. But if it should,
1203 * either by malice or ignorance, we panic, since the potential
1204 * for havoc is too high.
1205 */
1206 if (snprintf (backfname, sizeof backfname, "%s~", path_dhcpd_db)
1207 >= sizeof backfname)
1208 log_fatal("new_lease_file: backup lease file path too long");
1209
1210 /* Get the old database out of the way... */
1211 if (unlink (backfname) < 0 && errno != ENOENT) {
1212 log_error ("Can't remove old lease database backup %s: %m",
1213 backfname);
1214 goto fail;
1215 }
1216 if (link(path_dhcpd_db, backfname) < 0) {
1217 if (errno == ENOENT) {
1218 log_error("%s is missing - no lease db to backup.",
1219 path_dhcpd_db);
1220 } else {
1221 log_error("Can't backup lease database %s to %s: %m",
1222 path_dhcpd_db, backfname);
1223 goto fail;
1224 }
1225 }
1226 #if defined (TRACING)
1227 }
1228 #endif
1229
1230 /* Move in the new file... */
1231 if (rename (newfname, path_dhcpd_db) < 0) {
1232 log_error ("Can't install new lease database %s to %s: %m",
1233 newfname, path_dhcpd_db);
1234 goto fail;
1235 }
1236
1237 counting = 1;
1238 return 1;
1239
1240 fail:
1241 lease_file_is_corrupt = db_validity;
1242 fdfail:
1243 (void)unlink (newfname);
1244 return 0;
1245 }
1246
1247 int group_writer (struct group_object *group)
1248 {
1249 if (!write_group (group))
1250 return 0;
1251 if (!commit_leases ())
1252 return 0;
1253 return 1;
1254 }