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