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