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