00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "dhcpd.h"
00031 #include "omapip/hash.h"
00032
00033 struct subnet *subnets;
00034 struct shared_network *shared_networks;
00035 host_hash_t *host_hw_addr_hash;
00036 host_hash_t *host_uid_hash;
00037 host_hash_t *host_name_hash;
00038 lease_id_hash_t *lease_uid_hash;
00039 lease_ip_hash_t *lease_ip_addr_hash;
00040 lease_id_hash_t *lease_hw_addr_hash;
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 typedef struct host_id_info {
00061 struct option *option;
00062 host_hash_t *values_hash;
00063 int relays;
00064 struct host_id_info *next;
00065 } host_id_info_t;
00066
00067 static host_id_info_t *host_id_info = NULL;
00068
00069 int numclasseswritten;
00070
00071 omapi_object_type_t *dhcp_type_host;
00072
00073 isc_result_t enter_class(cd, dynamicp, commit)
00074 struct class *cd;
00075 int dynamicp;
00076 int commit;
00077 {
00078 if (!collections -> classes) {
00079
00080 if (cd->name == NULL)
00081 return DHCP_R_INVALIDARG;
00082
00083 class_reference (&collections -> classes, cd, MDL);
00084 } else if (cd->name != NULL) {
00085 struct class *c = 0;
00086
00087 if (find_class(&c, cd->name, MDL) != ISC_R_NOTFOUND) {
00088 class_dereference(&c, MDL);
00089 return ISC_R_EXISTS;
00090 }
00091
00092
00093 for (c = collections -> classes;
00094 c -> nic; c = c -> nic)
00095 ;
00096 class_reference (&c -> nic, cd, MDL);
00097 }
00098
00099 if (dynamicp && commit) {
00100 const char *name = cd->name;
00101
00102 if (name == NULL) {
00103 name = cd->superclass->name;
00104 }
00105
00106 write_named_billing_class ((const unsigned char *)name, 0, cd);
00107 if (!commit_leases ())
00108 return ISC_R_IOERROR;
00109 }
00110
00111 return ISC_R_SUCCESS;
00112 }
00113
00114
00115
00116
00117
00118
00119
00120 #define SS_NOSYNC 1
00121 #define SS_QFOLLOW 2
00122 static int server_starting = 0;
00123
00124 static int find_uid_statement (struct executable_statement *esp,
00125 void *vp, int condp)
00126 {
00127 struct executable_statement **evp = vp;
00128
00129 if (esp -> op == supersede_option_statement &&
00130 esp -> data.option &&
00131 (esp -> data.option -> option -> universe ==
00132 &dhcp_universe) &&
00133 (esp -> data.option -> option -> code ==
00134 DHO_DHCP_CLIENT_IDENTIFIER)) {
00135 if (condp) {
00136 log_error ("dhcp client identifier may not be %s",
00137 "specified conditionally.");
00138 } else if (!(*evp)) {
00139 executable_statement_reference (evp, esp, MDL);
00140 return 1;
00141 } else {
00142 log_error ("only one dhcp client identifier may be %s",
00143 "specified");
00144 }
00145 }
00146 return 0;
00147 }
00148
00149
00150 static host_id_info_t *
00151 find_host_id_info(unsigned int option_code, int relays) {
00152 host_id_info_t *p;
00153
00154 for (p = host_id_info; p != NULL; p = p->next) {
00155 if ((p->option->code == option_code) &&
00156 (p->relays == relays)) {
00157 break;
00158 }
00159 }
00160 return p;
00161 }
00162
00163
00164 #if 0
00165 isc_result_t
00166 print_host(const void *name, unsigned len, void *value) {
00167 struct host_decl *h;
00168 printf("--------------\n");
00169 printf("name:'%s'\n", print_hex_1(len, name, 60));
00170 printf("len:%d\n", len);
00171 h = (struct host_decl *)value;
00172 printf("host @%p is '%s'\n", h, h->name);
00173 return ISC_R_SUCCESS;
00174 }
00175
00176 void
00177 hash_print_hosts(struct hash_table *h) {
00178 hash_foreach(h, print_host);
00179 printf("--------------\n");
00180 }
00181 #endif
00182
00183 void
00184 change_host_uid(struct host_decl *host, const char *uid, int len) {
00185
00186 if (host_uid_hash == NULL) {
00187 if (!host_new_hash(&host_uid_hash, HOST_HASH_SIZE, MDL)) {
00188 log_fatal("Can't allocate host/uid hash");
00189 }
00190 }
00191
00192
00193
00194
00195 if (host->client_identifier.data != NULL) {
00196 host_hash_delete(host_uid_hash,
00197 host->client_identifier.data,
00198 host->client_identifier.len,
00199 MDL);
00200 data_string_forget(&host->client_identifier, MDL);
00201 }
00202
00203
00204
00205
00206 memset(&host->client_identifier, 0, sizeof(host->client_identifier));
00207 host->client_identifier.len = len;
00208 if (!buffer_allocate(&host->client_identifier.buffer, len, MDL)) {
00209 log_fatal("Can't allocate uid buffer");
00210 }
00211 host->client_identifier.data = host->client_identifier.buffer->data;
00212 memcpy((char *)host->client_identifier.data, uid, len);
00213
00214
00215
00216
00217 host_hash_add(host_uid_hash, host->client_identifier.data,
00218 host->client_identifier.len, host, MDL);
00219 }
00220
00221 isc_result_t enter_host (hd, dynamicp, commit)
00222 struct host_decl *hd;
00223 int dynamicp;
00224 int commit;
00225 {
00226 struct host_decl *hp = (struct host_decl *)0;
00227 struct host_decl *np = (struct host_decl *)0;
00228 struct executable_statement *esp;
00229 host_id_info_t *h_id_info;
00230
00231 if (!host_name_hash) {
00232 if (!host_new_hash(&host_name_hash, HOST_HASH_SIZE, MDL))
00233 log_fatal ("Can't allocate host name hash");
00234 host_hash_add (host_name_hash,
00235 (unsigned char *)hd -> name,
00236 strlen (hd -> name), hd, MDL);
00237 } else {
00238 host_hash_lookup (&hp, host_name_hash,
00239 (unsigned char *)hd -> name,
00240 strlen (hd -> name), MDL);
00241
00242
00243 if (hp && (hp -> flags & HOST_DECL_DELETED)) {
00244 host_hash_delete (host_name_hash,
00245 (unsigned char *)hd -> name,
00246 strlen (hd -> name), MDL);
00247
00248
00249 if (hp -> flags & HOST_DECL_STATIC) {
00250 hd -> flags |= HOST_DECL_STATIC;
00251 }
00252 host_dereference (&hp, MDL);
00253 }
00254
00255
00256
00257 if (hp && hp == hd) {
00258 host_dereference (&hp, MDL);
00259 delete_host (hd, 0);
00260 if (!write_host (hd))
00261 return ISC_R_IOERROR;
00262 hd -> flags &= ~HOST_DECL_DELETED;
00263 }
00264
00265
00266
00267 if (!hp) {
00268 host_hash_add (host_name_hash,
00269 (unsigned char *)hd -> name,
00270 strlen (hd -> name), hd, MDL);
00271 } else {
00272
00273
00274 host_dereference (&hp, MDL);
00275 return ISC_R_EXISTS;
00276 }
00277 }
00278
00279 if (hd -> n_ipaddr)
00280 host_dereference (&hd -> n_ipaddr, MDL);
00281
00282 if (!hd -> type)
00283 hd -> type = dhcp_type_host;
00284
00285 if (hd -> interface.hlen) {
00286 if (!host_hw_addr_hash) {
00287 if (!host_new_hash(&host_hw_addr_hash,
00288 HOST_HASH_SIZE, MDL))
00289 log_fatal ("Can't allocate host/hw hash");
00290 } else {
00291
00292
00293 host_hash_lookup (&hp, host_hw_addr_hash,
00294 hd -> interface.hbuf,
00295 hd -> interface.hlen, MDL);
00296 }
00297 if (!hp)
00298 host_hash_add (host_hw_addr_hash, hd -> interface.hbuf,
00299 hd -> interface.hlen, hd, MDL);
00300 else {
00301
00302
00303
00304 for (np = hp; np -> n_ipaddr; np = np -> n_ipaddr)
00305 ;
00306 host_reference (&np -> n_ipaddr, hd, MDL);
00307 host_dereference (&hp, MDL);
00308 }
00309 }
00310
00311
00312
00313
00314 esp = NULL;
00315 if (executable_statement_foreach (hd->group->statements,
00316 find_uid_statement, &esp, 0)) {
00317 (void) evaluate_option_cache (&hd->client_identifier,
00318 NULL, NULL, NULL, NULL, NULL,
00319 &global_scope,
00320 esp->data.option, MDL);
00321 }
00322
00323
00324
00325 if (hd -> client_identifier.len) {
00326
00327
00328 if (!host_uid_hash) {
00329 if (!host_new_hash(&host_uid_hash,
00330 HOST_HASH_SIZE, MDL))
00331 log_fatal ("Can't allocate host/uid hash");
00332
00333 host_hash_add (host_uid_hash,
00334 hd -> client_identifier.data,
00335 hd -> client_identifier.len,
00336 hd, MDL);
00337 } else {
00338
00339
00340
00341 if (host_hash_lookup (&hp, host_uid_hash,
00342 hd -> client_identifier.data,
00343 hd -> client_identifier.len,
00344 MDL)) {
00345
00346 if (!np) {
00347 for (np = hp; np -> n_ipaddr;
00348 np = np -> n_ipaddr) {
00349 if (hd == np)
00350 break;
00351 }
00352 if (hd != np)
00353 host_reference (&np -> n_ipaddr,
00354 hd, MDL);
00355 }
00356 host_dereference (&hp, MDL);
00357 } else {
00358 host_hash_add (host_uid_hash,
00359 hd -> client_identifier.data,
00360 hd -> client_identifier.len,
00361 hd, MDL);
00362 }
00363 }
00364 }
00365
00366
00367
00368
00369
00370 if (hd->host_id_option != NULL) {
00371
00372
00373
00374
00375 h_id_info = find_host_id_info(hd->host_id_option->code,
00376 hd->relays);
00377 if (h_id_info == NULL) {
00378 h_id_info = dmalloc(sizeof(*h_id_info), MDL);
00379 if (h_id_info == NULL) {
00380 log_fatal("No memory for host-identifier "
00381 "option information.");
00382 }
00383 option_reference(&h_id_info->option,
00384 hd->host_id_option, MDL);
00385 if (!host_new_hash(&h_id_info->values_hash,
00386 HOST_HASH_SIZE, MDL)) {
00387 log_fatal("No memory for host-identifier "
00388 "option hash.");
00389 }
00390 h_id_info->relays = hd->relays;
00391 h_id_info->next = host_id_info;
00392 host_id_info = h_id_info;
00393 }
00394
00395 if (host_hash_lookup(&hp, h_id_info->values_hash,
00396 hd->host_id.data, hd->host_id.len, MDL)) {
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407 if (np == NULL) {
00408 np = hp;
00409 while (np->n_ipaddr != NULL) {
00410 np = np->n_ipaddr;
00411 }
00412 if (hd != np) {
00413 host_reference(&np->n_ipaddr, hd, MDL);
00414 }
00415 }
00416 host_dereference(&hp, MDL);
00417 } else {
00418 host_hash_add(h_id_info->values_hash,
00419 hd->host_id.data,
00420 hd->host_id.len,
00421 hd, MDL);
00422 }
00423 }
00424
00425 if (dynamicp && commit) {
00426 if (!write_host (hd))
00427 return ISC_R_IOERROR;
00428 if (!commit_leases ())
00429 return ISC_R_IOERROR;
00430 }
00431
00432 return ISC_R_SUCCESS;
00433 }
00434
00435
00436 isc_result_t delete_class (cp, commit)
00437 struct class *cp;
00438 int commit;
00439 {
00440 cp->flags |= CLASS_DECL_DELETED;
00441
00442
00443
00444
00445 if (commit) {
00446 write_named_billing_class ((unsigned char *)cp->name, 0, cp);
00447 if (!commit_leases ())
00448 return ISC_R_IOERROR;
00449 }
00450
00451
00452
00453
00454 if (cp->superclass) {
00455 class_hash_delete(cp->superclass->hash,
00456 (const char *)cp->hash_string.data,
00457 cp->hash_string.len,
00458 MDL);
00459 }
00460
00461
00462 unlink_class(&cp);
00463
00464 return ISC_R_SUCCESS;
00465 }
00466
00467
00468 isc_result_t delete_host (hd, commit)
00469 struct host_decl *hd;
00470 int commit;
00471 {
00472 struct host_decl *hp = (struct host_decl *)0;
00473 struct host_decl *np = (struct host_decl *)0;
00474 struct host_decl *foo;
00475 int hw_head = 0, uid_head = 1;
00476
00477
00478 if (hd -> flags & HOST_DECL_DELETED)
00479 return ISC_R_SUCCESS;
00480
00481
00482 hd -> flags |= HOST_DECL_DELETED;
00483
00484 if (hd -> interface.hlen) {
00485 if (host_hw_addr_hash) {
00486 if (host_hash_lookup (&hp, host_hw_addr_hash,
00487 hd -> interface.hbuf,
00488 hd -> interface.hlen, MDL)) {
00489 if (hp == hd) {
00490 host_hash_delete (host_hw_addr_hash,
00491 hd -> interface.hbuf,
00492 hd -> interface.hlen, MDL);
00493 hw_head = 1;
00494 } else {
00495 np = (struct host_decl *)0;
00496 foo = (struct host_decl *)0;
00497 host_reference (&foo, hp, MDL);
00498 while (foo) {
00499 if (foo == hd)
00500 break;
00501 if (np)
00502 host_dereference (&np, MDL);
00503 host_reference (&np, foo, MDL);
00504 host_dereference (&foo, MDL);
00505 if (np -> n_ipaddr)
00506 host_reference (&foo, np -> n_ipaddr, MDL);
00507 }
00508
00509 if (foo) {
00510 host_dereference (&np -> n_ipaddr, MDL);
00511 if (hd -> n_ipaddr)
00512 host_reference (&np -> n_ipaddr,
00513 hd -> n_ipaddr, MDL);
00514 host_dereference (&foo, MDL);
00515 }
00516 if (np)
00517 host_dereference (&np, MDL);
00518 }
00519 host_dereference (&hp, MDL);
00520 }
00521 }
00522 }
00523
00524
00525
00526 if (hd -> client_identifier.len) {
00527 if (host_uid_hash) {
00528 if (host_hash_lookup (&hp, host_uid_hash,
00529 hd -> client_identifier.data,
00530 hd -> client_identifier.len, MDL)) {
00531 if (hp == hd) {
00532 host_hash_delete (host_uid_hash,
00533 hd -> client_identifier.data,
00534 hd -> client_identifier.len, MDL);
00535 uid_head = 1;
00536 } else {
00537 np = (struct host_decl *)0;
00538 foo = (struct host_decl *)0;
00539 host_reference (&foo, hp, MDL);
00540 while (foo) {
00541 if (foo == hd)
00542 break;
00543 if (np)
00544 host_dereference (&np, MDL);
00545 host_reference (&np, foo, MDL);
00546 host_dereference (&foo, MDL);
00547 if (np -> n_ipaddr)
00548 host_reference (&foo, np -> n_ipaddr, MDL);
00549 }
00550
00551 if (foo) {
00552 host_dereference (&np -> n_ipaddr, MDL);
00553 if (hd -> n_ipaddr)
00554 host_reference (&np -> n_ipaddr,
00555 hd -> n_ipaddr, MDL);
00556 host_dereference (&foo, MDL);
00557 }
00558 if (np)
00559 host_dereference (&np, MDL);
00560 }
00561 host_dereference (&hp, MDL);
00562 }
00563 }
00564 }
00565
00566 if (hd->host_id_option != NULL) {
00567 option_dereference(&hd->host_id_option, MDL);
00568 data_string_forget(&hd->host_id, MDL);
00569 }
00570
00571 if (hd -> n_ipaddr) {
00572 if (uid_head && hd -> n_ipaddr -> client_identifier.len) {
00573 host_hash_add
00574 (host_uid_hash,
00575 hd -> n_ipaddr -> client_identifier.data,
00576 hd -> n_ipaddr -> client_identifier.len,
00577 hd -> n_ipaddr, MDL);
00578 }
00579 if (hw_head && hd -> n_ipaddr -> interface.hlen) {
00580 host_hash_add (host_hw_addr_hash,
00581 hd -> n_ipaddr -> interface.hbuf,
00582 hd -> n_ipaddr -> interface.hlen,
00583 hd -> n_ipaddr, MDL);
00584 }
00585 host_dereference (&hd -> n_ipaddr, MDL);
00586 }
00587
00588 if (host_name_hash) {
00589 if (host_hash_lookup (&hp, host_name_hash,
00590 (unsigned char *)hd -> name,
00591 strlen (hd -> name), MDL)) {
00592 if (hp == hd && !(hp -> flags & HOST_DECL_STATIC)) {
00593 host_hash_delete (host_name_hash,
00594 (unsigned char *)hd -> name,
00595 strlen (hd -> name), MDL);
00596 }
00597 host_dereference (&hp, MDL);
00598 }
00599 }
00600
00601 if (commit) {
00602 if (!write_host (hd))
00603 return ISC_R_IOERROR;
00604 if (!commit_leases ())
00605 return ISC_R_IOERROR;
00606 }
00607 return ISC_R_SUCCESS;
00608 }
00609
00610 int find_hosts_by_haddr (struct host_decl **hp, int htype,
00611 const unsigned char *haddr, unsigned hlen,
00612 const char *file, int line)
00613 {
00614 struct hardware h;
00615 #if defined(LDAP_CONFIGURATION)
00616 int ret;
00617
00618 if ((ret = find_haddr_in_ldap (hp, htype, hlen, haddr, file, line)))
00619 return ret;
00620 #endif
00621
00622 h.hlen = hlen + 1;
00623 h.hbuf [0] = htype;
00624 memcpy (&h.hbuf [1], haddr, hlen);
00625
00626 return host_hash_lookup (hp, host_hw_addr_hash,
00627 h.hbuf, h.hlen, file, line);
00628 }
00629
00630 int find_hosts_by_uid (struct host_decl **hp,
00631 const unsigned char *data, unsigned len,
00632 const char *file, int line)
00633 {
00634 return host_hash_lookup (hp, host_uid_hash, data, len, file, line);
00635 }
00636
00637 int
00638 find_hosts_by_option(struct host_decl **hp,
00639 struct packet *packet,
00640 struct option_state *opt_state,
00641 const char *file, int line) {
00642 host_id_info_t *p;
00643 struct option_cache *oc;
00644 struct data_string data;
00645 int found;
00646 struct packet *relay_packet;
00647 struct option_state *relay_state;
00648
00649 for (p = host_id_info; p != NULL; p = p->next) {
00650 relay_packet = packet;
00651 relay_state = opt_state;
00652
00653
00654
00655
00656
00657
00658 if ((p->relays != 0) && (packet->options == opt_state)) {
00659 int i = p->relays;
00660 while ((i != 0) &&
00661 (relay_packet->dhcpv6_container_packet != NULL)) {
00662 relay_packet =
00663 relay_packet->dhcpv6_container_packet;
00664 i--;
00665 }
00666
00667
00668 if ((p->relays <= MAX_V6RELAY_HOPS) && (i != 0))
00669 continue;
00670
00671 relay_state = relay_packet->options;
00672 }
00673
00674 oc = lookup_option(p->option->universe,
00675 relay_state, p->option->code);
00676 if (oc != NULL) {
00677 memset(&data, 0, sizeof(data));
00678
00679 if (!evaluate_option_cache(&data, relay_packet, NULL,
00680 NULL, relay_state, NULL,
00681 &global_scope, oc,
00682 MDL)) {
00683 log_error("Error evaluating option cache");
00684 return 0;
00685 }
00686
00687 found = host_hash_lookup(hp, p->values_hash,
00688 data.data, data.len,
00689 file, line);
00690
00691 data_string_forget(&data, MDL);
00692
00693 if (found) {
00694 return 1;
00695 }
00696 }
00697 }
00698 return 0;
00699 }
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709 int find_host_for_network (struct subnet **sp, struct host_decl **host,
00710 struct iaddr *addr, struct shared_network *share)
00711 {
00712 int i;
00713 struct iaddr ip_address;
00714 struct host_decl *hp;
00715 struct data_string fixed_addr;
00716
00717 memset (&fixed_addr, 0, sizeof fixed_addr);
00718
00719 for (hp = *host; hp; hp = hp -> n_ipaddr) {
00720 if (!hp -> fixed_addr)
00721 continue;
00722 if (!evaluate_option_cache (&fixed_addr, (struct packet *)0,
00723 (struct lease *)0,
00724 (struct client_state *)0,
00725 (struct option_state *)0,
00726 (struct option_state *)0,
00727 &global_scope,
00728 hp -> fixed_addr, MDL))
00729 continue;
00730 for (i = 0; i < fixed_addr.len; i += 4) {
00731 ip_address.len = 4;
00732 memcpy (ip_address.iabuf,
00733 fixed_addr.data + i, 4);
00734 if (find_grouped_subnet (sp, share, ip_address, MDL)) {
00735 struct host_decl *tmp = (struct host_decl *)0;
00736 *addr = ip_address;
00737
00738
00739
00740
00741
00742 host_reference (&tmp, *host, MDL);
00743 host_dereference (host, MDL);
00744 host_reference (host, hp, MDL);
00745 host_dereference (&tmp, MDL);
00746 data_string_forget (&fixed_addr, MDL);
00747 return 1;
00748 }
00749 }
00750 data_string_forget (&fixed_addr, MDL);
00751 }
00752 return 0;
00753 }
00754
00755 void new_address_range (cfile, low, high, subnet, pool, lpchain)
00756 struct parse *cfile;
00757 struct iaddr low, high;
00758 struct subnet *subnet;
00759 struct pool *pool;
00760 struct lease **lpchain;
00761 {
00762 #if defined(COMPACT_LEASES)
00763 struct lease *address_range;
00764 #endif
00765 unsigned min, max, i;
00766 char lowbuf [16], highbuf [16], netbuf [16];
00767 struct shared_network *share = subnet -> shared_network;
00768 struct lease *lt = (struct lease *)0;
00769 #if !defined(COMPACT_LEASES)
00770 isc_result_t status;
00771 #endif
00772
00773
00774 if (!share) {
00775 strcpy (netbuf, piaddr (subnet -> net));
00776 log_fatal ("No shared network for network %s (%s)",
00777 netbuf, piaddr (subnet -> netmask));
00778 }
00779
00780
00781 if (!lease_uid_hash) {
00782 if (!lease_id_new_hash(&lease_uid_hash, LEASE_HASH_SIZE, MDL))
00783 log_fatal ("Can't allocate lease/uid hash");
00784 }
00785 if (!lease_ip_addr_hash) {
00786 if (!lease_ip_new_hash(&lease_ip_addr_hash, LEASE_HASH_SIZE,
00787 MDL))
00788 log_fatal ("Can't allocate lease/ip hash");
00789 }
00790 if (!lease_hw_addr_hash) {
00791 if (!lease_id_new_hash(&lease_hw_addr_hash, LEASE_HASH_SIZE,
00792 MDL))
00793 log_fatal ("Can't allocate lease/hw hash");
00794 }
00795
00796
00797 if (!addr_eq(subnet->net, subnet_number(low, subnet->netmask))) {
00798 strcpy(lowbuf, piaddr(low));
00799 strcpy(netbuf, piaddr(subnet->net));
00800 log_fatal("bad range, address %s not in subnet %s netmask %s",
00801 lowbuf, netbuf, piaddr(subnet->netmask));
00802 }
00803
00804 if (!addr_eq(subnet->net, subnet_number(high, subnet->netmask))) {
00805 strcpy(highbuf, piaddr(high));
00806 strcpy(netbuf, piaddr(subnet->net));
00807 log_fatal("bad range, address %s not in subnet %s netmask %s",
00808 highbuf, netbuf, piaddr(subnet->netmask));
00809 }
00810
00811
00812 max = host_addr (high, subnet -> netmask);
00813 min = host_addr (low, subnet -> netmask);
00814
00815
00816 if (min > max) {
00817 max = min;
00818 min = host_addr (high, subnet -> netmask);
00819 }
00820
00821
00822 #if defined (COMPACT_LEASES)
00823 address_range = new_leases (max - min + 1, MDL);
00824 if (!address_range) {
00825 strcpy (lowbuf, piaddr (low));
00826 strcpy (highbuf, piaddr (high));
00827 log_fatal ("No memory for address range %s-%s.",
00828 lowbuf, highbuf);
00829 }
00830 #endif
00831
00832
00833 for (i = 0; i < max - min + 1; i++) {
00834 struct lease *lp = (struct lease *)0;
00835 #if defined (COMPACT_LEASES)
00836 omapi_object_initialize ((omapi_object_t *)&address_range [i],
00837 dhcp_type_lease,
00838 0, sizeof (struct lease), MDL);
00839 lease_reference (&lp, &address_range [i], MDL);
00840 #else
00841 status = lease_allocate (&lp, MDL);
00842 if (status != ISC_R_SUCCESS)
00843 log_fatal ("No memory for lease %s: %s",
00844 piaddr (ip_addr (subnet -> net,
00845 subnet -> netmask,
00846 i + min)),
00847 isc_result_totext (status));
00848 #endif
00849 lp->ip_addr = ip_addr(subnet->net, subnet->netmask, i + min);
00850 lp->starts = MIN_TIME;
00851 lp->ends = MIN_TIME;
00852 subnet_reference(&lp->subnet, subnet, MDL);
00853 pool_reference(&lp->pool, pool, MDL);
00854 lp->binding_state = FTS_FREE;
00855 lp->next_binding_state = FTS_FREE;
00856 lp->rewind_binding_state = FTS_FREE;
00857 lp->flags = 0;
00858
00859
00860 if (find_lease_by_ip_addr (<, lp -> ip_addr, MDL)) {
00861 if (lt -> pool) {
00862 parse_warn (cfile,
00863 "lease %s is declared twice!",
00864 piaddr (lp -> ip_addr));
00865 } else
00866 pool_reference (< -> pool, pool, MDL);
00867 lease_dereference (<, MDL);
00868 } else
00869 lease_ip_hash_add(lease_ip_addr_hash,
00870 lp->ip_addr.iabuf, lp->ip_addr.len,
00871 lp, MDL);
00872
00873 if (lpchain) {
00874 if (*lpchain) {
00875 lease_reference (&lp -> next, *lpchain, MDL);
00876 lease_dereference (lpchain, MDL);
00877 }
00878 lease_reference (lpchain, lp, MDL);
00879 }
00880 lease_dereference (&lp, MDL);
00881 }
00882 }
00883
00884 int find_subnet (struct subnet **sp,
00885 struct iaddr addr, const char *file, int line)
00886 {
00887 struct subnet *rv;
00888
00889 for (rv = subnets; rv; rv = rv -> next_subnet) {
00890 if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net)) {
00891 if (subnet_reference (sp, rv,
00892 file, line) != ISC_R_SUCCESS)
00893 return 0;
00894 return 1;
00895 }
00896 }
00897 return 0;
00898 }
00899
00900 int find_grouped_subnet (struct subnet **sp,
00901 struct shared_network *share, struct iaddr addr,
00902 const char *file, int line)
00903 {
00904 struct subnet *rv;
00905
00906 for (rv = share -> subnets; rv; rv = rv -> next_sibling) {
00907 if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net)) {
00908 if (subnet_reference (sp, rv,
00909 file, line) != ISC_R_SUCCESS)
00910 return 0;
00911 return 1;
00912 }
00913 }
00914 return 0;
00915 }
00916
00917
00918 int
00919 subnet_inner_than(const struct subnet *subnet,
00920 const struct subnet *scan,
00921 int warnp) {
00922 if (addr_eq(subnet_number(subnet->net, scan->netmask), scan->net) ||
00923 addr_eq(subnet_number(scan->net, subnet->netmask), subnet->net)) {
00924 char n1buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255")];
00925 int i, j;
00926 for (i = 0; i < 128; i++)
00927 if (subnet->netmask.iabuf[3 - (i >> 3)]
00928 & (1 << (i & 7)))
00929 break;
00930 for (j = 0; j < 128; j++)
00931 if (scan->netmask.iabuf[3 - (j >> 3)] &
00932 (1 << (j & 7)))
00933 break;
00934 if (warnp) {
00935 strcpy(n1buf, piaddr(subnet->net));
00936 log_error("Warning: subnet %s/%d overlaps subnet %s/%d",
00937 n1buf, 32 - i,
00938 piaddr(scan->net), 32 - j);
00939 }
00940 if (i < j)
00941 return 1;
00942 }
00943 return 0;
00944 }
00945
00946
00947 void enter_subnet (subnet)
00948 struct subnet *subnet;
00949 {
00950 struct subnet *scan = (struct subnet *)0;
00951 struct subnet *next = (struct subnet *)0;
00952 struct subnet *prev = (struct subnet *)0;
00953
00954
00955 if (subnets)
00956 subnet_reference (&next, subnets, MDL);
00957 while (next) {
00958 subnet_reference (&scan, next, MDL);
00959 subnet_dereference (&next, MDL);
00960
00961
00962
00963
00964 if (subnet_inner_than (subnet, scan, 1)) {
00965 if (prev) {
00966 if (prev -> next_subnet)
00967 subnet_dereference (&prev -> next_subnet, MDL);
00968 subnet_reference (&prev -> next_subnet, subnet, MDL);
00969 subnet_dereference (&prev, MDL);
00970 } else {
00971 subnet_dereference (&subnets, MDL);
00972 subnet_reference (&subnets, subnet, MDL);
00973 }
00974 subnet_reference (&subnet -> next_subnet, scan, MDL);
00975 subnet_dereference (&scan, MDL);
00976 return;
00977 }
00978 subnet_reference (&prev, scan, MDL);
00979 subnet_dereference (&scan, MDL);
00980 }
00981 if (prev)
00982 subnet_dereference (&prev, MDL);
00983
00984
00985 if (subnets) {
00986 subnet_reference (&subnet -> next_subnet, subnets, MDL);
00987 subnet_dereference (&subnets, MDL);
00988 }
00989 subnet_reference (&subnets, subnet, MDL);
00990 }
00991
00992
00993
00994 void enter_shared_network (share)
00995 struct shared_network *share;
00996 {
00997 if (shared_networks) {
00998 shared_network_reference (&share -> next,
00999 shared_networks, MDL);
01000 shared_network_dereference (&shared_networks, MDL);
01001 }
01002 shared_network_reference (&shared_networks, share, MDL);
01003 }
01004
01005 void new_shared_network_interface (cfile, share, name)
01006 struct parse *cfile;
01007 struct shared_network *share;
01008 const char *name;
01009 {
01010 struct interface_info *ip;
01011 isc_result_t status;
01012
01013 if (share -> interface) {
01014 parse_warn (cfile,
01015 "A subnet or shared network can't be connected %s",
01016 "to two interfaces.");
01017 return;
01018 }
01019
01020 for (ip = interfaces; ip; ip = ip -> next)
01021 if (!strcmp (ip -> name, name))
01022 break;
01023 if (!ip) {
01024 status = interface_allocate (&ip, MDL);
01025 if (status != ISC_R_SUCCESS)
01026 log_fatal ("new_shared_network_interface %s: %s",
01027 name, isc_result_totext (status));
01028 if (strlen (name) > sizeof ip -> name) {
01029 memcpy (ip -> name, name, (sizeof ip -> name) - 1);
01030 ip -> name [(sizeof ip -> name) - 1] = 0;
01031 } else
01032 strcpy (ip -> name, name);
01033 if (interfaces) {
01034 interface_reference (&ip -> next, interfaces, MDL);
01035 interface_dereference (&interfaces, MDL);
01036 }
01037 interface_reference (&interfaces, ip, MDL);
01038 ip -> flags = INTERFACE_REQUESTED;
01039
01040 shared_network_reference (&ip -> shared_network, share, MDL);
01041 interface_reference (&share -> interface, ip, MDL);
01042 }
01043 }
01044
01045
01046
01047
01048
01049
01050
01051 void enter_lease (lease)
01052 struct lease *lease;
01053 {
01054 struct lease *comp = (struct lease *)0;
01055
01056 if (find_lease_by_ip_addr (&comp, lease -> ip_addr, MDL)) {
01057 if (!comp -> pool) {
01058 log_error ("undeclared lease found in database: %s",
01059 piaddr (lease -> ip_addr));
01060 } else
01061 pool_reference (&lease -> pool, comp -> pool, MDL);
01062
01063 if (comp -> subnet)
01064 subnet_reference (&lease -> subnet,
01065 comp -> subnet, MDL);
01066 lease_ip_hash_delete(lease_ip_addr_hash,
01067 lease->ip_addr.iabuf, lease->ip_addr.len,
01068 MDL);
01069 lease_dereference (&comp, MDL);
01070 }
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081 if (!lease -> subnet) {
01082 log_error ("lease %s: no subnet.", piaddr (lease -> ip_addr));
01083 return;
01084 }
01085 lease_ip_hash_add(lease_ip_addr_hash, lease->ip_addr.iabuf,
01086 lease->ip_addr.len, lease, MDL);
01087 }
01088
01089
01090
01091
01092
01093
01094 int supersede_lease (comp, lease, commit, propogate, pimmediate)
01095 struct lease *comp, *lease;
01096 int commit;
01097 int propogate;
01098 int pimmediate;
01099 {
01100 struct lease *lp, **lq, *prev;
01101 struct timeval tv;
01102 #if defined (FAILOVER_PROTOCOL)
01103 int do_pool_check = 0;
01104
01105
01106
01107
01108 if (pimmediate && !commit)
01109 return 0;
01110 #endif
01111
01112
01113 if (!lease)
01114 goto just_move_it;
01115
01116
01117 if (lease -> flags & STATIC_LEASE)
01118 return 1;
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129 if (lease -> binding_state != FTS_ABANDONED &&
01130 lease -> next_binding_state != FTS_ABANDONED &&
01131 comp -> binding_state == FTS_ACTIVE &&
01132 (((comp -> uid && lease -> uid) &&
01133 (comp -> uid_len != lease -> uid_len ||
01134 memcmp (comp -> uid, lease -> uid, comp -> uid_len))) ||
01135 (!comp -> uid &&
01136 ((comp -> hardware_addr.hlen !=
01137 lease -> hardware_addr.hlen) ||
01138 memcmp (comp -> hardware_addr.hbuf,
01139 lease -> hardware_addr.hbuf,
01140 comp -> hardware_addr.hlen))))) {
01141 log_error ("Lease conflict at %s",
01142 piaddr (comp -> ip_addr));
01143 }
01144
01145
01146
01147 if (comp->uid) {
01148 uid_hash_delete(comp);
01149 if (comp->uid != comp->uid_buf) {
01150 dfree(comp->uid, MDL);
01151 comp->uid_max = 0;
01152 comp->uid_len = 0;
01153 }
01154 comp -> uid = (unsigned char *)0;
01155 }
01156
01157
01158
01159
01160 if (comp->hardware_addr.hlen)
01161 hw_hash_delete(comp);
01162
01163
01164 if (comp -> billing_class != lease -> billing_class) {
01165 if (comp -> billing_class)
01166 unbill_class (comp, comp -> billing_class);
01167 if (lease -> billing_class)
01168 bill_class (comp, lease -> billing_class);
01169 }
01170
01171
01172 comp -> starts = lease -> starts;
01173 if (lease -> uid) {
01174 if (lease -> uid_len <= sizeof (lease -> uid_buf)) {
01175 memcpy (comp -> uid_buf,
01176 lease -> uid, lease -> uid_len);
01177 comp -> uid = &comp -> uid_buf [0];
01178 comp -> uid_max = sizeof comp -> uid_buf;
01179 comp -> uid_len = lease -> uid_len;
01180 } else if (lease -> uid != &lease -> uid_buf [0]) {
01181 comp -> uid = lease -> uid;
01182 comp -> uid_max = lease -> uid_max;
01183 lease -> uid = (unsigned char *)0;
01184 lease -> uid_max = 0;
01185 comp -> uid_len = lease -> uid_len;
01186 lease -> uid_len = 0;
01187 } else {
01188 log_fatal ("corrupt lease uid.");
01189 }
01190 } else {
01191 comp -> uid = (unsigned char *)0;
01192 comp -> uid_len = comp -> uid_max = 0;
01193 }
01194 if (comp -> host)
01195 host_dereference (&comp -> host, MDL);
01196 host_reference (&comp -> host, lease -> host, MDL);
01197 comp -> hardware_addr = lease -> hardware_addr;
01198 comp -> flags = ((lease -> flags & ~PERSISTENT_FLAGS) |
01199 (comp -> flags & ~EPHEMERAL_FLAGS));
01200 if (comp -> scope)
01201 binding_scope_dereference (&comp -> scope, MDL);
01202 if (lease -> scope) {
01203 binding_scope_reference (&comp -> scope, lease -> scope, MDL);
01204 binding_scope_dereference (&lease -> scope, MDL);
01205 }
01206
01207 if (comp -> agent_options)
01208 option_chain_head_dereference (&comp -> agent_options, MDL);
01209 if (lease -> agent_options) {
01210
01211
01212 if (lease -> next_binding_state == FTS_ACTIVE ||
01213 lease -> next_binding_state == FTS_EXPIRED)
01214 option_chain_head_reference (&comp -> agent_options,
01215 lease -> agent_options,
01216 MDL);
01217 option_chain_head_dereference (&lease -> agent_options, MDL);
01218 }
01219
01220
01221 if (comp -> client_hostname)
01222 dfree (comp -> client_hostname, MDL);
01223 comp -> client_hostname = lease -> client_hostname;
01224 lease -> client_hostname = (char *)0;
01225
01226 if (lease->on_star.on_expiry) {
01227 if (comp->on_star.on_expiry)
01228 executable_statement_dereference
01229 (&comp->on_star.on_expiry, MDL);
01230 executable_statement_reference (&comp->on_star.on_expiry,
01231 lease->on_star.on_expiry,
01232 MDL);
01233 }
01234 if (lease->on_star.on_commit) {
01235 if (comp->on_star.on_commit)
01236 executable_statement_dereference
01237 (&comp->on_star.on_commit, MDL);
01238 executable_statement_reference (&comp->on_star.on_commit,
01239 lease->on_star.on_commit,
01240 MDL);
01241 }
01242 if (lease->on_star.on_release) {
01243 if (comp->on_star.on_release)
01244 executable_statement_dereference
01245 (&comp->on_star.on_release, MDL);
01246 executable_statement_reference (&comp->on_star.on_release,
01247 lease->on_star.on_release,
01248 MDL);
01249 }
01250
01251
01252 if (comp->uid)
01253 uid_hash_add(comp);
01254
01255
01256 if (comp->hardware_addr.hlen)
01257 hw_hash_add(comp);
01258
01259 comp->cltt = lease->cltt;
01260 #if defined (FAILOVER_PROTOCOL)
01261 comp->tstp = lease->tstp;
01262 comp->tsfp = lease->tsfp;
01263 comp->atsfp = lease->atsfp;
01264 #endif
01265 comp->ends = lease->ends;
01266 comp->next_binding_state = lease->next_binding_state;
01267
01268
01269
01270
01271
01272
01273
01274
01275 if (lease->ddns_cb != NULL)
01276 comp->ddns_cb = lease->ddns_cb;
01277
01278 just_move_it:
01279 #if defined (FAILOVER_PROTOCOL)
01280
01281
01282
01283
01284
01285 if (propogate)
01286 comp->atsfp = 0;
01287 #endif
01288
01289 if (!comp -> pool) {
01290 log_error ("Supersede_lease: lease %s with no pool.",
01291 piaddr (comp -> ip_addr));
01292 return 0;
01293 }
01294
01295
01296 switch (comp -> binding_state) {
01297 case FTS_FREE:
01298 if (comp->flags & RESERVED_LEASE)
01299 lq = &comp->pool->reserved;
01300 else {
01301 lq = &comp->pool->free;
01302 comp->pool->free_leases--;
01303 }
01304
01305 #if defined(FAILOVER_PROTOCOL)
01306 do_pool_check = 1;
01307 #endif
01308 break;
01309
01310 case FTS_ACTIVE:
01311 lq = &comp -> pool -> active;
01312 break;
01313
01314 case FTS_EXPIRED:
01315 case FTS_RELEASED:
01316 case FTS_RESET:
01317 lq = &comp -> pool -> expired;
01318 break;
01319
01320 case FTS_ABANDONED:
01321 lq = &comp -> pool -> abandoned;
01322 break;
01323
01324 case FTS_BACKUP:
01325 if (comp->flags & RESERVED_LEASE)
01326 lq = &comp->pool->reserved;
01327 else {
01328 lq = &comp->pool->backup;
01329 comp->pool->backup_leases--;
01330 }
01331
01332 #if defined(FAILOVER_PROTOCOL)
01333 do_pool_check = 1;
01334 #endif
01335 break;
01336
01337 default:
01338 log_error ("Lease with bogus binding state: %d",
01339 comp -> binding_state);
01340 #if defined (BINDING_STATE_DEBUG)
01341 abort ();
01342 #endif
01343 return 0;
01344 }
01345
01346
01347
01348
01349 prev = (struct lease *)0;
01350 for (lp = *lq; lp; lp = lp -> next) {
01351 if (lp == comp)
01352 break;
01353 prev = lp;
01354 }
01355
01356 if (!lp) {
01357 log_fatal("Lease with binding state %s not on its queue.",
01358 (comp->binding_state < 1 ||
01359 comp->binding_state > FTS_LAST)
01360 ? "unknown"
01361 : binding_state_names[comp->binding_state - 1]);
01362 }
01363
01364 if (prev) {
01365 lease_dereference (&prev -> next, MDL);
01366 if (comp -> next) {
01367 lease_reference (&prev -> next, comp -> next, MDL);
01368 lease_dereference (&comp -> next, MDL);
01369 }
01370 } else {
01371 lease_dereference (lq, MDL);
01372 if (comp -> next) {
01373 lease_reference (lq, comp -> next, MDL);
01374 lease_dereference (&comp -> next, MDL);
01375 }
01376 }
01377
01378
01379 if (commit || !pimmediate)
01380 make_binding_state_transition (comp);
01381
01382
01383
01384 if (!lease_enqueue (comp))
01385 return 0;
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398 if ((commit || !pimmediate) &&
01399 comp -> sort_time != MIN_TIME &&
01400 comp -> sort_time > cur_time &&
01401 (comp -> sort_time < comp -> pool -> next_event_time ||
01402 comp -> pool -> next_event_time == MIN_TIME)) {
01403 comp -> pool -> next_event_time = comp -> sort_time;
01404 tv . tv_sec = comp -> pool -> next_event_time;
01405 tv . tv_usec = 0;
01406 add_timeout (&tv,
01407 pool_timer, comp -> pool,
01408 (tvref_t)pool_reference,
01409 (tvunref_t)pool_dereference);
01410 }
01411
01412 if (commit) {
01413 #if defined(FAILOVER_PROTOCOL)
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423 if (propogate && (comp->pool->failover_peer != NULL) &&
01424 ((comp->pool->failover_peer->service_state ==
01425 cooperating) ||
01426 (comp->pool->failover_peer->service_state ==
01427 not_responding)))
01428 comp->rewind_binding_state = comp->binding_state;
01429 #endif
01430
01431 if (!write_lease (comp))
01432 return 0;
01433 if ((server_starting & SS_NOSYNC) == 0) {
01434 if (!commit_leases ())
01435 return 0;
01436 }
01437 }
01438
01439 #if defined (FAILOVER_PROTOCOL)
01440 if (propogate) {
01441 comp -> desired_binding_state = comp -> binding_state;
01442 if (!dhcp_failover_queue_update (comp, pimmediate))
01443 return 0;
01444 }
01445 if (do_pool_check && comp->pool->failover_peer)
01446 dhcp_failover_pool_check(comp->pool);
01447 #endif
01448
01449
01450
01451
01452
01453
01454 if ((commit || !pimmediate) &&
01455 comp -> sort_time < cur_time &&
01456 comp -> next_binding_state != comp -> binding_state)
01457 pool_timer (comp -> pool);
01458
01459 return 1;
01460 }
01461
01462 void make_binding_state_transition (struct lease *lease)
01463 {
01464
01465 #if defined (FAILOVER_PROTOCOL)
01466 dhcp_failover_state_t *peer;
01467
01468 if (lease -> pool && lease -> pool -> failover_peer)
01469 peer = lease -> pool -> failover_peer;
01470 else
01471 peer = (dhcp_failover_state_t *)0;
01472 #endif
01473
01474
01475
01476 if (lease -> next_binding_state != lease -> binding_state &&
01477 ((
01478 #if defined (FAILOVER_PROTOCOL)
01479 peer &&
01480 (lease->binding_state == FTS_EXPIRED ||
01481 lease->binding_state == FTS_ACTIVE) &&
01482 (lease->next_binding_state == FTS_FREE ||
01483 lease->next_binding_state == FTS_BACKUP)) ||
01484 (!peer &&
01485 #endif
01486 lease -> binding_state == FTS_ACTIVE &&
01487 lease -> next_binding_state != FTS_RELEASED))) {
01488 #if defined (NSUPDATE)
01489 (void) ddns_removals(lease, NULL, NULL, ISC_TRUE);
01490 #endif
01491 if (lease->on_star.on_expiry) {
01492 execute_statements(NULL, NULL, lease,
01493 NULL, NULL, NULL,
01494 &lease->scope,
01495 lease->on_star.on_expiry,
01496 NULL);
01497 if (lease->on_star.on_expiry)
01498 executable_statement_dereference
01499 (&lease->on_star.on_expiry, MDL);
01500 }
01501
01502
01503 if (lease->on_star.on_release)
01504 executable_statement_dereference
01505 (&lease->on_star.on_release, MDL);
01506
01507
01508 if (lease -> billing_class)
01509 unbill_class (lease, lease -> billing_class);
01510 if (lease -> agent_options)
01511 option_chain_head_dereference (&lease -> agent_options,
01512 MDL);
01513 if (lease -> client_hostname) {
01514 dfree (lease -> client_hostname, MDL);
01515 lease -> client_hostname = (char *)0;
01516 }
01517 if (lease -> host)
01518 host_dereference (&lease -> host, MDL);
01519
01520
01521 lease -> tstp = lease -> ends;
01522 }
01523
01524
01525
01526 if (lease -> next_binding_state != lease -> binding_state &&
01527 ((
01528 #if defined (FAILOVER_PROTOCOL)
01529 peer &&
01530 lease -> binding_state == FTS_RELEASED &&
01531 (lease -> next_binding_state == FTS_FREE ||
01532 lease -> next_binding_state == FTS_BACKUP)) ||
01533 (!peer &&
01534 #endif
01535 lease -> binding_state == FTS_ACTIVE &&
01536 lease -> next_binding_state == FTS_RELEASED))) {
01537 #if defined (NSUPDATE)
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553 (void) ddns_removals(lease, NULL, NULL, ISC_TRUE);
01554 #endif
01555 if (lease->on_star.on_release) {
01556 execute_statements(NULL, NULL, lease,
01557 NULL, NULL, NULL,
01558 &lease->scope,
01559 lease->on_star.on_release,
01560 NULL);
01561 executable_statement_dereference
01562 (&lease->on_star.on_release, MDL);
01563 }
01564
01565
01566 if (lease->on_star.on_expiry)
01567 executable_statement_dereference
01568 (&lease->on_star.on_expiry, MDL);
01569
01570
01571
01572 if (lease -> billing_class)
01573 unbill_class (lease, lease -> billing_class);
01574 if (lease -> agent_options)
01575 option_chain_head_dereference (&lease -> agent_options,
01576 MDL);
01577 if (lease -> client_hostname) {
01578 dfree (lease -> client_hostname, MDL);
01579 lease -> client_hostname = (char *)0;
01580 }
01581 if (lease -> host)
01582 host_dereference (&lease -> host, MDL);
01583
01584
01585
01586 lease -> tstp = lease -> ends;
01587 }
01588
01589 #if defined (DEBUG_LEASE_STATE_TRANSITIONS)
01590 log_debug ("lease %s moves from %s to %s",
01591 piaddr (lease -> ip_addr),
01592 binding_state_print (lease -> binding_state),
01593 binding_state_print (lease -> next_binding_state));
01594 #endif
01595
01596 lease -> binding_state = lease -> next_binding_state;
01597 switch (lease -> binding_state) {
01598 case FTS_ACTIVE:
01599 #if defined (FAILOVER_PROTOCOL)
01600 if (lease -> pool && lease -> pool -> failover_peer)
01601 lease -> next_binding_state = FTS_EXPIRED;
01602 else
01603 #endif
01604 lease -> next_binding_state = FTS_FREE;
01605 break;
01606
01607 case FTS_EXPIRED:
01608 case FTS_RELEASED:
01609 case FTS_ABANDONED:
01610 case FTS_RESET:
01611 lease->next_binding_state = FTS_FREE;
01612 #if defined(FAILOVER_PROTOCOL)
01613
01614
01615
01616
01617 if ((lease->pool != NULL) &&
01618 (lease->pool->failover_peer != NULL) &&
01619 (lease->pool->failover_peer->me.state == partner_down))
01620 lease->tsfp =
01621 (lease->pool->failover_peer->me.stos +
01622 lease->pool->failover_peer->mclt);
01623 #endif
01624 break;
01625
01626 case FTS_FREE:
01627 case FTS_BACKUP:
01628 lease -> next_binding_state = lease -> binding_state;
01629 break;
01630 }
01631 #if defined (DEBUG_LEASE_STATE_TRANSITIONS)
01632 log_debug ("lease %s: next binding state %s",
01633 piaddr (lease -> ip_addr),
01634 binding_state_print (lease -> next_binding_state));
01635 #endif
01636 }
01637
01638
01639
01640 int lease_copy (struct lease **lp,
01641 struct lease *lease, const char *file, int line)
01642 {
01643 struct lease *lt = (struct lease *)0;
01644 isc_result_t status;
01645
01646 status = lease_allocate (<, MDL);
01647 if (status != ISC_R_SUCCESS)
01648 return 0;
01649
01650 lt -> ip_addr = lease -> ip_addr;
01651 lt -> starts = lease -> starts;
01652 lt -> ends = lease -> ends;
01653 lt -> uid_len = lease -> uid_len;
01654 lt -> uid_max = lease -> uid_max;
01655 if (lease -> uid == lease -> uid_buf) {
01656 lt -> uid = lt -> uid_buf;
01657 memcpy (lt -> uid_buf, lease -> uid_buf, sizeof lt -> uid_buf);
01658 } else if (!lease -> uid_max) {
01659 lt -> uid = (unsigned char *)0;
01660 } else {
01661 lt -> uid = dmalloc (lt -> uid_max, MDL);
01662 if (!lt -> uid) {
01663 lease_dereference (<, MDL);
01664 return 0;
01665 }
01666 memcpy (lt -> uid, lease -> uid, lease -> uid_max);
01667 }
01668 if (lease -> client_hostname) {
01669 lt -> client_hostname =
01670 dmalloc (strlen (lease -> client_hostname) + 1, MDL);
01671 if (!lt -> client_hostname) {
01672 lease_dereference (<, MDL);
01673 return 0;
01674 }
01675 strcpy (lt -> client_hostname, lease -> client_hostname);
01676 }
01677 if (lease -> scope)
01678 binding_scope_reference (< -> scope, lease -> scope, MDL);
01679 if (lease -> agent_options)
01680 option_chain_head_reference (< -> agent_options,
01681 lease -> agent_options, MDL);
01682 host_reference (< -> host, lease -> host, file, line);
01683 subnet_reference (< -> subnet, lease -> subnet, file, line);
01684 pool_reference (< -> pool, lease -> pool, file, line);
01685 class_reference (< -> billing_class,
01686 lease -> billing_class, file, line);
01687 lt -> hardware_addr = lease -> hardware_addr;
01688 if (lease->on_star.on_expiry)
01689 executable_statement_reference (<->on_star.on_expiry,
01690 lease->on_star.on_expiry,
01691 file, line);
01692 if (lease->on_star.on_commit)
01693 executable_statement_reference (<->on_star.on_commit,
01694 lease->on_star.on_commit,
01695 file, line);
01696 if (lease->on_star.on_release)
01697 executable_statement_reference (<->on_star.on_release,
01698 lease->on_star.on_release,
01699 file, line);
01700 lt->flags = lease->flags;
01701 lt->tstp = lease->tstp;
01702 lt->tsfp = lease->tsfp;
01703 lt->atsfp = lease->atsfp;
01704 lt->cltt = lease -> cltt;
01705 lt->binding_state = lease->binding_state;
01706 lt->next_binding_state = lease->next_binding_state;
01707 lt->rewind_binding_state = lease->rewind_binding_state;
01708 status = lease_reference(lp, lt, file, line);
01709 lease_dereference(<, MDL);
01710 return status == ISC_R_SUCCESS;
01711 }
01712
01713
01714 void release_lease (lease, packet)
01715 struct lease *lease;
01716 struct packet *packet;
01717 {
01718
01719
01720 #if defined (NSUPDATE)
01721 (void) ddns_removals(lease, NULL, NULL, ISC_FALSE);
01722 #endif
01723 if (lease->on_star.on_release) {
01724 execute_statements (NULL, packet, lease,
01725 NULL, packet->options,
01726 NULL, &lease->scope,
01727 lease->on_star.on_release, NULL);
01728 if (lease->on_star.on_release)
01729 executable_statement_dereference
01730 (&lease->on_star.on_release, MDL);
01731 }
01732
01733
01734
01735
01736 if (lease->on_star.on_expiry)
01737 executable_statement_dereference
01738 (&lease->on_star.on_expiry, MDL);
01739
01740 if (lease -> binding_state != FTS_FREE &&
01741 lease -> binding_state != FTS_BACKUP &&
01742 lease -> binding_state != FTS_RELEASED &&
01743 lease -> binding_state != FTS_EXPIRED &&
01744 lease -> binding_state != FTS_RESET) {
01745 if (lease->on_star.on_commit)
01746 executable_statement_dereference
01747 (&lease->on_star.on_commit, MDL);
01748
01749
01750 if (lease -> scope)
01751 binding_scope_dereference (&lease -> scope, MDL);
01752
01753
01754 lease -> ends = cur_time;
01755
01756
01757
01758
01759 lease->tstp = cur_time;
01760 #if defined (FAILOVER_PROTOCOL)
01761 if (lease -> pool && lease -> pool -> failover_peer) {
01762 dhcp_failover_state_t *peer = NULL;
01763
01764 if (lease->pool != NULL)
01765 peer = lease->pool->failover_peer;
01766
01767 if ((peer->service_state == not_cooperating) &&
01768 (((peer->i_am == primary) &&
01769 (lease->rewind_binding_state == FTS_FREE)) ||
01770 ((peer->i_am == secondary) &&
01771 (lease->rewind_binding_state == FTS_BACKUP)))) {
01772 lease->next_binding_state =
01773 lease->rewind_binding_state;
01774 } else
01775 lease -> next_binding_state = FTS_RELEASED;
01776 } else {
01777 lease -> next_binding_state = FTS_FREE;
01778 }
01779 #else
01780 lease -> next_binding_state = FTS_FREE;
01781 #endif
01782 supersede_lease (lease, (struct lease *)0, 1, 1, 1);
01783 }
01784 }
01785
01786
01787
01788
01789 void abandon_lease (lease, message)
01790 struct lease *lease;
01791 const char *message;
01792 {
01793 struct lease *lt = (struct lease *)0;
01794 #if defined (NSUPDATE)
01795 (void) ddns_removals(lease, NULL, NULL, ISC_FALSE);
01796 #endif
01797
01798 if (!lease_copy (<, lease, MDL))
01799 return;
01800
01801 if (lt->scope)
01802 binding_scope_dereference(<->scope, MDL);
01803
01804 lt -> ends = cur_time;
01805 lt -> next_binding_state = FTS_ABANDONED;
01806
01807 log_error ("Abandoning IP address %s: %s",
01808 piaddr (lease -> ip_addr), message);
01809 lt -> hardware_addr.hlen = 0;
01810 if (lt -> uid && lt -> uid != lt -> uid_buf)
01811 dfree (lt -> uid, MDL);
01812 lt -> uid = (unsigned char *)0;
01813 lt -> uid_len = 0;
01814 lt -> uid_max = 0;
01815 supersede_lease (lease, lt, 1, 1, 1);
01816 lease_dereference (<, MDL);
01817 }
01818
01819 #if 0
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830 void dissociate_lease (lease)
01831 struct lease *lease;
01832 {
01833 struct lease *lt = (struct lease *)0;
01834 #if defined (NSUPDATE)
01835 (void) ddns_removals(lease, NULL, NULL, ISC_FALSE);
01836 #endif
01837
01838 if (!lease_copy (<, lease, MDL))
01839 return;
01840
01841 #if defined (FAILOVER_PROTOCOL)
01842 if (lease -> pool && lease -> pool -> failover_peer) {
01843 lt -> next_binding_state = FTS_RESET;
01844 } else {
01845 lt -> next_binding_state = FTS_FREE;
01846 }
01847 #else
01848 lt -> next_binding_state = FTS_FREE;
01849 #endif
01850 lt -> ends = cur_time;
01851 lt -> hardware_addr.hlen = 0;
01852 if (lt -> uid && lt -> uid != lt -> uid_buf)
01853 dfree (lt -> uid, MDL);
01854 lt -> uid = (unsigned char *)0;
01855 lt -> uid_len = 0;
01856 lt -> uid_max = 0;
01857 supersede_lease (lease, lt, 1, 1, 1);
01858 lease_dereference (<, MDL);
01859 }
01860 #endif
01861
01862
01863 void pool_timer (vpool)
01864 void *vpool;
01865 {
01866 struct pool *pool;
01867 struct lease *next = (struct lease *)0;
01868 struct lease *lease = (struct lease *)0;
01869 #define FREE_LEASES 0
01870 #define ACTIVE_LEASES 1
01871 #define EXPIRED_LEASES 2
01872 #define ABANDONED_LEASES 3
01873 #define BACKUP_LEASES 4
01874 #define RESERVED_LEASES 5
01875 struct lease **lptr[RESERVED_LEASES+1];
01876 TIME next_expiry = MAX_TIME;
01877 int i;
01878 struct timeval tv;
01879
01880 pool = (struct pool *)vpool;
01881
01882 lptr [FREE_LEASES] = &pool -> free;
01883 lptr [ACTIVE_LEASES] = &pool -> active;
01884 lptr [EXPIRED_LEASES] = &pool -> expired;
01885 lptr [ABANDONED_LEASES] = &pool -> abandoned;
01886 lptr [BACKUP_LEASES] = &pool -> backup;
01887 lptr[RESERVED_LEASES] = &pool->reserved;
01888
01889 for (i = FREE_LEASES; i <= RESERVED_LEASES; i++) {
01890
01891 if (!*(lptr [i]))
01892 continue;
01893
01894 #if defined (FAILOVER_PROTOCOL)
01895 if (pool->failover_peer &&
01896 pool->failover_peer->me.state != partner_down) {
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910 if ((i == ACTIVE_LEASES) &&
01911 (pool->failover_peer->i_am == secondary) &&
01912 (pool->failover_peer->me.state == normal))
01913 continue;
01914
01915
01916
01917
01918 if (i == EXPIRED_LEASES)
01919 continue;
01920 }
01921 #endif
01922 lease_reference (&lease, *(lptr [i]), MDL);
01923
01924 while (lease) {
01925
01926 if (next)
01927 lease_dereference (&next, MDL);
01928 if (lease -> next)
01929 lease_reference (&next, lease -> next, MDL);
01930
01931
01932
01933 if (lease -> sort_time > cur_time) {
01934 if (lease -> sort_time < next_expiry)
01935 next_expiry = lease -> sort_time;
01936 break;
01937 }
01938
01939
01940
01941
01942
01943
01944 if (lease->next_binding_state != lease->binding_state)
01945 {
01946 #if defined(FAILOVER_PROTOCOL)
01947 dhcp_failover_state_t *peer = NULL;
01948
01949 if (lease->pool != NULL)
01950 peer = lease->pool->failover_peer;
01951
01952
01953 if (peer != NULL &&
01954 peer->service_state == not_cooperating &&
01955 lease->next_binding_state == FTS_EXPIRED &&
01956 ((peer->i_am == primary &&
01957 lease->rewind_binding_state == FTS_FREE)
01958 ||
01959 (peer->i_am == secondary &&
01960 lease->rewind_binding_state ==
01961 FTS_BACKUP)))
01962 lease->next_binding_state =
01963 lease->rewind_binding_state;
01964 #endif
01965 supersede_lease(lease, NULL, 1, 1, 1);
01966 }
01967
01968 lease_dereference (&lease, MDL);
01969 if (next)
01970 lease_reference (&lease, next, MDL);
01971 }
01972 if (next)
01973 lease_dereference (&next, MDL);
01974 if (lease)
01975 lease_dereference (&lease, MDL);
01976 }
01977 if (next_expiry != MAX_TIME) {
01978 pool -> next_event_time = next_expiry;
01979 tv . tv_sec = pool -> next_event_time;
01980 tv . tv_usec = 0;
01981 add_timeout (&tv, pool_timer, pool,
01982 (tvref_t)pool_reference,
01983 (tvunref_t)pool_dereference);
01984 } else
01985 pool -> next_event_time = MIN_TIME;
01986
01987 }
01988
01989
01990
01991 int find_lease_by_ip_addr (struct lease **lp, struct iaddr addr,
01992 const char *file, int line)
01993 {
01994 return lease_ip_hash_lookup(lp, lease_ip_addr_hash, addr.iabuf,
01995 addr.len, file, line);
01996 }
01997
01998 int find_lease_by_uid (struct lease **lp, const unsigned char *uid,
01999 unsigned len, const char *file, int line)
02000 {
02001 if (len == 0)
02002 return 0;
02003 return lease_id_hash_lookup (lp, lease_uid_hash, uid, len, file, line);
02004 }
02005
02006 int find_lease_by_hw_addr (struct lease **lp,
02007 const unsigned char *hwaddr, unsigned hwlen,
02008 const char *file, int line)
02009 {
02010 if (hwlen == 0)
02011 return (0);
02012
02013
02014
02015
02016
02017 if ((hwlen == 1) && (hwaddr[0] == HTYPE_INFINIBAND))
02018 return (0);
02019
02020 return (lease_id_hash_lookup(lp, lease_hw_addr_hash, hwaddr, hwlen,
02021 file, line));
02022 }
02023
02024
02025
02026
02027
02028
02029
02030
02031
02032
02033
02034
02035
02036
02037 static isc_boolean_t
02038 client_lease_preferred(struct lease *cand, struct lease *lease)
02039 {
02040 if (cand->binding_state == FTS_ACTIVE) {
02041 if (lease->binding_state == FTS_ACTIVE &&
02042 lease->ends >= cand->ends)
02043 return ISC_TRUE;
02044 } else if (cand->binding_state == FTS_EXPIRED ||
02045 cand->binding_state == FTS_RELEASED) {
02046 if (lease->binding_state == FTS_ACTIVE)
02047 return ISC_TRUE;
02048
02049 if ((lease->binding_state == FTS_EXPIRED ||
02050 lease->binding_state == FTS_RELEASED) &&
02051 lease->cltt >= cand->cltt)
02052 return ISC_TRUE;
02053 } else if (cand->binding_state != FTS_ABANDONED) {
02054 if (lease->binding_state == FTS_ACTIVE ||
02055 lease->binding_state == FTS_EXPIRED ||
02056 lease->binding_state == FTS_RELEASED)
02057 return ISC_TRUE;
02058
02059 if (lease->binding_state != FTS_ABANDONED &&
02060 lease->cltt >= cand->cltt)
02061 return ISC_TRUE;
02062 } else {
02063 if (lease->binding_state != FTS_ABANDONED ||
02064 lease->cltt >= cand->cltt)
02065 return ISC_TRUE;
02066 }
02067
02068 return ISC_FALSE;
02069 }
02070
02071
02072 void
02073 uid_hash_add(struct lease *lease)
02074 {
02075 struct lease *head = NULL;
02076 struct lease *cand = NULL;
02077 struct lease *prev = NULL;
02078 struct lease *next = NULL;
02079
02080
02081 if (!find_lease_by_uid (&head, lease -> uid, lease -> uid_len, MDL))
02082 lease_id_hash_add(lease_uid_hash, lease->uid, lease->uid_len,
02083 lease, MDL);
02084 else {
02085
02086
02087
02088
02089
02090
02091
02092 lease_reference(&cand, head, MDL);
02093 while (cand != NULL) {
02094 if (client_lease_preferred(cand, lease))
02095 break;
02096
02097 if (prev != NULL)
02098 lease_dereference(&prev, MDL);
02099 lease_reference(&prev, cand, MDL);
02100
02101 if (cand->n_uid != NULL)
02102 lease_reference(&next, cand->n_uid, MDL);
02103
02104 lease_dereference(&cand, MDL);
02105
02106 if (next != NULL) {
02107 lease_reference(&cand, next, MDL);
02108 lease_dereference(&next, MDL);
02109 }
02110 }
02111
02112
02113
02114
02115 if (prev == NULL) {
02116 lease_reference(&lease->n_uid, head, MDL);
02117 lease_id_hash_delete(lease_uid_hash, lease->uid,
02118 lease->uid_len, MDL);
02119 lease_id_hash_add(lease_uid_hash, lease->uid,
02120 lease->uid_len, lease, MDL);
02121 } else {
02122 if(prev->n_uid != NULL) {
02123 lease_reference(&lease->n_uid, prev->n_uid,
02124 MDL);
02125 lease_dereference(&prev->n_uid, MDL);
02126 }
02127 lease_reference(&prev->n_uid, lease, MDL);
02128
02129 lease_dereference(&prev, MDL);
02130 }
02131
02132 if (cand != NULL)
02133 lease_dereference(&cand, MDL);
02134 lease_dereference(&head, MDL);
02135 }
02136 }
02137
02138
02139
02140 void uid_hash_delete (lease)
02141 struct lease *lease;
02142 {
02143 struct lease *head = (struct lease *)0;
02144 struct lease *scan;
02145
02146
02147 if (!find_lease_by_uid (&head, lease -> uid, lease -> uid_len, MDL)) {
02148 if (lease -> n_uid)
02149 lease_dereference (&lease -> n_uid, MDL);
02150 return;
02151 }
02152
02153
02154
02155
02156 if (head == lease) {
02157 lease_id_hash_delete(lease_uid_hash, lease->uid,
02158 lease->uid_len, MDL);
02159 if (lease -> n_uid) {
02160 lease_id_hash_add(lease_uid_hash, lease->n_uid->uid,
02161 lease->n_uid->uid_len, lease->n_uid,
02162 MDL);
02163 lease_dereference (&lease -> n_uid, MDL);
02164 }
02165 } else {
02166
02167
02168
02169 for (scan = head; scan -> n_uid; scan = scan -> n_uid) {
02170 if (scan -> n_uid == lease) {
02171 lease_dereference (&scan -> n_uid, MDL);
02172 if (lease -> n_uid) {
02173 lease_reference (&scan -> n_uid,
02174 lease -> n_uid, MDL);
02175 lease_dereference (&lease -> n_uid,
02176 MDL);
02177 }
02178 break;
02179 }
02180 }
02181 }
02182 lease_dereference (&head, MDL);
02183 }
02184
02185
02186
02187
02188
02189 void
02190 hw_hash_add(struct lease *lease)
02191 {
02192 struct lease *head = NULL;
02193 struct lease *cand = NULL;
02194 struct lease *prev = NULL;
02195 struct lease *next = NULL;
02196
02197
02198
02199
02200
02201 if ((lease->hardware_addr.hlen == 1) &&
02202 (lease->hardware_addr.hbuf[0] == HTYPE_INFINIBAND))
02203 return;
02204
02205
02206 if (!find_lease_by_hw_addr (&head, lease -> hardware_addr.hbuf,
02207 lease -> hardware_addr.hlen, MDL))
02208 lease_id_hash_add(lease_hw_addr_hash,
02209 lease->hardware_addr.hbuf,
02210 lease->hardware_addr.hlen, lease, MDL);
02211 else {
02212
02213
02214
02215
02216
02217
02218
02219 lease_reference(&cand, head, MDL);
02220 while (cand != NULL) {
02221 if (client_lease_preferred(cand, lease))
02222 break;
02223
02224 if (prev != NULL)
02225 lease_dereference(&prev, MDL);
02226 lease_reference(&prev, cand, MDL);
02227
02228 if (cand->n_hw != NULL)
02229 lease_reference(&next, cand->n_hw, MDL);
02230
02231 lease_dereference(&cand, MDL);
02232
02233 if (next != NULL) {
02234 lease_reference(&cand, next, MDL);
02235 lease_dereference(&next, MDL);
02236 }
02237 }
02238
02239
02240
02241
02242 if (prev == NULL) {
02243 lease_reference(&lease->n_hw, head, MDL);
02244 lease_id_hash_delete(lease_hw_addr_hash,
02245 lease->hardware_addr.hbuf,
02246 lease->hardware_addr.hlen, MDL);
02247 lease_id_hash_add(lease_hw_addr_hash,
02248 lease->hardware_addr.hbuf,
02249 lease->hardware_addr.hlen,
02250 lease, MDL);
02251 } else {
02252 if(prev->n_hw != NULL) {
02253 lease_reference(&lease->n_hw, prev->n_hw,
02254 MDL);
02255 lease_dereference(&prev->n_hw, MDL);
02256 }
02257 lease_reference(&prev->n_hw, lease, MDL);
02258
02259 lease_dereference(&prev, MDL);
02260 }
02261
02262 if (cand != NULL)
02263 lease_dereference(&cand, MDL);
02264 lease_dereference(&head, MDL);
02265 }
02266 }
02267
02268
02269
02270 void hw_hash_delete (lease)
02271 struct lease *lease;
02272 {
02273 struct lease *head = (struct lease *)0;
02274 struct lease *next = (struct lease *)0;
02275
02276
02277
02278
02279
02280 if ((lease->hardware_addr.hlen == 1) &&
02281 (lease->hardware_addr.hbuf[0] == HTYPE_INFINIBAND))
02282 return;
02283
02284
02285 if (!find_lease_by_hw_addr (&head, lease -> hardware_addr.hbuf,
02286 lease -> hardware_addr.hlen, MDL)) {
02287 if (lease -> n_hw)
02288 lease_dereference (&lease -> n_hw, MDL);
02289 return;
02290 }
02291
02292
02293
02294
02295 if (head == lease) {
02296 lease_id_hash_delete(lease_hw_addr_hash,
02297 lease->hardware_addr.hbuf,
02298 lease->hardware_addr.hlen, MDL);
02299 if (lease->n_hw) {
02300 lease_id_hash_add(lease_hw_addr_hash,
02301 lease->n_hw->hardware_addr.hbuf,
02302 lease->n_hw->hardware_addr.hlen,
02303 lease->n_hw, MDL);
02304 lease_dereference(&lease->n_hw, MDL);
02305 }
02306 } else {
02307
02308
02309
02310 while (head -> n_hw) {
02311 if (head -> n_hw == lease) {
02312 lease_dereference (&head -> n_hw, MDL);
02313 if (lease -> n_hw) {
02314 lease_reference (&head -> n_hw,
02315 lease -> n_hw, MDL);
02316 lease_dereference (&lease -> n_hw,
02317 MDL);
02318 }
02319 break;
02320 }
02321 lease_reference (&next, head -> n_hw, MDL);
02322 lease_dereference (&head, MDL);
02323 lease_reference (&head, next, MDL);
02324 lease_dereference (&next, MDL);
02325 }
02326 }
02327 if (head)
02328 lease_dereference (&head, MDL);
02329 }
02330
02331
02332 int write_leases4(void) {
02333 struct lease *l;
02334 struct shared_network *s;
02335 struct pool *p;
02336 struct lease **lptr[RESERVED_LEASES+1];
02337 int num_written = 0, i;
02338
02339
02340 for (s = shared_networks; s; s = s->next) {
02341 for (p = s->pools; p; p = p->next) {
02342 lptr[FREE_LEASES] = &p->free;
02343 lptr[ACTIVE_LEASES] = &p->active;
02344 lptr[EXPIRED_LEASES] = &p->expired;
02345 lptr[ABANDONED_LEASES] = &p->abandoned;
02346 lptr[BACKUP_LEASES] = &p->backup;
02347 lptr[RESERVED_LEASES] = &p->reserved;
02348
02349 for (i = FREE_LEASES; i <= RESERVED_LEASES; i++) {
02350 for (l = *(lptr[i]); l; l = l->next) {
02351 #if !defined (DEBUG_DUMP_ALL_LEASES)
02352 if (l->hardware_addr.hlen != 0 || l->uid_len != 0 ||
02353 l->tsfp != 0 || l->binding_state != FTS_FREE)
02354 #endif
02355 {
02356 if (write_lease(l) == 0)
02357 return (0);
02358 num_written++;
02359 }
02360 }
02361 }
02362 }
02363 }
02364
02365 log_info ("Wrote %d leases to leases file.", num_written);
02366 return (1);
02367 }
02368
02369
02370
02371 int write_leases ()
02372 {
02373 struct host_decl *hp;
02374 struct group_object *gp;
02375 struct hash_bucket *hb;
02376 struct class *cp;
02377 struct collection *colp;
02378 int i;
02379 int num_written;
02380
02381
02382 if (collections->classes) {
02383 numclasseswritten = 0;
02384 for (colp = collections ; colp ; colp = colp->next) {
02385 for (cp = colp->classes ; cp ; cp = cp->nic) {
02386 write_named_billing_class(
02387 (unsigned char *)cp->name,
02388 0, cp);
02389 }
02390 }
02391
02392
02393 log_info ("Wrote %d class decls to leases file.",
02394 numclasseswritten);
02395 }
02396
02397
02398
02399 if (group_name_hash) {
02400 num_written = 0;
02401 for (i = 0; i < group_name_hash -> hash_count; i++) {
02402 for (hb = group_name_hash -> buckets [i];
02403 hb; hb = hb -> next) {
02404 gp = (struct group_object *)hb -> value;
02405 if ((gp -> flags & GROUP_OBJECT_DYNAMIC) ||
02406 ((gp -> flags & GROUP_OBJECT_STATIC) &&
02407 (gp -> flags & GROUP_OBJECT_DELETED))) {
02408 if (!write_group (gp))
02409 return 0;
02410 ++num_written;
02411 }
02412 }
02413 }
02414 log_info ("Wrote %d group decls to leases file.", num_written);
02415 }
02416
02417
02418 if (host_name_hash) {
02419 num_written = 0;
02420 for (i = 0; i < host_name_hash -> hash_count; i++) {
02421 for (hb = host_name_hash -> buckets [i];
02422 hb; hb = hb -> next) {
02423 hp = (struct host_decl *)hb -> value;
02424 if (((hp -> flags & HOST_DECL_STATIC) &&
02425 (hp -> flags & HOST_DECL_DELETED))) {
02426 if (!write_host (hp))
02427 return 0;
02428 ++num_written;
02429 }
02430 }
02431 }
02432 log_info ("Wrote %d deleted host decls to leases file.",
02433 num_written);
02434 }
02435
02436
02437 if (host_name_hash) {
02438 num_written = 0;
02439 for (i = 0; i < host_name_hash -> hash_count; i++) {
02440 for (hb = host_name_hash -> buckets [i];
02441 hb; hb = hb -> next) {
02442 hp = (struct host_decl *)hb -> value;
02443 if ((hp -> flags & HOST_DECL_DYNAMIC)) {
02444 if (!write_host (hp))
02445 ++num_written;
02446 }
02447 }
02448 }
02449 log_info ("Wrote %d new dynamic host decls to leases file.",
02450 num_written);
02451 }
02452
02453 #if defined (FAILOVER_PROTOCOL)
02454
02455 if (!dhcp_failover_write_all_states ())
02456 return 0;
02457 #endif
02458
02459 switch (local_family) {
02460 case AF_INET:
02461 if (write_leases4() == 0)
02462 return (0);
02463 break;
02464 #ifdef DHCPv6
02465 case AF_INET6:
02466 if (write_leases6() == 0)
02467 return (0);
02468 break;
02469 #endif
02470 }
02471
02472 if (commit_leases() == 0)
02473 return (0);
02474 return (1);
02475 }
02476
02477
02478
02479
02480
02481
02482
02483
02484
02485
02486
02487
02488
02489 int lease_enqueue (struct lease *comp)
02490 {
02491 struct lease **lq, *prev, *lp;
02492 static struct lease **last_lq = NULL;
02493 static struct lease *last_insert_point = NULL;
02494
02495
02496 if (!comp -> pool)
02497 return 0;
02498
02499
02500 switch (comp -> binding_state) {
02501 case FTS_FREE:
02502 if (comp->flags & RESERVED_LEASE) {
02503 lq = &comp->pool->reserved;
02504 } else {
02505 lq = &comp->pool->free;
02506 comp->pool->free_leases++;
02507 }
02508 comp -> sort_time = comp -> ends;
02509 break;
02510
02511 case FTS_ACTIVE:
02512 lq = &comp -> pool -> active;
02513 comp -> sort_time = comp -> ends;
02514 break;
02515
02516 case FTS_EXPIRED:
02517 case FTS_RELEASED:
02518 case FTS_RESET:
02519 lq = &comp -> pool -> expired;
02520 #if defined(FAILOVER_PROTOCOL)
02521
02522
02523
02524
02525
02526
02527
02528
02529
02530
02531
02532
02533 if (comp->pool->failover_peer &&
02534 comp->pool->failover_peer->me.state == partner_down)
02535 comp->sort_time = (comp->tsfp > comp->ends) ?
02536 comp->tsfp : comp->ends;
02537 else
02538 #endif
02539 comp->sort_time = comp->ends;
02540
02541 break;
02542
02543 case FTS_ABANDONED:
02544 lq = &comp -> pool -> abandoned;
02545 comp -> sort_time = comp -> ends;
02546 break;
02547
02548 case FTS_BACKUP:
02549 if (comp->flags & RESERVED_LEASE) {
02550 lq = &comp->pool->reserved;
02551 } else {
02552 lq = &comp->pool->backup;
02553 comp->pool->backup_leases++;
02554 }
02555 comp -> sort_time = comp -> ends;
02556 break;
02557
02558 default:
02559 log_error ("Lease with bogus binding state: %d",
02560 comp -> binding_state);
02561 #if defined (BINDING_STATE_DEBUG)
02562 abort ();
02563 #endif
02564 return 0;
02565 }
02566
02567
02568
02569
02570
02571
02572 if ((server_starting & SS_QFOLLOW) && (lq == last_lq) &&
02573 (comp != last_insert_point) &&
02574 (last_insert_point->sort_time <= comp->sort_time)) {
02575 prev = last_insert_point;
02576 lp = prev->next;
02577 } else {
02578 prev = NULL;
02579 lp = *lq;
02580 }
02581
02582
02583 for (; lp ; lp = lp->next) {
02584 if (lp -> sort_time >= comp -> sort_time)
02585 break;
02586 prev = lp;
02587 }
02588
02589 if (prev) {
02590 if (prev -> next) {
02591 lease_reference (&comp -> next, prev -> next, MDL);
02592 lease_dereference (&prev -> next, MDL);
02593 }
02594 lease_reference (&prev -> next, comp, MDL);
02595 } else {
02596 if (*lq) {
02597 lease_reference (&comp -> next, *lq, MDL);
02598 lease_dereference (lq, MDL);
02599 }
02600 lease_reference (lq, comp, MDL);
02601 }
02602 last_insert_point = comp;
02603 last_lq = lq;
02604 return 1;
02605 }
02606
02607
02608
02609
02610
02611 isc_result_t
02612 lease_instantiate(const void *key, unsigned len, void *object)
02613 {
02614 struct lease *lease = object;
02615 struct class *class;
02616
02617
02618
02619 if (!lease -> pool) {
02620 lease_ip_hash_delete(lease_ip_addr_hash, lease->ip_addr.iabuf,
02621 lease->ip_addr.len, MDL);
02622 return ISC_R_SUCCESS;
02623 }
02624
02625
02626
02627
02628
02629
02630
02631 if (!lease_enqueue(lease))
02632 return ISC_R_SUCCESS;
02633
02634
02635 if (lease -> uid) {
02636 uid_hash_add (lease);
02637 }
02638
02639
02640 if (lease -> hardware_addr.hlen) {
02641 hw_hash_add (lease);
02642 }
02643
02644
02645 if (lease -> billing_class) {
02646 class = (struct class *)0;
02647 class_reference (&class, lease -> billing_class, MDL);
02648 class_dereference (&lease -> billing_class, MDL);
02649
02650
02651 if (lease -> binding_state == FTS_ACTIVE ||
02652 lease -> binding_state == FTS_EXPIRED ||
02653 lease -> binding_state == FTS_RELEASED ||
02654 lease -> binding_state == FTS_RESET)
02655 bill_class (lease, class);
02656 class_dereference (&class, MDL);
02657 }
02658 return ISC_R_SUCCESS;
02659 }
02660
02661
02662
02663
02664
02665
02666 void expire_all_pools ()
02667 {
02668 struct shared_network *s;
02669 struct pool *p;
02670 int i;
02671 struct lease *l;
02672 struct lease **lptr[RESERVED_LEASES+1];
02673
02674
02675 server_starting = SS_NOSYNC | SS_QFOLLOW;
02676
02677
02678
02679 lease_ip_hash_foreach(lease_ip_addr_hash, lease_instantiate);
02680
02681
02682
02683
02684
02685
02686
02687 server_starting &= ~SS_QFOLLOW;
02688 for (s = shared_networks; s; s = s -> next) {
02689 for (p = s -> pools; p; p = p -> next) {
02690 pool_timer (p);
02691
02692 p -> lease_count = 0;
02693 p -> free_leases = 0;
02694 p -> backup_leases = 0;
02695
02696 lptr [FREE_LEASES] = &p -> free;
02697 lptr [ACTIVE_LEASES] = &p -> active;
02698 lptr [EXPIRED_LEASES] = &p -> expired;
02699 lptr [ABANDONED_LEASES] = &p -> abandoned;
02700 lptr [BACKUP_LEASES] = &p -> backup;
02701 lptr [RESERVED_LEASES] = &p->reserved;
02702
02703 for (i = FREE_LEASES; i <= RESERVED_LEASES; i++) {
02704 for (l = *(lptr [i]); l; l = l -> next) {
02705 p -> lease_count++;
02706 if (l -> ends <= cur_time) {
02707 if (l->binding_state == FTS_FREE) {
02708 if (i == FREE_LEASES)
02709 p->free_leases++;
02710 else if (i != RESERVED_LEASES)
02711 log_fatal("Impossible case "
02712 "at %s:%d.", MDL);
02713 } else if (l->binding_state == FTS_BACKUP) {
02714 if (i == BACKUP_LEASES)
02715 p->backup_leases++;
02716 else if (i != RESERVED_LEASES)
02717 log_fatal("Impossible case "
02718 "at %s:%d.", MDL);
02719 }
02720 }
02721 #if defined (FAILOVER_PROTOCOL)
02722 if (p -> failover_peer &&
02723 l -> tstp > l -> atsfp &&
02724 !(l -> flags & ON_UPDATE_QUEUE)) {
02725 l -> desired_binding_state = l -> binding_state;
02726 dhcp_failover_queue_update (l, 1);
02727 }
02728 #endif
02729 }
02730 }
02731 }
02732 }
02733
02734
02735 server_starting = 0;
02736 }
02737
02738 void dump_subnets ()
02739 {
02740 struct lease *l;
02741 struct shared_network *s;
02742 struct subnet *n;
02743 struct pool *p;
02744 struct lease **lptr[RESERVED_LEASES+1];
02745 int i;
02746
02747 log_info ("Subnets:");
02748 for (n = subnets; n; n = n -> next_subnet) {
02749 log_debug (" Subnet %s", piaddr (n -> net));
02750 log_debug (" netmask %s",
02751 piaddr (n -> netmask));
02752 }
02753 log_info ("Shared networks:");
02754 for (s = shared_networks; s; s = s -> next) {
02755 log_info (" %s", s -> name);
02756 for (p = s -> pools; p; p = p -> next) {
02757 lptr [FREE_LEASES] = &p -> free;
02758 lptr [ACTIVE_LEASES] = &p -> active;
02759 lptr [EXPIRED_LEASES] = &p -> expired;
02760 lptr [ABANDONED_LEASES] = &p -> abandoned;
02761 lptr [BACKUP_LEASES] = &p -> backup;
02762 lptr [RESERVED_LEASES] = &p->reserved;
02763
02764 for (i = FREE_LEASES; i <= RESERVED_LEASES; i++) {
02765 for (l = *(lptr [i]); l; l = l -> next) {
02766 print_lease (l);
02767 }
02768 }
02769 }
02770 }
02771 }
02772
02773 HASH_FUNCTIONS(lease_ip, const unsigned char *, struct lease, lease_ip_hash_t,
02774 lease_reference, lease_dereference, do_ip4_hash)
02775 HASH_FUNCTIONS(lease_id, const unsigned char *, struct lease, lease_id_hash_t,
02776 lease_reference, lease_dereference, do_id_hash)
02777 HASH_FUNCTIONS (host, const unsigned char *, struct host_decl, host_hash_t,
02778 host_reference, host_dereference, do_string_hash)
02779 HASH_FUNCTIONS (class, const char *, struct class, class_hash_t,
02780 class_reference, class_dereference, do_string_hash)
02781
02782 #if defined (DEBUG_MEMORY_LEAKAGE) && \
02783 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
02784 extern struct hash_table *dns_zone_hash;
02785 extern struct interface_info **interface_vector;
02786 extern int interface_count;
02787 dhcp_control_object_t *dhcp_control_object;
02788 extern struct hash_table *auth_key_hash;
02789 struct hash_table *universe_hash;
02790 struct universe **universes;
02791 int universe_count, universe_max;
02792 #if 0
02793 extern int end;
02794 #endif
02795
02796 #if defined (COMPACT_LEASES)
02797 extern struct lease *lease_hunks;
02798 #endif
02799
02800 void free_everything(void)
02801 {
02802 struct subnet *sc = (struct subnet *)0, *sn = (struct subnet *)0;
02803 struct shared_network *nc = (struct shared_network *)0,
02804 *nn = (struct shared_network *)0;
02805 struct pool *pc = (struct pool *)0, *pn = (struct pool *)0;
02806 struct lease *lc = (struct lease *)0, *ln = (struct lease *)0;
02807 struct interface_info *ic = (struct interface_info *)0,
02808 *in = (struct interface_info *)0;
02809 struct class *cc = (struct class *)0, *cn = (struct class *)0;
02810 struct collection *lp;
02811 int i;
02812
02813
02814 if (host_hw_addr_hash)
02815 host_free_hash_table (&host_hw_addr_hash, MDL);
02816 host_hw_addr_hash = 0;
02817 if (host_uid_hash)
02818 host_free_hash_table (&host_uid_hash, MDL);
02819 host_uid_hash = 0;
02820 if (lease_uid_hash)
02821 lease_id_free_hash_table (&lease_uid_hash, MDL);
02822 lease_uid_hash = 0;
02823 if (lease_ip_addr_hash)
02824 lease_ip_free_hash_table (&lease_ip_addr_hash, MDL);
02825 lease_ip_addr_hash = 0;
02826 if (lease_hw_addr_hash)
02827 lease_id_free_hash_table (&lease_hw_addr_hash, MDL);
02828 lease_hw_addr_hash = 0;
02829 if (host_name_hash)
02830 host_free_hash_table (&host_name_hash, MDL);
02831 host_name_hash = 0;
02832 if (dns_zone_hash)
02833 dns_zone_free_hash_table (&dns_zone_hash, MDL);
02834 dns_zone_hash = 0;
02835
02836 while (host_id_info != NULL) {
02837 host_id_info_t *tmp;
02838 option_dereference(&host_id_info->option, MDL);
02839 host_free_hash_table(&host_id_info->values_hash, MDL);
02840 tmp = host_id_info->next;
02841 dfree(host_id_info, MDL);
02842 host_id_info = tmp;
02843 }
02844 #if 0
02845 if (auth_key_hash)
02846 auth_key_free_hash_table (&auth_key_hash, MDL);
02847 #endif
02848 auth_key_hash = 0;
02849
02850 omapi_object_dereference ((omapi_object_t **)&dhcp_control_object,
02851 MDL);
02852
02853 for (lp = collections; lp; lp = lp -> next) {
02854 if (lp -> classes) {
02855 class_reference (&cn, lp -> classes, MDL);
02856 do {
02857 if (cn) {
02858 class_reference (&cc, cn, MDL);
02859 class_dereference (&cn, MDL);
02860 }
02861 if (cc -> nic) {
02862 class_reference (&cn, cc -> nic, MDL);
02863 class_dereference (&cc -> nic, MDL);
02864 }
02865 group_dereference (&cc -> group, MDL);
02866 if (cc -> hash) {
02867 class_free_hash_table (&cc -> hash, MDL);
02868 cc -> hash = (struct hash_table *)0;
02869 }
02870 class_dereference (&cc, MDL);
02871 } while (cn);
02872 class_dereference (&lp -> classes, MDL);
02873 }
02874 }
02875
02876 if (interface_vector) {
02877 for (i = 0; i < interface_count; i++) {
02878 if (interface_vector [i])
02879 interface_dereference (&interface_vector [i], MDL);
02880 }
02881 dfree (interface_vector, MDL);
02882 interface_vector = 0;
02883 }
02884
02885 if (interfaces) {
02886 interface_reference (&in, interfaces, MDL);
02887 do {
02888 if (in) {
02889 interface_reference (&ic, in, MDL);
02890 interface_dereference (&in, MDL);
02891 }
02892 if (ic -> next) {
02893 interface_reference (&in, ic -> next, MDL);
02894 interface_dereference (&ic -> next, MDL);
02895 }
02896 omapi_unregister_io_object ((omapi_object_t *)ic);
02897 if (ic -> shared_network) {
02898 if (ic -> shared_network -> interface)
02899 interface_dereference
02900 (&ic -> shared_network -> interface, MDL);
02901 shared_network_dereference (&ic -> shared_network, MDL);
02902 }
02903 interface_dereference (&ic, MDL);
02904 } while (in);
02905 interface_dereference (&interfaces, MDL);
02906 }
02907
02908
02909 if (subnets) {
02910 subnet_reference (&sn, subnets, MDL);
02911 do {
02912 if (sn) {
02913 subnet_reference (&sc, sn, MDL);
02914 subnet_dereference (&sn, MDL);
02915 }
02916 if (sc -> next_subnet) {
02917 subnet_reference (&sn, sc -> next_subnet, MDL);
02918 subnet_dereference (&sc -> next_subnet, MDL);
02919 }
02920 if (sc -> next_sibling)
02921 subnet_dereference (&sc -> next_sibling, MDL);
02922 if (sc -> shared_network)
02923 shared_network_dereference (&sc -> shared_network, MDL);
02924 group_dereference (&sc -> group, MDL);
02925 if (sc -> interface)
02926 interface_dereference (&sc -> interface, MDL);
02927 subnet_dereference (&sc, MDL);
02928 } while (sn);
02929 subnet_dereference (&subnets, MDL);
02930 }
02931
02932
02933
02934
02935
02936
02937
02938 if (shared_networks) {
02939 shared_network_dereference (&shared_networks, MDL);
02940
02941 } else if (0) {
02942 shared_network_reference (&nn, shared_networks, MDL);
02943 do {
02944 if (nn) {
02945 shared_network_reference (&nc, nn, MDL);
02946 shared_network_dereference (&nn, MDL);
02947 }
02948 if (nc -> next) {
02949 shared_network_reference (&nn, nc -> next, MDL);
02950 shared_network_dereference (&nc -> next, MDL);
02951 }
02952
02953
02954 if (nc -> pools) {
02955 pool_reference (&pn, nc -> pools, MDL);
02956 do {
02957 struct lease **lptr[RESERVED_LEASES+1];
02958
02959 if (pn) {
02960 pool_reference (&pc, pn, MDL);
02961 pool_dereference (&pn, MDL);
02962 }
02963 if (pc -> next) {
02964 pool_reference (&pn, pc -> next, MDL);
02965 pool_dereference (&pc -> next, MDL);
02966 }
02967
02968 lptr [FREE_LEASES] = &pc -> free;
02969 lptr [ACTIVE_LEASES] = &pc -> active;
02970 lptr [EXPIRED_LEASES] = &pc -> expired;
02971 lptr [ABANDONED_LEASES] = &pc -> abandoned;
02972 lptr [BACKUP_LEASES] = &pc -> backup;
02973 lptr [RESERVED_LEASES] = &pc->reserved;
02974
02975
02976 for (i = FREE_LEASES ; i <= RESERVED_LEASES ; i++) {
02977 if (*lptr [i]) {
02978 lease_reference (&ln, *lptr [i], MDL);
02979 do {
02980 if (ln) {
02981 lease_reference (&lc, ln, MDL);
02982 lease_dereference (&ln, MDL);
02983 }
02984 if (lc -> next) {
02985 lease_reference (&ln, lc -> next, MDL);
02986 lease_dereference (&lc -> next, MDL);
02987 }
02988 if (lc -> billing_class)
02989 class_dereference (&lc -> billing_class,
02990 MDL);
02991 if (lc -> state)
02992 free_lease_state (lc -> state, MDL);
02993 lc -> state = (struct lease_state *)0;
02994 if (lc -> n_hw)
02995 lease_dereference (&lc -> n_hw, MDL);
02996 if (lc -> n_uid)
02997 lease_dereference (&lc -> n_uid, MDL);
02998 lease_dereference (&lc, MDL);
02999 } while (ln);
03000 lease_dereference (lptr [i], MDL);
03001 }
03002 }
03003 if (pc -> group)
03004 group_dereference (&pc -> group, MDL);
03005 if (pc -> shared_network)
03006 shared_network_dereference (&pc -> shared_network,
03007 MDL);
03008 pool_dereference (&pc, MDL);
03009 } while (pn);
03010 pool_dereference (&nc -> pools, MDL);
03011 }
03012
03013
03014 group_dereference (&nc -> group, MDL);
03015 shared_network_dereference (&nc, MDL);
03016 } while (nn);
03017 shared_network_dereference (&shared_networks, MDL);
03018 }
03019
03020 cancel_all_timeouts ();
03021 relinquish_timeouts ();
03022 relinquish_ackqueue();
03023 trace_free_all ();
03024 group_dereference (&root_group, MDL);
03025 executable_statement_dereference (&default_classification_rules, MDL);
03026
03027 shutdown_state = shutdown_drop_omapi_connections;
03028 omapi_io_state_foreach (dhcp_io_shutdown, 0);
03029 shutdown_state = shutdown_listeners;
03030 omapi_io_state_foreach (dhcp_io_shutdown, 0);
03031 shutdown_state = shutdown_dhcp;
03032 omapi_io_state_foreach (dhcp_io_shutdown, 0);
03033
03034 omapi_object_dereference ((omapi_object_t **)&icmp_state, MDL);
03035
03036 universe_free_hash_table (&universe_hash, MDL);
03037 for (i = 0; i < universe_count; i++) {
03038 #if 0
03039 union {
03040 const char *c;
03041 char *s;
03042 } foo;
03043 #endif
03044 if (universes [i]) {
03045 if (universes[i]->name_hash)
03046 option_name_free_hash_table(
03047 &universes[i]->name_hash,
03048 MDL);
03049 if (universes[i]->code_hash)
03050 option_code_free_hash_table(
03051 &universes[i]->code_hash,
03052 MDL);
03053 #if 0
03054 if (universes [i] -> name > (char *)&end) {
03055 foo.c = universes [i] -> name;
03056 dfree (foo.s, MDL);
03057 }
03058 if (universes [i] > (struct universe *)&end)
03059 dfree (universes [i], MDL);
03060 #endif
03061 }
03062 }
03063 dfree (universes, MDL);
03064
03065 relinquish_free_lease_states ();
03066 relinquish_free_pairs ();
03067 relinquish_free_expressions ();
03068 relinquish_free_binding_values ();
03069 relinquish_free_option_caches ();
03070 relinquish_free_packets ();
03071 #if defined(COMPACT_LEASES)
03072 relinquish_lease_hunks ();
03073 #endif
03074 relinquish_hash_bucket_hunks ();
03075 omapi_type_relinquish ();
03076 }
03077 #endif