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