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