ISC DHCP  4.3.1
A reference DHCPv4 and DHCPv6 implementation
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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  /* Update the number of elements in the pond. Conveniently
3845  * we have the total size of the block in bits and the amount
3846  * we would allocate per element in units. For an address units
3847  * will always be 128, for a prefix it will be something else.
3848  */
3849  pond->num_total += 1 << (units - bits);
3850 }
3851 
3878 static void
3879 add_ipv6_pond_to_network(struct group *group,
3880  struct ipv6_pond **ret_pond) {
3881 
3882  struct ipv6_pond *pond = NULL, *last = NULL;
3883  struct permit *p;
3884  isc_result_t status;
3885  struct shared_network *shared = group->subnet->shared_network;
3886 
3887  for (pond = shared->ipv6_pond; pond; pond = pond->next) {
3888  if ((pond->group->statements == group->statements) &&
3889  (pond->prohibit_list == NULL) &&
3890  (pond->permit_list != NULL) &&
3891  (pond->permit_list->next == NULL) &&
3892  (pond->permit_list->type == permit_all_clients)) {
3893  ipv6_pond_reference(ret_pond, pond, MDL);
3894  return;
3895  }
3896  last = pond;
3897  }
3898 
3899  /* no pond available, make one */
3900  status = ipv6_pond_allocate(&pond, MDL);
3901  if (status != ISC_R_SUCCESS)
3902  log_fatal ("no memory for ad-hoc ipv6 pond: %s",
3903  isc_result_totext (status));
3904  p = new_permit (MDL);
3905  if (p == NULL)
3906  log_fatal ("no memory for ad-hoc ipv6 permit.");
3907 
3908  /* we permit all clients */
3909  p->type = permit_all_clients;
3910  pond->permit_list = p;
3911 
3912  /* and attach the pond to the return argument and the shared network */
3913  ipv6_pond_reference(ret_pond, pond, MDL);
3914 
3915  if (shared->ipv6_pond)
3916  ipv6_pond_reference(&last->next, pond, MDL);
3917  else
3918  ipv6_pond_reference(&shared->ipv6_pond, pond, MDL);
3919 
3920  shared_network_reference(&pond->shared_network, shared, MDL);
3921  if (!clone_group (&pond->group, group, MDL))
3922  log_fatal ("no memory for anon pool group.");
3923 
3924  ipv6_pond_dereference(&pond, MDL);
3925  return;
3926 }
3927 
3928 static void
3929 check_addr_in_subnet(struct subnet *subnet, struct iaddr *addr) {
3930  char lowbuf [INET6_ADDRSTRLEN], netbuf [INET6_ADDRSTRLEN];
3931 
3932  if (!addr_eq(subnet->net, subnet_number(*addr, subnet->netmask))) {
3933  strncpy(lowbuf, piaddr(*addr), INET6_ADDRSTRLEN);
3934  strncpy(netbuf, piaddr(subnet->net), INET6_ADDRSTRLEN);
3935  log_fatal("bad range6, address %s not in subnet6 %s/%d",
3936  lowbuf, netbuf, subnet->prefix_len);
3937  }
3938 
3939 }
3940 
3941 /* address-range6-declaration :== ip-address6 ip-address6 SEMI
3942  | ip-address6 SLASH number SEMI
3943  | ip-address6 [SLASH number] TEMPORARY SEMI */
3944 
3945 void
3946 parse_address_range6(struct parse *cfile,
3947  struct group *group,
3948  struct ipv6_pond *inpond) {
3949  struct iaddr lo, hi;
3950  int bits;
3951  enum dhcp_token token;
3952  const char *val;
3953  struct iaddrcidrnetlist *nets, net;
3954  struct iaddrcidrnetlist *p;
3955  u_int16_t type = D6O_IA_NA;
3956  struct ipv6_pond *pond = NULL;
3957 
3958  if (local_family != AF_INET6) {
3959  parse_warn(cfile, "range6 statement is only supported "
3960  "in DHCPv6 mode.");
3961  skip_to_semi(cfile);
3962  return;
3963  }
3964 
3965  /* This is enforced by the caller, this is just a sanity check. */
3966  if (group->subnet == NULL)
3967  log_fatal("Impossible condition at %s:%d.", MDL);
3968 
3969  /*
3970  * Read starting address.
3971  */
3972  if (!parse_ip6_addr(cfile, &lo)) {
3973  return;
3974  }
3975 
3976  /*
3977  * zero out the net entry in case we use it
3978  */
3979  memset(&net, 0, sizeof(net));
3980  net.cidrnet.lo_addr = lo;
3981 
3982  check_addr_in_subnet(group->subnet, &lo);
3983 
3984  /*
3985  * See if we we're using range or CIDR notation or TEMPORARY
3986  */
3987  token = peek_token(&val, NULL, cfile);
3988  if (token == SLASH) {
3989  /*
3990  * '/' means CIDR notation, so read the bits we want.
3991  */
3992  skip_token(NULL, NULL, cfile);
3993  token = next_token(&val, NULL, cfile);
3994  if (token != NUMBER) {
3995  parse_warn(cfile, "expecting number");
3996  skip_to_semi(cfile);
3997  return;
3998  }
3999  net.cidrnet.bits = atoi(val);
4000  bits = net.cidrnet.bits;
4001  if ((bits < 0) || (bits > 128)) {
4002  parse_warn(cfile, "networks have 0 to 128 bits");
4003  skip_to_semi(cfile);
4004  return;
4005  }
4006 
4007  if (!is_cidr_mask_valid(&net.cidrnet.lo_addr, bits)) {
4008  parse_warn(cfile, "network mask too short");
4009  skip_to_semi(cfile);
4010  return;
4011  }
4012 
4013  /*
4014  * can be temporary (RFC 4941 like)
4015  */
4016  token = peek_token(&val, NULL, cfile);
4017  if (token == TEMPORARY) {
4018  if (bits < 64)
4019  parse_warn(cfile, "temporary mask too short");
4020  if (bits == 128)
4021  parse_warn(cfile, "temporary singleton?");
4022  skip_token(NULL, NULL, cfile);
4023  type = D6O_IA_TA;
4024  }
4025 
4026  nets = &net;
4027 
4028  } else if (token == TEMPORARY) {
4029  /*
4030  * temporary (RFC 4941)
4031  */
4032  type = D6O_IA_TA;
4033  skip_token(NULL, NULL, cfile);
4034  net.cidrnet.bits = 64;
4036  net.cidrnet.bits)) {
4037  parse_warn(cfile, "network mask too short");
4038  skip_to_semi(cfile);
4039  return;
4040  }
4041 
4042  nets = &net;
4043 
4044  } else {
4045  /*
4046  * No '/', so we are looking for the end address of
4047  * the IPv6 pool.
4048  */
4049  if (!parse_ip6_addr(cfile, &hi)) {
4050  return;
4051  }
4052 
4053  check_addr_in_subnet(group->subnet, &hi);
4054 
4055  /*
4056  * Convert our range to a set of CIDR networks.
4057  */
4058  nets = NULL;
4059  if (range2cidr(&nets, &lo, &hi) != ISC_R_SUCCESS) {
4060  log_fatal("Error converting range to CIDR networks");
4061  }
4062 
4063  }
4064 
4065  /*
4066  * See if we have a pond for this set of pools.
4067  * If the caller supplied one we use it, otherwise
4068  * check the shared network
4069  */
4070 
4071  if (inpond != NULL) {
4072  ipv6_pond_reference(&pond, inpond, MDL);
4073  } else {
4074  add_ipv6_pond_to_network(group, &pond);
4075  }
4076 
4077  /* Now that we have a pond add the nets we have parsed */
4078  for (p=nets; p != NULL; p=p->next) {
4079  add_ipv6_pool_to_subnet(group->subnet, type,
4080  &p->cidrnet.lo_addr,
4081  p->cidrnet.bits, 128, pond);
4082  }
4083 
4084  /* if we allocated a list free it now */
4085  if (nets != &net)
4086  free_iaddrcidrnetlist(&nets);
4087 
4088  ipv6_pond_dereference(&pond, MDL);
4089 
4090  token = next_token(NULL, NULL, cfile);
4091  if (token != SEMI) {
4092  parse_warn(cfile, "semicolon expected.");
4093  skip_to_semi(cfile);
4094  return;
4095  }
4096 }
4097 
4098 /* prefix6-declaration :== ip-address6 ip-address6 SLASH number SEMI */
4099 
4100 void
4101 parse_prefix6(struct parse *cfile,
4102  struct group *group,
4103  struct ipv6_pond *inpond) {
4104  struct iaddr lo, hi;
4105  int bits;
4106  enum dhcp_token token;
4107  const char *val;
4108  struct iaddrcidrnetlist *nets;
4109  struct iaddrcidrnetlist *p;
4110  struct ipv6_pond *pond = NULL;
4111 
4112  if (local_family != AF_INET6) {
4113  parse_warn(cfile, "prefix6 statement is only supported "
4114  "in DHCPv6 mode.");
4115  skip_to_semi(cfile);
4116  return;
4117  }
4118 
4119  /* This is enforced by the caller, so it's just a sanity check. */
4120  if (group->subnet == NULL)
4121  log_fatal("Impossible condition at %s:%d.", MDL);
4122 
4123  /*
4124  * Read starting and ending address.
4125  */
4126  if (!parse_ip6_addr(cfile, &lo)) {
4127  return;
4128  }
4129  if (!parse_ip6_addr(cfile, &hi)) {
4130  return;
4131  }
4132 
4133  /*
4134  * Next is '/' number ';'.
4135  */
4136  token = next_token(NULL, NULL, cfile);
4137  if (token != SLASH) {
4138  parse_warn(cfile, "expecting '/'");
4139  if (token != SEMI)
4140  skip_to_semi(cfile);
4141  return;
4142  }
4143  token = next_token(&val, NULL, cfile);
4144  if (token != NUMBER) {
4145  parse_warn(cfile, "expecting number");
4146  if (token != SEMI)
4147  skip_to_semi(cfile);
4148  return;
4149  }
4150  bits = atoi(val);
4151  if ((bits <= 0) || (bits >= 128)) {
4152  parse_warn(cfile, "networks have 0 to 128 bits (exclusive)");
4153  return;
4154  }
4155  if (!is_cidr_mask_valid(&lo, bits) ||
4156  !is_cidr_mask_valid(&hi, bits)) {
4157  parse_warn(cfile, "network mask too short");
4158  return;
4159  }
4160  token = next_token(NULL, NULL, cfile);
4161  if (token != SEMI) {
4162  parse_warn(cfile, "semicolon expected.");
4163  skip_to_semi(cfile);
4164  return;
4165  }
4166 
4167  /*
4168  * Convert our range to a set of CIDR networks.
4169  */
4170  nets = NULL;
4171  if (range2cidr(&nets, &lo, &hi) != ISC_R_SUCCESS) {
4172  log_fatal("Error converting prefix to CIDR");
4173  }
4174 
4175  /*
4176  * See if we have a pond for this set of pools.
4177  * If the caller supplied one we use it, otherwise
4178  * check the shared network
4179  */
4180 
4181  if (inpond != NULL) {
4182  ipv6_pond_reference(&pond, inpond, MDL);
4183  } else {
4184  add_ipv6_pond_to_network(group, &pond);
4185  }
4186 
4187  for (p = nets; p != NULL; p = p->next) {
4188  /* Normalize and check. */
4189  if (p->cidrnet.bits == 128) {
4190  p->cidrnet.bits = bits;
4191  }
4192  if (p->cidrnet.bits > bits) {
4193  parse_warn(cfile, "impossible mask length");
4194  continue;
4195  }
4196  add_ipv6_pool_to_subnet(group->subnet, D6O_IA_PD,
4197  &p->cidrnet.lo_addr,
4198  p->cidrnet.bits, bits, pond);
4199  }
4200 
4201  free_iaddrcidrnetlist(&nets);
4202 }
4203 
4204 /* fixed-prefix6 :== ip6-address SLASH number SEMI */
4205 
4206 void
4207 parse_fixed_prefix6(struct parse *cfile, struct host_decl *host_decl) {
4208  struct iaddrcidrnetlist *ia, **h;
4209  enum dhcp_token token;
4210  const char *val;
4211 
4212  /*
4213  * Get the head of the fixed-prefix list.
4214  */
4215  h = &host_decl->fixed_prefix;
4216 
4217  /*
4218  * Walk to the end.
4219  */
4220  while (*h != NULL) {
4221  h = &((*h)->next);
4222  }
4223 
4224  /*
4225  * Allocate a new iaddrcidrnetlist structure.
4226  */
4227  ia = dmalloc(sizeof(*ia), MDL);
4228  if (!ia) {
4229  log_fatal("Out of memory");
4230  }
4231 
4232  /*
4233  * Parse it.
4234  */
4235  if (!parse_ip6_addr(cfile, &ia->cidrnet.lo_addr)) {
4236  dfree(ia, MDL);
4237  return;
4238  }
4239  token = next_token(NULL, NULL, cfile);
4240  if (token != SLASH) {
4241  dfree(ia, MDL);
4242  parse_warn(cfile, "expecting '/'");
4243  if (token != SEMI)
4244  skip_to_semi(cfile);
4245  return;
4246  }
4247  token = next_token(&val, NULL, cfile);
4248  if (token != NUMBER) {
4249  dfree(ia, MDL);
4250  parse_warn(cfile, "expecting number");
4251  if (token != SEMI)
4252  skip_to_semi(cfile);
4253  return;
4254  }
4255  token = next_token(NULL, NULL, cfile);
4256  if (token != SEMI) {
4257  dfree(ia, MDL);
4258  parse_warn(cfile, "semicolon expected.");
4259  skip_to_semi(cfile);
4260  return;
4261  }
4262 
4263  /*
4264  * Fill it.
4265  */
4266  ia->cidrnet.bits = atoi(val);
4267  if ((ia->cidrnet.bits < 0) || (ia->cidrnet.bits > 128)) {
4268  dfree(ia, MDL);
4269  parse_warn(cfile, "networks have 0 to 128 bits");
4270  return;
4271  }
4272  if (!is_cidr_mask_valid(&ia->cidrnet.lo_addr, ia->cidrnet.bits)) {
4273  dfree(ia, MDL);
4274  parse_warn(cfile, "network mask too short");
4275  return;
4276  }
4277 
4278  /*
4279  * Store it.
4280  */
4281  *h = ia;
4282  return;
4283 }
4284 
4304 void parse_pool6_statement (cfile, group, type)
4305  struct parse *cfile;
4306  struct group *group;
4307  int type;
4308 {
4309  enum dhcp_token token;
4310  const char *val;
4311  int done = 0;
4312  struct ipv6_pond *pond, **p;
4313  int declaration = 0;
4314  isc_result_t status;
4315 
4316  pond = NULL;
4317  status = ipv6_pond_allocate(&pond, MDL);
4318  if (status != ISC_R_SUCCESS)
4319  log_fatal("no memory for pool6: %s",
4320  isc_result_totext (status));
4321 
4322  if (type == SUBNET_DECL)
4323  shared_network_reference(&pond->shared_network,
4324  group->subnet->shared_network,
4325  MDL);
4326  else {
4327  parse_warn(cfile, "Dynamic pool6s are only valid inside "
4328  "subnet statements.");
4329  skip_to_semi(cfile);
4330  return;
4331  }
4332 
4333  if (clone_group(&pond->group, group, MDL) == 0)
4334  log_fatal("can't clone pool6 group.");
4335 
4336  if (parse_lbrace(cfile) == 0) {
4337  ipv6_pond_dereference(&pond, MDL);
4338  return;
4339  }
4340 
4341  do {
4342  token = peek_token(&val, NULL, cfile);
4343  switch (token) {
4344  case RANGE6:
4345  skip_token(NULL, NULL, cfile);
4346  parse_address_range6(cfile, group, pond);
4347  break;
4348 
4349  case PREFIX6:
4350  skip_token(NULL, NULL, cfile);
4351  parse_prefix6(cfile, group, pond);
4352  break;
4353 
4354  case ALLOW:
4355  skip_token(NULL, NULL, cfile);
4356  get_permit(cfile, &pond->permit_list, 1,
4357  &pond->valid_from, &pond->valid_until);
4358  break;
4359 
4360  case DENY:
4361  skip_token(NULL, NULL, cfile);
4362  get_permit(cfile, &pond->prohibit_list, 0,
4363  &pond->valid_from, &pond->valid_until);
4364  break;
4365 
4366  case RBRACE:
4367  skip_token(&val, NULL, cfile);
4368  done = 1;
4369  break;
4370 
4371  case END_OF_FILE:
4372  /*
4373  * We can get to END_OF_FILE if, for instance,
4374  * the parse_statement() reads all available tokens
4375  * and leaves us at the end.
4376  */
4377  parse_warn(cfile, "unexpected end of file");
4378  goto cleanup;
4379 
4380  default:
4381  declaration = parse_statement(cfile, pond->group,
4382  POOL_DECL, NULL,
4383  declaration);
4384  break;
4385  }
4386  } while (!done);
4387 
4388  /*
4389  * A possible optimization is to see if this pond can be merged into
4390  * an already existing pond. But I'll pass on that for now as we need
4391  * to repoint the leases to the other pond which is annoying. SAR
4392  */
4393 
4394  /*
4395  * Add this pond to the list (will need updating if we add the
4396  * optimization).
4397  */
4398 
4399  p = &pond->shared_network->ipv6_pond;
4400  for (; *p; p = &((*p)->next))
4401  ;
4402  ipv6_pond_reference(p, pond, MDL);
4403 
4404  /* Don't allow a pool6 declaration with no addresses or
4405  prefixes, since it is probably a configuration error. */
4406  if (pond->ipv6_pools == NULL) {
4407  parse_warn (cfile, "Pool6 declaration with no %s.",
4408  "address range6 or prefix6");
4409  log_error ("Pool6 declarations must always contain at least");
4410  log_error ("one range6 or prefix6 statement.");
4411  }
4412 
4413 cleanup:
4414  ipv6_pond_dereference(&pond, MDL);
4415 }
4416 
4417 
4418 
4419 #endif /* DHCPv6 */
4420 
4421 /* allow-deny-keyword :== BOOTP
4422  | BOOTING
4423  | DYNAMIC_BOOTP
4424  | UNKNOWN_CLIENTS */
4425 
4426 int parse_allow_deny (oc, cfile, flag)
4427  struct option_cache **oc;
4428  struct parse *cfile;
4429  int flag;
4430 {
4431  enum dhcp_token token;
4432  const char *val;
4433  unsigned char rf = flag;
4434  unsigned code;
4435  struct option *option = NULL;
4436  struct expression *data = (struct expression *)0;
4437  int status;
4438 
4439  if (!make_const_data (&data, &rf, 1, 0, 1, MDL))
4440  return 0;
4441 
4442  token = next_token (&val, (unsigned *)0, cfile);
4443  switch (token) {
4444  case TOKEN_BOOTP:
4445  code = SV_ALLOW_BOOTP;
4446  break;
4447 
4448  case BOOTING:
4449  code = SV_ALLOW_BOOTING;
4450  break;
4451 
4452  case DYNAMIC_BOOTP:
4453  code = SV_DYNAMIC_BOOTP;
4454  break;
4455 
4456  case UNKNOWN_CLIENTS:
4457  code = SV_BOOT_UNKNOWN_CLIENTS;
4458  break;
4459 
4460  case DUPLICATES:
4461  code = SV_DUPLICATES;
4462  break;
4463 
4464  case DECLINES:
4465  code= SV_DECLINES;
4466  break;
4467 
4468  case CLIENT_UPDATES:
4469  code = SV_CLIENT_UPDATES;
4470  break;
4471 
4472  case LEASEQUERY:
4473  code = SV_LEASEQUERY;
4474  break;
4475 
4476  default:
4477  parse_warn (cfile, "expecting allow/deny key");
4478  skip_to_semi (cfile);
4479  return 0;
4480  }
4481  /* Reference on option is passed to option cache. */
4482  if (!option_code_hash_lookup(&option, server_universe.code_hash,
4483  &code, 0, MDL))
4484  log_fatal("Unable to find server option %u (%s:%d).",
4485  code, MDL);
4486  status = option_cache(oc, NULL, data, option, MDL);
4487  expression_dereference (&data, MDL);
4488  parse_semi (cfile);
4489  return status;
4490 }
4491 
4492 void
4494 #if !defined(DHCPv6)
4495  parse_warn(cfile, "No DHCPv6 support.");
4496  skip_to_semi(cfile);
4497 #else /* defined(DHCPv6) */
4498  enum dhcp_token token;
4499  struct ia_xx *ia;
4500  const char *val;
4501  struct ia_xx *old_ia;
4502  unsigned int len;
4503  u_int32_t iaid;
4504  struct iaddr iaddr;
4505  binding_state_t state;
4506  u_int32_t prefer;
4507  u_int32_t valid;
4508  TIME end_time;
4509  struct iasubopt *iaaddr;
4510  struct ipv6_pool *pool;
4511  char addr_buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
4512  isc_boolean_t newbinding;
4513  struct binding_scope *scope = NULL;
4514  struct binding *bnd;
4515  struct binding_value *nv = NULL;
4516  struct executable_statement *on_star[2] = {NULL, NULL};
4517  int lose, i;
4518 
4519  if (local_family != AF_INET6) {
4520  parse_warn(cfile, "IA_NA is only supported in DHCPv6 mode.");
4521  skip_to_semi(cfile);
4522  return;
4523  }
4524 
4525  token = next_token(&val, &len, cfile);
4526  if (token != STRING) {
4527  parse_warn(cfile, "corrupt lease file; "
4528  "expecting an iaid+ia_na string");
4529  skip_to_semi(cfile);
4530  return;
4531  }
4532  if (len < 5) {
4533  parse_warn(cfile, "corrupt lease file; "
4534  "iaid+ia_na string too short");
4535  skip_to_semi(cfile);
4536  return;
4537  }
4538 
4539  memcpy(&iaid, val, 4);
4540  ia = NULL;
4541  if (ia_allocate(&ia, iaid, val+4, len-4, MDL) != ISC_R_SUCCESS) {
4542  log_fatal("Out of memory.");
4543  }
4544  ia->ia_type = D6O_IA_NA;
4545 
4546  token = next_token(&val, NULL, cfile);
4547  if (token != LBRACE) {
4548  parse_warn(cfile, "corrupt lease file; expecting left brace");
4549  skip_to_semi(cfile);
4550  return;
4551  }
4552 
4553  for (;;) {
4554  token = next_token(&val, NULL, cfile);
4555  if (token == RBRACE) break;
4556 
4557  if (token == CLTT) {
4558  ia->cltt = parse_date (cfile);
4559  continue;
4560  }
4561 
4562  if (token != IAADDR) {
4563  parse_warn(cfile, "corrupt lease file; "
4564  "expecting IAADDR or right brace");
4565  skip_to_semi(cfile);
4566  return;
4567  }
4568 
4569  if (!parse_ip6_addr(cfile, &iaddr)) {
4570  parse_warn(cfile, "corrupt lease file; "
4571  "expecting IPv6 address");
4572  skip_to_semi(cfile);
4573  return;
4574  }
4575 
4576  token = next_token(&val, NULL, cfile);
4577  if (token != LBRACE) {
4578  parse_warn(cfile, "corrupt lease file; "
4579  "expecting left brace");
4580  skip_to_semi(cfile);
4581  return;
4582  }
4583 
4584  state = FTS_LAST+1;
4585  prefer = valid = 0;
4586  end_time = -1;
4587  for (;;) {
4588  token = next_token(&val, NULL, cfile);
4589  if (token == RBRACE) break;
4590 
4591  switch(token) {
4592  /* Lease binding state. */
4593  case BINDING:
4594  token = next_token(&val, NULL, cfile);
4595  if (token != STATE) {
4596  parse_warn(cfile, "corrupt lease file; "
4597  "expecting state");
4598  skip_to_semi(cfile);
4599  return;
4600  }
4601  token = next_token(&val, NULL, cfile);
4602  switch (token) {
4603  case TOKEN_ABANDONED:
4604  state = FTS_ABANDONED;
4605  break;
4606  case TOKEN_FREE:
4607  state = FTS_FREE;
4608  break;
4609  case TOKEN_ACTIVE:
4610  state = FTS_ACTIVE;
4611  break;
4612  case TOKEN_EXPIRED:
4613  state = FTS_EXPIRED;
4614  break;
4615  case TOKEN_RELEASED:
4616  state = FTS_RELEASED;
4617  break;
4618  default:
4619  parse_warn(cfile,
4620  "corrupt lease "
4621  "file; "
4622  "expecting a "
4623  "binding state.");
4624  skip_to_semi(cfile);
4625  return;
4626  }
4627 
4628  token = next_token(&val, NULL, cfile);
4629  if (token != SEMI) {
4630  parse_warn(cfile, "corrupt lease file; "
4631  "expecting "
4632  "semicolon.");
4633  }
4634  break;
4635 
4636  /* Lease preferred lifetime. */
4637  case PREFERRED_LIFE:
4638  token = next_token(&val, NULL, cfile);
4639  if (token != NUMBER) {
4640  parse_warn(cfile, "%s is not a valid "
4641  "preferred time",
4642  val);
4643  skip_to_semi(cfile);
4644  continue;
4645  }
4646  prefer = atoi (val);
4647 
4648  /*
4649  * Currently we peek for the semi-colon to
4650  * allow processing of older lease files that
4651  * don't have the semi-colon. Eventually we
4652  * should remove the peeking code.
4653  */
4654  token = peek_token(&val, NULL, cfile);
4655  if (token == SEMI) {
4656  skip_token(&val, NULL, cfile);
4657  } else {
4658  parse_warn(cfile,
4659  "corrupt lease file; "
4660  "expecting semicolon.");
4661  }
4662  break;
4663 
4664  /* Lease valid lifetime. */
4665  case MAX_LIFE:
4666  token = next_token(&val, NULL, cfile);
4667  if (token != NUMBER) {
4668  parse_warn(cfile, "%s is not a valid "
4669  "max time",
4670  val);
4671  skip_to_semi(cfile);
4672  continue;
4673  }
4674  valid = atoi (val);
4675 
4676  /*
4677  * Currently we peek for the semi-colon to
4678  * allow processing of older lease files that
4679  * don't have the semi-colon. Eventually we
4680  * should remove the peeking code.
4681  */
4682  token = peek_token(&val, NULL, cfile);
4683  if (token == SEMI) {
4684  skip_token(&val, NULL, cfile);
4685  } else {
4686  parse_warn(cfile,
4687  "corrupt lease file; "
4688  "expecting semicolon.");
4689  }
4690  break;
4691 
4692  /* Lease expiration time. */
4693  case ENDS:
4694  end_time = parse_date(cfile);
4695  break;
4696 
4697  /* Lease binding scopes. */
4698  case TOKEN_SET:
4699  token = next_token(&val, NULL, cfile);
4700  if ((token != NAME) &&
4701  (token != NUMBER_OR_NAME)) {
4702  parse_warn(cfile, "%s is not a valid "
4703  "variable name",
4704  val);
4705  skip_to_semi(cfile);
4706  continue;
4707  }
4708 
4709  if (scope != NULL)
4710  bnd = find_binding(scope, val);
4711  else {
4712  if (!binding_scope_allocate(&scope,
4713  MDL)) {
4714  log_fatal("Out of memory for "
4715  "lease binding "
4716  "scope.");
4717  }
4718 
4719  bnd = NULL;
4720  }
4721 
4722  if (bnd == NULL) {
4723  bnd = dmalloc(sizeof(*bnd),
4724  MDL);
4725  if (bnd == NULL) {
4726  log_fatal("No memory for "
4727  "lease binding.");
4728  }
4729 
4730  bnd->name = dmalloc(strlen(val) + 1,
4731  MDL);
4732  if (bnd->name == NULL) {
4733  log_fatal("No memory for "
4734  "binding name.");
4735  }
4736  strcpy(bnd->name, val);
4737 
4738  newbinding = ISC_TRUE;
4739  } else {
4740  newbinding = ISC_FALSE;
4741  }
4742 
4743  if (!binding_value_allocate(&nv, MDL)) {
4744  log_fatal("no memory for binding "
4745  "value.");
4746  }
4747 
4748  token = next_token(NULL, NULL, cfile);
4749  if (token != EQUAL) {
4750  parse_warn(cfile, "expecting '=' in "
4751  "set statement.");
4752  goto binding_err;
4753  }
4754 
4755  if (!parse_binding_value(cfile, nv)) {
4756  binding_err:
4758  binding_scope_dereference(&scope, MDL);
4759  return;
4760  }
4761 
4762  if (newbinding) {
4764  nv, MDL);
4765  bnd->next = scope->bindings;
4766  scope->bindings = bnd;
4767  } else {
4769  MDL);
4771  nv, MDL);
4772  }
4773 
4775  parse_semi(cfile);
4776  break;
4777 
4778  case ON:
4779  lose = 0;
4780  /*
4781  * Depending on the user config we may
4782  * have one or two on statements. We
4783  * need to save information about both
4784  * of them until we allocate the
4785  * iasubopt to hold them.
4786  */
4787  if (on_star[0] == NULL) {
4788  if (!parse_on_statement (&on_star[0],
4789  cfile,
4790  &lose)) {
4791  parse_warn(cfile,
4792  "corrupt lease "
4793  "file; bad ON "
4794  "statement");
4795  skip_to_rbrace (cfile, 1);
4796  return;
4797  }
4798  } else {
4799  if (!parse_on_statement (&on_star[1],
4800  cfile,
4801  &lose)) {
4802  parse_warn(cfile,
4803  "corrupt lease "
4804  "file; bad ON "
4805  "statement");
4806  skip_to_rbrace (cfile, 1);
4807  return;
4808  }
4809  }
4810 
4811  break;
4812 
4813  default:
4814  parse_warn(cfile, "corrupt lease file; "
4815  "expecting ia_na contents, "
4816  "got '%s'", val);
4817  skip_to_semi(cfile);
4818  continue;
4819  }
4820  }
4821 
4822  if (state == FTS_LAST+1) {
4823  parse_warn(cfile, "corrupt lease file; "
4824  "missing state in iaaddr");
4825  return;
4826  }
4827  if (end_time == -1) {
4828  parse_warn(cfile, "corrupt lease file; "
4829  "missing end time in iaaddr");
4830  return;
4831  }
4832 
4833  iaaddr = NULL;
4834  if (iasubopt_allocate(&iaaddr, MDL) != ISC_R_SUCCESS) {
4835  log_fatal("Out of memory.");
4836  }
4837  memcpy(&iaaddr->addr, iaddr.iabuf, sizeof(iaaddr->addr));
4838  iaaddr->plen = 0;
4839  iaaddr->state = state;
4840  iaaddr->prefer = prefer;
4841  iaaddr->valid = valid;
4842  if (iaaddr->state == FTS_RELEASED)
4843  iaaddr->hard_lifetime_end_time = end_time;
4844 
4845  if (scope != NULL) {
4846  binding_scope_reference(&iaaddr->scope, scope, MDL);
4847  binding_scope_dereference(&scope, MDL);
4848  }
4849 
4850  /*
4851  * Check on both on statements. Because of how we write the
4852  * lease file we know which is which if we have two but it's
4853  * easier to write the code to be independent. We do assume
4854  * that the statements won't overlap.
4855  */
4856  for (i = 0;
4857  (i < 2) && on_star[i] != NULL ;
4858  i++) {
4859  if ((on_star[i]->data.on.evtypes & ON_EXPIRY) &&
4860  on_star[i]->data.on.statements) {
4862  (&iaaddr->on_star.on_expiry,
4863  on_star[i]->data.on.statements, MDL);
4864  }
4865  if ((on_star[i]->data.on.evtypes & ON_RELEASE) &&
4866  on_star[i]->data.on.statements) {
4868  (&iaaddr->on_star.on_release,
4869  on_star[i]->data.on.statements, MDL);
4870  }
4871  executable_statement_dereference (&on_star[i], MDL);
4872  }
4873 
4874  /* find the pool this address is in */
4875  pool = NULL;
4876  if (find_ipv6_pool(&pool, D6O_IA_NA,
4877  &iaaddr->addr) != ISC_R_SUCCESS) {
4878  inet_ntop(AF_INET6, &iaaddr->addr,
4879  addr_buf, sizeof(addr_buf));
4880  parse_warn(cfile, "no pool found for address %s",
4881  addr_buf);
4882  return;
4883  }
4884 
4885  /* remove old information */
4886  if (cleanup_lease6(ia_na_active, pool,
4887  iaaddr, ia) != ISC_R_SUCCESS) {
4888  inet_ntop(AF_INET6, &iaaddr->addr,
4889  addr_buf, sizeof(addr_buf));
4890  parse_warn(cfile, "duplicate na lease for address %s",
4891  addr_buf);
4892  }
4893 
4894  /*
4895  * if we like the lease we add it to our various structues
4896  * otherwise we leave it and it will get cleaned when we
4897  * do the iasubopt_dereference.
4898  */
4899  if ((state == FTS_ACTIVE) || (state == FTS_ABANDONED)) {
4900  ia_add_iasubopt(ia, iaaddr, MDL);
4901  ia_reference(&iaaddr->ia, ia, MDL);
4902  add_lease6(pool, iaaddr, end_time);
4903  }
4904 
4905  iasubopt_dereference(&iaaddr, MDL);
4906  ipv6_pool_dereference(&pool, MDL);
4907  }
4908 
4909  /*
4910  * If we have an existing record for this IA_NA, remove it.
4911  */
4912  old_ia = NULL;
4913  if (ia_hash_lookup(&old_ia, ia_na_active,
4914  (unsigned char *)ia->iaid_duid.data,
4915  ia->iaid_duid.len, MDL)) {
4916  ia_hash_delete(ia_na_active,
4917  (unsigned char *)ia->iaid_duid.data,
4918  ia->iaid_duid.len, MDL);
4919  ia_dereference(&old_ia, MDL);
4920  }
4921 
4922  /*
4923  * If we have addresses, add this, otherwise don't bother.
4924  */
4925  if (ia->num_iasubopt > 0) {
4926  ia_hash_add(ia_na_active,
4927  (unsigned char *)ia->iaid_duid.data,
4928  ia->iaid_duid.len, ia, MDL);
4929  }
4930  ia_dereference(&ia, MDL);
4931 #endif /* defined(DHCPv6) */
4932 }
4933 
4934 void
4936 #if !defined(DHCPv6)
4937  parse_warn(cfile, "No DHCPv6 support.");
4938  skip_to_semi(cfile);
4939 #else /* defined(DHCPv6) */
4940  enum dhcp_token token;
4941  struct ia_xx *ia;
4942  const char *val;
4943  struct ia_xx *old_ia;
4944  unsigned int len;
4945  u_int32_t iaid;
4946  struct iaddr iaddr;
4947  binding_state_t state;
4948  u_int32_t prefer;
4949  u_int32_t valid;
4950  TIME end_time;
4951  struct iasubopt *iaaddr;
4952  struct ipv6_pool *pool;
4953  char addr_buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
4954  isc_boolean_t newbinding;
4955  struct binding_scope *scope = NULL;
4956  struct binding *bnd;
4957  struct binding_value *nv = NULL;
4958  struct executable_statement *on_star[2] = {NULL, NULL};
4959  int lose, i;
4960 
4961  if (local_family != AF_INET6) {
4962  parse_warn(cfile, "IA_TA is only supported in DHCPv6 mode.");
4963  skip_to_semi(cfile);
4964  return;
4965  }
4966 
4967  token = next_token(&val, &len, cfile);
4968  if (token != STRING) {
4969  parse_warn(cfile, "corrupt lease file; "
4970  "expecting an iaid+ia_ta string");
4971  skip_to_semi(cfile);
4972  return;
4973  }
4974  if (len < 5) {
4975  parse_warn(cfile, "corrupt lease file; "
4976  "iaid+ia_ta string too short");
4977  skip_to_semi(cfile);
4978  return;
4979  }
4980 
4981  memcpy(&iaid, val, 4);
4982  ia = NULL;
4983  if (ia_allocate(&ia, iaid, val+4, len-4, MDL) != ISC_R_SUCCESS) {
4984  log_fatal("Out of memory.");
4985  }
4986  ia->ia_type = D6O_IA_TA;
4987 
4988  token = next_token(&val, NULL, cfile);
4989  if (token != LBRACE) {
4990  parse_warn(cfile, "corrupt lease file; expecting left brace");
4991  skip_to_semi(cfile);
4992  return;
4993  }
4994 
4995  for (;;) {
4996  token = next_token(&val, NULL, cfile);
4997  if (token == RBRACE) break;
4998 
4999  if (token == CLTT) {
5000  ia->cltt = parse_date (cfile);
5001  continue;
5002  }
5003 
5004  if (token != IAADDR) {
5005  parse_warn(cfile, "corrupt lease file; "
5006  "expecting IAADDR or right brace");
5007  skip_to_semi(cfile);
5008  return;
5009  }
5010 
5011  if (!parse_ip6_addr(cfile, &iaddr)) {
5012  parse_warn(cfile, "corrupt lease file; "
5013  "expecting IPv6 address");
5014  skip_to_semi(cfile);
5015  return;
5016  }
5017 
5018  token = next_token(&val, NULL, cfile);
5019  if (token != LBRACE) {
5020  parse_warn(cfile, "corrupt lease file; "
5021  "expecting left brace");
5022  skip_to_semi(cfile);
5023  return;
5024  }
5025 
5026  state = FTS_LAST+1;
5027  prefer = valid = 0;
5028  end_time = -1;
5029  for (;;) {
5030  token = next_token(&val, NULL, cfile);
5031  if (token == RBRACE) break;
5032 
5033  switch(token) {
5034  /* Lease binding state. */
5035  case BINDING:
5036  token = next_token(&val, NULL, cfile);
5037  if (token != STATE) {
5038  parse_warn(cfile, "corrupt lease file; "
5039  "expecting state");
5040  skip_to_semi(cfile);
5041  return;
5042  }
5043  token = next_token(&val, NULL, cfile);
5044  switch (token) {
5045  case TOKEN_ABANDONED:
5046  state = FTS_ABANDONED;
5047  break;
5048  case TOKEN_FREE:
5049  state = FTS_FREE;
5050  break;
5051  case TOKEN_ACTIVE:
5052  state = FTS_ACTIVE;
5053  break;
5054  case TOKEN_EXPIRED:
5055  state = FTS_EXPIRED;
5056  break;
5057  case TOKEN_RELEASED:
5058  state = FTS_RELEASED;
5059  break;
5060  default:
5061  parse_warn(cfile,
5062  "corrupt lease "
5063  "file; "
5064  "expecting a "
5065  "binding state.");
5066  skip_to_semi(cfile);
5067  return;
5068  }
5069 
5070  token = next_token(&val, NULL, cfile);
5071  if (token != SEMI) {
5072  parse_warn(cfile, "corrupt lease file; "
5073  "expecting "
5074  "semicolon.");
5075  }
5076  break;
5077 
5078  /* Lease preferred lifetime. */
5079  case PREFERRED_LIFE:
5080  token = next_token(&val, NULL, cfile);
5081  if (token != NUMBER) {
5082  parse_warn(cfile, "%s is not a valid "
5083  "preferred time",
5084  val);
5085  skip_to_semi(cfile);
5086  continue;
5087  }
5088  prefer = atoi (val);
5089 
5090  /*
5091  * Currently we peek for the semi-colon to
5092  * allow processing of older lease files that
5093  * don't have the semi-colon. Eventually we
5094  * should remove the peeking code.
5095  */
5096  token = peek_token(&val, NULL, cfile);
5097  if (token == SEMI) {
5098  skip_token(&val, NULL, cfile);
5099  } else {
5100  parse_warn(cfile,
5101  "corrupt lease file; "
5102  "expecting semicolon.");
5103  }
5104  break;
5105 
5106  /* Lease valid lifetime. */
5107  case MAX_LIFE:
5108  token = next_token(&val, NULL, cfile);
5109  if (token != NUMBER) {
5110  parse_warn(cfile, "%s is not a valid "
5111  "max time",
5112  val);
5113  skip_to_semi(cfile);
5114  continue;
5115  }
5116  valid = atoi (val);
5117 
5118  /*
5119  * Currently we peek for the semi-colon to
5120  * allow processing of older lease files that
5121  * don't have the semi-colon. Eventually we
5122  * should remove the peeking code.
5123  */
5124  token = peek_token(&val, NULL, cfile);
5125  if (token == SEMI) {
5126  skip_token(&val, NULL, cfile);
5127  } else {
5128  parse_warn(cfile,
5129  "corrupt lease file; "
5130  "expecting semicolon.");
5131  }
5132  break;
5133 
5134  /* Lease expiration time. */
5135  case ENDS:
5136  end_time = parse_date(cfile);
5137  break;
5138 
5139  /* Lease binding scopes. */
5140  case TOKEN_SET:
5141  token = next_token(&val, NULL, cfile);
5142  if ((token != NAME) &&
5143  (token != NUMBER_OR_NAME)) {
5144  parse_warn(cfile, "%s is not a valid "
5145  "variable name",
5146  val);
5147  skip_to_semi(cfile);
5148  continue;
5149  }
5150 
5151  if (scope != NULL)
5152  bnd = find_binding(scope, val);
5153  else {
5154  if (!binding_scope_allocate(&scope,
5155  MDL)) {
5156  log_fatal("Out of memory for "
5157  "lease binding "
5158  "scope.");
5159  }
5160 
5161  bnd = NULL;
5162  }
5163 
5164  if (bnd == NULL) {
5165  bnd = dmalloc(sizeof(*bnd),
5166  MDL);
5167  if (bnd == NULL) {
5168  log_fatal("No memory for "
5169  "lease binding.");
5170  }
5171 
5172  bnd->name = dmalloc(strlen(val) + 1,
5173  MDL);
5174  if (bnd->name == NULL) {
5175  log_fatal("No memory for "
5176  "binding name.");
5177  }
5178  strcpy(bnd->name, val);
5179 
5180  newbinding = ISC_TRUE;
5181  } else {
5182  newbinding = ISC_FALSE;
5183  }
5184 
5185  if (!binding_value_allocate(&nv, MDL)) {
5186  log_fatal("no memory for binding "
5187  "value.");
5188  }
5189 
5190  token = next_token(NULL, NULL, cfile);
5191  if (token != EQUAL) {
5192  parse_warn(cfile, "expecting '=' in "
5193  "set statement.");
5194  goto binding_err;
5195  }
5196 
5197  if (!parse_binding_value(cfile, nv)) {
5198  binding_err:
5200  binding_scope_dereference(&scope, MDL);
5201  return;
5202  }
5203 
5204  if (newbinding) {
5206  nv, MDL);
5207  bnd->next = scope->bindings;
5208  scope->bindings = bnd;
5209  } else {
5211  MDL);
5213  nv, MDL);
5214  }
5215 
5217  parse_semi(cfile);
5218  break;
5219 
5220  case ON:
5221  lose = 0;
5222  /*
5223  * Depending on the user config we may
5224  * have one or two on statements. We
5225  * need to save information about both
5226  * of them until we allocate the
5227  * iasubopt to hold them.
5228  */
5229  if (on_star[0] == NULL) {
5230  if (!parse_on_statement (&on_star[0],
5231  cfile,
5232  &lose)) {
5233  parse_warn(cfile,
5234  "corrupt lease "
5235  "file; bad ON "
5236  "statement");
5237  skip_to_rbrace (cfile, 1);
5238  return;
5239  }
5240  } else {
5241  if (!parse_on_statement (&on_star[1],
5242  cfile,
5243  &lose)) {
5244  parse_warn(cfile,
5245  "corrupt lease "
5246  "file; bad ON "
5247  "statement");
5248  skip_to_rbrace (cfile, 1);
5249  return;
5250  }
5251  }
5252 
5253  break;
5254 
5255  default:
5256  parse_warn(cfile, "corrupt lease file; "
5257  "expecting ia_ta contents, "
5258  "got '%s'", val);
5259  skip_to_semi(cfile);
5260  continue;
5261  }
5262  }
5263 
5264  if (state == FTS_LAST+1) {
5265  parse_warn(cfile, "corrupt lease file; "
5266  "missing state in iaaddr");
5267  return;
5268  }
5269  if (end_time == -1) {
5270  parse_warn(cfile, "corrupt lease file; "
5271  "missing end time in iaaddr");
5272  return;
5273  }
5274 
5275  iaaddr = NULL;
5276  if (iasubopt_allocate(&iaaddr, MDL) != ISC_R_SUCCESS) {
5277  log_fatal("Out of memory.");
5278  }
5279  memcpy(&iaaddr->addr, iaddr.iabuf, sizeof(iaaddr->addr));
5280  iaaddr->plen = 0;
5281  iaaddr->state = state;
5282  iaaddr->prefer = prefer;
5283  iaaddr->valid = valid;
5284  if (iaaddr->state == FTS_RELEASED)
5285  iaaddr->hard_lifetime_end_time = end_time;
5286 
5287  if (scope != NULL) {
5288  binding_scope_reference(&iaaddr->scope, scope, MDL);
5289  binding_scope_dereference(&scope, MDL);
5290  }
5291 
5292  /*
5293  * Check on both on statements. Because of how we write the
5294  * lease file we know which is which if we have two but it's
5295  * easier to write the code to be independent. We do assume
5296  * that the statements won't overlap.
5297  */
5298  for (i = 0;
5299  (i < 2) && on_star[i] != NULL ;
5300  i++) {
5301  if ((on_star[i]->data.on.evtypes & ON_EXPIRY) &&
5302  on_star[i]->data.on.statements) {
5304  (&iaaddr->on_star.on_expiry,
5305  on_star[i]->data.on.statements, MDL);
5306  }
5307  if ((on_star[i]->data.on.evtypes & ON_RELEASE) &&
5308  on_star[i]->data.on.statements) {
5310  (&iaaddr->on_star.on_release,
5311  on_star[i]->data.on.statements, MDL);
5312  }
5313  executable_statement_dereference (&on_star[i], MDL);
5314  }
5315 
5316  /* find the pool this address is in */
5317  pool = NULL;
5318  if (find_ipv6_pool(&pool, D6O_IA_TA,
5319  &iaaddr->addr) != ISC_R_SUCCESS) {
5320  inet_ntop(AF_INET6, &iaaddr->addr,
5321  addr_buf, sizeof(addr_buf));
5322  parse_warn(cfile, "no pool found for address %s",
5323  addr_buf);
5324  return;
5325  }
5326 
5327  /* remove old information */
5328  if (cleanup_lease6(ia_ta_active, pool,
5329  iaaddr, ia) != ISC_R_SUCCESS) {
5330  inet_ntop(AF_INET6, &iaaddr->addr,
5331  addr_buf, sizeof(addr_buf));
5332  parse_warn(cfile, "duplicate ta lease for address %s",
5333  addr_buf);
5334  }
5335 
5336  /*
5337  * if we like the lease we add it to our various structues
5338  * otherwise we leave it and it will get cleaned when we
5339  * do the iasubopt_dereference.
5340  */
5341  if ((state == FTS_ACTIVE) || (state == FTS_ABANDONED)) {
5342  ia_add_iasubopt(ia, iaaddr, MDL);
5343  ia_reference(&iaaddr->ia, ia, MDL);
5344  add_lease6(pool, iaaddr, end_time);
5345  }
5346 
5347  ipv6_pool_dereference(&pool, MDL);
5348  iasubopt_dereference(&iaaddr, MDL);
5349  }
5350 
5351  /*
5352  * If we have an existing record for this IA_TA, remove it.
5353  */
5354  old_ia = NULL;
5355  if (ia_hash_lookup(&old_ia, ia_ta_active,
5356  (unsigned char *)ia->iaid_duid.data,
5357  ia->iaid_duid.len, MDL)) {
5358  ia_hash_delete(ia_ta_active,
5359  (unsigned char *)ia->iaid_duid.data,
5360  ia->iaid_duid.len, MDL);
5361  ia_dereference(&old_ia, MDL);
5362  }
5363 
5364  /*
5365  * If we have addresses, add this, otherwise don't bother.
5366  */
5367  if (ia->num_iasubopt > 0) {
5368  ia_hash_add(ia_ta_active,
5369  (unsigned char *)ia->iaid_duid.data,
5370  ia->iaid_duid.len, ia, MDL);
5371  }
5372  ia_dereference(&ia, MDL);
5373 #endif /* defined(DHCPv6) */
5374 }
5375 
5376 void
5378 #if !defined(DHCPv6)
5379  parse_warn(cfile, "No DHCPv6 support.");
5380  skip_to_semi(cfile);
5381 #else /* defined(DHCPv6) */
5382  enum dhcp_token token;
5383  struct ia_xx *ia;
5384  const char *val;
5385  struct ia_xx *old_ia;
5386  unsigned int len;
5387  u_int32_t iaid;
5388  struct iaddr iaddr;
5389  u_int8_t plen;
5390  binding_state_t state;
5391  u_int32_t prefer;
5392  u_int32_t valid;
5393  TIME end_time;
5394  struct iasubopt *iapref;
5395  struct ipv6_pool *pool;
5396  char addr_buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
5397  isc_boolean_t newbinding;
5398  struct binding_scope *scope = NULL;
5399  struct binding *bnd;
5400  struct binding_value *nv = NULL;
5401  struct executable_statement *on_star[2] = {NULL, NULL};
5402  int lose, i;
5403 
5404  if (local_family != AF_INET6) {
5405  parse_warn(cfile, "IA_PD is only supported in DHCPv6 mode.");
5406  skip_to_semi(cfile);
5407  return;
5408  }
5409 
5410  token = next_token(&val, &len, cfile);
5411  if (token != STRING) {
5412  parse_warn(cfile, "corrupt lease file; "
5413  "expecting an iaid+ia_pd string");
5414  skip_to_semi(cfile);
5415  return;
5416  }
5417  if (len < 5) {
5418  parse_warn(cfile, "corrupt lease file; "
5419  "iaid+ia_pd string too short");
5420  skip_to_semi(cfile);
5421  return;
5422  }
5423 
5424  memcpy(&iaid, val, 4);
5425  ia = NULL;
5426  if (ia_allocate(&ia, iaid, val+4, len-4, MDL) != ISC_R_SUCCESS) {
5427  log_fatal("Out of memory.");
5428  }
5429  ia->ia_type = D6O_IA_PD;
5430 
5431  token = next_token(&val, NULL, cfile);
5432  if (token != LBRACE) {
5433  parse_warn(cfile, "corrupt lease file; expecting left brace");
5434  skip_to_semi(cfile);
5435  return;
5436  }
5437 
5438  for (;;) {
5439  token = next_token(&val, NULL, cfile);
5440  if (token == RBRACE) break;
5441 
5442  if (token == CLTT) {
5443  ia->cltt = parse_date (cfile);
5444  continue;
5445  }
5446 
5447  if (token != IAPREFIX) {
5448  parse_warn(cfile, "corrupt lease file; expecting "
5449  "IAPREFIX or right brace");
5450  skip_to_semi(cfile);
5451  return;
5452  }
5453 
5454  if (!parse_ip6_prefix(cfile, &iaddr, &plen)) {
5455  parse_warn(cfile, "corrupt lease file; "
5456  "expecting IPv6 prefix");
5457  skip_to_semi(cfile);
5458  return;
5459  }
5460 
5461  token = next_token(&val, NULL, cfile);
5462  if (token != LBRACE) {
5463  parse_warn(cfile, "corrupt lease file; "
5464  "expecting left brace");
5465  skip_to_semi(cfile);
5466  return;
5467  }
5468 
5469  state = FTS_LAST+1;
5470  prefer = valid = 0;
5471  end_time = -1;
5472  for (;;) {
5473  token = next_token(&val, NULL, cfile);
5474  if (token == RBRACE) break;
5475 
5476  switch(token) {
5477  /* Prefix binding state. */
5478  case BINDING:
5479  token = next_token(&val, NULL, cfile);
5480  if (token != STATE) {
5481  parse_warn(cfile, "corrupt lease file; "
5482  "expecting state");
5483  skip_to_semi(cfile);
5484  return;
5485  }
5486  token = next_token(&val, NULL, cfile);
5487  switch (token) {
5488  case TOKEN_ABANDONED:
5489  state = FTS_ABANDONED;
5490  break;
5491  case TOKEN_FREE:
5492  state = FTS_FREE;
5493  break;
5494  case TOKEN_ACTIVE:
5495  state = FTS_ACTIVE;
5496  break;
5497  case TOKEN_EXPIRED:
5498  state = FTS_EXPIRED;
5499  break;
5500  case TOKEN_RELEASED:
5501  state = FTS_RELEASED;
5502  break;
5503  default:
5504  parse_warn(cfile,
5505  "corrupt lease "
5506  "file; "
5507  "expecting a "
5508  "binding state.");
5509  skip_to_semi(cfile);
5510  return;
5511  }
5512 
5513  token = next_token(&val, NULL, cfile);
5514  if (token != SEMI) {
5515  parse_warn(cfile, "corrupt lease file; "
5516  "expecting "
5517  "semicolon.");
5518  }
5519  break;
5520 
5521  /* Lease preferred lifetime. */
5522  case PREFERRED_LIFE:
5523  token = next_token(&val, NULL, cfile);
5524  if (token != NUMBER) {
5525  parse_warn(cfile, "%s is not a valid "
5526  "preferred time",
5527  val);
5528  skip_to_semi(cfile);
5529  continue;
5530  }
5531  prefer = atoi (val);
5532 
5533  /*
5534  * Currently we peek for the semi-colon to
5535  * allow processing of older lease files that
5536  * don't have the semi-colon. Eventually we
5537  * should remove the peeking code.
5538  */
5539  token = peek_token(&val, NULL, cfile);
5540  if (token == SEMI) {
5541  skip_token(&val, NULL, cfile);
5542  } else {
5543  parse_warn(cfile,
5544  "corrupt lease file; "
5545  "expecting semicolon.");
5546  }
5547  break;
5548 
5549  /* Lease valid lifetime. */
5550  case MAX_LIFE:
5551  token = next_token(&val, NULL, cfile);
5552  if (token != NUMBER) {
5553  parse_warn(cfile, "%s is not a valid "
5554  "max time",
5555  val);
5556  skip_to_semi(cfile);
5557  continue;
5558  }
5559  valid = atoi (val);
5560 
5561  /*
5562  * Currently we peek for the semi-colon to
5563  * allow processing of older lease files that
5564  * don't have the semi-colon. Eventually we
5565  * should remove the peeking code.
5566  */
5567  token = peek_token(&val, NULL, cfile);
5568  if (token == SEMI) {
5569  skip_token(&val, NULL, cfile);
5570  } else {
5571  parse_warn(cfile,
5572  "corrupt lease file; "
5573  "expecting semicolon.");
5574  }
5575  break;
5576 
5577  /* Prefix expiration time. */
5578  case ENDS:
5579  end_time = parse_date(cfile);
5580  break;
5581 
5582  /* Prefix binding scopes. */
5583  case TOKEN_SET:
5584  token = next_token(&val, NULL, cfile);
5585  if ((token != NAME) &&
5586  (token != NUMBER_OR_NAME)) {
5587  parse_warn(cfile, "%s is not a valid "
5588  "variable name",
5589  val);
5590  skip_to_semi(cfile);
5591  continue;
5592  }
5593 
5594  if (scope != NULL)
5595  bnd = find_binding(scope, val);
5596  else {
5597  if (!binding_scope_allocate(&scope,
5598  MDL)) {
5599  log_fatal("Out of memory for "
5600  "lease binding "
5601  "scope.");
5602  }
5603 
5604  bnd = NULL;
5605  }
5606 
5607  if (bnd == NULL) {
5608  bnd = dmalloc(sizeof(*bnd),
5609  MDL);
5610  if (bnd == NULL) {
5611  log_fatal("No memory for "
5612  "prefix binding.");
5613  }
5614 
5615  bnd->name = dmalloc(strlen(val) + 1,
5616  MDL);
5617  if (bnd->name == NULL) {
5618  log_fatal("No memory for "
5619  "binding name.");
5620  }
5621  strcpy(bnd->name, val);
5622 
5623  newbinding = ISC_TRUE;
5624  } else {
5625  newbinding = ISC_FALSE;
5626  }
5627 
5628  if (!binding_value_allocate(&nv, MDL)) {
5629  log_fatal("no memory for binding "
5630  "value.");
5631  }
5632 
5633  token = next_token(NULL, NULL, cfile);
5634  if (token != EQUAL) {
5635  parse_warn(cfile, "expecting '=' in "
5636  "set statement.");
5637  goto binding_err;
5638  }
5639 
5640  if (!parse_binding_value(cfile, nv)) {
5641  binding_err:
5643  binding_scope_dereference(&scope, MDL);
5644  return;
5645  }
5646 
5647  if (newbinding) {
5649  nv, MDL);
5650  bnd->next = scope->bindings;
5651  scope->bindings = bnd;
5652  } else {
5654  MDL);
5656  nv, MDL);
5657  }
5658 
5660  parse_semi(cfile);
5661  break;
5662 
5663  case ON:
5664  lose = 0;
5665  /*
5666  * Depending on the user config we may
5667  * have one or two on statements. We
5668  * need to save information about both
5669  * of them until we allocate the
5670  * iasubopt to hold them.
5671  */
5672  if (on_star[0] == NULL) {
5673  if (!parse_on_statement (&on_star[0],
5674  cfile,
5675  &lose)) {
5676  parse_warn(cfile,
5677  "corrupt lease "
5678  "file; bad ON "
5679  "statement");
5680  skip_to_rbrace (cfile, 1);
5681  return;
5682  }
5683  } else {
5684  if (!parse_on_statement (&on_star[1],
5685  cfile,
5686  &lose)) {
5687  parse_warn(cfile,
5688  "corrupt lease "
5689  "file; bad ON "
5690  "statement");
5691  skip_to_rbrace (cfile, 1);
5692  return;
5693  }
5694  }
5695 
5696  break;
5697 
5698  default:
5699  parse_warn(cfile, "corrupt lease file; "
5700  "expecting ia_pd contents, "
5701  "got '%s'", val);
5702  skip_to_semi(cfile);
5703  continue;
5704  }
5705  }
5706 
5707  if (state == FTS_LAST+1) {
5708  parse_warn(cfile, "corrupt lease file; "
5709  "missing state in iaprefix");
5710  return;
5711  }
5712  if (end_time == -1) {
5713  parse_warn(cfile, "corrupt lease file; "
5714  "missing end time in iaprefix");
5715  return;
5716  }
5717 
5718  iapref = NULL;
5719  if (iasubopt_allocate(&iapref, MDL) != ISC_R_SUCCESS) {
5720  log_fatal("Out of memory.");
5721  }
5722  memcpy(&iapref->addr, iaddr.iabuf, sizeof(iapref->addr));
5723  iapref->plen = plen;
5724  iapref->state = state;
5725  iapref->prefer = prefer;
5726  iapref->valid = valid;
5727  if (iapref->state == FTS_RELEASED)
5728  iapref->hard_lifetime_end_time = end_time;
5729 
5730  if (scope != NULL) {
5731  binding_scope_reference(&iapref->scope, scope, MDL);
5732  binding_scope_dereference(&scope, MDL);
5733  }
5734 
5735  /*
5736  * Check on both on statements. Because of how we write the
5737  * lease file we know which is which if we have two but it's
5738  * easier to write the code to be independent. We do assume
5739  * that the statements won't overlap.
5740  */
5741  for (i = 0;
5742  (i < 2) && on_star[i] != NULL ;
5743  i++) {
5744  if ((on_star[i]->data.on.evtypes & ON_EXPIRY) &&
5745  on_star[i]->data.on.statements) {
5747  (&iapref->on_star.on_expiry,
5748  on_star[i]->data.on.statements, MDL);
5749  }
5750  if ((on_star[i]->data.on.evtypes & ON_RELEASE) &&
5751  on_star[i]->data.on.statements) {
5753  (&iapref->on_star.on_release,
5754  on_star[i]->data.on.statements, MDL);
5755  }
5756  executable_statement_dereference (&on_star[i], MDL);
5757  }
5758 
5759  /* find the pool this address is in */
5760  pool = NULL;
5761  if (find_ipv6_pool(&pool, D6O_IA_PD,
5762  &iapref->addr) != ISC_R_SUCCESS) {
5763  inet_ntop(AF_INET6, &iapref->addr,
5764  addr_buf, sizeof(addr_buf));
5765  parse_warn(cfile, "no pool found for address %s",
5766  addr_buf);
5767  return;
5768  }
5769 
5770  /* remove old information */
5771  if (cleanup_lease6(ia_pd_active, pool,
5772  iapref, ia) != ISC_R_SUCCESS) {
5773  inet_ntop(AF_INET6, &iapref->addr,
5774  addr_buf, sizeof(addr_buf));
5775  parse_warn(cfile, "duplicate pd lease for address %s",
5776  addr_buf);
5777  }
5778 
5779  /*
5780  * if we like the lease we add it to our various structues
5781  * otherwise we leave it and it will get cleaned when we
5782  * do the iasubopt_dereference.
5783  */
5784  if ((state == FTS_ACTIVE) || (state == FTS_ABANDONED)) {
5785  ia_add_iasubopt(ia, iapref, MDL);
5786  ia_reference(&iapref->ia, ia, MDL);
5787  add_lease6(pool, iapref, end_time);
5788  }
5789 
5790  ipv6_pool_dereference(&pool, MDL);
5791  iasubopt_dereference(&iapref, MDL);
5792  }
5793 
5794  /*
5795  * If we have an existing record for this IA_PD, remove it.
5796  */
5797  old_ia = NULL;
5798  if (ia_hash_lookup(&old_ia, ia_pd_active,
5799  (unsigned char *)ia->iaid_duid.data,
5800  ia->iaid_duid.len, MDL)) {
5801  ia_hash_delete(ia_pd_active,
5802  (unsigned char *)ia->iaid_duid.data,
5803  ia->iaid_duid.len, MDL);
5804  ia_dereference(&old_ia, MDL);
5805  }
5806 
5807  /*
5808  * If we have prefixes, add this, otherwise don't bother.
5809  */
5810  if (ia->num_iasubopt > 0) {
5811  ia_hash_add(ia_pd_active,
5812  (unsigned char *)ia->iaid_duid.data,
5813  ia->iaid_duid.len, ia, MDL);
5814  }
5815  ia_dereference(&ia, MDL);
5816 #endif /* defined(DHCPv6) */
5817 }
5818 
5819 #ifdef DHCPv6
5820 /*
5821  * When we parse a server-duid statement in a lease file, we are
5822  * looking at the saved server DUID from a previous run. In this case
5823  * we expect it to be followed by the binary representation of the
5824  * DUID stored in a string:
5825  *
5826  * server-duid "\000\001\000\001\015\221\034JRT\000\0224Y";
5827  */
5828 void
5829 parse_server_duid(struct parse *cfile) {
5830  enum dhcp_token token;
5831  const char *val;
5832  unsigned int len;
5833  struct data_string duid;
5834 
5835  token = next_token(&val, &len, cfile);
5836  if (token != STRING) {
5837  parse_warn(cfile, "corrupt lease file; expecting a DUID");
5838  skip_to_semi(cfile);
5839  return;
5840  }
5841 
5842  memset(&duid, 0, sizeof(duid));
5843  duid.len = len;
5844  if (!buffer_allocate(&duid.buffer, duid.len, MDL)) {
5845  log_fatal("Out of memory storing DUID");
5846  }
5847  duid.data = (unsigned char *)duid.buffer->data;
5848  memcpy(duid.buffer->data, val, len);
5849 
5850  set_server_duid(&duid);
5851 
5852  data_string_forget(&duid, MDL);
5853 
5854  token = next_token(&val, &len, cfile);
5855  if (token != SEMI) {
5856  parse_warn(cfile, "corrupt lease file; expecting a semicolon");
5857  skip_to_semi(cfile);
5858  return;
5859  }
5860 }
5861 
5862 /*
5863  * When we parse a server-duid statement in a config file, we will
5864  * have the type of the server DUID to generate, and possibly the
5865  * actual value defined.
5866  *
5867  * server-duid llt;
5868  * server-duid llt ethernet|ieee802|fddi 213982198 00:16:6F:49:7D:9B;
5869  * server-duid ll;
5870  * server-duid ll ethernet|ieee802|fddi 00:16:6F:49:7D:9B;
5871  * server-duid en 2495 "enterprise-specific-identifier-1234";
5872  */
5873 void
5874 parse_server_duid_conf(struct parse *cfile) {
5875  enum dhcp_token token;
5876  const char *val;
5877  unsigned int len;
5878  u_int32_t enterprise_number;
5879  int ll_type;
5880  struct data_string ll_addr;
5881  u_int32_t llt_time;
5882  struct data_string duid;
5883  int duid_type_num;
5884 
5885  /*
5886  * Consume the SERVER_DUID token.
5887  */
5888  skip_token(NULL, NULL, cfile);
5889 
5890  /*
5891  * Obtain the DUID type.
5892  */
5893  token = next_token(&val, NULL, cfile);
5894 
5895  /*
5896  * Enterprise is the easiest - enterprise number and raw data
5897  * are required.
5898  */
5899  if (token == EN) {
5900  /*
5901  * Get enterprise number and identifier.
5902  */
5903  token = next_token(&val, NULL, cfile);
5904  if (token != NUMBER) {
5905  parse_warn(cfile, "enterprise number expected");
5906  skip_to_semi(cfile);
5907  return;
5908  }
5909  enterprise_number = atoi(val);
5910 
5911  token = next_token(&val, &len, cfile);
5912  if (token != STRING) {
5913  parse_warn(cfile, "identifier expected");
5914  skip_to_semi(cfile);
5915  return;
5916  }
5917 
5918  /*
5919  * Save the DUID.
5920  */
5921  memset(&duid, 0, sizeof(duid));
5922  duid.len = 2 + 4 + len;
5923  if (!buffer_allocate(&duid.buffer, duid.len, MDL)) {
5924  log_fatal("Out of memory storing DUID");
5925  }
5926  duid.data = (unsigned char *)duid.buffer->data;
5927  putUShort(duid.buffer->data, DUID_EN);
5928  putULong(duid.buffer->data + 2, enterprise_number);
5929  memcpy(duid.buffer->data + 6, val, len);
5930 
5931  set_server_duid(&duid);
5932  data_string_forget(&duid, MDL);
5933  }
5934 
5935  /*
5936  * Next easiest is the link-layer DUID. It consists only of
5937  * the LL directive, or optionally the specific value to use.
5938  *
5939  * If we have LL only, then we set the type. If we have the
5940  * value, then we set the actual DUID.
5941  */
5942  else if (token == LL) {
5943  if (peek_token(NULL, NULL, cfile) == SEMI) {
5945  } else {
5946  /*
5947  * Get our hardware type and address.
5948  */
5949  token = next_token(NULL, NULL, cfile);
5950  switch (token) {
5951  case ETHERNET:
5952  ll_type = HTYPE_ETHER;
5953  break;
5954  case TOKEN_RING:
5955  ll_type = HTYPE_IEEE802;
5956  break;
5957  case TOKEN_FDDI:
5958  ll_type = HTYPE_FDDI;
5959  break;
5960  default:
5961  parse_warn(cfile, "hardware type expected");
5962  skip_to_semi(cfile);
5963  return;
5964  }
5965  memset(&ll_addr, 0, sizeof(ll_addr));
5966  if (!parse_cshl(&ll_addr, cfile)) {
5967  return;
5968  }
5969 
5970  /*
5971  * Save the DUID.
5972  */
5973  memset(&duid, 0, sizeof(duid));
5974  duid.len = 2 + 2 + ll_addr.len;
5975  if (!buffer_allocate(&duid.buffer, duid.len, MDL)) {
5976  log_fatal("Out of memory storing DUID");
5977  }
5978  duid.data = (unsigned char *)duid.buffer->data;
5979  putUShort(duid.buffer->data, DUID_LL);
5980  putUShort(duid.buffer->data + 2, ll_type);
5981  memcpy(duid.buffer->data + 4,
5982  ll_addr.data, ll_addr.len);
5983 
5984  set_server_duid(&duid);
5985  data_string_forget(&duid, MDL);
5986  data_string_forget(&ll_addr, MDL);
5987  }
5988  }
5989 
5990  /*
5991  * Finally the link-layer DUID plus time. It consists only of
5992  * the LLT directive, or optionally the specific value to use.
5993  *
5994  * If we have LLT only, then we set the type. If we have the
5995  * value, then we set the actual DUID.
5996  */
5997  else if (token == LLT) {
5998  if (peek_token(NULL, NULL, cfile) == SEMI) {
6000  } else {
6001  /*
6002  * Get our hardware type, timestamp, and address.
6003  */
6004  token = next_token(NULL, NULL, cfile);
6005  switch (token) {
6006  case ETHERNET:
6007  ll_type = HTYPE_ETHER;
6008  break;
6009  case TOKEN_RING:
6010  ll_type = HTYPE_IEEE802;
6011  break;
6012  case TOKEN_FDDI:
6013  ll_type = HTYPE_FDDI;
6014  break;
6015  default:
6016  parse_warn(cfile, "hardware type expected");
6017  skip_to_semi(cfile);
6018  return;
6019  }
6020 
6021  token = next_token(&val, NULL, cfile);
6022  if (token != NUMBER) {
6023  parse_warn(cfile, "timestamp expected");
6024  skip_to_semi(cfile);
6025  return;
6026  }
6027  llt_time = atoi(val);
6028 
6029  memset(&ll_addr, 0, sizeof(ll_addr));
6030  if (!parse_cshl(&ll_addr, cfile)) {
6031  return;
6032  }
6033 
6034  /*
6035  * Save the DUID.
6036  */
6037  memset(&duid, 0, sizeof(duid));
6038  duid.len = 2 + 2 + 4 + ll_addr.len;
6039  if (!buffer_allocate(&duid.buffer, duid.len, MDL)) {
6040  log_fatal("Out of memory storing DUID");
6041  }
6042  duid.data = (unsigned char *)duid.buffer->data;
6043  putUShort(duid.buffer->data, DUID_LLT);
6044  putUShort(duid.buffer->data + 2, ll_type);
6045  putULong(duid.buffer->data + 4, llt_time);
6046  memcpy(duid.buffer->data + 8,
6047  ll_addr.data, ll_addr.len);
6048 
6049  set_server_duid(&duid);
6050  data_string_forget(&duid, MDL);
6051  data_string_forget(&ll_addr, MDL);
6052  }
6053  }
6054 
6055  /*
6056  * If users want they can use a number for DUID types.
6057  * This is useful for supporting future, not-yet-defined
6058  * DUID types.
6059  *
6060  * In this case, they have to put in the complete value.
6061  *
6062  * This also works for existing DUID types of course.
6063  */
6064  else if (token == NUMBER) {
6065  duid_type_num = atoi(val);
6066 
6067  token = next_token(&val, &len, cfile);
6068  if (token != STRING) {
6069  parse_warn(cfile, "identifier expected");
6070  skip_to_semi(cfile);
6071  return;
6072  }
6073 
6074  /*
6075  * Save the DUID.
6076  */
6077  memset(&duid, 0, sizeof(duid));
6078  duid.len = 2 + len;
6079  if (!buffer_allocate(&duid.buffer, duid.len, MDL)) {
6080  log_fatal("Out of memory storing DUID");
6081  }
6082  duid.data = (unsigned char *)duid.buffer->data;
6083  putUShort(duid.buffer->data, duid_type_num);
6084  memcpy(duid.buffer->data + 2, val, len);
6085 
6086  set_server_duid(&duid);
6087  data_string_forget(&duid, MDL);
6088  }
6089 
6090  /*
6091  * Anything else is an error.
6092  */
6093  else {
6094  parse_warn(cfile, "DUID type of LLT, EN, or LL expected");
6095  skip_to_semi(cfile);
6096  return;
6097  }
6098 
6099  /*
6100  * Finally consume our trailing semicolon.
6101  */
6102  token = next_token(NULL, NULL, cfile);
6103  if (token != SEMI) {
6104  parse_warn(cfile, "semicolon expected");
6105  skip_to_semi(cfile);
6106  }
6107 }
6108 
6109 #endif /* DHCPv6 */
6110 
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:846
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:1606
int executable_statement_allocate(struct executable_statement **ptr, const char *file, int line)
Definition: alloc.c:959
struct class * nic
Definition: dhcpd.h:981
Definition: tree.h:31
TIME valid_from
Definition: dhcpd.h:1612
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:942
#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:1228
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:909
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:1541
#define CLASS_TYPE_VENDOR
Definition: dhcpd.h:973
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:2753
enum dhcp_token token
Definition: dhcpd.h:284
Definition: dhctoken.h:71
void parse_pool6_statement(struct parse *, struct group *, int)
Definition: dhcpd.h:952
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:3508
struct ipv6_pond * ipv6_pond
Definition: dhcpd.h:945
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:882
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:1011
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:946
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:1608
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:2399
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:875
struct group * root_group
Definition: memory.c:31
enum binding_value::@15 type
struct data_string hash_string
Definition: dhcpd.h:996
#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:1517
int log_error(const char *,...) __attribute__((__format__(__printf__
struct collection * collections
Definition: dhcpd.h:3027
time_t cltt
Definition: dhcpd.h:1547
#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:1538
struct binding_scope * scope
Definition: dhcpd.h:1513
dhcp_failover_state_t * failover_peer
Definition: dhcpd.h:948
int parse_semi(struct parse *cfile)
Definition: parse.c:129
struct ipv6_pond * ipv6_pond
Definition: dhcpd.h:1590
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:928
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:869
struct permit * prohibit_list
Definition: dhcpd.h:1611
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:983
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:4935
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:859
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:1012
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:1106
#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:1514
struct permit * prohibit_list
Definition: dhcpd.h:912
Definition: tree.h:345
#define HOST_DECL_STATIC
Definition: dhcpd.h:883
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:903
void parse_ia_na_declaration(struct parse *cfile)
Definition: confpars.c:4493
#define CLASS_TYPE_SUBCLASS
Definition: dhcpd.h:976
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:906
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:975
struct iaddr net
Definition: dhcpd.h:959
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:830
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:925
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:1989
struct expression * expr
Definition: dhcpd.h:999
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:3441
struct pool * pool
Definition: dhcpd.h:518
struct iaddrcidrnetlist * next
Definition: inet.h:76
char * name
Definition: dhcpd.h:867
#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:1511
TIME atsfp
Definition: dhcpd.h:579
struct data_string iaid_duid
Definition: dhcpd.h:1543
int authoritative
Definition: dhcpd.h:858
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:1946
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:1003
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:1810
struct permit * next
Definition: dhcpd.h:891
u_int32_t prefer
Definition: dhcpd.h:1516
const char * name
Definition: tree.h:346
TIME valid_until
Definition: dhcpd.h:1613
int bits
Definition: dhcpd.h:1579
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:871
#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:5241
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:1545
struct ipv6_pool ** ipv6_pools
Definition: dhcpd.h:1615
u_int16_t ia_type
Definition: dhcpd.h:1544
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:1512
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:3110
struct shared_network * shared_network
Definition: dhcpd.h:956
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:2077
int prefix_len
Definition: dhcpd.h:961
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:4893
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:962
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:843
int parse_option_data(struct expression **expr, struct parse *cfile, int lookups, struct option *option)
Definition: parse.c:4786
void cleanup(void)
union binding_value::value value
struct shared_network * shared_network
Definition: dhcpd.h:857
Definition: dhctoken.h:39
dhcp_token
Definition: dhctoken.h:35
TIME cltt
Definition: dhcpd.h:580
struct lease ** billed_leases
Definition: dhcpd.h:988
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:924
ipv6_pool structure
Definition: dhcpd.h:1575
Definition: dhcpd.h:890
struct data_string const_data
Definition: tree.h:228
int local_family
Definition: discover.c:55
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:939
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:876
ia_hash_t * ia_pd_active
struct group_object * named_group
Definition: dhcpd.h:878
Definition: dhcpd.h:851
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:2356
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:856
#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:960
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:1251
void parse_prefix6(struct parse *cfile, struct group *group, struct ipv6_pond *)
struct option * host_id_option
Definition: dhcpd.h:870
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:955
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:902
struct interface_info * interface
Definition: dhcpd.h:943
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:2439
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:844
Definition: dhctoken.h:45
void parse_ia_pd_declaration(struct parse *cfile)
Definition: confpars.c:5377
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:1016
Definition: dhctoken.h:73
struct lease * next
Definition: dhcpd.h:509
int num_total
Definition: dhcpd.h:1618
#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:1604
Definition: tree.h:118
#define HOST_DECL
Definition: dhcpd.h:624
#define CLASS_TYPE_USER
Definition: dhcpd.h:974
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:1518
int flags
Definition: dhcpd.h:880
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:910
const char * file
Definition: dhcpd.h:3557
char * name
Definition: dhcpd.h:937
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:911
#define ON_RELEASE
Definition: statement.h:73
void putUShort(unsigned char *, u_int32_t)
Definition: convert.c:86
struct subnet * subnet
Definition: dhcpd.h:1589
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:1587
void trace_conf_stop(trace_type_t *ttype)
struct in6_addr addr
Definition: dhcpd.h:1510
int parse_allow_deny(struct option_cache **oc, struct parse *cfile, int flag)
Definition: confpars.c:4426
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:979
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:868
struct permit * permit_list
Definition: dhcpd.h:1610
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:842
int clone_group(struct group **gp, struct group *group, const char *file, int line)
Definition: memory.c:130
int relays
Definition: dhcpd.h:887
int parse_warn(struct parse *cfile, const char *fmt,...)
Definition: parse.c:5593
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:957
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:1607
struct pool * pools
Definition: dhcpd.h:944
#define GROUP_OBJECT_STATIC
Definition: dhcpd.h:847
struct group * group
Definition: dhcpd.h:877
struct buffer * buffer
Definition: tree.h:78
struct pool * next
Definition: dhcpd.h:908
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:1006
Definition: dhctoken.h:224
#define FTS_ACTIVE
Definition: dhcpd.h:485
int num_pools