]> git.ipfire.org Git - thirdparty/dhcp.git/blame - server/confpars.c
Multiple items to clean up IPv6 address processing.
[thirdparty/dhcp.git] / server / confpars.c
CommitLineData
d7837182
TL
1/* confpars.c
2
3 Parser for dhcpd config file... */
4
5/*
bc7f8b8e 6 * Copyright (c) 2004-2012 by Internet Systems Consortium, Inc. ("ISC")
98311e4b 7 * Copyright (c) 1995-2003 by Internet Software Consortium
d7837182 8 *
98311e4b
DH
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
d7837182 12 *
98311e4b
DH
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
d7837182 20 *
98311e4b
DH
21 * Internet Systems Consortium, Inc.
22 * 950 Charter Street
23 * Redwood City, CA 94063
24 * <info@isc.org>
2c85ac9b 25 * https://www.isc.org/
49733f31 26 *
98311e4b 27 * This software has been written for Internet Systems Consortium
49733f31 28 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
98311e4b 29 * To learn more about Internet Systems Consortium, see
2c85ac9b 30 * ``https://www.isc.org/''. To learn more about Vixie Enterprises,
49733f31
TL
31 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
32 * ``http://www.nominum.com''.
d7837182
TL
33 */
34
d7837182 35#include "dhcpd.h"
d7837182 36
3a16098f 37static unsigned char global_host_once = 1;
7d6180be 38static unsigned char dhcpv6_class_once = 1;
d7837182 39
7285af30
DH
40static int parse_binding_value(struct parse *cfile,
41 struct binding_value *value);
42
e15d235d
TL
43#if defined (TRACING)
44trace_type_t *trace_readconf_type;
45trace_type_t *trace_readleases_type;
e15d235d
TL
46
47void parse_trace_setup ()
48{
49 trace_readconf_type = trace_type_register ("readconf", (void *)0,
50 trace_conf_input,
51 trace_conf_stop, MDL);
52 trace_readleases_type = trace_type_register ("readleases", (void *)0,
53 trace_conf_input,
54 trace_conf_stop, MDL);
55}
662df45a 56#endif
e15d235d 57
0b69dcc8 58/* conf-file :== parameters declarations END_OF_FILE
2d59f590
TL
59 parameters :== <nil> | parameter | parameters parameter
60 declarations :== <nil> | declaration | declarations declaration */
d7837182 61
35454d8a 62isc_result_t readconf ()
20916cae 63{
33692791
DH
64 isc_result_t res;
65
66 res = read_conf_file (path_dhcpd_conf, root_group, ROOT_GROUP, 0);
67#if defined(LDAP_CONFIGURATION)
68 if (res != ISC_R_SUCCESS)
69 return (res);
70
71 return ldap_read_config ();
72#else
73 return (res);
74#endif
20916cae
TL
75}
76
e15d235d
TL
77isc_result_t read_conf_file (const char *filename, struct group *group,
78 int group_type, int leasep)
79{
80 int file;
81 struct parse *cfile;
82 isc_result_t status;
83#if defined (TRACING)
84 char *fbuf, *dbuf;
85 off_t flen;
86 int result;
87 unsigned tflen, ulen;
88 trace_type_t *ttype;
89
90 if (leasep)
91 ttype = trace_readleases_type;
92 else
93 ttype = trace_readconf_type;
94
95 /* If we're in playback, we need to snarf the contents of the
96 named file out of the playback file rather than trying to
97 open and read it. */
98 if (trace_playback ()) {
99 dbuf = (char *)0;
100 tflen = 0;
101 status = trace_get_file (ttype, filename, &tflen, &dbuf);
102 if (status != ISC_R_SUCCESS)
103 return status;
104 ulen = tflen;
105
106 /* What we get back is filename\0contents, where contents is
107 terminated just by the length. So we figure out the length
108 of the filename, and subtract that and the NUL from the
109 total length to get the length of the contents of the file.
110 We make fbuf a pointer to the contents of the file, and
111 leave dbuf as it is so we can free it later. */
112 tflen = strlen (dbuf);
113 ulen = ulen - tflen - 1;
114 fbuf = dbuf + tflen + 1;
115 goto memfile;
116 }
117#endif
118
119 if ((file = open (filename, O_RDONLY)) < 0) {
120 if (leasep) {
121 log_error ("Can't open lease database %s: %m --",
122 path_dhcpd_db);
123 log_error (" check for failed database %s!",
124 "rewrite attempt");
125 log_error ("Please read the dhcpd.leases manual%s",
126 " page if you");
127 log_fatal ("don't know what to do about this.");
128 } else {
129 log_fatal ("Can't open %s: %m", filename);
130 }
131 }
132
133 cfile = (struct parse *)0;
134#if defined (TRACING)
135 flen = lseek (file, (off_t)0, SEEK_END);
136 if (flen < 0) {
137 boom:
138 log_fatal ("Can't lseek on %s: %m", filename);
139 }
140 if (lseek (file, (off_t)0, SEEK_SET) < 0)
141 goto boom;
142 /* Can't handle files greater than 2^31-1. */
143 if (flen > 0x7FFFFFFFUL)
144 log_fatal ("%s: file is too long to buffer.", filename);
145 ulen = flen;
146
147 /* Allocate a buffer that will be what's written to the tracefile,
148 and also will be what we parse from. */
149 tflen = strlen (filename);
150 dbuf = dmalloc (ulen + tflen + 1, MDL);
151 if (!dbuf)
152 log_fatal ("No memory for %s (%d bytes)",
153 filename, ulen);
154
155 /* Copy the name into the beginning, nul-terminated. */
156 strcpy (dbuf, filename);
157
158 /* Load the file in after the NUL. */
159 fbuf = dbuf + tflen + 1;
160 result = read (file, fbuf, ulen);
161 if (result < 0)
162 log_fatal ("Can't read in %s: %m", filename);
163 if (result != ulen)
164 log_fatal ("%s: short read of %d bytes instead of %d.",
165 filename, ulen, result);
98311e4b 166 close (file);
e15d235d
TL
167 memfile:
168 /* If we're recording, write out the filename and file contents. */
169 if (trace_record ())
170 trace_write_packet (ttype, ulen + tflen + 1, dbuf, MDL);
c40e954c 171 status = new_parse(&cfile, -1, fbuf, ulen, filename, 0); /* XXX */
e15d235d 172#else
c40e954c 173 status = new_parse(&cfile, file, NULL, 0, filename, 0);
e15d235d 174#endif
c40e954c
EH
175 if (status != ISC_R_SUCCESS || cfile == NULL)
176 return status;
177
e15d235d
TL
178 if (leasep)
179 status = lease_file_subparse (cfile);
180 else
181 status = conf_file_subparse (cfile, group, group_type);
182 end_parse (&cfile);
183#if defined (TRACING)
184 dfree (dbuf, MDL);
185#endif
e15d235d
TL
186 return status;
187}
188
189#if defined (TRACING)
190void trace_conf_input (trace_type_t *ttype, unsigned len, char *data)
191{
192 char *fbuf;
193 unsigned flen;
194 unsigned tflen;
195 struct parse *cfile = (struct parse *)0;
196 static int postconf_initialized;
197 static int leaseconf_initialized;
c40e954c 198 isc_result_t status;
e15d235d
TL
199
200 /* Do what's done above, except that we don't have to read in the
201 data, because it's already been read for us. */
202 tflen = strlen (data);
203 flen = len - tflen - 1;
204 fbuf = data + tflen + 1;
205
206 /* If we're recording, write out the filename and file contents. */
207 if (trace_record ())
208 trace_write_packet (ttype, len, data, MDL);
c40e954c
EH
209
210 status = new_parse(&cfile, -1, fbuf, flen, data, 0);
211 if (status == ISC_R_SUCCESS || cfile != NULL) {
212 if (ttype == trace_readleases_type)
213 lease_file_subparse (cfile);
214 else
215 conf_file_subparse (cfile, root_group, ROOT_GROUP);
216 end_parse (&cfile);
217 }
e15d235d
TL
218
219 /* Postconfiguration needs to be done after the config file
220 has been loaded. */
221 if (!postconf_initialized && ttype == trace_readconf_type) {
222 postconf_initialization (0);
223 postconf_initialized = 1;
224 }
225
226 if (!leaseconf_initialized && ttype == trace_readleases_type) {
227 db_startup (0);
228 leaseconf_initialized = 1;
d758ad8c 229 postdb_startup ();
e15d235d
TL
230 }
231}
232
233void trace_conf_stop (trace_type_t *ttype) { }
234#endif
235
0b69dcc8 236/* conf-file :== parameters declarations END_OF_FILE
20916cae
TL
237 parameters :== <nil> | parameter | parameters parameter
238 declarations :== <nil> | declaration | declarations declaration */
239
e15d235d
TL
240isc_result_t conf_file_subparse (struct parse *cfile, struct group *group,
241 int group_type)
d7837182 242{
b1b7b521 243 const char *val;
6f8fb41f 244 enum dhcp_token token;
2d59f590 245 int declaration = 0;
35454d8a 246 int status;
7e8381e5 247
d7837182 248 do {
b3519f23 249 token = peek_token (&val, (unsigned *)0, cfile);
0b69dcc8 250 if (token == END_OF_FILE)
d7837182 251 break;
20916cae 252 declaration = parse_statement (cfile, group, group_type,
ece6ea33
TL
253 (struct host_decl *)0,
254 declaration);
d7837182 255 } while (1);
b3519f23 256 token = next_token (&val, (unsigned *)0, cfile);
88ddda34 257
98bf1607 258 status = cfile->warnings_occurred ? DHCP_R_BADPARSE : ISC_R_SUCCESS;
35454d8a 259 return status;
1358b874
TL
260}
261
0b69dcc8 262/* lease-file :== lease-declarations END_OF_FILE
20ae1aff 263 lease-statements :== <nil>
2d59f590
TL
264 | lease-declaration
265 | lease-declarations lease-declaration */
5376e3e9 266
e15d235d 267isc_result_t lease_file_subparse (struct parse *cfile)
1358b874 268{
b1b7b521 269 const char *val;
6f8fb41f 270 enum dhcp_token token;
35454d8a 271 isc_result_t status;
7dfc8ac2 272
1358b874 273 do {
b3519f23 274 token = next_token (&val, (unsigned *)0, cfile);
0b69dcc8 275 if (token == END_OF_FILE)
1358b874 276 break;
52e79d12 277 if (token == LEASE) {
20916cae
TL
278 struct lease *lease = (struct lease *)0;
279 if (parse_lease_declaration (&lease, cfile)) {
1358b874 280 enter_lease (lease);
20916cae 281 lease_dereference (&lease, MDL);
96d7d13e 282 } else
35454d8a
TL
283 parse_warn (cfile,
284 "possibly corrupt lease file");
98bd7ca0
DH
285 } else if (token == IA_NA) {
286 parse_ia_na_declaration(cfile);
1d9774ab
FD
287 } else if (token == IA_TA) {
288 parse_ia_ta_declaration(cfile);
289 } else if (token == IA_PD) {
290 parse_ia_pd_declaration(cfile);
899d754f 291 } else if (token == CLASS) {
06e77c34
DH
292 parse_class_declaration(0, cfile, root_group,
293 CLASS_TYPE_CLASS);
899d754f 294 } else if (token == SUBCLASS) {
06e77c34
DH
295 parse_class_declaration(0, cfile, root_group,
296 CLASS_TYPE_SUBCLASS);
52e79d12 297 } else if (token == HOST) {
20916cae 298 parse_host_declaration (cfile, root_group);
35454d8a 299 } else if (token == GROUP) {
20916cae 300 parse_group_declaration (cfile, root_group);
a4ba3160
TL
301#if defined (FAILOVER_PROTOCOL)
302 } else if (token == FAILOVER) {
303 parse_failover_state_declaration
304 (cfile, (dhcp_failover_state_t *)0);
305#endif
fe5b0fdd 306#ifdef DHCPv6
98bd7ca0
DH
307 } else if (token == SERVER_DUID) {
308 parse_server_duid(cfile);
fe5b0fdd 309#endif /* DHCPv6 */
52e79d12
TL
310 } else {
311 log_error ("Corrupt lease file - possible data loss!");
312 skip_to_semi (cfile);
1358b874
TL
313 }
314
315 } while (1);
35454d8a 316
98bf1607 317 status = cfile->warnings_occurred ? DHCP_R_BADPARSE : ISC_R_SUCCESS;
35454d8a 318 return status;
d7837182
TL
319}
320
2d59f590
TL
321/* statement :== parameter | declaration
322
6d103865 323 parameter :== DEFAULT_LEASE_TIME lease_time
2d59f590
TL
324 | MAX_LEASE_TIME lease_time
325 | DYNAMIC_BOOTP_LEASE_CUTOFF date
326 | DYNAMIC_BOOTP_LEASE_LENGTH lease_time
327 | BOOT_UNKNOWN_CLIENTS boolean
328 | ONE_LEASE_PER_CLIENT boolean
5fea7b10 329 | GET_LEASE_HOSTNAMES boolean
c256bae9 330 | USE_HOST_DECL_NAME boolean
2d59f590
TL
331 | NEXT_SERVER ip-addr-or-hostname SEMI
332 | option_parameter
333 | SERVER-IDENTIFIER ip-addr-or-hostname SEMI
334 | FILENAME string-parameter
335 | SERVER_NAME string-parameter
336 | hardware-parameter
337 | fixed-address-parameter
99fd97cc
TL
338 | ALLOW allow-deny-keyword
339 | DENY allow-deny-keyword
59b85ebd 340 | USE_LEASE_ADDR_FOR_DEFAULT_ROUTE boolean
763adef1
TL
341 | AUTHORITATIVE
342 | NOT AUTHORITATIVE
2d59f590
TL
343
344 declaration :== host-declaration
345 | group-declaration
346 | shared-network-declaration
347 | subnet-declaration
348 | VENDOR_CLASS class-declaration
349 | USER_CLASS class-declaration
350 | RANGE address-range-declaration */
351
352int parse_statement (cfile, group, type, host_decl, declaration)
35454d8a 353 struct parse *cfile;
7dfc8ac2
TL
354 struct group *group;
355 int type;
356 struct host_decl *host_decl;
2d59f590 357 int declaration;
d7837182 358{
6f8fb41f 359 enum dhcp_token token;
b1b7b521 360 const char *val;
7dfc8ac2 361 struct shared_network *share;
28868515 362 char *n;
7dfc8ac2 363 struct hardware hardware;
ece6ea33 364 struct executable_statement *et, *ep;
f7fdb216 365 struct option *option = NULL;
ece6ea33
TL
366 struct option_cache *cache;
367 int lose;
b1b7b521 368 int known;
20916cae 369 isc_result_t status;
f7fdb216 370 unsigned code;
d7837182 371
b3519f23 372 token = peek_token (&val, (unsigned *)0, cfile);
e68de775
TL
373
374 switch (token) {
20916cae 375 case INCLUDE:
b3519f23
TL
376 next_token (&val, (unsigned *)0, cfile);
377 token = next_token (&val, (unsigned *)0, cfile);
20916cae
TL
378 if (token != STRING) {
379 parse_warn (cfile, "filename string expected.");
380 skip_to_semi (cfile);
381 } else {
e15d235d 382 status = read_conf_file (val, group, type, 0);
20916cae
TL
383 if (status != ISC_R_SUCCESS)
384 parse_warn (cfile, "%s: bad parse.", val);
385 parse_semi (cfile);
386 }
387 return 1;
388
d7837182 389 case HOST:
b3519f23 390 next_token (&val, (unsigned *)0, cfile);
3a16098f
DH
391 if (type != HOST_DECL && type != CLASS_DECL) {
392 if (global_host_once &&
393 (type == SUBNET_DECL || type == SHARED_NET_DECL)) {
394 global_host_once = 0;
395 log_error("WARNING: Host declarations are "
396 "global. They are not limited to "
397 "the scope you declared them in.");
398 }
399
2d59f590 400 parse_host_declaration (cfile, group);
3a16098f 401 } else {
35454d8a
TL
402 parse_warn (cfile,
403 "host declarations not allowed here.");
7dfc8ac2 404 skip_to_semi (cfile);
d7837182 405 }
7dfc8ac2
TL
406 return 1;
407
408 case GROUP:
b3519f23 409 next_token (&val, (unsigned *)0, cfile);
ece6ea33 410 if (type != HOST_DECL && type != CLASS_DECL)
2d59f590 411 parse_group_declaration (cfile, group);
7dfc8ac2 412 else {
35454d8a
TL
413 parse_warn (cfile,
414 "group declarations not allowed here.");
7dfc8ac2 415 skip_to_semi (cfile);
d7837182 416 }
7dfc8ac2
TL
417 return 1;
418
1f814ff2 419 case SHARED_NETWORK:
b3519f23 420 next_token (&val, (unsigned *)0, cfile);
2d59f590
TL
421 if (type == SHARED_NET_DECL ||
422 type == HOST_DECL ||
ece6ea33
TL
423 type == SUBNET_DECL ||
424 type == CLASS_DECL) {
35454d8a 425 parse_warn (cfile, "shared-network parameters not %s.",
7dfc8ac2
TL
426 "allowed here");
427 skip_to_semi (cfile);
428 break;
1f814ff2 429 }
7dfc8ac2 430
2d59f590 431 parse_shared_net_declaration (cfile, group);
7dfc8ac2
TL
432 return 1;
433
685963dc 434 case SUBNET:
98bd7ca0 435 case SUBNET6:
b3519f23 436 next_token (&val, (unsigned *)0, cfile);
ece6ea33
TL
437 if (type == HOST_DECL || type == SUBNET_DECL ||
438 type == CLASS_DECL) {
35454d8a
TL
439 parse_warn (cfile,
440 "subnet declarations not allowed here.");
7dfc8ac2
TL
441 skip_to_semi (cfile);
442 return 1;
443 }
444
2d59f590 445 /* If we're in a subnet declaration, just do the parse. */
7d6180be 446 if (group->shared_network != NULL) {
98bd7ca0
DH
447 if (token == SUBNET) {
448 parse_subnet_declaration(cfile,
449 group->shared_network);
450 } else {
451 parse_subnet6_declaration(cfile,
452 group->shared_network);
453 }
7dfc8ac2
TL
454 break;
455 }
456
7d6180be
DH
457 /*
458 * Otherwise, cons up a fake shared network structure
459 * and populate it with the lone subnet...because the
460 * intention most likely is to refer to the entire link
461 * by shorthand, any configuration inside the subnet is
462 * actually placed in the shared-network's group.
463 */
7dfc8ac2 464
7d6180be 465 share = NULL;
20916cae
TL
466 status = shared_network_allocate (&share, MDL);
467 if (status != ISC_R_SUCCESS)
468 log_fatal ("Can't allocate shared subnet: %s",
469 isc_result_totext (status));
470 if (!clone_group (&share -> group, group, MDL))
f84d544b 471 log_fatal ("Can't allocate group for shared net");
6ceb9118
TL
472 shared_network_reference (&share -> group -> shared_network,
473 share, MDL);
7dfc8ac2 474
7d6180be
DH
475 /*
476 * This is an implicit shared network, not explicit in
477 * the config.
478 */
479 share->flags |= SHARED_IMPLICIT;
480
98bd7ca0
DH
481 if (token == SUBNET) {
482 parse_subnet_declaration(cfile, share);
483 } else {
484 parse_subnet6_declaration(cfile, share);
485 }
763adef1
TL
486
487 /* share -> subnets is the subnet we just parsed. */
98bd7ca0
DH
488 if (share->subnets) {
489 interface_reference(&share->interface,
490 share->subnets->interface,
491 MDL);
7dfc8ac2 492
763adef1 493 /* Make the shared network name from network number. */
98bd7ca0
DH
494 if (token == SUBNET) {
495 n = piaddrmask(&share->subnets->net,
496 &share->subnets->netmask);
497 } else {
498 n = piaddrcidr(&share->subnets->net,
499 share->subnets->prefix_len);
500 }
501
502 share->name = strdup(n);
503
504 if (share->name == NULL)
505 log_fatal("Out of memory allocating default "
506 "shared network name (\"%s\").", n);
763adef1
TL
507
508 /* Copy the authoritative parameter from the subnet,
509 since there is no opportunity to declare it here. */
98bd7ca0
DH
510 share->group->authoritative =
511 share->subnets->group->authoritative;
512 enter_shared_network(share);
d7837182 513 }
98bd7ca0 514 shared_network_dereference(&share, MDL);
7dfc8ac2
TL
515 return 1;
516
24a75c03 517 case VENDOR_CLASS:
b3519f23 518 next_token (&val, (unsigned *)0, cfile);
ece6ea33 519 if (type == CLASS_DECL) {
35454d8a
TL
520 parse_warn (cfile,
521 "class declarations not allowed here.");
ece6ea33
TL
522 skip_to_semi (cfile);
523 break;
524 }
06e77c34 525 parse_class_declaration(NULL, cfile, group, CLASS_TYPE_VENDOR);
7dfc8ac2
TL
526 return 1;
527
24a75c03 528 case USER_CLASS:
b3519f23 529 next_token (&val, (unsigned *)0, cfile);
ece6ea33 530 if (type == CLASS_DECL) {
35454d8a
TL
531 parse_warn (cfile,
532 "class declarations not allowed here.");
ece6ea33
TL
533 skip_to_semi (cfile);
534 break;
535 }
06e77c34 536 parse_class_declaration(NULL, cfile, group, CLASS_TYPE_USER);
7dfc8ac2 537 return 1;
1f814ff2 538
ece6ea33 539 case CLASS:
b3519f23 540 next_token (&val, (unsigned *)0, cfile);
ece6ea33 541 if (type == CLASS_DECL) {
35454d8a
TL
542 parse_warn (cfile,
543 "class declarations not allowed here.");
59b85ebd 544 skip_to_semi (cfile);
ece6ea33 545 break;
59b85ebd 546 }
06e77c34 547 parse_class_declaration(NULL, cfile, group, CLASS_TYPE_CLASS);
ece6ea33 548 return 1;
59b85ebd 549
ece6ea33 550 case SUBCLASS:
b3519f23 551 next_token (&val, (unsigned *)0, cfile);
ece6ea33 552 if (type == CLASS_DECL) {
35454d8a
TL
553 parse_warn (cfile,
554 "class declarations not allowed here.");
ece6ea33 555 skip_to_semi (cfile);
7dfc8ac2 556 break;
7dfc8ac2 557 }
06e77c34
DH
558 parse_class_declaration(NULL, cfile, group,
559 CLASS_TYPE_SUBCLASS);
ece6ea33 560 return 1;
7dfc8ac2
TL
561
562 case HARDWARE:
b3519f23 563 next_token (&val, (unsigned *)0, cfile);
76981d9f 564 memset (&hardware, 0, sizeof hardware);
2178df03
DH
565 if (host_decl && memcmp(&hardware, &(host_decl->interface),
566 sizeof(hardware)) != 0) {
567 parse_warn(cfile, "Host %s hardware address already "
568 "configured.", host_decl->name);
569 break;
570 }
571
2d59f590 572 parse_hardware_param (cfile, &hardware);
7dfc8ac2
TL
573 if (host_decl)
574 host_decl -> interface = hardware;
575 else
35454d8a 576 parse_warn (cfile, "hardware address parameter %s",
7dfc8ac2
TL
577 "not allowed here.");
578 break;
579
580 case FIXED_ADDR:
98bd7ca0
DH
581 case FIXED_ADDR6:
582 next_token(&val, NULL, cfile);
583 cache = NULL;
584 if (parse_fixed_addr_param(&cache, cfile, token)) {
98311e4b 585 if (host_decl) {
98bd7ca0
DH
586 if (host_decl->fixed_addr) {
587 option_cache_dereference(&cache, MDL);
588 parse_warn(cfile,
589 "Only one fixed address "
590 "declaration per host.");
98311e4b 591 } else {
98bd7ca0 592 host_decl->fixed_addr = cache;
98311e4b
DH
593 }
594 } else {
98bd7ca0
DH
595 parse_warn(cfile,
596 "fixed-address parameter not "
597 "allowed here.");
598 option_cache_dereference(&cache, MDL);
20916cae 599 }
6f8fb41f 600 }
7dfc8ac2
TL
601 break;
602
f63b4929 603 case POOL:
b3519f23 604 next_token (&val, (unsigned *)0, cfile);
9322442f 605 if (type == POOL_DECL) {
35454d8a 606 parse_warn (cfile, "pool declared within pool.");
61252edf 607 skip_to_semi(cfile);
9322442f
FD
608 } else if (type != SUBNET_DECL && type != SHARED_NET_DECL) {
609 parse_warn (cfile, "pool declared outside of network");
610 skip_to_semi(cfile);
611 } else
61252edf
EH
612 parse_pool_statement (cfile, group, type);
613
f63b4929
TL
614 return declaration;
615
7dfc8ac2 616 case RANGE:
b3519f23 617 next_token (&val, (unsigned *)0, cfile);
2d59f590 618 if (type != SUBNET_DECL || !group -> subnet) {
35454d8a
TL
619 parse_warn (cfile,
620 "range declaration not allowed here.");
7dfc8ac2 621 skip_to_semi (cfile);
2d59f590 622 return declaration;
7dfc8ac2 623 }
98311e4b
DH
624 parse_address_range (cfile, group, type, (struct pool *)0,
625 (struct lease **)0);
2d59f590 626 return declaration;
7dfc8ac2 627
fe5b0fdd 628#ifdef DHCPv6
98bd7ca0
DH
629 case RANGE6:
630 next_token(NULL, NULL, cfile);
631 if ((type != SUBNET_DECL) || (group->subnet == NULL)) {
632 parse_warn (cfile,
633 "range6 declaration not allowed here.");
634 skip_to_semi(cfile);
635 return declaration;
636 }
637 parse_address_range6(cfile, group);
638 return declaration;
80c9fdb0
FD
639
640 case PREFIX6:
641 next_token(NULL, NULL, cfile);
bd72740e 642 if ((type != SUBNET_DECL) || (group->subnet == NULL)) {
80c9fdb0 643 parse_warn (cfile,
9322442f 644 "prefix6 declaration not allowed here.");
80c9fdb0
FD
645 skip_to_semi(cfile);
646 return declaration;
647 }
648 parse_prefix6(cfile, group);
649 return declaration;
650
651 case FIXED_PREFIX6:
652 next_token(&val, NULL, cfile);
653 if (!host_decl) {
654 parse_warn (cfile,
655 "fixed-prefix6 declaration not "
656 "allowed here.");
657 skip_to_semi(cfile);
658 break;
659 }
660 parse_fixed_prefix6(cfile, host_decl);
661 break;
662
fe5b0fdd 663#endif /* DHCPv6 */
98bd7ca0 664
763adef1 665 case TOKEN_NOT:
b3519f23
TL
666 token = next_token (&val, (unsigned *)0, cfile);
667 token = next_token (&val, (unsigned *)0, cfile);
763adef1
TL
668 switch (token) {
669 case AUTHORITATIVE:
670 group -> authoritative = 0;
671 goto authoritative;
672 default:
35454d8a 673 parse_warn (cfile, "expecting assertion");
763adef1
TL
674 skip_to_semi (cfile);
675 break;
676 }
677 break;
678 case AUTHORITATIVE:
b3519f23 679 token = next_token (&val, (unsigned *)0, cfile);
763adef1
TL
680 group -> authoritative = 1;
681 authoritative:
1b8223ae 682 if (type == HOST_DECL)
35454d8a 683 parse_warn (cfile, "authority makes no sense here.");
763adef1
TL
684 parse_semi (cfile);
685 break;
686
8230a054
TL
687 /* "server-identifier" is a special hack, equivalent to
688 "option dhcp-server-identifier". */
689 case SERVER_IDENTIFIER:
f7fdb216
DH
690 code = DHO_DHCP_SERVER_IDENTIFIER;
691 if (!option_code_hash_lookup(&option, dhcp_universe.code_hash,
692 &code, 0, MDL))
693 log_fatal("Server identifier not in hash (%s:%d).",
694 MDL);
b3519f23 695 token = next_token (&val, (unsigned *)0, cfile);
8230a054
TL
696 goto finish_option;
697
6f8fb41f 698 case OPTION:
b3519f23
TL
699 token = next_token (&val, (unsigned *)0, cfile);
700 token = peek_token (&val, (unsigned *)0, cfile);
822d95c9
TL
701 if (token == SPACE) {
702 if (type != ROOT_GROUP) {
35454d8a
TL
703 parse_warn (cfile,
704 "option space definitions %s",
436f1c8c 705 "may not be scoped.");
822d95c9 706 skip_to_semi (cfile);
822d95c9
TL
707 break;
708 }
709 parse_option_space_decl (cfile);
710 return declaration;
711 }
712
b1b7b521 713 known = 0;
f7fdb216
DH
714 status = parse_option_name(cfile, 1, &known, &option);
715 if (status == ISC_R_SUCCESS) {
b3519f23 716 token = peek_token (&val, (unsigned *)0, cfile);
8230a054
TL
717 if (token == CODE) {
718 if (type != ROOT_GROUP) {
35454d8a 719 parse_warn (cfile,
ab58ff49 720 "option definitions%s",
822d95c9 721 " may not be scoped.");
8230a054 722 skip_to_semi (cfile);
f7fdb216 723 option_dereference(&option, MDL);
8230a054
TL
724 break;
725 }
b3519f23 726 next_token (&val, (unsigned *)0, cfile);
86f1d4b7
DH
727
728 /*
729 * If the option was known, remove it from the
730 * code and name hashes before redefining it.
731 */
732 if (known) {
733 option_name_hash_delete(
734 option->universe->name_hash,
735 option->name, 0, MDL);
736 option_code_hash_delete(
737 option->universe->code_hash,
738 &option->code, 0, MDL);
739 }
740
f7fdb216
DH
741 parse_option_code_definition(cfile, option);
742 option_dereference(&option, MDL);
8230a054
TL
743 return declaration;
744 }
745
746 /* If this wasn't an option code definition, don't
747 allow an unknown option. */
b1b7b521 748 if (!known) {
35454d8a 749 parse_warn (cfile, "unknown option %s.%s",
8230a054
TL
750 option -> universe -> name,
751 option -> name);
752 skip_to_semi (cfile);
f7fdb216 753 option_dereference(&option, MDL);
8230a054
TL
754 return declaration;
755 }
756
757 finish_option:
79a65726
TL
758 et = (struct executable_statement *)0;
759 if (!parse_option_statement
760 (&et, cfile, 1, option,
761 supersede_option_statement))
6f8fb41f 762 return declaration;
f7fdb216 763 option_dereference(&option, MDL);
6f8fb41f
TL
764 goto insert_statement;
765 } else
766 return declaration;
767
768 break;
769
763adef1 770 case FAILOVER:
98311e4b 771 if (type != ROOT_GROUP && type != SHARED_NET_DECL) {
9e9b2261
TL
772 parse_warn (cfile, "failover peers may only be %s",
773 "defined in shared-network");
774 log_error ("declarations and the outer scope.");
775 skip_to_semi (cfile);
776 break;
777 }
b3519f23 778 token = next_token (&val, (unsigned *)0, cfile);
22009f79 779#if defined (FAILOVER_PROTOCOL)
763adef1 780 parse_failover_peer (cfile, group, type);
22009f79
TL
781#else
782 parse_warn (cfile, "No failover support.");
783 skip_to_semi (cfile);
763adef1 784#endif
22009f79 785 break;
98bd7ca0 786
fe5b0fdd 787#ifdef DHCPv6
98bd7ca0
DH
788 case SERVER_DUID:
789 parse_server_duid_conf(cfile);
790 break;
fe5b0fdd 791#endif /* DHCPv6 */
763adef1 792
d7837182 793 default:
ece6ea33 794 et = (struct executable_statement *)0;
588af269
TL
795 lose = 0;
796 if (!parse_executable_statement (&et, cfile, &lose,
797 context_any)) {
798 if (!lose) {
799 if (declaration)
35454d8a
TL
800 parse_warn (cfile,
801 "expecting a declaration");
588af269 802 else
35454d8a 803 parse_warn (cfile,
ab58ff49 804 "expecting a parameter %s",
35454d8a 805 "or declaration");
588af269 806 skip_to_semi (cfile);
ece6ea33 807 }
ece6ea33
TL
808 return declaration;
809 }
026975bb
TL
810 if (!et)
811 return declaration;
ece6ea33
TL
812 insert_statement:
813 if (group -> statements) {
79a65726
TL
814 int multi = 0;
815
816 /* If this set of statements is only referenced
817 by this group, just add the current statement
818 to the end of the chain. */
ece6ea33
TL
819 for (ep = group -> statements; ep -> next;
820 ep = ep -> next)
79a65726
TL
821 if (ep -> refcnt > 1) /* XXX */
822 multi = 1;
823 if (!multi) {
436f1c8c
TL
824 executable_statement_reference (&ep -> next,
825 et, MDL);
d758ad8c 826 executable_statement_dereference (&et, MDL);
79a65726
TL
827 return declaration;
828 }
ece6ea33 829
79a65726
TL
830 /* Otherwise, make a parent chain, and put the
831 current group statements first and the new
832 statement in the next pointer. */
833 ep = (struct executable_statement *)0;
436f1c8c 834 if (!executable_statement_allocate (&ep, MDL))
79a65726
TL
835 log_fatal ("No memory for statements.");
836 ep -> op = statements_statement;
436f1c8c
TL
837 executable_statement_reference (&ep -> data.statements,
838 group -> statements,
839 MDL);
840 executable_statement_reference (&ep -> next, et, MDL);
841 executable_statement_dereference (&group -> statements,
842 MDL);
843 executable_statement_reference (&group -> statements,
844 ep, MDL);
d758ad8c
TL
845 executable_statement_dereference (&ep, MDL);
846 } else {
436f1c8c
TL
847 executable_statement_reference (&group -> statements,
848 et, MDL);
d758ad8c
TL
849 }
850 executable_statement_dereference (&et, MDL);
6f8fb41f 851 return declaration;
d7837182 852 }
1f814ff2 853
7dfc8ac2 854 return 0;
d7837182
TL
855}
856
763adef1
TL
857#if defined (FAILOVER_PROTOCOL)
858void parse_failover_peer (cfile, group, type)
35454d8a 859 struct parse *cfile;
763adef1
TL
860 struct group *group;
861 int type;
862{
863 enum dhcp_token token;
b1b7b521 864 const char *val;
9e9b2261
TL
865 dhcp_failover_state_t *peer;
866 u_int32_t *tp;
763adef1 867 char *name;
9e9b2261
TL
868 u_int32_t split;
869 u_int8_t hba [32];
165bce70 870 unsigned hba_len = sizeof hba;
9e9b2261
TL
871 int i;
872 struct expression *expr;
e9623235 873 isc_result_t status;
05815916 874 dhcp_failover_config_t *cp;
763adef1 875
b3519f23 876 token = next_token (&val, (unsigned *)0, cfile);
763adef1 877 if (token != PEER) {
9e9b2261 878 parse_warn (cfile, "expecting \"peer\"");
763adef1
TL
879 skip_to_semi (cfile);
880 return;
881 }
882
b3519f23 883 token = next_token (&val, (unsigned *)0, cfile);
763adef1 884 if (is_identifier (token) || token == STRING) {
436f1c8c 885 name = dmalloc (strlen (val) + 1, MDL);
9e9b2261 886 if (!name)
8ae2d595 887 log_fatal ("no memory for peer name %s", name);
9e9b2261 888 strcpy (name, val);
763adef1 889 } else {
9e9b2261 890 parse_warn (cfile, "expecting failover peer name.");
763adef1
TL
891 skip_to_semi (cfile);
892 return;
893 }
894
895 /* See if there's a peer declaration by this name. */
9e9b2261 896 peer = (dhcp_failover_state_t *)0;
20916cae 897 find_failover_peer (&peer, name, MDL);
763adef1 898
b3519f23 899 token = next_token (&val, (unsigned *)0, cfile);
763adef1 900 if (token == SEMI) {
436f1c8c 901 dfree (name, MDL);
763adef1 902 if (type != SHARED_NET_DECL)
35454d8a 903 parse_warn (cfile, "failover peer reference not %s",
763adef1
TL
904 "in shared-network declaration");
905 else {
906 if (!peer) {
35454d8a 907 parse_warn (cfile, "reference to unknown%s%s",
763adef1
TL
908 " failover peer ", name);
909 return;
910 }
20916cae
TL
911 dhcp_failover_state_reference
912 (&group -> shared_network -> failover_peer,
913 peer, MDL);
763adef1 914 }
20916cae 915 dhcp_failover_state_dereference (&peer, MDL);
763adef1 916 return;
a4ba3160 917 } else if (token == STATE) {
763adef1 918 if (!peer) {
a4ba3160 919 parse_warn (cfile, "state declaration for unknown%s%s",
763adef1
TL
920 " failover peer ", name);
921 return;
922 }
a4ba3160 923 parse_failover_state_declaration (cfile, peer);
20916cae 924 dhcp_failover_state_dereference (&peer, MDL);
763adef1
TL
925 return;
926 } else if (token != LBRACE) {
35454d8a 927 parse_warn (cfile, "expecting left brace");
763adef1
TL
928 skip_to_semi (cfile);
929 }
930
931 /* Make sure this isn't a redeclaration. */
932 if (peer) {
35454d8a 933 parse_warn (cfile, "redeclaration of failover peer %s", name);
763adef1 934 skip_to_rbrace (cfile, 1);
20916cae 935 dhcp_failover_state_dereference (&peer, MDL);
763adef1
TL
936 return;
937 }
938
20916cae
TL
939 status = dhcp_failover_state_allocate (&peer, MDL);
940 if (status != ISC_R_SUCCESS)
941 log_fatal ("Can't allocate failover peer %s: %s",
942 name, isc_result_totext (status));
763adef1
TL
943
944 /* Save the name. */
945 peer -> name = name;
946
947 do {
05815916
TL
948 cp = &peer -> me;
949 peer:
b3519f23 950 token = next_token (&val, (unsigned *)0, cfile);
763adef1
TL
951 switch (token) {
952 case RBRACE:
953 break;
9e9b2261 954
763adef1
TL
955 case PRIMARY:
956 peer -> i_am = primary;
957 break;
9e9b2261 958
763adef1
TL
959 case SECONDARY:
960 peer -> i_am = secondary;
007e3ee4
TL
961 if (peer -> hba)
962 parse_warn (cfile,
963 "secondary may not define %s",
964 "load balance settings.");
763adef1 965 break;
9e9b2261 966
e9623235 967 case PEER:
05815916
TL
968 cp = &peer -> partner;
969 goto peer;
e9623235
TL
970
971 case ADDRESS:
9e9b2261
TL
972 expr = (struct expression *)0;
973 if (!parse_ip_addr_or_hostname (&expr, cfile, 0)) {
763adef1 974 skip_to_rbrace (cfile, 1);
20916cae 975 dhcp_failover_state_dereference (&peer, MDL);
763adef1
TL
976 return;
977 }
05815916
TL
978 option_cache (&cp -> address,
979 (struct data_string *)0, expr,
d758ad8c 980 (struct option *)0, MDL);
436f1c8c 981 expression_dereference (&expr, MDL);
763adef1 982 break;
e9623235 983
763adef1 984 case PORT:
b3519f23 985 token = next_token (&val, (unsigned *)0, cfile);
763adef1 986 if (token != NUMBER) {
35454d8a 987 parse_warn (cfile, "expecting number");
763adef1
TL
988 skip_to_rbrace (cfile, 1);
989 }
05815916 990 cp -> port = atoi (val);
763adef1 991 break;
9e9b2261 992
2426234f
DH
993 case MAX_LEASE_MISBALANCE:
994 tp = &peer->max_lease_misbalance;
995 goto parse_idle;
996
997 case MAX_LEASE_OWNERSHIP:
998 tp = &peer->max_lease_ownership;
999 goto parse_idle;
1000
1001 case MAX_BALANCE:
1002 tp = &peer->max_balance;
1003 goto parse_idle;
1004
1005 case MIN_BALANCE:
1006 tp = &peer->min_balance;
1007 goto parse_idle;
1008
9e3eb22a
DH
1009 case AUTO_PARTNER_DOWN:
1010 tp = &peer->auto_partner_down;
1011 goto parse_idle;
1012
763adef1 1013 case MAX_RESPONSE_DELAY:
05815916 1014 tp = &cp -> max_response_delay;
763adef1 1015 parse_idle:
b3519f23 1016 token = next_token (&val, (unsigned *)0, cfile);
763adef1 1017 if (token != NUMBER) {
35454d8a 1018 parse_warn (cfile, "expecting number.");
763adef1 1019 skip_to_rbrace (cfile, 1);
20916cae 1020 dhcp_failover_state_dereference (&peer, MDL);
763adef1
TL
1021 return;
1022 }
1023 *tp = atoi (val);
9e9b2261
TL
1024 break;
1025
1026 case MAX_UNACKED_UPDATES:
05815916 1027 tp = &cp -> max_flying_updates;
9e9b2261
TL
1028 goto parse_idle;
1029
1030 case MCLT:
1031 tp = &peer -> mclt;
1032 goto parse_idle;
1033
1034 case HBA:
e9623235 1035 hba_len = 32;
007e3ee4
TL
1036 if (peer -> i_am == secondary)
1037 parse_warn (cfile,
1038 "secondary may not define %s",
1039 "load balance settings.");
9e9b2261 1040 if (!parse_numeric_aggregate (cfile, hba, &hba_len,
e9623235 1041 COLON, 16, 8)) {
9e9b2261 1042 skip_to_rbrace (cfile, 1);
20916cae 1043 dhcp_failover_state_dereference (&peer, MDL);
9e9b2261
TL
1044 return;
1045 }
e9623235
TL
1046 if (hba_len != 32) {
1047 parse_warn (cfile,
1048 "HBA must be exactly 32 bytes.");
1049 dfree (hba, MDL);
1050 break;
1051 }
9e9b2261 1052 make_hba:
436f1c8c 1053 peer -> hba = dmalloc (32, MDL);
9e9b2261 1054 if (!peer -> hba) {
436f1c8c
TL
1055 dfree (peer -> name, MDL);
1056 dfree (peer, MDL);
9e9b2261
TL
1057 }
1058 memcpy (peer -> hba, hba, 32);
1059 break;
1060
1061 case SPLIT:
b3519f23 1062 token = next_token (&val, (unsigned *)0, cfile);
007e3ee4
TL
1063 if (peer -> i_am == secondary)
1064 parse_warn (cfile,
1065 "secondary may not define %s",
1066 "load balance settings.");
9e9b2261
TL
1067 if (token != NUMBER) {
1068 parse_warn (cfile, "expecting number");
1069 skip_to_rbrace (cfile, 1);
20916cae 1070 dhcp_failover_state_dereference (&peer, MDL);
9e9b2261
TL
1071 return;
1072 }
20916cae 1073 split = atoi (val);
9e9b2261
TL
1074 if (split > 255) {
1075 parse_warn (cfile, "split must be < 256");
1076 } else {
1077 memset (hba, 0, sizeof hba);
1078 for (i = 0; i < split; i++) {
1079 if (i < split)
1080 hba [i / 8] |= (1 << (i & 7));
1081 }
1082 goto make_hba;
1083 }
1084 break;
1085
e9623235 1086 case LOAD:
b3519f23 1087 token = next_token (&val, (unsigned *)0, cfile);
e9623235
TL
1088 if (token != BALANCE) {
1089 parse_warn (cfile, "expecting 'balance'");
1090 badload:
1091 skip_to_rbrace (cfile, 1);
1092 break;
1093 }
b3519f23 1094 token = next_token (&val, (unsigned *)0, cfile);
e9623235
TL
1095 if (token != TOKEN_MAX) {
1096 parse_warn (cfile, "expecting 'max'");
1097 goto badload;
1098 }
b3519f23 1099 token = next_token (&val, (unsigned *)0, cfile);
e9623235
TL
1100 if (token != SECONDS) {
1101 parse_warn (cfile, "expecting 'secs'");
1102 goto badload;
1103 }
b3519f23 1104 token = next_token (&val, (unsigned *)0, cfile);
e9623235
TL
1105 if (token != NUMBER) {
1106 parse_warn (cfile, "expecting number");
1107 goto badload;
1108 }
1109 peer -> load_balance_max_secs = atoi (val);
1110 break;
1111
763adef1 1112 default:
35454d8a
TL
1113 parse_warn (cfile,
1114 "invalid statement in peer declaration");
763adef1 1115 skip_to_rbrace (cfile, 1);
20916cae 1116 dhcp_failover_state_dereference (&peer, MDL);
763adef1
TL
1117 return;
1118 }
e9623235
TL
1119 if (token != RBRACE && !parse_semi (cfile)) {
1120 skip_to_rbrace (cfile, 1);
20916cae 1121 dhcp_failover_state_dereference (&peer, MDL);
e9623235
TL
1122 return;
1123 }
763adef1 1124 } while (token != RBRACE);
98311e4b
DH
1125
1126 /* me.address can be null; the failover link initiate code tries to
1127 * derive a reasonable address to use.
1128 */
1129 if (!peer -> partner.address)
1130 parse_warn (cfile, "peer address may not be omitted");
1131
d340bc24
DH
1132 if (!peer->me.port)
1133 peer->me.port = DEFAULT_FAILOVER_PORT;
1134 if (!peer->partner.port)
1135 peer->partner.port = DEFAULT_FAILOVER_PORT;
98311e4b
DH
1136
1137 if (peer -> i_am == primary) {
1138 if (!peer -> hba) {
1139 parse_warn (cfile,
007e3ee4 1140 "primary failover server must have hba or split.");
98311e4b
DH
1141 } else if (!peer -> mclt) {
1142 parse_warn (cfile,
1143 "primary failover server must have mclt.");
1144 }
1145 }
007e3ee4 1146
2426234f
DH
1147 if (!peer->max_lease_misbalance)
1148 peer->max_lease_misbalance = DEFAULT_MAX_LEASE_MISBALANCE;
1149 if (!peer->max_lease_ownership)
1150 peer->max_lease_ownership = DEFAULT_MAX_LEASE_OWNERSHIP;
1151 if (!peer->max_balance)
1152 peer->max_balance = DEFAULT_MAX_BALANCE_TIME;
1153 if (!peer->min_balance)
1154 peer->min_balance = DEFAULT_MIN_BALANCE_TIME;
1155 if (!peer->me.max_flying_updates)
1156 peer->me.max_flying_updates = DEFAULT_MAX_FLYING_UPDATES;
1157 if (!peer->me.max_response_delay)
1158 peer->me.max_response_delay = DEFAULT_MAX_RESPONSE_DELAY;
1159
1160 if (type == SHARED_NET_DECL)
1161 group->shared_network->failover_peer = peer;
6f8a0361
TL
1162
1163 /* Set the initial state. */
1164 if (peer -> i_am == primary) {
1165 peer -> me.state = recover;
1166 peer -> me.stos = cur_time;
1167 peer -> partner.state = unknown_state;
1168 peer -> partner.stos = cur_time;
1169 } else {
1170 peer -> me.state = recover;
1171 peer -> me.stos = cur_time;
1172 peer -> partner.state = unknown_state;
1173 peer -> partner.stos = cur_time;
1174 }
1175
e9623235
TL
1176 status = enter_failover_peer (peer);
1177 if (status != ISC_R_SUCCESS)
1178 parse_warn (cfile, "failover peer %s: %s",
1179 peer -> name, isc_result_totext (status));
20916cae 1180 dhcp_failover_state_dereference (&peer, MDL);
763adef1
TL
1181}
1182
a4ba3160
TL
1183void parse_failover_state_declaration (struct parse *cfile,
1184 dhcp_failover_state_t *peer)
1185{
1186 enum dhcp_token token;
1187 const char *val;
1188 char *name;
1189 dhcp_failover_state_t *state;
05815916 1190 dhcp_failover_config_t *cp;
a4ba3160
TL
1191
1192 if (!peer) {
b3519f23 1193 token = next_token (&val, (unsigned *)0, cfile);
a4ba3160
TL
1194 if (token != PEER) {
1195 parse_warn (cfile, "expecting \"peer\"");
1196 skip_to_semi (cfile);
1197 return;
1198 }
1199
b3519f23 1200 token = next_token (&val, (unsigned *)0, cfile);
a4ba3160
TL
1201 if (is_identifier (token) || token == STRING) {
1202 name = dmalloc (strlen (val) + 1, MDL);
1203 if (!name)
1204 log_fatal ("failover peer name %s: no memory",
1205 name);
1206 strcpy (name, val);
1207 } else {
1208 parse_warn (cfile, "expecting failover peer name.");
1209 skip_to_semi (cfile);
1210 return;
1211 }
1212
1213 /* See if there's a peer declaration by this name. */
1214 state = (dhcp_failover_state_t *)0;
20916cae 1215 find_failover_peer (&state, name, MDL);
a4ba3160
TL
1216 if (!state) {
1217 parse_warn (cfile, "unknown failover peer: %s", name);
1218 skip_to_semi (cfile);
1219 return;
1220 }
1221
b3519f23 1222 token = next_token (&val, (unsigned *)0, cfile);
a4ba3160
TL
1223 if (token != STATE) {
1224 parse_warn (cfile, "expecting 'state'");
1225 if (token != SEMI)
1226 skip_to_semi (cfile);
1227 return;
1228 }
20916cae
TL
1229 } else {
1230 state = (dhcp_failover_state_t *)0;
1231 dhcp_failover_state_reference (&state, peer, MDL);
1232 }
b3519f23 1233 token = next_token (&val, (unsigned *)0, cfile);
a4ba3160
TL
1234 if (token != LBRACE) {
1235 parse_warn (cfile, "expecting left brace");
1236 if (token != SEMI)
1237 skip_to_semi (cfile);
20916cae 1238 dhcp_failover_state_dereference (&state, MDL);
a4ba3160
TL
1239 return;
1240 }
1241 do {
b3519f23 1242 token = next_token (&val, (unsigned *)0, cfile);
a4ba3160
TL
1243 switch (token) {
1244 case RBRACE:
1245 break;
1246 case MY:
05815916
TL
1247 cp = &state -> me;
1248 do_state:
b3519f23 1249 token = next_token (&val, (unsigned *)0, cfile);
a4ba3160
TL
1250 if (token != STATE) {
1251 parse_warn (cfile, "expecting 'state'");
20916cae 1252 goto bogus;
a4ba3160
TL
1253 }
1254 parse_failover_state (cfile,
05815916 1255 &cp -> state, &cp -> stos);
a4ba3160 1256 break;
05815916 1257
a4ba3160 1258 case PARTNER:
05815916
TL
1259 cp = &state -> partner;
1260 goto do_state;
1261
d758ad8c
TL
1262 case MCLT:
1263 if (state -> i_am == primary) {
1264 parse_warn (cfile,
1265 "mclt not valid for primary");
1266 goto bogus;
1267 }
1268 token = next_token (&val, (unsigned *)0, cfile);
1269 if (token != NUMBER) {
1270 parse_warn (cfile, "expecting a number.");
1271 goto bogus;
1272 }
1273 state -> mclt = atoi (val);
1274 parse_semi (cfile);
1275 break;
1276
a4ba3160
TL
1277 default:
1278 parse_warn (cfile, "expecting state setting.");
d758ad8c 1279 bogus:
20916cae
TL
1280 skip_to_rbrace (cfile, 1);
1281 dhcp_failover_state_dereference (&state, MDL);
a4ba3160
TL
1282 return;
1283 }
1284 } while (token != RBRACE);
20916cae 1285 dhcp_failover_state_dereference (&state, MDL);
a4ba3160
TL
1286}
1287
9e9b2261 1288void parse_failover_state (cfile, state, stos)
35454d8a 1289 struct parse *cfile;
9e9b2261
TL
1290 enum failover_state *state;
1291 TIME *stos;
763adef1
TL
1292{
1293 enum dhcp_token token;
b1b7b521 1294 const char *val;
9e9b2261
TL
1295 enum failover_state state_in;
1296 TIME stos_in;
763adef1 1297
b3519f23 1298 token = next_token (&val, (unsigned *)0, cfile);
763adef1 1299 switch (token) {
05815916
TL
1300 case UNKNOWN_STATE:
1301 state_in = unknown_state;
1302 break;
1303
763adef1 1304 case PARTNER_DOWN:
9e9b2261
TL
1305 state_in = partner_down;
1306 break;
1307
763adef1 1308 case NORMAL:
9e9b2261
TL
1309 state_in = normal;
1310 break;
1311
763adef1 1312 case COMMUNICATIONS_INTERRUPTED:
9e9b2261
TL
1313 state_in = communications_interrupted;
1314 break;
1315
792156a9
DH
1316 case CONFLICT_DONE:
1317 state_in = conflict_done;
1318 break;
1319
9a092d2e
TL
1320 case RESOLUTION_INTERRUPTED:
1321 state_in = resolution_interrupted;
a4ba3160
TL
1322 break;
1323
05815916
TL
1324 case POTENTIAL_CONFLICT:
1325 state_in = potential_conflict;
1326 break;
1327
763adef1 1328 case RECOVER:
9e9b2261
TL
1329 state_in = recover;
1330 break;
a4ba3160 1331
3417f5cf
TL
1332 case RECOVER_WAIT:
1333 state_in = recover_wait;
1334 break;
1335
05815916
TL
1336 case RECOVER_DONE:
1337 state_in = recover_done;
1338 break;
1339
1340 case SHUTDOWN:
1341 state_in = shut_down;
1342 break;
1343
1344 case PAUSED:
1345 state_in = paused;
1346 break;
1347
1348 case STARTUP:
1349 state_in = startup;
a4ba3160 1350 break;
9e9b2261 1351
763adef1 1352 default:
35454d8a 1353 parse_warn (cfile, "unknown failover state");
9e9b2261
TL
1354 skip_to_semi (cfile);
1355 return;
763adef1 1356 }
9e9b2261 1357
b3519f23 1358 token = next_token (&val, (unsigned *)0, cfile);
6f8a0361
TL
1359 if (token == SEMI) {
1360 stos_in = cur_time;
1361 } else {
1362 if (token != AT) {
1363 parse_warn (cfile, "expecting \"at\"");
1364 skip_to_semi (cfile);
1365 return;
1366 }
1367
1368 stos_in = parse_date (cfile);
1369 if (!stos_in)
1370 return;
9e9b2261
TL
1371 }
1372
6f8a0361
TL
1373 /* Now that we've apparently gotten a clean parse, we
1374 can trust that this is a state that was fully committed to
1375 disk, so we can install it. */
9e9b2261
TL
1376 *stos = stos_in;
1377 *state = state_in;
763adef1
TL
1378}
1379#endif /* defined (FAILOVER_PROTOCOL) */
1380
98311e4b
DH
1381/* Permit_list_match returns 1 if every element of the permit list in lhs
1382 also appears in rhs. Note that this doesn't by itself mean that the
1383 two lists are equal - to check for equality, permit_list_match has to
1384 return 1 with (list1, list2) and with (list2, list1). */
1385
1386int permit_list_match (struct permit *lhs, struct permit *rhs)
1387{
1388 struct permit *plp, *prp;
1389 int matched;
1390
1391 if (!lhs)
1392 return 1;
1393 if (!rhs)
1394 return 0;
1395 for (plp = lhs; plp; plp = plp -> next) {
1396 matched = 0;
1397 for (prp = rhs; prp; prp = prp -> next) {
1398 if (prp -> type == plp -> type &&
1399 (prp -> type != permit_class ||
1400 prp -> class == plp -> class)) {
1401 matched = 1;
1402 break;
1403 }
1404 }
1405 if (!matched)
1406 return 0;
1407 }
1408 return 1;
1409}
1410
f63b4929 1411void parse_pool_statement (cfile, group, type)
35454d8a 1412 struct parse *cfile;
f63b4929
TL
1413 struct group *group;
1414 int type;
1415{
1416 enum dhcp_token token;
b1b7b521 1417 const char *val;
f63b4929 1418 int done = 0;
98311e4b 1419 struct pool *pool, **p, *pp;
f63b4929
TL
1420 struct permit *permit;
1421 struct permit **permit_head;
74f45f96 1422 int declaration = 0;
e9623235 1423 isc_result_t status;
98311e4b 1424 struct lease *lpchain = (struct lease *)0, *lp;
b1d3778c
DH
1425 TIME t;
1426 int is_allow = 0;
f63b4929 1427
20916cae
TL
1428 pool = (struct pool *)0;
1429 status = pool_allocate (&pool, MDL);
1430 if (status != ISC_R_SUCCESS)
6ceb9118
TL
1431 log_fatal ("no memory for pool: %s",
1432 isc_result_totext (status));
f63b4929 1433
9e9b2261 1434 if (type == SUBNET_DECL)
20916cae
TL
1435 shared_network_reference (&pool -> shared_network,
1436 group -> subnet -> shared_network,
1437 MDL);
75eaa6ff 1438 else if (type == SHARED_NET_DECL)
20916cae
TL
1439 shared_network_reference (&pool -> shared_network,
1440 group -> shared_network, MDL);
75eaa6ff
EH
1441 else {
1442 parse_warn(cfile, "Dynamic pools are only valid inside "
1443 "subnet or shared-network statements.");
1444 skip_to_semi(cfile);
1445 return;
1446 }
9e9b2261 1447
75eaa6ff
EH
1448 if (pool->shared_network == NULL ||
1449 !clone_group(&pool->group, pool->shared_network->group, MDL))
1450 log_fatal("can't clone pool group.");
98311e4b 1451
22009f79 1452#if defined (FAILOVER_PROTOCOL)
9e9b2261
TL
1453 /* Inherit the failover peer from the shared network. */
1454 if (pool -> shared_network -> failover_peer)
20916cae
TL
1455 dhcp_failover_state_reference
1456 (&pool -> failover_peer,
1457 pool -> shared_network -> failover_peer, MDL);
22009f79 1458#endif
9e9b2261 1459
20916cae
TL
1460 if (!parse_lbrace (cfile)) {
1461 pool_dereference (&pool, MDL);
f63b4929 1462 return;
20916cae
TL
1463 }
1464
f63b4929 1465 do {
b3519f23 1466 token = peek_token (&val, (unsigned *)0, cfile);
e5e41be4 1467 switch (token) {
8da06bb1 1468 case TOKEN_NO:
b3519f23
TL
1469 next_token (&val, (unsigned *)0, cfile);
1470 token = next_token (&val, (unsigned *)0, cfile);
9e9b2261 1471 if (token != FAILOVER ||
b3519f23
TL
1472 (token = next_token (&val, (unsigned *)0,
1473 cfile)) != PEER) {
9e9b2261
TL
1474 parse_warn (cfile,
1475 "expecting \"failover peer\".");
1476 skip_to_semi (cfile);
1477 continue;
1478 }
22009f79 1479#if defined (FAILOVER_PROTOCOL)
9e9b2261 1480 if (pool -> failover_peer)
20916cae
TL
1481 dhcp_failover_state_dereference
1482 (&pool -> failover_peer, MDL);
22009f79 1483#endif
9e9b2261
TL
1484 break;
1485
a4ba3160 1486#if defined (FAILOVER_PROTOCOL)
e9623235 1487 case FAILOVER:
b3519f23
TL
1488 next_token (&val, (unsigned *)0, cfile);
1489 token = next_token (&val, (unsigned *)0, cfile);
e9623235
TL
1490 if (token != PEER) {
1491 parse_warn (cfile, "expecting 'peer'.");
1492 skip_to_semi (cfile);
1493 break;
1494 }
b3519f23 1495 token = next_token (&val, (unsigned *)0, cfile);
e9623235
TL
1496 if (token != STRING) {
1497 parse_warn (cfile, "expecting string.");
1498 skip_to_semi (cfile);
1499 break;
1500 }
1501 if (pool -> failover_peer)
20916cae
TL
1502 dhcp_failover_state_dereference
1503 (&pool -> failover_peer, MDL);
e9623235 1504 status = find_failover_peer (&pool -> failover_peer,
20916cae 1505 val, MDL);
e9623235
TL
1506 if (status != ISC_R_SUCCESS)
1507 parse_warn (cfile,
1508 "failover peer %s: %s", val,
1509 isc_result_totext (status));
a609e69b
TL
1510 else
1511 pool -> failover_peer -> pool_count++;
e9623235
TL
1512 parse_semi (cfile);
1513 break;
a4ba3160 1514#endif
e9623235 1515
f63b4929 1516 case RANGE:
b3519f23 1517 next_token (&val, (unsigned *)0, cfile);
98311e4b
DH
1518 parse_address_range (cfile, group, type,
1519 pool, &lpchain);
f63b4929
TL
1520 break;
1521 case ALLOW:
1522 permit_head = &pool -> permit_list;
b1d3778c
DH
1523 /* remember the clause which leads to get_permit */
1524 is_allow = 1;
f63b4929 1525 get_permit:
436f1c8c 1526 permit = new_permit (MDL);
f63b4929 1527 if (!permit)
8ae2d595 1528 log_fatal ("no memory for permit");
b3519f23
TL
1529 next_token (&val, (unsigned *)0, cfile);
1530 token = next_token (&val, (unsigned *)0, cfile);
f63b4929
TL
1531 switch (token) {
1532 case UNKNOWN:
1533 permit -> type = permit_unknown_clients;
1534 get_clients:
b3519f23
TL
1535 if (next_token (&val, (unsigned *)0,
1536 cfile) != CLIENTS) {
35454d8a
TL
1537 parse_warn (cfile,
1538 "expecting \"clients\"");
f63b4929 1539 skip_to_semi (cfile);
436f1c8c 1540 free_permit (permit, MDL);
f63b4929
TL
1541 continue;
1542 }
1543 break;
1544
98311e4b
DH
1545 case KNOWN_CLIENTS:
1546 permit -> type = permit_known_clients;
1547 break;
1548
ad1a6484
TL
1549 case UNKNOWN_CLIENTS:
1550 permit -> type = permit_unknown_clients;
1551 break;
1552
f63b4929
TL
1553 case KNOWN:
1554 permit -> type = permit_known_clients;
1555 goto get_clients;
1556
1557 case AUTHENTICATED:
1558 permit -> type = permit_authenticated_clients;
1559 goto get_clients;
1560
1561 case UNAUTHENTICATED:
1562 permit -> type =
1563 permit_unauthenticated_clients;
1564 goto get_clients;
1565
1566 case ALL:
1567 permit -> type = permit_all_clients;
1568 goto get_clients;
1569 break;
1570
1571 case DYNAMIC:
1572 permit -> type = permit_dynamic_bootp_clients;
b3519f23
TL
1573 if (next_token (&val, (unsigned *)0,
1574 cfile) != TOKEN_BOOTP) {
35454d8a
TL
1575 parse_warn (cfile,
1576 "expecting \"bootp\"");
f63b4929 1577 skip_to_semi (cfile);
436f1c8c 1578 free_permit (permit, MDL);
f63b4929
TL
1579 continue;
1580 }
1581 goto get_clients;
1582
1583 case MEMBERS:
b3519f23
TL
1584 if (next_token (&val, (unsigned *)0,
1585 cfile) != OF) {
35454d8a 1586 parse_warn (cfile, "expecting \"of\"");
f63b4929 1587 skip_to_semi (cfile);
436f1c8c 1588 free_permit (permit, MDL);
f63b4929
TL
1589 continue;
1590 }
b3519f23
TL
1591 if (next_token (&val, (unsigned *)0,
1592 cfile) != STRING) {
35454d8a
TL
1593 parse_warn (cfile,
1594 "expecting class name.");
f63b4929 1595 skip_to_semi (cfile);
436f1c8c 1596 free_permit (permit, MDL);
f63b4929
TL
1597 continue;
1598 }
1599 permit -> type = permit_class;
20916cae
TL
1600 permit -> class = (struct class *)0;
1601 find_class (&permit -> class, val, MDL);
f63b4929 1602 if (!permit -> class)
35454d8a
TL
1603 parse_warn (cfile,
1604 "no such class: %s", val);
e5e41be4
TL
1605 break;
1606
b1d3778c
DH
1607 case AFTER:
1608 if (pool->valid_from || pool->valid_until) {
1609 parse_warn(cfile,
1610 "duplicate \"after\" clause.");
1611 skip_to_semi(cfile);
1612 free_permit(permit, MDL);
1613 continue;
1614 }
1615 t = parse_date_core(cfile);
1616 permit->type = permit_after;
1617 permit->after = t;
1618 if (is_allow) {
1619 pool->valid_from = t;
1620 } else {
1621 pool->valid_until = t;
1622 }
1623 break;
1624
f63b4929 1625 default:
35454d8a 1626 parse_warn (cfile, "expecting permit type.");
f63b4929
TL
1627 skip_to_semi (cfile);
1628 break;
1629 }
1630 while (*permit_head)
1631 permit_head = &((*permit_head) -> next);
1632 *permit_head = permit;
74f45f96 1633 parse_semi (cfile);
f63b4929
TL
1634 break;
1635
1636 case DENY:
1637 permit_head = &pool -> prohibit_list;
b1d3778c
DH
1638 /* remember the clause which leads to get_permit */
1639 is_allow = 0;
f63b4929
TL
1640 goto get_permit;
1641
1642 case RBRACE:
b3519f23 1643 next_token (&val, (unsigned *)0, cfile);
f63b4929
TL
1644 done = 1;
1645 break;
1646
237f8d3a
SK
1647 case END_OF_FILE:
1648 /*
1649 * We can get to END_OF_FILE if, for instance,
1650 * the parse_statement() reads all available tokens
1651 * and leaves us at the end.
1652 */
2914245e 1653 parse_warn(cfile, "unexpected end of file");
237f8d3a
SK
1654 goto cleanup;
1655
f63b4929 1656 default:
74f45f96
TL
1657 declaration = parse_statement (cfile, pool -> group,
1658 POOL_DECL,
1659 (struct host_decl *)0,
1660 declaration);
f63b4929
TL
1661 break;
1662 }
1663 } while (!done);
1664
98311e4b
DH
1665 /* See if there's already a pool into which we can merge this one. */
1666 for (pp = pool -> shared_network -> pools; pp; pp = pp -> next) {
98311e4b
DH
1667 if (pp -> group -> statements != pool -> group -> statements)
1668 continue;
1669#if defined (FAILOVER_PROTOCOL)
1670 if (pool -> failover_peer != pp -> failover_peer)
1671 continue;
1672#endif
1673 if (!permit_list_match (pp -> permit_list,
1674 pool -> permit_list) ||
1675 !permit_list_match (pool -> permit_list,
1676 pp -> permit_list) ||
1677 !permit_list_match (pp -> prohibit_list,
1678 pool -> prohibit_list) ||
1679 !permit_list_match (pool -> prohibit_list,
1680 pp -> prohibit_list))
1681 continue;
1682
1683 /* Okay, we can merge these two pools. All we have to
1684 do is fix up the leases, which all point to their pool. */
1685 for (lp = lpchain; lp; lp = lp -> next) {
1686 pool_dereference (&lp -> pool, MDL);
1687 pool_reference (&lp -> pool, pp, MDL);
1688 }
1689 break;
1690 }
1691
1692 /* If we didn't succeed in merging this pool into another, put
1693 it on the list. */
1694 if (!pp) {
1695 p = &pool -> shared_network -> pools;
1696 for (; *p; p = &((*p) -> next))
1697 ;
1698 pool_reference (p, pool, MDL);
1699 }
1700
1701 /* Don't allow a pool declaration with no addresses, since it is
1702 probably a configuration error. */
1703 if (!lpchain) {
1704 parse_warn (cfile, "Pool declaration with no address range.");
1705 log_error ("Pool declarations must always contain at least");
1706 log_error ("one range statement.");
1707 }
1708
237f8d3a 1709cleanup:
98311e4b
DH
1710 /* Dereference the lease chain. */
1711 lp = (struct lease *)0;
1712 while (lpchain) {
1713 lease_reference (&lp, lpchain, MDL);
1714 lease_dereference (&lpchain, MDL);
1715 if (lp -> next) {
1716 lease_reference (&lpchain, lp -> next, MDL);
1717 lease_dereference (&lp -> next, MDL);
1718 lease_dereference (&lp, MDL);
1719 }
1720 }
20916cae 1721 pool_dereference (&pool, MDL);
f63b4929
TL
1722}
1723
7dfc8ac2
TL
1724/* Expect a left brace; if there isn't one, skip over the rest of the
1725 statement and return zero; otherwise, return 1. */
1726
1727int parse_lbrace (cfile)
35454d8a 1728 struct parse *cfile;
7dfc8ac2 1729{
6f8fb41f 1730 enum dhcp_token token;
b1b7b521 1731 const char *val;
7dfc8ac2 1732
b3519f23 1733 token = next_token (&val, (unsigned *)0, cfile);
7dfc8ac2 1734 if (token != LBRACE) {
35454d8a 1735 parse_warn (cfile, "expecting left brace.");
7dfc8ac2
TL
1736 skip_to_semi (cfile);
1737 return 0;
1738 }
1739 return 1;
d7837182
TL
1740}
1741
7dfc8ac2 1742
2d59f590 1743/* host-declaration :== hostname RBRACE parameters declarations LBRACE */
d7837182 1744
2d59f590 1745void parse_host_declaration (cfile, group)
35454d8a 1746 struct parse *cfile;
7dfc8ac2 1747 struct group *group;
d7837182 1748{
b1b7b521 1749 const char *val;
6f8fb41f 1750 enum dhcp_token token;
7dfc8ac2 1751 struct host_decl *host;
f3c3d674 1752 char *name;
2d59f590 1753 int declaration = 0;
612fded7 1754 int dynamicp = 0;
ff129930 1755 int deleted = 0;
92ce3f81 1756 isc_result_t status;
98bd7ca0
DH
1757 int known;
1758 struct option *option;
b55d0d5f 1759 struct expression *expr = NULL;
7dfc8ac2 1760
20916cae 1761 name = parse_host_name (cfile);
6c5223f5
TL
1762 if (!name) {
1763 parse_warn (cfile, "expecting a name for host declaration.");
1764 skip_to_semi (cfile);
20916cae 1765 return;
6c5223f5 1766 }
7dfc8ac2 1767
20916cae
TL
1768 host = (struct host_decl *)0;
1769 status = host_allocate (&host, MDL);
1770 if (status != ISC_R_SUCCESS)
1771 log_fatal ("can't allocate host decl struct %s: %s",
1772 name, isc_result_totext (status));
7dfc8ac2 1773 host -> name = name;
f84d544b
TL
1774 if (!clone_group (&host -> group, group, MDL)) {
1775 log_fatal ("can't clone group for host %s", name);
20916cae
TL
1776 boom:
1777 host_dereference (&host, MDL);
1778 return;
1779 }
7dfc8ac2
TL
1780
1781 if (!parse_lbrace (cfile))
20916cae 1782 goto boom;
d7837182 1783
d7837182 1784 do {
b3519f23 1785 token = peek_token (&val, (unsigned *)0, cfile);
7dfc8ac2 1786 if (token == RBRACE) {
b3519f23 1787 token = next_token (&val, (unsigned *)0, cfile);
d7837182
TL
1788 break;
1789 }
0b69dcc8 1790 if (token == END_OF_FILE) {
b3519f23 1791 token = next_token (&val, (unsigned *)0, cfile);
35454d8a 1792 parse_warn (cfile, "unexpected end of file");
5376e3e9
TL
1793 break;
1794 }
612fded7
TL
1795 /* If the host declaration was created by the server,
1796 remember to save it. */
1797 if (token == DYNAMIC) {
1798 dynamicp = 1;
b3519f23 1799 token = next_token (&val, (unsigned *)0, cfile);
612fded7
TL
1800 if (!parse_semi (cfile))
1801 break;
1802 continue;
1803 }
ff129930
TL
1804 /* If the host declaration was created by the server,
1805 remember to save it. */
007e3ee4 1806 if (token == TOKEN_DELETED) {
ff129930 1807 deleted = 1;
b3519f23 1808 token = next_token (&val, (unsigned *)0, cfile);
ff129930
TL
1809 if (!parse_semi (cfile))
1810 break;
1811 continue;
1812 }
29c35bed
TL
1813
1814 if (token == GROUP) {
1815 struct group_object *go;
b3519f23
TL
1816 token = next_token (&val, (unsigned *)0, cfile);
1817 token = next_token (&val, (unsigned *)0, cfile);
29c35bed 1818 if (token != STRING && !is_identifier (token)) {
35454d8a
TL
1819 parse_warn (cfile,
1820 "expecting string or identifier.");
29c35bed
TL
1821 skip_to_rbrace (cfile, 1);
1822 break;
1823 }
20916cae
TL
1824 go = (struct group_object *)0;
1825 if (!group_hash_lookup (&go, group_name_hash,
1826 val, strlen (val), MDL)) {
35454d8a
TL
1827 parse_warn (cfile, "unknown group %s in host %s",
1828 val, host -> name);
29c35bed
TL
1829 } else {
1830 if (host -> named_group)
20916cae
TL
1831 group_object_dereference
1832 (&host -> named_group, MDL);
1833 group_object_reference (&host -> named_group,
1834 go, MDL);
1835 group_object_dereference (&go, MDL);
29c35bed
TL
1836 }
1837 if (!parse_semi (cfile))
1838 break;
1839 continue;
1840 }
1841
1842 if (token == UID) {
b1b7b521 1843 const char *s;
29c35bed 1844 unsigned char *t = 0;
b1b7b521 1845 unsigned len;
29c35bed 1846
b3519f23 1847 token = next_token (&val, (unsigned *)0, cfile);
436f1c8c 1848 data_string_forget (&host -> client_identifier, MDL);
29c35bed 1849
2178df03
DH
1850 if (host->client_identifier.len != 0) {
1851 parse_warn(cfile, "Host %s already has a "
1852 "client identifier.",
1853 host->name);
1854 break;
1855 }
1856
29c35bed 1857 /* See if it's a string or a cshl. */
b3519f23 1858 token = peek_token (&val, (unsigned *)0, cfile);
29c35bed 1859 if (token == STRING) {
b3519f23 1860 token = next_token (&val, &len, cfile);
29c35bed 1861 s = val;
29c35bed
TL
1862 host -> client_identifier.terminated = 1;
1863 } else {
1864 len = 0;
1865 t = parse_numeric_aggregate
1866 (cfile,
1867 (unsigned char *)0, &len, ':', 16, 8);
1868 if (!t) {
35454d8a
TL
1869 parse_warn (cfile,
1870 "expecting hex list.");
29c35bed
TL
1871 skip_to_semi (cfile);
1872 }
b1b7b521 1873 s = (const char *)t;
29c35bed
TL
1874 }
1875 if (!buffer_allocate
1876 (&host -> client_identifier.buffer,
436f1c8c 1877 len + host -> client_identifier.terminated, MDL))
29c35bed
TL
1878 log_fatal ("no memory for uid for host %s.",
1879 host -> name);
1880 host -> client_identifier.data =
1881 host -> client_identifier.buffer -> data;
1882 host -> client_identifier.len = len;
b1b7b521 1883 memcpy (host -> client_identifier.buffer -> data, s,
29c35bed
TL
1884 len + host -> client_identifier.terminated);
1885 if (t)
436f1c8c 1886 dfree (t, MDL);
29c35bed
TL
1887
1888 if (!parse_semi (cfile))
1889 break;
1890 continue;
1891 }
b55d0d5f 1892
98bd7ca0
DH
1893 if (token == HOST_IDENTIFIER) {
1894 if (host->host_id_option != NULL) {
1895 parse_warn(cfile,
1896 "only one host-identifier allowed "
1897 "per host");
1898 skip_to_rbrace(cfile, 1);
1899 break;
1900 }
1901 next_token(&val, NULL, cfile);
1902 token = next_token(&val, NULL, cfile);
1903 if (token != OPTION) {
1904 parse_warn(cfile,
20ae1aff 1905 "host-identifier must be an option");
98bd7ca0
DH
1906 skip_to_rbrace(cfile, 1);
1907 break;
1908 }
1909 known = 0;
1910 option = NULL;
1911 status = parse_option_name(cfile, 1, &known, &option);
1912 if ((status != ISC_R_SUCCESS) || (option == NULL)) {
1913 break;
1914 }
1915 if (!known) {
1916 parse_warn(cfile, "unknown option %s.%s",
1917 option->universe->name,
1918 option->name);
1919 skip_to_rbrace(cfile, 1);
1920 break;
1921 }
1922
b55d0d5f
EH
1923 if (! parse_option_data(&expr, cfile, 1, option)) {
1924 skip_to_rbrace(cfile, 1);
1925 option_dereference(&option, MDL);
1926 break;
1927 }
1928
98bd7ca0
DH
1929 if (!parse_semi(cfile)) {
1930 skip_to_rbrace(cfile, 1);
1931 expression_dereference(&expr, MDL);
1932 option_dereference(&option, MDL);
1933 break;
1934 }
1935
1936 option_reference(&host->host_id_option, option, MDL);
1937 option_dereference(&option, MDL);
1938 data_string_copy(&host->host_id,
1939 &expr->data.const_data, MDL);
1940 expression_dereference(&expr, MDL);
1941 continue;
1942 }
1943
b55d0d5f
EH
1944 declaration = parse_statement(cfile, host->group, HOST_DECL,
1945 host, declaration);
d7837182 1946 } while (1);
7dfc8ac2 1947
ff129930 1948 if (deleted) {
20916cae
TL
1949 struct host_decl *hp = (struct host_decl *)0;
1950 if (host_hash_lookup (&hp, host_name_hash,
1951 (unsigned char *)host -> name,
1952 strlen (host -> name), MDL)) {
ff129930 1953 delete_host (hp, 0);
20916cae 1954 host_dereference (&hp, MDL);
ff129930 1955 }
ff129930 1956 } else {
29c35bed
TL
1957 if (host -> named_group && host -> named_group -> group) {
1958 if (host -> group -> statements ||
1959 (host -> group -> authoritative !=
b83bf1d1
TL
1960 host -> named_group -> group -> authoritative)) {
1961 if (host -> group -> next)
1962 group_dereference (&host -> group -> next,
1963 MDL);
20916cae
TL
1964 group_reference (&host -> group -> next,
1965 host -> named_group -> group,
1966 MDL);
b83bf1d1 1967 } else {
20916cae
TL
1968 group_dereference (&host -> group, MDL);
1969 group_reference (&host -> group,
1970 host -> named_group -> group,
1971 MDL);
29c35bed
TL
1972 }
1973 }
1974
b86799bf
TL
1975 if (dynamicp)
1976 host -> flags |= HOST_DECL_DYNAMIC;
1977 else
1978 host -> flags |= HOST_DECL_STATIC;
1979
92ce3f81
TL
1980 status = enter_host (host, dynamicp, 0);
1981 if (status != ISC_R_SUCCESS)
ab58ff49
TL
1982 parse_warn (cfile, "host %s: %s", host -> name,
1983 isc_result_totext (status));
ff129930 1984 }
20916cae 1985 host_dereference (&host, MDL);
d7837182
TL
1986}
1987
2d59f590 1988/* class-declaration :== STRING LBRACE parameters declarations RBRACE
24a75c03
TL
1989*/
1990
20916cae
TL
1991int parse_class_declaration (cp, cfile, group, type)
1992 struct class **cp;
35454d8a 1993 struct parse *cfile;
7dfc8ac2 1994 struct group *group;
24a75c03
TL
1995 int type;
1996{
b1b7b521 1997 const char *val;
6f8fb41f 1998 enum dhcp_token token;
20916cae 1999 struct class *class = (struct class *)0, *pc = (struct class *)0;
f4d0f440 2000 int declaration = 0;
e5e41be4 2001 int lose = 0;
ece6ea33 2002 struct data_string data;
d758ad8c
TL
2003 char *name;
2004 const char *tname;
ece6ea33 2005 struct executable_statement *stmt = (struct executable_statement *)0;
de94ca72 2006 int new = 1;
98311e4b 2007 isc_result_t status = ISC_R_FAILURE;
06e77c34
DH
2008 int matchedonce = 0;
2009 int submatchedonce = 0;
f7fdb216 2010 unsigned code;
24a75c03 2011
7d6180be
DH
2012 if (dhcpv6_class_once && local_family == AF_INET6) {
2013 dhcpv6_class_once = 0;
2014 log_error("WARNING: class declarations are not supported "
2015 "for DHCPv6.");
2016 }
2017
b3519f23 2018 token = next_token (&val, (unsigned *)0, cfile);
24a75c03 2019 if (token != STRING) {
35454d8a 2020 parse_warn (cfile, "Expecting class name");
24a75c03 2021 skip_to_semi (cfile);
20916cae 2022 return 0;
24a75c03
TL
2023 }
2024
ece6ea33 2025 /* See if there's already a class with the specified name. */
20916cae 2026 find_class (&pc, val, MDL);
ece6ea33 2027
06e77c34
DH
2028 /* If it is a class, we're updating it. If it's any of the other
2029 * types (subclass, vendor or user class), the named class is a
2030 * reference to the parent class so its mandatory.
2031 */
2032 if (pc && (type == CLASS_TYPE_CLASS)) {
2033 class_reference(&class, pc, MDL);
de94ca72 2034 new = 0;
06e77c34
DH
2035 class_dereference(&pc, MDL);
2036 } else if (!pc && (type != CLASS_TYPE_CLASS)) {
2037 parse_warn(cfile, "no class named %s", val);
2038 skip_to_semi(cfile);
20916cae 2039 return 0;
ece6ea33
TL
2040 }
2041
2042 /* The old vendor-class and user-class declarations had an implicit
2043 match. We don't do the implicit match anymore. Instead, for
2044 backward compatibility, we have an implicit-vendor-class and an
2045 implicit-user-class. vendor-class and user-class declarations
2046 are turned into subclasses of the implicit classes, and the
8b500185 2047 submatch expression of the implicit classes extracts the contents of
ece6ea33 2048 the vendor class or user class. */
06e77c34 2049 if ((type == CLASS_TYPE_VENDOR) || (type == CLASS_TYPE_USER)) {
ece6ea33 2050 data.len = strlen (val);
6f8fb41f 2051 data.buffer = (struct buffer *)0;
436f1c8c 2052 if (!buffer_allocate (&data.buffer, data.len + 1, MDL))
20916cae 2053 log_fatal ("no memory for class name.");
6f8fb41f 2054 data.data = &data.buffer -> data [0];
ece6ea33
TL
2055 data.terminated = 1;
2056
d758ad8c 2057 tname = type ? "implicit-vendor-class" : "implicit-user-class";
06e77c34 2058 } else if (type == CLASS_TYPE_CLASS) {
d758ad8c 2059 tname = val;
20916cae 2060 } else {
d758ad8c 2061 tname = (const char *)0;
20916cae
TL
2062 }
2063
d758ad8c
TL
2064 if (tname) {
2065 name = dmalloc (strlen (tname) + 1, MDL);
2066 if (!name)
2067 log_fatal ("No memory for class name %s.", tname);
2068 strcpy (name, val);
2069 } else
2070 name = (char *)0;
ece6ea33
TL
2071
2072 /* If this is a straight subclass, parse the hash string. */
06e77c34 2073 if (type == CLASS_TYPE_SUBCLASS) {
b3519f23 2074 token = peek_token (&val, (unsigned *)0, cfile);
ece6ea33 2075 if (token == STRING) {
b3519f23 2076 token = next_token (&val, &data.len, cfile);
6f8fb41f 2077 data.buffer = (struct buffer *)0;
20916cae
TL
2078 if (!buffer_allocate (&data.buffer,
2079 data.len + 1, MDL)) {
2080 if (pc)
2081 class_dereference (&pc, MDL);
2082
2083 return 0;
2084 }
ece6ea33 2085 data.terminated = 1;
6f8fb41f 2086 data.data = &data.buffer -> data [0];
b3519f23
TL
2087 memcpy ((char *)data.buffer -> data, val,
2088 data.len + 1);
ece6ea33 2089 } else if (token == NUMBER_OR_NAME || token == NUMBER) {
6f8fb41f 2090 memset (&data, 0, sizeof data);
20916cae 2091 if (!parse_cshl (&data, cfile)) {
06e77c34
DH
2092 if (pc)
2093 class_dereference (&pc, MDL);
20916cae 2094 return 0;
b19f2e1c 2095 }
e68de775 2096 } else {
35454d8a 2097 parse_warn (cfile, "Expecting string or hex list.");
d758ad8c
TL
2098 if (pc)
2099 class_dereference (&pc, MDL);
20916cae 2100 return 0;
ece6ea33
TL
2101 }
2102 }
2103
2104 /* See if there's already a class in the hash table matching the
2105 hash data. */
06e77c34 2106 if (type != CLASS_TYPE_CLASS)
20916cae
TL
2107 class_hash_lookup (&class, pc -> hash,
2108 (const char *)data.data, data.len, MDL);
ece6ea33
TL
2109
2110 /* If we didn't find an existing class, allocate a new one. */
2111 if (!class) {
2112 /* Allocate the class structure... */
20916cae 2113 status = class_allocate (&class, MDL);
ece6ea33 2114 if (pc) {
20916cae
TL
2115 group_reference (&class -> group, pc -> group, MDL);
2116 class_reference (&class -> superclass, pc, MDL);
88dcab62
TL
2117 class -> lease_limit = pc -> lease_limit;
2118 if (class -> lease_limit) {
2119 class -> billed_leases =
2120 dmalloc (class -> lease_limit *
436f1c8c 2121 sizeof (struct lease *), MDL);
88dcab62 2122 if (!class -> billed_leases)
e68de775 2123 log_fatal ("no memory for billing");
88dcab62
TL
2124 memset (class -> billed_leases, 0,
2125 (class -> lease_limit *
2126 sizeof class -> billed_leases));
2127 }
436f1c8c 2128 data_string_copy (&class -> hash_string, &data, MDL);
98311e4b 2129 if (!pc -> hash &&
f7fdb216 2130 !class_new_hash (&pc->hash, SCLASS_HASH_SIZE, MDL))
98311e4b
DH
2131 log_fatal ("No memory for subclass hash.");
2132 class_hash_add (pc -> hash,
2133 (const char *)class -> hash_string.data,
2134 class -> hash_string.len,
2135 (void *)class, MDL);
ece6ea33 2136 } else {
06e77c34
DH
2137 if (class->group)
2138 group_dereference(&class->group, MDL);
20916cae
TL
2139 if (!clone_group (&class -> group, group, MDL))
2140 log_fatal ("no memory to clone class group.");
ece6ea33
TL
2141 }
2142
2143 /* If this is an implicit vendor or user class, add a
2144 statement that causes the vendor or user class ID to
2145 be sent back in the reply. */
06e77c34 2146 if (type == CLASS_TYPE_VENDOR || type == CLASS_TYPE_USER) {
20916cae
TL
2147 stmt = (struct executable_statement *)0;
2148 if (!executable_statement_allocate (&stmt, MDL))
8ae2d595 2149 log_fatal ("no memory for class statement.");
ece6ea33 2150 stmt -> op = supersede_option_statement;
6f8fb41f 2151 if (option_cache_allocate (&stmt -> data.option,
436f1c8c 2152 MDL)) {
6f8fb41f 2153 stmt -> data.option -> data = data;
f7fdb216 2154 code = (type == CLASS_TYPE_VENDOR)
ca3a51a5 2155 ? DHO_VENDOR_CLASS_IDENTIFIER
f7fdb216
DH
2156 : DHO_USER_CLASS;
2157 option_code_hash_lookup(
2158 &stmt->data.option->option,
2159 dhcp_universe.code_hash,
2160 &code, 0, MDL);
6f8fb41f 2161 }
ece6ea33
TL
2162 class -> statements = stmt;
2163 }
de94ca72
TL
2164
2165 /* Save the name, if there is one. */
06e77c34
DH
2166 if (class->name != NULL)
2167 dfree(class->name, MDL);
2168 class->name = name;
ece6ea33 2169 }
7dfc8ac2 2170
06e77c34
DH
2171 if (type != CLASS_TYPE_CLASS)
2172 data_string_forget(&data, MDL);
88dcab62 2173
20916cae 2174 /* Spawned classes don't have to have their own settings. */
88dcab62 2175 if (class -> superclass) {
b3519f23 2176 token = peek_token (&val, (unsigned *)0, cfile);
e68de775 2177 if (token == SEMI) {
b3519f23 2178 next_token (&val, (unsigned *)0, cfile);
20916cae
TL
2179 if (cp)
2180 status = class_reference (cp, class, MDL);
2181 class_dereference (&class, MDL);
d758ad8c
TL
2182 if (pc)
2183 class_dereference (&pc, MDL);
20916cae 2184 return cp ? (status == ISC_R_SUCCESS) : 1;
e68de775
TL
2185 }
2186 /* Give the subclass its own group. */
f84d544b
TL
2187 if (!clone_group (&class -> group, class -> group, MDL))
2188 log_fatal ("can't clone class group.");
2189
88dcab62
TL
2190 }
2191
20916cae
TL
2192 if (!parse_lbrace (cfile)) {
2193 class_dereference (&class, MDL);
2194 if (pc)
2195 class_dereference (&pc, MDL);
2196 return 0;
2197 }
24a75c03
TL
2198
2199 do {
b3519f23 2200 token = peek_token (&val, (unsigned *)0, cfile);
7dfc8ac2 2201 if (token == RBRACE) {
b3519f23 2202 token = next_token (&val, (unsigned *)0, cfile);
24a75c03 2203 break;
0b69dcc8 2204 } else if (token == END_OF_FILE) {
b3519f23 2205 token = next_token (&val, (unsigned *)0, cfile);
35454d8a 2206 parse_warn (cfile, "unexpected end of file");
5376e3e9 2207 break;
899d754f 2208 } else if (token == DYNAMIC) {
06e77c34 2209 class->flags |= CLASS_DECL_DYNAMIC;
899d754f
JB
2210 token = next_token (&val, (unsigned *)0, cfile);
2211 if (!parse_semi (cfile))
2212 break;
2213 continue;
2214 } else if (token == TOKEN_DELETED) {
06e77c34 2215 class->flags |= CLASS_DECL_DELETED;
899d754f
JB
2216 token = next_token (&val, (unsigned *)0, cfile);
2217 if (!parse_semi (cfile))
2218 break;
2219 continue;
ece6ea33
TL
2220 } else if (token == MATCH) {
2221 if (pc) {
35454d8a
TL
2222 parse_warn (cfile,
2223 "invalid match in subclass.");
ece6ea33
TL
2224 skip_to_semi (cfile);
2225 break;
2226 }
98311e4b
DH
2227 token = next_token (&val, (unsigned *)0, cfile);
2228 token = peek_token (&val, (unsigned *)0, cfile);
2229 if (token != IF)
2230 goto submatch;
06e77c34
DH
2231 token = next_token (&val, (unsigned *)0, cfile);
2232 if (matchedonce) {
2233 parse_warn(cfile, "A class may only have "
2234 "one 'match if' clause.");
2235 skip_to_semi(cfile);
ece6ea33
TL
2236 break;
2237 }
06e77c34
DH
2238 matchedonce = 1;
2239 if (class->expr)
2240 expression_dereference(&class->expr, MDL);
2241 if (!parse_boolean_expression (&class->expr, cfile,
9e383163
TL
2242 &lose)) {
2243 if (!lose) {
2244 parse_warn (cfile,
2245 "expecting boolean expr.");
2246 skip_to_semi (cfile);
2247 }
2248 } else {
6f8fb41f 2249#if defined (DEBUG_EXPRESSION_PARSE)
9e383163
TL
2250 print_expression ("class match",
2251 class -> expr);
6f8fb41f 2252#endif
9e383163
TL
2253 parse_semi (cfile);
2254 }
ece6ea33 2255 } else if (token == SPAWN) {
06e77c34 2256 token = next_token (&val, (unsigned *)0, cfile);
ece6ea33 2257 if (pc) {
35454d8a
TL
2258 parse_warn (cfile,
2259 "invalid spawn in subclass.");
ece6ea33
TL
2260 skip_to_semi (cfile);
2261 break;
2262 }
b19f2e1c 2263 class -> spawning = 1;
b3519f23 2264 token = next_token (&val, (unsigned *)0, cfile);
ece6ea33 2265 if (token != WITH) {
35454d8a
TL
2266 parse_warn (cfile,
2267 "expecting with after spawn");
ece6ea33
TL
2268 skip_to_semi (cfile);
2269 break;
2270 }
06d3e394 2271 submatch:
06e77c34 2272 if (submatchedonce) {
35454d8a
TL
2273 parse_warn (cfile,
2274 "can't override existing %s.",
8b500185
TL
2275 "submatch/spawn");
2276 skip_to_semi (cfile);
2277 break;
2278 }
06e77c34
DH
2279 submatchedonce = 1;
2280 if (class->submatch)
2281 expression_dereference(&class->submatch, MDL);
9e383163
TL
2282 if (!parse_data_expression (&class -> submatch,
2283 cfile, &lose)) {
2284 if (!lose) {
2285 parse_warn (cfile,
2286 "expecting data expr.");
2287 skip_to_semi (cfile);
2288 }
2289 } else {
6f8fb41f 2290#if defined (DEBUG_EXPRESSION_PARSE)
9e383163
TL
2291 print_expression ("class submatch",
2292 class -> submatch);
6f8fb41f 2293#endif
9e383163
TL
2294 parse_semi (cfile);
2295 }
88dcab62 2296 } else if (token == LEASE) {
b3519f23
TL
2297 next_token (&val, (unsigned *)0, cfile);
2298 token = next_token (&val, (unsigned *)0, cfile);
88dcab62 2299 if (token != LIMIT) {
35454d8a 2300 parse_warn (cfile, "expecting \"limit\"");
88dcab62
TL
2301 if (token != SEMI)
2302 skip_to_semi (cfile);
2303 break;
2304 }
b3519f23 2305 token = next_token (&val, (unsigned *)0, cfile);
88dcab62 2306 if (token != NUMBER) {
35454d8a 2307 parse_warn (cfile, "expecting a number");
88dcab62
TL
2308 if (token != SEMI)
2309 skip_to_semi (cfile);
2310 break;
2311 }
2312 class -> lease_limit = atoi (val);
06e77c34
DH
2313 if (class->billed_leases)
2314 dfree(class->billed_leases, MDL);
88dcab62
TL
2315 class -> billed_leases =
2316 dmalloc (class -> lease_limit *
436f1c8c 2317 sizeof (struct lease *), MDL);
88dcab62 2318 if (!class -> billed_leases)
8ae2d595 2319 log_fatal ("no memory for billed leases.");
88dcab62
TL
2320 memset (class -> billed_leases, 0,
2321 (class -> lease_limit *
2322 sizeof class -> billed_leases));
2323 have_billing_classes = 1;
2324 parse_semi (cfile);
24a75c03 2325 } else {
2d59f590
TL
2326 declaration = parse_statement (cfile, class -> group,
2327 CLASS_DECL,
2328 (struct host_decl *)0,
2329 declaration);
24a75c03
TL
2330 }
2331 } while (1);
899d754f 2332
06e77c34
DH
2333 if (class->flags & CLASS_DECL_DELETED) {
2334 if (type == CLASS_TYPE_CLASS) {
2335 struct class *theclass = NULL;
899d754f 2336
06e77c34
DH
2337 status = find_class(&theclass, class->name, MDL);
2338 if (status == ISC_R_SUCCESS) {
2339 delete_class(theclass, 0);
2340 class_dereference(&theclass, MDL);
2341 }
2342 } else {
2343 class_hash_delete(pc->hash,
2344 (char *)class->hash_string.data,
2345 class->hash_string.len, MDL);
899d754f 2346 }
06e77c34 2347 } else if (type == CLASS_TYPE_CLASS && new) {
de94ca72 2348 if (!collections -> classes)
20916cae 2349 class_reference (&collections -> classes, class, MDL);
de94ca72 2350 else {
20916cae
TL
2351 struct class *c;
2352 for (c = collections -> classes;
2353 c -> nic; c = c -> nic)
de94ca72 2354 ;
20916cae 2355 class_reference (&c -> nic, class, MDL);
de94ca72
TL
2356 }
2357 }
06e77c34 2358
899d754f 2359 if (cp) /* should always be 0??? */
20916cae
TL
2360 status = class_reference (cp, class, MDL);
2361 class_dereference (&class, MDL);
2362 if (pc)
2363 class_dereference (&pc, MDL);
2364 return cp ? (status == ISC_R_SUCCESS) : 1;
24a75c03
TL
2365}
2366
2d59f590
TL
2367/* shared-network-declaration :==
2368 hostname LBRACE declarations parameters RBRACE */
1f814ff2 2369
2d59f590 2370void parse_shared_net_declaration (cfile, group)
35454d8a 2371 struct parse *cfile;
7dfc8ac2 2372 struct group *group;
1f814ff2 2373{
b1b7b521 2374 const char *val;
6f8fb41f 2375 enum dhcp_token token;
1f814ff2 2376 struct shared_network *share;
1f814ff2 2377 char *name;
2d59f590 2378 int declaration = 0;
20916cae 2379 isc_result_t status;
1f814ff2 2380
20916cae
TL
2381 share = (struct shared_network *)0;
2382 status = shared_network_allocate (&share, MDL);
2383 if (status != ISC_R_SUCCESS)
2384 log_fatal ("Can't allocate shared subnet: %s",
2385 isc_result_totext (status));
2386 clone_group (&share -> group, group, MDL);
2387 shared_network_reference (&share -> group -> shared_network,
2388 share, MDL);
1f814ff2
TL
2389
2390 /* Get the name of the shared network... */
b3519f23 2391 token = peek_token (&val, (unsigned *)0, cfile);
7dfc8ac2 2392 if (token == STRING) {
b3519f23 2393 token = next_token (&val, (unsigned *)0, cfile);
7dfc8ac2
TL
2394
2395 if (val [0] == 0) {
35454d8a 2396 parse_warn (cfile, "zero-length shared network name");
7dfc8ac2
TL
2397 val = "<no-name-given>";
2398 }
436f1c8c 2399 name = dmalloc (strlen (val) + 1, MDL);
7dfc8ac2 2400 if (!name)
8ae2d595 2401 log_fatal ("no memory for shared network name");
7dfc8ac2
TL
2402 strcpy (name, val);
2403 } else {
2404 name = parse_host_name (cfile);
20916cae 2405 if (!name) {
6c5223f5
TL
2406 parse_warn (cfile,
2407 "expecting a name for shared-network");
2408 skip_to_semi (cfile);
20916cae 2409 shared_network_dereference (&share, MDL);
7dfc8ac2 2410 return;
20916cae 2411 }
1f814ff2 2412 }
1f814ff2
TL
2413 share -> name = name;
2414
20916cae
TL
2415 if (!parse_lbrace (cfile)) {
2416 shared_network_dereference (&share, MDL);
7dfc8ac2 2417 return;
20916cae 2418 }
7dfc8ac2 2419
1f814ff2 2420 do {
b3519f23 2421 token = peek_token (&val, (unsigned *)0, cfile);
7dfc8ac2 2422 if (token == RBRACE) {
b3519f23 2423 token = next_token (&val, (unsigned *)0, cfile);
20916cae 2424 if (!share -> subnets)
4bd8800e
TL
2425 parse_warn (cfile,
2426 "empty shared-network decl");
20916cae
TL
2427 else
2428 enter_shared_network (share);
2429 shared_network_dereference (&share, MDL);
1f814ff2 2430 return;
0b69dcc8 2431 } else if (token == END_OF_FILE) {
b3519f23 2432 token = next_token (&val, (unsigned *)0, cfile);
35454d8a 2433 parse_warn (cfile, "unexpected end of file");
5376e3e9 2434 break;
79931db3 2435 } else if (token == INTERFACE) {
b3519f23
TL
2436 token = next_token (&val, (unsigned *)0, cfile);
2437 token = next_token (&val, (unsigned *)0, cfile);
79931db3
TL
2438 new_shared_network_interface (cfile, share, val);
2439 if (!parse_semi (cfile))
2440 break;
2441 continue;
1f814ff2 2442 }
5376e3e9 2443
2d59f590
TL
2444 declaration = parse_statement (cfile, share -> group,
2445 SHARED_NET_DECL,
2446 (struct host_decl *)0,
2447 declaration);
1f814ff2 2448 } while (1);
20916cae 2449 shared_network_dereference (&share, MDL);
1f814ff2
TL
2450}
2451
98bd7ca0
DH
2452
2453static int
2454common_subnet_parsing(struct parse *cfile,
2455 struct shared_network *share,
2456 struct subnet *subnet) {
2457 enum dhcp_token token;
2458 struct subnet *t, *u;
2459 const char *val;
2460 int declaration = 0;
2461
2462 enter_subnet(subnet);
2463
2464 if (!parse_lbrace(cfile)) {
2465 subnet_dereference(&subnet, MDL);
2466 return 0;
2467 }
2468
2469 do {
2470 token = peek_token(&val, NULL, cfile);
2471 if (token == RBRACE) {
2472 token = next_token(&val, NULL, cfile);
2473 break;
2474 } else if (token == END_OF_FILE) {
2475 token = next_token(&val, NULL, cfile);
2476 parse_warn (cfile, "unexpected end of file");
2477 break;
2478 } else if (token == INTERFACE) {
2479 token = next_token(&val, NULL, cfile);
2480 token = next_token(&val, NULL, cfile);
2481 new_shared_network_interface(cfile, share, val);
2482 if (!parse_semi(cfile))
2483 break;
2484 continue;
2485 }
2486 declaration = parse_statement(cfile, subnet->group,
2487 SUBNET_DECL,
2488 NULL,
2489 declaration);
2490 } while (1);
2491
2492 /* Add the subnet to the list of subnets in this shared net. */
2493 if (share->subnets == NULL) {
2494 subnet_reference(&share->subnets, subnet, MDL);
2495 } else {
2496 u = NULL;
2497 for (t = share->subnets; t->next_sibling; t = t->next_sibling) {
2498 if (subnet_inner_than(subnet, t, 0)) {
2499 subnet_reference(&subnet->next_sibling, t, MDL);
2500 if (u) {
2501 subnet_dereference(&u->next_sibling,
2502 MDL);
2503 subnet_reference(&u->next_sibling,
2504 subnet, MDL);
2505 } else {
2506 subnet_dereference(&share->subnets,
2507 MDL);
2508 subnet_reference(&share->subnets,
2509 subnet, MDL);
2510 }
2511 subnet_dereference(&subnet, MDL);
2512 return 1;
2513 }
2514 u = t;
2515 }
2516 subnet_reference(&t->next_sibling, subnet, MDL);
2517 }
2518 subnet_dereference(&subnet, MDL);
2519 return 1;
2520}
2521
2d59f590
TL
2522/* subnet-declaration :==
2523 net NETMASK netmask RBRACE parameters declarations LBRACE */
685963dc 2524
2d59f590 2525void parse_subnet_declaration (cfile, share)
35454d8a 2526 struct parse *cfile;
1f814ff2 2527 struct shared_network *share;
685963dc 2528{
b1b7b521 2529 const char *val;
6f8fb41f 2530 enum dhcp_token token;
28868515 2531 struct subnet *subnet;
7dfc8ac2 2532 struct iaddr iaddr;
685963dc 2533 unsigned char addr [4];
b1b7b521 2534 unsigned len = sizeof addr;
20916cae 2535 isc_result_t status;
685963dc 2536
20916cae
TL
2537 subnet = (struct subnet *)0;
2538 status = subnet_allocate (&subnet, MDL);
2539 if (status != ISC_R_SUCCESS)
2540 log_fatal ("Allocation of new subnet failed: %s",
2541 isc_result_totext (status));
2542 shared_network_reference (&subnet -> shared_network, share, MDL);
7d6180be
DH
2543
2544 /*
2545 * If our parent shared network was implicitly created by the software,
2546 * and not explicitly configured by the user, then we actually put all
2547 * configuration scope in the parent (the shared network and subnet
2548 * share the same {}-level scope).
2549 *
2550 * Otherwise, we clone the parent group and continue as normal.
2551 */
2552 if (share->flags & SHARED_IMPLICIT) {
2553 group_reference(&subnet->group, share->group, MDL);
2554 } else {
2555 if (!clone_group(&subnet->group, share->group, MDL)) {
2556 log_fatal("Allocation of group for new subnet failed.");
2557 }
2558 }
20916cae 2559 subnet_reference (&subnet -> group -> subnet, subnet, MDL);
685963dc
TL
2560
2561 /* Get the network number... */
20916cae
TL
2562 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) {
2563 subnet_dereference (&subnet, MDL);
7dfc8ac2 2564 return;
20916cae 2565 }
7dfc8ac2
TL
2566 memcpy (iaddr.iabuf, addr, len);
2567 iaddr.len = len;
2568 subnet -> net = iaddr;
685963dc 2569
b3519f23 2570 token = next_token (&val, (unsigned *)0, cfile);
685963dc 2571 if (token != NETMASK) {
35454d8a 2572 parse_warn (cfile, "Expecting netmask");
685963dc 2573 skip_to_semi (cfile);
7dfc8ac2 2574 return;
685963dc
TL
2575 }
2576
2577 /* Get the netmask... */
20916cae
TL
2578 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) {
2579 subnet_dereference (&subnet, MDL);
7dfc8ac2 2580 return;
20916cae 2581 }
7dfc8ac2
TL
2582 memcpy (iaddr.iabuf, addr, len);
2583 iaddr.len = len;
2584 subnet -> netmask = iaddr;
685963dc 2585
20916cae
TL
2586 /* Validate the network number/netmask pair. */
2587 if (host_addr (subnet -> net, subnet -> netmask)) {
98311e4b
DH
2588 char *maskstr;
2589
2590 maskstr = strdup (piaddr (subnet -> netmask));
20916cae 2591 parse_warn (cfile,
98311e4b
DH
2592 "subnet %s netmask %s: bad subnet number/mask combination.",
2593 piaddr (subnet -> net), maskstr);
2594 free(maskstr);
20916cae
TL
2595 subnet_dereference (&subnet, MDL);
2596 skip_to_semi (cfile);
2597 return;
2598 }
2599
98bd7ca0
DH
2600 common_subnet_parsing(cfile, share, subnet);
2601}
685963dc 2602
98bd7ca0
DH
2603/* subnet6-declaration :==
2604 net / bits RBRACE parameters declarations LBRACE */
2605
2606void
2607parse_subnet6_declaration(struct parse *cfile, struct shared_network *share) {
28868515
SK
2608#if !defined(DHCPv6)
2609 parse_warn(cfile, "No DHCPv6 support.");
2610 skip_to_semi(cfile);
2611#else /* defined(DHCPv6) */
98bd7ca0
DH
2612 struct subnet *subnet;
2613 isc_result_t status;
2614 enum dhcp_token token;
2615 const char *val;
2616 char *endp;
2617 int ofs;
2618 const static int mask[] = { 0x00, 0x80, 0xC0, 0xE0,
2619 0xF0, 0xF8, 0xFC, 0xFE };
2620 struct iaddr iaddr;
98bd7ca0 2621
771484ac
EH
2622 if (local_family != AF_INET6) {
2623 parse_warn(cfile, "subnet6 statement is only supported "
2624 "in DHCPv6 mode.");
2625 skip_to_semi(cfile);
2626 return;
2627 }
2628
98bd7ca0
DH
2629 subnet = NULL;
2630 status = subnet_allocate(&subnet, MDL);
2631 if (status != ISC_R_SUCCESS) {
2632 log_fatal("Allocation of new subnet failed: %s",
2633 isc_result_totext(status));
2634 }
2635 shared_network_reference(&subnet->shared_network, share, MDL);
7d6180be
DH
2636
2637 /*
2638 * If our parent shared network was implicitly created by the software,
2639 * and not explicitly configured by the user, then we actually put all
2640 * configuration scope in the parent (the shared network and subnet
2641 * share the same {}-level scope).
2642 *
2643 * Otherwise, we clone the parent group and continue as normal.
2644 */
2645 if (share->flags & SHARED_IMPLICIT) {
2646 group_reference(&subnet->group, share->group, MDL);
2647 } else {
2648 if (!clone_group(&subnet->group, share->group, MDL)) {
2649 log_fatal("Allocation of group for new subnet failed.");
2650 }
98bd7ca0
DH
2651 }
2652 subnet_reference(&subnet->group->subnet, subnet, MDL);
2653
2654 if (!parse_ip6_addr(cfile, &subnet->net)) {
2655 subnet_dereference(&subnet, MDL);
7dfc8ac2 2656 return;
20916cae 2657 }
7dfc8ac2 2658
98bd7ca0
DH
2659 token = next_token(&val, NULL, cfile);
2660 if (token != SLASH) {
2661 parse_warn(cfile, "Expecting a '/'.");
2662 skip_to_semi(cfile);
2663 return;
2664 }
1f814ff2 2665
98bd7ca0
DH
2666 token = next_token(&val, NULL, cfile);
2667 if (token != NUMBER) {
2668 parse_warn(cfile, "Expecting a number.");
2669 skip_to_semi(cfile);
2670 return;
2671 }
2672
2673 subnet->prefix_len = strtol(val, &endp, 10);
2674 if ((subnet->prefix_len < 0) ||
2675 (subnet->prefix_len > 128) ||
2676 (*endp != '\0')) {
2677 parse_warn(cfile, "Expecting a number between 0 and 128.");
2678 skip_to_semi(cfile);
2679 return;
2680 }
2681
9b21e73e
SK
2682 if (!is_cidr_mask_valid(&subnet->net, subnet->prefix_len)) {
2683 parse_warn(cfile, "New subnet mask too short.");
2684 skip_to_semi(cfile);
2685 return;
2686 }
2687
98bd7ca0
DH
2688 /*
2689 * Create a netmask.
2690 */
2691 subnet->netmask.len = 16;
2692 ofs = subnet->prefix_len / 8;
2693 if (ofs < subnet->netmask.len) {
2694 subnet->netmask.iabuf[ofs] = mask[subnet->prefix_len % 8];
2695 }
2696 while (--ofs >= 0) {
2697 subnet->netmask.iabuf[ofs] = 0xFF;
2698 }
2699
2700 /* Validate the network number/netmask pair. */
2701 iaddr = subnet_number(subnet->net, subnet->netmask);
2702 if (memcmp(&iaddr, &subnet->net, 16) != 0) {
2703 parse_warn(cfile,
2704 "subnet %s/%d: prefix not long enough for address.",
2705 piaddr(subnet->net), subnet->prefix_len);
2706 subnet_dereference(&subnet, MDL);
2707 skip_to_semi(cfile);
2708 return;
2709 }
2710
2711 if (!common_subnet_parsing(cfile, share, subnet)) {
2712 return;
7dfc8ac2 2713 }
fe5b0fdd 2714#endif /* defined(DHCPv6) */
685963dc
TL
2715}
2716
2d59f590 2717/* group-declaration :== RBRACE parameters declarations LBRACE */
7dfc8ac2 2718
2d59f590 2719void parse_group_declaration (cfile, group)
35454d8a 2720 struct parse *cfile;
7dfc8ac2 2721 struct group *group;
685963dc 2722{
b1b7b521 2723 const char *val;
6f8fb41f 2724 enum dhcp_token token;
7dfc8ac2 2725 struct group *g;
2d59f590 2726 int declaration = 0;
29c35bed
TL
2727 struct group_object *t;
2728 isc_result_t status;
d9eefc5d 2729 char *name = NULL;
29c35bed
TL
2730 int deletedp = 0;
2731 int dynamicp = 0;
2732 int staticp = 0;
685963dc 2733
20916cae
TL
2734 g = (struct group *)0;
2735 if (!clone_group (&g, group, MDL))
2736 log_fatal ("no memory for explicit group.");
685963dc 2737
b3519f23 2738 token = peek_token (&val, (unsigned *)0, cfile);
29c35bed 2739 if (is_identifier (token) || token == STRING) {
b3519f23 2740 next_token (&val, (unsigned *)0, cfile);
29c35bed 2741
436f1c8c 2742 name = dmalloc (strlen (val) + 1, MDL);
29c35bed
TL
2743 if (!name)
2744 log_fatal ("no memory for group decl name %s", val);
2745 strcpy (name, val);
2746 }
2747
20916cae
TL
2748 if (!parse_lbrace (cfile)) {
2749 group_dereference (&g, MDL);
7dfc8ac2 2750 return;
20916cae 2751 }
d7837182 2752
7dfc8ac2 2753 do {
b3519f23 2754 token = peek_token (&val, (unsigned *)0, cfile);
5376e3e9 2755 if (token == RBRACE) {
b3519f23 2756 token = next_token (&val, (unsigned *)0, cfile);
7dfc8ac2 2757 break;
0b69dcc8 2758 } else if (token == END_OF_FILE) {
b3519f23 2759 token = next_token (&val, (unsigned *)0, cfile);
35454d8a 2760 parse_warn (cfile, "unexpected end of file");
5376e3e9 2761 break;
007e3ee4 2762 } else if (token == TOKEN_DELETED) {
b3519f23 2763 token = next_token (&val, (unsigned *)0, cfile);
29c35bed
TL
2764 parse_semi (cfile);
2765 deletedp = 1;
2766 } else if (token == DYNAMIC) {
b3519f23 2767 token = next_token (&val, (unsigned *)0, cfile);
29c35bed
TL
2768 parse_semi (cfile);
2769 dynamicp = 1;
2770 } else if (token == STATIC) {
b3519f23 2771 token = next_token (&val, (unsigned *)0, cfile);
29c35bed
TL
2772 parse_semi (cfile);
2773 staticp = 1;
5376e3e9 2774 }
2d59f590
TL
2775 declaration = parse_statement (cfile, g, GROUP_DECL,
2776 (struct host_decl *)0,
2777 declaration);
7dfc8ac2 2778 } while (1);
29c35bed
TL
2779
2780 if (name) {
2781 if (deletedp) {
2782 if (group_name_hash) {
20916cae
TL
2783 t = (struct group_object *)0;
2784 if (group_hash_lookup (&t, group_name_hash,
2785 name,
2786 strlen (name), MDL)) {
29c35bed
TL
2787 delete_group (t, 0);
2788 }
2789 }
2790 } else {
20916cae
TL
2791 t = (struct group_object *)0;
2792 status = group_object_allocate (&t, MDL);
2793 if (status != ISC_R_SUCCESS)
2794 log_fatal ("no memory for group decl %s: %s",
2795 val, isc_result_totext (status));
2796 group_reference (&t -> group, g, MDL);
29c35bed
TL
2797 t -> name = name;
2798 t -> flags = ((staticp ? GROUP_OBJECT_STATIC : 0) |
2799 (dynamicp ? GROUP_OBJECT_DYNAMIC : 0) |
2800 (deletedp ? GROUP_OBJECT_DELETED : 0));
2801 supersede_group (t, 0);
2802 }
20916cae
TL
2803 if (t)
2804 group_object_dereference (&t, MDL);
29c35bed 2805 }
d7837182
TL
2806}
2807
2d59f590
TL
2808/* fixed-addr-parameter :== ip-addrs-or-hostnames SEMI
2809 ip-addrs-or-hostnames :== ip-addr-or-hostname
2810 | ip-addrs-or-hostnames ip-addr-or-hostname */
d7837182 2811
98bd7ca0
DH
2812int
2813parse_fixed_addr_param(struct option_cache **oc,
2814 struct parse *cfile,
2815 enum dhcp_token type) {
2816 int parse_ok;
b1b7b521 2817 const char *val;
6f8fb41f 2818 enum dhcp_token token;
98bd7ca0 2819 struct expression *expr = NULL;
6f8fb41f
TL
2820 struct expression *tmp, *new;
2821 int status;
1f814ff2
TL
2822
2823 do {
98bd7ca0
DH
2824 tmp = NULL;
2825 if (type == FIXED_ADDR) {
2826 parse_ok = parse_ip_addr_or_hostname(&tmp, cfile, 1);
2827 } else {
2828 /* INSIST(type == FIXED_ADDR6); */
2829 parse_ok = parse_ip6_addr_expr(&tmp, cfile);
2830 }
2831 if (parse_ok) {
2832 if (expr != NULL) {
2833 new = NULL;
2834 status = make_concat(&new, expr, tmp);
2835 expression_dereference(&expr, MDL);
2836 expression_dereference(&tmp, MDL);
2837 if (!status) {
028a8588 2838 return 0;
98bd7ca0 2839 }
028a8588 2840 expr = new;
98bd7ca0 2841 } else {
028a8588 2842 expr = tmp;
98bd7ca0 2843 }
6f8fb41f 2844 } else {
98bd7ca0 2845 if (expr != NULL) {
436f1c8c 2846 expression_dereference (&expr, MDL);
98bd7ca0 2847 }
6f8fb41f
TL
2848 return 0;
2849 }
98bd7ca0
DH
2850 token = peek_token(&val, NULL, cfile);
2851 if (token == COMMA) {
2852 token = next_token(&val, NULL, cfile);
2853 }
1f814ff2 2854 } while (token == COMMA);
7dfc8ac2 2855
98bd7ca0
DH
2856 if (!parse_semi(cfile)) {
2857 if (expr) {
436f1c8c 2858 expression_dereference (&expr, MDL);
98bd7ca0 2859 }
6f8fb41f
TL
2860 return 0;
2861 }
98bd7ca0
DH
2862
2863 status = option_cache(oc, NULL, expr, NULL, MDL);
2864 expression_dereference(&expr, MDL);
6f8fb41f 2865 return status;
d7837182
TL
2866}
2867
2d59f590
TL
2868/* lease_declaration :== LEASE ip_address LBRACE lease_parameters RBRACE
2869
2870 lease_parameters :== <nil>
2871 | lease_parameter
2872 | lease_parameters lease_parameter
2873
2874 lease_parameter :== STARTS date
2875 | ENDS date
2876 | TIMESTAMP date
2877 | HARDWARE hardware-parameter
2878 | UID hex_numbers SEMI
ccf5778a
TL
2879 | HOSTNAME hostname SEMI
2880 | CLIENT_HOSTNAME hostname SEMI
2d59f590
TL
2881 | CLASS identifier SEMI
2882 | DYNAMIC_BOOTP SEMI */
2883
20916cae 2884int parse_lease_declaration (struct lease **lp, struct parse *cfile)
d7837182 2885{
b1b7b521 2886 const char *val;
6f8fb41f 2887 enum dhcp_token token;
d7837182 2888 unsigned char addr [4];
b1b7b521 2889 unsigned len = sizeof addr;
d7837182
TL
2890 int seenmask = 0;
2891 int seenbit;
2892 char tbuf [32];
20916cae 2893 struct lease *lease;
96d7d13e
TL
2894 struct executable_statement *on;
2895 int lose;
9e9b2261 2896 TIME t;
436f1c8c
TL
2897 int noequal, newbinding;
2898 struct binding *binding;
7285af30 2899 struct binding_value *nv;
20916cae 2900 isc_result_t status;
6c5223f5
TL
2901 struct option_cache *oc;
2902 pair *p;
e15d235d 2903 binding_state_t new_state;
b3519f23 2904 unsigned buflen = 0;
f545ef7f 2905 struct class *class;
d7837182 2906
20916cae
TL
2907 lease = (struct lease *)0;
2908 status = lease_allocate (&lease, MDL);
2909 if (status != ISC_R_SUCCESS)
2910 return 0;
9375101b 2911
d7837182 2912 /* Get the address for which the lease has been issued. */
20916cae
TL
2913 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) {
2914 lease_dereference (&lease, MDL);
2915 return 0;
2916 }
2917 memcpy (lease -> ip_addr.iabuf, addr, len);
2918 lease -> ip_addr.len = len;
d7837182 2919
20916cae
TL
2920 if (!parse_lbrace (cfile)) {
2921 lease_dereference (&lease, MDL);
2922 return 0;
2923 }
7dfc8ac2 2924
d7837182 2925 do {
b3519f23 2926 token = next_token (&val, (unsigned *)0, cfile);
7dfc8ac2 2927 if (token == RBRACE)
d7837182 2928 break;
0b69dcc8 2929 else if (token == END_OF_FILE) {
35454d8a 2930 parse_warn (cfile, "unexpected end of file");
5376e3e9
TL
2931 break;
2932 }
ece6ea33 2933 strncpy (tbuf, val, sizeof tbuf);
d7837182
TL
2934 tbuf [(sizeof tbuf) - 1] = 0;
2935
2936 /* Parse any of the times associated with the lease. */
9e9b2261
TL
2937 switch (token) {
2938 case STARTS:
2939 case ENDS:
2940 case TIMESTAMP:
2941 case TSTP:
2942 case TSFP:
88cd8aca 2943 case ATSFP:
8c8e27c5 2944 case CLTT:
7dfc8ac2 2945 t = parse_date (cfile);
d7837182
TL
2946 switch (token) {
2947 case STARTS:
2948 seenbit = 1;
20916cae 2949 lease -> starts = t;
d7837182
TL
2950 break;
2951
2952 case ENDS:
2953 seenbit = 2;
20916cae 2954 lease -> ends = t;
d7837182
TL
2955 break;
2956
9e9b2261
TL
2957 case TSTP:
2958 seenbit = 65536;
20916cae 2959 lease -> tstp = t;
19d868b2 2960 break;
9e9b2261
TL
2961
2962 case TSFP:
2963 seenbit = 131072;
20916cae 2964 lease -> tsfp = t;
d7837182 2965 break;
88cd8aca
DH
2966
2967 case ATSFP:
2968 seenbit = 262144;
2969 lease->atsfp = t;
2970 break;
9e9b2261 2971
8c8e27c5
TL
2972 case CLTT:
2973 seenbit = 524288;
20916cae 2974 lease -> cltt = t;
8c8e27c5
TL
2975 break;
2976
9e9b2261 2977 default: /* for gcc, we'll never get here. */
98311e4b
DH
2978 log_fatal ("Impossible error at %s:%d.", MDL);
2979 return 0;
9e9b2261
TL
2980 }
2981 break;
d7837182 2982
c57db45c 2983 /* Colon-separated hexadecimal octets... */
9e9b2261
TL
2984 case UID:
2985 seenbit = 8;
b3519f23 2986 token = peek_token (&val, (unsigned *)0, cfile);
9e9b2261
TL
2987 if (token == STRING) {
2988 unsigned char *tuid;
b3519f23 2989 token = next_token (&val, &buflen, cfile);
a3cd7f28 2990 if (buflen < sizeof lease -> uid_buf) {
b3519f23 2991 tuid = lease -> uid_buf;
a3cd7f28
TL
2992 lease -> uid_max =
2993 sizeof lease -> uid_buf;
2994 } else {
b3519f23
TL
2995 tuid = ((unsigned char *)
2996 dmalloc (buflen, MDL));
2997 if (!tuid) {
2998 log_error ("no space for uid");
2999 lease_dereference (&lease,
3000 MDL);
3001 return 0;
3002 }
a3cd7f28 3003 lease -> uid_max = buflen;
d7837182 3004 }
7ebf32da 3005 lease -> uid_len = buflen;
20916cae
TL
3006 memcpy (tuid, val, lease -> uid_len);
3007 lease -> uid = tuid;
9e9b2261 3008 } else {
b3519f23 3009 buflen = 0;
20916cae
TL
3010 lease -> uid = (parse_numeric_aggregate
3011 (cfile, (unsigned char *)0,
b3519f23 3012 &buflen, ':', 16, 8));
20916cae
TL
3013 if (!lease -> uid) {
3014 lease_dereference (&lease, MDL);
3015 return 0;
3016 }
7ebf32da 3017 lease -> uid_len = buflen;
a3cd7f28 3018 lease -> uid_max = buflen;
20916cae
TL
3019 if (lease -> uid_len == 0) {
3020 lease -> uid = (unsigned char *)0;
9e9b2261
TL
3021 parse_warn (cfile, "zero-length uid");
3022 seenbit = 0;
d0463358 3023 parse_semi (cfile);
9e9b2261
TL
3024 break;
3025 }
3026 }
d0463358 3027 parse_semi (cfile);
20916cae 3028 if (!lease -> uid) {
9e9b2261
TL
3029 log_fatal ("No memory for lease uid");
3030 }
3031 break;
a55ccdd0 3032
9e9b2261
TL
3033 case CLASS:
3034 seenbit = 32;
b3519f23 3035 token = next_token (&val, (unsigned *)0, cfile);
9e9b2261
TL
3036 if (!is_identifier (token)) {
3037 if (token != SEMI)
3038 skip_to_rbrace (cfile, 1);
20916cae
TL
3039 lease_dereference (&lease, MDL);
3040 return 0;
9e9b2261 3041 }
d0463358 3042 parse_semi (cfile);
9e9b2261
TL
3043 /* for now, we aren't using this. */
3044 break;
ccf5778a 3045
9e9b2261
TL
3046 case HARDWARE:
3047 seenbit = 64;
3048 parse_hardware_param (cfile,
20916cae 3049 &lease -> hardware_addr);
9e9b2261
TL
3050 break;
3051
a55ccdd0
DH
3052 case TOKEN_RESERVED:
3053 seenbit = 0;
3054 lease->flags |= RESERVED_LEASE;
3055 parse_semi(cfile);
3056 break;
3057
9e9b2261 3058 case DYNAMIC_BOOTP:
a55ccdd0 3059 seenbit = 0;
98311e4b 3060 lease -> flags |= BOOTP_LEASE;
d0463358 3061 parse_semi (cfile);
9e9b2261 3062 break;
a55ccdd0
DH
3063
3064 /* XXX: Reverse compatibility? */
007e3ee4
TL
3065 case TOKEN_ABANDONED:
3066 seenbit = 256;
3067 lease -> binding_state = FTS_ABANDONED;
3068 lease -> next_binding_state = FTS_ABANDONED;
d0463358 3069 parse_semi (cfile);
9e9b2261
TL
3070 break;
3071
007e3ee4
TL
3072 case TOKEN_NEXT:
3073 seenbit = 128;
b3519f23 3074 token = next_token (&val, (unsigned *)0, cfile);
301a5b66
TL
3075 if (token != BINDING) {
3076 parse_warn (cfile, "expecting 'binding'");
3077 skip_to_semi (cfile);
3078 break;
3079 }
007e3ee4
TL
3080 goto do_binding_state;
3081
fdfebedf
DH
3082 case REWIND:
3083 seenbit = 512;
3084 token = next_token(&val, NULL, cfile);
3085 if (token != BINDING) {
3086 parse_warn(cfile, "expecting 'binding'");
3087 skip_to_semi(cfile);
3088 break;
3089 }
3090 goto do_binding_state;
3091
007e3ee4 3092 case BINDING:
9e9b2261 3093 seenbit = 256;
007e3ee4
TL
3094
3095 do_binding_state:
b3519f23 3096 token = next_token (&val, (unsigned *)0, cfile);
007e3ee4
TL
3097 if (token != STATE) {
3098 parse_warn (cfile, "expecting 'state'");
3099 skip_to_semi (cfile);
3100 break;
3101 }
b3519f23 3102 token = next_token (&val, (unsigned *)0, cfile);
007e3ee4
TL
3103 switch (token) {
3104 case TOKEN_ABANDONED:
e15d235d 3105 new_state = FTS_ABANDONED;
007e3ee4
TL
3106 break;
3107 case TOKEN_FREE:
e15d235d 3108 new_state = FTS_FREE;
007e3ee4
TL
3109 break;
3110 case TOKEN_ACTIVE:
e15d235d 3111 new_state = FTS_ACTIVE;
007e3ee4
TL
3112 break;
3113 case TOKEN_EXPIRED:
e15d235d 3114 new_state = FTS_EXPIRED;
007e3ee4
TL
3115 break;
3116 case TOKEN_RELEASED:
e15d235d 3117 new_state = FTS_RELEASED;
007e3ee4
TL
3118 break;
3119 case TOKEN_RESET:
e15d235d 3120 new_state = FTS_RESET;
007e3ee4
TL
3121 break;
3122 case TOKEN_BACKUP:
e15d235d 3123 new_state = FTS_BACKUP;
007e3ee4 3124 break;
a55ccdd0
DH
3125
3126 /* RESERVED and BOOTP states preserved for
20ae1aff 3127 * compatibleness with older versions.
a55ccdd0 3128 */
007e3ee4 3129 case TOKEN_RESERVED:
98311e4b 3130 new_state = FTS_ACTIVE;
a55ccdd0 3131 lease->flags |= RESERVED_LEASE;
007e3ee4
TL
3132 break;
3133 case TOKEN_BOOTP:
98311e4b 3134 new_state = FTS_ACTIVE;
a55ccdd0 3135 lease->flags |= BOOTP_LEASE;
007e3ee4 3136 break;
a55ccdd0 3137
007e3ee4
TL
3138 default:
3139 parse_warn (cfile,
3140 "%s: expecting a binding state.",
3141 val);
3142 skip_to_semi (cfile);
98311e4b 3143 return 0;
007e3ee4 3144 }
e15d235d
TL
3145
3146 if (seenbit == 256) {
3147 lease -> binding_state = new_state;
3148
fdfebedf
DH
3149 /*
3150 * Apply default/conservative next/rewind
3151 * binding states if they haven't been set
3152 * yet. These defaults will be over-ridden if
3153 * they are set later in parsing.
3154 */
e15d235d 3155 if (!(seenmask & 128))
fdfebedf
DH
3156 lease->next_binding_state = new_state;
3157
3158 /* The most conservative rewind state. */
3159 if (!(seenmask & 512))
3160 lease->rewind_binding_state = new_state;
3161 } else if (seenbit == 128)
e15d235d 3162 lease -> next_binding_state = new_state;
fdfebedf
DH
3163 else if (seenbit == 512)
3164 lease->rewind_binding_state = new_state;
3165 else
3166 log_fatal("Impossible condition at %s:%d.",
3167 MDL);
3168
d0463358 3169 parse_semi (cfile);
9e9b2261 3170 break;
ccf5778a 3171
9e9b2261
TL
3172 case CLIENT_HOSTNAME:
3173 seenbit = 1024;
b3519f23
TL
3174 token = peek_token (&val, (unsigned *)0, cfile);
3175 if (token == STRING) {
3176 if (!parse_string (cfile,
3177 &lease -> client_hostname,
3178 (unsigned *)0)) {
3179 lease_dereference (&lease, MDL);
3180 return 0;
3181 }
3182 } else {
20916cae 3183 lease -> client_hostname =
9e9b2261 3184 parse_host_name (cfile);
20916cae 3185 if (lease -> client_hostname)
d0463358 3186 parse_semi (cfile);
b3519f23
TL
3187 else {
3188 parse_warn (cfile,
3189 "expecting a hostname.");
3190 skip_to_semi (cfile);
3191 lease_dereference (&lease, MDL);
3192 return 0;
3193 }
d0463358 3194 }
9e9b2261
TL
3195 break;
3196
3197 case BILLING:
3198 seenbit = 2048;
f545ef7f 3199 class = (struct class *)0;
b3519f23 3200 token = next_token (&val, (unsigned *)0, cfile);
9e9b2261 3201 if (token == CLASS) {
b3519f23
TL
3202 token = next_token (&val,
3203 (unsigned *)0, cfile);
9e9b2261
TL
3204 if (token != STRING) {
3205 parse_warn (cfile, "expecting string");
88dcab62
TL
3206 if (token != SEMI)
3207 skip_to_semi (cfile);
9e9b2261
TL
3208 token = BILLING;
3209 break;
88dcab62 3210 }
aaafa64a 3211 if (lease -> billing_class)
ed1dc2c5
TL
3212 class_dereference (&lease -> billing_class,
3213 MDL);
f545ef7f
TL
3214 find_class (&class, val, MDL);
3215 if (!class)
9e9b2261
TL
3216 parse_warn (cfile,
3217 "unknown class %s", val);
3218 parse_semi (cfile);
3219 } else if (token == SUBCLASS) {
20916cae 3220 if (lease -> billing_class)
ed1dc2c5
TL
3221 class_dereference (&lease -> billing_class,
3222 MDL);
06e77c34
DH
3223 parse_class_declaration(&class, cfile, NULL,
3224 CLASS_TYPE_SUBCLASS);
9e9b2261
TL
3225 } else {
3226 parse_warn (cfile, "expecting \"class\"");
3227 if (token != SEMI)
3228 skip_to_semi (cfile);
3229 }
f545ef7f 3230 if (class) {
ed1dc2c5
TL
3231 class_reference (&lease -> billing_class,
3232 class, MDL);
f545ef7f
TL
3233 class_dereference (&class, MDL);
3234 }
9e9b2261 3235 break;
96d7d13e 3236
9e9b2261
TL
3237 case ON:
3238 on = (struct executable_statement *)0;
3239 lose = 0;
3240 if (!parse_on_statement (&on, cfile, &lose)) {
3241 skip_to_rbrace (cfile, 1);
20916cae
TL
3242 lease_dereference (&lease, MDL);
3243 return 0;
7dfc8ac2 3244 }
436f1c8c 3245 seenbit = 0;
d0463358 3246 if ((on -> data.on.evtypes & ON_EXPIRY) &&
9e9b2261 3247 on -> data.on.statements) {
436f1c8c 3248 seenbit |= 16384;
9e9b2261 3249 executable_statement_reference
20916cae 3250 (&lease -> on_expiry,
436f1c8c 3251 on -> data.on.statements, MDL);
d0463358
TL
3252 }
3253 if ((on -> data.on.evtypes & ON_RELEASE) &&
3254 on -> data.on.statements) {
436f1c8c 3255 seenbit |= 32768;
9e9b2261 3256 executable_statement_reference
20916cae 3257 (&lease -> on_release,
436f1c8c 3258 on -> data.on.statements, MDL);
9e9b2261 3259 }
436f1c8c 3260 executable_statement_dereference (&on, MDL);
9e9b2261 3261 break;
7285af30 3262
9e383163 3263 case OPTION:
a609e69b 3264 case SUPERSEDE:
9e383163
TL
3265 noequal = 0;
3266 seenbit = 0;
3267 oc = (struct option_cache *)0;
3268 if (parse_option_decl (&oc, cfile)) {
6c5223f5
TL
3269 if (oc -> option -> universe !=
3270 &agent_universe) {
3271 parse_warn (cfile,
3272 "agent option expected.");
3273 option_cache_dereference (&oc, MDL);
3274 break;
3275 }
3276 if (!lease -> agent_options &&
3277 !(option_chain_head_allocate
3278 (&lease -> agent_options, MDL))) {
3279 log_error ("no memory to stash agent option");
3280 break;
3281 }
3282 for (p = &lease -> agent_options -> first;
3283 *p; p = &((*p) -> cdr))
3284 ;
3285 *p = cons (0, 0);
3286 option_cache_reference (((struct option_cache **)
3287 &((*p) -> car)), oc, MDL);
3288 option_cache_dereference (&oc, MDL);
9e383163
TL
3289 }
3290 break;
3291
436f1c8c
TL
3292 case TOKEN_SET:
3293 noequal = 0;
3294
b3519f23 3295 token = next_token (&val, (unsigned *)0, cfile);
436f1c8c
TL
3296 if (token != NAME && token != NUMBER_OR_NAME) {
3297 parse_warn (cfile,
3298 "%s can't be a variable name",
3299 val);
3300 badset:
3301 skip_to_semi (cfile);
20916cae
TL
3302 lease_dereference (&lease, MDL);
3303 return 0;
436f1c8c
TL
3304 }
3305
3306 seenbit = 0;
3307 special_set:
6ceb9118
TL
3308 if (lease -> scope)
3309 binding = find_binding (lease -> scope, val);
3310 else
3311 binding = (struct binding *)0;
7285af30 3312
436f1c8c 3313 if (!binding) {
6ceb9118
TL
3314 if (!lease -> scope)
3315 if (!(binding_scope_allocate
3316 (&lease -> scope, MDL)))
3317 log_fatal ("no memory for scope");
d758ad8c
TL
3318 binding = dmalloc (sizeof *binding, MDL);
3319 if (!binding)
3320 log_fatal ("No memory for lease %s.",
3321 "binding");
3322 memset (binding, 0, sizeof *binding);
3323 binding -> name =
3324 dmalloc (strlen (val) + 1, MDL);
3325 if (!binding -> name)
3326 log_fatal ("No memory for binding %s.",
3327 "name");
3328 strcpy (binding -> name, val);
3329 newbinding = 1;
98311e4b 3330 } else {
7285af30 3331 newbinding = 0;
436f1c8c 3332 }
98311e4b 3333
8bfe717e 3334 nv = NULL;
7285af30
DH
3335 if (!binding_value_allocate(&nv, MDL))
3336 log_fatal("no memory for binding value.");
436f1c8c
TL
3337
3338 if (!noequal) {
b3519f23 3339 token = next_token (&val, (unsigned *)0, cfile);
436f1c8c
TL
3340 if (token != EQUAL) {
3341 parse_warn (cfile,
3342 "expecting '=' in set statement.");
3343 goto badset;
3344 }
3345 }
3346
7285af30
DH
3347 if (!parse_binding_value(cfile, nv)) {
3348 binding_value_dereference(&nv, MDL);
3349 lease_dereference(&lease, MDL);
20916cae 3350 return 0;
436f1c8c 3351 }
7285af30 3352
436f1c8c 3353 if (newbinding) {
7285af30
DH
3354 binding_value_reference(&binding->value,
3355 nv, MDL);
3356 binding->next = lease->scope->bindings;
3357 lease->scope->bindings = binding;
3358 } else {
3359 binding_value_dereference(&binding->value, MDL);
3360 binding_value_reference(&binding->value,
3361 nv, MDL);
436f1c8c 3362 }
7285af30
DH
3363
3364 binding_value_dereference(&nv, MDL);
3365 parse_semi(cfile);
436f1c8c
TL
3366 break;
3367
7285af30 3368 /* case NAME: */
9e9b2261 3369 default:
436f1c8c
TL
3370 if (!strcasecmp (val, "ddns-fwd-name")) {
3371 seenbit = 4096;
3372 noequal = 1;
3373 goto special_set;
3374 } else if (!strcasecmp (val, "ddns-rev-name")) {
3375 seenbit = 8192;
3376 noequal = 1;
3377 goto special_set;
7285af30
DH
3378 } else
3379 parse_warn(cfile, "Unexpected configuration "
3380 "directive.");
9e9b2261
TL
3381 skip_to_semi (cfile);
3382 seenbit = 0;
20916cae
TL
3383 lease_dereference (&lease, MDL);
3384 return 0;
9e9b2261 3385 }
7dfc8ac2 3386
d7837182 3387 if (seenmask & seenbit) {
35454d8a
TL
3388 parse_warn (cfile,
3389 "Too many %s parameters in lease %s\n",
20916cae 3390 tbuf, piaddr (lease -> ip_addr));
d7837182
TL
3391 } else
3392 seenmask |= seenbit;
7dfc8ac2 3393
d7837182 3394 } while (1);
8afe0787
TL
3395
3396 /* If no binding state is specified, make one up. */
3397 if (!(seenmask & 256)) {
e73a0769
TL
3398 if (lease -> ends > cur_time ||
3399 lease -> on_expiry || lease -> on_release)
8afe0787 3400 lease -> binding_state = FTS_ACTIVE;
301a5b66 3401#if defined (FAILOVER_PROTOCOL)
e73a0769
TL
3402 else if (lease -> pool && lease -> pool -> failover_peer)
3403 lease -> binding_state = FTS_EXPIRED;
301a5b66 3404#endif
8afe0787
TL
3405 else
3406 lease -> binding_state = FTS_FREE;
e73a0769 3407 if (lease -> binding_state == FTS_ACTIVE) {
301a5b66 3408#if defined (FAILOVER_PROTOCOL)
e73a0769
TL
3409 if (lease -> pool && lease -> pool -> failover_peer)
3410 lease -> next_binding_state = FTS_EXPIRED;
3411 else
301a5b66 3412#endif
e73a0769
TL
3413 lease -> next_binding_state = FTS_FREE;
3414 } else
3415 lease -> next_binding_state = lease -> binding_state;
fdfebedf
DH
3416
3417 /* The most conservative rewind state implies no rewind. */
3418 lease->rewind_binding_state = lease->binding_state;
8afe0787
TL
3419 }
3420
6f8a0361
TL
3421 if (!(seenmask & 65536))
3422 lease -> tstp = lease -> ends;
3423
20916cae
TL
3424 lease_reference (lp, lease, MDL);
3425 lease_dereference (&lease, MDL);
3426 return 1;
d7837182
TL
3427}
3428
7285af30
DH
3429/* Parse the right side of a 'binding value'.
3430 *
3431 * set foo = "bar"; is a string
3432 * set foo = false; is a boolean
3433 * set foo = %31; is a numeric value.
3434 */
3435static int
3436parse_binding_value(struct parse *cfile, struct binding_value *value)
3437{
3438 struct data_string *data;
3439 unsigned char *s;
3440 const char *val;
3441 unsigned buflen;
3442 int token;
3443
3444 if ((cfile == NULL) || (value == NULL))
3445 log_fatal("Invalid arguments at %s:%d.", MDL);
3446
3447 token = peek_token(&val, NULL, cfile);
3448 if (token == STRING) {
3449 token = next_token(&val, &buflen, cfile);
3450
3451 value->type = binding_data;
3452 value->value.data.len = buflen;
3453
3454 data = &value->value.data;
3455
3456 if (!buffer_allocate(&data->buffer, buflen + 1, MDL))
3457 log_fatal ("No memory for binding.");
3458
3459 memcpy(data->buffer->data, val, buflen + 1);
3460
3461 data->data = data->buffer->data;
3462 data->terminated = 1;
3463 } else if (token == NUMBER_OR_NAME) {
3464 value->type = binding_data;
3465
3466 data = &value->value.data;
3467 s = parse_numeric_aggregate(cfile, NULL, &data->len,
3468 ':', 16, 8);
3469 if (s == NULL) {
3470 skip_to_semi(cfile);
3471 return 0;
3472 }
3473
3474 if (data->len) {
3475 if (!buffer_allocate(&data->buffer, data->len + 1,
3476 MDL))
3477 log_fatal("No memory for binding.");
3478
3479 memcpy(data->buffer->data, s, data->len);
3480 data->data = data->buffer->data;
3481
3482 dfree (s, MDL);
3483 }
3484 } else if (token == PERCENT) {
3485 token = next_token(&val, NULL, cfile);
3486 token = next_token(&val, NULL, cfile);
3487 if (token != NUMBER) {
3488 parse_warn(cfile, "expecting decimal number.");
3489 if (token != SEMI)
3490 skip_to_semi(cfile);
3491 return 0;
3492 }
3493 value->type = binding_numeric;
3494 value->value.intval = atol(val);
3495 } else if (token == NAME) {
3496 token = next_token(&val, NULL, cfile);
3497 value->type = binding_boolean;
3498 if (!strcasecmp(val, "true"))
3499 value->value.boolean = 1;
3500 else if (!strcasecmp(val, "false"))
3501 value->value.boolean = 0;
3502 else {
3503 parse_warn(cfile, "expecting true or false");
3504 if (token != SEMI)
3505 skip_to_semi(cfile);
3506 return 0;
3507 }
3508 } else {
3509 parse_warn (cfile, "expecting a constant value.");
3510 if (token != SEMI)
3511 skip_to_semi (cfile);
3512 return 0;
3513 }
3514
3515 return 1;
3516}
3517
2d59f590
TL
3518/* address-range-declaration :== ip-address ip-address SEMI
3519 | DYNAMIC_BOOTP ip-address ip-address SEMI */
d7837182 3520
98311e4b 3521void parse_address_range (cfile, group, type, inpool, lpchain)
35454d8a 3522 struct parse *cfile;
f63b4929
TL
3523 struct group *group;
3524 int type;
20916cae 3525 struct pool *inpool;
98311e4b 3526 struct lease **lpchain;
d7837182 3527{
f63b4929 3528 struct iaddr low, high, net;
d7837182 3529 unsigned char addr [4];
b1b7b521 3530 unsigned len = sizeof addr;
6f8fb41f 3531 enum dhcp_token token;
b1b7b521 3532 const char *val;
1f814ff2 3533 int dynamic = 0;
f63b4929
TL
3534 struct subnet *subnet;
3535 struct shared_network *share;
20916cae
TL
3536 struct pool *pool;
3537 isc_result_t status;
1f814ff2 3538
b3519f23
TL
3539 if ((token = peek_token (&val,
3540 (unsigned *)0, cfile)) == DYNAMIC_BOOTP) {
3541 token = next_token (&val, (unsigned *)0, cfile);
ece6ea33 3542 dynamic = 1;
1f814ff2 3543 }
d7837182
TL
3544
3545 /* Get the bottom address in the range... */
7dfc8ac2
TL
3546 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
3547 return;
089fb364
TL
3548 memcpy (low.iabuf, addr, len);
3549 low.len = len;
d7837182 3550
2d59f590 3551 /* Only one address? */
b3519f23 3552 token = peek_token (&val, (unsigned *)0, cfile);
2d59f590
TL
3553 if (token == SEMI)
3554 high = low;
3555 else {
d7837182 3556 /* Get the top address in the range... */
2d59f590
TL
3557 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
3558 return;
3559 memcpy (high.iabuf, addr, len);
3560 high.len = len;
3561 }
d7837182 3562
b3519f23 3563 token = next_token (&val, (unsigned *)0, cfile);
7dfc8ac2 3564 if (token != SEMI) {
35454d8a 3565 parse_warn (cfile, "semicolon expected.");
7dfc8ac2
TL
3566 skip_to_semi (cfile);
3567 return;
3568 }
3569
f63b4929
TL
3570 if (type == SUBNET_DECL) {
3571 subnet = group -> subnet;
3572 share = subnet -> shared_network;
3573 } else {
3574 share = group -> shared_network;
3575 for (subnet = share -> subnets;
3576 subnet; subnet = subnet -> next_sibling) {
3577 net = subnet_number (low, subnet -> netmask);
e5e41be4 3578 if (addr_eq (net, subnet -> net))
f63b4929
TL
3579 break;
3580 }
3581 if (!subnet) {
35454d8a 3582 parse_warn (cfile, "address range not on network %s",
f63b4929 3583 group -> shared_network -> name);
e5e41be4
TL
3584 log_error ("Be sure to place pool statement after %s",
3585 "related subnet declarations.");
f63b4929
TL
3586 return;
3587 }
3588 }
3589
20916cae 3590 if (!inpool) {
0a1dfb65 3591 struct pool *last = (struct pool *)0;
9e9b2261 3592
f63b4929
TL
3593 /* If we're permitting dynamic bootp for this range,
3594 then look for a pool with an empty prohibit list and
436f1c8c 3595 a permit list with one entry that permits all clients. */
f63b4929 3596 for (pool = share -> pools; pool; pool = pool -> next) {
436f1c8c
TL
3597 if ((!dynamic && !pool -> permit_list &&
3598 pool -> prohibit_list &&
3599 !pool -> prohibit_list -> next &&
3600 (pool -> prohibit_list -> type ==
3601 permit_dynamic_bootp_clients)) ||
3602 (dynamic && !pool -> prohibit_list &&
f63b4929
TL
3603 pool -> permit_list &&
3604 !pool -> permit_list -> next &&
3605 (pool -> permit_list -> type ==
d9eefc5d 3606 permit_all_clients))) {
436f1c8c 3607 break;
f63b4929
TL
3608 }
3609 last = pool;
3610 }
3611
3612 /* If we didn't get a pool, make one. */
3613 if (!pool) {
436f1c8c 3614 struct permit *p;
20916cae
TL
3615 status = pool_allocate (&pool, MDL);
3616 if (status != ISC_R_SUCCESS)
3617 log_fatal ("no memory for ad-hoc pool: %s",
3618 isc_result_totext (status));
436f1c8c
TL
3619 p = new_permit (MDL);
3620 if (!p)
3621 log_fatal ("no memory for ad-hoc permit.");
3622
3623 /* Dynamic pools permit all clients. Otherwise
3624 we prohibit BOOTP clients. */
f63b4929 3625 if (dynamic) {
436f1c8c
TL
3626 p -> type = permit_all_clients;
3627 pool -> permit_list = p;
3628 } else {
3629 p -> type = permit_dynamic_bootp_clients;
3630 pool -> prohibit_list = p;
f63b4929 3631 }
436f1c8c 3632
f63b4929 3633 if (share -> pools)
20916cae 3634 pool_reference (&last -> next, pool, MDL);
f63b4929 3635 else
20916cae
TL
3636 pool_reference (&share -> pools, pool, MDL);
3637 shared_network_reference (&pool -> shared_network,
3638 share, MDL);
3639 if (!clone_group (&pool -> group, share -> group, MDL))
3640 log_fatal ("no memory for anon pool group.");
a79ed92b
TL
3641 } else {
3642 pool = (struct pool *)0;
0a1dfb65
TL
3643 if (last)
3644 pool_reference (&pool, last, MDL);
3645 else
3646 pool_reference (&pool, share -> pools, MDL);
f63b4929 3647 }
a79ed92b
TL
3648 } else {
3649 pool = (struct pool *)0;
20916cae 3650 pool_reference (&pool, inpool, MDL);
a79ed92b 3651 }
20916cae 3652
c5261618
TL
3653#if defined (FAILOVER_PROTOCOL)
3654 if (pool -> failover_peer && dynamic) {
3655 /* Doctor, do you think I'm overly sensitive
3656 about getting bug reports I can't fix? */
3657 parse_warn (cfile, "dynamic-bootp flag is %s",
3658 "not permitted for address");
3659 log_error ("range declarations where there is a failover");
3660 log_error ("peer in scope. If you wish to declare an");
3661 log_error ("address range from which dynamic bootp leases");
3662 log_error ("can be allocated, please declare it within a");
3663 log_error ("pool declaration that also contains the \"no");
3664 log_error ("failover\" statement. The failover protocol");
3665 log_error ("itself does not permit dynamic bootp - this");
3666 log_error ("is not a limitation specific to the ISC DHCP");
3667 log_error ("server. Please don't ask me to defend this");
3668 log_error ("until you have read and really tried %s",
3669 "to understand");
3670 log_error ("the failover protocol specification.");
3671
3672 /* We don't actually bomb at this point - instead,
3673 we let parse_lease_file notice the error and
3674 bomb at that point - it's easier. */
f63b4929 3675 }
c5261618 3676#endif /* FAILOVER_PROTOCOL */
f63b4929 3677
d7837182 3678 /* Create the new address range... */
98311e4b 3679 new_address_range (cfile, low, high, subnet, pool, lpchain);
20916cae 3680 pool_dereference (&pool, MDL);
d7837182
TL
3681}
3682
fe5b0fdd 3683#ifdef DHCPv6
98bd7ca0 3684static void
7d6180be
DH
3685add_ipv6_pool_to_subnet(struct subnet *subnet, u_int16_t type,
3686 struct iaddr *lo_addr, int bits, int units) {
98bd7ca0 3687 struct ipv6_pool *pool;
7d6180be 3688 struct shared_network *share;
98bd7ca0
DH
3689 struct in6_addr tmp_in6_addr;
3690 int num_pools;
3691 struct ipv6_pool **tmp;
3692
7d6180be
DH
3693 share = subnet->shared_network;
3694
98bd7ca0
DH
3695 /*
3696 * Create our pool.
3697 */
3698 if (lo_addr->len != sizeof(tmp_in6_addr)) {
3699 log_fatal("Internal error: Attempt to add non-IPv6 address "
3700 "to IPv6 shared network.");
3701 }
3702 memcpy(&tmp_in6_addr, lo_addr->iabuf, sizeof(tmp_in6_addr));
3703 pool = NULL;
9322442f
FD
3704 if (ipv6_pool_allocate(&pool, type, &tmp_in6_addr,
3705 bits, units, MDL) != ISC_R_SUCCESS) {
98bd7ca0
DH
3706 log_fatal("Out of memory");
3707 }
3708
3709 /*
3710 * Add to our global IPv6 pool set.
3711 */
3712 if (add_ipv6_pool(pool) != ISC_R_SUCCESS) {
3713 log_fatal ("Out of memory");
3714 }
3715
3716 /*
7d6180be 3717 * Link the pool to its network.
98bd7ca0 3718 */
7d6180be
DH
3719 pool->subnet = NULL;
3720 subnet_reference(&pool->subnet, subnet, MDL);
98bd7ca0
DH
3721 pool->shared_network = NULL;
3722 shared_network_reference(&pool->shared_network, share, MDL);
3723
3724 /*
3725 * Increase our array size for ipv6_pools in the shared_network.
3726 */
3727 if (share->ipv6_pools == NULL) {
3728 num_pools = 0;
3729 } else {
3730 num_pools = 0;
3731 while (share->ipv6_pools[num_pools] != NULL) {
3732 num_pools++;
3733 }
3734 }
3735 tmp = dmalloc(sizeof(struct ipv6_pool *) * (num_pools + 2), MDL);
3736 if (tmp == NULL) {
3737 log_fatal("Out of memory");
3738 }
3739 if (num_pools > 0) {
3740 memcpy(tmp, share->ipv6_pools,
3741 sizeof(struct ipv6_pool *) * num_pools);
3742 }
3743 if (share->ipv6_pools != NULL) {
3744 dfree(share->ipv6_pools, MDL);
3745 }
3746 share->ipv6_pools = tmp;
3747
3748 /*
3749 * Record this pool in our array of pools for this shared network.
3750 */
3751 ipv6_pool_reference(&share->ipv6_pools[num_pools], pool, MDL);
3752 share->ipv6_pools[num_pools+1] = NULL;
3753}
3754
3755/* address-range6-declaration :== ip-address6 ip-address6 SEMI
80c9fdb0 3756 | ip-address6 SLASH number SEMI
783259b1 3757 | ip-address6 [SLASH number] TEMPORARY SEMI */
98bd7ca0
DH
3758
3759void
3760parse_address_range6(struct parse *cfile, struct group *group) {
3761 struct iaddr lo, hi;
3762 int bits;
3763 enum dhcp_token token;
3764 const char *val;
98bd7ca0
DH
3765 struct iaddrcidrnetlist *nets;
3766 struct iaddrcidrnetlist *p;
783259b1 3767 u_int16_t type = D6O_IA_NA;
98bd7ca0 3768
771484ac
EH
3769 if (local_family != AF_INET6) {
3770 parse_warn(cfile, "range6 statement is only supported "
3771 "in DHCPv6 mode.");
3772 skip_to_semi(cfile);
3773 return;
3774 }
3775
7d6180be
DH
3776 /* This is enforced by the caller, this is just a sanity check. */
3777 if (group->subnet == NULL)
3778 log_fatal("Impossible condition at %s:%d.", MDL);
98bd7ca0
DH
3779
3780 /*
3781 * Read starting address.
3782 */
3783 if (!parse_ip6_addr(cfile, &lo)) {
3784 return;
3785 }
3786
3787 /*
80c9fdb0 3788 * See if we we're using range or CIDR notation or TEMPORARY
98bd7ca0
DH
3789 */
3790 token = peek_token(&val, NULL, cfile);
3791 if (token == SLASH) {
3792 /*
3793 * '/' means CIDR notation, so read the bits we want.
3794 */
3795 next_token(NULL, NULL, cfile);
3796 token = next_token(&val, NULL, cfile);
3797 if (token != NUMBER) {
3798 parse_warn(cfile, "expecting number");
3799 skip_to_semi(cfile);
3800 return;
3801 }
3802 bits = atoi(val);
3803 if ((bits < 0) || (bits > 128)) {
3804 parse_warn(cfile, "networks have 0 to 128 bits");
3805 skip_to_semi(cfile);
3806 return;
3807 }
9b21e73e
SK
3808 if (!is_cidr_mask_valid(&lo, bits)) {
3809 parse_warn(cfile, "network mask too short");
3810 skip_to_semi(cfile);
3811 return;
3812 }
98bd7ca0 3813
783259b1
FD
3814 /*
3815 * can be temporary (RFC 4941 like)
3816 */
3817 token = peek_token(&val, NULL, cfile);
3818 if (token == TEMPORARY) {
3819 if (bits < 64)
3820 parse_warn(cfile, "temporary mask too short");
3821 if (bits == 128)
3822 parse_warn(cfile, "temporary singleton?");
3823 token = next_token(NULL, NULL, cfile);
3824 type = D6O_IA_TA;
3825 }
3826
3827 add_ipv6_pool_to_subnet(group->subnet, type, &lo,
3828 bits, 128);
98bd7ca0 3829
80c9fdb0
FD
3830 } else if (token == TEMPORARY) {
3831 /*
3832 * temporary (RFC 4941)
3833 */
783259b1 3834 type = D6O_IA_TA;
80c9fdb0
FD
3835 next_token(NULL, NULL, cfile);
3836 bits = 64;
3837 if (!is_cidr_mask_valid(&lo, bits)) {
3838 parse_warn(cfile, "network mask too short");
3839 skip_to_semi(cfile);
3840 return;
3841 }
80c9fdb0 3842
783259b1
FD
3843 add_ipv6_pool_to_subnet(group->subnet, type, &lo,
3844 bits, 128);
98bd7ca0
DH
3845 } else {
3846 /*
3847 * No '/', so we are looking for the end address of
3848 * the IPv6 pool.
3849 */
3850 if (!parse_ip6_addr(cfile, &hi)) {
3851 return;
3852 }
3853
3854 /*
3855 * Convert our range to a set of CIDR networks.
3856 */
3857 nets = NULL;
3858 if (range2cidr(&nets, &lo, &hi) != ISC_R_SUCCESS) {
3859 log_fatal("Error converting range to CIDR networks");
3860 }
3861
3862 for (p=nets; p != NULL; p=p->next) {
783259b1 3863 add_ipv6_pool_to_subnet(group->subnet, type,
7d6180be
DH
3864 &p->cidrnet.lo_addr,
3865 p->cidrnet.bits, 128);
98bd7ca0
DH
3866 }
3867
3868 free_iaddrcidrnetlist(&nets);
98bd7ca0
DH
3869 }
3870
3871 token = next_token(NULL, NULL, cfile);
3872 if (token != SEMI) {
3873 parse_warn(cfile, "semicolon expected.");
3874 skip_to_semi(cfile);
3875 return;
3876 }
3877}
80c9fdb0 3878
80c9fdb0
FD
3879/* prefix6-declaration :== ip-address6 ip-address6 SLASH number SEMI */
3880
3881void
3882parse_prefix6(struct parse *cfile, struct group *group) {
3883 struct iaddr lo, hi;
3884 int bits;
3885 enum dhcp_token token;
3886 const char *val;
3887 struct iaddrcidrnetlist *nets;
3888 struct iaddrcidrnetlist *p;
3889
bd72740e
FD
3890 if (local_family != AF_INET6) {
3891 parse_warn(cfile, "prefix6 statement is only supported "
3892 "in DHCPv6 mode.");
3893 skip_to_semi(cfile);
3894 return;
3895 }
3896
7d6180be
DH
3897 /* This is enforced by the caller, so it's just a sanity check. */
3898 if (group->subnet == NULL)
3899 log_fatal("Impossible condition at %s:%d.", MDL);
3900
80c9fdb0
FD
3901 /*
3902 * Read starting and ending address.
3903 */
3904 if (!parse_ip6_addr(cfile, &lo)) {
3905 return;
3906 }
3907 if (!parse_ip6_addr(cfile, &hi)) {
3908 return;
3909 }
3910
3911 /*
3912 * Next is '/' number ';'.
3913 */
3914 token = next_token(NULL, NULL, cfile);
3915 if (token != SLASH) {
3916 parse_warn(cfile, "expecting '/'");
3917 if (token != SEMI)
3918 skip_to_semi(cfile);
3919 return;
3920 }
3921 token = next_token(&val, NULL, cfile);
3922 if (token != NUMBER) {
3923 parse_warn(cfile, "expecting number");
3924 if (token != SEMI)
3925 skip_to_semi(cfile);
3926 return;
3927 }
3928 bits = atoi(val);
3929 if ((bits <= 0) || (bits >= 128)) {
3930 parse_warn(cfile, "networks have 0 to 128 bits (exclusive)");
3931 return;
3932 }
3933 if (!is_cidr_mask_valid(&lo, bits) ||
3934 !is_cidr_mask_valid(&hi, bits)) {
3935 parse_warn(cfile, "network mask too short");
3936 return;
3937 }
3938 token = next_token(NULL, NULL, cfile);
3939 if (token != SEMI) {
3940 parse_warn(cfile, "semicolon expected.");
3941 skip_to_semi(cfile);
3942 return;
3943 }
3944
80c9fdb0
FD
3945 /*
3946 * Convert our range to a set of CIDR networks.
3947 */
3948 nets = NULL;
3949 if (range2cidr(&nets, &lo, &hi) != ISC_R_SUCCESS) {
3950 log_fatal("Error converting prefix to CIDR");
3951 }
3952
3953 for (p = nets; p != NULL; p = p->next) {
3954 /* Normalize and check. */
3955 if (p->cidrnet.bits == 128) {
3956 p->cidrnet.bits = bits;
3957 }
3958 if (p->cidrnet.bits > bits) {
3959 parse_warn(cfile, "impossible mask length");
3960 continue;
3961 }
7d6180be
DH
3962 add_ipv6_pool_to_subnet(group->subnet, D6O_IA_PD,
3963 &p->cidrnet.lo_addr,
3964 p->cidrnet.bits, bits);
80c9fdb0
FD
3965 }
3966
3967 free_iaddrcidrnetlist(&nets);
3968}
3969
3970/* fixed-prefix6 :== ip6-address SLASH number SEMI */
3971
3972void
3973parse_fixed_prefix6(struct parse *cfile, struct host_decl *host_decl) {
3974 struct iaddrcidrnetlist *ia, **h;
3975 enum dhcp_token token;
3976 const char *val;
3977
3978 /*
3979 * Get the head of the fixed-prefix list.
3980 */
3981 h = &host_decl->fixed_prefix;
3982
3983 /*
3984 * Walk to the end.
3985 */
3986 while (*h != NULL) {
3987 h = &((*h)->next);
3988 }
3989
3990 /*
3991 * Allocate a new iaddrcidrnetlist structure.
3992 */
3993 ia = dmalloc(sizeof(*ia), MDL);
3994 if (!ia) {
3995 log_fatal("Out of memory");
3996 }
3997
3998 /*
3999 * Parse it.
4000 */
4001 if (!parse_ip6_addr(cfile, &ia->cidrnet.lo_addr)) {
4002 dfree(ia, MDL);
4003 return;
4004 }
4005 token = next_token(NULL, NULL, cfile);
4006 if (token != SLASH) {
4007 dfree(ia, MDL);
4008 parse_warn(cfile, "expecting '/'");
4009 if (token != SEMI)
4010 skip_to_semi(cfile);
4011 return;
4012 }
4013 token = next_token(&val, NULL, cfile);
4014 if (token != NUMBER) {
4015 dfree(ia, MDL);
4016 parse_warn(cfile, "expecting number");
4017 if (token != SEMI)
4018 skip_to_semi(cfile);
4019 return;
4020 }
4021 token = next_token(NULL, NULL, cfile);
4022 if (token != SEMI) {
4023 dfree(ia, MDL);
4024 parse_warn(cfile, "semicolon expected.");
4025 skip_to_semi(cfile);
4026 return;
4027 }
4028
4029 /*
4030 * Fill it.
4031 */
4032 ia->cidrnet.bits = atoi(val);
4033 if ((ia->cidrnet.bits < 0) || (ia->cidrnet.bits > 128)) {
4034 dfree(ia, MDL);
4035 parse_warn(cfile, "networks have 0 to 128 bits");
4036 return;
4037 }
4038 if (!is_cidr_mask_valid(&ia->cidrnet.lo_addr, ia->cidrnet.bits)) {
4039 dfree(ia, MDL);
4040 parse_warn(cfile, "network mask too short");
4041 return;
4042 }
4043
4044 /*
4045 * Store it.
4046 */
4047 *h = ia;
4048 return;
4049}
fe5b0fdd 4050#endif /* DHCPv6 */
98bd7ca0 4051
c358155d
TL
4052/* allow-deny-keyword :== BOOTP
4053 | BOOTING
4054 | DYNAMIC_BOOTP
1db5e2c0 4055 | UNKNOWN_CLIENTS */
c358155d
TL
4056
4057int parse_allow_deny (oc, cfile, flag)
4058 struct option_cache **oc;
4059 struct parse *cfile;
4060 int flag;
4061{
4062 enum dhcp_token token;
4063 const char *val;
4064 unsigned char rf = flag;
f7fdb216
DH
4065 unsigned code;
4066 struct option *option = NULL;
c358155d
TL
4067 struct expression *data = (struct expression *)0;
4068 int status;
4069
d758ad8c 4070 if (!make_const_data (&data, &rf, 1, 0, 1, MDL))
c358155d
TL
4071 return 0;
4072
b3519f23 4073 token = next_token (&val, (unsigned *)0, cfile);
c358155d 4074 switch (token) {
007e3ee4 4075 case TOKEN_BOOTP:
f7fdb216 4076 code = SV_ALLOW_BOOTP;
c358155d
TL
4077 break;
4078
4079 case BOOTING:
f7fdb216 4080 code = SV_ALLOW_BOOTING;
c358155d
TL
4081 break;
4082
4083 case DYNAMIC_BOOTP:
f7fdb216 4084 code = SV_DYNAMIC_BOOTP;
c358155d
TL
4085 break;
4086
4087 case UNKNOWN_CLIENTS:
f7fdb216 4088 code = SV_BOOT_UNKNOWN_CLIENTS;
c358155d
TL
4089 break;
4090
4091 case DUPLICATES:
f7fdb216 4092 code = SV_DUPLICATES;
c358155d
TL
4093 break;
4094
4095 case DECLINES:
f7fdb216 4096 code= SV_DECLINES;
c358155d
TL
4097 break;
4098
6fdcc1a0 4099 case CLIENT_UPDATES:
f7fdb216 4100 code = SV_CLIENT_UPDATES;
6fdcc1a0
TL
4101 break;
4102
6d103865
SK
4103 case LEASEQUERY:
4104 code = SV_LEASEQUERY;
4105 break;
4106
c358155d
TL
4107 default:
4108 parse_warn (cfile, "expecting allow/deny key");
4109 skip_to_semi (cfile);
4110 return 0;
4111 }
f7fdb216
DH
4112 /* Reference on option is passed to option cache. */
4113 if (!option_code_hash_lookup(&option, server_universe.code_hash,
4114 &code, 0, MDL))
4115 log_fatal("Unable to find server option %u (%s:%d).",
4116 code, MDL);
4117 status = option_cache(oc, NULL, data, option, MDL);
d758ad8c 4118 expression_dereference (&data, MDL);
c358155d
TL
4119 parse_semi (cfile);
4120 return status;
4121}
4122
98bd7ca0
DH
4123void
4124parse_ia_na_declaration(struct parse *cfile) {
28868515
SK
4125#if !defined(DHCPv6)
4126 parse_warn(cfile, "No DHCPv6 support.");
4127 skip_to_semi(cfile);
4128#else /* defined(DHCPv6) */
98bd7ca0 4129 enum dhcp_token token;
9322442f 4130 struct ia_xx *ia;
98bd7ca0 4131 const char *val;
9322442f 4132 struct ia_xx *old_ia;
28868515 4133 unsigned int len;
98bd7ca0
DH
4134 u_int32_t iaid;
4135 struct iaddr iaddr;
4136 binding_state_t state;
1acab09f
FD
4137 u_int32_t prefer;
4138 u_int32_t valid;
98bd7ca0 4139 TIME end_time;
1d17db44 4140 struct iasubopt *iaaddr;
98bd7ca0
DH
4141 struct ipv6_pool *pool;
4142 char addr_buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
7285af30
DH
4143 isc_boolean_t newbinding;
4144 struct binding_scope *scope=NULL;
4145 struct binding *bnd;
4146 struct binding_value *nv=NULL;
98bd7ca0 4147
771484ac
EH
4148 if (local_family != AF_INET6) {
4149 parse_warn(cfile, "IA_NA is only supported in DHCPv6 mode.");
4150 skip_to_semi(cfile);
4151 return;
4152 }
4153
98bd7ca0
DH
4154 token = next_token(&val, &len, cfile);
4155 if (token != STRING) {
4156 parse_warn(cfile, "corrupt lease file; "
4157 "expecting an iaid+ia_na string");
4158 skip_to_semi(cfile);
4159 return;
4160 }
4161 if (len < 5) {
4162 parse_warn(cfile, "corrupt lease file; "
4163 "iaid+ia_na string too short");
4164 skip_to_semi(cfile);
4165 return;
4166 }
4167
4168 memcpy(&iaid, val, 4);
1d9774ab 4169 ia = NULL;
9322442f 4170 if (ia_allocate(&ia, iaid, val+4, len-4, MDL) != ISC_R_SUCCESS) {
98bd7ca0
DH
4171 log_fatal("Out of memory.");
4172 }
1d9774ab 4173 ia->ia_type = D6O_IA_NA;
98bd7ca0
DH
4174
4175 token = next_token(&val, NULL, cfile);
4176 if (token != LBRACE) {
4177 parse_warn(cfile, "corrupt lease file; expecting left brace");
4178 skip_to_semi(cfile);
4179 return;
4180 }
4181
4182 for (;;) {
4183 token = next_token(&val, NULL, cfile);
4184 if (token == RBRACE) break;
4185
1acab09f
FD
4186 if (token == CLTT) {
4187 ia->cltt = parse_date (cfile);
4188 continue;
4189 }
4190
98bd7ca0
DH
4191 if (token != IAADDR) {
4192 parse_warn(cfile, "corrupt lease file; "
4193 "expecting IAADDR or right brace");
4194 skip_to_semi(cfile);
4195 return;
4196 }
4197
4198 if (!parse_ip6_addr(cfile, &iaddr)) {
4199 parse_warn(cfile, "corrupt lease file; "
4200 "expecting IPv6 address");
4201 skip_to_semi(cfile);
4202 return;
4203 }
4204
4205 token = next_token(&val, NULL, cfile);
4206 if (token != LBRACE) {
4207 parse_warn(cfile, "corrupt lease file; "
4208 "expecting left brace");
4209 skip_to_semi(cfile);
4210 return;
4211 }
4212
4213 state = FTS_LAST+1;
1acab09f 4214 prefer = valid = 0;
98bd7ca0
DH
4215 end_time = -1;
4216 for (;;) {
4217 token = next_token(&val, NULL, cfile);
4218 if (token == RBRACE) break;
4219
7285af30
DH
4220 switch(token) {
4221 /* Lease binding state. */
4222 case BINDING:
98bd7ca0
DH
4223 token = next_token(&val, NULL, cfile);
4224 if (token != STATE) {
4225 parse_warn(cfile, "corrupt lease file; "
4226 "expecting state");
4227 skip_to_semi(cfile);
4228 return;
4229 }
4230 token = next_token(&val, NULL, cfile);
4231 switch (token) {
4232 case TOKEN_ABANDONED:
4233 state = FTS_ABANDONED;
4234 break;
4235 case TOKEN_FREE:
4236 state = FTS_FREE;
4237 break;
4238 case TOKEN_ACTIVE:
4239 state = FTS_ACTIVE;
4240 break;
4241 case TOKEN_EXPIRED:
4242 state = FTS_EXPIRED;
4243 break;
4244 case TOKEN_RELEASED:
4245 state = FTS_RELEASED;
4246 break;
4247 default:
4248 parse_warn(cfile,
4249 "corrupt lease "
4250 "file; "
4251 "expecting a "
4252 "binding state.");
4253 skip_to_semi(cfile);
4254 return;
4255 }
4256
4257 token = next_token(&val, NULL, cfile);
4258 if (token != SEMI) {
4259 parse_warn(cfile, "corrupt lease file; "
4260 "expecting "
4261 "semicolon.");
4262 }
7285af30 4263 break;
98bd7ca0 4264
1acab09f
FD
4265 /* Lease preferred lifetime. */
4266 case PREFERRED_LIFE:
4267 token = next_token(&val, NULL, cfile);
4268 if (token != NUMBER) {
4269 parse_warn(cfile, "%s is not a valid "
4270 "preferred time",
4271 val);
4272 skip_to_semi(cfile);
4273 continue;
4274 }
4275 prefer = atoi (val);
ad59838e
SR
4276
4277 /*
4278 * Currently we peek for the semi-colon to
4279 * allow processing of older lease files that
4280 * don't have the semi-colon. Eventually we
4281 * should remove the peeking code.
4282 */
4283 token = peek_token(&val, NULL, cfile);
4284 if (token == SEMI) {
4285 token = next_token(&val, NULL, cfile);
4286 } else {
4287 parse_warn(cfile,
4288 "corrupt lease file; "
4289 "expecting semicolon.");
4290 }
1acab09f
FD
4291 break;
4292
4293 /* Lease valid lifetime. */
4294 case MAX_LIFE:
4295 token = next_token(&val, NULL, cfile);
4296 if (token != NUMBER) {
4297 parse_warn(cfile, "%s is not a valid "
4298 "max time",
4299 val);
4300 skip_to_semi(cfile);
4301 continue;
4302 }
4303 valid = atoi (val);
ad59838e
SR
4304
4305 /*
4306 * Currently we peek for the semi-colon to
4307 * allow processing of older lease files that
4308 * don't have the semi-colon. Eventually we
4309 * should remove the peeking code.
4310 */
4311 token = peek_token(&val, NULL, cfile);
4312 if (token == SEMI) {
4313 token = next_token(&val, NULL, cfile);
4314 } else {
4315 parse_warn(cfile,
4316 "corrupt lease file; "
4317 "expecting semicolon.");
4318 }
1acab09f
FD
4319 break;
4320
7285af30
DH
4321 /* Lease expiration time. */
4322 case ENDS:
98bd7ca0 4323 end_time = parse_date(cfile);
7285af30
DH
4324 break;
4325
4326 /* Lease binding scopes. */
4327 case TOKEN_SET:
4328 token = next_token(&val, NULL, cfile);
4329 if ((token != NAME) &&
4330 (token != NUMBER_OR_NAME)) {
4331 parse_warn(cfile, "%s is not a valid "
4332 "variable name",
4333 val);
4334 skip_to_semi(cfile);
4335 continue;
4336 }
4337
4338 if (scope != NULL)
4339 bnd = find_binding(scope, val);
4340 else {
4341 if (!binding_scope_allocate(&scope,
4342 MDL)) {
4343 log_fatal("Out of memory for "
4344 "lease binding "
4345 "scope.");
4346 }
4347
4348 bnd = NULL;
4349 }
4350
4351 if (bnd == NULL) {
4352 bnd = dmalloc(sizeof(*bnd),
4353 MDL);
4354 if (bnd == NULL) {
4355 log_fatal("No memory for "
4356 "lease binding.");
4357 }
4358
4359 bnd->name = dmalloc(strlen(val) + 1,
4360 MDL);
4361 if (bnd->name == NULL) {
4362 log_fatal("No memory for "
4363 "binding name.");
4364 }
4365 strcpy(bnd->name, val);
4366
4367 newbinding = ISC_TRUE;
4368 } else {
4369 newbinding = ISC_FALSE;
4370 }
4371
4372 if (!binding_value_allocate(&nv, MDL)) {
4373 log_fatal("no memory for binding "
4374 "value.");
4375 }
4376
4377 token = next_token(NULL, NULL, cfile);
4378 if (token != EQUAL) {
4379 parse_warn(cfile, "expecting '=' in "
4380 "set statement.");
4381 goto binding_err;
4382 }
4383
4384 if (!parse_binding_value(cfile, nv)) {
4385 binding_err:
4386 binding_value_dereference(&nv, MDL);
4387 binding_scope_dereference(&scope, MDL);
4388 return;
4389 }
4390
4391 if (newbinding) {
4392 binding_value_reference(&bnd->value,
4393 nv, MDL);
4394 bnd->next = scope->bindings;
4395 scope->bindings = bnd;
4396 } else {
4397 binding_value_dereference(&bnd->value,
4398 MDL);
4399 binding_value_reference(&bnd->value,
4400 nv, MDL);
4401 }
4402
4403 binding_value_dereference(&nv, MDL);
4404 parse_semi(cfile);
4405 break;
4406
4407 default:
98bd7ca0 4408 parse_warn(cfile, "corrupt lease file; "
7285af30 4409 "expecting ia_na contents, "
98bd7ca0
DH
4410 "got '%s'", val);
4411 skip_to_semi(cfile);
7285af30 4412 continue;
98bd7ca0
DH
4413 }
4414 }
4415
4416 if (state == FTS_LAST+1) {
4417 parse_warn(cfile, "corrupt lease file; "
4418 "missing state in iaaddr");
4419 return;
4420 }
4421 if (end_time == -1) {
4422 parse_warn(cfile, "corrupt lease file; "
4423 "missing end time in iaaddr");
4424 return;
4425 }
4426
4427 iaaddr = NULL;
1d17db44 4428 if (iasubopt_allocate(&iaaddr, MDL) != ISC_R_SUCCESS) {
98bd7ca0
DH
4429 log_fatal("Out of memory.");
4430 }
4431 memcpy(&iaaddr->addr, iaddr.iabuf, sizeof(iaaddr->addr));
9322442f 4432 iaaddr->plen = 0;
98bd7ca0 4433 iaaddr->state = state;
1acab09f
FD
4434 iaaddr->prefer = prefer;
4435 iaaddr->valid = valid;
5d89d60f
FD
4436 if (iaaddr->state == FTS_RELEASED)
4437 iaaddr->hard_lifetime_end_time = end_time;
98bd7ca0 4438
7285af30
DH
4439 if (scope != NULL) {
4440 binding_scope_reference(&iaaddr->scope, scope, MDL);
4441 binding_scope_dereference(&scope, MDL);
4442 }
4443
bc7f8b8e 4444 /* find the pool this address is in */
98bd7ca0 4445 pool = NULL;
9322442f
FD
4446 if (find_ipv6_pool(&pool, D6O_IA_NA,
4447 &iaaddr->addr) != ISC_R_SUCCESS) {
4448 inet_ntop(AF_INET6, &iaaddr->addr,
98bd7ca0 4449 addr_buf, sizeof(addr_buf));
bc7f8b8e 4450 parse_warn(cfile, "no pool found for address %s",
98bd7ca0
DH
4451 addr_buf);
4452 return;
4453 }
bc7f8b8e
SR
4454
4455 /* remove old information */
4456 if (cleanup_lease6(ia_na_active, pool,
4457 iaaddr, ia) != ISC_R_SUCCESS) {
4458 inet_ntop(AF_INET6, &iaaddr->addr,
4459 addr_buf, sizeof(addr_buf));
4460 parse_warn(cfile, "duplicate na lease for address %s",
4461 addr_buf);
4462 }
4463
4464 /*
4465 * if we like the lease we add it to our various structues
4466 * otherwise we leave it and it will get cleaned when we
4467 * do the iasubopt_dereference.
4468 */
4469 if ((state == FTS_ACTIVE) || (state == FTS_ABANDONED)) {
4470 ia_add_iasubopt(ia, iaaddr, MDL);
4471 ia_reference(&iaaddr->ia, ia, MDL);
4472 add_lease6(pool, iaaddr, end_time);
4473 }
4474
1d17db44 4475 iasubopt_dereference(&iaaddr, MDL);
bc7f8b8e 4476 ipv6_pool_dereference(&pool, MDL);
98bd7ca0
DH
4477 }
4478
d9b43370
SK
4479 /*
4480 * If we have an existing record for this IA_NA, remove it.
4481 */
1d9774ab 4482 old_ia = NULL;
9322442f
FD
4483 if (ia_hash_lookup(&old_ia, ia_na_active,
4484 (unsigned char *)ia->iaid_duid.data,
4485 ia->iaid_duid.len, MDL)) {
4486 ia_hash_delete(ia_na_active,
4487 (unsigned char *)ia->iaid_duid.data,
4488 ia->iaid_duid.len, MDL);
4489 ia_dereference(&old_ia, MDL);
d9b43370
SK
4490 }
4491
4492 /*
4493 * If we have addresses, add this, otherwise don't bother.
4494 */
1d17db44 4495 if (ia->num_iasubopt > 0) {
9322442f
FD
4496 ia_hash_add(ia_na_active,
4497 (unsigned char *)ia->iaid_duid.data,
4498 ia->iaid_duid.len, ia, MDL);
d9b43370 4499 }
9322442f 4500 ia_dereference(&ia, MDL);
1d9774ab
FD
4501#endif /* defined(DHCPv6) */
4502}
4503
4504void
4505parse_ia_ta_declaration(struct parse *cfile) {
4506#if !defined(DHCPv6)
4507 parse_warn(cfile, "No DHCPv6 support.");
4508 skip_to_semi(cfile);
4509#else /* defined(DHCPv6) */
4510 enum dhcp_token token;
9322442f 4511 struct ia_xx *ia;
1d9774ab 4512 const char *val;
9322442f 4513 struct ia_xx *old_ia;
1d9774ab
FD
4514 unsigned int len;
4515 u_int32_t iaid;
4516 struct iaddr iaddr;
4517 binding_state_t state;
1acab09f
FD
4518 u_int32_t prefer;
4519 u_int32_t valid;
1d9774ab 4520 TIME end_time;
1d17db44 4521 struct iasubopt *iaaddr;
1d9774ab
FD
4522 struct ipv6_pool *pool;
4523 char addr_buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
4524 isc_boolean_t newbinding;
4525 struct binding_scope *scope=NULL;
4526 struct binding *bnd;
4527 struct binding_value *nv=NULL;
4528
771484ac
EH
4529 if (local_family != AF_INET6) {
4530 parse_warn(cfile, "IA_TA is only supported in DHCPv6 mode.");
4531 skip_to_semi(cfile);
4532 return;
4533 }
4534
1d9774ab
FD
4535 token = next_token(&val, &len, cfile);
4536 if (token != STRING) {
4537 parse_warn(cfile, "corrupt lease file; "
4538 "expecting an iaid+ia_ta string");
4539 skip_to_semi(cfile);
4540 return;
4541 }
4542 if (len < 5) {
4543 parse_warn(cfile, "corrupt lease file; "
4544 "iaid+ia_ta string too short");
4545 skip_to_semi(cfile);
4546 return;
4547 }
4548
4549 memcpy(&iaid, val, 4);
4550 ia = NULL;
9322442f 4551 if (ia_allocate(&ia, iaid, val+4, len-4, MDL) != ISC_R_SUCCESS) {
1d9774ab
FD
4552 log_fatal("Out of memory.");
4553 }
4554 ia->ia_type = D6O_IA_TA;
4555
4556 token = next_token(&val, NULL, cfile);
4557 if (token != LBRACE) {
4558 parse_warn(cfile, "corrupt lease file; expecting left brace");
4559 skip_to_semi(cfile);
4560 return;
4561 }
4562
4563 for (;;) {
4564 token = next_token(&val, NULL, cfile);
4565 if (token == RBRACE) break;
4566
1acab09f
FD
4567 if (token == CLTT) {
4568 ia->cltt = parse_date (cfile);
4569 continue;
4570 }
4571
1d9774ab
FD
4572 if (token != IAADDR) {
4573 parse_warn(cfile, "corrupt lease file; "
4574 "expecting IAADDR or right brace");
4575 skip_to_semi(cfile);
4576 return;
4577 }
4578
4579 if (!parse_ip6_addr(cfile, &iaddr)) {
4580 parse_warn(cfile, "corrupt lease file; "
4581 "expecting IPv6 address");
4582 skip_to_semi(cfile);
4583 return;
4584 }
4585
4586 token = next_token(&val, NULL, cfile);
4587 if (token != LBRACE) {
4588 parse_warn(cfile, "corrupt lease file; "
4589 "expecting left brace");
4590 skip_to_semi(cfile);
4591 return;
4592 }
4593
4594 state = FTS_LAST+1;
1acab09f 4595 prefer = valid = 0;
1d9774ab
FD
4596 end_time = -1;
4597 for (;;) {
4598 token = next_token(&val, NULL, cfile);
4599 if (token == RBRACE) break;
4600
4601 switch(token) {
4602 /* Lease binding state. */
4603 case BINDING:
4604 token = next_token(&val, NULL, cfile);
4605 if (token != STATE) {
4606 parse_warn(cfile, "corrupt lease file; "
4607 "expecting state");
4608 skip_to_semi(cfile);
4609 return;
4610 }
4611 token = next_token(&val, NULL, cfile);
4612 switch (token) {
4613 case TOKEN_ABANDONED:
4614 state = FTS_ABANDONED;
4615 break;
4616 case TOKEN_FREE:
4617 state = FTS_FREE;
4618 break;
4619 case TOKEN_ACTIVE:
4620 state = FTS_ACTIVE;
4621 break;
4622 case TOKEN_EXPIRED:
4623 state = FTS_EXPIRED;
4624 break;
4625 case TOKEN_RELEASED:
4626 state = FTS_RELEASED;
4627 break;
4628 default:
4629 parse_warn(cfile,
4630 "corrupt lease "
4631 "file; "
4632 "expecting a "
4633 "binding state.");
4634 skip_to_semi(cfile);
4635 return;
4636 }
4637
4638 token = next_token(&val, NULL, cfile);
4639 if (token != SEMI) {
4640 parse_warn(cfile, "corrupt lease file; "
4641 "expecting "
4642 "semicolon.");
4643 }
4644 break;
4645
1acab09f
FD
4646 /* Lease preferred lifetime. */
4647 case PREFERRED_LIFE:
4648 token = next_token(&val, NULL, cfile);
4649 if (token != NUMBER) {
4650 parse_warn(cfile, "%s is not a valid "
4651 "preferred time",
4652 val);
4653 skip_to_semi(cfile);
4654 continue;
4655 }
4656 prefer = atoi (val);
ad59838e
SR
4657
4658 /*
4659 * Currently we peek for the semi-colon to
4660 * allow processing of older lease files that
4661 * don't have the semi-colon. Eventually we
4662 * should remove the peeking code.
4663 */
4664 token = peek_token(&val, NULL, cfile);
4665 if (token == SEMI) {
4666 token = next_token(&val, NULL, cfile);
4667 } else {
4668 parse_warn(cfile,
4669 "corrupt lease file; "
4670 "expecting semicolon.");
4671 }
1acab09f
FD
4672 break;
4673
4674 /* Lease valid lifetime. */
4675 case MAX_LIFE:
4676 token = next_token(&val, NULL, cfile);
4677 if (token != NUMBER) {
4678 parse_warn(cfile, "%s is not a valid "
4679 "max time",
4680 val);
4681 skip_to_semi(cfile);
4682 continue;
4683 }
4684 valid = atoi (val);
ad59838e
SR
4685
4686 /*
4687 * Currently we peek for the semi-colon to
4688 * allow processing of older lease files that
4689 * don't have the semi-colon. Eventually we
4690 * should remove the peeking code.
4691 */
4692 token = peek_token(&val, NULL, cfile);
4693 if (token == SEMI) {
4694 token = next_token(&val, NULL, cfile);
4695 } else {
4696 parse_warn(cfile,
4697 "corrupt lease file; "
4698 "expecting semicolon.");
4699 }
1acab09f
FD
4700 break;
4701
1d9774ab
FD
4702 /* Lease expiration time. */
4703 case ENDS:
4704 end_time = parse_date(cfile);
4705 break;
4706
4707 /* Lease binding scopes. */
4708 case TOKEN_SET:
4709 token = next_token(&val, NULL, cfile);
4710 if ((token != NAME) &&
4711 (token != NUMBER_OR_NAME)) {
4712 parse_warn(cfile, "%s is not a valid "
4713 "variable name",
4714 val);
4715 skip_to_semi(cfile);
4716 continue;
4717 }
4718
4719 if (scope != NULL)
4720 bnd = find_binding(scope, val);
4721 else {
4722 if (!binding_scope_allocate(&scope,
4723 MDL)) {
4724 log_fatal("Out of memory for "
4725 "lease binding "
4726 "scope.");
4727 }
4728
4729 bnd = NULL;
4730 }
4731
4732 if (bnd == NULL) {
4733 bnd = dmalloc(sizeof(*bnd),
4734 MDL);
4735 if (bnd == NULL) {
4736 log_fatal("No memory for "
4737 "lease binding.");
4738 }
4739
4740 bnd->name = dmalloc(strlen(val) + 1,
4741 MDL);
4742 if (bnd->name == NULL) {
4743 log_fatal("No memory for "
4744 "binding name.");
4745 }
4746 strcpy(bnd->name, val);
4747
4748 newbinding = ISC_TRUE;
4749 } else {
4750 newbinding = ISC_FALSE;
4751 }
4752
4753 if (!binding_value_allocate(&nv, MDL)) {
4754 log_fatal("no memory for binding "
4755 "value.");
4756 }
4757
4758 token = next_token(NULL, NULL, cfile);
4759 if (token != EQUAL) {
4760 parse_warn(cfile, "expecting '=' in "
4761 "set statement.");
4762 goto binding_err;
4763 }
4764
4765 if (!parse_binding_value(cfile, nv)) {
4766 binding_err:
4767 binding_value_dereference(&nv, MDL);
4768 binding_scope_dereference(&scope, MDL);
4769 return;
4770 }
4771
4772 if (newbinding) {
4773 binding_value_reference(&bnd->value,
4774 nv, MDL);
4775 bnd->next = scope->bindings;
4776 scope->bindings = bnd;
4777 } else {
4778 binding_value_dereference(&bnd->value,
4779 MDL);
4780 binding_value_reference(&bnd->value,
4781 nv, MDL);
4782 }
4783
4784 binding_value_dereference(&nv, MDL);
4785 parse_semi(cfile);
4786 break;
4787
4788 default:
4789 parse_warn(cfile, "corrupt lease file; "
4790 "expecting ia_ta contents, "
4791 "got '%s'", val);
4792 skip_to_semi(cfile);
4793 continue;
4794 }
4795 }
4796
4797 if (state == FTS_LAST+1) {
4798 parse_warn(cfile, "corrupt lease file; "
4799 "missing state in iaaddr");
4800 return;
4801 }
4802 if (end_time == -1) {
4803 parse_warn(cfile, "corrupt lease file; "
4804 "missing end time in iaaddr");
4805 return;
4806 }
4807
4808 iaaddr = NULL;
1d17db44 4809 if (iasubopt_allocate(&iaaddr, MDL) != ISC_R_SUCCESS) {
1d9774ab
FD
4810 log_fatal("Out of memory.");
4811 }
4812 memcpy(&iaaddr->addr, iaddr.iabuf, sizeof(iaaddr->addr));
9322442f 4813 iaaddr->plen = 0;
1d9774ab 4814 iaaddr->state = state;
1acab09f
FD
4815 iaaddr->prefer = prefer;
4816 iaaddr->valid = valid;
5d89d60f
FD
4817 if (iaaddr->state == FTS_RELEASED)
4818 iaaddr->hard_lifetime_end_time = end_time;
1d9774ab
FD
4819
4820 if (scope != NULL) {
4821 binding_scope_reference(&iaaddr->scope, scope, MDL);
4822 binding_scope_dereference(&scope, MDL);
4823 }
4824
bc7f8b8e 4825 /* find the pool this address is in */
1d9774ab 4826 pool = NULL;
9322442f
FD
4827 if (find_ipv6_pool(&pool, D6O_IA_TA,
4828 &iaaddr->addr) != ISC_R_SUCCESS) {
4829 inet_ntop(AF_INET6, &iaaddr->addr,
1d9774ab 4830 addr_buf, sizeof(addr_buf));
bc7f8b8e 4831 parse_warn(cfile, "no pool found for address %s",
1d9774ab
FD
4832 addr_buf);
4833 return;
4834 }
bc7f8b8e
SR
4835
4836 /* remove old information */
4837 if (cleanup_lease6(ia_ta_active, pool,
4838 iaaddr, ia) != ISC_R_SUCCESS) {
4839 inet_ntop(AF_INET6, &iaaddr->addr,
4840 addr_buf, sizeof(addr_buf));
4841 parse_warn(cfile, "duplicate ta lease for address %s",
4842 addr_buf);
4843 }
4844
4845 /*
4846 * if we like the lease we add it to our various structues
4847 * otherwise we leave it and it will get cleaned when we
4848 * do the iasubopt_dereference.
4849 */
4850 if ((state == FTS_ACTIVE) || (state == FTS_ABANDONED)) {
4851 ia_add_iasubopt(ia, iaaddr, MDL);
4852 ia_reference(&iaaddr->ia, ia, MDL);
4853 add_lease6(pool, iaaddr, end_time);
4854 }
4855
1d9774ab 4856 ipv6_pool_dereference(&pool, MDL);
1d17db44 4857 iasubopt_dereference(&iaaddr, MDL);
1d9774ab
FD
4858 }
4859
4860 /*
4861 * If we have an existing record for this IA_TA, remove it.
4862 */
4863 old_ia = NULL;
9322442f
FD
4864 if (ia_hash_lookup(&old_ia, ia_ta_active,
4865 (unsigned char *)ia->iaid_duid.data,
4866 ia->iaid_duid.len, MDL)) {
4867 ia_hash_delete(ia_ta_active,
4868 (unsigned char *)ia->iaid_duid.data,
4869 ia->iaid_duid.len, MDL);
4870 ia_dereference(&old_ia, MDL);
1d9774ab
FD
4871 }
4872
4873 /*
4874 * If we have addresses, add this, otherwise don't bother.
4875 */
1d17db44 4876 if (ia->num_iasubopt > 0) {
9322442f
FD
4877 ia_hash_add(ia_ta_active,
4878 (unsigned char *)ia->iaid_duid.data,
4879 ia->iaid_duid.len, ia, MDL);
1d9774ab 4880 }
9322442f 4881 ia_dereference(&ia, MDL);
1d9774ab
FD
4882#endif /* defined(DHCPv6) */
4883}
4884
4885void
4886parse_ia_pd_declaration(struct parse *cfile) {
4887#if !defined(DHCPv6)
4888 parse_warn(cfile, "No DHCPv6 support.");
4889 skip_to_semi(cfile);
4890#else /* defined(DHCPv6) */
4891 enum dhcp_token token;
9322442f 4892 struct ia_xx *ia;
1d9774ab 4893 const char *val;
9322442f 4894 struct ia_xx *old_ia;
1d9774ab
FD
4895 unsigned int len;
4896 u_int32_t iaid;
4897 struct iaddr iaddr;
4898 u_int8_t plen;
4899 binding_state_t state;
1acab09f
FD
4900 u_int32_t prefer;
4901 u_int32_t valid;
1d9774ab 4902 TIME end_time;
1d17db44 4903 struct iasubopt *iapref;
9322442f 4904 struct ipv6_pool *pool;
1d9774ab
FD
4905 char addr_buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
4906 isc_boolean_t newbinding;
4907 struct binding_scope *scope=NULL;
4908 struct binding *bnd;
4909 struct binding_value *nv=NULL;
4910
771484ac
EH
4911 if (local_family != AF_INET6) {
4912 parse_warn(cfile, "IA_PD is only supported in DHCPv6 mode.");
4913 skip_to_semi(cfile);
4914 return;
4915 }
4916
1d9774ab
FD
4917 token = next_token(&val, &len, cfile);
4918 if (token != STRING) {
4919 parse_warn(cfile, "corrupt lease file; "
4920 "expecting an iaid+ia_pd string");
4921 skip_to_semi(cfile);
4922 return;
4923 }
4924 if (len < 5) {
4925 parse_warn(cfile, "corrupt lease file; "
4926 "iaid+ia_pd string too short");
4927 skip_to_semi(cfile);
4928 return;
4929 }
4930
4931 memcpy(&iaid, val, 4);
9322442f
FD
4932 ia = NULL;
4933 if (ia_allocate(&ia, iaid, val+4, len-4, MDL) != ISC_R_SUCCESS) {
1d9774ab
FD
4934 log_fatal("Out of memory.");
4935 }
9322442f 4936 ia->ia_type = D6O_IA_PD;
1d9774ab
FD
4937
4938 token = next_token(&val, NULL, cfile);
4939 if (token != LBRACE) {
4940 parse_warn(cfile, "corrupt lease file; expecting left brace");
4941 skip_to_semi(cfile);
4942 return;
4943 }
4944
4945 for (;;) {
4946 token = next_token(&val, NULL, cfile);
4947 if (token == RBRACE) break;
4948
1acab09f
FD
4949 if (token == CLTT) {
4950 ia->cltt = parse_date (cfile);
4951 continue;
4952 }
4953
1d9774ab
FD
4954 if (token != IAPREFIX) {
4955 parse_warn(cfile, "corrupt lease file; expecting "
4956 "IAPREFIX or right brace");
4957 skip_to_semi(cfile);
4958 return;
4959 }
4960
4961 if (!parse_ip6_prefix(cfile, &iaddr, &plen)) {
4962 parse_warn(cfile, "corrupt lease file; "
4963 "expecting IPv6 prefix");
4964 skip_to_semi(cfile);
4965 return;
4966 }
4967
4968 token = next_token(&val, NULL, cfile);
4969 if (token != LBRACE) {
4970 parse_warn(cfile, "corrupt lease file; "
4971 "expecting left brace");
4972 skip_to_semi(cfile);
4973 return;
4974 }
4975
4976 state = FTS_LAST+1;
1acab09f 4977 prefer = valid = 0;
1d9774ab
FD
4978 end_time = -1;
4979 for (;;) {
4980 token = next_token(&val, NULL, cfile);
4981 if (token == RBRACE) break;
4982
4983 switch(token) {
4984 /* Prefix binding state. */
4985 case BINDING:
4986 token = next_token(&val, NULL, cfile);
4987 if (token != STATE) {
4988 parse_warn(cfile, "corrupt lease file; "
4989 "expecting state");
4990 skip_to_semi(cfile);
4991 return;
4992 }
4993 token = next_token(&val, NULL, cfile);
4994 switch (token) {
4995 case TOKEN_ABANDONED:
4996 state = FTS_ABANDONED;
4997 break;
4998 case TOKEN_FREE:
4999 state = FTS_FREE;
5000 break;
5001 case TOKEN_ACTIVE:
5002 state = FTS_ACTIVE;
5003 break;
5004 case TOKEN_EXPIRED:
5005 state = FTS_EXPIRED;
5006 break;
5007 case TOKEN_RELEASED:
5008 state = FTS_RELEASED;
5009 break;
5010 default:
5011 parse_warn(cfile,
5012 "corrupt lease "
5013 "file; "
5014 "expecting a "
5015 "binding state.");
5016 skip_to_semi(cfile);
5017 return;
5018 }
5019
5020 token = next_token(&val, NULL, cfile);
5021 if (token != SEMI) {
5022 parse_warn(cfile, "corrupt lease file; "
5023 "expecting "
5024 "semicolon.");
5025 }
5026 break;
5027
1acab09f
FD
5028 /* Lease preferred lifetime. */
5029 case PREFERRED_LIFE:
5030 token = next_token(&val, NULL, cfile);
5031 if (token != NUMBER) {
5032 parse_warn(cfile, "%s is not a valid "
5033 "preferred time",
5034 val);
5035 skip_to_semi(cfile);
5036 continue;
5037 }
5038 prefer = atoi (val);
ad59838e
SR
5039
5040 /*
5041 * Currently we peek for the semi-colon to
5042 * allow processing of older lease files that
5043 * don't have the semi-colon. Eventually we
5044 * should remove the peeking code.
5045 */
5046 token = peek_token(&val, NULL, cfile);
5047 if (token == SEMI) {
5048 token = next_token(&val, NULL, cfile);
5049 } else {
5050 parse_warn(cfile,
5051 "corrupt lease file; "
5052 "expecting semicolon.");
5053 }
1acab09f
FD
5054 break;
5055
5056 /* Lease valid lifetime. */
5057 case MAX_LIFE:
5058 token = next_token(&val, NULL, cfile);
5059 if (token != NUMBER) {
5060 parse_warn(cfile, "%s is not a valid "
5061 "max time",
5062 val);
5063 skip_to_semi(cfile);
5064 continue;
5065 }
5066 valid = atoi (val);
ad59838e
SR
5067
5068 /*
5069 * Currently we peek for the semi-colon to
5070 * allow processing of older lease files that
5071 * don't have the semi-colon. Eventually we
5072 * should remove the peeking code.
5073 */
5074 token = peek_token(&val, NULL, cfile);
5075 if (token == SEMI) {
5076 token = next_token(&val, NULL, cfile);
5077 } else {
5078 parse_warn(cfile,
5079 "corrupt lease file; "
5080 "expecting semicolon.");
5081 }
1acab09f
FD
5082 break;
5083
1d9774ab
FD
5084 /* Prefix expiration time. */
5085 case ENDS:
5086 end_time = parse_date(cfile);
5087 break;
5088
5089 /* Prefix binding scopes. */
5090 case TOKEN_SET:
5091 token = next_token(&val, NULL, cfile);
5092 if ((token != NAME) &&
5093 (token != NUMBER_OR_NAME)) {
5094 parse_warn(cfile, "%s is not a valid "
5095 "variable name",
5096 val);
5097 skip_to_semi(cfile);
5098 continue;
5099 }
5100
5101 if (scope != NULL)
5102 bnd = find_binding(scope, val);
5103 else {
5104 if (!binding_scope_allocate(&scope,
5105 MDL)) {
5106 log_fatal("Out of memory for "
5107 "lease binding "
5108 "scope.");
5109 }
5110
5111 bnd = NULL;
5112 }
5113
5114 if (bnd == NULL) {
5115 bnd = dmalloc(sizeof(*bnd),
5116 MDL);
5117 if (bnd == NULL) {
5118 log_fatal("No memory for "
5119 "prefix binding.");
5120 }
5121
5122 bnd->name = dmalloc(strlen(val) + 1,
5123 MDL);
5124 if (bnd->name == NULL) {
5125 log_fatal("No memory for "
5126 "binding name.");
5127 }
5128 strcpy(bnd->name, val);
5129
5130 newbinding = ISC_TRUE;
5131 } else {
5132 newbinding = ISC_FALSE;
5133 }
5134
5135 if (!binding_value_allocate(&nv, MDL)) {
5136 log_fatal("no memory for binding "
5137 "value.");
5138 }
5139
5140 token = next_token(NULL, NULL, cfile);
5141 if (token != EQUAL) {
5142 parse_warn(cfile, "expecting '=' in "
5143 "set statement.");
5144 goto binding_err;
5145 }
5146
5147 if (!parse_binding_value(cfile, nv)) {
5148 binding_err:
5149 binding_value_dereference(&nv, MDL);
5150 binding_scope_dereference(&scope, MDL);
5151 return;
5152 }
5153
5154 if (newbinding) {
5155 binding_value_reference(&bnd->value,
5156 nv, MDL);
5157 bnd->next = scope->bindings;
5158 scope->bindings = bnd;
5159 } else {
5160 binding_value_dereference(&bnd->value,
5161 MDL);
5162 binding_value_reference(&bnd->value,
5163 nv, MDL);
5164 }
5165
5166 binding_value_dereference(&nv, MDL);
5167 parse_semi(cfile);
5168 break;
5169
5170 default:
5171 parse_warn(cfile, "corrupt lease file; "
5172 "expecting ia_pd contents, "
5173 "got '%s'", val);
5174 skip_to_semi(cfile);
5175 continue;
5176 }
5177 }
5178
5179 if (state == FTS_LAST+1) {
5180 parse_warn(cfile, "corrupt lease file; "
5181 "missing state in iaprefix");
5182 return;
5183 }
5184 if (end_time == -1) {
5185 parse_warn(cfile, "corrupt lease file; "
5186 "missing end time in iaprefix");
5187 return;
5188 }
5189
5190 iapref = NULL;
1d17db44 5191 if (iasubopt_allocate(&iapref, MDL) != ISC_R_SUCCESS) {
1d9774ab
FD
5192 log_fatal("Out of memory.");
5193 }
9322442f 5194 memcpy(&iapref->addr, iaddr.iabuf, sizeof(iapref->addr));
1d9774ab
FD
5195 iapref->plen = plen;
5196 iapref->state = state;
1acab09f
FD
5197 iapref->prefer = prefer;
5198 iapref->valid = valid;
5d89d60f
FD
5199 if (iapref->state == FTS_RELEASED)
5200 iapref->hard_lifetime_end_time = end_time;
1d9774ab
FD
5201
5202 if (scope != NULL) {
5203 binding_scope_reference(&iapref->scope, scope, MDL);
5204 binding_scope_dereference(&scope, MDL);
5205 }
5206
bc7f8b8e 5207 /* find the pool this address is in */
9322442f
FD
5208 pool = NULL;
5209 if (find_ipv6_pool(&pool, D6O_IA_PD,
5210 &iapref->addr) != ISC_R_SUCCESS) {
5211 inet_ntop(AF_INET6, &iapref->addr,
1d9774ab 5212 addr_buf, sizeof(addr_buf));
bc7f8b8e 5213 parse_warn(cfile, "no pool found for address %s",
1d9774ab
FD
5214 addr_buf);
5215 return;
5216 }
bc7f8b8e
SR
5217
5218 /* remove old information */
5219 if (cleanup_lease6(ia_pd_active, pool,
5220 iapref, ia) != ISC_R_SUCCESS) {
5221 inet_ntop(AF_INET6, &iapref->addr,
5222 addr_buf, sizeof(addr_buf));
5223 parse_warn(cfile, "duplicate pd lease for address %s",
5224 addr_buf);
5225 }
5226
5227 /*
5228 * if we like the lease we add it to our various structues
5229 * otherwise we leave it and it will get cleaned when we
5230 * do the iasubopt_dereference.
5231 */
5232 if ((state == FTS_ACTIVE) || (state == FTS_ABANDONED)) {
5233 ia_add_iasubopt(ia, iapref, MDL);
5234 ia_reference(&iapref->ia, ia, MDL);
5235 add_lease6(pool, iapref, end_time);
5236 }
5237
9322442f 5238 ipv6_pool_dereference(&pool, MDL);
1d17db44 5239 iasubopt_dereference(&iapref, MDL);
1d9774ab
FD
5240 }
5241
5242 /*
5243 * If we have an existing record for this IA_PD, remove it.
5244 */
9322442f
FD
5245 old_ia = NULL;
5246 if (ia_hash_lookup(&old_ia, ia_pd_active,
5247 (unsigned char *)ia->iaid_duid.data,
5248 ia->iaid_duid.len, MDL)) {
5249 ia_hash_delete(ia_pd_active,
5250 (unsigned char *)ia->iaid_duid.data,
5251 ia->iaid_duid.len, MDL);
5252 ia_dereference(&old_ia, MDL);
1d9774ab
FD
5253 }
5254
5255 /*
5256 * If we have prefixes, add this, otherwise don't bother.
5257 */
1d17db44 5258 if (ia->num_iasubopt > 0) {
9322442f
FD
5259 ia_hash_add(ia_pd_active,
5260 (unsigned char *)ia->iaid_duid.data,
5261 ia->iaid_duid.len, ia, MDL);
1d9774ab 5262 }
9322442f 5263 ia_dereference(&ia, MDL);
fe5b0fdd 5264#endif /* defined(DHCPv6) */
98bd7ca0
DH
5265}
5266
fe5b0fdd 5267#ifdef DHCPv6
98bd7ca0
DH
5268/*
5269 * When we parse a server-duid statement in a lease file, we are
5270 * looking at the saved server DUID from a previous run. In this case
5271 * we expect it to be followed by the binary representation of the
5272 * DUID stored in a string:
5273 *
5274 * server-duid "\000\001\000\001\015\221\034JRT\000\0224Y";
5275 */
5276void
5277parse_server_duid(struct parse *cfile) {
5278 enum dhcp_token token;
5279 const char *val;
28868515 5280 unsigned int len;
98bd7ca0
DH
5281 struct data_string duid;
5282
5283 token = next_token(&val, &len, cfile);
5284 if (token != STRING) {
5285 parse_warn(cfile, "corrupt lease file; expecting a DUID");
5286 skip_to_semi(cfile);
5287 return;
5288 }
5289
5290 memset(&duid, 0, sizeof(duid));
5291 duid.len = len;
5292 if (!buffer_allocate(&duid.buffer, duid.len, MDL)) {
5293 log_fatal("Out of memory storing DUID");
5294 }
28868515 5295 duid.data = (unsigned char *)duid.buffer->data;
98bd7ca0
DH
5296 memcpy(duid.buffer->data, val, len);
5297
5298 set_server_duid(&duid);
5299
5300 data_string_forget(&duid, MDL);
5301
5302 token = next_token(&val, &len, cfile);
5303 if (token != SEMI) {
5304 parse_warn(cfile, "corrupt lease file; expecting a semicolon");
5305 skip_to_semi(cfile);
5306 return;
5307 }
5308}
5309
5310/*
5311 * When we parse a server-duid statement in a config file, we will
5312 * have the type of the server DUID to generate, and possibly the
5313 * actual value defined.
5314 *
5315 * server-duid llt;
5316 * server-duid llt ethernet|ieee802|fddi 213982198 00:16:6F:49:7D:9B;
5317 * server-duid ll;
5318 * server-duid ll ethernet|ieee802|fddi 00:16:6F:49:7D:9B;
20ae1aff 5319 * server-duid en 2495 "enterprise-specific-identifier-1234";
98bd7ca0
DH
5320 */
5321void
5322parse_server_duid_conf(struct parse *cfile) {
5323 enum dhcp_token token;
5324 const char *val;
28868515 5325 unsigned int len;
98bd7ca0
DH
5326 u_int32_t enterprise_number;
5327 int ll_type;
5328 struct data_string ll_addr;
5329 u_int32_t llt_time;
5330 struct data_string duid;
5331 int duid_type_num;
5332
5333 /*
5334 * Consume the SERVER_DUID token.
5335 */
5336 token = next_token(NULL, NULL, cfile);
5337
5338 /*
5339 * Obtain the DUID type.
5340 */
5341 token = next_token(&val, NULL, cfile);
5342
5343 /*
5344 * Enterprise is the easiest - enterprise number and raw data
5345 * are required.
5346 */
5347 if (token == EN) {
5348 /*
5349 * Get enterprise number and identifier.
5350 */
5351 token = next_token(&val, NULL, cfile);
5352 if (token != NUMBER) {
5353 parse_warn(cfile, "enterprise number expected");
5354 skip_to_semi(cfile);
5355 return;
5356 }
5357 enterprise_number = atoi(val);
5358
5359 token = next_token(&val, &len, cfile);
5360 if (token != STRING) {
5361 parse_warn(cfile, "identifier expected");
5362 skip_to_semi(cfile);
5363 return;
5364 }
5365
5366 /*
5367 * Save the DUID.
5368 */
5369 memset(&duid, 0, sizeof(duid));
5370 duid.len = 2 + 4 + len;
5371 if (!buffer_allocate(&duid.buffer, duid.len, MDL)) {
5372 log_fatal("Out of memory storing DUID");
5373 }
28868515 5374 duid.data = (unsigned char *)duid.buffer->data;
98bd7ca0
DH
5375 putUShort(duid.buffer->data, DUID_EN);
5376 putULong(duid.buffer->data + 2, enterprise_number);
5377 memcpy(duid.buffer->data + 6, val, len);
5378
5379 set_server_duid(&duid);
5380 data_string_forget(&duid, MDL);
5381 }
5382
5383 /*
5384 * Next easiest is the link-layer DUID. It consists only of
5385 * the LL directive, or optionally the specific value to use.
5386 *
5387 * If we have LL only, then we set the type. If we have the
5388 * value, then we set the actual DUID.
5389 */
5390 else if (token == LL) {
5391 if (peek_token(NULL, NULL, cfile) == SEMI) {
5392 set_server_duid_type(DUID_LL);
5393 } else {
5394 /*
5395 * Get our hardware type and address.
5396 */
5397 token = next_token(NULL, NULL, cfile);
5398 switch (token) {
5399 case ETHERNET:
5400 ll_type = HTYPE_ETHER;
5401 break;
5402 case TOKEN_RING:
5403 ll_type = HTYPE_IEEE802;
5404 break;
219a65eb 5405 case TOKEN_FDDI:
98bd7ca0
DH
5406 ll_type = HTYPE_FDDI;
5407 break;
5408 default:
5409 parse_warn(cfile, "hardware type expected");
5410 skip_to_semi(cfile);
5411 return;
5412 }
5413 memset(&ll_addr, 0, sizeof(ll_addr));
5414 if (!parse_cshl(&ll_addr, cfile)) {
5415 return;
5416 }
5417
5418 /*
5419 * Save the DUID.
5420 */
5421 memset(&duid, 0, sizeof(duid));
5422 duid.len = 2 + 2 + ll_addr.len;
5423 if (!buffer_allocate(&duid.buffer, duid.len, MDL)) {
5424 log_fatal("Out of memory storing DUID");
5425 }
28868515 5426 duid.data = (unsigned char *)duid.buffer->data;
98bd7ca0
DH
5427 putUShort(duid.buffer->data, DUID_LL);
5428 putULong(duid.buffer->data + 2, ll_type);
5429 memcpy(duid.buffer->data + 4,
5430 ll_addr.data, ll_addr.len);
5431
5432 set_server_duid(&duid);
5433 data_string_forget(&duid, MDL);
5434 data_string_forget(&ll_addr, MDL);
5435 }
5436 }
5437
5438 /*
5439 * Finally the link-layer DUID plus time. It consists only of
5440 * the LLT directive, or optionally the specific value to use.
5441 *
5442 * If we have LLT only, then we set the type. If we have the
5443 * value, then we set the actual DUID.
5444 */
5445 else if (token == LLT) {
5446 if (peek_token(NULL, NULL, cfile) == SEMI) {
5447 set_server_duid_type(DUID_LLT);
5448 } else {
5449 /*
5450 * Get our hardware type, timestamp, and address.
5451 */
5452 token = next_token(NULL, NULL, cfile);
5453 switch (token) {
5454 case ETHERNET:
5455 ll_type = HTYPE_ETHER;
5456 break;
5457 case TOKEN_RING:
5458 ll_type = HTYPE_IEEE802;
5459 break;
219a65eb 5460 case TOKEN_FDDI:
98bd7ca0
DH
5461 ll_type = HTYPE_FDDI;
5462 break;
5463 default:
5464 parse_warn(cfile, "hardware type expected");
5465 skip_to_semi(cfile);
5466 return;
5467 }
5468
5469 token = next_token(&val, NULL, cfile);
5470 if (token != NUMBER) {
5471 parse_warn(cfile, "timestamp expected");
5472 skip_to_semi(cfile);
5473 return;
5474 }
5475 llt_time = atoi(val);
5476
5477 memset(&ll_addr, 0, sizeof(ll_addr));
5478 if (!parse_cshl(&ll_addr, cfile)) {
5479 return;
5480 }
5481
5482 /*
5483 * Save the DUID.
5484 */
5485 memset(&duid, 0, sizeof(duid));
5486 duid.len = 2 + 2 + 4 + ll_addr.len;
5487 if (!buffer_allocate(&duid.buffer, duid.len, MDL)) {
5488 log_fatal("Out of memory storing DUID");
5489 }
28868515 5490 duid.data = (unsigned char *)duid.buffer->data;
98bd7ca0
DH
5491 putUShort(duid.buffer->data, DUID_LLT);
5492 putULong(duid.buffer->data + 2, ll_type);
5493 putULong(duid.buffer->data + 4, llt_time);
5494 memcpy(duid.buffer->data + 8,
5495 ll_addr.data, ll_addr.len);
5496
5497 set_server_duid(&duid);
5498 data_string_forget(&duid, MDL);
5499 data_string_forget(&ll_addr, MDL);
5500 }
5501 }
5502
5503 /*
5504 * If users want they can use a number for DUID types.
5505 * This is useful for supporting future, not-yet-defined
5506 * DUID types.
5507 *
5508 * In this case, they have to put in the complete value.
5509 *
5510 * This also works for existing DUID types of course.
5511 */
5512 else if (token == NUMBER) {
5513 duid_type_num = atoi(val);
5514
5515 token = next_token(&val, &len, cfile);
5516 if (token != STRING) {
5517 parse_warn(cfile, "identifier expected");
5518 skip_to_semi(cfile);
5519 return;
5520 }
5521
5522 /*
5523 * Save the DUID.
5524 */
5525 memset(&duid, 0, sizeof(duid));
5526 duid.len = 2 + len;
5527 if (!buffer_allocate(&duid.buffer, duid.len, MDL)) {
5528 log_fatal("Out of memory storing DUID");
5529 }
28868515 5530 duid.data = (unsigned char *)duid.buffer->data;
98bd7ca0
DH
5531 putUShort(duid.buffer->data, duid_type_num);
5532 memcpy(duid.buffer->data + 2, val, len);
5533
5534 set_server_duid(&duid);
5535 data_string_forget(&duid, MDL);
5536 }
5537
5538 /*
5539 * Anything else is an error.
5540 */
5541 else {
5542 parse_warn(cfile, "DUID type of LLT, EN, or LL expected");
5543 skip_to_semi(cfile);
5544 return;
5545 }
5546
5547 /*
5548 * Finally consume our trailing semicolon.
5549 */
5550 token = next_token(NULL, NULL, cfile);
5551 if (token != SEMI) {
5552 parse_warn(cfile, "semicolon expected");
5553 skip_to_semi(cfile);
5554 }
5555}
fe5b0fdd
DH
5556
5557#endif /* DHCPv6 */
5558