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