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