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