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