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