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