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