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