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