]> git.ipfire.org Git - thirdparty/dhcp.git/blob - server/confpars.c
Merged rt12324, DHCPLEASEQUERY.
[thirdparty/dhcp.git] / server / confpars.c
1 /* confpars.c
2
3 Parser for dhcpd config file... */
4
5 /*
6 * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1995-2003 by Internet Software Consortium
8 *
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 *
21 * Internet Systems Consortium, Inc.
22 * 950 Charter Street
23 * Redwood City, CA 94063
24 * <info@isc.org>
25 * http://www.isc.org/
26 *
27 * This software has been written for Internet Systems Consortium
28 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29 * To learn more about Internet Systems Consortium, see
30 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
31 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
32 * ``http://www.nominum.com''.
33 */
34
35 #ifndef lint
36 static char copyright[] =
37 "$Id: confpars.c,v 1.159 2006/07/25 13:26:00 shane Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n";
38 #endif /* not lint */
39
40 #include "dhcpd.h"
41
42 static TIME parsed_time;
43 static unsigned char global_host_once = 1;
44
45 #if defined (TRACING)
46 trace_type_t *trace_readconf_type;
47 trace_type_t *trace_readleases_type;
48
49 void parse_trace_setup ()
50 {
51 trace_readconf_type = trace_type_register ("readconf", (void *)0,
52 trace_conf_input,
53 trace_conf_stop, MDL);
54 trace_readleases_type = trace_type_register ("readleases", (void *)0,
55 trace_conf_input,
56 trace_conf_stop, MDL);
57 }
58 #endif
59
60 /* conf-file :== parameters declarations END_OF_FILE
61 parameters :== <nil> | parameter | parameters parameter
62 declarations :== <nil> | declaration | declarations declaration */
63
64 isc_result_t readconf ()
65 {
66 return read_conf_file (path_dhcpd_conf, root_group, ROOT_GROUP, 0);
67 }
68
69 isc_result_t read_conf_file (const char *filename, struct group *group,
70 int group_type, int leasep)
71 {
72 int file;
73 struct parse *cfile;
74 isc_result_t status;
75 #if defined (TRACING)
76 char *fbuf, *dbuf;
77 off_t flen;
78 int result;
79 unsigned tflen, ulen;
80 trace_type_t *ttype;
81
82 if (leasep)
83 ttype = trace_readleases_type;
84 else
85 ttype = trace_readconf_type;
86
87 /* If we're in playback, we need to snarf the contents of the
88 named file out of the playback file rather than trying to
89 open and read it. */
90 if (trace_playback ()) {
91 dbuf = (char *)0;
92 tflen = 0;
93 status = trace_get_file (ttype, filename, &tflen, &dbuf);
94 if (status != ISC_R_SUCCESS)
95 return status;
96 ulen = tflen;
97
98 /* What we get back is filename\0contents, where contents is
99 terminated just by the length. So we figure out the length
100 of the filename, and subtract that and the NUL from the
101 total length to get the length of the contents of the file.
102 We make fbuf a pointer to the contents of the file, and
103 leave dbuf as it is so we can free it later. */
104 tflen = strlen (dbuf);
105 ulen = ulen - tflen - 1;
106 fbuf = dbuf + tflen + 1;
107 goto memfile;
108 }
109 #endif
110
111 if ((file = open (filename, O_RDONLY)) < 0) {
112 if (leasep) {
113 log_error ("Can't open lease database %s: %m --",
114 path_dhcpd_db);
115 log_error (" check for failed database %s!",
116 "rewrite attempt");
117 log_error ("Please read the dhcpd.leases manual%s",
118 " page if you");
119 log_fatal ("don't know what to do about this.");
120 } else {
121 log_fatal ("Can't open %s: %m", filename);
122 }
123 }
124
125 cfile = (struct parse *)0;
126 #if defined (TRACING)
127 flen = lseek (file, (off_t)0, SEEK_END);
128 if (flen < 0) {
129 boom:
130 log_fatal ("Can't lseek on %s: %m", filename);
131 }
132 if (lseek (file, (off_t)0, SEEK_SET) < 0)
133 goto boom;
134 /* Can't handle files greater than 2^31-1. */
135 if (flen > 0x7FFFFFFFUL)
136 log_fatal ("%s: file is too long to buffer.", filename);
137 ulen = flen;
138
139 /* Allocate a buffer that will be what's written to the tracefile,
140 and also will be what we parse from. */
141 tflen = strlen (filename);
142 dbuf = dmalloc (ulen + tflen + 1, MDL);
143 if (!dbuf)
144 log_fatal ("No memory for %s (%d bytes)",
145 filename, ulen);
146
147 /* Copy the name into the beginning, nul-terminated. */
148 strcpy (dbuf, filename);
149
150 /* Load the file in after the NUL. */
151 fbuf = dbuf + tflen + 1;
152 result = read (file, fbuf, ulen);
153 if (result < 0)
154 log_fatal ("Can't read in %s: %m", filename);
155 if (result != ulen)
156 log_fatal ("%s: short read of %d bytes instead of %d.",
157 filename, ulen, result);
158 close (file);
159 memfile:
160 /* If we're recording, write out the filename and file contents. */
161 if (trace_record ())
162 trace_write_packet (ttype, ulen + tflen + 1, dbuf, MDL);
163 new_parse (&cfile, -1, fbuf, ulen, filename, 0); /* XXX */
164 #else
165 new_parse (&cfile, file, (char *)0, 0, filename, 0);
166 #endif
167 if (leasep)
168 status = lease_file_subparse (cfile);
169 else
170 status = conf_file_subparse (cfile, group, group_type);
171 end_parse (&cfile);
172 #if defined (TRACING)
173 dfree (dbuf, MDL);
174 #endif
175 return status;
176 }
177
178 #if defined (TRACING)
179 void trace_conf_input (trace_type_t *ttype, unsigned len, char *data)
180 {
181 char *fbuf;
182 unsigned flen;
183 unsigned tflen;
184 struct parse *cfile = (struct parse *)0;
185 static int postconf_initialized;
186 static int leaseconf_initialized;
187
188 /* Do what's done above, except that we don't have to read in the
189 data, because it's already been read for us. */
190 tflen = strlen (data);
191 flen = len - tflen - 1;
192 fbuf = data + tflen + 1;
193
194 /* If we're recording, write out the filename and file contents. */
195 if (trace_record ())
196 trace_write_packet (ttype, len, data, MDL);
197 new_parse (&cfile, -1, fbuf, flen, data, 0);
198 if (ttype == trace_readleases_type)
199 lease_file_subparse (cfile);
200 else
201 conf_file_subparse (cfile, root_group, ROOT_GROUP);
202 end_parse (&cfile);
203
204 /* Postconfiguration needs to be done after the config file
205 has been loaded. */
206 if (!postconf_initialized && ttype == trace_readconf_type) {
207 postconf_initialization (0);
208 postconf_initialized = 1;
209 }
210
211 if (!leaseconf_initialized && ttype == trace_readleases_type) {
212 db_startup (0);
213 leaseconf_initialized = 1;
214 postdb_startup ();
215 }
216 }
217
218 void trace_conf_stop (trace_type_t *ttype) { }
219 #endif
220
221 /* conf-file :== parameters declarations END_OF_FILE
222 parameters :== <nil> | parameter | parameters parameter
223 declarations :== <nil> | declaration | declarations declaration */
224
225 isc_result_t conf_file_subparse (struct parse *cfile, struct group *group,
226 int group_type)
227 {
228 const char *val;
229 enum dhcp_token token;
230 int declaration = 0;
231 int status;
232
233 do {
234 token = peek_token (&val, (unsigned *)0, cfile);
235 if (token == END_OF_FILE)
236 break;
237 declaration = parse_statement (cfile, group, group_type,
238 (struct host_decl *)0,
239 declaration);
240 } while (1);
241 token = next_token (&val, (unsigned *)0, cfile);
242
243 status = cfile -> warnings_occurred ? ISC_R_BADPARSE : ISC_R_SUCCESS;
244 return status;
245 }
246
247 /* lease-file :== lease-declarations END_OF_FILE
248 lease-statments :== <nil>
249 | lease-declaration
250 | lease-declarations lease-declaration */
251
252 isc_result_t lease_file_subparse (struct parse *cfile)
253 {
254 const char *val;
255 enum dhcp_token token;
256 isc_result_t status;
257
258 do {
259 token = next_token (&val, (unsigned *)0, cfile);
260 if (token == END_OF_FILE)
261 break;
262 if (token == LEASE) {
263 struct lease *lease = (struct lease *)0;
264 if (parse_lease_declaration (&lease, cfile)) {
265 enter_lease (lease);
266 lease_dereference (&lease, MDL);
267 } else
268 parse_warn (cfile,
269 "possibly corrupt lease file");
270 } else if (token == CLASS) {
271 parse_class_declaration(0, cfile, root_group,
272 CLASS_TYPE_CLASS);
273 } else if (token == SUBCLASS) {
274 parse_class_declaration(0, cfile, root_group,
275 CLASS_TYPE_SUBCLASS);
276 } else if (token == HOST) {
277 parse_host_declaration (cfile, root_group);
278 } else if (token == GROUP) {
279 parse_group_declaration (cfile, root_group);
280 #if defined (FAILOVER_PROTOCOL)
281 } else if (token == FAILOVER) {
282 parse_failover_state_declaration
283 (cfile, (dhcp_failover_state_t *)0);
284 #endif
285 } else {
286 log_error ("Corrupt lease file - possible data loss!");
287 skip_to_semi (cfile);
288 }
289
290 } while (1);
291
292 status = cfile -> warnings_occurred ? ISC_R_BADPARSE : ISC_R_SUCCESS;
293 return status;
294 }
295
296 /* statement :== parameter | declaration
297
298 parameter :== DEFAULT_LEASE_TIME lease_time
299 | MAX_LEASE_TIME lease_time
300 | DYNAMIC_BOOTP_LEASE_CUTOFF date
301 | DYNAMIC_BOOTP_LEASE_LENGTH lease_time
302 | BOOT_UNKNOWN_CLIENTS boolean
303 | ONE_LEASE_PER_CLIENT boolean
304 | GET_LEASE_HOSTNAMES boolean
305 | USE_HOST_DECL_NAME boolean
306 | NEXT_SERVER ip-addr-or-hostname SEMI
307 | option_parameter
308 | SERVER-IDENTIFIER ip-addr-or-hostname SEMI
309 | FILENAME string-parameter
310 | SERVER_NAME string-parameter
311 | hardware-parameter
312 | fixed-address-parameter
313 | ALLOW allow-deny-keyword
314 | DENY allow-deny-keyword
315 | USE_LEASE_ADDR_FOR_DEFAULT_ROUTE boolean
316 | AUTHORITATIVE
317 | NOT AUTHORITATIVE
318
319 declaration :== host-declaration
320 | group-declaration
321 | shared-network-declaration
322 | subnet-declaration
323 | VENDOR_CLASS class-declaration
324 | USER_CLASS class-declaration
325 | RANGE address-range-declaration */
326
327 int parse_statement (cfile, group, type, host_decl, declaration)
328 struct parse *cfile;
329 struct group *group;
330 int type;
331 struct host_decl *host_decl;
332 int declaration;
333 {
334 enum dhcp_token token;
335 const char *val;
336 struct shared_network *share;
337 char *t, *n;
338 struct expression *expr;
339 struct data_string data;
340 struct hardware hardware;
341 struct executable_statement *et, *ep;
342 struct option *option = NULL;
343 struct option_cache *cache;
344 int lose;
345 struct data_string key_id;
346 int known;
347 isc_result_t status;
348 unsigned code;
349
350 token = peek_token (&val, (unsigned *)0, cfile);
351
352 switch (token) {
353 case INCLUDE:
354 next_token (&val, (unsigned *)0, cfile);
355 token = next_token (&val, (unsigned *)0, cfile);
356 if (token != STRING) {
357 parse_warn (cfile, "filename string expected.");
358 skip_to_semi (cfile);
359 } else {
360 status = read_conf_file (val, group, type, 0);
361 if (status != ISC_R_SUCCESS)
362 parse_warn (cfile, "%s: bad parse.", val);
363 parse_semi (cfile);
364 }
365 return 1;
366
367 case HOST:
368 next_token (&val, (unsigned *)0, cfile);
369 if (type != HOST_DECL && type != CLASS_DECL) {
370 if (global_host_once &&
371 (type == SUBNET_DECL || type == SHARED_NET_DECL)) {
372 global_host_once = 0;
373 log_error("WARNING: Host declarations are "
374 "global. They are not limited to "
375 "the scope you declared them in.");
376 }
377
378 parse_host_declaration (cfile, group);
379 } else {
380 parse_warn (cfile,
381 "host declarations not allowed here.");
382 skip_to_semi (cfile);
383 }
384 return 1;
385
386 case GROUP:
387 next_token (&val, (unsigned *)0, cfile);
388 if (type != HOST_DECL && type != CLASS_DECL)
389 parse_group_declaration (cfile, group);
390 else {
391 parse_warn (cfile,
392 "group declarations not allowed here.");
393 skip_to_semi (cfile);
394 }
395 return 1;
396
397 case SHARED_NETWORK:
398 next_token (&val, (unsigned *)0, cfile);
399 if (type == SHARED_NET_DECL ||
400 type == HOST_DECL ||
401 type == SUBNET_DECL ||
402 type == CLASS_DECL) {
403 parse_warn (cfile, "shared-network parameters not %s.",
404 "allowed here");
405 skip_to_semi (cfile);
406 break;
407 }
408
409 parse_shared_net_declaration (cfile, group);
410 return 1;
411
412 case SUBNET:
413 next_token (&val, (unsigned *)0, cfile);
414 if (type == HOST_DECL || type == SUBNET_DECL ||
415 type == CLASS_DECL) {
416 parse_warn (cfile,
417 "subnet declarations not allowed here.");
418 skip_to_semi (cfile);
419 return 1;
420 }
421
422 /* If we're in a subnet declaration, just do the parse. */
423 if (group -> shared_network) {
424 parse_subnet_declaration (cfile,
425 group -> shared_network);
426 break;
427 }
428
429 /* Otherwise, cons up a fake shared network structure
430 and populate it with the lone subnet... */
431
432 share = (struct shared_network *)0;
433 status = shared_network_allocate (&share, MDL);
434 if (status != ISC_R_SUCCESS)
435 log_fatal ("Can't allocate shared subnet: %s",
436 isc_result_totext (status));
437 if (!clone_group (&share -> group, group, MDL))
438 log_fatal ("Can't allocate group for shared net");
439 shared_network_reference (&share -> group -> shared_network,
440 share, MDL);
441
442 parse_subnet_declaration (cfile, share);
443
444 /* share -> subnets is the subnet we just parsed. */
445 if (share -> subnets) {
446 interface_reference (&share -> interface,
447 share -> subnets -> interface,
448 MDL);
449
450 /* Make the shared network name from network number. */
451 n = piaddrmask (share -> subnets -> net,
452 share -> subnets -> netmask, MDL);
453 share -> name = n;
454
455 /* Copy the authoritative parameter from the subnet,
456 since there is no opportunity to declare it here. */
457 share -> group -> authoritative =
458 share -> subnets -> group -> authoritative;
459 enter_shared_network (share);
460 }
461 shared_network_dereference (&share, MDL);
462 return 1;
463
464 case VENDOR_CLASS:
465 next_token (&val, (unsigned *)0, cfile);
466 if (type == CLASS_DECL) {
467 parse_warn (cfile,
468 "class declarations not allowed here.");
469 skip_to_semi (cfile);
470 break;
471 }
472 parse_class_declaration(NULL, cfile, group, CLASS_TYPE_VENDOR);
473 return 1;
474
475 case USER_CLASS:
476 next_token (&val, (unsigned *)0, cfile);
477 if (type == CLASS_DECL) {
478 parse_warn (cfile,
479 "class declarations not allowed here.");
480 skip_to_semi (cfile);
481 break;
482 }
483 parse_class_declaration(NULL, cfile, group, CLASS_TYPE_USER);
484 return 1;
485
486 case CLASS:
487 next_token (&val, (unsigned *)0, cfile);
488 if (type == CLASS_DECL) {
489 parse_warn (cfile,
490 "class declarations not allowed here.");
491 skip_to_semi (cfile);
492 break;
493 }
494 parse_class_declaration(NULL, cfile, group, CLASS_TYPE_CLASS);
495 return 1;
496
497 case SUBCLASS:
498 next_token (&val, (unsigned *)0, cfile);
499 if (type == CLASS_DECL) {
500 parse_warn (cfile,
501 "class declarations not allowed here.");
502 skip_to_semi (cfile);
503 break;
504 }
505 parse_class_declaration(NULL, cfile, group,
506 CLASS_TYPE_SUBCLASS);
507 return 1;
508
509 case HARDWARE:
510 next_token (&val, (unsigned *)0, cfile);
511 memset (&hardware, 0, sizeof hardware);
512 if (host_decl && memcmp(&hardware, &(host_decl->interface),
513 sizeof(hardware)) != 0) {
514 parse_warn(cfile, "Host %s hardware address already "
515 "configured.", host_decl->name);
516 break;
517 }
518
519 parse_hardware_param (cfile, &hardware);
520 if (host_decl)
521 host_decl -> interface = hardware;
522 else
523 parse_warn (cfile, "hardware address parameter %s",
524 "not allowed here.");
525 break;
526
527 case FIXED_ADDR:
528 next_token (&val, (unsigned *)0, cfile);
529 cache = (struct option_cache *)0;
530 if (parse_fixed_addr_param (&cache, cfile)) {
531 if (host_decl) {
532 if (host_decl -> fixed_addr) {
533 option_cache_dereference (&cache, MDL);
534 parse_warn (cfile,
535 "Only one fixed address%s",
536 " declaration per host.");
537 } else {
538 host_decl -> fixed_addr = cache;
539 }
540 } else {
541 parse_warn (cfile,
542 "fixed-address parameter not %s",
543 "allowed here.");
544 option_cache_dereference (&cache, MDL);
545 }
546 }
547 break;
548
549 case POOL:
550 next_token (&val, (unsigned *)0, cfile);
551 if (type != SUBNET_DECL && type != SHARED_NET_DECL) {
552 parse_warn (cfile, "pool declared outside of network");
553 }
554 if (type == POOL_DECL) {
555 parse_warn (cfile, "pool declared within pool.");
556 }
557 parse_pool_statement (cfile, group, type);
558 return declaration;
559
560 case RANGE:
561 next_token (&val, (unsigned *)0, cfile);
562 if (type != SUBNET_DECL || !group -> subnet) {
563 parse_warn (cfile,
564 "range declaration not allowed here.");
565 skip_to_semi (cfile);
566 return declaration;
567 }
568 parse_address_range (cfile, group, type, (struct pool *)0,
569 (struct lease **)0);
570 return declaration;
571
572 case TOKEN_NOT:
573 token = next_token (&val, (unsigned *)0, cfile);
574 token = next_token (&val, (unsigned *)0, cfile);
575 switch (token) {
576 case AUTHORITATIVE:
577 group -> authoritative = 0;
578 goto authoritative;
579 default:
580 parse_warn (cfile, "expecting assertion");
581 skip_to_semi (cfile);
582 break;
583 }
584 break;
585 case AUTHORITATIVE:
586 token = next_token (&val, (unsigned *)0, cfile);
587 group -> authoritative = 1;
588 authoritative:
589 if (type == HOST_DECL)
590 parse_warn (cfile, "authority makes no sense here.");
591 parse_semi (cfile);
592 break;
593
594 /* "server-identifier" is a special hack, equivalent to
595 "option dhcp-server-identifier". */
596 case SERVER_IDENTIFIER:
597 code = DHO_DHCP_SERVER_IDENTIFIER;
598 if (!option_code_hash_lookup(&option, dhcp_universe.code_hash,
599 &code, 0, MDL))
600 log_fatal("Server identifier not in hash (%s:%d).",
601 MDL);
602 token = next_token (&val, (unsigned *)0, cfile);
603 goto finish_option;
604
605 case OPTION:
606 token = next_token (&val, (unsigned *)0, cfile);
607 token = peek_token (&val, (unsigned *)0, cfile);
608 if (token == SPACE) {
609 if (type != ROOT_GROUP) {
610 parse_warn (cfile,
611 "option space definitions %s",
612 "may not be scoped.");
613 skip_to_semi (cfile);
614 break;
615 }
616 parse_option_space_decl (cfile);
617 return declaration;
618 }
619
620 known = 0;
621 status = parse_option_name(cfile, 1, &known, &option);
622 if (status == ISC_R_SUCCESS) {
623 token = peek_token (&val, (unsigned *)0, cfile);
624 if (token == CODE) {
625 if (type != ROOT_GROUP) {
626 parse_warn (cfile,
627 "option definitions%s",
628 " may not be scoped.");
629 skip_to_semi (cfile);
630 option_dereference(&option, MDL);
631 break;
632 }
633 next_token (&val, (unsigned *)0, cfile);
634 parse_option_code_definition(cfile, option);
635 option_dereference(&option, MDL);
636 return declaration;
637 }
638
639 /* If this wasn't an option code definition, don't
640 allow an unknown option. */
641 if (!known) {
642 parse_warn (cfile, "unknown option %s.%s",
643 option -> universe -> name,
644 option -> name);
645 skip_to_semi (cfile);
646 option_dereference(&option, MDL);
647 return declaration;
648 }
649
650 finish_option:
651 et = (struct executable_statement *)0;
652 if (!parse_option_statement
653 (&et, cfile, 1, option,
654 supersede_option_statement))
655 return declaration;
656 option_dereference(&option, MDL);
657 goto insert_statement;
658 } else
659 return declaration;
660
661 break;
662
663 case FAILOVER:
664 if (type != ROOT_GROUP && type != SHARED_NET_DECL) {
665 parse_warn (cfile, "failover peers may only be %s",
666 "defined in shared-network");
667 log_error ("declarations and the outer scope.");
668 skip_to_semi (cfile);
669 break;
670 }
671 token = next_token (&val, (unsigned *)0, cfile);
672 #if defined (FAILOVER_PROTOCOL)
673 parse_failover_peer (cfile, group, type);
674 #else
675 parse_warn (cfile, "No failover support.");
676 skip_to_semi (cfile);
677 #endif
678 break;
679
680 default:
681 et = (struct executable_statement *)0;
682 lose = 0;
683 if (!parse_executable_statement (&et, cfile, &lose,
684 context_any)) {
685 if (!lose) {
686 if (declaration)
687 parse_warn (cfile,
688 "expecting a declaration");
689 else
690 parse_warn (cfile,
691 "expecting a parameter %s",
692 "or declaration");
693 skip_to_semi (cfile);
694 }
695 return declaration;
696 }
697 if (!et)
698 return declaration;
699 insert_statement:
700 if (group -> statements) {
701 int multi = 0;
702
703 /* If this set of statements is only referenced
704 by this group, just add the current statement
705 to the end of the chain. */
706 for (ep = group -> statements; ep -> next;
707 ep = ep -> next)
708 if (ep -> refcnt > 1) /* XXX */
709 multi = 1;
710 if (!multi) {
711 executable_statement_reference (&ep -> next,
712 et, MDL);
713 executable_statement_dereference (&et, MDL);
714 return declaration;
715 }
716
717 /* Otherwise, make a parent chain, and put the
718 current group statements first and the new
719 statement in the next pointer. */
720 ep = (struct executable_statement *)0;
721 if (!executable_statement_allocate (&ep, MDL))
722 log_fatal ("No memory for statements.");
723 ep -> op = statements_statement;
724 executable_statement_reference (&ep -> data.statements,
725 group -> statements,
726 MDL);
727 executable_statement_reference (&ep -> next, et, MDL);
728 executable_statement_dereference (&group -> statements,
729 MDL);
730 executable_statement_reference (&group -> statements,
731 ep, MDL);
732 executable_statement_dereference (&ep, MDL);
733 } else {
734 executable_statement_reference (&group -> statements,
735 et, MDL);
736 }
737 executable_statement_dereference (&et, MDL);
738 return declaration;
739 }
740
741 return 0;
742 }
743
744 #if defined (FAILOVER_PROTOCOL)
745 void parse_failover_peer (cfile, group, type)
746 struct parse *cfile;
747 struct group *group;
748 int type;
749 {
750 enum dhcp_token token;
751 const char *val;
752 dhcp_failover_state_t *peer;
753 u_int32_t *tp;
754 char *name;
755 u_int32_t split;
756 u_int8_t hba [32];
757 unsigned hba_len = sizeof hba;
758 int i;
759 struct expression *expr;
760 isc_result_t status;
761 dhcp_failover_config_t *cp;
762
763 token = next_token (&val, (unsigned *)0, cfile);
764 if (token != PEER) {
765 parse_warn (cfile, "expecting \"peer\"");
766 skip_to_semi (cfile);
767 return;
768 }
769
770 token = next_token (&val, (unsigned *)0, cfile);
771 if (is_identifier (token) || token == STRING) {
772 name = dmalloc (strlen (val) + 1, MDL);
773 if (!name)
774 log_fatal ("no memory for peer name %s", name);
775 strcpy (name, val);
776 } else {
777 parse_warn (cfile, "expecting failover peer name.");
778 skip_to_semi (cfile);
779 return;
780 }
781
782 /* See if there's a peer declaration by this name. */
783 peer = (dhcp_failover_state_t *)0;
784 find_failover_peer (&peer, name, MDL);
785
786 token = next_token (&val, (unsigned *)0, cfile);
787 if (token == SEMI) {
788 dfree (name, MDL);
789 if (type != SHARED_NET_DECL)
790 parse_warn (cfile, "failover peer reference not %s",
791 "in shared-network declaration");
792 else {
793 if (!peer) {
794 parse_warn (cfile, "reference to unknown%s%s",
795 " failover peer ", name);
796 return;
797 }
798 dhcp_failover_state_reference
799 (&group -> shared_network -> failover_peer,
800 peer, MDL);
801 }
802 dhcp_failover_state_dereference (&peer, MDL);
803 return;
804 } else if (token == STATE) {
805 if (!peer) {
806 parse_warn (cfile, "state declaration for unknown%s%s",
807 " failover peer ", name);
808 return;
809 }
810 parse_failover_state_declaration (cfile, peer);
811 dhcp_failover_state_dereference (&peer, MDL);
812 return;
813 } else if (token != LBRACE) {
814 parse_warn (cfile, "expecting left brace");
815 skip_to_semi (cfile);
816 }
817
818 /* Make sure this isn't a redeclaration. */
819 if (peer) {
820 parse_warn (cfile, "redeclaration of failover peer %s", name);
821 skip_to_rbrace (cfile, 1);
822 dhcp_failover_state_dereference (&peer, MDL);
823 return;
824 }
825
826 status = dhcp_failover_state_allocate (&peer, MDL);
827 if (status != ISC_R_SUCCESS)
828 log_fatal ("Can't allocate failover peer %s: %s",
829 name, isc_result_totext (status));
830
831 /* Save the name. */
832 peer -> name = name;
833
834 do {
835 cp = &peer -> me;
836 peer:
837 token = next_token (&val, (unsigned *)0, cfile);
838 switch (token) {
839 case RBRACE:
840 break;
841
842 case PRIMARY:
843 peer -> i_am = primary;
844 break;
845
846 case SECONDARY:
847 peer -> i_am = secondary;
848 if (peer -> hba)
849 parse_warn (cfile,
850 "secondary may not define %s",
851 "load balance settings.");
852 break;
853
854 case PEER:
855 cp = &peer -> partner;
856 goto peer;
857
858 case ADDRESS:
859 expr = (struct expression *)0;
860 if (!parse_ip_addr_or_hostname (&expr, cfile, 0)) {
861 skip_to_rbrace (cfile, 1);
862 dhcp_failover_state_dereference (&peer, MDL);
863 return;
864 }
865 option_cache (&cp -> address,
866 (struct data_string *)0, expr,
867 (struct option *)0, MDL);
868 expression_dereference (&expr, MDL);
869 break;
870
871 case PORT:
872 token = next_token (&val, (unsigned *)0, cfile);
873 if (token != NUMBER) {
874 parse_warn (cfile, "expecting number");
875 skip_to_rbrace (cfile, 1);
876 }
877 cp -> port = atoi (val);
878 break;
879
880 case MAX_LEASE_MISBALANCE:
881 tp = &peer->max_lease_misbalance;
882 goto parse_idle;
883
884 case MAX_LEASE_OWNERSHIP:
885 tp = &peer->max_lease_ownership;
886 goto parse_idle;
887
888 case MAX_BALANCE:
889 tp = &peer->max_balance;
890 goto parse_idle;
891
892 case MIN_BALANCE:
893 tp = &peer->min_balance;
894 goto parse_idle;
895
896 case MAX_RESPONSE_DELAY:
897 tp = &cp -> max_response_delay;
898 parse_idle:
899 token = next_token (&val, (unsigned *)0, cfile);
900 if (token != NUMBER) {
901 parse_warn (cfile, "expecting number.");
902 skip_to_rbrace (cfile, 1);
903 dhcp_failover_state_dereference (&peer, MDL);
904 return;
905 }
906 *tp = atoi (val);
907 break;
908
909 case MAX_UNACKED_UPDATES:
910 tp = &cp -> max_flying_updates;
911 goto parse_idle;
912
913 case MCLT:
914 tp = &peer -> mclt;
915 goto parse_idle;
916
917 case HBA:
918 hba_len = 32;
919 if (peer -> i_am == secondary)
920 parse_warn (cfile,
921 "secondary may not define %s",
922 "load balance settings.");
923 if (!parse_numeric_aggregate (cfile, hba, &hba_len,
924 COLON, 16, 8)) {
925 skip_to_rbrace (cfile, 1);
926 dhcp_failover_state_dereference (&peer, MDL);
927 return;
928 }
929 if (hba_len != 32) {
930 parse_warn (cfile,
931 "HBA must be exactly 32 bytes.");
932 dfree (hba, MDL);
933 break;
934 }
935 make_hba:
936 peer -> hba = dmalloc (32, MDL);
937 if (!peer -> hba) {
938 dfree (peer -> name, MDL);
939 dfree (peer, MDL);
940 }
941 memcpy (peer -> hba, hba, 32);
942 break;
943
944 case SPLIT:
945 token = next_token (&val, (unsigned *)0, cfile);
946 if (peer -> i_am == secondary)
947 parse_warn (cfile,
948 "secondary may not define %s",
949 "load balance settings.");
950 if (token != NUMBER) {
951 parse_warn (cfile, "expecting number");
952 badsplit:
953 skip_to_rbrace (cfile, 1);
954 dhcp_failover_state_dereference (&peer, MDL);
955 return;
956 }
957 split = atoi (val);
958 if (split > 255) {
959 parse_warn (cfile, "split must be < 256");
960 } else {
961 memset (hba, 0, sizeof hba);
962 for (i = 0; i < split; i++) {
963 if (i < split)
964 hba [i / 8] |= (1 << (i & 7));
965 }
966 goto make_hba;
967 }
968 break;
969
970 case LOAD:
971 token = next_token (&val, (unsigned *)0, cfile);
972 if (token != BALANCE) {
973 parse_warn (cfile, "expecting 'balance'");
974 badload:
975 skip_to_rbrace (cfile, 1);
976 break;
977 }
978 token = next_token (&val, (unsigned *)0, cfile);
979 if (token != TOKEN_MAX) {
980 parse_warn (cfile, "expecting 'max'");
981 goto badload;
982 }
983 token = next_token (&val, (unsigned *)0, cfile);
984 if (token != SECONDS) {
985 parse_warn (cfile, "expecting 'secs'");
986 goto badload;
987 }
988 token = next_token (&val, (unsigned *)0, cfile);
989 if (token != NUMBER) {
990 parse_warn (cfile, "expecting number");
991 goto badload;
992 }
993 peer -> load_balance_max_secs = atoi (val);
994 break;
995
996 default:
997 parse_warn (cfile,
998 "invalid statement in peer declaration");
999 skip_to_rbrace (cfile, 1);
1000 dhcp_failover_state_dereference (&peer, MDL);
1001 return;
1002 }
1003 if (token != RBRACE && !parse_semi (cfile)) {
1004 skip_to_rbrace (cfile, 1);
1005 dhcp_failover_state_dereference (&peer, MDL);
1006 return;
1007 }
1008 } while (token != RBRACE);
1009
1010 /* me.address can be null; the failover link initiate code tries to
1011 * derive a reasonable address to use.
1012 */
1013 if (!peer -> partner.address)
1014 parse_warn (cfile, "peer address may not be omitted");
1015
1016 /* XXX - when/if we get a port number assigned, just set as default */
1017 if (!peer -> me.port)
1018 parse_warn (cfile, "local port may not be omitted");
1019 if (!peer -> partner.port)
1020 parse_warn (cfile, "peer port may not be omitted");
1021
1022 if (peer -> i_am == primary) {
1023 if (!peer -> hba) {
1024 parse_warn (cfile,
1025 "primary failover server must have hba or split.");
1026 } else if (!peer -> mclt) {
1027 parse_warn (cfile,
1028 "primary failover server must have mclt.");
1029 }
1030 }
1031
1032 if (!peer->max_lease_misbalance)
1033 peer->max_lease_misbalance = DEFAULT_MAX_LEASE_MISBALANCE;
1034 if (!peer->max_lease_ownership)
1035 peer->max_lease_ownership = DEFAULT_MAX_LEASE_OWNERSHIP;
1036 if (!peer->max_balance)
1037 peer->max_balance = DEFAULT_MAX_BALANCE_TIME;
1038 if (!peer->min_balance)
1039 peer->min_balance = DEFAULT_MIN_BALANCE_TIME;
1040 if (!peer->me.max_flying_updates)
1041 peer->me.max_flying_updates = DEFAULT_MAX_FLYING_UPDATES;
1042 if (!peer->me.max_response_delay)
1043 peer->me.max_response_delay = DEFAULT_MAX_RESPONSE_DELAY;
1044
1045 if (type == SHARED_NET_DECL)
1046 group->shared_network->failover_peer = peer;
1047
1048 /* Set the initial state. */
1049 if (peer -> i_am == primary) {
1050 peer -> me.state = recover;
1051 peer -> me.stos = cur_time;
1052 peer -> partner.state = unknown_state;
1053 peer -> partner.stos = cur_time;
1054 } else {
1055 peer -> me.state = recover;
1056 peer -> me.stos = cur_time;
1057 peer -> partner.state = unknown_state;
1058 peer -> partner.stos = cur_time;
1059 }
1060
1061 status = enter_failover_peer (peer);
1062 if (status != ISC_R_SUCCESS)
1063 parse_warn (cfile, "failover peer %s: %s",
1064 peer -> name, isc_result_totext (status));
1065 dhcp_failover_state_dereference (&peer, MDL);
1066 }
1067
1068 void parse_failover_state_declaration (struct parse *cfile,
1069 dhcp_failover_state_t *peer)
1070 {
1071 enum dhcp_token token;
1072 const char *val;
1073 char *name;
1074 dhcp_failover_state_t *state;
1075 dhcp_failover_config_t *cp;
1076
1077 if (!peer) {
1078 token = next_token (&val, (unsigned *)0, cfile);
1079 if (token != PEER) {
1080 parse_warn (cfile, "expecting \"peer\"");
1081 skip_to_semi (cfile);
1082 return;
1083 }
1084
1085 token = next_token (&val, (unsigned *)0, cfile);
1086 if (is_identifier (token) || token == STRING) {
1087 name = dmalloc (strlen (val) + 1, MDL);
1088 if (!name)
1089 log_fatal ("failover peer name %s: no memory",
1090 name);
1091 strcpy (name, val);
1092 } else {
1093 parse_warn (cfile, "expecting failover peer name.");
1094 skip_to_semi (cfile);
1095 return;
1096 }
1097
1098 /* See if there's a peer declaration by this name. */
1099 state = (dhcp_failover_state_t *)0;
1100 find_failover_peer (&state, name, MDL);
1101 if (!state) {
1102 parse_warn (cfile, "unknown failover peer: %s", name);
1103 skip_to_semi (cfile);
1104 return;
1105 }
1106
1107 token = next_token (&val, (unsigned *)0, cfile);
1108 if (token != STATE) {
1109 parse_warn (cfile, "expecting 'state'");
1110 if (token != SEMI)
1111 skip_to_semi (cfile);
1112 return;
1113 }
1114 } else {
1115 state = (dhcp_failover_state_t *)0;
1116 dhcp_failover_state_reference (&state, peer, MDL);
1117 }
1118 token = next_token (&val, (unsigned *)0, cfile);
1119 if (token != LBRACE) {
1120 parse_warn (cfile, "expecting left brace");
1121 if (token != SEMI)
1122 skip_to_semi (cfile);
1123 dhcp_failover_state_dereference (&state, MDL);
1124 return;
1125 }
1126 do {
1127 token = next_token (&val, (unsigned *)0, cfile);
1128 switch (token) {
1129 case RBRACE:
1130 break;
1131 case MY:
1132 cp = &state -> me;
1133 do_state:
1134 token = next_token (&val, (unsigned *)0, cfile);
1135 if (token != STATE) {
1136 parse_warn (cfile, "expecting 'state'");
1137 goto bogus;
1138 }
1139 parse_failover_state (cfile,
1140 &cp -> state, &cp -> stos);
1141 break;
1142
1143 case PARTNER:
1144 cp = &state -> partner;
1145 goto do_state;
1146
1147 case MCLT:
1148 if (state -> i_am == primary) {
1149 parse_warn (cfile,
1150 "mclt not valid for primary");
1151 goto bogus;
1152 }
1153 token = next_token (&val, (unsigned *)0, cfile);
1154 if (token != NUMBER) {
1155 parse_warn (cfile, "expecting a number.");
1156 goto bogus;
1157 }
1158 state -> mclt = atoi (val);
1159 parse_semi (cfile);
1160 break;
1161
1162 default:
1163 parse_warn (cfile, "expecting state setting.");
1164 bogus:
1165 skip_to_rbrace (cfile, 1);
1166 dhcp_failover_state_dereference (&state, MDL);
1167 return;
1168 }
1169 } while (token != RBRACE);
1170 dhcp_failover_state_dereference (&state, MDL);
1171 }
1172
1173 void parse_failover_state (cfile, state, stos)
1174 struct parse *cfile;
1175 enum failover_state *state;
1176 TIME *stos;
1177 {
1178 enum dhcp_token token;
1179 const char *val;
1180 enum failover_state state_in;
1181 TIME stos_in;
1182
1183 token = next_token (&val, (unsigned *)0, cfile);
1184 switch (token) {
1185 case UNKNOWN_STATE:
1186 state_in = unknown_state;
1187 break;
1188
1189 case PARTNER_DOWN:
1190 state_in = partner_down;
1191 break;
1192
1193 case NORMAL:
1194 state_in = normal;
1195 break;
1196
1197 case COMMUNICATIONS_INTERRUPTED:
1198 state_in = communications_interrupted;
1199 break;
1200
1201 case RESOLUTION_INTERRUPTED:
1202 state_in = resolution_interrupted;
1203 break;
1204
1205 case POTENTIAL_CONFLICT:
1206 state_in = potential_conflict;
1207 break;
1208
1209 case RECOVER:
1210 state_in = recover;
1211 break;
1212
1213 case RECOVER_WAIT:
1214 state_in = recover_wait;
1215 break;
1216
1217 case RECOVER_DONE:
1218 state_in = recover_done;
1219 break;
1220
1221 case SHUTDOWN:
1222 state_in = shut_down;
1223 break;
1224
1225 case PAUSED:
1226 state_in = paused;
1227 break;
1228
1229 case STARTUP:
1230 state_in = startup;
1231 break;
1232
1233 default:
1234 parse_warn (cfile, "unknown failover state");
1235 skip_to_semi (cfile);
1236 return;
1237 }
1238
1239 token = next_token (&val, (unsigned *)0, cfile);
1240 if (token == SEMI) {
1241 stos_in = cur_time;
1242 } else {
1243 if (token != AT) {
1244 parse_warn (cfile, "expecting \"at\"");
1245 skip_to_semi (cfile);
1246 return;
1247 }
1248
1249 stos_in = parse_date (cfile);
1250 if (!stos_in)
1251 return;
1252 }
1253
1254 /* Now that we've apparently gotten a clean parse, we
1255 can trust that this is a state that was fully committed to
1256 disk, so we can install it. */
1257 *stos = stos_in;
1258 *state = state_in;
1259 }
1260 #endif /* defined (FAILOVER_PROTOCOL) */
1261
1262 /* Permit_list_match returns 1 if every element of the permit list in lhs
1263 also appears in rhs. Note that this doesn't by itself mean that the
1264 two lists are equal - to check for equality, permit_list_match has to
1265 return 1 with (list1, list2) and with (list2, list1). */
1266
1267 int permit_list_match (struct permit *lhs, struct permit *rhs)
1268 {
1269 struct permit *plp, *prp;
1270 int matched;
1271
1272 if (!lhs)
1273 return 1;
1274 if (!rhs)
1275 return 0;
1276 for (plp = lhs; plp; plp = plp -> next) {
1277 matched = 0;
1278 for (prp = rhs; prp; prp = prp -> next) {
1279 if (prp -> type == plp -> type &&
1280 (prp -> type != permit_class ||
1281 prp -> class == plp -> class)) {
1282 matched = 1;
1283 break;
1284 }
1285 }
1286 if (!matched)
1287 return 0;
1288 }
1289 return 1;
1290 }
1291
1292 void parse_pool_statement (cfile, group, type)
1293 struct parse *cfile;
1294 struct group *group;
1295 int type;
1296 {
1297 enum dhcp_token token;
1298 const char *val;
1299 int done = 0;
1300 struct pool *pool, **p, *pp;
1301 struct permit *permit;
1302 struct permit **permit_head;
1303 int declaration = 0;
1304 isc_result_t status;
1305 struct lease *lpchain = (struct lease *)0, *lp;
1306
1307 pool = (struct pool *)0;
1308 status = pool_allocate (&pool, MDL);
1309 if (status != ISC_R_SUCCESS)
1310 log_fatal ("no memory for pool: %s",
1311 isc_result_totext (status));
1312
1313 if (type == SUBNET_DECL)
1314 shared_network_reference (&pool -> shared_network,
1315 group -> subnet -> shared_network,
1316 MDL);
1317 else
1318 shared_network_reference (&pool -> shared_network,
1319 group -> shared_network, MDL);
1320
1321 if (!clone_group (&pool -> group, pool -> shared_network -> group, MDL))
1322 log_fatal ("can't clone pool group.");
1323
1324 #if defined (FAILOVER_PROTOCOL)
1325 /* Inherit the failover peer from the shared network. */
1326 if (pool -> shared_network -> failover_peer)
1327 dhcp_failover_state_reference
1328 (&pool -> failover_peer,
1329 pool -> shared_network -> failover_peer, MDL);
1330 #endif
1331
1332 if (!parse_lbrace (cfile)) {
1333 pool_dereference (&pool, MDL);
1334 return;
1335 }
1336
1337 do {
1338 token = peek_token (&val, (unsigned *)0, cfile);
1339 switch (token) {
1340 case NO:
1341 next_token (&val, (unsigned *)0, cfile);
1342 token = next_token (&val, (unsigned *)0, cfile);
1343 if (token != FAILOVER ||
1344 (token = next_token (&val, (unsigned *)0,
1345 cfile)) != PEER) {
1346 parse_warn (cfile,
1347 "expecting \"failover peer\".");
1348 skip_to_semi (cfile);
1349 continue;
1350 }
1351 #if defined (FAILOVER_PROTOCOL)
1352 if (pool -> failover_peer)
1353 dhcp_failover_state_dereference
1354 (&pool -> failover_peer, MDL);
1355 #endif
1356 break;
1357
1358 #if defined (FAILOVER_PROTOCOL)
1359 case FAILOVER:
1360 next_token (&val, (unsigned *)0, cfile);
1361 token = next_token (&val, (unsigned *)0, cfile);
1362 if (token != PEER) {
1363 parse_warn (cfile, "expecting 'peer'.");
1364 skip_to_semi (cfile);
1365 break;
1366 }
1367 token = next_token (&val, (unsigned *)0, cfile);
1368 if (token != STRING) {
1369 parse_warn (cfile, "expecting string.");
1370 skip_to_semi (cfile);
1371 break;
1372 }
1373 if (pool -> failover_peer)
1374 dhcp_failover_state_dereference
1375 (&pool -> failover_peer, MDL);
1376 status = find_failover_peer (&pool -> failover_peer,
1377 val, MDL);
1378 if (status != ISC_R_SUCCESS)
1379 parse_warn (cfile,
1380 "failover peer %s: %s", val,
1381 isc_result_totext (status));
1382 else
1383 pool -> failover_peer -> pool_count++;
1384 parse_semi (cfile);
1385 break;
1386 #endif
1387
1388 case RANGE:
1389 next_token (&val, (unsigned *)0, cfile);
1390 parse_address_range (cfile, group, type,
1391 pool, &lpchain);
1392 break;
1393 case ALLOW:
1394 permit_head = &pool -> permit_list;
1395 get_permit:
1396 permit = new_permit (MDL);
1397 if (!permit)
1398 log_fatal ("no memory for permit");
1399 next_token (&val, (unsigned *)0, cfile);
1400 token = next_token (&val, (unsigned *)0, cfile);
1401 switch (token) {
1402 case UNKNOWN:
1403 permit -> type = permit_unknown_clients;
1404 get_clients:
1405 if (next_token (&val, (unsigned *)0,
1406 cfile) != CLIENTS) {
1407 parse_warn (cfile,
1408 "expecting \"clients\"");
1409 skip_to_semi (cfile);
1410 free_permit (permit, MDL);
1411 continue;
1412 }
1413 break;
1414
1415 case KNOWN_CLIENTS:
1416 permit -> type = permit_known_clients;
1417 break;
1418
1419 case UNKNOWN_CLIENTS:
1420 permit -> type = permit_unknown_clients;
1421 break;
1422
1423 case KNOWN:
1424 permit -> type = permit_known_clients;
1425 goto get_clients;
1426
1427 case AUTHENTICATED:
1428 permit -> type = permit_authenticated_clients;
1429 goto get_clients;
1430
1431 case UNAUTHENTICATED:
1432 permit -> type =
1433 permit_unauthenticated_clients;
1434 goto get_clients;
1435
1436 case ALL:
1437 permit -> type = permit_all_clients;
1438 goto get_clients;
1439 break;
1440
1441 case DYNAMIC:
1442 permit -> type = permit_dynamic_bootp_clients;
1443 if (next_token (&val, (unsigned *)0,
1444 cfile) != TOKEN_BOOTP) {
1445 parse_warn (cfile,
1446 "expecting \"bootp\"");
1447 skip_to_semi (cfile);
1448 free_permit (permit, MDL);
1449 continue;
1450 }
1451 goto get_clients;
1452
1453 case MEMBERS:
1454 if (next_token (&val, (unsigned *)0,
1455 cfile) != OF) {
1456 parse_warn (cfile, "expecting \"of\"");
1457 skip_to_semi (cfile);
1458 free_permit (permit, MDL);
1459 continue;
1460 }
1461 if (next_token (&val, (unsigned *)0,
1462 cfile) != STRING) {
1463 parse_warn (cfile,
1464 "expecting class name.");
1465 skip_to_semi (cfile);
1466 free_permit (permit, MDL);
1467 continue;
1468 }
1469 permit -> type = permit_class;
1470 permit -> class = (struct class *)0;
1471 find_class (&permit -> class, val, MDL);
1472 if (!permit -> class)
1473 parse_warn (cfile,
1474 "no such class: %s", val);
1475 break;
1476
1477 default:
1478 parse_warn (cfile, "expecting permit type.");
1479 skip_to_semi (cfile);
1480 break;
1481 }
1482 while (*permit_head)
1483 permit_head = &((*permit_head) -> next);
1484 *permit_head = permit;
1485 parse_semi (cfile);
1486 break;
1487
1488 case DENY:
1489 permit_head = &pool -> prohibit_list;
1490 goto get_permit;
1491
1492 case RBRACE:
1493 next_token (&val, (unsigned *)0, cfile);
1494 done = 1;
1495 break;
1496
1497 default:
1498 declaration = parse_statement (cfile, pool -> group,
1499 POOL_DECL,
1500 (struct host_decl *)0,
1501 declaration);
1502 break;
1503 }
1504 } while (!done);
1505
1506 #if defined (FAILOVER_PROTOCOL)
1507 /* We can't do failover on a pool that supports dynamic bootp,
1508 because BOOTP doesn't support leases, and failover absolutely
1509 depends on lease timing. */
1510 if (pool -> failover_peer) {
1511 /* This search order matches the search orders later in
1512 * execution - deny first, if not denied, check permit
1513 * list. A dynamic bootp client may be known or unknown,
1514 * it may belong to a member of a class, but it definitely
1515 * will not be authenticated since that requires DHCP
1516 * to work. So a dynamic bootp client is definitely not
1517 * an authenticated client, and we can't say for sure about
1518 * anything else.
1519 *
1520 * So we nag the user.
1521 */
1522 for (permit = pool -> prohibit_list; permit;
1523 permit = permit -> next) {
1524 if (permit -> type == permit_dynamic_bootp_clients ||
1525 permit -> type == permit_unauthenticated_clients ||
1526 permit -> type == permit_all_clients)
1527 break;
1528 }
1529 if (!permit) {
1530 permit = pool -> permit_list;
1531 do {
1532 if (!permit ||
1533 permit -> type !=
1534 permit_authenticated_clients) {
1535 parse_warn (cfile,
1536 "pools with failover peers %s",
1537 "may not permit dynamic bootp.");
1538 log_error ("Either write a \"%s\" %s",
1539 "no failover",
1540 "statement and use disjoint");
1541 log_error ("pools, or%s (%s) %s",
1542 " don't permit dynamic bootp",
1543 "\"deny dynamic bootp clients;\"",
1544 "in this pool.");
1545 log_error ("This is a protocol,%s %s",
1546 " limitation, not an ISC DHCP",
1547 "limitation, so");
1548 log_error ("please don't request an %s",
1549 "enhancement or ask why this is.");
1550
1551 break;
1552 }
1553
1554 permit = permit -> next;
1555 } while (permit);
1556 }
1557 }
1558 #endif /* FAILOVER_PROTOCOL */
1559
1560 /* See if there's already a pool into which we can merge this one. */
1561 for (pp = pool -> shared_network -> pools; pp; pp = pp -> next) {
1562 struct lease *l;
1563
1564 if (pp -> group -> statements != pool -> group -> statements)
1565 continue;
1566 #if defined (FAILOVER_PROTOCOL)
1567 if (pool -> failover_peer != pp -> failover_peer)
1568 continue;
1569 #endif
1570 if (!permit_list_match (pp -> permit_list,
1571 pool -> permit_list) ||
1572 !permit_list_match (pool -> permit_list,
1573 pp -> permit_list) ||
1574 !permit_list_match (pp -> prohibit_list,
1575 pool -> prohibit_list) ||
1576 !permit_list_match (pool -> prohibit_list,
1577 pp -> prohibit_list))
1578 continue;
1579
1580 /* Okay, we can merge these two pools. All we have to
1581 do is fix up the leases, which all point to their pool. */
1582 for (lp = lpchain; lp; lp = lp -> next) {
1583 pool_dereference (&lp -> pool, MDL);
1584 pool_reference (&lp -> pool, pp, MDL);
1585 }
1586 break;
1587 }
1588
1589 /* If we didn't succeed in merging this pool into another, put
1590 it on the list. */
1591 if (!pp) {
1592 p = &pool -> shared_network -> pools;
1593 for (; *p; p = &((*p) -> next))
1594 ;
1595 pool_reference (p, pool, MDL);
1596 }
1597
1598 /* Don't allow a pool declaration with no addresses, since it is
1599 probably a configuration error. */
1600 if (!lpchain) {
1601 parse_warn (cfile, "Pool declaration with no address range.");
1602 log_error ("Pool declarations must always contain at least");
1603 log_error ("one range statement.");
1604 }
1605
1606 /* Dereference the lease chain. */
1607 lp = (struct lease *)0;
1608 while (lpchain) {
1609 lease_reference (&lp, lpchain, MDL);
1610 lease_dereference (&lpchain, MDL);
1611 if (lp -> next) {
1612 lease_reference (&lpchain, lp -> next, MDL);
1613 lease_dereference (&lp -> next, MDL);
1614 lease_dereference (&lp, MDL);
1615 }
1616 }
1617 pool_dereference (&pool, MDL);
1618 }
1619
1620 /* boolean :== ON SEMI | OFF SEMI | TRUE SEMI | FALSE SEMI */
1621
1622 int parse_boolean (cfile)
1623 struct parse *cfile;
1624 {
1625 enum dhcp_token token;
1626 const char *val;
1627 int rv;
1628
1629 token = next_token (&val, (unsigned *)0, cfile);
1630 if (!strcasecmp (val, "true")
1631 || !strcasecmp (val, "on"))
1632 rv = 1;
1633 else if (!strcasecmp (val, "false")
1634 || !strcasecmp (val, "off"))
1635 rv = 0;
1636 else {
1637 parse_warn (cfile,
1638 "boolean value (true/false/on/off) expected");
1639 skip_to_semi (cfile);
1640 return 0;
1641 }
1642 parse_semi (cfile);
1643 return rv;
1644 }
1645
1646 /* Expect a left brace; if there isn't one, skip over the rest of the
1647 statement and return zero; otherwise, return 1. */
1648
1649 int parse_lbrace (cfile)
1650 struct parse *cfile;
1651 {
1652 enum dhcp_token token;
1653 const char *val;
1654
1655 token = next_token (&val, (unsigned *)0, cfile);
1656 if (token != LBRACE) {
1657 parse_warn (cfile, "expecting left brace.");
1658 skip_to_semi (cfile);
1659 return 0;
1660 }
1661 return 1;
1662 }
1663
1664
1665 /* host-declaration :== hostname RBRACE parameters declarations LBRACE */
1666
1667 void parse_host_declaration (cfile, group)
1668 struct parse *cfile;
1669 struct group *group;
1670 {
1671 const char *val;
1672 enum dhcp_token token;
1673 struct host_decl *host;
1674 char *name;
1675 int declaration = 0;
1676 int dynamicp = 0;
1677 int deleted = 0;
1678 isc_result_t status;
1679
1680 name = parse_host_name (cfile);
1681 if (!name) {
1682 parse_warn (cfile, "expecting a name for host declaration.");
1683 skip_to_semi (cfile);
1684 return;
1685 }
1686
1687 host = (struct host_decl *)0;
1688 status = host_allocate (&host, MDL);
1689 if (status != ISC_R_SUCCESS)
1690 log_fatal ("can't allocate host decl struct %s: %s",
1691 name, isc_result_totext (status));
1692 host -> name = name;
1693 if (!clone_group (&host -> group, group, MDL)) {
1694 log_fatal ("can't clone group for host %s", name);
1695 boom:
1696 host_dereference (&host, MDL);
1697 return;
1698 }
1699
1700 if (!parse_lbrace (cfile))
1701 goto boom;
1702
1703 do {
1704 token = peek_token (&val, (unsigned *)0, cfile);
1705 if (token == RBRACE) {
1706 token = next_token (&val, (unsigned *)0, cfile);
1707 break;
1708 }
1709 if (token == END_OF_FILE) {
1710 token = next_token (&val, (unsigned *)0, cfile);
1711 parse_warn (cfile, "unexpected end of file");
1712 break;
1713 }
1714 /* If the host declaration was created by the server,
1715 remember to save it. */
1716 if (token == DYNAMIC) {
1717 dynamicp = 1;
1718 token = next_token (&val, (unsigned *)0, cfile);
1719 if (!parse_semi (cfile))
1720 break;
1721 continue;
1722 }
1723 /* If the host declaration was created by the server,
1724 remember to save it. */
1725 if (token == TOKEN_DELETED) {
1726 deleted = 1;
1727 token = next_token (&val, (unsigned *)0, cfile);
1728 if (!parse_semi (cfile))
1729 break;
1730 continue;
1731 }
1732
1733 if (token == GROUP) {
1734 struct group_object *go;
1735 token = next_token (&val, (unsigned *)0, cfile);
1736 token = next_token (&val, (unsigned *)0, cfile);
1737 if (token != STRING && !is_identifier (token)) {
1738 parse_warn (cfile,
1739 "expecting string or identifier.");
1740 skip_to_rbrace (cfile, 1);
1741 break;
1742 }
1743 go = (struct group_object *)0;
1744 if (!group_hash_lookup (&go, group_name_hash,
1745 val, strlen (val), MDL)) {
1746 parse_warn (cfile, "unknown group %s in host %s",
1747 val, host -> name);
1748 } else {
1749 if (host -> named_group)
1750 group_object_dereference
1751 (&host -> named_group, MDL);
1752 group_object_reference (&host -> named_group,
1753 go, MDL);
1754 group_object_dereference (&go, MDL);
1755 }
1756 if (!parse_semi (cfile))
1757 break;
1758 continue;
1759 }
1760
1761 if (token == UID) {
1762 const char *s;
1763 unsigned char *t = 0;
1764 unsigned len;
1765
1766 token = next_token (&val, (unsigned *)0, cfile);
1767 data_string_forget (&host -> client_identifier, MDL);
1768
1769 if (host->client_identifier.len != 0) {
1770 parse_warn(cfile, "Host %s already has a "
1771 "client identifier.",
1772 host->name);
1773 break;
1774 }
1775
1776 /* See if it's a string or a cshl. */
1777 token = peek_token (&val, (unsigned *)0, cfile);
1778 if (token == STRING) {
1779 token = next_token (&val, &len, cfile);
1780 s = val;
1781 host -> client_identifier.terminated = 1;
1782 } else {
1783 len = 0;
1784 t = parse_numeric_aggregate
1785 (cfile,
1786 (unsigned char *)0, &len, ':', 16, 8);
1787 if (!t) {
1788 parse_warn (cfile,
1789 "expecting hex list.");
1790 skip_to_semi (cfile);
1791 }
1792 s = (const char *)t;
1793 }
1794 if (!buffer_allocate
1795 (&host -> client_identifier.buffer,
1796 len + host -> client_identifier.terminated, MDL))
1797 log_fatal ("no memory for uid for host %s.",
1798 host -> name);
1799 host -> client_identifier.data =
1800 host -> client_identifier.buffer -> data;
1801 host -> client_identifier.len = len;
1802 memcpy (host -> client_identifier.buffer -> data, s,
1803 len + host -> client_identifier.terminated);
1804 if (t)
1805 dfree (t, MDL);
1806
1807 if (!parse_semi (cfile))
1808 break;
1809 continue;
1810 }
1811 declaration = parse_statement (cfile, host -> group,
1812 HOST_DECL, host,
1813 declaration);
1814 } while (1);
1815
1816 if (deleted) {
1817 struct host_decl *hp = (struct host_decl *)0;
1818 if (host_hash_lookup (&hp, host_name_hash,
1819 (unsigned char *)host -> name,
1820 strlen (host -> name), MDL)) {
1821 delete_host (hp, 0);
1822 host_dereference (&hp, MDL);
1823 }
1824 } else {
1825 if (host -> named_group && host -> named_group -> group) {
1826 if (host -> group -> statements ||
1827 (host -> group -> authoritative !=
1828 host -> named_group -> group -> authoritative)) {
1829 if (host -> group -> next)
1830 group_dereference (&host -> group -> next,
1831 MDL);
1832 group_reference (&host -> group -> next,
1833 host -> named_group -> group,
1834 MDL);
1835 } else {
1836 group_dereference (&host -> group, MDL);
1837 group_reference (&host -> group,
1838 host -> named_group -> group,
1839 MDL);
1840 }
1841 }
1842
1843 if (dynamicp)
1844 host -> flags |= HOST_DECL_DYNAMIC;
1845 else
1846 host -> flags |= HOST_DECL_STATIC;
1847
1848 status = enter_host (host, dynamicp, 0);
1849 if (status != ISC_R_SUCCESS)
1850 parse_warn (cfile, "host %s: %s", host -> name,
1851 isc_result_totext (status));
1852 }
1853 host_dereference (&host, MDL);
1854 }
1855
1856 /* class-declaration :== STRING LBRACE parameters declarations RBRACE
1857 */
1858
1859 int parse_class_declaration (cp, cfile, group, type)
1860 struct class **cp;
1861 struct parse *cfile;
1862 struct group *group;
1863 int type;
1864 {
1865 const char *val;
1866 enum dhcp_token token;
1867 struct class *class = (struct class *)0, *pc = (struct class *)0;
1868 int declaration = 0;
1869 int lose = 0;
1870 struct data_string data;
1871 char *name;
1872 const char *tname;
1873 struct executable_statement *stmt = (struct executable_statement *)0;
1874 struct expression *expr;
1875 int new = 1;
1876 isc_result_t status = ISC_R_FAILURE;
1877 int matchedonce = 0;
1878 int submatchedonce = 0;
1879 unsigned code;
1880
1881 token = next_token (&val, (unsigned *)0, cfile);
1882 if (token != STRING) {
1883 parse_warn (cfile, "Expecting class name");
1884 skip_to_semi (cfile);
1885 return 0;
1886 }
1887
1888 /* See if there's already a class with the specified name. */
1889 find_class (&pc, val, MDL);
1890
1891 /* If it is a class, we're updating it. If it's any of the other
1892 * types (subclass, vendor or user class), the named class is a
1893 * reference to the parent class so its mandatory.
1894 */
1895 if (pc && (type == CLASS_TYPE_CLASS)) {
1896 class_reference(&class, pc, MDL);
1897 new = 0;
1898 class_dereference(&pc, MDL);
1899 } else if (!pc && (type != CLASS_TYPE_CLASS)) {
1900 parse_warn(cfile, "no class named %s", val);
1901 skip_to_semi(cfile);
1902 return 0;
1903 }
1904
1905 /* The old vendor-class and user-class declarations had an implicit
1906 match. We don't do the implicit match anymore. Instead, for
1907 backward compatibility, we have an implicit-vendor-class and an
1908 implicit-user-class. vendor-class and user-class declarations
1909 are turned into subclasses of the implicit classes, and the
1910 submatch expression of the implicit classes extracts the contents of
1911 the vendor class or user class. */
1912 if ((type == CLASS_TYPE_VENDOR) || (type == CLASS_TYPE_USER)) {
1913 data.len = strlen (val);
1914 data.buffer = (struct buffer *)0;
1915 if (!buffer_allocate (&data.buffer, data.len + 1, MDL))
1916 log_fatal ("no memory for class name.");
1917 data.data = &data.buffer -> data [0];
1918 data.terminated = 1;
1919
1920 tname = type ? "implicit-vendor-class" : "implicit-user-class";
1921 } else if (type == CLASS_TYPE_CLASS) {
1922 tname = val;
1923 } else {
1924 tname = (const char *)0;
1925 }
1926
1927 if (tname) {
1928 name = dmalloc (strlen (tname) + 1, MDL);
1929 if (!name)
1930 log_fatal ("No memory for class name %s.", tname);
1931 strcpy (name, val);
1932 } else
1933 name = (char *)0;
1934
1935 /* If this is a straight subclass, parse the hash string. */
1936 if (type == CLASS_TYPE_SUBCLASS) {
1937 token = peek_token (&val, (unsigned *)0, cfile);
1938 if (token == STRING) {
1939 token = next_token (&val, &data.len, cfile);
1940 data.buffer = (struct buffer *)0;
1941 if (!buffer_allocate (&data.buffer,
1942 data.len + 1, MDL)) {
1943 if (pc)
1944 class_dereference (&pc, MDL);
1945
1946 return 0;
1947 }
1948 data.terminated = 1;
1949 data.data = &data.buffer -> data [0];
1950 memcpy ((char *)data.buffer -> data, val,
1951 data.len + 1);
1952 } else if (token == NUMBER_OR_NAME || token == NUMBER) {
1953 memset (&data, 0, sizeof data);
1954 if (!parse_cshl (&data, cfile)) {
1955 if (pc)
1956 class_dereference (&pc, MDL);
1957 return 0;
1958 }
1959 } else {
1960 parse_warn (cfile, "Expecting string or hex list.");
1961 if (pc)
1962 class_dereference (&pc, MDL);
1963 return 0;
1964 }
1965 }
1966
1967 /* See if there's already a class in the hash table matching the
1968 hash data. */
1969 if (type != CLASS_TYPE_CLASS)
1970 class_hash_lookup (&class, pc -> hash,
1971 (const char *)data.data, data.len, MDL);
1972
1973 /* If we didn't find an existing class, allocate a new one. */
1974 if (!class) {
1975 /* Allocate the class structure... */
1976 status = class_allocate (&class, MDL);
1977 if (pc) {
1978 group_reference (&class -> group, pc -> group, MDL);
1979 class_reference (&class -> superclass, pc, MDL);
1980 class -> lease_limit = pc -> lease_limit;
1981 if (class -> lease_limit) {
1982 class -> billed_leases =
1983 dmalloc (class -> lease_limit *
1984 sizeof (struct lease *), MDL);
1985 if (!class -> billed_leases)
1986 log_fatal ("no memory for billing");
1987 memset (class -> billed_leases, 0,
1988 (class -> lease_limit *
1989 sizeof class -> billed_leases));
1990 }
1991 data_string_copy (&class -> hash_string, &data, MDL);
1992 if (!pc -> hash &&
1993 !class_new_hash (&pc->hash, SCLASS_HASH_SIZE, MDL))
1994 log_fatal ("No memory for subclass hash.");
1995 class_hash_add (pc -> hash,
1996 (const char *)class -> hash_string.data,
1997 class -> hash_string.len,
1998 (void *)class, MDL);
1999 } else {
2000 if (class->group)
2001 group_dereference(&class->group, MDL);
2002 if (!clone_group (&class -> group, group, MDL))
2003 log_fatal ("no memory to clone class group.");
2004 }
2005
2006 /* If this is an implicit vendor or user class, add a
2007 statement that causes the vendor or user class ID to
2008 be sent back in the reply. */
2009 if (type == CLASS_TYPE_VENDOR || type == CLASS_TYPE_USER) {
2010 stmt = (struct executable_statement *)0;
2011 if (!executable_statement_allocate (&stmt, MDL))
2012 log_fatal ("no memory for class statement.");
2013 stmt -> op = supersede_option_statement;
2014 if (option_cache_allocate (&stmt -> data.option,
2015 MDL)) {
2016 stmt -> data.option -> data = data;
2017 code = (type == CLASS_TYPE_VENDOR)
2018 ? DHO_VENDOR_CLASS_IDENTIFIER
2019 : DHO_USER_CLASS;
2020 option_code_hash_lookup(
2021 &stmt->data.option->option,
2022 dhcp_universe.code_hash,
2023 &code, 0, MDL);
2024 }
2025 class -> statements = stmt;
2026 }
2027
2028 /* Save the name, if there is one. */
2029 if (class->name != NULL)
2030 dfree(class->name, MDL);
2031 class->name = name;
2032 }
2033
2034 if (type != CLASS_TYPE_CLASS)
2035 data_string_forget(&data, MDL);
2036
2037 /* Spawned classes don't have to have their own settings. */
2038 if (class -> superclass) {
2039 token = peek_token (&val, (unsigned *)0, cfile);
2040 if (token == SEMI) {
2041 next_token (&val, (unsigned *)0, cfile);
2042 if (cp)
2043 status = class_reference (cp, class, MDL);
2044 class_dereference (&class, MDL);
2045 if (pc)
2046 class_dereference (&pc, MDL);
2047 return cp ? (status == ISC_R_SUCCESS) : 1;
2048 }
2049 /* Give the subclass its own group. */
2050 if (!clone_group (&class -> group, class -> group, MDL))
2051 log_fatal ("can't clone class group.");
2052
2053 }
2054
2055 if (!parse_lbrace (cfile)) {
2056 class_dereference (&class, MDL);
2057 if (pc)
2058 class_dereference (&pc, MDL);
2059 return 0;
2060 }
2061
2062 do {
2063 token = peek_token (&val, (unsigned *)0, cfile);
2064 if (token == RBRACE) {
2065 token = next_token (&val, (unsigned *)0, cfile);
2066 break;
2067 } else if (token == END_OF_FILE) {
2068 token = next_token (&val, (unsigned *)0, cfile);
2069 parse_warn (cfile, "unexpected end of file");
2070 break;
2071 } else if (token == DYNAMIC) {
2072 class->flags |= CLASS_DECL_DYNAMIC;
2073 token = next_token (&val, (unsigned *)0, cfile);
2074 if (!parse_semi (cfile))
2075 break;
2076 continue;
2077 } else if (token == TOKEN_DELETED) {
2078 class->flags |= CLASS_DECL_DELETED;
2079 token = next_token (&val, (unsigned *)0, cfile);
2080 if (!parse_semi (cfile))
2081 break;
2082 continue;
2083 } else if (token == MATCH) {
2084 if (pc) {
2085 parse_warn (cfile,
2086 "invalid match in subclass.");
2087 skip_to_semi (cfile);
2088 break;
2089 }
2090 token = next_token (&val, (unsigned *)0, cfile);
2091 token = peek_token (&val, (unsigned *)0, cfile);
2092 if (token != IF)
2093 goto submatch;
2094 token = next_token (&val, (unsigned *)0, cfile);
2095 if (matchedonce) {
2096 parse_warn(cfile, "A class may only have "
2097 "one 'match if' clause.");
2098 skip_to_semi(cfile);
2099 break;
2100 }
2101 matchedonce = 1;
2102 if (class->expr)
2103 expression_dereference(&class->expr, MDL);
2104 if (!parse_boolean_expression (&class->expr, cfile,
2105 &lose)) {
2106 if (!lose) {
2107 parse_warn (cfile,
2108 "expecting boolean expr.");
2109 skip_to_semi (cfile);
2110 }
2111 } else {
2112 #if defined (DEBUG_EXPRESSION_PARSE)
2113 print_expression ("class match",
2114 class -> expr);
2115 #endif
2116 parse_semi (cfile);
2117 }
2118 } else if (token == SPAWN) {
2119 token = next_token (&val, (unsigned *)0, cfile);
2120 if (pc) {
2121 parse_warn (cfile,
2122 "invalid spawn in subclass.");
2123 skip_to_semi (cfile);
2124 break;
2125 }
2126 class -> spawning = 1;
2127 token = next_token (&val, (unsigned *)0, cfile);
2128 if (token != WITH) {
2129 parse_warn (cfile,
2130 "expecting with after spawn");
2131 skip_to_semi (cfile);
2132 break;
2133 }
2134 submatch:
2135 if (submatchedonce) {
2136 parse_warn (cfile,
2137 "can't override existing %s.",
2138 "submatch/spawn");
2139 skip_to_semi (cfile);
2140 break;
2141 }
2142 submatchedonce = 1;
2143 if (class->submatch)
2144 expression_dereference(&class->submatch, MDL);
2145 if (!parse_data_expression (&class -> submatch,
2146 cfile, &lose)) {
2147 if (!lose) {
2148 parse_warn (cfile,
2149 "expecting data expr.");
2150 skip_to_semi (cfile);
2151 }
2152 } else {
2153 #if defined (DEBUG_EXPRESSION_PARSE)
2154 print_expression ("class submatch",
2155 class -> submatch);
2156 #endif
2157 parse_semi (cfile);
2158 }
2159 } else if (token == LEASE) {
2160 next_token (&val, (unsigned *)0, cfile);
2161 token = next_token (&val, (unsigned *)0, cfile);
2162 if (token != LIMIT) {
2163 parse_warn (cfile, "expecting \"limit\"");
2164 if (token != SEMI)
2165 skip_to_semi (cfile);
2166 break;
2167 }
2168 token = next_token (&val, (unsigned *)0, cfile);
2169 if (token != NUMBER) {
2170 parse_warn (cfile, "expecting a number");
2171 if (token != SEMI)
2172 skip_to_semi (cfile);
2173 break;
2174 }
2175 class -> lease_limit = atoi (val);
2176 if (class->billed_leases)
2177 dfree(class->billed_leases, MDL);
2178 class -> billed_leases =
2179 dmalloc (class -> lease_limit *
2180 sizeof (struct lease *), MDL);
2181 if (!class -> billed_leases)
2182 log_fatal ("no memory for billed leases.");
2183 memset (class -> billed_leases, 0,
2184 (class -> lease_limit *
2185 sizeof class -> billed_leases));
2186 have_billing_classes = 1;
2187 parse_semi (cfile);
2188 } else {
2189 declaration = parse_statement (cfile, class -> group,
2190 CLASS_DECL,
2191 (struct host_decl *)0,
2192 declaration);
2193 }
2194 } while (1);
2195
2196 if (class->flags & CLASS_DECL_DELETED) {
2197 if (type == CLASS_TYPE_CLASS) {
2198 struct class *theclass = NULL;
2199
2200 status = find_class(&theclass, class->name, MDL);
2201 if (status == ISC_R_SUCCESS) {
2202 delete_class(theclass, 0);
2203 class_dereference(&theclass, MDL);
2204 }
2205 } else {
2206 class_hash_delete(pc->hash,
2207 (char *)class->hash_string.data,
2208 class->hash_string.len, MDL);
2209 }
2210 } else if (type == CLASS_TYPE_CLASS && new) {
2211 if (!collections -> classes)
2212 class_reference (&collections -> classes, class, MDL);
2213 else {
2214 struct class *c;
2215 for (c = collections -> classes;
2216 c -> nic; c = c -> nic)
2217 ;
2218 class_reference (&c -> nic, class, MDL);
2219 }
2220 }
2221
2222 if (cp) /* should always be 0??? */
2223 status = class_reference (cp, class, MDL);
2224 class_dereference (&class, MDL);
2225 if (pc)
2226 class_dereference (&pc, MDL);
2227 return cp ? (status == ISC_R_SUCCESS) : 1;
2228 }
2229
2230 /* shared-network-declaration :==
2231 hostname LBRACE declarations parameters RBRACE */
2232
2233 void parse_shared_net_declaration (cfile, group)
2234 struct parse *cfile;
2235 struct group *group;
2236 {
2237 const char *val;
2238 enum dhcp_token token;
2239 struct shared_network *share;
2240 char *name;
2241 int declaration = 0;
2242 isc_result_t status;
2243
2244 share = (struct shared_network *)0;
2245 status = shared_network_allocate (&share, MDL);
2246 if (status != ISC_R_SUCCESS)
2247 log_fatal ("Can't allocate shared subnet: %s",
2248 isc_result_totext (status));
2249 clone_group (&share -> group, group, MDL);
2250 shared_network_reference (&share -> group -> shared_network,
2251 share, MDL);
2252
2253 /* Get the name of the shared network... */
2254 token = peek_token (&val, (unsigned *)0, cfile);
2255 if (token == STRING) {
2256 token = next_token (&val, (unsigned *)0, cfile);
2257
2258 if (val [0] == 0) {
2259 parse_warn (cfile, "zero-length shared network name");
2260 val = "<no-name-given>";
2261 }
2262 name = dmalloc (strlen (val) + 1, MDL);
2263 if (!name)
2264 log_fatal ("no memory for shared network name");
2265 strcpy (name, val);
2266 } else {
2267 name = parse_host_name (cfile);
2268 if (!name) {
2269 parse_warn (cfile,
2270 "expecting a name for shared-network");
2271 skip_to_semi (cfile);
2272 shared_network_dereference (&share, MDL);
2273 return;
2274 }
2275 }
2276 share -> name = name;
2277
2278 if (!parse_lbrace (cfile)) {
2279 shared_network_dereference (&share, MDL);
2280 return;
2281 }
2282
2283 do {
2284 token = peek_token (&val, (unsigned *)0, cfile);
2285 if (token == RBRACE) {
2286 token = next_token (&val, (unsigned *)0, cfile);
2287 if (!share -> subnets)
2288 parse_warn (cfile,
2289 "empty shared-network decl");
2290 else
2291 enter_shared_network (share);
2292 shared_network_dereference (&share, MDL);
2293 return;
2294 } else if (token == END_OF_FILE) {
2295 token = next_token (&val, (unsigned *)0, cfile);
2296 parse_warn (cfile, "unexpected end of file");
2297 break;
2298 } else if (token == INTERFACE) {
2299 token = next_token (&val, (unsigned *)0, cfile);
2300 token = next_token (&val, (unsigned *)0, cfile);
2301 new_shared_network_interface (cfile, share, val);
2302 if (!parse_semi (cfile))
2303 break;
2304 continue;
2305 }
2306
2307 declaration = parse_statement (cfile, share -> group,
2308 SHARED_NET_DECL,
2309 (struct host_decl *)0,
2310 declaration);
2311 } while (1);
2312 shared_network_dereference (&share, MDL);
2313 }
2314
2315 /* subnet-declaration :==
2316 net NETMASK netmask RBRACE parameters declarations LBRACE */
2317
2318 void parse_subnet_declaration (cfile, share)
2319 struct parse *cfile;
2320 struct shared_network *share;
2321 {
2322 const char *val;
2323 enum dhcp_token token;
2324 struct subnet *subnet, *t, *u;
2325 struct iaddr iaddr;
2326 unsigned char addr [4];
2327 unsigned len = sizeof addr;
2328 int declaration = 0;
2329 struct interface_info *ip;
2330 isc_result_t status;
2331
2332 subnet = (struct subnet *)0;
2333 status = subnet_allocate (&subnet, MDL);
2334 if (status != ISC_R_SUCCESS)
2335 log_fatal ("Allocation of new subnet failed: %s",
2336 isc_result_totext (status));
2337 shared_network_reference (&subnet -> shared_network, share, MDL);
2338 if (!clone_group (&subnet -> group, share -> group, MDL))
2339 log_fatal ("allocation of group for new subnet failed.");
2340 subnet_reference (&subnet -> group -> subnet, subnet, MDL);
2341
2342 /* Get the network number... */
2343 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) {
2344 subnet_dereference (&subnet, MDL);
2345 return;
2346 }
2347 memcpy (iaddr.iabuf, addr, len);
2348 iaddr.len = len;
2349 subnet -> net = iaddr;
2350
2351 token = next_token (&val, (unsigned *)0, cfile);
2352 if (token != NETMASK) {
2353 parse_warn (cfile, "Expecting netmask");
2354 skip_to_semi (cfile);
2355 return;
2356 }
2357
2358 /* Get the netmask... */
2359 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) {
2360 subnet_dereference (&subnet, MDL);
2361 return;
2362 }
2363 memcpy (iaddr.iabuf, addr, len);
2364 iaddr.len = len;
2365 subnet -> netmask = iaddr;
2366
2367 /* Validate the network number/netmask pair. */
2368 if (host_addr (subnet -> net, subnet -> netmask)) {
2369 char *maskstr;
2370
2371 maskstr = strdup (piaddr (subnet -> netmask));
2372 parse_warn (cfile,
2373 "subnet %s netmask %s: bad subnet number/mask combination.",
2374 piaddr (subnet -> net), maskstr);
2375 free(maskstr);
2376 subnet_dereference (&subnet, MDL);
2377 skip_to_semi (cfile);
2378 return;
2379 }
2380
2381 enter_subnet (subnet);
2382
2383 if (!parse_lbrace (cfile)) {
2384 subnet_dereference (&subnet, MDL);
2385 return;
2386 }
2387
2388 do {
2389 token = peek_token (&val, (unsigned *)0, cfile);
2390 if (token == RBRACE) {
2391 token = next_token (&val, (unsigned *)0, cfile);
2392 break;
2393 } else if (token == END_OF_FILE) {
2394 token = next_token (&val, (unsigned *)0, cfile);
2395 parse_warn (cfile, "unexpected end of file");
2396 break;
2397 } else if (token == INTERFACE) {
2398 token = next_token (&val, (unsigned *)0, cfile);
2399 token = next_token (&val, (unsigned *)0, cfile);
2400 new_shared_network_interface (cfile, share, val);
2401 if (!parse_semi (cfile))
2402 break;
2403 continue;
2404 }
2405 declaration = parse_statement (cfile, subnet -> group,
2406 SUBNET_DECL,
2407 (struct host_decl *)0,
2408 declaration);
2409 } while (1);
2410
2411 /* Add the subnet to the list of subnets in this shared net. */
2412 if (!share -> subnets)
2413 subnet_reference (&share -> subnets, subnet, MDL);
2414 else {
2415 u = (struct subnet *)0;
2416 for (t = share -> subnets;
2417 t -> next_sibling; t = t -> next_sibling) {
2418 if (subnet_inner_than (subnet, t, 0)) {
2419 subnet_reference (&subnet -> next_sibling,
2420 t, MDL);
2421 if (u) {
2422 subnet_dereference (&u -> next_sibling,
2423 MDL);
2424 subnet_reference (&u -> next_sibling,
2425 subnet, MDL);
2426 } else {
2427 subnet_dereference (&share -> subnets,
2428 MDL);
2429 subnet_reference (&share -> subnets,
2430 subnet, MDL);
2431 }
2432 subnet_dereference (&subnet, MDL);
2433 return;
2434 }
2435 u = t;
2436 }
2437 subnet_reference (&t -> next_sibling, subnet, MDL);
2438 }
2439 subnet_dereference (&subnet, MDL);
2440 }
2441
2442 /* group-declaration :== RBRACE parameters declarations LBRACE */
2443
2444 void parse_group_declaration (cfile, group)
2445 struct parse *cfile;
2446 struct group *group;
2447 {
2448 const char *val;
2449 enum dhcp_token token;
2450 struct group *g;
2451 int declaration = 0;
2452 struct group_object *t;
2453 isc_result_t status;
2454 char *name = NULL;
2455 int deletedp = 0;
2456 int dynamicp = 0;
2457 int staticp = 0;
2458
2459 g = (struct group *)0;
2460 if (!clone_group (&g, group, MDL))
2461 log_fatal ("no memory for explicit group.");
2462
2463 token = peek_token (&val, (unsigned *)0, cfile);
2464 if (is_identifier (token) || token == STRING) {
2465 next_token (&val, (unsigned *)0, cfile);
2466
2467 name = dmalloc (strlen (val) + 1, MDL);
2468 if (!name)
2469 log_fatal ("no memory for group decl name %s", val);
2470 strcpy (name, val);
2471 }
2472
2473 if (!parse_lbrace (cfile)) {
2474 group_dereference (&g, MDL);
2475 return;
2476 }
2477
2478 do {
2479 token = peek_token (&val, (unsigned *)0, cfile);
2480 if (token == RBRACE) {
2481 token = next_token (&val, (unsigned *)0, cfile);
2482 break;
2483 } else if (token == END_OF_FILE) {
2484 token = next_token (&val, (unsigned *)0, cfile);
2485 parse_warn (cfile, "unexpected end of file");
2486 break;
2487 } else if (token == TOKEN_DELETED) {
2488 token = next_token (&val, (unsigned *)0, cfile);
2489 parse_semi (cfile);
2490 deletedp = 1;
2491 } else if (token == DYNAMIC) {
2492 token = next_token (&val, (unsigned *)0, cfile);
2493 parse_semi (cfile);
2494 dynamicp = 1;
2495 } else if (token == STATIC) {
2496 token = next_token (&val, (unsigned *)0, cfile);
2497 parse_semi (cfile);
2498 staticp = 1;
2499 }
2500 declaration = parse_statement (cfile, g, GROUP_DECL,
2501 (struct host_decl *)0,
2502 declaration);
2503 } while (1);
2504
2505 if (name) {
2506 if (deletedp) {
2507 if (group_name_hash) {
2508 t = (struct group_object *)0;
2509 if (group_hash_lookup (&t, group_name_hash,
2510 name,
2511 strlen (name), MDL)) {
2512 delete_group (t, 0);
2513 }
2514 }
2515 } else {
2516 t = (struct group_object *)0;
2517 status = group_object_allocate (&t, MDL);
2518 if (status != ISC_R_SUCCESS)
2519 log_fatal ("no memory for group decl %s: %s",
2520 val, isc_result_totext (status));
2521 group_reference (&t -> group, g, MDL);
2522 t -> name = name;
2523 t -> flags = ((staticp ? GROUP_OBJECT_STATIC : 0) |
2524 (dynamicp ? GROUP_OBJECT_DYNAMIC : 0) |
2525 (deletedp ? GROUP_OBJECT_DELETED : 0));
2526 supersede_group (t, 0);
2527 }
2528 if (t)
2529 group_object_dereference (&t, MDL);
2530 }
2531 }
2532
2533 /* fixed-addr-parameter :== ip-addrs-or-hostnames SEMI
2534 ip-addrs-or-hostnames :== ip-addr-or-hostname
2535 | ip-addrs-or-hostnames ip-addr-or-hostname */
2536
2537 int parse_fixed_addr_param (oc, cfile)
2538 struct option_cache **oc;
2539 struct parse *cfile;
2540 {
2541 const char *val;
2542 enum dhcp_token token;
2543 struct expression *expr = (struct expression *)0;
2544 struct expression *tmp, *new;
2545 int status;
2546
2547 do {
2548 tmp = (struct expression *)0;
2549 if (parse_ip_addr_or_hostname (&tmp, cfile, 1)) {
2550 if (expr) {
2551 new = (struct expression *)0;
2552 status = make_concat (&new, expr, tmp);
2553 expression_dereference (&expr, MDL);
2554 expression_dereference (&tmp, MDL);
2555 if (!status)
2556 return 0;
2557 expr = new;
2558 } else
2559 expr = tmp;
2560 } else {
2561 if (expr)
2562 expression_dereference (&expr, MDL);
2563 return 0;
2564 }
2565 token = peek_token (&val, (unsigned *)0, cfile);
2566 if (token == COMMA)
2567 token = next_token (&val, (unsigned *)0, cfile);
2568 } while (token == COMMA);
2569
2570 if (!parse_semi (cfile)) {
2571 if (expr)
2572 expression_dereference (&expr, MDL);
2573 return 0;
2574 }
2575 status = option_cache (oc, (struct data_string *)0, expr,
2576 (struct option *)0, MDL);
2577 expression_dereference (&expr, MDL);
2578 return status;
2579 }
2580
2581 /* lease_declaration :== LEASE ip_address LBRACE lease_parameters RBRACE
2582
2583 lease_parameters :== <nil>
2584 | lease_parameter
2585 | lease_parameters lease_parameter
2586
2587 lease_parameter :== STARTS date
2588 | ENDS date
2589 | TIMESTAMP date
2590 | HARDWARE hardware-parameter
2591 | UID hex_numbers SEMI
2592 | HOSTNAME hostname SEMI
2593 | CLIENT_HOSTNAME hostname SEMI
2594 | CLASS identifier SEMI
2595 | DYNAMIC_BOOTP SEMI */
2596
2597 int parse_lease_declaration (struct lease **lp, struct parse *cfile)
2598 {
2599 const char *val;
2600 enum dhcp_token token;
2601 unsigned char addr [4];
2602 unsigned len = sizeof addr;
2603 int seenmask = 0;
2604 int seenbit;
2605 char tbuf [32];
2606 struct lease *lease;
2607 struct executable_statement *on;
2608 struct expression *exp;
2609 struct data_string ds;
2610 int lose;
2611 TIME t;
2612 char *s;
2613 int noequal, newbinding;
2614 struct binding *binding;
2615 isc_result_t status;
2616 struct option_cache *oc;
2617 pair *p;
2618 binding_state_t new_state;
2619 unsigned buflen = 0;
2620 struct class *class;
2621
2622 lease = (struct lease *)0;
2623 status = lease_allocate (&lease, MDL);
2624 if (status != ISC_R_SUCCESS)
2625 return 0;
2626
2627 /* Get the address for which the lease has been issued. */
2628 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) {
2629 lease_dereference (&lease, MDL);
2630 return 0;
2631 }
2632 memcpy (lease -> ip_addr.iabuf, addr, len);
2633 lease -> ip_addr.len = len;
2634
2635 if (!parse_lbrace (cfile)) {
2636 lease_dereference (&lease, MDL);
2637 return 0;
2638 }
2639
2640 do {
2641 token = next_token (&val, (unsigned *)0, cfile);
2642 if (token == RBRACE)
2643 break;
2644 else if (token == END_OF_FILE) {
2645 parse_warn (cfile, "unexpected end of file");
2646 break;
2647 }
2648 strncpy (tbuf, val, sizeof tbuf);
2649 tbuf [(sizeof tbuf) - 1] = 0;
2650
2651 /* Parse any of the times associated with the lease. */
2652 switch (token) {
2653 case STARTS:
2654 case ENDS:
2655 case TIMESTAMP:
2656 case TSTP:
2657 case TSFP:
2658 case ATSFP:
2659 case CLTT:
2660 t = parse_date (cfile);
2661 switch (token) {
2662 case STARTS:
2663 seenbit = 1;
2664 lease -> starts = t;
2665 break;
2666
2667 case ENDS:
2668 seenbit = 2;
2669 lease -> ends = t;
2670 break;
2671
2672 case TSTP:
2673 seenbit = 65536;
2674 lease -> tstp = t;
2675 break;
2676
2677 case TSFP:
2678 seenbit = 131072;
2679 lease -> tsfp = t;
2680 break;
2681
2682 case ATSFP:
2683 seenbit = 262144;
2684 lease->atsfp = t;
2685 break;
2686
2687 case CLTT:
2688 seenbit = 524288;
2689 lease -> cltt = t;
2690 break;
2691
2692 default: /* for gcc, we'll never get here. */
2693 log_fatal ("Impossible error at %s:%d.", MDL);
2694 return 0;
2695 }
2696 break;
2697
2698 /* Colon-seperated hexadecimal octets... */
2699 case UID:
2700 seenbit = 8;
2701 token = peek_token (&val, (unsigned *)0, cfile);
2702 if (token == STRING) {
2703 unsigned char *tuid;
2704 token = next_token (&val, &buflen, cfile);
2705 if (buflen < sizeof lease -> uid_buf) {
2706 tuid = lease -> uid_buf;
2707 lease -> uid_max =
2708 sizeof lease -> uid_buf;
2709 } else {
2710 tuid = ((unsigned char *)
2711 dmalloc (buflen, MDL));
2712 if (!tuid) {
2713 log_error ("no space for uid");
2714 lease_dereference (&lease,
2715 MDL);
2716 return 0;
2717 }
2718 lease -> uid_max = buflen;
2719 }
2720 lease -> uid_len = buflen;
2721 memcpy (tuid, val, lease -> uid_len);
2722 lease -> uid = tuid;
2723 } else {
2724 buflen = 0;
2725 lease -> uid = (parse_numeric_aggregate
2726 (cfile, (unsigned char *)0,
2727 &buflen, ':', 16, 8));
2728 if (!lease -> uid) {
2729 lease_dereference (&lease, MDL);
2730 return 0;
2731 }
2732 lease -> uid_len = buflen;
2733 lease -> uid_max = buflen;
2734 if (lease -> uid_len == 0) {
2735 lease -> uid = (unsigned char *)0;
2736 parse_warn (cfile, "zero-length uid");
2737 seenbit = 0;
2738 parse_semi (cfile);
2739 break;
2740 }
2741 }
2742 parse_semi (cfile);
2743 if (!lease -> uid) {
2744 log_fatal ("No memory for lease uid");
2745 }
2746 break;
2747
2748 case CLASS:
2749 seenbit = 32;
2750 token = next_token (&val, (unsigned *)0, cfile);
2751 if (!is_identifier (token)) {
2752 if (token != SEMI)
2753 skip_to_rbrace (cfile, 1);
2754 lease_dereference (&lease, MDL);
2755 return 0;
2756 }
2757 parse_semi (cfile);
2758 /* for now, we aren't using this. */
2759 break;
2760
2761 case HARDWARE:
2762 seenbit = 64;
2763 parse_hardware_param (cfile,
2764 &lease -> hardware_addr);
2765 break;
2766
2767 case TOKEN_RESERVED:
2768 seenbit = 0;
2769 lease->flags |= RESERVED_LEASE;
2770 parse_semi(cfile);
2771 break;
2772
2773 case DYNAMIC_BOOTP:
2774 seenbit = 0;
2775 lease -> flags |= BOOTP_LEASE;
2776 parse_semi (cfile);
2777 break;
2778
2779 /* XXX: Reverse compatibility? */
2780 case TOKEN_ABANDONED:
2781 seenbit = 256;
2782 lease -> binding_state = FTS_ABANDONED;
2783 lease -> next_binding_state = FTS_ABANDONED;
2784 parse_semi (cfile);
2785 break;
2786
2787 case TOKEN_NEXT:
2788 seenbit = 128;
2789 token = next_token (&val, (unsigned *)0, cfile);
2790 if (token != BINDING) {
2791 parse_warn (cfile, "expecting 'binding'");
2792 skip_to_semi (cfile);
2793 break;
2794 }
2795 goto do_binding_state;
2796
2797 case BINDING:
2798 seenbit = 256;
2799
2800 do_binding_state:
2801 token = next_token (&val, (unsigned *)0, cfile);
2802 if (token != STATE) {
2803 parse_warn (cfile, "expecting 'state'");
2804 skip_to_semi (cfile);
2805 break;
2806 }
2807 token = next_token (&val, (unsigned *)0, cfile);
2808 switch (token) {
2809 case TOKEN_ABANDONED:
2810 new_state = FTS_ABANDONED;
2811 break;
2812 case TOKEN_FREE:
2813 new_state = FTS_FREE;
2814 break;
2815 case TOKEN_ACTIVE:
2816 new_state = FTS_ACTIVE;
2817 break;
2818 case TOKEN_EXPIRED:
2819 new_state = FTS_EXPIRED;
2820 break;
2821 case TOKEN_RELEASED:
2822 new_state = FTS_RELEASED;
2823 break;
2824 case TOKEN_RESET:
2825 new_state = FTS_RESET;
2826 break;
2827 case TOKEN_BACKUP:
2828 new_state = FTS_BACKUP;
2829 break;
2830
2831 /* RESERVED and BOOTP states preserved for
2832 * compatiblity with older versions.
2833 */
2834 case TOKEN_RESERVED:
2835 new_state = FTS_ACTIVE;
2836 lease->flags |= RESERVED_LEASE;
2837 break;
2838 case TOKEN_BOOTP:
2839 new_state = FTS_ACTIVE;
2840 lease->flags |= BOOTP_LEASE;
2841 break;
2842
2843 default:
2844 parse_warn (cfile,
2845 "%s: expecting a binding state.",
2846 val);
2847 skip_to_semi (cfile);
2848 return 0;
2849 }
2850
2851 if (seenbit == 256) {
2852 lease -> binding_state = new_state;
2853
2854 /* If no next binding state is specified, it's
2855 the same as the current state. */
2856 if (!(seenmask & 128))
2857 lease -> next_binding_state = new_state;
2858 } else
2859 lease -> next_binding_state = new_state;
2860
2861 parse_semi (cfile);
2862 break;
2863
2864 case CLIENT_HOSTNAME:
2865 seenbit = 1024;
2866 token = peek_token (&val, (unsigned *)0, cfile);
2867 if (token == STRING) {
2868 if (!parse_string (cfile,
2869 &lease -> client_hostname,
2870 (unsigned *)0)) {
2871 lease_dereference (&lease, MDL);
2872 return 0;
2873 }
2874 } else {
2875 lease -> client_hostname =
2876 parse_host_name (cfile);
2877 if (lease -> client_hostname)
2878 parse_semi (cfile);
2879 else {
2880 parse_warn (cfile,
2881 "expecting a hostname.");
2882 skip_to_semi (cfile);
2883 lease_dereference (&lease, MDL);
2884 return 0;
2885 }
2886 }
2887 break;
2888
2889 case BILLING:
2890 seenbit = 2048;
2891 class = (struct class *)0;
2892 token = next_token (&val, (unsigned *)0, cfile);
2893 if (token == CLASS) {
2894 token = next_token (&val,
2895 (unsigned *)0, cfile);
2896 if (token != STRING) {
2897 parse_warn (cfile, "expecting string");
2898 if (token != SEMI)
2899 skip_to_semi (cfile);
2900 token = BILLING;
2901 break;
2902 }
2903 if (lease -> billing_class)
2904 class_dereference (&lease -> billing_class,
2905 MDL);
2906 find_class (&class, val, MDL);
2907 if (!class)
2908 parse_warn (cfile,
2909 "unknown class %s", val);
2910 parse_semi (cfile);
2911 } else if (token == SUBCLASS) {
2912 if (lease -> billing_class)
2913 class_dereference (&lease -> billing_class,
2914 MDL);
2915 parse_class_declaration(&class, cfile, NULL,
2916 CLASS_TYPE_SUBCLASS);
2917 } else {
2918 parse_warn (cfile, "expecting \"class\"");
2919 if (token != SEMI)
2920 skip_to_semi (cfile);
2921 }
2922 if (class) {
2923 class_reference (&lease -> billing_class,
2924 class, MDL);
2925 class_dereference (&class, MDL);
2926 }
2927 break;
2928
2929 case ON:
2930 on = (struct executable_statement *)0;
2931 lose = 0;
2932 if (!parse_on_statement (&on, cfile, &lose)) {
2933 skip_to_rbrace (cfile, 1);
2934 lease_dereference (&lease, MDL);
2935 return 0;
2936 }
2937 seenbit = 0;
2938 if ((on -> data.on.evtypes & ON_EXPIRY) &&
2939 on -> data.on.statements) {
2940 seenbit |= 16384;
2941 executable_statement_reference
2942 (&lease -> on_expiry,
2943 on -> data.on.statements, MDL);
2944 }
2945 if ((on -> data.on.evtypes & ON_RELEASE) &&
2946 on -> data.on.statements) {
2947 seenbit |= 32768;
2948 executable_statement_reference
2949 (&lease -> on_release,
2950 on -> data.on.statements, MDL);
2951 }
2952 executable_statement_dereference (&on, MDL);
2953 break;
2954
2955 case OPTION:
2956 case SUPERSEDE:
2957 noequal = 0;
2958 seenbit = 0;
2959 oc = (struct option_cache *)0;
2960 if (parse_option_decl (&oc, cfile)) {
2961 if (oc -> option -> universe !=
2962 &agent_universe) {
2963 parse_warn (cfile,
2964 "agent option expected.");
2965 option_cache_dereference (&oc, MDL);
2966 break;
2967 }
2968 if (!lease -> agent_options &&
2969 !(option_chain_head_allocate
2970 (&lease -> agent_options, MDL))) {
2971 log_error ("no memory to stash agent option");
2972 break;
2973 }
2974 for (p = &lease -> agent_options -> first;
2975 *p; p = &((*p) -> cdr))
2976 ;
2977 *p = cons (0, 0);
2978 option_cache_reference (((struct option_cache **)
2979 &((*p) -> car)), oc, MDL);
2980 option_cache_dereference (&oc, MDL);
2981 }
2982 break;
2983
2984 case TOKEN_SET:
2985 noequal = 0;
2986
2987 token = next_token (&val, (unsigned *)0, cfile);
2988 if (token != NAME && token != NUMBER_OR_NAME) {
2989 parse_warn (cfile,
2990 "%s can't be a variable name",
2991 val);
2992 badset:
2993 skip_to_semi (cfile);
2994 lease_dereference (&lease, MDL);
2995 return 0;
2996 }
2997
2998 seenbit = 0;
2999 special_set:
3000 if (lease -> scope)
3001 binding = find_binding (lease -> scope, val);
3002 else
3003 binding = (struct binding *)0;
3004 if (!binding) {
3005 if (!lease -> scope)
3006 if (!(binding_scope_allocate
3007 (&lease -> scope, MDL)))
3008 log_fatal ("no memory for scope");
3009 binding = dmalloc (sizeof *binding, MDL);
3010 if (!binding)
3011 log_fatal ("No memory for lease %s.",
3012 "binding");
3013 memset (binding, 0, sizeof *binding);
3014 binding -> name =
3015 dmalloc (strlen (val) + 1, MDL);
3016 if (!binding -> name)
3017 log_fatal ("No memory for binding %s.",
3018 "name");
3019 strcpy (binding -> name, val);
3020 newbinding = 1;
3021 } else {
3022 if (binding -> value)
3023 binding_value_dereference (&binding -> value,
3024 MDL);
3025 newbinding = 0;
3026 }
3027
3028 if (!binding_value_allocate (&binding -> value, MDL))
3029 log_fatal ("no memory for binding value.");
3030
3031 if (!noequal) {
3032 token = next_token (&val, (unsigned *)0, cfile);
3033 if (token != EQUAL) {
3034 parse_warn (cfile,
3035 "expecting '=' in set statement.");
3036 goto badset;
3037 }
3038 }
3039
3040 token = peek_token (&val, (unsigned *)0, cfile);
3041 if (token == STRING) {
3042 unsigned char *tuid;
3043 token = next_token (&val, &buflen, cfile);
3044 binding -> value -> type = binding_data;
3045 binding -> value -> value.data.len = buflen;
3046 if (!(buffer_allocate
3047 (&binding -> value -> value.data.buffer,
3048 buflen + 1, MDL)))
3049 log_fatal ("No memory for binding.");
3050 memcpy ((char *)
3051 (binding -> value ->
3052 value.data.buffer -> data),
3053 val, buflen + 1);
3054 binding -> value -> value.data.data =
3055 binding -> value -> value.data.buffer -> data;
3056 binding -> value -> value.data.terminated = 1;
3057 } else if (token == NUMBER_OR_NAME) {
3058 binding -> value -> type = binding_data;
3059 s = ((char *)
3060 (parse_numeric_aggregate
3061 (cfile, (unsigned char *)0,
3062 &binding -> value -> value.data.len,
3063 ':', 16, 8)));
3064 if (!s) {
3065 binding_value_dereference
3066 (&binding -> value, MDL);
3067 lease_dereference (&lease, MDL);
3068 return 0;
3069 }
3070 if (binding -> value -> value.data.len) {
3071 if (!(buffer_allocate
3072 (&binding -> value -> value.data.buffer,
3073 binding -> value -> value.data.len + 1,
3074 MDL)))
3075 log_fatal ("No memory for binding.");
3076 memcpy ((binding -> value ->
3077 value.data.buffer -> data), s,
3078 binding -> value -> value.data.len);
3079 dfree (s, MDL);
3080 binding -> value -> value.data.data =
3081 binding -> value -> value.data.buffer -> data;
3082 }
3083 } else if (token == PERCENT) {
3084 token = next_token (&val, (unsigned *)0, cfile);
3085 token = next_token (&val, (unsigned *)0, cfile);
3086 if (token != NUMBER) {
3087 parse_warn (cfile,
3088 "expecting decimal number.");
3089 if (token != SEMI)
3090 skip_to_semi (cfile);
3091 binding_value_dereference
3092 (&binding -> value, MDL);
3093 lease_dereference (&lease, MDL);
3094 return 0;
3095 }
3096 binding -> value -> type = binding_numeric;
3097 binding -> value -> value.intval = atol (val);
3098 } else if (token == NAME) {
3099 token = next_token (&val,
3100 (unsigned *)0, cfile);
3101 binding -> value -> type = binding_boolean;
3102 if (!strcasecmp (val, "true"))
3103 binding -> value -> value.boolean = 1;
3104 else if (!strcasecmp (val, "false"))
3105 binding -> value -> value.boolean = 0;
3106 else
3107 goto badbool;
3108 } else {
3109 badbool:
3110 parse_warn (cfile,
3111 "expecting a constant value.");
3112 skip_to_semi (cfile);
3113 binding_value_dereference (&binding -> value,
3114 MDL);
3115 lease_dereference (&lease, MDL);
3116 return 0;
3117 }
3118
3119 if (newbinding) {
3120 binding -> next = lease -> scope -> bindings;
3121 lease -> scope -> bindings = binding;
3122 }
3123 parse_semi (cfile);
3124 break;
3125
3126 default:
3127 if (!strcasecmp (val, "ddns-fwd-name")) {
3128 seenbit = 4096;
3129 noequal = 1;
3130 goto special_set;
3131 } else if (!strcasecmp (val, "ddns-rev-name")) {
3132 seenbit = 8192;
3133 noequal = 1;
3134 goto special_set;
3135 }
3136 skip_to_semi (cfile);
3137 seenbit = 0;
3138 lease_dereference (&lease, MDL);
3139 return 0;
3140 }
3141
3142 if (seenmask & seenbit) {
3143 parse_warn (cfile,
3144 "Too many %s parameters in lease %s\n",
3145 tbuf, piaddr (lease -> ip_addr));
3146 } else
3147 seenmask |= seenbit;
3148
3149 } while (1);
3150
3151 /* If no binding state is specified, make one up. */
3152 if (!(seenmask & 256)) {
3153 if (lease -> ends > cur_time ||
3154 lease -> on_expiry || lease -> on_release)
3155 lease -> binding_state = FTS_ACTIVE;
3156 #if defined (FAILOVER_PROTOCOL)
3157 else if (lease -> pool && lease -> pool -> failover_peer)
3158 lease -> binding_state = FTS_EXPIRED;
3159 #endif
3160 else
3161 lease -> binding_state = FTS_FREE;
3162 if (lease -> binding_state == FTS_ACTIVE) {
3163 #if defined (FAILOVER_PROTOCOL)
3164 if (lease -> pool && lease -> pool -> failover_peer)
3165 lease -> next_binding_state = FTS_EXPIRED;
3166 else
3167 #endif
3168 lease -> next_binding_state = FTS_FREE;
3169 } else
3170 lease -> next_binding_state = lease -> binding_state;
3171 }
3172
3173 if (!(seenmask & 65536))
3174 lease -> tstp = lease -> ends;
3175
3176 lease_reference (lp, lease, MDL);
3177 lease_dereference (&lease, MDL);
3178 return 1;
3179 }
3180
3181 /* address-range-declaration :== ip-address ip-address SEMI
3182 | DYNAMIC_BOOTP ip-address ip-address SEMI */
3183
3184 void parse_address_range (cfile, group, type, inpool, lpchain)
3185 struct parse *cfile;
3186 struct group *group;
3187 int type;
3188 struct pool *inpool;
3189 struct lease **lpchain;
3190 {
3191 struct iaddr low, high, net;
3192 unsigned char addr [4];
3193 unsigned len = sizeof addr;
3194 enum dhcp_token token;
3195 const char *val;
3196 int dynamic = 0;
3197 struct subnet *subnet;
3198 struct shared_network *share;
3199 struct pool *p;
3200 struct pool *pool;
3201 isc_result_t status;
3202
3203 if ((token = peek_token (&val,
3204 (unsigned *)0, cfile)) == DYNAMIC_BOOTP) {
3205 token = next_token (&val, (unsigned *)0, cfile);
3206 dynamic = 1;
3207 }
3208
3209 /* Get the bottom address in the range... */
3210 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
3211 return;
3212 memcpy (low.iabuf, addr, len);
3213 low.len = len;
3214
3215 /* Only one address? */
3216 token = peek_token (&val, (unsigned *)0, cfile);
3217 if (token == SEMI)
3218 high = low;
3219 else {
3220 /* Get the top address in the range... */
3221 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
3222 return;
3223 memcpy (high.iabuf, addr, len);
3224 high.len = len;
3225 }
3226
3227 token = next_token (&val, (unsigned *)0, cfile);
3228 if (token != SEMI) {
3229 parse_warn (cfile, "semicolon expected.");
3230 skip_to_semi (cfile);
3231 return;
3232 }
3233
3234 if (type == SUBNET_DECL) {
3235 subnet = group -> subnet;
3236 share = subnet -> shared_network;
3237 } else {
3238 share = group -> shared_network;
3239 for (subnet = share -> subnets;
3240 subnet; subnet = subnet -> next_sibling) {
3241 net = subnet_number (low, subnet -> netmask);
3242 if (addr_eq (net, subnet -> net))
3243 break;
3244 }
3245 if (!subnet) {
3246 parse_warn (cfile, "address range not on network %s",
3247 group -> shared_network -> name);
3248 log_error ("Be sure to place pool statement after %s",
3249 "related subnet declarations.");
3250 return;
3251 }
3252 }
3253
3254 if (!inpool) {
3255 struct pool *last = (struct pool *)0;
3256
3257 /* If we're permitting dynamic bootp for this range,
3258 then look for a pool with an empty prohibit list and
3259 a permit list with one entry that permits all clients. */
3260 for (pool = share -> pools; pool; pool = pool -> next) {
3261 if ((!dynamic && !pool -> permit_list &&
3262 pool -> prohibit_list &&
3263 !pool -> prohibit_list -> next &&
3264 (pool -> prohibit_list -> type ==
3265 permit_dynamic_bootp_clients)) ||
3266 (dynamic && !pool -> prohibit_list &&
3267 pool -> permit_list &&
3268 !pool -> permit_list -> next &&
3269 (pool -> permit_list -> type ==
3270 permit_all_clients))) {
3271 break;
3272 }
3273 last = pool;
3274 }
3275
3276 /* If we didn't get a pool, make one. */
3277 if (!pool) {
3278 struct permit *p;
3279 status = pool_allocate (&pool, MDL);
3280 if (status != ISC_R_SUCCESS)
3281 log_fatal ("no memory for ad-hoc pool: %s",
3282 isc_result_totext (status));
3283 p = new_permit (MDL);
3284 if (!p)
3285 log_fatal ("no memory for ad-hoc permit.");
3286
3287 /* Dynamic pools permit all clients. Otherwise
3288 we prohibit BOOTP clients. */
3289 if (dynamic) {
3290 p -> type = permit_all_clients;
3291 pool -> permit_list = p;
3292 } else {
3293 p -> type = permit_dynamic_bootp_clients;
3294 pool -> prohibit_list = p;
3295 }
3296
3297 if (share -> pools)
3298 pool_reference (&last -> next, pool, MDL);
3299 else
3300 pool_reference (&share -> pools, pool, MDL);
3301 shared_network_reference (&pool -> shared_network,
3302 share, MDL);
3303 if (!clone_group (&pool -> group, share -> group, MDL))
3304 log_fatal ("no memory for anon pool group.");
3305 } else {
3306 pool = (struct pool *)0;
3307 if (last)
3308 pool_reference (&pool, last, MDL);
3309 else
3310 pool_reference (&pool, share -> pools, MDL);
3311 }
3312 } else {
3313 pool = (struct pool *)0;
3314 pool_reference (&pool, inpool, MDL);
3315 }
3316
3317 #if defined (FAILOVER_PROTOCOL)
3318 if (pool -> failover_peer && dynamic) {
3319 /* Doctor, do you think I'm overly sensitive
3320 about getting bug reports I can't fix? */
3321 parse_warn (cfile, "dynamic-bootp flag is %s",
3322 "not permitted for address");
3323 log_error ("range declarations where there is a failover");
3324 log_error ("peer in scope. If you wish to declare an");
3325 log_error ("address range from which dynamic bootp leases");
3326 log_error ("can be allocated, please declare it within a");
3327 log_error ("pool declaration that also contains the \"no");
3328 log_error ("failover\" statement. The failover protocol");
3329 log_error ("itself does not permit dynamic bootp - this");
3330 log_error ("is not a limitation specific to the ISC DHCP");
3331 log_error ("server. Please don't ask me to defend this");
3332 log_error ("until you have read and really tried %s",
3333 "to understand");
3334 log_error ("the failover protocol specification.");
3335
3336 /* We don't actually bomb at this point - instead,
3337 we let parse_lease_file notice the error and
3338 bomb at that point - it's easier. */
3339 }
3340 #endif /* FAILOVER_PROTOCOL */
3341
3342 /* Create the new address range... */
3343 new_address_range (cfile, low, high, subnet, pool, lpchain);
3344 pool_dereference (&pool, MDL);
3345 }
3346
3347 /* allow-deny-keyword :== BOOTP
3348 | BOOTING
3349 | DYNAMIC_BOOTP
3350 | UNKNOWN_CLIENTS */
3351
3352 int parse_allow_deny (oc, cfile, flag)
3353 struct option_cache **oc;
3354 struct parse *cfile;
3355 int flag;
3356 {
3357 enum dhcp_token token;
3358 const char *val;
3359 unsigned char rf = flag;
3360 unsigned code;
3361 struct option *option = NULL;
3362 struct expression *data = (struct expression *)0;
3363 int status;
3364
3365 if (!make_const_data (&data, &rf, 1, 0, 1, MDL))
3366 return 0;
3367
3368 token = next_token (&val, (unsigned *)0, cfile);
3369 switch (token) {
3370 case TOKEN_BOOTP:
3371 code = SV_ALLOW_BOOTP;
3372 break;
3373
3374 case BOOTING:
3375 code = SV_ALLOW_BOOTING;
3376 break;
3377
3378 case DYNAMIC_BOOTP:
3379 code = SV_DYNAMIC_BOOTP;
3380 break;
3381
3382 case UNKNOWN_CLIENTS:
3383 code = SV_BOOT_UNKNOWN_CLIENTS;
3384 break;
3385
3386 case DUPLICATES:
3387 code = SV_DUPLICATES;
3388 break;
3389
3390 case DECLINES:
3391 code= SV_DECLINES;
3392 break;
3393
3394 case CLIENT_UPDATES:
3395 code = SV_CLIENT_UPDATES;
3396 break;
3397
3398 case LEASEQUERY:
3399 code = SV_LEASEQUERY;
3400 break;
3401
3402 default:
3403 parse_warn (cfile, "expecting allow/deny key");
3404 skip_to_semi (cfile);
3405 return 0;
3406 }
3407 /* Reference on option is passed to option cache. */
3408 if (!option_code_hash_lookup(&option, server_universe.code_hash,
3409 &code, 0, MDL))
3410 log_fatal("Unable to find server option %u (%s:%d).",
3411 code, MDL);
3412 status = option_cache(oc, NULL, data, option, MDL);
3413 expression_dereference (&data, MDL);
3414 parse_semi (cfile);
3415 return status;
3416 }
3417