]> git.ipfire.org Git - thirdparty/dhcp.git/blob - server/confpars.c
[master] Server now supports EUI-64 based address allocation scheme
[thirdparty/dhcp.git] / server / confpars.c
1 /* confpars.c
2
3 Parser for dhcpd config file... */
4
5 /*
6 * Copyright (c) 2004-2017 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1995-2003 by Internet Software Consortium
8 *
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 *
21 * Internet Systems Consortium, Inc.
22 * 950 Charter Street
23 * Redwood City, CA 94063
24 * <info@isc.org>
25 * https://www.isc.org/
26 *
27 */
28
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 == CLASS_TYPE_VENDOR) ?
2268 "implicit-vendor-class" : "implicit-user-class";
2269
2270 } else if (type == CLASS_TYPE_CLASS) {
2271 tname = val;
2272 } else {
2273 tname = NULL;
2274 }
2275
2276 if (tname) {
2277 name = dmalloc (strlen (tname) + 1, MDL);
2278 if (!name)
2279 log_fatal ("No memory for class name %s.", tname);
2280 strcpy (name, tname);
2281 } else
2282 name = NULL;
2283
2284 /* If this is a straight subclass, parse the hash string. */
2285 if (type == CLASS_TYPE_SUBCLASS) {
2286 token = peek_token (&val, NULL, cfile);
2287 if (token == STRING) {
2288 skip_token(&val, &data.len, cfile);
2289 data.buffer = NULL;
2290
2291 if (!buffer_allocate (&data.buffer,
2292 data.len + 1, MDL)) {
2293 if (pc)
2294 class_dereference (&pc, MDL);
2295
2296 return 0;
2297 }
2298 data.terminated = 1;
2299 data.data = &data.buffer -> data [0];
2300 memcpy ((char *)data.buffer -> data, val,
2301 data.len + 1);
2302 } else if (token == NUMBER_OR_NAME || token == NUMBER) {
2303 memset (&data, 0, sizeof data);
2304 if (!parse_cshl (&data, cfile)) {
2305 if (pc)
2306 class_dereference (&pc, MDL);
2307 return 0;
2308 }
2309 } else {
2310 parse_warn (cfile, "Expecting string or hex list.");
2311 if (pc)
2312 class_dereference (&pc, MDL);
2313 return 0;
2314 }
2315 }
2316
2317 /* See if there's already a class in the hash table matching the
2318 hash data. */
2319 if (type != CLASS_TYPE_CLASS)
2320 class_hash_lookup (&class, pc -> hash,
2321 (const char *)data.data, data.len, MDL);
2322
2323 /* If we didn't find an existing class, allocate a new one. */
2324 if (!class) {
2325 /* Allocate the class structure... */
2326 if (type == CLASS_TYPE_SUBCLASS) {
2327 status = subclass_allocate (&class, MDL);
2328 } else {
2329 status = class_allocate (&class, MDL);
2330 }
2331 if (pc) {
2332 group_reference (&class -> group, pc -> group, MDL);
2333 class_reference (&class -> superclass, pc, MDL);
2334 class -> lease_limit = pc -> lease_limit;
2335 if (class -> lease_limit) {
2336 class -> billed_leases =
2337 dmalloc (class -> lease_limit *
2338 sizeof (struct lease *), MDL);
2339 if (!class -> billed_leases)
2340 log_fatal ("no memory for billing");
2341 memset (class -> billed_leases, 0,
2342 (class -> lease_limit *
2343 sizeof (struct lease *)));
2344 }
2345 data_string_copy (&class -> hash_string, &data, MDL);
2346 if (!pc -> hash &&
2347 !class_new_hash (&pc->hash, SCLASS_HASH_SIZE, MDL))
2348 log_fatal ("No memory for subclass hash.");
2349 class_hash_add (pc -> hash,
2350 (const char *)class -> hash_string.data,
2351 class -> hash_string.len,
2352 (void *)class, MDL);
2353 } else {
2354 if (class->group)
2355 group_dereference(&class->group, MDL);
2356 if (!clone_group (&class -> group, group, MDL))
2357 log_fatal ("no memory to clone class group.");
2358 }
2359
2360 /* If this is an implicit vendor or user class, add a
2361 statement that causes the vendor or user class ID to
2362 be sent back in the reply. */
2363 if (type == CLASS_TYPE_VENDOR || type == CLASS_TYPE_USER) {
2364 stmt = NULL;
2365 if (!executable_statement_allocate (&stmt, MDL))
2366 log_fatal ("no memory for class statement.");
2367 stmt -> op = supersede_option_statement;
2368 if (option_cache_allocate (&stmt -> data.option,
2369 MDL)) {
2370 stmt -> data.option -> data = data;
2371 code = (type == CLASS_TYPE_VENDOR)
2372 ? DHO_VENDOR_CLASS_IDENTIFIER
2373 : DHO_USER_CLASS;
2374 option_code_hash_lookup(
2375 &stmt->data.option->option,
2376 dhcp_universe.code_hash,
2377 &code, 0, MDL);
2378 }
2379 class -> statements = stmt;
2380 }
2381
2382 /* Save the name, if there is one. */
2383 if (class->name != NULL)
2384 dfree(class->name, MDL);
2385 class->name = name;
2386 }
2387
2388 if (type != CLASS_TYPE_CLASS)
2389 data_string_forget(&data, MDL);
2390
2391 /* Spawned classes don't have to have their own settings. */
2392 if (class -> superclass) {
2393 token = peek_token (&val, NULL, cfile);
2394 if (token == SEMI) {
2395 skip_token(&val, NULL, cfile);
2396
2397 if (cp)
2398 status = class_reference (cp, class, MDL);
2399 class_dereference (&class, MDL);
2400 if (pc)
2401 class_dereference (&pc, MDL);
2402 return cp ? (status == ISC_R_SUCCESS) : 1;
2403 }
2404 /* Give the subclass its own group. */
2405 if (!clone_group (&class -> group, class -> group, MDL))
2406 log_fatal ("can't clone class group.");
2407
2408 }
2409
2410 if (!parse_lbrace (cfile)) {
2411 class_dereference (&class, MDL);
2412 if (pc)
2413 class_dereference (&pc, MDL);
2414 return 0;
2415 }
2416
2417 do {
2418 token = peek_token (&val, NULL, cfile);
2419 if (token == RBRACE) {
2420 skip_token(&val, NULL, cfile);
2421 break;
2422 } else if (token == END_OF_FILE) {
2423 skip_token(&val, NULL, cfile);
2424 parse_warn (cfile, "unexpected end of file");
2425 break;
2426 } else if (token == DYNAMIC) {
2427 class->flags |= CLASS_DECL_DYNAMIC;
2428 skip_token(&val, NULL, cfile);
2429 if (!parse_semi (cfile))
2430 break;
2431 continue;
2432 } else if (token == TOKEN_DELETED) {
2433 class->flags |= CLASS_DECL_DELETED;
2434 skip_token(&val, NULL, cfile);
2435 if (!parse_semi (cfile))
2436 break;
2437 continue;
2438 } else if (token == MATCH) {
2439 if (pc) {
2440 parse_warn (cfile,
2441 "invalid match in subclass.");
2442 skip_to_semi (cfile);
2443 break;
2444 }
2445 skip_token(&val, NULL, cfile);
2446 token = peek_token (&val, NULL, cfile);
2447 if (token != IF)
2448 goto submatch;
2449 skip_token(&val, NULL, cfile);
2450 if (matchedonce) {
2451 parse_warn(cfile, "A class may only have "
2452 "one 'match if' clause.");
2453 skip_to_semi(cfile);
2454 break;
2455 }
2456 matchedonce = 1;
2457 if (class->expr)
2458 expression_dereference(&class->expr, MDL);
2459 if (!parse_boolean_expression (&class->expr, cfile,
2460 &lose)) {
2461 if (!lose) {
2462 parse_warn (cfile,
2463 "expecting boolean expr.");
2464 skip_to_semi (cfile);
2465 }
2466 } else {
2467 #if defined (DEBUG_EXPRESSION_PARSE)
2468 print_expression ("class match",
2469 class -> expr);
2470 #endif
2471 parse_semi (cfile);
2472 }
2473 } else if (token == SPAWN) {
2474 skip_token(&val, NULL, cfile);
2475 if (pc) {
2476 parse_warn (cfile,
2477 "invalid spawn in subclass.");
2478 skip_to_semi (cfile);
2479 break;
2480 }
2481 class -> spawning = 1;
2482 token = next_token (&val, NULL, cfile);
2483 if (token != WITH) {
2484 parse_warn (cfile,
2485 "expecting with after spawn");
2486 skip_to_semi (cfile);
2487 break;
2488 }
2489 submatch:
2490 if (submatchedonce) {
2491 parse_warn (cfile,
2492 "can't override existing %s.",
2493 "submatch/spawn");
2494 skip_to_semi (cfile);
2495 break;
2496 }
2497 submatchedonce = 1;
2498 if (class->submatch)
2499 expression_dereference(&class->submatch, MDL);
2500 if (!parse_data_expression (&class -> submatch,
2501 cfile, &lose)) {
2502 if (!lose) {
2503 parse_warn (cfile,
2504 "expecting data expr.");
2505 skip_to_semi (cfile);
2506 }
2507 } else {
2508 #if defined (DEBUG_EXPRESSION_PARSE)
2509 print_expression ("class submatch",
2510 class -> submatch);
2511 #endif
2512 parse_semi (cfile);
2513 }
2514 } else if (token == LEASE) {
2515 skip_token(&val, NULL, cfile);
2516 token = next_token (&val, NULL, cfile);
2517 if (token != LIMIT) {
2518 parse_warn (cfile, "expecting \"limit\"");
2519 if (token != SEMI)
2520 skip_to_semi (cfile);
2521 break;
2522 }
2523 token = next_token (&val, NULL, cfile);
2524 if (token != NUMBER) {
2525 parse_warn (cfile, "expecting a number");
2526 if (token != SEMI)
2527 skip_to_semi (cfile);
2528 break;
2529 }
2530 class -> lease_limit = atoi (val);
2531 if (class->billed_leases)
2532 dfree(class->billed_leases, MDL);
2533 class -> billed_leases =
2534 dmalloc (class -> lease_limit *
2535 sizeof (struct lease *), MDL);
2536 if (!class -> billed_leases)
2537 log_fatal ("no memory for billed leases.");
2538 memset (class -> billed_leases, 0,
2539 (class -> lease_limit *
2540 sizeof (struct lease *)));
2541 have_billing_classes = 1;
2542 parse_semi (cfile);
2543 } else {
2544 declaration = parse_statement (cfile, class -> group,
2545 CLASS_DECL, NULL,
2546 declaration);
2547 }
2548 } while (1);
2549
2550 if (class->flags & CLASS_DECL_DELETED) {
2551 if (type == CLASS_TYPE_CLASS) {
2552 struct class *theclass = NULL;
2553
2554 status = find_class(&theclass, class->name, MDL);
2555 if (status == ISC_R_SUCCESS) {
2556 delete_class(theclass, 0);
2557 class_dereference(&theclass, MDL);
2558 }
2559 } else {
2560 class_hash_delete(pc->hash,
2561 (char *)class->hash_string.data,
2562 class->hash_string.len, MDL);
2563 }
2564 } else if (type == CLASS_TYPE_CLASS && new) {
2565 if (!collections -> classes)
2566 class_reference (&collections -> classes, class, MDL);
2567 else {
2568 struct class *c;
2569 for (c = collections -> classes;
2570 c -> nic; c = c -> nic)
2571 ;
2572 class_reference (&c -> nic, class, MDL);
2573 }
2574 }
2575
2576 if (cp) /* should always be 0??? */
2577 status = class_reference (cp, class, MDL);
2578 class_dereference (&class, MDL);
2579 if (pc)
2580 class_dereference (&pc, MDL);
2581 return cp ? (status == ISC_R_SUCCESS) : 1;
2582 }
2583
2584 /* shared-network-declaration :==
2585 hostname LBRACE declarations parameters RBRACE */
2586
2587 void parse_shared_net_declaration (cfile, group)
2588 struct parse *cfile;
2589 struct group *group;
2590 {
2591 const char *val;
2592 enum dhcp_token token;
2593 struct shared_network *share;
2594 char *name;
2595 int declaration = 0;
2596 isc_result_t status;
2597
2598 share = (struct shared_network *)0;
2599 status = shared_network_allocate (&share, MDL);
2600 if (status != ISC_R_SUCCESS)
2601 log_fatal ("Can't allocate shared subnet: %s",
2602 isc_result_totext (status));
2603 if (clone_group (&share -> group, group, MDL) == 0) {
2604 log_fatal ("Can't clone group for shared net");
2605 }
2606 shared_network_reference (&share -> group -> shared_network,
2607 share, MDL);
2608
2609 /* Get the name of the shared network... */
2610 token = peek_token (&val, (unsigned *)0, cfile);
2611 if (token == STRING) {
2612 skip_token(&val, (unsigned *)0, cfile);
2613
2614 if (val [0] == 0) {
2615 parse_warn (cfile, "zero-length shared network name");
2616 val = "<no-name-given>";
2617 }
2618 name = dmalloc (strlen (val) + 1, MDL);
2619 if (!name)
2620 log_fatal ("no memory for shared network name");
2621 strcpy (name, val);
2622 } else {
2623 name = parse_host_name (cfile);
2624 if (!name) {
2625 parse_warn (cfile,
2626 "expecting a name for shared-network");
2627 skip_to_semi (cfile);
2628 shared_network_dereference (&share, MDL);
2629 return;
2630 }
2631 }
2632 share -> name = name;
2633
2634 if (!parse_lbrace (cfile)) {
2635 shared_network_dereference (&share, MDL);
2636 return;
2637 }
2638
2639 do {
2640 token = peek_token (&val, (unsigned *)0, cfile);
2641 if (token == RBRACE) {
2642 skip_token(&val, (unsigned *)0, cfile);
2643 if (!share -> subnets)
2644 parse_warn (cfile,
2645 "empty shared-network decl");
2646 else
2647 enter_shared_network (share);
2648 shared_network_dereference (&share, MDL);
2649 return;
2650 } else if (token == END_OF_FILE) {
2651 skip_token(&val, (unsigned *)0, cfile);
2652 parse_warn (cfile, "unexpected end of file");
2653 break;
2654 } else if (token == INTERFACE) {
2655 skip_token(&val, (unsigned *)0, cfile);
2656 token = next_token (&val, (unsigned *)0, cfile);
2657 new_shared_network_interface (cfile, share, val);
2658 if (!parse_semi (cfile))
2659 break;
2660 continue;
2661 }
2662
2663 declaration = parse_statement (cfile, share -> group,
2664 SHARED_NET_DECL,
2665 (struct host_decl *)0,
2666 declaration);
2667 } while (1);
2668 shared_network_dereference (&share, MDL);
2669 }
2670
2671
2672 static int
2673 common_subnet_parsing(struct parse *cfile,
2674 struct shared_network *share,
2675 struct subnet *subnet) {
2676 enum dhcp_token token;
2677 struct subnet *t, *u;
2678 const char *val;
2679 int declaration = 0;
2680
2681 enter_subnet(subnet);
2682
2683 if (!parse_lbrace(cfile)) {
2684 subnet_dereference(&subnet, MDL);
2685 return 0;
2686 }
2687
2688 do {
2689 token = peek_token(&val, NULL, cfile);
2690 if (token == RBRACE) {
2691 skip_token(&val, NULL, cfile);
2692 break;
2693 } else if (token == END_OF_FILE) {
2694 skip_token(&val, NULL, cfile);
2695 parse_warn (cfile, "unexpected end of file");
2696 break;
2697 } else if (token == INTERFACE) {
2698 skip_token(&val, NULL, cfile);
2699 token = next_token(&val, NULL, cfile);
2700 new_shared_network_interface(cfile, share, val);
2701 if (!parse_semi(cfile))
2702 break;
2703 continue;
2704 }
2705 declaration = parse_statement(cfile, subnet->group,
2706 SUBNET_DECL,
2707 NULL,
2708 declaration);
2709 } while (1);
2710
2711 /* Add the subnet to the list of subnets in this shared net. */
2712 if (share->subnets == NULL) {
2713 subnet_reference(&share->subnets, subnet, MDL);
2714 } else {
2715 u = NULL;
2716 for (t = share->subnets; t->next_sibling; t = t->next_sibling) {
2717 if (subnet_inner_than(subnet, t, 0)) {
2718 subnet_reference(&subnet->next_sibling, t, MDL);
2719 if (u) {
2720 subnet_dereference(&u->next_sibling,
2721 MDL);
2722 subnet_reference(&u->next_sibling,
2723 subnet, MDL);
2724 } else {
2725 subnet_dereference(&share->subnets,
2726 MDL);
2727 subnet_reference(&share->subnets,
2728 subnet, MDL);
2729 }
2730 subnet_dereference(&subnet, MDL);
2731 return 1;
2732 }
2733 u = t;
2734 }
2735 subnet_reference(&t->next_sibling, subnet, MDL);
2736 }
2737 subnet_dereference(&subnet, MDL);
2738 return 1;
2739 }
2740
2741 /* subnet-declaration :==
2742 net NETMASK netmask RBRACE parameters declarations LBRACE */
2743
2744 void parse_subnet_declaration (cfile, share)
2745 struct parse *cfile;
2746 struct shared_network *share;
2747 {
2748 const char *val;
2749 enum dhcp_token token;
2750 struct subnet *subnet;
2751 struct iaddr iaddr;
2752 unsigned char addr [4];
2753 unsigned len = sizeof addr;
2754 isc_result_t status;
2755
2756 subnet = (struct subnet *)0;
2757 status = subnet_allocate (&subnet, MDL);
2758 if (status != ISC_R_SUCCESS)
2759 log_fatal ("Allocation of new subnet failed: %s",
2760 isc_result_totext (status));
2761 shared_network_reference (&subnet -> shared_network, share, MDL);
2762
2763 /*
2764 * If our parent shared network was implicitly created by the software,
2765 * and not explicitly configured by the user, then we actually put all
2766 * configuration scope in the parent (the shared network and subnet
2767 * share the same {}-level scope).
2768 *
2769 * Otherwise, we clone the parent group and continue as normal.
2770 */
2771 if (share->flags & SHARED_IMPLICIT) {
2772 group_reference(&subnet->group, share->group, MDL);
2773 } else {
2774 if (!clone_group(&subnet->group, share->group, MDL)) {
2775 log_fatal("Allocation of group for new subnet failed.");
2776 }
2777 }
2778 subnet_reference (&subnet -> group -> subnet, subnet, MDL);
2779
2780 /* Get the network number... */
2781 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) {
2782 subnet_dereference (&subnet, MDL);
2783 return;
2784 }
2785 memcpy (iaddr.iabuf, addr, len);
2786 iaddr.len = len;
2787 subnet -> net = iaddr;
2788
2789 token = next_token (&val, (unsigned *)0, cfile);
2790 if (token != NETMASK) {
2791 parse_warn (cfile, "Expecting netmask");
2792 skip_to_semi (cfile);
2793 return;
2794 }
2795
2796 /* Get the netmask... */
2797 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) {
2798 subnet_dereference (&subnet, MDL);
2799 return;
2800 }
2801 memcpy (iaddr.iabuf, addr, len);
2802 iaddr.len = len;
2803 subnet -> netmask = iaddr;
2804
2805 /* Validate the network number/netmask pair. */
2806 if (host_addr (subnet -> net, subnet -> netmask)) {
2807 char *maskstr;
2808
2809 /* dup it, since piaddr is re-entrant */
2810 maskstr = strdup (piaddr (subnet -> netmask));
2811 if (maskstr == NULL) {
2812 log_fatal("Allocation of subnet maskstr failed: %s",
2813 piaddr (subnet -> net));
2814 }
2815
2816 parse_warn (cfile,
2817 "subnet %s netmask %s: bad subnet number/mask combination.",
2818 piaddr (subnet -> net), maskstr);
2819 free(maskstr);
2820 subnet_dereference (&subnet, MDL);
2821 skip_to_semi (cfile);
2822 return;
2823 }
2824
2825 common_subnet_parsing(cfile, share, subnet);
2826 }
2827
2828 /* subnet6-declaration :==
2829 net / bits RBRACE parameters declarations LBRACE */
2830
2831 void
2832 parse_subnet6_declaration(struct parse *cfile, struct shared_network *share) {
2833 #if !defined(DHCPv6)
2834 parse_warn(cfile, "No DHCPv6 support.");
2835 skip_to_semi(cfile);
2836 #else /* defined(DHCPv6) */
2837 struct subnet *subnet;
2838 isc_result_t status;
2839 enum dhcp_token token;
2840 const char *val;
2841 char *endp;
2842 int ofs;
2843 const static int mask[] = { 0x00, 0x80, 0xC0, 0xE0,
2844 0xF0, 0xF8, 0xFC, 0xFE };
2845 struct iaddr iaddr;
2846
2847 #if defined(DHCP4o6)
2848 if ((local_family != AF_INET6) && !dhcpv4_over_dhcpv6) {
2849 parse_warn(cfile, "subnet6 statement is only supported "
2850 "in DHCPv6 and DHCPv4o6 modes.");
2851 skip_to_semi(cfile);
2852 return;
2853 }
2854 #else /* defined(DHCP4o6) */
2855 if (local_family != AF_INET6) {
2856 parse_warn(cfile, "subnet6 statement is only supported "
2857 "in DHCPv6 mode.");
2858 skip_to_semi(cfile);
2859 return;
2860 }
2861 #endif /* !defined(DHCP4o6) */
2862
2863 subnet = NULL;
2864 status = subnet_allocate(&subnet, MDL);
2865 if (status != ISC_R_SUCCESS) {
2866 log_fatal("Allocation of new subnet failed: %s",
2867 isc_result_totext(status));
2868 }
2869 shared_network_reference(&subnet->shared_network, share, MDL);
2870
2871 /*
2872 * If our parent shared network was implicitly created by the software,
2873 * and not explicitly configured by the user, then we actually put all
2874 * configuration scope in the parent (the shared network and subnet
2875 * share the same {}-level scope).
2876 *
2877 * Otherwise, we clone the parent group and continue as normal.
2878 */
2879 if (share->flags & SHARED_IMPLICIT) {
2880 group_reference(&subnet->group, share->group, MDL);
2881 } else {
2882 if (!clone_group(&subnet->group, share->group, MDL)) {
2883 log_fatal("Allocation of group for new subnet failed.");
2884 }
2885 }
2886 subnet_reference(&subnet->group->subnet, subnet, MDL);
2887
2888 if (!parse_ip6_addr(cfile, &subnet->net)) {
2889 subnet_dereference(&subnet, MDL);
2890 return;
2891 }
2892
2893 token = next_token(&val, NULL, cfile);
2894 if (token != SLASH) {
2895 parse_warn(cfile, "Expecting a '/'.");
2896 skip_to_semi(cfile);
2897 return;
2898 }
2899
2900 token = next_token(&val, NULL, cfile);
2901 if (token != NUMBER) {
2902 parse_warn(cfile, "Expecting a number.");
2903 skip_to_semi(cfile);
2904 return;
2905 }
2906
2907 subnet->prefix_len = strtol(val, &endp, 10);
2908 if ((subnet->prefix_len < 0) ||
2909 (subnet->prefix_len > 128) ||
2910 (*endp != '\0')) {
2911 parse_warn(cfile, "Expecting a number between 0 and 128.");
2912 skip_to_semi(cfile);
2913 return;
2914 }
2915
2916 if (!is_cidr_mask_valid(&subnet->net, subnet->prefix_len)) {
2917 parse_warn(cfile, "New subnet mask too short.");
2918 skip_to_semi(cfile);
2919 return;
2920 }
2921
2922 /*
2923 * Create a netmask.
2924 */
2925 subnet->netmask.len = 16;
2926 ofs = subnet->prefix_len / 8;
2927 if (ofs < subnet->netmask.len) {
2928 subnet->netmask.iabuf[ofs] = mask[subnet->prefix_len % 8];
2929 }
2930 while (--ofs >= 0) {
2931 subnet->netmask.iabuf[ofs] = 0xFF;
2932 }
2933
2934 /* Validate the network number/netmask pair. */
2935 iaddr = subnet_number(subnet->net, subnet->netmask);
2936 if (memcmp(&iaddr, &subnet->net, 16) != 0) {
2937 parse_warn(cfile,
2938 "subnet %s/%d: prefix not long enough for address.",
2939 piaddr(subnet->net), subnet->prefix_len);
2940 subnet_dereference(&subnet, MDL);
2941 skip_to_semi(cfile);
2942 return;
2943 }
2944
2945 if (!common_subnet_parsing(cfile, share, subnet)) {
2946 return;
2947 }
2948 #endif /* defined(DHCPv6) */
2949 }
2950
2951 /* group-declaration :== RBRACE parameters declarations LBRACE */
2952
2953 void parse_group_declaration (cfile, group)
2954 struct parse *cfile;
2955 struct group *group;
2956 {
2957 const char *val;
2958 enum dhcp_token token;
2959 struct group *g;
2960 int declaration = 0;
2961 struct group_object *t = NULL;
2962 isc_result_t status;
2963 char *name = NULL;
2964 int deletedp = 0;
2965 int dynamicp = 0;
2966 int staticp = 0;
2967
2968 g = NULL;
2969 if (!clone_group(&g, group, MDL))
2970 log_fatal("no memory for explicit group.");
2971
2972 token = peek_token(&val, NULL, cfile);
2973 if (is_identifier (token) || token == STRING) {
2974 skip_token(&val, NULL, cfile);
2975
2976 name = dmalloc(strlen(val) + 1, MDL);
2977 if (!name)
2978 log_fatal("no memory for group decl name %s", val);
2979 strcpy(name, val);
2980 }
2981
2982 if (!parse_lbrace(cfile)) {
2983 group_dereference(&g, MDL);
2984 return;
2985 }
2986
2987 do {
2988 token = peek_token(&val, NULL, cfile);
2989 if (token == RBRACE) {
2990 skip_token(&val, NULL, cfile);
2991 break;
2992 } else if (token == END_OF_FILE) {
2993 skip_token(&val, NULL, cfile);
2994 parse_warn(cfile, "unexpected end of file");
2995 break;
2996 } else if (token == TOKEN_DELETED) {
2997 skip_token(&val, NULL, cfile);
2998 parse_semi(cfile);
2999 deletedp = 1;
3000 } else if (token == DYNAMIC) {
3001 skip_token(&val, NULL, cfile);
3002 parse_semi(cfile);
3003 dynamicp = 1;
3004 } else if (token == STATIC) {
3005 skip_token(&val, NULL, cfile);
3006 parse_semi(cfile);
3007 staticp = 1;
3008 }
3009 declaration = parse_statement(cfile, g, GROUP_DECL,
3010 NULL, declaration);
3011 } while (1);
3012
3013 if (name) {
3014 if (deletedp) {
3015 if (group_name_hash) {
3016 t = NULL;
3017 if (group_hash_lookup(&t, group_name_hash,
3018 name,
3019 strlen(name), MDL)) {
3020 delete_group(t, 0);
3021 }
3022 }
3023 } else {
3024 t = NULL;
3025 status = group_object_allocate(&t, MDL);
3026 if (status != ISC_R_SUCCESS)
3027 log_fatal("no memory for group decl %s: %s",
3028 val, isc_result_totext(status));
3029 group_reference(&t->group, g, MDL);
3030 t->name = name;
3031 /* no need to include deletedp as it's handled above */
3032 t->flags = ((staticp ? GROUP_OBJECT_STATIC : 0) |
3033 (dynamicp ? GROUP_OBJECT_DYNAMIC : 0));
3034 supersede_group(t, 0);
3035 }
3036 if (t != NULL)
3037 group_object_dereference(&t, MDL);
3038 }
3039 }
3040
3041 /* fixed-addr-parameter :== ip-addrs-or-hostnames SEMI
3042 ip-addrs-or-hostnames :== ip-addr-or-hostname
3043 | ip-addrs-or-hostnames ip-addr-or-hostname */
3044
3045 int
3046 parse_fixed_addr_param(struct option_cache **oc,
3047 struct parse *cfile,
3048 enum dhcp_token type) {
3049 int parse_ok;
3050 const char *val;
3051 enum dhcp_token token;
3052 struct expression *expr = NULL;
3053 struct expression *tmp, *new;
3054 int status;
3055
3056 do {
3057 tmp = NULL;
3058 if (type == FIXED_ADDR) {
3059 parse_ok = parse_ip_addr_or_hostname(&tmp, cfile, 1);
3060 } else {
3061 /* INSIST(type == FIXED_ADDR6); */
3062 parse_ok = parse_ip6_addr_expr(&tmp, cfile);
3063 }
3064 if (parse_ok) {
3065 if (expr != NULL) {
3066 new = NULL;
3067 status = make_concat(&new, expr, tmp);
3068 expression_dereference(&expr, MDL);
3069 expression_dereference(&tmp, MDL);
3070 if (!status) {
3071 return 0;
3072 }
3073 expr = new;
3074 } else {
3075 expr = tmp;
3076 }
3077 } else {
3078 if (expr != NULL) {
3079 expression_dereference (&expr, MDL);
3080 }
3081 return 0;
3082 }
3083 token = peek_token(&val, NULL, cfile);
3084 if (token == COMMA) {
3085 token = next_token(&val, NULL, cfile);
3086 }
3087 } while (token == COMMA);
3088
3089 if (!parse_semi(cfile)) {
3090 if (expr) {
3091 expression_dereference (&expr, MDL);
3092 }
3093 return 0;
3094 }
3095
3096 status = option_cache(oc, NULL, expr, NULL, MDL);
3097 expression_dereference(&expr, MDL);
3098 return status;
3099 }
3100
3101 /* lease_declaration :== LEASE ip_address LBRACE lease_parameters RBRACE
3102
3103 lease_parameters :== <nil>
3104 | lease_parameter
3105 | lease_parameters lease_parameter
3106
3107 lease_parameter :== STARTS date
3108 | ENDS date
3109 | TIMESTAMP date
3110 | HARDWARE hardware-parameter
3111 | UID hex_numbers SEMI
3112 | HOSTNAME hostname SEMI
3113 | CLIENT_HOSTNAME hostname SEMI
3114 | CLASS identifier SEMI
3115 | DYNAMIC_BOOTP SEMI */
3116
3117 int parse_lease_declaration (struct lease **lp, struct parse *cfile)
3118 {
3119 const char *val;
3120 enum dhcp_token token;
3121 unsigned char addr [4];
3122 unsigned len = sizeof addr;
3123 int seenmask = 0;
3124 int seenbit;
3125 char tbuf [32];
3126 struct lease *lease;
3127 struct executable_statement *on;
3128 int lose;
3129 TIME t;
3130 int noequal, newbinding;
3131 struct binding *binding;
3132 struct binding_value *nv;
3133 isc_result_t status;
3134 struct option_cache *oc;
3135 pair *p;
3136 binding_state_t new_state;
3137 unsigned buflen = 0;
3138 struct class *class;
3139
3140 lease = (struct lease *)0;
3141 status = lease_allocate (&lease, MDL);
3142 if (status != ISC_R_SUCCESS)
3143 return 0;
3144
3145 /* Get the address for which the lease has been issued. */
3146 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) {
3147 lease_dereference (&lease, MDL);
3148 return 0;
3149 }
3150 memcpy (lease -> ip_addr.iabuf, addr, len);
3151 lease -> ip_addr.len = len;
3152
3153 if (!parse_lbrace (cfile)) {
3154 lease_dereference (&lease, MDL);
3155 return 0;
3156 }
3157
3158 do {
3159 token = next_token (&val, (unsigned *)0, cfile);
3160 if (token == RBRACE)
3161 break;
3162 else if (token == END_OF_FILE) {
3163 parse_warn (cfile, "unexpected end of file");
3164 break;
3165 }
3166 strncpy (tbuf, val, sizeof tbuf);
3167 tbuf [(sizeof tbuf) - 1] = 0;
3168
3169 /* Parse any of the times associated with the lease. */
3170 switch (token) {
3171 case STARTS:
3172 case ENDS:
3173 case TIMESTAMP:
3174 case TSTP:
3175 case TSFP:
3176 case ATSFP:
3177 case CLTT:
3178 t = parse_date (cfile);
3179 switch (token) {
3180 case STARTS:
3181 seenbit = 1;
3182 lease -> starts = t;
3183 break;
3184
3185 case ENDS:
3186 seenbit = 2;
3187 lease -> ends = t;
3188 break;
3189
3190 case TSTP:
3191 seenbit = 65536;
3192 lease -> tstp = t;
3193 break;
3194
3195 case TSFP:
3196 seenbit = 131072;
3197 lease -> tsfp = t;
3198 break;
3199
3200 case ATSFP:
3201 seenbit = 262144;
3202 lease->atsfp = t;
3203 break;
3204
3205 case CLTT:
3206 seenbit = 524288;
3207 lease -> cltt = t;
3208 break;
3209
3210 default: /* for gcc, we'll never get here. */
3211 log_fatal ("Impossible error at %s:%d.", MDL);
3212 return 0;
3213 }
3214 break;
3215
3216 /* Colon-separated hexadecimal octets... */
3217 case UID:
3218 seenbit = 8;
3219 token = peek_token (&val, (unsigned *)0, cfile);
3220 if (token == STRING) {
3221 unsigned char *tuid;
3222 skip_token(&val, &buflen, cfile);
3223 if (buflen < sizeof lease -> uid_buf) {
3224 tuid = lease -> uid_buf;
3225 lease -> uid_max =
3226 sizeof lease -> uid_buf;
3227 } else {
3228 tuid = ((unsigned char *)
3229 dmalloc (buflen, MDL));
3230 if (!tuid) {
3231 log_error ("no space for uid");
3232 lease_dereference (&lease,
3233 MDL);
3234 return 0;
3235 }
3236 lease -> uid_max = buflen;
3237 }
3238 lease -> uid_len = buflen;
3239 memcpy (tuid, val, lease -> uid_len);
3240 lease -> uid = tuid;
3241 } else {
3242 buflen = 0;
3243 lease -> uid = (parse_numeric_aggregate
3244 (cfile, (unsigned char *)0,
3245 &buflen, ':', 16, 8));
3246 if (!lease -> uid) {
3247 lease_dereference (&lease, MDL);
3248 return 0;
3249 }
3250 lease -> uid_len = buflen;
3251 lease -> uid_max = buflen;
3252 if (lease -> uid_len == 0) {
3253 lease -> uid = (unsigned char *)0;
3254 parse_warn (cfile, "zero-length uid");
3255 seenbit = 0;
3256 parse_semi (cfile);
3257 break;
3258 }
3259 }
3260 parse_semi (cfile);
3261 if (!lease -> uid) {
3262 log_fatal ("No memory for lease uid");
3263 }
3264 break;
3265
3266 case CLASS:
3267 seenbit = 32;
3268 token = next_token (&val, (unsigned *)0, cfile);
3269 if (!is_identifier (token)) {
3270 if (token != SEMI)
3271 skip_to_rbrace (cfile, 1);
3272 lease_dereference (&lease, MDL);
3273 return 0;
3274 }
3275 parse_semi (cfile);
3276 /* for now, we aren't using this. */
3277 break;
3278
3279 case HARDWARE:
3280 seenbit = 64;
3281 parse_hardware_param (cfile,
3282 &lease -> hardware_addr);
3283 break;
3284
3285 case TOKEN_RESERVED:
3286 seenbit = 0;
3287 lease->flags |= RESERVED_LEASE;
3288 parse_semi(cfile);
3289 break;
3290
3291 case DYNAMIC_BOOTP:
3292 seenbit = 0;
3293 lease -> flags |= BOOTP_LEASE;
3294 parse_semi (cfile);
3295 break;
3296
3297 /* XXX: Reverse compatibility? */
3298 case TOKEN_ABANDONED:
3299 seenbit = 256;
3300 lease -> binding_state = FTS_ABANDONED;
3301 lease -> next_binding_state = FTS_ABANDONED;
3302 parse_semi (cfile);
3303 break;
3304
3305 case TOKEN_NEXT:
3306 seenbit = 128;
3307 token = next_token (&val, (unsigned *)0, cfile);
3308 if (token != BINDING) {
3309 parse_warn (cfile, "expecting 'binding'");
3310 skip_to_semi (cfile);
3311 break;
3312 }
3313 goto do_binding_state;
3314
3315 case REWIND:
3316 seenbit = 512;
3317 token = next_token(&val, NULL, cfile);
3318 if (token != BINDING) {
3319 parse_warn(cfile, "expecting 'binding'");
3320 skip_to_semi(cfile);
3321 break;
3322 }
3323 goto do_binding_state;
3324
3325 case BINDING:
3326 seenbit = 256;
3327
3328 do_binding_state:
3329 token = next_token (&val, (unsigned *)0, cfile);
3330 if (token != STATE) {
3331 parse_warn (cfile, "expecting 'state'");
3332 skip_to_semi (cfile);
3333 break;
3334 }
3335 token = next_token (&val, (unsigned *)0, cfile);
3336 switch (token) {
3337 case TOKEN_ABANDONED:
3338 new_state = FTS_ABANDONED;
3339 break;
3340 case TOKEN_FREE:
3341 new_state = FTS_FREE;
3342 break;
3343 case TOKEN_ACTIVE:
3344 new_state = FTS_ACTIVE;
3345 break;
3346 case TOKEN_EXPIRED:
3347 new_state = FTS_EXPIRED;
3348 break;
3349 case TOKEN_RELEASED:
3350 new_state = FTS_RELEASED;
3351 break;
3352 case TOKEN_RESET:
3353 new_state = FTS_RESET;
3354 break;
3355 case TOKEN_BACKUP:
3356 new_state = FTS_BACKUP;
3357 break;
3358
3359 /* RESERVED and BOOTP states preserved for
3360 * compatibleness with older versions.
3361 */
3362 case TOKEN_RESERVED:
3363 new_state = FTS_ACTIVE;
3364 lease->flags |= RESERVED_LEASE;
3365 break;
3366 case TOKEN_BOOTP:
3367 new_state = FTS_ACTIVE;
3368 lease->flags |= BOOTP_LEASE;
3369 break;
3370
3371 default:
3372 parse_warn (cfile,
3373 "%s: expecting a binding state.",
3374 val);
3375 skip_to_semi (cfile);
3376 return 0;
3377 }
3378
3379 if (seenbit == 256) {
3380 lease -> binding_state = new_state;
3381
3382 /*
3383 * Apply default/conservative next/rewind
3384 * binding states if they haven't been set
3385 * yet. These defaults will be over-ridden if
3386 * they are set later in parsing.
3387 */
3388 if (!(seenmask & 128))
3389 lease->next_binding_state = new_state;
3390
3391 /* The most conservative rewind state. */
3392 if (!(seenmask & 512))
3393 lease->rewind_binding_state = new_state;
3394 } else if (seenbit == 128)
3395 lease -> next_binding_state = new_state;
3396 else if (seenbit == 512)
3397 lease->rewind_binding_state = new_state;
3398 else
3399 log_fatal("Impossible condition at %s:%d.",
3400 MDL);
3401
3402 parse_semi (cfile);
3403 break;
3404
3405 case CLIENT_HOSTNAME:
3406 seenbit = 1024;
3407 token = peek_token (&val, (unsigned *)0, cfile);
3408 if (token == STRING) {
3409 if (!parse_string (cfile,
3410 &lease -> client_hostname,
3411 (unsigned *)0)) {
3412 lease_dereference (&lease, MDL);
3413 return 0;
3414 }
3415 } else {
3416 lease -> client_hostname =
3417 parse_host_name (cfile);
3418 if (lease -> client_hostname)
3419 parse_semi (cfile);
3420 else {
3421 parse_warn (cfile,
3422 "expecting a hostname.");
3423 skip_to_semi (cfile);
3424 lease_dereference (&lease, MDL);
3425 return 0;
3426 }
3427 }
3428 break;
3429
3430 case BILLING:
3431 seenbit = 2048;
3432 class = (struct class *)0;
3433 token = next_token (&val, (unsigned *)0, cfile);
3434 if (token == CLASS) {
3435 token = next_token (&val,
3436 (unsigned *)0, cfile);
3437 if (token != STRING) {
3438 parse_warn (cfile, "expecting string");
3439 if (token != SEMI)
3440 skip_to_semi (cfile);
3441 token = BILLING;
3442 break;
3443 }
3444 if (lease -> billing_class)
3445 class_dereference (&lease -> billing_class,
3446 MDL);
3447 find_class (&class, val, MDL);
3448 if (!class)
3449 parse_warn (cfile,
3450 "unknown class %s", val);
3451 parse_semi (cfile);
3452 } else if (token == SUBCLASS) {
3453 if (lease -> billing_class)
3454 class_dereference (&lease -> billing_class,
3455 MDL);
3456 parse_class_declaration(&class, cfile, NULL,
3457 CLASS_TYPE_SUBCLASS);
3458 } else {
3459 parse_warn (cfile, "expecting \"class\"");
3460 if (token != SEMI)
3461 skip_to_semi (cfile);
3462 }
3463 if (class) {
3464 class_reference (&lease -> billing_class,
3465 class, MDL);
3466 class_dereference (&class, MDL);
3467 }
3468 break;
3469
3470 case ON:
3471 on = (struct executable_statement *)0;
3472 lose = 0;
3473 if (!parse_on_statement (&on, cfile, &lose)) {
3474 skip_to_rbrace (cfile, 1);
3475 lease_dereference (&lease, MDL);
3476 return 0;
3477 }
3478 seenbit = 0;
3479 if ((on->data.on.evtypes & ON_EXPIRY) &&
3480 on->data.on.statements) {
3481 seenbit |= 16384;
3482 executable_statement_reference
3483 (&lease->on_star.on_expiry,
3484 on->data.on.statements, MDL);
3485 }
3486 if ((on->data.on.evtypes & ON_RELEASE) &&
3487 on->data.on.statements) {
3488 seenbit |= 32768;
3489 executable_statement_reference
3490 (&lease->on_star.on_release,
3491 on->data.on.statements, MDL);
3492 }
3493 executable_statement_dereference (&on, MDL);
3494 break;
3495
3496 case OPTION:
3497 case SUPERSEDE:
3498 noequal = 0;
3499 seenbit = 0;
3500 oc = (struct option_cache *)0;
3501 if (parse_option_decl (&oc, cfile)) {
3502 if (oc -> option -> universe !=
3503 &agent_universe) {
3504 parse_warn (cfile,
3505 "agent option expected.");
3506 option_cache_dereference (&oc, MDL);
3507 break;
3508 }
3509 if (!lease -> agent_options &&
3510 !(option_chain_head_allocate
3511 (&lease -> agent_options, MDL))) {
3512 log_error ("no memory to stash agent option");
3513 break;
3514 }
3515 for (p = &lease -> agent_options -> first;
3516 *p; p = &((*p) -> cdr))
3517 ;
3518 *p = cons (0, 0);
3519 option_cache_reference (((struct option_cache **)
3520 &((*p) -> car)), oc, MDL);
3521 option_cache_dereference (&oc, MDL);
3522 }
3523 break;
3524
3525 case TOKEN_SET:
3526 noequal = 0;
3527
3528 token = next_token (&val, (unsigned *)0, cfile);
3529 if (token != NAME && token != NUMBER_OR_NAME) {
3530 parse_warn (cfile,
3531 "%s can't be a variable name",
3532 val);
3533 badset:
3534 skip_to_semi (cfile);
3535 lease_dereference (&lease, MDL);
3536 return 0;
3537 }
3538
3539 seenbit = 0;
3540 special_set:
3541 if (lease -> scope)
3542 binding = find_binding (lease -> scope, val);
3543 else
3544 binding = (struct binding *)0;
3545
3546 if (!binding) {
3547 if (!lease -> scope)
3548 if (!(binding_scope_allocate
3549 (&lease -> scope, MDL)))
3550 log_fatal ("no memory for scope");
3551 binding = dmalloc (sizeof *binding, MDL);
3552 if (!binding)
3553 log_fatal ("No memory for lease %s.",
3554 "binding");
3555 memset (binding, 0, sizeof *binding);
3556 binding -> name =
3557 dmalloc (strlen (val) + 1, MDL);
3558 if (!binding -> name)
3559 log_fatal ("No memory for binding %s.",
3560 "name");
3561 strcpy (binding -> name, val);
3562 newbinding = 1;
3563 } else {
3564 newbinding = 0;
3565 }
3566
3567 nv = NULL;
3568 if (!binding_value_allocate(&nv, MDL))
3569 log_fatal("no memory for binding value.");
3570
3571 if (!noequal) {
3572 token = next_token (&val, (unsigned *)0, cfile);
3573 if (token != EQUAL) {
3574 parse_warn (cfile,
3575 "expecting '=' in set statement.");
3576 goto badset;
3577 }
3578 }
3579
3580 if (!parse_binding_value(cfile, nv)) {
3581 binding_value_dereference(&nv, MDL);
3582 lease_dereference(&lease, MDL);
3583 return 0;
3584 }
3585
3586 if (newbinding) {
3587 binding_value_reference(&binding->value,
3588 nv, MDL);
3589 binding->next = lease->scope->bindings;
3590 lease->scope->bindings = binding;
3591 } else {
3592 binding_value_dereference(&binding->value, MDL);
3593 binding_value_reference(&binding->value,
3594 nv, MDL);
3595 }
3596
3597 binding_value_dereference(&nv, MDL);
3598 parse_semi(cfile);
3599 break;
3600
3601 /* case NAME: */
3602 default:
3603 if (!strcasecmp (val, "ddns-fwd-name")) {
3604 seenbit = 4096;
3605 noequal = 1;
3606 goto special_set;
3607 } else if (!strcasecmp (val, "ddns-rev-name")) {
3608 seenbit = 8192;
3609 noequal = 1;
3610 goto special_set;
3611 } else
3612 parse_warn(cfile, "Unexpected configuration "
3613 "directive.");
3614 skip_to_semi (cfile);
3615 seenbit = 0;
3616 lease_dereference (&lease, MDL);
3617 return 0;
3618 }
3619
3620 if (seenmask & seenbit) {
3621 parse_warn (cfile,
3622 "Too many %s parameters in lease %s\n",
3623 tbuf, piaddr (lease -> ip_addr));
3624 } else
3625 seenmask |= seenbit;
3626
3627 } while (1);
3628
3629 /* If no binding state is specified, make one up. */
3630 if (!(seenmask & 256)) {
3631 if (lease->ends > cur_time ||
3632 lease->on_star.on_expiry || lease->on_star.on_release)
3633 lease->binding_state = FTS_ACTIVE;
3634 #if defined (FAILOVER_PROTOCOL)
3635 else if (lease->pool && lease->pool->failover_peer)
3636 lease->binding_state = FTS_EXPIRED;
3637 #endif
3638 else
3639 lease->binding_state = FTS_FREE;
3640 if (lease->binding_state == FTS_ACTIVE) {
3641 #if defined (FAILOVER_PROTOCOL)
3642 if (lease->pool && lease->pool->failover_peer)
3643 lease->next_binding_state = FTS_EXPIRED;
3644 else
3645 #endif
3646 lease->next_binding_state = FTS_FREE;
3647 } else
3648 lease->next_binding_state = lease->binding_state;
3649
3650 /* The most conservative rewind state implies no rewind. */
3651 lease->rewind_binding_state = lease->binding_state;
3652 }
3653
3654 if (!(seenmask & 65536))
3655 lease->tstp = lease->ends;
3656
3657 lease_reference (lp, lease, MDL);
3658 lease_dereference (&lease, MDL);
3659 return 1;
3660 }
3661
3662 /* Parse the right side of a 'binding value'.
3663 *
3664 * set foo = "bar"; is a string
3665 * set foo = false; is a boolean
3666 * set foo = %31; is a numeric value.
3667 */
3668 static int
3669 parse_binding_value(struct parse *cfile, struct binding_value *value)
3670 {
3671 struct data_string *data;
3672 unsigned char *s;
3673 const char *val;
3674 unsigned buflen;
3675 int token;
3676
3677 if ((cfile == NULL) || (value == NULL))
3678 log_fatal("Invalid arguments at %s:%d.", MDL);
3679
3680 token = peek_token(&val, NULL, cfile);
3681 if (token == STRING) {
3682 skip_token(&val, &buflen, cfile);
3683
3684 value->type = binding_data;
3685 value->value.data.len = buflen;
3686
3687 data = &value->value.data;
3688
3689 if (!buffer_allocate(&data->buffer, buflen + 1, MDL))
3690 log_fatal ("No memory for binding.");
3691
3692 memcpy(data->buffer->data, val, buflen + 1);
3693
3694 data->data = data->buffer->data;
3695 data->terminated = 1;
3696 } else if (token == NUMBER_OR_NAME) {
3697 value->type = binding_data;
3698
3699 data = &value->value.data;
3700 s = parse_numeric_aggregate(cfile, NULL, &data->len,
3701 ':', 16, 8);
3702 if (s == NULL) {
3703 skip_to_semi(cfile);
3704 return 0;
3705 }
3706
3707 if (data->len) {
3708 if (!buffer_allocate(&data->buffer, data->len + 1,
3709 MDL))
3710 log_fatal("No memory for binding.");
3711
3712 memcpy(data->buffer->data, s, data->len);
3713 data->data = data->buffer->data;
3714
3715 dfree (s, MDL);
3716 }
3717 } else if (token == PERCENT) {
3718 skip_token(&val, NULL, cfile);
3719 token = next_token(&val, NULL, cfile);
3720 if (token != NUMBER) {
3721 parse_warn(cfile, "expecting decimal number.");
3722 if (token != SEMI)
3723 skip_to_semi(cfile);
3724 return 0;
3725 }
3726 value->type = binding_numeric;
3727 value->value.intval = atol(val);
3728 } else if (token == NAME) {
3729 token = next_token(&val, NULL, cfile);
3730 value->type = binding_boolean;
3731 if (!strcasecmp(val, "true"))
3732 value->value.boolean = 1;
3733 else if (!strcasecmp(val, "false"))
3734 value->value.boolean = 0;
3735 else {
3736 parse_warn(cfile, "expecting true or false");
3737 if (token != SEMI)
3738 skip_to_semi(cfile);
3739 return 0;
3740 }
3741 } else {
3742 parse_warn (cfile, "expecting a constant value.");
3743 if (token != SEMI)
3744 skip_to_semi (cfile);
3745 return 0;
3746 }
3747
3748 return 1;
3749 }
3750
3751 /* address-range-declaration :== ip-address ip-address SEMI
3752 | DYNAMIC_BOOTP ip-address ip-address SEMI */
3753
3754 void parse_address_range (cfile, group, type, inpool, lpchain)
3755 struct parse *cfile;
3756 struct group *group;
3757 int type;
3758 struct pool *inpool;
3759 struct lease **lpchain;
3760 {
3761 struct iaddr low, high, net;
3762 unsigned char addr [4];
3763 unsigned len = sizeof addr;
3764 enum dhcp_token token;
3765 const char *val;
3766 int dynamic = 0;
3767 struct subnet *subnet;
3768 struct shared_network *share;
3769 struct pool *pool;
3770 isc_result_t status;
3771
3772 if ((token = peek_token (&val,
3773 (unsigned *)0, cfile)) == DYNAMIC_BOOTP) {
3774 skip_token(&val, (unsigned *)0, cfile);
3775 dynamic = 1;
3776 }
3777
3778 /* Get the bottom address in the range... */
3779 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
3780 return;
3781 memcpy (low.iabuf, addr, len);
3782 low.len = len;
3783
3784 /* Only one address? */
3785 token = peek_token (&val, (unsigned *)0, cfile);
3786 if (token == SEMI)
3787 high = low;
3788 else {
3789 /* Get the top address in the range... */
3790 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
3791 return;
3792 memcpy (high.iabuf, addr, len);
3793 high.len = len;
3794 }
3795
3796 token = next_token (&val, (unsigned *)0, cfile);
3797 if (token != SEMI) {
3798 parse_warn (cfile, "semicolon expected.");
3799 skip_to_semi (cfile);
3800 return;
3801 }
3802
3803 if (type == SUBNET_DECL) {
3804 subnet = group -> subnet;
3805 share = subnet -> shared_network;
3806 } else {
3807 share = group -> shared_network;
3808 for (subnet = share -> subnets;
3809 subnet; subnet = subnet -> next_sibling) {
3810 net = subnet_number (low, subnet -> netmask);
3811 if (addr_eq (net, subnet -> net))
3812 break;
3813 }
3814 if (!subnet) {
3815 parse_warn (cfile, "address range not on network %s",
3816 group -> shared_network -> name);
3817 log_error ("Be sure to place pool statement after %s",
3818 "related subnet declarations.");
3819 return;
3820 }
3821 }
3822
3823 if (!inpool) {
3824 struct pool *last = (struct pool *)0;
3825
3826 /* If we're permitting dynamic bootp for this range,
3827 then look for a pool with an empty prohibit list and
3828 a permit list with one entry that permits all clients. */
3829 for (pool = share -> pools; pool; pool = pool -> next) {
3830 if ((!dynamic && !pool -> permit_list &&
3831 pool -> prohibit_list &&
3832 !pool -> prohibit_list -> next &&
3833 (pool -> prohibit_list -> type ==
3834 permit_dynamic_bootp_clients)) ||
3835 (dynamic && !pool -> prohibit_list &&
3836 pool -> permit_list &&
3837 !pool -> permit_list -> next &&
3838 (pool -> permit_list -> type ==
3839 permit_all_clients))) {
3840 break;
3841 }
3842 last = pool;
3843 }
3844
3845 /* If we didn't get a pool, make one. */
3846 if (!pool) {
3847 struct permit *p;
3848 status = pool_allocate (&pool, MDL);
3849 if (status != ISC_R_SUCCESS)
3850 log_fatal ("no memory for ad-hoc pool: %s",
3851 isc_result_totext (status));
3852 p = new_permit (MDL);
3853 if (!p)
3854 log_fatal ("no memory for ad-hoc permit.");
3855
3856 /* Dynamic pools permit all clients. Otherwise
3857 we prohibit BOOTP clients. */
3858 if (dynamic) {
3859 p -> type = permit_all_clients;
3860 pool -> permit_list = p;
3861 } else {
3862 p -> type = permit_dynamic_bootp_clients;
3863 pool -> prohibit_list = p;
3864 }
3865
3866 if (share -> pools)
3867 pool_reference (&last -> next, pool, MDL);
3868 else
3869 pool_reference (&share -> pools, pool, MDL);
3870 shared_network_reference (&pool -> shared_network,
3871 share, MDL);
3872 if (!clone_group (&pool -> group, share -> group, MDL))
3873 log_fatal ("no memory for anon pool group.");
3874 } else {
3875 pool = (struct pool *)0;
3876 if (last)
3877 pool_reference (&pool, last, MDL);
3878 else
3879 pool_reference (&pool, share -> pools, MDL);
3880 }
3881 } else {
3882 pool = (struct pool *)0;
3883 pool_reference (&pool, inpool, MDL);
3884 }
3885
3886 #if defined (FAILOVER_PROTOCOL)
3887 if (pool -> failover_peer && dynamic) {
3888 /* Doctor, do you think I'm overly sensitive
3889 about getting bug reports I can't fix? */
3890 parse_warn (cfile, "dynamic-bootp flag is %s",
3891 "not permitted for address");
3892 log_error ("range declarations where there is a failover");
3893 log_error ("peer in scope. If you wish to declare an");
3894 log_error ("address range from which dynamic bootp leases");
3895 log_error ("can be allocated, please declare it within a");
3896 log_error ("pool declaration that also contains the \"no");
3897 log_error ("failover\" statement. The failover protocol");
3898 log_error ("itself does not permit dynamic bootp - this");
3899 log_error ("is not a limitation specific to the ISC DHCP");
3900 log_error ("server. Please don't ask me to defend this");
3901 log_error ("until you have read and really tried %s",
3902 "to understand");
3903 log_error ("the failover protocol specification.");
3904
3905 /* We don't actually bomb at this point - instead,
3906 we let parse_lease_file notice the error and
3907 bomb at that point - it's easier. */
3908 }
3909 #endif /* FAILOVER_PROTOCOL */
3910
3911 /* Create the new address range... */
3912 new_address_range (cfile, low, high, subnet, pool, lpchain);
3913 pool_dereference (&pool, MDL);
3914 }
3915
3916 #ifdef DHCPv6
3917 static void
3918 add_ipv6_pool_to_subnet(struct subnet *subnet, u_int16_t type,
3919 struct iaddr *lo_addr, int bits, int units,
3920 struct ipv6_pond *pond) {
3921 struct ipv6_pool *pool;
3922 struct in6_addr tmp_in6_addr;
3923 int num_pools;
3924 struct ipv6_pool **tmp;
3925
3926 /*
3927 * Create our pool.
3928 */
3929 if (lo_addr->len != sizeof(tmp_in6_addr)) {
3930 log_fatal("Internal error: Attempt to add non-IPv6 address "
3931 "to IPv6 shared network.");
3932 }
3933 memcpy(&tmp_in6_addr, lo_addr->iabuf, sizeof(tmp_in6_addr));
3934 pool = NULL;
3935 if (ipv6_pool_allocate(&pool, type, &tmp_in6_addr,
3936 bits, units, MDL) != ISC_R_SUCCESS) {
3937 log_fatal("Out of memory");
3938 }
3939
3940 /*
3941 * Add to our global IPv6 pool set.
3942 */
3943 if (add_ipv6_pool(pool) != ISC_R_SUCCESS) {
3944 log_fatal ("Out of memory");
3945 }
3946
3947 /*
3948 * Link the pool to its network.
3949 */
3950 pool->subnet = NULL;
3951 subnet_reference(&pool->subnet, subnet, MDL);
3952 pool->shared_network = NULL;
3953 shared_network_reference(&pool->shared_network,
3954 subnet->shared_network, MDL);
3955 pool->ipv6_pond = NULL;
3956 ipv6_pond_reference(&pool->ipv6_pond, pond, MDL);
3957
3958 /*
3959 * Increase our array size for ipv6_pools in the pond
3960 */
3961 if (pond->ipv6_pools == NULL) {
3962 num_pools = 0;
3963 } else {
3964 num_pools = 0;
3965 while (pond->ipv6_pools[num_pools] != NULL) {
3966 num_pools++;
3967 }
3968 }
3969 tmp = dmalloc(sizeof(struct ipv6_pool *) * (num_pools + 2), MDL);
3970 if (tmp == NULL) {
3971 log_fatal("Out of memory");
3972 }
3973 if (num_pools > 0) {
3974 memcpy(tmp, pond->ipv6_pools,
3975 sizeof(struct ipv6_pool *) * num_pools);
3976 }
3977 if (pond->ipv6_pools != NULL) {
3978 dfree(pond->ipv6_pools, MDL);
3979 }
3980 pond->ipv6_pools = tmp;
3981
3982 /*
3983 * Record this pool in our array of pools for this shared network.
3984 */
3985 ipv6_pool_reference(&pond->ipv6_pools[num_pools], pool, MDL);
3986 pond->ipv6_pools[num_pools+1] = NULL;
3987
3988 /* Update the number of elements in the pond. Conveniently
3989 * we have the total size of the block in bits and the amount
3990 * we would allocate per element in units. For an address units
3991 * will always be 128, for a prefix it will be something else.
3992 *
3993 * We need to make sure the number of elements isn't too large
3994 * to track. If so, we flag it to avoid wasting time with log
3995 * threshold logic. We also emit a log stating that log-threshold
3996 * will be disabled for the shared-network but that's done
3997 * elsewhere via report_log_threshold().
3998 *
3999 */
4000
4001 /* Only bother if we aren't already flagged as jumbo */
4002 if (pond->jumbo_range == 0) {
4003 if ((units - bits) > (sizeof(isc_uint64_t) * 8)) {
4004 pond->jumbo_range = 1;
4005 pond->num_total = POND_TRACK_MAX;
4006 }
4007 else {
4008 isc_uint64_t space_left
4009 = POND_TRACK_MAX - pond->num_total;
4010 isc_uint64_t addon
4011 = (isc_uint64_t)(1) << (units - bits);
4012
4013 if (addon > space_left) {
4014 pond->jumbo_range = 1;
4015 pond->num_total = POND_TRACK_MAX;
4016 } else {
4017 pond->num_total += addon;
4018 }
4019 }
4020 }
4021 }
4022
4023 /*!
4024 *
4025 * \brief Find or create a default pond
4026 *
4027 * Find or create an ipv6_pond on which to attach the ipv6_pools. We
4028 * check the shared network to see if there is a general purpose
4029 * entry - this will have an empty prohibit list and a permit list
4030 * with a single entry that permits all clients. If the shared
4031 * network doesn't have one of them create it and attach it to
4032 * the shared network and the return argument.
4033 *
4034 * This function is used when we have a range6 or prefix6 statement
4035 * inside a subnet6 statement but outside of a pool6 statement.
4036 * This routine constructs the missing ipv6_pond structure so
4037 * we always have
4038 * shared_network -> ipv6_pond -> ipv6_pool
4039 *
4040 * \param[in] group = a pointer to the group structure from which
4041 * we can find the subnet and shared netowrk
4042 * structures
4043 * \param[out] ret_pond = a pointer to space for the pointer to
4044 * the structure to return
4045 *
4046 * \return
4047 * void
4048 */
4049 static void
4050 add_ipv6_pond_to_network(struct group *group,
4051 struct ipv6_pond **ret_pond) {
4052
4053 struct ipv6_pond *pond = NULL, *last = NULL;
4054 struct permit *p;
4055 isc_result_t status;
4056 struct shared_network *shared = group->subnet->shared_network;
4057
4058 for (pond = shared->ipv6_pond; pond; pond = pond->next) {
4059 if ((pond->group->statements == group->statements) &&
4060 (pond->prohibit_list == NULL) &&
4061 (pond->permit_list != NULL) &&
4062 (pond->permit_list->next == NULL) &&
4063 (pond->permit_list->type == permit_all_clients)) {
4064 ipv6_pond_reference(ret_pond, pond, MDL);
4065 return;
4066 }
4067 last = pond;
4068 }
4069
4070 /* no pond available, make one */
4071 status = ipv6_pond_allocate(&pond, MDL);
4072 if (status != ISC_R_SUCCESS)
4073 log_fatal ("no memory for ad-hoc ipv6 pond: %s",
4074 isc_result_totext (status));
4075 p = new_permit (MDL);
4076 if (p == NULL)
4077 log_fatal ("no memory for ad-hoc ipv6 permit.");
4078
4079 /* we permit all clients */
4080 p->type = permit_all_clients;
4081 pond->permit_list = p;
4082
4083 /* and attach the pond to the return argument and the shared network */
4084 ipv6_pond_reference(ret_pond, pond, MDL);
4085
4086 if (shared->ipv6_pond)
4087 ipv6_pond_reference(&last->next, pond, MDL);
4088 else
4089 ipv6_pond_reference(&shared->ipv6_pond, pond, MDL);
4090
4091 shared_network_reference(&pond->shared_network, shared, MDL);
4092 if (!clone_group (&pond->group, group, MDL))
4093 log_fatal ("no memory for anon pool group.");
4094
4095 ipv6_pond_dereference(&pond, MDL);
4096 return;
4097 }
4098
4099
4100 /* address-range6-declaration :== ip-address6 ip-address6 SEMI
4101 | ip-address6 SLASH number SEMI
4102 | ip-address6 [SLASH number] TEMPORARY SEMI */
4103
4104 void
4105 parse_address_range6(struct parse *cfile,
4106 struct group *group,
4107 struct ipv6_pond *inpond) {
4108 struct iaddr lo, hi;
4109 int bits;
4110 enum dhcp_token token;
4111 const char *val;
4112 struct iaddrcidrnetlist *nets, net;
4113 struct iaddrcidrnetlist *p;
4114 u_int16_t type = D6O_IA_NA;
4115 struct ipv6_pond *pond = NULL;
4116
4117 if (local_family != AF_INET6) {
4118 parse_warn(cfile, "range6 statement is only supported "
4119 "in DHCPv6 mode.");
4120 skip_to_semi(cfile);
4121 return;
4122 }
4123
4124 /* This is enforced by the caller, this is just a sanity check. */
4125 if (group->subnet == NULL)
4126 log_fatal("Impossible condition at %s:%d.", MDL);
4127
4128 /*
4129 * Read starting address.
4130 */
4131 if (!parse_ip6_addr(cfile, &lo)) {
4132 return;
4133 }
4134
4135 /* Make sure starting address is within the subnet */
4136 if (!addr_eq(group->subnet->net,
4137 subnet_number(lo, group->subnet->netmask))) {
4138 parse_warn(cfile, "range6 start address is outside the subnet");
4139 skip_to_semi(cfile);
4140 return;
4141 }
4142
4143 /*
4144 * zero out the net entry in case we use it
4145 */
4146 memset(&net, 0, sizeof(net));
4147 net.cidrnet.lo_addr = lo;
4148
4149 /*
4150 * See if we we're using range or CIDR notation or TEMPORARY
4151 */
4152 token = peek_token(&val, NULL, cfile);
4153 if (token == SLASH) {
4154 /*
4155 * '/' means CIDR notation, so read the bits we want.
4156 */
4157 skip_token(NULL, NULL, cfile);
4158 token = next_token(&val, NULL, cfile);
4159 if (token != NUMBER) {
4160 parse_warn(cfile, "expecting number");
4161 skip_to_semi(cfile);
4162 return;
4163 }
4164 net.cidrnet.bits = atoi(val);
4165 bits = net.cidrnet.bits;
4166 if ((bits < 0) || (bits > 128)) {
4167 parse_warn(cfile, "networks have 0 to 128 bits");
4168 skip_to_semi(cfile);
4169 return;
4170 }
4171 if (bits < group->subnet->prefix_len) {
4172 parse_warn(cfile,
4173 "network mask smaller than subnet mask");
4174 skip_to_semi(cfile);
4175 return;
4176 }
4177 if (!is_cidr_mask_valid(&net.cidrnet.lo_addr, bits)) {
4178 parse_warn(cfile, "network mask too short");
4179 skip_to_semi(cfile);
4180 return;
4181 }
4182 /*
4183 * can be temporary (RFC 4941 like)
4184 */
4185 token = peek_token(&val, NULL, cfile);
4186 if (token == TEMPORARY) {
4187 if (bits < 64)
4188 parse_warn(cfile, "temporary mask too short");
4189 if (bits == 128)
4190 parse_warn(cfile, "temporary singleton?");
4191 skip_token(NULL, NULL, cfile);
4192 type = D6O_IA_TA;
4193 }
4194
4195 nets = &net;
4196
4197 } else if (token == TEMPORARY) {
4198 /*
4199 * temporary (RFC 4941)
4200 */
4201 type = D6O_IA_TA;
4202 skip_token(NULL, NULL, cfile);
4203 net.cidrnet.bits = 64;
4204 if (!is_cidr_mask_valid(&net.cidrnet.lo_addr,
4205 net.cidrnet.bits)) {
4206 parse_warn(cfile, "network mask too short");
4207 skip_to_semi(cfile);
4208 return;
4209 }
4210
4211 nets = &net;
4212
4213 } else {
4214 /*
4215 * No '/', so we are looking for the end address of
4216 * the IPv6 pool.
4217 */
4218 if (!parse_ip6_addr(cfile, &hi)) {
4219 return;
4220 }
4221
4222 /* Make sure ending address is within the subnet */
4223 if (!addr_eq(group->subnet->net,
4224 subnet_number(hi, group->subnet->netmask))) {
4225 parse_warn(cfile,
4226 "range6 end address is outside the subnet");
4227 skip_to_semi(cfile);
4228 return;
4229 }
4230
4231 /*
4232 * Convert our range to a set of CIDR networks.
4233 */
4234 nets = NULL;
4235 if (range2cidr(&nets, &lo, &hi) != ISC_R_SUCCESS) {
4236 log_fatal("Error converting range to CIDR networks");
4237 }
4238
4239 }
4240
4241 /*
4242 * See if we have a pond for this set of pools.
4243 * If the caller supplied one we use it, otherwise
4244 * check the shared network
4245 */
4246
4247 if (inpond != NULL) {
4248 ipv6_pond_reference(&pond, inpond, MDL);
4249 } else {
4250 add_ipv6_pond_to_network(group, &pond);
4251 }
4252
4253 /* Now that we have a pond add the nets we have parsed */
4254 for (p=nets; p != NULL; p=p->next) {
4255 add_ipv6_pool_to_subnet(group->subnet, type,
4256 &p->cidrnet.lo_addr,
4257 p->cidrnet.bits, 128, pond);
4258 }
4259
4260 /* if we allocated a list free it now */
4261 if (nets != &net)
4262 free_iaddrcidrnetlist(&nets);
4263
4264 ipv6_pond_dereference(&pond, MDL);
4265
4266 token = next_token(NULL, NULL, cfile);
4267 if (token != SEMI) {
4268 parse_warn(cfile, "semicolon expected.");
4269 skip_to_semi(cfile);
4270 return;
4271 }
4272 }
4273
4274 /* prefix6-declaration :== ip-address6 ip-address6 SLASH number SEMI */
4275
4276 void
4277 parse_prefix6(struct parse *cfile,
4278 struct group *group,
4279 struct ipv6_pond *inpond) {
4280 struct iaddr lo, hi;
4281 int bits;
4282 enum dhcp_token token;
4283 const char *val;
4284 struct iaddrcidrnetlist *nets;
4285 struct iaddrcidrnetlist *p;
4286 struct ipv6_pond *pond = NULL;
4287
4288 if (local_family != AF_INET6) {
4289 parse_warn(cfile, "prefix6 statement is only supported "
4290 "in DHCPv6 mode.");
4291 skip_to_semi(cfile);
4292 return;
4293 }
4294
4295 /* This is enforced by the caller, so it's just a sanity check. */
4296 if (group->subnet == NULL)
4297 log_fatal("Impossible condition at %s:%d.", MDL);
4298
4299 /*
4300 * Read starting and ending address.
4301 */
4302 if (!parse_ip6_addr(cfile, &lo)) {
4303 return;
4304 }
4305
4306 #if 0
4307 /* Prefixes are not required to be within the subnet, but I'm not
4308 * entirely sure that we won't want to revive this code as a warning
4309 * in the future so I'm ifdeffing it
4310 */
4311
4312 /* Make sure starting prefix is within the subnet */
4313 if (!addr_eq(group->subnet->net,
4314 subnet_number(lo, group->subnet->netmask))) {
4315 parse_warn(cfile, "prefix6 start prefix"
4316 " is outside the subnet");
4317 skip_to_semi(cfile);
4318 return;
4319 }
4320 #endif
4321
4322 if (!parse_ip6_addr(cfile, &hi)) {
4323 return;
4324 }
4325
4326 #if 0
4327 /* Prefixes are not required to be within the subnet, but I'm not
4328 * entirely sure that we won't want to revive this code as a warning
4329 * in the future so I'm ifdeffing it
4330 */
4331
4332 /* Make sure ending prefix is within the subnet */
4333 if (!addr_eq(group->subnet->net,
4334 subnet_number(hi, group->subnet->netmask))) {
4335 parse_warn(cfile, "prefix6 end prefix"
4336 " is outside the subnet");
4337 skip_to_semi(cfile);
4338 return;
4339 }
4340 #endif
4341
4342 /*
4343 * Next is '/' number ';'.
4344 */
4345 token = next_token(NULL, NULL, cfile);
4346 if (token != SLASH) {
4347 parse_warn(cfile, "expecting '/'");
4348 if (token != SEMI)
4349 skip_to_semi(cfile);
4350 return;
4351 }
4352 token = next_token(&val, NULL, cfile);
4353 if (token != NUMBER) {
4354 parse_warn(cfile, "expecting number");
4355 if (token != SEMI)
4356 skip_to_semi(cfile);
4357 return;
4358 }
4359 bits = atoi(val);
4360 if ((bits <= 0) || (bits >= 128)) {
4361 parse_warn(cfile, "networks have 0 to 128 bits (exclusive)");
4362 return;
4363 }
4364
4365 #if 0
4366 /* Prefixes are not required to be within the subnet, but I'm not
4367 * entirely sure that we won't want to revive this code as a warning
4368 * in the future so I'm ifdeffing it
4369 */
4370
4371 if (bits < group->subnet->prefix_len) {
4372 parse_warn(cfile, "network mask smaller than subnet mask");
4373 skip_to_semi(cfile);
4374 return;
4375 }
4376 #endif
4377
4378 if (!is_cidr_mask_valid(&lo, bits) ||
4379 !is_cidr_mask_valid(&hi, bits)) {
4380 parse_warn(cfile, "network mask too short");
4381 skip_to_semi(cfile);
4382 return;
4383 }
4384 token = next_token(NULL, NULL, cfile);
4385 if (token != SEMI) {
4386 parse_warn(cfile, "semicolon expected.");
4387 skip_to_semi(cfile);
4388 return;
4389 }
4390
4391 /*
4392 * Convert our range to a set of CIDR networks.
4393 */
4394 nets = NULL;
4395 if (range2cidr(&nets, &lo, &hi) != ISC_R_SUCCESS) {
4396 log_fatal("Error converting prefix to CIDR");
4397 }
4398
4399 /*
4400 * See if we have a pond for this set of pools.
4401 * If the caller supplied one we use it, otherwise
4402 * check the shared network
4403 */
4404
4405 if (inpond != NULL) {
4406 ipv6_pond_reference(&pond, inpond, MDL);
4407 } else {
4408 add_ipv6_pond_to_network(group, &pond);
4409 }
4410
4411 for (p = nets; p != NULL; p = p->next) {
4412 /* Normalize and check. */
4413 if (p->cidrnet.bits == 128) {
4414 p->cidrnet.bits = bits;
4415 }
4416 if (p->cidrnet.bits > bits) {
4417 parse_warn(cfile, "impossible mask length");
4418 continue;
4419 }
4420 add_ipv6_pool_to_subnet(group->subnet, D6O_IA_PD,
4421 &p->cidrnet.lo_addr,
4422 p->cidrnet.bits, bits, pond);
4423 }
4424
4425 free_iaddrcidrnetlist(&nets);
4426 }
4427
4428 /* fixed-prefix6 :== ip6-address SLASH number SEMI */
4429
4430 void
4431 parse_fixed_prefix6(struct parse *cfile, struct host_decl *host_decl) {
4432 struct iaddrcidrnetlist *ia, **h;
4433 enum dhcp_token token;
4434 const char *val;
4435
4436 /*
4437 * Get the head of the fixed-prefix list.
4438 */
4439 h = &host_decl->fixed_prefix;
4440
4441 /*
4442 * Walk to the end.
4443 */
4444 while (*h != NULL) {
4445 h = &((*h)->next);
4446 }
4447
4448 /*
4449 * Allocate a new iaddrcidrnetlist structure.
4450 */
4451 ia = dmalloc(sizeof(*ia), MDL);
4452 if (!ia) {
4453 log_fatal("Out of memory");
4454 }
4455
4456 /*
4457 * Parse it.
4458 */
4459 if (!parse_ip6_addr(cfile, &ia->cidrnet.lo_addr)) {
4460 dfree(ia, MDL);
4461 return;
4462 }
4463 token = next_token(NULL, NULL, cfile);
4464 if (token != SLASH) {
4465 dfree(ia, MDL);
4466 parse_warn(cfile, "expecting '/'");
4467 if (token != SEMI)
4468 skip_to_semi(cfile);
4469 return;
4470 }
4471 token = next_token(&val, NULL, cfile);
4472 if (token != NUMBER) {
4473 dfree(ia, MDL);
4474 parse_warn(cfile, "expecting number");
4475 if (token != SEMI)
4476 skip_to_semi(cfile);
4477 return;
4478 }
4479 token = next_token(NULL, NULL, cfile);
4480 if (token != SEMI) {
4481 dfree(ia, MDL);
4482 parse_warn(cfile, "semicolon expected.");
4483 skip_to_semi(cfile);
4484 return;
4485 }
4486
4487 /*
4488 * Fill it.
4489 */
4490 ia->cidrnet.bits = atoi(val);
4491 if ((ia->cidrnet.bits < 0) || (ia->cidrnet.bits > 128)) {
4492 dfree(ia, MDL);
4493 parse_warn(cfile, "networks have 0 to 128 bits");
4494 return;
4495 }
4496 if (!is_cidr_mask_valid(&ia->cidrnet.lo_addr, ia->cidrnet.bits)) {
4497 dfree(ia, MDL);
4498 parse_warn(cfile, "network mask too short");
4499 return;
4500 }
4501
4502 /*
4503 * Store it.
4504 */
4505 *h = ia;
4506 return;
4507 }
4508
4509 /*!
4510 *
4511 * \brief Parse a pool6 statement
4512 *
4513 * Pool statements are used to group declarations and permit & deny information
4514 * with a specific address range. They must be declared within a shared network
4515 * or subnet and there may be multiple pools withing a shared network or subnet.
4516 * Each pool may have a different set of permit or deny options.
4517 *
4518 * \param[in] cfile = the configuration file being parsed
4519 * \param[in] group = the group structure for this pool
4520 * \param[in] type = the type of the enclosing statement. This must be
4521 * SUBNET_DECL for this function.
4522 *
4523 * \return
4524 * void - This function either parses the statement and updates the structures
4525 * or it generates an error message and possible halts the program if
4526 * it encounters a problem.
4527 */
4528 void parse_pool6_statement (cfile, group, type)
4529 struct parse *cfile;
4530 struct group *group;
4531 int type;
4532 {
4533 enum dhcp_token token;
4534 const char *val;
4535 int done = 0;
4536 struct ipv6_pond *pond, **p;
4537 int declaration = 0;
4538 isc_result_t status;
4539
4540 pond = NULL;
4541 status = ipv6_pond_allocate(&pond, MDL);
4542 if (status != ISC_R_SUCCESS)
4543 log_fatal("no memory for pool6: %s",
4544 isc_result_totext (status));
4545
4546 if (type == SUBNET_DECL)
4547 shared_network_reference(&pond->shared_network,
4548 group->subnet->shared_network,
4549 MDL);
4550 else {
4551 parse_warn(cfile, "pool6s are only valid inside "
4552 "subnet statements.");
4553 ipv6_pond_dereference(&pond, MDL);
4554 skip_to_semi(cfile);
4555 return;
4556 }
4557
4558 if (clone_group(&pond->group, group, MDL) == 0)
4559 log_fatal("can't clone pool6 group.");
4560
4561 if (parse_lbrace(cfile) == 0) {
4562 ipv6_pond_dereference(&pond, MDL);
4563 return;
4564 }
4565
4566 do {
4567 token = peek_token(&val, NULL, cfile);
4568 switch (token) {
4569 case RANGE6:
4570 skip_token(NULL, NULL, cfile);
4571 parse_address_range6(cfile, group, pond);
4572 break;
4573
4574 case PREFIX6:
4575 skip_token(NULL, NULL, cfile);
4576 parse_prefix6(cfile, group, pond);
4577 break;
4578
4579 case ALLOW:
4580 skip_token(NULL, NULL, cfile);
4581 get_permit(cfile, &pond->permit_list, 1,
4582 &pond->valid_from, &pond->valid_until);
4583 break;
4584
4585 case DENY:
4586 skip_token(NULL, NULL, cfile);
4587 get_permit(cfile, &pond->prohibit_list, 0,
4588 &pond->valid_from, &pond->valid_until);
4589 break;
4590
4591 case RBRACE:
4592 skip_token(&val, NULL, cfile);
4593 done = 1;
4594 break;
4595
4596 case END_OF_FILE:
4597 /*
4598 * We can get to END_OF_FILE if, for instance,
4599 * the parse_statement() reads all available tokens
4600 * and leaves us at the end.
4601 */
4602 parse_warn(cfile, "unexpected end of file");
4603 goto cleanup;
4604
4605 default:
4606 declaration = parse_statement(cfile, pond->group,
4607 POOL_DECL, NULL,
4608 declaration);
4609 break;
4610 }
4611 } while (!done);
4612
4613 /*
4614 * A possible optimization is to see if this pond can be merged into
4615 * an already existing pond. But I'll pass on that for now as we need
4616 * to repoint the leases to the other pond which is annoying. SAR
4617 */
4618
4619 /*
4620 * Add this pond to the list (will need updating if we add the
4621 * optimization).
4622 */
4623
4624 p = &pond->shared_network->ipv6_pond;
4625 for (; *p; p = &((*p)->next))
4626 ;
4627 ipv6_pond_reference(p, pond, MDL);
4628
4629 /* Don't allow a pool6 declaration with no addresses or
4630 prefixes, since it is probably a configuration error. */
4631 if (pond->ipv6_pools == NULL) {
4632 parse_warn (cfile, "Pool6 declaration with no %s.",
4633 "address range6 or prefix6");
4634 log_error ("Pool6 declarations must always contain at least");
4635 log_error ("one range6 or prefix6 statement.");
4636 }
4637
4638 cleanup:
4639 ipv6_pond_dereference(&pond, MDL);
4640 }
4641
4642
4643
4644 #endif /* DHCPv6 */
4645
4646 /* allow-deny-keyword :== BOOTP
4647 | BOOTING
4648 | DYNAMIC_BOOTP
4649 | UNKNOWN_CLIENTS */
4650
4651 int parse_allow_deny (oc, cfile, flag)
4652 struct option_cache **oc;
4653 struct parse *cfile;
4654 int flag;
4655 {
4656 enum dhcp_token token;
4657 const char *val;
4658 unsigned char rf = flag;
4659 unsigned code;
4660 struct option *option = NULL;
4661 struct expression *data = (struct expression *)0;
4662 int status;
4663
4664 if (!make_const_data (&data, &rf, 1, 0, 1, MDL))
4665 return 0;
4666
4667 token = next_token (&val, (unsigned *)0, cfile);
4668 switch (token) {
4669 case TOKEN_BOOTP:
4670 code = SV_ALLOW_BOOTP;
4671 break;
4672
4673 case BOOTING:
4674 code = SV_ALLOW_BOOTING;
4675 break;
4676
4677 case DYNAMIC_BOOTP:
4678 code = SV_DYNAMIC_BOOTP;
4679 break;
4680
4681 case UNKNOWN_CLIENTS:
4682 code = SV_BOOT_UNKNOWN_CLIENTS;
4683 break;
4684
4685 case DUPLICATES:
4686 code = SV_DUPLICATES;
4687 break;
4688
4689 case DECLINES:
4690 code= SV_DECLINES;
4691 break;
4692
4693 case CLIENT_UPDATES:
4694 code = SV_CLIENT_UPDATES;
4695 break;
4696
4697 case LEASEQUERY:
4698 code = SV_LEASEQUERY;
4699 break;
4700
4701 default:
4702 parse_warn (cfile, "expecting allow/deny key");
4703 skip_to_semi (cfile);
4704 expression_dereference (&data, MDL);
4705 return 0;
4706 }
4707 /* Reference on option is passed to option cache. */
4708 if (!option_code_hash_lookup(&option, server_universe.code_hash,
4709 &code, 0, MDL))
4710 log_fatal("Unable to find server option %u (%s:%d).",
4711 code, MDL);
4712 status = option_cache(oc, NULL, data, option, MDL);
4713 expression_dereference (&data, MDL);
4714 parse_semi (cfile);
4715 return status;
4716 }
4717
4718 void
4719 parse_ia_na_declaration(struct parse *cfile) {
4720 #if !defined(DHCPv6)
4721 parse_warn(cfile, "No DHCPv6 support.");
4722 skip_to_semi(cfile);
4723 #else /* defined(DHCPv6) */
4724 enum dhcp_token token;
4725 struct ia_xx *ia = NULL;
4726 const char *val;
4727 struct ia_xx *old_ia;
4728 u_int32_t iaid;
4729 struct iaddr iaddr;
4730 binding_state_t state;
4731 u_int32_t prefer;
4732 u_int32_t valid;
4733 TIME end_time;
4734 struct iasubopt *iaaddr;
4735 struct ipv6_pool *pool;
4736 char addr_buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
4737 isc_boolean_t newbinding;
4738 struct binding_scope *scope = NULL;
4739 struct binding *bnd;
4740 struct binding_value *nv = NULL;
4741 struct executable_statement *on_star[2] = {NULL, NULL};
4742 int lose, i;
4743
4744 if (local_family != AF_INET6) {
4745 parse_warn(cfile, "IA_NA is only supported in DHCPv6 mode.");
4746 skip_to_semi(cfile);
4747 return;
4748 }
4749
4750 if (!parse_iaid_duid(cfile, &ia, &iaid, MDL)) {
4751 return;
4752 }
4753
4754 ia->ia_type = D6O_IA_NA;
4755
4756 token = next_token(&val, NULL, cfile);
4757 if (token != LBRACE) {
4758 parse_warn(cfile, "corrupt lease file; expecting left brace");
4759 skip_to_semi(cfile);
4760 return;
4761 }
4762
4763 for (;;) {
4764 token = next_token(&val, NULL, cfile);
4765 if (token == RBRACE) break;
4766
4767 if (token == CLTT) {
4768 ia->cltt = parse_date (cfile);
4769 continue;
4770 }
4771
4772 if (token != IAADDR) {
4773 parse_warn(cfile, "corrupt lease file; "
4774 "expecting IAADDR or right brace");
4775 skip_to_semi(cfile);
4776 return;
4777 }
4778
4779 if (!parse_ip6_addr(cfile, &iaddr)) {
4780 parse_warn(cfile, "corrupt lease file; "
4781 "expecting IPv6 address");
4782 skip_to_semi(cfile);
4783 return;
4784 }
4785
4786 token = next_token(&val, NULL, cfile);
4787 if (token != LBRACE) {
4788 parse_warn(cfile, "corrupt lease file; "
4789 "expecting left brace");
4790 skip_to_semi(cfile);
4791 return;
4792 }
4793
4794 state = FTS_LAST+1;
4795 prefer = valid = 0;
4796 end_time = -1;
4797 for (;;) {
4798 token = next_token(&val, NULL, cfile);
4799 if (token == RBRACE) break;
4800
4801 switch(token) {
4802 case END_OF_FILE:
4803 /* We hit the end of file and don't know
4804 * what parts of the lease we may be missing
4805 * don't try to salvage the lease
4806 */
4807 parse_warn(cfile, "corrupt lease file; "
4808 "unexpected end of file");
4809 return;
4810
4811 /* Lease binding state. */
4812 case BINDING:
4813 token = next_token(&val, NULL, cfile);
4814 if (token != STATE) {
4815 parse_warn(cfile, "corrupt lease file; "
4816 "expecting state");
4817 skip_to_semi(cfile);
4818 return;
4819 }
4820 token = next_token(&val, NULL, cfile);
4821 switch (token) {
4822 case TOKEN_ABANDONED:
4823 state = FTS_ABANDONED;
4824 break;
4825 case TOKEN_FREE:
4826 state = FTS_FREE;
4827 break;
4828 case TOKEN_ACTIVE:
4829 state = FTS_ACTIVE;
4830 break;
4831 case TOKEN_EXPIRED:
4832 state = FTS_EXPIRED;
4833 break;
4834 case TOKEN_RELEASED:
4835 state = FTS_RELEASED;
4836 break;
4837 default:
4838 parse_warn(cfile,
4839 "corrupt lease "
4840 "file; "
4841 "expecting a "
4842 "binding state.");
4843 skip_to_semi(cfile);
4844 return;
4845 }
4846
4847 token = next_token(&val, NULL, cfile);
4848 if (token != SEMI) {
4849 parse_warn(cfile, "corrupt lease file; "
4850 "expecting "
4851 "semicolon.");
4852 }
4853 break;
4854
4855 /* Lease preferred lifetime. */
4856 case PREFERRED_LIFE:
4857 token = next_token(&val, NULL, cfile);
4858 if (token != NUMBER) {
4859 parse_warn(cfile, "%s is not a valid "
4860 "preferred time",
4861 val);
4862 skip_to_semi(cfile);
4863 continue;
4864 }
4865 prefer = atoi (val);
4866
4867 /*
4868 * Currently we peek for the semi-colon to
4869 * allow processing of older lease files that
4870 * don't have the semi-colon. Eventually we
4871 * should remove the peeking code.
4872 */
4873 token = peek_token(&val, NULL, cfile);
4874 if (token == SEMI) {
4875 skip_token(&val, NULL, cfile);
4876 } else {
4877 parse_warn(cfile,
4878 "corrupt lease file; "
4879 "expecting semicolon.");
4880 }
4881 break;
4882
4883 /* Lease valid lifetime. */
4884 case MAX_LIFE:
4885 token = next_token(&val, NULL, cfile);
4886 if (token != NUMBER) {
4887 parse_warn(cfile, "%s is not a valid "
4888 "max time",
4889 val);
4890 skip_to_semi(cfile);
4891 continue;
4892 }
4893 valid = atoi (val);
4894
4895 /*
4896 * Currently we peek for the semi-colon to
4897 * allow processing of older lease files that
4898 * don't have the semi-colon. Eventually we
4899 * should remove the peeking code.
4900 */
4901 token = peek_token(&val, NULL, cfile);
4902 if (token == SEMI) {
4903 skip_token(&val, NULL, cfile);
4904 } else {
4905 parse_warn(cfile,
4906 "corrupt lease file; "
4907 "expecting semicolon.");
4908 }
4909 break;
4910
4911 /* Lease expiration time. */
4912 case ENDS:
4913 end_time = parse_date(cfile);
4914 break;
4915
4916 /* Lease binding scopes. */
4917 case TOKEN_SET:
4918 token = next_token(&val, NULL, cfile);
4919 if ((token != NAME) &&
4920 (token != NUMBER_OR_NAME)) {
4921 parse_warn(cfile, "%s is not a valid "
4922 "variable name",
4923 val);
4924 skip_to_semi(cfile);
4925 continue;
4926 }
4927
4928 if (scope != NULL)
4929 bnd = find_binding(scope, val);
4930 else {
4931 if (!binding_scope_allocate(&scope,
4932 MDL)) {
4933 log_fatal("Out of memory for "
4934 "lease binding "
4935 "scope.");
4936 }
4937
4938 bnd = NULL;
4939 }
4940
4941 if (bnd == NULL) {
4942 bnd = dmalloc(sizeof(*bnd),
4943 MDL);
4944 if (bnd == NULL) {
4945 log_fatal("No memory for "
4946 "lease binding.");
4947 }
4948
4949 bnd->name = dmalloc(strlen(val) + 1,
4950 MDL);
4951 if (bnd->name == NULL) {
4952 log_fatal("No memory for "
4953 "binding name.");
4954 }
4955 strcpy(bnd->name, val);
4956
4957 newbinding = ISC_TRUE;
4958 } else {
4959 newbinding = ISC_FALSE;
4960 }
4961
4962 if (!binding_value_allocate(&nv, MDL)) {
4963 log_fatal("no memory for binding "
4964 "value.");
4965 }
4966
4967 token = next_token(NULL, NULL, cfile);
4968 if (token != EQUAL) {
4969 parse_warn(cfile, "expecting '=' in "
4970 "set statement.");
4971 goto binding_err;
4972 }
4973
4974 if (!parse_binding_value(cfile, nv)) {
4975 binding_err:
4976 binding_value_dereference(&nv, MDL);
4977 binding_scope_dereference(&scope, MDL);
4978 return;
4979 }
4980
4981 if (newbinding) {
4982 binding_value_reference(&bnd->value,
4983 nv, MDL);
4984 bnd->next = scope->bindings;
4985 scope->bindings = bnd;
4986 } else {
4987 binding_value_dereference(&bnd->value,
4988 MDL);
4989 binding_value_reference(&bnd->value,
4990 nv, MDL);
4991 }
4992
4993 binding_value_dereference(&nv, MDL);
4994 parse_semi(cfile);
4995 break;
4996
4997 case ON:
4998 lose = 0;
4999 /*
5000 * Depending on the user config we may
5001 * have one or two on statements. We
5002 * need to save information about both
5003 * of them until we allocate the
5004 * iasubopt to hold them.
5005 */
5006 if (on_star[0] == NULL) {
5007 if (!parse_on_statement (&on_star[0],
5008 cfile,
5009 &lose)) {
5010 parse_warn(cfile,
5011 "corrupt lease "
5012 "file; bad ON "
5013 "statement");
5014 skip_to_rbrace (cfile, 1);
5015 return;
5016 }
5017 } else {
5018 if (!parse_on_statement (&on_star[1],
5019 cfile,
5020 &lose)) {
5021 parse_warn(cfile,
5022 "corrupt lease "
5023 "file; bad ON "
5024 "statement");
5025 skip_to_rbrace (cfile, 1);
5026 return;
5027 }
5028 }
5029
5030 break;
5031
5032 default:
5033 parse_warn(cfile, "corrupt lease file; "
5034 "expecting ia_na contents, "
5035 "got '%s'", val);
5036 skip_to_semi(cfile);
5037 continue;
5038 }
5039 }
5040
5041 if (state == FTS_LAST+1) {
5042 parse_warn(cfile, "corrupt lease file; "
5043 "missing state in iaaddr");
5044 return;
5045 }
5046 if (end_time == -1) {
5047 parse_warn(cfile, "corrupt lease file; "
5048 "missing end time in iaaddr");
5049 return;
5050 }
5051
5052 iaaddr = NULL;
5053 if (iasubopt_allocate(&iaaddr, MDL) != ISC_R_SUCCESS) {
5054 log_fatal("Out of memory.");
5055 }
5056 memcpy(&iaaddr->addr, iaddr.iabuf, sizeof(iaaddr->addr));
5057 iaaddr->plen = 0;
5058 iaaddr->state = state;
5059 iaaddr->prefer = prefer;
5060 iaaddr->valid = valid;
5061 if (iaaddr->state == FTS_RELEASED)
5062 iaaddr->hard_lifetime_end_time = end_time;
5063
5064 if (scope != NULL) {
5065 binding_scope_reference(&iaaddr->scope, scope, MDL);
5066 binding_scope_dereference(&scope, MDL);
5067 }
5068
5069 /*
5070 * Check on both on statements. Because of how we write the
5071 * lease file we know which is which if we have two but it's
5072 * easier to write the code to be independent. We do assume
5073 * that the statements won't overlap.
5074 */
5075 for (i = 0;
5076 (i < 2) && on_star[i] != NULL ;
5077 i++) {
5078 if ((on_star[i]->data.on.evtypes & ON_EXPIRY) &&
5079 on_star[i]->data.on.statements) {
5080 executable_statement_reference
5081 (&iaaddr->on_star.on_expiry,
5082 on_star[i]->data.on.statements, MDL);
5083 }
5084 if ((on_star[i]->data.on.evtypes & ON_RELEASE) &&
5085 on_star[i]->data.on.statements) {
5086 executable_statement_reference
5087 (&iaaddr->on_star.on_release,
5088 on_star[i]->data.on.statements, MDL);
5089 }
5090 executable_statement_dereference (&on_star[i], MDL);
5091 }
5092
5093 /* find the pool this address is in */
5094 pool = NULL;
5095 if (find_ipv6_pool(&pool, D6O_IA_NA,
5096 &iaaddr->addr) != ISC_R_SUCCESS) {
5097 inet_ntop(AF_INET6, &iaaddr->addr,
5098 addr_buf, sizeof(addr_buf));
5099 log_error("No pool found for IA_NA address %s",
5100 addr_buf);
5101 iasubopt_dereference(&iaaddr, MDL);
5102 continue;
5103 }
5104 #ifdef EUI_64
5105 if ((pool->ipv6_pond->use_eui_64) &&
5106 (!valid_for_eui_64_pool(pool, &ia->iaid_duid, IAID_LEN,
5107 &iaaddr->addr))) {
5108 log_error("Non EUI-64 lease in EUI-64 pool: %s"
5109 " discarding it",
5110 pin6_addr(&iaaddr->addr));
5111 iasubopt_dereference(&iaaddr, MDL);
5112 continue;
5113 }
5114 #endif
5115
5116 /* remove old information */
5117 if (cleanup_lease6(ia_na_active, pool,
5118 iaaddr, ia) != ISC_R_SUCCESS) {
5119 inet_ntop(AF_INET6, &iaaddr->addr,
5120 addr_buf, sizeof(addr_buf));
5121 parse_warn(cfile, "duplicate na lease for address %s",
5122 addr_buf);
5123 }
5124
5125 /*
5126 * if we like the lease we add it to our various structues
5127 * otherwise we leave it and it will get cleaned when we
5128 * do the iasubopt_dereference.
5129 */
5130 if ((state == FTS_ACTIVE) || (state == FTS_ABANDONED)) {
5131 ia_add_iasubopt(ia, iaaddr, MDL);
5132 ia_reference(&iaaddr->ia, ia, MDL);
5133 add_lease6(pool, iaaddr, end_time);
5134 }
5135
5136 iasubopt_dereference(&iaaddr, MDL);
5137 ipv6_pool_dereference(&pool, MDL);
5138 }
5139
5140 /*
5141 * If we have an existing record for this IA_NA, remove it.
5142 */
5143 old_ia = NULL;
5144 if (ia_hash_lookup(&old_ia, ia_na_active,
5145 (unsigned char *)ia->iaid_duid.data,
5146 ia->iaid_duid.len, MDL)) {
5147 ia_hash_delete(ia_na_active,
5148 (unsigned char *)ia->iaid_duid.data,
5149 ia->iaid_duid.len, MDL);
5150 ia_dereference(&old_ia, MDL);
5151 }
5152
5153 /*
5154 * If we have addresses, add this, otherwise don't bother.
5155 */
5156 if (ia->num_iasubopt > 0) {
5157 ia_hash_add(ia_na_active,
5158 (unsigned char *)ia->iaid_duid.data,
5159 ia->iaid_duid.len, ia, MDL);
5160 }
5161 ia_dereference(&ia, MDL);
5162 #endif /* defined(DHCPv6) */
5163 }
5164
5165 void
5166 parse_ia_ta_declaration(struct parse *cfile) {
5167 #if !defined(DHCPv6)
5168 parse_warn(cfile, "No DHCPv6 support.");
5169 skip_to_semi(cfile);
5170 #else /* defined(DHCPv6) */
5171 enum dhcp_token token;
5172 struct ia_xx *ia = NULL;
5173 const char *val;
5174 struct ia_xx *old_ia;
5175 u_int32_t iaid;
5176 struct iaddr iaddr;
5177 binding_state_t state;
5178 u_int32_t prefer;
5179 u_int32_t valid;
5180 TIME end_time;
5181 struct iasubopt *iaaddr;
5182 struct ipv6_pool *pool;
5183 char addr_buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
5184 isc_boolean_t newbinding;
5185 struct binding_scope *scope = NULL;
5186 struct binding *bnd;
5187 struct binding_value *nv = NULL;
5188 struct executable_statement *on_star[2] = {NULL, NULL};
5189 int lose, i;
5190
5191 if (local_family != AF_INET6) {
5192 parse_warn(cfile, "IA_TA is only supported in DHCPv6 mode.");
5193 skip_to_semi(cfile);
5194 return;
5195 }
5196
5197 if (!parse_iaid_duid(cfile, &ia, &iaid, MDL)) {
5198 return;
5199 }
5200
5201 ia->ia_type = D6O_IA_TA;
5202
5203 token = next_token(&val, NULL, cfile);
5204 if (token != LBRACE) {
5205 parse_warn(cfile, "corrupt lease file; expecting left brace");
5206 skip_to_semi(cfile);
5207 return;
5208 }
5209
5210 for (;;) {
5211 token = next_token(&val, NULL, cfile);
5212 if (token == RBRACE) break;
5213
5214 if (token == CLTT) {
5215 ia->cltt = parse_date (cfile);
5216 continue;
5217 }
5218
5219 if (token != IAADDR) {
5220 parse_warn(cfile, "corrupt lease file; "
5221 "expecting IAADDR or right brace");
5222 skip_to_semi(cfile);
5223 return;
5224 }
5225
5226 if (!parse_ip6_addr(cfile, &iaddr)) {
5227 parse_warn(cfile, "corrupt lease file; "
5228 "expecting IPv6 address");
5229 skip_to_semi(cfile);
5230 return;
5231 }
5232
5233 token = next_token(&val, NULL, cfile);
5234 if (token != LBRACE) {
5235 parse_warn(cfile, "corrupt lease file; "
5236 "expecting left brace");
5237 skip_to_semi(cfile);
5238 return;
5239 }
5240
5241 state = FTS_LAST+1;
5242 prefer = valid = 0;
5243 end_time = -1;
5244 for (;;) {
5245 token = next_token(&val, NULL, cfile);
5246 if (token == RBRACE) break;
5247
5248 switch(token) {
5249 case END_OF_FILE:
5250 /* We hit the end of file and don't know
5251 * what parts of the lease we may be missing
5252 * don't try to salvage the lease
5253 */
5254 parse_warn(cfile, "corrupt lease file; "
5255 "unexpected end of file");
5256 return;
5257
5258 /* Lease binding state. */
5259 case BINDING:
5260 token = next_token(&val, NULL, cfile);
5261 if (token != STATE) {
5262 parse_warn(cfile, "corrupt lease file; "
5263 "expecting state");
5264 skip_to_semi(cfile);
5265 return;
5266 }
5267 token = next_token(&val, NULL, cfile);
5268 switch (token) {
5269 case TOKEN_ABANDONED:
5270 state = FTS_ABANDONED;
5271 break;
5272 case TOKEN_FREE:
5273 state = FTS_FREE;
5274 break;
5275 case TOKEN_ACTIVE:
5276 state = FTS_ACTIVE;
5277 break;
5278 case TOKEN_EXPIRED:
5279 state = FTS_EXPIRED;
5280 break;
5281 case TOKEN_RELEASED:
5282 state = FTS_RELEASED;
5283 break;
5284 default:
5285 parse_warn(cfile,
5286 "corrupt lease "
5287 "file; "
5288 "expecting a "
5289 "binding state.");
5290 skip_to_semi(cfile);
5291 return;
5292 }
5293
5294 token = next_token(&val, NULL, cfile);
5295 if (token != SEMI) {
5296 parse_warn(cfile, "corrupt lease file; "
5297 "expecting "
5298 "semicolon.");
5299 }
5300 break;
5301
5302 /* Lease preferred lifetime. */
5303 case PREFERRED_LIFE:
5304 token = next_token(&val, NULL, cfile);
5305 if (token != NUMBER) {
5306 parse_warn(cfile, "%s is not a valid "
5307 "preferred time",
5308 val);
5309 skip_to_semi(cfile);
5310 continue;
5311 }
5312 prefer = atoi (val);
5313
5314 /*
5315 * Currently we peek for the semi-colon to
5316 * allow processing of older lease files that
5317 * don't have the semi-colon. Eventually we
5318 * should remove the peeking code.
5319 */
5320 token = peek_token(&val, NULL, cfile);
5321 if (token == SEMI) {
5322 skip_token(&val, NULL, cfile);
5323 } else {
5324 parse_warn(cfile,
5325 "corrupt lease file; "
5326 "expecting semicolon.");
5327 }
5328 break;
5329
5330 /* Lease valid lifetime. */
5331 case MAX_LIFE:
5332 token = next_token(&val, NULL, cfile);
5333 if (token != NUMBER) {
5334 parse_warn(cfile, "%s is not a valid "
5335 "max time",
5336 val);
5337 skip_to_semi(cfile);
5338 continue;
5339 }
5340 valid = atoi (val);
5341
5342 /*
5343 * Currently we peek for the semi-colon to
5344 * allow processing of older lease files that
5345 * don't have the semi-colon. Eventually we
5346 * should remove the peeking code.
5347 */
5348 token = peek_token(&val, NULL, cfile);
5349 if (token == SEMI) {
5350 skip_token(&val, NULL, cfile);
5351 } else {
5352 parse_warn(cfile,
5353 "corrupt lease file; "
5354 "expecting semicolon.");
5355 }
5356 break;
5357
5358 /* Lease expiration time. */
5359 case ENDS:
5360 end_time = parse_date(cfile);
5361 break;
5362
5363 /* Lease binding scopes. */
5364 case TOKEN_SET:
5365 token = next_token(&val, NULL, cfile);
5366 if ((token != NAME) &&
5367 (token != NUMBER_OR_NAME)) {
5368 parse_warn(cfile, "%s is not a valid "
5369 "variable name",
5370 val);
5371 skip_to_semi(cfile);
5372 continue;
5373 }
5374
5375 if (scope != NULL)
5376 bnd = find_binding(scope, val);
5377 else {
5378 if (!binding_scope_allocate(&scope,
5379 MDL)) {
5380 log_fatal("Out of memory for "
5381 "lease binding "
5382 "scope.");
5383 }
5384
5385 bnd = NULL;
5386 }
5387
5388 if (bnd == NULL) {
5389 bnd = dmalloc(sizeof(*bnd),
5390 MDL);
5391 if (bnd == NULL) {
5392 log_fatal("No memory for "
5393 "lease binding.");
5394 }
5395
5396 bnd->name = dmalloc(strlen(val) + 1,
5397 MDL);
5398 if (bnd->name == NULL) {
5399 log_fatal("No memory for "
5400 "binding name.");
5401 }
5402 strcpy(bnd->name, val);
5403
5404 newbinding = ISC_TRUE;
5405 } else {
5406 newbinding = ISC_FALSE;
5407 }
5408
5409 if (!binding_value_allocate(&nv, MDL)) {
5410 log_fatal("no memory for binding "
5411 "value.");
5412 }
5413
5414 token = next_token(NULL, NULL, cfile);
5415 if (token != EQUAL) {
5416 parse_warn(cfile, "expecting '=' in "
5417 "set statement.");
5418 goto binding_err;
5419 }
5420
5421 if (!parse_binding_value(cfile, nv)) {
5422 binding_err:
5423 binding_value_dereference(&nv, MDL);
5424 binding_scope_dereference(&scope, MDL);
5425 return;
5426 }
5427
5428 if (newbinding) {
5429 binding_value_reference(&bnd->value,
5430 nv, MDL);
5431 bnd->next = scope->bindings;
5432 scope->bindings = bnd;
5433 } else {
5434 binding_value_dereference(&bnd->value,
5435 MDL);
5436 binding_value_reference(&bnd->value,
5437 nv, MDL);
5438 }
5439
5440 binding_value_dereference(&nv, MDL);
5441 parse_semi(cfile);
5442 break;
5443
5444 case ON:
5445 lose = 0;
5446 /*
5447 * Depending on the user config we may
5448 * have one or two on statements. We
5449 * need to save information about both
5450 * of them until we allocate the
5451 * iasubopt to hold them.
5452 */
5453 if (on_star[0] == NULL) {
5454 if (!parse_on_statement (&on_star[0],
5455 cfile,
5456 &lose)) {
5457 parse_warn(cfile,
5458 "corrupt lease "
5459 "file; bad ON "
5460 "statement");
5461 skip_to_rbrace (cfile, 1);
5462 return;
5463 }
5464 } else {
5465 if (!parse_on_statement (&on_star[1],
5466 cfile,
5467 &lose)) {
5468 parse_warn(cfile,
5469 "corrupt lease "
5470 "file; bad ON "
5471 "statement");
5472 skip_to_rbrace (cfile, 1);
5473 return;
5474 }
5475 }
5476
5477 break;
5478
5479 default:
5480 parse_warn(cfile, "corrupt lease file; "
5481 "expecting ia_ta contents, "
5482 "got '%s'", val);
5483 skip_to_semi(cfile);
5484 continue;
5485 }
5486 }
5487
5488 if (state == FTS_LAST+1) {
5489 parse_warn(cfile, "corrupt lease file; "
5490 "missing state in iaaddr");
5491 return;
5492 }
5493 if (end_time == -1) {
5494 parse_warn(cfile, "corrupt lease file; "
5495 "missing end time in iaaddr");
5496 return;
5497 }
5498
5499 iaaddr = NULL;
5500 if (iasubopt_allocate(&iaaddr, MDL) != ISC_R_SUCCESS) {
5501 log_fatal("Out of memory.");
5502 }
5503 memcpy(&iaaddr->addr, iaddr.iabuf, sizeof(iaaddr->addr));
5504 iaaddr->plen = 0;
5505 iaaddr->state = state;
5506 iaaddr->prefer = prefer;
5507 iaaddr->valid = valid;
5508 if (iaaddr->state == FTS_RELEASED)
5509 iaaddr->hard_lifetime_end_time = end_time;
5510
5511 if (scope != NULL) {
5512 binding_scope_reference(&iaaddr->scope, scope, MDL);
5513 binding_scope_dereference(&scope, MDL);
5514 }
5515
5516 /*
5517 * Check on both on statements. Because of how we write the
5518 * lease file we know which is which if we have two but it's
5519 * easier to write the code to be independent. We do assume
5520 * that the statements won't overlap.
5521 */
5522 for (i = 0;
5523 (i < 2) && on_star[i] != NULL ;
5524 i++) {
5525 if ((on_star[i]->data.on.evtypes & ON_EXPIRY) &&
5526 on_star[i]->data.on.statements) {
5527 executable_statement_reference
5528 (&iaaddr->on_star.on_expiry,
5529 on_star[i]->data.on.statements, MDL);
5530 }
5531 if ((on_star[i]->data.on.evtypes & ON_RELEASE) &&
5532 on_star[i]->data.on.statements) {
5533 executable_statement_reference
5534 (&iaaddr->on_star.on_release,
5535 on_star[i]->data.on.statements, MDL);
5536 }
5537 executable_statement_dereference (&on_star[i], MDL);
5538 }
5539
5540 /* find the pool this address is in */
5541 pool = NULL;
5542 if (find_ipv6_pool(&pool, D6O_IA_TA,
5543 &iaaddr->addr) != ISC_R_SUCCESS) {
5544 inet_ntop(AF_INET6, &iaaddr->addr,
5545 addr_buf, sizeof(addr_buf));
5546 log_error("No pool found for IA_TA address %s",
5547 addr_buf);
5548 iasubopt_dereference(&iaaddr, MDL);
5549 continue;
5550 }
5551
5552 /* remove old information */
5553 if (cleanup_lease6(ia_ta_active, pool,
5554 iaaddr, ia) != ISC_R_SUCCESS) {
5555 inet_ntop(AF_INET6, &iaaddr->addr,
5556 addr_buf, sizeof(addr_buf));
5557 parse_warn(cfile, "duplicate ta lease for address %s",
5558 addr_buf);
5559 }
5560
5561 /*
5562 * if we like the lease we add it to our various structues
5563 * otherwise we leave it and it will get cleaned when we
5564 * do the iasubopt_dereference.
5565 */
5566 if ((state == FTS_ACTIVE) || (state == FTS_ABANDONED)) {
5567 ia_add_iasubopt(ia, iaaddr, MDL);
5568 ia_reference(&iaaddr->ia, ia, MDL);
5569 add_lease6(pool, iaaddr, end_time);
5570 }
5571
5572 ipv6_pool_dereference(&pool, MDL);
5573 iasubopt_dereference(&iaaddr, MDL);
5574 }
5575
5576 /*
5577 * If we have an existing record for this IA_TA, remove it.
5578 */
5579 old_ia = NULL;
5580 if (ia_hash_lookup(&old_ia, ia_ta_active,
5581 (unsigned char *)ia->iaid_duid.data,
5582 ia->iaid_duid.len, MDL)) {
5583 ia_hash_delete(ia_ta_active,
5584 (unsigned char *)ia->iaid_duid.data,
5585 ia->iaid_duid.len, MDL);
5586 ia_dereference(&old_ia, MDL);
5587 }
5588
5589 /*
5590 * If we have addresses, add this, otherwise don't bother.
5591 */
5592 if (ia->num_iasubopt > 0) {
5593 ia_hash_add(ia_ta_active,
5594 (unsigned char *)ia->iaid_duid.data,
5595 ia->iaid_duid.len, ia, MDL);
5596 }
5597 ia_dereference(&ia, MDL);
5598 #endif /* defined(DHCPv6) */
5599 }
5600
5601 void
5602 parse_ia_pd_declaration(struct parse *cfile) {
5603 #if !defined(DHCPv6)
5604 parse_warn(cfile, "No DHCPv6 support.");
5605 skip_to_semi(cfile);
5606 #else /* defined(DHCPv6) */
5607 enum dhcp_token token;
5608 struct ia_xx *ia = NULL;
5609 const char *val;
5610 struct ia_xx *old_ia;
5611 u_int32_t iaid;
5612 struct iaddr iaddr;
5613 u_int8_t plen;
5614 binding_state_t state;
5615 u_int32_t prefer;
5616 u_int32_t valid;
5617 TIME end_time;
5618 struct iasubopt *iapref;
5619 struct ipv6_pool *pool;
5620 char addr_buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
5621 isc_boolean_t newbinding;
5622 struct binding_scope *scope = NULL;
5623 struct binding *bnd;
5624 struct binding_value *nv = NULL;
5625 struct executable_statement *on_star[2] = {NULL, NULL};
5626 int lose, i;
5627
5628 if (local_family != AF_INET6) {
5629 parse_warn(cfile, "IA_PD is only supported in DHCPv6 mode.");
5630 skip_to_semi(cfile);
5631 return;
5632 }
5633
5634 if (!parse_iaid_duid(cfile, &ia, &iaid, MDL)) {
5635 return;
5636 }
5637
5638 ia->ia_type = D6O_IA_PD;
5639
5640 token = next_token(&val, NULL, cfile);
5641 if (token != LBRACE) {
5642 parse_warn(cfile, "corrupt lease file; expecting left brace");
5643 skip_to_semi(cfile);
5644 return;
5645 }
5646
5647 for (;;) {
5648 token = next_token(&val, NULL, cfile);
5649 if (token == RBRACE) break;
5650
5651 if (token == CLTT) {
5652 ia->cltt = parse_date (cfile);
5653 continue;
5654 }
5655
5656 if (token != IAPREFIX) {
5657 parse_warn(cfile, "corrupt lease file; expecting "
5658 "IAPREFIX or right brace");
5659 skip_to_semi(cfile);
5660 return;
5661 }
5662
5663 if (!parse_ip6_prefix(cfile, &iaddr, &plen)) {
5664 parse_warn(cfile, "corrupt lease file; "
5665 "expecting IPv6 prefix");
5666 skip_to_semi(cfile);
5667 return;
5668 }
5669
5670 token = next_token(&val, NULL, cfile);
5671 if (token != LBRACE) {
5672 parse_warn(cfile, "corrupt lease file; "
5673 "expecting left brace");
5674 skip_to_semi(cfile);
5675 return;
5676 }
5677
5678 state = FTS_LAST+1;
5679 prefer = valid = 0;
5680 end_time = -1;
5681 for (;;) {
5682 token = next_token(&val, NULL, cfile);
5683 if (token == RBRACE) break;
5684
5685 switch(token) {
5686 case END_OF_FILE:
5687 /* We hit the end of file and don't know
5688 * what parts of the lease we may be missing
5689 * don't try to salvage the lease
5690 */
5691 parse_warn(cfile, "corrupt lease file; "
5692 "unexpected end of file");
5693 return;
5694
5695 /* Prefix binding state. */
5696 case BINDING:
5697 token = next_token(&val, NULL, cfile);
5698 if (token != STATE) {
5699 parse_warn(cfile, "corrupt lease file; "
5700 "expecting state");
5701 skip_to_semi(cfile);
5702 return;
5703 }
5704 token = next_token(&val, NULL, cfile);
5705 switch (token) {
5706 case TOKEN_ABANDONED:
5707 state = FTS_ABANDONED;
5708 break;
5709 case TOKEN_FREE:
5710 state = FTS_FREE;
5711 break;
5712 case TOKEN_ACTIVE:
5713 state = FTS_ACTIVE;
5714 break;
5715 case TOKEN_EXPIRED:
5716 state = FTS_EXPIRED;
5717 break;
5718 case TOKEN_RELEASED:
5719 state = FTS_RELEASED;
5720 break;
5721 default:
5722 parse_warn(cfile,
5723 "corrupt lease "
5724 "file; "
5725 "expecting a "
5726 "binding state.");
5727 skip_to_semi(cfile);
5728 return;
5729 }
5730
5731 token = next_token(&val, NULL, cfile);
5732 if (token != SEMI) {
5733 parse_warn(cfile, "corrupt lease file; "
5734 "expecting "
5735 "semicolon.");
5736 }
5737 break;
5738
5739 /* Lease preferred lifetime. */
5740 case PREFERRED_LIFE:
5741 token = next_token(&val, NULL, cfile);
5742 if (token != NUMBER) {
5743 parse_warn(cfile, "%s is not a valid "
5744 "preferred time",
5745 val);
5746 skip_to_semi(cfile);
5747 continue;
5748 }
5749 prefer = atoi (val);
5750
5751 /*
5752 * Currently we peek for the semi-colon to
5753 * allow processing of older lease files that
5754 * don't have the semi-colon. Eventually we
5755 * should remove the peeking code.
5756 */
5757 token = peek_token(&val, NULL, cfile);
5758 if (token == SEMI) {
5759 skip_token(&val, NULL, cfile);
5760 } else {
5761 parse_warn(cfile,
5762 "corrupt lease file; "
5763 "expecting semicolon.");
5764 }
5765 break;
5766
5767 /* Lease valid lifetime. */
5768 case MAX_LIFE:
5769 token = next_token(&val, NULL, cfile);
5770 if (token != NUMBER) {
5771 parse_warn(cfile, "%s is not a valid "
5772 "max time",
5773 val);
5774 skip_to_semi(cfile);
5775 continue;
5776 }
5777 valid = atoi (val);
5778
5779 /*
5780 * Currently we peek for the semi-colon to
5781 * allow processing of older lease files that
5782 * don't have the semi-colon. Eventually we
5783 * should remove the peeking code.
5784 */
5785 token = peek_token(&val, NULL, cfile);
5786 if (token == SEMI) {
5787 skip_token(&val, NULL, cfile);
5788 } else {
5789 parse_warn(cfile,
5790 "corrupt lease file; "
5791 "expecting semicolon.");
5792 }
5793 break;
5794
5795 /* Prefix expiration time. */
5796 case ENDS:
5797 end_time = parse_date(cfile);
5798 break;
5799
5800 /* Prefix binding scopes. */
5801 case TOKEN_SET:
5802 token = next_token(&val, NULL, cfile);
5803 if ((token != NAME) &&
5804 (token != NUMBER_OR_NAME)) {
5805 parse_warn(cfile, "%s is not a valid "
5806 "variable name",
5807 val);
5808 skip_to_semi(cfile);
5809 continue;
5810 }
5811
5812 if (scope != NULL)
5813 bnd = find_binding(scope, val);
5814 else {
5815 if (!binding_scope_allocate(&scope,
5816 MDL)) {
5817 log_fatal("Out of memory for "
5818 "lease binding "
5819 "scope.");
5820 }
5821
5822 bnd = NULL;
5823 }
5824
5825 if (bnd == NULL) {
5826 bnd = dmalloc(sizeof(*bnd),
5827 MDL);
5828 if (bnd == NULL) {
5829 log_fatal("No memory for "
5830 "prefix binding.");
5831 }
5832
5833 bnd->name = dmalloc(strlen(val) + 1,
5834 MDL);
5835 if (bnd->name == NULL) {
5836 log_fatal("No memory for "
5837 "binding name.");
5838 }
5839 strcpy(bnd->name, val);
5840
5841 newbinding = ISC_TRUE;
5842 } else {
5843 newbinding = ISC_FALSE;
5844 }
5845
5846 if (!binding_value_allocate(&nv, MDL)) {
5847 log_fatal("no memory for binding "
5848 "value.");
5849 }
5850
5851 token = next_token(NULL, NULL, cfile);
5852 if (token != EQUAL) {
5853 parse_warn(cfile, "expecting '=' in "
5854 "set statement.");
5855 goto binding_err;
5856 }
5857
5858 if (!parse_binding_value(cfile, nv)) {
5859 binding_err:
5860 binding_value_dereference(&nv, MDL);
5861 binding_scope_dereference(&scope, MDL);
5862 return;
5863 }
5864
5865 if (newbinding) {
5866 binding_value_reference(&bnd->value,
5867 nv, MDL);
5868 bnd->next = scope->bindings;
5869 scope->bindings = bnd;
5870 } else {
5871 binding_value_dereference(&bnd->value,
5872 MDL);
5873 binding_value_reference(&bnd->value,
5874 nv, MDL);
5875 }
5876
5877 binding_value_dereference(&nv, MDL);
5878 parse_semi(cfile);
5879 break;
5880
5881 case ON:
5882 lose = 0;
5883 /*
5884 * Depending on the user config we may
5885 * have one or two on statements. We
5886 * need to save information about both
5887 * of them until we allocate the
5888 * iasubopt to hold them.
5889 */
5890 if (on_star[0] == NULL) {
5891 if (!parse_on_statement (&on_star[0],
5892 cfile,
5893 &lose)) {
5894 parse_warn(cfile,
5895 "corrupt lease "
5896 "file; bad ON "
5897 "statement");
5898 skip_to_rbrace (cfile, 1);
5899 return;
5900 }
5901 } else {
5902 if (!parse_on_statement (&on_star[1],
5903 cfile,
5904 &lose)) {
5905 parse_warn(cfile,
5906 "corrupt lease "
5907 "file; bad ON "
5908 "statement");
5909 skip_to_rbrace (cfile, 1);
5910 return;
5911 }
5912 }
5913
5914 break;
5915
5916 default:
5917 parse_warn(cfile, "corrupt lease file; "
5918 "expecting ia_pd contents, "
5919 "got '%s'", val);
5920 skip_to_semi(cfile);
5921 continue;
5922 }
5923 }
5924
5925 if (state == FTS_LAST+1) {
5926 parse_warn(cfile, "corrupt lease file; "
5927 "missing state in iaprefix");
5928 return;
5929 }
5930 if (end_time == -1) {
5931 parse_warn(cfile, "corrupt lease file; "
5932 "missing end time in iaprefix");
5933 return;
5934 }
5935
5936 iapref = NULL;
5937 if (iasubopt_allocate(&iapref, MDL) != ISC_R_SUCCESS) {
5938 log_fatal("Out of memory.");
5939 }
5940 memcpy(&iapref->addr, iaddr.iabuf, sizeof(iapref->addr));
5941 iapref->plen = plen;
5942 iapref->state = state;
5943 iapref->prefer = prefer;
5944 iapref->valid = valid;
5945 if (iapref->state == FTS_RELEASED)
5946 iapref->hard_lifetime_end_time = end_time;
5947
5948 if (scope != NULL) {
5949 binding_scope_reference(&iapref->scope, scope, MDL);
5950 binding_scope_dereference(&scope, MDL);
5951 }
5952
5953 /*
5954 * Check on both on statements. Because of how we write the
5955 * lease file we know which is which if we have two but it's
5956 * easier to write the code to be independent. We do assume
5957 * that the statements won't overlap.
5958 */
5959 for (i = 0;
5960 (i < 2) && on_star[i] != NULL ;
5961 i++) {
5962 if ((on_star[i]->data.on.evtypes & ON_EXPIRY) &&
5963 on_star[i]->data.on.statements) {
5964 executable_statement_reference
5965 (&iapref->on_star.on_expiry,
5966 on_star[i]->data.on.statements, MDL);
5967 }
5968 if ((on_star[i]->data.on.evtypes & ON_RELEASE) &&
5969 on_star[i]->data.on.statements) {
5970 executable_statement_reference
5971 (&iapref->on_star.on_release,
5972 on_star[i]->data.on.statements, MDL);
5973 }
5974 executable_statement_dereference (&on_star[i], MDL);
5975 }
5976
5977 /* find the pool this address is in */
5978 pool = NULL;
5979 if (find_ipv6_pool(&pool, D6O_IA_PD,
5980 &iapref->addr) != ISC_R_SUCCESS) {
5981 inet_ntop(AF_INET6, &iapref->addr,
5982 addr_buf, sizeof(addr_buf));
5983 log_error("No pool found for prefix %s", addr_buf);
5984 iasubopt_dereference(&iapref, MDL);
5985 continue;
5986 }
5987
5988 /* remove old information */
5989 if (cleanup_lease6(ia_pd_active, pool,
5990 iapref, ia) != ISC_R_SUCCESS) {
5991 inet_ntop(AF_INET6, &iapref->addr,
5992 addr_buf, sizeof(addr_buf));
5993 parse_warn(cfile, "duplicate pd lease for address %s",
5994 addr_buf);
5995 }
5996
5997 /*
5998 * if we like the lease we add it to our various structues
5999 * otherwise we leave it and it will get cleaned when we
6000 * do the iasubopt_dereference.
6001 */
6002 if ((state == FTS_ACTIVE) || (state == FTS_ABANDONED)) {
6003 ia_add_iasubopt(ia, iapref, MDL);
6004 ia_reference(&iapref->ia, ia, MDL);
6005 add_lease6(pool, iapref, end_time);
6006 }
6007
6008 ipv6_pool_dereference(&pool, MDL);
6009 iasubopt_dereference(&iapref, MDL);
6010 }
6011
6012 /*
6013 * If we have an existing record for this IA_PD, remove it.
6014 */
6015 old_ia = NULL;
6016 if (ia_hash_lookup(&old_ia, ia_pd_active,
6017 (unsigned char *)ia->iaid_duid.data,
6018 ia->iaid_duid.len, MDL)) {
6019 ia_hash_delete(ia_pd_active,
6020 (unsigned char *)ia->iaid_duid.data,
6021 ia->iaid_duid.len, MDL);
6022 ia_dereference(&old_ia, MDL);
6023 }
6024
6025 /*
6026 * If we have prefixes, add this, otherwise don't bother.
6027 */
6028 if (ia->num_iasubopt > 0) {
6029 ia_hash_add(ia_pd_active,
6030 (unsigned char *)ia->iaid_duid.data,
6031 ia->iaid_duid.len, ia, MDL);
6032 }
6033 ia_dereference(&ia, MDL);
6034 #endif /* defined(DHCPv6) */
6035 }
6036
6037 #ifdef DHCPv6
6038 /*
6039 * When we parse a server-duid statement in a lease file, we are
6040 * looking at the saved server DUID from a previous run. In this case
6041 * we expect it to be followed by the binary representation of the
6042 * DUID stored in a string:
6043 *
6044 * server-duid "\000\001\000\001\015\221\034JRT\000\0224Y";
6045 *
6046 * OR as a hex string of digits:
6047 *
6048 * server-duid 00:01:00:01:1e:68:b3:db:0a:00:27:00:00:02;
6049 */
6050 void
6051 parse_server_duid(struct parse *cfile) {
6052 struct data_string duid;
6053 unsigned char bytes[128]; /* Maximum valid DUID is 128 */
6054 unsigned int len;
6055
6056 len = parse_X(cfile, bytes, sizeof(bytes));
6057 if (len <= 2) {
6058 parse_warn(cfile, "Invalid duid contents");
6059 skip_to_semi(cfile);
6060 return;
6061 }
6062
6063 memset(&duid, 0x0, sizeof(duid));
6064 if (!buffer_allocate(&duid.buffer, len, MDL)) {
6065 log_fatal("parse_server_duid: out of memory");
6066 }
6067
6068 memcpy(duid.buffer->data, bytes, len);
6069 duid.len = len;
6070 duid.data = duid.buffer->data;
6071
6072 set_server_duid(&duid);
6073 data_string_forget(&duid, MDL);
6074
6075 parse_semi(cfile);
6076 }
6077
6078 /*
6079 * When we parse a server-duid statement in a config file, we will
6080 * have the type of the server DUID to generate, and possibly the
6081 * actual value defined.
6082 *
6083 * server-duid llt;
6084 * server-duid llt ethernet|ieee802|fddi 213982198 00:16:6F:49:7D:9B;
6085 * server-duid ll;
6086 * server-duid ll ethernet|ieee802|fddi 00:16:6F:49:7D:9B;
6087 * server-duid en 2495 "enterprise-specific-identifier-1234";
6088 */
6089 void
6090 parse_server_duid_conf(struct parse *cfile) {
6091 enum dhcp_token token;
6092 const char *val;
6093 unsigned int len;
6094 u_int32_t enterprise_number;
6095 int ll_type;
6096 struct data_string ll_addr;
6097 u_int32_t llt_time;
6098 struct data_string duid;
6099 int duid_type_num;
6100
6101 /*
6102 * Consume the SERVER_DUID token.
6103 */
6104 skip_token(NULL, NULL, cfile);
6105
6106 /*
6107 * Obtain the DUID type.
6108 */
6109 token = next_token(&val, NULL, cfile);
6110
6111 /*
6112 * Enterprise is the easiest - enterprise number and raw data
6113 * are required.
6114 */
6115 if (token == EN) {
6116 /*
6117 * Get enterprise number and identifier.
6118 */
6119 token = next_token(&val, NULL, cfile);
6120 if (token != NUMBER) {
6121 parse_warn(cfile, "enterprise number expected");
6122 skip_to_semi(cfile);
6123 return;
6124 }
6125 enterprise_number = atoi(val);
6126
6127 token = next_token(&val, &len, cfile);
6128 if (token != STRING) {
6129 parse_warn(cfile, "identifier expected");
6130 skip_to_semi(cfile);
6131 return;
6132 }
6133
6134 /*
6135 * Save the DUID.
6136 */
6137 memset(&duid, 0, sizeof(duid));
6138 duid.len = 2 + 4 + len;
6139 if (!buffer_allocate(&duid.buffer, duid.len, MDL)) {
6140 log_fatal("Out of memory storing DUID");
6141 }
6142 duid.data = (unsigned char *)duid.buffer->data;
6143 putUShort(duid.buffer->data, DUID_EN);
6144 putULong(duid.buffer->data + 2, enterprise_number);
6145 memcpy(duid.buffer->data + 6, val, len);
6146
6147 set_server_duid(&duid);
6148 data_string_forget(&duid, MDL);
6149 }
6150
6151 /*
6152 * Next easiest is the link-layer DUID. It consists only of
6153 * the LL directive, or optionally the specific value to use.
6154 *
6155 * If we have LL only, then we set the type. If we have the
6156 * value, then we set the actual DUID.
6157 */
6158 else if (token == LL) {
6159 if (peek_token(NULL, NULL, cfile) == SEMI) {
6160 set_server_duid_type(DUID_LL);
6161 } else {
6162 /*
6163 * Get our hardware type and address.
6164 */
6165 token = next_token(NULL, NULL, cfile);
6166 switch (token) {
6167 case ETHERNET:
6168 ll_type = HTYPE_ETHER;
6169 break;
6170 case TOKEN_RING:
6171 ll_type = HTYPE_IEEE802;
6172 break;
6173 case TOKEN_FDDI:
6174 ll_type = HTYPE_FDDI;
6175 break;
6176 default:
6177 parse_warn(cfile, "hardware type expected");
6178 skip_to_semi(cfile);
6179 return;
6180 }
6181 memset(&ll_addr, 0, sizeof(ll_addr));
6182 if (!parse_cshl(&ll_addr, cfile)) {
6183 return;
6184 }
6185
6186 /*
6187 * Save the DUID.
6188 */
6189 memset(&duid, 0, sizeof(duid));
6190 duid.len = 2 + 2 + ll_addr.len;
6191 if (!buffer_allocate(&duid.buffer, duid.len, MDL)) {
6192 log_fatal("Out of memory storing DUID");
6193 }
6194 duid.data = (unsigned char *)duid.buffer->data;
6195 putUShort(duid.buffer->data, DUID_LL);
6196 putUShort(duid.buffer->data + 2, ll_type);
6197 memcpy(duid.buffer->data + 4,
6198 ll_addr.data, ll_addr.len);
6199
6200 set_server_duid(&duid);
6201 data_string_forget(&duid, MDL);
6202 data_string_forget(&ll_addr, MDL);
6203 }
6204 }
6205
6206 /*
6207 * Finally the link-layer DUID plus time. It consists only of
6208 * the LLT directive, or optionally the specific value to use.
6209 *
6210 * If we have LLT only, then we set the type. If we have the
6211 * value, then we set the actual DUID.
6212 */
6213 else if (token == LLT) {
6214 if (peek_token(NULL, NULL, cfile) == SEMI) {
6215 set_server_duid_type(DUID_LLT);
6216 } else {
6217 /*
6218 * Get our hardware type, timestamp, and address.
6219 */
6220 token = next_token(NULL, NULL, cfile);
6221 switch (token) {
6222 case ETHERNET:
6223 ll_type = HTYPE_ETHER;
6224 break;
6225 case TOKEN_RING:
6226 ll_type = HTYPE_IEEE802;
6227 break;
6228 case TOKEN_FDDI:
6229 ll_type = HTYPE_FDDI;
6230 break;
6231 default:
6232 parse_warn(cfile, "hardware type expected");
6233 skip_to_semi(cfile);
6234 return;
6235 }
6236
6237 token = next_token(&val, NULL, cfile);
6238 if (token != NUMBER) {
6239 parse_warn(cfile, "timestamp expected");
6240 skip_to_semi(cfile);
6241 return;
6242 }
6243 llt_time = atoi(val);
6244
6245 memset(&ll_addr, 0, sizeof(ll_addr));
6246 if (!parse_cshl(&ll_addr, cfile)) {
6247 return;
6248 }
6249
6250 /*
6251 * Save the DUID.
6252 */
6253 memset(&duid, 0, sizeof(duid));
6254 duid.len = 2 + 2 + 4 + ll_addr.len;
6255 if (!buffer_allocate(&duid.buffer, duid.len, MDL)) {
6256 log_fatal("Out of memory storing DUID");
6257 }
6258 duid.data = (unsigned char *)duid.buffer->data;
6259 putUShort(duid.buffer->data, DUID_LLT);
6260 putUShort(duid.buffer->data + 2, ll_type);
6261 putULong(duid.buffer->data + 4, llt_time);
6262 memcpy(duid.buffer->data + 8,
6263 ll_addr.data, ll_addr.len);
6264
6265 set_server_duid(&duid);
6266 data_string_forget(&duid, MDL);
6267 data_string_forget(&ll_addr, MDL);
6268 }
6269 }
6270
6271 /*
6272 * If users want they can use a number for DUID types.
6273 * This is useful for supporting future, not-yet-defined
6274 * DUID types.
6275 *
6276 * In this case, they have to put in the complete value.
6277 *
6278 * This also works for existing DUID types of course.
6279 */
6280 else if (token == NUMBER) {
6281 duid_type_num = atoi(val);
6282
6283 token = next_token(&val, &len, cfile);
6284 if (token != STRING) {
6285 parse_warn(cfile, "identifier expected");
6286 skip_to_semi(cfile);
6287 return;
6288 }
6289
6290 /*
6291 * Save the DUID.
6292 */
6293 memset(&duid, 0, sizeof(duid));
6294 duid.len = 2 + len;
6295 if (!buffer_allocate(&duid.buffer, duid.len, MDL)) {
6296 log_fatal("Out of memory storing DUID");
6297 }
6298 duid.data = (unsigned char *)duid.buffer->data;
6299 putUShort(duid.buffer->data, duid_type_num);
6300 memcpy(duid.buffer->data + 2, val, len);
6301
6302 set_server_duid(&duid);
6303 data_string_forget(&duid, MDL);
6304 }
6305
6306 /*
6307 * Anything else is an error.
6308 */
6309 else {
6310 parse_warn(cfile, "DUID type of LLT, EN, or LL expected");
6311 skip_to_semi(cfile);
6312 return;
6313 }
6314
6315 /*
6316 * Finally consume our trailing semicolon.
6317 */
6318 token = next_token(NULL, NULL, cfile);
6319 if (token != SEMI) {
6320 parse_warn(cfile, "semicolon expected");
6321 skip_to_semi(cfile);
6322 }
6323 }
6324
6325 /*!
6326 * \brief Creates a byte-order corrected uint32 from a buffer
6327 *
6328 * This function creates an integer value from a buffer, converting from
6329 * the byte order specified by authoring-byte-order to the current server's
6330 * byte order if they are different. The conversion works in either direction.
6331 *
6332 * If the parameter, authoring-byte-order hasn't yet been encountered we will
6333 * emit a warning and then default the byte order to match the current server's
6334 * byte order (i.e. no conversion will done).
6335 *
6336 * \param source buffer containing the "raw" four byte data
6337 * \return uint32_t containing the corrected value
6338 */
6339 uint32_t parse_byte_order_uint32(const void *source) {
6340 uint32_t value;
6341
6342 /* use memcpy to avoid any alignment monkey business */
6343 memcpy(&value, source, 4);
6344
6345 if (authoring_byte_order == 0) {
6346 log_error ("WARNING: "
6347 "authoring-byte-order not in the lease file.\n"
6348 "Assuming file byte order matches this server.\n");
6349 authoring_byte_order = DHCP_BYTE_ORDER;
6350 }
6351
6352 if (authoring_byte_order != DHCP_BYTE_ORDER) {
6353 value = (((value >> 24) & 0xff) | // move byte 3 to byte 0
6354 ((value << 8) & 0xff0000) | // move byte 1 to byte 2
6355 ((value >> 8) & 0xff00) | // move byte 2 to byte 1
6356 ((value << 24) & 0xff000000)); // byte 0 to byte 3
6357 }
6358
6359 return (value);
6360 }
6361
6362 /* !brief Parses an iaid/duid string into an iaid and struct ia
6363 *
6364 * Given a string containing the iaid-duid value read from the file,
6365 * and using the format specified by input lease-id-format, convert
6366 * it into an IAID value and an ia_xx struct.
6367 *
6368 * \param cfile - file being parsed
6369 * \param ia - pointer in which to store the allocated ia_xx struct
6370 * \param iaid - pointer in which to return the IAID value
6371 * \param file - source file name of invocation
6372 * \param line - line numbe of invocation
6373 *
6374 * \return 0 if parsing fails, non-zero otherwise
6375 */
6376 int
6377 parse_iaid_duid(struct parse* cfile, struct ia_xx** ia, u_int32_t *iaid,
6378 const char* file, int line) {
6379 unsigned char bytes[132]; /* Maximum valid IAID-DUID is 132 */
6380 unsigned int len;
6381
6382 if (!ia) {
6383 log_error("parse_iaid_duid: ia ptr cannot be null");
6384 return (0);
6385 }
6386
6387 *ia = NULL;
6388 len = parse_X(cfile, bytes, sizeof(bytes));
6389 if (len <= 5) {
6390 parse_warn(cfile, "corrupt lease file; "
6391 "iaid+ia_xx string too short");
6392 skip_to_semi(cfile);
6393 return (0);
6394 }
6395
6396 /* Extract the IAID from the front */
6397 *iaid = parse_byte_order_uint32(bytes);
6398
6399 /* Instantiate the ia_xx */
6400 if (ia_allocate(ia, *iaid, (const char*)bytes + 4, len - 4, file, line)
6401 != ISC_R_SUCCESS) {
6402 log_fatal("parse_iaid_duid:Out of memory.");
6403 }
6404
6405 return (1);
6406 }
6407
6408 #endif /* DHCPv6 */
6409