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