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