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