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