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