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