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