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