1 /* $NetBSD: mdb.c,v 1.2 2014/07/12 12:09:38 spz Exp $ */ 2 /* mdb.c 3 4 Server-specific in-memory database support. */ 5 6 /* 7 * Copyright (c) 2011-2014 by Internet Systems Consortium, Inc. ("ISC") 8 * Copyright (c) 2004-2009 by Internet Systems Consortium, Inc. ("ISC") 9 * Copyright (c) 1996-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: mdb.c,v 1.2 2014/07/12 12:09:38 spz Exp $"); 33 34 #include "dhcpd.h" 35 #include "omapip/hash.h" 36 37 struct subnet *subnets; 38 struct shared_network *shared_networks; 39 host_hash_t *host_hw_addr_hash; 40 host_hash_t *host_uid_hash; 41 host_hash_t *host_name_hash; 42 lease_id_hash_t *lease_uid_hash; 43 lease_ip_hash_t *lease_ip_addr_hash; 44 lease_id_hash_t *lease_hw_addr_hash; 45 46 /* 47 * We allow users to specify any option as a host identifier. 48 * 49 * Any host is uniquely identified by the combination of 50 * option type & option data. 51 * 52 * We expect people will only use a few types of options as host 53 * identifier. Because of this, we store a list with an entry for 54 * each option type. Each of these has a hash table, which contains 55 * hash of the option data. 56 * 57 * For v6 we also include a relay count - this specifies which 58 * relay to check for the requested option. As each different 59 * value of relays creates a new instance admins should use the 60 * same value across each option for all host-identifers. 61 * A value of 0 indicates that we aren't doing relay options 62 * and should simply look in the current option list. 63 */ 64 typedef struct host_id_info { 65 struct option *option; 66 host_hash_t *values_hash; 67 int relays; 68 struct host_id_info *next; 69 } host_id_info_t; 70 71 static host_id_info_t *host_id_info = NULL; 72 73 int numclasseswritten; 74 75 omapi_object_type_t *dhcp_type_host; 76 77 isc_result_t enter_class(cd, dynamicp, commit) 78 struct class *cd; 79 int dynamicp; 80 int commit; 81 { 82 if (!collections -> classes) { 83 /* A subclass with no parent is invalid. */ 84 if (cd->name == NULL) 85 return DHCP_R_INVALIDARG; 86 87 class_reference (&collections -> classes, cd, MDL); 88 } else if (cd->name != NULL) { /* regular class */ 89 struct class *c = 0; 90 91 if (find_class(&c, cd->name, MDL) != ISC_R_NOTFOUND) { 92 class_dereference(&c, MDL); 93 return ISC_R_EXISTS; 94 } 95 96 /* Find the tail. */ 97 for (c = collections -> classes; 98 c -> nic; c = c -> nic) 99 /* nothing */ ; 100 class_reference (&c -> nic, cd, MDL); 101 } 102 103 if (dynamicp && commit) { 104 const char *name = cd->name; 105 106 if (name == NULL) { 107 name = cd->superclass->name; 108 } 109 110 write_named_billing_class ((const unsigned char *)name, 0, cd); 111 if (!commit_leases ()) 112 return ISC_R_IOERROR; 113 } 114 115 return ISC_R_SUCCESS; 116 } 117 118 119 /* Variable to check if we're starting the server. The server will init as 120 * starting - but just to be safe start out as false to avoid triggering new 121 * special-case code 122 * XXX: There is actually a server_startup state...which is never entered... 123 */ 124 #define SS_NOSYNC 1 125 #define SS_QFOLLOW 2 126 static int server_starting = 0; 127 128 static int find_uid_statement (struct executable_statement *esp, 129 void *vp, int condp) 130 { 131 struct executable_statement **evp = vp; 132 133 if (esp -> op == supersede_option_statement && 134 esp -> data.option && 135 (esp -> data.option -> option -> universe == 136 &dhcp_universe) && 137 (esp -> data.option -> option -> code == 138 DHO_DHCP_CLIENT_IDENTIFIER)) { 139 if (condp) { 140 log_error ("dhcp client identifier may not be %s", 141 "specified conditionally."); 142 } else if (!(*evp)) { 143 executable_statement_reference (evp, esp, MDL); 144 return 1; 145 } else { 146 log_error ("only one dhcp client identifier may be %s", 147 "specified"); 148 } 149 } 150 return 0; 151 } 152 153 154 static host_id_info_t * 155 find_host_id_info(unsigned int option_code, int relays) { 156 host_id_info_t *p; 157 158 for (p = host_id_info; p != NULL; p = p->next) { 159 if ((p->option->code == option_code) && 160 (p->relays == relays)) { 161 break; 162 } 163 } 164 return p; 165 } 166 167 /* Debugging code */ 168 #if 0 169 isc_result_t 170 print_host(const void *name, unsigned len, void *value) { 171 struct host_decl *h; 172 printf("--------------\n"); 173 printf("name:'%s'\n", print_hex_1(len, name, 60)); 174 printf("len:%d\n", len); 175 h = (struct host_decl *)value; 176 printf("host @%p is '%s'\n", h, h->name); 177 return ISC_R_SUCCESS; 178 } 179 180 void 181 hash_print_hosts(struct hash_table *h) { 182 hash_foreach(h, print_host); 183 printf("--------------\n"); 184 } 185 #endif /* 0 */ 186 187 void 188 change_host_uid(struct host_decl *host, const char *uid, int len) { 189 /* XXX: should consolidate this type of code throughout */ 190 if (host_uid_hash == NULL) { 191 if (!host_new_hash(&host_uid_hash, HOST_HASH_SIZE, MDL)) { 192 log_fatal("Can't allocate host/uid hash"); 193 } 194 } 195 196 /* 197 * Remove the old entry, if one exists. 198 */ 199 if (host->client_identifier.data != NULL) { 200 host_hash_delete(host_uid_hash, 201 host->client_identifier.data, 202 host->client_identifier.len, 203 MDL); 204 data_string_forget(&host->client_identifier, MDL); 205 } 206 207 /* 208 * Set our new value. 209 */ 210 memset(&host->client_identifier, 0, sizeof(host->client_identifier)); 211 host->client_identifier.len = len; 212 if (!buffer_allocate(&host->client_identifier.buffer, len, MDL)) { 213 log_fatal("Can't allocate uid buffer"); 214 } 215 host->client_identifier.data = host->client_identifier.buffer->data; 216 memcpy((char *)host->client_identifier.data, uid, len); 217 218 /* 219 * And add to hash. 220 */ 221 host_hash_add(host_uid_hash, host->client_identifier.data, 222 host->client_identifier.len, host, MDL); 223 } 224 225 isc_result_t enter_host (hd, dynamicp, commit) 226 struct host_decl *hd; 227 int dynamicp; 228 int commit; 229 { 230 struct host_decl *hp = (struct host_decl *)0; 231 struct host_decl *np = (struct host_decl *)0; 232 struct executable_statement *esp; 233 host_id_info_t *h_id_info; 234 235 if (!host_name_hash) { 236 if (!host_new_hash(&host_name_hash, HOST_HASH_SIZE, MDL)) 237 log_fatal ("Can't allocate host name hash"); 238 host_hash_add (host_name_hash, 239 (unsigned char *)hd -> name, 240 strlen (hd -> name), hd, MDL); 241 } else { 242 host_hash_lookup (&hp, host_name_hash, 243 (unsigned char *)hd -> name, 244 strlen (hd -> name), MDL); 245 246 /* If it's deleted, we can supersede it. */ 247 if (hp && (hp -> flags & HOST_DECL_DELETED)) { 248 host_hash_delete (host_name_hash, 249 (unsigned char *)hd -> name, 250 strlen (hd -> name), MDL); 251 /* If the old entry wasn't dynamic, then we 252 always have to keep the deletion. */ 253 if (hp -> flags & HOST_DECL_STATIC) { 254 hd -> flags |= HOST_DECL_STATIC; 255 } 256 host_dereference (&hp, MDL); 257 } 258 259 /* If we are updating an existing host declaration, we 260 can just delete it and add it again. */ 261 if (hp && hp == hd) { 262 host_dereference (&hp, MDL); 263 delete_host (hd, 0); 264 if (!write_host (hd)) 265 return ISC_R_IOERROR; 266 hd -> flags &= ~HOST_DECL_DELETED; 267 } 268 269 /* If there isn't already a host decl matching this 270 address, add it to the hash table. */ 271 if (!hp) { 272 host_hash_add (host_name_hash, 273 (unsigned char *)hd -> name, 274 strlen (hd -> name), hd, MDL); 275 } else { 276 /* XXX actually, we have to delete the old one 277 XXX carefully and replace it. Not done yet. */ 278 host_dereference (&hp, MDL); 279 return ISC_R_EXISTS; 280 } 281 } 282 283 if (hd -> n_ipaddr) 284 host_dereference (&hd -> n_ipaddr, MDL); 285 286 if (!hd -> type) 287 hd -> type = dhcp_type_host; 288 289 if (hd -> interface.hlen) { 290 if (!host_hw_addr_hash) { 291 if (!host_new_hash(&host_hw_addr_hash, 292 HOST_HASH_SIZE, MDL)) 293 log_fatal ("Can't allocate host/hw hash"); 294 } else { 295 /* If there isn't already a host decl matching this 296 address, add it to the hash table. */ 297 host_hash_lookup (&hp, host_hw_addr_hash, 298 hd -> interface.hbuf, 299 hd -> interface.hlen, MDL); 300 } 301 if (!hp) 302 host_hash_add (host_hw_addr_hash, hd -> interface.hbuf, 303 hd -> interface.hlen, hd, MDL); 304 else { 305 /* If there was already a host declaration for 306 this hardware address, add this one to the 307 end of the list. */ 308 for (np = hp; np -> n_ipaddr; np = np -> n_ipaddr) 309 ; 310 host_reference (&np -> n_ipaddr, hd, MDL); 311 host_dereference (&hp, MDL); 312 } 313 } 314 315 /* See if there's a statement that sets the client identifier. 316 This is a kludge - the client identifier really shouldn't be 317 set with an executable statement. */ 318 esp = NULL; 319 if (executable_statement_foreach (hd->group->statements, 320 find_uid_statement, &esp, 0)) { 321 (void) evaluate_option_cache (&hd->client_identifier, 322 NULL, NULL, NULL, NULL, NULL, 323 &global_scope, 324 esp->data.option, MDL); 325 } 326 327 /* If we got a client identifier, hash this entry by 328 client identifier. */ 329 if (hd -> client_identifier.len) { 330 /* If there's no uid hash, make one; otherwise, see if 331 there's already an entry in the hash for this host. */ 332 if (!host_uid_hash) { 333 if (!host_new_hash(&host_uid_hash, 334 HOST_HASH_SIZE, MDL)) 335 log_fatal ("Can't allocate host/uid hash"); 336 337 host_hash_add (host_uid_hash, 338 hd -> client_identifier.data, 339 hd -> client_identifier.len, 340 hd, MDL); 341 } else { 342 /* If there's already a host declaration for this 343 client identifier, add this one to the end of the 344 list. Otherwise, add it to the hash table. */ 345 if (host_hash_lookup (&hp, host_uid_hash, 346 hd -> client_identifier.data, 347 hd -> client_identifier.len, 348 MDL)) { 349 /* Don't link it in twice... */ 350 if (!np) { 351 for (np = hp; np -> n_ipaddr; 352 np = np -> n_ipaddr) { 353 if (hd == np) 354 break; 355 } 356 if (hd != np) 357 host_reference (&np -> n_ipaddr, 358 hd, MDL); 359 } 360 host_dereference (&hp, MDL); 361 } else { 362 host_hash_add (host_uid_hash, 363 hd -> client_identifier.data, 364 hd -> client_identifier.len, 365 hd, MDL); 366 } 367 } 368 } 369 370 371 /* 372 * If we use an option as our host identifier, record it here. 373 */ 374 if (hd->host_id_option != NULL) { 375 /* 376 * Look for the host identifier information for this option, 377 * and create a new entry if there is none. 378 */ 379 h_id_info = find_host_id_info(hd->host_id_option->code, 380 hd->relays); 381 if (h_id_info == NULL) { 382 h_id_info = dmalloc(sizeof(*h_id_info), MDL); 383 if (h_id_info == NULL) { 384 log_fatal("No memory for host-identifier " 385 "option information."); 386 } 387 option_reference(&h_id_info->option, 388 hd->host_id_option, MDL); 389 if (!host_new_hash(&h_id_info->values_hash, 390 HOST_HASH_SIZE, MDL)) { 391 log_fatal("No memory for host-identifier " 392 "option hash."); 393 } 394 h_id_info->relays = hd->relays; 395 h_id_info->next = host_id_info; 396 host_id_info = h_id_info; 397 } 398 399 if (host_hash_lookup(&hp, h_id_info->values_hash, 400 hd->host_id.data, hd->host_id.len, MDL)) { 401 /* 402 * If this option is already present, then add 403 * this host to the list in n_ipaddr, unless 404 * we have already done so previously. 405 * 406 * XXXSK: This seems scary to me, but I don't 407 * fully understand how these are used. 408 * Shouldn't there be multiple lists, or 409 * maybe we should just forbid duplicates? 410 */ 411 if (np == NULL) { 412 np = hp; 413 while (np->n_ipaddr != NULL) { 414 np = np->n_ipaddr; 415 } 416 if (hd != np) { 417 host_reference(&np->n_ipaddr, hd, MDL); 418 } 419 } 420 host_dereference(&hp, MDL); 421 } else { 422 host_hash_add(h_id_info->values_hash, 423 hd->host_id.data, 424 hd->host_id.len, 425 hd, MDL); 426 } 427 } 428 429 if (dynamicp && commit) { 430 if (!write_host (hd)) 431 return ISC_R_IOERROR; 432 if (!commit_leases ()) 433 return ISC_R_IOERROR; 434 } 435 436 return ISC_R_SUCCESS; 437 } 438 439 440 isc_result_t delete_class (cp, commit) 441 struct class *cp; 442 int commit; 443 { 444 cp->flags |= CLASS_DECL_DELETED; 445 446 /* do the write first as we won't be leaving it in any data 447 structures, unlike the host objects */ 448 449 if (commit) { 450 write_named_billing_class ((unsigned char *)cp->name, 0, cp); 451 if (!commit_leases ()) 452 return ISC_R_IOERROR; 453 } 454 455 /* 456 * If this is a subclass remove it from the class's hash table 457 */ 458 if (cp->superclass) { 459 class_hash_delete(cp->superclass->hash, 460 (const char *)cp->hash_string.data, 461 cp->hash_string.len, 462 MDL); 463 } 464 465 /* remove from collections */ 466 unlink_class(&cp); 467 468 return ISC_R_SUCCESS; 469 } 470 471 472 isc_result_t delete_host (hd, commit) 473 struct host_decl *hd; 474 int commit; 475 { 476 struct host_decl *hp = (struct host_decl *)0; 477 struct host_decl *np = (struct host_decl *)0; 478 struct host_decl *foo; 479 int hw_head = 0, uid_head = 1; 480 481 /* Don't need to do it twice. */ 482 if (hd -> flags & HOST_DECL_DELETED) 483 return ISC_R_SUCCESS; 484 485 /* But we do need to do it once! :') */ 486 hd -> flags |= HOST_DECL_DELETED; 487 488 if (hd -> interface.hlen) { 489 if (host_hw_addr_hash) { 490 if (host_hash_lookup (&hp, host_hw_addr_hash, 491 hd -> interface.hbuf, 492 hd -> interface.hlen, MDL)) { 493 if (hp == hd) { 494 host_hash_delete (host_hw_addr_hash, 495 hd -> interface.hbuf, 496 hd -> interface.hlen, MDL); 497 hw_head = 1; 498 } else { 499 np = (struct host_decl *)0; 500 foo = (struct host_decl *)0; 501 host_reference (&foo, hp, MDL); 502 while (foo) { 503 if (foo == hd) 504 break; 505 if (np) 506 host_dereference (&np, MDL); 507 host_reference (&np, foo, MDL); 508 host_dereference (&foo, MDL); 509 if (np -> n_ipaddr) 510 host_reference (&foo, np -> n_ipaddr, MDL); 511 } 512 513 if (foo) { 514 host_dereference (&np -> n_ipaddr, MDL); 515 if (hd -> n_ipaddr) 516 host_reference (&np -> n_ipaddr, 517 hd -> n_ipaddr, MDL); 518 host_dereference (&foo, MDL); 519 } 520 if (np) 521 host_dereference (&np, MDL); 522 } 523 host_dereference (&hp, MDL); 524 } 525 } 526 } 527 528 /* If we got a client identifier, hash this entry by 529 client identifier. */ 530 if (hd -> client_identifier.len) { 531 if (host_uid_hash) { 532 if (host_hash_lookup (&hp, host_uid_hash, 533 hd -> client_identifier.data, 534 hd -> client_identifier.len, MDL)) { 535 if (hp == hd) { 536 host_hash_delete (host_uid_hash, 537 hd -> client_identifier.data, 538 hd -> client_identifier.len, MDL); 539 uid_head = 1; 540 } else { 541 np = (struct host_decl *)0; 542 foo = (struct host_decl *)0; 543 host_reference (&foo, hp, MDL); 544 while (foo) { 545 if (foo == hd) 546 break; 547 if (np) 548 host_dereference (&np, MDL); 549 host_reference (&np, foo, MDL); 550 host_dereference (&foo, MDL); 551 if (np -> n_ipaddr) 552 host_reference (&foo, np -> n_ipaddr, MDL); 553 } 554 555 if (foo) { 556 host_dereference (&np -> n_ipaddr, MDL); 557 if (hd -> n_ipaddr) 558 host_reference (&np -> n_ipaddr, 559 hd -> n_ipaddr, MDL); 560 host_dereference (&foo, MDL); 561 } 562 if (np) 563 host_dereference (&np, MDL); 564 } 565 host_dereference (&hp, MDL); 566 } 567 } 568 } 569 570 if (hd->host_id_option != NULL) { 571 option_dereference(&hd->host_id_option, MDL); 572 data_string_forget(&hd->host_id, MDL); 573 } 574 575 if (hd -> n_ipaddr) { 576 if (uid_head && hd -> n_ipaddr -> client_identifier.len) { 577 host_hash_add 578 (host_uid_hash, 579 hd -> n_ipaddr -> client_identifier.data, 580 hd -> n_ipaddr -> client_identifier.len, 581 hd -> n_ipaddr, MDL); 582 } 583 if (hw_head && hd -> n_ipaddr -> interface.hlen) { 584 host_hash_add (host_hw_addr_hash, 585 hd -> n_ipaddr -> interface.hbuf, 586 hd -> n_ipaddr -> interface.hlen, 587 hd -> n_ipaddr, MDL); 588 } 589 host_dereference (&hd -> n_ipaddr, MDL); 590 } 591 592 if (host_name_hash) { 593 if (host_hash_lookup (&hp, host_name_hash, 594 (unsigned char *)hd -> name, 595 strlen (hd -> name), MDL)) { 596 if (hp == hd && !(hp -> flags & HOST_DECL_STATIC)) { 597 host_hash_delete (host_name_hash, 598 (unsigned char *)hd -> name, 599 strlen (hd -> name), MDL); 600 } 601 host_dereference (&hp, MDL); 602 } 603 } 604 605 if (commit) { 606 if (!write_host (hd)) 607 return ISC_R_IOERROR; 608 if (!commit_leases ()) 609 return ISC_R_IOERROR; 610 } 611 return ISC_R_SUCCESS; 612 } 613 614 int find_hosts_by_haddr (struct host_decl **hp, int htype, 615 const unsigned char *haddr, unsigned hlen, 616 const char *file, int line) 617 { 618 struct hardware h; 619 #if defined(LDAP_CONFIGURATION) 620 int ret; 621 622 if ((ret = find_haddr_in_ldap (hp, htype, hlen, haddr, file, line))) 623 return ret; 624 #endif 625 626 h.hlen = hlen + 1; 627 h.hbuf [0] = htype; 628 memcpy (&h.hbuf [1], haddr, hlen); 629 630 return host_hash_lookup (hp, host_hw_addr_hash, 631 h.hbuf, h.hlen, file, line); 632 } 633 634 int find_hosts_by_uid (struct host_decl **hp, 635 const unsigned char *data, unsigned len, 636 const char *file, int line) 637 { 638 return host_hash_lookup (hp, host_uid_hash, data, len, file, line); 639 } 640 641 int 642 find_hosts_by_option(struct host_decl **hp, 643 struct packet *packet, 644 struct option_state *opt_state, 645 const char *file, int line) { 646 host_id_info_t *p; 647 struct option_cache *oc; 648 struct data_string data; 649 int found; 650 struct packet *relay_packet; 651 struct option_state *relay_state; 652 653 for (p = host_id_info; p != NULL; p = p->next) { 654 relay_packet = packet; 655 relay_state = opt_state; 656 657 /* If this option block is for a relay (relays != 0) 658 * and we are processing the main options and not 659 * options from the IA (packet->options == opt_state) 660 * try to find the proper relay 661 */ 662 if ((p->relays != 0) && (packet->options == opt_state)) { 663 int i = p->relays; 664 while ((i != 0) && 665 (relay_packet->dhcpv6_container_packet != NULL)) { 666 relay_packet = 667 relay_packet->dhcpv6_container_packet; 668 i--; 669 } 670 /* We wanted a specific relay but were 671 * unable to find it */ 672 if ((p->relays <= MAX_V6RELAY_HOPS) && (i != 0)) 673 continue; 674 675 relay_state = relay_packet->options; 676 } 677 678 oc = lookup_option(p->option->universe, 679 relay_state, p->option->code); 680 if (oc != NULL) { 681 memset(&data, 0, sizeof(data)); 682 683 if (!evaluate_option_cache(&data, relay_packet, NULL, 684 NULL, relay_state, NULL, 685 &global_scope, oc, 686 MDL)) { 687 log_error("Error evaluating option cache"); 688 return 0; 689 } 690 691 found = host_hash_lookup(hp, p->values_hash, 692 data.data, data.len, 693 file, line); 694 695 data_string_forget(&data, MDL); 696 697 if (found) { 698 return 1; 699 } 700 } 701 } 702 return 0; 703 } 704 705 /* More than one host_decl can be returned by find_hosts_by_haddr or 706 find_hosts_by_uid, and each host_decl can have multiple addresses. 707 Loop through the list of hosts, and then for each host, through the 708 list of addresses, looking for an address that's in the same shared 709 network as the one specified. Store the matching address through 710 the addr pointer, update the host pointer to point at the host_decl 711 that matched, and return the subnet that matched. */ 712 713 int find_host_for_network (struct subnet **sp, struct host_decl **host, 714 struct iaddr *addr, struct shared_network *share) 715 { 716 int i; 717 struct iaddr ip_address; 718 struct host_decl *hp; 719 struct data_string fixed_addr; 720 721 memset (&fixed_addr, 0, sizeof fixed_addr); 722 723 for (hp = *host; hp; hp = hp -> n_ipaddr) { 724 if (!hp -> fixed_addr) 725 continue; 726 if (!evaluate_option_cache (&fixed_addr, (struct packet *)0, 727 (struct lease *)0, 728 (struct client_state *)0, 729 (struct option_state *)0, 730 (struct option_state *)0, 731 &global_scope, 732 hp -> fixed_addr, MDL)) 733 continue; 734 for (i = 0; i < fixed_addr.len; i += 4) { 735 ip_address.len = 4; 736 memcpy (ip_address.iabuf, 737 fixed_addr.data + i, 4); 738 if (find_grouped_subnet (sp, share, ip_address, MDL)) { 739 struct host_decl *tmp = (struct host_decl *)0; 740 *addr = ip_address; 741 /* This is probably not necessary, but 742 just in case *host is the only reference 743 to that host declaration, make a temporary 744 reference so that dereferencing it doesn't 745 dereference hp out from under us. */ 746 host_reference (&tmp, *host, MDL); 747 host_dereference (host, MDL); 748 host_reference (host, hp, MDL); 749 host_dereference (&tmp, MDL); 750 data_string_forget (&fixed_addr, MDL); 751 return 1; 752 } 753 } 754 data_string_forget (&fixed_addr, MDL); 755 } 756 return 0; 757 } 758 759 void new_address_range (cfile, low, high, subnet, pool, lpchain) 760 struct parse *cfile; 761 struct iaddr low, high; 762 struct subnet *subnet; 763 struct pool *pool; 764 struct lease **lpchain; 765 { 766 #if defined(COMPACT_LEASES) 767 struct lease *address_range; 768 #endif 769 unsigned min, max, i; 770 char lowbuf [16], highbuf [16], netbuf [16]; 771 struct shared_network *share = subnet -> shared_network; 772 struct lease *lt = (struct lease *)0; 773 #if !defined(COMPACT_LEASES) 774 isc_result_t status; 775 #endif 776 777 /* All subnets should have attached shared network structures. */ 778 if (!share) { 779 strcpy (netbuf, piaddr (subnet -> net)); 780 log_fatal ("No shared network for network %s (%s)", 781 netbuf, piaddr (subnet -> netmask)); 782 } 783 784 /* Initialize the hash table if it hasn't been done yet. */ 785 if (!lease_uid_hash) { 786 if (!lease_id_new_hash(&lease_uid_hash, LEASE_HASH_SIZE, MDL)) 787 log_fatal ("Can't allocate lease/uid hash"); 788 } 789 if (!lease_ip_addr_hash) { 790 if (!lease_ip_new_hash(&lease_ip_addr_hash, LEASE_HASH_SIZE, 791 MDL)) 792 log_fatal ("Can't allocate lease/ip hash"); 793 } 794 if (!lease_hw_addr_hash) { 795 if (!lease_id_new_hash(&lease_hw_addr_hash, LEASE_HASH_SIZE, 796 MDL)) 797 log_fatal ("Can't allocate lease/hw hash"); 798 } 799 800 /* Make sure that high and low addresses are in this subnet. */ 801 if (!addr_eq(subnet->net, subnet_number(low, subnet->netmask))) { 802 strcpy(lowbuf, piaddr(low)); 803 strcpy(netbuf, piaddr(subnet->net)); 804 log_fatal("bad range, address %s not in subnet %s netmask %s", 805 lowbuf, netbuf, piaddr(subnet->netmask)); 806 } 807 808 if (!addr_eq(subnet->net, subnet_number(high, subnet->netmask))) { 809 strcpy(highbuf, piaddr(high)); 810 strcpy(netbuf, piaddr(subnet->net)); 811 log_fatal("bad range, address %s not in subnet %s netmask %s", 812 highbuf, netbuf, piaddr(subnet->netmask)); 813 } 814 815 /* Get the high and low host addresses... */ 816 max = host_addr (high, subnet -> netmask); 817 min = host_addr (low, subnet -> netmask); 818 819 /* Allow range to be specified high-to-low as well as low-to-high. */ 820 if (min > max) { 821 max = min; 822 min = host_addr (high, subnet -> netmask); 823 } 824 825 /* Get a lease structure for each address in the range. */ 826 #if defined (COMPACT_LEASES) 827 address_range = new_leases (max - min + 1, MDL); 828 if (!address_range) { 829 strcpy (lowbuf, piaddr (low)); 830 strcpy (highbuf, piaddr (high)); 831 log_fatal ("No memory for address range %s-%s.", 832 lowbuf, highbuf); 833 } 834 #endif 835 836 /* Fill out the lease structures with some minimal information. */ 837 for (i = 0; i < max - min + 1; i++) { 838 struct lease *lp = (struct lease *)0; 839 #if defined (COMPACT_LEASES) 840 omapi_object_initialize ((omapi_object_t *)&address_range [i], 841 dhcp_type_lease, 842 0, sizeof (struct lease), MDL); 843 lease_reference (&lp, &address_range [i], MDL); 844 #else 845 status = lease_allocate (&lp, MDL); 846 if (status != ISC_R_SUCCESS) 847 log_fatal ("No memory for lease %s: %s", 848 piaddr (ip_addr (subnet -> net, 849 subnet -> netmask, 850 i + min)), 851 isc_result_totext (status)); 852 #endif 853 lp->ip_addr = ip_addr(subnet->net, subnet->netmask, i + min); 854 lp->starts = MIN_TIME; 855 lp->ends = MIN_TIME; 856 subnet_reference(&lp->subnet, subnet, MDL); 857 pool_reference(&lp->pool, pool, MDL); 858 lp->binding_state = FTS_FREE; 859 lp->next_binding_state = FTS_FREE; 860 lp->rewind_binding_state = FTS_FREE; 861 lp->flags = 0; 862 863 /* Remember the lease in the IP address hash. */ 864 if (find_lease_by_ip_addr (<, lp -> ip_addr, MDL)) { 865 if (lt -> pool) { 866 parse_warn (cfile, 867 "lease %s is declared twice!", 868 piaddr (lp -> ip_addr)); 869 } else 870 pool_reference (< -> pool, pool, MDL); 871 lease_dereference (<, MDL); 872 } else 873 lease_ip_hash_add(lease_ip_addr_hash, 874 lp->ip_addr.iabuf, lp->ip_addr.len, 875 lp, MDL); 876 /* Put the lease on the chain for the caller. */ 877 if (lpchain) { 878 if (*lpchain) { 879 lease_reference (&lp -> next, *lpchain, MDL); 880 lease_dereference (lpchain, MDL); 881 } 882 lease_reference (lpchain, lp, MDL); 883 } 884 lease_dereference (&lp, MDL); 885 } 886 } 887 888 int find_subnet (struct subnet **sp, 889 struct iaddr addr, const char *file, int line) 890 { 891 struct subnet *rv; 892 893 for (rv = subnets; rv; rv = rv -> next_subnet) { 894 if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net)) { 895 if (subnet_reference (sp, rv, 896 file, line) != ISC_R_SUCCESS) 897 return 0; 898 return 1; 899 } 900 } 901 return 0; 902 } 903 904 int find_grouped_subnet (struct subnet **sp, 905 struct shared_network *share, struct iaddr addr, 906 const char *file, int line) 907 { 908 struct subnet *rv; 909 910 for (rv = share -> subnets; rv; rv = rv -> next_sibling) { 911 if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net)) { 912 if (subnet_reference (sp, rv, 913 file, line) != ISC_R_SUCCESS) 914 return 0; 915 return 1; 916 } 917 } 918 return 0; 919 } 920 921 /* XXX: could speed up if everyone had a prefix length */ 922 int 923 subnet_inner_than(const struct subnet *subnet, 924 const struct subnet *scan, 925 int warnp) { 926 if (addr_eq(subnet_number(subnet->net, scan->netmask), scan->net) || 927 addr_eq(subnet_number(scan->net, subnet->netmask), subnet->net)) { 928 char n1buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255")]; 929 int i, j; 930 for (i = 0; i < 128; i++) 931 if (subnet->netmask.iabuf[3 - (i >> 3)] 932 & (1 << (i & 7))) 933 break; 934 for (j = 0; j < 128; j++) 935 if (scan->netmask.iabuf[3 - (j >> 3)] & 936 (1 << (j & 7))) 937 break; 938 if (warnp) { 939 strcpy(n1buf, piaddr(subnet->net)); 940 log_error("Warning: subnet %s/%d overlaps subnet %s/%d", 941 n1buf, 32 - i, 942 piaddr(scan->net), 32 - j); 943 } 944 if (i < j) 945 return 1; 946 } 947 return 0; 948 } 949 950 /* Enter a new subnet into the subnet list. */ 951 void enter_subnet (subnet) 952 struct subnet *subnet; 953 { 954 struct subnet *scan = (struct subnet *)0; 955 struct subnet *next = (struct subnet *)0; 956 struct subnet *prev = (struct subnet *)0; 957 958 /* Check for duplicates... */ 959 if (subnets) 960 subnet_reference (&next, subnets, MDL); 961 while (next) { 962 subnet_reference (&scan, next, MDL); 963 subnet_dereference (&next, MDL); 964 965 /* When we find a conflict, make sure that the 966 subnet with the narrowest subnet mask comes 967 first. */ 968 if (subnet_inner_than (subnet, scan, 1)) { 969 if (prev) { 970 if (prev -> next_subnet) 971 subnet_dereference (&prev -> next_subnet, MDL); 972 subnet_reference (&prev -> next_subnet, subnet, MDL); 973 subnet_dereference (&prev, MDL); 974 } else { 975 subnet_dereference (&subnets, MDL); 976 subnet_reference (&subnets, subnet, MDL); 977 } 978 subnet_reference (&subnet -> next_subnet, scan, MDL); 979 subnet_dereference (&scan, MDL); 980 return; 981 } 982 subnet_reference (&prev, scan, MDL); 983 subnet_dereference (&scan, MDL); 984 } 985 if (prev) 986 subnet_dereference (&prev, MDL); 987 988 /* XXX use the BSD radix tree code instead of a linked list. */ 989 if (subnets) { 990 subnet_reference (&subnet -> next_subnet, subnets, MDL); 991 subnet_dereference (&subnets, MDL); 992 } 993 subnet_reference (&subnets, subnet, MDL); 994 } 995 996 /* Enter a new shared network into the shared network list. */ 997 998 void enter_shared_network (share) 999 struct shared_network *share; 1000 { 1001 if (shared_networks) { 1002 shared_network_reference (&share -> next, 1003 shared_networks, MDL); 1004 shared_network_dereference (&shared_networks, MDL); 1005 } 1006 shared_network_reference (&shared_networks, share, MDL); 1007 } 1008 1009 void new_shared_network_interface (cfile, share, name) 1010 struct parse *cfile; 1011 struct shared_network *share; 1012 const char *name; 1013 { 1014 struct interface_info *ip; 1015 isc_result_t status; 1016 1017 if (share -> interface) { 1018 parse_warn (cfile, 1019 "A subnet or shared network can't be connected %s", 1020 "to two interfaces."); 1021 return; 1022 } 1023 1024 for (ip = interfaces; ip; ip = ip -> next) 1025 if (!strcmp (ip -> name, name)) 1026 break; 1027 if (!ip) { 1028 status = interface_allocate (&ip, MDL); 1029 if (status != ISC_R_SUCCESS) 1030 log_fatal ("new_shared_network_interface %s: %s", 1031 name, isc_result_totext (status)); 1032 if (strlen (name) > sizeof ip -> name) { 1033 memcpy (ip -> name, name, (sizeof ip -> name) - 1); 1034 ip -> name [(sizeof ip -> name) - 1] = 0; 1035 } else 1036 strcpy (ip -> name, name); 1037 if (interfaces) { 1038 interface_reference (&ip -> next, interfaces, MDL); 1039 interface_dereference (&interfaces, MDL); 1040 } 1041 interface_reference (&interfaces, ip, MDL); 1042 ip -> flags = INTERFACE_REQUESTED; 1043 /* XXX this is a reference loop. */ 1044 shared_network_reference (&ip -> shared_network, share, MDL); 1045 interface_reference (&share -> interface, ip, MDL); 1046 } 1047 } 1048 1049 /* Enter a lease into the system. This is called by the parser each 1050 time it reads in a new lease. If the subnet for that lease has 1051 already been read in (usually the case), just update that lease; 1052 otherwise, allocate temporary storage for the lease and keep it around 1053 until we're done reading in the config file. */ 1054 1055 void enter_lease (lease) 1056 struct lease *lease; 1057 { 1058 struct lease *comp = (struct lease *)0; 1059 1060 if (find_lease_by_ip_addr (&comp, lease -> ip_addr, MDL)) { 1061 if (!comp -> pool) { 1062 log_error ("undeclared lease found in database: %s", 1063 piaddr (lease -> ip_addr)); 1064 } else 1065 pool_reference (&lease -> pool, comp -> pool, MDL); 1066 1067 if (comp -> subnet) 1068 subnet_reference (&lease -> subnet, 1069 comp -> subnet, MDL); 1070 lease_ip_hash_delete(lease_ip_addr_hash, 1071 lease->ip_addr.iabuf, lease->ip_addr.len, 1072 MDL); 1073 lease_dereference (&comp, MDL); 1074 } 1075 1076 /* The only way a lease can get here without a subnet is if it's in 1077 the lease file, but not in the dhcpd.conf file. In this case, we 1078 *should* keep it around until it's expired, but never reallocate it 1079 or renew it. Currently, to maintain consistency, we are not doing 1080 this. 1081 XXX fix this so that the lease is kept around until it expires. 1082 XXX this will be important in IPv6 with addresses that become 1083 XXX non-renewable as a result of a renumbering event. */ 1084 1085 if (!lease -> subnet) { 1086 log_error ("lease %s: no subnet.", piaddr (lease -> ip_addr)); 1087 return; 1088 } 1089 lease_ip_hash_add(lease_ip_addr_hash, lease->ip_addr.iabuf, 1090 lease->ip_addr.len, lease, MDL); 1091 } 1092 1093 /* Replace the data in an existing lease with the data in a new lease; 1094 adjust hash tables to suit, and insertion sort the lease into the 1095 list of leases by expiry time so that we can always find the oldest 1096 lease. */ 1097 1098 int supersede_lease (comp, lease, commit, propogate, pimmediate) 1099 struct lease *comp, *lease; 1100 int commit; 1101 int propogate; 1102 int pimmediate; 1103 { 1104 struct lease *lp, **lq, *prev; 1105 struct timeval tv; 1106 #if defined (FAILOVER_PROTOCOL) 1107 int do_pool_check = 0; 1108 1109 /* We must commit leases before sending updates regarding them 1110 to failover peers. It is, therefore, an error to set pimmediate 1111 and not commit. */ 1112 if (pimmediate && !commit) 1113 return 0; 1114 #endif 1115 1116 /* If there is no sample lease, just do the move. */ 1117 if (!lease) 1118 goto just_move_it; 1119 1120 /* Static leases are not currently kept in the database... */ 1121 if (lease -> flags & STATIC_LEASE) 1122 return 1; 1123 1124 /* If the existing lease hasn't expired and has a different 1125 unique identifier or, if it doesn't have a unique 1126 identifier, a different hardware address, then the two 1127 leases are in conflict. If the existing lease has a uid 1128 and the new one doesn't, but they both have the same 1129 hardware address, and dynamic bootp is allowed on this 1130 lease, then we allow that, in case a dynamic BOOTP lease is 1131 requested *after* a DHCP lease has been assigned. */ 1132 1133 if (lease -> binding_state != FTS_ABANDONED && 1134 lease -> next_binding_state != FTS_ABANDONED && 1135 comp -> binding_state == FTS_ACTIVE && 1136 (((comp -> uid && lease -> uid) && 1137 (comp -> uid_len != lease -> uid_len || 1138 memcmp (comp -> uid, lease -> uid, comp -> uid_len))) || 1139 (!comp -> uid && 1140 ((comp -> hardware_addr.hlen != 1141 lease -> hardware_addr.hlen) || 1142 memcmp (comp -> hardware_addr.hbuf, 1143 lease -> hardware_addr.hbuf, 1144 comp -> hardware_addr.hlen))))) { 1145 log_error ("Lease conflict at %s", 1146 piaddr (comp -> ip_addr)); 1147 } 1148 1149 /* If there's a Unique ID, dissociate it from the hash 1150 table and free it if necessary. */ 1151 if (comp->uid) { 1152 uid_hash_delete(comp); 1153 if (comp->uid != comp->uid_buf) { 1154 dfree(comp->uid, MDL); 1155 comp->uid_max = 0; 1156 comp->uid_len = 0; 1157 } 1158 comp -> uid = (unsigned char *)0; 1159 } 1160 1161 /* If there's a hardware address, remove the lease from its 1162 * old position in the hash bucket's ordered list. 1163 */ 1164 if (comp->hardware_addr.hlen) 1165 hw_hash_delete(comp); 1166 1167 /* If the lease has been billed to a class, remove the billing. */ 1168 if (comp -> billing_class != lease -> billing_class) { 1169 if (comp -> billing_class) 1170 unbill_class (comp, comp -> billing_class); 1171 if (lease -> billing_class) 1172 bill_class (comp, lease -> billing_class); 1173 } 1174 1175 /* Copy the data files, but not the linkages. */ 1176 comp -> starts = lease -> starts; 1177 if (lease -> uid) { 1178 if (lease -> uid_len <= sizeof (lease -> uid_buf)) { 1179 memcpy (comp -> uid_buf, 1180 lease -> uid, lease -> uid_len); 1181 comp -> uid = &comp -> uid_buf [0]; 1182 comp -> uid_max = sizeof comp -> uid_buf; 1183 comp -> uid_len = lease -> uid_len; 1184 } else if (lease -> uid != &lease -> uid_buf [0]) { 1185 comp -> uid = lease -> uid; 1186 comp -> uid_max = lease -> uid_max; 1187 lease -> uid = (unsigned char *)0; 1188 lease -> uid_max = 0; 1189 comp -> uid_len = lease -> uid_len; 1190 lease -> uid_len = 0; 1191 } else { 1192 log_fatal ("corrupt lease uid."); /* XXX */ 1193 } 1194 } else { 1195 comp -> uid = (unsigned char *)0; 1196 comp -> uid_len = comp -> uid_max = 0; 1197 } 1198 if (comp -> host) 1199 host_dereference (&comp -> host, MDL); 1200 host_reference (&comp -> host, lease -> host, MDL); 1201 comp -> hardware_addr = lease -> hardware_addr; 1202 comp -> flags = ((lease -> flags & ~PERSISTENT_FLAGS) | 1203 (comp -> flags & ~EPHEMERAL_FLAGS)); 1204 if (comp -> scope) 1205 binding_scope_dereference (&comp -> scope, MDL); 1206 if (lease -> scope) { 1207 binding_scope_reference (&comp -> scope, lease -> scope, MDL); 1208 binding_scope_dereference (&lease -> scope, MDL); 1209 } 1210 1211 if (comp -> agent_options) 1212 option_chain_head_dereference (&comp -> agent_options, MDL); 1213 if (lease -> agent_options) { 1214 /* Only retain the agent options if the lease is still 1215 affirmatively associated with a client. */ 1216 if (lease -> next_binding_state == FTS_ACTIVE || 1217 lease -> next_binding_state == FTS_EXPIRED) 1218 option_chain_head_reference (&comp -> agent_options, 1219 lease -> agent_options, 1220 MDL); 1221 option_chain_head_dereference (&lease -> agent_options, MDL); 1222 } 1223 1224 /* Record the hostname information in the lease. */ 1225 if (comp -> client_hostname) 1226 dfree (comp -> client_hostname, MDL); 1227 comp -> client_hostname = lease -> client_hostname; 1228 lease -> client_hostname = (char *)0; 1229 1230 if (lease->on_star.on_expiry) { 1231 if (comp->on_star.on_expiry) 1232 executable_statement_dereference 1233 (&comp->on_star.on_expiry, MDL); 1234 executable_statement_reference (&comp->on_star.on_expiry, 1235 lease->on_star.on_expiry, 1236 MDL); 1237 } 1238 if (lease->on_star.on_commit) { 1239 if (comp->on_star.on_commit) 1240 executable_statement_dereference 1241 (&comp->on_star.on_commit, MDL); 1242 executable_statement_reference (&comp->on_star.on_commit, 1243 lease->on_star.on_commit, 1244 MDL); 1245 } 1246 if (lease->on_star.on_release) { 1247 if (comp->on_star.on_release) 1248 executable_statement_dereference 1249 (&comp->on_star.on_release, MDL); 1250 executable_statement_reference (&comp->on_star.on_release, 1251 lease->on_star.on_release, 1252 MDL); 1253 } 1254 1255 /* Record the lease in the uid hash if necessary. */ 1256 if (comp->uid) 1257 uid_hash_add(comp); 1258 1259 /* Record it in the hardware address hash if necessary. */ 1260 if (comp->hardware_addr.hlen) 1261 hw_hash_add(comp); 1262 1263 comp->cltt = lease->cltt; 1264 #if defined (FAILOVER_PROTOCOL) 1265 comp->tstp = lease->tstp; 1266 comp->tsfp = lease->tsfp; 1267 comp->atsfp = lease->atsfp; 1268 #endif /* FAILOVER_PROTOCOL */ 1269 comp->ends = lease->ends; 1270 comp->next_binding_state = lease->next_binding_state; 1271 1272 /* 1273 * If we have a control block pointer copy it in. 1274 * We don't zero out an older ponter as it is still 1275 * in use. We shouldn't need to overwrite an 1276 * old pointer with a new one as the old transaction 1277 * should have been cancelled before getting here. 1278 */ 1279 if (lease->ddns_cb != NULL) 1280 comp->ddns_cb = lease->ddns_cb; 1281 1282 just_move_it: 1283 #if defined (FAILOVER_PROTOCOL) 1284 /* 1285 * Atsfp should be cleared upon any state change that implies 1286 * propagation whether supersede_lease was given a copy lease 1287 * structure or not (often from the pool_timer()). 1288 */ 1289 if (propogate) 1290 comp->atsfp = 0; 1291 #endif /* FAILOVER_PROTOCOL */ 1292 1293 if (!comp -> pool) { 1294 log_error ("Supersede_lease: lease %s with no pool.", 1295 piaddr (comp -> ip_addr)); 1296 return 0; 1297 } 1298 1299 /* Figure out which queue it's on. */ 1300 switch (comp -> binding_state) { 1301 case FTS_FREE: 1302 if (comp->flags & RESERVED_LEASE) 1303 lq = &comp->pool->reserved; 1304 else { 1305 lq = &comp->pool->free; 1306 comp->pool->free_leases--; 1307 } 1308 1309 #if defined(FAILOVER_PROTOCOL) 1310 do_pool_check = 1; 1311 #endif 1312 break; 1313 1314 case FTS_ACTIVE: 1315 lq = &comp -> pool -> active; 1316 break; 1317 1318 case FTS_EXPIRED: 1319 case FTS_RELEASED: 1320 case FTS_RESET: 1321 lq = &comp -> pool -> expired; 1322 break; 1323 1324 case FTS_ABANDONED: 1325 lq = &comp -> pool -> abandoned; 1326 break; 1327 1328 case FTS_BACKUP: 1329 if (comp->flags & RESERVED_LEASE) 1330 lq = &comp->pool->reserved; 1331 else { 1332 lq = &comp->pool->backup; 1333 comp->pool->backup_leases--; 1334 } 1335 1336 #if defined(FAILOVER_PROTOCOL) 1337 do_pool_check = 1; 1338 #endif 1339 break; 1340 1341 default: 1342 log_error ("Lease with bogus binding state: %d", 1343 comp -> binding_state); 1344 #if defined (BINDING_STATE_DEBUG) 1345 abort (); 1346 #endif 1347 return 0; 1348 } 1349 1350 /* Remove the lease from its current place in its current 1351 timer sequence. */ 1352 /* XXX this is horrid. */ 1353 prev = (struct lease *)0; 1354 for (lp = *lq; lp; lp = lp -> next) { 1355 if (lp == comp) 1356 break; 1357 prev = lp; 1358 } 1359 1360 if (!lp) { 1361 log_fatal("Lease with binding state %s not on its queue.", 1362 (comp->binding_state < 1 || 1363 comp->binding_state > FTS_LAST) 1364 ? "unknown" 1365 : binding_state_names[comp->binding_state - 1]); 1366 } 1367 1368 if (prev) { 1369 lease_dereference (&prev -> next, MDL); 1370 if (comp -> next) { 1371 lease_reference (&prev -> next, comp -> next, MDL); 1372 lease_dereference (&comp -> next, MDL); 1373 } 1374 } else { 1375 lease_dereference (lq, MDL); 1376 if (comp -> next) { 1377 lease_reference (lq, comp -> next, MDL); 1378 lease_dereference (&comp -> next, MDL); 1379 } 1380 } 1381 1382 /* Make the state transition. */ 1383 if (commit || !pimmediate) 1384 make_binding_state_transition (comp); 1385 1386 /* Put the lease back on the appropriate queue. If the lease 1387 is corrupt (as detected by lease_enqueue), don't go any farther. */ 1388 if (!lease_enqueue (comp)) 1389 return 0; 1390 1391 /* If this is the next lease that will timeout on the pool, 1392 zap the old timeout and set the timeout on this pool to the 1393 time that the lease's next event will happen. 1394 1395 We do not actually set the timeout unless commit is true - 1396 we don't want to thrash the timer queue when reading the 1397 lease database. Instead, the database code calls the 1398 expiry event on each pool after reading in the lease file, 1399 and the expiry code sets the timer if there's anything left 1400 to expire after it's run any outstanding expiry events on 1401 the pool. */ 1402 if ((commit || !pimmediate) && 1403 comp -> sort_time != MIN_TIME && 1404 comp -> sort_time > cur_time && 1405 (comp -> sort_time < comp -> pool -> next_event_time || 1406 comp -> pool -> next_event_time == MIN_TIME)) { 1407 comp -> pool -> next_event_time = comp -> sort_time; 1408 tv . tv_sec = comp -> pool -> next_event_time; 1409 tv . tv_usec = 0; 1410 add_timeout (&tv, 1411 pool_timer, comp -> pool, 1412 (tvref_t)pool_reference, 1413 (tvunref_t)pool_dereference); 1414 } 1415 1416 if (commit) { 1417 #if defined(FAILOVER_PROTOCOL) 1418 /* 1419 * If commit and propogate are set, then we can save a 1420 * possible fsync later in BNDUPD socket transmission by 1421 * stepping the rewind state forward to the new state, in 1422 * case it has changed. This is only worth doing if the 1423 * failover connection is currently connected, as in this 1424 * case it is likely we will be transmitting to the peer very 1425 * shortly. 1426 */ 1427 if (propogate && (comp->pool->failover_peer != NULL) && 1428 ((comp->pool->failover_peer->service_state == 1429 cooperating) || 1430 (comp->pool->failover_peer->service_state == 1431 not_responding))) 1432 comp->rewind_binding_state = comp->binding_state; 1433 #endif 1434 1435 if (!write_lease (comp)) 1436 return 0; 1437 if ((server_starting & SS_NOSYNC) == 0) { 1438 if (!commit_leases ()) 1439 return 0; 1440 } 1441 } 1442 1443 #if defined (FAILOVER_PROTOCOL) 1444 if (propogate) { 1445 comp -> desired_binding_state = comp -> binding_state; 1446 if (!dhcp_failover_queue_update (comp, pimmediate)) 1447 return 0; 1448 } 1449 if (do_pool_check && comp->pool->failover_peer) 1450 dhcp_failover_pool_check(comp->pool); 1451 #endif 1452 1453 /* If the current binding state has already expired, do an 1454 expiry event right now. */ 1455 /* XXX At some point we should optimize this so that we don't 1456 XXX write the lease twice, but this is a safe way to fix the 1457 XXX problem for 3.0 (I hope!). */ 1458 if ((commit || !pimmediate) && 1459 comp -> sort_time < cur_time && 1460 comp -> next_binding_state != comp -> binding_state) 1461 pool_timer (comp -> pool); 1462 1463 return 1; 1464 } 1465 1466 void make_binding_state_transition (struct lease *lease) 1467 { 1468 1469 #if defined (FAILOVER_PROTOCOL) 1470 dhcp_failover_state_t *peer; 1471 1472 if (lease -> pool && lease -> pool -> failover_peer) 1473 peer = lease -> pool -> failover_peer; 1474 else 1475 peer = (dhcp_failover_state_t *)0; 1476 #endif 1477 1478 /* If the lease was active and is now no longer active, but isn't 1479 released, then it just expired, so do the expiry event. */ 1480 if (lease -> next_binding_state != lease -> binding_state && 1481 (( 1482 #if defined (FAILOVER_PROTOCOL) 1483 peer && 1484 (lease->binding_state == FTS_EXPIRED || 1485 lease->binding_state == FTS_ACTIVE) && 1486 (lease->next_binding_state == FTS_FREE || 1487 lease->next_binding_state == FTS_BACKUP)) || 1488 (!peer && 1489 #endif 1490 lease -> binding_state == FTS_ACTIVE && 1491 lease -> next_binding_state != FTS_RELEASED))) { 1492 #if defined (NSUPDATE) 1493 (void) ddns_removals(lease, NULL, NULL, ISC_TRUE); 1494 #endif 1495 if (lease->on_star.on_expiry) { 1496 execute_statements(NULL, NULL, lease, 1497 NULL, NULL, NULL, 1498 &lease->scope, 1499 lease->on_star.on_expiry, 1500 NULL); 1501 if (lease->on_star.on_expiry) 1502 executable_statement_dereference 1503 (&lease->on_star.on_expiry, MDL); 1504 } 1505 1506 /* No sense releasing a lease after it's expired. */ 1507 if (lease->on_star.on_release) 1508 executable_statement_dereference 1509 (&lease->on_star.on_release, MDL); 1510 /* Get rid of client-specific bindings that are only 1511 correct when the lease is active. */ 1512 if (lease -> billing_class) 1513 unbill_class (lease, lease -> billing_class); 1514 if (lease -> agent_options) 1515 option_chain_head_dereference (&lease -> agent_options, 1516 MDL); 1517 if (lease -> client_hostname) { 1518 dfree (lease -> client_hostname, MDL); 1519 lease -> client_hostname = (char *)0; 1520 } 1521 if (lease -> host) 1522 host_dereference (&lease -> host, MDL); 1523 1524 /* Send the expiry time to the peer. */ 1525 lease -> tstp = lease -> ends; 1526 } 1527 1528 /* If the lease was active and is now released, do the release 1529 event. */ 1530 if (lease -> next_binding_state != lease -> binding_state && 1531 (( 1532 #if defined (FAILOVER_PROTOCOL) 1533 peer && 1534 lease -> binding_state == FTS_RELEASED && 1535 (lease -> next_binding_state == FTS_FREE || 1536 lease -> next_binding_state == FTS_BACKUP)) || 1537 (!peer && 1538 #endif 1539 lease -> binding_state == FTS_ACTIVE && 1540 lease -> next_binding_state == FTS_RELEASED))) { 1541 #if defined (NSUPDATE) 1542 /* 1543 * Note: ddns_removals() is also iterated when the lease 1544 * enters state 'released' in 'release_lease()'. The below 1545 * is caught when a peer receives a BNDUPD from a failover 1546 * peer; it may not have received the client's release (it 1547 * may have been offline). 1548 * 1549 * We could remove the call from release_lease() because 1550 * it will also catch here on the originating server after the 1551 * peer acknowledges the state change. However, there could 1552 * be many hours inbetween, and in this case we /know/ the 1553 * client is no longer using the lease when we receive the 1554 * release message. This is not true of expiry, where the 1555 * peer may have extended the lease. 1556 */ 1557 (void) ddns_removals(lease, NULL, NULL, ISC_TRUE); 1558 #endif 1559 if (lease->on_star.on_release) { 1560 execute_statements(NULL, NULL, lease, 1561 NULL, NULL, NULL, 1562 &lease->scope, 1563 lease->on_star.on_release, 1564 NULL); 1565 executable_statement_dereference 1566 (&lease->on_star.on_release, MDL); 1567 } 1568 1569 /* A released lease can't expire. */ 1570 if (lease->on_star.on_expiry) 1571 executable_statement_dereference 1572 (&lease->on_star.on_expiry, MDL); 1573 1574 /* Get rid of client-specific bindings that are only 1575 correct when the lease is active. */ 1576 if (lease -> billing_class) 1577 unbill_class (lease, lease -> billing_class); 1578 if (lease -> agent_options) 1579 option_chain_head_dereference (&lease -> agent_options, 1580 MDL); 1581 if (lease -> client_hostname) { 1582 dfree (lease -> client_hostname, MDL); 1583 lease -> client_hostname = (char *)0; 1584 } 1585 if (lease -> host) 1586 host_dereference (&lease -> host, MDL); 1587 1588 /* Send the release time (should be == cur_time) to the 1589 peer. */ 1590 lease -> tstp = lease -> ends; 1591 } 1592 1593 #if defined (DEBUG_LEASE_STATE_TRANSITIONS) 1594 log_debug ("lease %s moves from %s to %s", 1595 piaddr (lease -> ip_addr), 1596 binding_state_print (lease -> binding_state), 1597 binding_state_print (lease -> next_binding_state)); 1598 #endif 1599 1600 lease -> binding_state = lease -> next_binding_state; 1601 switch (lease -> binding_state) { 1602 case FTS_ACTIVE: 1603 #if defined (FAILOVER_PROTOCOL) 1604 if (lease -> pool && lease -> pool -> failover_peer) 1605 lease -> next_binding_state = FTS_EXPIRED; 1606 else 1607 #endif 1608 lease -> next_binding_state = FTS_FREE; 1609 break; 1610 1611 case FTS_EXPIRED: 1612 case FTS_RELEASED: 1613 case FTS_ABANDONED: 1614 case FTS_RESET: 1615 lease->next_binding_state = FTS_FREE; 1616 #if defined(FAILOVER_PROTOCOL) 1617 /* If we are not in partner_down, leases don't go from 1618 EXPIRED to FREE on a timeout - only on an update. 1619 If we're in partner_down, they expire at mclt past 1620 the time we entered partner_down. */ 1621 if ((lease->pool != NULL) && 1622 (lease->pool->failover_peer != NULL) && 1623 (lease->pool->failover_peer->me.state == partner_down)) 1624 lease->tsfp = 1625 (lease->pool->failover_peer->me.stos + 1626 lease->pool->failover_peer->mclt); 1627 #endif /* FAILOVER_PROTOCOL */ 1628 break; 1629 1630 case FTS_FREE: 1631 case FTS_BACKUP: 1632 lease -> next_binding_state = lease -> binding_state; 1633 break; 1634 } 1635 #if defined (DEBUG_LEASE_STATE_TRANSITIONS) 1636 log_debug ("lease %s: next binding state %s", 1637 piaddr (lease -> ip_addr), 1638 binding_state_print (lease -> next_binding_state)); 1639 #endif 1640 } 1641 1642 /* Copy the contents of one lease into another, correctly maintaining 1643 reference counts. */ 1644 int lease_copy (struct lease **lp, 1645 struct lease *lease, const char *file, int line) 1646 { 1647 struct lease *lt = (struct lease *)0; 1648 isc_result_t status; 1649 1650 status = lease_allocate (<, MDL); 1651 if (status != ISC_R_SUCCESS) 1652 return 0; 1653 1654 lt -> ip_addr = lease -> ip_addr; 1655 lt -> starts = lease -> starts; 1656 lt -> ends = lease -> ends; 1657 lt -> uid_len = lease -> uid_len; 1658 lt -> uid_max = lease -> uid_max; 1659 if (lease -> uid == lease -> uid_buf) { 1660 lt -> uid = lt -> uid_buf; 1661 memcpy (lt -> uid_buf, lease -> uid_buf, sizeof lt -> uid_buf); 1662 } else if (!lease -> uid_max) { 1663 lt -> uid = (unsigned char *)0; 1664 } else { 1665 lt -> uid = dmalloc (lt -> uid_max, MDL); 1666 if (!lt -> uid) { 1667 lease_dereference (<, MDL); 1668 return 0; 1669 } 1670 memcpy (lt -> uid, lease -> uid, lease -> uid_max); 1671 } 1672 if (lease -> client_hostname) { 1673 lt -> client_hostname = 1674 dmalloc (strlen (lease -> client_hostname) + 1, MDL); 1675 if (!lt -> client_hostname) { 1676 lease_dereference (<, MDL); 1677 return 0; 1678 } 1679 strcpy (lt -> client_hostname, lease -> client_hostname); 1680 } 1681 if (lease -> scope) 1682 binding_scope_reference (< -> scope, lease -> scope, MDL); 1683 if (lease -> agent_options) 1684 option_chain_head_reference (< -> agent_options, 1685 lease -> agent_options, MDL); 1686 host_reference (< -> host, lease -> host, file, line); 1687 subnet_reference (< -> subnet, lease -> subnet, file, line); 1688 pool_reference (< -> pool, lease -> pool, file, line); 1689 class_reference (< -> billing_class, 1690 lease -> billing_class, file, line); 1691 lt -> hardware_addr = lease -> hardware_addr; 1692 if (lease->on_star.on_expiry) 1693 executable_statement_reference (<->on_star.on_expiry, 1694 lease->on_star.on_expiry, 1695 file, line); 1696 if (lease->on_star.on_commit) 1697 executable_statement_reference (<->on_star.on_commit, 1698 lease->on_star.on_commit, 1699 file, line); 1700 if (lease->on_star.on_release) 1701 executable_statement_reference (<->on_star.on_release, 1702 lease->on_star.on_release, 1703 file, line); 1704 lt->flags = lease->flags; 1705 lt->tstp = lease->tstp; 1706 lt->tsfp = lease->tsfp; 1707 lt->atsfp = lease->atsfp; 1708 lt->cltt = lease -> cltt; 1709 lt->binding_state = lease->binding_state; 1710 lt->next_binding_state = lease->next_binding_state; 1711 lt->rewind_binding_state = lease->rewind_binding_state; 1712 status = lease_reference(lp, lt, file, line); 1713 lease_dereference(<, MDL); 1714 return status == ISC_R_SUCCESS; 1715 } 1716 1717 /* Release the specified lease and re-hash it as appropriate. */ 1718 void release_lease (lease, packet) 1719 struct lease *lease; 1720 struct packet *packet; 1721 { 1722 /* If there are statements to execute when the lease is 1723 released, execute them. */ 1724 #if defined (NSUPDATE) 1725 (void) ddns_removals(lease, NULL, NULL, ISC_FALSE); 1726 #endif 1727 if (lease->on_star.on_release) { 1728 execute_statements (NULL, packet, lease, 1729 NULL, packet->options, 1730 NULL, &lease->scope, 1731 lease->on_star.on_release, NULL); 1732 if (lease->on_star.on_release) 1733 executable_statement_dereference 1734 (&lease->on_star.on_release, MDL); 1735 } 1736 1737 /* We do either the on_release or the on_expiry events, but 1738 not both (it's possible that they could be the same, 1739 in any case). */ 1740 if (lease->on_star.on_expiry) 1741 executable_statement_dereference 1742 (&lease->on_star.on_expiry, MDL); 1743 1744 if (lease -> binding_state != FTS_FREE && 1745 lease -> binding_state != FTS_BACKUP && 1746 lease -> binding_state != FTS_RELEASED && 1747 lease -> binding_state != FTS_EXPIRED && 1748 lease -> binding_state != FTS_RESET) { 1749 if (lease->on_star.on_commit) 1750 executable_statement_dereference 1751 (&lease->on_star.on_commit, MDL); 1752 1753 /* Blow away any bindings. */ 1754 if (lease -> scope) 1755 binding_scope_dereference (&lease -> scope, MDL); 1756 1757 /* Set sort times to the present. */ 1758 lease -> ends = cur_time; 1759 /* Lower layers of muckery set tstp to ->ends. But we send 1760 * protocol messages before this. So it is best to set 1761 * tstp now anyway. 1762 */ 1763 lease->tstp = cur_time; 1764 #if defined (FAILOVER_PROTOCOL) 1765 if (lease -> pool && lease -> pool -> failover_peer) { 1766 dhcp_failover_state_t *peer = NULL; 1767 1768 if (lease->pool != NULL) 1769 peer = lease->pool->failover_peer; 1770 1771 if ((peer->service_state == not_cooperating) && 1772 (((peer->i_am == primary) && 1773 (lease->rewind_binding_state == FTS_FREE)) || 1774 ((peer->i_am == secondary) && 1775 (lease->rewind_binding_state == FTS_BACKUP)))) { 1776 lease->next_binding_state = 1777 lease->rewind_binding_state; 1778 } else 1779 lease -> next_binding_state = FTS_RELEASED; 1780 } else { 1781 lease -> next_binding_state = FTS_FREE; 1782 } 1783 #else 1784 lease -> next_binding_state = FTS_FREE; 1785 #endif 1786 supersede_lease (lease, (struct lease *)0, 1, 1, 1); 1787 } 1788 } 1789 1790 /* Abandon the specified lease (set its timeout to infinity and its 1791 particulars to zero, and re-hash it as appropriate. */ 1792 1793 void abandon_lease (lease, message) 1794 struct lease *lease; 1795 const char *message; 1796 { 1797 struct lease *lt = (struct lease *)0; 1798 #if defined (NSUPDATE) 1799 (void) ddns_removals(lease, NULL, NULL, ISC_FALSE); 1800 #endif 1801 1802 if (!lease_copy (<, lease, MDL)) 1803 return; 1804 1805 if (lt->scope) 1806 binding_scope_dereference(<->scope, MDL); 1807 1808 lt -> ends = cur_time; /* XXX */ 1809 lt -> next_binding_state = FTS_ABANDONED; 1810 1811 log_error ("Abandoning IP address %s: %s", 1812 piaddr (lease -> ip_addr), message); 1813 lt -> hardware_addr.hlen = 0; 1814 if (lt -> uid && lt -> uid != lt -> uid_buf) 1815 dfree (lt -> uid, MDL); 1816 lt -> uid = (unsigned char *)0; 1817 lt -> uid_len = 0; 1818 lt -> uid_max = 0; 1819 supersede_lease (lease, lt, 1, 1, 1); 1820 lease_dereference (<, MDL); 1821 } 1822 1823 #if 0 1824 /* 1825 * This doesn't appear to be in use for anything anymore. 1826 * I'm ifdeffing it now and if there are no complaints in 1827 * the future it will be removed. 1828 * SAR 1829 */ 1830 1831 /* Abandon the specified lease (set its timeout to infinity and its 1832 particulars to zero, and re-hash it as appropriate. */ 1833 1834 void dissociate_lease (lease) 1835 struct lease *lease; 1836 { 1837 struct lease *lt = (struct lease *)0; 1838 #if defined (NSUPDATE) 1839 (void) ddns_removals(lease, NULL, NULL, ISC_FALSE); 1840 #endif 1841 1842 if (!lease_copy (<, lease, MDL)) 1843 return; 1844 1845 #if defined (FAILOVER_PROTOCOL) 1846 if (lease -> pool && lease -> pool -> failover_peer) { 1847 lt -> next_binding_state = FTS_RESET; 1848 } else { 1849 lt -> next_binding_state = FTS_FREE; 1850 } 1851 #else 1852 lt -> next_binding_state = FTS_FREE; 1853 #endif 1854 lt -> ends = cur_time; /* XXX */ 1855 lt -> hardware_addr.hlen = 0; 1856 if (lt -> uid && lt -> uid != lt -> uid_buf) 1857 dfree (lt -> uid, MDL); 1858 lt -> uid = (unsigned char *)0; 1859 lt -> uid_len = 0; 1860 lt -> uid_max = 0; 1861 supersede_lease (lease, lt, 1, 1, 1); 1862 lease_dereference (<, MDL); 1863 } 1864 #endif 1865 1866 /* Timer called when a lease in a particular pool expires. */ 1867 void pool_timer (vpool) 1868 void *vpool; 1869 { 1870 struct pool *pool; 1871 struct lease *next = (struct lease *)0; 1872 struct lease *lease = (struct lease *)0; 1873 #define FREE_LEASES 0 1874 #define ACTIVE_LEASES 1 1875 #define EXPIRED_LEASES 2 1876 #define ABANDONED_LEASES 3 1877 #define BACKUP_LEASES 4 1878 #define RESERVED_LEASES 5 1879 struct lease **lptr[RESERVED_LEASES+1]; 1880 TIME next_expiry = MAX_TIME; 1881 int i; 1882 struct timeval tv; 1883 1884 pool = (struct pool *)vpool; 1885 1886 lptr [FREE_LEASES] = &pool -> free; 1887 lptr [ACTIVE_LEASES] = &pool -> active; 1888 lptr [EXPIRED_LEASES] = &pool -> expired; 1889 lptr [ABANDONED_LEASES] = &pool -> abandoned; 1890 lptr [BACKUP_LEASES] = &pool -> backup; 1891 lptr[RESERVED_LEASES] = &pool->reserved; 1892 1893 for (i = FREE_LEASES; i <= RESERVED_LEASES; i++) { 1894 /* If there's nothing on the queue, skip it. */ 1895 if (!*(lptr [i])) 1896 continue; 1897 1898 #if defined (FAILOVER_PROTOCOL) 1899 if (pool->failover_peer && 1900 pool->failover_peer->me.state != partner_down) { 1901 /* 1902 * Normally the secondary doesn't initiate expiration 1903 * events (unless in partner-down), but rather relies 1904 * on the primary to expire the lease. However, when 1905 * disconnected from its peer, the server is allowed to 1906 * rewind a lease to the previous state that the peer 1907 * would have recorded it. This means there may be 1908 * opportunities for active->free or active->backup 1909 * expirations while out of contact. 1910 * 1911 * Q: Should we limit this expiration to 1912 * comms-interrupt rather than not-normal? 1913 */ 1914 if ((i == ACTIVE_LEASES) && 1915 (pool->failover_peer->i_am == secondary) && 1916 (pool->failover_peer->me.state == normal)) 1917 continue; 1918 1919 /* Leases in an expired state don't move to 1920 free because of a timeout unless we're in 1921 partner_down. */ 1922 if (i == EXPIRED_LEASES) 1923 continue; 1924 } 1925 #endif 1926 lease_reference (&lease, *(lptr [i]), MDL); 1927 1928 while (lease) { 1929 /* Remember the next lease in the list. */ 1930 if (next) 1931 lease_dereference (&next, MDL); 1932 if (lease -> next) 1933 lease_reference (&next, lease -> next, MDL); 1934 1935 /* If we've run out of things to expire on this list, 1936 stop. */ 1937 if (lease -> sort_time > cur_time) { 1938 if (lease -> sort_time < next_expiry) 1939 next_expiry = lease -> sort_time; 1940 break; 1941 } 1942 1943 /* If there is a pending state change, and 1944 this lease has gotten to the time when the 1945 state change should happen, just call 1946 supersede_lease on it to make the change 1947 happen. */ 1948 if (lease->next_binding_state != lease->binding_state) 1949 { 1950 #if defined(FAILOVER_PROTOCOL) 1951 dhcp_failover_state_t *peer = NULL; 1952 1953 if (lease->pool != NULL) 1954 peer = lease->pool->failover_peer; 1955 1956 /* Can we rewind the lease to a free state? */ 1957 if (peer != NULL && 1958 peer->service_state == not_cooperating && 1959 lease->next_binding_state == FTS_EXPIRED && 1960 ((peer->i_am == primary && 1961 lease->rewind_binding_state == FTS_FREE) 1962 || 1963 (peer->i_am == secondary && 1964 lease->rewind_binding_state == 1965 FTS_BACKUP))) 1966 lease->next_binding_state = 1967 lease->rewind_binding_state; 1968 #endif 1969 supersede_lease(lease, NULL, 1, 1, 1); 1970 } 1971 1972 lease_dereference (&lease, MDL); 1973 if (next) 1974 lease_reference (&lease, next, MDL); 1975 } 1976 if (next) 1977 lease_dereference (&next, MDL); 1978 if (lease) 1979 lease_dereference (&lease, MDL); 1980 } 1981 if (next_expiry != MAX_TIME) { 1982 pool -> next_event_time = next_expiry; 1983 tv . tv_sec = pool -> next_event_time; 1984 tv . tv_usec = 0; 1985 add_timeout (&tv, pool_timer, pool, 1986 (tvref_t)pool_reference, 1987 (tvunref_t)pool_dereference); 1988 } else 1989 pool -> next_event_time = MIN_TIME; 1990 1991 } 1992 1993 /* Locate the lease associated with a given IP address... */ 1994 1995 int find_lease_by_ip_addr (struct lease **lp, struct iaddr addr, 1996 const char *file, int line) 1997 { 1998 return lease_ip_hash_lookup(lp, lease_ip_addr_hash, addr.iabuf, 1999 addr.len, file, line); 2000 } 2001 2002 int find_lease_by_uid (struct lease **lp, const unsigned char *uid, 2003 unsigned len, const char *file, int line) 2004 { 2005 if (len == 0) 2006 return 0; 2007 return lease_id_hash_lookup (lp, lease_uid_hash, uid, len, file, line); 2008 } 2009 2010 int find_lease_by_hw_addr (struct lease **lp, 2011 const unsigned char *hwaddr, unsigned hwlen, 2012 const char *file, int line) 2013 { 2014 if (hwlen == 0) 2015 return (0); 2016 2017 /* 2018 * If it's an infiniband address don't bother 2019 * as we don't have a useful address to hash. 2020 */ 2021 if ((hwlen == 1) && (hwaddr[0] == HTYPE_INFINIBAND)) 2022 return (0); 2023 2024 return (lease_id_hash_lookup(lp, lease_hw_addr_hash, hwaddr, hwlen, 2025 file, line)); 2026 } 2027 2028 /* If the lease is preferred over the candidate, return truth. The 2029 * 'cand' and 'lease' names are retained to read more clearly against 2030 * the 'uid_hash_add' and 'hw_hash_add' functions (this is common logic 2031 * to those two functions). 2032 * 2033 * 1) ACTIVE leases are preferred. The active lease with 2034 * the longest lifetime is preferred over shortest. 2035 * 2) "transitional states" are next, this time with the 2036 * most recent CLTT. 2037 * 3) free/backup/etc states are next, again with CLTT. In truth we 2038 * should never see reset leases for this. 2039 * 4) Abandoned leases are always dead last. 2040 */ 2041 static isc_boolean_t 2042 client_lease_preferred(struct lease *cand, struct lease *lease) 2043 { 2044 if (cand->binding_state == FTS_ACTIVE) { 2045 if (lease->binding_state == FTS_ACTIVE && 2046 lease->ends >= cand->ends) 2047 return ISC_TRUE; 2048 } else if (cand->binding_state == FTS_EXPIRED || 2049 cand->binding_state == FTS_RELEASED) { 2050 if (lease->binding_state == FTS_ACTIVE) 2051 return ISC_TRUE; 2052 2053 if ((lease->binding_state == FTS_EXPIRED || 2054 lease->binding_state == FTS_RELEASED) && 2055 lease->cltt >= cand->cltt) 2056 return ISC_TRUE; 2057 } else if (cand->binding_state != FTS_ABANDONED) { 2058 if (lease->binding_state == FTS_ACTIVE || 2059 lease->binding_state == FTS_EXPIRED || 2060 lease->binding_state == FTS_RELEASED) 2061 return ISC_TRUE; 2062 2063 if (lease->binding_state != FTS_ABANDONED && 2064 lease->cltt >= cand->cltt) 2065 return ISC_TRUE; 2066 } else /* (cand->binding_state == FTS_ABANDONED) */ { 2067 if (lease->binding_state != FTS_ABANDONED || 2068 lease->cltt >= cand->cltt) 2069 return ISC_TRUE; 2070 } 2071 2072 return ISC_FALSE; 2073 } 2074 2075 /* Add the specified lease to the uid hash. */ 2076 void 2077 uid_hash_add(struct lease *lease) 2078 { 2079 struct lease *head = NULL; 2080 struct lease *cand = NULL; 2081 struct lease *prev = NULL; 2082 struct lease *next = NULL; 2083 2084 /* If it's not in the hash, just add it. */ 2085 if (!find_lease_by_uid (&head, lease -> uid, lease -> uid_len, MDL)) 2086 lease_id_hash_add(lease_uid_hash, lease->uid, lease->uid_len, 2087 lease, MDL); 2088 else { 2089 /* Otherwise, insert it into the list in order of its 2090 * preference for "resuming allocation to the client." 2091 * 2092 * Because we don't have control of the hash bucket index 2093 * directly, we have to remove and re-insert the client 2094 * id into the hash if we're inserting onto the head. 2095 */ 2096 lease_reference(&cand, head, MDL); 2097 while (cand != NULL) { 2098 if (client_lease_preferred(cand, lease)) 2099 break; 2100 2101 if (prev != NULL) 2102 lease_dereference(&prev, MDL); 2103 lease_reference(&prev, cand, MDL); 2104 2105 if (cand->n_uid != NULL) 2106 lease_reference(&next, cand->n_uid, MDL); 2107 2108 lease_dereference(&cand, MDL); 2109 2110 if (next != NULL) { 2111 lease_reference(&cand, next, MDL); 2112 lease_dereference(&next, MDL); 2113 } 2114 } 2115 2116 /* If we want to insert 'before cand', and prev is NULL, 2117 * then it was the head of the list. Assume that position. 2118 */ 2119 if (prev == NULL) { 2120 lease_reference(&lease->n_uid, head, MDL); 2121 lease_id_hash_delete(lease_uid_hash, lease->uid, 2122 lease->uid_len, MDL); 2123 lease_id_hash_add(lease_uid_hash, lease->uid, 2124 lease->uid_len, lease, MDL); 2125 } else /* (prev != NULL) */ { 2126 if(prev->n_uid != NULL) { 2127 lease_reference(&lease->n_uid, prev->n_uid, 2128 MDL); 2129 lease_dereference(&prev->n_uid, MDL); 2130 } 2131 lease_reference(&prev->n_uid, lease, MDL); 2132 2133 lease_dereference(&prev, MDL); 2134 } 2135 2136 if (cand != NULL) 2137 lease_dereference(&cand, MDL); 2138 lease_dereference(&head, MDL); 2139 } 2140 } 2141 2142 /* Delete the specified lease from the uid hash. */ 2143 2144 void uid_hash_delete (lease) 2145 struct lease *lease; 2146 { 2147 struct lease *head = (struct lease *)0; 2148 struct lease *scan; 2149 2150 /* If it's not in the hash, we have no work to do. */ 2151 if (!find_lease_by_uid (&head, lease -> uid, lease -> uid_len, MDL)) { 2152 if (lease -> n_uid) 2153 lease_dereference (&lease -> n_uid, MDL); 2154 return; 2155 } 2156 2157 /* If the lease we're freeing is at the head of the list, 2158 remove the hash table entry and add a new one with the 2159 next lease on the list (if there is one). */ 2160 if (head == lease) { 2161 lease_id_hash_delete(lease_uid_hash, lease->uid, 2162 lease->uid_len, MDL); 2163 if (lease -> n_uid) { 2164 lease_id_hash_add(lease_uid_hash, lease->n_uid->uid, 2165 lease->n_uid->uid_len, lease->n_uid, 2166 MDL); 2167 lease_dereference (&lease -> n_uid, MDL); 2168 } 2169 } else { 2170 /* Otherwise, look for the lease in the list of leases 2171 attached to the hash table entry, and remove it if 2172 we find it. */ 2173 for (scan = head; scan -> n_uid; scan = scan -> n_uid) { 2174 if (scan -> n_uid == lease) { 2175 lease_dereference (&scan -> n_uid, MDL); 2176 if (lease -> n_uid) { 2177 lease_reference (&scan -> n_uid, 2178 lease -> n_uid, MDL); 2179 lease_dereference (&lease -> n_uid, 2180 MDL); 2181 } 2182 break; 2183 } 2184 } 2185 } 2186 lease_dereference (&head, MDL); 2187 } 2188 2189 /* Add the specified lease to the hardware address hash. */ 2190 /* We don't add leases with infiniband addresses to the 2191 * hash as there isn't any address to hash on. */ 2192 2193 void 2194 hw_hash_add(struct lease *lease) 2195 { 2196 struct lease *head = NULL; 2197 struct lease *cand = NULL; 2198 struct lease *prev = NULL; 2199 struct lease *next = NULL; 2200 2201 /* 2202 * If it's an infiniband address don't bother 2203 * as we don't have a useful address to hash. 2204 */ 2205 if ((lease->hardware_addr.hlen == 1) && 2206 (lease->hardware_addr.hbuf[0] == HTYPE_INFINIBAND)) 2207 return; 2208 2209 /* If it's not in the hash, just add it. */ 2210 if (!find_lease_by_hw_addr (&head, lease -> hardware_addr.hbuf, 2211 lease -> hardware_addr.hlen, MDL)) 2212 lease_id_hash_add(lease_hw_addr_hash, 2213 lease->hardware_addr.hbuf, 2214 lease->hardware_addr.hlen, lease, MDL); 2215 else { 2216 /* Otherwise, insert it into the list in order of its 2217 * preference for "resuming allocation to the client." 2218 * 2219 * Because we don't have control of the hash bucket index 2220 * directly, we have to remove and re-insert the client 2221 * id into the hash if we're inserting onto the head. 2222 */ 2223 lease_reference(&cand, head, MDL); 2224 while (cand != NULL) { 2225 if (client_lease_preferred(cand, lease)) 2226 break; 2227 2228 if (prev != NULL) 2229 lease_dereference(&prev, MDL); 2230 lease_reference(&prev, cand, MDL); 2231 2232 if (cand->n_hw != NULL) 2233 lease_reference(&next, cand->n_hw, MDL); 2234 2235 lease_dereference(&cand, MDL); 2236 2237 if (next != NULL) { 2238 lease_reference(&cand, next, MDL); 2239 lease_dereference(&next, MDL); 2240 } 2241 } 2242 2243 /* If we want to insert 'before cand', and prev is NULL, 2244 * then it was the head of the list. Assume that position. 2245 */ 2246 if (prev == NULL) { 2247 lease_reference(&lease->n_hw, head, MDL); 2248 lease_id_hash_delete(lease_hw_addr_hash, 2249 lease->hardware_addr.hbuf, 2250 lease->hardware_addr.hlen, MDL); 2251 lease_id_hash_add(lease_hw_addr_hash, 2252 lease->hardware_addr.hbuf, 2253 lease->hardware_addr.hlen, 2254 lease, MDL); 2255 } else /* (prev != NULL) */ { 2256 if(prev->n_hw != NULL) { 2257 lease_reference(&lease->n_hw, prev->n_hw, 2258 MDL); 2259 lease_dereference(&prev->n_hw, MDL); 2260 } 2261 lease_reference(&prev->n_hw, lease, MDL); 2262 2263 lease_dereference(&prev, MDL); 2264 } 2265 2266 if (cand != NULL) 2267 lease_dereference(&cand, MDL); 2268 lease_dereference(&head, MDL); 2269 } 2270 } 2271 2272 /* Delete the specified lease from the hardware address hash. */ 2273 2274 void hw_hash_delete (lease) 2275 struct lease *lease; 2276 { 2277 struct lease *head = (struct lease *)0; 2278 struct lease *next = (struct lease *)0; 2279 2280 /* 2281 * If it's an infiniband address don't bother 2282 * as we don't have a useful address to hash. 2283 */ 2284 if ((lease->hardware_addr.hlen == 1) && 2285 (lease->hardware_addr.hbuf[0] == HTYPE_INFINIBAND)) 2286 return; 2287 2288 /* If it's not in the hash, we have no work to do. */ 2289 if (!find_lease_by_hw_addr (&head, lease -> hardware_addr.hbuf, 2290 lease -> hardware_addr.hlen, MDL)) { 2291 if (lease -> n_hw) 2292 lease_dereference (&lease -> n_hw, MDL); 2293 return; 2294 } 2295 2296 /* If the lease we're freeing is at the head of the list, 2297 remove the hash table entry and add a new one with the 2298 next lease on the list (if there is one). */ 2299 if (head == lease) { 2300 lease_id_hash_delete(lease_hw_addr_hash, 2301 lease->hardware_addr.hbuf, 2302 lease->hardware_addr.hlen, MDL); 2303 if (lease->n_hw) { 2304 lease_id_hash_add(lease_hw_addr_hash, 2305 lease->n_hw->hardware_addr.hbuf, 2306 lease->n_hw->hardware_addr.hlen, 2307 lease->n_hw, MDL); 2308 lease_dereference(&lease->n_hw, MDL); 2309 } 2310 } else { 2311 /* Otherwise, look for the lease in the list of leases 2312 attached to the hash table entry, and remove it if 2313 we find it. */ 2314 while (head -> n_hw) { 2315 if (head -> n_hw == lease) { 2316 lease_dereference (&head -> n_hw, MDL); 2317 if (lease -> n_hw) { 2318 lease_reference (&head -> n_hw, 2319 lease -> n_hw, MDL); 2320 lease_dereference (&lease -> n_hw, 2321 MDL); 2322 } 2323 break; 2324 } 2325 lease_reference (&next, head -> n_hw, MDL); 2326 lease_dereference (&head, MDL); 2327 lease_reference (&head, next, MDL); 2328 lease_dereference (&next, MDL); 2329 } 2330 } 2331 if (head) 2332 lease_dereference (&head, MDL); 2333 } 2334 2335 /* Write v4 leases to permanent storage. */ 2336 static int write_leases4(void) { 2337 struct lease *l; 2338 struct shared_network *s; 2339 struct pool *p; 2340 struct lease **lptr[RESERVED_LEASES+1]; 2341 int num_written = 0, i; 2342 2343 /* Write all the leases. */ 2344 for (s = shared_networks; s; s = s->next) { 2345 for (p = s->pools; p; p = p->next) { 2346 lptr[FREE_LEASES] = &p->free; 2347 lptr[ACTIVE_LEASES] = &p->active; 2348 lptr[EXPIRED_LEASES] = &p->expired; 2349 lptr[ABANDONED_LEASES] = &p->abandoned; 2350 lptr[BACKUP_LEASES] = &p->backup; 2351 lptr[RESERVED_LEASES] = &p->reserved; 2352 2353 for (i = FREE_LEASES; i <= RESERVED_LEASES; i++) { 2354 for (l = *(lptr[i]); l; l = l->next) { 2355 #if !defined (DEBUG_DUMP_ALL_LEASES) 2356 if (l->hardware_addr.hlen != 0 || l->uid_len != 0 || 2357 l->tsfp != 0 || l->binding_state != FTS_FREE) 2358 #endif 2359 { 2360 if (write_lease(l) == 0) 2361 return (0); 2362 num_written++; 2363 } 2364 } 2365 } 2366 } 2367 } 2368 2369 log_info ("Wrote %d leases to leases file.", num_written); 2370 return (1); 2371 } 2372 2373 /* Write all interesting leases to permanent storage. */ 2374 2375 int write_leases () 2376 { 2377 struct host_decl *hp; 2378 struct group_object *gp; 2379 struct hash_bucket *hb; 2380 struct class *cp; 2381 struct collection *colp; 2382 int i; 2383 int num_written; 2384 2385 /* write all the dynamically-created class declarations. */ 2386 if (collections->classes) { 2387 numclasseswritten = 0; 2388 for (colp = collections ; colp ; colp = colp->next) { 2389 for (cp = colp->classes ; cp ; cp = cp->nic) { 2390 write_named_billing_class( 2391 (unsigned char *)cp->name, 2392 0, cp); 2393 } 2394 } 2395 2396 /* XXXJAB this number doesn't include subclasses... */ 2397 log_info ("Wrote %d class decls to leases file.", 2398 numclasseswritten); 2399 } 2400 2401 2402 /* Write all the dynamically-created group declarations. */ 2403 if (group_name_hash) { 2404 num_written = 0; 2405 for (i = 0; i < group_name_hash -> hash_count; i++) { 2406 for (hb = group_name_hash -> buckets [i]; 2407 hb; hb = hb -> next) { 2408 gp = (struct group_object *)hb -> value; 2409 if ((gp -> flags & GROUP_OBJECT_DYNAMIC) || 2410 ((gp -> flags & GROUP_OBJECT_STATIC) && 2411 (gp -> flags & GROUP_OBJECT_DELETED))) { 2412 if (!write_group (gp)) 2413 return 0; 2414 ++num_written; 2415 } 2416 } 2417 } 2418 log_info ("Wrote %d group decls to leases file.", num_written); 2419 } 2420 2421 /* Write all the deleted host declarations. */ 2422 if (host_name_hash) { 2423 num_written = 0; 2424 for (i = 0; i < host_name_hash -> hash_count; i++) { 2425 for (hb = host_name_hash -> buckets [i]; 2426 hb; hb = hb -> next) { 2427 hp = (struct host_decl *)hb -> value; 2428 if (((hp -> flags & HOST_DECL_STATIC) && 2429 (hp -> flags & HOST_DECL_DELETED))) { 2430 if (!write_host (hp)) 2431 return 0; 2432 ++num_written; 2433 } 2434 } 2435 } 2436 log_info ("Wrote %d deleted host decls to leases file.", 2437 num_written); 2438 } 2439 2440 /* Write all the new, dynamic host declarations. */ 2441 if (host_name_hash) { 2442 num_written = 0; 2443 for (i = 0; i < host_name_hash -> hash_count; i++) { 2444 for (hb = host_name_hash -> buckets [i]; 2445 hb; hb = hb -> next) { 2446 hp = (struct host_decl *)hb -> value; 2447 if ((hp -> flags & HOST_DECL_DYNAMIC)) { 2448 if (!write_host (hp)) 2449 ++num_written; 2450 } 2451 } 2452 } 2453 log_info ("Wrote %d new dynamic host decls to leases file.", 2454 num_written); 2455 } 2456 2457 #if defined (FAILOVER_PROTOCOL) 2458 /* Write all the failover states. */ 2459 if (!dhcp_failover_write_all_states ()) 2460 return 0; 2461 #endif 2462 2463 switch (local_family) { 2464 case AF_INET: 2465 if (write_leases4() == 0) 2466 return (0); 2467 break; 2468 #ifdef DHCPv6 2469 case AF_INET6: 2470 if (write_leases6() == 0) 2471 return (0); 2472 break; 2473 #endif /* DHCPv6 */ 2474 } 2475 2476 if (commit_leases() == 0) 2477 return (0); 2478 return (1); 2479 } 2480 2481 /* In addition to placing this lease upon a lease queue depending on its 2482 * state, it also keeps track of the number of FREE and BACKUP leases in 2483 * existence, and sets the sort_time on the lease. 2484 * 2485 * Sort_time is used in pool_timer() to determine when the lease will 2486 * bubble to the top of the list and be supersede_lease()'d into its next 2487 * state (possibly, if all goes well). Example, ACTIVE leases move to 2488 * EXPIRED state when the 'ends' value is reached, so that is its sort 2489 * time. Most queues are sorted by 'ends', since it is generally best 2490 * practice to re-use the oldest lease, to reduce address collision 2491 * chances. 2492 */ 2493 int lease_enqueue (struct lease *comp) 2494 { 2495 struct lease **lq, *prev, *lp; 2496 static struct lease **last_lq = NULL; 2497 static struct lease *last_insert_point = NULL; 2498 2499 /* No queue to put it on? */ 2500 if (!comp -> pool) 2501 return 0; 2502 2503 /* Figure out which queue it's going to. */ 2504 switch (comp -> binding_state) { 2505 case FTS_FREE: 2506 if (comp->flags & RESERVED_LEASE) { 2507 lq = &comp->pool->reserved; 2508 } else { 2509 lq = &comp->pool->free; 2510 comp->pool->free_leases++; 2511 } 2512 comp -> sort_time = comp -> ends; 2513 break; 2514 2515 case FTS_ACTIVE: 2516 lq = &comp -> pool -> active; 2517 comp -> sort_time = comp -> ends; 2518 break; 2519 2520 case FTS_EXPIRED: 2521 case FTS_RELEASED: 2522 case FTS_RESET: 2523 lq = &comp -> pool -> expired; 2524 #if defined(FAILOVER_PROTOCOL) 2525 /* In partner_down, tsfp is the time at which the lease 2526 * may be reallocated (stos+mclt). We can do that with 2527 * lease_mine_to_reallocate() anywhere between tsfp and 2528 * ends. But we prefer to wait until ends before doing it 2529 * automatically (choose the greater of the two). Note 2530 * that 'ends' is usually a historic timestamp in the 2531 * case of expired leases, is really only in the future 2532 * on released leases, and if we know a lease to be released 2533 * the peer might still know it to be active...in which case 2534 * it's possible the peer has renewed this lease, so avoid 2535 * doing that. 2536 */ 2537 if (comp->pool->failover_peer && 2538 comp->pool->failover_peer->me.state == partner_down) 2539 comp->sort_time = (comp->tsfp > comp->ends) ? 2540 comp->tsfp : comp->ends; 2541 else 2542 #endif 2543 comp->sort_time = comp->ends; 2544 2545 break; 2546 2547 case FTS_ABANDONED: 2548 lq = &comp -> pool -> abandoned; 2549 comp -> sort_time = comp -> ends; 2550 break; 2551 2552 case FTS_BACKUP: 2553 if (comp->flags & RESERVED_LEASE) { 2554 lq = &comp->pool->reserved; 2555 } else { 2556 lq = &comp->pool->backup; 2557 comp->pool->backup_leases++; 2558 } 2559 comp -> sort_time = comp -> ends; 2560 break; 2561 2562 default: 2563 log_error ("Lease with bogus binding state: %d", 2564 comp -> binding_state); 2565 #if defined (BINDING_STATE_DEBUG) 2566 abort (); 2567 #endif 2568 return 0; 2569 } 2570 2571 /* This only works during server startup: during runtime, the last 2572 * lease may be dequeued in between calls. If the queue is the same 2573 * as was used previously, and the lease structure isn't (this is not 2574 * a re-queue), use that as a starting point for the insertion-sort. 2575 */ 2576 if ((server_starting & SS_QFOLLOW) && (lq == last_lq) && 2577 (comp != last_insert_point) && 2578 (last_insert_point->sort_time <= comp->sort_time)) { 2579 prev = last_insert_point; 2580 lp = prev->next; 2581 } else { 2582 prev = NULL; 2583 lp = *lq; 2584 } 2585 2586 /* Insertion sort the lease onto the appropriate queue. */ 2587 for (; lp ; lp = lp->next) { 2588 if (lp -> sort_time >= comp -> sort_time) 2589 break; 2590 prev = lp; 2591 } 2592 2593 if (prev) { 2594 if (prev -> next) { 2595 lease_reference (&comp -> next, prev -> next, MDL); 2596 lease_dereference (&prev -> next, MDL); 2597 } 2598 lease_reference (&prev -> next, comp, MDL); 2599 } else { 2600 if (*lq) { 2601 lease_reference (&comp -> next, *lq, MDL); 2602 lease_dereference (lq, MDL); 2603 } 2604 lease_reference (lq, comp, MDL); 2605 } 2606 last_insert_point = comp; 2607 last_lq = lq; 2608 return 1; 2609 } 2610 2611 /* For a given lease, sort it onto the right list in its pool and put it 2612 in each appropriate hash, understanding that it's already by definition 2613 in lease_ip_addr_hash. */ 2614 2615 isc_result_t 2616 lease_instantiate(const void *key, unsigned len, void *object) 2617 { 2618 struct lease *lease = object; 2619 struct class *class; 2620 /* XXX If the lease doesn't have a pool at this point, it's an 2621 XXX orphan, which we *should* keep around until it expires, 2622 XXX but which right now we just forget. */ 2623 if (!lease -> pool) { 2624 lease_ip_hash_delete(lease_ip_addr_hash, lease->ip_addr.iabuf, 2625 lease->ip_addr.len, MDL); 2626 return ISC_R_SUCCESS; 2627 } 2628 2629 /* Put the lease on the right queue. Failure to queue is probably 2630 * due to a bogus binding state. In such a case, we claim success, 2631 * so that later leases in a hash_foreach are processed, but we 2632 * return early as we really don't want hw address hash entries or 2633 * other cruft to surround such a bogus entry. 2634 */ 2635 if (!lease_enqueue(lease)) 2636 return ISC_R_SUCCESS; 2637 2638 /* Record the lease in the uid hash if possible. */ 2639 if (lease -> uid) { 2640 uid_hash_add (lease); 2641 } 2642 2643 /* Record it in the hardware address hash if possible. */ 2644 if (lease -> hardware_addr.hlen) { 2645 hw_hash_add (lease); 2646 } 2647 2648 /* If the lease has a billing class, set up the billing. */ 2649 if (lease -> billing_class) { 2650 class = (struct class *)0; 2651 class_reference (&class, lease -> billing_class, MDL); 2652 class_dereference (&lease -> billing_class, MDL); 2653 /* If the lease is available for allocation, the billing 2654 is invalid, so we don't keep it. */ 2655 if (lease -> binding_state == FTS_ACTIVE || 2656 lease -> binding_state == FTS_EXPIRED || 2657 lease -> binding_state == FTS_RELEASED || 2658 lease -> binding_state == FTS_RESET) 2659 bill_class (lease, class); 2660 class_dereference (&class, MDL); 2661 } 2662 return ISC_R_SUCCESS; 2663 } 2664 2665 /* Run expiry events on every pool. This is called on startup so that 2666 any expiry events that occurred after the server stopped and before it 2667 was restarted can be run. At the same time, if failover support is 2668 compiled in, we compute the balance of leases for the pool. */ 2669 2670 void expire_all_pools () 2671 { 2672 struct shared_network *s; 2673 struct pool *p; 2674 int i; 2675 struct lease *l; 2676 struct lease **lptr[RESERVED_LEASES+1]; 2677 2678 /* Indicate that we are in the startup phase */ 2679 server_starting = SS_NOSYNC | SS_QFOLLOW; 2680 2681 /* First, go over the hash list and actually put all the leases 2682 on the appropriate lists. */ 2683 lease_ip_hash_foreach(lease_ip_addr_hash, lease_instantiate); 2684 2685 /* Loop through each pool in each shared network and call the 2686 * expiry routine on the pool. It is no longer safe to follow 2687 * the queue insertion point, as expiration of a lease can move 2688 * it between queues (and this may be the lease that function 2689 * points at). 2690 */ 2691 server_starting &= ~SS_QFOLLOW; 2692 for (s = shared_networks; s; s = s -> next) { 2693 for (p = s -> pools; p; p = p -> next) { 2694 pool_timer (p); 2695 2696 p -> lease_count = 0; 2697 p -> free_leases = 0; 2698 p -> backup_leases = 0; 2699 2700 lptr [FREE_LEASES] = &p -> free; 2701 lptr [ACTIVE_LEASES] = &p -> active; 2702 lptr [EXPIRED_LEASES] = &p -> expired; 2703 lptr [ABANDONED_LEASES] = &p -> abandoned; 2704 lptr [BACKUP_LEASES] = &p -> backup; 2705 lptr [RESERVED_LEASES] = &p->reserved; 2706 2707 for (i = FREE_LEASES; i <= RESERVED_LEASES; i++) { 2708 for (l = *(lptr [i]); l; l = l -> next) { 2709 p -> lease_count++; 2710 if (l -> ends <= cur_time) { 2711 if (l->binding_state == FTS_FREE) { 2712 if (i == FREE_LEASES) 2713 p->free_leases++; 2714 else if (i != RESERVED_LEASES) 2715 log_fatal("Impossible case " 2716 "at %s:%d.", MDL); 2717 } else if (l->binding_state == FTS_BACKUP) { 2718 if (i == BACKUP_LEASES) 2719 p->backup_leases++; 2720 else if (i != RESERVED_LEASES) 2721 log_fatal("Impossible case " 2722 "at %s:%d.", MDL); 2723 } 2724 } 2725 #if defined (FAILOVER_PROTOCOL) 2726 if (p -> failover_peer && 2727 l -> tstp > l -> atsfp && 2728 !(l -> flags & ON_UPDATE_QUEUE)) { 2729 l -> desired_binding_state = l -> binding_state; 2730 dhcp_failover_queue_update (l, 1); 2731 } 2732 #endif 2733 } 2734 } 2735 } 2736 } 2737 2738 /* turn off startup phase */ 2739 server_starting = 0; 2740 } 2741 2742 void dump_subnets () 2743 { 2744 struct lease *l; 2745 struct shared_network *s; 2746 struct subnet *n; 2747 struct pool *p; 2748 struct lease **lptr[RESERVED_LEASES+1]; 2749 int i; 2750 2751 log_info ("Subnets:"); 2752 for (n = subnets; n; n = n -> next_subnet) { 2753 log_debug (" Subnet %s", piaddr (n -> net)); 2754 log_debug (" netmask %s", 2755 piaddr (n -> netmask)); 2756 } 2757 log_info ("Shared networks:"); 2758 for (s = shared_networks; s; s = s -> next) { 2759 log_info (" %s", s -> name); 2760 for (p = s -> pools; p; p = p -> next) { 2761 lptr [FREE_LEASES] = &p -> free; 2762 lptr [ACTIVE_LEASES] = &p -> active; 2763 lptr [EXPIRED_LEASES] = &p -> expired; 2764 lptr [ABANDONED_LEASES] = &p -> abandoned; 2765 lptr [BACKUP_LEASES] = &p -> backup; 2766 lptr [RESERVED_LEASES] = &p->reserved; 2767 2768 for (i = FREE_LEASES; i <= RESERVED_LEASES; i++) { 2769 for (l = *(lptr [i]); l; l = l -> next) { 2770 print_lease (l); 2771 } 2772 } 2773 } 2774 } 2775 } 2776 2777 HASH_FUNCTIONS(lease_ip, const unsigned char *, struct lease, lease_ip_hash_t, 2778 lease_reference, lease_dereference, do_ip4_hash) 2779 HASH_FUNCTIONS(lease_id, const unsigned char *, struct lease, lease_id_hash_t, 2780 lease_reference, lease_dereference, do_id_hash) 2781 HASH_FUNCTIONS (host, const unsigned char *, struct host_decl, host_hash_t, 2782 host_reference, host_dereference, do_string_hash) 2783 HASH_FUNCTIONS (class, const char *, struct class, class_hash_t, 2784 class_reference, class_dereference, do_string_hash) 2785 2786 #if defined (DEBUG_MEMORY_LEAKAGE) && \ 2787 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) 2788 extern struct hash_table *dns_zone_hash; 2789 extern struct interface_info **interface_vector; 2790 extern int interface_count; 2791 dhcp_control_object_t *dhcp_control_object; 2792 extern struct hash_table *auth_key_hash; 2793 struct hash_table *universe_hash; 2794 struct universe **universes; 2795 int universe_count, universe_max; 2796 #if 0 2797 extern int end; 2798 #endif 2799 2800 #if defined (COMPACT_LEASES) 2801 extern struct lease *lease_hunks; 2802 #endif 2803 2804 void free_everything(void) 2805 { 2806 struct subnet *sc = (struct subnet *)0, *sn = (struct subnet *)0; 2807 struct shared_network *nc = (struct shared_network *)0, 2808 *nn = (struct shared_network *)0; 2809 struct pool *pc = (struct pool *)0, *pn = (struct pool *)0; 2810 struct lease *lc = (struct lease *)0, *ln = (struct lease *)0; 2811 struct interface_info *ic = (struct interface_info *)0, 2812 *in = (struct interface_info *)0; 2813 struct class *cc = (struct class *)0, *cn = (struct class *)0; 2814 struct collection *lp; 2815 int i; 2816 2817 /* Get rid of all the hash tables. */ 2818 if (host_hw_addr_hash) 2819 host_free_hash_table (&host_hw_addr_hash, MDL); 2820 host_hw_addr_hash = 0; 2821 if (host_uid_hash) 2822 host_free_hash_table (&host_uid_hash, MDL); 2823 host_uid_hash = 0; 2824 if (lease_uid_hash) 2825 lease_id_free_hash_table (&lease_uid_hash, MDL); 2826 lease_uid_hash = 0; 2827 if (lease_ip_addr_hash) 2828 lease_ip_free_hash_table (&lease_ip_addr_hash, MDL); 2829 lease_ip_addr_hash = 0; 2830 if (lease_hw_addr_hash) 2831 lease_id_free_hash_table (&lease_hw_addr_hash, MDL); 2832 lease_hw_addr_hash = 0; 2833 if (host_name_hash) 2834 host_free_hash_table (&host_name_hash, MDL); 2835 host_name_hash = 0; 2836 if (dns_zone_hash) 2837 dns_zone_free_hash_table (&dns_zone_hash, MDL); 2838 dns_zone_hash = 0; 2839 2840 while (host_id_info != NULL) { 2841 host_id_info_t *tmp; 2842 option_dereference(&host_id_info->option, MDL); 2843 host_free_hash_table(&host_id_info->values_hash, MDL); 2844 tmp = host_id_info->next; 2845 dfree(host_id_info, MDL); 2846 host_id_info = tmp; 2847 } 2848 #if 0 2849 if (auth_key_hash) 2850 auth_key_free_hash_table (&auth_key_hash, MDL); 2851 #endif 2852 auth_key_hash = 0; 2853 2854 omapi_object_dereference ((omapi_object_t **)&dhcp_control_object, 2855 MDL); 2856 2857 for (lp = collections; lp; lp = lp -> next) { 2858 if (lp -> classes) { 2859 class_reference (&cn, lp -> classes, MDL); 2860 do { 2861 if (cn) { 2862 class_reference (&cc, cn, MDL); 2863 class_dereference (&cn, MDL); 2864 } 2865 if (cc -> nic) { 2866 class_reference (&cn, cc -> nic, MDL); 2867 class_dereference (&cc -> nic, MDL); 2868 } 2869 group_dereference (&cc -> group, MDL); 2870 if (cc -> hash) { 2871 class_free_hash_table (&cc -> hash, MDL); 2872 cc -> hash = (struct hash_table *)0; 2873 } 2874 class_dereference (&cc, MDL); 2875 } while (cn); 2876 class_dereference (&lp -> classes, MDL); 2877 } 2878 } 2879 2880 if (interface_vector) { 2881 for (i = 0; i < interface_count; i++) { 2882 if (interface_vector [i]) 2883 interface_dereference (&interface_vector [i], MDL); 2884 } 2885 dfree (interface_vector, MDL); 2886 interface_vector = 0; 2887 } 2888 2889 if (interfaces) { 2890 interface_reference (&in, interfaces, MDL); 2891 do { 2892 if (in) { 2893 interface_reference (&ic, in, MDL); 2894 interface_dereference (&in, MDL); 2895 } 2896 if (ic -> next) { 2897 interface_reference (&in, ic -> next, MDL); 2898 interface_dereference (&ic -> next, MDL); 2899 } 2900 omapi_unregister_io_object ((omapi_object_t *)ic); 2901 if (ic -> shared_network) { 2902 if (ic -> shared_network -> interface) 2903 interface_dereference 2904 (&ic -> shared_network -> interface, MDL); 2905 shared_network_dereference (&ic -> shared_network, MDL); 2906 } 2907 interface_dereference (&ic, MDL); 2908 } while (in); 2909 interface_dereference (&interfaces, MDL); 2910 } 2911 2912 /* Subnets are complicated because of the extra links. */ 2913 if (subnets) { 2914 subnet_reference (&sn, subnets, MDL); 2915 do { 2916 if (sn) { 2917 subnet_reference (&sc, sn, MDL); 2918 subnet_dereference (&sn, MDL); 2919 } 2920 if (sc -> next_subnet) { 2921 subnet_reference (&sn, sc -> next_subnet, MDL); 2922 subnet_dereference (&sc -> next_subnet, MDL); 2923 } 2924 if (sc -> next_sibling) 2925 subnet_dereference (&sc -> next_sibling, MDL); 2926 if (sc -> shared_network) 2927 shared_network_dereference (&sc -> shared_network, MDL); 2928 group_dereference (&sc -> group, MDL); 2929 if (sc -> interface) 2930 interface_dereference (&sc -> interface, MDL); 2931 subnet_dereference (&sc, MDL); 2932 } while (sn); 2933 subnet_dereference (&subnets, MDL); 2934 } 2935 2936 /* So are shared networks. */ 2937 /* XXX: this doesn't work presently, but i'm ok just filtering 2938 * it out of the noise (you get a bigger spike on the real leaks). 2939 * It would be good to fix this, but it is not a "real bug," so not 2940 * today. This hack is incomplete, it doesn't trim out sub-values. 2941 */ 2942 if (shared_networks) { 2943 shared_network_dereference (&shared_networks, MDL); 2944 /* This is the old method (tries to free memory twice, broken) */ 2945 } else if (0) { 2946 shared_network_reference (&nn, shared_networks, MDL); 2947 do { 2948 if (nn) { 2949 shared_network_reference (&nc, nn, MDL); 2950 shared_network_dereference (&nn, MDL); 2951 } 2952 if (nc -> next) { 2953 shared_network_reference (&nn, nc -> next, MDL); 2954 shared_network_dereference (&nc -> next, MDL); 2955 } 2956 2957 /* As are pools. */ 2958 if (nc -> pools) { 2959 pool_reference (&pn, nc -> pools, MDL); 2960 do { 2961 struct lease **lptr[RESERVED_LEASES+1]; 2962 2963 if (pn) { 2964 pool_reference (&pc, pn, MDL); 2965 pool_dereference (&pn, MDL); 2966 } 2967 if (pc -> next) { 2968 pool_reference (&pn, pc -> next, MDL); 2969 pool_dereference (&pc -> next, MDL); 2970 } 2971 2972 lptr [FREE_LEASES] = &pc -> free; 2973 lptr [ACTIVE_LEASES] = &pc -> active; 2974 lptr [EXPIRED_LEASES] = &pc -> expired; 2975 lptr [ABANDONED_LEASES] = &pc -> abandoned; 2976 lptr [BACKUP_LEASES] = &pc -> backup; 2977 lptr [RESERVED_LEASES] = &pc->reserved; 2978 2979 /* As (sigh) are leases. */ 2980 for (i = FREE_LEASES ; i <= RESERVED_LEASES ; i++) { 2981 if (*lptr [i]) { 2982 lease_reference (&ln, *lptr [i], MDL); 2983 do { 2984 if (ln) { 2985 lease_reference (&lc, ln, MDL); 2986 lease_dereference (&ln, MDL); 2987 } 2988 if (lc -> next) { 2989 lease_reference (&ln, lc -> next, MDL); 2990 lease_dereference (&lc -> next, MDL); 2991 } 2992 if (lc -> billing_class) 2993 class_dereference (&lc -> billing_class, 2994 MDL); 2995 if (lc -> state) 2996 free_lease_state (lc -> state, MDL); 2997 lc -> state = (struct lease_state *)0; 2998 if (lc -> n_hw) 2999 lease_dereference (&lc -> n_hw, MDL); 3000 if (lc -> n_uid) 3001 lease_dereference (&lc -> n_uid, MDL); 3002 lease_dereference (&lc, MDL); 3003 } while (ln); 3004 lease_dereference (lptr [i], MDL); 3005 } 3006 } 3007 if (pc -> group) 3008 group_dereference (&pc -> group, MDL); 3009 if (pc -> shared_network) 3010 shared_network_dereference (&pc -> shared_network, 3011 MDL); 3012 pool_dereference (&pc, MDL); 3013 } while (pn); 3014 pool_dereference (&nc -> pools, MDL); 3015 } 3016 /* Because of a circular reference, we need to nuke this 3017 manually. */ 3018 group_dereference (&nc -> group, MDL); 3019 shared_network_dereference (&nc, MDL); 3020 } while (nn); 3021 shared_network_dereference (&shared_networks, MDL); 3022 } 3023 3024 cancel_all_timeouts (); 3025 relinquish_timeouts (); 3026 relinquish_ackqueue(); 3027 trace_free_all (); 3028 group_dereference (&root_group, MDL); 3029 executable_statement_dereference (&default_classification_rules, MDL); 3030 3031 shutdown_state = shutdown_drop_omapi_connections; 3032 omapi_io_state_foreach (dhcp_io_shutdown, 0); 3033 shutdown_state = shutdown_listeners; 3034 omapi_io_state_foreach (dhcp_io_shutdown, 0); 3035 shutdown_state = shutdown_dhcp; 3036 omapi_io_state_foreach (dhcp_io_shutdown, 0); 3037 3038 omapi_object_dereference ((omapi_object_t **)&icmp_state, MDL); 3039 3040 universe_free_hash_table (&universe_hash, MDL); 3041 for (i = 0; i < universe_count; i++) { 3042 #if 0 3043 union { 3044 const char *c; 3045 char *s; 3046 } foo; 3047 #endif 3048 if (universes [i]) { 3049 if (universes[i]->name_hash) 3050 option_name_free_hash_table( 3051 &universes[i]->name_hash, 3052 MDL); 3053 if (universes[i]->code_hash) 3054 option_code_free_hash_table( 3055 &universes[i]->code_hash, 3056 MDL); 3057 #if 0 3058 if (universes [i] -> name > (char *)&end) { 3059 foo.c = universes [i] -> name; 3060 dfree (foo.s, MDL); 3061 } 3062 if (universes [i] > (struct universe *)&end) 3063 dfree (universes [i], MDL); 3064 #endif 3065 } 3066 } 3067 dfree (universes, MDL); 3068 3069 relinquish_free_lease_states (); 3070 relinquish_free_pairs (); 3071 relinquish_free_expressions (); 3072 relinquish_free_binding_values (); 3073 relinquish_free_option_caches (); 3074 relinquish_free_packets (); 3075 #if defined(COMPACT_LEASES) 3076 relinquish_lease_hunks (); 3077 #endif 3078 relinquish_hash_bucket_hunks (); 3079 omapi_type_relinquish (); 3080 } 3081 #endif /* DEBUG_MEMORY_LEAKAGE_ON_EXIT */ 3082