]> git.ipfire.org Git - thirdparty/dhcp.git/blob - server/confpars.c
Sanitize Solaris build.
[thirdparty/dhcp.git] / server / confpars.c
1 /* confpars.c
2
3 Parser for dhcpd config file... */
4
5 /*
6 * Copyright (c) 1996-1999 Internet Software Consortium.
7 * Use is subject to license terms which appear in the file named
8 * ISC-LICENSE that should have accompanied this file when you
9 * received it. If a file named ISC-LICENSE did not accompany this
10 * file, or you are not sure the one you have is correct, you may
11 * obtain an applicable copy of the license at:
12 *
13 * http://www.isc.org/isc-license-1.0.html.
14 *
15 * This file is part of the ISC DHCP distribution. The documentation
16 * associated with this file is listed in the file DOCUMENTATION,
17 * included in the top-level directory of this release.
18 *
19 * Support and other services are available for ISC products - see
20 * http://www.isc.org for more information.
21 */
22
23 #ifndef lint
24 static char copyright[] =
25 "$Id: confpars.c,v 1.65 1999/03/16 06:37:51 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
26 #endif /* not lint */
27
28 #include "dhcpd.h"
29 #include "dhctoken.h"
30
31 static TIME parsed_time;
32
33 /* conf-file :== parameters declarations EOF
34 parameters :== <nil> | parameter | parameters parameter
35 declarations :== <nil> | declaration | declarations declaration */
36
37 int readconf ()
38 {
39 FILE *cfile;
40 char *val;
41 enum dhcp_token token;
42 int declaration = 0;
43
44 new_parse (path_dhcpd_conf);
45
46 /* Set up the initial dhcp option universe. */
47 initialize_universes ();
48
49 root_group.authoritative = 0;
50
51 if ((cfile = fopen (path_dhcpd_conf, "r")) == NULL)
52 log_fatal ("Can't open %s: %m", path_dhcpd_conf);
53 do {
54 token = peek_token (&val, cfile);
55 if (token == EOF)
56 break;
57 declaration = parse_statement (cfile, &root_group,
58 ROOT_GROUP,
59 (struct host_decl *)0,
60 declaration);
61 } while (1);
62 token = next_token (&val, cfile); /* Clear the peek buffer */
63
64 return !warnings_occurred;
65 }
66
67 /* lease-file :== lease-declarations EOF
68 lease-statments :== <nil>
69 | lease-declaration
70 | lease-declarations lease-declaration */
71
72 void read_leases ()
73 {
74 FILE *cfile;
75 char *val;
76 enum dhcp_token token;
77
78 new_parse (path_dhcpd_db);
79
80 /* Open the lease file. If we can't open it, fail. The reason
81 for this is that although on initial startup, the absence of
82 a lease file is perfectly benign, if dhcpd has been running
83 and this file is absent, it means that dhcpd tried and failed
84 to rewrite the lease database. If we proceed and the
85 problem which caused the rewrite to fail has been fixed, but no
86 human has corrected the database problem, then we are left
87 thinking that no leases have been assigned to anybody, which
88 could create severe network chaos. */
89 if ((cfile = fopen (path_dhcpd_db, "r")) == NULL)
90 log_fatal ("Can't open lease database %s: %m -- %s",
91 path_dhcpd_db,
92 "check for failed database rewrite attempt!");
93 do {
94 token = next_token (&val, cfile);
95 if (token == EOF)
96 break;
97 if (token != LEASE) {
98 log_error ("Corrupt lease file - possible data loss!");
99 skip_to_semi (cfile);
100 } else {
101 struct lease *lease;
102 lease = parse_lease_declaration (cfile);
103 if (lease)
104 enter_lease (lease);
105 else
106 parse_warn ("possibly corrupt lease file");
107 }
108
109 } while (1);
110 }
111
112 /* statement :== parameter | declaration
113
114 parameter :== timestamp
115 | DEFAULT_LEASE_TIME lease_time
116 | MAX_LEASE_TIME lease_time
117 | DYNAMIC_BOOTP_LEASE_CUTOFF date
118 | DYNAMIC_BOOTP_LEASE_LENGTH lease_time
119 | BOOT_UNKNOWN_CLIENTS boolean
120 | ONE_LEASE_PER_CLIENT boolean
121 | GET_LEASE_HOSTNAMES boolean
122 | USE_HOST_DECL_NAME boolean
123 | NEXT_SERVER ip-addr-or-hostname SEMI
124 | option_parameter
125 | SERVER-IDENTIFIER ip-addr-or-hostname SEMI
126 | FILENAME string-parameter
127 | SERVER_NAME string-parameter
128 | hardware-parameter
129 | fixed-address-parameter
130 | ALLOW allow-deny-keyword
131 | DENY allow-deny-keyword
132 | USE_LEASE_ADDR_FOR_DEFAULT_ROUTE boolean
133 | AUTHORITATIVE
134 | NOT AUTHORITATIVE
135 | AUTH_KEY key-id key-value
136
137 declaration :== host-declaration
138 | group-declaration
139 | shared-network-declaration
140 | subnet-declaration
141 | VENDOR_CLASS class-declaration
142 | USER_CLASS class-declaration
143 | RANGE address-range-declaration */
144
145 int parse_statement (cfile, group, type, host_decl, declaration)
146 FILE *cfile;
147 struct group *group;
148 int type;
149 struct host_decl *host_decl;
150 int declaration;
151 {
152 enum dhcp_token token;
153 char *val;
154 struct shared_network *share;
155 char *t, *n;
156 struct expression *expr;
157 struct data_string data;
158 struct hardware hardware;
159 struct executable_statement *et, *ep;
160 struct option *option;
161 struct option_cache *cache;
162 int lose;
163 struct data_string key_id;
164
165 switch (peek_token (&val, cfile)) {
166 case AUTH_KEY:
167 memset (&key_id, 0, sizeof key_id);
168 if (parse_auth_key (&key_id, cfile)) {
169 if (type == HOST_DECL)
170 data_string_copy (&host_decl -> auth_key_id,
171 &key_id, "parse_statement");
172 data_string_forget (&key_id, "parse_statement");
173 }
174 break;
175 case HOST:
176 next_token (&val, cfile);
177 if (type != HOST_DECL && type != CLASS_DECL)
178 parse_host_declaration (cfile, group);
179 else {
180 parse_warn ("host declarations not allowed here.");
181 skip_to_semi (cfile);
182 }
183 return 1;
184
185 case GROUP:
186 next_token (&val, cfile);
187 if (type != HOST_DECL && type != CLASS_DECL)
188 parse_group_declaration (cfile, group);
189 else {
190 parse_warn ("host declarations not allowed here.");
191 skip_to_semi (cfile);
192 }
193 return 1;
194
195 case TIMESTAMP:
196 next_token (&val, cfile);
197 parsed_time = parse_timestamp (cfile);
198 break;
199
200 case SHARED_NETWORK:
201 next_token (&val, cfile);
202 if (type == SHARED_NET_DECL ||
203 type == HOST_DECL ||
204 type == SUBNET_DECL ||
205 type == CLASS_DECL) {
206 parse_warn ("shared-network parameters not %s.",
207 "allowed here");
208 skip_to_semi (cfile);
209 break;
210 }
211
212 parse_shared_net_declaration (cfile, group);
213 return 1;
214
215 case SUBNET:
216 next_token (&val, cfile);
217 if (type == HOST_DECL || type == SUBNET_DECL ||
218 type == CLASS_DECL) {
219 parse_warn ("subnet declarations not allowed here.");
220 skip_to_semi (cfile);
221 return 1;
222 }
223
224 /* If we're in a subnet declaration, just do the parse. */
225 if (group -> shared_network) {
226 parse_subnet_declaration (cfile,
227 group -> shared_network);
228 break;
229 }
230
231 /* Otherwise, cons up a fake shared network structure
232 and populate it with the lone subnet... */
233
234 share = new_shared_network ("parse_statement");
235 if (!share)
236 log_fatal ("No memory for shared subnet");
237 share -> group = clone_group (group, "parse_statement:subnet");
238 share -> group -> shared_network = share;
239
240 parse_subnet_declaration (cfile, share);
241
242 /* share -> subnets is the subnet we just parsed. */
243 if (share -> subnets) {
244 share -> interface =
245 share -> subnets -> interface;
246
247 /* Make the shared network name from network number. */
248 n = piaddr (share -> subnets -> net);
249 t = malloc (strlen (n) + 1);
250 if (!t)
251 log_fatal ("no memory for subnet name");
252 strcpy (t, n);
253 share -> name = t;
254
255 /* Copy the authoritative parameter from the subnet,
256 since there is no opportunity to declare it here. */
257 share -> group -> authoritative =
258 share -> subnets -> group -> authoritative;
259 enter_shared_network (share);
260 }
261 return 1;
262
263 case VENDOR_CLASS:
264 next_token (&val, cfile);
265 if (type == CLASS_DECL) {
266 parse_warn ("class declarations not allowed here.");
267 skip_to_semi (cfile);
268 break;
269 }
270 parse_class_declaration (cfile, group, 0);
271 return 1;
272
273 case USER_CLASS:
274 next_token (&val, cfile);
275 if (type == CLASS_DECL) {
276 parse_warn ("class declarations not allowed here.");
277 skip_to_semi (cfile);
278 break;
279 }
280 parse_class_declaration (cfile, group, 1);
281 return 1;
282
283 case CLASS:
284 next_token (&val, cfile);
285 if (type == CLASS_DECL) {
286 parse_warn ("class declarations not allowed here.");
287 skip_to_semi (cfile);
288 break;
289 }
290 parse_class_declaration (cfile, group, 2);
291 return 1;
292
293 case SUBCLASS:
294 next_token (&val, cfile);
295 if (type == CLASS_DECL) {
296 parse_warn ("class declarations not allowed here.");
297 skip_to_semi (cfile);
298 break;
299 }
300 parse_class_declaration (cfile, group, 3);
301 return 1;
302
303 case HARDWARE:
304 next_token (&val, cfile);
305 parse_hardware_param (cfile, &hardware);
306 if (host_decl)
307 host_decl -> interface = hardware;
308 else
309 parse_warn ("hardware address parameter %s",
310 "not allowed here.");
311 break;
312
313 case FIXED_ADDR:
314 next_token (&val, cfile);
315 cache = (struct option_cache *)0;
316 parse_fixed_addr_param (&cache, cfile);
317 if (host_decl)
318 host_decl -> fixed_addr = cache;
319 else {
320 parse_warn ("fixed-address parameter not %s",
321 "allowed here.");
322 option_cache_dereference (&cache, "parse_statement");
323 }
324 break;
325
326 case POOL:
327 next_token (&val, cfile);
328 if (type != SUBNET_DECL && type != SHARED_NET_DECL) {
329 parse_warn ("pool declared outside of network");
330 }
331 if (type == POOL_DECL) {
332 parse_warn ("pool declared within pool.");
333 }
334 parse_pool_statement (cfile, group, type);
335 return declaration;
336
337 case RANGE:
338 next_token (&val, cfile);
339 if (type != SUBNET_DECL || !group -> subnet) {
340 parse_warn ("range declaration not allowed here.");
341 skip_to_semi (cfile);
342 return declaration;
343 }
344 parse_address_range (cfile, group, type, (struct pool *)0);
345 return declaration;
346
347 case ALLOW:
348 case DENY:
349 token = next_token (&val, cfile);
350 cache = (struct option_cache *)0;
351 if (!parse_allow_deny (&cache, cfile,
352 token == ALLOW ? 1 : 0))
353 return declaration;
354 et = (struct executable_statement *)dmalloc (sizeof *et,
355 "allow/deny");
356 if (!et)
357 log_fatal ("no memory for %s statement",
358 token == ALLOW ? "allow" : "deny");
359 memset (et, 0, sizeof *et);
360 et -> op = supersede_option_statement;
361 et -> data.option = cache;
362 goto insert_statement;
363
364 case TOKEN_NOT:
365 token = next_token (&val, cfile);
366 token = next_token (&val, cfile);
367 switch (token) {
368 case AUTHORITATIVE:
369 group -> authoritative = 0;
370 goto authoritative;
371 default:
372 parse_warn ("expecting assertion");
373 skip_to_semi (cfile);
374 break;
375 }
376 break;
377 case AUTHORITATIVE:
378 token = next_token (&val, cfile);
379 group -> authoritative = 1;
380 authoritative:
381 if (type == HOST_DECL)
382 parse_warn ("authority makes no sense here.");
383 parse_semi (cfile);
384 break;
385
386 case OPTION:
387 token = next_token (&val, cfile);
388 option = parse_option_name (cfile);
389 if (option) {
390 et = parse_option_statement
391 (cfile, 1, option,
392 supersede_option_statement);
393 if (!et)
394 return declaration;
395 goto insert_statement;
396 } else
397 return declaration;
398
399 break;
400
401 #if defined (FAILOVER_PROTOCOL)
402 case FAILOVER:
403 parse_failover_peer (cfile, group, type);
404 break;
405 #endif
406
407 default:
408 et = (struct executable_statement *)0;
409 if (is_identifier (token)) {
410 option = ((struct option *)
411 hash_lookup (server_universe.hash,
412 (unsigned char *)val, 0));
413 if (option) {
414 token = next_token (&val, cfile);
415 et = parse_option_statement
416 (cfile, 1, option,
417 supersede_option_statement);
418 if (!et)
419 return declaration;
420 }
421 }
422
423 if (!et) {
424 lose = 0;
425 et = parse_executable_statement (cfile, &lose);
426 if (!et) {
427 if (!lose) {
428 if (declaration)
429 parse_warn ("expecting a %s.",
430 "declaration");
431 else
432 parse_warn ("expecting a%s%s.",
433 " parameter",
434 " or declaration");
435 skip_to_semi (cfile);
436 }
437 return declaration;
438 }
439 }
440 if (!et) {
441 parse_warn ("expecting a %sdeclaration",
442 declaration ? "" : "parameter or ");
443 return declaration;
444 }
445 insert_statement:
446 if (group -> statements) {
447 for (ep = group -> statements; ep -> next;
448 ep = ep -> next)
449 ;
450 ep -> next = et;
451
452 } else
453 group -> statements = et;
454 return declaration;
455 }
456
457 if (declaration) {
458 parse_warn ("parameters not allowed after first declaration.");
459 return 1;
460 }
461
462 return 0;
463 }
464
465 #if defined (FAILOVER_PROTOCOL)
466 void parse_failover_peer (cfile, group, type)
467 FILE *cfile;
468 struct group *group;
469 int type;
470 {
471 enum dhcp_token token;
472 char *val;
473 struct failover_peer *peer;
474 TIME *tp;
475 char *name;
476
477 if (type != SHARED_NET_DECL && type != ROOT_GROUP) {
478 parse_warn ("failover peer statements not in shared-network%s"
479 " declaration or at top level.");
480 skip_to_semi (cfile);
481 return;
482 }
483
484 token = next_token (&val, cfile);
485 if (token != PEER) {
486 parse_warn ("expecting peer keyword");
487 skip_to_semi (cfile);
488 return;
489 }
490
491 token = next_token (&val, cfile);
492 if (is_identifier (token) || token == STRING) {
493 name = dmalloc (strlen (name) + 1, "peer name");
494 if (!peer -> name)
495 log_fatal ("no memory for peer name %s", name);
496 } else {
497 parse_warn ("expecting identifier or left brace");
498 skip_to_semi (cfile);
499 return;
500 }
501
502 /* See if there's a peer declaration by this name. */
503 peer = find_failover_peer (name);
504
505 token = next_token (&val, cfile);
506 if (token == SEMI) {
507 dfree (name, "peer name");
508 if (type != SHARED_NET_DECL)
509 parse_warn ("failover peer reference not %s",
510 "in shared-network declaration");
511 else {
512 if (!peer) {
513 parse_warn ("reference to unknown%s%s",
514 " failover peer ", name);
515 return;
516 }
517 group -> shared_network -> failover_peer =
518 peer;
519 }
520 return;
521 } else if (token == MY || token == PARTNER) {
522 if (!peer) {
523 parse_warn ("reference to unknown%s%s",
524 " failover peer ", name);
525 return;
526 }
527 if ((token == MY
528 ? peer -> my_state
529 : peer -> partner_state) = parse_failover_state (cfile) ==
530 invalid_state)
531 skip_to_semi (cfile);
532 else
533 parse_semi (cfile);
534 return;
535 } else if (token != LBRACE) {
536 parse_warn ("expecting left brace");
537 skip_to_semi (cfile);
538 }
539
540 /* Make sure this isn't a redeclaration. */
541 if (peer) {
542 parse_warn ("redeclaration of failover peer %s", name);
543 skip_to_rbrace (cfile, 1);
544 return;
545 }
546
547 peer = new_failover_peer ("parse_failover_peer");
548 if (!peer)
549 log_fatal ("no memory for %sfailover peer%s%s.",
550 name ? "" : "anonymous", name ? " " : "", name);
551
552 /* Save the name. */
553 peer -> name = name;
554
555 do {
556 token = next_token (&val, cfile);
557 switch (token) {
558 case RBRACE:
559 break;
560 case PRIMARY:
561 peer -> i_am = primary;
562 break;
563 case SECONDARY:
564 peer -> i_am = secondary;
565 break;
566 case IDENTIFIER:
567 if (!parse_ip_addr_or_hostname (&peer -> address,
568 cfile, 0)) {
569 skip_to_rbrace (cfile, 1);
570 return;
571 }
572 break;
573 case PORT:
574 token = next_token (&val, cfile);
575 if (token != NUMBER) {
576 parse_warn ("expecting number");
577 skip_to_rbrace (cfile, 1);
578 }
579 peer -> port = atoi (val);
580 if (!parse_semi (cfile)) {
581 skip_to_rbrace (cfile, 1);
582 return;
583 }
584 break;
585 case MAX_TRANSMIT_IDLE:
586 tp = &peer -> max_transmit_idle;
587 goto parse_idle;
588 case MAX_RESPONSE_DELAY:
589 tp = &peer -> max_transmit_idle;
590 parse_idle:
591 token = next_token (&val, cfile);
592 if (token != NUMBER) {
593 parse_warn ("expecting number.");
594 skip_to_rbrace (cfile, 1);
595 return;
596 }
597 *tp = atoi (val);
598 default:
599 parse_warn ("invalid statement in peer declaration");
600 skip_to_rbrace (cfile, 1);
601 return;
602 }
603 } while (token != RBRACE);
604
605 if (type == SHARED_NET_DECL) {
606 group -> shared_network -> failover_peer = peer;
607 }
608 enter_failover_peer (peer);
609 }
610
611 enum failover_state parse_failover_state (cfile)
612 FILE *cfile;
613 {
614 enum dhcp_token token;
615 char *val;
616
617 token = next_token (&val, cfile);
618 switch (token) {
619 case PARTNER_DOWN:
620 return partner_down;
621 case NORMAL:
622 return normal;
623 case COMMUNICATIONS_INTERRUPTED:
624 return communications_interrupted;
625 case POTENTIAL_CONFLICT:
626 return potential_conflict;
627 case RECOVER:
628 return recover;
629 default:
630 parse_warn ("unknown failover state");
631 break;
632 }
633 return invalid_state;
634 }
635 #endif /* defined (FAILOVER_PROTOCOL) */
636
637 void parse_pool_statement (cfile, group, type)
638 FILE *cfile;
639 struct group *group;
640 int type;
641 {
642 enum dhcp_token token;
643 char *val;
644 int done = 0;
645 struct pool *pool, **p;
646 struct permit *permit;
647 struct permit **permit_head;
648 int declaration = 0;
649
650 pool = new_pool ("parse_pool_statement");
651 if (!pool)
652 log_fatal ("no memory for pool.");
653
654 pool -> group = clone_group (group, "parse_pool_statement");
655
656 if (!parse_lbrace (cfile))
657 return;
658 do {
659 switch (peek_token (&val, cfile)) {
660 case RANGE:
661 next_token (&val, cfile);
662 parse_address_range (cfile, group, type, pool);
663 break;
664 case ALLOW:
665 permit_head = &pool -> permit_list;
666 get_permit:
667 permit = new_permit ("parse_pool_statement");
668 if (!permit)
669 log_fatal ("no memory for permit");
670 next_token (&val, cfile);
671 token = next_token (&val, cfile);
672 switch (token) {
673 case UNKNOWN:
674 permit -> type = permit_unknown_clients;
675 get_clients:
676 if (next_token (&val, cfile) != CLIENTS) {
677 parse_warn ("expecting \"clients\"");
678 skip_to_semi (cfile);
679 free_permit (permit,
680 "parse_pool_statement");
681 continue;
682 }
683 break;
684
685 case KNOWN:
686 permit -> type = permit_known_clients;
687 goto get_clients;
688
689 case AUTHENTICATED:
690 permit -> type = permit_authenticated_clients;
691 goto get_clients;
692
693 case UNAUTHENTICATED:
694 permit -> type =
695 permit_unauthenticated_clients;
696 goto get_clients;
697
698 case ALL:
699 permit -> type = permit_all_clients;
700 goto get_clients;
701 break;
702
703 case DYNAMIC:
704 permit -> type = permit_dynamic_bootp_clients;
705 if (next_token (&val, cfile) != BOOTP) {
706 parse_warn ("expecting \"bootp\"");
707 skip_to_semi (cfile);
708 free_permit (permit,
709 "parse_pool_statement");
710 continue;
711 }
712 goto get_clients;
713
714 case MEMBERS:
715 if (next_token (&val, cfile) != OF) {
716 parse_warn ("expecting \"of\"");
717 skip_to_semi (cfile);
718 free_permit (permit,
719 "parse_pool_statement");
720 continue;
721 }
722 if (next_token (&val, cfile) != STRING) {
723 parse_warn ("expecting class name.");
724 skip_to_semi (cfile);
725 free_permit (permit,
726 "parse_pool_statement");
727 continue;
728 }
729 permit -> type = permit_class;
730 permit -> class = find_class (val);
731 if (!permit -> class)
732 parse_warn ("no such class: %s", val);
733 default:
734 parse_warn ("expecting permit type.");
735 skip_to_semi (cfile);
736 break;
737 }
738 while (*permit_head)
739 permit_head = &((*permit_head) -> next);
740 *permit_head = permit;
741 parse_semi (cfile);
742 break;
743
744 case DENY:
745 permit_head = &pool -> prohibit_list;
746 goto get_permit;
747
748 case RBRACE:
749 next_token (&val, cfile);
750 done = 1;
751 break;
752
753 default:
754 declaration = parse_statement (cfile, pool -> group,
755 POOL_DECL,
756 (struct host_decl *)0,
757 declaration);
758 break;
759 }
760 } while (!done);
761
762 if (type == SUBNET_DECL)
763 pool -> shared_network = group -> subnet -> shared_network;
764 else
765 pool -> shared_network = group -> shared_network;
766
767 p = &pool -> shared_network -> pools;
768 for (; *p; p = &((*p) -> next))
769 ;
770 *p = pool;
771 }
772
773 /* allow-deny-keyword :== BOOTP
774 | BOOTING
775 | DYNAMIC_BOOTP
776 | UNKNOWN_CLIENTS */
777
778 int parse_allow_deny (oc, cfile, flag)
779 struct option_cache **oc;
780 FILE *cfile;
781 int flag;
782 {
783 enum dhcp_token token;
784 char *val;
785 unsigned char rf = flag;
786 struct expression *data = (struct expression *)0;
787 int status;
788
789 if (!make_const_data (&data, &rf, 1, 0, 1))
790 return 0;
791
792 token = next_token (&val, cfile);
793 switch (token) {
794 case BOOTP:
795 status = option_cache (oc, (struct data_string *)0, data,
796 &server_options [SV_ALLOW_BOOTP]);
797 break;
798
799 case BOOTING:
800 status = option_cache (oc, (struct data_string *)0, data,
801 &server_options [SV_ALLOW_BOOTING]);
802 break;
803
804 case DYNAMIC_BOOTP:
805 status = option_cache (oc, (struct data_string *)0, data,
806 &server_options [SV_DYNAMIC_BOOTP]);
807 break;
808
809 case UNKNOWN_CLIENTS:
810 status = (option_cache
811 (oc, (struct data_string *)0, data,
812 &server_options [SV_BOOT_UNKNOWN_CLIENTS]));
813 break;
814
815 default:
816 parse_warn ("expecting allow/deny key");
817 skip_to_semi (cfile);
818 return 0;
819 }
820 parse_semi (cfile);
821 return status;
822 }
823
824 /* boolean :== ON SEMI | OFF SEMI | TRUE SEMI | FALSE SEMI */
825
826 int parse_boolean (cfile)
827 FILE *cfile;
828 {
829 enum dhcp_token token;
830 char *val;
831 int rv;
832
833 token = next_token (&val, cfile);
834 if (!strcasecmp (val, "true")
835 || !strcasecmp (val, "on"))
836 rv = 1;
837 else if (!strcasecmp (val, "false")
838 || !strcasecmp (val, "off"))
839 rv = 0;
840 else {
841 parse_warn ("boolean value (true/false/on/off) expected");
842 skip_to_semi (cfile);
843 return 0;
844 }
845 parse_semi (cfile);
846 return rv;
847 }
848
849 /* Expect a left brace; if there isn't one, skip over the rest of the
850 statement and return zero; otherwise, return 1. */
851
852 int parse_lbrace (cfile)
853 FILE *cfile;
854 {
855 enum dhcp_token token;
856 char *val;
857
858 token = next_token (&val, cfile);
859 if (token != LBRACE) {
860 parse_warn ("expecting left brace.");
861 skip_to_semi (cfile);
862 return 0;
863 }
864 return 1;
865 }
866
867
868 /* host-declaration :== hostname RBRACE parameters declarations LBRACE */
869
870 void parse_host_declaration (cfile, group)
871 FILE *cfile;
872 struct group *group;
873 {
874 char *val;
875 enum dhcp_token token;
876 struct host_decl *host;
877 char *name;
878 int declaration = 0;
879
880 token = peek_token (&val, cfile);
881 if (token != LBRACE) {
882 name = parse_host_name (cfile);
883 if (!name)
884 return;
885 } else {
886 name = (char *)0;
887 }
888
889 host = (struct host_decl *)dmalloc (sizeof (struct host_decl),
890 "parse_host_declaration");
891 if (!host)
892 log_fatal ("can't allocate host decl struct %s.", name);
893
894 host -> name = name;
895 host -> group = clone_group (group, "parse_host_declaration");
896
897 if (!parse_lbrace (cfile))
898 return;
899
900 do {
901 token = peek_token (&val, cfile);
902 if (token == RBRACE) {
903 token = next_token (&val, cfile);
904 break;
905 }
906 if (token == EOF) {
907 token = next_token (&val, cfile);
908 parse_warn ("unexpected end of file");
909 break;
910 }
911 declaration = parse_statement (cfile, host -> group,
912 HOST_DECL, host,
913 declaration);
914 } while (1);
915
916 enter_host (host);
917 }
918
919 /* class-declaration :== STRING LBRACE parameters declarations RBRACE
920 */
921
922 struct class *parse_class_declaration (cfile, group, type)
923 FILE *cfile;
924 struct group *group;
925 int type;
926 {
927 char *val;
928 enum dhcp_token token;
929 struct class *class = (struct class *)0, *pc;
930 int declaration = 0;
931 int lose;
932 struct data_string data;
933 char *name;
934 struct executable_statement *stmt = (struct executable_statement *)0;
935 struct expression *expr;
936 int new = 1;
937
938 token = next_token (&val, cfile);
939 if (token != STRING) {
940 parse_warn ("Expecting class name");
941 skip_to_semi (cfile);
942 return (struct class *)0;
943 }
944
945 /* See if there's already a class with the specified name. */
946 pc = (struct class *)find_class (val);
947
948 /* If this isn't a subclass, we're updating an existing class. */
949 if (pc && type != 0 && type != 1 && type != 3) {
950 class = pc;
951 new = 0;
952 pc = (struct class *)0;
953 }
954
955 /* If this _is_ a subclass, there _must_ be a class with the
956 same name. */
957 if (!pc && (type == 0 || type == 1 || type == 3)) {
958 parse_warn ("no class named %s", val);
959 skip_to_semi (cfile);
960 return (struct class *)0;
961 }
962
963 /* The old vendor-class and user-class declarations had an implicit
964 match. We don't do the implicit match anymore. Instead, for
965 backward compatibility, we have an implicit-vendor-class and an
966 implicit-user-class. vendor-class and user-class declarations
967 are turned into subclasses of the implicit classes, and the
968 submatch expression of the implicit classes extracts the contents of
969 the vendor class or user class. */
970 if (type == 0 || type == 1) {
971 data.len = strlen (val);
972 data.buffer = (struct buffer *)0;
973 if (!buffer_allocate (&data.buffer,
974 data.len + 1, "parse_class_declaration"))
975 log_fatal ("no memoy for class name.");
976 data.data = &data.buffer -> data [0];
977 data.terminated = 1;
978
979 name = type ? "implicit-vendor-class" : "implicit-user-class";
980 } else if (type == 2) {
981 if (!(name = dmalloc (strlen (val) + 1,
982 "parse_class_declaration")))
983 log_fatal ("No memory for class name %s.", val);
984 strcpy (name, val);
985 } else {
986 name = (char *)0;
987 }
988
989 /* If this is a straight subclass, parse the hash string. */
990 if (type == 3) {
991 token = peek_token (&val, cfile);
992 if (token == STRING) {
993 token = next_token (&val, cfile);
994 data.len = strlen (val);
995 data.buffer = (struct buffer *)0;
996 if (!buffer_allocate (&data.buffer, data.len + 1,
997 "parse_class_declaration"))
998 return (struct class *)0;
999 data.terminated = 1;
1000 data.data = &data.buffer -> data [0];
1001 strcpy ((char *)data.data, val);
1002 } else if (token == NUMBER_OR_NAME || token == NUMBER) {
1003 memset (&data, 0, sizeof data);
1004 if (!parse_cshl (&data, cfile))
1005 return (struct class *)0;
1006 }
1007 }
1008
1009 /* See if there's already a class in the hash table matching the
1010 hash data. */
1011 if (type == 0 || type == 1 || type == 3)
1012 class = ((struct class *)
1013 hash_lookup (pc -> hash, data.data, data.len));
1014
1015 /* If we didn't find an existing class, allocate a new one. */
1016 if (!class) {
1017 /* Allocate the class structure... */
1018 class = (struct class *)dmalloc (sizeof (struct class),
1019 "parse_class_declaration");
1020 if (!class)
1021 log_fatal ("No memory for class %s.", val);
1022 memset (class, 0, sizeof *class);
1023 if (pc) {
1024 class -> group = pc -> group;
1025 class -> group = pc -> group;
1026 class -> superclass = pc;
1027 class -> lease_limit = pc -> lease_limit;
1028 if (class -> lease_limit) {
1029 class -> billed_leases =
1030 dmalloc (class -> lease_limit *
1031 sizeof (struct lease *),
1032 "check_collection");
1033 if (!class -> billed_leases)
1034 log_fatal ("no memory for billed leases");
1035 memset (class -> billed_leases, 0,
1036 (class -> lease_limit *
1037 sizeof class -> billed_leases));
1038 }
1039 data_string_copy (&class -> hash_string, &data,
1040 "check_collection");
1041 if (!pc -> hash)
1042 pc -> hash = new_hash ();
1043 add_hash (pc -> hash,
1044 class -> hash_string.data,
1045 class -> hash_string.len,
1046 (unsigned char *)class);
1047 } else {
1048 class -> group =
1049 clone_group (group, "parse_class_declaration");
1050 }
1051
1052 /* If this is an implicit vendor or user class, add a
1053 statement that causes the vendor or user class ID to
1054 be sent back in the reply. */
1055 if (type == 0 || type == 1) {
1056 stmt = ((struct executable_statement *)
1057 dmalloc (sizeof (struct executable_statement),
1058 "implicit user/vendor class"));
1059 if (!stmt)
1060 log_fatal ("no memory for class statement.");
1061 memset (stmt, 0, sizeof *stmt);
1062 stmt -> op = supersede_option_statement;
1063 if (option_cache_allocate (&stmt -> data.option,
1064 "parse_class_statement")) {
1065 stmt -> data.option -> data = data;
1066 stmt -> data.option -> option =
1067 dhcp_universe.options
1068 [type
1069 ? DHO_DHCP_CLASS_IDENTIFIER
1070 : DHO_DHCP_USER_CLASS_ID];
1071 }
1072 class -> statements = stmt;
1073 }
1074
1075 /* Save the name, if there is one. */
1076 class -> name = name;
1077 }
1078
1079 if (type == 0 || type == 1 || type == 3)
1080 data_string_forget (&data, "check_collection");
1081
1082 /* Spawned classes don't have their own settings. */
1083 if (class -> superclass) {
1084 parse_semi (cfile);
1085 return class;
1086 }
1087
1088 if (!parse_lbrace (cfile))
1089 return (struct class *)0;
1090
1091 do {
1092 token = peek_token (&val, cfile);
1093 if (token == RBRACE) {
1094 token = next_token (&val, cfile);
1095 break;
1096 } else if (token == EOF) {
1097 token = next_token (&val, cfile);
1098 parse_warn ("unexpected end of file");
1099 break;
1100 } else if (token == MATCH) {
1101 if (pc) {
1102 parse_warn ("invalid match in subclass.");
1103 skip_to_semi (cfile);
1104 break;
1105 }
1106 if (class -> expr) {
1107 parse_warn ("can't override match.");
1108 skip_to_semi (cfile);
1109 break;
1110 }
1111 token = next_token (&val, cfile);
1112 token = next_token (&val, cfile);
1113 if (token != IF)
1114 goto submatch;
1115 parse_boolean_expression (&class -> expr, cfile,
1116 &lose);
1117 if (lose)
1118 break;
1119 #if defined (DEBUG_EXPRESSION_PARSE)
1120 print_expression ("class match", class -> expr);
1121 #endif
1122 parse_semi (cfile);
1123 } else if (token == SPAWN) {
1124 if (pc) {
1125 parse_warn ("invalid spawn in subclass.");
1126 skip_to_semi (cfile);
1127 break;
1128 }
1129 token = next_token (&val, cfile);
1130 token = next_token (&val, cfile);
1131 if (token != WITH) {
1132 parse_warn ("expecting with after spawn");
1133 skip_to_semi (cfile);
1134 break;
1135 }
1136 class -> spawning = 1;
1137 submatch:
1138 if (class -> submatch) {
1139 parse_warn ("can't override existing %s.",
1140 "submatch/spawn");
1141 skip_to_semi (cfile);
1142 break;
1143 }
1144 parse_data_expression (&class -> submatch,
1145 cfile, &lose);
1146 if (lose)
1147 break;
1148 #if defined (DEBUG_EXPRESSION_PARSE)
1149 print_expression ("class submatch",
1150 class -> submatch);
1151 #endif
1152 parse_semi (cfile);
1153 } else if (token == LEASE) {
1154 next_token (&val, cfile);
1155 token = next_token (&val, cfile);
1156 if (token != LIMIT) {
1157 parse_warn ("expecting \"limit\"");
1158 if (token != SEMI)
1159 skip_to_semi (cfile);
1160 break;
1161 }
1162 token = next_token (&val, cfile);
1163 if (token != NUMBER) {
1164 parse_warn ("expecting a number");
1165 if (token != SEMI)
1166 skip_to_semi (cfile);
1167 break;
1168 }
1169 class -> lease_limit = atoi (val);
1170 class -> billed_leases =
1171 dmalloc (class -> lease_limit *
1172 sizeof (struct lease *),
1173 "check_collection");
1174 if (!class -> billed_leases)
1175 log_fatal ("no memory for billed leases.");
1176 memset (class -> billed_leases, 0,
1177 (class -> lease_limit *
1178 sizeof class -> billed_leases));
1179 have_billing_classes = 1;
1180 parse_semi (cfile);
1181 } else {
1182 declaration = parse_statement (cfile, class -> group,
1183 CLASS_DECL,
1184 (struct host_decl *)0,
1185 declaration);
1186 }
1187 } while (1);
1188 if (type == 2 && new) {
1189 if (!collections -> classes)
1190 collections -> classes = class;
1191 else {
1192 struct class *cp;
1193 for (cp = collections -> classes;
1194 cp -> nic; cp = cp -> nic)
1195 ;
1196 cp -> nic = class;
1197 }
1198 }
1199 return class;
1200 }
1201
1202 /* shared-network-declaration :==
1203 hostname LBRACE declarations parameters RBRACE */
1204
1205 void parse_shared_net_declaration (cfile, group)
1206 FILE *cfile;
1207 struct group *group;
1208 {
1209 char *val;
1210 enum dhcp_token token;
1211 struct shared_network *share;
1212 char *name;
1213 int declaration = 0;
1214
1215 share = new_shared_network ("parse_shared_net_declaration");
1216 if (!share)
1217 log_fatal ("No memory for shared subnet");
1218 share -> pools = (struct pool *)0;
1219 share -> next = (struct shared_network *)0;
1220 share -> interface = (struct interface_info *)0;
1221 share -> group = clone_group (group, "parse_shared_net_declaration");
1222 share -> group -> shared_network = share;
1223
1224 /* Get the name of the shared network... */
1225 token = peek_token (&val, cfile);
1226 if (token == STRING) {
1227 token = next_token (&val, cfile);
1228
1229 if (val [0] == 0) {
1230 parse_warn ("zero-length shared network name");
1231 val = "<no-name-given>";
1232 }
1233 name = malloc (strlen (val) + 1);
1234 if (!name)
1235 log_fatal ("no memory for shared network name");
1236 strcpy (name, val);
1237 } else {
1238 name = parse_host_name (cfile);
1239 if (!name)
1240 return;
1241 }
1242 share -> name = name;
1243
1244 if (!parse_lbrace (cfile))
1245 return;
1246
1247 do {
1248 token = peek_token (&val, cfile);
1249 if (token == RBRACE) {
1250 token = next_token (&val, cfile);
1251 if (!share -> subnets) {
1252 parse_warn ("empty shared-network decl");
1253 return;
1254 }
1255 enter_shared_network (share);
1256 return;
1257 } else if (token == EOF) {
1258 token = next_token (&val, cfile);
1259 parse_warn ("unexpected end of file");
1260 break;
1261 }
1262
1263 declaration = parse_statement (cfile, share -> group,
1264 SHARED_NET_DECL,
1265 (struct host_decl *)0,
1266 declaration);
1267 } while (1);
1268 }
1269
1270 /* subnet-declaration :==
1271 net NETMASK netmask RBRACE parameters declarations LBRACE */
1272
1273 void parse_subnet_declaration (cfile, share)
1274 FILE *cfile;
1275 struct shared_network *share;
1276 {
1277 char *val;
1278 enum dhcp_token token;
1279 struct subnet *subnet, *t, *u;
1280 struct iaddr iaddr;
1281 unsigned char addr [4];
1282 int len = sizeof addr;
1283 int declaration = 0;
1284
1285 subnet = new_subnet ("parse_subnet_declaration");
1286 if (!subnet)
1287 log_fatal ("No memory for new subnet");
1288 subnet -> shared_network = share;
1289 subnet -> group = clone_group (share -> group,
1290 "parse_subnet_declaration");
1291 subnet -> group -> subnet = subnet;
1292
1293 /* Get the network number... */
1294 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
1295 return;
1296 memcpy (iaddr.iabuf, addr, len);
1297 iaddr.len = len;
1298 subnet -> net = iaddr;
1299
1300 token = next_token (&val, cfile);
1301 if (token != NETMASK) {
1302 parse_warn ("Expecting netmask");
1303 skip_to_semi (cfile);
1304 return;
1305 }
1306
1307 /* Get the netmask... */
1308 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
1309 return;
1310 memcpy (iaddr.iabuf, addr, len);
1311 iaddr.len = len;
1312 subnet -> netmask = iaddr;
1313
1314 enter_subnet (subnet);
1315
1316 if (!parse_lbrace (cfile))
1317 return;
1318
1319 do {
1320 token = peek_token (&val, cfile);
1321 if (token == RBRACE) {
1322 token = next_token (&val, cfile);
1323 break;
1324 } else if (token == EOF) {
1325 token = next_token (&val, cfile);
1326 parse_warn ("unexpected end of file");
1327 break;
1328 }
1329 declaration = parse_statement (cfile, subnet -> group,
1330 SUBNET_DECL,
1331 (struct host_decl *)0,
1332 declaration);
1333 } while (1);
1334
1335 /* Add the subnet to the list of subnets in this shared net. */
1336 if (!share -> subnets)
1337 share -> subnets = subnet;
1338 else {
1339 u = (struct subnet *)0;
1340 for (t = share -> subnets;
1341 t -> next_sibling; t = t -> next_sibling) {
1342 if (subnet_inner_than (subnet, t, 0)) {
1343 if (u)
1344 u -> next_sibling = subnet;
1345 else
1346 share -> subnets = subnet;
1347 subnet -> next_sibling = t;
1348 return;
1349 }
1350 u = t;
1351 }
1352 t -> next_sibling = subnet;
1353 }
1354 }
1355
1356 /* group-declaration :== RBRACE parameters declarations LBRACE */
1357
1358 void parse_group_declaration (cfile, group)
1359 FILE *cfile;
1360 struct group *group;
1361 {
1362 char *val;
1363 enum dhcp_token token;
1364 struct group *g;
1365 int declaration = 0;
1366
1367 g = clone_group (group, "parse_group_declaration");
1368
1369 if (!parse_lbrace (cfile))
1370 return;
1371
1372 do {
1373 token = peek_token (&val, cfile);
1374 if (token == RBRACE) {
1375 token = next_token (&val, cfile);
1376 break;
1377 } else if (token == EOF) {
1378 token = next_token (&val, cfile);
1379 parse_warn ("unexpected end of file");
1380 break;
1381 }
1382 declaration = parse_statement (cfile, g, GROUP_DECL,
1383 (struct host_decl *)0,
1384 declaration);
1385 } while (1);
1386 }
1387
1388 /* fixed-addr-parameter :== ip-addrs-or-hostnames SEMI
1389 ip-addrs-or-hostnames :== ip-addr-or-hostname
1390 | ip-addrs-or-hostnames ip-addr-or-hostname */
1391
1392 int parse_fixed_addr_param (oc, cfile)
1393 struct option_cache **oc;
1394 FILE *cfile;
1395 {
1396 char *val;
1397 enum dhcp_token token;
1398 struct expression *expr = (struct expression *)0;
1399 struct expression *tmp, *new;
1400 int status;
1401
1402 do {
1403 tmp = (struct expression *)0;
1404 if (parse_ip_addr_or_hostname (&tmp, cfile, 1)) {
1405 if (expr) {
1406 new = (struct expression *)0;
1407 status = make_concat (&new, expr, tmp);
1408 expression_dereference
1409 (&expr, "parse_fixed_addr_param");
1410 expression_dereference
1411 (&tmp, "parse_fixed_addr_param");
1412 if (status)
1413 return 0;
1414 expr = new;
1415 } else
1416 expr = tmp;
1417 } else {
1418 if (expr)
1419 expression_dereference
1420 (&expr, "parse_fixed_addr_param");
1421 return 0;
1422 }
1423 token = peek_token (&val, cfile);
1424 if (token == COMMA)
1425 token = next_token (&val, cfile);
1426 } while (token == COMMA);
1427
1428 if (!parse_semi (cfile)) {
1429 if (expr)
1430 expression_dereference (&expr,
1431 "parse_fixed_addr_param");
1432 return 0;
1433 }
1434 status = option_cache (oc, (struct data_string *)0, expr,
1435 (struct option *)0);
1436 expression_dereference (&expr, "parse_fixed_addr_param");
1437 return status;
1438 }
1439
1440 /* timestamp :== date
1441
1442 Timestamps are actually not used in dhcpd.conf, which is a static file,
1443 but rather in the database file and the journal file. (Okay, actually
1444 they're not even used there yet). */
1445
1446 TIME parse_timestamp (cfile)
1447 FILE *cfile;
1448 {
1449 TIME rv;
1450
1451 rv = parse_date (cfile);
1452 return rv;
1453 }
1454
1455 /* lease_declaration :== LEASE ip_address LBRACE lease_parameters RBRACE
1456
1457 lease_parameters :== <nil>
1458 | lease_parameter
1459 | lease_parameters lease_parameter
1460
1461 lease_parameter :== STARTS date
1462 | ENDS date
1463 | TIMESTAMP date
1464 | HARDWARE hardware-parameter
1465 | UID hex_numbers SEMI
1466 | HOSTNAME hostname SEMI
1467 | CLIENT_HOSTNAME hostname SEMI
1468 | CLASS identifier SEMI
1469 | DYNAMIC_BOOTP SEMI */
1470
1471 struct lease *parse_lease_declaration (cfile)
1472 FILE *cfile;
1473 {
1474 char *val;
1475 enum dhcp_token token;
1476 unsigned char addr [4];
1477 int len = sizeof addr;
1478 int seenmask = 0;
1479 int seenbit;
1480 char tbuf [32];
1481 static struct lease lease;
1482
1483 /* Zap the lease structure... */
1484 memset (&lease, 0, sizeof lease);
1485
1486 /* Get the address for which the lease has been issued. */
1487 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
1488 return (struct lease *)0;
1489 memcpy (lease.ip_addr.iabuf, addr, len);
1490 lease.ip_addr.len = len;
1491
1492 if (!parse_lbrace (cfile))
1493 return (struct lease *)0;
1494
1495 do {
1496 token = next_token (&val, cfile);
1497 if (token == RBRACE)
1498 break;
1499 else if (token == EOF) {
1500 parse_warn ("unexpected end of file");
1501 break;
1502 }
1503 strncpy (tbuf, val, sizeof tbuf);
1504 tbuf [(sizeof tbuf) - 1] = 0;
1505
1506 /* Parse any of the times associated with the lease. */
1507 if (token == STARTS || token == ENDS || token == TIMESTAMP) {
1508 TIME t;
1509 t = parse_date (cfile);
1510 switch (token) {
1511 case STARTS:
1512 seenbit = 1;
1513 lease.starts = t;
1514 break;
1515
1516 case ENDS:
1517 seenbit = 2;
1518 lease.ends = t;
1519 break;
1520
1521 case TIMESTAMP:
1522 seenbit = 4;
1523 lease.timestamp = t;
1524 break;
1525
1526 default:
1527 /*NOTREACHED*/
1528 seenbit = 0;
1529 break;
1530 }
1531 } else {
1532 switch (token) {
1533 /* Colon-seperated hexadecimal octets... */
1534 case UID:
1535 seenbit = 8;
1536 token = peek_token (&val, cfile);
1537 if (token == STRING) {
1538 token = next_token (&val, cfile);
1539 lease.uid_len = strlen (val) + 1;
1540 lease.uid = (unsigned char *)
1541 malloc (lease.uid_len);
1542 if (!lease.uid) {
1543 log_error ("no space for uid");
1544 return (struct lease *)0;
1545 }
1546 memcpy (lease.uid, val, lease.uid_len);
1547 } else {
1548 lease.uid_len = 0;
1549 lease.uid = parse_numeric_aggregate
1550 (cfile, (unsigned char *)0,
1551 &lease.uid_len, ':', 16, 8);
1552 if (!lease.uid) {
1553 log_error ("no space for uid");
1554 return (struct lease *)0;
1555 }
1556 if (lease.uid_len == 0) {
1557 lease.uid = (unsigned char *)0;
1558 parse_warn ("zero-length uid");
1559 seenbit = 0;
1560 break;
1561 }
1562 }
1563 if (!lease.uid) {
1564 log_fatal ("No memory for lease uid");
1565 }
1566 break;
1567
1568 case CLASS:
1569 seenbit = 32;
1570 token = next_token (&val, cfile);
1571 if (!is_identifier (token)) {
1572 if (token != SEMI)
1573 skip_to_semi (cfile);
1574 return (struct lease *)0;
1575 }
1576 /* for now, we aren't using this. */
1577 break;
1578
1579 case HARDWARE:
1580 seenbit = 64;
1581 parse_hardware_param (cfile,
1582 &lease.hardware_addr);
1583 break;
1584
1585 case DYNAMIC_BOOTP:
1586 seenbit = 128;
1587 lease.flags |= BOOTP_LEASE;
1588 break;
1589
1590 case ABANDONED:
1591 seenbit = 256;
1592 lease.flags |= ABANDONED_LEASE;
1593 break;
1594
1595 case HOSTNAME:
1596 seenbit = 512;
1597 token = peek_token (&val, cfile);
1598 if (token == STRING)
1599 lease.hostname = parse_string (cfile);
1600 else
1601 lease.hostname =
1602 parse_host_name (cfile);
1603 if (!lease.hostname) {
1604 seenbit = 0;
1605 return (struct lease *)0;
1606 }
1607 break;
1608
1609 case CLIENT_HOSTNAME:
1610 seenbit = 1024;
1611 token = peek_token (&val, cfile);
1612 if (token == STRING)
1613 lease.client_hostname =
1614 parse_string (cfile);
1615 else
1616 lease.client_hostname =
1617 parse_host_name (cfile);
1618 break;
1619
1620 case BILLING:
1621 seenbit = 2048;
1622 token = next_token (&val, cfile);
1623 if (token == CLASS) {
1624 token = next_token (&val, cfile);
1625 if (token != STRING) {
1626 parse_warn
1627 ("expecting string");
1628 if (token != SEMI)
1629 skip_to_semi (cfile);
1630 token = BILLING;
1631 break;
1632 }
1633 lease.billing_class = find_class (val);
1634 if (!lease.billing_class)
1635 parse_warn ("unknown class %s",
1636 val);
1637 parse_semi (cfile);
1638 } else if (token == SUBCLASS) {
1639 lease.billing_class =
1640 parse_class_declaration
1641 (cfile, (struct group *)0, 3);
1642 } else {
1643 parse_warn ("expecting \"class\"");
1644 if (token != SEMI)
1645 skip_to_semi (cfile);
1646 }
1647 token = BILLING;
1648 break;
1649
1650 default:
1651 skip_to_semi (cfile);
1652 seenbit = 0;
1653 return (struct lease *)0;
1654 }
1655
1656 if (token != HARDWARE && token != STRING
1657 && token != BILLING) {
1658 token = next_token (&val, cfile);
1659 if (token != SEMI) {
1660 parse_warn ("semicolon expected.");
1661 skip_to_semi (cfile);
1662 return (struct lease *)0;
1663 }
1664 }
1665 }
1666 if (seenmask & seenbit) {
1667 parse_warn ("Too many %s parameters in lease %s\n",
1668 tbuf, piaddr (lease.ip_addr));
1669 } else
1670 seenmask |= seenbit;
1671
1672 } while (1);
1673 return &lease;
1674 }
1675
1676 /* address-range-declaration :== ip-address ip-address SEMI
1677 | DYNAMIC_BOOTP ip-address ip-address SEMI */
1678
1679 void parse_address_range (cfile, group, type, pool)
1680 FILE *cfile;
1681 struct group *group;
1682 int type;
1683 struct pool *pool;
1684 {
1685 struct iaddr low, high, net;
1686 unsigned char addr [4];
1687 int len = sizeof addr;
1688 enum dhcp_token token;
1689 char *val;
1690 int dynamic = 0;
1691 struct subnet *subnet;
1692 struct shared_network *share;
1693 struct pool *p;
1694
1695 if ((token = peek_token (&val, cfile)) == DYNAMIC_BOOTP) {
1696 token = next_token (&val, cfile);
1697 dynamic = 1;
1698 }
1699
1700 /* Get the bottom address in the range... */
1701 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
1702 return;
1703 memcpy (low.iabuf, addr, len);
1704 low.len = len;
1705
1706 /* Only one address? */
1707 token = peek_token (&val, cfile);
1708 if (token == SEMI)
1709 high = low;
1710 else {
1711 /* Get the top address in the range... */
1712 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
1713 return;
1714 memcpy (high.iabuf, addr, len);
1715 high.len = len;
1716 }
1717
1718 token = next_token (&val, cfile);
1719 if (token != SEMI) {
1720 parse_warn ("semicolon expected.");
1721 skip_to_semi (cfile);
1722 return;
1723 }
1724
1725 if (type == SUBNET_DECL) {
1726 subnet = group -> subnet;
1727 share = subnet -> shared_network;
1728 } else {
1729 share = group -> shared_network;
1730 for (subnet = share -> subnets;
1731 subnet; subnet = subnet -> next_sibling) {
1732 net = subnet_number (low, subnet -> netmask);
1733 if (addr_eq (low, subnet -> net))
1734 break;
1735 }
1736 if (!subnet) {
1737 parse_warn ("address range not on network %s",
1738 group -> shared_network -> name);
1739 return;
1740 }
1741 }
1742
1743 if (!pool) {
1744 struct pool *last;
1745 /* If we're permitting dynamic bootp for this range,
1746 then look for a pool with an empty prohibit list and
1747 a permit list with one entry which permits dynamic
1748 bootp. */
1749 for (pool = share -> pools; pool; pool = pool -> next) {
1750 if ((!dynamic &&
1751 !pool -> permit_list && !pool -> prohibit_list) ||
1752 (dynamic &&
1753 !pool -> prohibit_list &&
1754 pool -> permit_list &&
1755 !pool -> permit_list -> next &&
1756 (pool -> permit_list -> type ==
1757 permit_dynamic_bootp_clients))) {
1758 break;
1759 }
1760 last = pool;
1761 }
1762
1763 /* If we didn't get a pool, make one. */
1764 if (!pool) {
1765 pool = new_pool ("parse_address_range");
1766 if (!pool)
1767 log_fatal ("no memory for ad-hoc pool.");
1768 if (dynamic) {
1769 pool -> permit_list =
1770 new_permit ("parse_address_range");
1771 if (!pool -> permit_list)
1772 log_fatal ("no memory for ad-hoc permit.");
1773 pool -> permit_list -> type =
1774 permit_dynamic_bootp_clients;
1775 }
1776 if (share -> pools)
1777 last -> next = pool;
1778 else
1779 share -> pools = pool;
1780 pool -> shared_network = share;
1781 pool -> group = clone_group (share -> group,
1782 "parse_address_range");
1783 }
1784 }
1785
1786 /* Create the new address range... */
1787 new_address_range (low, high, subnet, pool);
1788 }
1789