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