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