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