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