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