ISC DHCP  4.3.2
A reference DHCPv4 and DHCPv6 implementation
confpars.c
Go to the documentation of this file.
1 /* confpars.c
2 
3  Parser for dhcpd config file... */
4 
5 /*
6  * Copyright (c) 2004-2015 by Internet Systems Consortium, Inc. ("ISC")
7  * Copyright (c) 1995-2003 by Internet Software Consortium
8  *
9  * Permission to use, copy, modify, and distribute this software for any
10  * purpose with or without fee is hereby granted, provided that the above
11  * copyright notice and this permission notice appear in all copies.
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  * 950 Charter Street
23  * Redwood City, CA 94063
24  * <info@isc.org>
25  * https://www.isc.org/
26  *
27  */
28 
31 #include "dhcpd.h"
32 
33 static unsigned char global_host_once = 1;
34 
35 static int parse_binding_value(struct parse *cfile,
36  struct binding_value *value);
37 
38 #if defined (TRACING)
39 trace_type_t *trace_readconf_type;
40 trace_type_t *trace_readleases_type;
41 
42 void parse_trace_setup ()
43 {
44  trace_readconf_type = trace_type_register ("readconf", (void *)0,
47  trace_readleases_type = trace_type_register ("readleases", (void *)0,
50 }
51 #endif
52 
53 /* conf-file :== parameters declarations END_OF_FILE
54  parameters :== <nil> | parameter | parameters parameter
55  declarations :== <nil> | declaration | declarations declaration */
56 
57 isc_result_t readconf ()
58 {
59  isc_result_t res;
60 
62 #if defined(LDAP_CONFIGURATION)
63  if (res != ISC_R_SUCCESS)
64  return (res);
65 
66  return ldap_read_config ();
67 #else
68  return (res);
69 #endif
70 }
71 
72 isc_result_t read_conf_file (const char *filename, struct group *group,
73  int group_type, int leasep)
74 {
75  int file;
76  struct parse *cfile;
77  isc_result_t status;
78 #if defined (TRACING)
79  char *fbuf, *dbuf;
80  off_t flen;
81  int result;
82  unsigned tflen, ulen;
83  trace_type_t *ttype;
84 
85  if (leasep)
86  ttype = trace_readleases_type;
87  else
88  ttype = trace_readconf_type;
89 
90  /* If we're in playback, we need to snarf the contents of the
91  named file out of the playback file rather than trying to
92  open and read it. */
93  if (trace_playback ()) {
94  dbuf = (char *)0;
95  tflen = 0;
96  status = trace_get_file (ttype, filename, &tflen, &dbuf);
97  if (status != ISC_R_SUCCESS)
98  return status;
99  ulen = tflen;
100 
101  /* What we get back is filename\0contents, where contents is
102  terminated just by the length. So we figure out the length
103  of the filename, and subtract that and the NUL from the
104  total length to get the length of the contents of the file.
105  We make fbuf a pointer to the contents of the file, and
106  leave dbuf as it is so we can free it later. */
107  tflen = strlen (dbuf);
108  ulen = ulen - tflen - 1;
109  fbuf = dbuf + tflen + 1;
110  goto memfile;
111  }
112 #endif
113 
114  if ((file = open (filename, O_RDONLY | O_CLOEXEC)) < 0) {
115  if (leasep) {
116  log_error ("Can't open lease database %s: %m --",
117  path_dhcpd_db);
118  log_error (" check for failed database %s!",
119  "rewrite attempt");
120  log_error ("Please read the dhcpd.leases manual%s",
121  " page if you");
122  log_fatal ("don't know what to do about this.");
123  } else {
124  log_fatal ("Can't open %s: %m", filename);
125  }
126  }
127 
128  cfile = (struct parse *)0;
129 #if defined (TRACING)
130  flen = lseek (file, (off_t)0, SEEK_END);
131  if (flen < 0) {
132  boom:
133  log_fatal ("Can't lseek on %s: %m", filename);
134  }
135  if (lseek (file, (off_t)0, SEEK_SET) < 0)
136  goto boom;
137  /* Can't handle files greater than 2^31-1. */
138  if (flen > 0x7FFFFFFFUL)
139  log_fatal ("%s: file is too long to buffer.", filename);
140  ulen = flen;
141 
142  /* Allocate a buffer that will be what's written to the tracefile,
143  and also will be what we parse from. */
144  tflen = strlen (filename);
145  dbuf = dmalloc (ulen + tflen + 1, MDL);
146  if (!dbuf)
147  log_fatal ("No memory for %s (%d bytes)",
148  filename, ulen);
149 
150  /* Copy the name into the beginning, nul-terminated. */
151  strcpy (dbuf, filename);
152 
153  /* Load the file in after the NUL. */
154  fbuf = dbuf + tflen + 1;
155  result = read (file, fbuf, ulen);
156  if (result < 0)
157  log_fatal ("Can't read in %s: %m", filename);
158  if (result != ulen)
159  log_fatal ("%s: short read of %d bytes instead of %d.",
160  filename, ulen, result);
161  close (file);
162  memfile:
163  /* If we're recording, write out the filename and file contents. */
164  if (trace_record ())
165  trace_write_packet (ttype, ulen + tflen + 1, dbuf, MDL);
166  status = new_parse(&cfile, -1, fbuf, ulen, filename, 0); /* XXX */
167 #else
168  status = new_parse(&cfile, file, NULL, 0, filename, 0);
169 #endif
170  if (status != ISC_R_SUCCESS || cfile == NULL)
171  return status;
172 
173  if (leasep)
174  status = lease_file_subparse (cfile);
175  else
176  status = conf_file_subparse (cfile, group, group_type);
177  end_parse (&cfile);
178 #if defined (TRACING)
179  dfree (dbuf, MDL);
180 #endif
181  return status;
182 }
183 
184 #if defined (TRACING)
185 void trace_conf_input (trace_type_t *ttype, unsigned len, char *data)
186 {
187  char *fbuf;
188  unsigned flen;
189  unsigned tflen;
190  struct parse *cfile = (struct parse *)0;
191  static int postconf_initialized;
192  static int leaseconf_initialized;
193  isc_result_t status;
194 
195  /* Do what's done above, except that we don't have to read in the
196  data, because it's already been read for us. */
197  tflen = strlen (data);
198  flen = len - tflen - 1;
199  fbuf = data + tflen + 1;
200 
201  /* If we're recording, write out the filename and file contents. */
202  if (trace_record ())
203  trace_write_packet (ttype, len, data, MDL);
204 
205  status = new_parse(&cfile, -1, fbuf, flen, data, 0);
206  if (status == ISC_R_SUCCESS || cfile != NULL) {
207  if (ttype == trace_readleases_type)
208  lease_file_subparse (cfile);
209  else
211  end_parse (&cfile);
212  }
213 
214  /* Postconfiguration needs to be done after the config file
215  has been loaded. */
216  if (!postconf_initialized && ttype == trace_readconf_type) {
218  postconf_initialized = 1;
219  }
220 
221  if (!leaseconf_initialized && ttype == trace_readleases_type) {
222 #if defined (PARANOIA)
223  db_startup (0, 0, 0);
224 #else
225  db_startup (0);
226 #endif /* PARANOIA */
227  leaseconf_initialized = 1;
228  postdb_startup ();
229  }
230 }
231 
232 void trace_conf_stop (trace_type_t *ttype) { }
233 #endif
234 
235 /* conf-file :== parameters declarations END_OF_FILE
236  parameters :== <nil> | parameter | parameters parameter
237  declarations :== <nil> | declaration | declarations declaration */
238 
239 isc_result_t conf_file_subparse (struct parse *cfile, struct group *group,
240  int group_type)
241 {
242  const char *val;
243  enum dhcp_token token;
244  int declaration = 0;
245  int status;
246 
247  do {
248  token = peek_token (&val, (unsigned *)0, cfile);
249  if (token == END_OF_FILE)
250  break;
251  declaration = parse_statement (cfile, group, group_type,
252  (struct host_decl *)0,
253  declaration);
254  } while (1);
255  skip_token(&val, (unsigned *)0, cfile);
256 
257  status = cfile->warnings_occurred ? DHCP_R_BADPARSE : ISC_R_SUCCESS;
258  return status;
259 }
260 
261 /* lease-file :== lease-declarations END_OF_FILE
262  lease-statements :== <nil>
263  | lease-declaration
264  | lease-declarations lease-declaration */
265 
266 isc_result_t lease_file_subparse (struct parse *cfile)
267 {
268  const char *val;
269  enum dhcp_token token;
270  isc_result_t status;
271 
272  do {
273  token = next_token (&val, (unsigned *)0, cfile);
274  if (token == END_OF_FILE)
275  break;
276  if (token == LEASE) {
277  struct lease *lease = (struct lease *)0;
278  if (parse_lease_declaration (&lease, cfile)) {
279  enter_lease (lease);
280  lease_dereference (&lease, MDL);
281  } else
282  parse_warn (cfile,
283  "possibly corrupt lease file");
284  } else if (token == IA_NA) {
286  } else if (token == IA_TA) {
288  } else if (token == IA_PD) {
290  } else if (token == CLASS) {
293  } else if (token == SUBCLASS) {
296  } else if (token == HOST) {
298  } else if (token == GROUP) {
300 #if defined (FAILOVER_PROTOCOL)
301  } else if (token == FAILOVER) {
303  (cfile, (dhcp_failover_state_t *)0);
304 #endif
305 #ifdef DHCPv6
306  } else if (token == SERVER_DUID) {
307  parse_server_duid(cfile);
308 #endif /* DHCPv6 */
309  } else {
310  log_error ("Corrupt lease file - possible data loss!");
311  skip_to_semi (cfile);
312  }
313 
314  } while (1);
315 
316  status = cfile->warnings_occurred ? DHCP_R_BADPARSE : ISC_R_SUCCESS;
317  return status;
318 }
319 
320 /* statement :== parameter | declaration
321 
322  parameter :== DEFAULT_LEASE_TIME lease_time
323  | MAX_LEASE_TIME lease_time
324  | DYNAMIC_BOOTP_LEASE_CUTOFF date
325  | DYNAMIC_BOOTP_LEASE_LENGTH lease_time
326  | BOOT_UNKNOWN_CLIENTS boolean
327  | ONE_LEASE_PER_CLIENT boolean
328  | GET_LEASE_HOSTNAMES boolean
329  | USE_HOST_DECL_NAME boolean
330  | NEXT_SERVER ip-addr-or-hostname SEMI
331  | option_parameter
332  | SERVER-IDENTIFIER ip-addr-or-hostname SEMI
333  | FILENAME string-parameter
334  | SERVER_NAME string-parameter
335  | hardware-parameter
336  | fixed-address-parameter
337  | ALLOW allow-deny-keyword
338  | DENY allow-deny-keyword
339  | USE_LEASE_ADDR_FOR_DEFAULT_ROUTE boolean
340  | AUTHORITATIVE
341  | NOT AUTHORITATIVE
342 
343  declaration :== host-declaration
344  | group-declaration
345  | shared-network-declaration
346  | subnet-declaration
347  | VENDOR_CLASS class-declaration
348  | USER_CLASS class-declaration
349  | RANGE address-range-declaration */
350 
351 int parse_statement (cfile, group, type, host_decl, declaration)
352  struct parse *cfile;
353  struct group *group;
354  int type;
355  struct host_decl *host_decl;
356  int declaration;
357 {
358  enum dhcp_token token;
359  const char *val;
360  struct shared_network *share;
361  char *n;
362  struct hardware hardware;
363  struct executable_statement *et, *ep;
364  struct option *option = NULL;
365  struct option_cache *cache;
366  int lose;
367  int known;
368  isc_result_t status;
369  unsigned code;
370 
371  token = peek_token (&val, (unsigned *)0, cfile);
372 
373  switch (token) {
374  case INCLUDE:
375  skip_token(&val, (unsigned *)0, cfile);
376  token = next_token (&val, (unsigned *)0, cfile);
377  if (token != STRING) {
378  parse_warn (cfile, "filename string expected.");
379  skip_to_semi (cfile);
380  } else {
381  status = read_conf_file (val, group, type, 0);
382  if (status != ISC_R_SUCCESS)
383  parse_warn (cfile, "%s: bad parse.", val);
384  parse_semi (cfile);
385  }
386  return 1;
387 
388  case HOST:
389  skip_token(&val, (unsigned *)0, cfile);
390  if (type != HOST_DECL && type != CLASS_DECL) {
391  if (global_host_once &&
392  (type == SUBNET_DECL || type == SHARED_NET_DECL)) {
393  global_host_once = 0;
394  log_error("WARNING: Host declarations are "
395  "global. They are not limited to "
396  "the scope you declared them in.");
397  }
398 
399  parse_host_declaration (cfile, group);
400  } else {
401  parse_warn (cfile,
402  "host declarations not allowed here.");
403  skip_to_semi (cfile);
404  }
405  return 1;
406 
407  case GROUP:
408  skip_token(&val, (unsigned *)0, cfile);
409  if (type != HOST_DECL && type != CLASS_DECL)
410  parse_group_declaration (cfile, group);
411  else {
412  parse_warn (cfile,
413  "group declarations not allowed here.");
414  skip_to_semi (cfile);
415  }
416  return 1;
417 
418  case SHARED_NETWORK:
419  skip_token(&val, (unsigned *)0, cfile);
420  if (type == SHARED_NET_DECL ||
421  type == HOST_DECL ||
422  type == SUBNET_DECL ||
423  type == CLASS_DECL) {
424  parse_warn (cfile, "shared-network parameters not %s.",
425  "allowed here");
426  skip_to_semi (cfile);
427  break;
428  }
429 
430  parse_shared_net_declaration (cfile, group);
431  return 1;
432 
433  case SUBNET:
434  case SUBNET6:
435  skip_token(&val, (unsigned *)0, cfile);
436  if (type == HOST_DECL || type == SUBNET_DECL ||
437  type == CLASS_DECL) {
438  parse_warn (cfile,
439  "subnet declarations not allowed here.");
440  skip_to_semi (cfile);
441  return 1;
442  }
443 
444  /* If we're in a subnet declaration, just do the parse. */
445  if (group->shared_network != NULL) {
446  if (token == SUBNET) {
448  group->shared_network);
449  } else {
451  group->shared_network);
452  }
453  break;
454  }
455 
456  /*
457  * Otherwise, cons up a fake shared network structure
458  * and populate it with the lone subnet...because the
459  * intention most likely is to refer to the entire link
460  * by shorthand, any configuration inside the subnet is
461  * actually placed in the shared-network's group.
462  */
463 
464  share = NULL;
465  status = shared_network_allocate (&share, MDL);
466  if (status != ISC_R_SUCCESS)
467  log_fatal ("Can't allocate shared subnet: %s",
468  isc_result_totext (status));
469  if (!clone_group (&share -> group, group, MDL))
470  log_fatal ("Can't allocate group for shared net");
471  shared_network_reference (&share -> group -> shared_network,
472  share, MDL);
473 
474  /*
475  * This is an implicit shared network, not explicit in
476  * the config.
477  */
478  share->flags |= SHARED_IMPLICIT;
479 
480  if (token == SUBNET) {
481  parse_subnet_declaration(cfile, share);
482  } else {
483  parse_subnet6_declaration(cfile, share);
484  }
485 
486  /* share -> subnets is the subnet we just parsed. */
487  if (share->subnets) {
488  interface_reference(&share->interface,
489  share->subnets->interface,
490  MDL);
491 
492  /* Make the shared network name from network number. */
493  if (token == SUBNET) {
494  n = piaddrmask(&share->subnets->net,
495  &share->subnets->netmask);
496  } else {
497  n = piaddrcidr(&share->subnets->net,
498  share->subnets->prefix_len);
499  }
500 
501  share->name = strdup(n);
502 
503  if (share->name == NULL)
504  log_fatal("Out of memory allocating default "
505  "shared network name (\"%s\").", n);
506 
507  /* Copy the authoritative parameter from the subnet,
508  since there is no opportunity to declare it here. */
509  share->group->authoritative =
510  share->subnets->group->authoritative;
511  enter_shared_network(share);
512  }
513  shared_network_dereference(&share, MDL);
514  return 1;
515 
516  case VENDOR_CLASS:
517  skip_token(&val, (unsigned *)0, cfile);
518  if (type == CLASS_DECL) {
519  parse_warn (cfile,
520  "class declarations not allowed here.");
521  skip_to_semi (cfile);
522  break;
523  }
524  parse_class_declaration(NULL, cfile, group, CLASS_TYPE_VENDOR);
525  return 1;
526 
527  case USER_CLASS:
528  skip_token(&val, (unsigned *)0, cfile);
529  if (type == CLASS_DECL) {
530  parse_warn (cfile,
531  "class declarations not allowed here.");
532  skip_to_semi (cfile);
533  break;
534  }
535  parse_class_declaration(NULL, cfile, group, CLASS_TYPE_USER);
536  return 1;
537 
538  case CLASS:
539  skip_token(&val, (unsigned *)0, cfile);
540  if (type == CLASS_DECL) {
541  parse_warn (cfile,
542  "class declarations not allowed here.");
543  skip_to_semi (cfile);
544  break;
545  }
546  parse_class_declaration(NULL, cfile, group, CLASS_TYPE_CLASS);
547  return 1;
548 
549  case SUBCLASS:
550  skip_token(&val, (unsigned *)0, cfile);
551  if (type == CLASS_DECL) {
552  parse_warn (cfile,
553  "class declarations not allowed here.");
554  skip_to_semi (cfile);
555  break;
556  }
557  parse_class_declaration(NULL, cfile, group,
559  return 1;
560 
561  case HARDWARE:
562  skip_token(&val, (unsigned *)0, cfile);
563  memset (&hardware, 0, sizeof hardware);
564  if (host_decl && memcmp(&hardware, &(host_decl->interface),
565  sizeof(hardware)) != 0) {
566  parse_warn(cfile, "Host %s hardware address already "
567  "configured.", host_decl->name);
568  break;
569  }
570 
571  parse_hardware_param (cfile, &hardware);
572  if (host_decl)
573  host_decl -> interface = hardware;
574  else
575  parse_warn (cfile, "hardware address parameter %s",
576  "not allowed here.");
577  break;
578 
579  case FIXED_ADDR:
580  case FIXED_ADDR6:
581  skip_token(&val, NULL, cfile);
582  cache = NULL;
583  if (parse_fixed_addr_param(&cache, cfile, token)) {
584  if (host_decl) {
585  if (host_decl->fixed_addr) {
586  option_cache_dereference(&cache, MDL);
587  parse_warn(cfile,
588  "Only one fixed address "
589  "declaration per host.");
590  } else {
591  host_decl->fixed_addr = cache;
592  }
593  } else {
594  parse_warn(cfile,
595  "fixed-address parameter not "
596  "allowed here.");
597  option_cache_dereference(&cache, MDL);
598  }
599  }
600  break;
601 
602  case POOL:
603  skip_token(&val, (unsigned *)0, cfile);
604  if (type == POOL_DECL) {
605  parse_warn (cfile, "pool declared within pool.");
606  skip_to_semi(cfile);
607  } else if (type != SUBNET_DECL && type != SHARED_NET_DECL) {
608  parse_warn (cfile, "pool declared outside of network");
609  skip_to_semi(cfile);
610  } else
611  parse_pool_statement (cfile, group, type);
612 
613  return declaration;
614 
615  case RANGE:
616  skip_token(&val, (unsigned *)0, cfile);
617  if (type != SUBNET_DECL || !group -> subnet) {
618  parse_warn (cfile,
619  "range declaration not allowed here.");
620  skip_to_semi (cfile);
621  return declaration;
622  }
623  parse_address_range (cfile, group, type, (struct pool *)0,
624  (struct lease **)0);
625  return declaration;
626 
627 #ifdef DHCPv6
628  case RANGE6:
629  skip_token(NULL, NULL, cfile);
630  if ((type != SUBNET_DECL) || (group->subnet == NULL)) {
631  parse_warn (cfile,
632  "range6 declaration not allowed here.");
633  skip_to_semi(cfile);
634  return declaration;
635  }
636  parse_address_range6(cfile, group, NULL);
637  return declaration;
638 
639  case PREFIX6:
640  skip_token(NULL, NULL, cfile);
641  if ((type != SUBNET_DECL) || (group->subnet == NULL)) {
642  parse_warn (cfile,
643  "prefix6 declaration not allowed here.");
644  skip_to_semi(cfile);
645  return declaration;
646  }
647  parse_prefix6(cfile, group, NULL);
648  return declaration;
649 
650  case FIXED_PREFIX6:
651  skip_token(&val, NULL, cfile);
652  if (!host_decl) {
653  parse_warn (cfile,
654  "fixed-prefix6 declaration not "
655  "allowed here.");
656  skip_to_semi(cfile);
657  break;
658  }
659  parse_fixed_prefix6(cfile, host_decl);
660  break;
661 
662  case POOL6:
663  skip_token(&val, NULL, cfile);
664  if (type == POOL_DECL) {
665  parse_warn (cfile, "pool6 declared within pool.");
666  skip_to_semi(cfile);
667  } else if (type != SUBNET_DECL) {
668  parse_warn (cfile, "pool6 declared outside of network");
669  skip_to_semi(cfile);
670  } else
671  parse_pool6_statement (cfile, group, type);
672 
673  return declaration;
674 
675 #endif /* DHCPv6 */
676 
677  case TOKEN_NOT:
678  skip_token(&val, (unsigned *)0, cfile);
679  token = next_token (&val, (unsigned *)0, cfile);
680  switch (token) {
681  case AUTHORITATIVE:
682  group -> authoritative = 0;
683  goto authoritative;
684  default:
685  parse_warn (cfile, "expecting assertion");
686  skip_to_semi (cfile);
687  break;
688  }
689  break;
690  case AUTHORITATIVE:
691  skip_token(&val, (unsigned *)0, cfile);
692  group -> authoritative = 1;
693  authoritative:
694  if (type == HOST_DECL)
695  parse_warn (cfile, "authority makes no sense here.");
696  parse_semi (cfile);
697  break;
698 
699  /* "server-identifier" is a special hack, equivalent to
700  "option dhcp-server-identifier". */
701  case SERVER_IDENTIFIER:
703  if (!option_code_hash_lookup(&option, dhcp_universe.code_hash,
704  &code, 0, MDL))
705  log_fatal("Server identifier not in hash (%s:%d).",
706  MDL);
707  skip_token(&val, (unsigned *)0, cfile);
708  goto finish_option;
709 
710  case OPTION:
711  skip_token(&val, (unsigned *)0, cfile);
712  token = peek_token (&val, (unsigned *)0, cfile);
713  if (token == SPACE) {
714  if (type != ROOT_GROUP) {
715  parse_warn (cfile,
716  "option space definitions %s",
717  "may not be scoped.");
718  skip_to_semi (cfile);
719  break;
720  }
721  parse_option_space_decl (cfile);
722  return declaration;
723  }
724 
725  known = 0;
726  status = parse_option_name(cfile, 1, &known, &option);
727  if (status == ISC_R_SUCCESS) {
728  token = peek_token (&val, (unsigned *)0, cfile);
729  if (token == CODE) {
730  if (type != ROOT_GROUP) {
731  parse_warn (cfile,
732  "option definitions%s",
733  " may not be scoped.");
734  skip_to_semi (cfile);
735  option_dereference(&option, MDL);
736  break;
737  }
738  skip_token(&val, (unsigned *)0, cfile);
739 
740  /*
741  * If the option was known, remove it from the
742  * code and name hashes before redefining it.
743  */
744  if (known) {
745  option_name_hash_delete(
746  option->universe->name_hash,
747  option->name, 0, MDL);
748  option_code_hash_delete(
749  option->universe->code_hash,
750  &option->code, 0, MDL);
751  }
752 
753  parse_option_code_definition(cfile, option);
754  option_dereference(&option, MDL);
755  return declaration;
756  }
757 
758  /* If this wasn't an option code definition, don't
759  allow an unknown option. */
760  if (!known) {
761  parse_warn (cfile, "unknown option %s.%s",
762  option -> universe -> name,
763  option -> name);
764  skip_to_semi (cfile);
765  option_dereference(&option, MDL);
766  return declaration;
767  }
768 
769  finish_option:
770  et = (struct executable_statement *)0;
772  (&et, cfile, 1, option,
774  return declaration;
775  option_dereference(&option, MDL);
776  goto insert_statement;
777  } else
778  return declaration;
779 
780  break;
781 
782  case FAILOVER:
783  if (type != ROOT_GROUP && type != SHARED_NET_DECL) {
784  parse_warn (cfile, "failover peers may only be %s",
785  "defined in shared-network");
786  log_error ("declarations and the outer scope.");
787  skip_to_semi (cfile);
788  break;
789  }
790  token = next_token (&val, (unsigned *)0, cfile);
791 #if defined (FAILOVER_PROTOCOL)
792  parse_failover_peer (cfile, group, type);
793 #else
794  parse_warn (cfile, "No failover support.");
795  skip_to_semi (cfile);
796 #endif
797  break;
798 
799 #ifdef DHCPv6
800  case SERVER_DUID:
801  parse_server_duid_conf(cfile);
802  break;
803 #endif /* DHCPv6 */
804 
805  default:
806  et = (struct executable_statement *)0;
807  lose = 0;
808  if (!parse_executable_statement (&et, cfile, &lose,
809  context_any)) {
810  if (!lose) {
811  if (declaration)
812  parse_warn (cfile,
813  "expecting a declaration");
814  else
815  parse_warn (cfile,
816  "expecting a parameter %s",
817  "or declaration");
818  skip_to_semi (cfile);
819  }
820  return declaration;
821  }
822  if (!et)
823  return declaration;
824  insert_statement:
825  if (group -> statements) {
826  int multi = 0;
827 
828  /* If this set of statements is only referenced
829  by this group, just add the current statement
830  to the end of the chain. */
831  for (ep = group -> statements; ep -> next;
832  ep = ep -> next)
833  if (ep -> refcnt > 1) /* XXX */
834  multi = 1;
835  if (!multi) {
837  et, MDL);
839  return declaration;
840  }
841 
842  /* Otherwise, make a parent chain, and put the
843  current group statements first and the new
844  statement in the next pointer. */
845  ep = (struct executable_statement *)0;
847  log_fatal ("No memory for statements.");
848  ep -> op = statements_statement;
850  group -> statements,
851  MDL);
854  MDL);
856  ep, MDL);
858  } else {
860  et, MDL);
861  }
863  return declaration;
864  }
865 
866  return 0;
867 }
868 
869 #if defined (FAILOVER_PROTOCOL)
870 void parse_failover_peer (cfile, group, type)
871  struct parse *cfile;
872  struct group *group;
873  int type;
874 {
875  enum dhcp_token token;
876  const char *val;
877  dhcp_failover_state_t *peer;
878  u_int32_t *tp;
879  char *name;
880  u_int32_t split;
881  u_int8_t hba [32];
882  unsigned hba_len = sizeof hba;
883  int i;
884  struct expression *expr;
885  isc_result_t status;
886  dhcp_failover_config_t *cp;
887 
888  token = next_token (&val, (unsigned *)0, cfile);
889  if (token != PEER) {
890  parse_warn (cfile, "expecting \"peer\"");
891  skip_to_semi (cfile);
892  return;
893  }
894 
895  token = next_token (&val, (unsigned *)0, cfile);
896  if (is_identifier (token) || token == STRING) {
897  name = dmalloc (strlen (val) + 1, MDL);
898  if (!name)
899  log_fatal ("no memory for peer name %s", name);
900  strcpy (name, val);
901  } else {
902  parse_warn (cfile, "expecting failover peer name.");
903  skip_to_semi (cfile);
904  return;
905  }
906 
907  /* See if there's a peer declaration by this name. */
908  peer = (dhcp_failover_state_t *)0;
909  find_failover_peer (&peer, name, MDL);
910 
911  token = next_token (&val, (unsigned *)0, cfile);
912  if (token == SEMI) {
913  if (type != SHARED_NET_DECL)
914  parse_warn (cfile, "failover peer reference not %s",
915  "in shared-network declaration");
916  else {
917  if (!peer) {
918  parse_warn (cfile, "reference to unknown%s%s",
919  " failover peer ", name);
920  dfree (name, MDL);
921  return;
922  }
923  dhcp_failover_state_reference
924  (&group -> shared_network -> failover_peer,
925  peer, MDL);
926  }
927  dhcp_failover_state_dereference (&peer, MDL);
928  dfree (name, MDL);
929  return;
930  } else if (token == STATE) {
931  if (!peer) {
932  parse_warn (cfile, "state declaration for unknown%s%s",
933  " failover peer ", name);
934  dfree (name, MDL);
935  return;
936  }
937  parse_failover_state_declaration (cfile, peer);
938  dhcp_failover_state_dereference (&peer, MDL);
939  dfree (name, MDL);
940  return;
941  } else if (token != LBRACE) {
942  parse_warn (cfile, "expecting left brace");
943  skip_to_semi (cfile);
944  }
945 
946  /* Make sure this isn't a redeclaration. */
947  if (peer) {
948  parse_warn (cfile, "redeclaration of failover peer %s", name);
949  skip_to_rbrace (cfile, 1);
950  dhcp_failover_state_dereference (&peer, MDL);
951  dfree (name, MDL);
952  return;
953  }
954 
955  status = dhcp_failover_state_allocate (&peer, MDL);
956  if (status != ISC_R_SUCCESS)
957  log_fatal ("Can't allocate failover peer %s: %s",
958  name, isc_result_totext (status));
959 
960  /* Save the name. */
961  peer -> name = name;
962 
963  do {
964  cp = &peer -> me;
965  peer:
966  token = next_token (&val, (unsigned *)0, cfile);
967  switch (token) {
968  case RBRACE:
969  break;
970 
971  case PRIMARY:
972  peer -> i_am = primary;
973  break;
974 
975  case SECONDARY:
976  peer -> i_am = secondary;
977  if (peer -> hba)
978  parse_warn (cfile,
979  "secondary may not define %s",
980  "load balance settings.");
981  break;
982 
983  case PEER:
984  cp = &peer -> partner;
985  goto peer;
986 
987  case ADDRESS:
988  expr = (struct expression *)0;
989  if (!parse_ip_addr_or_hostname (&expr, cfile, 0)) {
990  skip_to_rbrace (cfile, 1);
991  dhcp_failover_state_dereference (&peer, MDL);
992  return;
993  }
994  option_cache (&cp -> address,
995  (struct data_string *)0, expr,
996  (struct option *)0, MDL);
997  expression_dereference (&expr, MDL);
998  break;
999 
1000  case PORT:
1001  token = next_token (&val, (unsigned *)0, cfile);
1002  if (token != NUMBER) {
1003  parse_warn (cfile, "expecting number");
1004  skip_to_rbrace (cfile, 1);
1005  }
1006  cp -> port = atoi (val);
1007  break;
1008 
1009  case MAX_LEASE_MISBALANCE:
1010  tp = &peer->max_lease_misbalance;
1011  goto parse_idle;
1012 
1013  case MAX_LEASE_OWNERSHIP:
1014  tp = &peer->max_lease_ownership;
1015  goto parse_idle;
1016 
1017  case MAX_BALANCE:
1018  tp = &peer->max_balance;
1019  goto parse_idle;
1020 
1021  case MIN_BALANCE:
1022  tp = &peer->min_balance;
1023  goto parse_idle;
1024 
1025  case AUTO_PARTNER_DOWN:
1026  tp = &peer->auto_partner_down;
1027  goto parse_idle;
1028 
1029  case MAX_RESPONSE_DELAY:
1030  tp = &cp -> max_response_delay;
1031  parse_idle:
1032  token = next_token (&val, (unsigned *)0, cfile);
1033  if (token != NUMBER) {
1034  parse_warn (cfile, "expecting number.");
1035  skip_to_rbrace (cfile, 1);
1036  dhcp_failover_state_dereference (&peer, MDL);
1037  return;
1038  }
1039  *tp = atoi (val);
1040  break;
1041 
1042  case MAX_UNACKED_UPDATES:
1043  tp = &cp -> max_flying_updates;
1044  goto parse_idle;
1045 
1046  case MCLT:
1047  tp = &peer -> mclt;
1048  goto parse_idle;
1049 
1050  case HBA:
1051  hba_len = 32;
1052  if (peer -> i_am == secondary)
1053  parse_warn (cfile,
1054  "secondary may not define %s",
1055  "load balance settings.");
1056  if (!parse_numeric_aggregate (cfile, hba, &hba_len,
1057  COLON, 16, 8)) {
1058  skip_to_rbrace (cfile, 1);
1059  dhcp_failover_state_dereference (&peer, MDL);
1060  return;
1061  }
1062  if (hba_len != 32) {
1063  parse_warn (cfile,
1064  "HBA must be exactly 32 bytes.");
1065  break;
1066  }
1067  make_hba:
1068  peer -> hba = dmalloc (32, MDL);
1069  if (!peer -> hba) {
1070  dfree (peer -> name, MDL);
1071  dfree (peer, MDL);
1072  }
1073  memcpy (peer -> hba, hba, 32);
1074  break;
1075 
1076  case SPLIT:
1077  token = next_token (&val, (unsigned *)0, cfile);
1078  if (peer -> i_am == secondary)
1079  parse_warn (cfile,
1080  "secondary may not define %s",
1081  "load balance settings.");
1082  if (token != NUMBER) {
1083  parse_warn (cfile, "expecting number");
1084  skip_to_rbrace (cfile, 1);
1085  dhcp_failover_state_dereference (&peer, MDL);
1086  return;
1087  }
1088  split = atoi (val);
1089  if (split > 256) {
1090  parse_warn (cfile, "split must be between "
1091  "0 and 256, inclusive");
1092  } else {
1093  memset (hba, 0, sizeof hba);
1094  for (i = 0; i < split; i++) {
1095  if (i < split)
1096  hba [i / 8] |= (1 << (i & 7));
1097  }
1098  goto make_hba;
1099  }
1100  break;
1101 
1102  case LOAD:
1103  token = next_token (&val, (unsigned *)0, cfile);
1104  if (token != BALANCE) {
1105  parse_warn (cfile, "expecting 'balance'");
1106  badload:
1107  skip_to_rbrace (cfile, 1);
1108  break;
1109  }
1110  token = next_token (&val, (unsigned *)0, cfile);
1111  if (token != TOKEN_MAX) {
1112  parse_warn (cfile, "expecting 'max'");
1113  goto badload;
1114  }
1115  token = next_token (&val, (unsigned *)0, cfile);
1116  if (token != SECONDS) {
1117  parse_warn (cfile, "expecting 'secs'");
1118  goto badload;
1119  }
1120  token = next_token (&val, (unsigned *)0, cfile);
1121  if (token != NUMBER) {
1122  parse_warn (cfile, "expecting number");
1123  goto badload;
1124  }
1125  peer -> load_balance_max_secs = atoi (val);
1126  break;
1127 
1128  default:
1129  parse_warn (cfile,
1130  "invalid statement in peer declaration");
1131  skip_to_rbrace (cfile, 1);
1132  dhcp_failover_state_dereference (&peer, MDL);
1133  return;
1134  }
1135  if (token != RBRACE && !parse_semi (cfile)) {
1136  skip_to_rbrace (cfile, 1);
1137  dhcp_failover_state_dereference (&peer, MDL);
1138  return;
1139  }
1140  } while (token != RBRACE);
1141 
1142  /* me.address can be null; the failover link initiate code tries to
1143  * derive a reasonable address to use.
1144  */
1145  if (!peer -> partner.address)
1146  parse_warn (cfile, "peer address may not be omitted");
1147 
1148  if (!peer->me.port)
1149  peer->me.port = DEFAULT_FAILOVER_PORT;
1150  if (!peer->partner.port)
1151  peer->partner.port = DEFAULT_FAILOVER_PORT;
1152 
1153  if (peer -> i_am == primary) {
1154  if (!peer -> hba) {
1155  parse_warn (cfile,
1156  "primary failover server must have hba or split.");
1157  } else if (!peer -> mclt) {
1158  parse_warn (cfile,
1159  "primary failover server must have mclt.");
1160  }
1161  }
1162 
1163  if (!peer->max_lease_misbalance)
1164  peer->max_lease_misbalance = DEFAULT_MAX_LEASE_MISBALANCE;
1165  if (!peer->max_lease_ownership)
1166  peer->max_lease_ownership = DEFAULT_MAX_LEASE_OWNERSHIP;
1167  if (!peer->max_balance)
1168  peer->max_balance = DEFAULT_MAX_BALANCE_TIME;
1169  if (!peer->min_balance)
1170  peer->min_balance = DEFAULT_MIN_BALANCE_TIME;
1171  if (!peer->me.max_flying_updates)
1172  peer->me.max_flying_updates = DEFAULT_MAX_FLYING_UPDATES;
1173  if (!peer->me.max_response_delay)
1174  peer->me.max_response_delay = DEFAULT_MAX_RESPONSE_DELAY;
1175 
1176  if (type == SHARED_NET_DECL)
1177  group->shared_network->failover_peer = peer;
1178 
1179  /* Set the initial state. */
1180  if (peer -> i_am == primary) {
1181  peer -> me.state = recover;
1182  peer -> me.stos = cur_time;
1183  peer -> partner.state = unknown_state;
1184  peer -> partner.stos = cur_time;
1185  } else {
1186  peer -> me.state = recover;
1187  peer -> me.stos = cur_time;
1188  peer -> partner.state = unknown_state;
1189  peer -> partner.stos = cur_time;
1190  }
1191 
1192  status = enter_failover_peer (peer);
1193  if (status != ISC_R_SUCCESS)
1194  parse_warn (cfile, "failover peer %s: %s",
1195  peer -> name, isc_result_totext (status));
1196  dhcp_failover_state_dereference (&peer, MDL);
1197 }
1198 
1199 void parse_failover_state_declaration (struct parse *cfile,
1200  dhcp_failover_state_t *peer)
1201 {
1202  enum dhcp_token token;
1203  const char *val;
1204  char *name;
1205  dhcp_failover_state_t *state;
1206  dhcp_failover_config_t *cp;
1207 
1208  if (!peer) {
1209  token = next_token (&val, (unsigned *)0, cfile);
1210  if (token != PEER) {
1211  parse_warn (cfile, "expecting \"peer\"");
1212  skip_to_semi (cfile);
1213  return;
1214  }
1215 
1216  token = next_token (&val, (unsigned *)0, cfile);
1217  if (is_identifier (token) || token == STRING) {
1218  name = dmalloc (strlen (val) + 1, MDL);
1219  if (!name)
1220  log_fatal ("failover peer name %s: no memory",
1221  name);
1222  strcpy (name, val);
1223  } else {
1224  parse_warn (cfile, "expecting failover peer name.");
1225  skip_to_semi (cfile);
1226  return;
1227  }
1228 
1229  /* See if there's a peer declaration by this name. */
1230  state = (dhcp_failover_state_t *)0;
1231  find_failover_peer (&state, name, MDL);
1232  if (!state) {
1233  parse_warn (cfile, "unknown failover peer: %s", name);
1234  skip_to_semi (cfile);
1235  return;
1236  }
1237 
1238  token = next_token (&val, (unsigned *)0, cfile);
1239  if (token != STATE) {
1240  parse_warn (cfile, "expecting 'state'");
1241  if (token != SEMI)
1242  skip_to_semi (cfile);
1243  return;
1244  }
1245  } else {
1246  state = (dhcp_failover_state_t *)0;
1247  dhcp_failover_state_reference (&state, peer, MDL);
1248  }
1249  token = next_token (&val, (unsigned *)0, cfile);
1250  if (token != LBRACE) {
1251  parse_warn (cfile, "expecting left brace");
1252  if (token != SEMI)
1253  skip_to_semi (cfile);
1254  dhcp_failover_state_dereference (&state, MDL);
1255  return;
1256  }
1257  do {
1258  token = next_token (&val, (unsigned *)0, cfile);
1259  switch (token) {
1260  case RBRACE:
1261  break;
1262  case MY:
1263  cp = &state -> me;
1264  do_state:
1265  token = next_token (&val, (unsigned *)0, cfile);
1266  if (token != STATE) {
1267  parse_warn (cfile, "expecting 'state'");
1268  goto bogus;
1269  }
1270  parse_failover_state (cfile,
1271  &cp -> state, &cp -> stos);
1272  break;
1273 
1274  case PARTNER:
1275  cp = &state -> partner;
1276  goto do_state;
1277 
1278  case MCLT:
1279  if (state -> i_am == primary) {
1280  parse_warn (cfile,
1281  "mclt not valid for primary");
1282  goto bogus;
1283  }
1284  token = next_token (&val, (unsigned *)0, cfile);
1285  if (token != NUMBER) {
1286  parse_warn (cfile, "expecting a number.");
1287  goto bogus;
1288  }
1289  state -> mclt = atoi (val);
1290  parse_semi (cfile);
1291  break;
1292 
1293  default:
1294  parse_warn (cfile, "expecting state setting.");
1295  bogus:
1296  skip_to_rbrace (cfile, 1);
1297  dhcp_failover_state_dereference (&state, MDL);
1298  return;
1299  }
1300  } while (token != RBRACE);
1301  dhcp_failover_state_dereference (&state, MDL);
1302 }
1303 
1304 void parse_failover_state (cfile, state, stos)
1305  struct parse *cfile;
1306  enum failover_state *state;
1307  TIME *stos;
1308 {
1309  enum dhcp_token token;
1310  const char *val;
1311  enum failover_state state_in;
1312  TIME stos_in;
1313 
1314  token = next_token (&val, (unsigned *)0, cfile);
1315  switch (token) {
1316  case UNKNOWN_STATE:
1317  state_in = unknown_state;
1318  break;
1319 
1320  case PARTNER_DOWN:
1321  state_in = partner_down;
1322  break;
1323 
1324  case NORMAL:
1325  state_in = normal;
1326  break;
1327 
1329  state_in = communications_interrupted;
1330  break;
1331 
1332  case CONFLICT_DONE:
1333  state_in = conflict_done;
1334  break;
1335 
1337  state_in = resolution_interrupted;
1338  break;
1339 
1340  case POTENTIAL_CONFLICT:
1341  state_in = potential_conflict;
1342  break;
1343 
1344  case RECOVER:
1345  state_in = recover;
1346  break;
1347 
1348  case RECOVER_WAIT:
1349  state_in = recover_wait;
1350  break;
1351 
1352  case RECOVER_DONE:
1353  state_in = recover_done;
1354  break;
1355 
1356  case SHUTDOWN:
1357  state_in = shut_down;
1358  break;
1359 
1360  case PAUSED:
1361  state_in = paused;
1362  break;
1363 
1364  case STARTUP:
1365  state_in = startup;
1366  break;
1367 
1368  default:
1369  parse_warn (cfile, "unknown failover state");
1370  skip_to_semi (cfile);
1371  return;
1372  }
1373 
1374  token = next_token (&val, (unsigned *)0, cfile);
1375  if (token == SEMI) {
1376  stos_in = cur_time;
1377  } else {
1378  if (token != AT) {
1379  parse_warn (cfile, "expecting \"at\"");
1380  skip_to_semi (cfile);
1381  return;
1382  }
1383 
1384  stos_in = parse_date (cfile);
1385  if (!stos_in)
1386  return;
1387  }
1388 
1389  /* Now that we've apparently gotten a clean parse, we
1390  can trust that this is a state that was fully committed to
1391  disk, so we can install it. */
1392  *stos = stos_in;
1393  *state = state_in;
1394 }
1395 #endif /* defined (FAILOVER_PROTOCOL) */
1396 
1429 void get_permit(cfile, permit_head, is_allow, valid_from, valid_until)
1430  struct parse *cfile;
1431  struct permit **permit_head;
1432  int is_allow;
1433  TIME *valid_from, *valid_until;
1434 {
1435  enum dhcp_token token;
1436  struct permit *permit;
1437  const char *val;
1438  int need_clients = 1;
1439  TIME t;
1440 
1441  /* Create our permit structure */
1442  permit = new_permit(MDL);
1443  if (!permit)
1444  log_fatal ("no memory for permit");
1445 
1446  token = next_token(&val, NULL, cfile);
1447  switch (token) {
1448  case UNKNOWN:
1449  permit->type = permit_unknown_clients;
1450  break;
1451 
1452  case KNOWN_CLIENTS:
1453  need_clients = 0;
1454  permit->type = permit_known_clients;
1455  break;
1456 
1457  case UNKNOWN_CLIENTS:
1458  need_clients = 0;
1459  permit->type = permit_unknown_clients;
1460  break;
1461 
1462  case KNOWN:
1463  permit->type = permit_known_clients;
1464  break;
1465 
1466  case AUTHENTICATED:
1468  break;
1469 
1470  case UNAUTHENTICATED:
1472  break;
1473 
1474  case ALL:
1475  permit->type = permit_all_clients;
1476  break;
1477 
1478  case DYNAMIC:
1480  if (next_token (&val, NULL, cfile) != TOKEN_BOOTP) {
1481  parse_warn (cfile, "expecting \"bootp\"");
1482  skip_to_semi (cfile);
1483  free_permit (permit, MDL);
1484  return;
1485  }
1486  break;
1487 
1488  case MEMBERS:
1489  need_clients = 0;
1490  if (next_token (&val, NULL, cfile) != OF) {
1491  parse_warn (cfile, "expecting \"of\"");
1492  skip_to_semi (cfile);
1493  free_permit (permit, MDL);
1494  return;
1495  }
1496  if (next_token (&val, NULL, cfile) != STRING) {
1497  parse_warn (cfile, "expecting class name.");
1498  skip_to_semi (cfile);
1499  free_permit (permit, MDL);
1500  return;
1501  }
1502  permit->type = permit_class;
1503  permit->class = NULL;
1504  find_class(&permit->class, val, MDL);
1505  if (!permit->class)
1506  parse_warn(cfile, "no such class: %s", val);
1507  break;
1508 
1509  case AFTER:
1510  need_clients = 0;
1511  if (*valid_from || *valid_until) {
1512  parse_warn(cfile, "duplicate \"after\" clause.");
1513  skip_to_semi(cfile);
1514  free_permit(permit, MDL);
1515  return;
1516  }
1517  t = parse_date_core(cfile);
1518  permit->type = permit_after;
1519  permit->after = t;
1520  if (is_allow) {
1521  *valid_from = t;
1522  } else {
1523  *valid_until = t;
1524  }
1525  break;
1526 
1527  default:
1528  parse_warn (cfile, "expecting permit type.");
1529  skip_to_semi (cfile);
1530  free_permit (permit, MDL);
1531  return;
1532  }
1533 
1534  /*
1535  * The need_clients flag is set if we are expecting the
1536  * CLIENTS token
1537  */
1538  if ((need_clients != 0) &&
1539  (next_token (&val, NULL, cfile) != CLIENTS)) {
1540  parse_warn (cfile, "expecting \"clients\"");
1541  skip_to_semi (cfile);
1542  free_permit (permit, MDL);
1543  return;
1544  }
1545 
1546  while (*permit_head)
1547  permit_head = &((*permit_head)->next);
1548  *permit_head = permit;
1549  parse_semi (cfile);
1550 
1551  return;
1552 }
1553 
1554 /* Permit_list_match returns 1 if every element of the permit list in lhs
1555  also appears in rhs. Note that this doesn't by itself mean that the
1556  two lists are equal - to check for equality, permit_list_match has to
1557  return 1 with (list1, list2) and with (list2, list1). */
1558 
1559 int permit_list_match (struct permit *lhs, struct permit *rhs)
1560 {
1561  struct permit *plp, *prp;
1562  int matched;
1563 
1564  if (!lhs)
1565  return 1;
1566  if (!rhs)
1567  return 0;
1568  for (plp = lhs; plp; plp = plp -> next) {
1569  matched = 0;
1570  for (prp = rhs; prp; prp = prp -> next) {
1571  if (prp -> type == plp -> type &&
1572  (prp -> type != permit_class ||
1573  prp -> class == plp -> class)) {
1574  matched = 1;
1575  break;
1576  }
1577  }
1578  if (!matched)
1579  return 0;
1580  }
1581  return 1;
1582 }
1583 
1603 void parse_pool_statement (cfile, group, type)
1604  struct parse *cfile;
1605  struct group *group;
1606  int type;
1607 {
1608  enum dhcp_token token;
1609  const char *val;
1610  int done = 0;
1611  struct pool *pool, **p, *pp;
1612  int declaration = 0;
1613  isc_result_t status;
1614  struct lease *lpchain = NULL, *lp;
1615 
1616  pool = NULL;
1617  status = pool_allocate(&pool, MDL);
1618  if (status != ISC_R_SUCCESS)
1619  log_fatal ("no memory for pool: %s",
1620  isc_result_totext (status));
1621 
1622  if (type == SUBNET_DECL)
1623  shared_network_reference(&pool->shared_network,
1624  group->subnet->shared_network,
1625  MDL);
1626  else if (type == SHARED_NET_DECL)
1627  shared_network_reference(&pool->shared_network,
1628  group->shared_network, MDL);
1629  else {
1630  parse_warn(cfile, "Dynamic pools are only valid inside "
1631  "subnet or shared-network statements.");
1632  skip_to_semi(cfile);
1633  return;
1634  }
1635 
1636  if (pool->shared_network == NULL ||
1637  !clone_group(&pool->group, pool->shared_network->group, MDL))
1638  log_fatal("can't clone pool group.");
1639 
1640 #if defined (FAILOVER_PROTOCOL)
1641  /* Inherit the failover peer from the shared network. */
1642  if (pool->shared_network->failover_peer)
1643  dhcp_failover_state_reference
1644  (&pool->failover_peer,
1645  pool->shared_network->failover_peer, MDL);
1646 #endif
1647 
1648  if (!parse_lbrace(cfile)) {
1649  pool_dereference(&pool, MDL);
1650  return;
1651  }
1652 
1653  do {
1654  token = peek_token(&val, NULL, cfile);
1655  switch (token) {
1656  case TOKEN_NO:
1657  skip_token(&val, NULL, cfile);
1658  token = next_token(&val, NULL, cfile);
1659  if (token != FAILOVER ||
1660  (token = next_token(&val, NULL, cfile)) != PEER) {
1661  parse_warn(cfile,
1662  "expecting \"failover peer\".");
1663  skip_to_semi(cfile);
1664  continue;
1665  }
1666 #if defined (FAILOVER_PROTOCOL)
1667  if (pool->failover_peer)
1668  dhcp_failover_state_dereference
1669  (&pool->failover_peer, MDL);
1670 #endif
1671  break;
1672 
1673 #if defined (FAILOVER_PROTOCOL)
1674  case FAILOVER:
1675  skip_token(&val, NULL, cfile);
1676  token = next_token (&val, NULL, cfile);
1677  if (token != PEER) {
1678  parse_warn(cfile, "expecting 'peer'.");
1679  skip_to_semi(cfile);
1680  break;
1681  }
1682  token = next_token(&val, NULL, cfile);
1683  if (token != STRING) {
1684  parse_warn(cfile, "expecting string.");
1685  skip_to_semi(cfile);
1686  break;
1687  }
1688  if (pool->failover_peer)
1689  dhcp_failover_state_dereference
1690  (&pool->failover_peer, MDL);
1691  status = find_failover_peer(&pool->failover_peer,
1692  val, MDL);
1693  if (status != ISC_R_SUCCESS)
1694  parse_warn(cfile,
1695  "failover peer %s: %s", val,
1696  isc_result_totext (status));
1697  else
1698  pool->failover_peer->pool_count++;
1699  parse_semi(cfile);
1700  break;
1701 #endif
1702 
1703  case RANGE:
1704  skip_token(&val, NULL, cfile);
1705  parse_address_range (cfile, group, type,
1706  pool, &lpchain);
1707  break;
1708  case ALLOW:
1709  skip_token(&val, NULL, cfile);
1710  get_permit(cfile, &pool->permit_list, 1,
1711  &pool->valid_from, &pool->valid_until);
1712  break;
1713 
1714  case DENY:
1715  skip_token(&val, NULL, cfile);
1716  get_permit(cfile, &pool->prohibit_list, 0,
1717  &pool->valid_from, &pool->valid_until);
1718  break;
1719 
1720  case RBRACE:
1721  skip_token(&val, NULL, cfile);
1722  done = 1;
1723  break;
1724 
1725  case END_OF_FILE:
1726  /*
1727  * We can get to END_OF_FILE if, for instance,
1728  * the parse_statement() reads all available tokens
1729  * and leaves us at the end.
1730  */
1731  parse_warn(cfile, "unexpected end of file");
1732  goto cleanup;
1733 
1734  default:
1735  declaration = parse_statement(cfile, pool->group,
1736  POOL_DECL, NULL,
1737  declaration);
1738  break;
1739  }
1740  } while (!done);
1741 
1742  /* See if there's already a pool into which we can merge this one. */
1743  for (pp = pool->shared_network->pools; pp; pp = pp->next) {
1744  if (pp->group->statements != pool->group->statements)
1745  continue;
1746 #if defined (FAILOVER_PROTOCOL)
1747  if (pool->failover_peer != pp->failover_peer)
1748  continue;
1749 #endif
1750  if (!permit_list_match(pp->permit_list,
1751  pool->permit_list) ||
1753  pp->permit_list) ||
1755  pool->prohibit_list) ||
1757  pp->prohibit_list))
1758  continue;
1759 
1760  /* Okay, we can merge these two pools. All we have to
1761  do is fix up the leases, which all point to their pool. */
1762  for (lp = lpchain; lp; lp = lp->next) {
1763  pool_dereference(&lp->pool, MDL);
1764  pool_reference(&lp->pool, pp, MDL);
1765  }
1766  break;
1767  }
1768 
1769  /* If we didn't succeed in merging this pool into another, put
1770  it on the list. */
1771  if (!pp) {
1772  p = &pool->shared_network->pools;
1773  for (; *p; p = &((*p)->next))
1774  ;
1775  pool_reference(p, pool, MDL);
1776  }
1777 
1778  /* Don't allow a pool declaration with no addresses, since it is
1779  probably a configuration error. */
1780  if (!lpchain) {
1781  parse_warn(cfile, "Pool declaration with no address range.");
1782  log_error("Pool declarations must always contain at least");
1783  log_error("one range statement.");
1784  }
1785 
1786 cleanup:
1787  /* Dereference the lease chain. */
1788  lp = NULL;
1789  while (lpchain) {
1790  lease_reference(&lp, lpchain, MDL);
1791  lease_dereference(&lpchain, MDL);
1792  if (lp->next) {
1793  lease_reference(&lpchain, lp->next, MDL);
1794  lease_dereference(&lp->next, MDL);
1795  lease_dereference(&lp, MDL);
1796  }
1797  }
1798  pool_dereference(&pool, MDL);
1799 }
1800 
1801 /* Expect a left brace; if there isn't one, skip over the rest of the
1802  statement and return zero; otherwise, return 1. */
1803 
1804 int parse_lbrace (cfile)
1805  struct parse *cfile;
1806 {
1807  enum dhcp_token token;
1808  const char *val;
1809 
1810  token = next_token (&val, (unsigned *)0, cfile);
1811  if (token != LBRACE) {
1812  parse_warn (cfile, "expecting left brace.");
1813  skip_to_semi (cfile);
1814  return 0;
1815  }
1816  return 1;
1817 }
1818 
1819 
1820 /* host-declaration :== hostname RBRACE parameters declarations LBRACE */
1821 
1822 void parse_host_declaration (cfile, group)
1823  struct parse *cfile;
1824  struct group *group;
1825 {
1826  const char *val;
1827  enum dhcp_token token;
1828  struct host_decl *host;
1829  char *name;
1830  int declaration = 0;
1831  int dynamicp = 0;
1832  int deleted = 0;
1833  isc_result_t status;
1834  int known;
1835  struct option *option;
1836  struct expression *expr = NULL;
1837 
1838  name = parse_host_name (cfile);
1839  if (!name) {
1840  parse_warn (cfile, "expecting a name for host declaration.");
1841  skip_to_semi (cfile);
1842  return;
1843  }
1844 
1845  host = (struct host_decl *)0;
1846  status = host_allocate (&host, MDL);
1847  if (status != ISC_R_SUCCESS)
1848  log_fatal ("can't allocate host decl struct %s: %s",
1849  name, isc_result_totext (status));
1850  host -> name = name;
1851  if (!clone_group (&host -> group, group, MDL)) {
1852  log_fatal ("can't clone group for host %s", name);
1853  boom:
1854  host_dereference (&host, MDL);
1855  return;
1856  }
1857 
1858  if (!parse_lbrace (cfile))
1859  goto boom;
1860 
1861  do {
1862  token = peek_token (&val, (unsigned *)0, cfile);
1863  if (token == RBRACE) {
1864  skip_token(&val, (unsigned *)0, cfile);
1865  break;
1866  }
1867  if (token == END_OF_FILE) {
1868  skip_token(&val, (unsigned *)0, cfile);
1869  parse_warn (cfile, "unexpected end of file");
1870  break;
1871  }
1872  /* If the host declaration was created by the server,
1873  remember to save it. */
1874  if (token == DYNAMIC) {
1875  dynamicp = 1;
1876  skip_token(&val, (unsigned *)0, cfile);
1877  if (!parse_semi (cfile))
1878  break;
1879  continue;
1880  }
1881  /* If the host declaration was created by the server,
1882  remember to save it. */
1883  if (token == TOKEN_DELETED) {
1884  deleted = 1;
1885  skip_token(&val, (unsigned *)0, cfile);
1886  if (!parse_semi (cfile))
1887  break;
1888  continue;
1889  }
1890 
1891  if (token == GROUP) {
1892  struct group_object *go;
1893  skip_token(&val, (unsigned *)0, cfile);
1894  token = next_token (&val, (unsigned *)0, cfile);
1895  if (token != STRING && !is_identifier (token)) {
1896  parse_warn (cfile,
1897  "expecting string or identifier.");
1898  skip_to_rbrace (cfile, 1);
1899  break;
1900  }
1901  go = (struct group_object *)0;
1902  if (!group_hash_lookup (&go, group_name_hash,
1903  val, strlen (val), MDL)) {
1904  parse_warn (cfile, "unknown group %s in host %s",
1905  val, host -> name);
1906  } else {
1907  if (host -> named_group)
1908  group_object_dereference
1909  (&host -> named_group, MDL);
1910  group_object_reference (&host -> named_group,
1911  go, MDL);
1912  group_object_dereference (&go, MDL);
1913  }
1914  if (!parse_semi (cfile))
1915  break;
1916  continue;
1917  }
1918 
1919  if (token == UID) {
1920  const char *s;
1921  unsigned char *t = 0;
1922  unsigned len;
1923 
1924  skip_token(&val, (unsigned *)0, cfile);
1925  data_string_forget (&host -> client_identifier, MDL);
1926 
1927  if (host->client_identifier.len != 0) {
1928  parse_warn(cfile, "Host %s already has a "
1929  "client identifier.",
1930  host->name);
1931  break;
1932  }
1933 
1934  /* See if it's a string or a cshl. */
1935  token = peek_token (&val, (unsigned *)0, cfile);
1936  if (token == STRING) {
1937  skip_token(&val, &len, cfile);
1938  s = val;
1939  host -> client_identifier.terminated = 1;
1940  } else {
1941  len = 0;
1943  (cfile,
1944  (unsigned char *)0, &len, ':', 16, 8);
1945  if (!t) {
1946  parse_warn (cfile,
1947  "expecting hex list.");
1948  skip_to_semi (cfile);
1949  }
1950  s = (const char *)t;
1951  }
1952  if (!buffer_allocate
1953  (&host -> client_identifier.buffer,
1954  len + host -> client_identifier.terminated, MDL))
1955  log_fatal ("no memory for uid for host %s.",
1956  host -> name);
1957  host -> client_identifier.data =
1958  host -> client_identifier.buffer -> data;
1959  host -> client_identifier.len = len;
1960  memcpy (host -> client_identifier.buffer -> data, s,
1961  len + host -> client_identifier.terminated);
1962  if (t)
1963  dfree (t, MDL);
1964 
1965  if (!parse_semi (cfile))
1966  break;
1967  continue;
1968  }
1969 
1970  if (token == HOST_IDENTIFIER) {
1971  if (host->host_id_option != NULL) {
1972  parse_warn(cfile,
1973  "only one host-identifier allowed "
1974  "per host");
1975  skip_to_rbrace(cfile, 1);
1976  break;
1977  }
1978  skip_token(&val, NULL, cfile);
1979  token = next_token(&val, NULL, cfile);
1980  if (token == V6RELOPT) {
1981  token = next_token(&val, NULL, cfile);
1982  if (token != NUMBER) {
1983  parse_warn(cfile,
1984  "host-identifier v6relopt "
1985  "must have a number");
1986  skip_to_rbrace(cfile, 1);
1987  break;
1988  }
1989  host->relays = atoi(val);
1990  if (host->relays < 0) {
1991  parse_warn(cfile,
1992  "host-identifier v6relopt "
1993  "must have a number >= 0");
1994  skip_to_rbrace(cfile, 1);
1995  break;
1996  }
1997  } else if (token != OPTION) {
1998  parse_warn(cfile,
1999  "host-identifier must be an option"
2000  " or v6relopt");
2001  skip_to_rbrace(cfile, 1);
2002  break;
2003  }
2004  known = 0;
2005  option = NULL;
2006  status = parse_option_name(cfile, 1, &known, &option);
2007  if ((status != ISC_R_SUCCESS) || (option == NULL)) {
2008  break;
2009  }
2010  if (!known) {
2011  parse_warn(cfile, "unknown option %s.%s",
2012  option->universe->name,
2013  option->name);
2014  skip_to_rbrace(cfile, 1);
2015  break;
2016  }
2017 
2018  if (! parse_option_data(&expr, cfile, 1, option)) {
2019  skip_to_rbrace(cfile, 1);
2020  option_dereference(&option, MDL);
2021  break;
2022  }
2023 
2024  if (!parse_semi(cfile)) {
2025  skip_to_rbrace(cfile, 1);
2026  expression_dereference(&expr, MDL);
2027  option_dereference(&option, MDL);
2028  break;
2029  }
2030 
2031  option_reference(&host->host_id_option, option, MDL);
2032  option_dereference(&option, MDL);
2033  data_string_copy(&host->host_id,
2034  &expr->data.const_data, MDL);
2035  expression_dereference(&expr, MDL);
2036  continue;
2037  }
2038 
2039  declaration = parse_statement(cfile, host->group, HOST_DECL,
2040  host, declaration);
2041  } while (1);
2042 
2043  if (deleted) {
2044  struct host_decl *hp = (struct host_decl *)0;
2045  if (host_hash_lookup (&hp, host_name_hash,
2046  (unsigned char *)host -> name,
2047  strlen (host -> name), MDL)) {
2048  delete_host (hp, 0);
2049  host_dereference (&hp, MDL);
2050  }
2051  } else {
2052  if (host -> named_group && host -> named_group -> group) {
2053  if (host -> group -> statements ||
2054  (host -> group -> authoritative !=
2055  host -> named_group -> group -> authoritative)) {
2056  if (host -> group -> next)
2057  group_dereference (&host -> group -> next,
2058  MDL);
2059  group_reference (&host -> group -> next,
2060  host -> named_group -> group,
2061  MDL);
2062  } else {
2063  group_dereference (&host -> group, MDL);
2064  group_reference (&host -> group,
2065  host -> named_group -> group,
2066  MDL);
2067  }
2068  }
2069 
2070  if (dynamicp)
2071  host -> flags |= HOST_DECL_DYNAMIC;
2072  else
2073  host -> flags |= HOST_DECL_STATIC;
2074 
2075  status = enter_host (host, dynamicp, 0);
2076  if (status != ISC_R_SUCCESS)
2077  parse_warn (cfile, "host %s: %s", host -> name,
2078  isc_result_totext (status));
2079  }
2080  host_dereference (&host, MDL);
2081 }
2082 
2083 /* class-declaration :== STRING LBRACE parameters declarations RBRACE
2084 */
2085 
2086 int parse_class_declaration (cp, cfile, group, type)
2087  struct class **cp;
2088  struct parse *cfile;
2089  struct group *group;
2090  int type;
2091 {
2092  const char *val;
2093  enum dhcp_token token;
2094  struct class *class = NULL, *pc = NULL;
2095  int declaration = 0;
2096  int lose = 0;
2097  struct data_string data;
2098  char *name;
2099  const char *tname;
2100  struct executable_statement *stmt = NULL;
2101  int new = 1;
2102  isc_result_t status = ISC_R_FAILURE;
2103  int matchedonce = 0;
2104  int submatchedonce = 0;
2105  unsigned code;
2106 
2107  token = next_token (&val, NULL, cfile);
2108  if (token != STRING) {
2109  parse_warn (cfile, "Expecting class name");
2110  skip_to_semi (cfile);
2111  return 0;
2112  }
2113 
2114  /* See if there's already a class with the specified name. */
2115  find_class (&pc, val, MDL);
2116 
2117  /* If it is a class, we're updating it. If it's any of the other
2118  * types (subclass, vendor or user class), the named class is a
2119  * reference to the parent class so its mandatory.
2120  */
2121  if (pc && (type == CLASS_TYPE_CLASS)) {
2122  class_reference(&class, pc, MDL);
2123  new = 0;
2124  class_dereference(&pc, MDL);
2125  } else if (!pc && (type != CLASS_TYPE_CLASS)) {
2126  parse_warn(cfile, "no class named %s", val);
2127  skip_to_semi(cfile);
2128  return 0;
2129  }
2130 
2131  /* The old vendor-class and user-class declarations had an implicit
2132  match. We don't do the implicit match anymore. Instead, for
2133  backward compatibility, we have an implicit-vendor-class and an
2134  implicit-user-class. vendor-class and user-class declarations
2135  are turned into subclasses of the implicit classes, and the
2136  submatch expression of the implicit classes extracts the contents of
2137  the vendor class or user class. */
2138  if ((type == CLASS_TYPE_VENDOR) || (type == CLASS_TYPE_USER)) {
2139  data.len = strlen (val);
2140  data.buffer = NULL;
2141  if (!buffer_allocate (&data.buffer, data.len + 1, MDL))
2142  log_fatal ("no memory for class name.");
2143  data.data = &data.buffer -> data [0];
2144  data.terminated = 1;
2145 
2146  tname = type ? "implicit-vendor-class" : "implicit-user-class";
2147  } else if (type == CLASS_TYPE_CLASS) {
2148  tname = val;
2149  } else {
2150  tname = NULL;
2151  }
2152 
2153  if (tname) {
2154  name = dmalloc (strlen (tname) + 1, MDL);
2155  if (!name)
2156  log_fatal ("No memory for class name %s.", tname);
2157  strcpy (name, val);
2158  } else
2159  name = NULL;
2160 
2161  /* If this is a straight subclass, parse the hash string. */
2162  if (type == CLASS_TYPE_SUBCLASS) {
2163  token = peek_token (&val, NULL, cfile);
2164  if (token == STRING) {
2165  skip_token(&val, &data.len, cfile);
2166  data.buffer = NULL;
2167 
2168  if (!buffer_allocate (&data.buffer,
2169  data.len + 1, MDL)) {
2170  if (pc)
2171  class_dereference (&pc, MDL);
2172 
2173  return 0;
2174  }
2175  data.terminated = 1;
2176  data.data = &data.buffer -> data [0];
2177  memcpy ((char *)data.buffer -> data, val,
2178  data.len + 1);
2179  } else if (token == NUMBER_OR_NAME || token == NUMBER) {
2180  memset (&data, 0, sizeof data);
2181  if (!parse_cshl (&data, cfile)) {
2182  if (pc)
2183  class_dereference (&pc, MDL);
2184  return 0;
2185  }
2186  } else {
2187  parse_warn (cfile, "Expecting string or hex list.");
2188  if (pc)
2189  class_dereference (&pc, MDL);
2190  return 0;
2191  }
2192  }
2193 
2194  /* See if there's already a class in the hash table matching the
2195  hash data. */
2196  if (type != CLASS_TYPE_CLASS)
2197  class_hash_lookup (&class, pc -> hash,
2198  (const char *)data.data, data.len, MDL);
2199 
2200  /* If we didn't find an existing class, allocate a new one. */
2201  if (!class) {
2202  /* Allocate the class structure... */
2203  if (type == CLASS_TYPE_SUBCLASS) {
2204  status = subclass_allocate (&class, MDL);
2205  } else {
2206  status = class_allocate (&class, MDL);
2207  }
2208  if (pc) {
2209  group_reference (&class -> group, pc -> group, MDL);
2210  class_reference (&class -> superclass, pc, MDL);
2211  class -> lease_limit = pc -> lease_limit;
2212  if (class -> lease_limit) {
2213  class -> billed_leases =
2214  dmalloc (class -> lease_limit *
2215  sizeof (struct lease *), MDL);
2216  if (!class -> billed_leases)
2217  log_fatal ("no memory for billing");
2218  memset (class -> billed_leases, 0,
2219  (class -> lease_limit *
2220  sizeof (struct lease *)));
2221  }
2222  data_string_copy (&class -> hash_string, &data, MDL);
2223  if (!pc -> hash &&
2224  !class_new_hash (&pc->hash, SCLASS_HASH_SIZE, MDL))
2225  log_fatal ("No memory for subclass hash.");
2226  class_hash_add (pc -> hash,
2227  (const char *)class -> hash_string.data,
2228  class -> hash_string.len,
2229  (void *)class, MDL);
2230  } else {
2231  if (class->group)
2233  if (!clone_group (&class -> group, group, MDL))
2234  log_fatal ("no memory to clone class group.");
2235  }
2236 
2237  /* If this is an implicit vendor or user class, add a
2238  statement that causes the vendor or user class ID to
2239  be sent back in the reply. */
2240  if (type == CLASS_TYPE_VENDOR || type == CLASS_TYPE_USER) {
2241  stmt = NULL;
2242  if (!executable_statement_allocate (&stmt, MDL))
2243  log_fatal ("no memory for class statement.");
2244  stmt -> op = supersede_option_statement;
2245  if (option_cache_allocate (&stmt -> data.option,
2246  MDL)) {
2247  stmt -> data.option -> data = data;
2248  code = (type == CLASS_TYPE_VENDOR)
2250  : DHO_USER_CLASS;
2251  option_code_hash_lookup(
2252  &stmt->data.option->option,
2254  &code, 0, MDL);
2255  }
2256  class -> statements = stmt;
2257  }
2258 
2259  /* Save the name, if there is one. */
2260  if (class->name != NULL)
2261  dfree(class->name, MDL);
2262  class->name = name;
2263  }
2264 
2265  if (type != CLASS_TYPE_CLASS)
2266  data_string_forget(&data, MDL);
2267 
2268  /* Spawned classes don't have to have their own settings. */
2269  if (class -> superclass) {
2270  token = peek_token (&val, NULL, cfile);
2271  if (token == SEMI) {
2272  skip_token(&val, NULL, cfile);
2273 
2274  if (cp)
2275  status = class_reference (cp, class, MDL);
2276  class_dereference (&class, MDL);
2277  if (pc)
2278  class_dereference (&pc, MDL);
2279  return cp ? (status == ISC_R_SUCCESS) : 1;
2280  }
2281  /* Give the subclass its own group. */
2282  if (!clone_group (&class -> group, class -> group, MDL))
2283  log_fatal ("can't clone class group.");
2284 
2285  }
2286 
2287  if (!parse_lbrace (cfile)) {
2288  class_dereference (&class, MDL);
2289  if (pc)
2290  class_dereference (&pc, MDL);
2291  return 0;
2292  }
2293 
2294  do {
2295  token = peek_token (&val, NULL, cfile);
2296  if (token == RBRACE) {
2297  skip_token(&val, NULL, cfile);
2298  break;
2299  } else if (token == END_OF_FILE) {
2300  skip_token(&val, NULL, cfile);
2301  parse_warn (cfile, "unexpected end of file");
2302  break;
2303  } else if (token == DYNAMIC) {
2304  class->flags |= CLASS_DECL_DYNAMIC;
2305  skip_token(&val, NULL, cfile);
2306  if (!parse_semi (cfile))
2307  break;
2308  continue;
2309  } else if (token == TOKEN_DELETED) {
2310  class->flags |= CLASS_DECL_DELETED;
2311  skip_token(&val, NULL, cfile);
2312  if (!parse_semi (cfile))
2313  break;
2314  continue;
2315  } else if (token == MATCH) {
2316  if (pc) {
2317  parse_warn (cfile,
2318  "invalid match in subclass.");
2319  skip_to_semi (cfile);
2320  break;
2321  }
2322  skip_token(&val, NULL, cfile);
2323  token = peek_token (&val, NULL, cfile);
2324  if (token != IF)
2325  goto submatch;
2326  skip_token(&val, NULL, cfile);
2327  if (matchedonce) {
2328  parse_warn(cfile, "A class may only have "
2329  "one 'match if' clause.");
2330  skip_to_semi(cfile);
2331  break;
2332  }
2333  matchedonce = 1;
2334  if (class->expr)
2336  if (!parse_boolean_expression (&class->expr, cfile,
2337  &lose)) {
2338  if (!lose) {
2339  parse_warn (cfile,
2340  "expecting boolean expr.");
2341  skip_to_semi (cfile);
2342  }
2343  } else {
2344 #if defined (DEBUG_EXPRESSION_PARSE)
2345  print_expression ("class match",
2346  class -> expr);
2347 #endif
2348  parse_semi (cfile);
2349  }
2350  } else if (token == SPAWN) {
2351  skip_token(&val, NULL, cfile);
2352  if (pc) {
2353  parse_warn (cfile,
2354  "invalid spawn in subclass.");
2355  skip_to_semi (cfile);
2356  break;
2357  }
2358  class -> spawning = 1;
2359  token = next_token (&val, NULL, cfile);
2360  if (token != WITH) {
2361  parse_warn (cfile,
2362  "expecting with after spawn");
2363  skip_to_semi (cfile);
2364  break;
2365  }
2366  submatch:
2367  if (submatchedonce) {
2368  parse_warn (cfile,
2369  "can't override existing %s.",
2370  "submatch/spawn");
2371  skip_to_semi (cfile);
2372  break;
2373  }
2374  submatchedonce = 1;
2375  if (class->submatch)
2377  if (!parse_data_expression (&class -> submatch,
2378  cfile, &lose)) {
2379  if (!lose) {
2380  parse_warn (cfile,
2381  "expecting data expr.");
2382  skip_to_semi (cfile);
2383  }
2384  } else {
2385 #if defined (DEBUG_EXPRESSION_PARSE)
2386  print_expression ("class submatch",
2387  class -> submatch);
2388 #endif
2389  parse_semi (cfile);
2390  }
2391  } else if (token == LEASE) {
2392  skip_token(&val, NULL, cfile);
2393  token = next_token (&val, NULL, cfile);
2394  if (token != LIMIT) {
2395  parse_warn (cfile, "expecting \"limit\"");
2396  if (token != SEMI)
2397  skip_to_semi (cfile);
2398  break;
2399  }
2400  token = next_token (&val, NULL, cfile);
2401  if (token != NUMBER) {
2402  parse_warn (cfile, "expecting a number");
2403  if (token != SEMI)
2404  skip_to_semi (cfile);
2405  break;
2406  }
2407  class -> lease_limit = atoi (val);
2408  if (class->billed_leases)
2410  class -> billed_leases =
2411  dmalloc (class -> lease_limit *
2412  sizeof (struct lease *), MDL);
2413  if (!class -> billed_leases)
2414  log_fatal ("no memory for billed leases.");
2415  memset (class -> billed_leases, 0,
2416  (class -> lease_limit *
2417  sizeof (struct lease *)));
2419  parse_semi (cfile);
2420  } else {
2421  declaration = parse_statement (cfile, class -> group,
2422  CLASS_DECL, NULL,
2423  declaration);
2424  }
2425  } while (1);
2426 
2427  if (class->flags & CLASS_DECL_DELETED) {
2428  if (type == CLASS_TYPE_CLASS) {
2429  struct class *theclass = NULL;
2430 
2431  status = find_class(&theclass, class->name, MDL);
2432  if (status == ISC_R_SUCCESS) {
2433  delete_class(theclass, 0);
2434  class_dereference(&theclass, MDL);
2435  }
2436  } else {
2437  class_hash_delete(pc->hash,
2438  (char *)class->hash_string.data,
2439  class->hash_string.len, MDL);
2440  }
2441  } else if (type == CLASS_TYPE_CLASS && new) {
2442  if (!collections -> classes)
2443  class_reference (&collections -> classes, class, MDL);
2444  else {
2445  struct class *c;
2446  for (c = collections -> classes;
2447  c -> nic; c = c -> nic)
2448  ;
2449  class_reference (&c -> nic, class, MDL);
2450  }
2451  }
2452 
2453  if (cp) /* should always be 0??? */
2454  status = class_reference (cp, class, MDL);
2455  class_dereference (&class, MDL);
2456  if (pc)
2457  class_dereference (&pc, MDL);
2458  return cp ? (status == ISC_R_SUCCESS) : 1;
2459 }
2460 
2461 /* shared-network-declaration :==
2462  hostname LBRACE declarations parameters RBRACE */
2463 
2464 void parse_shared_net_declaration (cfile, group)
2465  struct parse *cfile;
2466  struct group *group;
2467 {
2468  const char *val;
2469  enum dhcp_token token;
2470  struct shared_network *share;
2471  char *name;
2472  int declaration = 0;
2473  isc_result_t status;
2474 
2475  share = (struct shared_network *)0;
2476  status = shared_network_allocate (&share, MDL);
2477  if (status != ISC_R_SUCCESS)
2478  log_fatal ("Can't allocate shared subnet: %s",
2479  isc_result_totext (status));
2480  if (clone_group (&share -> group, group, MDL) == 0) {
2481  log_fatal ("Can't clone group for shared net");
2482  }
2483  shared_network_reference (&share -> group -> shared_network,
2484  share, MDL);
2485 
2486  /* Get the name of the shared network... */
2487  token = peek_token (&val, (unsigned *)0, cfile);
2488  if (token == STRING) {
2489  skip_token(&val, (unsigned *)0, cfile);
2490 
2491  if (val [0] == 0) {
2492  parse_warn (cfile, "zero-length shared network name");
2493  val = "<no-name-given>";
2494  }
2495  name = dmalloc (strlen (val) + 1, MDL);
2496  if (!name)
2497  log_fatal ("no memory for shared network name");
2498  strcpy (name, val);
2499  } else {
2500  name = parse_host_name (cfile);
2501  if (!name) {
2502  parse_warn (cfile,
2503  "expecting a name for shared-network");
2504  skip_to_semi (cfile);
2505  shared_network_dereference (&share, MDL);
2506  return;
2507  }
2508  }
2509  share -> name = name;
2510 
2511  if (!parse_lbrace (cfile)) {
2512  shared_network_dereference (&share, MDL);
2513  return;
2514  }
2515 
2516  do {
2517  token = peek_token (&val, (unsigned *)0, cfile);
2518  if (token == RBRACE) {
2519  skip_token(&val, (unsigned *)0, cfile);
2520  if (!share -> subnets)
2521  parse_warn (cfile,
2522  "empty shared-network decl");
2523  else
2524  enter_shared_network (share);
2525  shared_network_dereference (&share, MDL);
2526  return;
2527  } else if (token == END_OF_FILE) {
2528  skip_token(&val, (unsigned *)0, cfile);
2529  parse_warn (cfile, "unexpected end of file");
2530  break;
2531  } else if (token == INTERFACE) {
2532  skip_token(&val, (unsigned *)0, cfile);
2533  token = next_token (&val, (unsigned *)0, cfile);
2534  new_shared_network_interface (cfile, share, val);
2535  if (!parse_semi (cfile))
2536  break;
2537  continue;
2538  }
2539 
2540  declaration = parse_statement (cfile, share -> group,
2542  (struct host_decl *)0,
2543  declaration);
2544  } while (1);
2545  shared_network_dereference (&share, MDL);
2546 }
2547 
2548 
2549 static int
2550 common_subnet_parsing(struct parse *cfile,
2551  struct shared_network *share,
2552  struct subnet *subnet) {
2553  enum dhcp_token token;
2554  struct subnet *t, *u;
2555  const char *val;
2556  int declaration = 0;
2557 
2558  enter_subnet(subnet);
2559 
2560  if (!parse_lbrace(cfile)) {
2561  subnet_dereference(&subnet, MDL);
2562  return 0;
2563  }
2564 
2565  do {
2566  token = peek_token(&val, NULL, cfile);
2567  if (token == RBRACE) {
2568  skip_token(&val, NULL, cfile);
2569  break;
2570  } else if (token == END_OF_FILE) {
2571  skip_token(&val, NULL, cfile);
2572  parse_warn (cfile, "unexpected end of file");
2573  break;
2574  } else if (token == INTERFACE) {
2575  skip_token(&val, NULL, cfile);
2576  token = next_token(&val, NULL, cfile);
2577  new_shared_network_interface(cfile, share, val);
2578  if (!parse_semi(cfile))
2579  break;
2580  continue;
2581  }
2582  declaration = parse_statement(cfile, subnet->group,
2583  SUBNET_DECL,
2584  NULL,
2585  declaration);
2586  } while (1);
2587 
2588  /* Add the subnet to the list of subnets in this shared net. */
2589  if (share->subnets == NULL) {
2590  subnet_reference(&share->subnets, subnet, MDL);
2591  } else {
2592  u = NULL;
2593  for (t = share->subnets; t->next_sibling; t = t->next_sibling) {
2594  if (subnet_inner_than(subnet, t, 0)) {
2595  subnet_reference(&subnet->next_sibling, t, MDL);
2596  if (u) {
2597  subnet_dereference(&u->next_sibling,
2598  MDL);
2599  subnet_reference(&u->next_sibling,
2600  subnet, MDL);
2601  } else {
2602  subnet_dereference(&share->subnets,
2603  MDL);
2604  subnet_reference(&share->subnets,
2605  subnet, MDL);
2606  }
2607  subnet_dereference(&subnet, MDL);
2608  return 1;
2609  }
2610  u = t;
2611  }
2612  subnet_reference(&t->next_sibling, subnet, MDL);
2613  }
2614  subnet_dereference(&subnet, MDL);
2615  return 1;
2616 }
2617 
2618 /* subnet-declaration :==
2619  net NETMASK netmask RBRACE parameters declarations LBRACE */
2620 
2621 void parse_subnet_declaration (cfile, share)
2622  struct parse *cfile;
2623  struct shared_network *share;
2624 {
2625  const char *val;
2626  enum dhcp_token token;
2627  struct subnet *subnet;
2628  struct iaddr iaddr;
2629  unsigned char addr [4];
2630  unsigned len = sizeof addr;
2631  isc_result_t status;
2632 
2633  subnet = (struct subnet *)0;
2634  status = subnet_allocate (&subnet, MDL);
2635  if (status != ISC_R_SUCCESS)
2636  log_fatal ("Allocation of new subnet failed: %s",
2637  isc_result_totext (status));
2638  shared_network_reference (&subnet -> shared_network, share, MDL);
2639 
2640  /*
2641  * If our parent shared network was implicitly created by the software,
2642  * and not explicitly configured by the user, then we actually put all
2643  * configuration scope in the parent (the shared network and subnet
2644  * share the same {}-level scope).
2645  *
2646  * Otherwise, we clone the parent group and continue as normal.
2647  */
2648  if (share->flags & SHARED_IMPLICIT) {
2649  group_reference(&subnet->group, share->group, MDL);
2650  } else {
2651  if (!clone_group(&subnet->group, share->group, MDL)) {
2652  log_fatal("Allocation of group for new subnet failed.");
2653  }
2654  }
2655  subnet_reference (&subnet -> group -> subnet, subnet, MDL);
2656 
2657  /* Get the network number... */
2658  if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) {
2659  subnet_dereference (&subnet, MDL);
2660  return;
2661  }
2662  memcpy (iaddr.iabuf, addr, len);
2663  iaddr.len = len;
2664  subnet -> net = iaddr;
2665 
2666  token = next_token (&val, (unsigned *)0, cfile);
2667  if (token != NETMASK) {
2668  parse_warn (cfile, "Expecting netmask");
2669  skip_to_semi (cfile);
2670  return;
2671  }
2672 
2673  /* Get the netmask... */
2674  if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) {
2675  subnet_dereference (&subnet, MDL);
2676  return;
2677  }
2678  memcpy (iaddr.iabuf, addr, len);
2679  iaddr.len = len;
2680  subnet -> netmask = iaddr;
2681 
2682  /* Validate the network number/netmask pair. */
2683  if (host_addr (subnet -> net, subnet -> netmask)) {
2684  char *maskstr;
2685 
2686  maskstr = strdup (piaddr (subnet -> netmask));
2687  parse_warn (cfile,
2688  "subnet %s netmask %s: bad subnet number/mask combination.",
2689  piaddr (subnet -> net), maskstr);
2690  free(maskstr);
2691  subnet_dereference (&subnet, MDL);
2692  skip_to_semi (cfile);
2693  return;
2694  }
2695 
2696  common_subnet_parsing(cfile, share, subnet);
2697 }
2698 
2699 /* subnet6-declaration :==
2700  net / bits RBRACE parameters declarations LBRACE */
2701 
2702 void
2703 parse_subnet6_declaration(struct parse *cfile, struct shared_network *share) {
2704 #if !defined(DHCPv6)
2705  parse_warn(cfile, "No DHCPv6 support.");
2706  skip_to_semi(cfile);
2707 #else /* defined(DHCPv6) */
2708  struct subnet *subnet;
2709  isc_result_t status;
2710  enum dhcp_token token;
2711  const char *val;
2712  char *endp;
2713  int ofs;
2714  const static int mask[] = { 0x00, 0x80, 0xC0, 0xE0,
2715  0xF0, 0xF8, 0xFC, 0xFE };
2716  struct iaddr iaddr;
2717 
2718  if (local_family != AF_INET6) {
2719  parse_warn(cfile, "subnet6 statement is only supported "
2720  "in DHCPv6 mode.");
2721  skip_to_semi(cfile);
2722  return;
2723  }
2724 
2725  subnet = NULL;
2726  status = subnet_allocate(&subnet, MDL);
2727  if (status != ISC_R_SUCCESS) {
2728  log_fatal("Allocation of new subnet failed: %s",
2729  isc_result_totext(status));
2730  }
2731  shared_network_reference(&subnet->shared_network, share, MDL);
2732 
2733  /*
2734  * If our parent shared network was implicitly created by the software,
2735  * and not explicitly configured by the user, then we actually put all
2736  * configuration scope in the parent (the shared network and subnet
2737  * share the same {}-level scope).
2738  *
2739  * Otherwise, we clone the parent group and continue as normal.
2740  */
2741  if (share->flags & SHARED_IMPLICIT) {
2742  group_reference(&subnet->group, share->group, MDL);
2743  } else {
2744  if (!clone_group(&subnet->group, share->group, MDL)) {
2745  log_fatal("Allocation of group for new subnet failed.");
2746  }
2747  }
2748  subnet_reference(&subnet->group->subnet, subnet, MDL);
2749 
2750  if (!parse_ip6_addr(cfile, &subnet->net)) {
2751  subnet_dereference(&subnet, MDL);
2752  return;
2753  }
2754 
2755  token = next_token(&val, NULL, cfile);
2756  if (token != SLASH) {
2757  parse_warn(cfile, "Expecting a '/'.");
2758  skip_to_semi(cfile);
2759  return;
2760  }
2761 
2762  token = next_token(&val, NULL, cfile);
2763  if (token != NUMBER) {
2764  parse_warn(cfile, "Expecting a number.");
2765  skip_to_semi(cfile);
2766  return;
2767  }
2768 
2769  subnet->prefix_len = strtol(val, &endp, 10);
2770  if ((subnet->prefix_len < 0) ||
2771  (subnet->prefix_len > 128) ||
2772  (*endp != '\0')) {
2773  parse_warn(cfile, "Expecting a number between 0 and 128.");
2774  skip_to_semi(cfile);
2775  return;
2776  }
2777 
2778  if (!is_cidr_mask_valid(&subnet->net, subnet->prefix_len)) {
2779  parse_warn(cfile, "New subnet mask too short.");
2780  skip_to_semi(cfile);
2781  return;
2782  }
2783 
2784  /*
2785  * Create a netmask.
2786  */
2787  subnet->netmask.len = 16;
2788  ofs = subnet->prefix_len / 8;
2789  if (ofs < subnet->netmask.len) {
2790  subnet->netmask.iabuf[ofs] = mask[subnet->prefix_len % 8];
2791  }
2792  while (--ofs >= 0) {
2793  subnet->netmask.iabuf[ofs] = 0xFF;
2794  }
2795 
2796  /* Validate the network number/netmask pair. */
2797  iaddr = subnet_number(subnet->net, subnet->netmask);
2798  if (memcmp(&iaddr, &subnet->net, 16) != 0) {
2799  parse_warn(cfile,
2800  "subnet %s/%d: prefix not long enough for address.",
2801  piaddr(subnet->net), subnet->prefix_len);
2802  subnet_dereference(&subnet, MDL);
2803  skip_to_semi(cfile);
2804  return;
2805  }
2806 
2807  if (!common_subnet_parsing(cfile, share, subnet)) {
2808  return;
2809  }
2810 #endif /* defined(DHCPv6) */
2811 }
2812 
2813 /* group-declaration :== RBRACE parameters declarations LBRACE */
2814 
2815 void parse_group_declaration (cfile, group)
2816  struct parse *cfile;
2817  struct group *group;
2818 {
2819  const char *val;
2820  enum dhcp_token token;
2821  struct group *g;
2822  int declaration = 0;
2823  struct group_object *t = NULL;
2824  isc_result_t status;
2825  char *name = NULL;
2826  int deletedp = 0;
2827  int dynamicp = 0;
2828  int staticp = 0;
2829 
2830  g = NULL;
2831  if (!clone_group(&g, group, MDL))
2832  log_fatal("no memory for explicit group.");
2833 
2834  token = peek_token(&val, NULL, cfile);
2835  if (is_identifier (token) || token == STRING) {
2836  skip_token(&val, NULL, cfile);
2837 
2838  name = dmalloc(strlen(val) + 1, MDL);
2839  if (!name)
2840  log_fatal("no memory for group decl name %s", val);
2841  strcpy(name, val);
2842  }
2843 
2844  if (!parse_lbrace(cfile)) {
2845  group_dereference(&g, MDL);
2846  return;
2847  }
2848 
2849  do {
2850  token = peek_token(&val, NULL, cfile);
2851  if (token == RBRACE) {
2852  skip_token(&val, NULL, cfile);
2853  break;
2854  } else if (token == END_OF_FILE) {
2855  skip_token(&val, NULL, cfile);
2856  parse_warn(cfile, "unexpected end of file");
2857  break;
2858  } else if (token == TOKEN_DELETED) {
2859  skip_token(&val, NULL, cfile);
2860  parse_semi(cfile);
2861  deletedp = 1;
2862  } else if (token == DYNAMIC) {
2863  skip_token(&val, NULL, cfile);
2864  parse_semi(cfile);
2865  dynamicp = 1;
2866  } else if (token == STATIC) {
2867  skip_token(&val, NULL, cfile);
2868  parse_semi(cfile);
2869  staticp = 1;
2870  }
2871  declaration = parse_statement(cfile, g, GROUP_DECL,
2872  NULL, declaration);
2873  } while (1);
2874 
2875  if (name) {
2876  if (deletedp) {
2877  if (group_name_hash) {
2878  t = NULL;
2879  if (group_hash_lookup(&t, group_name_hash,
2880  name,
2881  strlen(name), MDL)) {
2882  delete_group(t, 0);
2883  }
2884  }
2885  } else {
2886  t = NULL;
2887  status = group_object_allocate(&t, MDL);
2888  if (status != ISC_R_SUCCESS)
2889  log_fatal("no memory for group decl %s: %s",
2890  val, isc_result_totext(status));
2891  group_reference(&t->group, g, MDL);
2892  t->name = name;
2893  /* no need to include deletedp as it's handled above */
2894  t->flags = ((staticp ? GROUP_OBJECT_STATIC : 0) |
2895  (dynamicp ? GROUP_OBJECT_DYNAMIC : 0));
2896  supersede_group(t, 0);
2897  }
2898  if (t != NULL)
2899  group_object_dereference(&t, MDL);
2900  }
2901 }
2902 
2903 /* fixed-addr-parameter :== ip-addrs-or-hostnames SEMI
2904  ip-addrs-or-hostnames :== ip-addr-or-hostname
2905  | ip-addrs-or-hostnames ip-addr-or-hostname */
2906 
2907 int
2909  struct parse *cfile,
2910  enum dhcp_token type) {
2911  int parse_ok;
2912  const char *val;
2913  enum dhcp_token token;
2914  struct expression *expr = NULL;
2915  struct expression *tmp, *new;
2916  int status;
2917 
2918  do {
2919  tmp = NULL;
2920  if (type == FIXED_ADDR) {
2921  parse_ok = parse_ip_addr_or_hostname(&tmp, cfile, 1);
2922  } else {
2923  /* INSIST(type == FIXED_ADDR6); */
2924  parse_ok = parse_ip6_addr_expr(&tmp, cfile);
2925  }
2926  if (parse_ok) {
2927  if (expr != NULL) {
2928  new = NULL;
2929  status = make_concat(&new, expr, tmp);
2930  expression_dereference(&expr, MDL);
2931  expression_dereference(&tmp, MDL);
2932  if (!status) {
2933  return 0;
2934  }
2935  expr = new;
2936  } else {
2937  expr = tmp;
2938  }
2939  } else {
2940  if (expr != NULL) {
2941  expression_dereference (&expr, MDL);
2942  }
2943  return 0;
2944  }
2945  token = peek_token(&val, NULL, cfile);
2946  if (token == COMMA) {
2947  token = next_token(&val, NULL, cfile);
2948  }
2949  } while (token == COMMA);
2950 
2951  if (!parse_semi(cfile)) {
2952  if (expr) {
2953  expression_dereference (&expr, MDL);
2954  }
2955  return 0;
2956  }
2957 
2958  status = option_cache(oc, NULL, expr, NULL, MDL);
2959  expression_dereference(&expr, MDL);
2960  return status;
2961 }
2962 
2963 /* lease_declaration :== LEASE ip_address LBRACE lease_parameters RBRACE
2964 
2965  lease_parameters :== <nil>
2966  | lease_parameter
2967  | lease_parameters lease_parameter
2968 
2969  lease_parameter :== STARTS date
2970  | ENDS date
2971  | TIMESTAMP date
2972  | HARDWARE hardware-parameter
2973  | UID hex_numbers SEMI
2974  | HOSTNAME hostname SEMI
2975  | CLIENT_HOSTNAME hostname SEMI
2976  | CLASS identifier SEMI
2977  | DYNAMIC_BOOTP SEMI */
2978 
2979 int parse_lease_declaration (struct lease **lp, struct parse *cfile)
2980 {
2981  const char *val;
2982  enum dhcp_token token;
2983  unsigned char addr [4];
2984  unsigned len = sizeof addr;
2985  int seenmask = 0;
2986  int seenbit;
2987  char tbuf [32];
2988  struct lease *lease;
2989  struct executable_statement *on;
2990  int lose;
2991  TIME t;
2992  int noequal, newbinding;
2993  struct binding *binding;
2994  struct binding_value *nv;
2995  isc_result_t status;
2996  struct option_cache *oc;
2997  pair *p;
2998  binding_state_t new_state;
2999  unsigned buflen = 0;
3000  struct class *class;
3001 
3002  lease = (struct lease *)0;
3003  status = lease_allocate (&lease, MDL);
3004  if (status != ISC_R_SUCCESS)
3005  return 0;
3006 
3007  /* Get the address for which the lease has been issued. */
3008  if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) {
3009  lease_dereference (&lease, MDL);
3010  return 0;
3011  }
3012  memcpy (lease -> ip_addr.iabuf, addr, len);
3013  lease -> ip_addr.len = len;
3014 
3015  if (!parse_lbrace (cfile)) {
3016  lease_dereference (&lease, MDL);
3017  return 0;
3018  }
3019 
3020  do {
3021  token = next_token (&val, (unsigned *)0, cfile);
3022  if (token == RBRACE)
3023  break;
3024  else if (token == END_OF_FILE) {
3025  parse_warn (cfile, "unexpected end of file");
3026  break;
3027  }
3028  strncpy (tbuf, val, sizeof tbuf);
3029  tbuf [(sizeof tbuf) - 1] = 0;
3030 
3031  /* Parse any of the times associated with the lease. */
3032  switch (token) {
3033  case STARTS:
3034  case ENDS:
3035  case TIMESTAMP:
3036  case TSTP:
3037  case TSFP:
3038  case ATSFP:
3039  case CLTT:
3040  t = parse_date (cfile);
3041  switch (token) {
3042  case STARTS:
3043  seenbit = 1;
3044  lease -> starts = t;
3045  break;
3046 
3047  case ENDS:
3048  seenbit = 2;
3049  lease -> ends = t;
3050  break;
3051 
3052  case TSTP:
3053  seenbit = 65536;
3054  lease -> tstp = t;
3055  break;
3056 
3057  case TSFP:
3058  seenbit = 131072;
3059  lease -> tsfp = t;
3060  break;
3061 
3062  case ATSFP:
3063  seenbit = 262144;
3064  lease->atsfp = t;
3065  break;
3066 
3067  case CLTT:
3068  seenbit = 524288;
3069  lease -> cltt = t;
3070  break;
3071 
3072  default: /* for gcc, we'll never get here. */
3073  log_fatal ("Impossible error at %s:%d.", MDL);
3074  return 0;
3075  }
3076  break;
3077 
3078  /* Colon-separated hexadecimal octets... */
3079  case UID:
3080  seenbit = 8;
3081  token = peek_token (&val, (unsigned *)0, cfile);
3082  if (token == STRING) {
3083  unsigned char *tuid;
3084  skip_token(&val, &buflen, cfile);
3085  if (buflen < sizeof lease -> uid_buf) {
3086  tuid = lease -> uid_buf;
3087  lease -> uid_max =
3088  sizeof lease -> uid_buf;
3089  } else {
3090  tuid = ((unsigned char *)
3091  dmalloc (buflen, MDL));
3092  if (!tuid) {
3093  log_error ("no space for uid");
3094  lease_dereference (&lease,
3095  MDL);
3096  return 0;
3097  }
3098  lease -> uid_max = buflen;
3099  }
3100  lease -> uid_len = buflen;
3101  memcpy (tuid, val, lease -> uid_len);
3102  lease -> uid = tuid;
3103  } else {
3104  buflen = 0;
3105  lease -> uid = (parse_numeric_aggregate
3106  (cfile, (unsigned char *)0,
3107  &buflen, ':', 16, 8));
3108  if (!lease -> uid) {
3109  lease_dereference (&lease, MDL);
3110  return 0;
3111  }
3112  lease -> uid_len = buflen;
3113  lease -> uid_max = buflen;
3114  if (lease -> uid_len == 0) {
3115  lease -> uid = (unsigned char *)0;
3116  parse_warn (cfile, "zero-length uid");
3117  seenbit = 0;
3118  parse_semi (cfile);
3119  break;
3120  }
3121  }
3122  parse_semi (cfile);
3123  if (!lease -> uid) {
3124  log_fatal ("No memory for lease uid");
3125  }
3126  break;
3127 
3128  case CLASS:
3129  seenbit = 32;
3130  token = next_token (&val, (unsigned *)0, cfile);
3131  if (!is_identifier (token)) {
3132  if (token != SEMI)
3133  skip_to_rbrace (cfile, 1);
3134  lease_dereference (&lease, MDL);
3135  return 0;
3136  }
3137  parse_semi (cfile);
3138  /* for now, we aren't using this. */
3139  break;
3140 
3141  case HARDWARE:
3142  seenbit = 64;
3143  parse_hardware_param (cfile,
3144  &lease -> hardware_addr);
3145  break;
3146 
3147  case TOKEN_RESERVED:
3148  seenbit = 0;
3149  lease->flags |= RESERVED_LEASE;
3150  parse_semi(cfile);
3151  break;
3152 
3153  case DYNAMIC_BOOTP:
3154  seenbit = 0;
3155  lease -> flags |= BOOTP_LEASE;
3156  parse_semi (cfile);
3157  break;
3158 
3159  /* XXX: Reverse compatibility? */
3160  case TOKEN_ABANDONED:
3161  seenbit = 256;
3162  lease -> binding_state = FTS_ABANDONED;
3163  lease -> next_binding_state = FTS_ABANDONED;
3164  parse_semi (cfile);
3165  break;
3166 
3167  case TOKEN_NEXT:
3168  seenbit = 128;
3169  token = next_token (&val, (unsigned *)0, cfile);
3170  if (token != BINDING) {
3171  parse_warn (cfile, "expecting 'binding'");
3172  skip_to_semi (cfile);
3173  break;
3174  }
3175  goto do_binding_state;
3176 
3177  case REWIND:
3178  seenbit = 512;
3179  token = next_token(&val, NULL, cfile);
3180  if (token != BINDING) {
3181  parse_warn(cfile, "expecting 'binding'");
3182  skip_to_semi(cfile);
3183  break;
3184  }
3185  goto do_binding_state;
3186 
3187  case BINDING:
3188  seenbit = 256;
3189 
3190  do_binding_state:
3191  token = next_token (&val, (unsigned *)0, cfile);
3192  if (token != STATE) {
3193  parse_warn (cfile, "expecting 'state'");
3194  skip_to_semi (cfile);
3195  break;
3196  }
3197  token = next_token (&val, (unsigned *)0, cfile);
3198  switch (token) {
3199  case TOKEN_ABANDONED:
3200  new_state = FTS_ABANDONED;
3201  break;
3202  case TOKEN_FREE:
3203  new_state = FTS_FREE;
3204  break;
3205  case TOKEN_ACTIVE:
3206  new_state = FTS_ACTIVE;
3207  break;
3208  case TOKEN_EXPIRED:
3209  new_state = FTS_EXPIRED;
3210  break;
3211  case TOKEN_RELEASED:
3212  new_state = FTS_RELEASED;
3213  break;
3214  case TOKEN_RESET:
3215  new_state = FTS_RESET;
3216  break;
3217  case TOKEN_BACKUP:
3218  new_state = FTS_BACKUP;
3219  break;
3220 
3221  /* RESERVED and BOOTP states preserved for
3222  * compatibleness with older versions.
3223  */
3224  case TOKEN_RESERVED:
3225  new_state = FTS_ACTIVE;
3226  lease->flags |= RESERVED_LEASE;
3227  break;
3228  case TOKEN_BOOTP:
3229  new_state = FTS_ACTIVE;
3230  lease->flags |= BOOTP_LEASE;
3231  break;
3232 
3233  default:
3234  parse_warn (cfile,
3235  "%s: expecting a binding state.",
3236  val);
3237  skip_to_semi (cfile);
3238  return 0;
3239  }
3240 
3241  if (seenbit == 256) {
3242  lease -> binding_state = new_state;
3243 
3244  /*
3245  * Apply default/conservative next/rewind
3246  * binding states if they haven't been set
3247  * yet. These defaults will be over-ridden if
3248  * they are set later in parsing.
3249  */
3250  if (!(seenmask & 128))
3251  lease->next_binding_state = new_state;
3252 
3253  /* The most conservative rewind state. */
3254  if (!(seenmask & 512))
3255  lease->rewind_binding_state = new_state;
3256  } else if (seenbit == 128)
3257  lease -> next_binding_state = new_state;
3258  else if (seenbit == 512)
3259  lease->rewind_binding_state = new_state;
3260  else
3261  log_fatal("Impossible condition at %s:%d.",
3262  MDL);
3263 
3264  parse_semi (cfile);
3265  break;
3266 
3267  case CLIENT_HOSTNAME:
3268  seenbit = 1024;
3269  token = peek_token (&val, (unsigned *)0, cfile);
3270  if (token == STRING) {
3271  if (!parse_string (cfile,
3272  &lease -> client_hostname,
3273  (unsigned *)0)) {
3274  lease_dereference (&lease, MDL);
3275  return 0;
3276  }
3277  } else {
3278  lease -> client_hostname =
3279  parse_host_name (cfile);
3280  if (lease -> client_hostname)
3281  parse_semi (cfile);
3282  else {
3283  parse_warn (cfile,
3284  "expecting a hostname.");
3285  skip_to_semi (cfile);
3286  lease_dereference (&lease, MDL);
3287  return 0;
3288  }
3289  }
3290  break;
3291 
3292  case BILLING:
3293  seenbit = 2048;
3294  class = (struct class *)0;
3295  token = next_token (&val, (unsigned *)0, cfile);
3296  if (token == CLASS) {
3297  token = next_token (&val,
3298  (unsigned *)0, cfile);
3299  if (token != STRING) {
3300  parse_warn (cfile, "expecting string");
3301  if (token != SEMI)
3302  skip_to_semi (cfile);
3303  token = BILLING;
3304  break;
3305  }
3306  if (lease -> billing_class)
3307  class_dereference (&lease -> billing_class,
3308  MDL);
3309  find_class (&class, val, MDL);
3310  if (!class)
3311  parse_warn (cfile,
3312  "unknown class %s", val);
3313  parse_semi (cfile);
3314  } else if (token == SUBCLASS) {
3315  if (lease -> billing_class)
3316  class_dereference (&lease -> billing_class,
3317  MDL);
3318  parse_class_declaration(&class, cfile, NULL,
3320  } else {
3321  parse_warn (cfile, "expecting \"class\"");
3322  if (token != SEMI)
3323  skip_to_semi (cfile);
3324  }
3325  if (class) {
3326  class_reference (&lease -> billing_class,
3327  class, MDL);
3328  class_dereference (&class, MDL);
3329  }
3330  break;
3331 
3332  case ON:
3333  on = (struct executable_statement *)0;
3334  lose = 0;
3335  if (!parse_on_statement (&on, cfile, &lose)) {
3336  skip_to_rbrace (cfile, 1);
3337  lease_dereference (&lease, MDL);
3338  return 0;
3339  }
3340  seenbit = 0;
3341  if ((on->data.on.evtypes & ON_EXPIRY) &&
3342  on->data.on.statements) {
3343  seenbit |= 16384;
3345  (&lease->on_star.on_expiry,
3346  on->data.on.statements, MDL);
3347  }
3348  if ((on->data.on.evtypes & ON_RELEASE) &&
3349  on->data.on.statements) {
3350  seenbit |= 32768;
3352  (&lease->on_star.on_release,
3353  on->data.on.statements, MDL);
3354  }
3356  break;
3357 
3358  case OPTION:
3359  case SUPERSEDE:
3360  noequal = 0;
3361  seenbit = 0;
3362  oc = (struct option_cache *)0;
3363  if (parse_option_decl (&oc, cfile)) {
3364  if (oc -> option -> universe !=
3365  &agent_universe) {
3366  parse_warn (cfile,
3367  "agent option expected.");
3369  break;
3370  }
3371  if (!lease -> agent_options &&
3373  (&lease -> agent_options, MDL))) {
3374  log_error ("no memory to stash agent option");
3375  break;
3376  }
3377  for (p = &lease -> agent_options -> first;
3378  *p; p = &((*p) -> cdr))
3379  ;
3380  *p = cons (0, 0);
3381  option_cache_reference (((struct option_cache **)
3382  &((*p) -> car)), oc, MDL);
3384  }
3385  break;
3386 
3387  case TOKEN_SET:
3388  noequal = 0;
3389 
3390  token = next_token (&val, (unsigned *)0, cfile);
3391  if (token != NAME && token != NUMBER_OR_NAME) {
3392  parse_warn (cfile,
3393  "%s can't be a variable name",
3394  val);
3395  badset:
3396  skip_to_semi (cfile);
3397  lease_dereference (&lease, MDL);
3398  return 0;
3399  }
3400 
3401  seenbit = 0;
3402  special_set:
3403  if (lease -> scope)
3404  binding = find_binding (lease -> scope, val);
3405  else
3406  binding = (struct binding *)0;
3407 
3408  if (!binding) {
3409  if (!lease -> scope)
3411  (&lease -> scope, MDL)))
3412  log_fatal ("no memory for scope");
3413  binding = dmalloc (sizeof *binding, MDL);
3414  if (!binding)
3415  log_fatal ("No memory for lease %s.",
3416  "binding");
3417  memset (binding, 0, sizeof *binding);
3418  binding -> name =
3419  dmalloc (strlen (val) + 1, MDL);
3420  if (!binding -> name)
3421  log_fatal ("No memory for binding %s.",
3422  "name");
3423  strcpy (binding -> name, val);
3424  newbinding = 1;
3425  } else {
3426  newbinding = 0;
3427  }
3428 
3429  nv = NULL;
3430  if (!binding_value_allocate(&nv, MDL))
3431  log_fatal("no memory for binding value.");
3432 
3433  if (!noequal) {
3434  token = next_token (&val, (unsigned *)0, cfile);
3435  if (token != EQUAL) {
3436  parse_warn (cfile,
3437  "expecting '=' in set statement.");
3438  goto badset;
3439  }
3440  }
3441 
3442  if (!parse_binding_value(cfile, nv)) {
3444  lease_dereference(&lease, MDL);
3445  return 0;
3446  }
3447 
3448  if (newbinding) {
3449  binding_value_reference(&binding->value,
3450  nv, MDL);
3451  binding->next = lease->scope->bindings;
3452  lease->scope->bindings = binding;
3453  } else {
3454  binding_value_dereference(&binding->value, MDL);
3455  binding_value_reference(&binding->value,
3456  nv, MDL);
3457  }
3458 
3460  parse_semi(cfile);
3461  break;
3462 
3463  /* case NAME: */
3464  default:
3465  if (!strcasecmp (val, "ddns-fwd-name")) {
3466  seenbit = 4096;
3467  noequal = 1;
3468  goto special_set;
3469  } else if (!strcasecmp (val, "ddns-rev-name")) {
3470  seenbit = 8192;
3471  noequal = 1;
3472  goto special_set;
3473  } else
3474  parse_warn(cfile, "Unexpected configuration "
3475  "directive.");
3476  skip_to_semi (cfile);
3477  seenbit = 0;
3478  lease_dereference (&lease, MDL);
3479  return 0;
3480  }
3481 
3482  if (seenmask & seenbit) {
3483  parse_warn (cfile,
3484  "Too many %s parameters in lease %s\n",
3485  tbuf, piaddr (lease -> ip_addr));
3486  } else
3487  seenmask |= seenbit;
3488 
3489  } while (1);
3490 
3491  /* If no binding state is specified, make one up. */
3492  if (!(seenmask & 256)) {
3493  if (lease->ends > cur_time ||
3494  lease->on_star.on_expiry || lease->on_star.on_release)
3495  lease->binding_state = FTS_ACTIVE;
3496 #if defined (FAILOVER_PROTOCOL)
3497  else if (lease->pool && lease->pool->failover_peer)
3498  lease->binding_state = FTS_EXPIRED;
3499 #endif
3500  else
3501  lease->binding_state = FTS_FREE;
3502  if (lease->binding_state == FTS_ACTIVE) {
3503 #if defined (FAILOVER_PROTOCOL)
3504  if (lease->pool && lease->pool->failover_peer)
3506  else
3507 #endif
3508  lease->next_binding_state = FTS_FREE;
3509  } else
3510  lease->next_binding_state = lease->binding_state;
3511 
3512  /* The most conservative rewind state implies no rewind. */
3513  lease->rewind_binding_state = lease->binding_state;
3514  }
3515 
3516  if (!(seenmask & 65536))
3517  lease->tstp = lease->ends;
3518 
3519  lease_reference (lp, lease, MDL);
3520  lease_dereference (&lease, MDL);
3521  return 1;
3522 }
3523 
3524 /* Parse the right side of a 'binding value'.
3525  *
3526  * set foo = "bar"; is a string
3527  * set foo = false; is a boolean
3528  * set foo = %31; is a numeric value.
3529  */
3530 static int
3531 parse_binding_value(struct parse *cfile, struct binding_value *value)
3532 {
3533  struct data_string *data;
3534  unsigned char *s;
3535  const char *val;
3536  unsigned buflen;
3537  int token;
3538 
3539  if ((cfile == NULL) || (value == NULL))
3540  log_fatal("Invalid arguments at %s:%d.", MDL);
3541 
3542  token = peek_token(&val, NULL, cfile);
3543  if (token == STRING) {
3544  skip_token(&val, &buflen, cfile);
3545 
3546  value->type = binding_data;
3547  value->value.data.len = buflen;
3548 
3549  data = &value->value.data;
3550 
3551  if (!buffer_allocate(&data->buffer, buflen + 1, MDL))
3552  log_fatal ("No memory for binding.");
3553 
3554  memcpy(data->buffer->data, val, buflen + 1);
3555 
3556  data->data = data->buffer->data;
3557  data->terminated = 1;
3558  } else if (token == NUMBER_OR_NAME) {
3559  value->type = binding_data;
3560 
3561  data = &value->value.data;
3562  s = parse_numeric_aggregate(cfile, NULL, &data->len,
3563  ':', 16, 8);
3564  if (s == NULL) {
3565  skip_to_semi(cfile);
3566  return 0;
3567  }
3568 
3569  if (data->len) {
3570  if (!buffer_allocate(&data->buffer, data->len + 1,
3571  MDL))
3572  log_fatal("No memory for binding.");
3573 
3574  memcpy(data->buffer->data, s, data->len);
3575  data->data = data->buffer->data;
3576 
3577  dfree (s, MDL);
3578  }
3579  } else if (token == PERCENT) {
3580  skip_token(&val, NULL, cfile);
3581  token = next_token(&val, NULL, cfile);
3582  if (token != NUMBER) {
3583  parse_warn(cfile, "expecting decimal number.");
3584  if (token != SEMI)
3585  skip_to_semi(cfile);
3586  return 0;
3587  }
3588  value->type = binding_numeric;
3589  value->value.intval = atol(val);
3590  } else if (token == NAME) {
3591  token = next_token(&val, NULL, cfile);
3592  value->type = binding_boolean;
3593  if (!strcasecmp(val, "true"))
3594  value->value.boolean = 1;
3595  else if (!strcasecmp(val, "false"))
3596  value->value.boolean = 0;
3597  else {
3598  parse_warn(cfile, "expecting true or false");
3599  if (token != SEMI)
3600  skip_to_semi(cfile);
3601  return 0;
3602  }
3603  } else {
3604  parse_warn (cfile, "expecting a constant value.");
3605  if (token != SEMI)
3606  skip_to_semi (cfile);
3607  return 0;
3608  }
3609 
3610  return 1;
3611 }
3612 
3613 /* address-range-declaration :== ip-address ip-address SEMI
3614  | DYNAMIC_BOOTP ip-address ip-address SEMI */
3615 
3616 void parse_address_range (cfile, group, type, inpool, lpchain)
3617  struct parse *cfile;
3618  struct group *group;
3619  int type;
3620  struct pool *inpool;
3621  struct lease **lpchain;
3622 {
3623  struct iaddr low, high, net;
3624  unsigned char addr [4];
3625  unsigned len = sizeof addr;
3626  enum dhcp_token token;
3627  const char *val;
3628  int dynamic = 0;
3629  struct subnet *subnet;
3630  struct shared_network *share;
3631  struct pool *pool;
3632  isc_result_t status;
3633 
3634  if ((token = peek_token (&val,
3635  (unsigned *)0, cfile)) == DYNAMIC_BOOTP) {
3636  skip_token(&val, (unsigned *)0, cfile);
3637  dynamic = 1;
3638  }
3639 
3640  /* Get the bottom address in the range... */
3641  if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
3642  return;
3643  memcpy (low.iabuf, addr, len);
3644  low.len = len;
3645 
3646  /* Only one address? */
3647  token = peek_token (&val, (unsigned *)0, cfile);
3648  if (token == SEMI)
3649  high = low;
3650  else {
3651  /* Get the top address in the range... */
3652  if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
3653  return;
3654  memcpy (high.iabuf, addr, len);
3655  high.len = len;
3656  }
3657 
3658  token = next_token (&val, (unsigned *)0, cfile);
3659  if (token != SEMI) {
3660  parse_warn (cfile, "semicolon expected.");
3661  skip_to_semi (cfile);
3662  return;
3663  }
3664 
3665  if (type == SUBNET_DECL) {
3666  subnet = group -> subnet;
3667  share = subnet -> shared_network;
3668  } else {
3669  share = group -> shared_network;
3670  for (subnet = share -> subnets;
3671  subnet; subnet = subnet -> next_sibling) {
3672  net = subnet_number (low, subnet -> netmask);
3673  if (addr_eq (net, subnet -> net))
3674  break;
3675  }
3676  if (!subnet) {
3677  parse_warn (cfile, "address range not on network %s",
3678  group -> shared_network -> name);
3679  log_error ("Be sure to place pool statement after %s",
3680  "related subnet declarations.");
3681  return;
3682  }
3683  }
3684 
3685  if (!inpool) {
3686  struct pool *last = (struct pool *)0;
3687 
3688  /* If we're permitting dynamic bootp for this range,
3689  then look for a pool with an empty prohibit list and
3690  a permit list with one entry that permits all clients. */
3691  for (pool = share -> pools; pool; pool = pool -> next) {
3692  if ((!dynamic && !pool -> permit_list &&
3693  pool -> prohibit_list &&
3694  !pool -> prohibit_list -> next &&
3695  (pool -> prohibit_list -> type ==
3696  permit_dynamic_bootp_clients)) ||
3697  (dynamic && !pool -> prohibit_list &&
3698  pool -> permit_list &&
3699  !pool -> permit_list -> next &&
3700  (pool -> permit_list -> type ==
3701  permit_all_clients))) {
3702  break;
3703  }
3704  last = pool;
3705  }
3706 
3707  /* If we didn't get a pool, make one. */
3708  if (!pool) {
3709  struct permit *p;
3710  status = pool_allocate (&pool, MDL);
3711  if (status != ISC_R_SUCCESS)
3712  log_fatal ("no memory for ad-hoc pool: %s",
3713  isc_result_totext (status));
3714  p = new_permit (MDL);
3715  if (!p)
3716  log_fatal ("no memory for ad-hoc permit.");
3717 
3718  /* Dynamic pools permit all clients. Otherwise
3719  we prohibit BOOTP clients. */
3720  if (dynamic) {
3721  p -> type = permit_all_clients;
3722  pool -> permit_list = p;
3723  } else {
3724  p -> type = permit_dynamic_bootp_clients;
3725  pool -> prohibit_list = p;
3726  }
3727 
3728  if (share -> pools)
3729  pool_reference (&last -> next, pool, MDL);
3730  else
3731  pool_reference (&share -> pools, pool, MDL);
3732  shared_network_reference (&pool -> shared_network,
3733  share, MDL);
3734  if (!clone_group (&pool -> group, share -> group, MDL))
3735  log_fatal ("no memory for anon pool group.");
3736  } else {
3737  pool = (struct pool *)0;
3738  if (last)
3739  pool_reference (&pool, last, MDL);
3740  else
3741  pool_reference (&pool, share -> pools, MDL);
3742  }
3743  } else {
3744  pool = (struct pool *)0;
3745  pool_reference (&pool, inpool, MDL);
3746  }
3747 
3748 #if defined (FAILOVER_PROTOCOL)
3749  if (pool -> failover_peer && dynamic) {
3750  /* Doctor, do you think I'm overly sensitive
3751  about getting bug reports I can't fix? */
3752  parse_warn (cfile, "dynamic-bootp flag is %s",
3753  "not permitted for address");
3754  log_error ("range declarations where there is a failover");
3755  log_error ("peer in scope. If you wish to declare an");
3756  log_error ("address range from which dynamic bootp leases");
3757  log_error ("can be allocated, please declare it within a");
3758  log_error ("pool declaration that also contains the \"no");
3759  log_error ("failover\" statement. The failover protocol");
3760  log_error ("itself does not permit dynamic bootp - this");
3761  log_error ("is not a limitation specific to the ISC DHCP");
3762  log_error ("server. Please don't ask me to defend this");
3763  log_error ("until you have read and really tried %s",
3764  "to understand");
3765  log_error ("the failover protocol specification.");
3766 
3767  /* We don't actually bomb at this point - instead,
3768  we let parse_lease_file notice the error and
3769  bomb at that point - it's easier. */
3770  }
3771 #endif /* FAILOVER_PROTOCOL */
3772 
3773  /* Create the new address range... */
3774  new_address_range (cfile, low, high, subnet, pool, lpchain);
3775  pool_dereference (&pool, MDL);
3776 }
3777 
3778 #ifdef DHCPv6
3779 static void
3780 add_ipv6_pool_to_subnet(struct subnet *subnet, u_int16_t type,
3781  struct iaddr *lo_addr, int bits, int units,
3782  struct ipv6_pond *pond) {
3783  struct ipv6_pool *pool;
3784  struct in6_addr tmp_in6_addr;
3785  int num_pools;
3786  struct ipv6_pool **tmp;
3787 
3788  /*
3789  * Create our pool.
3790  */
3791  if (lo_addr->len != sizeof(tmp_in6_addr)) {
3792  log_fatal("Internal error: Attempt to add non-IPv6 address "
3793  "to IPv6 shared network.");
3794  }
3795  memcpy(&tmp_in6_addr, lo_addr->iabuf, sizeof(tmp_in6_addr));
3796  pool = NULL;
3797  if (ipv6_pool_allocate(&pool, type, &tmp_in6_addr,
3798  bits, units, MDL) != ISC_R_SUCCESS) {
3799  log_fatal("Out of memory");
3800  }
3801 
3802  /*
3803  * Add to our global IPv6 pool set.
3804  */
3805  if (add_ipv6_pool(pool) != ISC_R_SUCCESS) {
3806  log_fatal ("Out of memory");
3807  }
3808 
3809  /*
3810  * Link the pool to its network.
3811  */
3812  pool->subnet = NULL;
3813  subnet_reference(&pool->subnet, subnet, MDL);
3814  pool->shared_network = NULL;
3815  shared_network_reference(&pool->shared_network,
3816  subnet->shared_network, MDL);
3817  pool->ipv6_pond = NULL;
3818  ipv6_pond_reference(&pool->ipv6_pond, pond, MDL);
3819 
3820  /*
3821  * Increase our array size for ipv6_pools in the pond
3822  */
3823  if (pond->ipv6_pools == NULL) {
3824  num_pools = 0;
3825  } else {
3826  num_pools = 0;
3827  while (pond->ipv6_pools[num_pools] != NULL) {
3828  num_pools++;
3829  }
3830  }
3831  tmp = dmalloc(sizeof(struct ipv6_pool *) * (num_pools + 2), MDL);
3832  if (tmp == NULL) {
3833  log_fatal("Out of memory");
3834  }
3835  if (num_pools > 0) {
3836  memcpy(tmp, pond->ipv6_pools,
3837  sizeof(struct ipv6_pool *) * num_pools);
3838  }
3839  if (pond->ipv6_pools != NULL) {
3840  dfree(pond->ipv6_pools, MDL);
3841  }
3842  pond->ipv6_pools = tmp;
3843 
3844  /*
3845  * Record this pool in our array of pools for this shared network.
3846  */
3847  ipv6_pool_reference(&pond->ipv6_pools[num_pools], pool, MDL);
3848  pond->ipv6_pools[num_pools+1] = NULL;
3849 
3850  /* Update the number of elements in the pond. Conveniently
3851  * we have the total size of the block in bits and the amount
3852  * we would allocate per element in units. For an address units
3853  * will always be 128, for a prefix it will be something else.
3854  *
3855  * We need to make sure the number of elements isn't too large
3856  * to track. If so, we flag it to avoid wasting time with log
3857  * threshold logic. We also emit a log stating that log-threshold
3858  * will be disabled for the shared-network but that's done
3859  * elsewhere via report_log_threshold().
3860  *
3861  */
3862 
3863  /* Only bother if we aren't already flagged as jumbo */
3864  if (pond->jumbo_range == 0) {
3865  if ((units - bits) > (sizeof(isc_uint64_t) * 8)) {
3866  pond->jumbo_range = 1;
3867  pond->num_total = POND_TRACK_MAX;
3868  }
3869  else {
3870  isc_uint64_t space_left
3871  = POND_TRACK_MAX - pond->num_total;
3872  isc_uint64_t addon
3873  = (isc_uint64_t)(1) << (units - bits);
3874 
3875  if (addon > space_left) {
3876  pond->jumbo_range = 1;
3877  pond->num_total = POND_TRACK_MAX;
3878  } else {
3879  pond->num_total += addon;
3880  }
3881  }
3882  }
3883 }
3884 
3911 static void
3912 add_ipv6_pond_to_network(struct group *group,
3913  struct ipv6_pond **ret_pond) {
3914 
3915  struct ipv6_pond *pond = NULL, *last = NULL;
3916  struct permit *p;
3917  isc_result_t status;
3918  struct shared_network *shared = group->subnet->shared_network;
3919 
3920  for (pond = shared->ipv6_pond; pond; pond = pond->next) {
3921  if ((pond->group->statements == group->statements) &&
3922  (pond->prohibit_list == NULL) &&
3923  (pond->permit_list != NULL) &&
3924  (pond->permit_list->next == NULL) &&
3925  (pond->permit_list->type == permit_all_clients)) {
3926  ipv6_pond_reference(ret_pond, pond, MDL);
3927  return;
3928  }
3929  last = pond;
3930  }
3931 
3932  /* no pond available, make one */
3933  status = ipv6_pond_allocate(&pond, MDL);
3934  if (status != ISC_R_SUCCESS)
3935  log_fatal ("no memory for ad-hoc ipv6 pond: %s",
3936  isc_result_totext (status));
3937  p = new_permit (MDL);
3938  if (p == NULL)
3939  log_fatal ("no memory for ad-hoc ipv6 permit.");
3940 
3941  /* we permit all clients */
3942  p->type = permit_all_clients;
3943  pond->permit_list = p;
3944 
3945  /* and attach the pond to the return argument and the shared network */
3946  ipv6_pond_reference(ret_pond, pond, MDL);
3947 
3948  if (shared->ipv6_pond)
3949  ipv6_pond_reference(&last->next, pond, MDL);
3950  else
3951  ipv6_pond_reference(&shared->ipv6_pond, pond, MDL);
3952 
3953  shared_network_reference(&pond->shared_network, shared, MDL);
3954  if (!clone_group (&pond->group, group, MDL))
3955  log_fatal ("no memory for anon pool group.");
3956 
3957  ipv6_pond_dereference(&pond, MDL);
3958  return;
3959 }
3960 
3961 
3962 /* address-range6-declaration :== ip-address6 ip-address6 SEMI
3963  | ip-address6 SLASH number SEMI
3964  | ip-address6 [SLASH number] TEMPORARY SEMI */
3965 
3966 void
3967 parse_address_range6(struct parse *cfile,
3968  struct group *group,
3969  struct ipv6_pond *inpond) {
3970  struct iaddr lo, hi;
3971  int bits;
3972  enum dhcp_token token;
3973  const char *val;
3974  struct iaddrcidrnetlist *nets, net;
3975  struct iaddrcidrnetlist *p;
3976  u_int16_t type = D6O_IA_NA;
3977  struct ipv6_pond *pond = NULL;
3978 
3979  if (local_family != AF_INET6) {
3980  parse_warn(cfile, "range6 statement is only supported "
3981  "in DHCPv6 mode.");
3982  skip_to_semi(cfile);
3983  return;
3984  }
3985 
3986  /* This is enforced by the caller, this is just a sanity check. */
3987  if (group->subnet == NULL)
3988  log_fatal("Impossible condition at %s:%d.", MDL);
3989 
3990  /*
3991  * Read starting address.
3992  */
3993  if (!parse_ip6_addr(cfile, &lo)) {
3994  return;
3995  }
3996 
3997  /* Make sure starting address is within the subnet */
3998  if (!addr_eq(group->subnet->net,
3999  subnet_number(lo, group->subnet->netmask))) {
4000  parse_warn(cfile, "range6 start address is outside the subnet");
4001  skip_to_semi(cfile);
4002  return;
4003  }
4004 
4005  /*
4006  * zero out the net entry in case we use it
4007  */
4008  memset(&net, 0, sizeof(net));
4009  net.cidrnet.lo_addr = lo;
4010 
4011  /*
4012  * See if we we're using range or CIDR notation or TEMPORARY
4013  */
4014  token = peek_token(&val, NULL, cfile);
4015  if (token == SLASH) {
4016  /*
4017  * '/' means CIDR notation, so read the bits we want.
4018  */
4019  skip_token(NULL, NULL, cfile);
4020  token = next_token(&val, NULL, cfile);
4021  if (token != NUMBER) {
4022  parse_warn(cfile, "expecting number");
4023  skip_to_semi(cfile);
4024  return;
4025  }
4026  net.cidrnet.bits = atoi(val);
4027  bits = net.cidrnet.bits;
4028  if ((bits < 0) || (bits > 128)) {
4029  parse_warn(cfile, "networks have 0 to 128 bits");
4030  skip_to_semi(cfile);
4031  return;
4032  }
4033  if (bits < group->subnet->prefix_len) {
4034  parse_warn(cfile,
4035  "network mask smaller than subnet mask");
4036  skip_to_semi(cfile);
4037  return;
4038  }
4039  if (!is_cidr_mask_valid(&net.cidrnet.lo_addr, bits)) {
4040  parse_warn(cfile, "network mask too short");
4041  skip_to_semi(cfile);
4042  return;
4043  }
4044  /*
4045  * can be temporary (RFC 4941 like)
4046  */
4047  token = peek_token(&val, NULL, cfile);
4048  if (token == TEMPORARY) {
4049  if (bits < 64)
4050  parse_warn(cfile, "temporary mask too short");
4051  if (bits == 128)
4052  parse_warn(cfile, "temporary singleton?");
4053  skip_token(NULL, NULL, cfile);
4054  type = D6O_IA_TA;
4055  }
4056 
4057  nets = &net;
4058 
4059  } else if (token == TEMPORARY) {
4060  /*
4061  * temporary (RFC 4941)
4062  */
4063  type = D6O_IA_TA;
4064  skip_token(NULL, NULL, cfile);
4065  net.cidrnet.bits = 64;
4067  net.cidrnet.bits)) {
4068  parse_warn(cfile, "network mask too short");
4069  skip_to_semi(cfile);
4070  return;
4071  }
4072 
4073  nets = &net;
4074 
4075  } else {
4076  /*
4077  * No '/', so we are looking for the end address of
4078  * the IPv6 pool.
4079  */
4080  if (!parse_ip6_addr(cfile, &hi)) {
4081  return;
4082  }
4083 
4084  /* Make sure ending address is within the subnet */
4085  if (!addr_eq(group->subnet->net,
4086  subnet_number(hi, group->subnet->netmask))) {
4087  parse_warn(cfile,
4088  "range6 end address is outside the subnet");
4089  skip_to_semi(cfile);
4090  return;
4091  }
4092 
4093  /*
4094  * Convert our range to a set of CIDR networks.
4095  */
4096  nets = NULL;
4097  if (range2cidr(&nets, &lo, &hi) != ISC_R_SUCCESS) {
4098  log_fatal("Error converting range to CIDR networks");
4099  }
4100 
4101  }
4102 
4103  /*
4104  * See if we have a pond for this set of pools.
4105  * If the caller supplied one we use it, otherwise
4106  * check the shared network
4107  */
4108 
4109  if (inpond != NULL) {
4110  ipv6_pond_reference(&pond, inpond, MDL);
4111  } else {
4112  add_ipv6_pond_to_network(group, &pond);
4113  }
4114 
4115  /* Now that we have a pond add the nets we have parsed */
4116  for (p=nets; p != NULL; p=p->next) {
4117  add_ipv6_pool_to_subnet(group->subnet, type,
4118  &p->cidrnet.lo_addr,
4119  p->cidrnet.bits, 128, pond);
4120  }
4121 
4122  /* if we allocated a list free it now */
4123  if (nets != &net)
4124  free_iaddrcidrnetlist(&nets);
4125 
4126  ipv6_pond_dereference(&pond, MDL);
4127 
4128  token = next_token(NULL, NULL, cfile);
4129  if (token != SEMI) {
4130  parse_warn(cfile, "semicolon expected.");
4131  skip_to_semi(cfile);
4132  return;
4133  }
4134 }
4135 
4136 /* prefix6-declaration :== ip-address6 ip-address6 SLASH number SEMI */
4137 
4138 void
4139 parse_prefix6(struct parse *cfile,
4140  struct group *group,
4141  struct ipv6_pond *inpond) {
4142  struct iaddr lo, hi;
4143  int bits;
4144  enum dhcp_token token;
4145  const char *val;
4146  struct iaddrcidrnetlist *nets;
4147  struct iaddrcidrnetlist *p;
4148  struct ipv6_pond *pond = NULL;
4149 
4150  if (local_family != AF_INET6) {
4151  parse_warn(cfile, "prefix6 statement is only supported "
4152  "in DHCPv6 mode.");
4153  skip_to_semi(cfile);
4154  return;
4155  }
4156 
4157  /* This is enforced by the caller, so it's just a sanity check. */
4158  if (group->subnet == NULL)
4159  log_fatal("Impossible condition at %s:%d.", MDL);
4160 
4161  /*
4162  * Read starting and ending address.
4163  */
4164  if (!parse_ip6_addr(cfile, &lo)) {
4165  return;
4166  }
4167 
4168  /* Make sure starting prefix is within the subnet */
4169  if (!addr_eq(group->subnet->net,
4170  subnet_number(lo, group->subnet->netmask))) {
4171  parse_warn(cfile, "prefix6 start prefix"
4172  " is outside the subnet");
4173  skip_to_semi(cfile);
4174  return;
4175  }
4176 
4177  if (!parse_ip6_addr(cfile, &hi)) {
4178  return;
4179  }
4180 
4181  /* Make sure ending prefix is within the subnet */
4182  if (!addr_eq(group->subnet->net,
4183  subnet_number(hi, group->subnet->netmask))) {
4184  parse_warn(cfile, "prefix6 end prefix"
4185  " is outside the subnet");
4186  skip_to_semi(cfile);
4187  return;
4188  }
4189 
4190  /*
4191  * Next is '/' number ';'.
4192  */
4193  token = next_token(NULL, NULL, cfile);
4194  if (token != SLASH) {
4195  parse_warn(cfile, "expecting '/'");
4196  if (token != SEMI)
4197  skip_to_semi(cfile);
4198  return;
4199  }
4200  token = next_token(&val, NULL, cfile);
4201  if (token != NUMBER) {
4202  parse_warn(cfile, "expecting number");
4203  if (token != SEMI)
4204  skip_to_semi(cfile);
4205  return;
4206  }
4207  bits = atoi(val);
4208  if ((bits <= 0) || (bits >= 128)) {
4209  parse_warn(cfile, "networks have 0 to 128 bits (exclusive)");
4210  return;
4211  }
4212  if (bits < group->subnet->prefix_len) {
4213  parse_warn(cfile, "network mask smaller than subnet mask");
4214  skip_to_semi(cfile);
4215  return;
4216  }
4217  if (!is_cidr_mask_valid(&lo, bits) ||
4218  !is_cidr_mask_valid(&hi, bits)) {
4219  parse_warn(cfile, "network mask too short");
4220  skip_to_semi(cfile);
4221  return;
4222  }
4223  token = next_token(NULL, NULL, cfile);
4224  if (token != SEMI) {
4225  parse_warn(cfile, "semicolon expected.");
4226  skip_to_semi(cfile);
4227  return;
4228  }
4229 
4230  /*
4231  * Convert our range to a set of CIDR networks.
4232  */
4233  nets = NULL;
4234  if (range2cidr(&nets, &lo, &hi) != ISC_R_SUCCESS) {
4235  log_fatal("Error converting prefix to CIDR");
4236  }
4237 
4238  /*
4239  * See if we have a pond for this set of pools.
4240  * If the caller supplied one we use it, otherwise
4241  * check the shared network
4242  */
4243 
4244  if (inpond != NULL) {
4245  ipv6_pond_reference(&pond, inpond, MDL);
4246  } else {
4247  add_ipv6_pond_to_network(group, &pond);
4248  }
4249 
4250  for (p = nets; p != NULL; p = p->next) {
4251  /* Normalize and check. */
4252  if (p->cidrnet.bits == 128) {
4253  p->cidrnet.bits = bits;
4254  }
4255  if (p->cidrnet.bits > bits) {
4256  parse_warn(cfile, "impossible mask length");
4257  continue;
4258  }
4259  add_ipv6_pool_to_subnet(group->subnet, D6O_IA_PD,
4260  &p->cidrnet.lo_addr,
4261  p->cidrnet.bits, bits, pond);
4262  }
4263 
4264  free_iaddrcidrnetlist(&nets);
4265 }
4266 
4267 /* fixed-prefix6 :== ip6-address SLASH number SEMI */
4268 
4269 void
4270 parse_fixed_prefix6(struct parse *cfile, struct host_decl *host_decl) {
4271  struct iaddrcidrnetlist *ia, **h;
4272  enum dhcp_token token;
4273  const char *val;
4274 
4275  /*
4276  * Get the head of the fixed-prefix list.
4277  */
4278  h = &host_decl->fixed_prefix;
4279 
4280  /*
4281  * Walk to the end.
4282  */
4283  while (*h != NULL) {
4284  h = &((*h)->next);
4285  }
4286 
4287  /*
4288  * Allocate a new iaddrcidrnetlist structure.
4289  */
4290  ia = dmalloc(sizeof(*ia), MDL);
4291  if (!ia) {
4292  log_fatal("Out of memory");
4293  }
4294 
4295  /*
4296  * Parse it.
4297  */
4298  if (!parse_ip6_addr(cfile, &ia->cidrnet.lo_addr)) {
4299  dfree(ia, MDL);
4300  return;
4301  }
4302  token = next_token(NULL, NULL, cfile);
4303  if (token != SLASH) {
4304  dfree(ia, MDL);
4305  parse_warn(cfile, "expecting '/'");
4306  if (token != SEMI)
4307  skip_to_semi(cfile);
4308  return;
4309  }
4310  token = next_token(&val, NULL, cfile);
4311  if (token != NUMBER) {
4312  dfree(ia, MDL);
4313  parse_warn(cfile, "expecting number");
4314  if (token != SEMI)
4315  skip_to_semi(cfile);
4316  return;
4317  }
4318  token = next_token(NULL, NULL, cfile);
4319  if (token != SEMI) {
4320  dfree(ia, MDL);
4321  parse_warn(cfile, "semicolon expected.");
4322  skip_to_semi(cfile);
4323  return;
4324  }
4325 
4326  /*
4327  * Fill it.
4328  */
4329  ia->cidrnet.bits = atoi(val);
4330  if ((ia->cidrnet.bits < 0) || (ia->cidrnet.bits > 128)) {
4331  dfree(ia, MDL);
4332  parse_warn(cfile, "networks have 0 to 128 bits");
4333  return;
4334  }
4335  if (!is_cidr_mask_valid(&ia->cidrnet.lo_addr, ia->cidrnet.bits)) {
4336  dfree(ia, MDL);
4337  parse_warn(cfile, "network mask too short");
4338  return;
4339  }
4340 
4341  /*
4342  * Store it.
4343  */
4344  *h = ia;
4345  return;
4346 }
4347 
4367 void parse_pool6_statement (cfile, group, type)
4368  struct parse *cfile;
4369  struct group *group;
4370  int type;
4371 {
4372  enum dhcp_token token;
4373  const char *val;
4374  int done = 0;
4375  struct ipv6_pond *pond, **p;
4376  int declaration = 0;
4377  isc_result_t status;
4378 
4379  pond = NULL;
4380  status = ipv6_pond_allocate(&pond, MDL);
4381  if (status != ISC_R_SUCCESS)
4382  log_fatal("no memory for pool6: %s",
4383  isc_result_totext (status));
4384 
4385  if (type == SUBNET_DECL)
4386  shared_network_reference(&pond->shared_network,
4387  group->subnet->shared_network,
4388  MDL);
4389  else {
4390  parse_warn(cfile, "pool6s are only valid inside "
4391  "subnet statements.");
4392  ipv6_pond_dereference(&pond, MDL);
4393  skip_to_semi(cfile);
4394  return;
4395  }
4396 
4397  if (clone_group(&pond->group, group, MDL) == 0)
4398  log_fatal("can't clone pool6 group.");
4399 
4400  if (parse_lbrace(cfile) == 0) {
4401  ipv6_pond_dereference(&pond, MDL);
4402  return;
4403  }
4404 
4405  do {
4406  token = peek_token(&val, NULL, cfile);
4407  switch (token) {
4408  case RANGE6:
4409  skip_token(NULL, NULL, cfile);
4410  parse_address_range6(cfile, group, pond);
4411  break;
4412 
4413  case PREFIX6:
4414  skip_token(NULL, NULL, cfile);
4415  parse_prefix6(cfile, group, pond);
4416  break;
4417 
4418  case ALLOW:
4419  skip_token(NULL, NULL, cfile);
4420  get_permit(cfile, &pond->permit_list, 1,
4421  &pond->valid_from, &pond->valid_until);
4422  break;
4423 
4424  case DENY:
4425  skip_token(NULL, NULL, cfile);
4426  get_permit(cfile, &pond->prohibit_list, 0,
4427  &pond->valid_from, &pond->valid_until);
4428  break;
4429 
4430  case RBRACE:
4431  skip_token(&val, NULL, cfile);
4432  done = 1;
4433  break;
4434 
4435  case END_OF_FILE:
4436  /*
4437  * We can get to END_OF_FILE if, for instance,
4438  * the parse_statement() reads all available tokens
4439  * and leaves us at the end.
4440  */
4441  parse_warn(cfile, "unexpected end of file");
4442  goto cleanup;
4443 
4444  default:
4445  declaration = parse_statement(cfile, pond->group,
4446  POOL_DECL, NULL,
4447  declaration);
4448  break;
4449  }
4450  } while (!done);
4451 
4452  /*
4453  * A possible optimization is to see if this pond can be merged into
4454  * an already existing pond. But I'll pass on that for now as we need
4455  * to repoint the leases to the other pond which is annoying. SAR
4456  */
4457 
4458  /*
4459  * Add this pond to the list (will need updating if we add the
4460  * optimization).
4461  */
4462 
4463  p = &pond->shared_network->ipv6_pond;
4464  for (; *p; p = &((*p)->next))
4465  ;
4466  ipv6_pond_reference(p, pond, MDL);
4467 
4468  /* Don't allow a pool6 declaration with no addresses or
4469  prefixes, since it is probably a configuration error. */
4470  if (pond->ipv6_pools == NULL) {
4471  parse_warn (cfile, "Pool6 declaration with no %s.",
4472  "address range6 or prefix6");
4473  log_error ("Pool6 declarations must always contain at least");
4474  log_error ("one range6 or prefix6 statement.");
4475  }
4476 
4477 cleanup:
4478  ipv6_pond_dereference(&pond, MDL);
4479 }
4480 
4481 
4482 
4483 #endif /* DHCPv6 */
4484 
4485 /* allow-deny-keyword :== BOOTP
4486  | BOOTING
4487  | DYNAMIC_BOOTP
4488  | UNKNOWN_CLIENTS */
4489 
4490 int parse_allow_deny (oc, cfile, flag)
4491  struct option_cache **oc;
4492  struct parse *cfile;
4493  int flag;
4494 {
4495  enum dhcp_token token;
4496  const char *val;
4497  unsigned char rf = flag;
4498  unsigned code;
4499  struct option *option = NULL;
4500  struct expression *data = (struct expression *)0;
4501  int status;
4502 
4503  if (!make_const_data (&data, &rf, 1, 0, 1, MDL))
4504  return 0;
4505 
4506  token = next_token (&val, (unsigned *)0, cfile);
4507  switch (token) {
4508  case TOKEN_BOOTP:
4509  code = SV_ALLOW_BOOTP;
4510  break;
4511 
4512  case BOOTING:
4513  code = SV_ALLOW_BOOTING;
4514  break;
4515 
4516  case DYNAMIC_BOOTP:
4517  code = SV_DYNAMIC_BOOTP;
4518  break;
4519 
4520  case UNKNOWN_CLIENTS:
4521  code = SV_BOOT_UNKNOWN_CLIENTS;
4522  break;
4523 
4524  case DUPLICATES:
4525  code = SV_DUPLICATES;
4526  break;
4527 
4528  case DECLINES:
4529  code= SV_DECLINES;
4530  break;
4531 
4532  case CLIENT_UPDATES:
4533  code = SV_CLIENT_UPDATES;
4534  break;
4535 
4536  case LEASEQUERY:
4537  code = SV_LEASEQUERY;
4538  break;
4539 
4540  default:
4541  parse_warn (cfile, "expecting allow/deny key");
4542  skip_to_semi (cfile);
4543  expression_dereference (&data, MDL);
4544  return 0;
4545  }
4546  /* Reference on option is passed to option cache. */
4547  if (!option_code_hash_lookup(&option, server_universe.code_hash,
4548  &code, 0, MDL))
4549  log_fatal("Unable to find server option %u (%s:%d).",
4550  code, MDL);
4551  status = option_cache(oc, NULL, data, option, MDL);
4552  expression_dereference (&data, MDL);
4553  parse_semi (cfile);
4554  return status;
4555 }
4556 
4557 void
4559 #if !defined(DHCPv6)
4560  parse_warn(cfile, "No DHCPv6 support.");
4561  skip_to_semi(cfile);
4562 #else /* defined(DHCPv6) */
4563  enum dhcp_token token;
4564  struct ia_xx *ia;
4565  const char *val;
4566  struct ia_xx *old_ia;
4567  unsigned int len;
4568  u_int32_t iaid;
4569  struct iaddr iaddr;
4570  binding_state_t state;
4571  u_int32_t prefer;
4572  u_int32_t valid;
4573  TIME end_time;
4574  struct iasubopt *iaaddr;
4575  struct ipv6_pool *pool;
4576  char addr_buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
4577  isc_boolean_t newbinding;
4578  struct binding_scope *scope = NULL;
4579  struct binding *bnd;
4580  struct binding_value *nv = NULL;
4581  struct executable_statement *on_star[2] = {NULL, NULL};
4582  int lose, i;
4583 
4584  if (local_family != AF_INET6) {
4585  parse_warn(cfile, "IA_NA is only supported in DHCPv6 mode.");
4586  skip_to_semi(cfile);
4587  return;
4588  }
4589 
4590  token = next_token(&val, &len, cfile);
4591  if (token != STRING) {
4592  parse_warn(cfile, "corrupt lease file; "
4593  "expecting an iaid+ia_na string");
4594  skip_to_semi(cfile);
4595  return;
4596  }
4597  if (len < 5) {
4598  parse_warn(cfile, "corrupt lease file; "
4599  "iaid+ia_na string too short");
4600  skip_to_semi(cfile);
4601  return;
4602  }
4603 
4604  memcpy(&iaid, val, 4);
4605  ia = NULL;
4606  if (ia_allocate(&ia, iaid, val+4, len-4, MDL) != ISC_R_SUCCESS) {
4607  log_fatal("Out of memory.");
4608  }
4609  ia->ia_type = D6O_IA_NA;
4610 
4611  token = next_token(&val, NULL, cfile);
4612  if (token != LBRACE) {
4613  parse_warn(cfile, "corrupt lease file; expecting left brace");
4614  skip_to_semi(cfile);
4615  return;
4616  }
4617 
4618  for (;;) {
4619  token = next_token(&val, NULL, cfile);
4620  if (token == RBRACE) break;
4621 
4622  if (token == CLTT) {
4623  ia->cltt = parse_date (cfile);
4624  continue;
4625  }
4626 
4627  if (token != IAADDR) {
4628  parse_warn(cfile, "corrupt lease file; "
4629  "expecting IAADDR or right brace");
4630  skip_to_semi(cfile);
4631  return;
4632  }
4633 
4634  if (!parse_ip6_addr(cfile, &iaddr)) {
4635  parse_warn(cfile, "corrupt lease file; "
4636  "expecting IPv6 address");
4637  skip_to_semi(cfile);
4638  return;
4639  }
4640 
4641  token = next_token(&val, NULL, cfile);
4642  if (token != LBRACE) {
4643  parse_warn(cfile, "corrupt lease file; "
4644  "expecting left brace");
4645  skip_to_semi(cfile);
4646  return;
4647  }
4648 
4649  state = FTS_LAST+1;
4650  prefer = valid = 0;
4651  end_time = -1;
4652  for (;;) {
4653  token = next_token(&val, NULL, cfile);
4654  if (token == RBRACE) break;
4655 
4656  switch(token) {
4657  /* Lease binding state. */
4658  case BINDING:
4659  token = next_token(&val, NULL, cfile);
4660  if (token != STATE) {
4661  parse_warn(cfile, "corrupt lease file; "
4662  "expecting state");
4663  skip_to_semi(cfile);
4664  return;
4665  }
4666  token = next_token(&val, NULL, cfile);
4667  switch (token) {
4668  case TOKEN_ABANDONED:
4669  state = FTS_ABANDONED;
4670  break;
4671  case TOKEN_FREE:
4672  state = FTS_FREE;
4673  break;
4674  case TOKEN_ACTIVE:
4675  state = FTS_ACTIVE;
4676  break;
4677  case TOKEN_EXPIRED:
4678  state = FTS_EXPIRED;
4679  break;
4680  case TOKEN_RELEASED:
4681  state = FTS_RELEASED;
4682  break;
4683  default:
4684  parse_warn(cfile,
4685  "corrupt lease "
4686  "file; "
4687  "expecting a "
4688  "binding state.");
4689  skip_to_semi(cfile);
4690  return;
4691  }
4692 
4693  token = next_token(&val, NULL, cfile);
4694  if (token != SEMI) {
4695  parse_warn(cfile, "corrupt lease file; "
4696  "expecting "
4697  "semicolon.");
4698  }
4699  break;
4700 
4701  /* Lease preferred lifetime. */
4702  case PREFERRED_LIFE:
4703  token = next_token(&val, NULL, cfile);
4704  if (token != NUMBER) {
4705  parse_warn(cfile, "%s is not a valid "
4706  "preferred time",
4707  val);
4708  skip_to_semi(cfile);
4709  continue;
4710  }
4711  prefer = atoi (val);
4712 
4713  /*
4714  * Currently we peek for the semi-colon to
4715  * allow processing of older lease files that
4716  * don't have the semi-colon. Eventually we
4717  * should remove the peeking code.
4718  */
4719  token = peek_token(&val, NULL, cfile);
4720  if (token == SEMI) {
4721  skip_token(&val, NULL, cfile);
4722  } else {
4723  parse_warn(cfile,
4724  "corrupt lease file; "
4725  "expecting semicolon.");
4726  }
4727  break;
4728 
4729  /* Lease valid lifetime. */
4730  case MAX_LIFE:
4731  token = next_token(&val, NULL, cfile);
4732  if (token != NUMBER) {
4733  parse_warn(cfile, "%s is not a valid "
4734  "max time",
4735  val);
4736  skip_to_semi(cfile);
4737  continue;
4738  }
4739  valid = atoi (val);
4740 
4741  /*
4742  * Currently we peek for the semi-colon to
4743  * allow processing of older lease files that
4744  * don't have the semi-colon. Eventually we
4745  * should remove the peeking code.
4746  */
4747  token = peek_token(&val, NULL, cfile);
4748  if (token == SEMI) {
4749  skip_token(&val, NULL, cfile);
4750  } else {
4751  parse_warn(cfile,
4752  "corrupt lease file; "
4753  "expecting semicolon.");
4754  }
4755  break;
4756 
4757  /* Lease expiration time. */
4758  case ENDS:
4759  end_time = parse_date(cfile);
4760  break;
4761 
4762  /* Lease binding scopes. */
4763  case TOKEN_SET:
4764  token = next_token(&val, NULL, cfile);
4765  if ((token != NAME) &&
4766  (token != NUMBER_OR_NAME)) {
4767  parse_warn(cfile, "%s is not a valid "
4768  "variable name",
4769  val);
4770  skip_to_semi(cfile);
4771  continue;
4772  }
4773 
4774  if (scope != NULL)
4775  bnd = find_binding(scope, val);
4776  else {
4777  if (!binding_scope_allocate(&scope,
4778  MDL)) {
4779  log_fatal("Out of memory for "
4780  "lease binding "
4781  "scope.");
4782  }
4783 
4784  bnd = NULL;
4785  }
4786 
4787  if (bnd == NULL) {
4788  bnd = dmalloc(sizeof(*bnd),
4789  MDL);
4790  if (bnd == NULL) {
4791  log_fatal("No memory for "
4792  "lease binding.");
4793  }
4794 
4795  bnd->name = dmalloc(strlen(val) + 1,
4796  MDL);
4797  if (bnd->name == NULL) {
4798  log_fatal("No memory for "
4799  "binding name.");
4800  }
4801  strcpy(bnd->name, val);
4802 
4803  newbinding = ISC_TRUE;
4804  } else {
4805  newbinding = ISC_FALSE;
4806  }
4807 
4808  if (!binding_value_allocate(&nv, MDL)) {
4809  log_fatal("no memory for binding "
4810  "value.");
4811  }
4812 
4813  token = next_token(NULL, NULL, cfile);
4814  if (token != EQUAL) {
4815  parse_warn(cfile, "expecting '=' in "
4816  "set statement.");
4817  goto binding_err;
4818  }
4819 
4820  if (!parse_binding_value(cfile, nv)) {
4821  binding_err:
4823  binding_scope_dereference(&scope, MDL);
4824  return;
4825  }
4826 
4827  if (newbinding) {
4829  nv, MDL);
4830  bnd->next = scope->bindings;
4831  scope->bindings = bnd;
4832  } else {
4834  MDL);
4836  nv, MDL);
4837  }
4838 
4840  parse_semi(cfile);
4841  break;
4842 
4843  case ON:
4844  lose = 0;
4845  /*
4846  * Depending on the user config we may
4847  * have one or two on statements. We
4848  * need to save information about both
4849  * of them until we allocate the
4850  * iasubopt to hold them.
4851  */
4852  if (on_star[0] == NULL) {
4853  if (!parse_on_statement (&on_star[0],
4854  cfile,
4855  &lose)) {
4856  parse_warn(cfile,
4857  "corrupt lease "
4858  "file; bad ON "
4859  "statement");
4860  skip_to_rbrace (cfile, 1);
4861  return;
4862  }
4863  } else {
4864  if (!parse_on_statement (&on_star[1],
4865  cfile,
4866  &lose)) {
4867  parse_warn(cfile,
4868  "corrupt lease "
4869  "file; bad ON "
4870  "statement");
4871  skip_to_rbrace (cfile, 1);
4872  return;
4873  }
4874  }
4875 
4876  break;
4877 
4878  default:
4879  parse_warn(cfile, "corrupt lease file; "
4880  "expecting ia_na contents, "
4881  "got '%s'", val);
4882  skip_to_semi(cfile);
4883  continue;
4884  }
4885  }
4886 
4887  if (state == FTS_LAST+1) {
4888  parse_warn(cfile, "corrupt lease file; "
4889  "missing state in iaaddr");
4890  return;
4891  }
4892  if (end_time == -1) {
4893  parse_warn(cfile, "corrupt lease file; "
4894  "missing end time in iaaddr");
4895  return;
4896  }
4897 
4898  iaaddr = NULL;
4899  if (iasubopt_allocate(&iaaddr, MDL) != ISC_R_SUCCESS) {
4900  log_fatal("Out of memory.");
4901  }
4902  memcpy(&iaaddr->addr, iaddr.iabuf, sizeof(iaaddr->addr));
4903  iaaddr->plen = 0;
4904  iaaddr->state = state;
4905  iaaddr->prefer = prefer;
4906  iaaddr->valid = valid;
4907  if (iaaddr->state == FTS_RELEASED)
4908  iaaddr->hard_lifetime_end_time = end_time;
4909 
4910  if (scope != NULL) {
4911  binding_scope_reference(&iaaddr->scope, scope, MDL);
4912  binding_scope_dereference(&scope, MDL);
4913  }
4914 
4915  /*
4916  * Check on both on statements. Because of how we write the
4917  * lease file we know which is which if we have two but it's
4918  * easier to write the code to be independent. We do assume
4919  * that the statements won't overlap.
4920  */
4921  for (i = 0;
4922  (i < 2) && on_star[i] != NULL ;
4923  i++) {
4924  if ((on_star[i]->data.on.evtypes & ON_EXPIRY) &&
4925  on_star[i]->data.on.statements) {
4927  (&iaaddr->on_star.on_expiry,
4928  on_star[i]->data.on.statements, MDL);
4929  }
4930  if ((on_star[i]->data.on.evtypes & ON_RELEASE) &&
4931  on_star[i]->data.on.statements) {
4933  (&iaaddr->on_star.on_release,
4934  on_star[i]->data.on.statements, MDL);
4935  }
4936  executable_statement_dereference (&on_star[i], MDL);
4937  }
4938 
4939  /* find the pool this address is in */
4940  pool = NULL;
4941  if (find_ipv6_pool(&pool, D6O_IA_NA,
4942  &iaaddr->addr) != ISC_R_SUCCESS) {
4943  inet_ntop(AF_INET6, &iaaddr->addr,
4944  addr_buf, sizeof(addr_buf));
4945  parse_warn(cfile, "no pool found for address %s",
4946  addr_buf);
4947  return;
4948  }
4949 
4950  /* remove old information */
4951  if (cleanup_lease6(ia_na_active, pool,
4952  iaaddr, ia) != ISC_R_SUCCESS) {
4953  inet_ntop(AF_INET6, &iaaddr->addr,
4954  addr_buf, sizeof(addr_buf));
4955  parse_warn(cfile, "duplicate na lease for address %s",
4956  addr_buf);
4957  }
4958 
4959  /*
4960  * if we like the lease we add it to our various structues
4961  * otherwise we leave it and it will get cleaned when we
4962  * do the iasubopt_dereference.
4963  */
4964  if ((state == FTS_ACTIVE) || (state == FTS_ABANDONED)) {
4965  ia_add_iasubopt(ia, iaaddr, MDL);
4966  ia_reference(&iaaddr->ia, ia, MDL);
4967  add_lease6(pool, iaaddr, end_time);
4968  }
4969 
4970  iasubopt_dereference(&iaaddr, MDL);
4971  ipv6_pool_dereference(&pool, MDL);
4972  }
4973 
4974  /*
4975  * If we have an existing record for this IA_NA, remove it.
4976  */
4977  old_ia = NULL;
4978  if (ia_hash_lookup(&old_ia, ia_na_active,
4979  (unsigned char *)ia->iaid_duid.data,
4980  ia->iaid_duid.len, MDL)) {
4981  ia_hash_delete(ia_na_active,
4982  (unsigned char *)ia->iaid_duid.data,
4983  ia->iaid_duid.len, MDL);
4984  ia_dereference(&old_ia, MDL);
4985  }
4986 
4987  /*
4988  * If we have addresses, add this, otherwise don't bother.
4989  */
4990  if (ia->num_iasubopt > 0) {
4991  ia_hash_add(ia_na_active,
4992  (unsigned char *)ia->iaid_duid.data,
4993  ia->iaid_duid.len, ia, MDL);
4994  }
4995  ia_dereference(&ia, MDL);
4996 #endif /* defined(DHCPv6) */
4997 }
4998 
4999 void
5001 #if !defined(DHCPv6)
5002  parse_warn(cfile, "No DHCPv6 support.");
5003  skip_to_semi(cfile);
5004 #else /* defined(DHCPv6) */
5005  enum dhcp_token token;
5006  struct ia_xx *ia;
5007  const char *val;
5008  struct ia_xx *old_ia;
5009  unsigned int len;
5010  u_int32_t iaid;
5011  struct iaddr iaddr;
5012  binding_state_t state;
5013  u_int32_t prefer;
5014  u_int32_t valid;
5015  TIME end_time;
5016  struct iasubopt *iaaddr;
5017  struct ipv6_pool *pool;
5018  char addr_buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
5019  isc_boolean_t newbinding;
5020  struct binding_scope *scope = NULL;
5021  struct binding *bnd;
5022  struct binding_value *nv = NULL;
5023  struct executable_statement *on_star[2] = {NULL, NULL};
5024  int lose, i;
5025 
5026  if (local_family != AF_INET6) {
5027  parse_warn(cfile, "IA_TA is only supported in DHCPv6 mode.");
5028  skip_to_semi(cfile);
5029  return;
5030  }
5031 
5032  token = next_token(&val, &len, cfile);
5033  if (token != STRING) {
5034  parse_warn(cfile, "corrupt lease file; "
5035  "expecting an iaid+ia_ta string");
5036  skip_to_semi(cfile);
5037  return;
5038  }
5039  if (len < 5) {
5040  parse_warn(cfile, "corrupt lease file; "
5041  "iaid+ia_ta string too short");
5042  skip_to_semi(cfile);
5043  return;
5044  }
5045 
5046  memcpy(&iaid, val, 4);
5047  ia = NULL;
5048  if (ia_allocate(&ia, iaid, val+4, len-4, MDL) != ISC_R_SUCCESS) {
5049  log_fatal("Out of memory.");
5050  }
5051  ia->ia_type = D6O_IA_TA;
5052 
5053  token = next_token(&val, NULL, cfile);
5054  if (token != LBRACE) {
5055  parse_warn(cfile, "corrupt lease file; expecting left brace");
5056  skip_to_semi(cfile);
5057  return;
5058  }
5059 
5060  for (;;) {
5061  token = next_token(&val, NULL, cfile);
5062  if (token == RBRACE) break;
5063 
5064  if (token == CLTT) {
5065  ia->cltt = parse_date (cfile);
5066  continue;
5067  }
5068 
5069  if (token != IAADDR) {
5070  parse_warn(cfile, "corrupt lease file; "
5071  "expecting IAADDR or right brace");
5072  skip_to_semi(cfile);
5073  return;
5074  }
5075 
5076  if (!parse_ip6_addr(cfile, &iaddr)) {
5077  parse_warn(cfile, "corrupt lease file; "
5078  "expecting IPv6 address");
5079  skip_to_semi(cfile);
5080  return;
5081  }
5082 
5083  token = next_token(&val, NULL, cfile);
5084  if (token != LBRACE) {
5085  parse_warn(cfile, "corrupt lease file; "
5086  "expecting left brace");
5087  skip_to_semi(cfile);
5088  return;
5089  }
5090 
5091  state = FTS_LAST+1;
5092  prefer = valid = 0;
5093  end_time = -1;
5094  for (;;) {
5095  token = next_token(&val, NULL, cfile);
5096  if (token == RBRACE) break;
5097 
5098  switch(token) {
5099  /* Lease binding state. */
5100  case BINDING:
5101  token = next_token(&val, NULL, cfile);
5102  if (token != STATE) {
5103  parse_warn(cfile, "corrupt lease file; "
5104  "expecting state");
5105  skip_to_semi(cfile);
5106  return;
5107  }
5108  token = next_token(&val, NULL, cfile);
5109  switch (token) {
5110  case TOKEN_ABANDONED:
5111  state = FTS_ABANDONED;
5112  break;
5113  case TOKEN_FREE:
5114  state = FTS_FREE;
5115  break;
5116  case TOKEN_ACTIVE:
5117  state = FTS_ACTIVE;
5118  break;
5119  case TOKEN_EXPIRED:
5120  state = FTS_EXPIRED;
5121  break;
5122  case TOKEN_RELEASED:
5123  state = FTS_RELEASED;
5124  break;
5125  default:
5126  parse_warn(cfile,
5127  "corrupt lease "
5128  "file; "
5129  "expecting a "
5130  "binding state.");
5131  skip_to_semi(cfile);
5132  return;
5133  }
5134 
5135  token = next_token(&val, NULL, cfile);
5136  if (token != SEMI) {
5137  parse_warn(cfile, "corrupt lease file; "
5138  "expecting "
5139  "semicolon.");
5140  }
5141  break;
5142 
5143  /* Lease preferred lifetime. */
5144  case PREFERRED_LIFE:
5145  token = next_token(&val, NULL, cfile);
5146  if (token != NUMBER) {
5147  parse_warn(cfile, "%s is not a valid "
5148  "preferred time",
5149  val);
5150  skip_to_semi(cfile);
5151  continue;
5152  }
5153  prefer = atoi (val);
5154 
5155  /*
5156  * Currently we peek for the semi-colon to
5157  * allow processing of older lease files that
5158  * don't have the semi-colon. Eventually we
5159  * should remove the peeking code.
5160  */
5161  token = peek_token(&val, NULL, cfile);
5162  if (token == SEMI) {
5163  skip_token(&val, NULL, cfile);
5164  } else {
5165  parse_warn(cfile,
5166  "corrupt lease file; "
5167  "expecting semicolon.");
5168  }
5169  break;
5170 
5171  /* Lease valid lifetime. */
5172  case MAX_LIFE:
5173  token = next_token(&val, NULL, cfile);
5174  if (token != NUMBER) {
5175  parse_warn(cfile, "%s is not a valid "
5176  "max time",
5177  val);
5178  skip_to_semi(cfile);
5179  continue;
5180  }
5181  valid = atoi (val);
5182 
5183  /*
5184  * Currently we peek for the semi-colon to
5185  * allow processing of older lease files that
5186  * don't have the semi-colon. Eventually we
5187  * should remove the peeking code.
5188  */
5189  token = peek_token(&val, NULL, cfile);
5190  if (token == SEMI) {
5191  skip_token(&val, NULL, cfile);
5192  } else {
5193  parse_warn(cfile,
5194  "corrupt lease file; "
5195  "expecting semicolon.");
5196  }
5197  break;
5198 
5199  /* Lease expiration time. */
5200  case ENDS:
5201  end_time = parse_date(cfile);
5202  break;
5203 
5204  /* Lease binding scopes. */
5205  case TOKEN_SET:
5206  token = next_token(&val, NULL, cfile);
5207  if ((token != NAME) &&
5208  (token != NUMBER_OR_NAME)) {
5209  parse_warn(cfile, "%s is not a valid "
5210  "variable name",
5211  val);
5212  skip_to_semi(cfile);
5213  continue;
5214  }
5215 
5216  if (scope != NULL)
5217  bnd = find_binding(scope, val);
5218  else {
5219  if (!binding_scope_allocate(&scope,
5220  MDL)) {
5221  log_fatal("Out of memory for "
5222  "lease binding "
5223  "scope.");
5224  }
5225 
5226  bnd = NULL;
5227  }
5228 
5229  if (bnd == NULL) {
5230  bnd = dmalloc(sizeof(*bnd),
5231  MDL);
5232  if (bnd == NULL) {
5233  log_fatal("No memory for "
5234  "lease binding.");
5235  }
5236 
5237  bnd->name = dmalloc(strlen(val) + 1,
5238  MDL);
5239  if (bnd->name == NULL) {
5240  log_fatal("No memory for "
5241  "binding name.");
5242  }
5243  strcpy(bnd->name, val);
5244 
5245  newbinding = ISC_TRUE;
5246  } else {
5247  newbinding = ISC_FALSE;
5248  }
5249 
5250  if (!binding_value_allocate(&nv, MDL)) {
5251  log_fatal("no memory for binding "
5252  "value.");
5253  }
5254 
5255  token = next_token(NULL, NULL, cfile);
5256  if (token != EQUAL) {
5257  parse_warn(cfile, "expecting '=' in "
5258  "set statement.");
5259  goto binding_err;
5260  }
5261 
5262  if (!parse_binding_value(cfile, nv)) {
5263  binding_err:
5265  binding_scope_dereference(&scope, MDL);
5266  return;
5267  }
5268 
5269  if (newbinding) {
5271  nv, MDL);
5272  bnd->next = scope->bindings;
5273  scope->bindings = bnd;
5274  } else {
5276  MDL);
5278  nv, MDL);
5279  }
5280 
5282  parse_semi(cfile);
5283  break;
5284 
5285  case ON:
5286  lose = 0;
5287  /*
5288  * Depending on the user config we may
5289  * have one or two on statements. We
5290  * need to save information about both
5291  * of them until we allocate the
5292  * iasubopt to hold them.
5293  */
5294  if (on_star[0] == NULL) {
5295  if (!parse_on_statement (&on_star[0],
5296  cfile,
5297  &lose)) {
5298  parse_warn(cfile,
5299  "corrupt lease "
5300  "file; bad ON "
5301  "statement");
5302  skip_to_rbrace (cfile, 1);
5303  return;
5304  }
5305  } else {
5306  if (!parse_on_statement (&on_star[1],
5307  cfile,
5308  &lose)) {
5309  parse_warn(cfile,
5310  "corrupt lease "
5311  "file; bad ON "
5312  "statement");
5313  skip_to_rbrace (cfile, 1);
5314  return;
5315  }
5316  }
5317 
5318  break;
5319 
5320  default:
5321  parse_warn(cfile, "corrupt lease file; "
5322  "expecting ia_ta contents, "
5323  "got '%s'", val);
5324  skip_to_semi(cfile);
5325  continue;
5326  }
5327  }
5328 
5329  if (state == FTS_LAST+1) {
5330  parse_warn(cfile, "corrupt lease file; "
5331  "missing state in iaaddr");
5332  return;
5333  }
5334  if (end_time == -1) {
5335  parse_warn(cfile, "corrupt lease file; "
5336  "missing end time in iaaddr");
5337  return;
5338  }
5339 
5340  iaaddr = NULL;
5341  if (iasubopt_allocate(&iaaddr, MDL) != ISC_R_SUCCESS) {
5342  log_fatal("Out of memory.");
5343  }
5344  memcpy(&iaaddr->addr, iaddr.iabuf, sizeof(iaaddr->addr));
5345  iaaddr->plen = 0;
5346  iaaddr->state = state;
5347  iaaddr->prefer = prefer;
5348  iaaddr->valid = valid;
5349  if (iaaddr->state == FTS_RELEASED)
5350  iaaddr->hard_lifetime_end_time = end_time;
5351 
5352  if (scope != NULL) {
5353  binding_scope_reference(&iaaddr->scope, scope, MDL);
5354  binding_scope_dereference(&scope, MDL);
5355  }
5356 
5357  /*
5358  * Check on both on statements. Because of how we write the
5359  * lease file we know which is which if we have two but it's
5360  * easier to write the code to be independent. We do assume
5361  * that the statements won't overlap.
5362  */
5363  for (i = 0;
5364  (i < 2) && on_star[i] != NULL ;
5365  i++) {
5366  if ((on_star[i]->data.on.evtypes & ON_EXPIRY) &&
5367  on_star[i]->data.on.statements) {
5369  (&iaaddr->on_star.on_expiry,
5370  on_star[i]->data.on.statements, MDL);
5371  }
5372  if ((on_star[i]->data.on.evtypes & ON_RELEASE) &&
5373  on_star[i]->data.on.statements) {
5375  (&iaaddr->on_star.on_release,
5376  on_star[i]->data.on.statements, MDL);
5377  }
5378  executable_statement_dereference (&on_star[i], MDL);
5379  }
5380 
5381  /* find the pool this address is in */
5382  pool = NULL;
5383  if (find_ipv6_pool(&pool, D6O_IA_TA,
5384  &iaaddr->addr) != ISC_R_SUCCESS) {
5385  inet_ntop(AF_INET6, &iaaddr->addr,
5386  addr_buf, sizeof(addr_buf));
5387  parse_warn(cfile, "no pool found for address %s",
5388  addr_buf);
5389  return;
5390  }
5391 
5392  /* remove old information */
5393  if (cleanup_lease6(ia_ta_active, pool,
5394  iaaddr, ia) != ISC_R_SUCCESS) {
5395  inet_ntop(AF_INET6, &iaaddr->addr,
5396  addr_buf, sizeof(addr_buf));
5397  parse_warn(cfile, "duplicate ta lease for address %s",
5398  addr_buf);
5399  }
5400 
5401  /*
5402  * if we like the lease we add it to our various structues
5403  * otherwise we leave it and it will get cleaned when we
5404  * do the iasubopt_dereference.
5405  */
5406  if ((state == FTS_ACTIVE) || (state == FTS_ABANDONED)) {
5407  ia_add_iasubopt(ia, iaaddr, MDL);
5408  ia_reference(&iaaddr->ia, ia, MDL);
5409  add_lease6(pool, iaaddr, end_time);
5410  }
5411 
5412  ipv6_pool_dereference(&pool, MDL);
5413  iasubopt_dereference(&iaaddr, MDL);
5414  }
5415 
5416  /*
5417  * If we have an existing record for this IA_TA, remove it.
5418  */
5419  old_ia = NULL;
5420  if (ia_hash_lookup(&old_ia, ia_ta_active,
5421  (unsigned char *)ia->iaid_duid.data,
5422  ia->iaid_duid.len, MDL)) {
5423  ia_hash_delete(ia_ta_active,
5424  (unsigned char *)ia->iaid_duid.data,
5425  ia->iaid_duid.len, MDL);
5426  ia_dereference(&old_ia, MDL);
5427  }
5428 
5429  /*
5430  * If we have addresses, add this, otherwise don't bother.
5431  */
5432  if (ia->num_iasubopt > 0) {
5433  ia_hash_add(ia_ta_active,
5434  (unsigned char *)ia->iaid_duid.data,
5435  ia->iaid_duid.len, ia, MDL);
5436  }
5437  ia_dereference(&ia, MDL);
5438 #endif /* defined(DHCPv6) */
5439 }
5440 
5441 void
5443 #if !defined(DHCPv6)
5444  parse_warn(cfile, "No DHCPv6 support.");
5445  skip_to_semi(cfile);
5446 #else /* defined(DHCPv6) */
5447  enum dhcp_token token;
5448  struct ia_xx *ia;
5449  const char *val;
5450  struct ia_xx *old_ia;
5451  unsigned int len;
5452  u_int32_t iaid;
5453  struct iaddr iaddr;
5454  u_int8_t plen;
5455  binding_state_t state;
5456  u_int32_t prefer;
5457  u_int32_t valid;
5458  TIME end_time;
5459  struct iasubopt *iapref;
5460  struct ipv6_pool *pool;
5461  char addr_buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
5462  isc_boolean_t newbinding;
5463  struct binding_scope *scope = NULL;
5464  struct binding *bnd;
5465  struct binding_value *nv = NULL;
5466  struct executable_statement *on_star[2] = {NULL, NULL};
5467  int lose, i;
5468 
5469  if (local_family != AF_INET6) {
5470  parse_warn(cfile, "IA_PD is only supported in DHCPv6 mode.");
5471  skip_to_semi(cfile);
5472  return;
5473  }
5474 
5475  token = next_token(&val, &len, cfile);
5476  if (token != STRING) {
5477  parse_warn(cfile, "corrupt lease file; "
5478  "expecting an iaid+ia_pd string");
5479  skip_to_semi(cfile);
5480  return;
5481  }
5482  if (len < 5) {
5483  parse_warn(cfile, "corrupt lease file; "
5484  "iaid+ia_pd string too short");
5485  skip_to_semi(cfile);
5486  return;
5487  }
5488 
5489  memcpy(&iaid, val, 4);
5490  ia = NULL;
5491  if (ia_allocate(&ia, iaid, val+4, len-4, MDL) != ISC_R_SUCCESS) {
5492  log_fatal("Out of memory.");
5493  }
5494  ia->ia_type = D6O_IA_PD;
5495 
5496  token = next_token(&val, NULL, cfile);
5497  if (token != LBRACE) {
5498  parse_warn(cfile, "corrupt lease file; expecting left brace");
5499  skip_to_semi(cfile);
5500  return;
5501  }
5502 
5503  for (;;) {
5504  token = next_token(&val, NULL, cfile);
5505  if (token == RBRACE) break;
5506 
5507  if (token == CLTT) {
5508  ia->cltt = parse_date (cfile);
5509  continue;
5510  }
5511 
5512  if (token != IAPREFIX) {
5513  parse_warn(cfile, "corrupt lease file; expecting "
5514  "IAPREFIX or right brace");
5515  skip_to_semi(cfile);
5516  return;
5517  }
5518 
5519  if (!parse_ip6_prefix(cfile, &iaddr, &plen)) {
5520  parse_warn(cfile, "corrupt lease file; "
5521  "expecting IPv6 prefix");
5522  skip_to_semi(cfile);
5523  return;
5524  }
5525 
5526  token = next_token(&val, NULL, cfile);
5527  if (token != LBRACE) {
5528  parse_warn(cfile, "corrupt lease file; "
5529  "expecting left brace");
5530  skip_to_semi(cfile);
5531  return;
5532  }
5533 
5534  state = FTS_LAST+1;
5535  prefer = valid = 0;
5536  end_time = -1;
5537  for (;;) {
5538  token = next_token(&val, NULL, cfile);
5539  if (token == RBRACE) break;
5540 
5541  switch(token) {
5542  /* Prefix binding state. */
5543  case BINDING:
5544  token = next_token(&val, NULL, cfile);
5545  if (token != STATE) {
5546  parse_warn(cfile, "corrupt lease file; "
5547  "expecting state");
5548  skip_to_semi(cfile);
5549  return;
5550  }
5551  token = next_token(&val, NULL, cfile);
5552  switch (token) {
5553  case TOKEN_ABANDONED:
5554  state = FTS_ABANDONED;
5555  break;
5556  case TOKEN_FREE:
5557  state = FTS_FREE;
5558  break;
5559  case TOKEN_ACTIVE:
5560  state = FTS_ACTIVE;
5561  break;
5562  case TOKEN_EXPIRED:
5563  state = FTS_EXPIRED;
5564  break;
5565  case TOKEN_RELEASED:
5566  state = FTS_RELEASED;
5567  break;
5568  default:
5569  parse_warn(cfile,
5570  "corrupt lease "
5571  "file; "
5572  "expecting a "
5573  "binding state.");
5574  skip_to_semi(cfile);
5575  return;
5576  }
5577 
5578  token = next_token(&val, NULL, cfile);
5579  if (token != SEMI) {
5580  parse_warn(cfile, "corrupt lease file; "
5581  "expecting "
5582  "semicolon.");
5583  }
5584  break;
5585 
5586  /* Lease preferred lifetime. */
5587  case PREFERRED_LIFE:
5588  token = next_token(&val, NULL, cfile);
5589  if (token != NUMBER) {
5590  parse_warn(cfile, "%s is not a valid "
5591  "preferred time",
5592  val);
5593  skip_to_semi(cfile);
5594  continue;
5595  }
5596  prefer = atoi (val);
5597 
5598  /*
5599  * Currently we peek for the semi-colon to
5600  * allow processing of older lease files that
5601  * don't have the semi-colon. Eventually we
5602  * should remove the peeking code.
5603  */
5604  token = peek_token(&val, NULL, cfile);
5605  if (token == SEMI) {
5606  skip_token(&val, NULL, cfile);
5607  } else {
5608  parse_warn(cfile,
5609  "corrupt lease file; "
5610  "expecting semicolon.");
5611  }
5612  break;
5613 
5614  /* Lease valid lifetime. */
5615  case MAX_LIFE:
5616  token = next_token(&val, NULL, cfile);
5617  if (token != NUMBER) {
5618  parse_warn(cfile, "%s is not a valid "
5619  "max time",
5620  val);
5621  skip_to_semi(cfile);
5622  continue;
5623  }
5624  valid = atoi (val);
5625 
5626  /*
5627  * Currently we peek for the semi-colon to
5628  * allow processing of older lease files that
5629  * don't have the semi-colon. Eventually we
5630  * should remove the peeking code.
5631  */
5632  token = peek_token(&val, NULL, cfile);
5633  if (token == SEMI) {
5634  skip_token(&val, NULL, cfile);
5635  } else {
5636  parse_warn(cfile,
5637  "corrupt lease file; "
5638  "expecting semicolon.");
5639  }
5640  break;
5641 
5642  /* Prefix expiration time. */
5643  case ENDS:
5644  end_time = parse_date(cfile);
5645  break;
5646 
5647  /* Prefix binding scopes. */
5648  case TOKEN_SET:
5649  token = next_token(&val, NULL, cfile);
5650  if ((token != NAME) &&
5651  (token != NUMBER_OR_NAME)) {
5652  parse_warn(cfile, "%s is not a valid "
5653  "variable name",
5654  val);
5655  skip_to_semi(cfile);
5656  continue;
5657  }
5658 
5659  if (scope != NULL)
5660  bnd = find_binding(scope, val);
5661  else {
5662  if (!binding_scope_allocate(&scope,
5663  MDL)) {
5664  log_fatal("Out of memory for "
5665  "lease binding "
5666  "scope.");
5667  }
5668 
5669  bnd = NULL;
5670  }
5671 
5672  if (bnd == NULL) {
5673  bnd = dmalloc(sizeof(*bnd),
5674  MDL);
5675  if (bnd == NULL) {
5676  log_fatal("No memory for "
5677  "prefix binding.");
5678  }
5679 
5680  bnd->name = dmalloc(strlen(val) + 1,
5681  MDL);
5682  if (bnd->name == NULL) {
5683  log_fatal("No memory for "
5684  "binding name.");
5685  }
5686  strcpy(bnd->name, val);
5687 
5688  newbinding = ISC_TRUE;
5689  } else {
5690  newbinding = ISC_FALSE;
5691  }
5692 
5693  if (!binding_value_allocate(&nv, MDL)) {
5694  log_fatal("no memory for binding "
5695  "value.");
5696  }
5697 
5698  token = next_token(NULL, NULL, cfile);
5699  if (token != EQUAL) {
5700  parse_warn(cfile, "expecting '=' in "
5701  "set statement.");
5702  goto binding_err;
5703  }
5704 
5705  if (!parse_binding_value(cfile, nv)) {
5706  binding_err:
5708  binding_scope_dereference(&scope, MDL);
5709  return;
5710  }
5711 
5712  if (newbinding) {
5714  nv, MDL);
5715  bnd->next = scope->bindings;
5716  scope->bindings = bnd;
5717  } else {
5719  MDL);
5721  nv, MDL);
5722  }
5723 
5725  parse_semi(cfile);
5726  break;
5727 
5728  case ON:
5729  lose = 0;
5730  /*
5731  * Depending on the user config we may
5732  * have one or two on statements. We
5733  * need to save information about both
5734  * of them until we allocate the
5735  * iasubopt to hold them.
5736  */
5737  if (on_star[0] == NULL) {
5738  if (!parse_on_statement (&on_star[0],
5739  cfile,
5740  &lose)) {
5741  parse_warn(cfile,
5742  "corrupt lease "
5743  "file; bad ON "
5744  "statement");
5745  skip_to_rbrace (cfile, 1);
5746  return;
5747  }
5748  } else {
5749  if (!parse_on_statement (&on_star[1],
5750  cfile,
5751  &lose)) {
5752  parse_warn(cfile,
5753  "corrupt lease "
5754  "file; bad ON "
5755  "statement");
5756  skip_to_rbrace (cfile, 1);
5757  return;
5758  }
5759  }
5760 
5761  break;
5762 
5763  default:
5764  parse_warn(cfile, "corrupt lease file; "
5765  "expecting ia_pd contents, "
5766  "got '%s'", val);
5767  skip_to_semi(cfile);
5768  continue;
5769  }
5770  }
5771 
5772  if (state == FTS_LAST+1) {
5773  parse_warn(cfile, "corrupt lease file; "
5774  "missing state in iaprefix");
5775  return;
5776  }
5777  if (end_time == -1) {
5778  parse_warn(cfile, "corrupt lease file; "
5779  "missing end time in iaprefix");
5780  return;
5781  }
5782 
5783  iapref = NULL;
5784  if (iasubopt_allocate(&iapref, MDL) != ISC_R_SUCCESS) {
5785  log_fatal("Out of memory.");
5786  }
5787  memcpy(&iapref->addr, iaddr.iabuf, sizeof(iapref->addr));
5788  iapref->plen = plen;
5789  iapref->state = state;
5790  iapref->prefer = prefer;
5791  iapref->valid = valid;
5792  if (iapref->state == FTS_RELEASED)
5793  iapref->hard_lifetime_end_time = end_time;
5794 
5795  if (scope != NULL) {
5796  binding_scope_reference(&iapref->scope, scope, MDL);
5797  binding_scope_dereference(&scope, MDL);
5798  }
5799 
5800  /*
5801  * Check on both on statements. Because of how we write the
5802  * lease file we know which is which if we have two but it's
5803  * easier to write the code to be independent. We do assume
5804  * that the statements won't overlap.
5805  */
5806  for (i = 0;
5807  (i < 2) && on_star[i] != NULL ;
5808  i++) {
5809  if ((on_star[i]->data.on.evtypes & ON_EXPIRY) &&
5810  on_star[i]->data.on.statements) {
5812  (&iapref->on_star.on_expiry,
5813  on_star[i]->data.on.statements, MDL);
5814  }
5815  if ((on_star[i]->data.on.evtypes & ON_RELEASE) &&
5816  on_star[i]->data.on.statements) {
5818  (&iapref->on_star.on_release,
5819  on_star[i]->data.on.statements, MDL);
5820  }
5821  executable_statement_dereference (&on_star[i], MDL);
5822  }
5823 
5824  /* find the pool this address is in */
5825  pool = NULL;
5826  if (find_ipv6_pool(&pool, D6O_IA_PD,
5827  &iapref->addr) != ISC_R_SUCCESS) {
5828  inet_ntop(AF_INET6, &iapref->addr,
5829  addr_buf, sizeof(addr_buf));
5830  parse_warn(cfile, "no pool found for address %s",
5831  addr_buf);
5832  return;
5833  }
5834 
5835  /* remove old information */
5836  if (cleanup_lease6(ia_pd_active, pool,
5837  iapref, ia) != ISC_R_SUCCESS) {
5838  inet_ntop(AF_INET6, &iapref->addr,
5839  addr_buf, sizeof(addr_buf));
5840  parse_warn(cfile, "duplicate pd lease for address %s",
5841  addr_buf);
5842  }
5843 
5844  /*
5845  * if we like the lease we add it to our various structues
5846  * otherwise we leave it and it will get cleaned when we
5847  * do the iasubopt_dereference.
5848  */
5849  if ((state == FTS_ACTIVE) || (state == FTS_ABANDONED)) {
5850  ia_add_iasubopt(ia, iapref, MDL);
5851  ia_reference(&iapref->ia, ia, MDL);
5852  add_lease6(pool, iapref, end_time);
5853  }
5854 
5855  ipv6_pool_dereference(&pool, MDL);
5856  iasubopt_dereference(&iapref, MDL);
5857  }
5858 
5859  /*
5860  * If we have an existing record for this IA_PD, remove it.
5861  */
5862  old_ia = NULL;
5863  if (ia_hash_lookup(&old_ia, ia_pd_active,
5864  (unsigned char *)ia->iaid_duid.data,
5865  ia->iaid_duid.len, MDL)) {
5866  ia_hash_delete(ia_pd_active,
5867  (unsigned char *)ia->iaid_duid.data,
5868  ia->iaid_duid.len, MDL);
5869  ia_dereference(&old_ia, MDL);
5870  }
5871 
5872  /*
5873  * If we have prefixes, add this, otherwise don't bother.
5874  */
5875  if (ia->num_iasubopt > 0) {
5876  ia_hash_add(ia_pd_active,
5877  (unsigned char *)ia->iaid_duid.data,
5878  ia->iaid_duid.len, ia, MDL);
5879  }
5880  ia_dereference(&ia, MDL);
5881 #endif /* defined(DHCPv6) */
5882 }
5883 
5884 #ifdef DHCPv6
5885 /*
5886  * When we parse a server-duid statement in a lease file, we are
5887  * looking at the saved server DUID from a previous run. In this case
5888  * we expect it to be followed by the binary representation of the
5889  * DUID stored in a string:
5890  *
5891  * server-duid "\000\001\000\001\015\221\034JRT\000\0224Y";
5892  */
5893 void
5894 parse_server_duid(struct parse *cfile) {
5895  enum dhcp_token token;
5896  const char *val;
5897  unsigned int len;
5898  struct data_string duid;
5899 
5900  token = next_token(&val, &len, cfile);
5901  if (token != STRING) {
5902  parse_warn(cfile, "corrupt lease file; expecting a DUID");
5903  skip_to_semi(cfile);
5904  return;
5905  }
5906 
5907  memset(&duid, 0, sizeof(duid));
5908  duid.len = len;
5909  if (!buffer_allocate(&duid.buffer, duid.len, MDL)) {
5910  log_fatal("Out of memory storing DUID");
5911  }
5912  duid.data = (unsigned char *)duid.buffer->data;
5913  memcpy(duid.buffer->data, val, len);
5914 
5915  set_server_duid(&duid);
5916 
5917  data_string_forget(&duid, MDL);
5918 
5919  token = next_token(&val, &len, cfile);
5920  if (token != SEMI) {
5921  parse_warn(cfile, "corrupt lease file; expecting a semicolon");
5922  skip_to_semi(cfile);
5923  return;
5924  }
5925 }
5926 
5927 /*
5928  * When we parse a server-duid statement in a config file, we will
5929  * have the type of the server DUID to generate, and possibly the
5930  * actual value defined.
5931  *
5932  * server-duid llt;
5933  * server-duid llt ethernet|ieee802|fddi 213982198 00:16:6F:49:7D:9B;
5934  * server-duid ll;
5935  * server-duid ll ethernet|ieee802|fddi 00:16:6F:49:7D:9B;
5936  * server-duid en 2495 "enterprise-specific-identifier-1234";
5937  */
5938 void
5939 parse_server_duid_conf(struct parse *cfile) {
5940  enum dhcp_token token;
5941  const char *val;
5942  unsigned int len;
5943  u_int32_t enterprise_number;
5944  int ll_type;
5945  struct data_string ll_addr;
5946  u_int32_t llt_time;
5947  struct data_string duid;
5948  int duid_type_num;
5949 
5950  /*
5951  * Consume the SERVER_DUID token.
5952  */
5953  skip_token(NULL, NULL, cfile);
5954 
5955  /*
5956  * Obtain the DUID type.
5957  */
5958  token = next_token(&val, NULL, cfile);
5959 
5960  /*
5961  * Enterprise is the easiest - enterprise number and raw data
5962  * are required.
5963  */
5964  if (token == EN) {
5965  /*
5966  * Get enterprise number and identifier.
5967  */
5968  token = next_token(&val, NULL, cfile);
5969  if (token != NUMBER) {
5970  parse_warn(cfile, "enterprise number expected");
5971  skip_to_semi(cfile);
5972  return;
5973  }
5974  enterprise_number = atoi(val);
5975 
5976  token = next_token(&val, &len, cfile);
5977  if (token != STRING) {
5978  parse_warn(cfile, "identifier expected");
5979  skip_to_semi(cfile);
5980  return;
5981  }
5982 
5983  /*
5984  * Save the DUID.
5985  */
5986  memset(&duid, 0, sizeof(duid));
5987  duid.len = 2 + 4 + len;
5988  if (!buffer_allocate(&duid.buffer, duid.len, MDL)) {
5989  log_fatal("Out of memory storing DUID");
5990  }
5991  duid.data = (unsigned char *)duid.buffer->data;
5992  putUShort(duid.buffer->data, DUID_EN);
5993  putULong(duid.buffer->data + 2, enterprise_number);
5994  memcpy(duid.buffer->data + 6, val, len);
5995 
5996  set_server_duid(&duid);
5997  data_string_forget(&duid, MDL);
5998  }
5999 
6000  /*
6001  * Next easiest is the link-layer DUID. It consists only of
6002  * the LL directive, or optionally the specific value to use.
6003  *
6004  * If we have LL only, then we set the type. If we have the
6005  * value, then we set the actual DUID.
6006  */
6007  else if (token == LL) {
6008  if (peek_token(NULL, NULL, cfile) == SEMI) {
6010  } else {
6011  /*
6012  * Get our hardware type and address.
6013  */
6014  token = next_token(NULL, NULL, cfile);
6015  switch (token) {
6016  case ETHERNET:
6017  ll_type = HTYPE_ETHER;
6018  break;
6019  case TOKEN_RING:
6020  ll_type = HTYPE_IEEE802;
6021  break;
6022  case TOKEN_FDDI:
6023  ll_type = HTYPE_FDDI;
6024  break;
6025  default:
6026  parse_warn(cfile, "hardware type expected");
6027  skip_to_semi(cfile);
6028  return;
6029  }
6030  memset(&ll_addr, 0, sizeof(ll_addr));
6031  if (!parse_cshl(&ll_addr, cfile)) {
6032  return;
6033  }
6034 
6035  /*
6036  * Save the DUID.
6037  */
6038  memset(&duid, 0, sizeof(duid));
6039  duid.len = 2 + 2 + ll_addr.len;
6040  if (!buffer_allocate(&duid.buffer, duid.len, MDL)) {
6041  log_fatal("Out of memory storing DUID");
6042  }
6043  duid.data = (unsigned char *)duid.buffer->data;
6044  putUShort(duid.buffer->data, DUID_LL);
6045  putUShort(duid.buffer->data + 2, ll_type);
6046  memcpy(duid.buffer->data + 4,
6047  ll_addr.data, ll_addr.len);
6048 
6049  set_server_duid(&duid);
6050  data_string_forget(&duid, MDL);
6051  data_string_forget(&ll_addr, MDL);
6052  }
6053  }
6054 
6055  /*
6056  * Finally the link-layer DUID plus time. It consists only of
6057  * the LLT directive, or optionally the specific value to use.
6058  *
6059  * If we have LLT only, then we set the type. If we have the
6060  * value, then we set the actual DUID.
6061  */
6062  else if (token == LLT) {
6063  if (peek_token(NULL, NULL, cfile) == SEMI) {
6065  } else {
6066  /*
6067  * Get our hardware type, timestamp, and address.
6068  */
6069  token = next_token(NULL, NULL, cfile);
6070  switch (token) {
6071  case ETHERNET:
6072  ll_type = HTYPE_ETHER;
6073  break;
6074  case TOKEN_RING:
6075  ll_type = HTYPE_IEEE802;
6076  break;
6077  case TOKEN_FDDI:
6078  ll_type = HTYPE_FDDI;
6079  break;
6080  default:
6081  parse_warn(cfile, "hardware type expected");
6082  skip_to_semi(cfile);
6083  return;
6084  }
6085 
6086  token = next_token(&val, NULL, cfile);
6087  if (token != NUMBER) {
6088  parse_warn(cfile, "timestamp expected");
6089  skip_to_semi(cfile);
6090  return;
6091  }
6092  llt_time = atoi(val);
6093 
6094  memset(&ll_addr, 0, sizeof(ll_addr));
6095  if (!parse_cshl(&ll_addr, cfile)) {
6096  return;
6097  }
6098 
6099  /*
6100  * Save the DUID.
6101  */
6102  memset(&duid, 0, sizeof(duid));
6103  duid.len = 2 + 2 + 4 + ll_addr.len;
6104  if (!buffer_allocate(&duid.buffer, duid.len, MDL)) {
6105  log_fatal("Out of memory storing DUID");
6106  }
6107  duid.data = (unsigned char *)duid.buffer->data;
6108  putUShort(duid.buffer->data, DUID_LLT);
6109  putUShort(duid.buffer->data + 2, ll_type);
6110  putULong(duid.buffer->data + 4, llt_time);
6111  memcpy(duid.buffer->data + 8,
6112  ll_addr.data, ll_addr.len);
6113 
6114  set_server_duid(&duid);
6115  data_string_forget(&duid, MDL);
6116  data_string_forget(&ll_addr, MDL);
6117  }
6118  }
6119 
6120  /*
6121  * If users want they can use a number for DUID types.
6122  * This is useful for supporting future, not-yet-defined
6123  * DUID types.
6124  *
6125  * In this case, they have to put in the complete value.
6126  *
6127  * This also works for existing DUID types of course.
6128  */
6129  else if (token == NUMBER) {
6130  duid_type_num = atoi(val);
6131 
6132  token = next_token(&val, &len, cfile);
6133  if (token != STRING) {
6134  parse_warn(cfile, "identifier expected");
6135  skip_to_semi(cfile);
6136  return;
6137  }
6138 
6139  /*
6140  * Save the DUID.
6141  */
6142  memset(&duid, 0, sizeof(duid));
6143  duid.len = 2 + len;
6144  if (!buffer_allocate(&duid.buffer, duid.len, MDL)) {
6145  log_fatal("Out of memory storing DUID");
6146  }
6147  duid.data = (unsigned char *)duid.buffer->data;
6148  putUShort(duid.buffer->data, duid_type_num);
6149  memcpy(duid.buffer->data + 2, val, len);
6150 
6151  set_server_duid(&duid);
6152  data_string_forget(&duid, MDL);
6153  }
6154 
6155  /*
6156  * Anything else is an error.
6157  */
6158  else {
6159  parse_warn(cfile, "DUID type of LLT, EN, or LL expected");
6160  skip_to_semi(cfile);
6161  return;
6162  }
6163 
6164  /*
6165  * Finally consume our trailing semicolon.
6166  */
6167  token = next_token(NULL, NULL, cfile);
6168  if (token != SEMI) {
6169  parse_warn(cfile, "semicolon expected");
6170  skip_to_semi(cfile);
6171  }
6172 }
6173 
6174 #endif /* DHCPv6 */
6175 
const char * name
Definition: tree.h:303
#define FTS_ABANDONED
Definition: dhcpd.h:502
struct iaddrcidrnet cidrnet
Definition: inet.h:77
#define FTS_LAST
Definition: dhcpd.h:508
Definition: dhctoken.h:96
ia_hash_t * ia_ta_active
#define GROUP_OBJECT_DYNAMIC
Definition: dhcpd.h:879
int trace_playback(void)
void parse_option_space_decl(struct parse *cfile)
Definition: parse.c:1337
#define DUID_EN
Definition: dhcp6.h:120
int executable_statement_reference(struct executable_statement **ptr, struct executable_statement *bp, const char *file, int line)
Definition: alloc.c:973
struct ipv6_pond * next
Definition: dhcpd.h:1640
int executable_statement_allocate(struct executable_statement **ptr, const char *file, int line)
Definition: alloc.c:959
struct class * nic
Definition: dhcpd.h:1014
Definition: tree.h:31
TIME valid_from
Definition: dhcpd.h:1646
Definition: dhctoken.h:266
int parse_lease_declaration(struct lease **lp, struct parse *cfile)
Definition: confpars.c:2979
void parse_server_duid_conf(struct parse *cfile)
isc_result_t parse_option_name(struct parse *cfile, int allocate, int *known, struct option **opt)
Definition: parse.c:1196
void parse_trace_setup(void)
Definition: dhctoken.h:150
void trace_conf_input(trace_type_t *, unsigned, char *)
#define SV_ALLOW_BOOTING
Definition: dhcpd.h:672
Definition: dhctoken.h:75
int parse_option_code_definition(struct parse *cfile, struct option *option)
Definition: parse.c:1560
struct on_star on_star
Definition: dhcpd.h:537
isc_result_t read_conf_file(const char *filename, struct group *group, int group_type, int leasep)
Definition: confpars.c:72
struct universe * universe
Definition: tree.h:349
struct subnet * subnets
Definition: dhcpd.h:975
#define SHARED_NET_DECL
Definition: dhcpd.h:642
Definition: dhctoken.h:58
int binding_value_dereference(struct binding_value **v, const char *file, int line)
Definition: tree.c:653
isc_result_t delete_group(struct group_object *group, int writep)
Definition: memory.c:35
Definition: dhctoken.h:72
isc_result_t add_lease6(struct ipv6_pool *pool, struct iasubopt *lease, time_t valid_lifetime_end_time)
Definition: mdb6.c:1234
Definition: dhcpd.h:521
unsigned len
Definition: tree.h:80
int executable_statement_dereference(struct executable_statement **ptr, const char *file, int line)
Definition: execute.c:615
struct group * group
Definition: dhcpd.h:942
int bits
Definition: inet.h:72
const char * piaddr(const struct iaddr addr)
Definition: inet.c:581
#define FTS_FREE
Definition: dhcpd.h:498
Definition: dhcpd.h:1574
#define CLASS_TYPE_VENDOR
Definition: dhcpd.h:1006
unsigned char * uid
Definition: dhcpd.h:539
void parse_fixed_prefix6(struct parse *cfile, struct host_decl *host_decl)
struct permit * new_permit(const char *, int)
isc_result_t end_parse(struct parse **cfile)
Definition: conflex.c:103
int parse_statement(struct parse *cfile, struct group *group, int type, struct host_decl *host_decl, int declaration)
Definition: confpars.c:351
int permit_list_match(struct permit *lhs, struct permit *rhs)
Definition: confpars.c:1559
void * dmalloc(unsigned, const char *, int)
Definition: alloc.c:56
char * piaddrmask(struct iaddr *addr, struct iaddr *mask)
Definition: inet.c:608
isc_result_t ia_dereference(struct ia_xx **ia, const char *file, int line)
Definition: mdb6.c:402
int option_cache_dereference(struct option_cache **ptr, const char *file, int line)
Definition: options.c:2798
enum dhcp_token token
Definition: dhcpd.h:291
Definition: dhctoken.h:71
void parse_pool6_statement(struct parse *, struct group *, int)
Definition: dhcpd.h:985
struct universe server_universe
Definition: stables.c:175
struct iaddr ip_addr(struct iaddr subnet, struct iaddr mask, u_int32_t host_address)
Definition: inet.c:65
#define SV_DUPLICATES
Definition: dhcpd.h:691
#define DHO_USER_CLASS
Definition: dhcp.h:156
int parse_data_expression(struct expression **expr, struct parse *cfile, int *lose)
Definition: parse.c:3514
struct ipv6_pond * ipv6_pond
Definition: dhcpd.h:978
int binding_value_reference(struct binding_value **ptr, struct binding_value *src, const char *file, int line)
Definition: alloc.c:521
#define MDL
Definition: omapip.h:568
#define HOST_DECL_DYNAMIC
Definition: dhcpd.h:915
unsigned char iabuf[16]
Definition: inet.h:33
failover_state
Definition: failover.h:288
#define FTS_RELEASED
Definition: dhcpd.h:501
#define CLASS_DECL_DELETED
Definition: dhcpd.h:1044
Definition: dhctoken.h:152
struct data_string data
Definition: tree.h:110
struct binding * next
Definition: tree.h:119
enum executable_statement::statement_op op
#define is_identifier(x)
Definition: dhctoken.h:375
void db_startup(int, uid_t, gid_t)
struct executable_statement * on_release
Definition: dhcpd.h:517
struct group * group
Definition: dhcpd.h:979
int option_reference(struct option **dest, struct option *src, const char *file, int line)
Definition: tables.c:935
Definition: dhctoken.h:349
struct universe dhcp_universe
int group_reference(struct group **ptr, struct group *bp, const char *file, int line)
Definition: alloc.c:178
void data_string_forget(struct data_string *data, const char *file, int line)
Definition: alloc.c:1340
struct shared_network * shared_network
Definition: dhcpd.h:1642
isc_result_t ipv6_pond_reference(struct ipv6_pond **pond, struct ipv6_pond *src, const char *file, int line)
reference an IPv6 pond structure.
Definition: mdb6.c:2434
int option_cache_reference(struct option_cache **ptr, struct option_cache *src, const char *file, int line)
Definition: alloc.c:652
struct option_cache * fixed_addr
Definition: dhcpd.h:908
struct group * root_group
Definition: memory.c:31
enum binding_value::@15 type
struct data_string hash_string
Definition: dhcpd.h:1029
#define DUID_LL
Definition: dhcp6.h:121
#define SCLASS_HASH_SIZE
Definition: dhcpd.h:210
const char * path_dhcpd_db
Definition: dhcpd.c:85
u_int32_t valid
Definition: dhcpd.h:1550
int log_error(const char *,...) __attribute__((__format__(__printf__
struct collection * collections
Definition: dhcpd.h:3084
time_t cltt
Definition: dhcpd.h:1580
#define FTS_EXPIRED
Definition: dhcpd.h:500
trace_type_t * trace_type_register(const char *, void *, void(*)(trace_type_t *, unsigned, char *), void(*)(trace_type_t *), const char *, int)
int binding_scope_dereference(struct binding_scope **ptr, const char *file, int line)
Definition: tree.c:3775
void free_permit(struct permit *, const char *, int)
Definition: salloc.c:243
struct on_star on_star
Definition: dhcpd.h:1571
struct binding_scope * scope
Definition: dhcpd.h:1546
dhcp_failover_state_t * failover_peer
Definition: dhcpd.h:981
int parse_semi(struct parse *cfile)
Definition: parse.c:135
struct ipv6_pond * ipv6_pond
Definition: dhcpd.h:1624
unsigned short uid_max
Definition: dhcpd.h:541
struct subnet * subnets
Definition: mdb.c:33
Definition: dhctoken.h:68
struct executable_statement * next
Definition: statement.h:31
unsigned len
Definition: inet.h:32
dhcp_failover_state_t * failover_peer
Definition: dhcpd.h:961
int parse_fixed_addr_param(struct option_cache **oc, struct parse *cfile, enum dhcp_token type)
Definition: confpars.c:2908
enum dhcp_token peek_token(const char **rval, unsigned *rlen, struct parse *cfile)
Definition: conflex.c:429
isc_result_t lease_file_subparse(struct parse *cfile)
Definition: confpars.c:266
struct data_string client_identifier
Definition: dhcpd.h:902
struct permit * prohibit_list
Definition: dhcpd.h:1645
Definition: dhcpd.h:514
int terminated
Definition: tree.h:81
Definition: dhcpd.h:259
int parse_string(struct parse *cfile, char **sptr, unsigned *lptr)
Definition: parse.c:152
Definition: tree.h:302
char * name
Definition: dhcpd.h:1016
void parse_failover_state_declaration(struct parse *, dhcp_failover_state_t *)
void expression_dereference(struct expression **eptr, const char *file, int line)
Definition: tree.c:2802
#define SV_ALLOW_BOOTP
Definition: dhcpd.h:671
#define DHO_DHCP_SERVER_IDENTIFIER
Definition: dhcp.h:146
void log_fatal(const char *,...) __attribute__((__format__(__printf__
#define POND_TRACK_MAX
Definition: dhcpd.h:1664
void get_permit(struct parse *cfile, struct permit **permit_head, int is_allow, TIME *valid_from, TIME *valid_until)
Parse allow and deny statements.
Definition: confpars.c:1429
#define D6O_IA_TA
Definition: dhcp6.h:34
void parse_ia_ta_declaration(struct parse *cfile)
Definition: confpars.c:5000
int binding_value_allocate(struct binding_value **cptr, const char *file, int line)
Definition: alloc.c:501
#define SV_DYNAMIC_BOOTP
Definition: dhcpd.h:670
struct executable_statement * statements
Definition: dhcpd.h:892
int parse_cshl(struct data_string *data, struct parse *cfile)
Definition: parse.c:2028
#define DHCP_R_BADPARSE
Definition: result.h:53
void parse_group_declaration(struct parse *cfile, struct group *group)
Definition: confpars.c:2815
int option_cache_allocate(struct option_cache **cptr, const char *file, int line)
Definition: alloc.c:631
Definition: dhctoken.h:114
union expression::expr_union data
#define CLASS_DECL_DYNAMIC
Definition: dhcpd.h:1045
struct hardware hardware_addr
Definition: dhcpd.h:543
struct iaddr subnet_number(struct iaddr addr, struct iaddr mask)
Definition: inet.c:36
void postdb_startup(void)
Definition: dhcpd.c:1141
#define HTYPE_ETHER
Definition: dhcp.h:76
#define GROUP_DECL
Definition: dhcpd.h:645
isc_result_t ipv6_pool_allocate(struct ipv6_pool **pool, u_int16_t type, const struct in6_addr *start_addr, int bits, int units, const char *file, int line)
Create a new IPv6 lease pool structure.
Definition: mdb6.c:635
enum dhcp_token next_token(const char **rval, unsigned *rlen, struct parse *cfile)
Definition: conflex.c:355
int subnet_inner_than(const struct subnet *, const struct subnet *, int)
Definition: mdb.c:920
Definition: dhctoken.h:36
time_t hard_lifetime_end_time
Definition: dhcpd.h:1547
struct permit * prohibit_list
Definition: dhcpd.h:945
Definition: tree.h:346
#define HOST_DECL_STATIC
Definition: dhcpd.h:916
char * name
Definition: tree.h:120
isc_result_t readconf()
Definition: confpars.c:57
#define POOL_DECL
Definition: dhcpd.h:646
host_hash_t * host_name_hash
Definition: mdb.c:37
TIME after
Definition: dhcpd.h:936
void parse_ia_na_declaration(struct parse *cfile)
Definition: confpars.c:4558
#define CLASS_TYPE_SUBCLASS
Definition: dhcpd.h:1009
Definition: dhctoken.h:165
isc_result_t delete_host(struct host_decl *, int)
Definition: mdb.c:469
void enter_shared_network(struct shared_network *)
Definition: mdb.c:995
#define SV_DECLINES
Definition: dhcpd.h:692
Definition: dhcpd.h:939
isc_result_t cleanup_lease6(ia_hash_t *ia_table, struct ipv6_pool *pool, struct iasubopt *lease, struct ia_xx *ia)
Cleans up leases when reading from a lease file.
Definition: mdb6.c:1124
binding_state_t binding_state
Definition: dhcpd.h:577
ia_hash_t * ia_na_active
#define CLASS_TYPE_CLASS
Definition: dhcpd.h:1008
struct iaddr net
Definition: dhcpd.h:992
int buffer_allocate(struct buffer **ptr, unsigned len, const char *file, int line)
Definition: alloc.c:680
struct option_cache * option
Definition: statement.h:64
void postconf_initialization(int)
Definition: dhcpd.c:841
unsigned code
Definition: tree.h:350
int binding_scope_allocate(struct binding_scope **ptr, const char *file, int line)
Definition: alloc.c:1195
TIME valid_until
Definition: dhcpd.h:958
void putULong(unsigned char *, u_int32_t)
Definition: convert.c:70
int group_dereference(struct group **ptr, const char *file, int line)
Definition: alloc.c:206
#define skip_token(a, b, c)
Definition: dhcpd.h:2034
struct expression * expr
Definition: dhcpd.h:1032
void enter_lease(struct lease *)
Definition: mdb.c:1052
#define FTS_BACKUP
Definition: dhcpd.h:504
int parse_boolean_expression(struct expression **expr, struct parse *cfile, int *lose)
Definition: parse.c:3447
struct pool * pool
Definition: dhcpd.h:532
struct iaddrcidrnetlist * next
Definition: inet.h:76
char * name
Definition: dhcpd.h:900
#define SUBNET_DECL
Definition: dhcpd.h:643
option_name_hash_t * name_hash
Definition: tree.h:337
unsigned char * parse_numeric_aggregate(struct parse *cfile, unsigned char *buf, unsigned *max, int separator, int base, unsigned size)
Definition: parse.c:729
Definition: dhctoken.h:258
u_int8_t plen
Definition: dhcpd.h:1544
TIME atsfp
Definition: dhcpd.h:593
struct data_string iaid_duid
Definition: dhcpd.h:1576
int authoritative
Definition: dhcpd.h:891
isc_result_t free_iaddrcidrnetlist(struct iaddrcidrnetlist **result)
Definition: inet.c:505
int parse_lbrace(struct parse *cfile)
Definition: confpars.c:1804
void parse_subnet6_declaration(struct parse *cfile, struct shared_network *share)
Definition: confpars.c:2703
#define cur_time
Definition: dhcpd.h:1988
int make_concat(struct expression **expr, struct expression *left, struct expression *right)
Definition: tree.c:269
int trace_record(void)
TIME parse_date(struct parse *cfile)
Definition: parse.c:1176
Definition: dhctoken.h:221
TIME starts
Definition: dhcpd.h:527
struct expression * submatch
Definition: dhcpd.h:1036
Definition: dhctoken.h:228
u_int8_t flags
Definition: dhcpd.h:545
void dfree(void *, const char *, int)
Definition: alloc.c:131
void set_server_duid(struct data_string *new_duid)
isc_result_t add_ipv6_pool(struct ipv6_pool *pool)
Definition: mdb6.c:1845
struct permit * next
Definition: dhcpd.h:924
u_int32_t prefer
Definition: dhcpd.h:1549
const char * name
Definition: tree.h:347
TIME valid_until
Definition: dhcpd.h:1647
int bits
Definition: dhcpd.h:1612
enum permit::@0 type
int parse_ip6_addr(struct parse *cfile, struct iaddr *addr)
Definition: parse.c:401
int jumbo_range
Definition: dhcpd.h:1657
Definition: dhctoken.h:38
struct data_string host_id
Definition: dhcpd.h:904
#define FTS_RESET
Definition: dhcpd.h:503
int parse_ip_addr_or_hostname(struct expression **expr, struct parse *cfile, int uniform)
Definition: parse.c:264
struct option * option
Definition: dhcpd.h:360
void set_server_duid_type(int type)
int parse_option_decl(struct option_cache **oc, struct parse *cfile)
Definition: parse.c:5239
isc_result_t conf_file_subparse(struct parse *cfile, struct group *group, int group_type)
Definition: confpars.c:239
int num_iasubopt
Definition: dhcpd.h:1578
struct ipv6_pool ** ipv6_pools
Definition: dhcpd.h:1649
u_int16_t ia_type
Definition: dhcpd.h:1577
void skip_to_semi(struct parse *cfile)
Definition: parse.c:77
Definition: dhctoken.h:348
Definition: dhctoken.h:40
#define CLASS_DECL
Definition: dhcpd.h:644
int option_cache(struct option_cache **oc, struct data_string *dp, struct expression *expr, struct option *option, const char *file, int line)
Definition: tree.c:364
binding_state_t state
Definition: dhcpd.h:1545
void skip_to_rbrace(struct parse *cfile, int brace_count)
Definition: parse.c:94
void new_address_range(struct parse *, struct iaddr, struct iaddr, struct subnet *, struct pool *, struct lease **)
Definition: mdb.c:756
isc_result_t find_failover_peer(dhcp_failover_state_t **, const char *, const char *, int)
int parse_on_statement(struct executable_statement **result, struct parse *cfile, int *lose)
Definition: parse.c:3116
struct shared_network * shared_network
Definition: dhcpd.h:989
Definition: dhctoken.h:188
isc_result_t ipv6_pool_dereference(struct ipv6_pool **pool, const char *file, int line)
de-reference an IPv6 pool structure.
Definition: mdb6.c:772
isc_result_t find_ipv6_pool(struct ipv6_pool **pool, u_int16_t type, const struct in6_addr *addr)
Definition: mdb6.c:2112
int prefix_len
Definition: dhcpd.h:994
int addr_eq(struct iaddr addr1, struct iaddr addr2)
Definition: inet.c:168
struct executable_statement::@7::@9 on
char * parse_host_name(struct parse *cfile)
Definition: parse.c:192
int parse_option_statement(struct executable_statement **result, struct parse *cfile, int lookups, struct option *option, enum statement_op op)
Definition: parse.c:4891
isc_result_t delete_class(struct class *, int)
Definition: mdb.c:437
isc_result_t enter_failover_peer(dhcp_failover_state_t *)
struct group * group
Definition: dhcpd.h:995
union executable_statement::@7 data
void parse_shared_net_declaration(struct parse *cfile, struct group *group)
Definition: confpars.c:2464
char * name
Definition: dhcpd.h:876
int parse_option_data(struct expression **expr, struct parse *cfile, int lookups, struct option *option)
Definition: parse.c:4784
void cleanup(void)
union binding_value::value value
struct shared_network * shared_network
Definition: dhcpd.h:890
Definition: dhctoken.h:39
dhcp_token
Definition: dhctoken.h:35
TIME cltt
Definition: dhcpd.h:594
struct lease ** billed_leases
Definition: dhcpd.h:1021
const char * path_dhcpd_conf
Definition: dhcpd.c:84
Definition: inet.h:31
#define ROOT_GROUP
Definition: dhcpd.h:640
TIME valid_from
Definition: dhcpd.h:957
ipv6_pool structure
Definition: dhcpd.h:1608
Definition: dhcpd.h:923
struct data_string const_data
Definition: tree.h:229
int local_family
Definition: discover.c:55
int have_billing_classes
Definition: class.c:41
unsigned short uid_len
Definition: dhcpd.h:540
#define HTYPE_FDDI
Definition: dhcp.h:78
#define SHARED_IMPLICIT
Definition: dhcpd.h:972
u_int32_t host_addr(struct iaddr addr, struct iaddr mask)
Definition: inet.c:140
void parse_address_range(struct parse *cfile, struct group *group, int type, struct pool *inpool, struct lease **lpchain)
Definition: confpars.c:3616
int parse_ip6_addr_expr(struct expression **expr, struct parse *cfile)
Definition: parse.c:460
struct iaddrcidrnetlist * fixed_prefix
Definition: dhcpd.h:909
ia_hash_t * ia_pd_active
struct group_object * named_group
Definition: dhcpd.h:911
Definition: dhcpd.h:884
struct binding * bindings
Definition: tree.h:127
#define RESERVED_LEASE
Definition: dhcpd.h:548
Definition: dhctoken.h:220
isc_result_t ipv6_pond_allocate(struct ipv6_pond **pond, const char *file, int line)
Create a new IPv6 pond structure.
Definition: mdb6.c:2391
isc_boolean_t is_cidr_mask_valid(const struct iaddr *addr, int bits)
Definition: inet.c:305
int binding_scope_reference(struct binding_scope **ptr, struct binding_scope *bp, const char *file, int line)
Definition: alloc.c:1228
Definition: dhctoken.h:347
binding_state_t rewind_binding_state
Definition: dhcpd.h:580
TIME tstp
Definition: dhcpd.h:591
void parse_failover_state(struct parse *, enum failover_state *, TIME *)
#define ON_EXPIRY
Definition: statement.h:72
struct subnet * subnet
Definition: dhcpd.h:889
#define D6O_IA_NA
Definition: dhcp6.h:33
void parse_host_declaration(struct parse *cfile, struct group *group)
Definition: confpars.c:1822
int make_const_data(struct expression **expr, const unsigned char *data, unsigned len, int terminated, int allocate, const char *file, int line)
Definition: tree.c:220
Definition: dhctoken.h:167
int warnings_occurred
Definition: dhcpd.h:297
void parse_subnet_declaration(struct parse *cfile, struct shared_network *share)
Definition: confpars.c:2621
void parse_failover_peer(struct parse *, struct group *, int)
void parse_address_range6(struct parse *cfile, struct group *group, struct ipv6_pond *)
#define SV_BOOT_UNKNOWN_CLIENTS
Definition: dhcpd.h:669
TIME parse_date_core(struct parse *cfile)
Definition: parse.c:973
struct iaddr netmask
Definition: dhcpd.h:993
isc_result_t iasubopt_dereference(struct iasubopt **iasubopt, const char *file, int line)
Definition: mdb6.c:260
struct binding_value * value
Definition: tree.h:121
isc_result_t supersede_group(struct group_object *group, int writep)
Definition: memory.c:74
isc_result_t find_class(struct class **c, const char *s, const char *file, int line)
Definition: dhclient.c:1253
void parse_prefix6(struct parse *cfile, struct group *group, struct ipv6_pond *)
struct option * host_id_option
Definition: dhcpd.h:903
isc_result_t ia_allocate(struct ia_xx **ia, u_int32_t iaid, const char *duid, unsigned int duid_len, const char *file, int line)
Definition: mdb6.c:338
int option_chain_head_allocate(struct option_chain_head **ptr, const char *file, int line)
Definition: alloc.c:36
time_t TIME
Definition: dhcpd.h:85
int parse_ip6_prefix(struct parse *cfile, struct iaddr *addr, u_int8_t *plen)
Definition: parse.c:474
isc_result_t trace_get_file(trace_type_t *, const char *, unsigned *, char **)
struct subnet * next_sibling
Definition: dhcpd.h:988
isc_result_t ia_add_iasubopt(struct ia_xx *ia, struct iasubopt *iasubopt, const char *file, int line)
Definition: mdb6.c:438
unsigned char data[1]
Definition: tree.h:63
struct class * class
Definition: dhcpd.h:935
struct interface_info * interface
Definition: dhcpd.h:976
isc_result_t trace_write_packet(trace_type_t *, unsigned, const char *, const char *, int)
isc_result_t ipv6_pond_dereference(struct ipv6_pond **pond, const char *file, int line)
de-reference an IPv6 pond structure.
Definition: mdb6.c:2474
void enter_subnet(struct subnet *)
Definition: mdb.c:948
struct iaddr lo_addr
Definition: inet.h:71
TIME tsfp
Definition: dhcpd.h:592
isc_result_t enter_host(struct host_decl *, int, int)
Definition: mdb.c:222
int flags
Definition: dhcpd.h:877
Definition: dhctoken.h:45
void parse_ia_pd_declaration(struct parse *cfile)
Definition: confpars.c:5442
Definition: dhctoken.h:158
Definition: dhctoken.h:161
group_hash_t * group_name_hash
Definition: memory.c:32
Definition: dhctoken.h:172
struct executable_statement * statements
Definition: statement.h:68
int flags
Definition: dhcpd.h:1049
Definition: dhctoken.h:73
struct lease * next
Definition: dhcpd.h:523
#define DHO_VENDOR_CLASS_IDENTIFIER
Definition: dhcp.h:152
Definition: dhctoken.h:226
struct universe agent_universe
Definition: stables.c:165
ipv6_pond structure
Definition: dhcpd.h:1638
Definition: tree.h:118
#define HOST_DECL
Definition: dhcpd.h:641
#define CLASS_TYPE_USER
Definition: dhcpd.h:1007
Definition: dhctoken.h:206
isc_uint64_t num_total
Definition: dhcpd.h:1652
#define D6O_IA_PD
Definition: dhcp6.h:55
struct ipv6_pool ** pools
#define HTYPE_IEEE802
Definition: dhcp.h:77
#define DUID_LLT
Definition: dhcp6.h:119
char * piaddrcidr(const struct iaddr *addr, unsigned int bits)
Definition: inet.c:639
option_code_hash_t * code_hash
Definition: tree.h:338
struct ia_xx * ia
Definition: dhcpd.h:1551
int flags
Definition: dhcpd.h:913
void parse_server_duid(struct parse *cfile)
pair cons(caddr_t car, pair cdr)
Definition: tree.c:138
unsigned char uid_buf[7]
Definition: dhcpd.h:542
Definition: dhctoken.h:74
struct executable_statement * on_expiry
Definition: dhcpd.h:515
struct binding * find_binding(struct binding_scope *scope, const char *name)
Definition: tree.c:3744
#define BOOTP_LEASE
Definition: dhcpd.h:547
struct shared_network * shared_network
Definition: dhcpd.h:943
const char * file
Definition: dhcpd.h:3615
char * name
Definition: dhcpd.h:970
int parse_class_declaration(struct class **cp, struct parse *cfile, struct group *group, int type)
Definition: confpars.c:2086
void new_shared_network_interface(struct parse *, struct shared_network *, const char *)
Definition: mdb.c:1006
struct permit * permit_list
Definition: dhcpd.h:944
#define ON_RELEASE
Definition: statement.h:73
void putUShort(unsigned char *, u_int32_t)
Definition: convert.c:86
struct subnet * subnet
Definition: dhcpd.h:1623
unsigned long intval
Definition: tree.h:111
isc_result_t range2cidr(struct iaddrcidrnetlist **result, const struct iaddr *lo, const struct iaddr *hi)
Definition: inet.c:362
struct shared_network * shared_network
Definition: dhcpd.h:1621
void trace_conf_stop(trace_type_t *ttype)
struct in6_addr addr
Definition: dhcpd.h:1543
int parse_allow_deny(struct option_cache **oc, struct parse *cfile, int flag)
Definition: confpars.c:4490
isc_result_t ia_reference(struct ia_xx **ia, struct ia_xx *src, const char *file, int line)
Definition: mdb6.c:376
Definition: dhcpd.h:1012
const unsigned char * data
Definition: tree.h:79
TIME ends
Definition: dhcpd.h:527
struct binding_scope * scope
Definition: dhcpd.h:529
void data_string_copy(struct data_string *dest, const struct data_string *src, const char *file, int line)
Definition: alloc.c:1324
isc_result_t ipv6_pool_reference(struct ipv6_pool **pool, struct ipv6_pool *src, const char *file, int line)
reference an IPv6 pool structure.
Definition: mdb6.c:701
struct hardware interface
Definition: dhcpd.h:901
struct permit * permit_list
Definition: dhcpd.h:1644
Definition: dhctoken.h:37
int parse_executable_statement(struct executable_statement **result, struct parse *cfile, int *lose, enum expression_context case_context)
Definition: parse.c:2121
Definition: dhctoken.h:142
void parse_hardware_param(struct parse *cfile, struct hardware *hardware)
Definition: parse.c:610
struct group * group
Definition: dhcpd.h:875
int clone_group(struct group **gp, struct group *group, const char *file, int line)
Definition: memory.c:130
int relays
Definition: dhcpd.h:920
int parse_warn(struct parse *cfile, const char *fmt,...)
Definition: parse.c:5591
binding_state_t next_binding_state
Definition: dhcpd.h:578
#define SV_LEASEQUERY
Definition: dhcpd.h:712
u_int8_t binding_state_t
Definition: dhcpd.h:505
struct interface_info * interface
Definition: dhcpd.h:990
isc_result_t new_parse(struct parse **cfile, int file, char *inbuf, unsigned buflen, const char *name, int eolp)
Definition: conflex.c:41
void parse_pool_statement(struct parse *cfile, struct group *group, int type)
Parse a pool statement.
Definition: confpars.c:1603
struct group * group
Definition: dhcpd.h:1641
struct pool * pools
Definition: dhcpd.h:977
#define GROUP_OBJECT_STATIC
Definition: dhcpd.h:880
struct group * group
Definition: dhcpd.h:910
struct buffer * buffer
Definition: tree.h:78
struct pool * next
Definition: dhcpd.h:941
int option_dereference(struct option **dest, const char *file, int line)
Definition: tables.c:957
#define SV_CLIENT_UPDATES
Definition: dhcpd.h:703
char * client_hostname
Definition: dhcpd.h:528
struct group * group
Definition: dhcpd.h:1039
Definition: dhctoken.h:224
#define FTS_ACTIVE
Definition: dhcpd.h:499
int num_pools