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