]> git.ipfire.org Git - thirdparty/dhcp.git/blame - server/confpars.c
Put check_collection() outside of DEBUG_EXPRESSIONS conditional.
[thirdparty/dhcp.git] / server / confpars.c
CommitLineData
d7837182
TL
1/* confpars.c
2
3 Parser for dhcpd config file... */
4
5/*
59b85ebd 6 * Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium.
95821729 7 * All rights reserved.
d7837182
TL
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of The Internet Software Consortium nor the names
19 * of its contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
23 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
30 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * This software has been written for the Internet Software Consortium
37 * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
38 * Enterprises. To learn more about the Internet Software Consortium,
39 * see ``http://www.vix.com/isc''. To learn more about Vixie
40 * Enterprises, see ``http://www.vix.com''.
41 */
42
43#ifndef lint
44static char copyright[] =
028a8588 45"$Id: confpars.c,v 1.53 1998/11/06 00:31:08 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
d7837182
TL
46#endif /* not lint */
47
48#include "dhcpd.h"
49#include "dhctoken.h"
50
51static TIME parsed_time;
52
2d59f590
TL
53/* conf-file :== parameters declarations EOF
54 parameters :== <nil> | parameter | parameters parameter
55 declarations :== <nil> | declaration | declarations declaration */
d7837182 56
88ddda34 57int readconf ()
d7837182
TL
58{
59 FILE *cfile;
60 char *val;
6f8fb41f 61 enum dhcp_token token;
2d59f590 62 int declaration = 0;
d7837182 63
e2ac5814 64 new_parse (path_dhcpd_conf);
7e8381e5 65
d7837182
TL
66 /* Set up the initial dhcp option universe. */
67 initialize_universes ();
68
e2ac5814
TL
69 if ((cfile = fopen (path_dhcpd_conf, "r")) == NULL)
70 error ("Can't open %s: %m", path_dhcpd_conf);
d7837182
TL
71 do {
72 token = peek_token (&val, cfile);
73 if (token == EOF)
74 break;
2d59f590 75 declaration = parse_statement (cfile, &root_group,
ece6ea33
TL
76 ROOT_GROUP,
77 (struct host_decl *)0,
78 declaration);
d7837182 79 } while (1);
88ddda34
TL
80 token = next_token (&val, cfile); /* Clear the peek buffer */
81
82 return !warnings_occurred;
1358b874
TL
83}
84
2d59f590 85/* lease-file :== lease-declarations EOF
5376e3e9 86 lease-statments :== <nil>
2d59f590
TL
87 | lease-declaration
88 | lease-declarations lease-declaration */
5376e3e9 89
31f26cd3 90void read_leases ()
1358b874
TL
91{
92 FILE *cfile;
93 char *val;
6f8fb41f 94 enum dhcp_token token;
1358b874 95
e2ac5814 96 new_parse (path_dhcpd_db);
7dfc8ac2
TL
97
98 /* Open the lease file. If we can't open it, fail. The reason
99 for this is that although on initial startup, the absence of
100 a lease file is perfectly benign, if dhcpd has been running
101 and this file is absent, it means that dhcpd tried and failed
102 to rewrite the lease database. If we proceed and the
103 problem which caused the rewrite to fail has been fixed, but no
104 human has corrected the database problem, then we are left
105 thinking that no leases have been assigned to anybody, which
106 could create severe network chaos. */
e2ac5814 107 if ((cfile = fopen (path_dhcpd_db, "r")) == NULL)
7dfc8ac2 108 error ("Can't open lease database %s: %m -- %s",
e2ac5814 109 path_dhcpd_db,
7dfc8ac2 110 "check for failed database rewrite attempt!");
1358b874
TL
111 do {
112 token = next_token (&val, cfile);
1358b874
TL
113 if (token == EOF)
114 break;
115 if (token != LEASE) {
116 warn ("Corrupt lease file - possible data loss!");
117 skip_to_semi (cfile);
118 } else {
7dfc8ac2 119 struct lease *lease;
2d59f590 120 lease = parse_lease_declaration (cfile);
7dfc8ac2 121 if (lease)
1358b874 122 enter_lease (lease);
7dfc8ac2 123 else
1f814ff2 124 parse_warn ("possibly corrupt lease file");
1358b874
TL
125 }
126
127 } while (1);
d7837182
TL
128}
129
2d59f590
TL
130/* statement :== parameter | declaration
131
132 parameter :== timestamp
133 | DEFAULT_LEASE_TIME lease_time
134 | MAX_LEASE_TIME lease_time
135 | DYNAMIC_BOOTP_LEASE_CUTOFF date
136 | DYNAMIC_BOOTP_LEASE_LENGTH lease_time
137 | BOOT_UNKNOWN_CLIENTS boolean
138 | ONE_LEASE_PER_CLIENT boolean
5fea7b10 139 | GET_LEASE_HOSTNAMES boolean
c256bae9 140 | USE_HOST_DECL_NAME boolean
2d59f590
TL
141 | NEXT_SERVER ip-addr-or-hostname SEMI
142 | option_parameter
143 | SERVER-IDENTIFIER ip-addr-or-hostname SEMI
144 | FILENAME string-parameter
145 | SERVER_NAME string-parameter
146 | hardware-parameter
147 | fixed-address-parameter
99fd97cc
TL
148 | ALLOW allow-deny-keyword
149 | DENY allow-deny-keyword
59b85ebd 150 | USE_LEASE_ADDR_FOR_DEFAULT_ROUTE boolean
2d59f590
TL
151
152 declaration :== host-declaration
153 | group-declaration
154 | shared-network-declaration
155 | subnet-declaration
156 | VENDOR_CLASS class-declaration
157 | USER_CLASS class-declaration
158 | RANGE address-range-declaration */
159
160int parse_statement (cfile, group, type, host_decl, declaration)
d7837182 161 FILE *cfile;
7dfc8ac2
TL
162 struct group *group;
163 int type;
164 struct host_decl *host_decl;
2d59f590 165 int declaration;
d7837182 166{
6f8fb41f 167 enum dhcp_token token;
d7837182 168 char *val;
7dfc8ac2 169 struct shared_network *share;
7dfc8ac2 170 char *t, *n;
ece6ea33
TL
171 struct expression *expr;
172 struct data_string data;
7dfc8ac2 173 struct hardware hardware;
ece6ea33
TL
174 struct executable_statement *et, *ep;
175 struct option *option;
176 struct option_cache *cache;
177 int lose;
d7837182 178
ece6ea33 179 switch (peek_token (&val, cfile)) {
d7837182 180 case HOST:
ece6ea33
TL
181 next_token (&val, cfile);
182 if (type != HOST_DECL && type != CLASS_DECL)
2d59f590 183 parse_host_declaration (cfile, group);
7dfc8ac2 184 else {
2d59f590 185 parse_warn ("host declarations not allowed here.");
7dfc8ac2 186 skip_to_semi (cfile);
d7837182 187 }
7dfc8ac2
TL
188 return 1;
189
190 case GROUP:
ece6ea33
TL
191 next_token (&val, cfile);
192 if (type != HOST_DECL && type != CLASS_DECL)
2d59f590 193 parse_group_declaration (cfile, group);
7dfc8ac2 194 else {
2d59f590 195 parse_warn ("host declarations not allowed here.");
7dfc8ac2 196 skip_to_semi (cfile);
d7837182 197 }
7dfc8ac2
TL
198 return 1;
199
d7837182 200 case TIMESTAMP:
ece6ea33 201 next_token (&val, cfile);
7dfc8ac2 202 parsed_time = parse_timestamp (cfile);
d7837182 203 break;
7dfc8ac2 204
1f814ff2 205 case SHARED_NETWORK:
ece6ea33 206 next_token (&val, cfile);
2d59f590
TL
207 if (type == SHARED_NET_DECL ||
208 type == HOST_DECL ||
ece6ea33
TL
209 type == SUBNET_DECL ||
210 type == CLASS_DECL) {
2d59f590 211 parse_warn ("shared-network parameters not %s.",
7dfc8ac2
TL
212 "allowed here");
213 skip_to_semi (cfile);
214 break;
1f814ff2 215 }
7dfc8ac2 216
2d59f590 217 parse_shared_net_declaration (cfile, group);
7dfc8ac2
TL
218 return 1;
219
685963dc 220 case SUBNET:
ece6ea33
TL
221 next_token (&val, cfile);
222 if (type == HOST_DECL || type == SUBNET_DECL ||
223 type == CLASS_DECL) {
2d59f590 224 parse_warn ("subnet declarations not allowed here.");
7dfc8ac2
TL
225 skip_to_semi (cfile);
226 return 1;
227 }
228
2d59f590 229 /* If we're in a subnet declaration, just do the parse. */
7dfc8ac2 230 if (group -> shared_network) {
2d59f590
TL
231 parse_subnet_declaration (cfile,
232 group -> shared_network);
7dfc8ac2
TL
233 break;
234 }
235
236 /* Otherwise, cons up a fake shared network structure
237 and populate it with the lone subnet... */
238
239 share = new_shared_network ("parse_statement");
240 if (!share)
241 error ("No memory for shared subnet");
242 share -> group = clone_group (group, "parse_statement:subnet");
243 share -> group -> shared_network = share;
244
2d59f590 245 parse_subnet_declaration (cfile, share);
7dfc8ac2
TL
246 if (share -> subnets) {
247 share -> interface =
248 share -> subnets -> interface;
249
250 n = piaddr (share -> subnets -> net);
251 t = malloc (strlen (n) + 1);
1f814ff2
TL
252 if (!t)
253 error ("no memory for subnet name");
254 strcpy (t, n);
255 share -> name = t;
256 enter_shared_network (share);
d7837182 257 }
7dfc8ac2
TL
258 return 1;
259
24a75c03 260 case VENDOR_CLASS:
ece6ea33
TL
261 next_token (&val, cfile);
262 if (type == CLASS_DECL) {
263 parse_warn ("class declarations not allowed here.");
264 skip_to_semi (cfile);
265 break;
266 }
2d59f590 267 parse_class_declaration (cfile, group, 0);
7dfc8ac2
TL
268 return 1;
269
24a75c03 270 case USER_CLASS:
ece6ea33
TL
271 next_token (&val, cfile);
272 if (type == CLASS_DECL) {
273 parse_warn ("class declarations not allowed here.");
274 skip_to_semi (cfile);
275 break;
276 }
2d59f590 277 parse_class_declaration (cfile, group, 1);
7dfc8ac2 278 return 1;
1f814ff2 279
ece6ea33
TL
280 case CLASS:
281 next_token (&val, cfile);
282 if (type == CLASS_DECL) {
283 parse_warn ("class declarations not allowed here.");
59b85ebd 284 skip_to_semi (cfile);
ece6ea33 285 break;
59b85ebd 286 }
ece6ea33
TL
287 parse_class_declaration (cfile, group, 2);
288 return 1;
59b85ebd 289
ece6ea33
TL
290 case SUBCLASS:
291 next_token (&val, cfile);
292 if (type == CLASS_DECL) {
293 parse_warn ("class declarations not allowed here.");
294 skip_to_semi (cfile);
7dfc8ac2 295 break;
7dfc8ac2 296 }
ece6ea33
TL
297 parse_class_declaration (cfile, group, 3);
298 return 1;
7dfc8ac2
TL
299
300 case HARDWARE:
ece6ea33 301 next_token (&val, cfile);
2d59f590 302 parse_hardware_param (cfile, &hardware);
7dfc8ac2
TL
303 if (host_decl)
304 host_decl -> interface = hardware;
305 else
2d59f590 306 parse_warn ("hardware address parameter %s",
7dfc8ac2
TL
307 "not allowed here.");
308 break;
309
310 case FIXED_ADDR:
ece6ea33 311 next_token (&val, cfile);
6f8fb41f
TL
312 cache = (struct option_cache *)0;
313 parse_fixed_addr_param (&cache, cfile);
7dfc8ac2
TL
314 if (host_decl)
315 host_decl -> fixed_addr = cache;
6f8fb41f 316 else {
2d59f590 317 parse_warn ("fixed-address parameter not %s",
7dfc8ac2 318 "allowed here.");
6f8fb41f
TL
319 option_cache_dereference (&cache, "parse_statement");
320 }
7dfc8ac2
TL
321 break;
322
323 case RANGE:
ece6ea33 324 next_token (&val, cfile);
2d59f590
TL
325 if (type != SUBNET_DECL || !group -> subnet) {
326 parse_warn ("range declaration not allowed here.");
7dfc8ac2 327 skip_to_semi (cfile);
2d59f590 328 return declaration;
7dfc8ac2
TL
329 }
330 parse_address_range (cfile, group -> subnet);
2d59f590 331 return declaration;
7dfc8ac2 332
99fd97cc 333 case ALLOW:
99fd97cc 334 case DENY:
ece6ea33 335 token = next_token (&val, cfile);
6f8fb41f
TL
336 cache = (struct option_cache *)0;
337 if (!parse_allow_deny (&cache, cfile,
338 token == ALLOW ? 1 : 0))
339 return declaration;
ece6ea33
TL
340 et = (struct executable_statement *)dmalloc (sizeof *et,
341 "allow/deny");
342 if (!et)
343 error ("no memory for %s statement",
344 token == ALLOW ? "allow" : "deny");
345 memset (et, 0, sizeof *et);
346 et -> op = supersede_option_statement;
347 et -> data.option = cache;
348 goto insert_statement;
99fd97cc 349
6f8fb41f
TL
350 case OPTION:
351 token = next_token (&val, cfile);
352 option = parse_option_name (cfile);
353 if (option) {
354 et = parse_option_statement
355 (cfile, 1, option,
356 supersede_option_statement);
357 if (!et)
358 return declaration;
359 goto insert_statement;
360 } else
361 return declaration;
362
363 break;
364
d7837182 365 default:
ece6ea33
TL
366 et = (struct executable_statement *)0;
367 if (is_identifier (token)) {
368 option = ((struct option *)
369 hash_lookup (server_universe.hash,
370 (unsigned char *)val, 0));
371 if (option) {
6f8fb41f 372 token = next_token (&val, cfile);
ece6ea33
TL
373 et = parse_option_statement
374 (cfile, 1, option,
375 supersede_option_statement);
376 if (!et)
377 return declaration;
378 }
379 }
380
381 if (!et) {
382 lose = 0;
383 et = parse_executable_statement (cfile, &lose);
384 if (!et) {
385 if (declaration && !lose)
386 parse_warn ("expecting a %s.",
387 "declaration");
6f8fb41f 388 else if (!lose)
ece6ea33
TL
389 parse_warn ("expecting a parameter%s.",
390 " or declaration");
391 skip_to_semi (cfile);
392 return declaration;
393 }
394 }
395 if (!et) {
396 parse_warn ("expecting a %sdeclaration",
397 declaration ? "" : "parameter or ");
398 return declaration;
399 }
400 insert_statement:
401 if (group -> statements) {
402 for (ep = group -> statements; ep -> next;
403 ep = ep -> next)
404 ;
405 ep -> next = et;
406
6f8fb41f
TL
407 } else
408 group -> statements = et;
409 return declaration;
d7837182 410 }
1f814ff2 411
2d59f590
TL
412 if (declaration) {
413 parse_warn ("parameters not allowed after first declaration.");
7dfc8ac2 414 return 1;
1f814ff2 415 }
7dfc8ac2
TL
416
417 return 0;
d7837182
TL
418}
419
99fd97cc
TL
420/* allow-deny-keyword :== BOOTP
421 | BOOTING
422 | DYNAMIC_BOOTP
423 | UNKNOWN_CLIENTS */
424
6f8fb41f
TL
425int parse_allow_deny (oc, cfile, flag)
426 struct option_cache **oc;
99fd97cc 427 FILE *cfile;
99fd97cc
TL
428 int flag;
429{
6f8fb41f 430 enum dhcp_token token;
99fd97cc 431 char *val;
ece6ea33 432 char rf = flag;
6f8fb41f
TL
433 struct expression *data = (struct expression *)0;
434 int status;
435
436 if (!make_const_data (&data, &rf, 1, 0, 1))
437 return 0;
99fd97cc
TL
438
439 token = next_token (&val, cfile);
440 switch (token) {
441 case BOOTP:
6f8fb41f
TL
442 status = option_cache (oc, (struct data_string *)0, data,
443 &server_options [SV_ALLOW_BOOTP]);
99fd97cc
TL
444 break;
445
446 case BOOTING:
6f8fb41f
TL
447 status = option_cache (oc, (struct data_string *)0, data,
448 &server_options [SV_ALLOW_BOOTING]);
99fd97cc
TL
449 break;
450
451 case DYNAMIC_BOOTP:
6f8fb41f
TL
452 status = option_cache (oc, (struct data_string *)0, data,
453 &server_options [SV_DYNAMIC_BOOTP]);
99fd97cc
TL
454 break;
455
456 case UNKNOWN_CLIENTS:
6f8fb41f
TL
457 status = (option_cache
458 (oc, (struct data_string *)0, data,
459 &server_options [SV_BOOT_UNKNOWN_CLIENTS]));
99fd97cc
TL
460 break;
461
462 default:
463 parse_warn ("expecting allow/deny key");
464 skip_to_semi (cfile);
6f8fb41f 465 return 0;
99fd97cc
TL
466 }
467 parse_semi (cfile);
6f8fb41f 468 return status;
99fd97cc
TL
469}
470
5376e3e9
TL
471/* boolean :== ON SEMI | OFF SEMI | TRUE SEMI | FALSE SEMI */
472
473int parse_boolean (cfile)
474 FILE *cfile;
475{
6f8fb41f 476 enum dhcp_token token;
5376e3e9
TL
477 char *val;
478 int rv;
479
480 token = next_token (&val, cfile);
481 if (!strcasecmp (val, "true")
482 || !strcasecmp (val, "on"))
b179c997 483 rv = 1;
5376e3e9
TL
484 else if (!strcasecmp (val, "false")
485 || !strcasecmp (val, "off"))
486 rv = 0;
487 else {
488 parse_warn ("boolean value (true/false/on/off) expected");
489 skip_to_semi (cfile);
490 return 0;
491 }
492 parse_semi (cfile);
493 return rv;
494}
495
7dfc8ac2
TL
496/* Expect a left brace; if there isn't one, skip over the rest of the
497 statement and return zero; otherwise, return 1. */
498
499int parse_lbrace (cfile)
500 FILE *cfile;
501{
6f8fb41f 502 enum dhcp_token token;
7dfc8ac2
TL
503 char *val;
504
505 token = next_token (&val, cfile);
506 if (token != LBRACE) {
507 parse_warn ("expecting left brace.");
508 skip_to_semi (cfile);
509 return 0;
510 }
511 return 1;
d7837182
TL
512}
513
7dfc8ac2 514
2d59f590 515/* host-declaration :== hostname RBRACE parameters declarations LBRACE */
d7837182 516
2d59f590 517void parse_host_declaration (cfile, group)
d7837182 518 FILE *cfile;
7dfc8ac2 519 struct group *group;
d7837182
TL
520{
521 char *val;
6f8fb41f 522 enum dhcp_token token;
7dfc8ac2 523 struct host_decl *host;
f3c3d674 524 char *name;
2d59f590 525 int declaration = 0;
7dfc8ac2 526
f3c3d674
TL
527 token = peek_token (&val, cfile);
528 if (token != LBRACE) {
529 name = parse_host_name (cfile);
530 if (!name)
531 return;
532 } else {
533 name = (char *)0;
534 }
7dfc8ac2
TL
535
536 host = (struct host_decl *)dmalloc (sizeof (struct host_decl),
2d59f590 537 "parse_host_declaration");
7dfc8ac2
TL
538 if (!host)
539 error ("can't allocate host decl struct %s.", name);
540
541 host -> name = name;
2d59f590 542 host -> group = clone_group (group, "parse_host_declaration");
7dfc8ac2
TL
543
544 if (!parse_lbrace (cfile))
545 return;
d7837182 546
d7837182
TL
547 do {
548 token = peek_token (&val, cfile);
7dfc8ac2 549 if (token == RBRACE) {
d7837182
TL
550 token = next_token (&val, cfile);
551 break;
552 }
5376e3e9
TL
553 if (token == EOF) {
554 token = next_token (&val, cfile);
555 parse_warn ("unexpected end of file");
556 break;
557 }
2d59f590
TL
558 declaration = parse_statement (cfile, host -> group,
559 HOST_DECL, host,
560 declaration);
d7837182 561 } while (1);
7dfc8ac2
TL
562
563 enter_host (host);
d7837182
TL
564}
565
2d59f590 566/* class-declaration :== STRING LBRACE parameters declarations RBRACE
24a75c03
TL
567*/
568
2d59f590 569void parse_class_declaration (cfile, group, type)
24a75c03 570 FILE *cfile;
7dfc8ac2 571 struct group *group;
24a75c03
TL
572 int type;
573{
574 char *val;
6f8fb41f 575 enum dhcp_token token;
ece6ea33 576 struct class *class, *pc;
f4d0f440 577 int declaration = 0;
ece6ea33
TL
578 int lose;
579 struct data_string data;
580 char *name;
581 struct executable_statement *stmt = (struct executable_statement *)0;
582 struct expression *expr;
24a75c03
TL
583
584 token = next_token (&val, cfile);
585 if (token != STRING) {
586 parse_warn ("Expecting class name");
587 skip_to_semi (cfile);
7dfc8ac2 588 return;
24a75c03
TL
589 }
590
ece6ea33
TL
591 /* See if there's already a class with the specified name. */
592 pc = (struct class *)find_class (val);
593
594 /* If this isn't a subclass, we're updating an existing class. */
595 if (pc && type != 0 && type != 1 && type != 3) {
596 class = pc;
597 pc = (struct class *)0;
598 }
599
600 /* If this _is_ a subclass, there _must_ be a class with the
601 same name. */
602 if (!pc && (type == 0 || type == 1 || type == 3)) {
603 parse_warn ("no class named %s", val);
604 skip_to_semi (cfile);
605 return;
606 }
607
608 /* The old vendor-class and user-class declarations had an implicit
609 match. We don't do the implicit match anymore. Instead, for
610 backward compatibility, we have an implicit-vendor-class and an
611 implicit-user-class. vendor-class and user-class declarations
612 are turned into subclasses of the implicit classes, and the
613 spawn expression of the implicit classes extracts the contents of
614 the vendor class or user class. */
615 if (type == 0 || type == 1) {
616 data.len = strlen (val);
6f8fb41f
TL
617 data.buffer = (struct buffer *)0;
618 if (!buffer_allocate (&data.buffer,
619 data.len + 1, "parse_class_declaration"))
620 error ("no memoy for class name.");
621 data.data = &data.buffer -> data [0];
ece6ea33
TL
622 data.terminated = 1;
623
624 name = type ? "implicit-vendor-class" : "implicit-user-class";
625 } else if (type == 2) {
626 if (!(name = dmalloc (strlen (val) + 1,
627 "parse_class_declaration")))
628 error ("No memory for class name %s.", val);
629 strcpy (name, val);
630 } else {
631 name = (char *)0;
632 }
633
634 /* If this is a straight subclass, parse the hash string. */
635 if (type == 3) {
636 token = peek_token (&val, cfile);
637 if (token == STRING) {
638 token = next_token (&val, cfile);
639 data.len = strlen (val);
6f8fb41f
TL
640 data.buffer = (struct buffer *)0;
641 if (!buffer_allocate (&data.buffer, data.len + 1,
642 "parse_class_declaration"))
643 return;
ece6ea33 644 data.terminated = 1;
6f8fb41f
TL
645 data.data = &data.buffer -> data [0];
646 strcpy (data.data, val);
ece6ea33 647 } else if (token == NUMBER_OR_NAME || token == NUMBER) {
6f8fb41f
TL
648 memset (&data, 0, sizeof data);
649 if (!parse_cshl (&data, cfile))
ece6ea33
TL
650 return;
651 data.terminated = 0;
652 data.buffer = 0;
653 }
654 }
655
656 /* See if there's already a class in the hash table matching the
657 hash data. */
658 if (type == 0 || type == 1 || type == 3)
659 class = ((struct class *)
660 hash_lookup (pc -> hash, data.data, data.len));
661
662 /* If we didn't find an existing class, allocate a new one. */
663 if (!class) {
664 /* Allocate the class structure... */
665 class = (struct class *)dmalloc (sizeof (struct class),
666 "parse_class_declaration");
667 if (!class)
668 error ("No memory for class %s.", val);
669 memset (class, 0, sizeof *class);
670 if (pc) {
671 class -> group =
672 clone_group (pc -> group,
673 "parse_class_declaration");
674 add_hash (pc -> hash,
675 data.data, data.len, (unsigned char *)class);
676 } else {
677 class -> group =
678 clone_group (group, "parse_class_declaration");
679 }
680
681 /* If this is an implicit vendor or user class, add a
682 statement that causes the vendor or user class ID to
683 be sent back in the reply. */
684 if (type == 0 || type == 1) {
685 stmt = ((struct executable_statement *)
686 dmalloc (sizeof (struct executable_statement),
687 "implicit user/vendor class"));
688 if (!stmt)
689 error ("no memory for class statement.");
690 memset (stmt, 0, sizeof *stmt);
691 stmt -> op = supersede_option_statement;
6f8fb41f
TL
692 if (option_cache_allocate (&stmt -> data.option,
693 "parse_class_statement")) {
694 stmt -> data.option -> data = data;
695 stmt -> data.option -> option =
696 dhcp_universe.options
697 [type
698 ? DHO_DHCP_CLASS_IDENTIFIER
699 : DHO_DHCP_USER_CLASS_ID];
700 }
ece6ea33
TL
701 class -> statements = stmt;
702 }
703 }
7dfc8ac2
TL
704
705 if (!parse_lbrace (cfile))
706 return;
24a75c03
TL
707
708 do {
709 token = peek_token (&val, cfile);
7dfc8ac2 710 if (token == RBRACE) {
24a75c03
TL
711 token = next_token (&val, cfile);
712 break;
5376e3e9
TL
713 } else if (token == EOF) {
714 token = next_token (&val, cfile);
715 parse_warn ("unexpected end of file");
716 break;
ece6ea33
TL
717 } else if (token == MATCH) {
718 if (pc) {
719 parse_warn ("invalid match in subclass.");
720 skip_to_semi (cfile);
721 break;
722 }
723 if (class -> expr) {
724 parse_warn ("can't override match.");
725 skip_to_semi (cfile);
726 break;
727 }
728 token = next_token (&val, cfile);
729 token = next_token (&val, cfile);
730 if (token != IF) {
731 parse_warn ("expecting if after match");
732 skip_to_semi (cfile);
733 break;
734 }
6f8fb41f
TL
735 parse_boolean_expression (&class -> expr, cfile,
736 &lose);
ece6ea33
TL
737 if (lose)
738 break;
6f8fb41f
TL
739#if defined (DEBUG_EXPRESSION_PARSE)
740 print_expression ("class match", class -> expr);
741#endif
ece6ea33
TL
742 } else if (token == SPAWN) {
743 if (pc) {
744 parse_warn ("invalid spawn in subclass.");
745 skip_to_semi (cfile);
746 break;
747 }
748 if (class -> spawn) {
749 parse_warn ("can't override spawn.");
750 skip_to_semi (cfile);
751 break;
752 }
753 token = next_token (&val, cfile);
754 token = next_token (&val, cfile);
755 if (token != WITH) {
756 parse_warn ("expecting with after spawn");
757 skip_to_semi (cfile);
758 break;
759 }
6f8fb41f 760 parse_data_expression (&class -> spawn, cfile, &lose);
ece6ea33
TL
761 if (lose)
762 break;
6f8fb41f
TL
763#if defined (DEBUG_EXPRESSION_PARSE)
764 print_expression ("class match", class -> spawn);
765#endif
24a75c03 766 } else {
2d59f590
TL
767 declaration = parse_statement (cfile, class -> group,
768 CLASS_DECL,
769 (struct host_decl *)0,
770 declaration);
24a75c03
TL
771 }
772 } while (1);
773}
774
2d59f590
TL
775/* shared-network-declaration :==
776 hostname LBRACE declarations parameters RBRACE */
1f814ff2 777
2d59f590 778void parse_shared_net_declaration (cfile, group)
1f814ff2 779 FILE *cfile;
7dfc8ac2 780 struct group *group;
1f814ff2
TL
781{
782 char *val;
6f8fb41f 783 enum dhcp_token token;
1f814ff2 784 struct shared_network *share;
1f814ff2 785 char *name;
2d59f590 786 int declaration = 0;
1f814ff2 787
2d59f590 788 share = new_shared_network ("parse_shared_net_declaration");
1f814ff2
TL
789 if (!share)
790 error ("No memory for shared subnet");
791 share -> leases = (struct lease *)0;
792 share -> last_lease = (struct lease *)0;
793 share -> insertion_point = (struct lease *)0;
794 share -> next = (struct shared_network *)0;
9ab92650 795 share -> interface = (struct interface_info *)0;
2d59f590 796 share -> group = clone_group (group, "parse_shared_net_declaration");
7dfc8ac2 797 share -> group -> shared_network = share;
1f814ff2
TL
798
799 /* Get the name of the shared network... */
7dfc8ac2
TL
800 token = peek_token (&val, cfile);
801 if (token == STRING) {
802 token = next_token (&val, cfile);
803
804 if (val [0] == 0) {
805 parse_warn ("zero-length shared network name");
806 val = "<no-name-given>";
807 }
808 name = malloc (strlen (val) + 1);
809 if (!name)
810 error ("no memory for shared network name");
811 strcpy (name, val);
812 } else {
813 name = parse_host_name (cfile);
814 if (!name)
815 return;
1f814ff2 816 }
1f814ff2
TL
817 share -> name = name;
818
7dfc8ac2
TL
819 if (!parse_lbrace (cfile))
820 return;
821
1f814ff2 822 do {
7dfc8ac2
TL
823 token = peek_token (&val, cfile);
824 if (token == RBRACE) {
825 token = next_token (&val, cfile);
826 if (!share -> subnets) {
1f814ff2
TL
827 parse_warn ("empty shared-network decl");
828 return;
829 }
1f814ff2
TL
830 enter_shared_network (share);
831 return;
5376e3e9
TL
832 } else if (token == EOF) {
833 token = next_token (&val, cfile);
834 parse_warn ("unexpected end of file");
835 break;
1f814ff2 836 }
5376e3e9 837
2d59f590
TL
838 declaration = parse_statement (cfile, share -> group,
839 SHARED_NET_DECL,
840 (struct host_decl *)0,
841 declaration);
1f814ff2
TL
842 } while (1);
843}
844
2d59f590
TL
845/* subnet-declaration :==
846 net NETMASK netmask RBRACE parameters declarations LBRACE */
685963dc 847
2d59f590 848void parse_subnet_declaration (cfile, share)
685963dc 849 FILE *cfile;
1f814ff2 850 struct shared_network *share;
685963dc
TL
851{
852 char *val;
6f8fb41f 853 enum dhcp_token token;
7dfc8ac2
TL
854 struct subnet *subnet, *t;
855 struct iaddr iaddr;
685963dc
TL
856 unsigned char addr [4];
857 int len = sizeof addr;
2d59f590 858 int declaration = 0;
685963dc 859
2d59f590 860 subnet = new_subnet ("parse_subnet_declaration");
685963dc
TL
861 if (!subnet)
862 error ("No memory for new subnet");
1f814ff2 863 subnet -> shared_network = share;
7dfc8ac2 864 subnet -> group = clone_group (share -> group,
2d59f590 865 "parse_subnet_declaration");
7dfc8ac2 866 subnet -> group -> subnet = subnet;
685963dc
TL
867
868 /* Get the network number... */
7dfc8ac2
TL
869 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
870 return;
871 memcpy (iaddr.iabuf, addr, len);
872 iaddr.len = len;
873 subnet -> net = iaddr;
685963dc
TL
874
875 token = next_token (&val, cfile);
876 if (token != NETMASK) {
877 parse_warn ("Expecting netmask");
878 skip_to_semi (cfile);
7dfc8ac2 879 return;
685963dc
TL
880 }
881
882 /* Get the netmask... */
7dfc8ac2
TL
883 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
884 return;
885 memcpy (iaddr.iabuf, addr, len);
886 iaddr.len = len;
887 subnet -> netmask = iaddr;
685963dc
TL
888
889 enter_subnet (subnet);
890
7dfc8ac2
TL
891 if (!parse_lbrace (cfile))
892 return;
893
685963dc
TL
894 do {
895 token = peek_token (&val, cfile);
7dfc8ac2
TL
896 if (token == RBRACE) {
897 token = next_token (&val, cfile);
685963dc 898 break;
5376e3e9
TL
899 } else if (token == EOF) {
900 token = next_token (&val, cfile);
901 parse_warn ("unexpected end of file");
902 break;
7dfc8ac2 903 }
2d59f590
TL
904 declaration = parse_statement (cfile, subnet -> group,
905 SUBNET_DECL,
906 (struct host_decl *)0,
907 declaration);
685963dc 908 } while (1);
1f814ff2 909
6cdd0d0d 910 /* Add the subnet to the list of subnets in this shared net. */
7dfc8ac2
TL
911 if (!share -> subnets)
912 share -> subnets = subnet;
913 else {
914 for (t = share -> subnets;
6cdd0d0d 915 t -> next_sibling; t = t -> next_sibling)
7dfc8ac2 916 ;
6cdd0d0d 917 t -> next_sibling = subnet;
7dfc8ac2 918 }
685963dc
TL
919}
920
2d59f590 921/* group-declaration :== RBRACE parameters declarations LBRACE */
7dfc8ac2 922
2d59f590 923void parse_group_declaration (cfile, group)
685963dc 924 FILE *cfile;
7dfc8ac2 925 struct group *group;
685963dc
TL
926{
927 char *val;
6f8fb41f 928 enum dhcp_token token;
7dfc8ac2 929 struct group *g;
2d59f590 930 int declaration = 0;
685963dc 931
2d59f590 932 g = clone_group (group, "parse_group_declaration");
685963dc 933
7dfc8ac2
TL
934 if (!parse_lbrace (cfile))
935 return;
d7837182 936
7dfc8ac2
TL
937 do {
938 token = peek_token (&val, cfile);
5376e3e9
TL
939 if (token == RBRACE) {
940 token = next_token (&val, cfile);
7dfc8ac2 941 break;
5376e3e9
TL
942 } else if (token == EOF) {
943 token = next_token (&val, cfile);
944 parse_warn ("unexpected end of file");
945 break;
946 }
2d59f590
TL
947 declaration = parse_statement (cfile, g, GROUP_DECL,
948 (struct host_decl *)0,
949 declaration);
7dfc8ac2 950 } while (1);
d7837182
TL
951}
952
2d59f590
TL
953/* fixed-addr-parameter :== ip-addrs-or-hostnames SEMI
954 ip-addrs-or-hostnames :== ip-addr-or-hostname
955 | ip-addrs-or-hostnames ip-addr-or-hostname */
d7837182 956
6f8fb41f
TL
957int parse_fixed_addr_param (oc, cfile)
958 struct option_cache **oc;
d7837182 959 FILE *cfile;
d7837182 960{
1f814ff2 961 char *val;
6f8fb41f 962 enum dhcp_token token;
ece6ea33 963 struct expression *expr = (struct expression *)0;
6f8fb41f
TL
964 struct expression *tmp, *new;
965 int status;
1f814ff2
TL
966
967 do {
6f8fb41f
TL
968 tmp = (struct expression *)0;
969 if (parse_ip_addr_or_hostname (&tmp, cfile, 1)) {
028a8588
TL
970 if (expr) {
971 new = (struct expression *)0;
972 status = make_concat (&new, expr, tmp);
973 expression_dereference
974 (&expr, "parse_fixed_addr_param");
975 expression_dereference
976 (&tmp, "parse_fixed_addr_param");
977 if (status)
978 return 0;
979 expr = new;
980 } else
981 expr = tmp;
6f8fb41f
TL
982 } else {
983 if (expr)
984 expression_dereference
985 (&expr, "parse_fixed_addr_param");
986 return 0;
987 }
1f814ff2 988 token = peek_token (&val, cfile);
5376e3e9 989 if (token == COMMA)
1f814ff2
TL
990 token = next_token (&val, cfile);
991 } while (token == COMMA);
7dfc8ac2 992
6f8fb41f
TL
993 if (!parse_semi (cfile)) {
994 if (expr)
995 expression_dereference (&expr,
996 "parse_fixed_addr_param");
997 return 0;
998 }
999 status = option_cache (oc, (struct data_string *)0, expr,
1000 (struct option *)0);
1001 expression_dereference (&expr, "parse_fixed_addr_param");
1002 return status;
d7837182
TL
1003}
1004
5376e3e9 1005/* timestamp :== date
d7837182
TL
1006
1007 Timestamps are actually not used in dhcpd.conf, which is a static file,
5376e3e9
TL
1008 but rather in the database file and the journal file. (Okay, actually
1009 they're not even used there yet). */
d7837182 1010
7dfc8ac2 1011TIME parse_timestamp (cfile)
d7837182 1012 FILE *cfile;
d7837182 1013{
089fb364 1014 TIME rv;
089fb364 1015
7dfc8ac2 1016 rv = parse_date (cfile);
089fb364 1017 return rv;
d7837182
TL
1018}
1019
2d59f590
TL
1020/* lease_declaration :== LEASE ip_address LBRACE lease_parameters RBRACE
1021
1022 lease_parameters :== <nil>
1023 | lease_parameter
1024 | lease_parameters lease_parameter
1025
1026 lease_parameter :== STARTS date
1027 | ENDS date
1028 | TIMESTAMP date
1029 | HARDWARE hardware-parameter
1030 | UID hex_numbers SEMI
ccf5778a
TL
1031 | HOSTNAME hostname SEMI
1032 | CLIENT_HOSTNAME hostname SEMI
2d59f590
TL
1033 | CLASS identifier SEMI
1034 | DYNAMIC_BOOTP SEMI */
1035
1036struct lease *parse_lease_declaration (cfile)
d7837182 1037 FILE *cfile;
d7837182
TL
1038{
1039 char *val;
6f8fb41f 1040 enum dhcp_token token;
d7837182
TL
1041 unsigned char addr [4];
1042 int len = sizeof addr;
d7837182
TL
1043 int seenmask = 0;
1044 int seenbit;
1045 char tbuf [32];
d7837182
TL
1046 static struct lease lease;
1047
9375101b
TL
1048 /* Zap the lease structure... */
1049 memset (&lease, 0, sizeof lease);
1050
d7837182 1051 /* Get the address for which the lease has been issued. */
7dfc8ac2
TL
1052 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
1053 return (struct lease *)0;
089fb364
TL
1054 memcpy (lease.ip_addr.iabuf, addr, len);
1055 lease.ip_addr.len = len;
d7837182 1056
7dfc8ac2
TL
1057 if (!parse_lbrace (cfile))
1058 return (struct lease *)0;
1059
d7837182
TL
1060 do {
1061 token = next_token (&val, cfile);
7dfc8ac2 1062 if (token == RBRACE)
d7837182 1063 break;
5376e3e9
TL
1064 else if (token == EOF) {
1065 parse_warn ("unexpected end of file");
1066 break;
1067 }
ece6ea33 1068 strncpy (tbuf, val, sizeof tbuf);
d7837182
TL
1069 tbuf [(sizeof tbuf) - 1] = 0;
1070
1071 /* Parse any of the times associated with the lease. */
1072 if (token == STARTS || token == ENDS || token == TIMESTAMP) {
1073 TIME t;
7dfc8ac2 1074 t = parse_date (cfile);
d7837182
TL
1075 switch (token) {
1076 case STARTS:
1077 seenbit = 1;
1078 lease.starts = t;
1079 break;
1080
1081 case ENDS:
1082 seenbit = 2;
1083 lease.ends = t;
1084 break;
1085
1086 case TIMESTAMP:
1087 seenbit = 4;
1088 lease.timestamp = t;
1089 break;
19d868b2
TL
1090
1091 default:
1092 /*NOTREACHED*/
1093 seenbit = 0;
1094 break;
d7837182
TL
1095 }
1096 } else {
1097 switch (token) {
1098 /* Colon-seperated hexadecimal octets... */
1099 case UID:
1100 seenbit = 8;
9375101b
TL
1101 token = peek_token (&val, cfile);
1102 if (token == STRING) {
c4f1fbb0 1103 token = next_token (&val, cfile);
9375101b 1104 lease.uid_len = strlen (val) + 1;
7e8381e5
TL
1105 lease.uid = (unsigned char *)
1106 malloc (lease.uid_len);
c256bae9
TL
1107 if (!lease.uid) {
1108 warn ("no space for uid");
1109 return (struct lease *)0;
1110 }
7e8381e5 1111 memcpy (lease.uid, val, lease.uid_len);
9375101b 1112 } else {
7e8381e5
TL
1113 lease.uid_len = 0;
1114 lease.uid = parse_numeric_aggregate
7dfc8ac2 1115 (cfile, (unsigned char *)0,
9375101b 1116 &lease.uid_len, ':', 16, 8);
c256bae9
TL
1117 if (!lease.uid) {
1118 warn ("no space for uid");
7dfc8ac2 1119 return (struct lease *)0;
c256bae9 1120 }
9375101b 1121 if (lease.uid_len == 0) {
c256bae9 1122 lease.uid = (unsigned char *)0;
9375101b 1123 parse_warn ("zero-length uid");
c4f1fbb0 1124 seenbit = 0;
9375101b
TL
1125 break;
1126 }
1127 }
d7837182
TL
1128 if (!lease.uid) {
1129 error ("No memory for lease uid");
1130 }
d7837182
TL
1131 break;
1132
d7837182
TL
1133 case CLASS:
1134 seenbit = 32;
1135 token = next_token (&val, cfile);
1136 if (!is_identifier (token)) {
1137 if (token != SEMI)
1138 skip_to_semi (cfile);
7dfc8ac2 1139 return (struct lease *)0;
d7837182
TL
1140 }
1141 /* for now, we aren't using this. */
1142 break;
1143
1144 case HARDWARE:
1145 seenbit = 64;
2d59f590 1146 parse_hardware_param (cfile,
7dfc8ac2 1147 &lease.hardware_addr);
d7837182
TL
1148 break;
1149
1f814ff2
TL
1150 case DYNAMIC_BOOTP:
1151 seenbit = 128;
1152 lease.flags |= BOOTP_LEASE;
1153 break;
1154
4006d804
TL
1155 case ABANDONED:
1156 seenbit = 256;
1157 lease.flags |= ABANDONED_LEASE;
1158 break;
1159
ccf5778a
TL
1160 case HOSTNAME:
1161 seenbit = 512;
56a89931
TL
1162 token = peek_token (&val, cfile);
1163 if (token == STRING)
1164 lease.hostname = parse_string (cfile);
1165 else
1166 lease.hostname =
1167 parse_host_name (cfile);
ccf5778a
TL
1168 if (!lease.hostname) {
1169 seenbit = 0;
1170 return (struct lease *)0;
1171 }
1172 break;
1173
1174 case CLIENT_HOSTNAME:
05a8d03c 1175 seenbit = 1024;
200d216c
TL
1176 token = peek_token (&val, cfile);
1177 if (token == STRING)
1178 lease.client_hostname =
1179 parse_string (cfile);
1180 else
1181 lease.client_hostname =
1182 parse_host_name (cfile);
ccf5778a
TL
1183 break;
1184
d7837182 1185 default:
7dfc8ac2 1186 skip_to_semi (cfile);
19d868b2 1187 seenbit = 0;
7dfc8ac2
TL
1188 return (struct lease *)0;
1189 }
1190
ffba7052 1191 if (token != HARDWARE && token != STRING) {
7dfc8ac2
TL
1192 token = next_token (&val, cfile);
1193 if (token != SEMI) {
1194 parse_warn ("semicolon expected.");
1195 skip_to_semi (cfile);
1196 return (struct lease *)0;
1197 }
d7837182
TL
1198 }
1199 }
1200 if (seenmask & seenbit) {
2d59f590 1201 parse_warn ("Too many %s parameters in lease %s\n",
089fb364 1202 tbuf, piaddr (lease.ip_addr));
d7837182
TL
1203 } else
1204 seenmask |= seenbit;
7dfc8ac2 1205
d7837182
TL
1206 } while (1);
1207 return &lease;
1208}
1209
2d59f590
TL
1210/* address-range-declaration :== ip-address ip-address SEMI
1211 | DYNAMIC_BOOTP ip-address ip-address SEMI */
d7837182 1212
7dfc8ac2 1213void parse_address_range (cfile, subnet)
d7837182 1214 FILE *cfile;
685963dc 1215 struct subnet *subnet;
d7837182 1216{
685963dc 1217 struct iaddr low, high;
d7837182
TL
1218 unsigned char addr [4];
1219 int len = sizeof addr;
6f8fb41f 1220 enum dhcp_token token;
089fb364 1221 char *val;
1f814ff2
TL
1222 int dynamic = 0;
1223
1224 if ((token = peek_token (&val, cfile)) == DYNAMIC_BOOTP) {
5376e3e9 1225 token = next_token (&val, cfile);
ece6ea33 1226 dynamic = 1;
1f814ff2 1227 }
d7837182
TL
1228
1229 /* Get the bottom address in the range... */
7dfc8ac2
TL
1230 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
1231 return;
089fb364
TL
1232 memcpy (low.iabuf, addr, len);
1233 low.len = len;
d7837182 1234
2d59f590
TL
1235 /* Only one address? */
1236 token = peek_token (&val, cfile);
1237 if (token == SEMI)
1238 high = low;
1239 else {
d7837182 1240 /* Get the top address in the range... */
2d59f590
TL
1241 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
1242 return;
1243 memcpy (high.iabuf, addr, len);
1244 high.len = len;
1245 }
d7837182 1246
7dfc8ac2
TL
1247 token = next_token (&val, cfile);
1248 if (token != SEMI) {
1249 parse_warn ("semicolon expected.");
1250 skip_to_semi (cfile);
1251 return;
1252 }
1253
d7837182 1254 /* Create the new address range... */
1f814ff2 1255 new_address_range (low, high, subnet, dynamic);
d7837182
TL
1256}
1257