1 /* $NetBSD: db.c,v 1.1.1.3 2014/07/12 11:58:05 spz Exp $ */
2 /* db.c
3
4 Persistent database management routines for DHCPD... */
5
6 /*
7 * Copyright (c) 2012-2014 by Internet Systems Consortium, Inc. ("ISC")
8 * Copyright (c) 2004-2010 by Internet Systems Consortium, Inc. ("ISC")
9 * Copyright (c) 1995-2003 by Internet Software Consortium
10 *
11 * Permission to use, copy, modify, and distribute this software for any
12 * purpose with or without fee is hereby granted, provided that the above
13 * copyright notice and this permission notice appear in all copies.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
16 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
17 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
18 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 *
23 * Internet Systems Consortium, Inc.
24 * 950 Charter Street
25 * Redwood City, CA 94063
26 * <info@isc.org>
27 * https://www.isc.org/
28 *
29 */
30
31 #include <sys/cdefs.h>
32 __RCSID("$NetBSD: db.c,v 1.1.1.3 2014/07/12 11:58:05 spz Exp $");
33
34 #include "dhcpd.h"
35 #include <ctype.h>
36 #include <errno.h>
37
38 #define LEASE_REWRITE_PERIOD 3600
39
40 static isc_result_t write_binding_scope(FILE *db_file, struct binding *bnd,
41 char *prepend);
42
43 FILE *db_file;
44
45 static int counting = 0;
46 static int count = 0;
47 TIME write_time;
48 int lease_file_is_corrupt = 0;
49
50 /* Write a single binding scope value in parsable format.
51 */
52
53 static isc_result_t
write_binding_scope(FILE * db_file,struct binding * bnd,char * prepend)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
write_lease(lease)103 int write_lease (lease)
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. */
113 if (lease_file_is_corrupt)
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)
166 ? (binding_state_names
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));
296 lease_file_is_corrupt = 1;
297 }
298
299 return !errors;
300 }
301
write_host(host)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. */
311 if (lease_file_is_corrupt)
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 }
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
write_group(group)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
write_ia(const struct ia_xx * ia)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
543 s = quotify_buf(ia->iaid_duid.data, ia->iaid_duid.len, 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
write_server_duid(void)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 = quotify_buf(server_duid.data, server_duid.len, MDL);
716 data_string_forget(&server_duid, MDL);
717 if (s == NULL) {
718 goto error_exit;
719 }
720
721 /*
722 * Write to the leases file.
723 */
724 fprintf_ret = fprintf(db_file, "server-duid \"%s\";\n\n", s);
725 dfree(s, MDL);
726 if (fprintf_ret < 0) {
727 goto error_exit;
728 }
729
730 /*
731 * Check if we actually managed to write.
732 */
733 fflush(db_file);
734 return 1;
735
736 error_exit:
737 log_info("write_server_duid: unable to write server-duid");
738 lease_file_is_corrupt = 1;
739 return 0;
740 }
741 #endif /* DHCPv6 */
742
743 #if defined (FAILOVER_PROTOCOL)
write_failover_state(dhcp_failover_state_t * state)744 int write_failover_state (dhcp_failover_state_t *state)
745 {
746 int errors = 0;
747 const char *tval;
748
749 if (lease_file_is_corrupt)
750 if (!new_lease_file ())
751 return 0;
752
753 errno = 0;
754 fprintf (db_file, "\nfailover peer \"%s\" state {", state -> name);
755 if (errno)
756 ++errors;
757
758 tval = print_time(state->me.stos);
759 if (tval == NULL ||
760 fprintf(db_file, "\n my state %s at %s",
761 (state->me.state == startup) ?
762 dhcp_failover_state_name_print(state->saved_state) :
763 dhcp_failover_state_name_print(state->me.state),
764 tval) < 0)
765 ++errors;
766
767 tval = print_time(state->partner.stos);
768 if (tval == NULL ||
769 fprintf(db_file, "\n partner state %s at %s",
770 dhcp_failover_state_name_print(state->partner.state),
771 tval) < 0)
772 ++errors;
773
774 if (state -> i_am == secondary) {
775 errno = 0;
776 fprintf (db_file, "\n mclt %ld;",
777 (unsigned long)state -> mclt);
778 if (errno)
779 ++errors;
780 }
781
782 errno = 0;
783 fprintf (db_file, "\n}\n");
784 if (errno)
785 ++errors;
786
787 if (errors) {
788 log_info ("write_failover_state: unable to write state %s",
789 state -> name);
790 lease_file_is_corrupt = 1;
791 return 0;
792 }
793
794 return 1;
795
796 }
797 #endif
798
db_printable(s)799 int db_printable (s)
800 const unsigned char *s;
801 {
802 int i;
803 for (i = 0; s [i]; i++)
804 if (!isascii (s [i]) || !isprint (s [i])
805 || s [i] == '"' || s [i] == '\\')
806 return 0;
807 return 1;
808 }
809
db_printable_len(s,len)810 int db_printable_len (s, len)
811 const unsigned char *s;
812 unsigned len;
813 {
814 int i;
815
816 for (i = 0; i < len; i++)
817 if (!isascii (s [i]) || !isprint (s [i]) ||
818 s [i] == '"' || s [i] == '\\')
819 return 0;
820 return 1;
821 }
822
print_hash_string(FILE * fp,struct class * class)823 static int print_hash_string(FILE *fp, struct class *class)
824 {
825 int i;
826
827 for (i = 0 ; i < class->hash_string.len ; i++)
828 if (!isascii(class->hash_string.data[i]) ||
829 !isprint(class->hash_string.data[i]))
830 break;
831
832 if (i == class->hash_string.len) {
833 if (fprintf(fp, " \"%.*s\"", (int)class->hash_string.len,
834 class->hash_string.data) <= 0) {
835 log_error("Failure writing hash string: %m");
836 return 0;
837 }
838 } else {
839 if (fprintf(fp, " %2.2x", class->hash_string.data[0]) <= 0) {
840 log_error("Failure writing hash string: %m");
841 return 0;
842 }
843 for (i = 1 ; i < class->hash_string.len ; i++) {
844 if (fprintf(fp, ":%2.2x",
845 class->hash_string.data[i]) <= 0) {
846 log_error("Failure writing hash string: %m");
847 return 0;
848 }
849 }
850 }
851
852 return 1;
853 }
854
855
856 isc_result_t
write_named_billing_class(const void * key,unsigned len,void * object)857 write_named_billing_class(const void *key, unsigned len, void *object)
858 {
859 const unsigned char *name = key;
860 struct class *class = object;
861
862 if (class->flags & CLASS_DECL_DYNAMIC) {
863 numclasseswritten++;
864 if (class->superclass == 0) {
865 if (fprintf(db_file, "class \"%s\" {\n", name) <= 0)
866 return ISC_R_IOERROR;
867 } else {
868 if (fprintf(db_file, "subclass \"%s\"",
869 class->superclass->name) <= 0)
870 return ISC_R_IOERROR;
871 if (!print_hash_string(db_file, class))
872 return ISC_R_IOERROR;
873 if (fprintf(db_file, " {\n") <= 0)
874 return ISC_R_IOERROR;
875 }
876
877 if ((class->flags & CLASS_DECL_DELETED) != 0) {
878 if (fprintf(db_file, " deleted;\n") <= 0)
879 return ISC_R_IOERROR;
880 } else {
881 if (fprintf(db_file, " dynamic;\n") <= 0)
882 return ISC_R_IOERROR;
883 }
884
885 if (class->lease_limit > 0) {
886 if (fprintf(db_file, " lease limit %d;\n",
887 class->lease_limit) <= 0)
888 return ISC_R_IOERROR;
889 }
890
891 if (class->expr != 0) {
892 if (fprintf(db_file, " match if ") <= 0)
893 return ISC_R_IOERROR;
894
895 errno = 0;
896 write_expression(db_file, class->expr, 5, 5, 0);
897 if (errno)
898 return ISC_R_IOERROR;
899
900 if (fprintf(db_file, ";\n") <= 0)
901 return ISC_R_IOERROR;
902 }
903
904 if (class->submatch != 0) {
905 if (class->spawning) {
906 if (fprintf(db_file, " spawn ") <= 0)
907 return ISC_R_IOERROR;
908 } else {
909 if (fprintf(db_file, " match ") <= 0)
910 return ISC_R_IOERROR;
911 }
912
913 errno = 0;
914 write_expression(db_file, class->submatch, 5, 5, 0);
915 if (errno)
916 return ISC_R_IOERROR;
917
918 if (fprintf(db_file, ";\n") <= 0)
919 return ISC_R_IOERROR;
920 }
921
922 if (class->statements != 0) {
923 errno = 0;
924 write_statements(db_file, class->statements, 8);
925 if (errno)
926 return ISC_R_IOERROR;
927 }
928
929 /* XXXJAB this isn't right, but classes read in off the
930 leases file don't get the root group assigned to them
931 (due to clone_group() call). */
932 if (class->group != 0 && class->group->authoritative != 0) {
933 errno = 0;
934 write_statements(db_file, class->group->statements, 8);
935 if (errno)
936 return ISC_R_IOERROR;
937 }
938
939 if (fprintf(db_file, "}\n\n") <= 0)
940 return ISC_R_IOERROR;
941 }
942
943 if (class->hash != NULL) { /* yep. recursive. god help us. */
944 /* XXX - cannot check error status of this...
945 * foo_hash_foreach returns a count of operations completed.
946 */
947 class_hash_foreach(class->hash, write_named_billing_class);
948 }
949
950 return ISC_R_SUCCESS;
951 }
952
write_billing_classes()953 void write_billing_classes ()
954 {
955 struct collection *lp;
956 struct class *cp;
957
958 for (lp = collections; lp; lp = lp -> next) {
959 for (cp = lp -> classes; cp; cp = cp -> nic) {
960 if (cp -> spawning && cp -> hash) {
961 class_hash_foreach (cp -> hash, write_named_billing_class);
962 }
963 }
964 }
965 }
966
967 /* Write a spawned class to the database file. */
968
write_billing_class(class)969 int write_billing_class (class)
970 struct class *class;
971 {
972 int errors = 0;
973
974 if (lease_file_is_corrupt)
975 if (!new_lease_file ())
976 return 0;
977
978 if (!class -> superclass) {
979 errno = 0;
980 fprintf (db_file, "\n billing class \"%s\";", class -> name);
981 return !errno;
982 }
983
984 if (fprintf(db_file, "\n billing subclass \"%s\"",
985 class -> superclass -> name) < 0)
986 ++errors;
987
988 if (!print_hash_string(db_file, class))
989 ++errors;
990
991 if (fprintf(db_file, ";") < 0)
992 ++errors;
993
994 class -> dirty = !errors;
995 if (errors)
996 lease_file_is_corrupt = 1;
997
998 return !errors;
999 }
1000
1001 /* Commit leases after a timeout. */
commit_leases_timeout(void * foo)1002 void commit_leases_timeout (void *foo)
1003 {
1004 commit_leases ();
1005 }
1006
1007 /* Commit any leases that have been written out... */
1008
commit_leases()1009 int commit_leases ()
1010 {
1011 /* Commit any outstanding writes to the lease database file.
1012 We need to do this even if we're rewriting the file below,
1013 just in case the rewrite fails. */
1014 if (fflush (db_file) == EOF) {
1015 log_info("commit_leases: unable to commit, fflush(): %m");
1016 return (0);
1017 }
1018 if ((dont_use_fsync == 0) &&
1019 (fsync(fileno (db_file)) < 0)) {
1020 log_info ("commit_leases: unable to commit, fsync(): %m");
1021 return (0);
1022 }
1023
1024 /* send out all deferred ACKs now */
1025 flush_ackqueue(NULL);
1026
1027 /* If we haven't rewritten the lease database in over an
1028 hour, rewrite it now. (The length of time should probably
1029 be configurable. */
1030 if (count && cur_time - write_time > LEASE_REWRITE_PERIOD) {
1031 count = 0;
1032 write_time = cur_time;
1033 new_lease_file();
1034 }
1035 return (1);
1036 }
1037
1038 /*
1039 * rewrite the lease file about once an hour
1040 * This is meant as a quick patch for ticket 24887. It allows
1041 * us to rotate the v6 lease file without adding too many fsync()
1042 * calls. In the future wes should revisit this area and add
1043 * something similar to the delayed ack code for v4.
1044 */
commit_leases_timed()1045 int commit_leases_timed()
1046 {
1047 if ((count != 0) && (cur_time - write_time > LEASE_REWRITE_PERIOD)) {
1048 return (commit_leases());
1049 }
1050 return (1);
1051 }
1052
db_startup(testp)1053 void db_startup (testp)
1054 int testp;
1055 {
1056 isc_result_t status;
1057
1058 #if defined (TRACING)
1059 if (!trace_playback ()) {
1060 #endif
1061 /* Read in the existing lease file... */
1062 status = read_conf_file (path_dhcpd_db,
1063 (struct group *)0, 0, 1);
1064 if (status != ISC_R_SUCCESS) {
1065 /* XXX ignore status? */
1066 ;
1067 }
1068
1069 #if defined (TRACING)
1070 }
1071 #endif
1072
1073 #if defined (TRACING)
1074 /* If we're playing back, there is no lease file, so we can't
1075 append it, so we create one immediately (maybe this isn't
1076 the best solution... */
1077 if (trace_playback ()) {
1078 new_lease_file ();
1079 }
1080 #endif
1081 if (!testp) {
1082 db_file = fopen (path_dhcpd_db, "a");
1083 if (!db_file)
1084 log_fatal ("Can't open %s for append.", path_dhcpd_db);
1085 expire_all_pools ();
1086 #if defined (TRACING)
1087 if (trace_playback ())
1088 write_time = cur_time;
1089 else
1090 #endif
1091 time(&write_time);
1092 new_lease_file ();
1093 }
1094
1095 #if defined(REPORT_HASH_PERFORMANCE)
1096 log_info("Host HW hash: %s", host_hash_report(host_hw_addr_hash));
1097 log_info("Host UID hash: %s", host_hash_report(host_uid_hash));
1098 log_info("Lease IP hash: %s",
1099 lease_ip_hash_report(lease_ip_addr_hash));
1100 log_info("Lease UID hash: %s", lease_id_hash_report(lease_uid_hash));
1101 log_info("Lease HW hash: %s",
1102 lease_id_hash_report(lease_hw_addr_hash));
1103 #endif
1104 }
1105
new_lease_file()1106 int new_lease_file ()
1107 {
1108 char newfname [512];
1109 char backfname [512];
1110 TIME t;
1111 int db_fd;
1112 int db_validity;
1113 FILE *new_db_file;
1114
1115 /* Make a temporary lease file... */
1116 time(&t);
1117
1118 db_validity = lease_file_is_corrupt;
1119
1120 /* %Audit% Truncated filename causes panic. %2004.06.17,Safe%
1121 * This should never happen since the path is a configuration
1122 * variable from build-time or command-line. But if it should,
1123 * either by malice or ignorance, we panic, since the potential
1124 * for havoc is high.
1125 */
1126 if (snprintf (newfname, sizeof newfname, "%s.%d",
1127 path_dhcpd_db, (int)t) >= sizeof newfname)
1128 log_fatal("new_lease_file: lease file path too long");
1129
1130 db_fd = open (newfname, O_WRONLY | O_TRUNC | O_CREAT, 0664);
1131 if (db_fd < 0) {
1132 log_error ("Can't create new lease file: %m");
1133 return 0;
1134 }
1135 if ((new_db_file = fdopen(db_fd, "w")) == NULL) {
1136 log_error("Can't fdopen new lease file: %m");
1137 close(db_fd);
1138 goto fdfail;
1139 }
1140
1141 /* Close previous database, if any. */
1142 if (db_file)
1143 fclose(db_file);
1144 db_file = new_db_file;
1145
1146 errno = 0;
1147 fprintf (db_file, "# The format of this file is documented in the %s",
1148 "dhcpd.leases(5) manual page.\n");
1149 if (errno)
1150 goto fail;
1151
1152 fprintf (db_file, "# This lease file was written by isc-dhcp-%s\n\n",
1153 PACKAGE_VERSION);
1154 if (errno)
1155 goto fail;
1156
1157 /* At this point we have a new lease file that, so far, could not
1158 * be described as either corrupt nor valid.
1159 */
1160 lease_file_is_corrupt = 0;
1161
1162 /* Write out all the leases that we know of... */
1163 counting = 0;
1164 if (!write_leases ())
1165 goto fail;
1166
1167 #if defined (TRACING)
1168 if (!trace_playback ()) {
1169 #endif
1170 /* %Audit% Truncated filename causes panic. %2004.06.17,Safe%
1171 * This should never happen since the path is a configuration
1172 * variable from build-time or command-line. But if it should,
1173 * either by malice or ignorance, we panic, since the potential
1174 * for havoc is too high.
1175 */
1176 if (snprintf (backfname, sizeof backfname, "%s~", path_dhcpd_db)
1177 >= sizeof backfname)
1178 log_fatal("new_lease_file: backup lease file path too long");
1179
1180 /* Get the old database out of the way... */
1181 if (unlink (backfname) < 0 && errno != ENOENT) {
1182 log_error ("Can't remove old lease database backup %s: %m",
1183 backfname);
1184 goto fail;
1185 }
1186 if (link(path_dhcpd_db, backfname) < 0) {
1187 if (errno == ENOENT) {
1188 log_error("%s is missing - no lease db to backup.",
1189 path_dhcpd_db);
1190 } else {
1191 log_error("Can't backup lease database %s to %s: %m",
1192 path_dhcpd_db, backfname);
1193 goto fail;
1194 }
1195 }
1196 #if defined (TRACING)
1197 }
1198 #endif
1199
1200 /* Move in the new file... */
1201 if (rename (newfname, path_dhcpd_db) < 0) {
1202 log_error ("Can't install new lease database %s to %s: %m",
1203 newfname, path_dhcpd_db);
1204 goto fail;
1205 }
1206
1207 counting = 1;
1208 return 1;
1209
1210 fail:
1211 lease_file_is_corrupt = db_validity;
1212 fdfail:
1213 unlink (newfname);
1214 return 0;
1215 }
1216
group_writer(struct group_object * group)1217 int group_writer (struct group_object *group)
1218 {
1219 if (!write_group (group))
1220 return 0;
1221 if (!commit_leases ())
1222 return 0;
1223 return 1;
1224 }
1225