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 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 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 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 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 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 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) 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 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 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 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 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 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 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. */ 1002 void commit_leases_timeout (void *foo) 1003 { 1004 commit_leases (); 1005 } 1006 1007 /* Commit any leases that have been written out... */ 1008 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 */ 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 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 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 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