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