]> git.ipfire.org Git - thirdparty/dhcp.git/blame - server/confpars.c
Add argument to find_lease.
[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[] =
b83bf1d1 46"$Id: confpars.c,v 1.122 2000/08/15 22:23:33 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
2d59f590 587 if (declaration) {
35454d8a
TL
588 parse_warn (cfile,
589 "parameters not allowed after first declaration.");
7dfc8ac2 590 return 1;
1f814ff2 591 }
7dfc8ac2
TL
592
593 return 0;
d7837182
TL
594}
595
763adef1
TL
596#if defined (FAILOVER_PROTOCOL)
597void parse_failover_peer (cfile, group, type)
35454d8a 598 struct parse *cfile;
763adef1
TL
599 struct group *group;
600 int type;
601{
602 enum dhcp_token token;
b1b7b521 603 const char *val;
9e9b2261
TL
604 dhcp_failover_state_t *peer;
605 u_int32_t *tp;
763adef1 606 char *name;
9e9b2261
TL
607 u_int32_t split;
608 u_int8_t hba [32];
165bce70 609 unsigned hba_len = sizeof hba;
9e9b2261
TL
610 int i;
611 struct expression *expr;
e9623235
TL
612 isc_result_t status;
613 struct option_cache **paddr;
614 int *pport;
763adef1
TL
615
616 token = next_token (&val, cfile);
617 if (token != PEER) {
9e9b2261 618 parse_warn (cfile, "expecting \"peer\"");
763adef1
TL
619 skip_to_semi (cfile);
620 return;
621 }
622
623 token = next_token (&val, cfile);
624 if (is_identifier (token) || token == STRING) {
436f1c8c 625 name = dmalloc (strlen (val) + 1, MDL);
9e9b2261 626 if (!name)
8ae2d595 627 log_fatal ("no memory for peer name %s", name);
9e9b2261 628 strcpy (name, val);
763adef1 629 } else {
9e9b2261 630 parse_warn (cfile, "expecting failover peer name.");
763adef1
TL
631 skip_to_semi (cfile);
632 return;
633 }
634
635 /* See if there's a peer declaration by this name. */
9e9b2261 636 peer = (dhcp_failover_state_t *)0;
20916cae 637 find_failover_peer (&peer, name, MDL);
763adef1
TL
638
639 token = next_token (&val, cfile);
640 if (token == SEMI) {
436f1c8c 641 dfree (name, MDL);
763adef1 642 if (type != SHARED_NET_DECL)
35454d8a 643 parse_warn (cfile, "failover peer reference not %s",
763adef1
TL
644 "in shared-network declaration");
645 else {
646 if (!peer) {
35454d8a 647 parse_warn (cfile, "reference to unknown%s%s",
763adef1
TL
648 " failover peer ", name);
649 return;
650 }
20916cae
TL
651 dhcp_failover_state_reference
652 (&group -> shared_network -> failover_peer,
653 peer, MDL);
763adef1 654 }
20916cae 655 dhcp_failover_state_dereference (&peer, MDL);
763adef1 656 return;
a4ba3160 657 } else if (token == STATE) {
763adef1 658 if (!peer) {
a4ba3160 659 parse_warn (cfile, "state declaration for unknown%s%s",
763adef1
TL
660 " failover peer ", name);
661 return;
662 }
a4ba3160 663 parse_failover_state_declaration (cfile, peer);
20916cae 664 dhcp_failover_state_dereference (&peer, MDL);
763adef1
TL
665 return;
666 } else if (token != LBRACE) {
35454d8a 667 parse_warn (cfile, "expecting left brace");
763adef1
TL
668 skip_to_semi (cfile);
669 }
670
671 /* Make sure this isn't a redeclaration. */
672 if (peer) {
35454d8a 673 parse_warn (cfile, "redeclaration of failover peer %s", name);
763adef1 674 skip_to_rbrace (cfile, 1);
20916cae 675 dhcp_failover_state_dereference (&peer, MDL);
763adef1
TL
676 return;
677 }
678
20916cae
TL
679 status = dhcp_failover_state_allocate (&peer, MDL);
680 if (status != ISC_R_SUCCESS)
681 log_fatal ("Can't allocate failover peer %s: %s",
682 name, isc_result_totext (status));
763adef1
TL
683
684 /* Save the name. */
685 peer -> name = name;
686
a4ba3160 687 /* Set the initial state. */
b83bf1d1 688 peer -> my_state = potential_conflict;
a4ba3160
TL
689 peer -> my_stos = cur_time;
690 peer -> partner_state = unknown_state;
691 peer -> partner_stos = cur_time;
692
763adef1
TL
693 do {
694 token = next_token (&val, cfile);
695 switch (token) {
696 case RBRACE:
697 break;
9e9b2261 698
763adef1
TL
699 case PRIMARY:
700 peer -> i_am = primary;
701 break;
9e9b2261 702
763adef1
TL
703 case SECONDARY:
704 peer -> i_am = secondary;
007e3ee4
TL
705 if (peer -> hba)
706 parse_warn (cfile,
707 "secondary may not define %s",
708 "load balance settings.");
763adef1 709 break;
9e9b2261 710
e9623235
TL
711 case PEER:
712 token = next_token (&val, cfile);
713 switch (token) {
714 case ADDRESS:
715 paddr = &peer -> address;
716 goto doaddr;
717 case PORT:
718 pport = &peer -> port;
719 goto doport;
720 default:
721 parse_warn (cfile,
722 "expecting 'address' or 'port'");
723 skip_to_rbrace (cfile, 1);
20916cae 724 dhcp_failover_state_dereference (&peer, MDL);
e9623235
TL
725 return;
726 }
727 break;
728
729 case ADDRESS:
730 paddr = &peer -> server_addr;
731 doaddr:
9e9b2261
TL
732 expr = (struct expression *)0;
733 if (!parse_ip_addr_or_hostname (&expr, cfile, 0)) {
763adef1 734 skip_to_rbrace (cfile, 1);
20916cae 735 dhcp_failover_state_dereference (&peer, MDL);
763adef1
TL
736 return;
737 }
e9623235 738 option_cache (paddr, (struct data_string *)0, expr,
9e9b2261 739 (struct option *)0);
436f1c8c 740 expression_dereference (&expr, MDL);
763adef1 741 break;
e9623235 742
763adef1 743 case PORT:
e9623235
TL
744 pport = &peer -> listen_port;
745 doport:
763adef1
TL
746 token = next_token (&val, cfile);
747 if (token != NUMBER) {
35454d8a 748 parse_warn (cfile, "expecting number");
763adef1
TL
749 skip_to_rbrace (cfile, 1);
750 }
e9623235 751 *pport = atoi (val);
763adef1 752 break;
9e9b2261 753
763adef1
TL
754 case MAX_TRANSMIT_IDLE:
755 tp = &peer -> max_transmit_idle;
756 goto parse_idle;
9e9b2261 757
763adef1 758 case MAX_RESPONSE_DELAY:
81b53730 759 tp = &peer -> max_response_delay;
763adef1
TL
760 parse_idle:
761 token = next_token (&val, cfile);
762 if (token != NUMBER) {
35454d8a 763 parse_warn (cfile, "expecting number.");
763adef1 764 skip_to_rbrace (cfile, 1);
20916cae 765 dhcp_failover_state_dereference (&peer, MDL);
763adef1
TL
766 return;
767 }
768 *tp = atoi (val);
9e9b2261
TL
769 break;
770
771 case MAX_UNACKED_UPDATES:
772 tp = &peer -> max_flying_updates;
773 goto parse_idle;
774
775 case MCLT:
776 tp = &peer -> mclt;
777 goto parse_idle;
778
779 case HBA:
e9623235 780 hba_len = 32;
007e3ee4
TL
781 if (peer -> i_am == secondary)
782 parse_warn (cfile,
783 "secondary may not define %s",
784 "load balance settings.");
9e9b2261 785 if (!parse_numeric_aggregate (cfile, hba, &hba_len,
e9623235 786 COLON, 16, 8)) {
9e9b2261 787 skip_to_rbrace (cfile, 1);
20916cae 788 dhcp_failover_state_dereference (&peer, MDL);
9e9b2261
TL
789 return;
790 }
e9623235
TL
791 if (hba_len != 32) {
792 parse_warn (cfile,
793 "HBA must be exactly 32 bytes.");
794 dfree (hba, MDL);
795 break;
796 }
9e9b2261 797 make_hba:
436f1c8c 798 peer -> hba = dmalloc (32, MDL);
9e9b2261 799 if (!peer -> hba) {
436f1c8c
TL
800 dfree (peer -> name, MDL);
801 dfree (peer, MDL);
9e9b2261
TL
802 }
803 memcpy (peer -> hba, hba, 32);
804 break;
805
806 case SPLIT:
807 token = next_token (&val, cfile);
007e3ee4
TL
808 if (peer -> i_am == secondary)
809 parse_warn (cfile,
810 "secondary may not define %s",
811 "load balance settings.");
9e9b2261
TL
812 if (token != NUMBER) {
813 parse_warn (cfile, "expecting number");
20916cae 814 badsplit:
9e9b2261 815 skip_to_rbrace (cfile, 1);
20916cae 816 dhcp_failover_state_dereference (&peer, MDL);
9e9b2261
TL
817 return;
818 }
20916cae
TL
819 split = atoi (val);
820 if (!parse_semi (cfile))
821 goto badsplit;
9e9b2261
TL
822 if (split > 255) {
823 parse_warn (cfile, "split must be < 256");
824 } else {
825 memset (hba, 0, sizeof hba);
826 for (i = 0; i < split; i++) {
827 if (i < split)
828 hba [i / 8] |= (1 << (i & 7));
829 }
830 goto make_hba;
831 }
832 break;
833
e9623235
TL
834 case LOAD:
835 token = next_token (&val, cfile);
836 if (token != BALANCE) {
837 parse_warn (cfile, "expecting 'balance'");
838 badload:
839 skip_to_rbrace (cfile, 1);
840 break;
841 }
842 token = next_token (&val, cfile);
843 if (token != TOKEN_MAX) {
844 parse_warn (cfile, "expecting 'max'");
845 goto badload;
846 }
847 token = next_token (&val, cfile);
848 if (token != SECONDS) {
849 parse_warn (cfile, "expecting 'secs'");
850 goto badload;
851 }
852 token = next_token (&val, cfile);
853 if (token != NUMBER) {
854 parse_warn (cfile, "expecting number");
855 goto badload;
856 }
857 peer -> load_balance_max_secs = atoi (val);
858 break;
859
763adef1 860 default:
35454d8a
TL
861 parse_warn (cfile,
862 "invalid statement in peer declaration");
763adef1 863 skip_to_rbrace (cfile, 1);
20916cae 864 dhcp_failover_state_dereference (&peer, MDL);
763adef1
TL
865 return;
866 }
e9623235
TL
867 if (token != RBRACE && !parse_semi (cfile)) {
868 skip_to_rbrace (cfile, 1);
20916cae 869 dhcp_failover_state_dereference (&peer, MDL);
e9623235
TL
870 return;
871 }
763adef1
TL
872 } while (token != RBRACE);
873
007e3ee4
TL
874 if (peer -> i_am == primary && !peer -> hba) {
875 parse_warn (cfile,
876 "primary failover server must have hba or split.");
877 }
878
763adef1
TL
879 if (type == SHARED_NET_DECL) {
880 group -> shared_network -> failover_peer = peer;
881 }
e9623235
TL
882 status = enter_failover_peer (peer);
883 if (status != ISC_R_SUCCESS)
884 parse_warn (cfile, "failover peer %s: %s",
885 peer -> name, isc_result_totext (status));
20916cae 886 dhcp_failover_state_dereference (&peer, MDL);
763adef1
TL
887}
888
a4ba3160
TL
889void parse_failover_state_declaration (struct parse *cfile,
890 dhcp_failover_state_t *peer)
891{
892 enum dhcp_token token;
893 const char *val;
894 char *name;
895 dhcp_failover_state_t *state;
896
897 if (!peer) {
898 token = next_token (&val, cfile);
899 if (token != PEER) {
900 parse_warn (cfile, "expecting \"peer\"");
901 skip_to_semi (cfile);
902 return;
903 }
904
905 token = next_token (&val, cfile);
906 if (is_identifier (token) || token == STRING) {
907 name = dmalloc (strlen (val) + 1, MDL);
908 if (!name)
909 log_fatal ("failover peer name %s: no memory",
910 name);
911 strcpy (name, val);
912 } else {
913 parse_warn (cfile, "expecting failover peer name.");
914 skip_to_semi (cfile);
915 return;
916 }
917
918 /* See if there's a peer declaration by this name. */
919 state = (dhcp_failover_state_t *)0;
20916cae 920 find_failover_peer (&state, name, MDL);
a4ba3160
TL
921 if (!state) {
922 parse_warn (cfile, "unknown failover peer: %s", name);
923 skip_to_semi (cfile);
924 return;
925 }
926
927 token = next_token (&val, cfile);
928 if (token != STATE) {
929 parse_warn (cfile, "expecting 'state'");
930 if (token != SEMI)
931 skip_to_semi (cfile);
932 return;
933 }
20916cae
TL
934 } else {
935 state = (dhcp_failover_state_t *)0;
936 dhcp_failover_state_reference (&state, peer, MDL);
937 }
a4ba3160
TL
938 token = next_token (&val, cfile);
939 if (token != LBRACE) {
940 parse_warn (cfile, "expecting left brace");
941 if (token != SEMI)
942 skip_to_semi (cfile);
20916cae 943 dhcp_failover_state_dereference (&state, MDL);
a4ba3160
TL
944 return;
945 }
946 do {
947 token = next_token (&val, cfile);
948 switch (token) {
949 case RBRACE:
950 break;
951 case MY:
952 token = next_token (&val, cfile);
953 if (token != STATE) {
954 parse_warn (cfile, "expecting 'state'");
20916cae 955 goto bogus;
a4ba3160
TL
956 }
957 parse_failover_state (cfile,
958 &state -> my_state,
959 &state -> my_stos);
960 break;
961 case PARTNER:
962 token = next_token (&val, cfile);
963 if (token != STATE) {
964 parse_warn (cfile, "expecting 'state'");
20916cae 965 goto bogus;
a4ba3160
TL
966 }
967 parse_failover_state (cfile,
968 &state -> partner_state,
969 &state -> partner_stos);
970 break;
971 default:
20916cae 972 bogus:
a4ba3160 973 parse_warn (cfile, "expecting state setting.");
20916cae
TL
974 skip_to_rbrace (cfile, 1);
975 dhcp_failover_state_dereference (&state, MDL);
a4ba3160
TL
976 return;
977 }
978 } while (token != RBRACE);
20916cae 979 dhcp_failover_state_dereference (&state, MDL);
a4ba3160
TL
980}
981
9e9b2261 982void parse_failover_state (cfile, state, stos)
35454d8a 983 struct parse *cfile;
9e9b2261
TL
984 enum failover_state *state;
985 TIME *stos;
763adef1
TL
986{
987 enum dhcp_token token;
b1b7b521 988 const char *val;
9e9b2261
TL
989 enum failover_state state_in;
990 TIME stos_in;
763adef1
TL
991
992 token = next_token (&val, cfile);
993 switch (token) {
994 case PARTNER_DOWN:
9e9b2261
TL
995 state_in = partner_down;
996 break;
997
763adef1 998 case NORMAL:
9e9b2261
TL
999 state_in = normal;
1000 break;
1001
763adef1 1002 case COMMUNICATIONS_INTERRUPTED:
9e9b2261
TL
1003 state_in = communications_interrupted;
1004 break;
1005
763adef1 1006 case POTENTIAL_CONFLICT:
9e9b2261
TL
1007 state_in = potential_conflict;
1008 break;
1009
a4ba3160
TL
1010 case POTENTIAL_CONFLICT_NIC:
1011 state_in = potential_conflict;
1012 break;
1013
763adef1 1014 case RECOVER:
9e9b2261
TL
1015 state_in = recover;
1016 break;
a4ba3160
TL
1017
1018 case UNKNOWN_STATE:
1019 state_in = unknown_state;
1020 break;
9e9b2261 1021
763adef1 1022 default:
35454d8a 1023 parse_warn (cfile, "unknown failover state");
9e9b2261
TL
1024 skip_to_semi (cfile);
1025 return;
763adef1 1026 }
9e9b2261
TL
1027
1028 token = next_token (&val, cfile);
1029 if (token != AT) {
1030 parse_warn (cfile, "expecting \"at\"");
1031 skip_to_semi (cfile);
1032 return;
1033 }
1034
1035 stos_in = parse_date (cfile);
1036 if (!stos_in)
1037 return;
1038
1039 /* Now that we've apparently gotten a clean parse, we can trust
1040 that this is a state that was fully committed to disk, so
1041 we can install it. */
1042 *stos = stos_in;
1043 *state = state_in;
763adef1
TL
1044}
1045#endif /* defined (FAILOVER_PROTOCOL) */
1046
f63b4929 1047void parse_pool_statement (cfile, group, type)
35454d8a 1048 struct parse *cfile;
f63b4929
TL
1049 struct group *group;
1050 int type;
1051{
1052 enum dhcp_token token;
b1b7b521 1053 const char *val;
f63b4929
TL
1054 int done = 0;
1055 struct pool *pool, **p;
1056 struct permit *permit;
1057 struct permit **permit_head;
74f45f96 1058 int declaration = 0;
e9623235 1059 isc_result_t status;
f63b4929 1060
20916cae
TL
1061 pool = (struct pool *)0;
1062 status = pool_allocate (&pool, MDL);
1063 if (status != ISC_R_SUCCESS)
6ceb9118
TL
1064 log_fatal ("no memory for pool: %s",
1065 isc_result_totext (status));
f63b4929 1066
f84d544b 1067 if (!clone_group (&pool -> group, group, MDL))
6ceb9118 1068 log_fatal ("can't clone pool group.");
74f45f96 1069
9e9b2261 1070 if (type == SUBNET_DECL)
20916cae
TL
1071 shared_network_reference (&pool -> shared_network,
1072 group -> subnet -> shared_network,
1073 MDL);
9e9b2261 1074 else
20916cae
TL
1075 shared_network_reference (&pool -> shared_network,
1076 group -> shared_network, MDL);
9e9b2261 1077
22009f79 1078#if defined (FAILOVER_PROTOCOL)
9e9b2261
TL
1079 /* Inherit the failover peer from the shared network. */
1080 if (pool -> shared_network -> failover_peer)
20916cae
TL
1081 dhcp_failover_state_reference
1082 (&pool -> failover_peer,
1083 pool -> shared_network -> failover_peer, MDL);
22009f79 1084#endif
9e9b2261 1085
20916cae
TL
1086 if (!parse_lbrace (cfile)) {
1087 pool_dereference (&pool, MDL);
f63b4929 1088 return;
20916cae
TL
1089 }
1090
f63b4929 1091 do {
e5e41be4
TL
1092 token = peek_token (&val, cfile);
1093 switch (token) {
9e9b2261
TL
1094 case NO:
1095 next_token (&val, cfile);
1096 token = next_token (&val, cfile);
1097 if (token != FAILOVER ||
1098 (token = next_token (&val, cfile)) != PEER) {
1099 parse_warn (cfile,
1100 "expecting \"failover peer\".");
1101 skip_to_semi (cfile);
1102 continue;
1103 }
22009f79 1104#if defined (FAILOVER_PROTOCOL)
9e9b2261 1105 if (pool -> failover_peer)
20916cae
TL
1106 dhcp_failover_state_dereference
1107 (&pool -> failover_peer, MDL);
22009f79 1108#endif
9e9b2261
TL
1109 break;
1110
a4ba3160 1111#if defined (FAILOVER_PROTOCOL)
e9623235
TL
1112 case FAILOVER:
1113 next_token (&val, cfile);
1114 token = next_token (&val, cfile);
1115 if (token != PEER) {
1116 parse_warn (cfile, "expecting 'peer'.");
1117 skip_to_semi (cfile);
1118 break;
1119 }
1120 token = next_token (&val, cfile);
1121 if (token != STRING) {
1122 parse_warn (cfile, "expecting string.");
1123 skip_to_semi (cfile);
1124 break;
1125 }
1126 if (pool -> failover_peer)
20916cae
TL
1127 dhcp_failover_state_dereference
1128 (&pool -> failover_peer, MDL);
e9623235 1129 status = find_failover_peer (&pool -> failover_peer,
20916cae 1130 val, MDL);
e9623235
TL
1131 if (status != ISC_R_SUCCESS)
1132 parse_warn (cfile,
1133 "failover peer %s: %s", val,
1134 isc_result_totext (status));
1135 parse_semi (cfile);
1136 break;
a4ba3160 1137#endif
e9623235 1138
f63b4929
TL
1139 case RANGE:
1140 next_token (&val, cfile);
1141 parse_address_range (cfile, group, type, pool);
1142 break;
1143 case ALLOW:
1144 permit_head = &pool -> permit_list;
1145 get_permit:
436f1c8c 1146 permit = new_permit (MDL);
f63b4929 1147 if (!permit)
8ae2d595 1148 log_fatal ("no memory for permit");
f63b4929
TL
1149 next_token (&val, cfile);
1150 token = next_token (&val, cfile);
1151 switch (token) {
1152 case UNKNOWN:
1153 permit -> type = permit_unknown_clients;
1154 get_clients:
1155 if (next_token (&val, cfile) != CLIENTS) {
35454d8a
TL
1156 parse_warn (cfile,
1157 "expecting \"clients\"");
f63b4929 1158 skip_to_semi (cfile);
436f1c8c 1159 free_permit (permit, MDL);
f63b4929
TL
1160 continue;
1161 }
1162 break;
1163
ad1a6484
TL
1164 case UNKNOWN_CLIENTS:
1165 permit -> type = permit_unknown_clients;
1166 break;
1167
f63b4929
TL
1168 case KNOWN:
1169 permit -> type = permit_known_clients;
1170 goto get_clients;
1171
1172 case AUTHENTICATED:
1173 permit -> type = permit_authenticated_clients;
1174 goto get_clients;
1175
1176 case UNAUTHENTICATED:
1177 permit -> type =
1178 permit_unauthenticated_clients;
1179 goto get_clients;
1180
1181 case ALL:
1182 permit -> type = permit_all_clients;
1183 goto get_clients;
1184 break;
1185
1186 case DYNAMIC:
1187 permit -> type = permit_dynamic_bootp_clients;
007e3ee4 1188 if (next_token (&val, cfile) != TOKEN_BOOTP) {
35454d8a
TL
1189 parse_warn (cfile,
1190 "expecting \"bootp\"");
f63b4929 1191 skip_to_semi (cfile);
436f1c8c 1192 free_permit (permit, MDL);
f63b4929
TL
1193 continue;
1194 }
1195 goto get_clients;
1196
1197 case MEMBERS:
1198 if (next_token (&val, cfile) != OF) {
35454d8a 1199 parse_warn (cfile, "expecting \"of\"");
f63b4929 1200 skip_to_semi (cfile);
436f1c8c 1201 free_permit (permit, MDL);
f63b4929
TL
1202 continue;
1203 }
1204 if (next_token (&val, cfile) != STRING) {
35454d8a
TL
1205 parse_warn (cfile,
1206 "expecting class name.");
f63b4929 1207 skip_to_semi (cfile);
436f1c8c 1208 free_permit (permit, MDL);
f63b4929
TL
1209 continue;
1210 }
1211 permit -> type = permit_class;
20916cae
TL
1212 permit -> class = (struct class *)0;
1213 find_class (&permit -> class, val, MDL);
f63b4929 1214 if (!permit -> class)
35454d8a
TL
1215 parse_warn (cfile,
1216 "no such class: %s", val);
e5e41be4
TL
1217 break;
1218
f63b4929 1219 default:
35454d8a 1220 parse_warn (cfile, "expecting permit type.");
f63b4929
TL
1221 skip_to_semi (cfile);
1222 break;
1223 }
1224 while (*permit_head)
1225 permit_head = &((*permit_head) -> next);
1226 *permit_head = permit;
74f45f96 1227 parse_semi (cfile);
f63b4929
TL
1228 break;
1229
1230 case DENY:
1231 permit_head = &pool -> prohibit_list;
1232 goto get_permit;
1233
1234 case RBRACE:
1235 next_token (&val, cfile);
1236 done = 1;
1237 break;
1238
1239 default:
74f45f96
TL
1240 declaration = parse_statement (cfile, pool -> group,
1241 POOL_DECL,
1242 (struct host_decl *)0,
1243 declaration);
f63b4929
TL
1244 break;
1245 }
1246 } while (!done);
1247
9e9b2261
TL
1248#if defined (FAILOVER_PROTOCOL)
1249 /* We can't do failover on a pool that supports dynamic bootp,
1250 because BOOTP doesn't support leases, and failover absolutely
1251 depends on lease timing. */
1252 if (pool -> failover_peer) {
1253 for (permit = pool -> permit_list;
1254 permit; permit = permit -> next) {
1255 if (permit -> type == permit_dynamic_bootp_clients ||
1256 permit -> type == permit_all_clients) {
1257 dynamic_bootp_clash:
1258 parse_warn (cfile,
1259 "pools with failover peers %s",
1260 "may not permit dynamic bootp.");
e9623235 1261 log_error ("Either write a \"no failover\" %s",
9e9b2261
TL
1262 "statement and use disjoint");
1263 log_error ("pools, or don't permit dynamic%s",
e9623235 1264 " bootp.");
9e9b2261 1265 log_error ("This is a protocol limitation,%s",
e9623235 1266 " not an ISC DHCP limitation, so");
9e9b2261
TL
1267 log_error ("please don't request an %s",
1268 "enhancement or ask why this is.");
1269 goto clash_testing_done;
1270 }
1271 }
1272 if (!pool -> permit_list) {
1273 if (!pool -> prohibit_list)
1274 goto dynamic_bootp_clash;
1275
1276 for (permit = pool -> prohibit_list; permit;
1277 permit = permit -> next) {
1278 if (permit -> type ==
1279 permit_dynamic_bootp_clients ||
1280 permit -> type == permit_all_clients)
1281 goto clash_testing_done;
1282 }
1283 }
1284 }
1285 clash_testing_done:
1286#endif /* FAILOVER_PROTOCOL */
1287
f63b4929
TL
1288 p = &pool -> shared_network -> pools;
1289 for (; *p; p = &((*p) -> next))
1290 ;
20916cae
TL
1291 pool_reference (p, pool, MDL);
1292 pool_dereference (&pool, MDL);
f63b4929
TL
1293}
1294
5376e3e9
TL
1295/* boolean :== ON SEMI | OFF SEMI | TRUE SEMI | FALSE SEMI */
1296
1297int parse_boolean (cfile)
35454d8a 1298 struct parse *cfile;
5376e3e9 1299{
6f8fb41f 1300 enum dhcp_token token;
b1b7b521 1301 const char *val;
5376e3e9
TL
1302 int rv;
1303
1304 token = next_token (&val, cfile);
1305 if (!strcasecmp (val, "true")
1306 || !strcasecmp (val, "on"))
b179c997 1307 rv = 1;
5376e3e9
TL
1308 else if (!strcasecmp (val, "false")
1309 || !strcasecmp (val, "off"))
1310 rv = 0;
1311 else {
35454d8a
TL
1312 parse_warn (cfile,
1313 "boolean value (true/false/on/off) expected");
5376e3e9
TL
1314 skip_to_semi (cfile);
1315 return 0;
1316 }
1317 parse_semi (cfile);
1318 return rv;
1319}
1320
7dfc8ac2
TL
1321/* Expect a left brace; if there isn't one, skip over the rest of the
1322 statement and return zero; otherwise, return 1. */
1323
1324int parse_lbrace (cfile)
35454d8a 1325 struct parse *cfile;
7dfc8ac2 1326{
6f8fb41f 1327 enum dhcp_token token;
b1b7b521 1328 const char *val;
7dfc8ac2
TL
1329
1330 token = next_token (&val, cfile);
1331 if (token != LBRACE) {
35454d8a 1332 parse_warn (cfile, "expecting left brace.");
7dfc8ac2
TL
1333 skip_to_semi (cfile);
1334 return 0;
1335 }
1336 return 1;
d7837182
TL
1337}
1338
7dfc8ac2 1339
2d59f590 1340/* host-declaration :== hostname RBRACE parameters declarations LBRACE */
d7837182 1341
2d59f590 1342void parse_host_declaration (cfile, group)
35454d8a 1343 struct parse *cfile;
7dfc8ac2 1344 struct group *group;
d7837182 1345{
b1b7b521 1346 const char *val;
6f8fb41f 1347 enum dhcp_token token;
7dfc8ac2 1348 struct host_decl *host;
f3c3d674 1349 char *name;
2d59f590 1350 int declaration = 0;
612fded7 1351 int dynamicp = 0;
ff129930 1352 int deleted = 0;
92ce3f81 1353 isc_result_t status;
7dfc8ac2 1354
20916cae
TL
1355 name = parse_host_name (cfile);
1356 if (!name)
1357 return;
7dfc8ac2 1358
20916cae
TL
1359 host = (struct host_decl *)0;
1360 status = host_allocate (&host, MDL);
1361 if (status != ISC_R_SUCCESS)
1362 log_fatal ("can't allocate host decl struct %s: %s",
1363 name, isc_result_totext (status));
7dfc8ac2 1364 host -> name = name;
f84d544b
TL
1365 if (!clone_group (&host -> group, group, MDL)) {
1366 log_fatal ("can't clone group for host %s", name);
20916cae
TL
1367 boom:
1368 host_dereference (&host, MDL);
1369 return;
1370 }
7dfc8ac2
TL
1371
1372 if (!parse_lbrace (cfile))
20916cae 1373 goto boom;
d7837182 1374
d7837182
TL
1375 do {
1376 token = peek_token (&val, cfile);
7dfc8ac2 1377 if (token == RBRACE) {
d7837182
TL
1378 token = next_token (&val, cfile);
1379 break;
1380 }
5376e3e9
TL
1381 if (token == EOF) {
1382 token = next_token (&val, cfile);
35454d8a 1383 parse_warn (cfile, "unexpected end of file");
5376e3e9
TL
1384 break;
1385 }
612fded7
TL
1386 /* If the host declaration was created by the server,
1387 remember to save it. */
1388 if (token == DYNAMIC) {
1389 dynamicp = 1;
1390 token = next_token (&val, cfile);
1391 if (!parse_semi (cfile))
1392 break;
1393 continue;
1394 }
ff129930
TL
1395 /* If the host declaration was created by the server,
1396 remember to save it. */
007e3ee4 1397 if (token == TOKEN_DELETED) {
ff129930
TL
1398 deleted = 1;
1399 token = next_token (&val, cfile);
1400 if (!parse_semi (cfile))
1401 break;
1402 continue;
1403 }
29c35bed
TL
1404
1405 if (token == GROUP) {
1406 struct group_object *go;
1407 token = next_token (&val, cfile);
1408 token = next_token (&val, cfile);
1409 if (token != STRING && !is_identifier (token)) {
35454d8a
TL
1410 parse_warn (cfile,
1411 "expecting string or identifier.");
29c35bed
TL
1412 skip_to_rbrace (cfile, 1);
1413 break;
1414 }
20916cae
TL
1415 go = (struct group_object *)0;
1416 if (!group_hash_lookup (&go, group_name_hash,
1417 val, strlen (val), MDL)) {
35454d8a
TL
1418 parse_warn (cfile, "unknown group %s in host %s",
1419 val, host -> name);
29c35bed
TL
1420 } else {
1421 if (host -> named_group)
20916cae
TL
1422 group_object_dereference
1423 (&host -> named_group, MDL);
1424 group_object_reference (&host -> named_group,
1425 go, MDL);
1426 group_object_dereference (&go, MDL);
29c35bed
TL
1427 }
1428 if (!parse_semi (cfile))
1429 break;
1430 continue;
1431 }
1432
1433 if (token == UID) {
b1b7b521 1434 const char *s;
29c35bed 1435 unsigned char *t = 0;
b1b7b521 1436 unsigned len;
29c35bed
TL
1437
1438 token = next_token (&val, cfile);
436f1c8c 1439 data_string_forget (&host -> client_identifier, MDL);
29c35bed
TL
1440
1441 /* See if it's a string or a cshl. */
1442 token = peek_token (&val, cfile);
1443 if (token == STRING) {
1444 token = next_token (&val, cfile);
1445 s = val;
1446 len = strlen (val);
1447 host -> client_identifier.terminated = 1;
1448 } else {
1449 len = 0;
1450 t = parse_numeric_aggregate
1451 (cfile,
1452 (unsigned char *)0, &len, ':', 16, 8);
1453 if (!t) {
35454d8a
TL
1454 parse_warn (cfile,
1455 "expecting hex list.");
29c35bed
TL
1456 skip_to_semi (cfile);
1457 }
b1b7b521 1458 s = (const char *)t;
29c35bed
TL
1459 }
1460 if (!buffer_allocate
1461 (&host -> client_identifier.buffer,
436f1c8c 1462 len + host -> client_identifier.terminated, MDL))
29c35bed
TL
1463 log_fatal ("no memory for uid for host %s.",
1464 host -> name);
1465 host -> client_identifier.data =
1466 host -> client_identifier.buffer -> data;
1467 host -> client_identifier.len = len;
b1b7b521 1468 memcpy (host -> client_identifier.buffer -> data, s,
29c35bed
TL
1469 len + host -> client_identifier.terminated);
1470 if (t)
436f1c8c 1471 dfree (t, MDL);
29c35bed
TL
1472
1473 if (!parse_semi (cfile))
1474 break;
1475 continue;
1476 }
2d59f590
TL
1477 declaration = parse_statement (cfile, host -> group,
1478 HOST_DECL, host,
1479 declaration);
d7837182 1480 } while (1);
7dfc8ac2 1481
ff129930 1482 if (deleted) {
20916cae
TL
1483 struct host_decl *hp = (struct host_decl *)0;
1484 if (host_hash_lookup (&hp, host_name_hash,
1485 (unsigned char *)host -> name,
1486 strlen (host -> name), MDL)) {
ff129930 1487 delete_host (hp, 0);
20916cae 1488 host_dereference (&hp, MDL);
ff129930 1489 }
ff129930 1490 } else {
29c35bed
TL
1491 if (host -> named_group && host -> named_group -> group) {
1492 if (host -> group -> statements ||
1493 (host -> group -> authoritative !=
b83bf1d1
TL
1494 host -> named_group -> group -> authoritative)) {
1495 if (host -> group -> next)
1496 group_dereference (&host -> group -> next,
1497 MDL);
20916cae
TL
1498 group_reference (&host -> group -> next,
1499 host -> named_group -> group,
1500 MDL);
b83bf1d1 1501 } else {
20916cae
TL
1502 group_dereference (&host -> group, MDL);
1503 group_reference (&host -> group,
1504 host -> named_group -> group,
1505 MDL);
29c35bed
TL
1506 }
1507 }
1508
b86799bf
TL
1509 if (dynamicp)
1510 host -> flags |= HOST_DECL_DYNAMIC;
1511 else
1512 host -> flags |= HOST_DECL_STATIC;
1513
92ce3f81
TL
1514 status = enter_host (host, dynamicp, 0);
1515 if (status != ISC_R_SUCCESS)
ab58ff49
TL
1516 parse_warn (cfile, "host %s: %s", host -> name,
1517 isc_result_totext (status));
ff129930 1518 }
20916cae 1519 host_dereference (&host, MDL);
d7837182
TL
1520}
1521
2d59f590 1522/* class-declaration :== STRING LBRACE parameters declarations RBRACE
24a75c03
TL
1523*/
1524
20916cae
TL
1525int parse_class_declaration (cp, cfile, group, type)
1526 struct class **cp;
35454d8a 1527 struct parse *cfile;
7dfc8ac2 1528 struct group *group;
24a75c03
TL
1529 int type;
1530{
b1b7b521 1531 const char *val;
6f8fb41f 1532 enum dhcp_token token;
20916cae 1533 struct class *class = (struct class *)0, *pc = (struct class *)0;
f4d0f440 1534 int declaration = 0;
e5e41be4 1535 int lose = 0;
ece6ea33 1536 struct data_string data;
b1b7b521 1537 const char *name;
ece6ea33
TL
1538 struct executable_statement *stmt = (struct executable_statement *)0;
1539 struct expression *expr;
de94ca72 1540 int new = 1;
20916cae 1541 isc_result_t status;
24a75c03
TL
1542
1543 token = next_token (&val, cfile);
1544 if (token != STRING) {
35454d8a 1545 parse_warn (cfile, "Expecting class name");
24a75c03 1546 skip_to_semi (cfile);
20916cae 1547 return 0;
24a75c03
TL
1548 }
1549
ece6ea33 1550 /* See if there's already a class with the specified name. */
20916cae 1551 find_class (&pc, val, MDL);
ece6ea33
TL
1552
1553 /* If this isn't a subclass, we're updating an existing class. */
1554 if (pc && type != 0 && type != 1 && type != 3) {
20916cae 1555 class_reference (&class, pc, MDL);
de94ca72 1556 new = 0;
20916cae 1557 class_dereference (&pc, MDL);
ece6ea33
TL
1558 }
1559
1560 /* If this _is_ a subclass, there _must_ be a class with the
1561 same name. */
1562 if (!pc && (type == 0 || type == 1 || type == 3)) {
35454d8a 1563 parse_warn (cfile, "no class named %s", val);
ece6ea33 1564 skip_to_semi (cfile);
20916cae 1565 return 0;
ece6ea33
TL
1566 }
1567
1568 /* The old vendor-class and user-class declarations had an implicit
1569 match. We don't do the implicit match anymore. Instead, for
1570 backward compatibility, we have an implicit-vendor-class and an
1571 implicit-user-class. vendor-class and user-class declarations
1572 are turned into subclasses of the implicit classes, and the
8b500185 1573 submatch expression of the implicit classes extracts the contents of
ece6ea33
TL
1574 the vendor class or user class. */
1575 if (type == 0 || type == 1) {
1576 data.len = strlen (val);
6f8fb41f 1577 data.buffer = (struct buffer *)0;
436f1c8c 1578 if (!buffer_allocate (&data.buffer, data.len + 1, MDL))
20916cae 1579 log_fatal ("no memory for class name.");
6f8fb41f 1580 data.data = &data.buffer -> data [0];
ece6ea33
TL
1581 data.terminated = 1;
1582
1583 name = type ? "implicit-vendor-class" : "implicit-user-class";
1584 } else if (type == 2) {
20916cae
TL
1585 name = val;
1586 } else {
1587 name = (char *)0;
1588 }
1589
1590 if (name) {
b1b7b521 1591 char *tname;
436f1c8c 1592 if (!(tname = dmalloc (strlen (val) + 1, MDL)))
8ae2d595 1593 log_fatal ("No memory for class name %s.", val);
b1b7b521
TL
1594 strcpy (tname, val);
1595 name = tname;
ece6ea33
TL
1596 }
1597
1598 /* If this is a straight subclass, parse the hash string. */
1599 if (type == 3) {
1600 token = peek_token (&val, cfile);
1601 if (token == STRING) {
1602 token = next_token (&val, cfile);
1603 data.len = strlen (val);
6f8fb41f 1604 data.buffer = (struct buffer *)0;
20916cae
TL
1605 if (!buffer_allocate (&data.buffer,
1606 data.len + 1, MDL)) {
1607 if (pc)
1608 class_dereference (&pc, MDL);
1609
1610 return 0;
1611 }
ece6ea33 1612 data.terminated = 1;
6f8fb41f 1613 data.data = &data.buffer -> data [0];
b1b7b521 1614 strcpy ((char *)data.buffer -> data, val);
ece6ea33 1615 } else if (token == NUMBER_OR_NAME || token == NUMBER) {
6f8fb41f 1616 memset (&data, 0, sizeof data);
20916cae
TL
1617 if (!parse_cshl (&data, cfile)) {
1618 class_dereference (&pc, MDL);
1619 }
1620 return 0;
e68de775 1621 } else {
35454d8a 1622 parse_warn (cfile, "Expecting string or hex list.");
20916cae
TL
1623 class_dereference (&pc, MDL);
1624 return 0;
ece6ea33
TL
1625 }
1626 }
1627
1628 /* See if there's already a class in the hash table matching the
1629 hash data. */
1630 if (type == 0 || type == 1 || type == 3)
20916cae
TL
1631 class_hash_lookup (&class, pc -> hash,
1632 (const char *)data.data, data.len, MDL);
ece6ea33
TL
1633
1634 /* If we didn't find an existing class, allocate a new one. */
1635 if (!class) {
1636 /* Allocate the class structure... */
20916cae 1637 status = class_allocate (&class, MDL);
ece6ea33 1638 if (pc) {
20916cae
TL
1639 group_reference (&class -> group, pc -> group, MDL);
1640 class_reference (&class -> superclass, pc, MDL);
88dcab62
TL
1641 class -> lease_limit = pc -> lease_limit;
1642 if (class -> lease_limit) {
1643 class -> billed_leases =
1644 dmalloc (class -> lease_limit *
436f1c8c 1645 sizeof (struct lease *), MDL);
88dcab62 1646 if (!class -> billed_leases)
e68de775 1647 log_fatal ("no memory for billing");
88dcab62
TL
1648 memset (class -> billed_leases, 0,
1649 (class -> lease_limit *
1650 sizeof class -> billed_leases));
1651 }
436f1c8c 1652 data_string_copy (&class -> hash_string, &data, MDL);
88dcab62 1653 if (!pc -> hash)
20916cae
TL
1654 pc -> hash =
1655 new_hash ((hash_reference)
1656 omapi_object_reference,
1657 (hash_dereference)
1658 omapi_object_dereference, 0);
ece6ea33 1659 add_hash (pc -> hash,
88dcab62
TL
1660 class -> hash_string.data,
1661 class -> hash_string.len,
20916cae 1662 (void *)class, MDL);
ece6ea33 1663 } else {
20916cae
TL
1664 if (!clone_group (&class -> group, group, MDL))
1665 log_fatal ("no memory to clone class group.");
ece6ea33
TL
1666 }
1667
1668 /* If this is an implicit vendor or user class, add a
1669 statement that causes the vendor or user class ID to
1670 be sent back in the reply. */
1671 if (type == 0 || type == 1) {
20916cae
TL
1672 stmt = (struct executable_statement *)0;
1673 if (!executable_statement_allocate (&stmt, MDL))
8ae2d595 1674 log_fatal ("no memory for class statement.");
ece6ea33 1675 stmt -> op = supersede_option_statement;
6f8fb41f 1676 if (option_cache_allocate (&stmt -> data.option,
436f1c8c 1677 MDL)) {
6f8fb41f
TL
1678 stmt -> data.option -> data = data;
1679 stmt -> data.option -> option =
1680 dhcp_universe.options
1681 [type
ca3a51a5
TL
1682 ? DHO_VENDOR_CLASS_IDENTIFIER
1683 : DHO_USER_CLASS];
6f8fb41f 1684 }
ece6ea33
TL
1685 class -> statements = stmt;
1686 }
de94ca72
TL
1687
1688 /* Save the name, if there is one. */
1689 class -> name = name;
ece6ea33 1690 }
7dfc8ac2 1691
88dcab62 1692 if (type == 0 || type == 1 || type == 3)
436f1c8c 1693 data_string_forget (&data, MDL);
88dcab62 1694
20916cae 1695 /* Spawned classes don't have to have their own settings. */
88dcab62 1696 if (class -> superclass) {
e68de775
TL
1697 token = peek_token (&val, cfile);
1698 if (token == SEMI) {
1699 next_token (&val, cfile);
20916cae
TL
1700 if (cp)
1701 status = class_reference (cp, class, MDL);
1702 class_dereference (&class, MDL);
1703 return cp ? (status == ISC_R_SUCCESS) : 1;
e68de775
TL
1704 }
1705 /* Give the subclass its own group. */
f84d544b
TL
1706 if (!clone_group (&class -> group, class -> group, MDL))
1707 log_fatal ("can't clone class group.");
1708
88dcab62
TL
1709 }
1710
20916cae
TL
1711 if (!parse_lbrace (cfile)) {
1712 class_dereference (&class, MDL);
1713 if (pc)
1714 class_dereference (&pc, MDL);
1715 return 0;
1716 }
24a75c03
TL
1717
1718 do {
1719 token = peek_token (&val, cfile);
7dfc8ac2 1720 if (token == RBRACE) {
24a75c03
TL
1721 token = next_token (&val, cfile);
1722 break;
5376e3e9
TL
1723 } else if (token == EOF) {
1724 token = next_token (&val, cfile);
35454d8a 1725 parse_warn (cfile, "unexpected end of file");
5376e3e9 1726 break;
ece6ea33
TL
1727 } else if (token == MATCH) {
1728 if (pc) {
35454d8a
TL
1729 parse_warn (cfile,
1730 "invalid match in subclass.");
ece6ea33
TL
1731 skip_to_semi (cfile);
1732 break;
1733 }
1734 if (class -> expr) {
35454d8a 1735 parse_warn (cfile, "can't override match.");
ece6ea33
TL
1736 skip_to_semi (cfile);
1737 break;
1738 }
1739 token = next_token (&val, cfile);
e68de775 1740 token = peek_token (&val, cfile);
8b500185
TL
1741 if (token != IF)
1742 goto submatch;
e68de775 1743 token = next_token (&val, cfile);
6f8fb41f
TL
1744 parse_boolean_expression (&class -> expr, cfile,
1745 &lose);
ece6ea33
TL
1746 if (lose)
1747 break;
6f8fb41f
TL
1748#if defined (DEBUG_EXPRESSION_PARSE)
1749 print_expression ("class match", class -> expr);
1750#endif
de94ca72 1751 parse_semi (cfile);
ece6ea33
TL
1752 } else if (token == SPAWN) {
1753 if (pc) {
35454d8a
TL
1754 parse_warn (cfile,
1755 "invalid spawn in subclass.");
ece6ea33
TL
1756 skip_to_semi (cfile);
1757 break;
1758 }
ece6ea33
TL
1759 token = next_token (&val, cfile);
1760 token = next_token (&val, cfile);
1761 if (token != WITH) {
35454d8a
TL
1762 parse_warn (cfile,
1763 "expecting with after spawn");
ece6ea33
TL
1764 skip_to_semi (cfile);
1765 break;
1766 }
8b500185
TL
1767 class -> spawning = 1;
1768 submatch:
1769 if (class -> submatch) {
35454d8a
TL
1770 parse_warn (cfile,
1771 "can't override existing %s.",
8b500185
TL
1772 "submatch/spawn");
1773 skip_to_semi (cfile);
1774 break;
1775 }
1776 parse_data_expression (&class -> submatch,
1777 cfile, &lose);
ece6ea33
TL
1778 if (lose)
1779 break;
6f8fb41f 1780#if defined (DEBUG_EXPRESSION_PARSE)
8b500185
TL
1781 print_expression ("class submatch",
1782 class -> submatch);
6f8fb41f 1783#endif
de94ca72 1784 parse_semi (cfile);
88dcab62
TL
1785 } else if (token == LEASE) {
1786 next_token (&val, cfile);
1787 token = next_token (&val, cfile);
1788 if (token != LIMIT) {
35454d8a 1789 parse_warn (cfile, "expecting \"limit\"");
88dcab62
TL
1790 if (token != SEMI)
1791 skip_to_semi (cfile);
1792 break;
1793 }
1794 token = next_token (&val, cfile);
1795 if (token != NUMBER) {
35454d8a 1796 parse_warn (cfile, "expecting a number");
88dcab62
TL
1797 if (token != SEMI)
1798 skip_to_semi (cfile);
1799 break;
1800 }
1801 class -> lease_limit = atoi (val);
1802 class -> billed_leases =
1803 dmalloc (class -> lease_limit *
436f1c8c 1804 sizeof (struct lease *), MDL);
88dcab62 1805 if (!class -> billed_leases)
8ae2d595 1806 log_fatal ("no memory for billed leases.");
88dcab62
TL
1807 memset (class -> billed_leases, 0,
1808 (class -> lease_limit *
1809 sizeof class -> billed_leases));
1810 have_billing_classes = 1;
1811 parse_semi (cfile);
24a75c03 1812 } else {
2d59f590
TL
1813 declaration = parse_statement (cfile, class -> group,
1814 CLASS_DECL,
1815 (struct host_decl *)0,
1816 declaration);
24a75c03
TL
1817 }
1818 } while (1);
de94ca72
TL
1819 if (type == 2 && new) {
1820 if (!collections -> classes)
20916cae 1821 class_reference (&collections -> classes, class, MDL);
de94ca72 1822 else {
20916cae
TL
1823 struct class *c;
1824 for (c = collections -> classes;
1825 c -> nic; c = c -> nic)
de94ca72 1826 ;
20916cae 1827 class_reference (&c -> nic, class, MDL);
de94ca72
TL
1828 }
1829 }
20916cae
TL
1830 if (cp)
1831 status = class_reference (cp, class, MDL);
1832 class_dereference (&class, MDL);
1833 if (pc)
1834 class_dereference (&pc, MDL);
1835 return cp ? (status == ISC_R_SUCCESS) : 1;
24a75c03
TL
1836}
1837
2d59f590
TL
1838/* shared-network-declaration :==
1839 hostname LBRACE declarations parameters RBRACE */
1f814ff2 1840
2d59f590 1841void parse_shared_net_declaration (cfile, group)
35454d8a 1842 struct parse *cfile;
7dfc8ac2 1843 struct group *group;
1f814ff2 1844{
b1b7b521 1845 const char *val;
6f8fb41f 1846 enum dhcp_token token;
1f814ff2 1847 struct shared_network *share;
1f814ff2 1848 char *name;
2d59f590 1849 int declaration = 0;
20916cae 1850 isc_result_t status;
1f814ff2 1851
20916cae
TL
1852 share = (struct shared_network *)0;
1853 status = shared_network_allocate (&share, MDL);
1854 if (status != ISC_R_SUCCESS)
1855 log_fatal ("Can't allocate shared subnet: %s",
1856 isc_result_totext (status));
1857 clone_group (&share -> group, group, MDL);
1858 shared_network_reference (&share -> group -> shared_network,
1859 share, MDL);
1f814ff2
TL
1860
1861 /* Get the name of the shared network... */
7dfc8ac2
TL
1862 token = peek_token (&val, cfile);
1863 if (token == STRING) {
1864 token = next_token (&val, cfile);
1865
1866 if (val [0] == 0) {
35454d8a 1867 parse_warn (cfile, "zero-length shared network name");
7dfc8ac2
TL
1868 val = "<no-name-given>";
1869 }
436f1c8c 1870 name = dmalloc (strlen (val) + 1, MDL);
7dfc8ac2 1871 if (!name)
8ae2d595 1872 log_fatal ("no memory for shared network name");
7dfc8ac2
TL
1873 strcpy (name, val);
1874 } else {
1875 name = parse_host_name (cfile);
20916cae
TL
1876 if (!name) {
1877 shared_network_dereference (&share, MDL);
7dfc8ac2 1878 return;
20916cae 1879 }
1f814ff2 1880 }
1f814ff2
TL
1881 share -> name = name;
1882
20916cae
TL
1883 if (!parse_lbrace (cfile)) {
1884 shared_network_dereference (&share, MDL);
7dfc8ac2 1885 return;
20916cae 1886 }
7dfc8ac2 1887
1f814ff2 1888 do {
7dfc8ac2
TL
1889 token = peek_token (&val, cfile);
1890 if (token == RBRACE) {
1891 token = next_token (&val, cfile);
20916cae 1892 if (!share -> subnets)
4bd8800e
TL
1893 parse_warn (cfile,
1894 "empty shared-network decl");
20916cae
TL
1895 else
1896 enter_shared_network (share);
1897 shared_network_dereference (&share, MDL);
1f814ff2 1898 return;
5376e3e9
TL
1899 } else if (token == EOF) {
1900 token = next_token (&val, cfile);
35454d8a 1901 parse_warn (cfile, "unexpected end of file");
5376e3e9 1902 break;
79931db3
TL
1903 } else if (token == INTERFACE) {
1904 token = next_token (&val, cfile);
1905 token = next_token (&val, cfile);
1906 new_shared_network_interface (cfile, share, val);
1907 if (!parse_semi (cfile))
1908 break;
1909 continue;
1f814ff2 1910 }
5376e3e9 1911
2d59f590
TL
1912 declaration = parse_statement (cfile, share -> group,
1913 SHARED_NET_DECL,
1914 (struct host_decl *)0,
1915 declaration);
1f814ff2 1916 } while (1);
20916cae 1917 shared_network_dereference (&share, MDL);
1f814ff2
TL
1918}
1919
2d59f590
TL
1920/* subnet-declaration :==
1921 net NETMASK netmask RBRACE parameters declarations LBRACE */
685963dc 1922
2d59f590 1923void parse_subnet_declaration (cfile, share)
35454d8a 1924 struct parse *cfile;
1f814ff2 1925 struct shared_network *share;
685963dc 1926{
b1b7b521 1927 const char *val;
6f8fb41f 1928 enum dhcp_token token;
763adef1 1929 struct subnet *subnet, *t, *u;
7dfc8ac2 1930 struct iaddr iaddr;
685963dc 1931 unsigned char addr [4];
b1b7b521 1932 unsigned len = sizeof addr;
2d59f590 1933 int declaration = 0;
79931db3 1934 struct interface_info *ip;
20916cae 1935 isc_result_t status;
685963dc 1936
20916cae
TL
1937 subnet = (struct subnet *)0;
1938 status = subnet_allocate (&subnet, MDL);
1939 if (status != ISC_R_SUCCESS)
1940 log_fatal ("Allocation of new subnet failed: %s",
1941 isc_result_totext (status));
1942 shared_network_reference (&subnet -> shared_network, share, MDL);
1943 if (!clone_group (&subnet -> group, share -> group, MDL))
1944 log_fatal ("allocation of group for new subnet failed.");
1945 subnet_reference (&subnet -> group -> subnet, subnet, MDL);
685963dc
TL
1946
1947 /* Get the network number... */
20916cae
TL
1948 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) {
1949 subnet_dereference (&subnet, MDL);
7dfc8ac2 1950 return;
20916cae 1951 }
7dfc8ac2
TL
1952 memcpy (iaddr.iabuf, addr, len);
1953 iaddr.len = len;
1954 subnet -> net = iaddr;
685963dc
TL
1955
1956 token = next_token (&val, cfile);
1957 if (token != NETMASK) {
35454d8a 1958 parse_warn (cfile, "Expecting netmask");
685963dc 1959 skip_to_semi (cfile);
7dfc8ac2 1960 return;
685963dc
TL
1961 }
1962
1963 /* Get the netmask... */
20916cae
TL
1964 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) {
1965 subnet_dereference (&subnet, MDL);
7dfc8ac2 1966 return;
20916cae 1967 }
7dfc8ac2
TL
1968 memcpy (iaddr.iabuf, addr, len);
1969 iaddr.len = len;
1970 subnet -> netmask = iaddr;
685963dc 1971
20916cae
TL
1972 /* Validate the network number/netmask pair. */
1973 if (host_addr (subnet -> net, subnet -> netmask)) {
1974 parse_warn (cfile,
1975 "subnet %s: bad subnet number/mask combination.",
1976 piaddr (subnet -> net));
1977 subnet_dereference (&subnet, MDL);
1978 skip_to_semi (cfile);
1979 return;
1980 }
1981
685963dc
TL
1982 enter_subnet (subnet);
1983
20916cae
TL
1984 if (!parse_lbrace (cfile)) {
1985 subnet_dereference (&subnet, MDL);
7dfc8ac2 1986 return;
20916cae 1987 }
7dfc8ac2 1988
685963dc
TL
1989 do {
1990 token = peek_token (&val, cfile);
7dfc8ac2
TL
1991 if (token == RBRACE) {
1992 token = next_token (&val, cfile);
685963dc 1993 break;
5376e3e9
TL
1994 } else if (token == EOF) {
1995 token = next_token (&val, cfile);
35454d8a 1996 parse_warn (cfile, "unexpected end of file");
5376e3e9 1997 break;
79931db3
TL
1998 } else if (token == INTERFACE) {
1999 token = next_token (&val, cfile);
2000 token = next_token (&val, cfile);
2001 new_shared_network_interface (cfile, share, val);
2002 if (!parse_semi (cfile))
2003 break;
2004 continue;
7dfc8ac2 2005 }
2d59f590
TL
2006 declaration = parse_statement (cfile, subnet -> group,
2007 SUBNET_DECL,
2008 (struct host_decl *)0,
2009 declaration);
685963dc 2010 } while (1);
1f814ff2 2011
6cdd0d0d 2012 /* Add the subnet to the list of subnets in this shared net. */
7dfc8ac2 2013 if (!share -> subnets)
20916cae 2014 subnet_reference (&share -> subnets, subnet, MDL);
7dfc8ac2 2015 else {
763adef1 2016 u = (struct subnet *)0;
7dfc8ac2 2017 for (t = share -> subnets;
763adef1
TL
2018 t -> next_sibling; t = t -> next_sibling) {
2019 if (subnet_inner_than (subnet, t, 0)) {
20916cae
TL
2020 subnet_reference (&subnet -> next_sibling,
2021 t, MDL);
2022 if (u) {
2023 subnet_dereference (&u -> next_sibling,
2024 MDL);
2025 subnet_reference (&u -> next_sibling,
2026 subnet, MDL);
2027 } else {
2028 subnet_dereference (&share -> subnets,
2029 MDL);
2030 subnet_reference (&share -> subnets,
2031 subnet, MDL);
2032 }
2033 subnet_dereference (&subnet, MDL);
763adef1
TL
2034 return;
2035 }
2036 u = t;
2037 }
20916cae 2038 subnet_reference (&t -> next_sibling, subnet, MDL);
7dfc8ac2 2039 }
20916cae 2040 subnet_dereference (&subnet, MDL);
685963dc
TL
2041}
2042
2d59f590 2043/* group-declaration :== RBRACE parameters declarations LBRACE */
7dfc8ac2 2044
2d59f590 2045void parse_group_declaration (cfile, group)
35454d8a 2046 struct parse *cfile;
7dfc8ac2 2047 struct group *group;
685963dc 2048{
b1b7b521 2049 const char *val;
6f8fb41f 2050 enum dhcp_token token;
7dfc8ac2 2051 struct group *g;
2d59f590 2052 int declaration = 0;
29c35bed
TL
2053 struct group_object *t;
2054 isc_result_t status;
d9eefc5d 2055 char *name = NULL;
29c35bed
TL
2056 int deletedp = 0;
2057 int dynamicp = 0;
2058 int staticp = 0;
685963dc 2059
20916cae
TL
2060 g = (struct group *)0;
2061 if (!clone_group (&g, group, MDL))
2062 log_fatal ("no memory for explicit group.");
685963dc 2063
29c35bed
TL
2064 token = peek_token (&val, cfile);
2065 if (is_identifier (token) || token == STRING) {
2066 next_token (&val, cfile);
2067
436f1c8c 2068 name = dmalloc (strlen (val) + 1, MDL);
29c35bed
TL
2069 if (!name)
2070 log_fatal ("no memory for group decl name %s", val);
2071 strcpy (name, val);
2072 }
2073
20916cae
TL
2074 if (!parse_lbrace (cfile)) {
2075 group_dereference (&g, MDL);
7dfc8ac2 2076 return;
20916cae 2077 }
d7837182 2078
7dfc8ac2
TL
2079 do {
2080 token = peek_token (&val, cfile);
5376e3e9
TL
2081 if (token == RBRACE) {
2082 token = next_token (&val, cfile);
7dfc8ac2 2083 break;
5376e3e9
TL
2084 } else if (token == EOF) {
2085 token = next_token (&val, cfile);
35454d8a 2086 parse_warn (cfile, "unexpected end of file");
5376e3e9 2087 break;
007e3ee4 2088 } else if (token == TOKEN_DELETED) {
29c35bed
TL
2089 token = next_token (&val, cfile);
2090 parse_semi (cfile);
2091 deletedp = 1;
2092 } else if (token == DYNAMIC) {
2093 token = next_token (&val, cfile);
2094 parse_semi (cfile);
2095 dynamicp = 1;
2096 } else if (token == STATIC) {
2097 token = next_token (&val, cfile);
2098 parse_semi (cfile);
2099 staticp = 1;
5376e3e9 2100 }
2d59f590
TL
2101 declaration = parse_statement (cfile, g, GROUP_DECL,
2102 (struct host_decl *)0,
2103 declaration);
7dfc8ac2 2104 } while (1);
29c35bed
TL
2105
2106 if (name) {
2107 if (deletedp) {
2108 if (group_name_hash) {
20916cae
TL
2109 t = (struct group_object *)0;
2110 if (group_hash_lookup (&t, group_name_hash,
2111 name,
2112 strlen (name), MDL)) {
29c35bed
TL
2113 delete_group (t, 0);
2114 }
2115 }
2116 } else {
20916cae
TL
2117 t = (struct group_object *)0;
2118 status = group_object_allocate (&t, MDL);
2119 if (status != ISC_R_SUCCESS)
2120 log_fatal ("no memory for group decl %s: %s",
2121 val, isc_result_totext (status));
2122 group_reference (&t -> group, g, MDL);
29c35bed
TL
2123 t -> name = name;
2124 t -> flags = ((staticp ? GROUP_OBJECT_STATIC : 0) |
2125 (dynamicp ? GROUP_OBJECT_DYNAMIC : 0) |
2126 (deletedp ? GROUP_OBJECT_DELETED : 0));
2127 supersede_group (t, 0);
2128 }
20916cae
TL
2129 if (t)
2130 group_object_dereference (&t, MDL);
29c35bed 2131 }
d7837182
TL
2132}
2133
2d59f590
TL
2134/* fixed-addr-parameter :== ip-addrs-or-hostnames SEMI
2135 ip-addrs-or-hostnames :== ip-addr-or-hostname
2136 | ip-addrs-or-hostnames ip-addr-or-hostname */
d7837182 2137
6f8fb41f
TL
2138int parse_fixed_addr_param (oc, cfile)
2139 struct option_cache **oc;
35454d8a 2140 struct parse *cfile;
d7837182 2141{
b1b7b521 2142 const char *val;
6f8fb41f 2143 enum dhcp_token token;
ece6ea33 2144 struct expression *expr = (struct expression *)0;
6f8fb41f
TL
2145 struct expression *tmp, *new;
2146 int status;
1f814ff2
TL
2147
2148 do {
6f8fb41f
TL
2149 tmp = (struct expression *)0;
2150 if (parse_ip_addr_or_hostname (&tmp, cfile, 1)) {
028a8588
TL
2151 if (expr) {
2152 new = (struct expression *)0;
2153 status = make_concat (&new, expr, tmp);
436f1c8c
TL
2154 expression_dereference (&expr, MDL);
2155 expression_dereference (&tmp, MDL);
1dd632af 2156 if (!status)
028a8588
TL
2157 return 0;
2158 expr = new;
2159 } else
2160 expr = tmp;
6f8fb41f
TL
2161 } else {
2162 if (expr)
436f1c8c 2163 expression_dereference (&expr, MDL);
6f8fb41f
TL
2164 return 0;
2165 }
1f814ff2 2166 token = peek_token (&val, cfile);
5376e3e9 2167 if (token == COMMA)
1f814ff2
TL
2168 token = next_token (&val, cfile);
2169 } while (token == COMMA);
7dfc8ac2 2170
6f8fb41f
TL
2171 if (!parse_semi (cfile)) {
2172 if (expr)
436f1c8c 2173 expression_dereference (&expr, MDL);
6f8fb41f
TL
2174 return 0;
2175 }
2176 status = option_cache (oc, (struct data_string *)0, expr,
2177 (struct option *)0);
436f1c8c 2178 expression_dereference (&expr, MDL);
6f8fb41f 2179 return status;
d7837182
TL
2180}
2181
5376e3e9 2182/* timestamp :== date
d7837182
TL
2183
2184 Timestamps are actually not used in dhcpd.conf, which is a static file,
5376e3e9
TL
2185 but rather in the database file and the journal file. (Okay, actually
2186 they're not even used there yet). */
d7837182 2187
7dfc8ac2 2188TIME parse_timestamp (cfile)
35454d8a 2189 struct parse *cfile;
d7837182 2190{
089fb364 2191 TIME rv;
089fb364 2192
7dfc8ac2 2193 rv = parse_date (cfile);
089fb364 2194 return rv;
d7837182
TL
2195}
2196
2d59f590
TL
2197/* lease_declaration :== LEASE ip_address LBRACE lease_parameters RBRACE
2198
2199 lease_parameters :== <nil>
2200 | lease_parameter
2201 | lease_parameters lease_parameter
2202
2203 lease_parameter :== STARTS date
2204 | ENDS date
2205 | TIMESTAMP date
2206 | HARDWARE hardware-parameter
2207 | UID hex_numbers SEMI
ccf5778a
TL
2208 | HOSTNAME hostname SEMI
2209 | CLIENT_HOSTNAME hostname SEMI
2d59f590
TL
2210 | CLASS identifier SEMI
2211 | DYNAMIC_BOOTP SEMI */
2212
20916cae 2213int parse_lease_declaration (struct lease **lp, struct parse *cfile)
d7837182 2214{
b1b7b521 2215 const char *val;
6f8fb41f 2216 enum dhcp_token token;
d7837182 2217 unsigned char addr [4];
b1b7b521 2218 unsigned len = sizeof addr;
d7837182
TL
2219 int seenmask = 0;
2220 int seenbit;
2221 char tbuf [32];
20916cae 2222 struct lease *lease;
96d7d13e 2223 struct executable_statement *on;
436f1c8c
TL
2224 struct expression *exp;
2225 struct data_string ds;
96d7d13e 2226 int lose;
9e9b2261 2227 TIME t;
436f1c8c
TL
2228 char *s;
2229 int noequal, newbinding;
2230 struct binding *binding;
20916cae 2231 isc_result_t status;
007e3ee4 2232 binding_state_t *statep;
d7837182 2233
20916cae
TL
2234 lease = (struct lease *)0;
2235 status = lease_allocate (&lease, MDL);
2236 if (status != ISC_R_SUCCESS)
2237 return 0;
9375101b 2238
d7837182 2239 /* Get the address for which the lease has been issued. */
20916cae
TL
2240 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) {
2241 lease_dereference (&lease, MDL);
2242 return 0;
2243 }
2244 memcpy (lease -> ip_addr.iabuf, addr, len);
2245 lease -> ip_addr.len = len;
d7837182 2246
20916cae
TL
2247 if (!parse_lbrace (cfile)) {
2248 lease_dereference (&lease, MDL);
2249 return 0;
2250 }
7dfc8ac2 2251
d7837182
TL
2252 do {
2253 token = next_token (&val, cfile);
7dfc8ac2 2254 if (token == RBRACE)
d7837182 2255 break;
5376e3e9 2256 else if (token == EOF) {
35454d8a 2257 parse_warn (cfile, "unexpected end of file");
5376e3e9
TL
2258 break;
2259 }
ece6ea33 2260 strncpy (tbuf, val, sizeof tbuf);
d7837182
TL
2261 tbuf [(sizeof tbuf) - 1] = 0;
2262
2263 /* Parse any of the times associated with the lease. */
9e9b2261
TL
2264 switch (token) {
2265 case STARTS:
2266 case ENDS:
2267 case TIMESTAMP:
2268 case TSTP:
2269 case TSFP:
8c8e27c5 2270 case CLTT:
7dfc8ac2 2271 t = parse_date (cfile);
d7837182
TL
2272 switch (token) {
2273 case STARTS:
2274 seenbit = 1;
20916cae 2275 lease -> starts = t;
d7837182
TL
2276 break;
2277
2278 case ENDS:
2279 seenbit = 2;
20916cae 2280 lease -> ends = t;
d7837182
TL
2281 break;
2282
2283 case TIMESTAMP:
2284 seenbit = 4;
20916cae 2285 lease -> timestamp = t;
d7837182 2286 break;
19d868b2 2287
9e9b2261
TL
2288 case TSTP:
2289 seenbit = 65536;
20916cae 2290 lease -> tstp = t;
19d868b2 2291 break;
9e9b2261
TL
2292
2293 case TSFP:
2294 seenbit = 131072;
20916cae 2295 lease -> tsfp = t;
d7837182 2296 break;
9e9b2261 2297
8c8e27c5
TL
2298 case CLTT:
2299 seenbit = 524288;
20916cae 2300 lease -> cltt = t;
8c8e27c5
TL
2301 break;
2302
9e9b2261 2303 default: /* for gcc, we'll never get here. */
9d80b480 2304 break;
9e9b2261
TL
2305 }
2306 break;
d7837182 2307
9e9b2261
TL
2308 /* Colon-seperated hexadecimal octets... */
2309 case UID:
2310 seenbit = 8;
2311 token = peek_token (&val, cfile);
2312 if (token == STRING) {
2313 unsigned char *tuid;
d7837182 2314 token = next_token (&val, cfile);
20916cae 2315 lease -> uid_len = strlen (val);
436f1c8c 2316 tuid = ((unsigned char *)
20916cae 2317 dmalloc (lease -> uid_len, MDL));
9e9b2261
TL
2318 if (!tuid) {
2319 log_error ("no space for uid");
20916cae
TL
2320 lease_dereference (&lease, MDL);
2321 return 0;
d7837182 2322 }
20916cae
TL
2323 memcpy (tuid, val, lease -> uid_len);
2324 lease -> uid = tuid;
9e9b2261 2325 } else {
20916cae
TL
2326 lease -> uid_len = 0;
2327 lease -> uid = (parse_numeric_aggregate
2328 (cfile, (unsigned char *)0,
2329 &lease -> uid_len, ':',
2330 16, 8));
2331 if (!lease -> uid) {
2332 lease_dereference (&lease, MDL);
2333 return 0;
2334 }
2335 if (lease -> uid_len == 0) {
2336 lease -> uid = (unsigned char *)0;
9e9b2261
TL
2337 parse_warn (cfile, "zero-length uid");
2338 seenbit = 0;
d0463358 2339 parse_semi (cfile);
9e9b2261
TL
2340 break;
2341 }
2342 }
d0463358 2343 parse_semi (cfile);
20916cae 2344 if (!lease -> uid) {
9e9b2261
TL
2345 log_fatal ("No memory for lease uid");
2346 }
2347 break;
2348
2349 case CLASS:
2350 seenbit = 32;
2351 token = next_token (&val, cfile);
2352 if (!is_identifier (token)) {
2353 if (token != SEMI)
2354 skip_to_rbrace (cfile, 1);
20916cae
TL
2355 lease_dereference (&lease, MDL);
2356 return 0;
9e9b2261 2357 }
d0463358 2358 parse_semi (cfile);
9e9b2261
TL
2359 /* for now, we aren't using this. */
2360 break;
ccf5778a 2361
9e9b2261
TL
2362 case HARDWARE:
2363 seenbit = 64;
2364 parse_hardware_param (cfile,
20916cae 2365 &lease -> hardware_addr);
9e9b2261
TL
2366 break;
2367
2368 case DYNAMIC_BOOTP:
007e3ee4
TL
2369 seenbit = 256;
2370 lease -> binding_state = FTS_BOOTP;
2371 lease -> next_binding_state = FTS_BOOTP;
d0463358 2372 parse_semi (cfile);
9e9b2261
TL
2373 break;
2374
007e3ee4
TL
2375 case TOKEN_ABANDONED:
2376 seenbit = 256;
2377 lease -> binding_state = FTS_ABANDONED;
2378 lease -> next_binding_state = FTS_ABANDONED;
d0463358 2379 parse_semi (cfile);
9e9b2261
TL
2380 break;
2381
007e3ee4
TL
2382 case TOKEN_NEXT:
2383 seenbit = 128;
2384 statep = &lease -> next_binding_state;
301a5b66
TL
2385 token = next_token (&val, cfile);
2386 if (token != BINDING) {
2387 parse_warn (cfile, "expecting 'binding'");
2388 skip_to_semi (cfile);
2389 break;
2390 }
007e3ee4
TL
2391 goto do_binding_state;
2392
2393 case BINDING:
9e9b2261 2394 seenbit = 256;
007e3ee4
TL
2395 statep = &lease -> binding_state;
2396
2397 do_binding_state:
2398 token = next_token (&val, cfile);
2399 if (token != STATE) {
2400 parse_warn (cfile, "expecting 'state'");
2401 skip_to_semi (cfile);
2402 break;
2403 }
2404 token = next_token (&val, cfile);
2405 switch (token) {
2406 case TOKEN_ABANDONED:
2407 *statep = FTS_ABANDONED;
2408 break;
2409 case TOKEN_FREE:
2410 *statep = FTS_FREE;
2411 break;
2412 case TOKEN_ACTIVE:
2413 *statep = FTS_ACTIVE;
2414 break;
2415 case TOKEN_EXPIRED:
2416 *statep = FTS_EXPIRED;
2417 break;
2418 case TOKEN_RELEASED:
2419 *statep = FTS_RELEASED;
2420 break;
2421 case TOKEN_RESET:
2422 *statep = FTS_RESET;
2423 break;
2424 case TOKEN_BACKUP:
2425 *statep = FTS_BACKUP;
2426 break;
2427 case TOKEN_RESERVED:
2428 *statep = FTS_RESERVED;
2429 break;
2430 case TOKEN_BOOTP:
2431 *statep = FTS_BOOTP;
2432 break;
2433 default:
2434 parse_warn (cfile,
2435 "%s: expecting a binding state.",
2436 val);
2437 skip_to_semi (cfile);
2438 break;
2439 }
2440 /* If no next binding state is specified, it's
2441 the same as the current state. */
2442 if (!(seenmask & 128) && seenbit == 256)
2443 lease -> next_binding_state =
2444 lease -> binding_state;
d0463358 2445 parse_semi (cfile);
9e9b2261 2446 break;
ccf5778a 2447
9e9b2261
TL
2448 case HOSTNAME:
2449 seenbit = 512;
2450 token = peek_token (&val, cfile);
2451 if (token == STRING)
20916cae 2452 lease -> hostname = parse_string (cfile);
d0463358 2453 else {
20916cae
TL
2454 lease -> hostname = parse_host_name (cfile);
2455 if (lease -> hostname)
d0463358
TL
2456 parse_semi (cfile);
2457 }
20916cae 2458 if (!lease -> hostname) {
9e9b2261 2459 seenbit = 0;
20916cae 2460 return 0;
9e9b2261
TL
2461 }
2462 break;
2463
2464 case CLIENT_HOSTNAME:
2465 seenbit = 1024;
2466 token = peek_token (&val, cfile);
2467 if (token == STRING)
20916cae
TL
2468 lease -> client_hostname =
2469 parse_string (cfile);
d0463358 2470 else {
20916cae 2471 lease -> client_hostname =
9e9b2261 2472 parse_host_name (cfile);
20916cae 2473 if (lease -> client_hostname)
d0463358
TL
2474 parse_semi (cfile);
2475 }
20916cae 2476 if (!lease -> client_hostname) {
d0463358 2477 seenbit = 0;
20916cae
TL
2478 lease_dereference (&lease, MDL);
2479 return 0;
d0463358 2480 }
9e9b2261
TL
2481 break;
2482
2483 case BILLING:
2484 seenbit = 2048;
2485 token = next_token (&val, cfile);
2486 if (token == CLASS) {
88dcab62 2487 token = next_token (&val, cfile);
9e9b2261
TL
2488 if (token != STRING) {
2489 parse_warn (cfile, "expecting string");
88dcab62
TL
2490 if (token != SEMI)
2491 skip_to_semi (cfile);
9e9b2261
TL
2492 token = BILLING;
2493 break;
88dcab62 2494 }
20916cae
TL
2495 find_class (&lease -> billing_class, val, MDL);
2496 if (!lease -> billing_class)
9e9b2261
TL
2497 parse_warn (cfile,
2498 "unknown class %s", val);
2499 parse_semi (cfile);
2500 } else if (token == SUBCLASS) {
20916cae
TL
2501 if (lease -> billing_class)
2502 class_dereference
2503 (&lease -> billing_class, MDL);
2504 parse_class_declaration
2505 (&lease -> billing_class,
2506 cfile, (struct group *)0, 3);
9e9b2261
TL
2507 } else {
2508 parse_warn (cfile, "expecting \"class\"");
2509 if (token != SEMI)
2510 skip_to_semi (cfile);
2511 }
9e9b2261 2512 break;
96d7d13e 2513
9e9b2261
TL
2514 case ON:
2515 on = (struct executable_statement *)0;
2516 lose = 0;
2517 if (!parse_on_statement (&on, cfile, &lose)) {
2518 skip_to_rbrace (cfile, 1);
20916cae
TL
2519 lease_dereference (&lease, MDL);
2520 return 0;
7dfc8ac2 2521 }
436f1c8c 2522 seenbit = 0;
d0463358 2523 if ((on -> data.on.evtypes & ON_EXPIRY) &&
9e9b2261 2524 on -> data.on.statements) {
436f1c8c 2525 seenbit |= 16384;
9e9b2261 2526 executable_statement_reference
20916cae 2527 (&lease -> on_expiry,
436f1c8c 2528 on -> data.on.statements, MDL);
d0463358
TL
2529 }
2530 if ((on -> data.on.evtypes & ON_RELEASE) &&
2531 on -> data.on.statements) {
436f1c8c 2532 seenbit |= 32768;
9e9b2261 2533 executable_statement_reference
20916cae 2534 (&lease -> on_release,
436f1c8c 2535 on -> data.on.statements, MDL);
9e9b2261 2536 }
436f1c8c 2537 executable_statement_dereference (&on, MDL);
9e9b2261
TL
2538 break;
2539
436f1c8c
TL
2540 case TOKEN_SET:
2541 noequal = 0;
2542
2543 token = next_token (&val, cfile);
2544 if (token != NAME && token != NUMBER_OR_NAME) {
2545 parse_warn (cfile,
2546 "%s can't be a variable name",
2547 val);
2548 badset:
2549 skip_to_semi (cfile);
20916cae
TL
2550 lease_dereference (&lease, MDL);
2551 return 0;
436f1c8c
TL
2552 }
2553
2554 seenbit = 0;
2555 special_set:
6ceb9118
TL
2556 if (lease -> scope)
2557 binding = find_binding (lease -> scope, val);
2558 else
2559 binding = (struct binding *)0;
436f1c8c 2560 if (!binding) {
6ceb9118
TL
2561 if (!lease -> scope)
2562 if (!(binding_scope_allocate
2563 (&lease -> scope, MDL)))
2564 log_fatal ("no memory for scope");
436f1c8c
TL
2565 binding = dmalloc (sizeof *binding, MDL);
2566 if (!binding)
2567 log_fatal ("No memory for lease %s.",
2568 "binding");
2569 memset (binding, 0, sizeof *binding);
2570 binding -> name =
2571 dmalloc (strlen (val) + 1, MDL);
2572 if (!binding -> name)
2573 log_fatal ("No memory for binding %s.",
2574 "name");
2575 strcpy (binding -> name, val);
2576 newbinding = 1;
11cd757b
TL
2577 } else if (binding -> value) {
2578 binding_value_dereference (&binding -> value,
2579 MDL);
436f1c8c
TL
2580 newbinding = 0;
2581 }
11cd757b
TL
2582 if (!binding_value_allocate (&binding -> value, MDL))
2583 log_fatal ("no memory for binding value.");
436f1c8c
TL
2584
2585 if (!noequal) {
2586 token = next_token (&val, cfile);
2587 if (token != EQUAL) {
2588 parse_warn (cfile,
2589 "expecting '=' in set statement.");
2590 goto badset;
2591 }
2592 }
2593
2594 token = peek_token (&val, cfile);
2595 if (token == STRING) {
11cd757b
TL
2596 unsigned char *tuid;
2597 token = next_token (&val, cfile);
2598 binding -> value -> type = binding_data;
2599 binding -> value -> value.data.len = strlen (val);
2600 if (!(buffer_allocate
2601 (&binding -> value -> value.data.buffer,
2602 binding -> value-> value.data.len + 1,
2603 MDL)))
2604 log_fatal ("No memory for binding.");
2605 strcpy ((char *)
2606 (binding -> value ->
2607 value.data.buffer -> data), val);
2608 binding -> value -> value.data.data =
2609 binding -> value -> value.data.buffer -> data;
2610 binding -> value -> value.data.terminated = 1;
2611 } else if (token == NUMBER_OR_NAME) {
2612 binding -> value -> type = binding_data;
2613 s = ((char *)
2614 (parse_numeric_aggregate
2615 (cfile, (unsigned char *)0,
2616 &binding -> value -> value.data.len,
2617 ':', 16, 8)));
2618 if (!s) {
2619 binding_value_dereference
2620 (&binding -> value, MDL);
20916cae
TL
2621 lease_dereference (&lease, MDL);
2622 return 0;
11cd757b
TL
2623 }
2624 if (binding -> value -> value.data.len) {
436f1c8c 2625 if (!(buffer_allocate
11cd757b
TL
2626 (&binding -> value -> value.data.buffer,
2627 binding -> value -> value.data.len + 1,
2628 MDL)))
436f1c8c 2629 log_fatal ("No memory for binding.");
11cd757b
TL
2630 memcpy ((binding -> value ->
2631 value.data.buffer -> data), s,
2632 binding -> value -> value.data.len);
2633 dfree (s, MDL);
2634 binding -> value -> value.data.data =
2635 binding -> value -> value.data.buffer -> data;
2636 }
2637 } else if (token == PERCENT) {
2638 token = next_token (&val, cfile);
2639 token = next_token (&val, cfile);
2640 if (token != NUMBER) {
2641 parse_warn (cfile,
2642 "expecting decimal number.");
2643 if (token != SEMI)
2644 skip_to_semi (cfile);
2645 binding_value_dereference
2646 (&binding -> value, MDL);
20916cae
TL
2647 lease_dereference (&lease, MDL);
2648 return 0;
11cd757b
TL
2649 }
2650 binding -> value -> type = binding_numeric;
2651 binding -> value -> value.intval = atol (val);
2652 } else if (token == NAME) {
2653 token = next_token (&val, cfile);
2654 binding -> value -> type = binding_boolean;
2655 if (!strcasecmp (val, "true"))
2656 binding -> value -> value.boolean = 1;
2657 else if (!strcasecmp (val, "false"))
2658 binding -> value -> value.boolean = 0;
2659 else
2660 goto badbool;
436f1c8c 2661 } else {
11cd757b
TL
2662 badbool:
2663 parse_warn (cfile,
2664 "expecting a constant value.");
2665 skip_to_semi (cfile);
2666 binding_value_dereference (&binding -> value,
2667 MDL);
20916cae
TL
2668 lease_dereference (&lease, MDL);
2669 return 0;
436f1c8c 2670 }
11cd757b 2671
436f1c8c 2672 if (newbinding) {
6ceb9118
TL
2673 binding -> next = lease -> scope -> bindings;
2674 lease -> scope -> bindings = binding;
436f1c8c
TL
2675 }
2676 parse_semi (cfile);
2677 break;
2678
9e9b2261 2679 default:
436f1c8c
TL
2680 if (!strcasecmp (val, "ddns-fwd-name")) {
2681 seenbit = 4096;
2682 noequal = 1;
2683 goto special_set;
2684 } else if (!strcasecmp (val, "ddns-rev-name")) {
2685 seenbit = 8192;
2686 noequal = 1;
2687 goto special_set;
2688 }
9e9b2261
TL
2689 skip_to_semi (cfile);
2690 seenbit = 0;
20916cae
TL
2691 lease_dereference (&lease, MDL);
2692 return 0;
9e9b2261 2693 }
7dfc8ac2 2694
d7837182 2695 if (seenmask & seenbit) {
35454d8a
TL
2696 parse_warn (cfile,
2697 "Too many %s parameters in lease %s\n",
20916cae 2698 tbuf, piaddr (lease -> ip_addr));
d7837182
TL
2699 } else
2700 seenmask |= seenbit;
7dfc8ac2 2701
d7837182 2702 } while (1);
8afe0787
TL
2703
2704 /* If no binding state is specified, make one up. */
2705 if (!(seenmask & 256)) {
e73a0769
TL
2706 if (lease -> ends > cur_time ||
2707 lease -> on_expiry || lease -> on_release)
8afe0787 2708 lease -> binding_state = FTS_ACTIVE;
301a5b66 2709#if defined (FAILOVER_PROTOCOL)
e73a0769
TL
2710 else if (lease -> pool && lease -> pool -> failover_peer)
2711 lease -> binding_state = FTS_EXPIRED;
301a5b66 2712#endif
8afe0787
TL
2713 else
2714 lease -> binding_state = FTS_FREE;
e73a0769 2715 if (lease -> binding_state == FTS_ACTIVE) {
301a5b66 2716#if defined (FAILOVER_PROTOCOL)
e73a0769
TL
2717 if (lease -> pool && lease -> pool -> failover_peer)
2718 lease -> next_binding_state = FTS_EXPIRED;
2719 else
301a5b66 2720#endif
e73a0769
TL
2721 lease -> next_binding_state = FTS_FREE;
2722 } else
2723 lease -> next_binding_state = lease -> binding_state;
8afe0787
TL
2724 }
2725
20916cae
TL
2726 lease_reference (lp, lease, MDL);
2727 lease_dereference (&lease, MDL);
2728 return 1;
d7837182
TL
2729}
2730
2d59f590
TL
2731/* address-range-declaration :== ip-address ip-address SEMI
2732 | DYNAMIC_BOOTP ip-address ip-address SEMI */
d7837182 2733
20916cae 2734void parse_address_range (cfile, group, type, inpool)
35454d8a 2735 struct parse *cfile;
f63b4929
TL
2736 struct group *group;
2737 int type;
20916cae 2738 struct pool *inpool;
d7837182 2739{
f63b4929 2740 struct iaddr low, high, net;
d7837182 2741 unsigned char addr [4];
b1b7b521 2742 unsigned len = sizeof addr;
6f8fb41f 2743 enum dhcp_token token;
b1b7b521 2744 const char *val;
1f814ff2 2745 int dynamic = 0;
f63b4929
TL
2746 struct subnet *subnet;
2747 struct shared_network *share;
2748 struct pool *p;
20916cae
TL
2749 struct pool *pool;
2750 isc_result_t status;
1f814ff2
TL
2751
2752 if ((token = peek_token (&val, cfile)) == DYNAMIC_BOOTP) {
5376e3e9 2753 token = next_token (&val, cfile);
ece6ea33 2754 dynamic = 1;
1f814ff2 2755 }
d7837182
TL
2756
2757 /* Get the bottom address in the range... */
7dfc8ac2
TL
2758 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
2759 return;
089fb364
TL
2760 memcpy (low.iabuf, addr, len);
2761 low.len = len;
d7837182 2762
2d59f590
TL
2763 /* Only one address? */
2764 token = peek_token (&val, cfile);
2765 if (token == SEMI)
2766 high = low;
2767 else {
d7837182 2768 /* Get the top address in the range... */
2d59f590
TL
2769 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
2770 return;
2771 memcpy (high.iabuf, addr, len);
2772 high.len = len;
2773 }
d7837182 2774
7dfc8ac2
TL
2775 token = next_token (&val, cfile);
2776 if (token != SEMI) {
35454d8a 2777 parse_warn (cfile, "semicolon expected.");
7dfc8ac2
TL
2778 skip_to_semi (cfile);
2779 return;
2780 }
2781
f63b4929
TL
2782 if (type == SUBNET_DECL) {
2783 subnet = group -> subnet;
2784 share = subnet -> shared_network;
2785 } else {
2786 share = group -> shared_network;
2787 for (subnet = share -> subnets;
2788 subnet; subnet = subnet -> next_sibling) {
2789 net = subnet_number (low, subnet -> netmask);
e5e41be4 2790 if (addr_eq (net, subnet -> net))
f63b4929
TL
2791 break;
2792 }
2793 if (!subnet) {
35454d8a 2794 parse_warn (cfile, "address range not on network %s",
f63b4929 2795 group -> shared_network -> name);
e5e41be4
TL
2796 log_error ("Be sure to place pool statement after %s",
2797 "related subnet declarations.");
f63b4929
TL
2798 return;
2799 }
2800 }
2801
20916cae 2802 if (!inpool) {
0a1dfb65 2803 struct pool *last = (struct pool *)0;
9e9b2261 2804
f63b4929
TL
2805 /* If we're permitting dynamic bootp for this range,
2806 then look for a pool with an empty prohibit list and
436f1c8c 2807 a permit list with one entry that permits all clients. */
f63b4929 2808 for (pool = share -> pools; pool; pool = pool -> next) {
436f1c8c
TL
2809 if ((!dynamic && !pool -> permit_list &&
2810 pool -> prohibit_list &&
2811 !pool -> prohibit_list -> next &&
2812 (pool -> prohibit_list -> type ==
2813 permit_dynamic_bootp_clients)) ||
2814 (dynamic && !pool -> prohibit_list &&
f63b4929
TL
2815 pool -> permit_list &&
2816 !pool -> permit_list -> next &&
2817 (pool -> permit_list -> type ==
d9eefc5d 2818 permit_all_clients))) {
436f1c8c 2819 break;
f63b4929
TL
2820 }
2821 last = pool;
2822 }
2823
2824 /* If we didn't get a pool, make one. */
2825 if (!pool) {
436f1c8c 2826 struct permit *p;
20916cae
TL
2827 status = pool_allocate (&pool, MDL);
2828 if (status != ISC_R_SUCCESS)
2829 log_fatal ("no memory for ad-hoc pool: %s",
2830 isc_result_totext (status));
436f1c8c
TL
2831 p = new_permit (MDL);
2832 if (!p)
2833 log_fatal ("no memory for ad-hoc permit.");
2834
2835 /* Dynamic pools permit all clients. Otherwise
2836 we prohibit BOOTP clients. */
f63b4929 2837 if (dynamic) {
436f1c8c
TL
2838 p -> type = permit_all_clients;
2839 pool -> permit_list = p;
2840 } else {
2841 p -> type = permit_dynamic_bootp_clients;
2842 pool -> prohibit_list = p;
f63b4929 2843 }
436f1c8c 2844
f63b4929 2845 if (share -> pools)
20916cae 2846 pool_reference (&last -> next, pool, MDL);
f63b4929 2847 else
20916cae
TL
2848 pool_reference (&share -> pools, pool, MDL);
2849 shared_network_reference (&pool -> shared_network,
2850 share, MDL);
2851 if (!clone_group (&pool -> group, share -> group, MDL))
2852 log_fatal ("no memory for anon pool group.");
a79ed92b
TL
2853 } else {
2854 pool = (struct pool *)0;
0a1dfb65
TL
2855 if (last)
2856 pool_reference (&pool, last, MDL);
2857 else
2858 pool_reference (&pool, share -> pools, MDL);
f63b4929 2859 }
a79ed92b
TL
2860 } else {
2861 pool = (struct pool *)0;
20916cae 2862 pool_reference (&pool, inpool, MDL);
a79ed92b 2863 }
20916cae 2864
c5261618
TL
2865#if defined (FAILOVER_PROTOCOL)
2866 if (pool -> failover_peer && dynamic) {
2867 /* Doctor, do you think I'm overly sensitive
2868 about getting bug reports I can't fix? */
2869 parse_warn (cfile, "dynamic-bootp flag is %s",
2870 "not permitted for address");
2871 log_error ("range declarations where there is a failover");
2872 log_error ("peer in scope. If you wish to declare an");
2873 log_error ("address range from which dynamic bootp leases");
2874 log_error ("can be allocated, please declare it within a");
2875 log_error ("pool declaration that also contains the \"no");
2876 log_error ("failover\" statement. The failover protocol");
2877 log_error ("itself does not permit dynamic bootp - this");
2878 log_error ("is not a limitation specific to the ISC DHCP");
2879 log_error ("server. Please don't ask me to defend this");
2880 log_error ("until you have read and really tried %s",
2881 "to understand");
2882 log_error ("the failover protocol specification.");
2883
2884 /* We don't actually bomb at this point - instead,
2885 we let parse_lease_file notice the error and
2886 bomb at that point - it's easier. */
f63b4929 2887 }
c5261618 2888#endif /* FAILOVER_PROTOCOL */
f63b4929 2889
d7837182 2890 /* Create the new address range... */
f63b4929 2891 new_address_range (low, high, subnet, pool);
20916cae 2892 pool_dereference (&pool, MDL);
d7837182
TL
2893}
2894
c358155d
TL
2895/* allow-deny-keyword :== BOOTP
2896 | BOOTING
2897 | DYNAMIC_BOOTP
2898 | UNKNOWN_CLIENTS */
2899
2900int parse_allow_deny (oc, cfile, flag)
2901 struct option_cache **oc;
2902 struct parse *cfile;
2903 int flag;
2904{
2905 enum dhcp_token token;
2906 const char *val;
2907 unsigned char rf = flag;
2908 struct expression *data = (struct expression *)0;
2909 int status;
2910
2911 if (!make_const_data (&data, &rf, 1, 0, 1))
2912 return 0;
2913
2914 token = next_token (&val, cfile);
2915 switch (token) {
007e3ee4 2916 case TOKEN_BOOTP:
c358155d
TL
2917 status = option_cache (oc, (struct data_string *)0, data,
2918 &server_options [SV_ALLOW_BOOTP]);
2919 break;
2920
2921 case BOOTING:
2922 status = option_cache (oc, (struct data_string *)0, data,
2923 &server_options [SV_ALLOW_BOOTING]);
2924 break;
2925
2926 case DYNAMIC_BOOTP:
2927 status = option_cache (oc, (struct data_string *)0, data,
2928 &server_options [SV_DYNAMIC_BOOTP]);
2929 break;
2930
2931 case UNKNOWN_CLIENTS:
2932 status = (option_cache
2933 (oc, (struct data_string *)0, data,
2934 &server_options [SV_BOOT_UNKNOWN_CLIENTS]));
2935 break;
2936
2937 case DUPLICATES:
2938 status = option_cache (oc, (struct data_string *)0, data,
2939 &server_options [SV_DUPLICATES]);
2940 break;
2941
2942 case DECLINES:
2943 status = option_cache (oc, (struct data_string *)0, data,
2944 &server_options [SV_DECLINES]);
2945 break;
2946
2947 default:
2948 parse_warn (cfile, "expecting allow/deny key");
2949 skip_to_semi (cfile);
2950 return 0;
2951 }
2952 parse_semi (cfile);
2953 return status;
2954}
2955