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