]> git.ipfire.org Git - thirdparty/dhcp.git/blob - server/mdb.c
Changed supersede_lease() to return 1, even if the commit option is
[thirdparty/dhcp.git] / server / mdb.c
1 /* mdb.c
2
3 Server-specific in-memory database support. */
4
5 /*
6 * Copyright (c) 1996-2000 Internet Software Consortium.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of The Internet Software Consortium nor the names
19 * of its contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
23 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
30 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * This software has been written for the Internet Software Consortium
37 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
38 * To learn more about the Internet Software Consortium, see
39 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
40 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
41 * ``http://www.nominum.com''.
42 */
43
44 #ifndef lint
45 static char copyright[] =
46 "$Id: mdb.c,v 1.53 2001/02/15 21:34:07 neild Exp $ Copyright (c) 1996-2000 The Internet Software Consortium. All rights reserved.\n";
47 #endif /* not lint */
48
49 #include "dhcpd.h"
50
51 struct subnet *subnets;
52 struct shared_network *shared_networks;
53 struct hash_table *host_hw_addr_hash;
54 struct hash_table *host_uid_hash;
55 struct hash_table *lease_uid_hash;
56 struct hash_table *lease_ip_addr_hash;
57 struct hash_table *lease_hw_addr_hash;
58 struct hash_table *host_name_hash;
59
60 omapi_object_type_t *dhcp_type_host;
61
62 isc_result_t enter_host (hd, dynamicp, commit)
63 struct host_decl *hd;
64 int dynamicp;
65 int commit;
66 {
67 struct host_decl *hp = (struct host_decl *)0;
68 struct host_decl *np = (struct host_decl *)0;
69 struct executable_statement *esp;
70
71 if (!host_name_hash) {
72 host_name_hash =
73 new_hash ((hash_reference)host_reference,
74 (hash_dereference)host_dereference, 0);
75 if (!host_name_hash)
76 log_fatal ("Can't allocate host name hash");
77 host_hash_add (host_name_hash,
78 (unsigned char *)hd -> name,
79 strlen (hd -> name), hd, MDL);
80 } else {
81 host_hash_lookup (&hp, host_name_hash,
82 (unsigned char *)hd -> name,
83 strlen (hd -> name), MDL);
84
85 /* If it's deleted, we can supersede it. */
86 if (hp && (hp -> flags & HOST_DECL_DELETED)) {
87 host_hash_delete (host_name_hash,
88 (unsigned char *)hd -> name,
89 strlen (hd -> name), MDL);
90 /* If the old entry wasn't dynamic, then we
91 always have to keep the deletion. */
92 if (!hp -> flags & HOST_DECL_DYNAMIC)
93 hd -> flags |= HOST_DECL_STATIC;
94 }
95
96 /* If there isn't already a host decl matching this
97 address, add it to the hash table. */
98 if (!hp) {
99 host_hash_add (host_name_hash,
100 (unsigned char *)hd -> name,
101 strlen (hd -> name), hd, MDL);
102 } else {
103 /* XXX actually, we have to delete the old one
104 XXX carefully and replace it. Not done yet. */
105 host_dereference (&hp, MDL);
106 return ISC_R_EXISTS;
107 }
108 }
109
110 if (hd -> n_ipaddr)
111 host_dereference (&hd -> n_ipaddr, MDL);
112
113 if (!hd -> type)
114 hd -> type = dhcp_type_host;
115
116 if (hd -> interface.hlen) {
117 if (!host_hw_addr_hash) {
118 host_hw_addr_hash =
119 new_hash ((hash_reference)host_reference,
120 (hash_dereference)host_dereference,
121 0);
122 if (!host_hw_addr_hash)
123 log_fatal ("Can't allocate host/hw hash");
124 } else {
125 /* If there isn't already a host decl matching this
126 address, add it to the hash table. */
127 host_hash_lookup (&hp, host_hw_addr_hash,
128 hd -> interface.hbuf,
129 hd -> interface.hlen, MDL);
130 }
131 if (!hp)
132 host_hash_add (host_hw_addr_hash, hd -> interface.hbuf,
133 hd -> interface.hlen, hd, MDL);
134 else {
135 /* If there was already a host declaration for
136 this hardware address, add this one to the
137 end of the list. */
138 for (np = hp; np -> n_ipaddr; np = np -> n_ipaddr)
139 ;
140 host_reference (&np -> n_ipaddr, hd, MDL);
141 host_dereference (&hp, MDL);
142 }
143 }
144
145 /* See if there's a statement that sets the client identifier.
146 This is a kludge - the client identifier really shouldn't be
147 set with an executable statement. */
148 for (esp = hd -> group -> statements; esp; esp = esp -> next) {
149 if (esp -> op == supersede_option_statement &&
150 esp -> data.option &&
151 (esp -> data.option -> option -> universe ==
152 &dhcp_universe) &&
153 (esp -> data.option -> option -> code ==
154 DHO_DHCP_CLIENT_IDENTIFIER)) {
155 evaluate_option_cache
156 (&hd -> client_identifier, (struct packet *)0,
157 (struct lease *)0, (struct client_state *)0,
158 (struct option_state *)0,
159 (struct option_state *)0, &global_scope,
160 esp -> data.option, MDL);
161 break;
162 }
163 }
164
165 /* If we got a client identifier, hash this entry by
166 client identifier. */
167 if (hd -> client_identifier.len) {
168 /* If there's no uid hash, make one; otherwise, see if
169 there's already an entry in the hash for this host. */
170 if (!host_uid_hash) {
171 host_uid_hash =
172 new_hash ((hash_reference)host_reference,
173 (hash_dereference)host_dereference,
174 0);
175 if (!host_uid_hash)
176 log_fatal ("Can't allocate host/uid hash");
177
178 host_hash_add (host_uid_hash,
179 hd -> client_identifier.data,
180 hd -> client_identifier.len,
181 hd, MDL);
182 } else {
183 /* If there's already a host declaration for this
184 client identifier, add this one to the end of the
185 list. Otherwise, add it to the hash table. */
186 if (host_hash_lookup (&hp, host_uid_hash,
187 hd -> client_identifier.data,
188 hd -> client_identifier.len,
189 MDL)) {
190 /* Don't link it in twice... */
191 if (!np) {
192 for (np = hp; np -> n_ipaddr;
193 np = np -> n_ipaddr) {
194 if (hd == np)
195 break;
196 }
197 if (hd != np)
198 host_reference (&np -> n_ipaddr,
199 hd, MDL);
200 }
201 host_dereference (&hp, MDL);
202 } else {
203 host_hash_add (host_uid_hash,
204 hd -> client_identifier.data,
205 hd -> client_identifier.len,
206 hd, MDL);
207 }
208 }
209 }
210
211 if (dynamicp && commit) {
212 if (!write_host (hd))
213 return ISC_R_IOERROR;
214 if (!commit_leases ())
215 return ISC_R_IOERROR;
216 }
217
218 return ISC_R_SUCCESS;
219 }
220
221 isc_result_t delete_host (hd, commit)
222 struct host_decl *hd;
223 int commit;
224 {
225 struct host_decl *hp = (struct host_decl *)0;
226 struct host_decl *np = (struct host_decl *)0;
227 struct host_decl *foo;
228 struct executable_statement *esp;
229 int hw_head = 0, uid_head = 1;
230
231 /* Don't need to do it twice. */
232 if (hd -> flags & HOST_DECL_DELETED)
233 return ISC_R_SUCCESS;
234
235 /* But we do need to do it once! :') */
236 hd -> flags |= HOST_DECL_DELETED;
237
238 if (hd -> interface.hlen) {
239 if (host_hw_addr_hash) {
240 if (host_hash_lookup (&hp, host_hw_addr_hash,
241 hd -> interface.hbuf,
242 hd -> interface.hlen, MDL)) {
243 if (hp == hd) {
244 host_hash_delete (host_hw_addr_hash,
245 hd -> interface.hbuf,
246 hd -> interface.hlen, MDL);
247 hw_head = 1;
248 } else {
249 for (foo = hp; foo; foo = foo -> n_ipaddr) {
250 if (foo == hd)
251 break;
252 np = foo;
253 }
254 if (foo) {
255 host_dereference (&np -> n_ipaddr, MDL);
256 if (hd -> n_ipaddr)
257 host_reference (&np -> n_ipaddr,
258 hd -> n_ipaddr, MDL);
259 }
260 }
261 host_dereference (&hp, MDL);
262 }
263 }
264 }
265
266 /* If we got a client identifier, hash this entry by
267 client identifier. */
268 if (hd -> client_identifier.len) {
269 if (host_uid_hash) {
270 if (host_hash_lookup (&hp, host_uid_hash,
271 hd -> client_identifier.data,
272 hd -> client_identifier.len, MDL)) {
273 if (hp == hd) {
274 host_hash_delete (host_uid_hash,
275 hd -> client_identifier.data,
276 hd -> client_identifier.len, MDL);
277 uid_head = 1;
278 } else {
279 for (foo = hp; foo; foo = foo -> n_ipaddr) {
280 if (foo == hd)
281 break;
282 np = foo;
283 }
284 if (foo) {
285 if (np -> n_ipaddr)
286 host_dereference (&np -> n_ipaddr, MDL);
287 host_reference (&np -> n_ipaddr,
288 hd -> n_ipaddr, MDL);
289 }
290 }
291 host_dereference (&hp, MDL);
292 }
293 }
294 }
295
296 if (hd -> n_ipaddr) {
297 if (uid_head && hd -> n_ipaddr -> client_identifier.len) {
298 host_hash_add
299 (host_uid_hash,
300 hd -> n_ipaddr -> client_identifier.data,
301 hd -> n_ipaddr -> client_identifier.len,
302 hd -> n_ipaddr, MDL);
303 }
304 if (hw_head && hd -> n_ipaddr -> interface.hlen) {
305 host_hash_add (host_hw_addr_hash,
306 hd -> n_ipaddr -> interface.hbuf,
307 hd -> n_ipaddr -> interface.hlen,
308 hd -> n_ipaddr, MDL);
309 }
310 host_dereference (&hd -> n_ipaddr, MDL);
311 }
312
313 if (host_name_hash) {
314 if (host_hash_lookup (&hp, host_name_hash,
315 (unsigned char *)hd -> name,
316 strlen (hd -> name), MDL)) {
317 if (hp == hd && !(hp -> flags & HOST_DECL_STATIC)) {
318 host_hash_delete (host_name_hash,
319 (unsigned char *)hd -> name,
320 strlen (hd -> name), MDL);
321 }
322 host_dereference (&hp, MDL);
323 }
324 }
325
326 if (commit) {
327 if (!write_host (hd))
328 return ISC_R_IOERROR;
329 if (!commit_leases ())
330 return ISC_R_IOERROR;
331 }
332 return ISC_R_SUCCESS;
333 }
334
335 int find_hosts_by_haddr (struct host_decl **hp, int htype,
336 const unsigned char *haddr, unsigned hlen,
337 const char *file, int line)
338 {
339 struct host_decl *foo;
340 struct hardware h;
341
342 h.hlen = hlen + 1;
343 h.hbuf [0] = htype;
344 memcpy (&h.hbuf [1], haddr, hlen);
345
346 return host_hash_lookup (hp, host_hw_addr_hash,
347 h.hbuf, h.hlen, file, line);
348 }
349
350 int find_hosts_by_uid (struct host_decl **hp,
351 const unsigned char *data, unsigned len,
352 const char *file, int line)
353 {
354 return host_hash_lookup (hp, host_uid_hash, data, len, file, line);
355 }
356
357 /* More than one host_decl can be returned by find_hosts_by_haddr or
358 find_hosts_by_uid, and each host_decl can have multiple addresses.
359 Loop through the list of hosts, and then for each host, through the
360 list of addresses, looking for an address that's in the same shared
361 network as the one specified. Store the matching address through
362 the addr pointer, update the host pointer to point at the host_decl
363 that matched, and return the subnet that matched. */
364
365 int find_host_for_network (struct subnet **sp, struct host_decl **host,
366 struct iaddr *addr, struct shared_network *share)
367 {
368 int i;
369 struct subnet *subnet;
370 struct iaddr ip_address;
371 struct host_decl *hp;
372 struct data_string fixed_addr;
373
374 memset (&fixed_addr, 0, sizeof fixed_addr);
375
376 for (hp = *host; hp; hp = hp -> n_ipaddr) {
377 if (!hp -> fixed_addr)
378 continue;
379 if (!evaluate_option_cache (&fixed_addr, (struct packet *)0,
380 (struct lease *)0,
381 (struct client_state *)0,
382 (struct option_state *)0,
383 (struct option_state *)0,
384 &global_scope,
385 hp -> fixed_addr, MDL))
386 continue;
387 for (i = 0; i < fixed_addr.len; i += 4) {
388 ip_address.len = 4;
389 memcpy (ip_address.iabuf,
390 fixed_addr.data + i, 4);
391 if (find_grouped_subnet (sp, share, ip_address, MDL)) {
392 struct host_decl *tmp = (struct host_decl *)0;
393 *addr = ip_address;
394 /* This is probably not necessary, but
395 just in case *host is the only reference
396 to that host declaration, make a temporary
397 reference so that dereferencing it doesn't
398 dereference hp out from under us. */
399 host_reference (&tmp, *host, MDL);
400 host_dereference (host, MDL);
401 host_reference (host, hp, MDL);
402 host_dereference (&tmp, MDL);
403 data_string_forget (&fixed_addr, MDL);
404 return 1;
405 }
406 }
407 data_string_forget (&fixed_addr, MDL);
408 }
409 return 0;
410 }
411
412 void new_address_range (low, high, subnet, pool)
413 struct iaddr low, high;
414 struct subnet *subnet;
415 struct pool *pool;
416 {
417 struct lease *address_range, *lp, *plp;
418 struct iaddr net;
419 unsigned min, max, i;
420 char lowbuf [16], highbuf [16], netbuf [16];
421 struct shared_network *share = subnet -> shared_network;
422 isc_result_t status;
423 struct lease *lt = (struct lease *)0;
424
425 /* All subnets should have attached shared network structures. */
426 if (!share) {
427 strcpy (netbuf, piaddr (subnet -> net));
428 log_fatal ("No shared network for network %s (%s)",
429 netbuf, piaddr (subnet -> netmask));
430 }
431
432 /* Initialize the hash table if it hasn't been done yet. */
433 if (!lease_uid_hash) {
434 lease_uid_hash =
435 new_hash ((hash_reference)lease_reference,
436 (hash_dereference)lease_dereference, 0);
437 if (!lease_uid_hash)
438 log_fatal ("Can't allocate lease/uid hash");
439 }
440 if (!lease_ip_addr_hash) {
441 lease_ip_addr_hash =
442 new_hash ((hash_reference)lease_reference,
443 (hash_dereference)lease_dereference, 0);
444 if (!lease_uid_hash)
445 log_fatal ("Can't allocate lease/ip hash");
446 }
447 if (!lease_hw_addr_hash) {
448 lease_hw_addr_hash =
449 new_hash ((hash_reference)lease_reference,
450 (hash_dereference)lease_dereference, 0);
451 if (!lease_uid_hash)
452 log_fatal ("Can't allocate lease/hw hash");
453 }
454
455 /* Make sure that high and low addresses are in same subnet. */
456 net = subnet_number (low, subnet -> netmask);
457 if (!addr_eq (net, subnet_number (high, subnet -> netmask))) {
458 strcpy (lowbuf, piaddr (low));
459 strcpy (highbuf, piaddr (high));
460 strcpy (netbuf, piaddr (subnet -> netmask));
461 log_fatal ("Address range %s to %s, netmask %s spans %s!",
462 lowbuf, highbuf, netbuf, "multiple subnets");
463 }
464
465 /* Make sure that the addresses are on the correct subnet. */
466 if (!addr_eq (net, subnet -> net)) {
467 strcpy (lowbuf, piaddr (low));
468 strcpy (highbuf, piaddr (high));
469 strcpy (netbuf, piaddr (subnet -> netmask));
470 log_fatal ("Address range %s to %s not on net %s/%s!",
471 lowbuf, highbuf, piaddr (subnet -> net), netbuf);
472 }
473
474 /* Get the high and low host addresses... */
475 max = host_addr (high, subnet -> netmask);
476 min = host_addr (low, subnet -> netmask);
477
478 /* Allow range to be specified high-to-low as well as low-to-high. */
479 if (min > max) {
480 max = min;
481 min = host_addr (high, subnet -> netmask);
482 }
483
484 /* Get a lease structure for each address in the range. */
485 #if defined (COMPACT_LEASES)
486 address_range = new_leases (max - min + 1, MDL);
487 if (!address_range) {
488 strcpy (lowbuf, piaddr (low));
489 strcpy (highbuf, piaddr (high));
490 log_fatal ("No memory for address range %s-%s.",
491 lowbuf, highbuf);
492 }
493 #endif
494
495 /* Fill out the lease structures with some minimal information. */
496 for (i = 0; i < max - min + 1; i++) {
497 struct lease *lp = (struct lease *)0;
498 #if defined (COMPACT_LEASES)
499 omapi_object_initialize ((omapi_object_t *)&address_range [i],
500 dhcp_type_lease,
501 0, sizeof (struct lease), MDL);
502 lease_reference (&lp, &address_range [i], MDL);
503 #else
504 status = lease_allocate (&lp, MDL);
505 if (status != ISC_R_SUCCESS)
506 log_fatal ("No memory for lease %s: %s",
507 piaddr (ip_addr (subnet -> net,
508 subnet -> netmask,
509 i + min)),
510 isc_result_totext (status));
511 #endif
512 lp -> ip_addr = ip_addr (subnet -> net,
513 subnet -> netmask, i + min);
514 lp -> starts = lp -> timestamp = MIN_TIME;
515 lp -> ends = MIN_TIME;
516 subnet_reference (&lp -> subnet, subnet, MDL);
517 pool_reference (&lp -> pool, pool, MDL);
518 lp -> binding_state = FTS_FREE;
519 lp -> next_binding_state = FTS_FREE;
520 lp -> flags = 0;
521
522 /* Remember the lease in the IP address hash. */
523 if (find_lease_by_ip_addr (&lt, lp -> ip_addr, MDL)) {
524 if (lt -> pool) {
525 log_error ("duplicate entries for lease %s",
526 piaddr (lp -> ip_addr));
527 } else
528 pool_reference (&lt -> pool, pool, MDL);
529 lease_dereference (&lt, MDL);
530 } else
531 lease_hash_add (lease_ip_addr_hash,
532 lp -> ip_addr.iabuf,
533 lp -> ip_addr.len, lp, MDL);
534 lease_dereference (&lp, MDL);
535 }
536 }
537
538
539 #if defined (COMPACT_LEASES)
540 struct lease *free_leases;
541
542 /* If we are allocating leases in aggregations, there's really no way
543 to free one, although perhaps we can maintain a free list. */
544
545 isc_result_t dhcp_lease_free (omapi_object_t *lo,
546 const char *file, int line)
547 {
548 struct lease *lease;
549 if (lo -> type != dhcp_type_lease)
550 return ISC_R_INVALIDARG;
551 lease = (struct lease *)lo;
552 lease -> next = free_leases;
553 free_leases = lease;
554 return ISC_R_SUCCESS;
555 }
556
557 isc_result_t dhcp_lease_get (omapi_object_t **lp,
558 const char *file, int line)
559 {
560 struct lease **lease = (struct lease **)lp;
561 struct lease *lt;
562
563 if (free_leases) {
564 lt = free_leases;
565 free_leases = lt -> next;
566 *lease = lt;
567 return ISC_R_SUCCESS;
568 }
569 return ISC_R_NOMEMORY;
570 }
571 #endif
572
573 int find_subnet (struct subnet **sp,
574 struct iaddr addr, const char *file, int line)
575 {
576 struct subnet *rv;
577
578 for (rv = subnets; rv; rv = rv -> next_subnet) {
579 if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net)) {
580 if (subnet_reference (sp, rv,
581 file, line) != ISC_R_SUCCESS)
582 return 0;
583 return 1;
584 }
585 }
586 return 0;
587 }
588
589 int find_grouped_subnet (struct subnet **sp,
590 struct shared_network *share, struct iaddr addr,
591 const char *file, int line)
592 {
593 struct subnet *rv;
594
595 for (rv = share -> subnets; rv; rv = rv -> next_sibling) {
596 if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net)) {
597 if (subnet_reference (sp, rv,
598 file, line) != ISC_R_SUCCESS)
599 return 0;
600 return 1;
601 }
602 }
603 return 0;
604 }
605
606 int subnet_inner_than (subnet, scan, warnp)
607 struct subnet *subnet, *scan;
608 int warnp;
609 {
610 if (addr_eq (subnet_number (subnet -> net, scan -> netmask),
611 scan -> net) ||
612 addr_eq (subnet_number (scan -> net, subnet -> netmask),
613 subnet -> net)) {
614 char n1buf [16];
615 int i, j;
616 for (i = 0; i < 32; i++)
617 if (subnet -> netmask.iabuf [3 - (i >> 3)]
618 & (1 << (i & 7)))
619 break;
620 for (j = 0; j < 32; j++)
621 if (scan -> netmask.iabuf [3 - (j >> 3)] &
622 (1 << (j & 7)))
623 break;
624 strcpy (n1buf, piaddr (subnet -> net));
625 if (warnp)
626 log_error ("%ssubnet %s/%d overlaps subnet %s/%d",
627 "Warning: ", n1buf, 32 - i,
628 piaddr (scan -> net), 32 - j);
629 if (i < j)
630 return 1;
631 }
632 return 0;
633 }
634
635 /* Enter a new subnet into the subnet list. */
636 void enter_subnet (subnet)
637 struct subnet *subnet;
638 {
639 struct subnet *scan, *prev = (struct subnet *)0;
640
641 /* Check for duplicates... */
642 for (scan = subnets; scan; scan = scan -> next_subnet) {
643 /* When we find a conflict, make sure that the
644 subnet with the narrowest subnet mask comes
645 first. */
646 if (subnet_inner_than (subnet, scan, 1)) {
647 if (prev) {
648 subnet_reference (&prev -> next_subnet,
649 subnet, MDL);
650 } else
651 subnet_reference (&subnets, subnet, MDL);
652 subnet_reference (&subnet -> next_subnet, scan, MDL);
653 return;
654 }
655 prev = scan;
656 }
657
658 /* XXX use the BSD radix tree code instead of a linked list. */
659 subnet -> next_subnet = subnets;
660 subnets = subnet;
661 }
662
663 /* Enter a new shared network into the shared network list. */
664
665 void enter_shared_network (share)
666 struct shared_network *share;
667 {
668 if (shared_networks) {
669 shared_network_reference (&share -> next,
670 shared_networks, MDL);
671 shared_network_dereference (&shared_networks, MDL);
672 }
673 shared_network_reference (&shared_networks, share, MDL);
674 }
675
676 void new_shared_network_interface (cfile, share, name)
677 struct parse *cfile;
678 struct shared_network *share;
679 const char *name;
680 {
681 struct interface_info *ip;
682 isc_result_t status;
683
684 if (share -> interface) {
685 parse_warn (cfile,
686 "A subnet or shared network can't be connected %s",
687 "to two interfaces.");
688 return;
689 }
690
691 for (ip = interfaces; ip; ip = ip -> next)
692 if (!strcmp (ip -> name, name))
693 break;
694 if (!ip) {
695 status = interface_allocate (&ip, MDL);
696 if (status != ISC_R_SUCCESS)
697 log_fatal ("new_shared_network_interface %s: %s",
698 name, isc_result_totext (status));
699 if (strlen (name) > sizeof ip -> name) {
700 memcpy (ip -> name, name, (sizeof ip -> name) - 1);
701 ip -> name [(sizeof ip -> name) - 1] = 0;
702 } else
703 strcpy (ip -> name, name);
704 if (interfaces) {
705 interface_reference (&ip -> next, interfaces, MDL);
706 interface_dereference (&interfaces, MDL);
707 }
708 interface_reference (&interfaces, ip, MDL);
709 ip -> flags = INTERFACE_REQUESTED;
710 /* XXX this is a reference loop. */
711 shared_network_reference (&ip -> shared_network, share, MDL);
712 interface_reference (&share -> interface, ip, MDL);
713 }
714 }
715
716 /* Enter a lease into the system. This is called by the parser each
717 time it reads in a new lease. If the subnet for that lease has
718 already been read in (usually the case), just update that lease;
719 otherwise, allocate temporary storage for the lease and keep it around
720 until we're done reading in the config file. */
721
722 void enter_lease (lease)
723 struct lease *lease;
724 {
725 struct lease *comp = (struct lease *)0;
726 isc_result_t status;
727
728 if (find_lease_by_ip_addr (&comp, lease -> ip_addr, MDL)) {
729 if (!comp -> pool) {
730 log_error ("undeclared lease found in database: %s",
731 piaddr (lease -> ip_addr));
732 } else
733 pool_reference (&lease -> pool, comp -> pool, MDL);
734
735 if (comp -> subnet)
736 subnet_reference (&lease -> subnet,
737 comp -> subnet, MDL);
738 lease_hash_delete (lease_ip_addr_hash,
739 lease -> ip_addr.iabuf,
740 lease -> ip_addr.len, MDL);
741 lease_dereference (&comp, MDL);
742 }
743
744 /* The only way a lease can get here without a subnet is if it's in
745 the lease file, but not in the dhcpd.conf file. In this case, we
746 *should* keep it around until it's expired, but never reallocate it
747 or renew it. Currently, to maintain consistency, we are not doing
748 this.
749 XXX fix this so that the lease is kept around until it expires.
750 XXX this will be important in IPv6 with addresses that become
751 XXX non-renewable as a result of a renumbering event. */
752
753 if (!lease -> subnet) {
754 log_error ("lease %s: no subnet.", piaddr (lease -> ip_addr));
755 return;
756 }
757 lease_hash_add (lease_ip_addr_hash,
758 lease -> ip_addr.iabuf,
759 lease -> ip_addr.len, lease, MDL);
760 }
761
762 /* Replace the data in an existing lease with the data in a new lease;
763 adjust hash tables to suit, and insertion sort the lease into the
764 list of leases by expiry time so that we can always find the oldest
765 lease. */
766
767 int supersede_lease (comp, lease, commit, propogate, pimmediate)
768 struct lease *comp, *lease;
769 int commit;
770 int propogate;
771 int pimmediate;
772 {
773 int enter_uid = 0;
774 int enter_hwaddr = 0;
775 struct lease *lp, **lq, *prev;
776 TIME lp_next_state;
777
778 #if defined (FAILOVER_PROTOCOL)
779 /* We must commit leases before sending updates regarding them
780 to failover peers. It is, therefore, an error to set pimmediate
781 and not commit. */
782 if (pimmediate && !commit)
783 return 0;
784 #endif
785
786 /* If there is no sample lease, just do the move. */
787 if (!lease)
788 goto just_move_it;
789
790 /* Static leases are not currently kept in the database... */
791 if (lease -> flags & STATIC_LEASE)
792 return 1;
793
794 /* If the existing lease hasn't expired and has a different
795 unique identifier or, if it doesn't have a unique
796 identifier, a different hardware address, then the two
797 leases are in conflict. If the existing lease has a uid
798 and the new one doesn't, but they both have the same
799 hardware address, and dynamic bootp is allowed on this
800 lease, then we allow that, in case a dynamic BOOTP lease is
801 requested *after* a DHCP lease has been assigned. */
802
803 if (lease -> binding_state != FTS_ABANDONED &&
804 (comp -> binding_state == FTS_ACTIVE ||
805 comp -> binding_state == FTS_RESERVED ||
806 comp -> binding_state == FTS_BOOTP) &&
807 (((comp -> uid && lease -> uid) &&
808 (comp -> uid_len != lease -> uid_len ||
809 memcmp (comp -> uid, lease -> uid, comp -> uid_len))) ||
810 (!comp -> uid &&
811 ((comp -> hardware_addr.hlen !=
812 lease -> hardware_addr.hlen) ||
813 memcmp (comp -> hardware_addr.hbuf,
814 lease -> hardware_addr.hbuf,
815 comp -> hardware_addr.hlen))))) {
816 log_error ("Lease conflict at %s",
817 piaddr (comp -> ip_addr));
818 return 0;
819 }
820
821 /* If there's a Unique ID, dissociate it from the hash
822 table and free it if necessary. */
823 if (comp -> uid) {
824 uid_hash_delete (comp);
825 enter_uid = 1;
826 if (comp -> uid != &comp -> uid_buf [0]) {
827 dfree (comp -> uid, MDL);
828 comp -> uid_max = 0;
829 comp -> uid_len = 0;
830 }
831 comp -> uid = (unsigned char *)0;
832 } else
833 enter_uid = 1;
834
835 if (comp -> hardware_addr.hlen &&
836 ((comp -> hardware_addr.hlen !=
837 lease -> hardware_addr.hlen) ||
838 memcmp (comp -> hardware_addr.hbuf,
839 lease -> hardware_addr.hbuf,
840 comp -> hardware_addr.hlen))) {
841 hw_hash_delete (comp);
842 enter_hwaddr = 1;
843 } else if (!comp -> hardware_addr.hlen)
844 enter_hwaddr = 1;
845
846 /* If the lease has been billed to a class, remove the billing. */
847 if (comp -> billing_class != lease -> billing_class) {
848 if (comp -> billing_class)
849 unbill_class (comp, comp -> billing_class);
850 if (lease -> billing_class)
851 bill_class (comp, lease -> billing_class);
852 }
853
854 /* Copy the data files, but not the linkages. */
855 comp -> starts = lease -> starts;
856 if (lease -> uid) {
857 if (lease -> uid_len <= sizeof (lease -> uid_buf)) {
858 memcpy (comp -> uid_buf,
859 lease -> uid, lease -> uid_len);
860 comp -> uid = &comp -> uid_buf [0];
861 comp -> uid_max = sizeof comp -> uid_buf;
862 comp -> uid_len = lease -> uid_len;
863 } else if (lease -> uid != &lease -> uid_buf [0]) {
864 comp -> uid = lease -> uid;
865 comp -> uid_max = lease -> uid_max;
866 lease -> uid = (unsigned char *)0;
867 lease -> uid_max = 0;
868 comp -> uid_len = lease -> uid_len;
869 lease -> uid_len = 0;
870 } else {
871 log_fatal ("corrupt lease uid."); /* XXX */
872 }
873 } else {
874 comp -> uid = (unsigned char *)0;
875 comp -> uid_len = comp -> uid_max = 0;
876 }
877 if (comp -> host)
878 host_dereference (&comp -> host, MDL);
879 host_reference (&comp -> host, lease -> host, MDL);
880 comp -> hardware_addr = lease -> hardware_addr;
881 comp -> flags = ((lease -> flags & ~PERSISTENT_FLAGS) |
882 (comp -> flags & ~EPHEMERAL_FLAGS));
883 if (comp -> scope)
884 binding_scope_dereference (&comp -> scope, MDL);
885 if (lease -> scope) {
886 binding_scope_reference (&comp -> scope, lease -> scope, MDL);
887 binding_scope_dereference (&lease -> scope, MDL);
888 }
889
890 if (comp -> agent_options)
891 option_chain_head_dereference (&comp -> agent_options, MDL);
892 if (lease -> agent_options) {
893 /* Only retain the agent options if the lease is still
894 affirmatively associated with a client. */
895 if (lease -> next_binding_state == FTS_ACTIVE ||
896 lease -> next_binding_state == FTS_EXPIRED ||
897 lease -> next_binding_state == FTS_RESERVED ||
898 lease -> next_binding_state == FTS_BOOTP)
899 option_chain_head_reference (&comp -> agent_options,
900 lease -> agent_options,
901 MDL);
902 option_chain_head_dereference (&lease -> agent_options, MDL);
903 }
904
905 /* Record the hostname information in the lease. */
906 if (comp -> client_hostname)
907 dfree (comp -> client_hostname, MDL);
908 comp -> client_hostname = lease -> client_hostname;
909 lease -> client_hostname = (char *)0;
910
911 if (lease -> on_expiry) {
912 if (comp -> on_expiry)
913 executable_statement_dereference (&comp -> on_expiry,
914 MDL);
915 executable_statement_reference (&comp -> on_expiry,
916 lease -> on_expiry,
917 MDL);
918 }
919 if (lease -> on_commit) {
920 if (comp -> on_commit)
921 executable_statement_dereference (&comp -> on_commit,
922 MDL);
923 executable_statement_reference (&comp -> on_commit,
924 lease -> on_commit,
925 MDL);
926 }
927 if (lease -> on_release) {
928 if (comp -> on_release)
929 executable_statement_dereference (&comp -> on_release,
930 MDL);
931 executable_statement_reference (&comp -> on_release,
932 lease -> on_release, MDL);
933 }
934
935 /* Record the lease in the uid hash if necessary. */
936 if (enter_uid && lease -> uid) {
937 uid_hash_add (comp);
938 }
939
940 /* Record it in the hardware address hash if necessary. */
941 if (enter_hwaddr && lease -> hardware_addr.hlen) {
942 hw_hash_add (comp);
943 }
944
945 #if defined (FAILOVER_PROTOCOL)
946 comp -> cltt = lease -> cltt;
947 comp -> tstp = lease -> tstp;
948 comp -> tsfp = lease -> tsfp;
949 #endif /* FAILOVER_PROTOCOL */
950 comp -> ends = lease -> ends;
951 comp -> next_binding_state = lease -> next_binding_state;
952
953 just_move_it:
954 if (!comp -> pool) {
955 log_error ("Supersede_lease: lease %s with no pool.",
956 piaddr (comp -> ip_addr));
957 return 0;
958 }
959
960 /* Figure out which queue it's on. */
961 switch (comp -> binding_state) {
962 case FTS_FREE:
963 lq = &comp -> pool -> free;
964 comp -> pool -> free_leases--;
965 break;
966
967 case FTS_ACTIVE:
968 case FTS_RESERVED:
969 case FTS_BOOTP:
970 lq = &comp -> pool -> active;
971 break;
972
973 case FTS_EXPIRED:
974 case FTS_RELEASED:
975 case FTS_RESET:
976 lq = &comp -> pool -> expired;
977 break;
978
979 case FTS_ABANDONED:
980 lq = &comp -> pool -> abandoned;
981 break;
982
983 case FTS_BACKUP:
984 lq = &comp -> pool -> backup;
985 comp -> pool -> backup_leases--;
986 break;
987
988 default:
989 log_error ("Lease with bogus binding state: %d",
990 comp -> binding_state);
991 return 0;
992 }
993
994 /* Remove the lease from its current place in its current
995 timer sequence. */
996 prev = (struct lease *)0;
997 for (lp = *lq; lp; lp = lp -> next) {
998 if (lp == comp)
999 break;
1000 prev = lp;
1001 }
1002
1003 if (!lp) {
1004 log_error ("Lease with binding state %s not on its queue.",
1005 (comp -> binding_state < 1 &&
1006 comp -> binding_state < FTS_BOOTP)
1007 ? "unknown"
1008 : binding_state_names [comp -> binding_state - 1]);
1009 return 0;
1010 }
1011
1012 if (prev) {
1013 lease_dereference (&prev -> next, MDL);
1014 if (comp -> next) {
1015 lease_reference (&prev -> next, comp -> next, MDL);
1016 lease_dereference (&comp -> next, MDL);
1017 }
1018 } else {
1019 lease_dereference (lq, MDL);
1020 if (comp -> next) {
1021 lease_reference (lq, comp -> next, MDL);
1022 lease_dereference (&comp -> next, MDL);
1023 }
1024 }
1025
1026 /* Make the state transition. */
1027 if (commit)
1028 process_state_transition (comp);
1029
1030 /* Put the lease back on the appropriate queue. If the lease
1031 is corrupt (as detected by lease_enqueue), don't go any farther. */
1032 if (!lease_enqueue (comp))
1033 return 0;
1034
1035 /* If this is the next lease that will timeout on the pool,
1036 zap the old timeout and set the timeout on this pool to the
1037 time that the lease's next event will happen.
1038
1039 We do not actually set the timeout unless commit is true -
1040 we don't want to thrash the timer queue when reading the
1041 lease database. Instead, the database code calls the
1042 expiry event on each pool after reading in the lease file,
1043 and the expiry code sets the timer if there's anything left
1044 to expire after it's run any outstanding expiry events on
1045 the pool. */
1046 if (commit &&
1047 comp -> sort_time != MIN_TIME &&
1048 comp -> sort_time > cur_time &&
1049 (comp -> sort_time < comp -> pool -> next_event_time ||
1050 comp -> pool -> next_event_time == MIN_TIME)) {
1051 comp -> pool -> next_event_time = comp -> sort_time;
1052 add_timeout (comp -> pool -> next_event_time,
1053 pool_timer, comp -> pool,
1054 (tvref_t)pool_reference,
1055 (tvunref_t)pool_dereference);
1056 }
1057
1058 if (commit) {
1059 if (!write_lease (comp))
1060 return 0;
1061 if (!commit_leases ())
1062 return 0;
1063 }
1064
1065 #if defined (FAILOVER_PROTOCOL)
1066 if (propogate) {
1067 if (!dhcp_failover_queue_update (comp, pimmediate))
1068 return 0;
1069 }
1070 #endif
1071
1072 return 1;
1073 }
1074
1075 void process_state_transition (struct lease *lease)
1076 {
1077 #if defined (FAILOVER_PROTOCOL)
1078 dhcp_failover_state_t *peer;
1079
1080 if (lease && lease -> pool && lease -> pool -> failover_peer)
1081 peer = lease -> pool -> failover_peer;
1082 else
1083 peer = (dhcp_failover_state_t *)0;
1084 #endif
1085
1086 /* If the lease was active and is now no longer active, but isn't
1087 released, then it just expired, so do the expiry event. */
1088 if (lease -> next_binding_state != lease -> binding_state &&
1089 ((
1090 #if defined (FAILOVER_PROTOCOL)
1091 peer &&
1092 lease -> binding_state == FTS_EXPIRED &&
1093 (lease -> next_binding_state == FTS_FREE ||
1094 lease -> next_binding_state == FTS_BACKUP)) ||
1095 (!peer &&
1096 #endif
1097 (lease -> binding_state == FTS_ACTIVE ||
1098 lease -> binding_state == FTS_BOOTP ||
1099 lease -> binding_state == FTS_RESERVED) &&
1100 lease -> next_binding_state != FTS_RELEASED))) {
1101 ddns_removals (lease);
1102 if (lease -> on_expiry) {
1103 execute_statements ((struct binding_value **)0,
1104 (struct packet *)0, lease,
1105 (struct client_state *)0,
1106 (struct option_state *)0,
1107 (struct option_state *)0, /* XXX */
1108 &lease -> scope,
1109 lease -> on_expiry);
1110 if (lease -> on_expiry)
1111 executable_statement_dereference
1112 (&lease -> on_expiry, MDL);
1113 }
1114
1115 /* No sense releasing a lease after it's expired. */
1116 if (lease -> on_release)
1117 executable_statement_dereference (&lease -> on_release,
1118 MDL);
1119 /* Send the expiry time to the peer. */
1120 lease -> tstp = lease -> ends;
1121 }
1122
1123 /* If the lease was active and is now released, do the release
1124 event. */
1125 if (lease -> next_binding_state != lease -> binding_state &&
1126 ((
1127 #if defined (FAILOVER_PROTOCOL)
1128 peer &&
1129 lease -> binding_state == FTS_RELEASED &&
1130 (lease -> next_binding_state == FTS_FREE ||
1131 lease -> next_binding_state == FTS_BACKUP)) ||
1132 (!peer &&
1133 #endif
1134 (lease -> binding_state == FTS_ACTIVE ||
1135 lease -> binding_state == FTS_BOOTP ||
1136 lease -> binding_state == FTS_RESERVED) &&
1137 lease -> next_binding_state == FTS_RELEASED))) {
1138 ddns_removals (lease);
1139 if (lease -> on_release) {
1140 execute_statements ((struct binding_value **)0,
1141 (struct packet *)0, lease,
1142 (struct client_state *)0,
1143 (struct option_state *)0,
1144 (struct option_state *)0, /* XXX */
1145 &lease -> scope,
1146 lease -> on_release);
1147 executable_statement_dereference (&lease -> on_release,
1148 MDL);
1149 }
1150
1151 /* A released lease can't expire. */
1152 if (lease -> on_expiry)
1153 executable_statement_dereference (&lease -> on_expiry,
1154 MDL);
1155
1156 /* Send the release time (should be == cur_time) to the
1157 peer. */
1158 lease -> tstp = lease -> ends;
1159 }
1160
1161 lease -> binding_state = lease -> next_binding_state;
1162 if (lease -> binding_state == FTS_ACTIVE ||
1163 lease -> binding_state == FTS_BACKUP) {
1164 #if defined (FAILOVER_PROTOCOL)
1165 if (lease -> pool && lease -> pool -> failover_peer)
1166 lease -> next_binding_state = FTS_EXPIRED;
1167 else
1168 #endif
1169 lease -> next_binding_state = FTS_FREE;
1170 }
1171 }
1172
1173 /* Copy the contents of one lease into another, correctly maintaining
1174 reference counts. */
1175 int lease_copy (struct lease **lp,
1176 struct lease *lease, const char *file, int line)
1177 {
1178 struct lease *lt = (struct lease *)0;
1179 isc_result_t status;
1180
1181 status = lease_allocate (&lt, MDL);
1182 if (status != ISC_R_SUCCESS)
1183 return 0;
1184
1185 lt -> ip_addr = lease -> ip_addr;
1186 lt -> starts = lease -> starts;
1187 lt -> ends = lease -> ends;
1188 lt -> timestamp = lease -> timestamp;
1189 lt -> uid_len = lease -> uid_len;
1190 lt -> uid_max = lease -> uid_max;
1191 if (lease -> uid == lease -> uid_buf) {
1192 lt -> uid = lt -> uid_buf;
1193 memcpy (lt -> uid_buf, lease -> uid_buf, sizeof lt -> uid_buf);
1194 } else {
1195 lt -> uid = dmalloc (lt -> uid_max, MDL);
1196 if (!lt -> uid) {
1197 lease_dereference (&lt, MDL);
1198 return 0;
1199 }
1200 memcpy (lt -> uid, lease -> uid, lease -> uid_max);
1201 }
1202 if (lease -> client_hostname) {
1203 lt -> client_hostname =
1204 dmalloc (strlen (lease -> client_hostname) + 1, MDL);
1205 if (!lt -> client_hostname) {
1206 lease_dereference (&lt, MDL);
1207 return 0;
1208 }
1209 strcpy (lt -> client_hostname, lease -> client_hostname);
1210 }
1211 if (lease -> scope)
1212 binding_scope_reference (&lt -> scope, lease -> scope, MDL);
1213 if (lease -> agent_options)
1214 option_chain_head_reference (&lt -> agent_options,
1215 lease -> agent_options, MDL);
1216 host_reference (&lt -> host, lease -> host, file, line);
1217 subnet_reference (&lt -> subnet, lease -> subnet, file, line);
1218 pool_reference (&lt -> pool, lease -> pool, file, line);
1219 class_reference (&lt -> billing_class,
1220 lease -> billing_class, file, line);
1221 lt -> hardware_addr = lease -> hardware_addr;
1222 if (lease -> on_expiry)
1223 executable_statement_reference (&lt -> on_expiry,
1224 lease -> on_expiry,
1225 file, line);
1226 if (lease -> on_commit)
1227 executable_statement_reference (&lt -> on_commit,
1228 lease -> on_commit,
1229 file, line);
1230 if (lease -> on_release)
1231 executable_statement_reference (&lt -> on_release,
1232 lease -> on_release,
1233 file, line);
1234 lt -> flags = lease -> flags;
1235 lt -> tstp = lease -> tstp;
1236 lt -> tsfp = lease -> tsfp;
1237 lt -> cltt = lease -> cltt;
1238 lt -> binding_state = lease -> binding_state;
1239 lt -> next_binding_state = lease -> next_binding_state;
1240 status = lease_reference (lp, lt, file, line);
1241 lease_dereference (&lt, MDL);
1242 return status == ISC_R_SUCCESS;
1243 }
1244
1245 /* Release the specified lease and re-hash it as appropriate. */
1246 void release_lease (lease, packet)
1247 struct lease *lease;
1248 struct packet *packet;
1249 {
1250 /* If there are statements to execute when the lease is
1251 released, execute them. */
1252 ddns_removals (lease);
1253 if (lease -> on_release) {
1254 execute_statements ((struct binding_value **)0,
1255 packet, lease, (struct client_state *)0,
1256 packet -> options,
1257 (struct option_state *)0, /* XXX */
1258 &lease -> scope, lease -> on_release);
1259 if (lease -> on_release)
1260 executable_statement_dereference (&lease -> on_release,
1261 MDL);
1262 }
1263
1264 /* We do either the on_release or the on_expiry events, but
1265 not both (it's possible that they could be the same,
1266 in any case). */
1267 if (lease -> on_expiry)
1268 executable_statement_dereference (&lease -> on_expiry, MDL);
1269
1270 if (lease -> ends > cur_time) {
1271 if (lease -> on_commit)
1272 executable_statement_dereference (&lease -> on_commit,
1273 MDL);
1274
1275 /* Blow away any bindings. */
1276 if (lease -> scope)
1277 binding_scope_dereference (&lease -> scope, MDL);
1278 lease -> ends = cur_time;
1279 #if defined (FAILOVER_PROTOCOL)
1280 if (lease -> pool && lease -> pool -> failover_peer) {
1281 lease -> next_binding_state = FTS_RELEASED;
1282 } else {
1283 lease -> next_binding_state = FTS_FREE;
1284 }
1285 #else
1286 lease -> next_binding_state = FTS_FREE;
1287 #endif
1288 if (lease -> billing_class)
1289 class_dereference (&lease -> billing_class, MDL);
1290 supersede_lease (lease, (struct lease *)0, 1, 1, 1);
1291 }
1292 }
1293
1294 /* Abandon the specified lease (set its timeout to infinity and its
1295 particulars to zero, and re-hash it as appropriate. */
1296
1297 void abandon_lease (lease, message)
1298 struct lease *lease;
1299 const char *message;
1300 {
1301 struct lease *lt = (struct lease *)0;
1302
1303 if (!lease_copy (&lt, lease, MDL))
1304 return;
1305
1306 #if 0
1307 if (lt -> on_expiry)
1308 executable_statement_dereference (&lease -> on_expiry, MDL);
1309 if (lt -> on_release)
1310 executable_statement_dereference (&lease -> on_release, MDL);
1311 if (lt -> on_commit)
1312 executable_statement_dereference (&lease -> on_commit, MDL);
1313
1314 /* Blow away any bindings. */
1315 if (lt -> scope)
1316 binding_scope_dereference (&lt -> scope, MDL);
1317 #endif
1318
1319 lt -> ends = cur_time; /* XXX */
1320 lt -> next_binding_state = FTS_ABANDONED;
1321
1322 log_error ("Abandoning IP address %s: %s",
1323 piaddr (lease -> ip_addr), message);
1324 lt -> hardware_addr.hlen = 0;
1325 if (lt -> uid != lt -> uid_buf)
1326 dfree (lt -> uid, MDL);
1327 lt -> uid = (unsigned char *)0;
1328 lt -> uid_len = 0;
1329 lt -> uid_max = 0;
1330 if (lt -> billing_class)
1331 class_dereference (&lt -> billing_class, MDL);
1332 supersede_lease (lease, lt, 1, 1, 1);
1333 lease_dereference (&lt, MDL);
1334 }
1335
1336 /* Abandon the specified lease (set its timeout to infinity and its
1337 particulars to zero, and re-hash it as appropriate. */
1338
1339 void dissociate_lease (lease)
1340 struct lease *lease;
1341 {
1342 struct lease *lt = (struct lease *)0;
1343
1344 if (!lease_copy (&lt, lease, MDL))
1345 return;
1346
1347 #if 0
1348 if (lt -> on_expiry)
1349 executable_statement_dereference (&lease -> on_expiry, MDL);
1350 if (lt -> on_release)
1351 executable_statement_dereference (&lease -> on_release, MDL);
1352 if (lt -> on_commit)
1353 executable_statement_dereference (&lease -> on_commit, MDL);
1354
1355 /* Blow away any bindings. */
1356 if (lt -> scope)
1357 binding_scope_dereference (&lt -> scope, MDL);
1358 #endif
1359
1360 #if defined (FAILOVER_PROTOCOL)
1361 if (lease -> pool && lease -> pool -> failover_peer) {
1362 lt -> next_binding_state = FTS_RESET;
1363 } else {
1364 lt -> next_binding_state = FTS_FREE;
1365 }
1366 #else
1367 lt -> next_binding_state = FTS_FREE;
1368 #endif
1369 lt -> ends = cur_time; /* XXX */
1370 lt -> hardware_addr.hlen = 0;
1371 if (lt -> uid != lt -> uid_buf)
1372 dfree (lt -> uid, MDL);
1373 lt -> uid = (unsigned char *)0;
1374 lt -> uid_len = 0;
1375 lt -> uid_max = 0;
1376 if (lt -> billing_class)
1377 class_dereference (&lt -> billing_class, MDL);
1378 supersede_lease (lease, lt, 1, 1, 1);
1379 lease_dereference (&lt, MDL);
1380 }
1381
1382 /* Timer called when a lease in a particular pool expires. */
1383 void pool_timer (vpool)
1384 void *vpool;
1385 {
1386 struct pool *pool;
1387 struct lease *lt = (struct lease *)0;
1388 struct lease *next = (struct lease *)0;
1389 struct lease *lease = (struct lease *)0;
1390 struct lease **lptr [5];
1391 TIME next_expiry = MAX_TIME;
1392 int i;
1393
1394 pool = (struct pool *)vpool;
1395
1396 #define FREE_LEASES 0
1397 lptr [FREE_LEASES] = &pool -> free;
1398 #define ACTIVE_LEASES 1
1399 lptr [ACTIVE_LEASES] = &pool -> active;
1400 #define EXPIRED_LEASES 2
1401 lptr [EXPIRED_LEASES] = &pool -> expired;
1402 #define ABANDONED_LEASES 3
1403 lptr [ABANDONED_LEASES] = &pool -> abandoned;
1404 #define BACKUP_LEASES 4
1405 lptr [BACKUP_LEASES] = &pool -> backup;
1406
1407 for (i = FREE_LEASES; i <= BACKUP_LEASES; i++) {
1408 /* If there's nothing on the queue, skip it. */
1409 if (!*(lptr [i]))
1410 continue;
1411
1412 lease_reference (&lease, *(lptr [i]), MDL);
1413
1414 while (lease) {
1415 /* Remember the next lease in the list. */
1416 if (next)
1417 lease_dereference (&next, MDL);
1418 if (lease -> next)
1419 lease_reference (&next, lease -> next, MDL);
1420
1421 /* If we've run out of things to expire on this list,
1422 stop. */
1423 if (lease -> sort_time > cur_time) {
1424 if (lease -> sort_time < next_expiry)
1425 next_expiry = lease -> sort_time;
1426 break;
1427 }
1428
1429 /* If there is a pending state change, and
1430 this lease has gotten to the time when the
1431 state change should happen, just call
1432 supersede_lease on it to make the change
1433 happen. */
1434 if (lease -> next_binding_state !=
1435 lease -> binding_state)
1436 supersede_lease (lease,
1437 (struct lease *)0, 1, 1, 1);
1438
1439 lease_dereference (&lease, MDL);
1440 if (next)
1441 lease_reference (&lease, next, MDL);
1442 }
1443 if (next)
1444 lease_dereference (&next, MDL);
1445 if (lease)
1446 lease_dereference (&lease, MDL);
1447 }
1448 if (next_expiry != MAX_TIME) {
1449 pool -> next_event_time = next_expiry;
1450 add_timeout (pool -> next_event_time, pool_timer, pool,
1451 (tvref_t)pool_reference,
1452 (tvunref_t)pool_dereference);
1453 } else
1454 pool -> next_event_time = MIN_TIME;
1455
1456 }
1457
1458 /* Locate the lease associated with a given IP address... */
1459
1460 int find_lease_by_ip_addr (struct lease **lp, struct iaddr addr,
1461 const char *file, int line)
1462 {
1463 return lease_hash_lookup (lp, lease_ip_addr_hash,
1464 addr.iabuf, addr.len, file, line);
1465 }
1466
1467 int find_lease_by_uid (struct lease **lp, const unsigned char *uid,
1468 unsigned len, const char *file, int line)
1469 {
1470 if (len == 0)
1471 return 0;
1472 return lease_hash_lookup (lp, lease_uid_hash, uid, len, file, line);
1473 }
1474
1475 int find_lease_by_hw_addr (struct lease **lp,
1476 const unsigned char *hwaddr, unsigned hwlen,
1477 const char *file, int line)
1478 {
1479 if (hwlen == 0)
1480 return 0;
1481 return lease_hash_lookup (lp, lease_hw_addr_hash,
1482 hwaddr, hwlen, file, line);
1483 }
1484
1485 /* Add the specified lease to the uid hash. */
1486
1487 void uid_hash_add (lease)
1488 struct lease *lease;
1489 {
1490 struct lease *head = (struct lease *)0;
1491 struct lease *scan;
1492
1493
1494 /* If it's not in the hash, just add it. */
1495 if (!find_lease_by_uid (&head, lease -> uid, lease -> uid_len, MDL))
1496 lease_hash_add (lease_uid_hash, lease -> uid,
1497 lease -> uid_len, lease, MDL);
1498 else {
1499 /* Otherwise, attach it to the end of the list. */
1500 for (scan = head; scan -> n_uid; scan = scan -> n_uid)
1501 ;
1502 lease_reference (&scan -> n_uid, lease, MDL);
1503 lease_dereference (&head, MDL);
1504 }
1505 }
1506
1507 /* Delete the specified lease from the uid hash. */
1508
1509 void uid_hash_delete (lease)
1510 struct lease *lease;
1511 {
1512 struct lease *head = (struct lease *)0;
1513 struct lease *scan;
1514
1515 /* If it's not in the hash, we have no work to do. */
1516 if (!find_lease_by_uid (&head, lease -> uid, lease -> uid_len, MDL)) {
1517 if (lease -> n_uid)
1518 lease_dereference (&lease -> n_uid, MDL);
1519 return;
1520 }
1521
1522 /* If the lease we're freeing is at the head of the list,
1523 remove the hash table entry and add a new one with the
1524 next lease on the list (if there is one). */
1525 if (head == lease) {
1526 lease_hash_delete (lease_uid_hash,
1527 lease -> uid, lease -> uid_len, MDL);
1528 if (lease -> n_uid) {
1529 lease_hash_add (lease_uid_hash,
1530 lease -> n_uid -> uid,
1531 lease -> n_uid -> uid_len,
1532 lease -> n_uid, MDL);
1533 lease_dereference (&lease -> n_uid, MDL);
1534 }
1535 } else {
1536 /* Otherwise, look for the lease in the list of leases
1537 attached to the hash table entry, and remove it if
1538 we find it. */
1539 for (scan = head; scan -> n_uid; scan = scan -> n_uid) {
1540 if (scan -> n_uid == lease) {
1541 lease_dereference (&scan -> n_uid, MDL);
1542 if (lease -> n_uid) {
1543 lease_reference (&scan -> n_uid,
1544 lease -> n_uid, MDL);
1545 lease_dereference (&lease -> n_uid,
1546 MDL);
1547 }
1548 break;
1549 }
1550 }
1551 }
1552 lease_dereference (&head, MDL);
1553 }
1554
1555 /* Add the specified lease to the hardware address hash. */
1556
1557 void hw_hash_add (lease)
1558 struct lease *lease;
1559 {
1560 struct lease *head = (struct lease *)0;
1561 struct lease *scan;
1562
1563 /* If it's not in the hash, just add it. */
1564 if (!find_lease_by_hw_addr (&head, lease -> hardware_addr.hbuf,
1565 lease -> hardware_addr.hlen, MDL))
1566 lease_hash_add (lease_hw_addr_hash,
1567 lease -> hardware_addr.hbuf,
1568 lease -> hardware_addr.hlen,
1569 lease, MDL);
1570 else {
1571 /* Otherwise, attach it to the end of the list. */
1572 for (scan = head; scan -> n_hw; scan = scan -> n_hw)
1573 ;
1574 lease_reference (&scan -> n_hw, lease, MDL);
1575 lease_dereference (&head, MDL);
1576 }
1577 }
1578
1579 /* Delete the specified lease from the hardware address hash. */
1580
1581 void hw_hash_delete (lease)
1582 struct lease *lease;
1583 {
1584 struct lease *head = (struct lease *)0;
1585 struct lease *scan;
1586
1587 /* If it's not in the hash, we have no work to do. */
1588 if (!find_lease_by_hw_addr (&head, lease -> hardware_addr.hbuf,
1589 lease -> hardware_addr.hlen, MDL)) {
1590 if (lease -> n_hw)
1591 lease_dereference (&lease -> n_hw, MDL);
1592 return;
1593 }
1594
1595 /* If the lease we're freeing is at the head of the list,
1596 remove the hash table entry and add a new one with the
1597 next lease on the list (if there is one). */
1598 if (head == lease) {
1599 lease_hash_delete (lease_hw_addr_hash,
1600 lease -> hardware_addr.hbuf,
1601 lease -> hardware_addr.hlen, MDL);
1602 if (lease -> n_hw) {
1603 lease_hash_add (lease_hw_addr_hash,
1604 lease -> n_hw -> hardware_addr.hbuf,
1605 lease -> n_hw -> hardware_addr.hlen,
1606 lease -> n_hw, MDL);
1607 lease_dereference (&lease -> n_hw, MDL);
1608 }
1609 } else {
1610 /* Otherwise, look for the lease in the list of leases
1611 attached to the hash table entry, and remove it if
1612 we find it. */
1613 for (scan = head; scan -> n_hw; scan = scan -> n_hw) {
1614 if (scan -> n_hw == lease) {
1615 lease_dereference (&scan -> n_hw, MDL);
1616 if (lease -> n_hw) {
1617 lease_reference (&scan -> n_hw,
1618 lease -> n_hw, MDL);
1619 lease_dereference (&lease -> n_hw,
1620 MDL);
1621 }
1622 break;
1623 }
1624 }
1625 }
1626 lease_dereference (&head, MDL);
1627 }
1628
1629 /* Write all interesting leases to permanent storage. */
1630
1631 void write_leases ()
1632 {
1633 struct lease *l;
1634 struct shared_network *s;
1635 struct pool *p;
1636 struct host_decl *hp;
1637 struct group_object *gp;
1638 struct hash_bucket *hb;
1639 int i;
1640 int num_written;
1641 struct lease **lptr [5];
1642
1643 /* Write all the dynamically-created group declarations. */
1644 if (group_name_hash) {
1645 num_written = 0;
1646 for (i = 0; i < group_name_hash -> hash_count; i++) {
1647 for (hb = group_name_hash -> buckets [i];
1648 hb; hb = hb -> next) {
1649 gp = (struct group_object *)hb -> value;
1650 if ((gp -> flags & GROUP_OBJECT_DYNAMIC) ||
1651 ((gp -> flags & GROUP_OBJECT_STATIC) &&
1652 (gp -> flags & GROUP_OBJECT_DELETED))) {
1653 write_group (gp);
1654 ++num_written;
1655 }
1656 }
1657 }
1658 log_info ("Wrote %d group decls to leases file.", num_written);
1659 }
1660
1661 /* Write all the deleted host declarations. */
1662 if (host_name_hash) {
1663 num_written = 0;
1664 for (i = 0; i < host_name_hash -> hash_count; i++) {
1665 for (hb = host_name_hash -> buckets [i];
1666 hb; hb = hb -> next) {
1667 hp = (struct host_decl *)hb -> value;
1668 if (((hp -> flags & HOST_DECL_STATIC) &&
1669 (hp -> flags & HOST_DECL_DELETED))) {
1670 write_host (hp);
1671 ++num_written;
1672 }
1673 }
1674 }
1675 log_info ("Wrote %d deleted host decls to leases file.",
1676 num_written);
1677 }
1678
1679 /* Write all the new, dynamic host declarations. */
1680 if (host_name_hash) {
1681 num_written = 0;
1682 for (i = 0; i < host_name_hash -> hash_count; i++) {
1683 for (hb = host_name_hash -> buckets [i];
1684 hb; hb = hb -> next) {
1685 hp = (struct host_decl *)hb -> value;
1686 if ((hp -> flags & HOST_DECL_DYNAMIC)) {
1687 write_host (hp);
1688 ++num_written;
1689 }
1690 }
1691 }
1692 log_info ("Wrote %d new dynamic host decls to leases file.",
1693 num_written);
1694 }
1695
1696 #if defined (FAILOVER_PROTOCOL)
1697 /* Write all the failover states. */
1698 dhcp_failover_write_all_states ();
1699 #endif
1700
1701 /* Write all the leases. */
1702 num_written = 0;
1703 for (s = shared_networks; s; s = s -> next) {
1704 for (p = s -> pools; p; p = p -> next) {
1705 lptr [FREE_LEASES] = &p -> free;
1706 lptr [ACTIVE_LEASES] = &p -> active;
1707 lptr [EXPIRED_LEASES] = &p -> expired;
1708 lptr [ABANDONED_LEASES] = &p -> abandoned;
1709 lptr [BACKUP_LEASES] = &p -> backup;
1710
1711 for (i = FREE_LEASES; i <= BACKUP_LEASES; i++) {
1712 for (l = *(lptr [i]); l; l = l -> next) {
1713 if (l -> hardware_addr.hlen ||
1714 l -> uid_len ||
1715 (l -> binding_state != FTS_FREE)) {
1716 if (!write_lease (l))
1717 log_fatal ("Can't rewrite lease database");
1718 num_written++;
1719 }
1720 }
1721 }
1722 }
1723 }
1724 log_info ("Wrote %d leases to leases file.", num_written);
1725 if (!commit_leases ())
1726 log_fatal ("Can't commit leases to new database: %m");
1727 }
1728
1729 int lease_enqueue (struct lease *comp)
1730 {
1731 struct lease **lq, *prev, *lp;
1732
1733 /* No queue to put it on? */
1734 if (!comp -> pool)
1735 return 0;
1736
1737 /* Figure out which queue it's going to. */
1738 switch (comp -> binding_state) {
1739 case FTS_FREE:
1740 lq = &comp -> pool -> free;
1741 comp -> pool -> free_leases++;
1742 comp -> sort_time = comp -> ends;
1743 break;
1744
1745 case FTS_ACTIVE:
1746 case FTS_RESERVED:
1747 case FTS_BOOTP:
1748 lq = &comp -> pool -> active;
1749 comp -> sort_time = comp -> ends;
1750 break;
1751
1752 case FTS_EXPIRED:
1753 case FTS_RELEASED:
1754 case FTS_RESET:
1755 lq = &comp -> pool -> expired;
1756 comp -> sort_time = comp -> ends;
1757
1758 break;
1759
1760 case FTS_ABANDONED:
1761 lq = &comp -> pool -> abandoned;
1762 comp -> sort_time = comp -> ends;
1763 break;
1764
1765 case FTS_BACKUP:
1766 lq = &comp -> pool -> backup;
1767 comp -> pool -> backup_leases++;
1768 comp -> sort_time = comp -> ends;
1769 break;
1770
1771 default:
1772 log_error ("Lease with bogus binding state: %d",
1773 comp -> binding_state);
1774 return 0;
1775 }
1776
1777 /* Insertion sort the lease onto the appropriate queue. */
1778 prev = (struct lease *)0;
1779 for (lp = *lq; lp; lp = lp -> next) {
1780 if (lp -> sort_time >= comp -> sort_time)
1781 break;
1782 prev = lp;
1783 }
1784 if (prev) {
1785 if (prev -> next) {
1786 lease_reference (&comp -> next, prev -> next, MDL);
1787 lease_dereference (&prev -> next, MDL);
1788 }
1789 lease_reference (&prev -> next, comp, MDL);
1790 } else {
1791 if (*lq) {
1792 lease_reference (&comp -> next, *lq, MDL);
1793 lease_dereference (lq, MDL);
1794 }
1795 lease_reference (lq, comp, MDL);
1796 }
1797 return 1;
1798 }
1799
1800 /* For a given lease, sort it onto the right list in its pool and put it
1801 in each appropriate hash, understanding that it's already by definition
1802 in lease_ip_addr_hash. */
1803
1804 void lease_instantiate (const unsigned char *val, unsigned len,
1805 struct lease *lease)
1806 {
1807
1808 /* XXX If the lease doesn't have a pool at this point, it's an
1809 XXX orphan, which we *should* keep around until it expires,
1810 XXX but which right now we just forget. */
1811 if (!lease -> pool) {
1812 lease_hash_delete (lease_ip_addr_hash,
1813 lease -> ip_addr.iabuf,
1814 lease -> ip_addr.len, MDL);
1815 return;
1816 }
1817
1818 /* Put the lease on the right queue. */
1819 lease_enqueue (lease);
1820
1821 /* Record the lease in the uid hash if possible. */
1822 if (lease -> uid) {
1823 uid_hash_add (lease);
1824 }
1825
1826 /* Record it in the hardware address hash if possible. */
1827 if (lease -> hardware_addr.hlen) {
1828 hw_hash_add (lease);
1829 }
1830
1831 return;
1832 }
1833
1834 /* Run expiry events on every pool. This is called on startup so that
1835 any expiry events that occurred after the server stopped and before it
1836 was restarted can be run. At the same time, if failover support is
1837 compiled in, we compute the balance of leases for the pool. */
1838
1839 void expire_all_pools ()
1840 {
1841 struct shared_network *s;
1842 struct pool *p;
1843 struct hash_bucket *hb;
1844 int i;
1845 struct lease *l;
1846 struct lease **lptr [5];
1847
1848 /* First, go over the hash list and actually put all the leases
1849 on the appropriate lists. */
1850 lease_hash_foreach (lease_ip_addr_hash, lease_instantiate);
1851
1852 /* Loop through each pool in each shared network and call the
1853 expiry routine on the pool. */
1854 for (s = shared_networks; s; s = s -> next) {
1855 for (p = s -> pools; p; p = p -> next) {
1856 pool_timer (p);
1857
1858 p -> lease_count = 0;
1859 p -> free_leases = 0;
1860 p -> backup_leases = 0;
1861
1862 lptr [FREE_LEASES] = &p -> free;
1863 lptr [ACTIVE_LEASES] = &p -> active;
1864 lptr [EXPIRED_LEASES] = &p -> expired;
1865 lptr [ABANDONED_LEASES] = &p -> abandoned;
1866 lptr [BACKUP_LEASES] = &p -> backup;
1867
1868 for (i = FREE_LEASES; i <= BACKUP_LEASES; i++) {
1869 for (l = *(lptr [i]); l; l = l -> next) {
1870 p -> lease_count++;
1871 if (l -> ends <= cur_time) {
1872 if (l -> binding_state == FTS_FREE)
1873 p -> free_leases++;
1874 else if (l -> binding_state == FTS_BACKUP)
1875 p -> backup_leases++;
1876 }
1877 #if defined (FAILOVER_PROTOCOL)
1878 if (p -> failover_peer &&
1879 l -> tstp > l -> tsfp &&
1880 !(l -> flags & ON_UPDATE_QUEUE))
1881 dhcp_failover_queue_update (l, 1);
1882 #endif
1883 }
1884 }
1885 }
1886 }
1887 }
1888
1889 void dump_subnets ()
1890 {
1891 struct lease *l;
1892 struct shared_network *s;
1893 struct subnet *n;
1894 struct pool *p;
1895 struct lease **lptr [5];
1896 int i;
1897
1898 log_info ("Subnets:");
1899 for (n = subnets; n; n = n -> next_subnet) {
1900 log_debug (" Subnet %s", piaddr (n -> net));
1901 log_debug (" netmask %s",
1902 piaddr (n -> netmask));
1903 }
1904 log_info ("Shared networks:");
1905 for (s = shared_networks; s; s = s -> next) {
1906 log_info (" %s", s -> name);
1907 for (p = s -> pools; p; p = p -> next) {
1908 lptr [FREE_LEASES] = &p -> free;
1909 lptr [ACTIVE_LEASES] = &p -> active;
1910 lptr [EXPIRED_LEASES] = &p -> expired;
1911 lptr [ABANDONED_LEASES] = &p -> abandoned;
1912 lptr [BACKUP_LEASES] = &p -> backup;
1913
1914 for (i = FREE_LEASES; i <= BACKUP_LEASES; i++) {
1915 for (l = *(lptr [i]); l; l = l -> next) {
1916 print_lease (l);
1917 }
1918 }
1919 }
1920 }
1921 }
1922
1923 HASH_FUNCTIONS (lease, const unsigned char *, struct lease)
1924 HASH_FUNCTIONS (host, const unsigned char *, struct host_decl)
1925 HASH_FUNCTIONS (class, const char *, struct class)