]> git.ipfire.org Git - thirdparty/dhcp.git/blob - server/mdb.c
- Move ddns_removals out of the on_release conditionals so that it actually
[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.48 2001/01/04 00:30:53 mellon 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 there is no sample lease, just do the move. */
779 if (!lease)
780 goto just_move_it;
781
782 /* Static leases are not currently kept in the database... */
783 if (lease -> flags & STATIC_LEASE)
784 return 1;
785
786 /* If the existing lease hasn't expired and has a different
787 unique identifier or, if it doesn't have a unique
788 identifier, a different hardware address, then the two
789 leases are in conflict. If the existing lease has a uid
790 and the new one doesn't, but they both have the same
791 hardware address, and dynamic bootp is allowed on this
792 lease, then we allow that, in case a dynamic BOOTP lease is
793 requested *after* a DHCP lease has been assigned. */
794
795 if (lease -> binding_state != FTS_ABANDONED &&
796 (comp -> binding_state == FTS_ACTIVE ||
797 comp -> binding_state == FTS_RESERVED ||
798 comp -> binding_state == FTS_BOOTP) &&
799 (((comp -> uid && lease -> uid) &&
800 (comp -> uid_len != lease -> uid_len ||
801 memcmp (comp -> uid, lease -> uid, comp -> uid_len))) ||
802 (!comp -> uid &&
803 ((comp -> hardware_addr.hlen !=
804 lease -> hardware_addr.hlen) ||
805 memcmp (comp -> hardware_addr.hbuf,
806 lease -> hardware_addr.hbuf,
807 comp -> hardware_addr.hlen))))) {
808 log_error ("Lease conflict at %s",
809 piaddr (comp -> ip_addr));
810 return 0;
811 }
812
813 /* If there's a Unique ID, dissociate it from the hash
814 table and free it if necessary. */
815 if (comp -> uid) {
816 uid_hash_delete (comp);
817 enter_uid = 1;
818 if (comp -> uid != &comp -> uid_buf [0]) {
819 dfree (comp -> uid, MDL);
820 comp -> uid_max = 0;
821 comp -> uid_len = 0;
822 }
823 comp -> uid = (unsigned char *)0;
824 } else
825 enter_uid = 1;
826
827 if (comp -> hardware_addr.hlen &&
828 ((comp -> hardware_addr.hlen !=
829 lease -> hardware_addr.hlen) ||
830 memcmp (comp -> hardware_addr.hbuf,
831 lease -> hardware_addr.hbuf,
832 comp -> hardware_addr.hlen))) {
833 hw_hash_delete (comp);
834 enter_hwaddr = 1;
835 } else if (!comp -> hardware_addr.hlen)
836 enter_hwaddr = 1;
837
838 /* If the lease has been billed to a class, remove the billing. */
839 if (comp -> billing_class != lease -> billing_class) {
840 if (comp -> billing_class)
841 unbill_class (comp, comp -> billing_class);
842 if (lease -> billing_class)
843 bill_class (comp, lease -> billing_class);
844 }
845
846 /* Copy the data files, but not the linkages. */
847 comp -> starts = lease -> starts;
848 if (lease -> uid) {
849 if (lease -> uid_len <= sizeof (lease -> uid_buf)) {
850 memcpy (comp -> uid_buf,
851 lease -> uid, lease -> uid_len);
852 comp -> uid = &comp -> uid_buf [0];
853 comp -> uid_max = sizeof comp -> uid_buf;
854 } else if (lease -> uid != &lease -> uid_buf [0]) {
855 comp -> uid = lease -> uid;
856 comp -> uid_max = lease -> uid_max;
857 lease -> uid = (unsigned char *)0;
858 lease -> uid_max = 0;
859 } else {
860 log_fatal ("corrupt lease uid."); /* XXX */
861 }
862 } else {
863 comp -> uid = (unsigned char *)0;
864 comp -> uid_max = 0;
865 }
866 comp -> uid_len = lease -> uid_len;
867 if (comp -> host)
868 host_dereference (&comp -> host, MDL);
869 host_reference (&comp -> host, lease -> host, MDL);
870 comp -> hardware_addr = lease -> hardware_addr;
871 comp -> flags = ((lease -> flags & ~PERSISTENT_FLAGS) |
872 (comp -> flags & ~EPHEMERAL_FLAGS));
873 if (comp -> scope)
874 binding_scope_dereference (&comp -> scope, MDL);
875 if (lease -> scope) {
876 binding_scope_reference (&comp -> scope, lease -> scope, MDL);
877 binding_scope_dereference (&lease -> scope, MDL);
878 }
879
880 if (comp -> agent_options)
881 option_cache_dereference (&comp -> agent_options, MDL);
882 if (lease -> agent_options) {
883 /* Only retain the agent options if the lease is still
884 affirmatively associated with a client. */
885 if (lease -> binding_state == FTS_ACTIVE ||
886 lease -> binding_state == FTS_EXPIRED ||
887 lease -> binding_state == FTS_ABANDONED ||
888 lease -> binding_state == FTS_RESERVED ||
889 lease -> binding_state == FTS_BOOTP)
890 option_cache_reference (&comp -> agent_options,
891 lease -> agent_options, MDL);
892 option_cache_dereference (&lease -> agent_options, MDL);
893 }
894
895 /* Record the hostname information in the lease. */
896 if (comp -> hostname)
897 dfree (comp -> hostname, MDL);
898 comp -> hostname = lease -> hostname;
899 lease -> hostname = (char *)0;
900 if (comp -> client_hostname)
901 dfree (comp -> client_hostname, MDL);
902 comp -> client_hostname = lease -> client_hostname;
903 lease -> client_hostname = (char *)0;
904
905 if (lease -> on_expiry) {
906 if (comp -> on_expiry)
907 executable_statement_dereference (&comp -> on_expiry,
908 MDL);
909 executable_statement_reference (&comp -> on_expiry,
910 lease -> on_expiry,
911 MDL);
912 }
913 if (lease -> on_commit) {
914 if (comp -> on_commit)
915 executable_statement_dereference (&comp -> on_commit,
916 MDL);
917 executable_statement_reference (&comp -> on_commit,
918 lease -> on_commit,
919 MDL);
920 }
921 if (lease -> on_release) {
922 if (comp -> on_release)
923 executable_statement_dereference (&comp -> on_release,
924 MDL);
925 executable_statement_reference (&comp -> on_release,
926 lease -> on_release, MDL);
927 }
928
929 /* Record the lease in the uid hash if necessary. */
930 if (enter_uid && lease -> uid) {
931 uid_hash_add (comp);
932 }
933
934 /* Record it in the hardware address hash if necessary. */
935 if (enter_hwaddr && lease -> hardware_addr.hlen) {
936 hw_hash_add (comp);
937 }
938
939 #if defined (FAILOVER_PROTOCOL)
940 comp -> cltt = lease -> cltt;
941 comp -> tstp = lease -> tstp;
942 comp -> tsfp = lease -> tsfp;
943 #endif /* FAILOVER_PROTOCOL */
944 comp -> ends = lease -> ends;
945 comp -> next_binding_state = lease -> next_binding_state;
946
947 just_move_it:
948 /* Figure out which queue it's on. */
949 switch (comp -> binding_state) {
950 case FTS_FREE:
951 lq = &comp -> pool -> free;
952 comp -> pool -> free_leases--;
953 break;
954
955 case FTS_ACTIVE:
956 case FTS_RESERVED:
957 case FTS_BOOTP:
958 lq = &comp -> pool -> active;
959 break;
960
961 case FTS_EXPIRED:
962 case FTS_RELEASED:
963 case FTS_RESET:
964 lq = &comp -> pool -> expired;
965 break;
966
967 case FTS_ABANDONED:
968 lq = &comp -> pool -> abandoned;
969 break;
970
971 case FTS_BACKUP:
972 lq = &comp -> pool -> backup;
973 comp -> pool -> backup_leases--;
974 break;
975
976 default:
977 log_error ("Lease with bogus binding state: %d",
978 comp -> binding_state);
979 return 0;
980 }
981
982 /* Remove the lease from its current place in its current
983 timer sequence. */
984 prev = (struct lease *)0;
985 for (lp = *lq; lp; lp = lp -> next) {
986 if (lp == comp)
987 break;
988 prev = lp;
989 }
990
991 if (!lp) {
992 log_error ("Lease with binding state %s not on its queue.",
993 (comp -> binding_state < 1 &&
994 comp -> binding_state < FTS_BOOTP)
995 ? "unknown"
996 : binding_state_names [comp -> binding_state - 1]);
997 return 0;
998 }
999
1000 if (prev) {
1001 lease_dereference (&prev -> next, MDL);
1002 if (comp -> next) {
1003 lease_reference (&prev -> next, comp -> next, MDL);
1004 lease_dereference (&comp -> next, MDL);
1005 }
1006 } else {
1007 lease_dereference (lq, MDL);
1008 if (comp -> next) {
1009 lease_reference (lq, comp -> next, MDL);
1010 lease_dereference (&comp -> next, MDL);
1011 }
1012 }
1013
1014 /* Make the state transition. */
1015 if (commit)
1016 process_state_transition (comp);
1017
1018 /* Put the lease back on the appropriate queue. If the lease
1019 is corrupt (as detected by lease_enqueue), don't go any farther. */
1020 if (!lease_enqueue (comp))
1021 return 0;
1022
1023 /* If this is the next lease that will timeout on the pool,
1024 zap the old timeout and set the timeout on this pool to the
1025 time that the lease's next event will happen.
1026
1027 We do not actually set the timeout unless commit is true -
1028 we don't want to thrash the timer queue when reading the
1029 lease database. Instead, the database code calls the
1030 expiry event on each pool after reading in the lease file,
1031 and the expiry code sets the timer if there's anything left
1032 to expire after it's run any outstanding expiry events on
1033 the pool. */
1034 if (commit &&
1035 comp -> sort_time != MIN_TIME &&
1036 comp -> sort_time > cur_time &&
1037 (comp -> sort_time < comp -> pool -> next_event_time ||
1038 comp -> pool -> next_event_time == MIN_TIME)) {
1039 comp -> pool -> next_event_time = comp -> sort_time;
1040 add_timeout (comp -> pool -> next_event_time,
1041 pool_timer, comp -> pool,
1042 (tvref_t)pool_reference,
1043 (tvunref_t)pool_dereference);
1044 }
1045
1046 /* Return zero if we didn't commit the lease to permanent storage;
1047 nonzero if we did. */
1048 return commit && write_lease (comp) && commit_leases ()
1049 #if defined (FAILOVER_PROTOCOL)
1050 && (!propogate ||
1051 dhcp_failover_queue_update (comp, pimmediate))
1052 #endif
1053 ;
1054 }
1055
1056 void process_state_transition (struct lease *lease)
1057 {
1058 /* If the lease was active and is now no longer active, but isn't
1059 released, then it just expired, so do the expiry event. */
1060 if (lease -> next_binding_state != lease -> binding_state &&
1061 (lease -> binding_state == FTS_ACTIVE ||
1062 lease -> binding_state == FTS_BOOTP ||
1063 lease -> binding_state == FTS_RESERVED) &&
1064 lease -> next_binding_state != FTS_RELEASED) {
1065 ddns_removals (lease);
1066 if (lease -> on_expiry) {
1067 execute_statements ((struct binding_value **)0,
1068 (struct packet *)0, lease,
1069 (struct client_state *)0,
1070 (struct option_state *)0,
1071 (struct option_state *)0, /* XXX */
1072 &lease -> scope,
1073 lease -> on_expiry);
1074 if (lease -> on_expiry)
1075 executable_statement_dereference
1076 (&lease -> on_expiry, MDL);
1077 }
1078
1079 /* No sense releasing a lease after it's expired. */
1080 if (lease -> on_release)
1081 executable_statement_dereference (&lease -> on_release,
1082 MDL);
1083 /* Send the expiry time to the peer. */
1084 lease -> tstp = lease -> ends;
1085 }
1086
1087 /* If the lease was active and is now released, do the release
1088 event. */
1089 if ((lease -> binding_state == FTS_ACTIVE ||
1090 lease -> binding_state == FTS_BOOTP ||
1091 lease -> binding_state == FTS_RESERVED) &&
1092 lease -> next_binding_state == FTS_RELEASED) {
1093 ddns_removals (lease);
1094 if (lease -> on_release) {
1095 execute_statements ((struct binding_value **)0,
1096 (struct packet *)0, lease,
1097 (struct client_state *)0,
1098 (struct option_state *)0,
1099 (struct option_state *)0, /* XXX */
1100 &lease -> scope,
1101 lease -> on_release);
1102 executable_statement_dereference (&lease -> on_release,
1103 MDL);
1104 }
1105
1106 /* A released lease can't expire. */
1107 if (lease -> on_expiry)
1108 executable_statement_dereference (&lease -> on_expiry,
1109 MDL);
1110
1111 /* Send the release time (should be == cur_time) to the
1112 peer. */
1113 lease -> tstp = lease -> ends;
1114 }
1115
1116 lease -> binding_state = lease -> next_binding_state;
1117 if (lease -> binding_state == FTS_ACTIVE ||
1118 lease -> binding_state == FTS_BACKUP) {
1119 #if defined (FAILOVER_PROTOCOL)
1120 if (lease -> pool && lease -> pool -> failover_peer)
1121 lease -> next_binding_state = FTS_EXPIRED;
1122 else
1123 #endif
1124 lease -> next_binding_state = FTS_FREE;
1125 }
1126 }
1127
1128 /* Copy the contents of one lease into another, correctly maintaining
1129 reference counts. */
1130 int lease_copy (struct lease **lp,
1131 struct lease *lease, const char *file, int line)
1132 {
1133 struct lease *lt = (struct lease *)0;
1134 isc_result_t status;
1135
1136 status = lease_allocate (&lt, MDL);
1137 if (status != ISC_R_SUCCESS)
1138 return 0;
1139
1140 lt -> ip_addr = lease -> ip_addr;
1141 lt -> starts = lease -> starts;
1142 lt -> ends = lease -> ends;
1143 lt -> timestamp = lease -> timestamp;
1144 lt -> uid_len = lease -> uid_len;
1145 lt -> uid_max = lease -> uid_max;
1146 if (lease -> uid == lease -> uid_buf) {
1147 lt -> uid = lt -> uid_buf;
1148 memcpy (lt -> uid_buf, lease -> uid_buf, sizeof lt -> uid_buf);
1149 } else {
1150 lt -> uid = dmalloc (lt -> uid_max, MDL);
1151 if (!lt -> uid) {
1152 lease_dereference (&lt, MDL);
1153 return 0;
1154 }
1155 memcpy (lt -> uid, lease -> uid, lease -> uid_max);
1156 }
1157 if (lease -> hostname) {
1158 lt -> hostname = dmalloc (strlen (lease -> hostname) + 1, MDL);
1159 if (!lt -> hostname) {
1160 lease_dereference (&lt, MDL);
1161 return 0;
1162 }
1163 strcpy (lt -> hostname, lease -> hostname);
1164 }
1165 if (lease -> client_hostname) {
1166 lt -> client_hostname =
1167 dmalloc (strlen (lease -> client_hostname) + 1, MDL);
1168 if (!lt -> client_hostname) {
1169 lease_dereference (&lt, MDL);
1170 return 0;
1171 }
1172 strcpy (lt -> client_hostname, lease -> client_hostname);
1173 }
1174 if (lease -> scope)
1175 binding_scope_reference (&lt -> scope, lease -> scope, MDL);
1176 if (lease -> agent_options)
1177 option_cache_reference (&lt -> agent_options,
1178 lease -> agent_options, MDL);
1179 host_reference (&lt -> host, lease -> host, file, line);
1180 subnet_reference (&lt -> subnet, lease -> subnet, file, line);
1181 pool_reference (&lt -> pool, lease -> pool, file, line);
1182 class_reference (&lt -> billing_class,
1183 lease -> billing_class, file, line);
1184 lt -> hardware_addr = lease -> hardware_addr;
1185 if (lease -> on_expiry)
1186 executable_statement_reference (&lt -> on_expiry,
1187 lease -> on_expiry,
1188 file, line);
1189 if (lease -> on_commit)
1190 executable_statement_reference (&lt -> on_commit,
1191 lease -> on_commit,
1192 file, line);
1193 if (lease -> on_release)
1194 executable_statement_reference (&lt -> on_release,
1195 lease -> on_release,
1196 file, line);
1197 lt -> flags = lease -> flags;
1198 lt -> tstp = lease -> tstp;
1199 lt -> tsfp = lease -> tsfp;
1200 lt -> cltt = lease -> cltt;
1201 lt -> binding_state = lease -> binding_state;
1202 lt -> next_binding_state = lease -> next_binding_state;
1203 status = lease_reference (lp, lt, file, line);
1204 lease_dereference (&lt, MDL);
1205 return status == ISC_R_SUCCESS;
1206 }
1207
1208 /* Release the specified lease and re-hash it as appropriate. */
1209 void release_lease (lease, packet)
1210 struct lease *lease;
1211 struct packet *packet;
1212 {
1213 /* If there are statements to execute when the lease is
1214 released, execute them. */
1215 ddns_removals (lease);
1216 if (lease -> on_release) {
1217 execute_statements ((struct binding_value **)0,
1218 packet, lease, (struct client_state *)0,
1219 packet -> options,
1220 (struct option_state *)0, /* XXX */
1221 &lease -> scope, lease -> on_release);
1222 if (lease -> on_release)
1223 executable_statement_dereference (&lease -> on_release,
1224 MDL);
1225 }
1226
1227 /* We do either the on_release or the on_expiry events, but
1228 not both (it's possible that they could be the same,
1229 in any case). */
1230 if (lease -> on_expiry)
1231 executable_statement_dereference (&lease -> on_expiry, MDL);
1232
1233 if (lease -> ends > cur_time) {
1234 if (lease -> on_commit)
1235 executable_statement_dereference (&lease -> on_commit,
1236 MDL);
1237
1238 /* Blow away any bindings. */
1239 if (lease -> scope)
1240 binding_scope_dereference (&lease -> scope, MDL);
1241 lease -> ends = cur_time;
1242 #if defined (FAILOVER_PROTOCOL)
1243 if (lease -> pool && lease -> pool -> failover_peer) {
1244 lease -> next_binding_state = FTS_RELEASED;
1245 } else {
1246 lease -> next_binding_state = FTS_FREE;
1247 }
1248 #else
1249 lease -> next_binding_state = FTS_FREE;
1250 #endif
1251 if (lease -> billing_class)
1252 class_dereference (&lease -> billing_class, MDL);
1253 supersede_lease (lease, (struct lease *)0, 1, 1, 1);
1254 }
1255 }
1256
1257 /* Abandon the specified lease (set its timeout to infinity and its
1258 particulars to zero, and re-hash it as appropriate. */
1259
1260 void abandon_lease (lease, message)
1261 struct lease *lease;
1262 const char *message;
1263 {
1264 struct lease *lt = (struct lease *)0;
1265
1266 if (!lease_copy (&lt, lease, MDL))
1267 return;
1268
1269 #if 0
1270 if (lt -> on_expiry)
1271 executable_statement_dereference (&lease -> on_expiry, MDL);
1272 if (lt -> on_release)
1273 executable_statement_dereference (&lease -> on_release, MDL);
1274 if (lt -> on_commit)
1275 executable_statement_dereference (&lease -> on_commit, MDL);
1276
1277 /* Blow away any bindings. */
1278 if (lt -> scope)
1279 binding_scope_dereference (&lt -> scope, MDL);
1280 #endif
1281
1282 lt -> ends = cur_time; /* XXX */
1283 lt -> next_binding_state = FTS_ABANDONED;
1284
1285 log_error ("Abandoning IP address %s: %s",
1286 piaddr (lease -> ip_addr), message);
1287 lt -> hardware_addr.hlen = 0;
1288 if (lt -> uid != lt -> uid_buf)
1289 dfree (lt -> uid, MDL);
1290 lt -> uid = (unsigned char *)0;
1291 lt -> uid_len = 0;
1292 lt -> uid_max = 0;
1293 if (lt -> billing_class)
1294 class_dereference (&lt -> billing_class, MDL);
1295 supersede_lease (lease, lt, 1, 1, 1);
1296 lease_dereference (&lt, MDL);
1297 }
1298
1299 /* Abandon the specified lease (set its timeout to infinity and its
1300 particulars to zero, and re-hash it as appropriate. */
1301
1302 void dissociate_lease (lease)
1303 struct lease *lease;
1304 {
1305 struct lease *lt = (struct lease *)0;
1306
1307 if (!lease_copy (&lt, lease, MDL))
1308 return;
1309
1310 #if 0
1311 if (lt -> on_expiry)
1312 executable_statement_dereference (&lease -> on_expiry, MDL);
1313 if (lt -> on_release)
1314 executable_statement_dereference (&lease -> on_release, MDL);
1315 if (lt -> on_commit)
1316 executable_statement_dereference (&lease -> on_commit, MDL);
1317
1318 /* Blow away any bindings. */
1319 if (lt -> scope)
1320 binding_scope_dereference (&lt -> scope, MDL);
1321 #endif
1322
1323 #if defined (FAILOVER_PROTOCOL)
1324 if (lease -> pool && lease -> pool -> failover_peer) {
1325 lt -> next_binding_state = FTS_RESET;
1326 } else {
1327 lt -> next_binding_state = FTS_FREE;
1328 }
1329 #else
1330 lt -> next_binding_state = FTS_FREE;
1331 #endif
1332 lt -> ends = cur_time; /* XXX */
1333 lt -> hardware_addr.hlen = 0;
1334 if (lt -> uid != lt -> uid_buf)
1335 dfree (lt -> uid, MDL);
1336 lt -> uid = (unsigned char *)0;
1337 lt -> uid_len = 0;
1338 lt -> uid_max = 0;
1339 if (lt -> billing_class)
1340 class_dereference (&lt -> billing_class, MDL);
1341 supersede_lease (lease, lt, 1, 1, 1);
1342 lease_dereference (&lt, MDL);
1343 }
1344
1345 /* Timer called when a lease in a particular pool expires. */
1346 void pool_timer (vpool)
1347 void *vpool;
1348 {
1349 struct pool *pool;
1350 struct lease *lt = (struct lease *)0;
1351 struct lease *next = (struct lease *)0;
1352 struct lease *lease = (struct lease *)0;
1353 struct lease **lptr [5];
1354 TIME next_expiry = MAX_TIME;
1355 int i;
1356
1357 pool = (struct pool *)vpool;
1358
1359 #define FREE_LEASES 0
1360 lptr [FREE_LEASES] = &pool -> free;
1361 #define ACTIVE_LEASES 1
1362 lptr [ACTIVE_LEASES] = &pool -> active;
1363 #define EXPIRED_LEASES 2
1364 lptr [EXPIRED_LEASES] = &pool -> expired;
1365 #define ABANDONED_LEASES 3
1366 lptr [ABANDONED_LEASES] = &pool -> abandoned;
1367 #define BACKUP_LEASES 4
1368 lptr [BACKUP_LEASES] = &pool -> backup;
1369
1370 for (i = FREE_LEASES; i <= BACKUP_LEASES; i++) {
1371 /* If there's nothing on the queue, skip it. */
1372 if (!*(lptr [i]))
1373 continue;
1374
1375 lease_reference (&lease, *(lptr [i]), MDL);
1376
1377 while (lease) {
1378 /* Remember the next lease in the list. */
1379 if (next)
1380 lease_dereference (&next, MDL);
1381 if (lease -> next)
1382 lease_reference (&next, lease -> next, MDL);
1383
1384 /* If we've run out of things to expire on this list,
1385 stop. */
1386 if (lease -> sort_time > cur_time) {
1387 if (lease -> sort_time < next_expiry)
1388 next_expiry = lease -> sort_time;
1389 break;
1390 }
1391
1392 /* If there is a pending state change, and
1393 this lease has gotten to the time when the
1394 state change should happen, just call
1395 supersede_lease on it to make the change
1396 happen. */
1397 if (lease -> next_binding_state !=
1398 lease -> binding_state)
1399 supersede_lease (lease,
1400 (struct lease *)0, 1, 1, 1);
1401
1402 lease_dereference (&lease, MDL);
1403 if (next)
1404 lease_reference (&lease, next, MDL);
1405 }
1406 if (next)
1407 lease_dereference (&next, MDL);
1408 if (lease)
1409 lease_dereference (&lease, MDL);
1410 }
1411 if (next_expiry != MAX_TIME) {
1412 pool -> next_event_time = next_expiry;
1413 add_timeout (pool -> next_event_time, pool_timer, pool,
1414 (tvref_t)pool_reference,
1415 (tvunref_t)pool_dereference);
1416 } else
1417 pool -> next_event_time = MIN_TIME;
1418
1419 }
1420
1421 /* Locate the lease associated with a given IP address... */
1422
1423 int find_lease_by_ip_addr (struct lease **lp, struct iaddr addr,
1424 const char *file, int line)
1425 {
1426 return lease_hash_lookup (lp, lease_ip_addr_hash,
1427 addr.iabuf, addr.len, file, line);
1428 }
1429
1430 int find_lease_by_uid (struct lease **lp, const unsigned char *uid,
1431 unsigned len, const char *file, int line)
1432 {
1433 if (len == 0)
1434 return 0;
1435 return lease_hash_lookup (lp, lease_uid_hash, uid, len, file, line);
1436 }
1437
1438 int find_lease_by_hw_addr (struct lease **lp,
1439 const unsigned char *hwaddr, unsigned hwlen,
1440 const char *file, int line)
1441 {
1442 if (hwlen == 0)
1443 return 0;
1444 return lease_hash_lookup (lp, lease_hw_addr_hash,
1445 hwaddr, hwlen, file, line);
1446 }
1447
1448 /* Add the specified lease to the uid hash. */
1449
1450 void uid_hash_add (lease)
1451 struct lease *lease;
1452 {
1453 struct lease *head = (struct lease *)0;
1454 struct lease *scan;
1455
1456
1457 /* If it's not in the hash, just add it. */
1458 if (!find_lease_by_uid (&head, lease -> uid, lease -> uid_len, MDL))
1459 lease_hash_add (lease_uid_hash, lease -> uid,
1460 lease -> uid_len, lease, MDL);
1461 else {
1462 /* Otherwise, attach it to the end of the list. */
1463 for (scan = head; scan -> n_uid; scan = scan -> n_uid)
1464 ;
1465 lease_reference (&scan -> n_uid, lease, MDL);
1466 lease_dereference (&head, MDL);
1467 }
1468 }
1469
1470 /* Delete the specified lease from the uid hash. */
1471
1472 void uid_hash_delete (lease)
1473 struct lease *lease;
1474 {
1475 struct lease *head = (struct lease *)0;
1476 struct lease *scan;
1477
1478 /* If it's not in the hash, we have no work to do. */
1479 if (!find_lease_by_uid (&head, lease -> uid, lease -> uid_len, MDL)) {
1480 if (lease -> n_uid)
1481 lease_dereference (&lease -> n_uid, MDL);
1482 return;
1483 }
1484
1485 /* If the lease we're freeing is at the head of the list,
1486 remove the hash table entry and add a new one with the
1487 next lease on the list (if there is one). */
1488 if (head == lease) {
1489 lease_hash_delete (lease_uid_hash,
1490 lease -> uid, lease -> uid_len, MDL);
1491 if (lease -> n_uid) {
1492 lease_hash_add (lease_uid_hash,
1493 lease -> n_uid -> uid,
1494 lease -> n_uid -> uid_len,
1495 lease -> n_uid, MDL);
1496 lease_dereference (&lease -> n_uid, MDL);
1497 }
1498 } else {
1499 /* Otherwise, look for the lease in the list of leases
1500 attached to the hash table entry, and remove it if
1501 we find it. */
1502 for (scan = head; scan -> n_uid; scan = scan -> n_uid) {
1503 if (scan -> n_uid == lease) {
1504 lease_dereference (&scan -> n_uid, MDL);
1505 if (lease -> n_uid) {
1506 lease_reference (&scan -> n_uid,
1507 lease -> n_uid, MDL);
1508 lease_dereference (&lease -> n_uid,
1509 MDL);
1510 }
1511 break;
1512 }
1513 }
1514 }
1515 lease_dereference (&head, MDL);
1516 }
1517
1518 /* Add the specified lease to the hardware address hash. */
1519
1520 void hw_hash_add (lease)
1521 struct lease *lease;
1522 {
1523 struct lease *head = (struct lease *)0;
1524 struct lease *scan;
1525
1526 /* If it's not in the hash, just add it. */
1527 if (!find_lease_by_hw_addr (&head, lease -> hardware_addr.hbuf,
1528 lease -> hardware_addr.hlen, MDL))
1529 lease_hash_add (lease_hw_addr_hash,
1530 lease -> hardware_addr.hbuf,
1531 lease -> hardware_addr.hlen,
1532 lease, MDL);
1533 else {
1534 /* Otherwise, attach it to the end of the list. */
1535 for (scan = head; scan -> n_hw; scan = scan -> n_hw)
1536 ;
1537 lease_reference (&scan -> n_hw, lease, MDL);
1538 lease_dereference (&head, MDL);
1539 }
1540 }
1541
1542 /* Delete the specified lease from the hardware address hash. */
1543
1544 void hw_hash_delete (lease)
1545 struct lease *lease;
1546 {
1547 struct lease *head = (struct lease *)0;
1548 struct lease *scan;
1549
1550 /* If it's not in the hash, we have no work to do. */
1551 if (!find_lease_by_hw_addr (&head, lease -> hardware_addr.hbuf,
1552 lease -> hardware_addr.hlen, MDL)) {
1553 if (lease -> n_hw)
1554 lease_dereference (&lease -> n_hw, MDL);
1555 return;
1556 }
1557
1558 /* If the lease we're freeing is at the head of the list,
1559 remove the hash table entry and add a new one with the
1560 next lease on the list (if there is one). */
1561 if (head == lease) {
1562 lease_hash_delete (lease_hw_addr_hash,
1563 lease -> hardware_addr.hbuf,
1564 lease -> hardware_addr.hlen, MDL);
1565 if (lease -> n_hw) {
1566 lease_hash_add (lease_hw_addr_hash,
1567 lease -> n_hw -> hardware_addr.hbuf,
1568 lease -> n_hw -> hardware_addr.hlen,
1569 lease -> n_hw, MDL);
1570 lease_dereference (&lease -> n_hw, MDL);
1571 }
1572 } else {
1573 /* Otherwise, look for the lease in the list of leases
1574 attached to the hash table entry, and remove it if
1575 we find it. */
1576 for (scan = head; scan -> n_hw; scan = scan -> n_hw) {
1577 if (scan -> n_hw == lease) {
1578 lease_dereference (&scan -> n_hw, MDL);
1579 if (lease -> n_hw) {
1580 lease_reference (&scan -> n_hw,
1581 lease -> n_hw, MDL);
1582 lease_dereference (&lease -> n_hw,
1583 MDL);
1584 }
1585 break;
1586 }
1587 }
1588 }
1589 lease_dereference (&head, MDL);
1590 }
1591
1592 /* Write all interesting leases to permanent storage. */
1593
1594 void write_leases ()
1595 {
1596 struct lease *l;
1597 struct shared_network *s;
1598 struct pool *p;
1599 struct host_decl *hp;
1600 struct group_object *gp;
1601 struct hash_bucket *hb;
1602 int i;
1603 int num_written;
1604 struct lease **lptr [5];
1605
1606 /* Write all the dynamically-created group declarations. */
1607 if (group_name_hash) {
1608 num_written = 0;
1609 for (i = 0; i < group_name_hash -> hash_count; i++) {
1610 for (hb = group_name_hash -> buckets [i];
1611 hb; hb = hb -> next) {
1612 gp = (struct group_object *)hb -> value;
1613 if ((gp -> flags & GROUP_OBJECT_DYNAMIC) ||
1614 ((gp -> flags & GROUP_OBJECT_STATIC) &&
1615 (gp -> flags & GROUP_OBJECT_DELETED))) {
1616 write_group (gp);
1617 ++num_written;
1618 }
1619 }
1620 }
1621 log_info ("Wrote %d group decls to leases file.", num_written);
1622 }
1623
1624 /* Write all the deleted host declarations. */
1625 if (host_name_hash) {
1626 num_written = 0;
1627 for (i = 0; i < host_name_hash -> hash_count; i++) {
1628 for (hb = host_name_hash -> buckets [i];
1629 hb; hb = hb -> next) {
1630 hp = (struct host_decl *)hb -> value;
1631 if (((hp -> flags & HOST_DECL_STATIC) &&
1632 (hp -> flags & HOST_DECL_DELETED))) {
1633 write_host (hp);
1634 ++num_written;
1635 }
1636 }
1637 }
1638 log_info ("Wrote %d deleted host decls to leases file.",
1639 num_written);
1640 }
1641
1642 /* Write all the new, dynamic host declarations. */
1643 if (host_name_hash) {
1644 num_written = 0;
1645 for (i = 0; i < host_name_hash -> hash_count; i++) {
1646 for (hb = host_name_hash -> buckets [i];
1647 hb; hb = hb -> next) {
1648 hp = (struct host_decl *)hb -> value;
1649 if ((hp -> flags & HOST_DECL_DYNAMIC)) {
1650 write_host (hp);
1651 ++num_written;
1652 }
1653 }
1654 }
1655 log_info ("Wrote %d new dynamic host decls to leases file.",
1656 num_written);
1657 }
1658
1659 #if defined (FAILOVER_PROTOCOL)
1660 /* Write all the failover states. */
1661 dhcp_failover_write_all_states ();
1662 #endif
1663
1664 /* Write all the leases. */
1665 num_written = 0;
1666 for (s = shared_networks; s; s = s -> next) {
1667 for (p = s -> pools; p; p = p -> next) {
1668 lptr [FREE_LEASES] = &p -> free;
1669 lptr [ACTIVE_LEASES] = &p -> active;
1670 lptr [EXPIRED_LEASES] = &p -> expired;
1671 lptr [ABANDONED_LEASES] = &p -> abandoned;
1672 lptr [BACKUP_LEASES] = &p -> backup;
1673
1674 for (i = FREE_LEASES; i <= BACKUP_LEASES; i++) {
1675 for (l = *(lptr [i]); l; l = l -> next) {
1676 if (l -> hardware_addr.hlen ||
1677 l -> uid_len ||
1678 (l -> binding_state != FTS_FREE)) {
1679 if (!write_lease (l))
1680 log_fatal ("Can't rewrite lease database");
1681 num_written++;
1682 }
1683 }
1684 }
1685 }
1686 }
1687 log_info ("Wrote %d leases to leases file.", num_written);
1688 if (!commit_leases ())
1689 log_fatal ("Can't commit leases to new database: %m");
1690 }
1691
1692 int lease_enqueue (struct lease *comp)
1693 {
1694 struct lease **lq, *prev, *lp;
1695
1696 /* No queue to put it on? */
1697 if (!comp -> pool)
1698 return 0;
1699
1700 /* Figure out which queue it's going to. */
1701 switch (comp -> binding_state) {
1702 case FTS_FREE:
1703 lq = &comp -> pool -> free;
1704 comp -> pool -> free_leases++;
1705 comp -> sort_time = comp -> ends;
1706 break;
1707
1708 case FTS_ACTIVE:
1709 case FTS_RESERVED:
1710 case FTS_BOOTP:
1711 lq = &comp -> pool -> active;
1712 comp -> sort_time = comp -> ends;
1713 break;
1714
1715 case FTS_EXPIRED:
1716 case FTS_RELEASED:
1717 case FTS_RESET:
1718 lq = &comp -> pool -> expired;
1719 comp -> sort_time = comp -> ends;
1720
1721 break;
1722
1723 case FTS_ABANDONED:
1724 lq = &comp -> pool -> abandoned;
1725 comp -> sort_time = comp -> ends;
1726 break;
1727
1728 case FTS_BACKUP:
1729 lq = &comp -> pool -> backup;
1730 comp -> pool -> backup_leases++;
1731 comp -> sort_time = comp -> ends;
1732 break;
1733
1734 default:
1735 log_error ("Lease with bogus binding state: %d",
1736 comp -> binding_state);
1737 return 0;
1738 }
1739
1740 /* Insertion sort the lease onto the appropriate queue. */
1741 prev = (struct lease *)0;
1742 for (lp = *lq; lp; lp = lp -> next) {
1743 if (lp -> sort_time >= comp -> sort_time)
1744 break;
1745 prev = lp;
1746 }
1747 if (prev) {
1748 if (prev -> next) {
1749 lease_reference (&comp -> next, prev -> next, MDL);
1750 lease_dereference (&prev -> next, MDL);
1751 }
1752 lease_reference (&prev -> next, comp, MDL);
1753 } else {
1754 if (*lq) {
1755 lease_reference (&comp -> next, *lq, MDL);
1756 lease_dereference (lq, MDL);
1757 }
1758 lease_reference (lq, comp, MDL);
1759 }
1760 return 1;
1761 }
1762
1763 /* For a given lease, sort it onto the right list in its pool and put it
1764 in each appropriate hash, understanding that it's already by definition
1765 in lease_ip_addr_hash. */
1766
1767 void lease_instantiate (const unsigned char *val, unsigned len,
1768 struct lease *lease)
1769 {
1770
1771 /* XXX If the lease doesn't have a pool at this point, it's an
1772 XXX orphan, which we *should* keep around until it expires,
1773 XXX but which right now we just forget. */
1774 if (!lease -> pool) {
1775 lease_hash_delete (lease_ip_addr_hash,
1776 lease -> ip_addr.iabuf,
1777 lease -> ip_addr.len, MDL);
1778 return;
1779 }
1780
1781 /* Put the lease on the right queue. */
1782 lease_enqueue (lease);
1783
1784 /* Record the lease in the uid hash if possible. */
1785 if (lease -> uid) {
1786 uid_hash_add (lease);
1787 }
1788
1789 /* Record it in the hardware address hash if possible. */
1790 if (lease -> hardware_addr.hlen) {
1791 hw_hash_add (lease);
1792 }
1793
1794 return;
1795 }
1796
1797 /* Run expiry events on every pool. This is called on startup so that
1798 any expiry events that occurred after the server stopped and before it
1799 was restarted can be run. At the same time, if failover support is
1800 compiled in, we compute the balance of leases for the pool. */
1801
1802 void expire_all_pools ()
1803 {
1804 struct shared_network *s;
1805 struct pool *p;
1806 struct hash_bucket *hb;
1807 int i;
1808 struct lease *l;
1809 struct lease **lptr [5];
1810
1811 /* First, go over the hash list and actually put all the leases
1812 on the appropriate lists. */
1813 lease_hash_foreach (lease_ip_addr_hash, lease_instantiate);
1814
1815 /* Loop through each pool in each shared network and call the
1816 expiry routine on the pool. */
1817 for (s = shared_networks; s; s = s -> next) {
1818 for (p = s -> pools; p; p = p -> next) {
1819 pool_timer (p);
1820
1821 p -> lease_count = 0;
1822 p -> free_leases = 0;
1823 p -> backup_leases = 0;
1824
1825 lptr [FREE_LEASES] = &p -> free;
1826 lptr [ACTIVE_LEASES] = &p -> active;
1827 lptr [EXPIRED_LEASES] = &p -> expired;
1828 lptr [ABANDONED_LEASES] = &p -> abandoned;
1829 lptr [BACKUP_LEASES] = &p -> backup;
1830
1831 for (i = FREE_LEASES; i <= BACKUP_LEASES; i++) {
1832 for (l = *(lptr [i]); l; l = l -> next) {
1833 p -> lease_count++;
1834 if (l -> ends <= cur_time) {
1835 if (l -> binding_state == FTS_FREE)
1836 p -> free_leases++;
1837 else if (l -> binding_state == FTS_BACKUP)
1838 p -> backup_leases++;
1839 }
1840 #if defined (FAILOVER_PROTOCOL)
1841 if (p -> failover_peer &&
1842 l -> tstp > l -> tsfp &&
1843 !(l -> flags & ON_UPDATE_QUEUE))
1844 dhcp_failover_queue_update (l, 1);
1845 #endif
1846 }
1847 }
1848 }
1849 }
1850 }
1851
1852 void dump_subnets ()
1853 {
1854 struct lease *l;
1855 struct shared_network *s;
1856 struct subnet *n;
1857 struct pool *p;
1858 struct lease **lptr [5];
1859 int i;
1860
1861 log_info ("Subnets:");
1862 for (n = subnets; n; n = n -> next_subnet) {
1863 log_debug (" Subnet %s", piaddr (n -> net));
1864 log_debug (" netmask %s",
1865 piaddr (n -> netmask));
1866 }
1867 log_info ("Shared networks:");
1868 for (s = shared_networks; s; s = s -> next) {
1869 log_info (" %s", s -> name);
1870 for (p = s -> pools; p; p = p -> next) {
1871 lptr [FREE_LEASES] = &p -> free;
1872 lptr [ACTIVE_LEASES] = &p -> active;
1873 lptr [EXPIRED_LEASES] = &p -> expired;
1874 lptr [ABANDONED_LEASES] = &p -> abandoned;
1875 lptr [BACKUP_LEASES] = &p -> backup;
1876
1877 for (i = FREE_LEASES; i <= BACKUP_LEASES; i++) {
1878 for (l = *(lptr [i]); l; l = l -> next) {
1879 print_lease (l);
1880 }
1881 }
1882 }
1883 }
1884 }
1885
1886 HASH_FUNCTIONS (lease, const unsigned char *, struct lease)
1887 HASH_FUNCTIONS (host, const unsigned char *, struct host_decl)
1888 HASH_FUNCTIONS (class, const char *, struct class)