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