ISC DHCP 4.4.3-P1
A reference DHCPv4 and DHCPv6 implementation
 
Loading...
Searching...
No Matches
mdb.c
Go to the documentation of this file.
1/* mdb.c
2
3 Server-specific in-memory database support. */
4
5/*
6 * Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1996-2003 by Internet Software Consortium
8 *
9 * This Source Code Form is subject to the terms of the Mozilla Public
10 * License, v. 2.0. If a copy of the MPL was not distributed with this
11 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
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 * PO Box 360
23 * Newmarket, NH 03857 USA
24 * <info@isc.org>
25 * https://www.isc.org/
26 *
27 */
28
29#include "dhcpd.h"
30#include "omapip/hash.h"
31
40
41/*
42 * We allow users to specify any option as a host identifier.
43 *
44 * Any host is uniquely identified by the combination of
45 * option type & option data.
46 *
47 * We expect people will only use a few types of options as host
48 * identifier. Because of this, we store a list with an entry for
49 * each option type. Each of these has a hash table, which contains
50 * hash of the option data.
51 *
52 * For v6 we also include a relay count - this specifies which
53 * relay to check for the requested option. As each different
54 * value of relays creates a new instance admins should use the
55 * same value across each option for all host-identifers.
56 * A value of 0 indicates that we aren't doing relay options
57 * and should simply look in the current option list.
58 */
65
66static host_id_info_t *host_id_info = NULL;
67
69
71
72isc_result_t enter_class(cd, dynamicp, commit)
73 struct class *cd;
74 int dynamicp;
75 int commit;
76{
77 if (!collections -> classes) {
78 /* A subclass with no parent is invalid. */
79 if (cd->name == NULL)
80 return DHCP_R_INVALIDARG;
81
82 class_reference (&collections -> classes, cd, MDL);
83 } else if (cd->name != NULL) { /* regular class */
84 struct class *c = 0;
85
86 if (find_class(&c, cd->name, MDL) != ISC_R_NOTFOUND) {
87 class_dereference(&c, MDL);
88 return ISC_R_EXISTS;
89 }
90
91 /* Find the tail. */
92 for (c = collections -> classes;
93 c -> nic; c = c -> nic)
94 /* nothing */ ;
95 class_reference (&c -> nic, cd, MDL);
96 }
97
98 if (dynamicp && commit) {
99 const char *name = cd->name;
100
101 if (name == NULL) {
102 name = cd->superclass->name;
103 }
104
105 write_named_billing_class ((const unsigned char *)name, 0, cd);
106 if (!commit_leases ())
107 return ISC_R_IOERROR;
108 }
109
110 return ISC_R_SUCCESS;
111}
112
113
114/* Variable to check if we're starting the server. The server will init as
115 * starting - but just to be safe start out as false to avoid triggering new
116 * special-case code
117 * XXX: There is actually a server_startup state...which is never entered...
118 */
119#define SS_NOSYNC 1
120#define SS_QFOLLOW 2
121static int server_starting = 0;
122
123static int find_uid_statement (struct executable_statement *esp,
124 void *vp, int condp)
125{
126 struct executable_statement **evp = vp;
127
128 if (esp -> op == supersede_option_statement &&
129 esp -> data.option &&
130 (esp -> data.option -> option -> universe ==
131 &dhcp_universe) &&
132 ((esp -> data.option -> option -> code ==
134 (esp -> data.option -> option -> code == DHO_PXE_CLIENT_ID))) {
135 if (condp) {
136 log_error ("dhcp client identifier may not be %s",
137 "specified conditionally.");
138 } else if (!(*evp)) {
140 return 1;
141 } else {
142 log_error ("only one dhcp client identifier may be %s",
143 "specified");
144 }
145 }
146 return 0;
147}
148
149
150static host_id_info_t *
151find_host_id_info(unsigned int option_code, int relays) {
153
154 for (p = host_id_info; p != NULL; p = p->next) {
155 if ((p->option->code == option_code) &&
156 (p->relays == relays)) {
157 break;
158 }
159 }
160 return p;
161}
162
163/* Debugging code */
164#if 0
165isc_result_t
166print_host(const void *name, unsigned len, void *value) {
167 struct host_decl *h;
168 printf("--------------\n");
169 printf("name:'%s'\n", print_hex_1(len, name, 60));
170 printf("len:%d\n", len);
171 h = (struct host_decl *)value;
172 printf("host @%p is '%s'\n", h, h->name);
173 return ISC_R_SUCCESS;
174}
175
176void
177hash_print_hosts(struct hash_table *h) {
178 hash_foreach(h, print_host);
179 printf("--------------\n");
180}
181#endif /* 0 */
182
183void
184change_host_uid(struct host_decl *host, const char *uid, int len) {
185 /* XXX: should consolidate this type of code throughout */
186 if (host_uid_hash == NULL) {
187 if (!host_new_hash(&host_uid_hash, HOST_HASH_SIZE, MDL)) {
188 log_fatal("Can't allocate host/uid hash");
189 }
190 }
191
192 /*
193 * Remove the old entry, if one exists.
194 */
195 if (host->client_identifier.data != NULL) {
196 host_hash_delete(host_uid_hash,
199 MDL);
201 }
202
203 /*
204 * Set our new value.
205 */
206 memset(&host->client_identifier, 0, sizeof(host->client_identifier));
207 host->client_identifier.len = len;
208 if (!buffer_allocate(&host->client_identifier.buffer, len, MDL)) {
209 log_fatal("Can't allocate uid buffer");
210 }
212 memcpy((char *)host->client_identifier.data, uid, len);
213
214 /*
215 * And add to hash.
216 */
217 host_hash_add(host_uid_hash, host->client_identifier.data,
218 host->client_identifier.len, host, MDL);
219}
220
221isc_result_t enter_host (hd, dynamicp, commit)
222 struct host_decl *hd;
223 int dynamicp;
224 int commit;
225{
226 struct host_decl *hp = (struct host_decl *)0;
227 struct host_decl *np = (struct host_decl *)0;
228 struct executable_statement *esp;
229 host_id_info_t *h_id_info;
230
231 if (!host_name_hash) {
232 if (!host_new_hash(&host_name_hash, HOST_HASH_SIZE, MDL))
233 log_fatal ("Can't allocate host name hash");
234 host_hash_add (host_name_hash,
235 (unsigned char *)hd -> name,
236 strlen (hd -> name), hd, MDL);
237 } else {
238 host_hash_lookup (&hp, host_name_hash,
239 (unsigned char *)hd -> name,
240 strlen (hd -> name), MDL);
241
242 /* If it's deleted, we can supersede it. */
243 if (hp && (hp -> flags & HOST_DECL_DELETED)) {
244 host_hash_delete (host_name_hash,
245 (unsigned char *)hd -> name,
246 strlen (hd -> name), MDL);
247 /* If the old entry wasn't dynamic, then we
248 always have to keep the deletion. */
249 if (hp -> flags & HOST_DECL_STATIC) {
250 hd -> flags |= HOST_DECL_STATIC;
251 }
252 host_dereference (&hp, MDL);
253 }
254
255 /* If we are updating an existing host declaration, we
256 can just delete it and add it again. */
257 if (hp && hp == hd) {
258 host_dereference (&hp, MDL);
259 delete_host (hd, 0);
260 if (!write_host (hd))
261 return ISC_R_IOERROR;
262 hd -> flags &= ~HOST_DECL_DELETED;
263 }
264
265 /* If there isn't already a host decl matching this
266 address, add it to the hash table. */
267 if (!hp) {
268 host_hash_add (host_name_hash,
269 (unsigned char *)hd -> name,
270 strlen (hd -> name), hd, MDL);
271 } else {
272 /* XXX actually, we have to delete the old one
273 XXX carefully and replace it. Not done yet. */
274 host_dereference (&hp, MDL);
275 return ISC_R_EXISTS;
276 }
277 }
278
279 if (hd -> n_ipaddr)
280 host_dereference (&hd -> n_ipaddr, MDL);
281
282 if (!hd -> type)
283 hd -> type = dhcp_type_host;
284
285 if (hd -> interface.hlen) {
286 if (!host_hw_addr_hash) {
287 if (!host_new_hash(&host_hw_addr_hash,
289 log_fatal ("Can't allocate host/hw hash");
290 } else {
291 /* If there isn't already a host decl matching this
292 address, add it to the hash table. */
293 host_hash_lookup (&hp, host_hw_addr_hash,
294 hd -> interface.hbuf,
295 hd -> interface.hlen, MDL);
296 }
297 if (!hp)
298 host_hash_add (host_hw_addr_hash, hd -> interface.hbuf,
299 hd -> interface.hlen, hd, MDL);
300 else {
301 /* If there was already a host declaration for
302 this hardware address, add this one to the
303 end of the list. */
304 for (np = hp; np -> n_ipaddr; np = np -> n_ipaddr)
305 ;
306 host_reference (&np -> n_ipaddr, hd, MDL);
307 host_dereference (&hp, MDL);
308 }
309 }
310
311 /* See if there's a statement that sets the client identifier.
312 This is a kludge - the client identifier really shouldn't be
313 set with an executable statement. */
314 esp = NULL;
316 find_uid_statement, &esp, 0)) {
317 struct data_string cid;
318 memset(&cid, 0, sizeof(cid));
319 (void) evaluate_option_cache (&cid,
320 NULL, NULL, NULL, NULL, NULL,
322 esp->data.option, MDL);
323
324 if (hd->client_identifier.len > 0 && cid.len > 0) {
325 char uid_buf[256];
326 char cid_buf[256];
329 sizeof(uid_buf) - 1, uid_buf);
330
332 sizeof(cid_buf) - 1, cid_buf);
333
334 log_error ("Warning, host declaration '%s'"
335 " already has uid '%s',"
336 " ignoring dhcp-client-identifier '%s'",
337 hd->name, uid_buf, cid_buf);
338
339 data_string_forget(&cid, MDL);
340 } else {
341 memcpy(&hd->client_identifier, &cid, sizeof(cid));
342 }
343 }
344
345 /* If we got a client identifier, hash this entry by
346 client identifier. */
347 if (hd -> client_identifier.len) {
348 /* If there's no uid hash, make one; otherwise, see if
349 there's already an entry in the hash for this host. */
350 if (!host_uid_hash) {
351 if (!host_new_hash(&host_uid_hash,
353 log_fatal ("Can't allocate host/uid hash");
354
355 host_hash_add (host_uid_hash,
356 hd -> client_identifier.data,
357 hd -> client_identifier.len,
358 hd, MDL);
359 } else {
360 /* If there's already a host declaration for this
361 client identifier, add this one to the end of the
362 list. Otherwise, add it to the hash table. */
363 if (host_hash_lookup (&hp, host_uid_hash,
364 hd -> client_identifier.data,
365 hd -> client_identifier.len,
366 MDL)) {
367 /* Don't link it in twice... */
368 if (!np) {
369 for (np = hp; np -> n_ipaddr;
370 np = np -> n_ipaddr) {
371 if (hd == np)
372 break;
373 }
374 if (hd != np)
375 host_reference (&np -> n_ipaddr,
376 hd, MDL);
377 }
378 host_dereference (&hp, MDL);
379 } else {
380 host_hash_add (host_uid_hash,
381 hd -> client_identifier.data,
382 hd -> client_identifier.len,
383 hd, MDL);
384 }
385 }
386 }
387
388
389 /*
390 * If we use an option as our host identifier, record it here.
391 */
392 if (hd->host_id_option != NULL) {
393 /*
394 * Look for the host identifier information for this option,
395 * and create a new entry if there is none.
396 */
397 h_id_info = find_host_id_info(hd->host_id_option->code,
398 hd->relays);
399 if (h_id_info == NULL) {
400 h_id_info = dmalloc(sizeof(*h_id_info), MDL);
401 if (h_id_info == NULL) {
402 log_fatal("No memory for host-identifier "
403 "option information.");
404 }
405 option_reference(&h_id_info->option,
406 hd->host_id_option, MDL);
407 if (!host_new_hash(&h_id_info->values_hash,
409 log_fatal("No memory for host-identifier "
410 "option hash.");
411 }
412 h_id_info->relays = hd->relays;
413 h_id_info->next = host_id_info;
414 host_id_info = h_id_info;
415 }
416
417 if (host_hash_lookup(&hp, h_id_info->values_hash,
418 hd->host_id.data, hd->host_id.len, MDL)) {
419 /*
420 * If this option is already present, then add
421 * this host to the list in n_ipaddr, unless
422 * we have already done so previously.
423 *
424 * XXXSK: This seems scary to me, but I don't
425 * fully understand how these are used.
426 * Shouldn't there be multiple lists, or
427 * maybe we should just forbid duplicates?
428 */
429 if (np == NULL) {
430 np = hp;
431 while (np->n_ipaddr != NULL) {
432 np = np->n_ipaddr;
433 }
434 if (hd != np) {
435 host_reference(&np->n_ipaddr, hd, MDL);
436 }
437 }
438 host_dereference(&hp, MDL);
439 } else {
440 host_hash_add(h_id_info->values_hash,
441 hd->host_id.data,
442 hd->host_id.len,
443 hd, MDL);
444 }
445 }
446
447 if (dynamicp && commit) {
448 if (!write_host (hd))
449 return ISC_R_IOERROR;
450 if (!commit_leases ())
451 return ISC_R_IOERROR;
452 }
453
454 return ISC_R_SUCCESS;
455}
456
457
458isc_result_t delete_class (cp, commit)
459 struct class *cp;
460 int commit;
461{
463
464 /* do the write first as we won't be leaving it in any data
465 structures, unlike the host objects */
466
467 if (commit) {
468 write_named_billing_class ((unsigned char *)cp->name, 0, cp);
469 if (!commit_leases ())
470 return ISC_R_IOERROR;
471 }
472
473 /*
474 * If this is a subclass remove it from the class's hash table
475 */
476 if (cp->superclass) {
477 class_hash_delete(cp->superclass->hash,
478 (const char *)cp->hash_string.data,
479 cp->hash_string.len,
480 MDL);
481 }
482
483 /* remove from collections */
484 unlink_class(&cp);
485
486 return ISC_R_SUCCESS;
487}
488
489
490isc_result_t delete_host (hd, commit)
491 struct host_decl *hd;
492 int commit;
493{
494 struct host_decl *hp = (struct host_decl *)0;
495 struct host_decl *np = (struct host_decl *)0;
496 struct host_decl *foo;
497 int hw_head = 0, uid_head = 1;
498
499 /* Don't need to do it twice. */
500 if (hd -> flags & HOST_DECL_DELETED)
501 return ISC_R_SUCCESS;
502
503 /* But we do need to do it once! :') */
504 hd -> flags |= HOST_DECL_DELETED;
505
506 if (hd -> interface.hlen) {
507 if (host_hw_addr_hash) {
508 if (host_hash_lookup (&hp, host_hw_addr_hash,
509 hd -> interface.hbuf,
510 hd -> interface.hlen, MDL)) {
511 if (hp == hd) {
512 host_hash_delete (host_hw_addr_hash,
513 hd -> interface.hbuf,
514 hd -> interface.hlen, MDL);
515 hw_head = 1;
516 } else {
517 np = (struct host_decl *)0;
518 foo = (struct host_decl *)0;
519 host_reference (&foo, hp, MDL);
520 while (foo) {
521 if (foo == hd)
522 break;
523 if (np)
524 host_dereference (&np, MDL);
525 host_reference (&np, foo, MDL);
526 host_dereference (&foo, MDL);
527 if (np -> n_ipaddr)
528 host_reference (&foo, np -> n_ipaddr, MDL);
529 }
530
531 if (foo) {
532 host_dereference (&np -> n_ipaddr, MDL);
533 if (hd -> n_ipaddr)
534 host_reference (&np -> n_ipaddr,
535 hd -> n_ipaddr, MDL);
536 host_dereference (&foo, MDL);
537 }
538 if (np)
539 host_dereference (&np, MDL);
540 }
541 host_dereference (&hp, MDL);
542 }
543 }
544 }
545
546 /* If we got a client identifier, hash this entry by
547 client identifier. */
548 if (hd -> client_identifier.len) {
549 if (host_uid_hash) {
550 if (host_hash_lookup (&hp, host_uid_hash,
552 hd -> client_identifier.len, MDL)) {
553 if (hp == hd) {
554 host_hash_delete (host_uid_hash,
556 hd -> client_identifier.len, MDL);
557 uid_head = 1;
558 } else {
559 np = (struct host_decl *)0;
560 foo = (struct host_decl *)0;
561 host_reference (&foo, hp, MDL);
562 while (foo) {
563 if (foo == hd)
564 break;
565 if (np)
566 host_dereference (&np, MDL);
567 host_reference (&np, foo, MDL);
568 host_dereference (&foo, MDL);
569 if (np -> n_ipaddr)
570 host_reference (&foo, np -> n_ipaddr, MDL);
571 }
572
573 if (foo) {
574 host_dereference (&np -> n_ipaddr, MDL);
575 if (hd -> n_ipaddr)
576 host_reference (&np -> n_ipaddr,
577 hd -> n_ipaddr, MDL);
578 host_dereference (&foo, MDL);
579 }
580 if (np)
581 host_dereference (&np, MDL);
582 }
583 host_dereference (&hp, MDL);
584 }
585 }
586 }
587
588 if (hd->host_id_option != NULL) {
591 }
592
593 if (hd -> n_ipaddr) {
594 if (uid_head && hd -> n_ipaddr -> client_identifier.len) {
595 host_hash_add
599 hd -> n_ipaddr, MDL);
600 }
601 if (hw_head && hd -> n_ipaddr -> interface.hlen) {
602 host_hash_add (host_hw_addr_hash,
603 hd -> n_ipaddr -> interface.hbuf,
604 hd -> n_ipaddr -> interface.hlen,
605 hd -> n_ipaddr, MDL);
606 }
607 host_dereference (&hd -> n_ipaddr, MDL);
608 }
609
610 if (host_name_hash) {
611 if (host_hash_lookup (&hp, host_name_hash,
612 (unsigned char *)hd -> name,
613 strlen (hd -> name), MDL)) {
614 if (hp == hd && !(hp -> flags & HOST_DECL_STATIC)) {
615 host_hash_delete (host_name_hash,
616 (unsigned char *)hd -> name,
617 strlen (hd -> name), MDL);
618 }
619 host_dereference (&hp, MDL);
620 }
621 }
622
623 if (commit) {
624 if (!write_host (hd))
625 return ISC_R_IOERROR;
626 if (!commit_leases ())
627 return ISC_R_IOERROR;
628 }
629 return ISC_R_SUCCESS;
630}
631
632int find_hosts_by_haddr (struct host_decl **hp, int htype,
633 const unsigned char *haddr, unsigned hlen,
634 const char *file, int line)
635{
636 struct hardware h;
637#if defined(LDAP_CONFIGURATION)
638 int ret;
639
640 if ((ret = find_haddr_in_ldap (hp, htype, hlen, haddr, file, line)))
641 return ret;
642#endif
643
644 h.hlen = hlen + 1;
645 h.hbuf [0] = htype;
646 memcpy (&h.hbuf [1], haddr, hlen);
647
648 return host_hash_lookup (hp, host_hw_addr_hash,
649 h.hbuf, h.hlen, file, line);
650}
651
653 const unsigned char *data, unsigned len,
654 const char *file, int line)
655{
656 return host_hash_lookup (hp, host_uid_hash, data, len, file, line);
657}
658
659int
661 struct packet *packet,
662 struct option_state *opt_state,
663 const char *file, int line) {
665 struct option_cache *oc;
666 struct data_string data;
667 int found;
668 struct packet *relay_packet;
669 struct option_state *relay_state;
670
671#if defined(LDAP_CONFIGURATION)
672 if ((found = find_client_in_ldap (hp, packet, opt_state, file, line)))
673 return found;
674#endif
675
676 for (p = host_id_info; p != NULL; p = p->next) {
677 relay_packet = packet;
678 relay_state = opt_state;
679
680 /* If this option block is for a relay (relays != 0)
681 * and we are processing the main options and not
682 * options from the IA (packet->options == opt_state)
683 * try to find the proper relay
684 */
685 if ((p->relays != 0) && (packet->options == opt_state)) {
686 int i = p->relays;
687 while ((i != 0) &&
688 (relay_packet->dhcpv6_container_packet != NULL)) {
689 relay_packet =
690 relay_packet->dhcpv6_container_packet;
691 i--;
692 }
693 /* We wanted a specific relay but were
694 * unable to find it */
695 if ((p->relays <= MAX_V6RELAY_HOPS) && (i != 0))
696 continue;
697
698 relay_state = relay_packet->options;
699 }
700
702 relay_state, p->option->code);
703 if (oc != NULL) {
704 memset(&data, 0, sizeof(data));
705
706 if (!evaluate_option_cache(&data, relay_packet, NULL,
707 NULL, relay_state, NULL,
708 &global_scope, oc,
709 MDL)) {
710 log_error("Error evaluating option cache");
711 return 0;
712 }
713
714 found = host_hash_lookup(hp, p->values_hash,
715 data.data, data.len,
716 file, line);
717
718 data_string_forget(&data, MDL);
719
720 if (found) {
721 return 1;
722 }
723 }
724 }
725 return 0;
726}
727
728/* More than one host_decl can be returned by find_hosts_by_haddr or
729 find_hosts_by_uid, and each host_decl can have multiple addresses.
730 Loop through the list of hosts, and then for each host, through the
731 list of addresses, looking for an address that's in the same shared
732 network as the one specified. Store the matching address through
733 the addr pointer, update the host pointer to point at the host_decl
734 that matched, and return the subnet that matched. */
735
736int find_host_for_network (struct subnet **sp, struct host_decl **host,
737 struct iaddr *addr, struct shared_network *share)
738{
739 int i;
740 struct iaddr ip_address;
741 struct host_decl *hp;
742 struct data_string fixed_addr;
743
744 memset (&fixed_addr, 0, sizeof fixed_addr);
745
746 for (hp = *host; hp; hp = hp -> n_ipaddr) {
747 if (!hp -> fixed_addr)
748 continue;
749 if (!evaluate_option_cache (&fixed_addr, (struct packet *)0,
750 (struct lease *)0,
751 (struct client_state *)0,
752 (struct option_state *)0,
753 (struct option_state *)0,
755 hp -> fixed_addr, MDL))
756 continue;
757 for (i = 0; i < fixed_addr.len; i += 4) {
758 ip_address.len = 4;
759 memcpy (ip_address.iabuf,
760 fixed_addr.data + i, 4);
761 if (find_grouped_subnet (sp, share, ip_address, MDL)) {
762 struct host_decl *tmp = (struct host_decl *)0;
763 *addr = ip_address;
764 /* This is probably not necessary, but
765 just in case *host is the only reference
766 to that host declaration, make a temporary
767 reference so that dereferencing it doesn't
768 dereference hp out from under us. */
769 host_reference (&tmp, *host, MDL);
770 host_dereference (host, MDL);
771 host_reference (host, hp, MDL);
772 host_dereference (&tmp, MDL);
774 return 1;
775 }
776 }
778 }
779 return 0;
780}
781
782void new_address_range (cfile, low, high, subnet, pool, lpchain)
783 struct parse *cfile;
784 struct iaddr low, high;
785 struct subnet *subnet;
786 struct pool *pool;
787 struct lease **lpchain;
788{
789#if defined(COMPACT_LEASES)
790 struct lease *address_range;
791 unsigned s;
792#endif
793 unsigned min, max, i, num_addrs;
794 char lowbuf [16], highbuf [16], netbuf [16];
795 struct shared_network *share = subnet -> shared_network;
796 struct lease *lt = (struct lease *)0;
797#if !defined(COMPACT_LEASES)
798 isc_result_t status;
799#endif
800
801 /* All subnets should have attached shared network structures. */
802 if (!share) {
803 strcpy (netbuf, piaddr (subnet -> net));
804 log_fatal ("No shared network for network %s (%s)",
805 netbuf, piaddr (subnet -> netmask));
806 }
807
808 /* Initialize the hash table if it hasn't been done yet. */
809 if (!lease_uid_hash) {
810 if (!lease_id_new_hash(&lease_uid_hash, LEASE_HASH_SIZE, MDL))
811 log_fatal ("Can't allocate lease/uid hash");
812 }
813 if (!lease_ip_addr_hash) {
814 if (!lease_ip_new_hash(&lease_ip_addr_hash, LEASE_HASH_SIZE,
815 MDL))
816 log_fatal ("Can't allocate lease/ip hash");
817 }
818 if (!lease_hw_addr_hash) {
819 if (!lease_id_new_hash(&lease_hw_addr_hash, LEASE_HASH_SIZE,
820 MDL))
821 log_fatal ("Can't allocate lease/hw hash");
822 }
823
824 /* Make sure that high and low addresses are in this subnet. */
825 if (!addr_eq(subnet->net, subnet_number(low, subnet->netmask))) {
826 strcpy(lowbuf, piaddr(low));
827 strcpy(netbuf, piaddr(subnet->net));
828 log_fatal("bad range, address %s not in subnet %s netmask %s",
829 lowbuf, netbuf, piaddr(subnet->netmask));
830 }
831
832 if (!addr_eq(subnet->net, subnet_number(high, subnet->netmask))) {
833 strcpy(highbuf, piaddr(high));
834 strcpy(netbuf, piaddr(subnet->net));
835 log_fatal("bad range, address %s not in subnet %s netmask %s",
836 highbuf, netbuf, piaddr(subnet->netmask));
837 }
838
839 /* Get the high and low host addresses... */
840 max = host_addr (high, subnet -> netmask);
841 min = host_addr (low, subnet -> netmask);
842
843 /* Allow range to be specified high-to-low as well as low-to-high. */
844 if (min > max) {
845 max = min;
846 min = host_addr (high, subnet -> netmask);
847 }
848
849 /* get the number of addresses we want, and add it to the pool info
850 * this value is only for use when setting up lease chains and will
851 * be overwritten when expire_all_pools is run
852 */
853 num_addrs = max - min + 1;
854#if defined (BINARY_LEASES)
855 pool->lease_count += num_addrs;
856#endif
857
858 /* Get a lease structure for each address in the range. */
859#if defined (COMPACT_LEASES)
860 s = (num_addrs + 1) * sizeof (struct lease);
861 /* Check unsigned overflow in new_leases().
862 With 304 byte lease structure (x64_86), this happens at
863 range 10.0.0.0 10.215.148.52; */
864 if (((s % sizeof (struct lease)) != 0) ||
865 ((s / sizeof (struct lease)) != (num_addrs + 1))) {
866 strcpy (lowbuf, piaddr (low));
867 strcpy (highbuf, piaddr (high));
868 parse_warn (cfile, "%s-%s is an overly large address range.",
869 lowbuf, highbuf);
870 log_fatal ("Memory overflow.");
871 }
872 address_range = new_leases (num_addrs, MDL);
873 if (!address_range) {
874 strcpy (lowbuf, piaddr (low));
875 strcpy (highbuf, piaddr (high));
876 log_fatal ("No memory for address range %s-%s.",
877 lowbuf, highbuf);
878 }
879#endif
880
881 /* Fill out the lease structures with some minimal information. */
882 for (i = 0; i < num_addrs; i++) {
883 struct lease *lp = (struct lease *)0;
884#if defined (COMPACT_LEASES)
885 omapi_object_initialize ((omapi_object_t *)&address_range [i],
887 0, sizeof (struct lease), MDL);
888 lease_reference (&lp, &address_range [i], MDL);
889#else
890 status = lease_allocate (&lp, MDL);
891 if (status != ISC_R_SUCCESS)
892 log_fatal ("No memory for lease %s: %s",
893 piaddr (ip_addr (subnet -> net,
894 subnet -> netmask,
895 i + min)),
896 isc_result_totext (status));
897#endif
898 lp->ip_addr = ip_addr(subnet->net, subnet->netmask, i + min);
899 lp->starts = MIN_TIME;
900 lp->ends = MIN_TIME;
901 subnet_reference(&lp->subnet, subnet, MDL);
902 pool_reference(&lp->pool, pool, MDL);
906 lp->flags = 0;
907
908 /* Remember the lease in the IP address hash. */
909 if (find_lease_by_ip_addr (&lt, lp -> ip_addr, MDL)) {
910 if (lt -> pool) {
911 parse_warn (cfile,
912 "lease %s is declared twice!",
913 piaddr (lp -> ip_addr));
914 } else
915 pool_reference (&lt -> pool, pool, MDL);
916 lease_dereference (&lt, MDL);
917 } else
918 lease_ip_hash_add(lease_ip_addr_hash,
919 lp->ip_addr.iabuf, lp->ip_addr.len,
920 lp, MDL);
921 /* Put the lease on the chain for the caller. */
922 if (lpchain) {
923 if (*lpchain) {
924 lease_reference (&lp -> next, *lpchain, MDL);
925 lease_dereference (lpchain, MDL);
926 }
927 lease_reference (lpchain, lp, MDL);
928 }
929 lease_dereference (&lp, MDL);
930 }
931}
932
933int find_subnet (struct subnet **sp,
934 struct iaddr addr, const char *file, int line)
935{
936 struct subnet *rv;
937
938 for (rv = subnets; rv; rv = rv -> next_subnet) {
939#if defined(DHCP4o6)
940 if (addr.len != rv->netmask.len)
941 continue;
942#endif
943 if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net)) {
944 if (subnet_reference (sp, rv,
946 return 0;
947 return 1;
948 }
949 }
950 return 0;
951}
952
954 struct shared_network *share, struct iaddr addr,
955 const char *file, int line)
956{
957 struct subnet *rv;
958
959 for (rv = share -> subnets; rv; rv = rv -> next_sibling) {
960#if defined(DHCP4o6)
961 if (addr.len != rv->netmask.len)
962 continue;
963#endif
964 if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net)) {
965 if (subnet_reference (sp, rv,
967 return 0;
968 return 1;
969 }
970 }
971 return 0;
972}
973
974/* XXX: could speed up if everyone had a prefix length */
975int
977 const struct subnet *scan,
978 int warnp) {
979#if defined(DHCP4o6)
980 if (subnet->net.len != scan->net.len)
981 return 0;
982#endif
983 if (addr_eq(subnet_number(subnet->net, scan->netmask), scan->net) ||
985 char n1buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255")];
986 int i, j;
987 for (i = 0; i < 128; i++)
988 if (subnet->netmask.iabuf[3 - (i >> 3)]
989 & (1 << (i & 7)))
990 break;
991 for (j = 0; j < 128; j++)
992 if (scan->netmask.iabuf[3 - (j >> 3)] &
993 (1 << (j & 7)))
994 break;
995 if (warnp) {
996 strcpy(n1buf, piaddr(subnet->net));
997 log_error("Warning: subnet %s/%d overlaps subnet %s/%d",
998 n1buf, 32 - i,
999 piaddr(scan->net), 32 - j);
1000 }
1001 if (i < j)
1002 return 1;
1003 }
1004 return 0;
1005}
1006
1007/* Enter a new subnet into the subnet list. */
1009 struct subnet *subnet;
1010{
1011 struct subnet *scan = (struct subnet *)0;
1012 struct subnet *next = (struct subnet *)0;
1013 struct subnet *prev = (struct subnet *)0;
1014
1015 /* Check for duplicates... */
1016 if (subnets)
1017 subnet_reference (&next, subnets, MDL);
1018 while (next) {
1019 subnet_reference (&scan, next, MDL);
1020 subnet_dereference (&next, MDL);
1021
1022 /* When we find a conflict, make sure that the
1023 subnet with the narrowest subnet mask comes
1024 first. */
1025 if (subnet_inner_than (subnet, scan, 1)) {
1026 if (prev) {
1027 if (prev -> next_subnet)
1028 subnet_dereference (&prev -> next_subnet, MDL);
1029 subnet_reference (&prev -> next_subnet, subnet, MDL);
1030 subnet_dereference (&prev, MDL);
1031 } else {
1032 subnet_dereference (&subnets, MDL);
1033 subnet_reference (&subnets, subnet, MDL);
1034 }
1035 subnet_reference (&subnet -> next_subnet, scan, MDL);
1036 subnet_dereference (&scan, MDL);
1037 return;
1038 }
1039 subnet_reference (&prev, scan, MDL);
1040 subnet_dereference (&scan, MDL);
1041 }
1042 if (prev)
1043 subnet_dereference (&prev, MDL);
1044
1045 /* XXX use the BSD radix tree code instead of a linked list. */
1046 if (subnets) {
1047 subnet_reference (&subnet -> next_subnet, subnets, MDL);
1048 subnet_dereference (&subnets, MDL);
1049 }
1050 subnet_reference (&subnets, subnet, MDL);
1051}
1052
1053/* Enter a new shared network into the shared network list. */
1054
1056 struct shared_network *share;
1057{
1058 if (shared_networks) {
1059 shared_network_reference (&share -> next,
1061 shared_network_dereference (&shared_networks, MDL);
1062 }
1063 shared_network_reference (&shared_networks, share, MDL);
1064}
1065
1067 struct parse *cfile;
1068 struct shared_network *share;
1069 const char *name;
1070{
1071 struct interface_info *ip;
1072 isc_result_t status;
1073
1074 if (share -> interface) {
1075 parse_warn (cfile,
1076 "A subnet or shared network can't be connected %s",
1077 "to two interfaces.");
1078 return;
1079 }
1080
1081 for (ip = interfaces; ip; ip = ip -> next)
1082 if (!strcmp (ip -> name, name))
1083 break;
1084 if (!ip) {
1085 status = interface_allocate (&ip, MDL);
1086 if (status != ISC_R_SUCCESS)
1087 log_fatal ("new_shared_network_interface %s: %s",
1088 name, isc_result_totext (status));
1089 if (strlen (name) > sizeof ip -> name) {
1090 memcpy (ip -> name, name, (sizeof ip -> name) - 1);
1091 ip -> name [(sizeof ip -> name) - 1] = 0;
1092 } else
1093 strcpy (ip -> name, name);
1094 if (interfaces) {
1095 interface_reference (&ip -> next, interfaces, MDL);
1096 interface_dereference (&interfaces, MDL);
1097 }
1098 interface_reference (&interfaces, ip, MDL);
1100 /* XXX this is a reference loop. */
1101 shared_network_reference (&ip -> shared_network, share, MDL);
1102 interface_reference (&share -> interface, ip, MDL);
1103 }
1104}
1105
1106/* Enter a lease into the system. This is called by the parser each
1107 time it reads in a new lease. If the subnet for that lease has
1108 already been read in (usually the case), just update that lease;
1109 otherwise, allocate temporary storage for the lease and keep it around
1110 until we're done reading in the config file. */
1111
1113 struct lease *lease;
1114{
1115 struct lease *comp = (struct lease *)0;
1116
1117 if (find_lease_by_ip_addr (&comp, lease -> ip_addr, MDL)) {
1118 if (!comp -> pool) {
1119 log_error ("undeclared lease found in database: %s",
1120 piaddr (lease -> ip_addr));
1121 } else
1122 pool_reference (&lease -> pool, comp -> pool, MDL);
1123
1124 if (comp -> subnet)
1125 subnet_reference (&lease -> subnet,
1126 comp -> subnet, MDL);
1127 lease_ip_hash_delete(lease_ip_addr_hash,
1129 MDL);
1130 lease_dereference (&comp, MDL);
1131 }
1132
1133 /* The only way a lease can get here without a subnet is if it's in
1134 the lease file, but not in the dhcpd.conf file. In this case, we
1135 *should* keep it around until it's expired, but never reallocate it
1136 or renew it. Currently, to maintain consistency, we are not doing
1137 this.
1138 XXX fix this so that the lease is kept around until it expires.
1139 XXX this will be important in IPv6 with addresses that become
1140 XXX non-renewable as a result of a renumbering event. */
1141
1142 if (!lease -> subnet) {
1143 log_error ("lease %s: no subnet.", piaddr (lease -> ip_addr));
1144 return;
1145 }
1146 lease_ip_hash_add(lease_ip_addr_hash, lease->ip_addr.iabuf,
1148}
1149
1150/* Replace the data in an existing lease with the data in a new lease;
1151 adjust hash tables to suit, and insertion sort the lease into the
1152 list of leases by expiry time so that we can always find the oldest
1153 lease. */
1154
1155int supersede_lease (comp, lease, commit, propogate, pimmediate, from_pool)
1156 struct lease *comp, *lease;
1157 int commit;
1158 int propogate;
1159 int pimmediate;
1160 int from_pool;
1161{
1163 struct timeval tv;
1164#if defined (FAILOVER_PROTOCOL)
1165 int do_pool_check = 0;
1166
1167 /* We must commit leases before sending updates regarding them
1168 to failover peers. It is, therefore, an error to set pimmediate
1169 and not commit. */
1170 if (pimmediate && !commit)
1171 return 0;
1172#endif
1173 /* If there is no sample lease, just do the move. */
1174 if (!lease)
1175 goto just_move_it;
1176
1177 /* Static leases are not currently kept in the database... */
1178 if (lease -> flags & STATIC_LEASE)
1179 return 1;
1180
1181 /* If the existing lease hasn't expired and has a different
1182 unique identifier or, if it doesn't have a unique
1183 identifier, a different hardware address, then the two
1184 leases are in conflict. If the existing lease has a uid
1185 and the new one doesn't, but they both have the same
1186 hardware address, and dynamic bootp is allowed on this
1187 lease, then we allow that, in case a dynamic BOOTP lease is
1188 requested *after* a DHCP lease has been assigned. */
1189
1190 if (lease -> binding_state != FTS_ABANDONED &&
1191 lease -> next_binding_state != FTS_ABANDONED &&
1192 comp -> binding_state == FTS_ACTIVE &&
1193 (((comp -> uid && lease -> uid) &&
1194 (comp -> uid_len != lease -> uid_len ||
1195 memcmp (comp -> uid, lease -> uid, comp -> uid_len))) ||
1196 (!comp -> uid &&
1197 ((comp -> hardware_addr.hlen !=
1198 lease -> hardware_addr.hlen) ||
1199 memcmp (comp -> hardware_addr.hbuf,
1200 lease -> hardware_addr.hbuf,
1201 comp -> hardware_addr.hlen))))) {
1202 log_error ("Lease conflict at %s",
1203 piaddr (comp -> ip_addr));
1204 }
1205
1206 /* If there's a Unique ID, dissociate it from the hash
1207 table and free it if necessary. */
1208 if (comp->uid) {
1209 uid_hash_delete(comp);
1210 if (comp->uid != comp->uid_buf) {
1211 dfree(comp->uid, MDL);
1212 comp->uid_max = 0;
1213 comp->uid_len = 0;
1214 }
1215 comp -> uid = (unsigned char *)0;
1216 }
1217
1218 /* If there's a hardware address, remove the lease from its
1219 * old position in the hash bucket's ordered list.
1220 */
1221 if (comp->hardware_addr.hlen)
1222 hw_hash_delete(comp);
1223
1224 /* If the lease has been billed to a class, remove the billing. */
1225 if (comp -> billing_class != lease -> billing_class) {
1226 if (comp->billing_class)
1227 unbill_class(comp);
1228 if (lease -> billing_class)
1229 bill_class (comp, lease -> billing_class);
1230 }
1231
1232 /* Copy the data files, but not the linkages. */
1233 comp -> starts = lease -> starts;
1234 if (lease -> uid) {
1235 if (lease -> uid_len <= sizeof (lease -> uid_buf)) {
1236 memcpy (comp -> uid_buf,
1237 lease -> uid, lease -> uid_len);
1238 comp -> uid = &comp -> uid_buf [0];
1239 comp -> uid_max = sizeof comp -> uid_buf;
1240 comp -> uid_len = lease -> uid_len;
1241 } else if (lease -> uid != &lease -> uid_buf [0]) {
1242 comp -> uid = lease -> uid;
1243 comp -> uid_max = lease -> uid_max;
1244 lease -> uid = (unsigned char *)0;
1245 lease -> uid_max = 0;
1246 comp -> uid_len = lease -> uid_len;
1247 lease -> uid_len = 0;
1248 } else {
1249 log_fatal ("corrupt lease uid."); /* XXX */
1250 }
1251 } else {
1252 comp -> uid = (unsigned char *)0;
1253 comp -> uid_len = comp -> uid_max = 0;
1254 }
1255 if (comp -> host)
1256 host_dereference (&comp -> host, MDL);
1257 host_reference (&comp -> host, lease -> host, MDL);
1258 comp -> hardware_addr = lease -> hardware_addr;
1259 if (comp -> scope)
1260 binding_scope_dereference (&comp -> scope, MDL);
1261 if (lease -> scope) {
1262 binding_scope_reference (&comp -> scope, lease -> scope, MDL);
1263 binding_scope_dereference (&lease -> scope, MDL);
1264 }
1265
1266 if (comp -> agent_options)
1268 if (lease -> agent_options) {
1269 /* Only retain the agent options if the lease is still
1270 affirmatively associated with a client. */
1271 if (lease -> next_binding_state == FTS_ACTIVE ||
1272 lease -> next_binding_state == FTS_EXPIRED)
1275 MDL);
1277 }
1278
1279 /* Record the hostname information in the lease. */
1280 if (comp -> client_hostname)
1281 dfree (comp -> client_hostname, MDL);
1282 comp -> client_hostname = lease -> client_hostname;
1283 lease -> client_hostname = (char *)0;
1284
1285 if (lease->on_star.on_expiry) {
1286 if (comp->on_star.on_expiry)
1288 (&comp->on_star.on_expiry, MDL);
1291 MDL);
1292 }
1293 if (lease->on_star.on_commit) {
1294 if (comp->on_star.on_commit)
1296 (&comp->on_star.on_commit, MDL);
1299 MDL);
1300 }
1301 if (lease->on_star.on_release) {
1302 if (comp->on_star.on_release)
1304 (&comp->on_star.on_release, MDL);
1307 MDL);
1308 }
1309
1310 /* Record the lease in the uid hash if necessary. */
1311 if (comp->uid)
1312 uid_hash_add(comp);
1313
1314 /* Record it in the hardware address hash if necessary. */
1315 if (comp->hardware_addr.hlen)
1316 hw_hash_add(comp);
1317
1318 comp->cltt = lease->cltt;
1319#if defined (FAILOVER_PROTOCOL)
1320 comp->tstp = lease->tstp;
1321 comp->tsfp = lease->tsfp;
1322 comp->atsfp = lease->atsfp;
1323#endif /* FAILOVER_PROTOCOL */
1324 comp->ends = lease->ends;
1326
1327 /*
1328 * If we have a control block pointer copy it in.
1329 * We don't zero out an older ponter as it is still
1330 * in use. We shouldn't need to overwrite an
1331 * old pointer with a new one as the old transaction
1332 * should have been cancelled before getting here.
1333 */
1334 if (lease->ddns_cb != NULL)
1335 comp->ddns_cb = lease->ddns_cb;
1336
1337 just_move_it:
1338#if defined (FAILOVER_PROTOCOL)
1339 /*
1340 * Atsfp should be cleared upon any state change that implies
1341 * propagation whether supersede_lease was given a copy lease
1342 * structure or not (often from the pool_timer()).
1343 */
1344 if (propogate)
1345 comp->atsfp = 0;
1346#endif /* FAILOVER_PROTOCOL */
1347
1348 if (!comp -> pool) {
1349 log_error ("Supersede_lease: lease %s with no pool.",
1350 piaddr (comp -> ip_addr));
1351 return 0;
1352 }
1353
1354 /* Figure out which queue it's on. */
1355 switch (comp -> binding_state) {
1356 case FTS_FREE:
1357 if (comp->flags & RESERVED_LEASE)
1358 lq = &comp->pool->reserved;
1359 else {
1360 lq = &comp->pool->free;
1361 comp->pool->free_leases--;
1362 }
1363
1364#if defined(FAILOVER_PROTOCOL)
1365 do_pool_check = 1;
1366#endif
1367 break;
1368
1369 case FTS_ACTIVE:
1370 lq = &comp -> pool -> active;
1371 break;
1372
1373 case FTS_EXPIRED:
1374 case FTS_RELEASED:
1375 case FTS_RESET:
1376 lq = &comp -> pool -> expired;
1377 break;
1378
1379 case FTS_ABANDONED:
1380 lq = &comp -> pool -> abandoned;
1381 break;
1382
1383 case FTS_BACKUP:
1384 if (comp->flags & RESERVED_LEASE)
1385 lq = &comp->pool->reserved;
1386 else {
1387 lq = &comp->pool->backup;
1388 comp->pool->backup_leases--;
1389 }
1390
1391#if defined(FAILOVER_PROTOCOL)
1392 do_pool_check = 1;
1393#endif
1394 break;
1395
1396 default:
1397 log_error ("Lease with bogus binding state: %d",
1398 comp -> binding_state);
1399#if defined (BINDING_STATE_DEBUG)
1400 abort ();
1401#endif
1402 return 0;
1403 }
1404
1405 /* Remove the lease from its current place in its current
1406 timer sequence. */
1407 LEASE_REMOVEP(lq, comp);
1408
1409 /* Now that we've done the flag-affected queue removal
1410 * we can update the new lease's flags, if there's an
1411 * existing lease */
1412 if (lease) {
1413 comp->flags = ((lease->flags & ~PERSISTENT_FLAGS) |
1414 (comp->flags & ~EPHEMERAL_FLAGS));
1415 }
1416
1417 /* Make the state transition. */
1418 if (commit || !pimmediate)
1420
1421 /* Put the lease back on the appropriate queue. If the lease
1422 is corrupt (as detected by lease_enqueue), don't go any farther. */
1423 if (!lease_enqueue (comp))
1424 return 0;
1425
1426 /* If this is the next lease that will timeout on the pool,
1427 zap the old timeout and set the timeout on this pool to the
1428 time that the lease's next event will happen.
1429
1430 We do not actually set the timeout unless commit is true -
1431 we don't want to thrash the timer queue when reading the
1432 lease database. Instead, the database code calls the
1433 expiry event on each pool after reading in the lease file,
1434 and the expiry code sets the timer if there's anything left
1435 to expire after it's run any outstanding expiry events on
1436 the pool. */
1437 if ((commit || !pimmediate) &&
1438 comp -> sort_time != MIN_TIME &&
1439 comp -> sort_time > cur_time &&
1440 (comp -> sort_time < comp -> pool -> next_event_time ||
1441 comp -> pool -> next_event_time == MIN_TIME)) {
1442 comp -> pool -> next_event_time = comp -> sort_time;
1443 tv . tv_sec = comp -> pool -> next_event_time;
1444 tv . tv_usec = 0;
1445 add_timeout (&tv,
1446 pool_timer, comp -> pool,
1447 (tvref_t)pool_reference,
1448 (tvunref_t)pool_dereference);
1449 }
1450
1451 if (commit) {
1452#if defined(FAILOVER_PROTOCOL)
1453 /*
1454 * If commit and propogate are set, then we can save a
1455 * possible fsync later in BNDUPD socket transmission by
1456 * stepping the rewind state forward to the new state, in
1457 * case it has changed. This is only worth doing if the
1458 * failover connection is currently connected, as in this
1459 * case it is likely we will be transmitting to the peer very
1460 * shortly.
1461 */
1462 if (propogate && (comp->pool->failover_peer != NULL) &&
1463 ((comp->pool->failover_peer->service_state ==
1464 cooperating) ||
1465 (comp->pool->failover_peer->service_state ==
1467 comp->rewind_binding_state = comp->binding_state;
1468#endif
1469
1470 if (!write_lease (comp))
1471 return 0;
1472 if ((server_starting & SS_NOSYNC) == 0) {
1473 if (!commit_leases ())
1474 return 0;
1475 }
1476 }
1477
1478#if defined (FAILOVER_PROTOCOL)
1479 if (propogate) {
1480 comp -> desired_binding_state = comp -> binding_state;
1481 if (!dhcp_failover_queue_update (comp, pimmediate))
1482 return 0;
1483 }
1484 if (do_pool_check && comp->pool->failover_peer)
1486#endif
1487
1488 /* If the current binding state has already expired and we haven't
1489 * been called from pool_timer, do an expiry event right now.
1490 */
1491 /* XXX At some point we should optimize this so that we don't
1492 XXX write the lease twice, but this is a safe way to fix the
1493 XXX problem for 3.0 (I hope!). */
1494 if ((from_pool == 0) &&
1495 (commit || !pimmediate) &&
1496 (comp->sort_time < cur_time) &&
1497 (comp->next_binding_state != comp->binding_state))
1498 pool_timer(comp->pool);
1499
1500 return 1;
1501}
1502
1504{
1505
1506#if defined (FAILOVER_PROTOCOL)
1507 dhcp_failover_state_t *peer;
1508
1509 if (lease -> pool && lease -> pool -> failover_peer)
1510 peer = lease -> pool -> failover_peer;
1511 else
1512 peer = (dhcp_failover_state_t *)0;
1513#endif
1514
1515 /* If the lease was active and is now no longer active, but isn't
1516 released, then it just expired, so do the expiry event. */
1517 if (lease -> next_binding_state != lease -> binding_state &&
1518 ((
1519#if defined (FAILOVER_PROTOCOL)
1520 peer &&
1525 (!peer &&
1526#endif
1527 lease -> binding_state == FTS_ACTIVE &&
1528 lease -> next_binding_state != FTS_RELEASED))) {
1529#if defined (NSUPDATE)
1530 (void) ddns_removals(lease, NULL, NULL, ISC_TRUE);
1531#endif
1532 if (lease->on_star.on_expiry) {
1533 execute_statements(NULL, NULL, lease,
1534 NULL, NULL, NULL,
1535 &lease->scope,
1537 NULL);
1538 if (lease->on_star.on_expiry)
1541 }
1542
1543 /* No sense releasing a lease after it's expired. */
1547 /* Get rid of client-specific bindings that are only
1548 correct when the lease is active. */
1549 if (lease->billing_class)
1551 if (lease -> agent_options)
1553 MDL);
1554 if (lease -> client_hostname) {
1555 dfree (lease -> client_hostname, MDL);
1556 lease -> client_hostname = (char *)0;
1557 }
1558 if (lease -> host)
1559 host_dereference (&lease -> host, MDL);
1560
1561 /* Send the expiry time to the peer. */
1562 lease -> tstp = lease -> ends;
1563 }
1564
1565 /* If the lease was active and is now released, do the release
1566 event. */
1567 if (lease -> next_binding_state != lease -> binding_state &&
1568 ((
1569#if defined (FAILOVER_PROTOCOL)
1570 peer &&
1571 lease -> binding_state == FTS_RELEASED &&
1572 (lease -> next_binding_state == FTS_FREE ||
1573 lease -> next_binding_state == FTS_BACKUP)) ||
1574 (!peer &&
1575#endif
1576 lease -> binding_state == FTS_ACTIVE &&
1577 lease -> next_binding_state == FTS_RELEASED))) {
1578#if defined (NSUPDATE)
1579 /*
1580 * Note: ddns_removals() is also iterated when the lease
1581 * enters state 'released' in 'release_lease()'. The below
1582 * is caught when a peer receives a BNDUPD from a failover
1583 * peer; it may not have received the client's release (it
1584 * may have been offline).
1585 *
1586 * We could remove the call from release_lease() because
1587 * it will also catch here on the originating server after the
1588 * peer acknowledges the state change. However, there could
1589 * be many hours inbetween, and in this case we /know/ the
1590 * client is no longer using the lease when we receive the
1591 * release message. This is not true of expiry, where the
1592 * peer may have extended the lease.
1593 */
1594 (void) ddns_removals(lease, NULL, NULL, ISC_TRUE);
1595#endif
1596 if (lease->on_star.on_release) {
1597 execute_statements(NULL, NULL, lease,
1598 NULL, NULL, NULL,
1599 &lease->scope,
1601 NULL);
1604 }
1605
1606 /* A released lease can't expire. */
1607 if (lease->on_star.on_expiry)
1610
1611 /* Get rid of client-specific bindings that are only
1612 correct when the lease is active. */
1613 if (lease->billing_class)
1615 if (lease -> agent_options)
1617 MDL);
1618 if (lease -> client_hostname) {
1619 dfree (lease -> client_hostname, MDL);
1620 lease -> client_hostname = (char *)0;
1621 }
1622 if (lease -> host)
1623 host_dereference (&lease -> host, MDL);
1624
1625 /* Send the release time (should be == cur_time) to the
1626 peer. */
1627 lease -> tstp = lease -> ends;
1628 }
1629
1630#if defined (DEBUG_LEASE_STATE_TRANSITIONS)
1631 log_debug ("lease %s moves from %s to %s",
1632 piaddr (lease -> ip_addr),
1633 binding_state_print (lease -> binding_state),
1634 binding_state_print (lease -> next_binding_state));
1635#endif
1636
1637 lease -> binding_state = lease -> next_binding_state;
1638 switch (lease -> binding_state) {
1639 case FTS_ACTIVE:
1640#if defined (FAILOVER_PROTOCOL)
1641 if (lease -> pool && lease -> pool -> failover_peer)
1642 lease -> next_binding_state = FTS_EXPIRED;
1643 else
1644#endif
1645 lease -> next_binding_state = FTS_FREE;
1646 break;
1647
1648 case FTS_EXPIRED:
1649 case FTS_RELEASED:
1650 case FTS_ABANDONED:
1651 case FTS_RESET:
1653#if defined(FAILOVER_PROTOCOL)
1654 /* If we are not in partner_down, leases don't go from
1655 EXPIRED to FREE on a timeout - only on an update.
1656 If we're in partner_down, they expire at mclt past
1657 the time we entered partner_down. */
1658 if ((lease->pool != NULL) &&
1659 (lease->pool->failover_peer != NULL) &&
1660 (lease->pool->failover_peer->me.state == partner_down))
1661 lease->tsfp =
1662 (lease->pool->failover_peer->me.stos +
1663 lease->pool->failover_peer->mclt);
1664#endif /* FAILOVER_PROTOCOL */
1665 break;
1666
1667 case FTS_FREE:
1668 case FTS_BACKUP:
1669 lease -> next_binding_state = lease -> binding_state;
1670 break;
1671 }
1672#if defined (DEBUG_LEASE_STATE_TRANSITIONS)
1673 log_debug ("lease %s: next binding state %s",
1674 piaddr (lease -> ip_addr),
1675 binding_state_print (lease -> next_binding_state));
1676#endif
1677}
1678
1679/* Copy the contents of one lease into another, correctly maintaining
1680 reference counts. */
1681int lease_copy (struct lease **lp,
1682 struct lease *lease, const char *file, int line)
1683{
1684 struct lease *lt = (struct lease *)0;
1685 isc_result_t status;
1686
1687 status = lease_allocate (&lt, MDL);
1688 if (status != ISC_R_SUCCESS)
1689 return 0;
1690
1691 lt -> ip_addr = lease -> ip_addr;
1692 lt -> starts = lease -> starts;
1693 lt -> ends = lease -> ends;
1694 lt -> uid_len = lease -> uid_len;
1695 lt -> uid_max = lease -> uid_max;
1696 if (lease -> uid == lease -> uid_buf) {
1697 lt -> uid = lt -> uid_buf;
1698 memcpy (lt -> uid_buf, lease -> uid_buf, sizeof lt -> uid_buf);
1699 } else if (!lease -> uid_max) {
1700 lt -> uid = (unsigned char *)0;
1701 } else {
1702 lt -> uid = dmalloc (lt -> uid_max, MDL);
1703 if (!lt -> uid) {
1704 lease_dereference (&lt, MDL);
1705 return 0;
1706 }
1707 memcpy (lt -> uid, lease -> uid, lease -> uid_max);
1708 }
1709 if (lease -> client_hostname) {
1710 lt -> client_hostname =
1711 dmalloc (strlen (lease -> client_hostname) + 1, MDL);
1712 if (!lt -> client_hostname) {
1713 lease_dereference (&lt, MDL);
1714 return 0;
1715 }
1716 strcpy (lt -> client_hostname, lease -> client_hostname);
1717 }
1718 if (lease -> scope)
1720 if (lease -> agent_options)
1722 lease -> agent_options, MDL);
1723 host_reference (&lt -> host, lease -> host, file, line);
1724 subnet_reference (&lt -> subnet, lease -> subnet, file, line);
1725 pool_reference (&lt -> pool, lease -> pool, file, line);
1726 class_reference (&lt -> billing_class,
1729 if (lease->on_star.on_expiry)
1732 file, line);
1733 if (lease->on_star.on_commit)
1736 file, line);
1740 file, line);
1741 lt->flags = lease->flags;
1742 lt->tstp = lease->tstp;
1743 lt->tsfp = lease->tsfp;
1744 lt->atsfp = lease->atsfp;
1745 lt->cltt = lease -> cltt;
1749 status = lease_reference(lp, lt, file, line);
1750 lease_dereference(&lt, MDL);
1751 return status == ISC_R_SUCCESS;
1752}
1753
1754/* Release the specified lease and re-hash it as appropriate. */
1756 struct lease *lease;
1757 struct packet *packet;
1758{
1759 /* If there are statements to execute when the lease is
1760 released, execute them. */
1761#if defined (NSUPDATE)
1762 (void) ddns_removals(lease, NULL, NULL, ISC_FALSE);
1763#endif
1764 if (lease->on_star.on_release) {
1766 NULL, packet->options,
1767 NULL, &lease->scope,
1768 lease->on_star.on_release, NULL);
1772 }
1773
1774 /* We do either the on_release or the on_expiry events, but
1775 not both (it's possible that they could be the same,
1776 in any case). */
1777 if (lease->on_star.on_expiry)
1780
1781 if (lease -> binding_state != FTS_FREE &&
1782 lease -> binding_state != FTS_BACKUP &&
1783 lease -> binding_state != FTS_RELEASED &&
1784 lease -> binding_state != FTS_EXPIRED &&
1785 lease -> binding_state != FTS_RESET) {
1786 if (lease->on_star.on_commit)
1789
1790 /* Blow away any bindings. */
1791 if (lease -> scope)
1792 binding_scope_dereference (&lease -> scope, MDL);
1793
1794 /* Set sort times to the present. */
1795 lease -> ends = cur_time;
1796 /* Lower layers of muckery set tstp to ->ends. But we send
1797 * protocol messages before this. So it is best to set
1798 * tstp now anyway.
1799 */
1800 lease->tstp = cur_time;
1801#if defined (FAILOVER_PROTOCOL)
1802 if (lease -> pool && lease -> pool -> failover_peer) {
1803 dhcp_failover_state_t *peer = NULL;
1804
1805 if (lease->pool != NULL)
1806 peer = lease->pool->failover_peer;
1807
1808 if ((peer->service_state == not_cooperating) &&
1809 (((peer->i_am == primary) &&
1811 ((peer->i_am == secondary) &&
1815 } else
1816 lease -> next_binding_state = FTS_RELEASED;
1817 } else {
1818 lease -> next_binding_state = FTS_FREE;
1819 }
1820#else
1821 lease -> next_binding_state = FTS_FREE;
1822#endif
1823 supersede_lease(lease, NULL, 1, 1, 1, 0);
1824 }
1825}
1826
1827/* Abandon the specified lease (set its timeout to infinity and its
1828 particulars to zero, and re-hash it as appropriate. */
1829
1830void abandon_lease (lease, message)
1831 struct lease *lease;
1832 const char *message;
1833{
1834 struct lease *lt = NULL;
1835#if defined (NSUPDATE)
1836 (void) ddns_removals(lease, NULL, NULL, ISC_FALSE);
1837#endif
1838
1839 if (!lease_copy(&lt, lease, MDL)) {
1840 return;
1841 }
1842
1843 if (lt->scope) {
1845 }
1846
1847 /* Calculate the abandone expiry time. If it wraps,
1848 * use the maximum expiry time. */
1850 if (lt->ends < cur_time || lt->ends > MAX_TIME) {
1851 lt->ends = MAX_TIME;
1852 }
1853
1855
1856 log_error ("Abandoning IP address %s: %s", piaddr(lease->ip_addr),
1857 message);
1858 lt->hardware_addr.hlen = 0;
1859 if (lt->uid && lt->uid != lt->uid_buf) {
1860 dfree(lt->uid, MDL);
1861 }
1862
1863 lt->uid = NULL;
1864 lt->uid_len = 0;
1865 lt->uid_max = 0;
1866 supersede_lease(lease, lt, 1, 1, 1, 0);
1867 lease_dereference(&lt, MDL);
1868}
1869
1870#if 0
1871/*
1872 * This doesn't appear to be in use for anything anymore.
1873 * I'm ifdeffing it now and if there are no complaints in
1874 * the future it will be removed.
1875 * SAR
1876 */
1877
1878/* Abandon the specified lease (set its timeout to infinity and its
1879 particulars to zero, and re-hash it as appropriate. */
1880
1881void dissociate_lease (lease)
1882 struct lease *lease;
1883{
1884 struct lease *lt = (struct lease *)0;
1885#if defined (NSUPDATE)
1886 (void) ddns_removals(lease, NULL, NULL, ISC_FALSE);
1887#endif
1888
1889 if (!lease_copy (&lt, lease, MDL))
1890 return;
1891
1892#if defined (FAILOVER_PROTOCOL)
1893 if (lease -> pool && lease -> pool -> failover_peer) {
1895 } else {
1897 }
1898#else
1900#endif
1901 lt -> ends = cur_time; /* XXX */
1902 lt -> hardware_addr.hlen = 0;
1903 if (lt -> uid && lt -> uid != lt -> uid_buf)
1904 dfree (lt -> uid, MDL);
1905 lt -> uid = (unsigned char *)0;
1906 lt -> uid_len = 0;
1907 lt -> uid_max = 0;
1908 supersede_lease (lease, lt, 1, 1, 1, 0);
1909 lease_dereference (&lt, MDL);
1910}
1911#endif
1912
1913/* Timer called when a lease in a particular pool expires. */
1914void pool_timer (vpool)
1915 void *vpool;
1916{
1917 struct pool *pool;
1918 struct lease *next = NULL;
1919 struct lease *lease = NULL;
1920 struct lease *ltemp = NULL;
1921#define FREE_LEASES 0
1922#define ACTIVE_LEASES 1
1923#define EXPIRED_LEASES 2
1924#define ABANDONED_LEASES 3
1925#define BACKUP_LEASES 4
1926#define RESERVED_LEASES 5
1928 TIME next_expiry = MAX_TIME;
1929 int i;
1930 struct timeval tv;
1931
1932 pool = (struct pool *)vpool;
1933
1934 lptr[FREE_LEASES] = &pool->free;
1935 lptr[ACTIVE_LEASES] = &pool->active;
1936 lptr[EXPIRED_LEASES] = &pool->expired;
1938 lptr[BACKUP_LEASES] = &pool->backup;
1939 lptr[RESERVED_LEASES] = &pool->reserved;
1940
1941 for (i = FREE_LEASES; i <= RESERVED_LEASES; i++) {
1942 /* If there's nothing on the queue, skip it. */
1943 if (!(LEASE_NOT_EMPTYP(lptr[i])))
1944 continue;
1945
1946#if defined (FAILOVER_PROTOCOL)
1947 if (pool->failover_peer &&
1948 pool->failover_peer->me.state != partner_down) {
1949 /*
1950 * Normally the secondary doesn't initiate expiration
1951 * events (unless in partner-down), but rather relies
1952 * on the primary to expire the lease. However, when
1953 * disconnected from its peer, the server is allowed to
1954 * rewind a lease to the previous state that the peer
1955 * would have recorded it. This means there may be
1956 * opportunities for active->free or active->backup
1957 * expirations while out of contact.
1958 *
1959 * Q: Should we limit this expiration to
1960 * comms-interrupt rather than not-normal?
1961 */
1962 if ((i == ACTIVE_LEASES) &&
1963 (pool->failover_peer->i_am == secondary) &&
1964 (pool->failover_peer->me.state == normal))
1965 continue;
1966
1967 /* Leases in an expired state don't move to
1968 free because of a timeout unless we're in
1969 partner_down. */
1970 if (i == EXPIRED_LEASES)
1971 continue;
1972 }
1973#endif
1974 lease_reference(&lease, LEASE_GET_FIRSTP(lptr[i]), MDL);
1975
1976 while (lease) {
1977 /* Remember the next lease in the list. */
1978 if (next)
1979 lease_dereference(&next, MDL);
1980 ltemp = LEASE_GET_NEXTP(lptr[i], lease);
1981 if (ltemp)
1982 lease_reference(&next, ltemp, MDL);
1983
1984 /* If we've run out of things to expire on this list,
1985 stop. */
1986 if (lease->sort_time > cur_time) {
1987 if (lease->sort_time < next_expiry)
1988 next_expiry = lease->sort_time;
1989 break;
1990 }
1991
1992 /* If there is a pending state change, and
1993 this lease has gotten to the time when the
1994 state change should happen, just call
1995 supersede_lease on it to make the change
1996 happen. */
1998 {
1999#if defined(FAILOVER_PROTOCOL)
2000 dhcp_failover_state_t *peer = NULL;
2001
2002 if (lease->pool != NULL)
2003 peer = lease->pool->failover_peer;
2004
2005 /* Can we rewind the lease to a free state? */
2006 if (peer != NULL &&
2007 peer->service_state == not_cooperating &&
2009 ((peer->i_am == primary &&
2011 ||
2012 (peer->i_am == secondary &&
2014 FTS_BACKUP)))
2017#endif
2018 supersede_lease(lease, NULL, 1, 1, 1, 1);
2019 }
2020
2021 lease_dereference(&lease, MDL);
2022 if (next)
2023 lease_reference(&lease, next, MDL);
2024 }
2025 if (next)
2026 lease_dereference(&next, MDL);
2027 if (lease)
2028 lease_dereference(&lease, MDL);
2029 }
2030
2031 /* If we found something to expire and its expiration time
2032 * is either less than the current expiration time or the
2033 * current expiration time is already expired update the
2034 * timer.
2035 */
2036 if ((next_expiry != MAX_TIME) &&
2037 ((pool->next_event_time > next_expiry) ||
2038 (pool->next_event_time <= cur_time))) {
2039 pool->next_event_time = next_expiry;
2040 tv.tv_sec = pool->next_event_time;
2041 tv.tv_usec = 0;
2043 (tvref_t)pool_reference,
2044 (tvunref_t)pool_dereference);
2045 } else
2047
2048}
2049
2050/* Locate the lease associated with a given IP address... */
2051
2052int find_lease_by_ip_addr (struct lease **lp, struct iaddr addr,
2053 const char *file, int line)
2054{
2055 return lease_ip_hash_lookup(lp, lease_ip_addr_hash, addr.iabuf,
2056 addr.len, file, line);
2057}
2058
2059int find_lease_by_uid (struct lease **lp, const unsigned char *uid,
2060 unsigned len, const char *file, int line)
2061{
2062 if (len == 0)
2063 return 0;
2064 return lease_id_hash_lookup (lp, lease_uid_hash, uid, len, file, line);
2065}
2066
2068 const unsigned char *hwaddr, unsigned hwlen,
2069 const char *file, int line)
2070{
2071 if (hwlen == 0)
2072 return (0);
2073
2074 /*
2075 * If it's an infiniband address don't bother
2076 * as we don't have a useful address to hash.
2077 */
2078 if ((hwlen == 1) && (hwaddr[0] == HTYPE_INFINIBAND))
2079 return (0);
2080
2081 return (lease_id_hash_lookup(lp, lease_hw_addr_hash, hwaddr, hwlen,
2082 file, line));
2083}
2084
2085/* If the lease is preferred over the candidate, return truth. The
2086 * 'cand' and 'lease' names are retained to read more clearly against
2087 * the 'uid_hash_add' and 'hw_hash_add' functions (this is common logic
2088 * to those two functions).
2089 *
2090 * 1) ACTIVE leases are preferred. The active lease with
2091 * the longest lifetime is preferred over shortest.
2092 * 2) "transitional states" are next, this time with the
2093 * most recent CLTT.
2094 * 3) free/backup/etc states are next, again with CLTT. In truth we
2095 * should never see reset leases for this.
2096 * 4) Abandoned leases are always dead last.
2097 */
2098static isc_boolean_t
2099client_lease_preferred(struct lease *cand, struct lease *lease)
2100{
2101 if (cand->binding_state == FTS_ACTIVE) {
2102 if (lease->binding_state == FTS_ACTIVE &&
2103 lease->ends >= cand->ends)
2104 return ISC_TRUE;
2105 } else if (cand->binding_state == FTS_EXPIRED ||
2106 cand->binding_state == FTS_RELEASED) {
2108 return ISC_TRUE;
2109
2110 if ((lease->binding_state == FTS_EXPIRED ||
2112 lease->cltt >= cand->cltt)
2113 return ISC_TRUE;
2114 } else if (cand->binding_state != FTS_ABANDONED) {
2115 if (lease->binding_state == FTS_ACTIVE ||
2118 return ISC_TRUE;
2119
2121 lease->cltt >= cand->cltt)
2122 return ISC_TRUE;
2123 } else /* (cand->binding_state == FTS_ABANDONED) */ {
2125 lease->cltt >= cand->cltt)
2126 return ISC_TRUE;
2127 }
2128
2129 return ISC_FALSE;
2130}
2131
2132/* Add the specified lease to the uid hash. */
2133void
2135{
2136 struct lease *head = NULL;
2137 struct lease *cand = NULL;
2138 struct lease *prev = NULL;
2139 struct lease *next = NULL;
2140
2141 /* If it's not in the hash, just add it. */
2142 if (!find_lease_by_uid (&head, lease -> uid, lease -> uid_len, MDL))
2143 lease_id_hash_add(lease_uid_hash, lease->uid, lease->uid_len,
2144 lease, MDL);
2145 else {
2146 /* Otherwise, insert it into the list in order of its
2147 * preference for "resuming allocation to the client."
2148 *
2149 * Because we don't have control of the hash bucket index
2150 * directly, we have to remove and re-insert the client
2151 * id into the hash if we're inserting onto the head.
2152 */
2153 lease_reference(&cand, head, MDL);
2154 while (cand != NULL) {
2155 if (client_lease_preferred(cand, lease))
2156 break;
2157
2158 if (prev != NULL)
2159 lease_dereference(&prev, MDL);
2160 lease_reference(&prev, cand, MDL);
2161
2162 if (cand->n_uid != NULL)
2163 lease_reference(&next, cand->n_uid, MDL);
2164
2165 lease_dereference(&cand, MDL);
2166
2167 if (next != NULL) {
2168 lease_reference(&cand, next, MDL);
2169 lease_dereference(&next, MDL);
2170 }
2171 }
2172
2173 /* If we want to insert 'before cand', and prev is NULL,
2174 * then it was the head of the list. Assume that position.
2175 */
2176 if (prev == NULL) {
2177 lease_reference(&lease->n_uid, head, MDL);
2178 lease_id_hash_delete(lease_uid_hash, lease->uid,
2179 lease->uid_len, MDL);
2180 lease_id_hash_add(lease_uid_hash, lease->uid,
2181 lease->uid_len, lease, MDL);
2182 } else /* (prev != NULL) */ {
2183 if(prev->n_uid != NULL) {
2184 lease_reference(&lease->n_uid, prev->n_uid,
2185 MDL);
2186 lease_dereference(&prev->n_uid, MDL);
2187 }
2188 lease_reference(&prev->n_uid, lease, MDL);
2189
2190 lease_dereference(&prev, MDL);
2191 }
2192
2193 if (cand != NULL)
2194 lease_dereference(&cand, MDL);
2195 lease_dereference(&head, MDL);
2196 }
2197}
2198
2199/* Delete the specified lease from the uid hash. */
2200
2202 struct lease *lease;
2203{
2204 struct lease *head = (struct lease *)0;
2205 struct lease *scan;
2206
2207 /* If it's not in the hash, we have no work to do. */
2208 if (!find_lease_by_uid (&head, lease -> uid, lease -> uid_len, MDL)) {
2209 if (lease -> n_uid)
2210 lease_dereference (&lease -> n_uid, MDL);
2211 return;
2212 }
2213
2214 /* If the lease we're freeing is at the head of the list,
2215 remove the hash table entry and add a new one with the
2216 next lease on the list (if there is one). */
2217 if (head == lease) {
2218 lease_id_hash_delete(lease_uid_hash, lease->uid,
2219 lease->uid_len, MDL);
2220 if (lease -> n_uid) {
2221 lease_id_hash_add(lease_uid_hash, lease->n_uid->uid,
2223 MDL);
2224 lease_dereference (&lease -> n_uid, MDL);
2225 }
2226 } else {
2227 /* Otherwise, look for the lease in the list of leases
2228 attached to the hash table entry, and remove it if
2229 we find it. */
2230 for (scan = head; scan -> n_uid; scan = scan -> n_uid) {
2231 if (scan -> n_uid == lease) {
2232 lease_dereference (&scan -> n_uid, MDL);
2233 if (lease -> n_uid) {
2234 lease_reference (&scan -> n_uid,
2235 lease -> n_uid, MDL);
2236 lease_dereference (&lease -> n_uid,
2237 MDL);
2238 }
2239 break;
2240 }
2241 }
2242 }
2243 lease_dereference (&head, MDL);
2244}
2245
2246/* Add the specified lease to the hardware address hash. */
2247/* We don't add leases with infiniband addresses to the
2248 * hash as there isn't any address to hash on. */
2249
2250void
2252{
2253 struct lease *head = NULL;
2254 struct lease *cand = NULL;
2255 struct lease *prev = NULL;
2256 struct lease *next = NULL;
2257
2258 /*
2259 * If it's an infiniband address don't bother
2260 * as we don't have a useful address to hash.
2261 */
2262 if ((lease->hardware_addr.hlen == 1) &&
2264 return;
2265
2266 /* If it's not in the hash, just add it. */
2269 lease_id_hash_add(lease_hw_addr_hash,
2272 else {
2273 /* Otherwise, insert it into the list in order of its
2274 * preference for "resuming allocation to the client."
2275 *
2276 * Because we don't have control of the hash bucket index
2277 * directly, we have to remove and re-insert the client
2278 * id into the hash if we're inserting onto the head.
2279 */
2280 lease_reference(&cand, head, MDL);
2281 while (cand != NULL) {
2282 if (client_lease_preferred(cand, lease))
2283 break;
2284
2285 if (prev != NULL)
2286 lease_dereference(&prev, MDL);
2287 lease_reference(&prev, cand, MDL);
2288
2289 if (cand->n_hw != NULL)
2290 lease_reference(&next, cand->n_hw, MDL);
2291
2292 lease_dereference(&cand, MDL);
2293
2294 if (next != NULL) {
2295 lease_reference(&cand, next, MDL);
2296 lease_dereference(&next, MDL);
2297 }
2298 }
2299
2300 /* If we want to insert 'before cand', and prev is NULL,
2301 * then it was the head of the list. Assume that position.
2302 */
2303 if (prev == NULL) {
2304 lease_reference(&lease->n_hw, head, MDL);
2305 lease_id_hash_delete(lease_hw_addr_hash,
2308 lease_id_hash_add(lease_hw_addr_hash,
2311 lease, MDL);
2312 } else /* (prev != NULL) */ {
2313 if(prev->n_hw != NULL) {
2314 lease_reference(&lease->n_hw, prev->n_hw,
2315 MDL);
2316 lease_dereference(&prev->n_hw, MDL);
2317 }
2318 lease_reference(&prev->n_hw, lease, MDL);
2319
2320 lease_dereference(&prev, MDL);
2321 }
2322
2323 if (cand != NULL)
2324 lease_dereference(&cand, MDL);
2325 lease_dereference(&head, MDL);
2326 }
2327}
2328
2329/* Delete the specified lease from the hardware address hash. */
2330
2332 struct lease *lease;
2333{
2334 struct lease *head = (struct lease *)0;
2335 struct lease *next = (struct lease *)0;
2336
2337 /*
2338 * If it's an infiniband address don't bother
2339 * as we don't have a useful address to hash.
2340 */
2341 if ((lease->hardware_addr.hlen == 1) &&
2343 return;
2344
2345 /* If it's not in the hash, we have no work to do. */
2347 lease -> hardware_addr.hlen, MDL)) {
2348 if (lease -> n_hw)
2349 lease_dereference (&lease -> n_hw, MDL);
2350 return;
2351 }
2352
2353 /* If the lease we're freeing is at the head of the list,
2354 remove the hash table entry and add a new one with the
2355 next lease on the list (if there is one). */
2356 if (head == lease) {
2357 lease_id_hash_delete(lease_hw_addr_hash,
2360 if (lease->n_hw) {
2361 lease_id_hash_add(lease_hw_addr_hash,
2364 lease->n_hw, MDL);
2365 lease_dereference(&lease->n_hw, MDL);
2366 }
2367 } else {
2368 /* Otherwise, look for the lease in the list of leases
2369 attached to the hash table entry, and remove it if
2370 we find it. */
2371 while (head -> n_hw) {
2372 if (head -> n_hw == lease) {
2373 lease_dereference (&head -> n_hw, MDL);
2374 if (lease -> n_hw) {
2375 lease_reference (&head -> n_hw,
2376 lease -> n_hw, MDL);
2377 lease_dereference (&lease -> n_hw,
2378 MDL);
2379 }
2380 break;
2381 }
2382 lease_reference (&next, head -> n_hw, MDL);
2383 lease_dereference (&head, MDL);
2384 lease_reference (&head, next, MDL);
2385 lease_dereference (&next, MDL);
2386 }
2387 }
2388 if (head)
2389 lease_dereference (&head, MDL);
2390}
2391
2392/* Write v4 leases to permanent storage. */
2393int write_leases4(void) {
2394 struct lease *l;
2395 struct shared_network *s;
2396 struct pool *p;
2398 int num_written = 0, i;
2399
2400 /* Write all the leases. */
2401 for (s = shared_networks; s; s = s->next) {
2402 for (p = s->pools; p; p = p->next) {
2403 lptr[FREE_LEASES] = &p->free;
2404 lptr[ACTIVE_LEASES] = &p->active;
2405 lptr[EXPIRED_LEASES] = &p->expired;
2406 lptr[ABANDONED_LEASES] = &p->abandoned;
2407 lptr[BACKUP_LEASES] = &p->backup;
2408 lptr[RESERVED_LEASES] = &p->reserved;
2409
2410 for (i = FREE_LEASES; i <= RESERVED_LEASES; i++) {
2411 for (l = LEASE_GET_FIRSTP(lptr[i]);
2412 l != NULL;
2413 l = LEASE_GET_NEXTP(lptr[i], l)) {
2414#if !defined (DEBUG_DUMP_ALL_LEASES)
2415 if (l->hardware_addr.hlen != 0 || l->uid_len != 0 ||
2416 l->tsfp != 0 || l->binding_state != FTS_FREE)
2417#endif
2418 {
2419 if (write_lease(l) == 0)
2420 return (0);
2421 num_written++;
2422 }
2423 }
2424 }
2425 }
2426 }
2427
2428 log_info ("Wrote %d leases to leases file.", num_written);
2429 return (1);
2430}
2431
2432/* Write all interesting leases to permanent storage. */
2433
2435{
2436 struct host_decl *hp;
2437 struct group_object *gp;
2438 struct hash_bucket *hb;
2439 struct class *cp;
2440 struct collection *colp;
2441 int i;
2442 int num_written;
2443
2444 /* write all the dynamically-created class declarations. */
2445 if (collections->classes) {
2447 for (colp = collections ; colp ; colp = colp->next) {
2448 for (cp = colp->classes ; cp ; cp = cp->nic) {
2450 (unsigned char *)cp->name,
2451 0, cp);
2452 }
2453 }
2454
2455 /* XXXJAB this number doesn't include subclasses... */
2456 log_info ("Wrote %d class decls to leases file.",
2458 }
2459
2460
2461 /* Write all the dynamically-created group declarations. */
2462 if (group_name_hash) {
2463 num_written = 0;
2464 for (i = 0; i < group_name_hash -> hash_count; i++) {
2465 for (hb = group_name_hash -> buckets [i];
2466 hb; hb = hb -> next) {
2467 gp = (struct group_object *)hb -> value;
2468 if ((gp -> flags & GROUP_OBJECT_DYNAMIC) ||
2469 ((gp -> flags & GROUP_OBJECT_STATIC) &&
2470 (gp -> flags & GROUP_OBJECT_DELETED))) {
2471 if (!write_group (gp))
2472 return 0;
2473 ++num_written;
2474 }
2475 }
2476 }
2477 log_info ("Wrote %d group decls to leases file.", num_written);
2478 }
2479
2480 /* Write all the deleted host declarations. */
2481 if (host_name_hash) {
2482 num_written = 0;
2483 for (i = 0; i < host_name_hash -> hash_count; i++) {
2484 for (hb = host_name_hash -> buckets [i];
2485 hb; hb = hb -> next) {
2486 hp = (struct host_decl *)hb -> value;
2487 if (((hp -> flags & HOST_DECL_STATIC) &&
2488 (hp -> flags & HOST_DECL_DELETED))) {
2489 if (!write_host (hp))
2490 return 0;
2491 ++num_written;
2492 }
2493 }
2494 }
2495 log_info ("Wrote %d deleted host decls to leases file.",
2496 num_written);
2497 }
2498
2499 /* Write all the new, dynamic host declarations. */
2500 if (host_name_hash) {
2501 num_written = 0;
2502 for (i = 0; i < host_name_hash -> hash_count; i++) {
2503 for (hb = host_name_hash -> buckets [i];
2504 hb; hb = hb -> next) {
2505 hp = (struct host_decl *)hb -> value;
2506 if ((hp -> flags & HOST_DECL_DYNAMIC)) {
2507 if (!write_host (hp))
2508 ++num_written;
2509 }
2510 }
2511 }
2512 log_info ("Wrote %d new dynamic host decls to leases file.",
2513 num_written);
2514 }
2515
2516#if defined (FAILOVER_PROTOCOL)
2517 /* Write all the failover states. */
2519 return 0;
2520#endif
2521
2522 switch (local_family) {
2523 case AF_INET:
2524 if (write_leases4() == 0)
2525 return (0);
2526 break;
2527#ifdef DHCPv6
2528 case AF_INET6:
2529 if (write_leases6() == 0)
2530 return (0);
2531 break;
2532#endif /* DHCPv6 */
2533 }
2534
2535 if (commit_leases() == 0)
2536 return (0);
2537 return (1);
2538}
2539
2540#if !defined (BINARY_LEASES)
2541/* Unlink all the leases in the queue. */
2542void lease_remove_all(struct lease **lq) {
2543 struct lease *lp, *ln = NULL;
2544
2545 /* nothing to do */
2546 if (*lq == NULL)
2547 return;
2548
2549 /* We simply derefernce the first item in the list. When
2550 * it's reference counter goes to zero it will be cleaned
2551 * and the reference counter
2552 *
2553 * Get a pointer to the first item in the list and then
2554 * drop the reference from the queue pointer
2555 */
2556 lease_reference(&lp, *lq, MDL);
2557 lease_dereference(lq, MDL);
2558
2559 do {
2560 /* if we have a next save a pointer to it and unlink it */
2561 if (lp->next) {
2562 lease_reference(&ln, lp->next, MDL);
2563 lease_dereference(&lp->next, MDL);
2564 }
2565
2566 /* get rid of what we currently have */
2567 lease_dereference(&lp, MDL);
2568
2569 /* move the next to the current and loop */
2570 lp = ln;
2571 ln = NULL;
2572 } while (lp != NULL);
2573}
2574
2575/*
2576 * This routine walks through a given lease queue (lq) looking
2577 * for comp. If it doesn't find the lease it is a fatal error
2578 * as it should be on the given queue. Once we find the lease
2579 * we can remove it from this list.
2580 */
2581void lease_remove(struct lease **lq, struct lease *comp)
2582{
2583 struct lease *prev, *lp;
2584
2585 prev = NULL;
2586 for (lp = *lq; lp != NULL; lp = lp->next) {
2587 if (lp == comp)
2588 break;
2589 prev = lp;
2590 }
2591
2592 if (!lp) {
2593 log_fatal("Lease with binding state %s not on its queue.",
2594 (comp->binding_state < 1 ||
2595 comp->binding_state > FTS_LAST)
2596 ? "unknown"
2597 : binding_state_names[comp->binding_state - 1]);
2598 }
2599
2600 if (prev) {
2601 lease_dereference(&prev->next, MDL);
2602 if (comp->next) {
2603 lease_reference(&prev->next, comp->next, MDL);
2604 lease_dereference (&comp->next, MDL);
2605 }
2606 } else {
2607 lease_dereference(lq, MDL);
2608 if (comp->next) {
2609 lease_reference(lq, comp->next, MDL);
2610 lease_dereference(&comp->next, MDL);
2611 }
2612 }
2613}
2614
2615/* This routine inserts comp into lq in a sorted fashion.
2616 * The sort key is comp->sort_time, smaller values are
2617 * placed earlier in the list.
2618 */
2619void lease_insert(struct lease **lq, struct lease *comp)
2620{
2621 struct lease *prev, *lp;
2622 static struct lease **last_lq = NULL;
2623 static struct lease *last_insert_point = NULL;
2624
2625 /* This only works during server startup: during runtime, the last
2626 * lease may be dequeued in between calls. If the queue is the same
2627 * as was used previously, and the lease structure isn't (this is not
2628 * a re-queue), use that as a starting point for the insertion-sort.
2629 */
2630 if ((server_starting & SS_QFOLLOW) && (lq == last_lq) &&
2631 (comp != last_insert_point) &&
2632 (last_insert_point->sort_time <= comp->sort_time)) {
2633 prev = last_insert_point;
2634 lp = prev->next;
2635 } else {
2636 prev = NULL;
2637 lp = *lq;
2638 }
2639
2640 /* Insertion sort the lease onto the appropriate queue. */
2641 for (; lp != NULL ; lp = lp->next) {
2642 if (lp->sort_time >= comp->sort_time)
2643 break;
2644 prev = lp;
2645 }
2646
2647 if (prev) {
2648 if (prev->next) {
2649 lease_reference(&comp->next, prev->next, MDL);
2650 lease_dereference(&prev->next, MDL);
2651 }
2652 lease_reference(&prev->next, comp, MDL);
2653 } else {
2654 if (*lq) {
2655 lease_reference (&comp->next, *lq, MDL);
2656 lease_dereference(lq, MDL);
2657 }
2658 lease_reference(lq, comp, MDL);
2659 }
2660 last_insert_point = comp;
2661 last_lq = lq;
2662
2663 return;
2664}
2665#endif
2666
2667/* In addition to placing this lease upon a lease queue depending on its
2668 * state, it also keeps track of the number of FREE and BACKUP leases in
2669 * existence, and sets the sort_time on the lease.
2670 *
2671 * Sort_time is used in pool_timer() to determine when the lease will
2672 * bubble to the top of the list and be supersede_lease()'d into its next
2673 * state (possibly, if all goes well). Example, ACTIVE leases move to
2674 * EXPIRED state when the 'ends' value is reached, so that is its sort
2675 * time. Most queues are sorted by 'ends', since it is generally best
2676 * practice to re-use the oldest lease, to reduce address collision
2677 * chances.
2678 */
2679int lease_enqueue (struct lease *comp)
2680{
2682
2683 /* No queue to put it on? */
2684 if (!comp -> pool)
2685 return 0;
2686
2687 /* Figure out which queue it's going to. */
2688 switch (comp -> binding_state) {
2689 case FTS_FREE:
2690 if (comp->flags & RESERVED_LEASE) {
2691 lq = &comp->pool->reserved;
2692 } else {
2693 lq = &comp->pool->free;
2694 comp->pool->free_leases++;
2695 }
2696 comp -> sort_time = comp -> ends;
2697 break;
2698
2699 case FTS_ACTIVE:
2700 lq = &comp -> pool -> active;
2701 comp -> sort_time = comp -> ends;
2702 break;
2703
2704 case FTS_EXPIRED:
2705 case FTS_RELEASED:
2706 case FTS_RESET:
2707 lq = &comp -> pool -> expired;
2708#if defined(FAILOVER_PROTOCOL)
2709 /* In partner_down, tsfp is the time at which the lease
2710 * may be reallocated (stos+mclt). We can do that with
2711 * lease_mine_to_reallocate() anywhere between tsfp and
2712 * ends. But we prefer to wait until ends before doing it
2713 * automatically (choose the greater of the two). Note
2714 * that 'ends' is usually a historic timestamp in the
2715 * case of expired leases, is really only in the future
2716 * on released leases, and if we know a lease to be released
2717 * the peer might still know it to be active...in which case
2718 * it's possible the peer has renewed this lease, so avoid
2719 * doing that.
2720 */
2721 if (comp->pool->failover_peer &&
2722 comp->pool->failover_peer->me.state == partner_down)
2723 comp->sort_time = (comp->tsfp > comp->ends) ?
2724 comp->tsfp : comp->ends;
2725 else
2726#endif
2727 comp->sort_time = comp->ends;
2728
2729 break;
2730
2731 case FTS_ABANDONED:
2732 lq = &comp -> pool -> abandoned;
2733 comp -> sort_time = comp -> ends;
2734 break;
2735
2736 case FTS_BACKUP:
2737 if (comp->flags & RESERVED_LEASE) {
2738 lq = &comp->pool->reserved;
2739 } else {
2740 lq = &comp->pool->backup;
2741 comp->pool->backup_leases++;
2742 }
2743 comp -> sort_time = comp -> ends;
2744 break;
2745
2746 default:
2747 log_error ("Lease with bogus binding state: %d",
2748 comp -> binding_state);
2749#if defined (BINDING_STATE_DEBUG)
2750 abort ();
2751#endif
2752 return 0;
2753 }
2754
2755 LEASE_INSERTP(lq, comp);
2756
2757 return 1;
2758}
2759
2760/* For a given lease, sort it onto the right list in its pool and put it
2761 in each appropriate hash, understanding that it's already by definition
2762 in lease_ip_addr_hash. */
2763
2764isc_result_t
2765lease_instantiate(const void *key, unsigned len, void *object)
2766{
2767 struct lease *lease = object;
2768 struct class *class;
2769 /* XXX If the lease doesn't have a pool at this point, it's an
2770 XXX orphan, which we *should* keep around until it expires,
2771 XXX but which right now we just forget. */
2772 if (!lease -> pool) {
2773 lease_ip_hash_delete(lease_ip_addr_hash, lease->ip_addr.iabuf,
2774 lease->ip_addr.len, MDL);
2775 return ISC_R_SUCCESS;
2776 }
2777
2778#if defined (FAILOVER_PROTOCOL)
2779 /* If the lease is in FTS_BACKUP but there is no peer, then the
2780 * pool must have been formerly configured for failover and
2781 * is now configured as standalone. This means we need to
2782 * move the lease to FTS_FREE to make it available. */
2783 if ((lease->binding_state == FTS_BACKUP) &&
2784 (lease->pool->failover_peer == NULL)) {
2785#else
2786 /* We aren't compiled for failover, so just move to FTS_FREE */
2787 if (lease->binding_state == FTS_BACKUP) {
2788#endif
2792 }
2793
2794 /* Put the lease on the right queue. Failure to queue is probably
2795 * due to a bogus binding state. In such a case, we claim success,
2796 * so that later leases in a hash_foreach are processed, but we
2797 * return early as we really don't want hw address hash entries or
2798 * other cruft to surround such a bogus entry.
2799 */
2800 if (!lease_enqueue(lease))
2801 return ISC_R_SUCCESS;
2802
2803 /* Record the lease in the uid hash if possible. */
2804 if (lease -> uid) {
2806 }
2807
2808 /* Record it in the hardware address hash if possible. */
2809 if (lease -> hardware_addr.hlen) {
2811 }
2812
2813 /* If the lease has a billing class, set up the billing. */
2814 if (lease -> billing_class) {
2815 class = (struct class *)0;
2816 class_reference (&class, lease -> billing_class, MDL);
2817 class_dereference (&lease -> billing_class, MDL);
2818 /* If the lease is available for allocation, the billing
2819 is invalid, so we don't keep it. */
2820 if (lease -> binding_state == FTS_ACTIVE ||
2821 lease -> binding_state == FTS_EXPIRED ||
2822 lease -> binding_state == FTS_RELEASED ||
2823 lease -> binding_state == FTS_RESET)
2824 bill_class (lease, class);
2825 class_dereference (&class, MDL);
2826 }
2827 return ISC_R_SUCCESS;
2828}
2829
2830/* Run expiry events on every pool. This is called on startup so that
2831 any expiry events that occurred after the server stopped and before it
2832 was restarted can be run. At the same time, if failover support is
2833 compiled in, we compute the balance of leases for the pool. */
2834
2836{
2837 struct shared_network *s;
2838 struct pool *p;
2839 int i;
2840 struct lease *l;
2842
2843 /* Indicate that we are in the startup phase */
2844 server_starting = SS_NOSYNC | SS_QFOLLOW;
2845
2846#if defined (BINARY_LEASES)
2847 /* set up the growth factors for the binary leases.
2848 * We use 100% for free, 50% for active and backup
2849 * 20% for expired, abandoned and reserved
2850 * but no less than 100, 50, and 20.
2851 */
2852 for (s = shared_networks; s; s = s -> next) {
2853 for (p = s -> pools; p != NULL; p = p -> next) {
2854 size_t num_f = 100, num_a = 50, num_e = 20;
2855 if (p->lease_count > 100) {
2856 num_f = p->lease_count;
2857 num_a = num_f / 2;
2858 num_e = num_f / 5;
2859 }
2860 lc_init_growth(&p->free, num_f);
2861 lc_init_growth(&p->active, num_a);
2862 lc_init_growth(&p->expired, num_a);
2863 lc_init_growth(&p->abandoned, num_e);
2864 lc_init_growth(&p->backup, num_e);
2865 lc_init_growth(&p->reserved, num_e);
2866 }
2867 }
2868#endif
2869
2870 /* First, go over the hash list and actually put all the leases
2871 on the appropriate lists. */
2872 lease_ip_hash_foreach(lease_ip_addr_hash, lease_instantiate);
2873
2874 /* Loop through each pool in each shared network and call the
2875 * expiry routine on the pool. It is no longer safe to follow
2876 * the queue insertion point, as expiration of a lease can move
2877 * it between queues (and this may be the lease that function
2878 * points at).
2879 */
2880 server_starting &= ~SS_QFOLLOW;
2881 for (s = shared_networks; s; s = s -> next) {
2882 for (p = s -> pools; p; p = p -> next) {
2883 pool_timer (p);
2884
2885 p -> lease_count = 0;
2886 p -> free_leases = 0;
2887 p -> backup_leases = 0;
2888
2889 lptr [FREE_LEASES] = &p -> free;
2890 lptr [ACTIVE_LEASES] = &p -> active;
2891 lptr [EXPIRED_LEASES] = &p -> expired;
2892 lptr [ABANDONED_LEASES] = &p -> abandoned;
2893 lptr [BACKUP_LEASES] = &p -> backup;
2894 lptr [RESERVED_LEASES] = &p->reserved;
2895
2896 for (i = FREE_LEASES; i <= RESERVED_LEASES; i++) {
2897 for (l = LEASE_GET_FIRSTP(lptr[i]);
2898 l != NULL;
2899 l = LEASE_GET_NEXTP(lptr[i], l)) {
2900 p -> lease_count++;
2901 if (l -> ends <= cur_time) {
2902 if (l->binding_state == FTS_FREE) {
2903 if (i == FREE_LEASES)
2904 p->free_leases++;
2905 else if (i != RESERVED_LEASES)
2906 log_fatal("Impossible case "
2907 "at %s:%d.", MDL);
2908 } else if (l->binding_state == FTS_BACKUP) {
2909 if (i == BACKUP_LEASES)
2910 p->backup_leases++;
2911 else if (i != RESERVED_LEASES)
2912 log_fatal("Impossible case "
2913 "at %s:%d.", MDL);
2914 }
2915 }
2916#if defined (FAILOVER_PROTOCOL)
2917 if (p -> failover_peer &&
2918 l -> tstp > l -> atsfp &&
2919 !(l -> flags & ON_UPDATE_QUEUE)) {
2922 }
2923#endif
2924 }
2925 }
2926 }
2927 }
2928
2929 /* turn off startup phase */
2930 server_starting = 0;
2931}
2932
2934{
2935 struct lease *l;
2936 struct shared_network *s;
2937 struct subnet *n;
2938 struct pool *p;
2940 int i;
2941
2942 log_info ("Subnets:");
2943 for (n = subnets; n; n = n -> next_subnet) {
2944 log_debug (" Subnet %s", piaddr (n -> net));
2945 log_debug (" netmask %s",
2946 piaddr (n -> netmask));
2947 }
2948 log_info ("Shared networks:");
2949 for (s = shared_networks; s; s = s -> next) {
2950 log_info (" %s", s -> name);
2951 for (p = s -> pools; p; p = p -> next) {
2952 lptr [FREE_LEASES] = &p -> free;
2953 lptr [ACTIVE_LEASES] = &p -> active;
2954 lptr [EXPIRED_LEASES] = &p -> expired;
2955 lptr [ABANDONED_LEASES] = &p -> abandoned;
2956 lptr [BACKUP_LEASES] = &p -> backup;
2957 lptr [RESERVED_LEASES] = &p->reserved;
2958
2959 for (i = FREE_LEASES; i <= RESERVED_LEASES; i++) {
2960 for (l = LEASE_GET_FIRSTP(lptr[i]);
2961 l != NULL;
2962 l = LEASE_GET_NEXTP(lptr[i], l)) {
2963 print_lease (l);
2964 }
2965 }
2966 }
2967 }
2968}
2969
2970HASH_FUNCTIONS(lease_ip, const unsigned char *, struct lease, lease_ip_hash_t,
2971 lease_reference, lease_dereference, do_ip4_hash)
2972HASH_FUNCTIONS(lease_id, const unsigned char *, struct lease, lease_id_hash_t,
2973 lease_reference, lease_dereference, do_id_hash)
2974HASH_FUNCTIONS (host, const unsigned char *, struct host_decl, host_hash_t,
2975 host_reference, host_dereference, do_string_hash)
2976HASH_FUNCTIONS (class, const char *, struct class, class_hash_t,
2977 class_reference, class_dereference, do_string_hash)
2978
2979#if defined (DEBUG_MEMORY_LEAKAGE) && \
2980 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
2981extern struct hash_table *dns_zone_hash;
2982extern struct interface_info **interface_vector;
2983extern int interface_count;
2985extern struct hash_table *auth_key_hash;
2987struct universe **universes;
2989#if 0
2990extern int end;
2991#endif
2992
2993#if defined (COMPACT_LEASES)
2994extern struct lease *lease_hunks;
2995#endif
2996
2997void free_everything(void)
2998{
2999 struct subnet *sc = (struct subnet *)0, *sn = (struct subnet *)0;
3000 struct shared_network *nc = (struct shared_network *)0,
3001 *nn = (struct shared_network *)0;
3002 struct pool *pc = (struct pool *)0, *pn = (struct pool *)0;
3003 struct lease *lc = NULL, *ln = NULL, *ltemp = NULL;
3004 struct interface_info *ic = (struct interface_info *)0,
3005 *in = (struct interface_info *)0;
3006 struct class *cc = (struct class *)0, *cn = (struct class *)0;
3007 struct collection *lp;
3008 int i;
3009
3010 /* Get rid of all the hash tables. */
3012 host_free_hash_table (&host_hw_addr_hash, MDL);
3014 if (host_uid_hash)
3015 host_free_hash_table (&host_uid_hash, MDL);
3016 host_uid_hash = 0;
3017 if (lease_uid_hash)
3018 lease_id_free_hash_table (&lease_uid_hash, MDL);
3019 lease_uid_hash = 0;
3021 lease_ip_free_hash_table (&lease_ip_addr_hash, MDL);
3024 lease_id_free_hash_table (&lease_hw_addr_hash, MDL);
3026 if (host_name_hash)
3027 host_free_hash_table (&host_name_hash, MDL);
3028 host_name_hash = 0;
3029 if (dns_zone_hash)
3030 dns_zone_free_hash_table (&dns_zone_hash, MDL);
3031 dns_zone_hash = 0;
3032
3033 while (host_id_info != NULL) {
3034 host_id_info_t *tmp;
3036 host_free_hash_table(&host_id_info->values_hash, MDL);
3037 tmp = host_id_info->next;
3039 host_id_info = tmp;
3040 }
3041#if 0
3042 if (auth_key_hash)
3043 auth_key_free_hash_table (&auth_key_hash, MDL);
3044#endif
3045 auth_key_hash = 0;
3046
3048 MDL);
3049
3050 for (lp = collections; lp; lp = lp -> next) {
3051 if (lp -> classes) {
3052 class_reference (&cn, lp -> classes, MDL);
3053 do {
3054 if (cn) {
3055 class_reference (&cc, cn, MDL);
3056 class_dereference (&cn, MDL);
3057 }
3058 if (cc -> nic) {
3059 class_reference (&cn, cc -> nic, MDL);
3060 class_dereference (&cc -> nic, MDL);
3061 }
3062 group_dereference (&cc -> group, MDL);
3063 if (cc -> hash) {
3064 class_free_hash_table (&cc -> hash, MDL);
3065 cc -> hash = (struct hash_table *)0;
3066 }
3067 class_dereference (&cc, MDL);
3068 } while (cn);
3069 class_dereference (&lp -> classes, MDL);
3070 }
3071 }
3072
3073 if (interface_vector) {
3074 for (i = 0; i < interface_count; i++) {
3075 if (interface_vector [i])
3076 interface_dereference (&interface_vector [i], MDL);
3077 }
3079 interface_vector = 0;
3080 }
3081
3082 if (interfaces) {
3083 interface_reference (&in, interfaces, MDL);
3084 do {
3085 if (in) {
3086 interface_reference (&ic, in, MDL);
3087 interface_dereference (&in, MDL);
3088 }
3089 if (ic -> next) {
3090 interface_reference (&in, ic -> next, MDL);
3091 interface_dereference (&ic -> next, MDL);
3092 }
3094 if (ic -> shared_network) {
3095 if (ic -> shared_network -> interface)
3096 interface_dereference
3097 (&ic -> shared_network -> interface, MDL);
3098 shared_network_dereference (&ic -> shared_network, MDL);
3099 }
3100 interface_dereference (&ic, MDL);
3101 } while (in);
3102 interface_dereference (&interfaces, MDL);
3103 }
3104
3105 /* Subnets are complicated because of the extra links. */
3106 if (subnets) {
3107 subnet_reference (&sn, subnets, MDL);
3108 do {
3109 if (sn) {
3110 subnet_reference (&sc, sn, MDL);
3111 subnet_dereference (&sn, MDL);
3112 }
3113 if (sc -> next_subnet) {
3114 subnet_reference (&sn, sc -> next_subnet, MDL);
3115 subnet_dereference (&sc -> next_subnet, MDL);
3116 }
3117 if (sc -> next_sibling)
3118 subnet_dereference (&sc -> next_sibling, MDL);
3119 if (sc -> shared_network)
3120 shared_network_dereference (&sc -> shared_network, MDL);
3121 group_dereference (&sc -> group, MDL);
3122 if (sc -> interface)
3123 interface_dereference (&sc -> interface, MDL);
3124 subnet_dereference (&sc, MDL);
3125 } while (sn);
3126 subnet_dereference (&subnets, MDL);
3127 }
3128
3129 /* So are shared networks. */
3130 /* XXX: this doesn't work presently, but i'm ok just filtering
3131 * it out of the noise (you get a bigger spike on the real leaks).
3132 * It would be good to fix this, but it is not a "real bug," so not
3133 * today. This hack is incomplete, it doesn't trim out sub-values.
3134 */
3135 if (shared_networks) {
3136 shared_network_dereference (&shared_networks, MDL);
3137 /* This is the old method (tries to free memory twice, broken) */
3138 } else if (0) {
3139 shared_network_reference (&nn, shared_networks, MDL);
3140 do {
3141 if (nn) {
3142 shared_network_reference (&nc, nn, MDL);
3143 shared_network_dereference (&nn, MDL);
3144 }
3145 if (nc -> next) {
3146 shared_network_reference (&nn, nc -> next, MDL);
3147 shared_network_dereference (&nc -> next, MDL);
3148 }
3149
3150 /* As are pools. */
3151 if (nc -> pools) {
3152 pool_reference (&pn, nc -> pools, MDL);
3153 do {
3155
3156 if (pn) {
3157 pool_reference (&pc, pn, MDL);
3158 pool_dereference (&pn, MDL);
3159 }
3160 if (pc -> next) {
3161 pool_reference (&pn, pc -> next, MDL);
3162 pool_dereference (&pc -> next, MDL);
3163 }
3164
3165 lptr [FREE_LEASES] = &pc -> free;
3166 lptr [ACTIVE_LEASES] = &pc -> active;
3167 lptr [EXPIRED_LEASES] = &pc -> expired;
3168 lptr [ABANDONED_LEASES] = &pc -> abandoned;
3169 lptr [BACKUP_LEASES] = &pc -> backup;
3170 lptr [RESERVED_LEASES] = &pc->reserved;
3171
3172 /* As (sigh) are leases. */
3173 for (i = FREE_LEASES ; i <= RESERVED_LEASES ; i++) {
3174 if (LEASE_NOT_EMPTYP(lptr[i])) {
3175 lease_reference(&ln, LEASE_GET_FIRSTP(lptr[i]), MDL);
3176 do {
3177 /* save a pointer to the current lease */
3178 lease_reference (&lc, ln, MDL);
3179 lease_dereference (&ln, MDL);
3180
3181 /* get the next lease if there is one */
3182 ltemp = LEASE_GET_NEXTP(lptr[i], lc);
3183 if (ltemp != NULL) {
3184 lease_reference(&ln, ltemp, MDL);
3185 }
3186
3187 /* remove the current lease from the queue */
3188 LEASE_REMOVEP(lptr[i], lc);
3189
3190 if (lc -> billing_class)
3191 class_dereference (&lc -> billing_class,
3192 MDL);
3193 if (lc -> state)
3194 free_lease_state (lc -> state, MDL);
3195 lc -> state = (struct lease_state *)0;
3196 if (lc -> n_hw)
3197 lease_dereference (&lc -> n_hw, MDL);
3198 if (lc -> n_uid)
3199 lease_dereference (&lc -> n_uid, MDL);
3200 lease_dereference (&lc, MDL);
3201 } while (ln);
3202 }
3203 }
3204 if (pc -> group)
3205 group_dereference (&pc -> group, MDL);
3206 if (pc -> shared_network)
3207 shared_network_dereference (&pc -> shared_network,
3208 MDL);
3209 pool_dereference (&pc, MDL);
3210 } while (pn);
3211 pool_dereference (&nc -> pools, MDL);
3212 }
3213 /* Because of a circular reference, we need to nuke this
3214 manually. */
3215 group_dereference (&nc -> group, MDL);
3216 shared_network_dereference (&nc, MDL);
3217 } while (nn);
3218 shared_network_dereference (&shared_networks, MDL);
3219 }
3220
3223#if defined(DELAYED_ACK)
3224 relinquish_ackqueue();
3225#endif
3226 trace_free_all ();
3229
3236
3238
3239 universe_free_hash_table (&universe_hash, MDL);
3240 for (i = 0; i < universe_count; i++) {
3241#if 0
3242 union {
3243 const char *c;
3244 char *s;
3245 } foo;
3246#endif
3247 if (universes [i]) {
3248 if (universes[i]->name_hash)
3249 option_name_free_hash_table(
3250 &universes[i]->name_hash,
3251 MDL);
3252 if (universes[i]->code_hash)
3253 option_code_free_hash_table(
3254 &universes[i]->code_hash,
3255 MDL);
3256#if 0
3257 if (universes [i] -> name > (char *)&end) {
3258 foo.c = universes [i] -> name;
3259 dfree (foo.s, MDL);
3260 }
3261 if (universes [i] > (struct universe *)&end)
3262 dfree (universes [i], MDL);
3263#endif
3264 }
3265 }
3266 dfree (universes, MDL);
3267
3268 relinquish_free_lease_states ();
3269 relinquish_free_pairs ();
3270 relinquish_free_expressions ();
3271 relinquish_free_binding_values ();
3272 relinquish_free_option_caches ();
3273 relinquish_free_packets ();
3274#if defined(COMPACT_LEASES)
3276#endif
3279}
3280#endif /* DEBUG_MEMORY_LEAKAGE_ON_EXIT */
int group_dereference(struct group **ptr, const char *file, int line)
Definition alloc.c:205
int buffer_allocate(struct buffer **ptr, unsigned len, const char *file, int line)
Definition alloc.c:679
void data_string_forget(struct data_string *data, const char *file, int line)
Definition alloc.c:1339
int option_chain_head_reference(struct option_chain_head **ptr, struct option_chain_head *bp, const char *file, int line)
Definition alloc.c:67
int executable_statement_reference(struct executable_statement **ptr, struct executable_statement *bp, const char *file, int line)
Definition alloc.c:972
int binding_scope_reference(struct binding_scope **ptr, struct binding_scope *bp, const char *file, int line)
Definition alloc.c:1227
int option_chain_head_dereference(struct option_chain_head **ptr, const char *file, int line)
Definition alloc.c:95
void add_timeout(struct timeval *when, void *where, void *what, tvref_t ref, tvunref_t unref)
Definition dispatch.c:206
struct option_cache * lookup_option(struct universe *universe, struct option_state *options, unsigned code)
Definition options.c:2503
struct collection * collections
Definition parse.c:34
int parse_warn(struct parse *cfile, const char *fmt,...)
Definition parse.c:5643
void print_lease(struct lease *lease)
Definition print.c:194
void print_hex_or_string(unsigned len, const u_int8_t *data, unsigned limit, char *buf)
Definition print.c:419
#define FAILOVER_PROTOCOL
Definition config.h:33
isc_boolean_t
Definition data.h:150
#define ISC_TRUE
Definition data.h:153
#define ISC_FALSE
Definition data.h:152
int write_host(struct host_decl *host)
Definition dhclient.c:2245
int commit_leases()
Definition dhclient.c:2234
isc_result_t find_class(struct class **c, const char *s, const char *file, int line)
Definition dhclient.c:1542
void unbill_class(struct lease *lease)
Definition dhclient.c:1562
int write_lease(struct lease *lease)
Definition dhclient.c:2239
#define MAX_V6RELAY_HOPS
Definition dhcp6.h:246
#define DHO_DHCP_CLIENT_IDENTIFIER
Definition dhcp.h:150
#define DHO_PXE_CLIENT_ID
Definition dhcp.h:159
#define HTYPE_INFINIBAND
Definition dhcp.h:78
void cancel_all_timeouts(void)
host_hash_t * host_hw_addr_hash
Definition mdb.c:34
#define LEASE_STRUCT_PTR
Definition dhcpd.h:257
struct lease * new_leases(unsigned, const char *, int)
void(* tvunref_t)(void *, const char *, int)
Definition dhcpd.h:1454
#define INTERFACE_REQUESTED
Definition dhcpd.h:1424
int bill_class(struct lease *, struct class *)
Definition class.c:296
struct hash_table lease_id_hash_t
Definition dhcpd.h:81
#define FTS_FREE
Definition dhcpd.h:537
#define HOST_DECL_DYNAMIC
Definition dhcpd.h:993
void relinquish_timeouts(void)
#define EPHEMERAL_FLAGS
Definition dhcpd.h:605
int write_group(struct group_object *)
Definition db.c:449
#define GROUP_OBJECT_DELETED
Definition dhcpd.h:956
#define HOST_DECL_DELETED
Definition dhcpd.h:992
#define MIN_TIME
Definition dhcpd.h:1632
lease_id_hash_t * lease_hw_addr_hash
Definition mdb.c:39
time_t TIME
Definition dhcpd.h:85
omapi_object_type_t * dhcp_type_lease
Definition omapi.c:46
struct shared_network * shared_networks
Definition mdb.c:33
void free_lease_state(struct lease_state *, const char *, int)
Definition salloc.c:198
#define LEASE_INSERTP(LQ, LEASE)
Definition dhcpd.h:262
dhcp_control_object_t * dhcp_control_object
#define ON_UPDATE_QUEUE
Definition dhcpd.h:596
void(* tvref_t)(void *, void *, const char *, int)
Definition dhcpd.h:1453
u_int32_t abandon_lease_time
Definition dhcpd.c:99
struct subnet * subnets
Definition mdb.c:32
#define MAX_TIME
Definition dhcpd.h:1631
int find_lease_by_uid(struct lease **, const unsigned char *, unsigned, const char *, int)
Definition mdb.c:2059
#define HOST_DECL_STATIC
Definition dhcpd.h:994
struct ipv6_pool ** pools
lease_id_hash_t * lease_uid_hash
Definition mdb.c:37
int lease_copy(struct lease **, struct lease *, const char *, int)
Definition mdb.c:1681
#define PERSISTENT_FLAGS
Definition dhcpd.h:603
#define cur_time
Definition dhcpd.h:2126
@ shutdown_drop_omapi_connections
Definition dhcpd.h:272
@ shutdown_listeners
Definition dhcpd.h:270
@ shutdown_dhcp
Definition dhcpd.h:273
void dhcp_failover_pool_check(struct pool *)
#define STATIC_LEASE
Definition dhcpd.h:592
#define FTS_BACKUP
Definition dhcpd.h:543
int find_grouped_subnet(struct subnet **, struct shared_network *, struct iaddr, const char *, int)
Definition mdb.c:953
isc_result_t lease_instantiate(const void *, unsigned, void *)
Definition mdb.c:2765
void pool_timer(void *)
Definition mdb.c:1914
host_hash_t * host_name_hash
Definition mdb.c:36
int dhcp_failover_queue_update(struct lease *, int)
int find_lease_by_hw_addr(struct lease **, const unsigned char *, unsigned, const char *, int)
Definition mdb.c:2067
#define HOST_HASH_SIZE
Definition dhcpd.h:186
#define LEASE_REMOVEP(LQ, LEASE)
Definition dhcpd.h:263
struct hash_table lease_ip_hash_t
Definition dhcpd.h:80
host_hash_t * host_uid_hash
Definition mdb.c:35
void lc_init_growth(struct leasechain *lc, size_t growth)
int dhcp_failover_write_all_states(void)
enum dhcp_shutdown_state shutdown_state
Definition dhcpd.c:1638
struct hash_table host_hash_t
Definition dhcpd.h:82
struct executable_statement * default_classification_rules
Definition class.c:31
#define FTS_LAST
Definition dhcpd.h:547
#define GROUP_OBJECT_STATIC
Definition dhcpd.h:958
struct universe dhcp_universe
isc_result_t unlink_class(struct class **class)
Definition class.c:210
int subnet_inner_than(const struct subnet *, const struct subnet *, int)
Definition mdb.c:976
#define GROUP_OBJECT_DYNAMIC
Definition dhcpd.h:957
int write_leases6(void)
#define FTS_ACTIVE
Definition dhcpd.h:538
const char int line
Definition dhcpd.h:3802
int find_lease_by_ip_addr(struct lease **, struct iaddr, const char *, int)
Definition mdb.c:2052
#define LEASE_NOT_EMPTYP(LQ)
Definition dhcpd.h:265
int lease_enqueue(struct lease *)
Definition mdb.c:2679
#define FTS_RELEASED
Definition dhcpd.h:540
struct hash_table class_hash_t
Definition dhcpd.h:83
isc_result_t ddns_removals(struct lease *, struct iasubopt *, struct dhcp_ddns_cb *, isc_boolean_t)
#define CLASS_DECL_DELETED
Definition dhcpd.h:1134
#define FTS_RESET
Definition dhcpd.h:542
isc_result_t dhcp_io_shutdown(omapi_object_t *, void *)
Definition dhcpd.c:1640
#define RESERVED_LEASE
Definition dhcpd.h:594
const char * binding_state_names[]
Definition stables.c:161
#define FTS_ABANDONED
Definition dhcpd.h:541
#define LEASE_GET_FIRSTP(LQ)
Definition dhcpd.h:259
isc_result_t write_named_billing_class(const void *, unsigned, void *)
Definition db.c:879
int numclasseswritten
Definition mdb.c:68
const char * file
Definition dhcpd.h:3802
lease_ip_hash_t * lease_ip_addr_hash
Definition mdb.c:38
omapi_object_type_t * dhcp_type_host
Definition omapi.c:50
#define print_hex_1(len, data, limit)
Definition dhcpd.h:2638
#define LEASE_HASH_SIZE
Definition dhcpd.h:196
#define LEASE_GET_NEXTP(LQ, LEASE)
Definition dhcpd.h:261
void relinquish_lease_hunks(void)
#define FTS_EXPIRED
Definition dhcpd.h:539
int local_family
Definition discover.c:59
struct interface_info * interfaces
Definition discover.c:42
struct interface_info ** interface_vector
Definition discover.c:89
int interface_count
Definition discover.c:90
dns_zone_hash_t * dns_zone_hash
Definition dns.c:136
int execute_statements(struct binding_value **result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *out_options, struct binding_scope **scope, struct executable_statement *statements, struct on_star *on_star)
Definition execute.c:35
int executable_statement_foreach(struct executable_statement *stmt, int(*callback)(struct executable_statement *, void *, int), void *vp, int condp)
Definition execute.c:1120
int executable_statement_dereference(struct executable_statement **ptr, const char *file, int line)
Definition execute.c:630
const char * binding_state_print(enum failover_state state)
Definition failover.c:6505
@ partner_down
Definition failover.h:293
@ normal
Definition failover.h:291
@ not_cooperating
Definition failover.h:318
@ cooperating
Definition failover.h:317
@ not_responding
Definition failover.h:320
int hash_foreach(struct hash_table *, hash_foreach_func)
Definition hash.c:511
void relinquish_hash_bucket_hunks(void)
unsigned do_id_hash(const void *, unsigned, unsigned)
Definition hash.c:290
#define HASH_FUNCTIONS(name, bufarg, type, hashtype, ref, deref, hasher)
Definition hash.h:89
unsigned do_string_hash(const void *, unsigned, unsigned)
Definition hash.c:266
unsigned do_ip4_hash(const void *, unsigned, unsigned)
Definition hash.c:332
u_int32_t host_addr(struct iaddr addr, struct iaddr mask)
Definition inet.c:138
struct iaddr ip_addr(struct iaddr subnet, struct iaddr mask, u_int32_t host_address)
Definition inet.c:63
const char * piaddr(const struct iaddr addr)
Definition inet.c:579
int addr_eq(struct iaddr addr1, struct iaddr addr2)
Definition inet.c:166
struct iaddr subnet_number(struct iaddr addr, struct iaddr mask)
Definition inet.c:34
#define ISC_R_SUCCESS
@ supersede_option_statement
Definition keama.h:170
#define EXPIRED_LEASES
int lease_enqueue(struct lease *comp)
Definition mdb.c:2679
int write_leases4(void)
Definition mdb.c:2393
int lease_copy(struct lease **lp, struct lease *lease, const char *file, int line)
Definition mdb.c:1681
#define FREE_LEASES
#define SS_QFOLLOW
Definition mdb.c:120
void hw_hash_add(struct lease *lease)
Definition mdb.c:2251
#define ABANDONED_LEASES
int find_grouped_subnet(struct subnet **sp, struct shared_network *share, struct iaddr addr, const char *file, int line)
Definition mdb.c:953
void lease_insert(struct lease **lq, struct lease *comp)
Definition mdb.c:2619
#define SS_NOSYNC
Definition mdb.c:119
void hw_hash_delete(struct lease *lease)
Definition mdb.c:2331
void enter_subnet(struct subnet *subnet)
Definition mdb.c:1008
isc_result_t lease_instantiate(const void *key, unsigned len, void *object)
Definition mdb.c:2765
struct host_id_info host_id_info_t
void enter_lease(struct lease *lease)
Definition mdb.c:1112
int supersede_lease(struct lease *comp, struct lease *lease, int commit, int propogate, int pimmediate, int from_pool)
Definition mdb.c:1155
void uid_hash_add(struct lease *lease)
Definition mdb.c:2134
int find_hosts_by_uid(struct host_decl **hp, const unsigned char *data, unsigned len, const char *file, int line)
Definition mdb.c:652
void new_address_range(struct parse *cfile, struct iaddr low, struct iaddr high, struct subnet *subnet, struct pool *pool, struct lease **lpchain)
Definition mdb.c:782
isc_result_t enter_class(struct class *cd, int dynamicp, int commit)
Definition mdb.c:72
void change_host_uid(struct host_decl *host, const char *uid, int len)
Definition mdb.c:184
#define BACKUP_LEASES
void lease_remove_all(struct lease **lq)
Definition mdb.c:2542
int write_leases()
Definition mdb.c:2434
void enter_shared_network(struct shared_network *share)
Definition mdb.c:1055
int find_host_for_network(struct subnet **sp, struct host_decl **host, struct iaddr *addr, struct shared_network *share)
Definition mdb.c:736
isc_result_t enter_host(struct host_decl *hd, int dynamicp, int commit)
Definition mdb.c:221
void dump_subnets()
Definition mdb.c:2933
void pool_timer(void *vpool)
Definition mdb.c:1914
int find_hosts_by_option(struct host_decl **hp, struct packet *packet, struct option_state *opt_state, const char *file, int line)
Definition mdb.c:660
int find_lease_by_uid(struct lease **lp, const unsigned char *uid, unsigned len, const char *file, int line)
Definition mdb.c:2059
isc_result_t delete_class(struct class *cp, int commit)
Definition mdb.c:458
int find_subnet(struct subnet **sp, struct iaddr addr, const char *file, int line)
Definition mdb.c:933
int find_lease_by_hw_addr(struct lease **lp, const unsigned char *hwaddr, unsigned hwlen, const char *file, int line)
Definition mdb.c:2067
int find_lease_by_ip_addr(struct lease **lp, struct iaddr addr, const char *file, int line)
Definition mdb.c:2052
int find_hosts_by_haddr(struct host_decl **hp, int htype, const unsigned char *haddr, unsigned hlen, const char *file, int line)
Definition mdb.c:632
void lease_remove(struct lease **lq, struct lease *comp)
Definition mdb.c:2581
void expire_all_pools()
Definition mdb.c:2835
#define ACTIVE_LEASES
void new_shared_network_interface(struct parse *cfile, struct shared_network *share, const char *name)
Definition mdb.c:1066
void uid_hash_delete(struct lease *lease)
Definition mdb.c:2201
#define RESERVED_LEASES
isc_result_t delete_host(struct host_decl *hd, int commit)
Definition mdb.c:490
int subnet_inner_than(const struct subnet *subnet, const struct subnet *scan, int warnp)
Definition mdb.c:976
void release_lease(struct lease *lease, struct packet *packet)
Definition mdb.c:1755
void make_binding_state_transition(struct lease *lease)
Definition mdb.c:1503
void abandon_lease(struct lease *lease, const char *message)
Definition mdb.c:1830
struct group * root_group
Definition memory.c:31
group_hash_t * group_name_hash
Definition memory.c:32
#define MDL
Definition omapip.h:567
struct __omapi_object_type_t omapi_object_type_t
isc_result_t omapi_object_dereference(omapi_object_t **, const char *, int)
Definition alloc.c:593
isc_result_t omapi_unregister_io_object(omapi_object_t *)
Definition dispatch.c:355
struct __omapi_object omapi_object_t
Definition omapip.h:39
isc_result_t omapi_io_state_foreach(isc_result_t(*func)(omapi_object_t *, void *), void *p)
calls a given function on every object
Definition dispatch.c:967
void omapi_type_relinquish(void)
void * dmalloc(size_t, const char *, int)
Definition alloc.c:57
void dfree(void *, const char *, int)
Definition alloc.c:145
isc_result_t omapi_object_initialize(omapi_object_t *, omapi_object_type_t *, size_t, size_t, const char *, int)
Definition alloc.c:559
int log_error(const char *,...) __attribute__((__format__(__printf__
int int int log_debug(const char *,...) __attribute__((__format__(__printf__
void log_fatal(const char *,...) __attribute__((__format__(__printf__
int int log_info(const char *,...) __attribute__((__format__(__printf__
#define DHCP_R_INVALIDARG
Definition result.h:49
unsigned char data[1]
Definition tree.h:62
int flags
Definition dhcpd.h:1139
struct class * nic
Definition dhcpd.h:1104
struct class * superclass
Definition dhcpd.h:1105
class_hash_t * hash
Definition dhcpd.h:1118
struct data_string hash_string
Definition dhcpd.h:1119
char * name
Definition dhcpd.h:1106
struct class * classes
Definition dhcpd.h:1092
struct collection * next
Definition dhcpd.h:1089
struct buffer * buffer
Definition tree.h:77
const unsigned char * data
Definition tree.h:78
unsigned len
Definition tree.h:79
enum executable_statement::statement_op op
union executable_statement::@336221350347175166011011356261373334214214051201 data
struct option_cache * option
Definition statement.h:65
int flags
Definition dhcpd.h:955
Definition dhcpd.h:962
struct executable_statement * statements
Definition dhcpd.h:970
u_int8_t hlen
Definition dhcpd.h:492
u_int8_t hbuf[HARDWARE_ADDR_LEN+1]
Definition dhcpd.h:493
char * name
Definition dhcpd.h:978
struct option_cache * fixed_addr
Definition dhcpd.h:986
struct data_string client_identifier
Definition dhcpd.h:980
int relays
Definition dhcpd.h:998
struct data_string host_id
Definition dhcpd.h:982
struct option * host_id_option
Definition dhcpd.h:981
int flags
Definition dhcpd.h:991
struct group * group
Definition dhcpd.h:988
struct host_decl * n_ipaddr
Definition dhcpd.h:976
struct hardware interface
Definition dhcpd.h:979
struct host_id_info * next
Definition mdb.c:63
struct option * option
Definition mdb.c:60
host_hash_t * values_hash
Definition mdb.c:61
int relays
Definition mdb.c:62
Definition inet.h:31
unsigned char iabuf[16]
Definition inet.h:33
unsigned len
Definition inet.h:32
char name[IFNAMSIZ]
Definition dhcpd.h:1408
struct interface_info * next
Definition dhcpd.h:1383
u_int32_t flags
Definition dhcpd.h:1423
Definition ip.h:47
Definition dhcpd.h:560
TIME atsfp
Definition dhcpd.h:639
TIME ends
Definition dhcpd.h:570
binding_state_t next_binding_state
Definition dhcpd.h:624
struct pool * pool
Definition dhcpd.h:578
u_int8_t flags
Definition dhcpd.h:591
struct lease * n_uid
Definition dhcpd.h:567
TIME starts
Definition dhcpd.h:570
struct dhcp_ddns_cb * ddns_cb
Definition dhcpd.h:650
struct binding_scope * scope
Definition dhcpd.h:575
char * client_hostname
Definition dhcpd.h:574
struct iaddr ip_addr
Definition dhcpd.h:569
struct hardware hardware_addr
Definition dhcpd.h:589
TIME sort_time
Definition dhcpd.h:570
binding_state_t rewind_binding_state
Definition dhcpd.h:626
unsigned char * uid
Definition dhcpd.h:585
TIME tstp
Definition dhcpd.h:637
binding_state_t desired_binding_state
Definition dhcpd.h:625
struct on_star on_star
Definition dhcpd.h:583
TIME tsfp
Definition dhcpd.h:638
struct leasechain * lc
Definition dhcpd.h:565
struct lease * next
Definition dhcpd.h:562
struct subnet * subnet
Definition dhcpd.h:577
struct lease * prev
Definition dhcpd.h:564
unsigned char uid_buf[7]
Definition dhcpd.h:588
struct class * billing_class
Definition dhcpd.h:579
struct host_decl * host
Definition dhcpd.h:576
unsigned short uid_max
Definition dhcpd.h:587
binding_state_t binding_state
Definition dhcpd.h:623
struct lease * n_hw
Definition dhcpd.h:567
unsigned short uid_len
Definition dhcpd.h:586
TIME cltt
Definition dhcpd.h:640
struct executable_statement * on_commit
Definition dhcpd.h:555
struct executable_statement * on_expiry
Definition dhcpd.h:554
struct executable_statement * on_release
Definition dhcpd.h:556
Definition tree.h:345
unsigned code
Definition tree.h:349
struct universe * universe
Definition tree.h:348
struct packet * dhcpv6_container_packet
Definition dhcpd.h:422
struct option_state * options
Definition dhcpd.h:449
Definition dhcpd.h:288
Definition dhcpd.h:1029
LEASE_STRUCT expired
Definition dhcpd.h:1037
TIME next_event_time
Definition dhcpd.h:1042
int free_leases
Definition dhcpd.h:1044
int backup_leases
Definition dhcpd.h:1045
dhcp_failover_state_t * failover_peer
Definition dhcpd.h:1051
struct pool * next
Definition dhcpd.h:1031
int lease_count
Definition dhcpd.h:1043
LEASE_STRUCT free
Definition dhcpd.h:1038
LEASE_STRUCT abandoned
Definition dhcpd.h:1040
LEASE_STRUCT reserved
Definition dhcpd.h:1041
LEASE_STRUCT active
Definition dhcpd.h:1036
LEASE_STRUCT backup
Definition dhcpd.h:1039
struct shared_network * next
Definition dhcpd.h:1059
char * name
Definition dhcpd.h:1060
struct pool * pools
Definition dhcpd.h:1067
struct subnet * next_subnet
Definition dhcpd.h:1077
struct iaddr netmask
Definition dhcpd.h:1083
struct element * share
Definition confparse.c:58
struct iaddr net
Definition dhcpd.h:1082
struct string * addr
Definition confparse.c:59
struct subnet * next_sibling
Definition dhcpd.h:1078
unsigned end
Definition tree.h:335
int universe_count
Definition tables.c:976
int option_reference(struct option **dest, struct option *src, const char *file, int line)
Definition tables.c:992
int option_dereference(struct option **dest, const char *file, int line)
Definition tables.c:1014
universe_hash_t * universe_hash
Definition tables.c:974
int universe_max
Definition tables.c:976
struct universe ** universes
Definition tables.c:975
void trace_free_all(void)
int binding_scope_dereference(struct binding_scope **ptr, const char *file, int line)
Definition tree.c:3786
int evaluate_option_cache(struct data_string *result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct option_cache *oc, const char *file, int line)
Definition tree.c:2699
struct binding_scope * global_scope
Definition tree.c:38
Definition data.h:205