ISC DHCP  4.3.6b1
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-2017 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 == CLASS_TYPE_VENDOR) ?
2268  "implicit-vendor-class" : "implicit-user-class";
2269 
2270  } else if (type == CLASS_TYPE_CLASS) {
2271  tname = val;
2272  } else {
2273  tname = NULL;
2274  }
2275 
2276  if (tname) {
2277  name = dmalloc (strlen (tname) + 1, MDL);
2278  if (!name)
2279  log_fatal ("No memory for class name %s.", tname);
2280  strcpy (name, tname);
2281  } else
2282  name = NULL;
2283 
2284  /* If this is a straight subclass, parse the hash string. */
2285  if (type == CLASS_TYPE_SUBCLASS) {
2286  token = peek_token (&val, NULL, cfile);
2287  if (token == STRING) {
2288  skip_token(&val, &data.len, cfile);
2289  data.buffer = NULL;
2290 
2291  if (!buffer_allocate (&data.buffer,
2292  data.len + 1, MDL)) {
2293  if (pc)
2294  class_dereference (&pc, MDL);
2295 
2296  return 0;
2297  }
2298  data.terminated = 1;
2299  data.data = &data.buffer -> data [0];
2300  memcpy ((char *)data.buffer -> data, val,
2301  data.len + 1);
2302  } else if (token == NUMBER_OR_NAME || token == NUMBER) {
2303  memset (&data, 0, sizeof data);
2304  if (!parse_cshl (&data, cfile)) {
2305  if (pc)
2306  class_dereference (&pc, MDL);
2307  return 0;
2308  }
2309  } else {
2310  parse_warn (cfile, "Expecting string or hex list.");
2311  if (pc)
2312  class_dereference (&pc, MDL);
2313  return 0;
2314  }
2315  }
2316 
2317  /* See if there's already a class in the hash table matching the
2318  hash data. */
2319  if (type != CLASS_TYPE_CLASS)
2320  class_hash_lookup (&class, pc -> hash,
2321  (const char *)data.data, data.len, MDL);
2322 
2323  /* If we didn't find an existing class, allocate a new one. */
2324  if (!class) {
2325  /* Allocate the class structure... */
2326  if (type == CLASS_TYPE_SUBCLASS) {
2327  status = subclass_allocate (&class, MDL);
2328  } else {
2329  status = class_allocate (&class, MDL);
2330  }
2331  if (pc) {
2332  group_reference (&class -> group, pc -> group, MDL);
2333  class_reference (&class -> superclass, pc, MDL);
2334  class -> lease_limit = pc -> lease_limit;
2335  if (class -> lease_limit) {
2336  class -> billed_leases =
2337  dmalloc (class -> lease_limit *
2338  sizeof (struct lease *), MDL);
2339  if (!class -> billed_leases)
2340  log_fatal ("no memory for billing");
2341  memset (class -> billed_leases, 0,
2342  (class -> lease_limit *
2343  sizeof (struct lease *)));
2344  }
2345  data_string_copy (&class -> hash_string, &data, MDL);
2346  if (!pc -> hash &&
2347  !class_new_hash (&pc->hash, SCLASS_HASH_SIZE, MDL))
2348  log_fatal ("No memory for subclass hash.");
2349  class_hash_add (pc -> hash,
2350  (const char *)class -> hash_string.data,
2351  class -> hash_string.len,
2352  (void *)class, MDL);
2353  } else {
2354  if (class->group)
2356  if (!clone_group (&class -> group, group, MDL))
2357  log_fatal ("no memory to clone class group.");
2358  }
2359 
2360  /* If this is an implicit vendor or user class, add a
2361  statement that causes the vendor or user class ID to
2362  be sent back in the reply. */
2363  if (type == CLASS_TYPE_VENDOR || type == CLASS_TYPE_USER) {
2364  stmt = NULL;
2365  if (!executable_statement_allocate (&stmt, MDL))
2366  log_fatal ("no memory for class statement.");
2367  stmt -> op = supersede_option_statement;
2368  if (option_cache_allocate (&stmt -> data.option,
2369  MDL)) {
2370  stmt -> data.option -> data = data;
2371  code = (type == CLASS_TYPE_VENDOR)
2373  : DHO_USER_CLASS;
2374  option_code_hash_lookup(
2375  &stmt->data.option->option,
2377  &code, 0, MDL);
2378  }
2379  class -> statements = stmt;
2380  }
2381 
2382  /* Save the name, if there is one. */
2383  if (class->name != NULL)
2384  dfree(class->name, MDL);
2385  class->name = name;
2386  }
2387 
2388  if (type != CLASS_TYPE_CLASS)
2389  data_string_forget(&data, MDL);
2390 
2391  /* Spawned classes don't have to have their own settings. */
2392  if (class -> superclass) {
2393  token = peek_token (&val, NULL, cfile);
2394  if (token == SEMI) {
2395  skip_token(&val, NULL, cfile);
2396 
2397  if (cp)
2398  status = class_reference (cp, class, MDL);
2399  class_dereference (&class, MDL);
2400  if (pc)
2401  class_dereference (&pc, MDL);
2402  return cp ? (status == ISC_R_SUCCESS) : 1;
2403  }
2404  /* Give the subclass its own group. */
2405  if (!clone_group (&class -> group, class -> group, MDL))
2406  log_fatal ("can't clone class group.");
2407 
2408  }
2409 
2410  if (!parse_lbrace (cfile)) {
2411  class_dereference (&class, MDL);
2412  if (pc)
2413  class_dereference (&pc, MDL);
2414  return 0;
2415  }
2416 
2417  do {
2418  token = peek_token (&val, NULL, cfile);
2419  if (token == RBRACE) {
2420  skip_token(&val, NULL, cfile);
2421  break;
2422  } else if (token == END_OF_FILE) {
2423  skip_token(&val, NULL, cfile);
2424  parse_warn (cfile, "unexpected end of file");
2425  break;
2426  } else if (token == DYNAMIC) {
2427  class->flags |= CLASS_DECL_DYNAMIC;
2428  skip_token(&val, NULL, cfile);
2429  if (!parse_semi (cfile))
2430  break;
2431  continue;
2432  } else if (token == TOKEN_DELETED) {
2433  class->flags |= CLASS_DECL_DELETED;
2434  skip_token(&val, NULL, cfile);
2435  if (!parse_semi (cfile))
2436  break;
2437  continue;
2438  } else if (token == MATCH) {
2439  if (pc) {
2440  parse_warn (cfile,
2441  "invalid match in subclass.");
2442  skip_to_semi (cfile);
2443  break;
2444  }
2445  skip_token(&val, NULL, cfile);
2446  token = peek_token (&val, NULL, cfile);
2447  if (token != IF)
2448  goto submatch;
2449  skip_token(&val, NULL, cfile);
2450  if (matchedonce) {
2451  parse_warn(cfile, "A class may only have "
2452  "one 'match if' clause.");
2453  skip_to_semi(cfile);
2454  break;
2455  }
2456  matchedonce = 1;
2457  if (class->expr)
2459  if (!parse_boolean_expression (&class->expr, cfile,
2460  &lose)) {
2461  if (!lose) {
2462  parse_warn (cfile,
2463  "expecting boolean expr.");
2464  skip_to_semi (cfile);
2465  }
2466  } else {
2467 #if defined (DEBUG_EXPRESSION_PARSE)
2468  print_expression ("class match",
2469  class -> expr);
2470 #endif
2471  parse_semi (cfile);
2472  }
2473  } else if (token == SPAWN) {
2474  skip_token(&val, NULL, cfile);
2475  if (pc) {
2476  parse_warn (cfile,
2477  "invalid spawn in subclass.");
2478  skip_to_semi (cfile);
2479  break;
2480  }
2481  class -> spawning = 1;
2482  token = next_token (&val, NULL, cfile);
2483  if (token != WITH) {
2484  parse_warn (cfile,
2485  "expecting with after spawn");
2486  skip_to_semi (cfile);
2487  break;
2488  }
2489  submatch:
2490  if (submatchedonce) {
2491  parse_warn (cfile,
2492  "can't override existing %s.",
2493  "submatch/spawn");
2494  skip_to_semi (cfile);
2495  break;
2496  }
2497  submatchedonce = 1;
2498  if (class->submatch)
2500  if (!parse_data_expression (&class -> submatch,
2501  cfile, &lose)) {
2502  if (!lose) {
2503  parse_warn (cfile,
2504  "expecting data expr.");
2505  skip_to_semi (cfile);
2506  }
2507  } else {
2508 #if defined (DEBUG_EXPRESSION_PARSE)
2509  print_expression ("class submatch",
2510  class -> submatch);
2511 #endif
2512  parse_semi (cfile);
2513  }
2514  } else if (token == LEASE) {
2515  skip_token(&val, NULL, cfile);
2516  token = next_token (&val, NULL, cfile);
2517  if (token != LIMIT) {
2518  parse_warn (cfile, "expecting \"limit\"");
2519  if (token != SEMI)
2520  skip_to_semi (cfile);
2521  break;
2522  }
2523  token = next_token (&val, NULL, cfile);
2524  if (token != NUMBER) {
2525  parse_warn (cfile, "expecting a number");
2526  if (token != SEMI)
2527  skip_to_semi (cfile);
2528  break;
2529  }
2530  class -> lease_limit = atoi (val);
2531  if (class->billed_leases)
2533  class -> billed_leases =
2534  dmalloc (class -> lease_limit *
2535  sizeof (struct lease *), MDL);
2536  if (!class -> billed_leases)
2537  log_fatal ("no memory for billed leases.");
2538  memset (class -> billed_leases, 0,
2539  (class -> lease_limit *
2540  sizeof (struct lease *)));
2542  parse_semi (cfile);
2543  } else {
2544  declaration = parse_statement (cfile, class -> group,
2545  CLASS_DECL, NULL,
2546  declaration);
2547  }
2548  } while (1);
2549 
2550  if (class->flags & CLASS_DECL_DELETED) {
2551  if (type == CLASS_TYPE_CLASS) {
2552  struct class *theclass = NULL;
2553 
2554  status = find_class(&theclass, class->name, MDL);
2555  if (status == ISC_R_SUCCESS) {
2556  delete_class(theclass, 0);
2557  class_dereference(&theclass, MDL);
2558  }
2559  } else {
2560  class_hash_delete(pc->hash,
2561  (char *)class->hash_string.data,
2562  class->hash_string.len, MDL);
2563  }
2564  } else if (type == CLASS_TYPE_CLASS && new) {
2565  if (!collections -> classes)
2566  class_reference (&collections -> classes, class, MDL);
2567  else {
2568  struct class *c;
2569  for (c = collections -> classes;
2570  c -> nic; c = c -> nic)
2571  ;
2572  class_reference (&c -> nic, class, MDL);
2573  }
2574  }
2575 
2576  if (cp) /* should always be 0??? */
2577  status = class_reference (cp, class, MDL);
2578  class_dereference (&class, MDL);
2579  if (pc)
2580  class_dereference (&pc, MDL);
2581  return cp ? (status == ISC_R_SUCCESS) : 1;
2582 }
2583 
2584 /* shared-network-declaration :==
2585  hostname LBRACE declarations parameters RBRACE */
2586 
2587 void parse_shared_net_declaration (cfile, group)
2588  struct parse *cfile;
2589  struct group *group;
2590 {
2591  const char *val;
2592  enum dhcp_token token;
2593  struct shared_network *share;
2594  char *name;
2595  int declaration = 0;
2596  isc_result_t status;
2597 
2598  share = (struct shared_network *)0;
2599  status = shared_network_allocate (&share, MDL);
2600  if (status != ISC_R_SUCCESS)
2601  log_fatal ("Can't allocate shared subnet: %s",
2602  isc_result_totext (status));
2603  if (clone_group (&share -> group, group, MDL) == 0) {
2604  log_fatal ("Can't clone group for shared net");
2605  }
2606  shared_network_reference (&share -> group -> shared_network,
2607  share, MDL);
2608 
2609  /* Get the name of the shared network... */
2610  token = peek_token (&val, (unsigned *)0, cfile);
2611  if (token == STRING) {
2612  skip_token(&val, (unsigned *)0, cfile);
2613 
2614  if (val [0] == 0) {
2615  parse_warn (cfile, "zero-length shared network name");
2616  val = "<no-name-given>";
2617  }
2618  name = dmalloc (strlen (val) + 1, MDL);
2619  if (!name)
2620  log_fatal ("no memory for shared network name");
2621  strcpy (name, val);
2622  } else {
2623  name = parse_host_name (cfile);
2624  if (!name) {
2625  parse_warn (cfile,
2626  "expecting a name for shared-network");
2627  skip_to_semi (cfile);
2628  shared_network_dereference (&share, MDL);
2629  return;
2630  }
2631  }
2632  share -> name = name;
2633 
2634  if (!parse_lbrace (cfile)) {
2635  shared_network_dereference (&share, MDL);
2636  return;
2637  }
2638 
2639  do {
2640  token = peek_token (&val, (unsigned *)0, cfile);
2641  if (token == RBRACE) {
2642  skip_token(&val, (unsigned *)0, cfile);
2643  if (!share -> subnets)
2644  parse_warn (cfile,
2645  "empty shared-network decl");
2646  else
2647  enter_shared_network (share);
2648  shared_network_dereference (&share, MDL);
2649  return;
2650  } else if (token == END_OF_FILE) {
2651  skip_token(&val, (unsigned *)0, cfile);
2652  parse_warn (cfile, "unexpected end of file");
2653  break;
2654  } else if (token == INTERFACE) {
2655  skip_token(&val, (unsigned *)0, cfile);
2656  token = next_token (&val, (unsigned *)0, cfile);
2657  new_shared_network_interface (cfile, share, val);
2658  if (!parse_semi (cfile))
2659  break;
2660  continue;
2661  }
2662 
2663  declaration = parse_statement (cfile, share -> group,
2665  (struct host_decl *)0,
2666  declaration);
2667  } while (1);
2668  shared_network_dereference (&share, MDL);
2669 }
2670 
2671 
2672 static int
2673 common_subnet_parsing(struct parse *cfile,
2674  struct shared_network *share,
2675  struct subnet *subnet) {
2676  enum dhcp_token token;
2677  struct subnet *t, *u;
2678  const char *val;
2679  int declaration = 0;
2680 
2681  enter_subnet(subnet);
2682 
2683  if (!parse_lbrace(cfile)) {
2684  subnet_dereference(&subnet, MDL);
2685  return 0;
2686  }
2687 
2688  do {
2689  token = peek_token(&val, NULL, cfile);
2690  if (token == RBRACE) {
2691  skip_token(&val, NULL, cfile);
2692  break;
2693  } else if (token == END_OF_FILE) {
2694  skip_token(&val, NULL, cfile);
2695  parse_warn (cfile, "unexpected end of file");
2696  break;
2697  } else if (token == INTERFACE) {
2698  skip_token(&val, NULL, cfile);
2699  token = next_token(&val, NULL, cfile);
2700  new_shared_network_interface(cfile, share, val);
2701  if (!parse_semi(cfile))
2702  break;
2703  continue;
2704  }
2705  declaration = parse_statement(cfile, subnet->group,
2706  SUBNET_DECL,
2707  NULL,
2708  declaration);
2709  } while (1);
2710 
2711  /* Add the subnet to the list of subnets in this shared net. */
2712  if (share->subnets == NULL) {
2713  subnet_reference(&share->subnets, subnet, MDL);
2714  } else {
2715  u = NULL;
2716  for (t = share->subnets; t->next_sibling; t = t->next_sibling) {
2717  if (subnet_inner_than(subnet, t, 0)) {
2718  subnet_reference(&subnet->next_sibling, t, MDL);
2719  if (u) {
2720  subnet_dereference(&u->next_sibling,
2721  MDL);
2722  subnet_reference(&u->next_sibling,
2723  subnet, MDL);
2724  } else {
2725  subnet_dereference(&share->subnets,
2726  MDL);
2727  subnet_reference(&share->subnets,
2728  subnet, MDL);
2729  }
2730  subnet_dereference(&subnet, MDL);
2731  return 1;
2732  }
2733  u = t;
2734  }
2735  subnet_reference(&t->next_sibling, subnet, MDL);
2736  }
2737  subnet_dereference(&subnet, MDL);
2738  return 1;
2739 }
2740 
2741 /* subnet-declaration :==
2742  net NETMASK netmask RBRACE parameters declarations LBRACE */
2743 
2744 void parse_subnet_declaration (cfile, share)
2745  struct parse *cfile;
2746  struct shared_network *share;
2747 {
2748  const char *val;
2749  enum dhcp_token token;
2750  struct subnet *subnet;
2751  struct iaddr iaddr;
2752  unsigned char addr [4];
2753  unsigned len = sizeof addr;
2754  isc_result_t status;
2755 
2756  subnet = (struct subnet *)0;
2757  status = subnet_allocate (&subnet, MDL);
2758  if (status != ISC_R_SUCCESS)
2759  log_fatal ("Allocation of new subnet failed: %s",
2760  isc_result_totext (status));
2761  shared_network_reference (&subnet -> shared_network, share, MDL);
2762 
2763  /*
2764  * If our parent shared network was implicitly created by the software,
2765  * and not explicitly configured by the user, then we actually put all
2766  * configuration scope in the parent (the shared network and subnet
2767  * share the same {}-level scope).
2768  *
2769  * Otherwise, we clone the parent group and continue as normal.
2770  */
2771  if (share->flags & SHARED_IMPLICIT) {
2772  group_reference(&subnet->group, share->group, MDL);
2773  } else {
2774  if (!clone_group(&subnet->group, share->group, MDL)) {
2775  log_fatal("Allocation of group for new subnet failed.");
2776  }
2777  }
2778  subnet_reference (&subnet -> group -> subnet, subnet, MDL);
2779 
2780  /* Get the network number... */
2781  if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) {
2782  subnet_dereference (&subnet, MDL);
2783  return;
2784  }
2785  memcpy (iaddr.iabuf, addr, len);
2786  iaddr.len = len;
2787  subnet -> net = iaddr;
2788 
2789  token = next_token (&val, (unsigned *)0, cfile);
2790  if (token != NETMASK) {
2791  parse_warn (cfile, "Expecting netmask");
2792  skip_to_semi (cfile);
2793  return;
2794  }
2795 
2796  /* Get the netmask... */
2797  if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) {
2798  subnet_dereference (&subnet, MDL);
2799  return;
2800  }
2801  memcpy (iaddr.iabuf, addr, len);
2802  iaddr.len = len;
2803  subnet -> netmask = iaddr;
2804 
2805  /* Validate the network number/netmask pair. */
2806  if (host_addr (subnet -> net, subnet -> netmask)) {
2807  char *maskstr;
2808 
2809  /* dup it, since piaddr is re-entrant */
2810  maskstr = strdup (piaddr (subnet -> netmask));
2811  if (maskstr == NULL) {
2812  log_fatal("Allocation of subnet maskstr failed: %s",
2813  piaddr (subnet -> net));
2814  }
2815 
2816  parse_warn (cfile,
2817  "subnet %s netmask %s: bad subnet number/mask combination.",
2818  piaddr (subnet -> net), maskstr);
2819  free(maskstr);
2820  subnet_dereference (&subnet, MDL);
2821  skip_to_semi (cfile);
2822  return;
2823  }
2824 
2825  common_subnet_parsing(cfile, share, subnet);
2826 }
2827 
2828 /* subnet6-declaration :==
2829  net / bits RBRACE parameters declarations LBRACE */
2830 
2831 void
2832 parse_subnet6_declaration(struct parse *cfile, struct shared_network *share) {
2833 #if !defined(DHCPv6)
2834  parse_warn(cfile, "No DHCPv6 support.");
2835  skip_to_semi(cfile);
2836 #else /* defined(DHCPv6) */
2837  struct subnet *subnet;
2838  isc_result_t status;
2839  enum dhcp_token token;
2840  const char *val;
2841  char *endp;
2842  int ofs;
2843  const static int mask[] = { 0x00, 0x80, 0xC0, 0xE0,
2844  0xF0, 0xF8, 0xFC, 0xFE };
2845  struct iaddr iaddr;
2846 
2847 #if defined(DHCP4o6)
2848  if ((local_family != AF_INET6) && !dhcpv4_over_dhcpv6) {
2849  parse_warn(cfile, "subnet6 statement is only supported "
2850  "in DHCPv6 and DHCPv4o6 modes.");
2851  skip_to_semi(cfile);
2852  return;
2853  }
2854 #else /* defined(DHCP4o6) */
2855  if (local_family != AF_INET6) {
2856  parse_warn(cfile, "subnet6 statement is only supported "
2857  "in DHCPv6 mode.");
2858  skip_to_semi(cfile);
2859  return;
2860  }
2861 #endif /* !defined(DHCP4o6) */
2862 
2863  subnet = NULL;
2864  status = subnet_allocate(&subnet, MDL);
2865  if (status != ISC_R_SUCCESS) {
2866  log_fatal("Allocation of new subnet failed: %s",
2867  isc_result_totext(status));
2868  }
2869  shared_network_reference(&subnet->shared_network, share, MDL);
2870 
2871  /*
2872  * If our parent shared network was implicitly created by the software,
2873  * and not explicitly configured by the user, then we actually put all
2874  * configuration scope in the parent (the shared network and subnet
2875  * share the same {}-level scope).
2876  *
2877  * Otherwise, we clone the parent group and continue as normal.
2878  */
2879  if (share->flags & SHARED_IMPLICIT) {
2880  group_reference(&subnet->group, share->group, MDL);
2881  } else {
2882  if (!clone_group(&subnet->group, share->group, MDL)) {
2883  log_fatal("Allocation of group for new subnet failed.");
2884  }
2885  }
2886  subnet_reference(&subnet->group->subnet, subnet, MDL);
2887 
2888  if (!parse_ip6_addr(cfile, &subnet->net)) {
2889  subnet_dereference(&subnet, MDL);
2890  return;
2891  }
2892 
2893  token = next_token(&val, NULL, cfile);
2894  if (token != SLASH) {
2895  parse_warn(cfile, "Expecting a '/'.");
2896  skip_to_semi(cfile);
2897  return;
2898  }
2899 
2900  token = next_token(&val, NULL, cfile);
2901  if (token != NUMBER) {
2902  parse_warn(cfile, "Expecting a number.");
2903  skip_to_semi(cfile);
2904  return;
2905  }
2906 
2907  subnet->prefix_len = strtol(val, &endp, 10);
2908  if ((subnet->prefix_len < 0) ||
2909  (subnet->prefix_len > 128) ||
2910  (*endp != '\0')) {
2911  parse_warn(cfile, "Expecting a number between 0 and 128.");
2912  skip_to_semi(cfile);
2913  return;
2914  }
2915 
2916  if (!is_cidr_mask_valid(&subnet->net, subnet->prefix_len)) {
2917  parse_warn(cfile, "New subnet mask too short.");
2918  skip_to_semi(cfile);
2919  return;
2920  }
2921 
2922  /*
2923  * Create a netmask.
2924  */
2925  subnet->netmask.len = 16;
2926  ofs = subnet->prefix_len / 8;
2927  if (ofs < subnet->netmask.len) {
2928  subnet->netmask.iabuf[ofs] = mask[subnet->prefix_len % 8];
2929  }
2930  while (--ofs >= 0) {
2931  subnet->netmask.iabuf[ofs] = 0xFF;
2932  }
2933 
2934  /* Validate the network number/netmask pair. */
2935  iaddr = subnet_number(subnet->net, subnet->netmask);
2936  if (memcmp(&iaddr, &subnet->net, 16) != 0) {
2937  parse_warn(cfile,
2938  "subnet %s/%d: prefix not long enough for address.",
2939  piaddr(subnet->net), subnet->prefix_len);
2940  subnet_dereference(&subnet, MDL);
2941  skip_to_semi(cfile);
2942  return;
2943  }
2944 
2945  if (!common_subnet_parsing(cfile, share, subnet)) {
2946  return;
2947  }
2948 #endif /* defined(DHCPv6) */
2949 }
2950 
2951 /* group-declaration :== RBRACE parameters declarations LBRACE */
2952 
2953 void parse_group_declaration (cfile, group)
2954  struct parse *cfile;
2955  struct group *group;
2956 {
2957  const char *val;
2958  enum dhcp_token token;
2959  struct group *g;
2960  int declaration = 0;
2961  struct group_object *t = NULL;
2962  isc_result_t status;
2963  char *name = NULL;
2964  int deletedp = 0;
2965  int dynamicp = 0;
2966  int staticp = 0;
2967 
2968  g = NULL;
2969  if (!clone_group(&g, group, MDL))
2970  log_fatal("no memory for explicit group.");
2971 
2972  token = peek_token(&val, NULL, cfile);
2973  if (is_identifier (token) || token == STRING) {
2974  skip_token(&val, NULL, cfile);
2975 
2976  name = dmalloc(strlen(val) + 1, MDL);
2977  if (!name)
2978  log_fatal("no memory for group decl name %s", val);
2979  strcpy(name, val);
2980  }
2981 
2982  if (!parse_lbrace(cfile)) {
2983  group_dereference(&g, MDL);
2984  return;
2985  }
2986 
2987  do {
2988  token = peek_token(&val, NULL, cfile);
2989  if (token == RBRACE) {
2990  skip_token(&val, NULL, cfile);
2991  break;
2992  } else if (token == END_OF_FILE) {
2993  skip_token(&val, NULL, cfile);
2994  parse_warn(cfile, "unexpected end of file");
2995  break;
2996  } else if (token == TOKEN_DELETED) {
2997  skip_token(&val, NULL, cfile);
2998  parse_semi(cfile);
2999  deletedp = 1;
3000  } else if (token == DYNAMIC) {
3001  skip_token(&val, NULL, cfile);
3002  parse_semi(cfile);
3003  dynamicp = 1;
3004  } else if (token == STATIC) {
3005  skip_token(&val, NULL, cfile);
3006  parse_semi(cfile);
3007  staticp = 1;
3008  }
3009  declaration = parse_statement(cfile, g, GROUP_DECL,
3010  NULL, declaration);
3011  } while (1);
3012 
3013  if (name) {
3014  if (deletedp) {
3015  if (group_name_hash) {
3016  t = NULL;
3017  if (group_hash_lookup(&t, group_name_hash,
3018  name,
3019  strlen(name), MDL)) {
3020  delete_group(t, 0);
3021  }
3022  }
3023  } else {
3024  t = NULL;
3025  status = group_object_allocate(&t, MDL);
3026  if (status != ISC_R_SUCCESS)
3027  log_fatal("no memory for group decl %s: %s",
3028  val, isc_result_totext(status));
3029  group_reference(&t->group, g, MDL);
3030  t->name = name;
3031  /* no need to include deletedp as it's handled above */
3032  t->flags = ((staticp ? GROUP_OBJECT_STATIC : 0) |
3033  (dynamicp ? GROUP_OBJECT_DYNAMIC : 0));
3034  supersede_group(t, 0);
3035  }
3036  if (t != NULL)
3037  group_object_dereference(&t, MDL);
3038  }
3039 }
3040 
3041 /* fixed-addr-parameter :== ip-addrs-or-hostnames SEMI
3042  ip-addrs-or-hostnames :== ip-addr-or-hostname
3043  | ip-addrs-or-hostnames ip-addr-or-hostname */
3044 
3045 int
3047  struct parse *cfile,
3048  enum dhcp_token type) {
3049  int parse_ok;
3050  const char *val;
3051  enum dhcp_token token;
3052  struct expression *expr = NULL;
3053  struct expression *tmp, *new;
3054  int status;
3055 
3056  do {
3057  tmp = NULL;
3058  if (type == FIXED_ADDR) {
3059  parse_ok = parse_ip_addr_or_hostname(&tmp, cfile, 1);
3060  } else {
3061  /* INSIST(type == FIXED_ADDR6); */
3062  parse_ok = parse_ip6_addr_expr(&tmp, cfile);
3063  }
3064  if (parse_ok) {
3065  if (expr != NULL) {
3066  new = NULL;
3067  status = make_concat(&new, expr, tmp);
3068  expression_dereference(&expr, MDL);
3069  expression_dereference(&tmp, MDL);
3070  if (!status) {
3071  return 0;
3072  }
3073  expr = new;
3074  } else {
3075  expr = tmp;
3076  }
3077  } else {
3078  if (expr != NULL) {
3079  expression_dereference (&expr, MDL);
3080  }
3081  return 0;
3082  }
3083  token = peek_token(&val, NULL, cfile);
3084  if (token == COMMA) {
3085  token = next_token(&val, NULL, cfile);
3086  }
3087  } while (token == COMMA);
3088 
3089  if (!parse_semi(cfile)) {
3090  if (expr) {
3091  expression_dereference (&expr, MDL);
3092  }
3093  return 0;
3094  }
3095 
3096  status = option_cache(oc, NULL, expr, NULL, MDL);
3097  expression_dereference(&expr, MDL);
3098  return status;
3099 }
3100 
3101 /* lease_declaration :== LEASE ip_address LBRACE lease_parameters RBRACE
3102 
3103  lease_parameters :== <nil>
3104  | lease_parameter
3105  | lease_parameters lease_parameter
3106 
3107  lease_parameter :== STARTS date
3108  | ENDS date
3109  | TIMESTAMP date
3110  | HARDWARE hardware-parameter
3111  | UID hex_numbers SEMI
3112  | HOSTNAME hostname SEMI
3113  | CLIENT_HOSTNAME hostname SEMI
3114  | CLASS identifier SEMI
3115  | DYNAMIC_BOOTP SEMI */
3116 
3117 int parse_lease_declaration (struct lease **lp, struct parse *cfile)
3118 {
3119  const char *val;
3120  enum dhcp_token token;
3121  unsigned char addr [4];
3122  unsigned len = sizeof addr;
3123  int seenmask = 0;
3124  int seenbit;
3125  char tbuf [32];
3126  struct lease *lease;
3127  struct executable_statement *on;
3128  int lose;
3129  TIME t;
3130  int noequal, newbinding;
3131  struct binding *binding;
3132  struct binding_value *nv;
3133  isc_result_t status;
3134  struct option_cache *oc;
3135  pair *p;
3136  binding_state_t new_state;
3137  unsigned buflen = 0;
3138  struct class *class;
3139 
3140  lease = (struct lease *)0;
3141  status = lease_allocate (&lease, MDL);
3142  if (status != ISC_R_SUCCESS)
3143  return 0;
3144 
3145  /* Get the address for which the lease has been issued. */
3146  if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) {
3147  lease_dereference (&lease, MDL);
3148  return 0;
3149  }
3150  memcpy (lease -> ip_addr.iabuf, addr, len);
3151  lease -> ip_addr.len = len;
3152 
3153  if (!parse_lbrace (cfile)) {
3154  lease_dereference (&lease, MDL);
3155  return 0;
3156  }
3157 
3158  do {
3159  token = next_token (&val, (unsigned *)0, cfile);
3160  if (token == RBRACE)
3161  break;
3162  else if (token == END_OF_FILE) {
3163  parse_warn (cfile, "unexpected end of file");
3164  break;
3165  }
3166  strncpy (tbuf, val, sizeof tbuf);
3167  tbuf [(sizeof tbuf) - 1] = 0;
3168 
3169  /* Parse any of the times associated with the lease. */
3170  switch (token) {
3171  case STARTS:
3172  case ENDS:
3173  case TIMESTAMP:
3174  case TSTP:
3175  case TSFP:
3176  case ATSFP:
3177  case CLTT:
3178  t = parse_date (cfile);
3179  switch (token) {
3180  case STARTS:
3181  seenbit = 1;
3182  lease -> starts = t;
3183  break;
3184 
3185  case ENDS:
3186  seenbit = 2;
3187  lease -> ends = t;
3188  break;
3189 
3190  case TSTP:
3191  seenbit = 65536;
3192  lease -> tstp = t;
3193  break;
3194 
3195  case TSFP:
3196  seenbit = 131072;
3197  lease -> tsfp = t;
3198  break;
3199 
3200  case ATSFP:
3201  seenbit = 262144;
3202  lease->atsfp = t;
3203  break;
3204 
3205  case CLTT:
3206  seenbit = 524288;
3207  lease -> cltt = t;
3208  break;
3209 
3210  default: /* for gcc, we'll never get here. */
3211  log_fatal ("Impossible error at %s:%d.", MDL);
3212  return 0;
3213  }
3214  break;
3215 
3216  /* Colon-separated hexadecimal octets... */
3217  case UID:
3218  seenbit = 8;
3219  token = peek_token (&val, (unsigned *)0, cfile);
3220  if (token == STRING) {
3221  unsigned char *tuid;
3222  skip_token(&val, &buflen, cfile);
3223  if (buflen < sizeof lease -> uid_buf) {
3224  tuid = lease -> uid_buf;
3225  lease -> uid_max =
3226  sizeof lease -> uid_buf;
3227  } else {
3228  tuid = ((unsigned char *)
3229  dmalloc (buflen, MDL));
3230  if (!tuid) {
3231  log_error ("no space for uid");
3232  lease_dereference (&lease,
3233  MDL);
3234  return 0;
3235  }
3236  lease -> uid_max = buflen;
3237  }
3238  lease -> uid_len = buflen;
3239  memcpy (tuid, val, lease -> uid_len);
3240  lease -> uid = tuid;
3241  } else {
3242  buflen = 0;
3243  lease -> uid = (parse_numeric_aggregate
3244  (cfile, (unsigned char *)0,
3245  &buflen, ':', 16, 8));
3246  if (!lease -> uid) {
3247  lease_dereference (&lease, MDL);
3248  return 0;
3249  }
3250  lease -> uid_len = buflen;
3251  lease -> uid_max = buflen;
3252  if (lease -> uid_len == 0) {
3253  lease -> uid = (unsigned char *)0;
3254  parse_warn (cfile, "zero-length uid");
3255  seenbit = 0;
3256  parse_semi (cfile);
3257  break;
3258  }
3259  }
3260  parse_semi (cfile);
3261  if (!lease -> uid) {
3262  log_fatal ("No memory for lease uid");
3263  }
3264  break;
3265 
3266  case CLASS:
3267  seenbit = 32;
3268  token = next_token (&val, (unsigned *)0, cfile);
3269  if (!is_identifier (token)) {
3270  if (token != SEMI)
3271  skip_to_rbrace (cfile, 1);
3272  lease_dereference (&lease, MDL);
3273  return 0;
3274  }
3275  parse_semi (cfile);
3276  /* for now, we aren't using this. */
3277  break;
3278 
3279  case HARDWARE:
3280  seenbit = 64;
3281  parse_hardware_param (cfile,
3282  &lease -> hardware_addr);
3283  break;
3284 
3285  case TOKEN_RESERVED:
3286  seenbit = 0;
3287  lease->flags |= RESERVED_LEASE;
3288  parse_semi(cfile);
3289  break;
3290 
3291  case DYNAMIC_BOOTP:
3292  seenbit = 0;
3293  lease -> flags |= BOOTP_LEASE;
3294  parse_semi (cfile);
3295  break;
3296 
3297  /* XXX: Reverse compatibility? */
3298  case TOKEN_ABANDONED:
3299  seenbit = 256;
3300  lease -> binding_state = FTS_ABANDONED;
3301  lease -> next_binding_state = FTS_ABANDONED;
3302  parse_semi (cfile);
3303  break;
3304 
3305  case TOKEN_NEXT:
3306  seenbit = 128;
3307  token = next_token (&val, (unsigned *)0, cfile);
3308  if (token != BINDING) {
3309  parse_warn (cfile, "expecting 'binding'");
3310  skip_to_semi (cfile);
3311  break;
3312  }
3313  goto do_binding_state;
3314 
3315  case REWIND:
3316  seenbit = 512;
3317  token = next_token(&val, NULL, cfile);
3318  if (token != BINDING) {
3319  parse_warn(cfile, "expecting 'binding'");
3320  skip_to_semi(cfile);
3321  break;
3322  }
3323  goto do_binding_state;
3324 
3325  case BINDING:
3326  seenbit = 256;
3327 
3328  do_binding_state:
3329  token = next_token (&val, (unsigned *)0, cfile);
3330  if (token != STATE) {
3331  parse_warn (cfile, "expecting 'state'");
3332  skip_to_semi (cfile);
3333  break;
3334  }
3335  token = next_token (&val, (unsigned *)0, cfile);
3336  switch (token) {
3337  case TOKEN_ABANDONED:
3338  new_state = FTS_ABANDONED;
3339  break;
3340  case TOKEN_FREE:
3341  new_state = FTS_FREE;
3342  break;
3343  case TOKEN_ACTIVE:
3344  new_state = FTS_ACTIVE;
3345  break;
3346  case TOKEN_EXPIRED:
3347  new_state = FTS_EXPIRED;
3348  break;
3349  case TOKEN_RELEASED:
3350  new_state = FTS_RELEASED;
3351  break;
3352  case TOKEN_RESET:
3353  new_state = FTS_RESET;
3354  break;
3355  case TOKEN_BACKUP:
3356  new_state = FTS_BACKUP;
3357  break;
3358 
3359  /* RESERVED and BOOTP states preserved for
3360  * compatibleness with older versions.
3361  */
3362  case TOKEN_RESERVED:
3363  new_state = FTS_ACTIVE;
3364  lease->flags |= RESERVED_LEASE;
3365  break;
3366  case TOKEN_BOOTP:
3367  new_state = FTS_ACTIVE;
3368  lease->flags |= BOOTP_LEASE;
3369  break;
3370 
3371  default:
3372  parse_warn (cfile,
3373  "%s: expecting a binding state.",
3374  val);
3375  skip_to_semi (cfile);
3376  return 0;
3377  }
3378 
3379  if (seenbit == 256) {
3380  lease -> binding_state = new_state;
3381 
3382  /*
3383  * Apply default/conservative next/rewind
3384  * binding states if they haven't been set
3385  * yet. These defaults will be over-ridden if
3386  * they are set later in parsing.
3387  */
3388  if (!(seenmask & 128))
3389  lease->next_binding_state = new_state;
3390 
3391  /* The most conservative rewind state. */
3392  if (!(seenmask & 512))
3393  lease->rewind_binding_state = new_state;
3394  } else if (seenbit == 128)
3395  lease -> next_binding_state = new_state;
3396  else if (seenbit == 512)
3397  lease->rewind_binding_state = new_state;
3398  else
3399  log_fatal("Impossible condition at %s:%d.",
3400  MDL);
3401 
3402  parse_semi (cfile);
3403  break;
3404 
3405  case CLIENT_HOSTNAME:
3406  seenbit = 1024;
3407  token = peek_token (&val, (unsigned *)0, cfile);
3408  if (token == STRING) {
3409  if (!parse_string (cfile,
3410  &lease -> client_hostname,
3411  (unsigned *)0)) {
3412  lease_dereference (&lease, MDL);
3413  return 0;
3414  }
3415  } else {
3416  lease -> client_hostname =
3417  parse_host_name (cfile);
3418  if (lease -> client_hostname)
3419  parse_semi (cfile);
3420  else {
3421  parse_warn (cfile,
3422  "expecting a hostname.");
3423  skip_to_semi (cfile);
3424  lease_dereference (&lease, MDL);
3425  return 0;
3426  }
3427  }
3428  break;
3429 
3430  case BILLING:
3431  seenbit = 2048;
3432  class = (struct class *)0;
3433  token = next_token (&val, (unsigned *)0, cfile);
3434  if (token == CLASS) {
3435  token = next_token (&val,
3436  (unsigned *)0, cfile);
3437  if (token != STRING) {
3438  parse_warn (cfile, "expecting string");
3439  if (token != SEMI)
3440  skip_to_semi (cfile);
3441  token = BILLING;
3442  break;
3443  }
3444  if (lease -> billing_class)
3445  class_dereference (&lease -> billing_class,
3446  MDL);
3447  find_class (&class, val, MDL);
3448  if (!class)
3449  parse_warn (cfile,
3450  "unknown class %s", val);
3451  parse_semi (cfile);
3452  } else if (token == SUBCLASS) {
3453  if (lease -> billing_class)
3454  class_dereference (&lease -> billing_class,
3455  MDL);
3456  parse_class_declaration(&class, cfile, NULL,
3458  } else {
3459  parse_warn (cfile, "expecting \"class\"");
3460  if (token != SEMI)
3461  skip_to_semi (cfile);
3462  }
3463  if (class) {
3464  class_reference (&lease -> billing_class,
3465  class, MDL);
3466  class_dereference (&class, MDL);
3467  }
3468  break;
3469 
3470  case ON:
3471  on = (struct executable_statement *)0;
3472  lose = 0;
3473  if (!parse_on_statement (&on, cfile, &lose)) {
3474  skip_to_rbrace (cfile, 1);
3475  lease_dereference (&lease, MDL);
3476  return 0;
3477  }
3478  seenbit = 0;
3479  if ((on->data.on.evtypes & ON_EXPIRY) &&
3480  on->data.on.statements) {
3481  seenbit |= 16384;
3483  (&lease->on_star.on_expiry,
3484  on->data.on.statements, MDL);
3485  }
3486  if ((on->data.on.evtypes & ON_RELEASE) &&
3487  on->data.on.statements) {
3488  seenbit |= 32768;
3490  (&lease->on_star.on_release,
3491  on->data.on.statements, MDL);
3492  }
3494  break;
3495 
3496  case OPTION:
3497  case SUPERSEDE:
3498  noequal = 0;
3499  seenbit = 0;
3500  oc = (struct option_cache *)0;
3501  if (parse_option_decl (&oc, cfile)) {
3502  if (oc -> option -> universe !=
3503  &agent_universe) {
3504  parse_warn (cfile,
3505  "agent option expected.");
3507  break;
3508  }
3509  if (!lease -> agent_options &&
3511  (&lease -> agent_options, MDL))) {
3512  log_error ("no memory to stash agent option");
3513  break;
3514  }
3515  for (p = &lease -> agent_options -> first;
3516  *p; p = &((*p) -> cdr))
3517  ;
3518  *p = cons (0, 0);
3519  option_cache_reference (((struct option_cache **)
3520  &((*p) -> car)), oc, MDL);
3522  }
3523  break;
3524 
3525  case TOKEN_SET:
3526  noequal = 0;
3527 
3528  token = next_token (&val, (unsigned *)0, cfile);
3529  if (token != NAME && token != NUMBER_OR_NAME) {
3530  parse_warn (cfile,
3531  "%s can't be a variable name",
3532  val);
3533  badset:
3534  skip_to_semi (cfile);
3535  lease_dereference (&lease, MDL);
3536  return 0;
3537  }
3538 
3539  seenbit = 0;
3540  special_set:
3541  if (lease -> scope)
3542  binding = find_binding (lease -> scope, val);
3543  else
3544  binding = (struct binding *)0;
3545 
3546  if (!binding) {
3547  if (!lease -> scope)
3549  (&lease -> scope, MDL)))
3550  log_fatal ("no memory for scope");
3551  binding = dmalloc (sizeof *binding, MDL);
3552  if (!binding)
3553  log_fatal ("No memory for lease %s.",
3554  "binding");
3555  memset (binding, 0, sizeof *binding);
3556  binding -> name =
3557  dmalloc (strlen (val) + 1, MDL);
3558  if (!binding -> name)
3559  log_fatal ("No memory for binding %s.",
3560  "name");
3561  strcpy (binding -> name, val);
3562  newbinding = 1;
3563  } else {
3564  newbinding = 0;
3565  }
3566 
3567  nv = NULL;
3568  if (!binding_value_allocate(&nv, MDL))
3569  log_fatal("no memory for binding value.");
3570 
3571  if (!noequal) {
3572  token = next_token (&val, (unsigned *)0, cfile);
3573  if (token != EQUAL) {
3574  parse_warn (cfile,
3575  "expecting '=' in set statement.");
3576  goto badset;
3577  }
3578  }
3579 
3580  if (!parse_binding_value(cfile, nv)) {
3582  lease_dereference(&lease, MDL);
3583  return 0;
3584  }
3585 
3586  if (newbinding) {
3587  binding_value_reference(&binding->value,
3588  nv, MDL);
3589  binding->next = lease->scope->bindings;
3590  lease->scope->bindings = binding;
3591  } else {
3592  binding_value_dereference(&binding->value, MDL);
3593  binding_value_reference(&binding->value,
3594  nv, MDL);
3595  }
3596 
3598  parse_semi(cfile);
3599  break;
3600 
3601  /* case NAME: */
3602  default:
3603  if (!strcasecmp (val, "ddns-fwd-name")) {
3604  seenbit = 4096;
3605  noequal = 1;
3606  goto special_set;
3607  } else if (!strcasecmp (val, "ddns-rev-name")) {
3608  seenbit = 8192;
3609  noequal = 1;
3610  goto special_set;
3611  } else
3612  parse_warn(cfile, "Unexpected configuration "
3613  "directive.");
3614  skip_to_semi (cfile);
3615  seenbit = 0;
3616  lease_dereference (&lease, MDL);
3617  return 0;
3618  }
3619 
3620  if (seenmask & seenbit) {
3621  parse_warn (cfile,
3622  "Too many %s parameters in lease %s\n",
3623  tbuf, piaddr (lease -> ip_addr));
3624  } else
3625  seenmask |= seenbit;
3626 
3627  } while (1);
3628 
3629  /* If no binding state is specified, make one up. */
3630  if (!(seenmask & 256)) {
3631  if (lease->ends > cur_time ||
3632  lease->on_star.on_expiry || lease->on_star.on_release)
3633  lease->binding_state = FTS_ACTIVE;
3634 #if defined (FAILOVER_PROTOCOL)
3635  else if (lease->pool && lease->pool->failover_peer)
3636  lease->binding_state = FTS_EXPIRED;
3637 #endif
3638  else
3639  lease->binding_state = FTS_FREE;
3640  if (lease->binding_state == FTS_ACTIVE) {
3641 #if defined (FAILOVER_PROTOCOL)
3642  if (lease->pool && lease->pool->failover_peer)
3644  else
3645 #endif
3646  lease->next_binding_state = FTS_FREE;
3647  } else
3648  lease->next_binding_state = lease->binding_state;
3649 
3650  /* The most conservative rewind state implies no rewind. */
3651  lease->rewind_binding_state = lease->binding_state;
3652  }
3653 
3654  if (!(seenmask & 65536))
3655  lease->tstp = lease->ends;
3656 
3657  lease_reference (lp, lease, MDL);
3658  lease_dereference (&lease, MDL);
3659  return 1;
3660 }
3661 
3662 /* Parse the right side of a 'binding value'.
3663  *
3664  * set foo = "bar"; is a string
3665  * set foo = false; is a boolean
3666  * set foo = %31; is a numeric value.
3667  */
3668 static int
3669 parse_binding_value(struct parse *cfile, struct binding_value *value)
3670 {
3671  struct data_string *data;
3672  unsigned char *s;
3673  const char *val;
3674  unsigned buflen;
3675  int token;
3676 
3677  if ((cfile == NULL) || (value == NULL))
3678  log_fatal("Invalid arguments at %s:%d.", MDL);
3679 
3680  token = peek_token(&val, NULL, cfile);
3681  if (token == STRING) {
3682  skip_token(&val, &buflen, cfile);
3683 
3684  value->type = binding_data;
3685  value->value.data.len = buflen;
3686 
3687  data = &value->value.data;
3688 
3689  if (!buffer_allocate(&data->buffer, buflen + 1, MDL))
3690  log_fatal ("No memory for binding.");
3691 
3692  memcpy(data->buffer->data, val, buflen + 1);
3693 
3694  data->data = data->buffer->data;
3695  data->terminated = 1;
3696  } else if (token == NUMBER_OR_NAME) {
3697  value->type = binding_data;
3698 
3699  data = &value->value.data;
3700  s = parse_numeric_aggregate(cfile, NULL, &data->len,
3701  ':', 16, 8);
3702  if (s == NULL) {
3703  skip_to_semi(cfile);
3704  return 0;
3705  }
3706 
3707  if (data->len) {
3708  if (!buffer_allocate(&data->buffer, data->len + 1,
3709  MDL))
3710  log_fatal("No memory for binding.");
3711 
3712  memcpy(data->buffer->data, s, data->len);
3713  data->data = data->buffer->data;
3714 
3715  dfree (s, MDL);
3716  }
3717  } else if (token == PERCENT) {
3718  skip_token(&val, NULL, cfile);
3719  token = next_token(&val, NULL, cfile);
3720  if (token != NUMBER) {
3721  parse_warn(cfile, "expecting decimal number.");
3722  if (token != SEMI)
3723  skip_to_semi(cfile);
3724  return 0;
3725  }
3726  value->type = binding_numeric;
3727  value->value.intval = atol(val);
3728  } else if (token == NAME) {
3729  token = next_token(&val, NULL, cfile);
3730  value->type = binding_boolean;
3731  if (!strcasecmp(val, "true"))
3732  value->value.boolean = 1;
3733  else if (!strcasecmp(val, "false"))
3734  value->value.boolean = 0;
3735  else {
3736  parse_warn(cfile, "expecting true or false");
3737  if (token != SEMI)
3738  skip_to_semi(cfile);
3739  return 0;
3740  }
3741  } else {
3742  parse_warn (cfile, "expecting a constant value.");
3743  if (token != SEMI)
3744  skip_to_semi (cfile);
3745  return 0;
3746  }
3747 
3748  return 1;
3749 }
3750 
3751 /* address-range-declaration :== ip-address ip-address SEMI
3752  | DYNAMIC_BOOTP ip-address ip-address SEMI */
3753 
3754 void parse_address_range (cfile, group, type, inpool, lpchain)
3755  struct parse *cfile;
3756  struct group *group;
3757  int type;
3758  struct pool *inpool;
3759  struct lease **lpchain;
3760 {
3761  struct iaddr low, high, net;
3762  unsigned char addr [4];
3763  unsigned len = sizeof addr;
3764  enum dhcp_token token;
3765  const char *val;
3766  int dynamic = 0;
3767  struct subnet *subnet;
3768  struct shared_network *share;
3769  struct pool *pool;
3770  isc_result_t status;
3771 
3772  if ((token = peek_token (&val,
3773  (unsigned *)0, cfile)) == DYNAMIC_BOOTP) {
3774  skip_token(&val, (unsigned *)0, cfile);
3775  dynamic = 1;
3776  }
3777 
3778  /* Get the bottom address in the range... */
3779  if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
3780  return;
3781  memcpy (low.iabuf, addr, len);
3782  low.len = len;
3783 
3784  /* Only one address? */
3785  token = peek_token (&val, (unsigned *)0, cfile);
3786  if (token == SEMI)
3787  high = low;
3788  else {
3789  /* Get the top address in the range... */
3790  if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
3791  return;
3792  memcpy (high.iabuf, addr, len);
3793  high.len = len;
3794  }
3795 
3796  token = next_token (&val, (unsigned *)0, cfile);
3797  if (token != SEMI) {
3798  parse_warn (cfile, "semicolon expected.");
3799  skip_to_semi (cfile);
3800  return;
3801  }
3802 
3803  if (type == SUBNET_DECL) {
3804  subnet = group -> subnet;
3805  share = subnet -> shared_network;
3806  } else {
3807  share = group -> shared_network;
3808  for (subnet = share -> subnets;
3809  subnet; subnet = subnet -> next_sibling) {
3810  net = subnet_number (low, subnet -> netmask);
3811  if (addr_eq (net, subnet -> net))
3812  break;
3813  }
3814  if (!subnet) {
3815  parse_warn (cfile, "address range not on network %s",
3816  group -> shared_network -> name);
3817  log_error ("Be sure to place pool statement after %s",
3818  "related subnet declarations.");
3819  return;
3820  }
3821  }
3822 
3823  if (!inpool) {
3824  struct pool *last = (struct pool *)0;
3825 
3826  /* If we're permitting dynamic bootp for this range,
3827  then look for a pool with an empty prohibit list and
3828  a permit list with one entry that permits all clients. */
3829  for (pool = share -> pools; pool; pool = pool -> next) {
3830  if ((!dynamic && !pool -> permit_list &&
3831  pool -> prohibit_list &&
3832  !pool -> prohibit_list -> next &&
3833  (pool -> prohibit_list -> type ==
3834  permit_dynamic_bootp_clients)) ||
3835  (dynamic && !pool -> prohibit_list &&
3836  pool -> permit_list &&
3837  !pool -> permit_list -> next &&
3838  (pool -> permit_list -> type ==
3839  permit_all_clients))) {
3840  break;
3841  }
3842  last = pool;
3843  }
3844 
3845  /* If we didn't get a pool, make one. */
3846  if (!pool) {
3847  struct permit *p;
3848  status = pool_allocate (&pool, MDL);
3849  if (status != ISC_R_SUCCESS)
3850  log_fatal ("no memory for ad-hoc pool: %s",
3851  isc_result_totext (status));
3852  p = new_permit (MDL);
3853  if (!p)
3854  log_fatal ("no memory for ad-hoc permit.");
3855 
3856  /* Dynamic pools permit all clients. Otherwise
3857  we prohibit BOOTP clients. */
3858  if (dynamic) {
3859  p -> type = permit_all_clients;
3860  pool -> permit_list = p;
3861  } else {
3862  p -> type = permit_dynamic_bootp_clients;
3863  pool -> prohibit_list = p;
3864  }
3865 
3866  if (share -> pools)
3867  pool_reference (&last -> next, pool, MDL);
3868  else
3869  pool_reference (&share -> pools, pool, MDL);
3870  shared_network_reference (&pool -> shared_network,
3871  share, MDL);
3872  if (!clone_group (&pool -> group, share -> group, MDL))
3873  log_fatal ("no memory for anon pool group.");
3874  } else {
3875  pool = (struct pool *)0;
3876  if (last)
3877  pool_reference (&pool, last, MDL);
3878  else
3879  pool_reference (&pool, share -> pools, MDL);
3880  }
3881  } else {
3882  pool = (struct pool *)0;
3883  pool_reference (&pool, inpool, MDL);
3884  }
3885 
3886 #if defined (FAILOVER_PROTOCOL)
3887  if (pool -> failover_peer && dynamic) {
3888  /* Doctor, do you think I'm overly sensitive
3889  about getting bug reports I can't fix? */
3890  parse_warn (cfile, "dynamic-bootp flag is %s",
3891  "not permitted for address");
3892  log_error ("range declarations where there is a failover");
3893  log_error ("peer in scope. If you wish to declare an");
3894  log_error ("address range from which dynamic bootp leases");
3895  log_error ("can be allocated, please declare it within a");
3896  log_error ("pool declaration that also contains the \"no");
3897  log_error ("failover\" statement. The failover protocol");
3898  log_error ("itself does not permit dynamic bootp - this");
3899  log_error ("is not a limitation specific to the ISC DHCP");
3900  log_error ("server. Please don't ask me to defend this");
3901  log_error ("until you have read and really tried %s",
3902  "to understand");
3903  log_error ("the failover protocol specification.");
3904 
3905  /* We don't actually bomb at this point - instead,
3906  we let parse_lease_file notice the error and
3907  bomb at that point - it's easier. */
3908  }
3909 #endif /* FAILOVER_PROTOCOL */
3910 
3911  /* Create the new address range... */
3912  new_address_range (cfile, low, high, subnet, pool, lpchain);
3913  pool_dereference (&pool, MDL);
3914 }
3915 
3916 #ifdef DHCPv6
3917 static void
3918 add_ipv6_pool_to_subnet(struct subnet *subnet, u_int16_t type,
3919  struct iaddr *lo_addr, int bits, int units,
3920  struct ipv6_pond *pond) {
3921  struct ipv6_pool *pool;
3922  struct in6_addr tmp_in6_addr;
3923  int num_pools;
3924  struct ipv6_pool **tmp;
3925 
3926  /*
3927  * Create our pool.
3928  */
3929  if (lo_addr->len != sizeof(tmp_in6_addr)) {
3930  log_fatal("Internal error: Attempt to add non-IPv6 address "
3931  "to IPv6 shared network.");
3932  }
3933  memcpy(&tmp_in6_addr, lo_addr->iabuf, sizeof(tmp_in6_addr));
3934  pool = NULL;
3935  if (ipv6_pool_allocate(&pool, type, &tmp_in6_addr,
3936  bits, units, MDL) != ISC_R_SUCCESS) {
3937  log_fatal("Out of memory");
3938  }
3939 
3940  /*
3941  * Add to our global IPv6 pool set.
3942  */
3943  if (add_ipv6_pool(pool) != ISC_R_SUCCESS) {
3944  log_fatal ("Out of memory");
3945  }
3946 
3947  /*
3948  * Link the pool to its network.
3949  */
3950  pool->subnet = NULL;
3951  subnet_reference(&pool->subnet, subnet, MDL);
3952  pool->shared_network = NULL;
3953  shared_network_reference(&pool->shared_network,
3954  subnet->shared_network, MDL);
3955  pool->ipv6_pond = NULL;
3956  ipv6_pond_reference(&pool->ipv6_pond, pond, MDL);
3957 
3958  /*
3959  * Increase our array size for ipv6_pools in the pond
3960  */
3961  if (pond->ipv6_pools == NULL) {
3962  num_pools = 0;
3963  } else {
3964  num_pools = 0;
3965  while (pond->ipv6_pools[num_pools] != NULL) {
3966  num_pools++;
3967  }
3968  }
3969  tmp = dmalloc(sizeof(struct ipv6_pool *) * (num_pools + 2), MDL);
3970  if (tmp == NULL) {
3971  log_fatal("Out of memory");
3972  }
3973  if (num_pools > 0) {
3974  memcpy(tmp, pond->ipv6_pools,
3975  sizeof(struct ipv6_pool *) * num_pools);
3976  }
3977  if (pond->ipv6_pools != NULL) {
3978  dfree(pond->ipv6_pools, MDL);
3979  }
3980  pond->ipv6_pools = tmp;
3981 
3982  /*
3983  * Record this pool in our array of pools for this shared network.
3984  */
3985  ipv6_pool_reference(&pond->ipv6_pools[num_pools], pool, MDL);
3986  pond->ipv6_pools[num_pools+1] = NULL;
3987 
3988  /* Update the number of elements in the pond. Conveniently
3989  * we have the total size of the block in bits and the amount
3990  * we would allocate per element in units. For an address units
3991  * will always be 128, for a prefix it will be something else.
3992  *
3993  * We need to make sure the number of elements isn't too large
3994  * to track. If so, we flag it to avoid wasting time with log
3995  * threshold logic. We also emit a log stating that log-threshold
3996  * will be disabled for the shared-network but that's done
3997  * elsewhere via report_log_threshold().
3998  *
3999  */
4000 
4001  /* Only bother if we aren't already flagged as jumbo */
4002  if (pond->jumbo_range == 0) {
4003  if ((units - bits) > (sizeof(isc_uint64_t) * 8)) {
4004  pond->jumbo_range = 1;
4005  pond->num_total = POND_TRACK_MAX;
4006  }
4007  else {
4008  isc_uint64_t space_left
4009  = POND_TRACK_MAX - pond->num_total;
4010  isc_uint64_t addon
4011  = (isc_uint64_t)(1) << (units - bits);
4012 
4013  if (addon > space_left) {
4014  pond->jumbo_range = 1;
4015  pond->num_total = POND_TRACK_MAX;
4016  } else {
4017  pond->num_total += addon;
4018  }
4019  }
4020  }
4021 }
4022 
4049 static void
4050 add_ipv6_pond_to_network(struct group *group,
4051  struct ipv6_pond **ret_pond) {
4052 
4053  struct ipv6_pond *pond = NULL, *last = NULL;
4054  struct permit *p;
4055  isc_result_t status;
4056  struct shared_network *shared = group->subnet->shared_network;
4057 
4058  for (pond = shared->ipv6_pond; pond; pond = pond->next) {
4059  if ((pond->group->statements == group->statements) &&
4060  (pond->prohibit_list == NULL) &&
4061  (pond->permit_list != NULL) &&
4062  (pond->permit_list->next == NULL) &&
4063  (pond->permit_list->type == permit_all_clients)) {
4064  ipv6_pond_reference(ret_pond, pond, MDL);
4065  return;
4066  }
4067  last = pond;
4068  }
4069 
4070  /* no pond available, make one */
4071  status = ipv6_pond_allocate(&pond, MDL);
4072  if (status != ISC_R_SUCCESS)
4073  log_fatal ("no memory for ad-hoc ipv6 pond: %s",
4074  isc_result_totext (status));
4075  p = new_permit (MDL);
4076  if (p == NULL)
4077  log_fatal ("no memory for ad-hoc ipv6 permit.");
4078 
4079  /* we permit all clients */
4080  p->type = permit_all_clients;
4081  pond->permit_list = p;
4082 
4083  /* and attach the pond to the return argument and the shared network */
4084  ipv6_pond_reference(ret_pond, pond, MDL);
4085 
4086  if (shared->ipv6_pond)
4087  ipv6_pond_reference(&last->next, pond, MDL);
4088  else
4089  ipv6_pond_reference(&shared->ipv6_pond, pond, MDL);
4090 
4091  shared_network_reference(&pond->shared_network, shared, MDL);
4092  if (!clone_group (&pond->group, group, MDL))
4093  log_fatal ("no memory for anon pool group.");
4094 
4095  ipv6_pond_dereference(&pond, MDL);
4096  return;
4097 }
4098 
4099 
4100 /* address-range6-declaration :== ip-address6 ip-address6 SEMI
4101  | ip-address6 SLASH number SEMI
4102  | ip-address6 [SLASH number] TEMPORARY SEMI */
4103 
4104 void
4105 parse_address_range6(struct parse *cfile,
4106  struct group *group,
4107  struct ipv6_pond *inpond) {
4108  struct iaddr lo, hi;
4109  int bits;
4110  enum dhcp_token token;
4111  const char *val;
4112  struct iaddrcidrnetlist *nets, net;
4113  struct iaddrcidrnetlist *p;
4114  u_int16_t type = D6O_IA_NA;
4115  struct ipv6_pond *pond = NULL;
4116 
4117  if (local_family != AF_INET6) {
4118  parse_warn(cfile, "range6 statement is only supported "
4119  "in DHCPv6 mode.");
4120  skip_to_semi(cfile);
4121  return;
4122  }
4123 
4124  /* This is enforced by the caller, this is just a sanity check. */
4125  if (group->subnet == NULL)
4126  log_fatal("Impossible condition at %s:%d.", MDL);
4127 
4128  /*
4129  * Read starting address.
4130  */
4131  if (!parse_ip6_addr(cfile, &lo)) {
4132  return;
4133  }
4134 
4135  /* Make sure starting address is within the subnet */
4136  if (!addr_eq(group->subnet->net,
4137  subnet_number(lo, group->subnet->netmask))) {
4138  parse_warn(cfile, "range6 start address is outside the subnet");
4139  skip_to_semi(cfile);
4140  return;
4141  }
4142 
4143  /*
4144  * zero out the net entry in case we use it
4145  */
4146  memset(&net, 0, sizeof(net));
4147  net.cidrnet.lo_addr = lo;
4148 
4149  /*
4150  * See if we we're using range or CIDR notation or TEMPORARY
4151  */
4152  token = peek_token(&val, NULL, cfile);
4153  if (token == SLASH) {
4154  /*
4155  * '/' means CIDR notation, so read the bits we want.
4156  */
4157  skip_token(NULL, NULL, cfile);
4158  token = next_token(&val, NULL, cfile);
4159  if (token != NUMBER) {
4160  parse_warn(cfile, "expecting number");
4161  skip_to_semi(cfile);
4162  return;
4163  }
4164  net.cidrnet.bits = atoi(val);
4165  bits = net.cidrnet.bits;
4166  if ((bits < 0) || (bits > 128)) {
4167  parse_warn(cfile, "networks have 0 to 128 bits");
4168  skip_to_semi(cfile);
4169  return;
4170  }
4171  if (bits < group->subnet->prefix_len) {
4172  parse_warn(cfile,
4173  "network mask smaller than subnet mask");
4174  skip_to_semi(cfile);
4175  return;
4176  }
4177  if (!is_cidr_mask_valid(&net.cidrnet.lo_addr, bits)) {
4178  parse_warn(cfile, "network mask too short");
4179  skip_to_semi(cfile);
4180  return;
4181  }
4182  /*
4183  * can be temporary (RFC 4941 like)
4184  */
4185  token = peek_token(&val, NULL, cfile);
4186  if (token == TEMPORARY) {
4187  if (bits < 64)
4188  parse_warn(cfile, "temporary mask too short");
4189  if (bits == 128)
4190  parse_warn(cfile, "temporary singleton?");
4191  skip_token(NULL, NULL, cfile);
4192  type = D6O_IA_TA;
4193  }
4194 
4195  nets = &net;
4196 
4197  } else if (token == TEMPORARY) {
4198  /*
4199  * temporary (RFC 4941)
4200  */
4201  type = D6O_IA_TA;
4202  skip_token(NULL, NULL, cfile);
4203  net.cidrnet.bits = 64;
4205  net.cidrnet.bits)) {
4206  parse_warn(cfile, "network mask too short");
4207  skip_to_semi(cfile);
4208  return;
4209  }
4210 
4211  nets = &net;
4212 
4213  } else {
4214  /*
4215  * No '/', so we are looking for the end address of
4216  * the IPv6 pool.
4217  */
4218  if (!parse_ip6_addr(cfile, &hi)) {
4219  return;
4220  }
4221 
4222  /* Make sure ending address is within the subnet */
4223  if (!addr_eq(group->subnet->net,
4224  subnet_number(hi, group->subnet->netmask))) {
4225  parse_warn(cfile,
4226  "range6 end address is outside the subnet");
4227  skip_to_semi(cfile);
4228  return;
4229  }
4230 
4231  /*
4232  * Convert our range to a set of CIDR networks.
4233  */
4234  nets = NULL;
4235  if (range2cidr(&nets, &lo, &hi) != ISC_R_SUCCESS) {
4236  log_fatal("Error converting range to CIDR networks");
4237  }
4238 
4239  }
4240 
4241  /*
4242  * See if we have a pond for this set of pools.
4243  * If the caller supplied one we use it, otherwise
4244  * check the shared network
4245  */
4246 
4247  if (inpond != NULL) {
4248  ipv6_pond_reference(&pond, inpond, MDL);
4249  } else {
4250  add_ipv6_pond_to_network(group, &pond);
4251  }
4252 
4253  /* Now that we have a pond add the nets we have parsed */
4254  for (p=nets; p != NULL; p=p->next) {
4255  add_ipv6_pool_to_subnet(group->subnet, type,
4256  &p->cidrnet.lo_addr,
4257  p->cidrnet.bits, 128, pond);
4258  }
4259 
4260  /* if we allocated a list free it now */
4261  if (nets != &net)
4262  free_iaddrcidrnetlist(&nets);
4263 
4264  ipv6_pond_dereference(&pond, MDL);
4265 
4266  token = next_token(NULL, NULL, cfile);
4267  if (token != SEMI) {
4268  parse_warn(cfile, "semicolon expected.");
4269  skip_to_semi(cfile);
4270  return;
4271  }
4272 }
4273 
4274 /* prefix6-declaration :== ip-address6 ip-address6 SLASH number SEMI */
4275 
4276 void
4277 parse_prefix6(struct parse *cfile,
4278  struct group *group,
4279  struct ipv6_pond *inpond) {
4280  struct iaddr lo, hi;
4281  int bits;
4282  enum dhcp_token token;
4283  const char *val;
4284  struct iaddrcidrnetlist *nets;
4285  struct iaddrcidrnetlist *p;
4286  struct ipv6_pond *pond = NULL;
4287 
4288  if (local_family != AF_INET6) {
4289  parse_warn(cfile, "prefix6 statement is only supported "
4290  "in DHCPv6 mode.");
4291  skip_to_semi(cfile);
4292  return;
4293  }
4294 
4295  /* This is enforced by the caller, so it's just a sanity check. */
4296  if (group->subnet == NULL)
4297  log_fatal("Impossible condition at %s:%d.", MDL);
4298 
4299  /*
4300  * Read starting and ending address.
4301  */
4302  if (!parse_ip6_addr(cfile, &lo)) {
4303  return;
4304  }
4305 
4306 #if 0
4307  /* Prefixes are not required to be within the subnet, but I'm not
4308  * entirely sure that we won't want to revive this code as a warning
4309  * in the future so I'm ifdeffing it
4310  */
4311 
4312  /* Make sure starting prefix is within the subnet */
4313  if (!addr_eq(group->subnet->net,
4314  subnet_number(lo, group->subnet->netmask))) {
4315  parse_warn(cfile, "prefix6 start prefix"
4316  " is outside the subnet");
4317  skip_to_semi(cfile);
4318  return;
4319  }
4320 #endif
4321 
4322  if (!parse_ip6_addr(cfile, &hi)) {
4323  return;
4324  }
4325 
4326 #if 0
4327  /* Prefixes are not required to be within the subnet, but I'm not
4328  * entirely sure that we won't want to revive this code as a warning
4329  * in the future so I'm ifdeffing it
4330  */
4331 
4332  /* Make sure ending prefix is within the subnet */
4333  if (!addr_eq(group->subnet->net,
4334  subnet_number(hi, group->subnet->netmask))) {
4335  parse_warn(cfile, "prefix6 end prefix"
4336  " is outside the subnet");
4337  skip_to_semi(cfile);
4338  return;
4339  }
4340 #endif
4341 
4342  /*
4343  * Next is '/' number ';'.
4344  */
4345  token = next_token(NULL, NULL, cfile);
4346  if (token != SLASH) {
4347  parse_warn(cfile, "expecting '/'");
4348  if (token != SEMI)
4349  skip_to_semi(cfile);
4350  return;
4351  }
4352  token = next_token(&val, NULL, cfile);
4353  if (token != NUMBER) {
4354  parse_warn(cfile, "expecting number");
4355  if (token != SEMI)
4356  skip_to_semi(cfile);
4357  return;
4358  }
4359  bits = atoi(val);
4360  if ((bits <= 0) || (bits >= 128)) {
4361  parse_warn(cfile, "networks have 0 to 128 bits (exclusive)");
4362  return;
4363  }
4364 
4365 #if 0
4366  /* Prefixes are not required to be within the subnet, but I'm not
4367  * entirely sure that we won't want to revive this code as a warning
4368  * in the future so I'm ifdeffing it
4369  */
4370 
4371  if (bits < group->subnet->prefix_len) {
4372  parse_warn(cfile, "network mask smaller than subnet mask");
4373  skip_to_semi(cfile);
4374  return;
4375  }
4376 #endif
4377 
4378  if (!is_cidr_mask_valid(&lo, bits) ||
4379  !is_cidr_mask_valid(&hi, bits)) {
4380  parse_warn(cfile, "network mask too short");
4381  skip_to_semi(cfile);
4382  return;
4383  }
4384  token = next_token(NULL, NULL, cfile);
4385  if (token != SEMI) {
4386  parse_warn(cfile, "semicolon expected.");
4387  skip_to_semi(cfile);
4388  return;
4389  }
4390 
4391  /*
4392  * Convert our range to a set of CIDR networks.
4393  */
4394  nets = NULL;
4395  if (range2cidr(&nets, &lo, &hi) != ISC_R_SUCCESS) {
4396  log_fatal("Error converting prefix to CIDR");
4397  }
4398 
4399  /*
4400  * See if we have a pond for this set of pools.
4401  * If the caller supplied one we use it, otherwise
4402  * check the shared network
4403  */
4404 
4405  if (inpond != NULL) {
4406  ipv6_pond_reference(&pond, inpond, MDL);
4407  } else {
4408  add_ipv6_pond_to_network(group, &pond);
4409  }
4410 
4411  for (p = nets; p != NULL; p = p->next) {
4412  /* Normalize and check. */
4413  if (p->cidrnet.bits == 128) {
4414  p->cidrnet.bits = bits;
4415  }
4416  if (p->cidrnet.bits > bits) {
4417  parse_warn(cfile, "impossible mask length");
4418  continue;
4419  }
4420  add_ipv6_pool_to_subnet(group->subnet, D6O_IA_PD,
4421  &p->cidrnet.lo_addr,
4422  p->cidrnet.bits, bits, pond);
4423  }
4424 
4425  free_iaddrcidrnetlist(&nets);
4426 }
4427 
4428 /* fixed-prefix6 :== ip6-address SLASH number SEMI */
4429 
4430 void
4431 parse_fixed_prefix6(struct parse *cfile, struct host_decl *host_decl) {
4432  struct iaddrcidrnetlist *ia, **h;
4433  enum dhcp_token token;
4434  const char *val;
4435 
4436  /*
4437  * Get the head of the fixed-prefix list.
4438  */
4439  h = &host_decl->fixed_prefix;
4440 
4441  /*
4442  * Walk to the end.
4443  */
4444  while (*h != NULL) {
4445  h = &((*h)->next);
4446  }
4447 
4448  /*
4449  * Allocate a new iaddrcidrnetlist structure.
4450  */
4451  ia = dmalloc(sizeof(*ia), MDL);
4452  if (!ia) {
4453  log_fatal("Out of memory");
4454  }
4455 
4456  /*
4457  * Parse it.
4458  */
4459  if (!parse_ip6_addr(cfile, &ia->cidrnet.lo_addr)) {
4460  dfree(ia, MDL);
4461  return;
4462  }
4463  token = next_token(NULL, NULL, cfile);
4464  if (token != SLASH) {
4465  dfree(ia, MDL);
4466  parse_warn(cfile, "expecting '/'");
4467  if (token != SEMI)
4468  skip_to_semi(cfile);
4469  return;
4470  }
4471  token = next_token(&val, NULL, cfile);
4472  if (token != NUMBER) {
4473  dfree(ia, MDL);
4474  parse_warn(cfile, "expecting number");
4475  if (token != SEMI)
4476  skip_to_semi(cfile);
4477  return;
4478  }
4479  token = next_token(NULL, NULL, cfile);
4480  if (token != SEMI) {
4481  dfree(ia, MDL);
4482  parse_warn(cfile, "semicolon expected.");
4483  skip_to_semi(cfile);
4484  return;
4485  }
4486 
4487  /*
4488  * Fill it.
4489  */
4490  ia->cidrnet.bits = atoi(val);
4491  if ((ia->cidrnet.bits < 0) || (ia->cidrnet.bits > 128)) {
4492  dfree(ia, MDL);
4493  parse_warn(cfile, "networks have 0 to 128 bits");
4494  return;
4495  }
4496  if (!is_cidr_mask_valid(&ia->cidrnet.lo_addr, ia->cidrnet.bits)) {
4497  dfree(ia, MDL);
4498  parse_warn(cfile, "network mask too short");
4499  return;
4500  }
4501 
4502  /*
4503  * Store it.
4504  */
4505  *h = ia;
4506  return;
4507 }
4508 
4528 void parse_pool6_statement (cfile, group, type)
4529  struct parse *cfile;
4530  struct group *group;
4531  int type;
4532 {
4533  enum dhcp_token token;
4534  const char *val;
4535  int done = 0;
4536  struct ipv6_pond *pond, **p;
4537  int declaration = 0;
4538  isc_result_t status;
4539 
4540  pond = NULL;
4541  status = ipv6_pond_allocate(&pond, MDL);
4542  if (status != ISC_R_SUCCESS)
4543  log_fatal("no memory for pool6: %s",
4544  isc_result_totext (status));
4545 
4546  if (type == SUBNET_DECL)
4547  shared_network_reference(&pond->shared_network,
4548  group->subnet->shared_network,
4549  MDL);
4550  else {
4551  parse_warn(cfile, "pool6s are only valid inside "
4552  "subnet statements.");
4553  ipv6_pond_dereference(&pond, MDL);
4554  skip_to_semi(cfile);
4555  return;
4556  }
4557 
4558  if (clone_group(&pond->group, group, MDL) == 0)
4559  log_fatal("can't clone pool6 group.");
4560 
4561  if (parse_lbrace(cfile) == 0) {
4562  ipv6_pond_dereference(&pond, MDL);
4563  return;
4564  }
4565 
4566  do {
4567  token = peek_token(&val, NULL, cfile);
4568  switch (token) {
4569  case RANGE6:
4570  skip_token(NULL, NULL, cfile);
4571  parse_address_range6(cfile, group, pond);
4572  break;
4573 
4574  case PREFIX6:
4575  skip_token(NULL, NULL, cfile);
4576  parse_prefix6(cfile, group, pond);
4577  break;
4578 
4579  case ALLOW:
4580  skip_token(NULL, NULL, cfile);
4581  get_permit(cfile, &pond->permit_list, 1,
4582  &pond->valid_from, &pond->valid_until);
4583  break;
4584 
4585  case DENY:
4586  skip_token(NULL, NULL, cfile);
4587  get_permit(cfile, &pond->prohibit_list, 0,
4588  &pond->valid_from, &pond->valid_until);
4589  break;
4590 
4591  case RBRACE:
4592  skip_token(&val, NULL, cfile);
4593  done = 1;
4594  break;
4595 
4596  case END_OF_FILE:
4597  /*
4598  * We can get to END_OF_FILE if, for instance,
4599  * the parse_statement() reads all available tokens
4600  * and leaves us at the end.
4601  */
4602  parse_warn(cfile, "unexpected end of file");
4603  goto cleanup;
4604 
4605  default:
4606  declaration = parse_statement(cfile, pond->group,
4607  POOL_DECL, NULL,
4608  declaration);
4609  break;
4610  }
4611  } while (!done);
4612 
4613  /*
4614  * A possible optimization is to see if this pond can be merged into
4615  * an already existing pond. But I'll pass on that for now as we need
4616  * to repoint the leases to the other pond which is annoying. SAR
4617  */
4618 
4619  /*
4620  * Add this pond to the list (will need updating if we add the
4621  * optimization).
4622  */
4623 
4624  p = &pond->shared_network->ipv6_pond;
4625  for (; *p; p = &((*p)->next))
4626  ;
4627  ipv6_pond_reference(p, pond, MDL);
4628 
4629  /* Don't allow a pool6 declaration with no addresses or
4630  prefixes, since it is probably a configuration error. */
4631  if (pond->ipv6_pools == NULL) {
4632  parse_warn (cfile, "Pool6 declaration with no %s.",
4633  "address range6 or prefix6");
4634  log_error ("Pool6 declarations must always contain at least");
4635  log_error ("one range6 or prefix6 statement.");
4636  }
4637 
4638 cleanup:
4639  ipv6_pond_dereference(&pond, MDL);
4640 }
4641 
4642 
4643 
4644 #endif /* DHCPv6 */
4645 
4646 /* allow-deny-keyword :== BOOTP
4647  | BOOTING
4648  | DYNAMIC_BOOTP
4649  | UNKNOWN_CLIENTS */
4650 
4651 int parse_allow_deny (oc, cfile, flag)
4652  struct option_cache **oc;
4653  struct parse *cfile;
4654  int flag;
4655 {
4656  enum dhcp_token token;
4657  const char *val;
4658  unsigned char rf = flag;
4659  unsigned code;
4660  struct option *option = NULL;
4661  struct expression *data = (struct expression *)0;
4662  int status;
4663 
4664  if (!make_const_data (&data, &rf, 1, 0, 1, MDL))
4665  return 0;
4666 
4667  token = next_token (&val, (unsigned *)0, cfile);
4668  switch (token) {
4669  case TOKEN_BOOTP:
4670  code = SV_ALLOW_BOOTP;
4671  break;
4672 
4673  case BOOTING:
4674  code = SV_ALLOW_BOOTING;
4675  break;
4676 
4677  case DYNAMIC_BOOTP:
4678  code = SV_DYNAMIC_BOOTP;
4679  break;
4680 
4681  case UNKNOWN_CLIENTS:
4682  code = SV_BOOT_UNKNOWN_CLIENTS;
4683  break;
4684 
4685  case DUPLICATES:
4686  code = SV_DUPLICATES;
4687  break;
4688 
4689  case DECLINES:
4690  code= SV_DECLINES;
4691  break;
4692 
4693  case CLIENT_UPDATES:
4694  code = SV_CLIENT_UPDATES;
4695  break;
4696 
4697  case LEASEQUERY:
4698  code = SV_LEASEQUERY;
4699  break;
4700 
4701  default:
4702  parse_warn (cfile, "expecting allow/deny key");
4703  skip_to_semi (cfile);
4704  expression_dereference (&data, MDL);
4705  return 0;
4706  }
4707  /* Reference on option is passed to option cache. */
4708  if (!option_code_hash_lookup(&option, server_universe.code_hash,
4709  &code, 0, MDL))
4710  log_fatal("Unable to find server option %u (%s:%d).",
4711  code, MDL);
4712  status = option_cache(oc, NULL, data, option, MDL);
4713  expression_dereference (&data, MDL);
4714  parse_semi (cfile);
4715  return status;
4716 }
4717 
4718 void
4720 #if !defined(DHCPv6)
4721  parse_warn(cfile, "No DHCPv6 support.");
4722  skip_to_semi(cfile);
4723 #else /* defined(DHCPv6) */
4724  enum dhcp_token token;
4725  struct ia_xx *ia = NULL;
4726  const char *val;
4727  struct ia_xx *old_ia;
4728  u_int32_t iaid;
4729  struct iaddr iaddr;
4730  binding_state_t state;
4731  u_int32_t prefer;
4732  u_int32_t valid;
4733  TIME end_time;
4734  struct iasubopt *iaaddr;
4735  struct ipv6_pool *pool;
4736  char addr_buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
4737  isc_boolean_t newbinding;
4738  struct binding_scope *scope = NULL;
4739  struct binding *bnd;
4740  struct binding_value *nv = NULL;
4741  struct executable_statement *on_star[2] = {NULL, NULL};
4742  int lose, i;
4743 
4744  if (local_family != AF_INET6) {
4745  parse_warn(cfile, "IA_NA is only supported in DHCPv6 mode.");
4746  skip_to_semi(cfile);
4747  return;
4748  }
4749 
4750  if (!parse_iaid_duid(cfile, &ia, &iaid, MDL)) {
4751  return;
4752  }
4753 
4754  ia->ia_type = D6O_IA_NA;
4755 
4756  token = next_token(&val, NULL, cfile);
4757  if (token != LBRACE) {
4758  parse_warn(cfile, "corrupt lease file; expecting left brace");
4759  skip_to_semi(cfile);
4760  return;
4761  }
4762 
4763  for (;;) {
4764  token = next_token(&val, NULL, cfile);
4765  if (token == RBRACE) break;
4766 
4767  if (token == CLTT) {
4768  ia->cltt = parse_date (cfile);
4769  continue;
4770  }
4771 
4772  if (token != IAADDR) {
4773  parse_warn(cfile, "corrupt lease file; "
4774  "expecting IAADDR or right brace");
4775  skip_to_semi(cfile);
4776  return;
4777  }
4778 
4779  if (!parse_ip6_addr(cfile, &iaddr)) {
4780  parse_warn(cfile, "corrupt lease file; "
4781  "expecting IPv6 address");
4782  skip_to_semi(cfile);
4783  return;
4784  }
4785 
4786  token = next_token(&val, NULL, cfile);
4787  if (token != LBRACE) {
4788  parse_warn(cfile, "corrupt lease file; "
4789  "expecting left brace");
4790  skip_to_semi(cfile);
4791  return;
4792  }
4793 
4794  state = FTS_LAST+1;
4795  prefer = valid = 0;
4796  end_time = -1;
4797  for (;;) {
4798  token = next_token(&val, NULL, cfile);
4799  if (token == RBRACE) break;
4800 
4801  switch(token) {
4802  case END_OF_FILE:
4803  /* We hit the end of file and don't know
4804  * what parts of the lease we may be missing
4805  * don't try to salvage the lease
4806  */
4807  parse_warn(cfile, "corrupt lease file; "
4808  "unexpected end of file");
4809  return;
4810 
4811  /* Lease binding state. */
4812  case BINDING:
4813  token = next_token(&val, NULL, cfile);
4814  if (token != STATE) {
4815  parse_warn(cfile, "corrupt lease file; "
4816  "expecting state");
4817  skip_to_semi(cfile);
4818  return;
4819  }
4820  token = next_token(&val, NULL, cfile);
4821  switch (token) {
4822  case TOKEN_ABANDONED:
4823  state = FTS_ABANDONED;
4824  break;
4825  case TOKEN_FREE:
4826  state = FTS_FREE;
4827  break;
4828  case TOKEN_ACTIVE:
4829  state = FTS_ACTIVE;
4830  break;
4831  case TOKEN_EXPIRED:
4832  state = FTS_EXPIRED;
4833  break;
4834  case TOKEN_RELEASED:
4835  state = FTS_RELEASED;
4836  break;
4837  default:
4838  parse_warn(cfile,
4839  "corrupt lease "
4840  "file; "
4841  "expecting a "
4842  "binding state.");
4843  skip_to_semi(cfile);
4844  return;
4845  }
4846 
4847  token = next_token(&val, NULL, cfile);
4848  if (token != SEMI) {
4849  parse_warn(cfile, "corrupt lease file; "
4850  "expecting "
4851  "semicolon.");
4852  }
4853  break;
4854 
4855  /* Lease preferred lifetime. */
4856  case PREFERRED_LIFE:
4857  token = next_token(&val, NULL, cfile);
4858  if (token != NUMBER) {
4859  parse_warn(cfile, "%s is not a valid "
4860  "preferred time",
4861  val);
4862  skip_to_semi(cfile);
4863  continue;
4864  }
4865  prefer = atoi (val);
4866 
4867  /*
4868  * Currently we peek for the semi-colon to
4869  * allow processing of older lease files that
4870  * don't have the semi-colon. Eventually we
4871  * should remove the peeking code.
4872  */
4873  token = peek_token(&val, NULL, cfile);
4874  if (token == SEMI) {
4875  skip_token(&val, NULL, cfile);
4876  } else {
4877  parse_warn(cfile,
4878  "corrupt lease file; "
4879  "expecting semicolon.");
4880  }
4881  break;
4882 
4883  /* Lease valid lifetime. */
4884  case MAX_LIFE:
4885  token = next_token(&val, NULL, cfile);
4886  if (token != NUMBER) {
4887  parse_warn(cfile, "%s is not a valid "
4888  "max time",
4889  val);
4890  skip_to_semi(cfile);
4891  continue;
4892  }
4893  valid = atoi (val);
4894 
4895  /*
4896  * Currently we peek for the semi-colon to
4897  * allow processing of older lease files that
4898  * don't have the semi-colon. Eventually we
4899  * should remove the peeking code.
4900  */
4901  token = peek_token(&val, NULL, cfile);
4902  if (token == SEMI) {
4903  skip_token(&val, NULL, cfile);
4904  } else {
4905  parse_warn(cfile,
4906  "corrupt lease file; "
4907  "expecting semicolon.");
4908  }
4909  break;
4910 
4911  /* Lease expiration time. */
4912  case ENDS:
4913  end_time = parse_date(cfile);
4914  break;
4915 
4916  /* Lease binding scopes. */
4917  case TOKEN_SET:
4918  token = next_token(&val, NULL, cfile);
4919  if ((token != NAME) &&
4920  (token != NUMBER_OR_NAME)) {
4921  parse_warn(cfile, "%s is not a valid "
4922  "variable name",
4923  val);
4924  skip_to_semi(cfile);
4925  continue;
4926  }
4927 
4928  if (scope != NULL)
4929  bnd = find_binding(scope, val);
4930  else {
4931  if (!binding_scope_allocate(&scope,
4932  MDL)) {
4933  log_fatal("Out of memory for "
4934  "lease binding "
4935  "scope.");
4936  }
4937 
4938  bnd = NULL;
4939  }
4940 
4941  if (bnd == NULL) {
4942  bnd = dmalloc(sizeof(*bnd),
4943  MDL);
4944  if (bnd == NULL) {
4945  log_fatal("No memory for "
4946  "lease binding.");
4947  }
4948 
4949  bnd->name = dmalloc(strlen(val) + 1,
4950  MDL);
4951  if (bnd->name == NULL) {
4952  log_fatal("No memory for "
4953  "binding name.");
4954  }
4955  strcpy(bnd->name, val);
4956 
4957  newbinding = ISC_TRUE;
4958  } else {
4959  newbinding = ISC_FALSE;
4960  }
4961 
4962  if (!binding_value_allocate(&nv, MDL)) {
4963  log_fatal("no memory for binding "
4964  "value.");
4965  }
4966 
4967  token = next_token(NULL, NULL, cfile);
4968  if (token != EQUAL) {
4969  parse_warn(cfile, "expecting '=' in "
4970  "set statement.");
4971  goto binding_err;
4972  }
4973 
4974  if (!parse_binding_value(cfile, nv)) {
4975  binding_err:
4977  binding_scope_dereference(&scope, MDL);
4978  return;
4979  }
4980 
4981  if (newbinding) {
4983  nv, MDL);
4984  bnd->next = scope->bindings;
4985  scope->bindings = bnd;
4986  } else {
4988  MDL);
4990  nv, MDL);
4991  }
4992 
4994  parse_semi(cfile);
4995  break;
4996 
4997  case ON:
4998  lose = 0;
4999  /*
5000  * Depending on the user config we may
5001  * have one or two on statements. We
5002  * need to save information about both
5003  * of them until we allocate the
5004  * iasubopt to hold them.
5005  */
5006  if (on_star[0] == NULL) {
5007  if (!parse_on_statement (&on_star[0],
5008  cfile,
5009  &lose)) {
5010  parse_warn(cfile,
5011  "corrupt lease "
5012  "file; bad ON "
5013  "statement");
5014  skip_to_rbrace (cfile, 1);
5015  return;
5016  }
5017  } else {
5018  if (!parse_on_statement (&on_star[1],
5019  cfile,
5020  &lose)) {
5021  parse_warn(cfile,
5022  "corrupt lease "
5023  "file; bad ON "
5024  "statement");
5025  skip_to_rbrace (cfile, 1);
5026  return;
5027  }
5028  }
5029 
5030  break;
5031 
5032  default:
5033  parse_warn(cfile, "corrupt lease file; "
5034  "expecting ia_na contents, "
5035  "got '%s'", val);
5036  skip_to_semi(cfile);
5037  continue;
5038  }
5039  }
5040 
5041  if (state == FTS_LAST+1) {
5042  parse_warn(cfile, "corrupt lease file; "
5043  "missing state in iaaddr");
5044  return;
5045  }
5046  if (end_time == -1) {
5047  parse_warn(cfile, "corrupt lease file; "
5048  "missing end time in iaaddr");
5049  return;
5050  }
5051 
5052  iaaddr = NULL;
5053  if (iasubopt_allocate(&iaaddr, MDL) != ISC_R_SUCCESS) {
5054  log_fatal("Out of memory.");
5055  }
5056  memcpy(&iaaddr->addr, iaddr.iabuf, sizeof(iaaddr->addr));
5057  iaaddr->plen = 0;
5058  iaaddr->state = state;
5059  iaaddr->prefer = prefer;
5060  iaaddr->valid = valid;
5061  if (iaaddr->state == FTS_RELEASED)
5062  iaaddr->hard_lifetime_end_time = end_time;
5063 
5064  if (scope != NULL) {
5065  binding_scope_reference(&iaaddr->scope, scope, MDL);
5066  binding_scope_dereference(&scope, MDL);
5067  }
5068 
5069  /*
5070  * Check on both on statements. Because of how we write the
5071  * lease file we know which is which if we have two but it's
5072  * easier to write the code to be independent. We do assume
5073  * that the statements won't overlap.
5074  */
5075  for (i = 0;
5076  (i < 2) && on_star[i] != NULL ;
5077  i++) {
5078  if ((on_star[i]->data.on.evtypes & ON_EXPIRY) &&
5079  on_star[i]->data.on.statements) {
5081  (&iaaddr->on_star.on_expiry,
5082  on_star[i]->data.on.statements, MDL);
5083  }
5084  if ((on_star[i]->data.on.evtypes & ON_RELEASE) &&
5085  on_star[i]->data.on.statements) {
5087  (&iaaddr->on_star.on_release,
5088  on_star[i]->data.on.statements, MDL);
5089  }
5090  executable_statement_dereference (&on_star[i], MDL);
5091  }
5092 
5093  /* find the pool this address is in */
5094  pool = NULL;
5095  if (find_ipv6_pool(&pool, D6O_IA_NA,
5096  &iaaddr->addr) != ISC_R_SUCCESS) {
5097  inet_ntop(AF_INET6, &iaaddr->addr,
5098  addr_buf, sizeof(addr_buf));
5099  log_error("No pool found for IA_NA address %s",
5100  addr_buf);
5101  iasubopt_dereference(&iaaddr, MDL);
5102  continue;
5103  }
5104 
5105  /* remove old information */
5106  if (cleanup_lease6(ia_na_active, pool,
5107  iaaddr, ia) != ISC_R_SUCCESS) {
5108  inet_ntop(AF_INET6, &iaaddr->addr,
5109  addr_buf, sizeof(addr_buf));
5110  parse_warn(cfile, "duplicate na lease for address %s",
5111  addr_buf);
5112  }
5113 
5114  /*
5115  * if we like the lease we add it to our various structues
5116  * otherwise we leave it and it will get cleaned when we
5117  * do the iasubopt_dereference.
5118  */
5119  if ((state == FTS_ACTIVE) || (state == FTS_ABANDONED)) {
5120  ia_add_iasubopt(ia, iaaddr, MDL);
5121  ia_reference(&iaaddr->ia, ia, MDL);
5122  add_lease6(pool, iaaddr, end_time);
5123  }
5124 
5125  iasubopt_dereference(&iaaddr, MDL);
5126  ipv6_pool_dereference(&pool, MDL);
5127  }
5128 
5129  /*
5130  * If we have an existing record for this IA_NA, remove it.
5131  */
5132  old_ia = NULL;
5133  if (ia_hash_lookup(&old_ia, ia_na_active,
5134  (unsigned char *)ia->iaid_duid.data,
5135  ia->iaid_duid.len, MDL)) {
5136  ia_hash_delete(ia_na_active,
5137  (unsigned char *)ia->iaid_duid.data,
5138  ia->iaid_duid.len, MDL);
5139  ia_dereference(&old_ia, MDL);
5140  }
5141 
5142  /*
5143  * If we have addresses, add this, otherwise don't bother.
5144  */
5145  if (ia->num_iasubopt > 0) {
5146  ia_hash_add(ia_na_active,
5147  (unsigned char *)ia->iaid_duid.data,
5148  ia->iaid_duid.len, ia, MDL);
5149  }
5150  ia_dereference(&ia, MDL);
5151 #endif /* defined(DHCPv6) */
5152 }
5153 
5154 void
5156 #if !defined(DHCPv6)
5157  parse_warn(cfile, "No DHCPv6 support.");
5158  skip_to_semi(cfile);
5159 #else /* defined(DHCPv6) */
5160  enum dhcp_token token;
5161  struct ia_xx *ia = NULL;
5162  const char *val;
5163  struct ia_xx *old_ia;
5164  u_int32_t iaid;
5165  struct iaddr iaddr;
5166  binding_state_t state;
5167  u_int32_t prefer;
5168  u_int32_t valid;
5169  TIME end_time;
5170  struct iasubopt *iaaddr;
5171  struct ipv6_pool *pool;
5172  char addr_buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
5173  isc_boolean_t newbinding;
5174  struct binding_scope *scope = NULL;
5175  struct binding *bnd;
5176  struct binding_value *nv = NULL;
5177  struct executable_statement *on_star[2] = {NULL, NULL};
5178  int lose, i;
5179 
5180  if (local_family != AF_INET6) {
5181  parse_warn(cfile, "IA_TA is only supported in DHCPv6 mode.");
5182  skip_to_semi(cfile);
5183  return;
5184  }
5185 
5186  if (!parse_iaid_duid(cfile, &ia, &iaid, MDL)) {
5187  return;
5188  }
5189 
5190  ia->ia_type = D6O_IA_TA;
5191 
5192  token = next_token(&val, NULL, cfile);
5193  if (token != LBRACE) {
5194  parse_warn(cfile, "corrupt lease file; expecting left brace");
5195  skip_to_semi(cfile);
5196  return;
5197  }
5198 
5199  for (;;) {
5200  token = next_token(&val, NULL, cfile);
5201  if (token == RBRACE) break;
5202 
5203  if (token == CLTT) {
5204  ia->cltt = parse_date (cfile);
5205  continue;
5206  }
5207 
5208  if (token != IAADDR) {
5209  parse_warn(cfile, "corrupt lease file; "
5210  "expecting IAADDR or right brace");
5211  skip_to_semi(cfile);
5212  return;
5213  }
5214 
5215  if (!parse_ip6_addr(cfile, &iaddr)) {
5216  parse_warn(cfile, "corrupt lease file; "
5217  "expecting IPv6 address");
5218  skip_to_semi(cfile);
5219  return;
5220  }
5221 
5222  token = next_token(&val, NULL, cfile);
5223  if (token != LBRACE) {
5224  parse_warn(cfile, "corrupt lease file; "
5225  "expecting left brace");
5226  skip_to_semi(cfile);
5227  return;
5228  }
5229 
5230  state = FTS_LAST+1;
5231  prefer = valid = 0;
5232  end_time = -1;
5233  for (;;) {
5234  token = next_token(&val, NULL, cfile);
5235  if (token == RBRACE) break;
5236 
5237  switch(token) {
5238  case END_OF_FILE:
5239  /* We hit the end of file and don't know
5240  * what parts of the lease we may be missing
5241  * don't try to salvage the lease
5242  */
5243  parse_warn(cfile, "corrupt lease file; "
5244  "unexpected end of file");
5245  return;
5246 
5247  /* Lease binding state. */
5248  case BINDING:
5249  token = next_token(&val, NULL, cfile);
5250  if (token != STATE) {
5251  parse_warn(cfile, "corrupt lease file; "
5252  "expecting state");
5253  skip_to_semi(cfile);
5254  return;
5255  }
5256  token = next_token(&val, NULL, cfile);
5257  switch (token) {
5258  case TOKEN_ABANDONED:
5259  state = FTS_ABANDONED;
5260  break;
5261  case TOKEN_FREE:
5262  state = FTS_FREE;
5263  break;
5264  case TOKEN_ACTIVE:
5265  state = FTS_ACTIVE;
5266  break;
5267  case TOKEN_EXPIRED:
5268  state = FTS_EXPIRED;
5269  break;
5270  case TOKEN_RELEASED:
5271  state = FTS_RELEASED;
5272  break;
5273  default:
5274  parse_warn(cfile,
5275  "corrupt lease "
5276  "file; "
5277  "expecting a "
5278  "binding state.");
5279  skip_to_semi(cfile);
5280  return;
5281  }
5282 
5283  token = next_token(&val, NULL, cfile);
5284  if (token != SEMI) {
5285  parse_warn(cfile, "corrupt lease file; "
5286  "expecting "
5287  "semicolon.");
5288  }
5289  break;
5290 
5291  /* Lease preferred lifetime. */
5292  case PREFERRED_LIFE:
5293  token = next_token(&val, NULL, cfile);
5294  if (token != NUMBER) {
5295  parse_warn(cfile, "%s is not a valid "
5296  "preferred time",
5297  val);
5298  skip_to_semi(cfile);
5299  continue;
5300  }
5301  prefer = atoi (val);
5302 
5303  /*
5304  * Currently we peek for the semi-colon to
5305  * allow processing of older lease files that
5306  * don't have the semi-colon. Eventually we
5307  * should remove the peeking code.
5308  */
5309  token = peek_token(&val, NULL, cfile);
5310  if (token == SEMI) {
5311  skip_token(&val, NULL, cfile);
5312  } else {
5313  parse_warn(cfile,
5314  "corrupt lease file; "
5315  "expecting semicolon.");
5316  }
5317  break;
5318 
5319  /* Lease valid lifetime. */
5320  case MAX_LIFE:
5321  token = next_token(&val, NULL, cfile);
5322  if (token != NUMBER) {
5323  parse_warn(cfile, "%s is not a valid "
5324  "max time",
5325  val);
5326  skip_to_semi(cfile);
5327  continue;
5328  }
5329  valid = atoi (val);
5330 
5331  /*
5332  * Currently we peek for the semi-colon to
5333  * allow processing of older lease files that
5334  * don't have the semi-colon. Eventually we
5335  * should remove the peeking code.
5336  */
5337  token = peek_token(&val, NULL, cfile);
5338  if (token == SEMI) {
5339  skip_token(&val, NULL, cfile);
5340  } else {
5341  parse_warn(cfile,
5342  "corrupt lease file; "
5343  "expecting semicolon.");
5344  }
5345  break;
5346 
5347  /* Lease expiration time. */
5348  case ENDS:
5349  end_time = parse_date(cfile);
5350  break;
5351 
5352  /* Lease binding scopes. */
5353  case TOKEN_SET:
5354  token = next_token(&val, NULL, cfile);
5355  if ((token != NAME) &&
5356  (token != NUMBER_OR_NAME)) {
5357  parse_warn(cfile, "%s is not a valid "
5358  "variable name",
5359  val);
5360  skip_to_semi(cfile);
5361  continue;
5362  }
5363 
5364  if (scope != NULL)
5365  bnd = find_binding(scope, val);
5366  else {
5367  if (!binding_scope_allocate(&scope,
5368  MDL)) {
5369  log_fatal("Out of memory for "
5370  "lease binding "
5371  "scope.");
5372  }
5373 
5374  bnd = NULL;
5375  }
5376 
5377  if (bnd == NULL) {
5378  bnd = dmalloc(sizeof(*bnd),
5379  MDL);
5380  if (bnd == NULL) {
5381  log_fatal("No memory for "
5382  "lease binding.");
5383  }
5384 
5385  bnd->name = dmalloc(strlen(val) + 1,
5386  MDL);
5387  if (bnd->name == NULL) {
5388  log_fatal("No memory for "
5389  "binding name.");
5390  }
5391  strcpy(bnd->name, val);
5392 
5393  newbinding = ISC_TRUE;
5394  } else {
5395  newbinding = ISC_FALSE;
5396  }
5397 
5398  if (!binding_value_allocate(&nv, MDL)) {
5399  log_fatal("no memory for binding "
5400  "value.");
5401  }
5402 
5403  token = next_token(NULL, NULL, cfile);
5404  if (token != EQUAL) {
5405  parse_warn(cfile, "expecting '=' in "
5406  "set statement.");
5407  goto binding_err;
5408  }
5409 
5410  if (!parse_binding_value(cfile, nv)) {
5411  binding_err:
5413  binding_scope_dereference(&scope, MDL);
5414  return;
5415  }
5416 
5417  if (newbinding) {
5419  nv, MDL);
5420  bnd->next = scope->bindings;
5421  scope->bindings = bnd;
5422  } else {
5424  MDL);
5426  nv, MDL);
5427  }
5428 
5430  parse_semi(cfile);
5431  break;
5432 
5433  case ON:
5434  lose = 0;
5435  /*
5436  * Depending on the user config we may
5437  * have one or two on statements. We
5438  * need to save information about both
5439  * of them until we allocate the
5440  * iasubopt to hold them.
5441  */
5442  if (on_star[0] == NULL) {
5443  if (!parse_on_statement (&on_star[0],
5444  cfile,
5445  &lose)) {
5446  parse_warn(cfile,
5447  "corrupt lease "
5448  "file; bad ON "
5449  "statement");
5450  skip_to_rbrace (cfile, 1);
5451  return;
5452  }
5453  } else {
5454  if (!parse_on_statement (&on_star[1],
5455  cfile,
5456  &lose)) {
5457  parse_warn(cfile,
5458  "corrupt lease "
5459  "file; bad ON "
5460  "statement");
5461  skip_to_rbrace (cfile, 1);
5462  return;
5463  }
5464  }
5465 
5466  break;
5467 
5468  default:
5469  parse_warn(cfile, "corrupt lease file; "
5470  "expecting ia_ta contents, "
5471  "got '%s'", val);
5472  skip_to_semi(cfile);
5473  continue;
5474  }
5475  }
5476 
5477  if (state == FTS_LAST+1) {
5478  parse_warn(cfile, "corrupt lease file; "
5479  "missing state in iaaddr");
5480  return;
5481  }
5482  if (end_time == -1) {
5483  parse_warn(cfile, "corrupt lease file; "
5484  "missing end time in iaaddr");
5485  return;
5486  }
5487 
5488  iaaddr = NULL;
5489  if (iasubopt_allocate(&iaaddr, MDL) != ISC_R_SUCCESS) {
5490  log_fatal("Out of memory.");
5491  }
5492  memcpy(&iaaddr->addr, iaddr.iabuf, sizeof(iaaddr->addr));
5493  iaaddr->plen = 0;
5494  iaaddr->state = state;
5495  iaaddr->prefer = prefer;
5496  iaaddr->valid = valid;
5497  if (iaaddr->state == FTS_RELEASED)
5498  iaaddr->hard_lifetime_end_time = end_time;
5499 
5500  if (scope != NULL) {
5501  binding_scope_reference(&iaaddr->scope, scope, MDL);
5502  binding_scope_dereference(&scope, MDL);
5503  }
5504 
5505  /*
5506  * Check on both on statements. Because of how we write the
5507  * lease file we know which is which if we have two but it's
5508  * easier to write the code to be independent. We do assume
5509  * that the statements won't overlap.
5510  */
5511  for (i = 0;
5512  (i < 2) && on_star[i] != NULL ;
5513  i++) {
5514  if ((on_star[i]->data.on.evtypes & ON_EXPIRY) &&
5515  on_star[i]->data.on.statements) {
5517  (&iaaddr->on_star.on_expiry,
5518  on_star[i]->data.on.statements, MDL);
5519  }
5520  if ((on_star[i]->data.on.evtypes & ON_RELEASE) &&
5521  on_star[i]->data.on.statements) {
5523  (&iaaddr->on_star.on_release,
5524  on_star[i]->data.on.statements, MDL);
5525  }
5526  executable_statement_dereference (&on_star[i], MDL);
5527  }
5528 
5529  /* find the pool this address is in */
5530  pool = NULL;
5531  if (find_ipv6_pool(&pool, D6O_IA_TA,
5532  &iaaddr->addr) != ISC_R_SUCCESS) {
5533  inet_ntop(AF_INET6, &iaaddr->addr,
5534  addr_buf, sizeof(addr_buf));
5535  log_error("No pool found for IA_TA address %s",
5536  addr_buf);
5537  iasubopt_dereference(&iaaddr, MDL);
5538  continue;
5539  }
5540 
5541  /* remove old information */
5542  if (cleanup_lease6(ia_ta_active, pool,
5543  iaaddr, ia) != ISC_R_SUCCESS) {
5544  inet_ntop(AF_INET6, &iaaddr->addr,
5545  addr_buf, sizeof(addr_buf));
5546  parse_warn(cfile, "duplicate ta lease for address %s",
5547  addr_buf);
5548  }
5549 
5550  /*
5551  * if we like the lease we add it to our various structues
5552  * otherwise we leave it and it will get cleaned when we
5553  * do the iasubopt_dereference.
5554  */
5555  if ((state == FTS_ACTIVE) || (state == FTS_ABANDONED)) {
5556  ia_add_iasubopt(ia, iaaddr, MDL);
5557  ia_reference(&iaaddr->ia, ia, MDL);
5558  add_lease6(pool, iaaddr, end_time);
5559  }
5560 
5561  ipv6_pool_dereference(&pool, MDL);
5562  iasubopt_dereference(&iaaddr, MDL);
5563  }
5564 
5565  /*
5566  * If we have an existing record for this IA_TA, remove it.
5567  */
5568  old_ia = NULL;
5569  if (ia_hash_lookup(&old_ia, ia_ta_active,
5570  (unsigned char *)ia->iaid_duid.data,
5571  ia->iaid_duid.len, MDL)) {
5572  ia_hash_delete(ia_ta_active,
5573  (unsigned char *)ia->iaid_duid.data,
5574  ia->iaid_duid.len, MDL);
5575  ia_dereference(&old_ia, MDL);
5576  }
5577 
5578  /*
5579  * If we have addresses, add this, otherwise don't bother.
5580  */
5581  if (ia->num_iasubopt > 0) {
5582  ia_hash_add(ia_ta_active,
5583  (unsigned char *)ia->iaid_duid.data,
5584  ia->iaid_duid.len, ia, MDL);
5585  }
5586  ia_dereference(&ia, MDL);
5587 #endif /* defined(DHCPv6) */
5588 }
5589 
5590 void
5592 #if !defined(DHCPv6)
5593  parse_warn(cfile, "No DHCPv6 support.");
5594  skip_to_semi(cfile);
5595 #else /* defined(DHCPv6) */
5596  enum dhcp_token token;
5597  struct ia_xx *ia = NULL;
5598  const char *val;
5599  struct ia_xx *old_ia;
5600  u_int32_t iaid;
5601  struct iaddr iaddr;
5602  u_int8_t plen;
5603  binding_state_t state;
5604  u_int32_t prefer;
5605  u_int32_t valid;
5606  TIME end_time;
5607  struct iasubopt *iapref;
5608  struct ipv6_pool *pool;
5609  char addr_buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
5610  isc_boolean_t newbinding;
5611  struct binding_scope *scope = NULL;
5612  struct binding *bnd;
5613  struct binding_value *nv = NULL;
5614  struct executable_statement *on_star[2] = {NULL, NULL};
5615  int lose, i;
5616 
5617  if (local_family != AF_INET6) {
5618  parse_warn(cfile, "IA_PD is only supported in DHCPv6 mode.");
5619  skip_to_semi(cfile);
5620  return;
5621  }
5622 
5623  if (!parse_iaid_duid(cfile, &ia, &iaid, MDL)) {
5624  return;
5625  }
5626 
5627  ia->ia_type = D6O_IA_PD;
5628 
5629  token = next_token(&val, NULL, cfile);
5630  if (token != LBRACE) {
5631  parse_warn(cfile, "corrupt lease file; expecting left brace");
5632  skip_to_semi(cfile);
5633  return;
5634  }
5635 
5636  for (;;) {
5637  token = next_token(&val, NULL, cfile);
5638  if (token == RBRACE) break;
5639 
5640  if (token == CLTT) {
5641  ia->cltt = parse_date (cfile);
5642  continue;
5643  }
5644 
5645  if (token != IAPREFIX) {
5646  parse_warn(cfile, "corrupt lease file; expecting "
5647  "IAPREFIX or right brace");
5648  skip_to_semi(cfile);
5649  return;
5650  }
5651 
5652  if (!parse_ip6_prefix(cfile, &iaddr, &plen)) {
5653  parse_warn(cfile, "corrupt lease file; "
5654  "expecting IPv6 prefix");
5655  skip_to_semi(cfile);
5656  return;
5657  }
5658 
5659  token = next_token(&val, NULL, cfile);
5660  if (token != LBRACE) {
5661  parse_warn(cfile, "corrupt lease file; "
5662  "expecting left brace");
5663  skip_to_semi(cfile);
5664  return;
5665  }
5666 
5667  state = FTS_LAST+1;
5668  prefer = valid = 0;
5669  end_time = -1;
5670  for (;;) {
5671  token = next_token(&val, NULL, cfile);
5672  if (token == RBRACE) break;
5673 
5674  switch(token) {
5675  case END_OF_FILE:
5676  /* We hit the end of file and don't know
5677  * what parts of the lease we may be missing
5678  * don't try to salvage the lease
5679  */
5680  parse_warn(cfile, "corrupt lease file; "
5681  "unexpected end of file");
5682  return;
5683 
5684  /* Prefix binding state. */
5685  case BINDING:
5686  token = next_token(&val, NULL, cfile);
5687  if (token != STATE) {
5688  parse_warn(cfile, "corrupt lease file; "
5689  "expecting state");
5690  skip_to_semi(cfile);
5691  return;
5692  }
5693  token = next_token(&val, NULL, cfile);
5694  switch (token) {
5695  case TOKEN_ABANDONED:
5696  state = FTS_ABANDONED;
5697  break;
5698  case TOKEN_FREE:
5699  state = FTS_FREE;
5700  break;
5701  case TOKEN_ACTIVE:
5702  state = FTS_ACTIVE;
5703  break;
5704  case TOKEN_EXPIRED:
5705  state = FTS_EXPIRED;
5706  break;
5707  case TOKEN_RELEASED:
5708  state = FTS_RELEASED;
5709  break;
5710  default:
5711  parse_warn(cfile,
5712  "corrupt lease "
5713  "file; "
5714  "expecting a "
5715  "binding state.");
5716  skip_to_semi(cfile);
5717  return;
5718  }
5719 
5720  token = next_token(&val, NULL, cfile);
5721  if (token != SEMI) {
5722  parse_warn(cfile, "corrupt lease file; "
5723  "expecting "
5724  "semicolon.");
5725  }
5726  break;
5727 
5728  /* Lease preferred lifetime. */
5729  case PREFERRED_LIFE:
5730  token = next_token(&val, NULL, cfile);
5731  if (token != NUMBER) {
5732  parse_warn(cfile, "%s is not a valid "
5733  "preferred time",
5734  val);
5735  skip_to_semi(cfile);
5736  continue;
5737  }
5738  prefer = atoi (val);
5739 
5740  /*
5741  * Currently we peek for the semi-colon to
5742  * allow processing of older lease files that
5743  * don't have the semi-colon. Eventually we
5744  * should remove the peeking code.
5745  */
5746  token = peek_token(&val, NULL, cfile);
5747  if (token == SEMI) {
5748  skip_token(&val, NULL, cfile);
5749  } else {
5750  parse_warn(cfile,
5751  "corrupt lease file; "
5752  "expecting semicolon.");
5753  }
5754  break;
5755 
5756  /* Lease valid lifetime. */
5757  case MAX_LIFE:
5758  token = next_token(&val, NULL, cfile);
5759  if (token != NUMBER) {
5760  parse_warn(cfile, "%s is not a valid "
5761  "max time",
5762  val);
5763  skip_to_semi(cfile);
5764  continue;
5765  }
5766  valid = atoi (val);
5767 
5768  /*
5769  * Currently we peek for the semi-colon to
5770  * allow processing of older lease files that
5771  * don't have the semi-colon. Eventually we
5772  * should remove the peeking code.
5773  */
5774  token = peek_token(&val, NULL, cfile);
5775  if (token == SEMI) {
5776  skip_token(&val, NULL, cfile);
5777  } else {
5778  parse_warn(cfile,
5779  "corrupt lease file; "
5780  "expecting semicolon.");
5781  }
5782  break;
5783 
5784  /* Prefix expiration time. */
5785  case ENDS:
5786  end_time = parse_date(cfile);
5787  break;
5788 
5789  /* Prefix binding scopes. */
5790  case TOKEN_SET:
5791  token = next_token(&val, NULL, cfile);
5792  if ((token != NAME) &&
5793  (token != NUMBER_OR_NAME)) {
5794  parse_warn(cfile, "%s is not a valid "
5795  "variable name",
5796  val);
5797  skip_to_semi(cfile);
5798  continue;
5799  }
5800 
5801  if (scope != NULL)
5802  bnd = find_binding(scope, val);
5803  else {
5804  if (!binding_scope_allocate(&scope,
5805  MDL)) {
5806  log_fatal("Out of memory for "
5807  "lease binding "
5808  "scope.");
5809  }
5810 
5811  bnd = NULL;
5812  }
5813 
5814  if (bnd == NULL) {
5815  bnd = dmalloc(sizeof(*bnd),
5816  MDL);
5817  if (bnd == NULL) {
5818  log_fatal("No memory for "
5819  "prefix binding.");
5820  }
5821 
5822  bnd->name = dmalloc(strlen(val) + 1,
5823  MDL);
5824  if (bnd->name == NULL) {
5825  log_fatal("No memory for "
5826  "binding name.");
5827  }
5828  strcpy(bnd->name, val);
5829 
5830  newbinding = ISC_TRUE;
5831  } else {
5832  newbinding = ISC_FALSE;
5833  }
5834 
5835  if (!binding_value_allocate(&nv, MDL)) {
5836  log_fatal("no memory for binding "
5837  "value.");
5838  }
5839 
5840  token = next_token(NULL, NULL, cfile);
5841  if (token != EQUAL) {
5842  parse_warn(cfile, "expecting '=' in "
5843  "set statement.");
5844  goto binding_err;
5845  }
5846 
5847  if (!parse_binding_value(cfile, nv)) {
5848  binding_err:
5850  binding_scope_dereference(&scope, MDL);
5851  return;
5852  }
5853 
5854  if (newbinding) {
5856  nv, MDL);
5857  bnd->next = scope->bindings;
5858  scope->bindings = bnd;
5859  } else {
5861  MDL);
5863  nv, MDL);
5864  }
5865 
5867  parse_semi(cfile);
5868  break;
5869 
5870  case ON:
5871  lose = 0;
5872  /*
5873  * Depending on the user config we may
5874  * have one or two on statements. We
5875  * need to save information about both
5876  * of them until we allocate the
5877  * iasubopt to hold them.
5878  */
5879  if (on_star[0] == NULL) {
5880  if (!parse_on_statement (&on_star[0],
5881  cfile,
5882  &lose)) {
5883  parse_warn(cfile,
5884  "corrupt lease "
5885  "file; bad ON "
5886  "statement");
5887  skip_to_rbrace (cfile, 1);
5888  return;
5889  }
5890  } else {
5891  if (!parse_on_statement (&on_star[1],
5892  cfile,
5893  &lose)) {
5894  parse_warn(cfile,
5895  "corrupt lease "
5896  "file; bad ON "
5897  "statement");
5898  skip_to_rbrace (cfile, 1);
5899  return;
5900  }
5901  }
5902 
5903  break;
5904 
5905  default:
5906  parse_warn(cfile, "corrupt lease file; "
5907  "expecting ia_pd contents, "
5908  "got '%s'", val);
5909  skip_to_semi(cfile);
5910  continue;
5911  }
5912  }
5913 
5914  if (state == FTS_LAST+1) {
5915  parse_warn(cfile, "corrupt lease file; "
5916  "missing state in iaprefix");
5917  return;
5918  }
5919  if (end_time == -1) {
5920  parse_warn(cfile, "corrupt lease file; "
5921  "missing end time in iaprefix");
5922  return;
5923  }
5924 
5925  iapref = NULL;
5926  if (iasubopt_allocate(&iapref, MDL) != ISC_R_SUCCESS) {
5927  log_fatal("Out of memory.");
5928  }
5929  memcpy(&iapref->addr, iaddr.iabuf, sizeof(iapref->addr));
5930  iapref->plen = plen;
5931  iapref->state = state;
5932  iapref->prefer = prefer;
5933  iapref->valid = valid;
5934  if (iapref->state == FTS_RELEASED)
5935  iapref->hard_lifetime_end_time = end_time;
5936 
5937  if (scope != NULL) {
5938  binding_scope_reference(&iapref->scope, scope, MDL);
5939  binding_scope_dereference(&scope, MDL);
5940  }
5941 
5942  /*
5943  * Check on both on statements. Because of how we write the
5944  * lease file we know which is which if we have two but it's
5945  * easier to write the code to be independent. We do assume
5946  * that the statements won't overlap.
5947  */
5948  for (i = 0;
5949  (i < 2) && on_star[i] != NULL ;
5950  i++) {
5951  if ((on_star[i]->data.on.evtypes & ON_EXPIRY) &&
5952  on_star[i]->data.on.statements) {
5954  (&iapref->on_star.on_expiry,
5955  on_star[i]->data.on.statements, MDL);
5956  }
5957  if ((on_star[i]->data.on.evtypes & ON_RELEASE) &&
5958  on_star[i]->data.on.statements) {
5960  (&iapref->on_star.on_release,
5961  on_star[i]->data.on.statements, MDL);
5962  }
5963  executable_statement_dereference (&on_star[i], MDL);
5964  }
5965 
5966  /* Find the pool this address is in. We need to check prefix
5967  * lengths too in case the pool has been reconfigured. */
5968  pool = NULL;
5969  if ((find_ipv6_pool(&pool, D6O_IA_PD,
5970  &iapref->addr) != ISC_R_SUCCESS) ||
5971  (pool->units != iapref->plen)) {
5972  inet_ntop(AF_INET6, &iapref->addr,
5973  addr_buf, sizeof(addr_buf));
5974  log_error("No pool found for prefix %s/%d", addr_buf,
5975  iapref->plen);
5976  iasubopt_dereference(&iapref, MDL);
5977  continue;
5978  }
5979 
5980  /* remove old information */
5981  if (cleanup_lease6(ia_pd_active, pool,
5982  iapref, ia) != ISC_R_SUCCESS) {
5983  inet_ntop(AF_INET6, &iapref->addr,
5984  addr_buf, sizeof(addr_buf));
5985  parse_warn(cfile, "duplicate pd lease for address %s",
5986  addr_buf);
5987  }
5988 
5989  /*
5990  * if we like the lease we add it to our various structues
5991  * otherwise we leave it and it will get cleaned when we
5992  * do the iasubopt_dereference.
5993  */
5994  if ((state == FTS_ACTIVE) || (state == FTS_ABANDONED)) {
5995  ia_add_iasubopt(ia, iapref, MDL);
5996  ia_reference(&iapref->ia, ia, MDL);
5997  add_lease6(pool, iapref, end_time);
5998  }
5999 
6000  ipv6_pool_dereference(&pool, MDL);
6001  iasubopt_dereference(&iapref, MDL);
6002  }
6003 
6004  /*
6005  * If we have an existing record for this IA_PD, remove it.
6006  */
6007  old_ia = NULL;
6008  if (ia_hash_lookup(&old_ia, ia_pd_active,
6009  (unsigned char *)ia->iaid_duid.data,
6010  ia->iaid_duid.len, MDL)) {
6011  ia_hash_delete(ia_pd_active,
6012  (unsigned char *)ia->iaid_duid.data,
6013  ia->iaid_duid.len, MDL);
6014  ia_dereference(&old_ia, MDL);
6015  }
6016 
6017  /*
6018  * If we have prefixes, add this, otherwise don't bother.
6019  */
6020  if (ia->num_iasubopt > 0) {
6021  ia_hash_add(ia_pd_active,
6022  (unsigned char *)ia->iaid_duid.data,
6023  ia->iaid_duid.len, ia, MDL);
6024  }
6025  ia_dereference(&ia, MDL);
6026 #endif /* defined(DHCPv6) */
6027 }
6028 
6029 #ifdef DHCPv6
6030 /*
6031  * When we parse a server-duid statement in a lease file, we are
6032  * looking at the saved server DUID from a previous run. In this case
6033  * we expect it to be followed by the binary representation of the
6034  * DUID stored in a string:
6035  *
6036  * server-duid "\000\001\000\001\015\221\034JRT\000\0224Y";
6037  *
6038  * OR as a hex string of digits:
6039  *
6040  * server-duid 00:01:00:01:1e:68:b3:db:0a:00:27:00:00:02;
6041  */
6042 void
6043 parse_server_duid(struct parse *cfile) {
6044  struct data_string duid;
6045  unsigned char bytes[128]; /* Maximum valid DUID is 128 */
6046  unsigned int len;
6047 
6048  len = parse_X(cfile, bytes, sizeof(bytes));
6049  if (len <= 2) {
6050  parse_warn(cfile, "Invalid duid contents");
6051  skip_to_semi(cfile);
6052  return;
6053  }
6054 
6055  memset(&duid, 0x0, sizeof(duid));
6056  if (!buffer_allocate(&duid.buffer, len, MDL)) {
6057  log_fatal("parse_server_duid: out of memory");
6058  }
6059 
6060  memcpy(duid.buffer->data, bytes, len);
6061  duid.len = len;
6062  duid.data = duid.buffer->data;
6063 
6064  set_server_duid(&duid);
6065  data_string_forget(&duid, MDL);
6066 
6067  parse_semi(cfile);
6068 }
6069 
6070 /*
6071  * When we parse a server-duid statement in a config file, we will
6072  * have the type of the server DUID to generate, and possibly the
6073  * actual value defined.
6074  *
6075  * server-duid llt;
6076  * server-duid llt ethernet|ieee802|fddi 213982198 00:16:6F:49:7D:9B;
6077  * server-duid ll;
6078  * server-duid ll ethernet|ieee802|fddi 00:16:6F:49:7D:9B;
6079  * server-duid en 2495 "enterprise-specific-identifier-1234";
6080  */
6081 void
6082 parse_server_duid_conf(struct parse *cfile) {
6083  enum dhcp_token token;
6084  const char *val;
6085  unsigned int len;
6086  u_int32_t enterprise_number;
6087  int ll_type;
6088  struct data_string ll_addr;
6089  u_int32_t llt_time;
6090  struct data_string duid;
6091  int duid_type_num;
6092 
6093  /*
6094  * Consume the SERVER_DUID token.
6095  */
6096  skip_token(NULL, NULL, cfile);
6097 
6098  /*
6099  * Obtain the DUID type.
6100  */
6101  token = next_token(&val, NULL, cfile);
6102 
6103  /*
6104  * Enterprise is the easiest - enterprise number and raw data
6105  * are required.
6106  */
6107  if (token == EN) {
6108  /*
6109  * Get enterprise number and identifier.
6110  */
6111  token = next_token(&val, NULL, cfile);
6112  if (token != NUMBER) {
6113  parse_warn(cfile, "enterprise number expected");
6114  skip_to_semi(cfile);
6115  return;
6116  }
6117  enterprise_number = atoi(val);
6118 
6119  token = next_token(&val, &len, cfile);
6120  if (token != STRING) {
6121  parse_warn(cfile, "identifier expected");
6122  skip_to_semi(cfile);
6123  return;
6124  }
6125 
6126  /*
6127  * Save the DUID.
6128  */
6129  memset(&duid, 0, sizeof(duid));
6130  duid.len = 2 + 4 + len;
6131  if (!buffer_allocate(&duid.buffer, duid.len, MDL)) {
6132  log_fatal("Out of memory storing DUID");
6133  }
6134  duid.data = (unsigned char *)duid.buffer->data;
6135  putUShort(duid.buffer->data, DUID_EN);
6136  putULong(duid.buffer->data + 2, enterprise_number);
6137  memcpy(duid.buffer->data + 6, val, len);
6138 
6139  set_server_duid(&duid);
6140  data_string_forget(&duid, MDL);
6141  }
6142 
6143  /*
6144  * Next easiest is the link-layer DUID. It consists only of
6145  * the LL directive, or optionally the specific value to use.
6146  *
6147  * If we have LL only, then we set the type. If we have the
6148  * value, then we set the actual DUID.
6149  */
6150  else if (token == LL) {
6151  if (peek_token(NULL, NULL, cfile) == SEMI) {
6153  } else {
6154  /*
6155  * Get our hardware type and address.
6156  */
6157  token = next_token(NULL, NULL, cfile);
6158  switch (token) {
6159  case ETHERNET:
6160  ll_type = HTYPE_ETHER;
6161  break;
6162  case TOKEN_RING:
6163  ll_type = HTYPE_IEEE802;
6164  break;
6165  case TOKEN_FDDI:
6166  ll_type = HTYPE_FDDI;
6167  break;
6168  default:
6169  parse_warn(cfile, "hardware type expected");
6170  skip_to_semi(cfile);
6171  return;
6172  }
6173  memset(&ll_addr, 0, sizeof(ll_addr));
6174  if (!parse_cshl(&ll_addr, cfile)) {
6175  return;
6176  }
6177 
6178  /*
6179  * Save the DUID.
6180  */
6181  memset(&duid, 0, sizeof(duid));
6182  duid.len = 2 + 2 + ll_addr.len;
6183  if (!buffer_allocate(&duid.buffer, duid.len, MDL)) {
6184  log_fatal("Out of memory storing DUID");
6185  }
6186  duid.data = (unsigned char *)duid.buffer->data;
6187  putUShort(duid.buffer->data, DUID_LL);
6188  putUShort(duid.buffer->data + 2, ll_type);
6189  memcpy(duid.buffer->data + 4,
6190  ll_addr.data, ll_addr.len);
6191 
6192  set_server_duid(&duid);
6193  data_string_forget(&duid, MDL);
6194  data_string_forget(&ll_addr, MDL);
6195  }
6196  }
6197 
6198  /*
6199  * Finally the link-layer DUID plus time. It consists only of
6200  * the LLT directive, or optionally the specific value to use.
6201  *
6202  * If we have LLT only, then we set the type. If we have the
6203  * value, then we set the actual DUID.
6204  */
6205  else if (token == LLT) {
6206  if (peek_token(NULL, NULL, cfile) == SEMI) {
6208  } else {
6209  /*
6210  * Get our hardware type, timestamp, and address.
6211  */
6212  token = next_token(NULL, NULL, cfile);
6213  switch (token) {
6214  case ETHERNET:
6215  ll_type = HTYPE_ETHER;
6216  break;
6217  case TOKEN_RING:
6218  ll_type = HTYPE_IEEE802;
6219  break;
6220  case TOKEN_FDDI:
6221  ll_type = HTYPE_FDDI;
6222  break;
6223  default:
6224  parse_warn(cfile, "hardware type expected");
6225  skip_to_semi(cfile);
6226  return;
6227  }
6228 
6229  token = next_token(&val, NULL, cfile);
6230  if (token != NUMBER) {
6231  parse_warn(cfile, "timestamp expected");
6232  skip_to_semi(cfile);
6233  return;
6234  }
6235  llt_time = atoi(val);
6236 
6237  memset(&ll_addr, 0, sizeof(ll_addr));
6238  if (!parse_cshl(&ll_addr, cfile)) {
6239  return;
6240  }
6241 
6242  /*
6243  * Save the DUID.
6244  */
6245  memset(&duid, 0, sizeof(duid));
6246  duid.len = 2 + 2 + 4 + ll_addr.len;
6247  if (!buffer_allocate(&duid.buffer, duid.len, MDL)) {
6248  log_fatal("Out of memory storing DUID");
6249  }
6250  duid.data = (unsigned char *)duid.buffer->data;
6251  putUShort(duid.buffer->data, DUID_LLT);
6252  putUShort(duid.buffer->data + 2, ll_type);
6253  putULong(duid.buffer->data + 4, llt_time);
6254  memcpy(duid.buffer->data + 8,
6255  ll_addr.data, ll_addr.len);
6256 
6257  set_server_duid(&duid);
6258  data_string_forget(&duid, MDL);
6259  data_string_forget(&ll_addr, MDL);
6260  }
6261  }
6262 
6263  /*
6264  * If users want they can use a number for DUID types.
6265  * This is useful for supporting future, not-yet-defined
6266  * DUID types.
6267  *
6268  * In this case, they have to put in the complete value.
6269  *
6270  * This also works for existing DUID types of course.
6271  */
6272  else if (token == NUMBER) {
6273  duid_type_num = atoi(val);
6274 
6275  token = next_token(&val, &len, cfile);
6276  if (token != STRING) {
6277  parse_warn(cfile, "identifier expected");
6278  skip_to_semi(cfile);
6279  return;
6280  }
6281 
6282  /*
6283  * Save the DUID.
6284  */
6285  memset(&duid, 0, sizeof(duid));
6286  duid.len = 2 + len;
6287  if (!buffer_allocate(&duid.buffer, duid.len, MDL)) {
6288  log_fatal("Out of memory storing DUID");
6289  }
6290  duid.data = (unsigned char *)duid.buffer->data;
6291  putUShort(duid.buffer->data, duid_type_num);
6292  memcpy(duid.buffer->data + 2, val, len);
6293 
6294  set_server_duid(&duid);
6295  data_string_forget(&duid, MDL);
6296  }
6297 
6298  /*
6299  * Anything else is an error.
6300  */
6301  else {
6302  parse_warn(cfile, "DUID type of LLT, EN, or LL expected");
6303  skip_to_semi(cfile);
6304  return;
6305  }
6306 
6307  /*
6308  * Finally consume our trailing semicolon.
6309  */
6310  token = next_token(NULL, NULL, cfile);
6311  if (token != SEMI) {
6312  parse_warn(cfile, "semicolon expected");
6313  skip_to_semi(cfile);
6314  }
6315 }
6316 
6331 uint32_t parse_byte_order_uint32(const void *source) {
6332  uint32_t value;
6333 
6334  /* use memcpy to avoid any alignment monkey business */
6335  memcpy(&value, source, 4);
6336 
6337  if (authoring_byte_order == 0) {
6338  log_error ("WARNING: "
6339  "authoring-byte-order not in the lease file.\n"
6340  "Assuming file byte order matches this server.\n");
6342  }
6343 
6345  value = (((value >> 24) & 0xff) | // move byte 3 to byte 0
6346  ((value << 8) & 0xff0000) | // move byte 1 to byte 2
6347  ((value >> 8) & 0xff00) | // move byte 2 to byte 1
6348  ((value << 24) & 0xff000000)); // byte 0 to byte 3
6349  }
6350 
6351  return (value);
6352 }
6353 
6354 /* !brief Parses an iaid/duid string into an iaid and struct ia
6355  *
6356  * Given a string containing the iaid-duid value read from the file,
6357  * and using the format specified by input lease-id-format, convert
6358  * it into an IAID value and an ia_xx struct.
6359  *
6360  * \param cfile - file being parsed
6361  * \param ia - pointer in which to store the allocated ia_xx struct
6362  * \param iaid - pointer in which to return the IAID value
6363  * \param file - source file name of invocation
6364  * \param line - line numbe of invocation
6365  *
6366  * \return 0 if parsing fails, non-zero otherwise
6367 */
6368 int
6369 parse_iaid_duid(struct parse* cfile, struct ia_xx** ia, u_int32_t *iaid,
6370  const char* file, int line) {
6371  unsigned char bytes[132]; /* Maximum valid IAID-DUID is 132 */
6372  unsigned int len;
6373 
6374  if (!ia) {
6375  log_error("parse_iaid_duid: ia ptr cannot be null");
6376  return (0);
6377  }
6378 
6379  *ia = NULL;
6380  len = parse_X(cfile, bytes, sizeof(bytes));
6381  if (len <= 5) {
6382  parse_warn(cfile, "corrupt lease file; "
6383  "iaid+ia_xx string too short");
6384  skip_to_semi(cfile);
6385  return (0);
6386  }
6387 
6388  /* Extract the IAID from the front */
6389  *iaid = parse_byte_order_uint32(bytes);
6390 
6391  /* Instantiate the ia_xx */
6392  if (ia_allocate(ia, *iaid, (const char*)bytes + 4, len - 4, file, line)
6393  != ISC_R_SUCCESS) {
6394  log_fatal("parse_iaid_duid:Out of memory.");
6395  }
6396 
6397  return (1);
6398 }
6399 
6400 #endif /* DHCPv6 */
6401 
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:926
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:1711
int executable_statement_allocate(struct executable_statement **ptr, const char *file, int line)
Definition: alloc.c:958
struct class * nic
Definition: dhcpd.h:1073
Definition: tree.h:31
TIME valid_from
Definition: dhcpd.h:1717
Definition: dhctoken.h:265
int parse_lease_declaration(struct lease **lp, struct parse *cfile)
Definition: confpars.c:3117
const char int line
Definition: dhcpd.h:3723
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:1034
#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:1001
int bits
Definition: inet.h:72
const char * piaddr(const struct iaddr addr)
Definition: inet.c:579
#define FTS_FREE
Definition: dhcpd.h:533
Definition: dhcpd.h:1645
#define CLASS_TYPE_VENDOR
Definition: dhcpd.h:1065
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 units
Definition: dhcpd.h:1684
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
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:2888
enum dhcp_token token
Definition: dhcpd.h:320
Definition: dhctoken.h:70
void parse_pool6_statement(struct parse *, struct group *, int)
Definition: dhcpd.h:1044
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:1037
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:962
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:1103
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:1038
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:1713
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:955
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:1088
#define DUID_LL
Definition: dhcp6.h:167
#define SCLASS_HASH_SIZE
Definition: dhcpd.h:203
const char * path_dhcpd_db
Definition: dhcpd.c:88
u_int32_t valid
Definition: dhcpd.h:1621
int log_error(const char *,...) __attribute__((__format__(__printf__
struct collection * collections
Definition: dhcpd.h:3183
time_t cltt
Definition: dhcpd.h:1651
#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:1642
struct binding_scope * scope
Definition: dhcpd.h:1617
dhcp_failover_state_t * failover_peer
Definition: dhcpd.h:1040
int parse_semi(struct parse *cfile)
Definition: parse.c:135
struct ipv6_pond * ipv6_pond
Definition: dhcpd.h:1695
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:1020
int parse_fixed_addr_param(struct option_cache **oc, struct parse *cfile, enum dhcp_token type)
Definition: confpars.c:3046
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:949
struct permit * prohibit_list
Definition: dhcpd.h:1716
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:1075
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:1735
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:5155
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:939
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:2953
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:1104
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:1291
#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:1618
struct permit * prohibit_list
Definition: dhcpd.h:1004
Definition: tree.h:346
#define HOST_DECL_STATIC
Definition: dhcpd.h:963
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:983
void parse_ia_na_declaration(struct parse *cfile)
Definition: confpars.c:4719
#define CLASS_TYPE_SUBCLASS
Definition: dhcpd.h:1068
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:998
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:1067
struct iaddr net
Definition: dhcpd.h:1051
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:962
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:1017
trace_type_t * trace_type_register(const char *, void *, void(*)(trace_type_t *, unsigned, char *), void(*)(trace_type_t *), const char *, int)
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:2132
struct expression * expr
Definition: dhcpd.h:1091
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:947
#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:1615
TIME atsfp
Definition: dhcpd.h:635
struct data_string iaid_duid
Definition: dhcpd.h:1647
int authoritative
Definition: dhcpd.h:938
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:2832
#define cur_time
Definition: dhcpd.h:2077
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:1095
Definition: dhctoken.h:227
u_int8_t flags
Definition: dhcpd.h:587
void dfree(void *, const char *, int)
Definition: alloc.c:145
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:971
int lease_count
Definition: dhcpd.h:1012
u_int32_t prefer
Definition: dhcpd.h:1620
const char * name
Definition: tree.h:347
TIME valid_until
Definition: dhcpd.h:1718
int bits
Definition: dhcpd.h:1683
enum permit::@0 type
int parse_ip6_addr(struct parse *cfile, struct iaddr *addr)
Definition: parse.c:401
int jumbo_range
Definition: dhcpd.h:1728
Definition: dhctoken.h:37
struct data_string host_id
Definition: dhcpd.h:951
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:1649
struct ipv6_pool ** ipv6_pools
Definition: dhcpd.h:1720
u_int16_t ia_type
Definition: dhcpd.h:1648
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:1616
void * dmalloc(size_t, const char *, int)
Definition: alloc.c:57
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:1048
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:1053
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:1054
union executable_statement::@7 data
void parse_shared_net_declaration(struct parse *cfile, struct group *group)
Definition: confpars.c:2587
char * name
Definition: dhcpd.h:923
void db_startup(int testp)
Definition: dhclient.c:2000
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:937
Definition: dhctoken.h:38
dhcp_token
Definition: dhctoken.h:34
TIME cltt
Definition: dhcpd.h:636
struct lease ** billed_leases
Definition: dhcpd.h:1080
const char * path_dhcpd_conf
Definition: dhcpd.c:87
Definition: inet.h:31
#define ROOT_GROUP
Definition: dhcpd.h:682
TIME valid_from
Definition: dhcpd.h:1016
ipv6_pool structure
Definition: dhcpd.h:1679
Definition: dhcpd.h:970
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:1031
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:3754
int parse_ip6_addr_expr(struct expression **expr, struct parse *cfile)
Definition: parse.c:461
struct iaddrcidrnetlist * fixed_prefix
Definition: dhcpd.h:956
ia_hash_t * ia_pd_active
struct group_object * named_group
Definition: dhcpd.h:958
Definition: dhcpd.h:931
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:936
#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:2744
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:1052
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:1408
void parse_prefix6(struct parse *cfile, struct group *group, struct ipv6_pond *)
struct option * host_id_option
Definition: dhcpd.h:950
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:1047
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:982
struct interface_info * interface
Definition: dhcpd.h:1035
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:924
Definition: dhctoken.h:44
void parse_ia_pd_declaration(struct parse *cfile)
Definition: confpars.c:5591
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:1108
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:1709
Definition: tree.h:118
#define HOST_DECL
Definition: dhcpd.h:683
#define CLASS_TYPE_USER
Definition: dhcpd.h:1066
Definition: dhctoken.h:205
isc_uint64_t num_total
Definition: dhcpd.h:1723
#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:1622
int flags
Definition: dhcpd.h:960
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:1002
const char * file
Definition: dhcpd.h:3723
char * name
Definition: dhcpd.h:1029
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:1003
#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:1694
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:1692
void trace_conf_stop(trace_type_t *ttype)
struct in6_addr addr
Definition: dhcpd.h:1614
int parse_allow_deny(struct option_cache **oc, struct parse *cfile, int flag)
Definition: confpars.c:4651
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:1071
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:948
struct permit * permit_list
Definition: dhcpd.h:1715
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:922
int clone_group(struct group **gp, struct group *group, const char *file, int line)
Definition: memory.c:130
int relays
Definition: dhcpd.h:967
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:1049
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:1712
struct pool * pools
Definition: dhcpd.h:1036
#define GROUP_OBJECT_STATIC
Definition: dhcpd.h:927
struct group * group
Definition: dhcpd.h:957
struct buffer * buffer
Definition: tree.h:78
struct pool * next
Definition: dhcpd.h:1000
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:1098
Definition: dhctoken.h:223
#define FTS_ACTIVE
Definition: dhcpd.h:534
int num_pools