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