]> git.ipfire.org Git - thirdparty/dhcp.git/blob - server/mdb.c
- An assertion in lease counting relating to reserved leases was repaired.
[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-identifer "
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 struct iaddr net;
719 unsigned min, max, i;
720 char lowbuf [16], highbuf [16], netbuf [16];
721 struct shared_network *share = subnet -> shared_network;
722 struct lease *lt = (struct lease *)0;
723 #if !defined(COMPACT_LEASES)
724 isc_result_t status;
725 #endif
726
727 /* All subnets should have attached shared network structures. */
728 if (!share) {
729 strcpy (netbuf, piaddr (subnet -> net));
730 log_fatal ("No shared network for network %s (%s)",
731 netbuf, piaddr (subnet -> netmask));
732 }
733
734 /* Initialize the hash table if it hasn't been done yet. */
735 if (!lease_uid_hash) {
736 if (!lease_id_new_hash(&lease_uid_hash, LEASE_HASH_SIZE, MDL))
737 log_fatal ("Can't allocate lease/uid hash");
738 }
739 if (!lease_ip_addr_hash) {
740 if (!lease_ip_new_hash(&lease_ip_addr_hash, LEASE_HASH_SIZE,
741 MDL))
742 log_fatal ("Can't allocate lease/ip hash");
743 }
744 if (!lease_hw_addr_hash) {
745 if (!lease_id_new_hash(&lease_hw_addr_hash, LEASE_HASH_SIZE,
746 MDL))
747 log_fatal ("Can't allocate lease/hw hash");
748 }
749
750 /* Make sure that high and low addresses are in same subnet. */
751 net = subnet_number (low, subnet -> netmask);
752 if (!addr_eq (net, subnet_number (high, subnet -> netmask))) {
753 strcpy (lowbuf, piaddr (low));
754 strcpy (highbuf, piaddr (high));
755 strcpy (netbuf, piaddr (subnet -> netmask));
756 log_fatal ("Address range %s to %s, netmask %s spans %s!",
757 lowbuf, highbuf, netbuf, "multiple subnets");
758 }
759
760 /* Make sure that the addresses are on the correct subnet. */
761 if (!addr_eq (net, subnet -> net)) {
762 strcpy (lowbuf, piaddr (low));
763 strcpy (highbuf, piaddr (high));
764 strcpy (netbuf, piaddr (subnet -> netmask));
765 log_fatal ("Address range %s to %s not on net %s/%s!",
766 lowbuf, highbuf, piaddr (subnet -> net), netbuf);
767 }
768
769 /* Get the high and low host addresses... */
770 max = host_addr (high, subnet -> netmask);
771 min = host_addr (low, subnet -> netmask);
772
773 /* Allow range to be specified high-to-low as well as low-to-high. */
774 if (min > max) {
775 max = min;
776 min = host_addr (high, subnet -> netmask);
777 }
778
779 /* Get a lease structure for each address in the range. */
780 #if defined (COMPACT_LEASES)
781 address_range = new_leases (max - min + 1, MDL);
782 if (!address_range) {
783 strcpy (lowbuf, piaddr (low));
784 strcpy (highbuf, piaddr (high));
785 log_fatal ("No memory for address range %s-%s.",
786 lowbuf, highbuf);
787 }
788 #endif
789
790 /* Fill out the lease structures with some minimal information. */
791 for (i = 0; i < max - min + 1; i++) {
792 struct lease *lp = (struct lease *)0;
793 #if defined (COMPACT_LEASES)
794 omapi_object_initialize ((omapi_object_t *)&address_range [i],
795 dhcp_type_lease,
796 0, sizeof (struct lease), MDL);
797 lease_reference (&lp, &address_range [i], MDL);
798 #else
799 status = lease_allocate (&lp, MDL);
800 if (status != ISC_R_SUCCESS)
801 log_fatal ("No memory for lease %s: %s",
802 piaddr (ip_addr (subnet -> net,
803 subnet -> netmask,
804 i + min)),
805 isc_result_totext (status));
806 #endif
807 lp -> ip_addr = ip_addr (subnet -> net,
808 subnet -> netmask, i + min);
809 lp -> starts = MIN_TIME;
810 lp -> ends = MIN_TIME;
811 subnet_reference (&lp -> subnet, subnet, MDL);
812 pool_reference (&lp -> pool, pool, MDL);
813 lp -> binding_state = FTS_FREE;
814 lp -> next_binding_state = FTS_FREE;
815 lp -> flags = 0;
816
817 /* Remember the lease in the IP address hash. */
818 if (find_lease_by_ip_addr (&lt, lp -> ip_addr, MDL)) {
819 if (lt -> pool) {
820 parse_warn (cfile,
821 "lease %s is declared twice!",
822 piaddr (lp -> ip_addr));
823 } else
824 pool_reference (&lt -> pool, pool, MDL);
825 lease_dereference (&lt, MDL);
826 } else
827 lease_ip_hash_add(lease_ip_addr_hash,
828 lp->ip_addr.iabuf, lp->ip_addr.len,
829 lp, MDL);
830 /* Put the lease on the chain for the caller. */
831 if (lpchain) {
832 if (*lpchain) {
833 lease_reference (&lp -> next, *lpchain, MDL);
834 lease_dereference (lpchain, MDL);
835 }
836 lease_reference (lpchain, lp, MDL);
837 }
838 lease_dereference (&lp, MDL);
839 }
840 }
841
842 int find_subnet (struct subnet **sp,
843 struct iaddr addr, const char *file, int line)
844 {
845 struct subnet *rv;
846
847 for (rv = subnets; rv; rv = rv -> next_subnet) {
848 if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net)) {
849 if (subnet_reference (sp, rv,
850 file, line) != ISC_R_SUCCESS)
851 return 0;
852 return 1;
853 }
854 }
855 return 0;
856 }
857
858 int find_grouped_subnet (struct subnet **sp,
859 struct shared_network *share, struct iaddr addr,
860 const char *file, int line)
861 {
862 struct subnet *rv;
863
864 for (rv = share -> subnets; rv; rv = rv -> next_sibling) {
865 if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net)) {
866 if (subnet_reference (sp, rv,
867 file, line) != ISC_R_SUCCESS)
868 return 0;
869 return 1;
870 }
871 }
872 return 0;
873 }
874
875 /* XXX: could speed up if everyone had a prefix length */
876 int
877 subnet_inner_than(const struct subnet *subnet,
878 const struct subnet *scan,
879 int warnp) {
880 if (addr_eq(subnet_number(subnet->net, scan->netmask), scan->net) ||
881 addr_eq(subnet_number(scan->net, subnet->netmask), subnet->net)) {
882 char n1buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255")];
883 int i, j;
884 for (i = 0; i < 128; i++)
885 if (subnet->netmask.iabuf[3 - (i >> 3)]
886 & (1 << (i & 7)))
887 break;
888 for (j = 0; j < 128; j++)
889 if (scan->netmask.iabuf[3 - (j >> 3)] &
890 (1 << (j & 7)))
891 break;
892 if (warnp) {
893 strcpy(n1buf, piaddr(subnet->net));
894 log_error("Warning: subnet %s/%d overlaps subnet %s/%d",
895 n1buf, 32 - i,
896 piaddr(scan->net), 32 - j);
897 }
898 if (i < j)
899 return 1;
900 }
901 return 0;
902 }
903
904 /* Enter a new subnet into the subnet list. */
905 void enter_subnet (subnet)
906 struct subnet *subnet;
907 {
908 struct subnet *scan = (struct subnet *)0;
909 struct subnet *next = (struct subnet *)0;
910 struct subnet *prev = (struct subnet *)0;
911
912 /* Check for duplicates... */
913 if (subnets)
914 subnet_reference (&next, subnets, MDL);
915 while (next) {
916 subnet_reference (&scan, next, MDL);
917 subnet_dereference (&next, MDL);
918
919 /* When we find a conflict, make sure that the
920 subnet with the narrowest subnet mask comes
921 first. */
922 if (subnet_inner_than (subnet, scan, 1)) {
923 if (prev) {
924 if (prev -> next_subnet)
925 subnet_dereference (&prev -> next_subnet, MDL);
926 subnet_reference (&prev -> next_subnet, subnet, MDL);
927 subnet_dereference (&prev, MDL);
928 } else {
929 subnet_dereference (&subnets, MDL);
930 subnet_reference (&subnets, subnet, MDL);
931 }
932 subnet_reference (&subnet -> next_subnet, scan, MDL);
933 subnet_dereference (&scan, MDL);
934 return;
935 }
936 subnet_reference (&prev, scan, MDL);
937 subnet_dereference (&scan, MDL);
938 }
939 if (prev)
940 subnet_dereference (&prev, MDL);
941
942 /* XXX use the BSD radix tree code instead of a linked list. */
943 if (subnets) {
944 subnet_reference (&subnet -> next_subnet, subnets, MDL);
945 subnet_dereference (&subnets, MDL);
946 }
947 subnet_reference (&subnets, subnet, MDL);
948 }
949
950 /* Enter a new shared network into the shared network list. */
951
952 void enter_shared_network (share)
953 struct shared_network *share;
954 {
955 if (shared_networks) {
956 shared_network_reference (&share -> next,
957 shared_networks, MDL);
958 shared_network_dereference (&shared_networks, MDL);
959 }
960 shared_network_reference (&shared_networks, share, MDL);
961 }
962
963 void new_shared_network_interface (cfile, share, name)
964 struct parse *cfile;
965 struct shared_network *share;
966 const char *name;
967 {
968 struct interface_info *ip;
969 isc_result_t status;
970
971 if (share -> interface) {
972 parse_warn (cfile,
973 "A subnet or shared network can't be connected %s",
974 "to two interfaces.");
975 return;
976 }
977
978 for (ip = interfaces; ip; ip = ip -> next)
979 if (!strcmp (ip -> name, name))
980 break;
981 if (!ip) {
982 status = interface_allocate (&ip, MDL);
983 if (status != ISC_R_SUCCESS)
984 log_fatal ("new_shared_network_interface %s: %s",
985 name, isc_result_totext (status));
986 if (strlen (name) > sizeof ip -> name) {
987 memcpy (ip -> name, name, (sizeof ip -> name) - 1);
988 ip -> name [(sizeof ip -> name) - 1] = 0;
989 } else
990 strcpy (ip -> name, name);
991 if (interfaces) {
992 interface_reference (&ip -> next, interfaces, MDL);
993 interface_dereference (&interfaces, MDL);
994 }
995 interface_reference (&interfaces, ip, MDL);
996 ip -> flags = INTERFACE_REQUESTED;
997 /* XXX this is a reference loop. */
998 shared_network_reference (&ip -> shared_network, share, MDL);
999 interface_reference (&share -> interface, ip, MDL);
1000 }
1001 }
1002
1003 /* Enter a lease into the system. This is called by the parser each
1004 time it reads in a new lease. If the subnet for that lease has
1005 already been read in (usually the case), just update that lease;
1006 otherwise, allocate temporary storage for the lease and keep it around
1007 until we're done reading in the config file. */
1008
1009 void enter_lease (lease)
1010 struct lease *lease;
1011 {
1012 struct lease *comp = (struct lease *)0;
1013
1014 if (find_lease_by_ip_addr (&comp, lease -> ip_addr, MDL)) {
1015 if (!comp -> pool) {
1016 log_error ("undeclared lease found in database: %s",
1017 piaddr (lease -> ip_addr));
1018 } else
1019 pool_reference (&lease -> pool, comp -> pool, MDL);
1020
1021 if (comp -> subnet)
1022 subnet_reference (&lease -> subnet,
1023 comp -> subnet, MDL);
1024 lease_ip_hash_delete(lease_ip_addr_hash,
1025 lease->ip_addr.iabuf, lease->ip_addr.len,
1026 MDL);
1027 lease_dereference (&comp, MDL);
1028 }
1029
1030 /* The only way a lease can get here without a subnet is if it's in
1031 the lease file, but not in the dhcpd.conf file. In this case, we
1032 *should* keep it around until it's expired, but never reallocate it
1033 or renew it. Currently, to maintain consistency, we are not doing
1034 this.
1035 XXX fix this so that the lease is kept around until it expires.
1036 XXX this will be important in IPv6 with addresses that become
1037 XXX non-renewable as a result of a renumbering event. */
1038
1039 if (!lease -> subnet) {
1040 log_error ("lease %s: no subnet.", piaddr (lease -> ip_addr));
1041 return;
1042 }
1043 lease_ip_hash_add(lease_ip_addr_hash, lease->ip_addr.iabuf,
1044 lease->ip_addr.len, lease, MDL);
1045 }
1046
1047 /* Replace the data in an existing lease with the data in a new lease;
1048 adjust hash tables to suit, and insertion sort the lease into the
1049 list of leases by expiry time so that we can always find the oldest
1050 lease. */
1051
1052 int supersede_lease (comp, lease, commit, propogate, pimmediate)
1053 struct lease *comp, *lease;
1054 int commit;
1055 int propogate;
1056 int pimmediate;
1057 {
1058 struct lease *lp, **lq, *prev;
1059 #if defined (FAILOVER_PROTOCOL)
1060 int do_pool_check = 0;
1061
1062 /* We must commit leases before sending updates regarding them
1063 to failover peers. It is, therefore, an error to set pimmediate
1064 and not commit. */
1065 if (pimmediate && !commit)
1066 return 0;
1067 #endif
1068
1069 /* If there is no sample lease, just do the move. */
1070 if (!lease)
1071 goto just_move_it;
1072
1073 /* Static leases are not currently kept in the database... */
1074 if (lease -> flags & STATIC_LEASE)
1075 return 1;
1076
1077 /* If the existing lease hasn't expired and has a different
1078 unique identifier or, if it doesn't have a unique
1079 identifier, a different hardware address, then the two
1080 leases are in conflict. If the existing lease has a uid
1081 and the new one doesn't, but they both have the same
1082 hardware address, and dynamic bootp is allowed on this
1083 lease, then we allow that, in case a dynamic BOOTP lease is
1084 requested *after* a DHCP lease has been assigned. */
1085
1086 if (lease -> binding_state != FTS_ABANDONED &&
1087 lease -> next_binding_state != FTS_ABANDONED &&
1088 comp -> binding_state == FTS_ACTIVE &&
1089 (((comp -> uid && lease -> uid) &&
1090 (comp -> uid_len != lease -> uid_len ||
1091 memcmp (comp -> uid, lease -> uid, comp -> uid_len))) ||
1092 (!comp -> uid &&
1093 ((comp -> hardware_addr.hlen !=
1094 lease -> hardware_addr.hlen) ||
1095 memcmp (comp -> hardware_addr.hbuf,
1096 lease -> hardware_addr.hbuf,
1097 comp -> hardware_addr.hlen))))) {
1098 log_error ("Lease conflict at %s",
1099 piaddr (comp -> ip_addr));
1100 }
1101
1102 /* If there's a Unique ID, dissociate it from the hash
1103 table and free it if necessary. */
1104 if (comp->uid) {
1105 uid_hash_delete(comp);
1106 if (comp->uid != comp->uid_buf) {
1107 dfree(comp->uid, MDL);
1108 comp->uid_max = 0;
1109 comp->uid_len = 0;
1110 }
1111 comp -> uid = (unsigned char *)0;
1112 }
1113
1114 /* If there's a hardware address, remove the lease from its
1115 * old position in the hash bucket's ordered list.
1116 */
1117 if (comp->hardware_addr.hlen)
1118 hw_hash_delete(comp);
1119
1120 /* If the lease has been billed to a class, remove the billing. */
1121 if (comp -> billing_class != lease -> billing_class) {
1122 if (comp -> billing_class)
1123 unbill_class (comp, comp -> billing_class);
1124 if (lease -> billing_class)
1125 bill_class (comp, lease -> billing_class);
1126 }
1127
1128 /* Copy the data files, but not the linkages. */
1129 comp -> starts = lease -> starts;
1130 if (lease -> uid) {
1131 if (lease -> uid_len <= sizeof (lease -> uid_buf)) {
1132 memcpy (comp -> uid_buf,
1133 lease -> uid, lease -> uid_len);
1134 comp -> uid = &comp -> uid_buf [0];
1135 comp -> uid_max = sizeof comp -> uid_buf;
1136 comp -> uid_len = lease -> uid_len;
1137 } else if (lease -> uid != &lease -> uid_buf [0]) {
1138 comp -> uid = lease -> uid;
1139 comp -> uid_max = lease -> uid_max;
1140 lease -> uid = (unsigned char *)0;
1141 lease -> uid_max = 0;
1142 comp -> uid_len = lease -> uid_len;
1143 lease -> uid_len = 0;
1144 } else {
1145 log_fatal ("corrupt lease uid."); /* XXX */
1146 }
1147 } else {
1148 comp -> uid = (unsigned char *)0;
1149 comp -> uid_len = comp -> uid_max = 0;
1150 }
1151 if (comp -> host)
1152 host_dereference (&comp -> host, MDL);
1153 host_reference (&comp -> host, lease -> host, MDL);
1154 comp -> hardware_addr = lease -> hardware_addr;
1155 comp -> flags = ((lease -> flags & ~PERSISTENT_FLAGS) |
1156 (comp -> flags & ~EPHEMERAL_FLAGS));
1157 if (comp -> scope)
1158 binding_scope_dereference (&comp -> scope, MDL);
1159 if (lease -> scope) {
1160 binding_scope_reference (&comp -> scope, lease -> scope, MDL);
1161 binding_scope_dereference (&lease -> scope, MDL);
1162 }
1163
1164 if (comp -> agent_options)
1165 option_chain_head_dereference (&comp -> agent_options, MDL);
1166 if (lease -> agent_options) {
1167 /* Only retain the agent options if the lease is still
1168 affirmatively associated with a client. */
1169 if (lease -> next_binding_state == FTS_ACTIVE ||
1170 lease -> next_binding_state == FTS_EXPIRED)
1171 option_chain_head_reference (&comp -> agent_options,
1172 lease -> agent_options,
1173 MDL);
1174 option_chain_head_dereference (&lease -> agent_options, MDL);
1175 }
1176
1177 /* Record the hostname information in the lease. */
1178 if (comp -> client_hostname)
1179 dfree (comp -> client_hostname, MDL);
1180 comp -> client_hostname = lease -> client_hostname;
1181 lease -> client_hostname = (char *)0;
1182
1183 if (lease -> on_expiry) {
1184 if (comp -> on_expiry)
1185 executable_statement_dereference (&comp -> on_expiry,
1186 MDL);
1187 executable_statement_reference (&comp -> on_expiry,
1188 lease -> on_expiry,
1189 MDL);
1190 }
1191 if (lease -> on_commit) {
1192 if (comp -> on_commit)
1193 executable_statement_dereference (&comp -> on_commit,
1194 MDL);
1195 executable_statement_reference (&comp -> on_commit,
1196 lease -> on_commit,
1197 MDL);
1198 }
1199 if (lease -> on_release) {
1200 if (comp -> on_release)
1201 executable_statement_dereference (&comp -> on_release,
1202 MDL);
1203 executable_statement_reference (&comp -> on_release,
1204 lease -> on_release, MDL);
1205 }
1206
1207 /* Record the lease in the uid hash if necessary. */
1208 if (comp->uid)
1209 uid_hash_add(comp);
1210
1211 /* Record it in the hardware address hash if necessary. */
1212 if (comp->hardware_addr.hlen)
1213 hw_hash_add(comp);
1214
1215 comp->cltt = lease->cltt;
1216 #if defined (FAILOVER_PROTOCOL)
1217 comp->tstp = lease->tstp;
1218 comp->tsfp = lease->tsfp;
1219 comp->atsfp = lease->atsfp;
1220 #endif /* FAILOVER_PROTOCOL */
1221 comp->ends = lease->ends;
1222 comp->next_binding_state = lease->next_binding_state;
1223
1224 just_move_it:
1225 #if defined (FAILOVER_PROTOCOL)
1226 /* Atsfp should be cleared upon any state change that implies
1227 * propogation whether supersede_lease was given a copy lease
1228 * structure or not (often from the pool_timer()).
1229 */
1230 if (propogate)
1231 comp->atsfp = 0;
1232 #endif /* FAILOVER_PROTOCOL */
1233
1234 if (!comp -> pool) {
1235 log_error ("Supersede_lease: lease %s with no pool.",
1236 piaddr (comp -> ip_addr));
1237 return 0;
1238 }
1239
1240 /* Figure out which queue it's on. */
1241 switch (comp -> binding_state) {
1242 case FTS_FREE:
1243 lq = &comp -> pool -> free;
1244 if (!(comp->flags & RESERVED_LEASE))
1245 comp->pool->free_leases--;
1246
1247 #if defined(FAILOVER_PROTOCOL)
1248 do_pool_check = 1;
1249 #endif
1250 break;
1251
1252 case FTS_ACTIVE:
1253 lq = &comp -> pool -> active;
1254 break;
1255
1256 case FTS_EXPIRED:
1257 case FTS_RELEASED:
1258 case FTS_RESET:
1259 lq = &comp -> pool -> expired;
1260 break;
1261
1262 case FTS_ABANDONED:
1263 lq = &comp -> pool -> abandoned;
1264 break;
1265
1266 case FTS_BACKUP:
1267 lq = &comp -> pool -> backup;
1268 if (!(comp->flags & RESERVED_LEASE))
1269 comp->pool->backup_leases--;
1270
1271 #if defined(FAILOVER_PROTOCOL)
1272 do_pool_check = 1;
1273 #endif
1274 break;
1275
1276 default:
1277 log_error ("Lease with bogus binding state: %d",
1278 comp -> binding_state);
1279 #if defined (BINDING_STATE_DEBUG)
1280 abort ();
1281 #endif
1282 return 0;
1283 }
1284
1285 /* Remove the lease from its current place in its current
1286 timer sequence. */
1287 /* XXX this is horrid. */
1288 prev = (struct lease *)0;
1289 for (lp = *lq; lp; lp = lp -> next) {
1290 if (lp == comp)
1291 break;
1292 prev = lp;
1293 }
1294
1295 if (!lp) {
1296 log_fatal("Lease with binding state %s not on its queue.",
1297 (comp->binding_state < 1 ||
1298 comp->binding_state > FTS_LAST)
1299 ? "unknown"
1300 : binding_state_names[comp->binding_state - 1]);
1301 }
1302
1303 if (prev) {
1304 lease_dereference (&prev -> next, MDL);
1305 if (comp -> next) {
1306 lease_reference (&prev -> next, comp -> next, MDL);
1307 lease_dereference (&comp -> next, MDL);
1308 }
1309 } else {
1310 lease_dereference (lq, MDL);
1311 if (comp -> next) {
1312 lease_reference (lq, comp -> next, MDL);
1313 lease_dereference (&comp -> next, MDL);
1314 }
1315 }
1316
1317 /* Make the state transition. */
1318 if (commit || !pimmediate)
1319 make_binding_state_transition (comp);
1320
1321 /* Put the lease back on the appropriate queue. If the lease
1322 is corrupt (as detected by lease_enqueue), don't go any farther. */
1323 if (!lease_enqueue (comp))
1324 return 0;
1325
1326 /* If this is the next lease that will timeout on the pool,
1327 zap the old timeout and set the timeout on this pool to the
1328 time that the lease's next event will happen.
1329
1330 We do not actually set the timeout unless commit is true -
1331 we don't want to thrash the timer queue when reading the
1332 lease database. Instead, the database code calls the
1333 expiry event on each pool after reading in the lease file,
1334 and the expiry code sets the timer if there's anything left
1335 to expire after it's run any outstanding expiry events on
1336 the pool. */
1337 if ((commit || !pimmediate) &&
1338 comp -> sort_time != MIN_TIME &&
1339 comp -> sort_time > cur_time &&
1340 (comp -> sort_time < comp -> pool -> next_event_time ||
1341 comp -> pool -> next_event_time == MIN_TIME)) {
1342 comp -> pool -> next_event_time = comp -> sort_time;
1343 add_timeout (comp -> pool -> next_event_time,
1344 pool_timer, comp -> pool,
1345 (tvref_t)pool_reference,
1346 (tvunref_t)pool_dereference);
1347 }
1348
1349 if (commit) {
1350 if (!write_lease (comp))
1351 return 0;
1352 if ((server_starting & SS_NOSYNC) == 0) {
1353 if (!commit_leases ())
1354 return 0;
1355 }
1356 }
1357
1358 #if defined (FAILOVER_PROTOCOL)
1359 if (propogate) {
1360 comp -> desired_binding_state = comp -> binding_state;
1361 if (!dhcp_failover_queue_update (comp, pimmediate))
1362 return 0;
1363 }
1364 if (do_pool_check && comp->pool->failover_peer)
1365 dhcp_failover_pool_check(comp->pool);
1366 #endif
1367
1368 /* If the current binding state has already expired, do an
1369 expiry event right now. */
1370 /* XXX At some point we should optimize this so that we don't
1371 XXX write the lease twice, but this is a safe way to fix the
1372 XXX problem for 3.0 (I hope!). */
1373 if ((commit || !pimmediate) &&
1374 comp -> sort_time < cur_time &&
1375 comp -> next_binding_state != comp -> binding_state)
1376 pool_timer (comp -> pool);
1377
1378 return 1;
1379 }
1380
1381 void make_binding_state_transition (struct lease *lease)
1382 {
1383 #if defined (FAILOVER_PROTOCOL)
1384 dhcp_failover_state_t *peer;
1385
1386 if (lease && lease -> pool && lease -> pool -> failover_peer)
1387 peer = lease -> pool -> failover_peer;
1388 else
1389 peer = (dhcp_failover_state_t *)0;
1390 #endif
1391
1392 /* If the lease was active and is now no longer active, but isn't
1393 released, then it just expired, so do the expiry event. */
1394 if (lease -> next_binding_state != lease -> binding_state &&
1395 ((
1396 #if defined (FAILOVER_PROTOCOL)
1397 peer &&
1398 (lease -> binding_state == FTS_EXPIRED ||
1399 (peer -> i_am == secondary &&
1400 lease -> binding_state == FTS_ACTIVE)) &&
1401 (lease -> next_binding_state == FTS_FREE ||
1402 lease -> next_binding_state == FTS_BACKUP)) ||
1403 (!peer &&
1404 #endif
1405 lease -> binding_state == FTS_ACTIVE &&
1406 lease -> next_binding_state != FTS_RELEASED))) {
1407 #if defined (NSUPDATE)
1408 ddns_removals(lease, NULL);
1409 #endif
1410 if (lease -> on_expiry) {
1411 execute_statements ((struct binding_value **)0,
1412 (struct packet *)0, lease,
1413 (struct client_state *)0,
1414 (struct option_state *)0,
1415 (struct option_state *)0, /* XXX */
1416 &lease -> scope,
1417 lease -> on_expiry);
1418 if (lease -> on_expiry)
1419 executable_statement_dereference
1420 (&lease -> on_expiry, MDL);
1421 }
1422
1423 /* No sense releasing a lease after it's expired. */
1424 if (lease -> on_release)
1425 executable_statement_dereference (&lease -> on_release,
1426 MDL);
1427 /* Get rid of client-specific bindings that are only
1428 correct when the lease is active. */
1429 if (lease -> billing_class)
1430 unbill_class (lease, lease -> billing_class);
1431 if (lease -> agent_options)
1432 option_chain_head_dereference (&lease -> agent_options,
1433 MDL);
1434 if (lease -> client_hostname) {
1435 dfree (lease -> client_hostname, MDL);
1436 lease -> client_hostname = (char *)0;
1437 }
1438 if (lease -> host)
1439 host_dereference (&lease -> host, MDL);
1440
1441 /* Send the expiry time to the peer. */
1442 lease -> tstp = lease -> ends;
1443 }
1444
1445 /* If the lease was active and is now released, do the release
1446 event. */
1447 if (lease -> next_binding_state != lease -> binding_state &&
1448 ((
1449 #if defined (FAILOVER_PROTOCOL)
1450 peer &&
1451 lease -> binding_state == FTS_RELEASED &&
1452 (lease -> next_binding_state == FTS_FREE ||
1453 lease -> next_binding_state == FTS_BACKUP)) ||
1454 (!peer &&
1455 #endif
1456 lease -> binding_state == FTS_ACTIVE &&
1457 lease -> next_binding_state == FTS_RELEASED))) {
1458 #if defined (NSUPDATE)
1459 ddns_removals(lease, NULL);
1460 #endif
1461 if (lease -> on_release) {
1462 execute_statements ((struct binding_value **)0,
1463 (struct packet *)0, lease,
1464 (struct client_state *)0,
1465 (struct option_state *)0,
1466 (struct option_state *)0, /* XXX */
1467 &lease -> scope,
1468 lease -> on_release);
1469 executable_statement_dereference (&lease -> on_release,
1470 MDL);
1471 }
1472
1473 /* A released lease can't expire. */
1474 if (lease -> on_expiry)
1475 executable_statement_dereference (&lease -> on_expiry,
1476 MDL);
1477
1478 /* Get rid of client-specific bindings that are only
1479 correct when the lease is active. */
1480 if (lease -> billing_class)
1481 unbill_class (lease, lease -> billing_class);
1482 if (lease -> agent_options)
1483 option_chain_head_dereference (&lease -> agent_options,
1484 MDL);
1485 if (lease -> client_hostname) {
1486 dfree (lease -> client_hostname, MDL);
1487 lease -> client_hostname = (char *)0;
1488 }
1489 if (lease -> host)
1490 host_dereference (&lease -> host, MDL);
1491
1492 /* Send the release time (should be == cur_time) to the
1493 peer. */
1494 lease -> tstp = lease -> ends;
1495 }
1496
1497 #if defined (DEBUG_LEASE_STATE_TRANSITIONS)
1498 log_debug ("lease %s moves from %s to %s",
1499 piaddr (lease -> ip_addr),
1500 binding_state_print (lease -> binding_state),
1501 binding_state_print (lease -> next_binding_state));
1502 #endif
1503
1504 lease -> binding_state = lease -> next_binding_state;
1505 switch (lease -> binding_state) {
1506 case FTS_ACTIVE:
1507 #if defined (FAILOVER_PROTOCOL)
1508 if (lease -> pool && lease -> pool -> failover_peer)
1509 lease -> next_binding_state = FTS_EXPIRED;
1510 else
1511 #endif
1512 lease -> next_binding_state = FTS_FREE;
1513 break;
1514
1515 case FTS_EXPIRED:
1516 case FTS_RELEASED:
1517 case FTS_ABANDONED:
1518 case FTS_RESET:
1519 lease -> next_binding_state = FTS_FREE;
1520 /* If we are not in partner_down, leases don't go from
1521 EXPIRED to FREE on a timeout - only on an update.
1522 If we're in partner_down, they expire at mclt past
1523 the time we entered partner_down. */
1524 if (lease -> pool -> failover_peer &&
1525 lease -> pool -> failover_peer -> me.state == partner_down)
1526 lease -> tsfp =
1527 (lease -> pool -> failover_peer -> me.stos +
1528 lease -> pool -> failover_peer -> mclt);
1529 break;
1530
1531 case FTS_FREE:
1532 case FTS_BACKUP:
1533 lease -> next_binding_state = lease -> binding_state;
1534 break;
1535 }
1536 #if defined (DEBUG_LEASE_STATE_TRANSITIONS)
1537 log_debug ("lease %s: next binding state %s",
1538 piaddr (lease -> ip_addr),
1539 binding_state_print (lease -> next_binding_state));
1540 #endif
1541
1542 }
1543
1544 /* Copy the contents of one lease into another, correctly maintaining
1545 reference counts. */
1546 int lease_copy (struct lease **lp,
1547 struct lease *lease, const char *file, int line)
1548 {
1549 struct lease *lt = (struct lease *)0;
1550 isc_result_t status;
1551
1552 status = lease_allocate (&lt, MDL);
1553 if (status != ISC_R_SUCCESS)
1554 return 0;
1555
1556 lt -> ip_addr = lease -> ip_addr;
1557 lt -> starts = lease -> starts;
1558 lt -> ends = lease -> ends;
1559 lt -> uid_len = lease -> uid_len;
1560 lt -> uid_max = lease -> uid_max;
1561 if (lease -> uid == lease -> uid_buf) {
1562 lt -> uid = lt -> uid_buf;
1563 memcpy (lt -> uid_buf, lease -> uid_buf, sizeof lt -> uid_buf);
1564 } else if (!lease -> uid_max) {
1565 lt -> uid = (unsigned char *)0;
1566 } else {
1567 lt -> uid = dmalloc (lt -> uid_max, MDL);
1568 if (!lt -> uid) {
1569 lease_dereference (&lt, MDL);
1570 return 0;
1571 }
1572 memcpy (lt -> uid, lease -> uid, lease -> uid_max);
1573 }
1574 if (lease -> client_hostname) {
1575 lt -> client_hostname =
1576 dmalloc (strlen (lease -> client_hostname) + 1, MDL);
1577 if (!lt -> client_hostname) {
1578 lease_dereference (&lt, MDL);
1579 return 0;
1580 }
1581 strcpy (lt -> client_hostname, lease -> client_hostname);
1582 }
1583 if (lease -> scope)
1584 binding_scope_reference (&lt -> scope, lease -> scope, MDL);
1585 if (lease -> agent_options)
1586 option_chain_head_reference (&lt -> agent_options,
1587 lease -> agent_options, MDL);
1588 host_reference (&lt -> host, lease -> host, file, line);
1589 subnet_reference (&lt -> subnet, lease -> subnet, file, line);
1590 pool_reference (&lt -> pool, lease -> pool, file, line);
1591 class_reference (&lt -> billing_class,
1592 lease -> billing_class, file, line);
1593 lt -> hardware_addr = lease -> hardware_addr;
1594 if (lease -> on_expiry)
1595 executable_statement_reference (&lt -> on_expiry,
1596 lease -> on_expiry,
1597 file, line);
1598 if (lease -> on_commit)
1599 executable_statement_reference (&lt -> on_commit,
1600 lease -> on_commit,
1601 file, line);
1602 if (lease -> on_release)
1603 executable_statement_reference (&lt -> on_release,
1604 lease -> on_release,
1605 file, line);
1606 lt->flags = lease->flags;
1607 lt->tstp = lease->tstp;
1608 lt->tsfp = lease->tsfp;
1609 lt->atsfp = lease->atsfp;
1610 lt->cltt = lease -> cltt;
1611 lt->binding_state = lease->binding_state;
1612 lt->next_binding_state = lease->next_binding_state;
1613 status = lease_reference(lp, lt, file, line);
1614 lease_dereference(&lt, MDL);
1615 return status == ISC_R_SUCCESS;
1616 }
1617
1618 /* Release the specified lease and re-hash it as appropriate. */
1619 void release_lease (lease, packet)
1620 struct lease *lease;
1621 struct packet *packet;
1622 {
1623 /* If there are statements to execute when the lease is
1624 released, execute them. */
1625 #if defined (NSUPDATE)
1626 ddns_removals(lease, NULL);
1627 #endif
1628 if (lease -> on_release) {
1629 execute_statements ((struct binding_value **)0,
1630 packet, lease, (struct client_state *)0,
1631 packet -> options,
1632 (struct option_state *)0, /* XXX */
1633 &lease -> scope, lease -> on_release);
1634 if (lease -> on_release)
1635 executable_statement_dereference (&lease -> on_release,
1636 MDL);
1637 }
1638
1639 /* We do either the on_release or the on_expiry events, but
1640 not both (it's possible that they could be the same,
1641 in any case). */
1642 if (lease -> on_expiry)
1643 executable_statement_dereference (&lease -> on_expiry, MDL);
1644
1645 if (lease -> binding_state != FTS_FREE &&
1646 lease -> binding_state != FTS_BACKUP &&
1647 lease -> binding_state != FTS_RELEASED &&
1648 lease -> binding_state != FTS_EXPIRED &&
1649 lease -> binding_state != FTS_RESET) {
1650 if (lease -> on_commit)
1651 executable_statement_dereference (&lease -> on_commit,
1652 MDL);
1653
1654 /* Blow away any bindings. */
1655 if (lease -> scope)
1656 binding_scope_dereference (&lease -> scope, MDL);
1657
1658 /* Set sort times to the present. */
1659 lease -> ends = cur_time;
1660 /* Lower layers of muckery set tstp to ->ends. But we send
1661 * protocol messages before this. So it is best to set
1662 * tstp now anyway.
1663 */
1664 lease->tstp = cur_time;
1665 #if defined (FAILOVER_PROTOCOL)
1666 if (lease -> pool && lease -> pool -> failover_peer) {
1667 lease -> next_binding_state = FTS_RELEASED;
1668 } else {
1669 lease -> next_binding_state = FTS_FREE;
1670 }
1671 #else
1672 lease -> next_binding_state = FTS_FREE;
1673 #endif
1674 supersede_lease (lease, (struct lease *)0, 1, 1, 1);
1675 }
1676 }
1677
1678 /* Abandon the specified lease (set its timeout to infinity and its
1679 particulars to zero, and re-hash it as appropriate. */
1680
1681 void abandon_lease (lease, message)
1682 struct lease *lease;
1683 const char *message;
1684 {
1685 struct lease *lt = (struct lease *)0;
1686 #if defined (NSUPDATE)
1687 ddns_removals(lease, NULL);
1688 #endif
1689
1690 if (!lease_copy (&lt, lease, MDL))
1691 return;
1692
1693 if (lt->scope)
1694 binding_scope_dereference(&lt->scope, MDL);
1695
1696 lt -> ends = cur_time; /* XXX */
1697 lt -> next_binding_state = FTS_ABANDONED;
1698
1699 log_error ("Abandoning IP address %s: %s",
1700 piaddr (lease -> ip_addr), message);
1701 lt -> hardware_addr.hlen = 0;
1702 if (lt -> uid && lt -> uid != lt -> uid_buf)
1703 dfree (lt -> uid, MDL);
1704 lt -> uid = (unsigned char *)0;
1705 lt -> uid_len = 0;
1706 lt -> uid_max = 0;
1707 supersede_lease (lease, lt, 1, 1, 1);
1708 lease_dereference (&lt, MDL);
1709 }
1710
1711 /* Abandon the specified lease (set its timeout to infinity and its
1712 particulars to zero, and re-hash it as appropriate. */
1713
1714 void dissociate_lease (lease)
1715 struct lease *lease;
1716 {
1717 struct lease *lt = (struct lease *)0;
1718 #if defined (NSUPDATE)
1719 ddns_removals(lease, NULL);
1720 #endif
1721
1722 if (!lease_copy (&lt, lease, MDL))
1723 return;
1724
1725 #if defined (FAILOVER_PROTOCOL)
1726 if (lease -> pool && lease -> pool -> failover_peer) {
1727 lt -> next_binding_state = FTS_RESET;
1728 } else {
1729 lt -> next_binding_state = FTS_FREE;
1730 }
1731 #else
1732 lt -> next_binding_state = FTS_FREE;
1733 #endif
1734 lt -> ends = cur_time; /* XXX */
1735 lt -> hardware_addr.hlen = 0;
1736 if (lt -> uid && lt -> uid != lt -> uid_buf)
1737 dfree (lt -> uid, MDL);
1738 lt -> uid = (unsigned char *)0;
1739 lt -> uid_len = 0;
1740 lt -> uid_max = 0;
1741 supersede_lease (lease, lt, 1, 1, 1);
1742 lease_dereference (&lt, MDL);
1743 }
1744
1745 /* Timer called when a lease in a particular pool expires. */
1746 void pool_timer (vpool)
1747 void *vpool;
1748 {
1749 struct pool *pool;
1750 struct lease *next = (struct lease *)0;
1751 struct lease *lease = (struct lease *)0;
1752 #define FREE_LEASES 0
1753 #define ACTIVE_LEASES 1
1754 #define EXPIRED_LEASES 2
1755 #define ABANDONED_LEASES 3
1756 #define BACKUP_LEASES 4
1757 #define RESERVED_LEASES 5
1758 struct lease **lptr[RESERVED_LEASES+1];
1759 TIME next_expiry = MAX_TIME;
1760 int i;
1761
1762 pool = (struct pool *)vpool;
1763
1764 lptr [FREE_LEASES] = &pool -> free;
1765 lptr [ACTIVE_LEASES] = &pool -> active;
1766 lptr [EXPIRED_LEASES] = &pool -> expired;
1767 lptr [ABANDONED_LEASES] = &pool -> abandoned;
1768 lptr [BACKUP_LEASES] = &pool -> backup;
1769 lptr[RESERVED_LEASES] = &pool->reserved;
1770
1771 for (i = FREE_LEASES; i <= RESERVED_LEASES; i++) {
1772 /* If there's nothing on the queue, skip it. */
1773 if (!*(lptr [i]))
1774 continue;
1775
1776 #if defined (FAILOVER_PROTOCOL)
1777 if (pool -> failover_peer &&
1778 pool -> failover_peer -> me.state != partner_down) {
1779 /* The secondary can't remove a lease from the
1780 active state except in partner_down. */
1781 if (i == ACTIVE_LEASES &&
1782 pool -> failover_peer -> i_am == secondary)
1783 continue;
1784 /* Leases in an expired state don't move to
1785 free because of a timeout unless we're in
1786 partner_down. */
1787 if (i == EXPIRED_LEASES)
1788 continue;
1789 }
1790 #endif
1791 lease_reference (&lease, *(lptr [i]), MDL);
1792
1793 while (lease) {
1794 /* Remember the next lease in the list. */
1795 if (next)
1796 lease_dereference (&next, MDL);
1797 if (lease -> next)
1798 lease_reference (&next, lease -> next, MDL);
1799
1800 /* If we've run out of things to expire on this list,
1801 stop. */
1802 if (lease -> sort_time > cur_time) {
1803 if (lease -> sort_time < next_expiry)
1804 next_expiry = lease -> sort_time;
1805 break;
1806 }
1807
1808 /* If there is a pending state change, and
1809 this lease has gotten to the time when the
1810 state change should happen, just call
1811 supersede_lease on it to make the change
1812 happen. */
1813 if (lease -> next_binding_state !=
1814 lease -> binding_state)
1815 supersede_lease (lease,
1816 (struct lease *)0, 1, 1, 1);
1817
1818 lease_dereference (&lease, MDL);
1819 if (next)
1820 lease_reference (&lease, next, MDL);
1821 }
1822 if (next)
1823 lease_dereference (&next, MDL);
1824 if (lease)
1825 lease_dereference (&lease, MDL);
1826 }
1827 if (next_expiry != MAX_TIME) {
1828 pool -> next_event_time = next_expiry;
1829 add_timeout (pool -> next_event_time, pool_timer, pool,
1830 (tvref_t)pool_reference,
1831 (tvunref_t)pool_dereference);
1832 } else
1833 pool -> next_event_time = MIN_TIME;
1834
1835 }
1836
1837 /* Locate the lease associated with a given IP address... */
1838
1839 int find_lease_by_ip_addr (struct lease **lp, struct iaddr addr,
1840 const char *file, int line)
1841 {
1842 return lease_ip_hash_lookup(lp, lease_ip_addr_hash, addr.iabuf,
1843 addr.len, file, line);
1844 }
1845
1846 int find_lease_by_uid (struct lease **lp, const unsigned char *uid,
1847 unsigned len, const char *file, int line)
1848 {
1849 if (len == 0)
1850 return 0;
1851 return lease_id_hash_lookup (lp, lease_uid_hash, uid, len, file, line);
1852 }
1853
1854 int find_lease_by_hw_addr (struct lease **lp,
1855 const unsigned char *hwaddr, unsigned hwlen,
1856 const char *file, int line)
1857 {
1858 if (hwlen == 0)
1859 return 0;
1860 return lease_id_hash_lookup(lp, lease_hw_addr_hash, hwaddr, hwlen,
1861 file, line);
1862 }
1863
1864 /* If the lease is preferred over the candidate, return truth. The
1865 * 'cand' and 'lease' names are retained to read more clearly against
1866 * the 'uid_hash_add' and 'hw_hash_add' functions (this is common logic
1867 * to those two functions).
1868 *
1869 * 1) ACTIVE leases are preferred. The active lease with
1870 * the longest lifetime is preferred over shortest.
1871 * 2) "transitional states" are next, this time with the
1872 * most recent CLTT.
1873 * 3) free/backup/etc states are next, again with CLTT. In truth we
1874 * should never see reset leases for this.
1875 * 4) Abandoned leases are always dead last.
1876 */
1877 static isc_boolean_t
1878 client_lease_preferred(struct lease *cand, struct lease *lease)
1879 {
1880 if (cand->binding_state == FTS_ACTIVE) {
1881 if (lease->binding_state == FTS_ACTIVE &&
1882 lease->ends >= cand->ends)
1883 return ISC_TRUE;
1884 } else if (cand->binding_state == FTS_EXPIRED ||
1885 cand->binding_state == FTS_RELEASED) {
1886 if (lease->binding_state == FTS_ACTIVE)
1887 return ISC_TRUE;
1888
1889 if ((lease->binding_state == FTS_EXPIRED ||
1890 lease->binding_state == FTS_RELEASED) &&
1891 lease->cltt >= cand->cltt)
1892 return ISC_TRUE;
1893 } else if (cand->binding_state != FTS_ABANDONED) {
1894 if (lease->binding_state == FTS_ACTIVE ||
1895 lease->binding_state == FTS_EXPIRED ||
1896 lease->binding_state == FTS_RELEASED)
1897 return ISC_TRUE;
1898
1899 if (lease->binding_state != FTS_ABANDONED &&
1900 lease->cltt >= cand->cltt)
1901 return ISC_TRUE;
1902 } else /* (cand->binding_state == FTS_ABANDONED) */ {
1903 if (lease->binding_state != FTS_ABANDONED ||
1904 lease->cltt >= cand->cltt)
1905 return ISC_TRUE;
1906 }
1907
1908 return ISC_FALSE;
1909 }
1910
1911 /* Add the specified lease to the uid hash. */
1912 void
1913 uid_hash_add(struct lease *lease)
1914 {
1915 struct lease *head = NULL;
1916 struct lease *cand = NULL;
1917 struct lease *prev = NULL;
1918 struct lease *next = NULL;
1919
1920 /* If it's not in the hash, just add it. */
1921 if (!find_lease_by_uid (&head, lease -> uid, lease -> uid_len, MDL))
1922 lease_id_hash_add(lease_uid_hash, lease->uid, lease->uid_len,
1923 lease, MDL);
1924 else {
1925 /* Otherwise, insert it into the list in order of its
1926 * preference for "resuming allocation to the client."
1927 *
1928 * Because we don't have control of the hash bucket index
1929 * directly, we have to remove and re-insert the client
1930 * id into the hash if we're inserting onto the head.
1931 */
1932 lease_reference(&cand, head, MDL);
1933 while (cand != NULL) {
1934 if (client_lease_preferred(cand, lease))
1935 break;
1936
1937 if (prev != NULL)
1938 lease_dereference(&prev, MDL);
1939 lease_reference(&prev, cand, MDL);
1940
1941 if (cand->n_uid != NULL)
1942 lease_reference(&next, cand->n_uid, MDL);
1943
1944 lease_dereference(&cand, MDL);
1945
1946 if (next != NULL) {
1947 lease_reference(&cand, next, MDL);
1948 lease_dereference(&next, MDL);
1949 }
1950 }
1951
1952 /* If we want to insert 'before cand', and prev is NULL,
1953 * then it was the head of the list. Assume that position.
1954 */
1955 if (prev == NULL) {
1956 lease_reference(&lease->n_uid, head, MDL);
1957 lease_id_hash_delete(lease_uid_hash, lease->uid,
1958 lease->uid_len, MDL);
1959 lease_id_hash_add(lease_uid_hash, lease->uid,
1960 lease->uid_len, lease, MDL);
1961 } else /* (prev != NULL) */ {
1962 if(prev->n_uid != NULL) {
1963 lease_reference(&lease->n_uid, prev->n_uid,
1964 MDL);
1965 lease_dereference(&prev->n_uid, MDL);
1966 }
1967 lease_reference(&prev->n_uid, lease, MDL);
1968
1969 lease_dereference(&prev, MDL);
1970 }
1971
1972 if (cand != NULL)
1973 lease_dereference(&cand, MDL);
1974 lease_dereference(&head, MDL);
1975 }
1976 }
1977
1978 /* Delete the specified lease from the uid hash. */
1979
1980 void uid_hash_delete (lease)
1981 struct lease *lease;
1982 {
1983 struct lease *head = (struct lease *)0;
1984 struct lease *scan;
1985
1986 /* If it's not in the hash, we have no work to do. */
1987 if (!find_lease_by_uid (&head, lease -> uid, lease -> uid_len, MDL)) {
1988 if (lease -> n_uid)
1989 lease_dereference (&lease -> n_uid, MDL);
1990 return;
1991 }
1992
1993 /* If the lease we're freeing is at the head of the list,
1994 remove the hash table entry and add a new one with the
1995 next lease on the list (if there is one). */
1996 if (head == lease) {
1997 lease_id_hash_delete(lease_uid_hash, lease->uid,
1998 lease->uid_len, MDL);
1999 if (lease -> n_uid) {
2000 lease_id_hash_add(lease_uid_hash, lease->n_uid->uid,
2001 lease->n_uid->uid_len, lease->n_uid,
2002 MDL);
2003 lease_dereference (&lease -> n_uid, MDL);
2004 }
2005 } else {
2006 /* Otherwise, look for the lease in the list of leases
2007 attached to the hash table entry, and remove it if
2008 we find it. */
2009 for (scan = head; scan -> n_uid; scan = scan -> n_uid) {
2010 if (scan -> n_uid == lease) {
2011 lease_dereference (&scan -> n_uid, MDL);
2012 if (lease -> n_uid) {
2013 lease_reference (&scan -> n_uid,
2014 lease -> n_uid, MDL);
2015 lease_dereference (&lease -> n_uid,
2016 MDL);
2017 }
2018 break;
2019 }
2020 }
2021 }
2022 lease_dereference (&head, MDL);
2023 }
2024
2025 /* Add the specified lease to the hardware address hash. */
2026
2027 void
2028 hw_hash_add(struct lease *lease)
2029 {
2030 struct lease *head = NULL;
2031 struct lease *cand = NULL;
2032 struct lease *prev = NULL;
2033 struct lease *next = NULL;
2034
2035 /* If it's not in the hash, just add it. */
2036 if (!find_lease_by_hw_addr (&head, lease -> hardware_addr.hbuf,
2037 lease -> hardware_addr.hlen, MDL))
2038 lease_id_hash_add(lease_hw_addr_hash,
2039 lease->hardware_addr.hbuf,
2040 lease->hardware_addr.hlen, lease, MDL);
2041 else {
2042 /* Otherwise, insert it into the list in order of its
2043 * preference for "resuming allocation to the client."
2044 *
2045 * Because we don't have control of the hash bucket index
2046 * directly, we have to remove and re-insert the client
2047 * id into the hash if we're inserting onto the head.
2048 */
2049 lease_reference(&cand, head, MDL);
2050 while (cand != NULL) {
2051 if (client_lease_preferred(cand, lease))
2052 break;
2053
2054 if (prev != NULL)
2055 lease_dereference(&prev, MDL);
2056 lease_reference(&prev, cand, MDL);
2057
2058 if (cand->n_hw != NULL)
2059 lease_reference(&next, cand->n_hw, MDL);
2060
2061 lease_dereference(&cand, MDL);
2062
2063 if (next != NULL) {
2064 lease_reference(&cand, next, MDL);
2065 lease_dereference(&next, MDL);
2066 }
2067 }
2068
2069 /* If we want to insert 'before cand', and prev is NULL,
2070 * then it was the head of the list. Assume that position.
2071 */
2072 if (prev == NULL) {
2073 lease_reference(&lease->n_hw, head, MDL);
2074 lease_id_hash_delete(lease_hw_addr_hash,
2075 lease->hardware_addr.hbuf,
2076 lease->hardware_addr.hlen, MDL);
2077 lease_id_hash_add(lease_hw_addr_hash,
2078 lease->hardware_addr.hbuf,
2079 lease->hardware_addr.hlen,
2080 lease, MDL);
2081 } else /* (prev != NULL) */ {
2082 if(prev->n_hw != NULL) {
2083 lease_reference(&lease->n_hw, prev->n_hw,
2084 MDL);
2085 lease_dereference(&prev->n_hw, MDL);
2086 }
2087 lease_reference(&prev->n_hw, lease, MDL);
2088
2089 lease_dereference(&prev, MDL);
2090 }
2091
2092 if (cand != NULL)
2093 lease_dereference(&cand, MDL);
2094 lease_dereference(&head, MDL);
2095 }
2096 }
2097
2098 /* Delete the specified lease from the hardware address hash. */
2099
2100 void hw_hash_delete (lease)
2101 struct lease *lease;
2102 {
2103 struct lease *head = (struct lease *)0;
2104 struct lease *next = (struct lease *)0;
2105
2106 /* If it's not in the hash, we have no work to do. */
2107 if (!find_lease_by_hw_addr (&head, lease -> hardware_addr.hbuf,
2108 lease -> hardware_addr.hlen, MDL)) {
2109 if (lease -> n_hw)
2110 lease_dereference (&lease -> n_hw, MDL);
2111 return;
2112 }
2113
2114 /* If the lease we're freeing is at the head of the list,
2115 remove the hash table entry and add a new one with the
2116 next lease on the list (if there is one). */
2117 if (head == lease) {
2118 lease_id_hash_delete(lease_hw_addr_hash,
2119 lease->hardware_addr.hbuf,
2120 lease->hardware_addr.hlen, MDL);
2121 if (lease->n_hw) {
2122 lease_id_hash_add(lease_hw_addr_hash,
2123 lease->n_hw->hardware_addr.hbuf,
2124 lease->n_hw->hardware_addr.hlen,
2125 lease->n_hw, MDL);
2126 lease_dereference(&lease->n_hw, MDL);
2127 }
2128 } else {
2129 /* Otherwise, look for the lease in the list of leases
2130 attached to the hash table entry, and remove it if
2131 we find it. */
2132 while (head -> n_hw) {
2133 if (head -> n_hw == lease) {
2134 lease_dereference (&head -> n_hw, MDL);
2135 if (lease -> n_hw) {
2136 lease_reference (&head -> n_hw,
2137 lease -> n_hw, MDL);
2138 lease_dereference (&lease -> n_hw,
2139 MDL);
2140 }
2141 break;
2142 }
2143 lease_reference (&next, head -> n_hw, MDL);
2144 lease_dereference (&head, MDL);
2145 lease_reference (&head, next, MDL);
2146 lease_dereference (&next, MDL);
2147 }
2148 }
2149 if (head)
2150 lease_dereference (&head, MDL);
2151 }
2152
2153 /* Write all interesting leases to permanent storage. */
2154
2155 int write_leases ()
2156 {
2157 struct lease *l;
2158 struct shared_network *s;
2159 struct pool *p;
2160 struct host_decl *hp;
2161 struct group_object *gp;
2162 struct hash_bucket *hb;
2163 struct class *cp;
2164 struct collection *colp;
2165 int i;
2166 int num_written;
2167 struct lease **lptr[RESERVED_LEASES+1];
2168
2169 /* write all the dynamically-created class declarations. */
2170 if (collections->classes) {
2171 numclasseswritten = 0;
2172 for (colp = collections ; colp ; colp = colp->next) {
2173 for (cp = colp->classes ; cp ; cp = cp->nic) {
2174 write_named_billing_class(
2175 (unsigned char *)cp->name,
2176 0, cp);
2177 }
2178 }
2179
2180 /* XXXJAB this number doesn't include subclasses... */
2181 log_info ("Wrote %d class decls to leases file.",
2182 numclasseswritten);
2183 }
2184
2185
2186 /* Write all the dynamically-created group declarations. */
2187 if (group_name_hash) {
2188 num_written = 0;
2189 for (i = 0; i < group_name_hash -> hash_count; i++) {
2190 for (hb = group_name_hash -> buckets [i];
2191 hb; hb = hb -> next) {
2192 gp = (struct group_object *)hb -> value;
2193 if ((gp -> flags & GROUP_OBJECT_DYNAMIC) ||
2194 ((gp -> flags & GROUP_OBJECT_STATIC) &&
2195 (gp -> flags & GROUP_OBJECT_DELETED))) {
2196 if (!write_group (gp))
2197 return 0;
2198 ++num_written;
2199 }
2200 }
2201 }
2202 log_info ("Wrote %d group decls to leases file.", num_written);
2203 }
2204
2205 /* Write all the deleted host declarations. */
2206 if (host_name_hash) {
2207 num_written = 0;
2208 for (i = 0; i < host_name_hash -> hash_count; i++) {
2209 for (hb = host_name_hash -> buckets [i];
2210 hb; hb = hb -> next) {
2211 hp = (struct host_decl *)hb -> value;
2212 if (((hp -> flags & HOST_DECL_STATIC) &&
2213 (hp -> flags & HOST_DECL_DELETED))) {
2214 if (!write_host (hp))
2215 return 0;
2216 ++num_written;
2217 }
2218 }
2219 }
2220 log_info ("Wrote %d deleted host decls to leases file.",
2221 num_written);
2222 }
2223
2224 /* Write all the new, dynamic host declarations. */
2225 if (host_name_hash) {
2226 num_written = 0;
2227 for (i = 0; i < host_name_hash -> hash_count; i++) {
2228 for (hb = host_name_hash -> buckets [i];
2229 hb; hb = hb -> next) {
2230 hp = (struct host_decl *)hb -> value;
2231 if ((hp -> flags & HOST_DECL_DYNAMIC)) {
2232 if (!write_host (hp))
2233 ++num_written;
2234 }
2235 }
2236 }
2237 log_info ("Wrote %d new dynamic host decls to leases file.",
2238 num_written);
2239 }
2240
2241 #if defined (FAILOVER_PROTOCOL)
2242 /* Write all the failover states. */
2243 if (!dhcp_failover_write_all_states ())
2244 return 0;
2245 #endif
2246
2247 /* Write all the leases. */
2248 num_written = 0;
2249 for (s = shared_networks; s; s = s -> next) {
2250 for (p = s -> pools; p; p = p -> next) {
2251 lptr [FREE_LEASES] = &p -> free;
2252 lptr [ACTIVE_LEASES] = &p -> active;
2253 lptr [EXPIRED_LEASES] = &p -> expired;
2254 lptr [ABANDONED_LEASES] = &p -> abandoned;
2255 lptr [BACKUP_LEASES] = &p -> backup;
2256 lptr [RESERVED_LEASES] = &p->reserved;
2257
2258 for (i = FREE_LEASES; i <= RESERVED_LEASES; i++) {
2259 for (l = *(lptr [i]); l; l = l -> next) {
2260 #if !defined (DEBUG_DUMP_ALL_LEASES)
2261 if (l -> hardware_addr.hlen ||
2262 l -> uid_len ||
2263 (l -> binding_state != FTS_FREE))
2264 #endif
2265 {
2266 if (!write_lease (l))
2267 return 0;
2268 num_written++;
2269 }
2270 }
2271 }
2272 }
2273 }
2274 log_info ("Wrote %d leases to leases file.", num_written);
2275 #ifdef DHCPv6
2276 if (!write_leases6()) {
2277 return 0;
2278 }
2279 #endif /* DHCPv6 */
2280 if (!commit_leases ())
2281 return 0;
2282 return 1;
2283 }
2284
2285 /* In addition to placing this lease upon a lease queue depending on its
2286 * state, it also keeps track of the number of FREE and BACKUP leases in
2287 * existence, and sets the sort_time on the lease.
2288 *
2289 * Sort_time is used in pool_timer() to determine when the lease will
2290 * bubble to the top of the list and be supersede_lease()'d into its next
2291 * state (possibly, if all goes well). Example, ACTIVE leases move to
2292 * EXPIRED state when the 'ends' value is reached, so that is its sort
2293 * time. Most queues are sorted by 'ends', since it is generally best
2294 * practice to re-use the oldest lease, to reduce address collision
2295 * chances.
2296 */
2297 int lease_enqueue (struct lease *comp)
2298 {
2299 struct lease **lq, *prev, *lp;
2300 static struct lease **last_lq = NULL;
2301 static struct lease *last_insert_point = NULL;
2302
2303 /* No queue to put it on? */
2304 if (!comp -> pool)
2305 return 0;
2306
2307 /* Figure out which queue it's going to. */
2308 switch (comp -> binding_state) {
2309 case FTS_FREE:
2310 if (comp->flags & RESERVED_LEASE) {
2311 lq = &comp->pool->reserved;
2312 } else {
2313 lq = &comp->pool->free;
2314 comp->pool->free_leases++;
2315 }
2316 comp -> sort_time = comp -> ends;
2317 break;
2318
2319 case FTS_ACTIVE:
2320 lq = &comp -> pool -> active;
2321 comp -> sort_time = comp -> ends;
2322 break;
2323
2324 case FTS_EXPIRED:
2325 case FTS_RELEASED:
2326 case FTS_RESET:
2327 lq = &comp -> pool -> expired;
2328 #if defined(FAILOVER_PROTOCOL)
2329 /* In partner_down, tsfp is the time at which the lease
2330 * may be reallocated (stos+mclt). We can do that with
2331 * lease_mine_to_reallocate() anywhere between tsfp and
2332 * ends. But we prefer to wait until ends before doing it
2333 * automatically (choose the greater of the two). Note
2334 * that 'ends' is usually a historic timestamp in the
2335 * case of expired leases, is really only in the future
2336 * on released leases, and if we know a lease to be released
2337 * the peer might still know it to be active...in which case
2338 * it's possible the peer has renewed this lease, so avoid
2339 * doing that.
2340 */
2341 if (comp->pool->failover_peer &&
2342 comp->pool->failover_peer->me.state == partner_down)
2343 comp->sort_time = (comp->tsfp > comp->ends) ?
2344 comp->tsfp : comp->ends;
2345 else
2346 #endif
2347 comp->sort_time = comp->ends;
2348
2349 break;
2350
2351 case FTS_ABANDONED:
2352 lq = &comp -> pool -> abandoned;
2353 comp -> sort_time = comp -> ends;
2354 break;
2355
2356 case FTS_BACKUP:
2357 if (comp->flags & RESERVED_LEASE) {
2358 lq = &comp->pool->reserved;
2359 } else {
2360 lq = &comp->pool->backup;
2361 comp->pool->backup_leases++;
2362 }
2363 comp -> sort_time = comp -> ends;
2364 break;
2365
2366 default:
2367 log_error ("Lease with bogus binding state: %d",
2368 comp -> binding_state);
2369 #if defined (BINDING_STATE_DEBUG)
2370 abort ();
2371 #endif
2372 return 0;
2373 }
2374
2375 /* This only works during server startup: during runtime, the last
2376 * lease may be dequeued inbetween calls. If the queue is the same
2377 * as was used previously, and the lease structure isn't (this is not
2378 * a re-queue), use that as a starting point for the insertion-sort.
2379 */
2380 if ((server_starting & SS_QFOLLOW) && (lq == last_lq) &&
2381 (comp != last_insert_point) &&
2382 (last_insert_point->sort_time <= comp->sort_time)) {
2383 prev = last_insert_point;
2384 lp = prev->next;
2385 } else {
2386 prev = NULL;
2387 lp = *lq;
2388 }
2389
2390 /* Insertion sort the lease onto the appropriate queue. */
2391 for (; lp ; lp = lp->next) {
2392 if (lp -> sort_time >= comp -> sort_time)
2393 break;
2394 prev = lp;
2395 }
2396
2397 if (prev) {
2398 if (prev -> next) {
2399 lease_reference (&comp -> next, prev -> next, MDL);
2400 lease_dereference (&prev -> next, MDL);
2401 }
2402 lease_reference (&prev -> next, comp, MDL);
2403 } else {
2404 if (*lq) {
2405 lease_reference (&comp -> next, *lq, MDL);
2406 lease_dereference (lq, MDL);
2407 }
2408 lease_reference (lq, comp, MDL);
2409 }
2410 last_insert_point = comp;
2411 last_lq = lq;
2412 return 1;
2413 }
2414
2415 /* For a given lease, sort it onto the right list in its pool and put it
2416 in each appropriate hash, understanding that it's already by definition
2417 in lease_ip_addr_hash. */
2418
2419 isc_result_t
2420 lease_instantiate(const void *key, unsigned len, void *object)
2421 {
2422 struct lease *lease = object;
2423 struct class *class;
2424 /* XXX If the lease doesn't have a pool at this point, it's an
2425 XXX orphan, which we *should* keep around until it expires,
2426 XXX but which right now we just forget. */
2427 if (!lease -> pool) {
2428 lease_ip_hash_delete(lease_ip_addr_hash, lease->ip_addr.iabuf,
2429 lease->ip_addr.len, MDL);
2430 return ISC_R_SUCCESS;
2431 }
2432
2433 /* Put the lease on the right queue. Failure to queue is probably
2434 * due to a bogus binding state. In such a case, we claim success,
2435 * so that later leases in a hash_foreach are processed, but we
2436 * return early as we really don't want hw address hash entries or
2437 * other cruft to surround such a bogus entry.
2438 */
2439 if (!lease_enqueue(lease))
2440 return ISC_R_SUCCESS;
2441
2442 /* Record the lease in the uid hash if possible. */
2443 if (lease -> uid) {
2444 uid_hash_add (lease);
2445 }
2446
2447 /* Record it in the hardware address hash if possible. */
2448 if (lease -> hardware_addr.hlen) {
2449 hw_hash_add (lease);
2450 }
2451
2452 /* If the lease has a billing class, set up the billing. */
2453 if (lease -> billing_class) {
2454 class = (struct class *)0;
2455 class_reference (&class, lease -> billing_class, MDL);
2456 class_dereference (&lease -> billing_class, MDL);
2457 /* If the lease is available for allocation, the billing
2458 is invalid, so we don't keep it. */
2459 if (lease -> binding_state == FTS_ACTIVE ||
2460 lease -> binding_state == FTS_EXPIRED ||
2461 lease -> binding_state == FTS_RELEASED ||
2462 lease -> binding_state == FTS_RESET)
2463 bill_class (lease, class);
2464 class_dereference (&class, MDL);
2465 }
2466 return ISC_R_SUCCESS;
2467 }
2468
2469 /* Run expiry events on every pool. This is called on startup so that
2470 any expiry events that occurred after the server stopped and before it
2471 was restarted can be run. At the same time, if failover support is
2472 compiled in, we compute the balance of leases for the pool. */
2473
2474 void expire_all_pools ()
2475 {
2476 struct shared_network *s;
2477 struct pool *p;
2478 int i;
2479 struct lease *l;
2480 struct lease **lptr[RESERVED_LEASES+1];
2481
2482 /* Indicate that we are in the startup phase */
2483 server_starting = SS_NOSYNC | SS_QFOLLOW;
2484
2485 /* First, go over the hash list and actually put all the leases
2486 on the appropriate lists. */
2487 lease_ip_hash_foreach(lease_ip_addr_hash, lease_instantiate);
2488
2489 /* Loop through each pool in each shared network and call the
2490 * expiry routine on the pool. It is no longer safe to follow
2491 * the queue insertion point, as expiration of a lease can move
2492 * it between queues (and this may be the lease that function
2493 * points at).
2494 */
2495 server_starting &= ~SS_QFOLLOW;
2496 for (s = shared_networks; s; s = s -> next) {
2497 for (p = s -> pools; p; p = p -> next) {
2498 pool_timer (p);
2499
2500 p -> lease_count = 0;
2501 p -> free_leases = 0;
2502 p -> backup_leases = 0;
2503
2504 lptr [FREE_LEASES] = &p -> free;
2505 lptr [ACTIVE_LEASES] = &p -> active;
2506 lptr [EXPIRED_LEASES] = &p -> expired;
2507 lptr [ABANDONED_LEASES] = &p -> abandoned;
2508 lptr [BACKUP_LEASES] = &p -> backup;
2509 lptr [RESERVED_LEASES] = &p->reserved;
2510
2511 for (i = FREE_LEASES; i <= RESERVED_LEASES; i++) {
2512 for (l = *(lptr [i]); l; l = l -> next) {
2513 p -> lease_count++;
2514 if (l -> ends <= cur_time) {
2515 if (l->binding_state == FTS_FREE) {
2516 if (i == FREE_LEASES)
2517 p->free_leases++;
2518 else if (i != RESERVED_LEASES)
2519 log_fatal("Impossible case "
2520 "at %s:%d.", MDL);
2521 } else if (l->binding_state == FTS_BACKUP) {
2522 if (i == BACKUP_LEASES)
2523 p->backup_leases++;
2524 else if (i != RESERVED_LEASES)
2525 log_fatal("Impossible case "
2526 "at %s:%d.", MDL);
2527 }
2528 }
2529 #if defined (FAILOVER_PROTOCOL)
2530 if (p -> failover_peer &&
2531 l -> tstp > l -> atsfp &&
2532 !(l -> flags & ON_UPDATE_QUEUE)) {
2533 l -> desired_binding_state = l -> binding_state;
2534 dhcp_failover_queue_update (l, 1);
2535 }
2536 #endif
2537 }
2538 }
2539 }
2540 }
2541
2542 /* turn off startup phase */
2543 server_starting = 0;
2544 }
2545
2546 void dump_subnets ()
2547 {
2548 struct lease *l;
2549 struct shared_network *s;
2550 struct subnet *n;
2551 struct pool *p;
2552 struct lease **lptr[RESERVED_LEASES+1];
2553 int i;
2554
2555 log_info ("Subnets:");
2556 for (n = subnets; n; n = n -> next_subnet) {
2557 log_debug (" Subnet %s", piaddr (n -> net));
2558 log_debug (" netmask %s",
2559 piaddr (n -> netmask));
2560 }
2561 log_info ("Shared networks:");
2562 for (s = shared_networks; s; s = s -> next) {
2563 log_info (" %s", s -> name);
2564 for (p = s -> pools; p; p = p -> next) {
2565 lptr [FREE_LEASES] = &p -> free;
2566 lptr [ACTIVE_LEASES] = &p -> active;
2567 lptr [EXPIRED_LEASES] = &p -> expired;
2568 lptr [ABANDONED_LEASES] = &p -> abandoned;
2569 lptr [BACKUP_LEASES] = &p -> backup;
2570 lptr [RESERVED_LEASES] = &p->reserved;
2571
2572 for (i = FREE_LEASES; i <= RESERVED_LEASES; i++) {
2573 for (l = *(lptr [i]); l; l = l -> next) {
2574 print_lease (l);
2575 }
2576 }
2577 }
2578 }
2579 }
2580
2581 HASH_FUNCTIONS(lease_ip, const unsigned char *, struct lease, lease_ip_hash_t,
2582 lease_reference, lease_dereference, do_ip4_hash)
2583 HASH_FUNCTIONS(lease_id, const unsigned char *, struct lease, lease_id_hash_t,
2584 lease_reference, lease_dereference, do_id_hash)
2585 HASH_FUNCTIONS (host, const unsigned char *, struct host_decl, host_hash_t,
2586 host_reference, host_dereference, do_string_hash)
2587 HASH_FUNCTIONS (class, const char *, struct class, class_hash_t,
2588 class_reference, class_dereference, do_string_hash)
2589
2590 #if defined (DEBUG_MEMORY_LEAKAGE) && \
2591 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
2592 extern struct hash_table *dns_zone_hash;
2593 extern struct interface_info **interface_vector;
2594 extern int interface_count;
2595 dhcp_control_object_t *dhcp_control_object;
2596 extern struct hash_table *auth_key_hash;
2597 struct hash_table *universe_hash;
2598 struct universe **universes;
2599 int universe_count, universe_max;
2600 #if 0
2601 extern int end;
2602 #endif
2603
2604 #if defined (COMPACT_LEASES)
2605 extern struct lease *lease_hunks;
2606 #endif
2607
2608 void free_everything ()
2609 {
2610 struct subnet *sc = (struct subnet *)0, *sn = (struct subnet *)0;
2611 struct shared_network *nc = (struct shared_network *)0,
2612 *nn = (struct shared_network *)0;
2613 struct pool *pc = (struct pool *)0, *pn = (struct pool *)0;
2614 struct lease *lc = (struct lease *)0, *ln = (struct lease *)0;
2615 struct interface_info *ic = (struct interface_info *)0,
2616 *in = (struct interface_info *)0;
2617 struct class *cc = (struct class *)0, *cn = (struct class *)0;
2618 struct collection *lp;
2619 void *st = (shared_networks
2620 ? (shared_networks -> next
2621 ? shared_networks -> next -> next : 0) : 0);
2622 int i;
2623
2624
2625 /* Get rid of all the hash tables. */
2626 if (host_hw_addr_hash)
2627 host_free_hash_table (&host_hw_addr_hash, MDL);
2628 host_hw_addr_hash = 0;
2629 if (host_uid_hash)
2630 host_free_hash_table (&host_uid_hash, MDL);
2631 host_uid_hash = 0;
2632 if (lease_uid_hash)
2633 lease_free_hash_table (&lease_uid_hash, MDL);
2634 lease_uid_hash = 0;
2635 if (lease_ip_addr_hash)
2636 lease_free_hash_table (&lease_ip_addr_hash, MDL);
2637 lease_ip_addr_hash = 0;
2638 if (lease_hw_addr_hash)
2639 lease_free_hash_table (&lease_hw_addr_hash, MDL);
2640 lease_hw_addr_hash = 0;
2641 if (host_name_hash)
2642 host_free_hash_table (&host_name_hash, MDL);
2643 host_name_hash = 0;
2644 if (dns_zone_hash)
2645 dns_zone_free_hash_table (&dns_zone_hash, MDL);
2646 dns_zone_hash = 0;
2647
2648 while (host_id_info != NULL) {
2649 host_id_info_t *tmp;
2650 option_dereference(&host_id_info->option, MDL);
2651 host_free_hash_table(&host_id_info->values_hash, MDL);
2652 tmp = host_id_info->next;
2653 dfree(host_id_info, MDL);
2654 host_id_info = tmp;
2655 }
2656 #if 0
2657 if (auth_key_hash)
2658 auth_key_free_hash_table (&auth_key_hash, MDL);
2659 #endif
2660 auth_key_hash = 0;
2661
2662 omapi_object_dereference ((omapi_object_t **)&dhcp_control_object,
2663 MDL);
2664
2665 for (lp = collections; lp; lp = lp -> next) {
2666 if (lp -> classes) {
2667 class_reference (&cn, lp -> classes, MDL);
2668 do {
2669 if (cn) {
2670 class_reference (&cc, cn, MDL);
2671 class_dereference (&cn, MDL);
2672 }
2673 if (cc -> nic) {
2674 class_reference (&cn, cc -> nic, MDL);
2675 class_dereference (&cc -> nic, MDL);
2676 }
2677 group_dereference (&cc -> group, MDL);
2678 if (cc -> hash) {
2679 class_free_hash_table (&cc -> hash, MDL);
2680 cc -> hash = (struct hash_table *)0;
2681 }
2682 class_dereference (&cc, MDL);
2683 } while (cn);
2684 class_dereference (&lp -> classes, MDL);
2685 }
2686 }
2687
2688 if (interface_vector) {
2689 for (i = 0; i < interface_count; i++) {
2690 if (interface_vector [i])
2691 interface_dereference (&interface_vector [i], MDL);
2692 }
2693 dfree (interface_vector, MDL);
2694 interface_vector = 0;
2695 }
2696
2697 if (interfaces) {
2698 interface_reference (&in, interfaces, MDL);
2699 do {
2700 if (in) {
2701 interface_reference (&ic, in, MDL);
2702 interface_dereference (&in, MDL);
2703 }
2704 if (ic -> next) {
2705 interface_reference (&in, ic -> next, MDL);
2706 interface_dereference (&ic -> next, MDL);
2707 }
2708 omapi_unregister_io_object ((omapi_object_t *)ic);
2709 if (ic -> shared_network) {
2710 if (ic -> shared_network -> interface)
2711 interface_dereference
2712 (&ic -> shared_network -> interface, MDL);
2713 shared_network_dereference (&ic -> shared_network, MDL);
2714 }
2715 interface_dereference (&ic, MDL);
2716 } while (in);
2717 interface_dereference (&interfaces, MDL);
2718 }
2719
2720 /* Subnets are complicated because of the extra links. */
2721 if (subnets) {
2722 subnet_reference (&sn, subnets, MDL);
2723 do {
2724 if (sn) {
2725 subnet_reference (&sc, sn, MDL);
2726 subnet_dereference (&sn, MDL);
2727 }
2728 if (sc -> next_subnet) {
2729 subnet_reference (&sn, sc -> next_subnet, MDL);
2730 subnet_dereference (&sc -> next_subnet, MDL);
2731 }
2732 if (sc -> next_sibling)
2733 subnet_dereference (&sc -> next_sibling, MDL);
2734 if (sc -> shared_network)
2735 shared_network_dereference (&sc -> shared_network, MDL);
2736 group_dereference (&sc -> group, MDL);
2737 if (sc -> interface)
2738 interface_dereference (&sc -> interface, MDL);
2739 subnet_dereference (&sc, MDL);
2740 } while (sn);
2741 subnet_dereference (&subnets, MDL);
2742 }
2743
2744 /* So are shared networks. */
2745 if (shared_networks) {
2746 shared_network_reference (&nn, shared_networks, MDL);
2747 do {
2748 if (nn) {
2749 shared_network_reference (&nc, nn, MDL);
2750 shared_network_dereference (&nn, MDL);
2751 }
2752 if (nc -> next) {
2753 shared_network_reference (&nn, nc -> next, MDL);
2754 shared_network_dereference (&nc -> next, MDL);
2755 }
2756
2757 /* As are pools. */
2758 if (nc -> pools) {
2759 pool_reference (&pn, nc -> pools, MDL);
2760 do {
2761 struct lease **lptr[RESERVED_LEASES+1];
2762
2763 if (pn) {
2764 pool_reference (&pc, pn, MDL);
2765 pool_dereference (&pn, MDL);
2766 }
2767 if (pc -> next) {
2768 pool_reference (&pn, pc -> next, MDL);
2769 pool_dereference (&pc -> next, MDL);
2770 }
2771
2772 lptr [FREE_LEASES] = &pc -> free;
2773 lptr [ACTIVE_LEASES] = &pc -> active;
2774 lptr [EXPIRED_LEASES] = &pc -> expired;
2775 lptr [ABANDONED_LEASES] = &pc -> abandoned;
2776 lptr [BACKUP_LEASES] = &pc -> backup;
2777 lptr [RESERVED_LEASES] = &pc->reserved;
2778
2779 /* As (sigh) are leases. */
2780 for (i = FREE_LEASES ; i <= RESERVED_LEASES ; i++) {
2781 if (*lptr [i]) {
2782 lease_reference (&ln, *lptr [i], MDL);
2783 do {
2784 if (ln) {
2785 lease_reference (&lc, ln, MDL);
2786 lease_dereference (&ln, MDL);
2787 }
2788 if (lc -> next) {
2789 lease_reference (&ln, lc -> next, MDL);
2790 lease_dereference (&lc -> next, MDL);
2791 }
2792 if (lc -> billing_class)
2793 class_dereference (&lc -> billing_class,
2794 MDL);
2795 if (lc -> state)
2796 free_lease_state (lc -> state, MDL);
2797 lc -> state = (struct lease_state *)0;
2798 if (lc -> n_hw)
2799 lease_dereference (&lc -> n_hw, MDL);
2800 if (lc -> n_uid)
2801 lease_dereference (&lc -> n_uid, MDL);
2802 lease_dereference (&lc, MDL);
2803 } while (ln);
2804 lease_dereference (lptr [i], MDL);
2805 }
2806 }
2807 if (pc -> group)
2808 group_dereference (&pc -> group, MDL);
2809 if (pc -> shared_network)
2810 shared_network_dereference (&pc -> shared_network,
2811 MDL);
2812 pool_dereference (&pc, MDL);
2813 } while (pn);
2814 pool_dereference (&nc -> pools, MDL);
2815 }
2816 /* Because of a circular reference, we need to nuke this
2817 manually. */
2818 group_dereference (&nc -> group, MDL);
2819 shared_network_dereference (&nc, MDL);
2820 } while (nn);
2821 shared_network_dereference (&shared_networks, MDL);
2822 }
2823
2824 cancel_all_timeouts ();
2825 relinquish_timeouts ();
2826 trace_free_all ();
2827 group_dereference (&root_group, MDL);
2828 executable_statement_dereference (&default_classification_rules, MDL);
2829
2830 shutdown_state = shutdown_drop_omapi_connections;
2831 omapi_io_state_foreach (dhcp_io_shutdown, 0);
2832 shutdown_state = shutdown_listeners;
2833 omapi_io_state_foreach (dhcp_io_shutdown, 0);
2834 shutdown_state = shutdown_dhcp;
2835 omapi_io_state_foreach (dhcp_io_shutdown, 0);
2836
2837 omapi_object_dereference ((omapi_object_t **)&icmp_state, MDL);
2838
2839 universe_free_hash_table (&universe_hash, MDL);
2840 for (i = 0; i < universe_count; i++) {
2841 union {
2842 const char *c;
2843 char *s;
2844 } foo;
2845 if (universes [i]) {
2846 if (universes [i] -> hash)
2847 option_free_hash_table (&universes [i] -> hash,
2848 MDL);
2849 #if 0
2850 if (universes [i] -> name > (char *)&end) {
2851 foo.c = universes [i] -> name;
2852 dfree (foo.s, MDL);
2853 }
2854 if (universes [i] > (struct universe *)&end)
2855 dfree (universes [i], MDL);
2856 #endif
2857 }
2858 }
2859 dfree (universes, MDL);
2860
2861 relinquish_free_lease_states ();
2862 relinquish_free_pairs ();
2863 relinquish_free_expressions ();
2864 relinquish_free_binding_values ();
2865 relinquish_free_option_caches ();
2866 relinquish_free_packets ();
2867 relinquish_lease_hunks ();
2868 relinquish_hash_bucket_hunks ();
2869 omapi_type_relinquish ();
2870 }
2871 #endif /* DEBUG_MEMORY_LEAKAGE_ON_EXIT */