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