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