]> git.ipfire.org Git - thirdparty/dhcp.git/blame - server/confpars.c
Update version info and changelog
[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[] =
f3fe382d 46"$Id: confpars.c,v 1.146 2001/07/10 20:36:02 brister 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 2031 }
f3fe382d
JB
2032 } else if (type == 3 && dynamic) {
2033 class->flags |= CLASS_DECL_DYNAMIC;
de94ca72 2034 }
f3fe382d 2035
899d754f 2036 if (cp) /* should always be 0??? */
20916cae
TL
2037 status = class_reference (cp, class, MDL);
2038 class_dereference (&class, MDL);
2039 if (pc)
2040 class_dereference (&pc, MDL);
2041 return cp ? (status == ISC_R_SUCCESS) : 1;
24a75c03
TL
2042}
2043
2d59f590
TL
2044/* shared-network-declaration :==
2045 hostname LBRACE declarations parameters RBRACE */
1f814ff2 2046
2d59f590 2047void parse_shared_net_declaration (cfile, group)
35454d8a 2048 struct parse *cfile;
7dfc8ac2 2049 struct group *group;
1f814ff2 2050{
b1b7b521 2051 const char *val;
6f8fb41f 2052 enum dhcp_token token;
1f814ff2 2053 struct shared_network *share;
1f814ff2 2054 char *name;
2d59f590 2055 int declaration = 0;
20916cae 2056 isc_result_t status;
1f814ff2 2057
20916cae
TL
2058 share = (struct shared_network *)0;
2059 status = shared_network_allocate (&share, MDL);
2060 if (status != ISC_R_SUCCESS)
2061 log_fatal ("Can't allocate shared subnet: %s",
2062 isc_result_totext (status));
2063 clone_group (&share -> group, group, MDL);
2064 shared_network_reference (&share -> group -> shared_network,
2065 share, MDL);
1f814ff2
TL
2066
2067 /* Get the name of the shared network... */
b3519f23 2068 token = peek_token (&val, (unsigned *)0, cfile);
7dfc8ac2 2069 if (token == STRING) {
b3519f23 2070 token = next_token (&val, (unsigned *)0, cfile);
7dfc8ac2
TL
2071
2072 if (val [0] == 0) {
35454d8a 2073 parse_warn (cfile, "zero-length shared network name");
7dfc8ac2
TL
2074 val = "<no-name-given>";
2075 }
436f1c8c 2076 name = dmalloc (strlen (val) + 1, MDL);
7dfc8ac2 2077 if (!name)
8ae2d595 2078 log_fatal ("no memory for shared network name");
7dfc8ac2
TL
2079 strcpy (name, val);
2080 } else {
2081 name = parse_host_name (cfile);
20916cae 2082 if (!name) {
6c5223f5
TL
2083 parse_warn (cfile,
2084 "expecting a name for shared-network");
2085 skip_to_semi (cfile);
20916cae 2086 shared_network_dereference (&share, MDL);
7dfc8ac2 2087 return;
20916cae 2088 }
1f814ff2 2089 }
1f814ff2
TL
2090 share -> name = name;
2091
20916cae
TL
2092 if (!parse_lbrace (cfile)) {
2093 shared_network_dereference (&share, MDL);
7dfc8ac2 2094 return;
20916cae 2095 }
7dfc8ac2 2096
1f814ff2 2097 do {
b3519f23 2098 token = peek_token (&val, (unsigned *)0, cfile);
7dfc8ac2 2099 if (token == RBRACE) {
b3519f23 2100 token = next_token (&val, (unsigned *)0, cfile);
20916cae 2101 if (!share -> subnets)
4bd8800e
TL
2102 parse_warn (cfile,
2103 "empty shared-network decl");
20916cae
TL
2104 else
2105 enter_shared_network (share);
2106 shared_network_dereference (&share, MDL);
1f814ff2 2107 return;
0b69dcc8 2108 } else if (token == END_OF_FILE) {
b3519f23 2109 token = next_token (&val, (unsigned *)0, cfile);
35454d8a 2110 parse_warn (cfile, "unexpected end of file");
5376e3e9 2111 break;
79931db3 2112 } else if (token == INTERFACE) {
b3519f23
TL
2113 token = next_token (&val, (unsigned *)0, cfile);
2114 token = next_token (&val, (unsigned *)0, cfile);
79931db3
TL
2115 new_shared_network_interface (cfile, share, val);
2116 if (!parse_semi (cfile))
2117 break;
2118 continue;
1f814ff2 2119 }
5376e3e9 2120
2d59f590
TL
2121 declaration = parse_statement (cfile, share -> group,
2122 SHARED_NET_DECL,
2123 (struct host_decl *)0,
2124 declaration);
1f814ff2 2125 } while (1);
20916cae 2126 shared_network_dereference (&share, MDL);
1f814ff2
TL
2127}
2128
2d59f590
TL
2129/* subnet-declaration :==
2130 net NETMASK netmask RBRACE parameters declarations LBRACE */
685963dc 2131
2d59f590 2132void parse_subnet_declaration (cfile, share)
35454d8a 2133 struct parse *cfile;
1f814ff2 2134 struct shared_network *share;
685963dc 2135{
b1b7b521 2136 const char *val;
6f8fb41f 2137 enum dhcp_token token;
763adef1 2138 struct subnet *subnet, *t, *u;
7dfc8ac2 2139 struct iaddr iaddr;
685963dc 2140 unsigned char addr [4];
b1b7b521 2141 unsigned len = sizeof addr;
2d59f590 2142 int declaration = 0;
79931db3 2143 struct interface_info *ip;
20916cae 2144 isc_result_t status;
685963dc 2145
20916cae
TL
2146 subnet = (struct subnet *)0;
2147 status = subnet_allocate (&subnet, MDL);
2148 if (status != ISC_R_SUCCESS)
2149 log_fatal ("Allocation of new subnet failed: %s",
2150 isc_result_totext (status));
2151 shared_network_reference (&subnet -> shared_network, share, MDL);
2152 if (!clone_group (&subnet -> group, share -> group, MDL))
2153 log_fatal ("allocation of group for new subnet failed.");
2154 subnet_reference (&subnet -> group -> subnet, subnet, MDL);
685963dc
TL
2155
2156 /* Get the network number... */
20916cae
TL
2157 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) {
2158 subnet_dereference (&subnet, MDL);
7dfc8ac2 2159 return;
20916cae 2160 }
7dfc8ac2
TL
2161 memcpy (iaddr.iabuf, addr, len);
2162 iaddr.len = len;
2163 subnet -> net = iaddr;
685963dc 2164
b3519f23 2165 token = next_token (&val, (unsigned *)0, cfile);
685963dc 2166 if (token != NETMASK) {
35454d8a 2167 parse_warn (cfile, "Expecting netmask");
685963dc 2168 skip_to_semi (cfile);
7dfc8ac2 2169 return;
685963dc
TL
2170 }
2171
2172 /* Get the netmask... */
20916cae
TL
2173 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) {
2174 subnet_dereference (&subnet, MDL);
7dfc8ac2 2175 return;
20916cae 2176 }
7dfc8ac2
TL
2177 memcpy (iaddr.iabuf, addr, len);
2178 iaddr.len = len;
2179 subnet -> netmask = iaddr;
685963dc 2180
20916cae
TL
2181 /* Validate the network number/netmask pair. */
2182 if (host_addr (subnet -> net, subnet -> netmask)) {
2183 parse_warn (cfile,
2184 "subnet %s: bad subnet number/mask combination.",
2185 piaddr (subnet -> net));
2186 subnet_dereference (&subnet, MDL);
2187 skip_to_semi (cfile);
2188 return;
2189 }
2190
685963dc
TL
2191 enter_subnet (subnet);
2192
20916cae
TL
2193 if (!parse_lbrace (cfile)) {
2194 subnet_dereference (&subnet, MDL);
7dfc8ac2 2195 return;
20916cae 2196 }
7dfc8ac2 2197
685963dc 2198 do {
b3519f23 2199 token = peek_token (&val, (unsigned *)0, cfile);
7dfc8ac2 2200 if (token == RBRACE) {
b3519f23 2201 token = next_token (&val, (unsigned *)0, cfile);
685963dc 2202 break;
0b69dcc8 2203 } else if (token == END_OF_FILE) {
b3519f23 2204 token = next_token (&val, (unsigned *)0, cfile);
35454d8a 2205 parse_warn (cfile, "unexpected end of file");
5376e3e9 2206 break;
79931db3 2207 } else if (token == INTERFACE) {
b3519f23
TL
2208 token = next_token (&val, (unsigned *)0, cfile);
2209 token = next_token (&val, (unsigned *)0, cfile);
79931db3
TL
2210 new_shared_network_interface (cfile, share, val);
2211 if (!parse_semi (cfile))
2212 break;
2213 continue;
7dfc8ac2 2214 }
2d59f590
TL
2215 declaration = parse_statement (cfile, subnet -> group,
2216 SUBNET_DECL,
2217 (struct host_decl *)0,
2218 declaration);
685963dc 2219 } while (1);
1f814ff2 2220
6cdd0d0d 2221 /* Add the subnet to the list of subnets in this shared net. */
7dfc8ac2 2222 if (!share -> subnets)
20916cae 2223 subnet_reference (&share -> subnets, subnet, MDL);
7dfc8ac2 2224 else {
763adef1 2225 u = (struct subnet *)0;
7dfc8ac2 2226 for (t = share -> subnets;
763adef1
TL
2227 t -> next_sibling; t = t -> next_sibling) {
2228 if (subnet_inner_than (subnet, t, 0)) {
20916cae
TL
2229 subnet_reference (&subnet -> next_sibling,
2230 t, MDL);
2231 if (u) {
2232 subnet_dereference (&u -> next_sibling,
2233 MDL);
2234 subnet_reference (&u -> next_sibling,
2235 subnet, MDL);
2236 } else {
2237 subnet_dereference (&share -> subnets,
2238 MDL);
2239 subnet_reference (&share -> subnets,
2240 subnet, MDL);
2241 }
2242 subnet_dereference (&subnet, MDL);
763adef1
TL
2243 return;
2244 }
2245 u = t;
2246 }
20916cae 2247 subnet_reference (&t -> next_sibling, subnet, MDL);
7dfc8ac2 2248 }
20916cae 2249 subnet_dereference (&subnet, MDL);
685963dc
TL
2250}
2251
2d59f590 2252/* group-declaration :== RBRACE parameters declarations LBRACE */
7dfc8ac2 2253
2d59f590 2254void parse_group_declaration (cfile, group)
35454d8a 2255 struct parse *cfile;
7dfc8ac2 2256 struct group *group;
685963dc 2257{
b1b7b521 2258 const char *val;
6f8fb41f 2259 enum dhcp_token token;
7dfc8ac2 2260 struct group *g;
2d59f590 2261 int declaration = 0;
29c35bed
TL
2262 struct group_object *t;
2263 isc_result_t status;
d9eefc5d 2264 char *name = NULL;
29c35bed
TL
2265 int deletedp = 0;
2266 int dynamicp = 0;
2267 int staticp = 0;
685963dc 2268
20916cae
TL
2269 g = (struct group *)0;
2270 if (!clone_group (&g, group, MDL))
2271 log_fatal ("no memory for explicit group.");
685963dc 2272
b3519f23 2273 token = peek_token (&val, (unsigned *)0, cfile);
29c35bed 2274 if (is_identifier (token) || token == STRING) {
b3519f23 2275 next_token (&val, (unsigned *)0, cfile);
29c35bed 2276
436f1c8c 2277 name = dmalloc (strlen (val) + 1, MDL);
29c35bed
TL
2278 if (!name)
2279 log_fatal ("no memory for group decl name %s", val);
2280 strcpy (name, val);
2281 }
2282
20916cae
TL
2283 if (!parse_lbrace (cfile)) {
2284 group_dereference (&g, MDL);
7dfc8ac2 2285 return;
20916cae 2286 }
d7837182 2287
7dfc8ac2 2288 do {
b3519f23 2289 token = peek_token (&val, (unsigned *)0, cfile);
5376e3e9 2290 if (token == RBRACE) {
b3519f23 2291 token = next_token (&val, (unsigned *)0, cfile);
7dfc8ac2 2292 break;
0b69dcc8 2293 } else if (token == END_OF_FILE) {
b3519f23 2294 token = next_token (&val, (unsigned *)0, cfile);
35454d8a 2295 parse_warn (cfile, "unexpected end of file");
5376e3e9 2296 break;
007e3ee4 2297 } else if (token == TOKEN_DELETED) {
b3519f23 2298 token = next_token (&val, (unsigned *)0, cfile);
29c35bed
TL
2299 parse_semi (cfile);
2300 deletedp = 1;
2301 } else if (token == DYNAMIC) {
b3519f23 2302 token = next_token (&val, (unsigned *)0, cfile);
29c35bed
TL
2303 parse_semi (cfile);
2304 dynamicp = 1;
2305 } else if (token == STATIC) {
b3519f23 2306 token = next_token (&val, (unsigned *)0, cfile);
29c35bed
TL
2307 parse_semi (cfile);
2308 staticp = 1;
5376e3e9 2309 }
2d59f590
TL
2310 declaration = parse_statement (cfile, g, GROUP_DECL,
2311 (struct host_decl *)0,
2312 declaration);
7dfc8ac2 2313 } while (1);
29c35bed
TL
2314
2315 if (name) {
2316 if (deletedp) {
2317 if (group_name_hash) {
20916cae
TL
2318 t = (struct group_object *)0;
2319 if (group_hash_lookup (&t, group_name_hash,
2320 name,
2321 strlen (name), MDL)) {
29c35bed
TL
2322 delete_group (t, 0);
2323 }
2324 }
2325 } else {
20916cae
TL
2326 t = (struct group_object *)0;
2327 status = group_object_allocate (&t, MDL);
2328 if (status != ISC_R_SUCCESS)
2329 log_fatal ("no memory for group decl %s: %s",
2330 val, isc_result_totext (status));
2331 group_reference (&t -> group, g, MDL);
29c35bed
TL
2332 t -> name = name;
2333 t -> flags = ((staticp ? GROUP_OBJECT_STATIC : 0) |
2334 (dynamicp ? GROUP_OBJECT_DYNAMIC : 0) |
2335 (deletedp ? GROUP_OBJECT_DELETED : 0));
2336 supersede_group (t, 0);
2337 }
20916cae
TL
2338 if (t)
2339 group_object_dereference (&t, MDL);
29c35bed 2340 }
d7837182
TL
2341}
2342
2d59f590
TL
2343/* fixed-addr-parameter :== ip-addrs-or-hostnames SEMI
2344 ip-addrs-or-hostnames :== ip-addr-or-hostname
2345 | ip-addrs-or-hostnames ip-addr-or-hostname */
d7837182 2346
6f8fb41f
TL
2347int parse_fixed_addr_param (oc, cfile)
2348 struct option_cache **oc;
35454d8a 2349 struct parse *cfile;
d7837182 2350{
b1b7b521 2351 const char *val;
6f8fb41f 2352 enum dhcp_token token;
ece6ea33 2353 struct expression *expr = (struct expression *)0;
6f8fb41f
TL
2354 struct expression *tmp, *new;
2355 int status;
1f814ff2
TL
2356
2357 do {
6f8fb41f
TL
2358 tmp = (struct expression *)0;
2359 if (parse_ip_addr_or_hostname (&tmp, cfile, 1)) {
028a8588
TL
2360 if (expr) {
2361 new = (struct expression *)0;
2362 status = make_concat (&new, expr, tmp);
436f1c8c
TL
2363 expression_dereference (&expr, MDL);
2364 expression_dereference (&tmp, MDL);
1dd632af 2365 if (!status)
028a8588
TL
2366 return 0;
2367 expr = new;
2368 } else
2369 expr = tmp;
6f8fb41f
TL
2370 } else {
2371 if (expr)
436f1c8c 2372 expression_dereference (&expr, MDL);
6f8fb41f
TL
2373 return 0;
2374 }
b3519f23 2375 token = peek_token (&val, (unsigned *)0, cfile);
5376e3e9 2376 if (token == COMMA)
b3519f23 2377 token = next_token (&val, (unsigned *)0, cfile);
1f814ff2 2378 } while (token == COMMA);
7dfc8ac2 2379
6f8fb41f
TL
2380 if (!parse_semi (cfile)) {
2381 if (expr)
436f1c8c 2382 expression_dereference (&expr, MDL);
6f8fb41f
TL
2383 return 0;
2384 }
2385 status = option_cache (oc, (struct data_string *)0, expr,
d758ad8c 2386 (struct option *)0, MDL);
436f1c8c 2387 expression_dereference (&expr, MDL);
6f8fb41f 2388 return status;
d7837182
TL
2389}
2390
5376e3e9 2391/* timestamp :== date
d7837182
TL
2392
2393 Timestamps are actually not used in dhcpd.conf, which is a static file,
5376e3e9
TL
2394 but rather in the database file and the journal file. (Okay, actually
2395 they're not even used there yet). */
d7837182 2396
7dfc8ac2 2397TIME parse_timestamp (cfile)
35454d8a 2398 struct parse *cfile;
d7837182 2399{
089fb364 2400 TIME rv;
089fb364 2401
7dfc8ac2 2402 rv = parse_date (cfile);
089fb364 2403 return rv;
d7837182
TL
2404}
2405
2d59f590
TL
2406/* lease_declaration :== LEASE ip_address LBRACE lease_parameters RBRACE
2407
2408 lease_parameters :== <nil>
2409 | lease_parameter
2410 | lease_parameters lease_parameter
2411
2412 lease_parameter :== STARTS date
2413 | ENDS date
2414 | TIMESTAMP date
2415 | HARDWARE hardware-parameter
2416 | UID hex_numbers SEMI
ccf5778a
TL
2417 | HOSTNAME hostname SEMI
2418 | CLIENT_HOSTNAME hostname SEMI
2d59f590
TL
2419 | CLASS identifier SEMI
2420 | DYNAMIC_BOOTP SEMI */
2421
20916cae 2422int parse_lease_declaration (struct lease **lp, struct parse *cfile)
d7837182 2423{
b1b7b521 2424 const char *val;
6f8fb41f 2425 enum dhcp_token token;
d7837182 2426 unsigned char addr [4];
b1b7b521 2427 unsigned len = sizeof addr;
d7837182
TL
2428 int seenmask = 0;
2429 int seenbit;
2430 char tbuf [32];
20916cae 2431 struct lease *lease;
96d7d13e 2432 struct executable_statement *on;
436f1c8c
TL
2433 struct expression *exp;
2434 struct data_string ds;
96d7d13e 2435 int lose;
9e9b2261 2436 TIME t;
436f1c8c
TL
2437 char *s;
2438 int noequal, newbinding;
2439 struct binding *binding;
20916cae 2440 isc_result_t status;
6c5223f5
TL
2441 struct option_cache *oc;
2442 pair *p;
e15d235d 2443 binding_state_t new_state;
b3519f23 2444 unsigned buflen = 0;
f545ef7f 2445 struct class *class;
d7837182 2446
20916cae
TL
2447 lease = (struct lease *)0;
2448 status = lease_allocate (&lease, MDL);
2449 if (status != ISC_R_SUCCESS)
2450 return 0;
9375101b 2451
d7837182 2452 /* Get the address for which the lease has been issued. */
20916cae
TL
2453 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) {
2454 lease_dereference (&lease, MDL);
2455 return 0;
2456 }
2457 memcpy (lease -> ip_addr.iabuf, addr, len);
2458 lease -> ip_addr.len = len;
d7837182 2459
20916cae
TL
2460 if (!parse_lbrace (cfile)) {
2461 lease_dereference (&lease, MDL);
2462 return 0;
2463 }
7dfc8ac2 2464
d7837182 2465 do {
b3519f23 2466 token = next_token (&val, (unsigned *)0, cfile);
7dfc8ac2 2467 if (token == RBRACE)
d7837182 2468 break;
0b69dcc8 2469 else if (token == END_OF_FILE) {
35454d8a 2470 parse_warn (cfile, "unexpected end of file");
5376e3e9
TL
2471 break;
2472 }
ece6ea33 2473 strncpy (tbuf, val, sizeof tbuf);
d7837182
TL
2474 tbuf [(sizeof tbuf) - 1] = 0;
2475
2476 /* Parse any of the times associated with the lease. */
9e9b2261
TL
2477 switch (token) {
2478 case STARTS:
2479 case ENDS:
2480 case TIMESTAMP:
2481 case TSTP:
2482 case TSFP:
8c8e27c5 2483 case CLTT:
7dfc8ac2 2484 t = parse_date (cfile);
d7837182
TL
2485 switch (token) {
2486 case STARTS:
2487 seenbit = 1;
20916cae 2488 lease -> starts = t;
d7837182
TL
2489 break;
2490
2491 case ENDS:
2492 seenbit = 2;
20916cae 2493 lease -> ends = t;
d7837182
TL
2494 break;
2495
2496 case TIMESTAMP:
2497 seenbit = 4;
20916cae 2498 lease -> timestamp = t;
d7837182 2499 break;
19d868b2 2500
9e9b2261
TL
2501 case TSTP:
2502 seenbit = 65536;
20916cae 2503 lease -> tstp = t;
19d868b2 2504 break;
9e9b2261
TL
2505
2506 case TSFP:
2507 seenbit = 131072;
20916cae 2508 lease -> tsfp = t;
d7837182 2509 break;
9e9b2261 2510
8c8e27c5
TL
2511 case CLTT:
2512 seenbit = 524288;
20916cae 2513 lease -> cltt = t;
8c8e27c5
TL
2514 break;
2515
9e9b2261 2516 default: /* for gcc, we'll never get here. */
9d80b480 2517 break;
9e9b2261
TL
2518 }
2519 break;
d7837182 2520
9e9b2261
TL
2521 /* Colon-seperated hexadecimal octets... */
2522 case UID:
2523 seenbit = 8;
b3519f23 2524 token = peek_token (&val, (unsigned *)0, cfile);
9e9b2261
TL
2525 if (token == STRING) {
2526 unsigned char *tuid;
b3519f23 2527 token = next_token (&val, &buflen, cfile);
a3cd7f28 2528 if (buflen < sizeof lease -> uid_buf) {
b3519f23 2529 tuid = lease -> uid_buf;
a3cd7f28
TL
2530 lease -> uid_max =
2531 sizeof lease -> uid_buf;
2532 } else {
b3519f23
TL
2533 tuid = ((unsigned char *)
2534 dmalloc (buflen, MDL));
2535 if (!tuid) {
2536 log_error ("no space for uid");
2537 lease_dereference (&lease,
2538 MDL);
2539 return 0;
2540 }
a3cd7f28 2541 lease -> uid_max = buflen;
d7837182 2542 }
7ebf32da 2543 lease -> uid_len = buflen;
20916cae
TL
2544 memcpy (tuid, val, lease -> uid_len);
2545 lease -> uid = tuid;
9e9b2261 2546 } else {
b3519f23 2547 buflen = 0;
20916cae
TL
2548 lease -> uid = (parse_numeric_aggregate
2549 (cfile, (unsigned char *)0,
b3519f23 2550 &buflen, ':', 16, 8));
20916cae
TL
2551 if (!lease -> uid) {
2552 lease_dereference (&lease, MDL);
2553 return 0;
2554 }
7ebf32da 2555 lease -> uid_len = buflen;
a3cd7f28 2556 lease -> uid_max = buflen;
20916cae
TL
2557 if (lease -> uid_len == 0) {
2558 lease -> uid = (unsigned char *)0;
9e9b2261
TL
2559 parse_warn (cfile, "zero-length uid");
2560 seenbit = 0;
d0463358 2561 parse_semi (cfile);
9e9b2261
TL
2562 break;
2563 }
2564 }
d0463358 2565 parse_semi (cfile);
20916cae 2566 if (!lease -> uid) {
9e9b2261
TL
2567 log_fatal ("No memory for lease uid");
2568 }
2569 break;
2570
2571 case CLASS:
2572 seenbit = 32;
b3519f23 2573 token = next_token (&val, (unsigned *)0, cfile);
9e9b2261
TL
2574 if (!is_identifier (token)) {
2575 if (token != SEMI)
2576 skip_to_rbrace (cfile, 1);
20916cae
TL
2577 lease_dereference (&lease, MDL);
2578 return 0;
9e9b2261 2579 }
d0463358 2580 parse_semi (cfile);
9e9b2261
TL
2581 /* for now, we aren't using this. */
2582 break;
ccf5778a 2583
9e9b2261
TL
2584 case HARDWARE:
2585 seenbit = 64;
2586 parse_hardware_param (cfile,
20916cae 2587 &lease -> hardware_addr);
9e9b2261
TL
2588 break;
2589
2590 case DYNAMIC_BOOTP:
007e3ee4
TL
2591 seenbit = 256;
2592 lease -> binding_state = FTS_BOOTP;
2593 lease -> next_binding_state = FTS_BOOTP;
d0463358 2594 parse_semi (cfile);
9e9b2261
TL
2595 break;
2596
007e3ee4
TL
2597 case TOKEN_ABANDONED:
2598 seenbit = 256;
2599 lease -> binding_state = FTS_ABANDONED;
2600 lease -> next_binding_state = FTS_ABANDONED;
d0463358 2601 parse_semi (cfile);
9e9b2261
TL
2602 break;
2603
007e3ee4
TL
2604 case TOKEN_NEXT:
2605 seenbit = 128;
b3519f23 2606 token = next_token (&val, (unsigned *)0, cfile);
301a5b66
TL
2607 if (token != BINDING) {
2608 parse_warn (cfile, "expecting 'binding'");
2609 skip_to_semi (cfile);
2610 break;
2611 }
007e3ee4
TL
2612 goto do_binding_state;
2613
2614 case BINDING:
9e9b2261 2615 seenbit = 256;
007e3ee4
TL
2616
2617 do_binding_state:
b3519f23 2618 token = next_token (&val, (unsigned *)0, cfile);
007e3ee4
TL
2619 if (token != STATE) {
2620 parse_warn (cfile, "expecting 'state'");
2621 skip_to_semi (cfile);
2622 break;
2623 }
b3519f23 2624 token = next_token (&val, (unsigned *)0, cfile);
007e3ee4
TL
2625 switch (token) {
2626 case TOKEN_ABANDONED:
e15d235d 2627 new_state = FTS_ABANDONED;
007e3ee4
TL
2628 break;
2629 case TOKEN_FREE:
e15d235d 2630 new_state = FTS_FREE;
007e3ee4
TL
2631 break;
2632 case TOKEN_ACTIVE:
e15d235d 2633 new_state = FTS_ACTIVE;
007e3ee4
TL
2634 break;
2635 case TOKEN_EXPIRED:
e15d235d 2636 new_state = FTS_EXPIRED;
007e3ee4
TL
2637 break;
2638 case TOKEN_RELEASED:
e15d235d 2639 new_state = FTS_RELEASED;
007e3ee4
TL
2640 break;
2641 case TOKEN_RESET:
e15d235d 2642 new_state = FTS_RESET;
007e3ee4
TL
2643 break;
2644 case TOKEN_BACKUP:
e15d235d 2645 new_state = FTS_BACKUP;
007e3ee4
TL
2646 break;
2647 case TOKEN_RESERVED:
e15d235d 2648 new_state = FTS_RESERVED;
007e3ee4
TL
2649 break;
2650 case TOKEN_BOOTP:
e15d235d 2651 new_state = FTS_BOOTP;
007e3ee4
TL
2652 break;
2653 default:
2654 parse_warn (cfile,
2655 "%s: expecting a binding state.",
2656 val);
2657 skip_to_semi (cfile);
2658 break;
2659 }
e15d235d
TL
2660
2661 if (seenbit == 256) {
2662 lease -> binding_state = new_state;
2663
2664 /* If no next binding state is specified, it's
2665 the same as the current state. */
2666 if (!(seenmask & 128))
2667 lease -> next_binding_state = new_state;
2668 } else
2669 lease -> next_binding_state = new_state;
2670
d0463358 2671 parse_semi (cfile);
9e9b2261 2672 break;
ccf5778a 2673
9e9b2261
TL
2674 case CLIENT_HOSTNAME:
2675 seenbit = 1024;
b3519f23
TL
2676 token = peek_token (&val, (unsigned *)0, cfile);
2677 if (token == STRING) {
2678 if (!parse_string (cfile,
2679 &lease -> client_hostname,
2680 (unsigned *)0)) {
2681 lease_dereference (&lease, MDL);
2682 return 0;
2683 }
2684 } else {
20916cae 2685 lease -> client_hostname =
9e9b2261 2686 parse_host_name (cfile);
20916cae 2687 if (lease -> client_hostname)
d0463358 2688 parse_semi (cfile);
b3519f23
TL
2689 else {
2690 parse_warn (cfile,
2691 "expecting a hostname.");
2692 skip_to_semi (cfile);
2693 lease_dereference (&lease, MDL);
2694 return 0;
2695 }
d0463358 2696 }
9e9b2261
TL
2697 break;
2698
2699 case BILLING:
2700 seenbit = 2048;
f545ef7f 2701 class = (struct class *)0;
b3519f23 2702 token = next_token (&val, (unsigned *)0, cfile);
9e9b2261 2703 if (token == CLASS) {
b3519f23
TL
2704 token = next_token (&val,
2705 (unsigned *)0, cfile);
9e9b2261
TL
2706 if (token != STRING) {
2707 parse_warn (cfile, "expecting string");
88dcab62
TL
2708 if (token != SEMI)
2709 skip_to_semi (cfile);
9e9b2261
TL
2710 token = BILLING;
2711 break;
88dcab62 2712 }
aaafa64a 2713 if (lease -> billing_class)
ed1dc2c5
TL
2714 class_dereference (&lease -> billing_class,
2715 MDL);
f545ef7f
TL
2716 find_class (&class, val, MDL);
2717 if (!class)
9e9b2261
TL
2718 parse_warn (cfile,
2719 "unknown class %s", val);
2720 parse_semi (cfile);
2721 } else if (token == SUBCLASS) {
20916cae 2722 if (lease -> billing_class)
ed1dc2c5
TL
2723 class_dereference (&lease -> billing_class,
2724 MDL);
20916cae 2725 parse_class_declaration
f545ef7f 2726 (&class,
20916cae 2727 cfile, (struct group *)0, 3);
9e9b2261
TL
2728 } else {
2729 parse_warn (cfile, "expecting \"class\"");
2730 if (token != SEMI)
2731 skip_to_semi (cfile);
2732 }
f545ef7f 2733 if (class) {
ed1dc2c5
TL
2734 class_reference (&lease -> billing_class,
2735 class, MDL);
f545ef7f
TL
2736 class_dereference (&class, MDL);
2737 }
9e9b2261 2738 break;
96d7d13e 2739
9e9b2261
TL
2740 case ON:
2741 on = (struct executable_statement *)0;
2742 lose = 0;
2743 if (!parse_on_statement (&on, cfile, &lose)) {
2744 skip_to_rbrace (cfile, 1);
20916cae
TL
2745 lease_dereference (&lease, MDL);
2746 return 0;
7dfc8ac2 2747 }
436f1c8c 2748 seenbit = 0;
d0463358 2749 if ((on -> data.on.evtypes & ON_EXPIRY) &&
9e9b2261 2750 on -> data.on.statements) {
436f1c8c 2751 seenbit |= 16384;
9e9b2261 2752 executable_statement_reference
20916cae 2753 (&lease -> on_expiry,
436f1c8c 2754 on -> data.on.statements, MDL);
d0463358
TL
2755 }
2756 if ((on -> data.on.evtypes & ON_RELEASE) &&
2757 on -> data.on.statements) {
436f1c8c 2758 seenbit |= 32768;
9e9b2261 2759 executable_statement_reference
20916cae 2760 (&lease -> on_release,
436f1c8c 2761 on -> data.on.statements, MDL);
9e9b2261 2762 }
436f1c8c 2763 executable_statement_dereference (&on, MDL);
9e9b2261
TL
2764 break;
2765
9e383163
TL
2766 case OPTION:
2767 noequal = 0;
2768 seenbit = 0;
2769 oc = (struct option_cache *)0;
2770 if (parse_option_decl (&oc, cfile)) {
6c5223f5
TL
2771 if (oc -> option -> universe !=
2772 &agent_universe) {
2773 parse_warn (cfile,
2774 "agent option expected.");
2775 option_cache_dereference (&oc, MDL);
2776 break;
2777 }
2778 if (!lease -> agent_options &&
2779 !(option_chain_head_allocate
2780 (&lease -> agent_options, MDL))) {
2781 log_error ("no memory to stash agent option");
2782 break;
2783 }
2784 for (p = &lease -> agent_options -> first;
2785 *p; p = &((*p) -> cdr))
2786 ;
2787 *p = cons (0, 0);
2788 option_cache_reference (((struct option_cache **)
2789 &((*p) -> car)), oc, MDL);
2790 option_cache_dereference (&oc, MDL);
9e383163
TL
2791 }
2792 break;
2793
436f1c8c
TL
2794 case TOKEN_SET:
2795 noequal = 0;
2796
b3519f23 2797 token = next_token (&val, (unsigned *)0, cfile);
436f1c8c
TL
2798 if (token != NAME && token != NUMBER_OR_NAME) {
2799 parse_warn (cfile,
2800 "%s can't be a variable name",
2801 val);
2802 badset:
2803 skip_to_semi (cfile);
20916cae
TL
2804 lease_dereference (&lease, MDL);
2805 return 0;
436f1c8c
TL
2806 }
2807
2808 seenbit = 0;
2809 special_set:
6ceb9118
TL
2810 if (lease -> scope)
2811 binding = find_binding (lease -> scope, val);
2812 else
2813 binding = (struct binding *)0;
436f1c8c 2814 if (!binding) {
6ceb9118
TL
2815 if (!lease -> scope)
2816 if (!(binding_scope_allocate
2817 (&lease -> scope, MDL)))
2818 log_fatal ("no memory for scope");
d758ad8c
TL
2819 binding = dmalloc (sizeof *binding, MDL);
2820 if (!binding)
2821 log_fatal ("No memory for lease %s.",
2822 "binding");
2823 memset (binding, 0, sizeof *binding);
2824 binding -> name =
2825 dmalloc (strlen (val) + 1, MDL);
2826 if (!binding -> name)
2827 log_fatal ("No memory for binding %s.",
2828 "name");
2829 strcpy (binding -> name, val);
2830 newbinding = 1;
11cd757b
TL
2831 } else if (binding -> value) {
2832 binding_value_dereference (&binding -> value,
2833 MDL);
436f1c8c
TL
2834 newbinding = 0;
2835 }
11cd757b
TL
2836 if (!binding_value_allocate (&binding -> value, MDL))
2837 log_fatal ("no memory for binding value.");
436f1c8c
TL
2838
2839 if (!noequal) {
b3519f23 2840 token = next_token (&val, (unsigned *)0, cfile);
436f1c8c
TL
2841 if (token != EQUAL) {
2842 parse_warn (cfile,
2843 "expecting '=' in set statement.");
2844 goto badset;
2845 }
2846 }
2847
b3519f23 2848 token = peek_token (&val, (unsigned *)0, cfile);
436f1c8c 2849 if (token == STRING) {
11cd757b 2850 unsigned char *tuid;
b3519f23 2851 token = next_token (&val, &buflen, cfile);
11cd757b 2852 binding -> value -> type = binding_data;
b3519f23 2853 binding -> value -> value.data.len = buflen;
11cd757b
TL
2854 if (!(buffer_allocate
2855 (&binding -> value -> value.data.buffer,
b3519f23 2856 buflen + 1, MDL)))
11cd757b 2857 log_fatal ("No memory for binding.");
b3519f23 2858 memcpy ((char *)
11cd757b 2859 (binding -> value ->
b3519f23
TL
2860 value.data.buffer -> data),
2861 val, buflen + 1);
11cd757b
TL
2862 binding -> value -> value.data.data =
2863 binding -> value -> value.data.buffer -> data;
2864 binding -> value -> value.data.terminated = 1;
2865 } else if (token == NUMBER_OR_NAME) {
2866 binding -> value -> type = binding_data;
2867 s = ((char *)
2868 (parse_numeric_aggregate
2869 (cfile, (unsigned char *)0,
2870 &binding -> value -> value.data.len,
2871 ':', 16, 8)));
2872 if (!s) {
2873 binding_value_dereference
2874 (&binding -> value, MDL);
20916cae
TL
2875 lease_dereference (&lease, MDL);
2876 return 0;
11cd757b
TL
2877 }
2878 if (binding -> value -> value.data.len) {
436f1c8c 2879 if (!(buffer_allocate
11cd757b
TL
2880 (&binding -> value -> value.data.buffer,
2881 binding -> value -> value.data.len + 1,
2882 MDL)))
436f1c8c 2883 log_fatal ("No memory for binding.");
11cd757b
TL
2884 memcpy ((binding -> value ->
2885 value.data.buffer -> data), s,
2886 binding -> value -> value.data.len);
2887 dfree (s, MDL);
2888 binding -> value -> value.data.data =
2889 binding -> value -> value.data.buffer -> data;
2890 }
2891 } else if (token == PERCENT) {
b3519f23
TL
2892 token = next_token (&val, (unsigned *)0, cfile);
2893 token = next_token (&val, (unsigned *)0, cfile);
11cd757b
TL
2894 if (token != NUMBER) {
2895 parse_warn (cfile,
2896 "expecting decimal number.");
2897 if (token != SEMI)
2898 skip_to_semi (cfile);
2899 binding_value_dereference
2900 (&binding -> value, MDL);
20916cae
TL
2901 lease_dereference (&lease, MDL);
2902 return 0;
11cd757b
TL
2903 }
2904 binding -> value -> type = binding_numeric;
2905 binding -> value -> value.intval = atol (val);
2906 } else if (token == NAME) {
b3519f23
TL
2907 token = next_token (&val,
2908 (unsigned *)0, cfile);
11cd757b
TL
2909 binding -> value -> type = binding_boolean;
2910 if (!strcasecmp (val, "true"))
2911 binding -> value -> value.boolean = 1;
2912 else if (!strcasecmp (val, "false"))
2913 binding -> value -> value.boolean = 0;
2914 else
2915 goto badbool;
436f1c8c 2916 } else {
11cd757b
TL
2917 badbool:
2918 parse_warn (cfile,
2919 "expecting a constant value.");
2920 skip_to_semi (cfile);
2921 binding_value_dereference (&binding -> value,
2922 MDL);
20916cae
TL
2923 lease_dereference (&lease, MDL);
2924 return 0;
436f1c8c 2925 }
11cd757b 2926
436f1c8c 2927 if (newbinding) {
6ceb9118
TL
2928 binding -> next = lease -> scope -> bindings;
2929 lease -> scope -> bindings = binding;
436f1c8c
TL
2930 }
2931 parse_semi (cfile);
2932 break;
2933
9e9b2261 2934 default:
436f1c8c
TL
2935 if (!strcasecmp (val, "ddns-fwd-name")) {
2936 seenbit = 4096;
2937 noequal = 1;
2938 goto special_set;
2939 } else if (!strcasecmp (val, "ddns-rev-name")) {
2940 seenbit = 8192;
2941 noequal = 1;
2942 goto special_set;
2943 }
9e9b2261
TL
2944 skip_to_semi (cfile);
2945 seenbit = 0;
20916cae
TL
2946 lease_dereference (&lease, MDL);
2947 return 0;
9e9b2261 2948 }
7dfc8ac2 2949
d7837182 2950 if (seenmask & seenbit) {
35454d8a
TL
2951 parse_warn (cfile,
2952 "Too many %s parameters in lease %s\n",
20916cae 2953 tbuf, piaddr (lease -> ip_addr));
d7837182
TL
2954 } else
2955 seenmask |= seenbit;
7dfc8ac2 2956
d7837182 2957 } while (1);
8afe0787
TL
2958
2959 /* If no binding state is specified, make one up. */
2960 if (!(seenmask & 256)) {
e73a0769
TL
2961 if (lease -> ends > cur_time ||
2962 lease -> on_expiry || lease -> on_release)
8afe0787 2963 lease -> binding_state = FTS_ACTIVE;
301a5b66 2964#if defined (FAILOVER_PROTOCOL)
e73a0769
TL
2965 else if (lease -> pool && lease -> pool -> failover_peer)
2966 lease -> binding_state = FTS_EXPIRED;
301a5b66 2967#endif
8afe0787
TL
2968 else
2969 lease -> binding_state = FTS_FREE;
e73a0769 2970 if (lease -> binding_state == FTS_ACTIVE) {
301a5b66 2971#if defined (FAILOVER_PROTOCOL)
e73a0769
TL
2972 if (lease -> pool && lease -> pool -> failover_peer)
2973 lease -> next_binding_state = FTS_EXPIRED;
2974 else
301a5b66 2975#endif
e73a0769
TL
2976 lease -> next_binding_state = FTS_FREE;
2977 } else
2978 lease -> next_binding_state = lease -> binding_state;
8afe0787
TL
2979 }
2980
6f8a0361
TL
2981 if (!(seenmask & 65536))
2982 lease -> tstp = lease -> ends;
2983
20916cae
TL
2984 lease_reference (lp, lease, MDL);
2985 lease_dereference (&lease, MDL);
2986 return 1;
d7837182
TL
2987}
2988
2d59f590
TL
2989/* address-range-declaration :== ip-address ip-address SEMI
2990 | DYNAMIC_BOOTP ip-address ip-address SEMI */
d7837182 2991
20916cae 2992void parse_address_range (cfile, group, type, inpool)
35454d8a 2993 struct parse *cfile;
f63b4929
TL
2994 struct group *group;
2995 int type;
20916cae 2996 struct pool *inpool;
d7837182 2997{
f63b4929 2998 struct iaddr low, high, net;
d7837182 2999 unsigned char addr [4];
b1b7b521 3000 unsigned len = sizeof addr;
6f8fb41f 3001 enum dhcp_token token;
b1b7b521 3002 const char *val;
1f814ff2 3003 int dynamic = 0;
f63b4929
TL
3004 struct subnet *subnet;
3005 struct shared_network *share;
3006 struct pool *p;
20916cae
TL
3007 struct pool *pool;
3008 isc_result_t status;
1f814ff2 3009
b3519f23
TL
3010 if ((token = peek_token (&val,
3011 (unsigned *)0, cfile)) == DYNAMIC_BOOTP) {
3012 token = next_token (&val, (unsigned *)0, cfile);
ece6ea33 3013 dynamic = 1;
1f814ff2 3014 }
d7837182
TL
3015
3016 /* Get the bottom address in the range... */
7dfc8ac2
TL
3017 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
3018 return;
089fb364
TL
3019 memcpy (low.iabuf, addr, len);
3020 low.len = len;
d7837182 3021
2d59f590 3022 /* Only one address? */
b3519f23 3023 token = peek_token (&val, (unsigned *)0, cfile);
2d59f590
TL
3024 if (token == SEMI)
3025 high = low;
3026 else {
d7837182 3027 /* Get the top address in the range... */
2d59f590
TL
3028 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
3029 return;
3030 memcpy (high.iabuf, addr, len);
3031 high.len = len;
3032 }
d7837182 3033
b3519f23 3034 token = next_token (&val, (unsigned *)0, cfile);
7dfc8ac2 3035 if (token != SEMI) {
35454d8a 3036 parse_warn (cfile, "semicolon expected.");
7dfc8ac2
TL
3037 skip_to_semi (cfile);
3038 return;
3039 }
3040
f63b4929
TL
3041 if (type == SUBNET_DECL) {
3042 subnet = group -> subnet;
3043 share = subnet -> shared_network;
3044 } else {
3045 share = group -> shared_network;
3046 for (subnet = share -> subnets;
3047 subnet; subnet = subnet -> next_sibling) {
3048 net = subnet_number (low, subnet -> netmask);
e5e41be4 3049 if (addr_eq (net, subnet -> net))
f63b4929
TL
3050 break;
3051 }
3052 if (!subnet) {
35454d8a 3053 parse_warn (cfile, "address range not on network %s",
f63b4929 3054 group -> shared_network -> name);
e5e41be4
TL
3055 log_error ("Be sure to place pool statement after %s",
3056 "related subnet declarations.");
f63b4929
TL
3057 return;
3058 }
3059 }
3060
20916cae 3061 if (!inpool) {
0a1dfb65 3062 struct pool *last = (struct pool *)0;
9e9b2261 3063
f63b4929
TL
3064 /* If we're permitting dynamic bootp for this range,
3065 then look for a pool with an empty prohibit list and
436f1c8c 3066 a permit list with one entry that permits all clients. */
f63b4929 3067 for (pool = share -> pools; pool; pool = pool -> next) {
436f1c8c
TL
3068 if ((!dynamic && !pool -> permit_list &&
3069 pool -> prohibit_list &&
3070 !pool -> prohibit_list -> next &&
3071 (pool -> prohibit_list -> type ==
3072 permit_dynamic_bootp_clients)) ||
3073 (dynamic && !pool -> prohibit_list &&
f63b4929
TL
3074 pool -> permit_list &&
3075 !pool -> permit_list -> next &&
3076 (pool -> permit_list -> type ==
d9eefc5d 3077 permit_all_clients))) {
436f1c8c 3078 break;
f63b4929
TL
3079 }
3080 last = pool;
3081 }
3082
3083 /* If we didn't get a pool, make one. */
3084 if (!pool) {
436f1c8c 3085 struct permit *p;
20916cae
TL
3086 status = pool_allocate (&pool, MDL);
3087 if (status != ISC_R_SUCCESS)
3088 log_fatal ("no memory for ad-hoc pool: %s",
3089 isc_result_totext (status));
436f1c8c
TL
3090 p = new_permit (MDL);
3091 if (!p)
3092 log_fatal ("no memory for ad-hoc permit.");
3093
3094 /* Dynamic pools permit all clients. Otherwise
3095 we prohibit BOOTP clients. */
f63b4929 3096 if (dynamic) {
436f1c8c
TL
3097 p -> type = permit_all_clients;
3098 pool -> permit_list = p;
3099 } else {
3100 p -> type = permit_dynamic_bootp_clients;
3101 pool -> prohibit_list = p;
f63b4929 3102 }
436f1c8c 3103
f63b4929 3104 if (share -> pools)
20916cae 3105 pool_reference (&last -> next, pool, MDL);
f63b4929 3106 else
20916cae
TL
3107 pool_reference (&share -> pools, pool, MDL);
3108 shared_network_reference (&pool -> shared_network,
3109 share, MDL);
3110 if (!clone_group (&pool -> group, share -> group, MDL))
3111 log_fatal ("no memory for anon pool group.");
a79ed92b
TL
3112 } else {
3113 pool = (struct pool *)0;
0a1dfb65
TL
3114 if (last)
3115 pool_reference (&pool, last, MDL);
3116 else
3117 pool_reference (&pool, share -> pools, MDL);
f63b4929 3118 }
a79ed92b
TL
3119 } else {
3120 pool = (struct pool *)0;
20916cae 3121 pool_reference (&pool, inpool, MDL);
a79ed92b 3122 }
20916cae 3123
c5261618
TL
3124#if defined (FAILOVER_PROTOCOL)
3125 if (pool -> failover_peer && dynamic) {
3126 /* Doctor, do you think I'm overly sensitive
3127 about getting bug reports I can't fix? */
3128 parse_warn (cfile, "dynamic-bootp flag is %s",
3129 "not permitted for address");
3130 log_error ("range declarations where there is a failover");
3131 log_error ("peer in scope. If you wish to declare an");
3132 log_error ("address range from which dynamic bootp leases");
3133 log_error ("can be allocated, please declare it within a");
3134 log_error ("pool declaration that also contains the \"no");
3135 log_error ("failover\" statement. The failover protocol");
3136 log_error ("itself does not permit dynamic bootp - this");
3137 log_error ("is not a limitation specific to the ISC DHCP");
3138 log_error ("server. Please don't ask me to defend this");
3139 log_error ("until you have read and really tried %s",
3140 "to understand");
3141 log_error ("the failover protocol specification.");
3142
3143 /* We don't actually bomb at this point - instead,
3144 we let parse_lease_file notice the error and
3145 bomb at that point - it's easier. */
f63b4929 3146 }
c5261618 3147#endif /* FAILOVER_PROTOCOL */
f63b4929 3148
d7837182 3149 /* Create the new address range... */
f63b4929 3150 new_address_range (low, high, subnet, pool);
20916cae 3151 pool_dereference (&pool, MDL);
d7837182
TL
3152}
3153
c358155d
TL
3154/* allow-deny-keyword :== BOOTP
3155 | BOOTING
3156 | DYNAMIC_BOOTP
3157 | UNKNOWN_CLIENTS */
3158
3159int parse_allow_deny (oc, cfile, flag)
3160 struct option_cache **oc;
3161 struct parse *cfile;
3162 int flag;
3163{
3164 enum dhcp_token token;
3165 const char *val;
3166 unsigned char rf = flag;
3167 struct expression *data = (struct expression *)0;
3168 int status;
3169
d758ad8c 3170 if (!make_const_data (&data, &rf, 1, 0, 1, MDL))
c358155d
TL
3171 return 0;
3172
b3519f23 3173 token = next_token (&val, (unsigned *)0, cfile);
c358155d 3174 switch (token) {
007e3ee4 3175 case TOKEN_BOOTP:
c358155d 3176 status = option_cache (oc, (struct data_string *)0, data,
d758ad8c 3177 &server_options [SV_ALLOW_BOOTP], MDL);
c358155d
TL
3178 break;
3179
3180 case BOOTING:
3181 status = option_cache (oc, (struct data_string *)0, data,
d758ad8c
TL
3182 &server_options [SV_ALLOW_BOOTING],
3183 MDL);
c358155d
TL
3184 break;
3185
3186 case DYNAMIC_BOOTP:
3187 status = option_cache (oc, (struct data_string *)0, data,
d758ad8c
TL
3188 &server_options [SV_DYNAMIC_BOOTP],
3189 MDL);
c358155d
TL
3190 break;
3191
3192 case UNKNOWN_CLIENTS:
3193 status = (option_cache
3194 (oc, (struct data_string *)0, data,
d758ad8c 3195 &server_options [SV_BOOT_UNKNOWN_CLIENTS], MDL));
c358155d
TL
3196 break;
3197
3198 case DUPLICATES:
3199 status = option_cache (oc, (struct data_string *)0, data,
d758ad8c 3200 &server_options [SV_DUPLICATES], MDL);
c358155d
TL
3201 break;
3202
3203 case DECLINES:
3204 status = option_cache (oc, (struct data_string *)0, data,
d758ad8c 3205 &server_options [SV_DECLINES], MDL);
c358155d
TL
3206 break;
3207
6fdcc1a0
TL
3208 case CLIENT_UPDATES:
3209 status = option_cache (oc, (struct data_string *)0, data,
d758ad8c
TL
3210 &server_options [SV_CLIENT_UPDATES],
3211 MDL);
6fdcc1a0
TL
3212 break;
3213
c358155d
TL
3214 default:
3215 parse_warn (cfile, "expecting allow/deny key");
3216 skip_to_semi (cfile);
3217 return 0;
3218 }
d758ad8c 3219 expression_dereference (&data, MDL);
c358155d
TL
3220 parse_semi (cfile);
3221 return status;
3222}
3223