]> git.ipfire.org Git - thirdparty/dhcp.git/blob - client/clparse.c
Support for asynchronous ddns per ticket 19216 - convert to using isclib and
[thirdparty/dhcp.git] / client / clparse.c
1 /* clparse.c
2
3 Parser for dhclient config and lease files... */
4
5 /*
6 * Copyright (c) 2004-2008 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1996-2003 by Internet Software Consortium
8 *
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.
12 *
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.
20 *
21 * Internet Systems Consortium, Inc.
22 * 950 Charter Street
23 * Redwood City, CA 94063
24 * <info@isc.org>
25 * https://www.isc.org/
26 *
27 * This software has been written for Internet Systems Consortium
28 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29 * To learn more about Internet Systems Consortium, see
30 * ``https://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''.
33 */
34
35 #include "dhcpd.h"
36 #include <errno.h>
37
38 struct client_config top_level_config;
39
40 #define NUM_DEFAULT_REQUESTED_OPTS 9
41 struct option *default_requested_options[NUM_DEFAULT_REQUESTED_OPTS + 1];
42
43 static void parse_client_default_duid(struct parse *cfile);
44 static void parse_client6_lease_statement(struct parse *cfile);
45 #ifdef DHCPv6
46 static struct dhc6_ia *parse_client6_ia_na_statement(struct parse *cfile);
47 static struct dhc6_ia *parse_client6_ia_ta_statement(struct parse *cfile);
48 static struct dhc6_ia *parse_client6_ia_pd_statement(struct parse *cfile);
49 static struct dhc6_addr *parse_client6_iaaddr_statement(struct parse *cfile);
50 static struct dhc6_addr *parse_client6_iaprefix_statement(struct parse *cfile);
51 #endif /* DHCPv6 */
52
53 /* client-conf-file :== client-declarations END_OF_FILE
54 client-declarations :== <nil>
55 | client-declaration
56 | client-declarations client-declaration */
57
58 isc_result_t read_client_conf ()
59 {
60 struct client_config *config;
61 struct interface_info *ip;
62 struct parse *parse;
63 isc_result_t status;
64 unsigned code;
65
66 /* Initialize the default request list. */
67 memset(default_requested_options, 0, sizeof(default_requested_options));
68
69 /* 1 */
70 code = DHO_SUBNET_MASK;
71 option_code_hash_lookup(&default_requested_options[0],
72 dhcp_universe.code_hash, &code, 0, MDL);
73
74 /* 2 */
75 code = DHO_BROADCAST_ADDRESS;
76 option_code_hash_lookup(&default_requested_options[1],
77 dhcp_universe.code_hash, &code, 0, MDL);
78
79 /* 3 */
80 code = DHO_TIME_OFFSET;
81 option_code_hash_lookup(&default_requested_options[2],
82 dhcp_universe.code_hash, &code, 0, MDL);
83
84 /* 4 */
85 code = DHO_ROUTERS;
86 option_code_hash_lookup(&default_requested_options[3],
87 dhcp_universe.code_hash, &code, 0, MDL);
88
89 /* 5 */
90 code = DHO_DOMAIN_NAME;
91 option_code_hash_lookup(&default_requested_options[4],
92 dhcp_universe.code_hash, &code, 0, MDL);
93
94 /* 6 */
95 code = DHO_DOMAIN_NAME_SERVERS;
96 option_code_hash_lookup(&default_requested_options[5],
97 dhcp_universe.code_hash, &code, 0, MDL);
98
99 /* 7 */
100 code = DHO_HOST_NAME;
101 option_code_hash_lookup(&default_requested_options[6],
102 dhcp_universe.code_hash, &code, 0, MDL);
103
104 /* 8 */
105 code = D6O_NAME_SERVERS;
106 option_code_hash_lookup(&default_requested_options[7],
107 dhcpv6_universe.code_hash, &code, 0, MDL);
108
109 /* 9 */
110 code = D6O_DOMAIN_SEARCH;
111 option_code_hash_lookup(&default_requested_options[8],
112 dhcpv6_universe.code_hash, &code, 0, MDL);
113
114 for (code = 0 ; code < NUM_DEFAULT_REQUESTED_OPTS ; code++) {
115 if (default_requested_options[code] == NULL)
116 log_fatal("Unable to find option definition for "
117 "index %u during default parameter request "
118 "assembly.", code);
119 }
120
121 /* Initialize the top level client configuration. */
122 memset (&top_level_config, 0, sizeof top_level_config);
123
124 /* Set some defaults... */
125 top_level_config.timeout = 60;
126 top_level_config.select_interval = 0;
127 top_level_config.reboot_timeout = 10;
128 top_level_config.retry_interval = 300;
129 top_level_config.backoff_cutoff = 15;
130 top_level_config.initial_interval = 3;
131 top_level_config.bootp_policy = P_ACCEPT;
132 top_level_config.script_name = path_dhclient_script;
133 top_level_config.requested_options = default_requested_options;
134 top_level_config.omapi_port = -1;
135 top_level_config.do_forward_update = 1;
136 /* Requested lease time, used by DHCPv6 (DHCPv4 uses the option cache)
137 */
138 top_level_config.requested_lease = 7200;
139
140 group_allocate (&top_level_config.on_receipt, MDL);
141 if (!top_level_config.on_receipt)
142 log_fatal ("no memory for top-level on_receipt group");
143
144 group_allocate (&top_level_config.on_transmission, MDL);
145 if (!top_level_config.on_transmission)
146 log_fatal ("no memory for top-level on_transmission group");
147
148 status = read_client_conf_file (path_dhclient_conf,
149 (struct interface_info *)0,
150 &top_level_config);
151
152 parse = NULL;
153 if (status != ISC_R_SUCCESS) {
154 ;
155 #ifdef LATER
156 /* Set up the standard name service updater routine. */
157 status = new_parse(&parse, -1, default_client_config,
158 sizeof(default_client_config) - 1,
159 "default client configuration", 0);
160 if (status != ISC_R_SUCCESS)
161 log_fatal ("can't begin default client config!");
162 }
163
164 if (parse != NULL) {
165 do {
166 token = peek_token(&val, NULL, cfile);
167 if (token == END_OF_FILE)
168 break;
169 parse_client_statement(cfile, NULL, &top_level_config);
170 } while (1);
171 end_parse(&parse);
172 #endif
173 }
174
175 /* Set up state and config structures for clients that don't
176 have per-interface configuration statements. */
177 config = (struct client_config *)0;
178 for (ip = interfaces; ip; ip = ip -> next) {
179 if (!ip -> client) {
180 ip -> client = (struct client_state *)
181 dmalloc (sizeof (struct client_state), MDL);
182 if (!ip -> client)
183 log_fatal ("no memory for client state.");
184 memset (ip -> client, 0, sizeof *(ip -> client));
185 ip -> client -> interface = ip;
186 }
187
188 if (!ip -> client -> config) {
189 if (!config) {
190 config = (struct client_config *)
191 dmalloc (sizeof (struct client_config),
192 MDL);
193 if (!config)
194 log_fatal ("no memory for client config.");
195 memcpy (config, &top_level_config,
196 sizeof top_level_config);
197 }
198 ip -> client -> config = config;
199 }
200 }
201 return status;
202 }
203
204 int read_client_conf_file (const char *name, struct interface_info *ip,
205 struct client_config *client)
206 {
207 int file;
208 struct parse *cfile;
209 const char *val;
210 int token;
211 isc_result_t status;
212
213 if ((file = open (name, O_RDONLY)) < 0)
214 return uerr2isc (errno);
215
216 cfile = NULL;
217 status = new_parse(&cfile, file, NULL, 0, path_dhclient_conf, 0);
218 if (status != ISC_R_SUCCESS || cfile == NULL)
219 return status;
220
221 do {
222 token = peek_token (&val, (unsigned *)0, cfile);
223 if (token == END_OF_FILE)
224 break;
225 parse_client_statement (cfile, ip, client);
226 } while (1);
227 token = next_token (&val, (unsigned *)0, cfile);
228 status = (cfile -> warnings_occurred
229 ? DHCP_R_BADPARSE
230 : ISC_R_SUCCESS);
231 end_parse (&cfile);
232 return status;
233 }
234
235
236 /* lease-file :== client-lease-statements END_OF_FILE
237 client-lease-statements :== <nil>
238 | client-lease-statements LEASE client-lease-statement */
239
240 void read_client_leases ()
241 {
242 int file;
243 isc_result_t status;
244 struct parse *cfile;
245 const char *val;
246 int token;
247
248 /* Open the lease file. If we can't open it, just return -
249 we can safely trust the server to remember our state. */
250 if ((file = open (path_dhclient_db, O_RDONLY)) < 0)
251 return;
252
253 cfile = NULL;
254 status = new_parse(&cfile, file, NULL, 0, path_dhclient_db, 0);
255 if (status != ISC_R_SUCCESS || cfile == NULL)
256 return;
257
258 do {
259 token = next_token (&val, (unsigned *)0, cfile);
260 if (token == END_OF_FILE)
261 break;
262
263 switch (token) {
264 case DEFAULT_DUID:
265 parse_client_default_duid(cfile);
266 break;
267
268 case LEASE:
269 parse_client_lease_statement(cfile, 0);
270 break;
271
272 case LEASE6:
273 parse_client6_lease_statement(cfile);
274 break;
275
276 default:
277 log_error ("Corrupt lease file - possible data loss!");
278 skip_to_semi (cfile);
279 break;
280 }
281 } while (1);
282
283 end_parse (&cfile);
284 }
285
286 /* client-declaration :==
287 SEND option-decl |
288 DEFAULT option-decl |
289 SUPERSEDE option-decl |
290 PREPEND option-decl |
291 APPEND option-decl |
292 hardware-declaration |
293 ALSO REQUEST option-list |
294 ALSO REQUIRE option-list |
295 REQUEST option-list |
296 REQUIRE option-list |
297 TIMEOUT number |
298 RETRY number |
299 REBOOT number |
300 SELECT_TIMEOUT number |
301 SCRIPT string |
302 VENDOR_SPACE string |
303 interface-declaration |
304 LEASE client-lease-statement |
305 ALIAS client-lease-statement |
306 KEY key-definition */
307
308 void parse_client_statement (cfile, ip, config)
309 struct parse *cfile;
310 struct interface_info *ip;
311 struct client_config *config;
312 {
313 int token;
314 const char *val;
315 struct option *option = NULL;
316 struct executable_statement *stmt;
317 int lose;
318 char *name;
319 enum policy policy;
320 int known;
321 int tmp, i;
322 isc_result_t status;
323 struct option ***append_list, **new_list, **cat_list;
324
325 switch (peek_token (&val, (unsigned *)0, cfile)) {
326 case INCLUDE:
327 next_token (&val, (unsigned *)0, cfile);
328 token = next_token (&val, (unsigned *)0, cfile);
329 if (token != STRING) {
330 parse_warn (cfile, "filename string expected.");
331 skip_to_semi (cfile);
332 } else {
333 status = read_client_conf_file (val, ip, config);
334 if (status != ISC_R_SUCCESS)
335 parse_warn (cfile, "%s: bad parse.", val);
336 parse_semi (cfile);
337 }
338 return;
339
340 case KEY:
341 next_token (&val, (unsigned *)0, cfile);
342 if (ip) {
343 /* This may seem arbitrary, but there's a reason for
344 doing it: the authentication key database is not
345 scoped. If we allow the user to declare a key other
346 than in the outer scope, the user is very likely to
347 believe that the key will only be used in that
348 scope. If the user only wants the key to be used on
349 one interface, because it's known that the other
350 interface may be connected to an insecure net and
351 the secret key is considered sensitive, we don't
352 want to lull them into believing they've gotten
353 their way. This is a bit contrived, but people
354 tend not to be entirely rational about security. */
355 parse_warn (cfile, "key definition not allowed here.");
356 skip_to_semi (cfile);
357 break;
358 }
359 parse_key (cfile);
360 return;
361
362 case TOKEN_ALSO:
363 /* consume ALSO */
364 next_token(&val, NULL, cfile);
365
366 /* consume type of ALSO list. */
367 token = next_token(&val, NULL, cfile);
368
369 if (token == REQUEST) {
370 append_list = &config->requested_options;
371 } else if (token == REQUIRE) {
372 append_list = &config->required_options;
373 } else {
374 parse_warn(cfile, "expected REQUEST or REQUIRE list");
375 skip_to_semi(cfile);
376 return;
377 }
378
379 /* If there is no list, cut the concat short. */
380 if (*append_list == NULL) {
381 parse_option_list(cfile, append_list);
382 return;
383 }
384
385 /* Count the length of the existing list. */
386 for (i = 0 ; (*append_list)[i] != NULL ; i++)
387 ; /* This space intentionally left blank. */
388
389 /* If there's no codes on the list, cut the concat short. */
390 if (i == 0) {
391 parse_option_list(cfile, append_list);
392 return;
393 }
394
395 tmp = parse_option_list(cfile, &new_list);
396
397 if (tmp == 0 || new_list == NULL)
398 return;
399
400 /* Allocate 'i + tmp' buckets plus a terminator. */
401 cat_list = dmalloc(sizeof(struct option *) * (i + tmp + 1),
402 MDL);
403
404 if (cat_list == NULL) {
405 log_error("Unable to allocate memory for new "
406 "request list.");
407 skip_to_semi(cfile);
408 return;
409 }
410
411 for (i = 0 ; (*append_list)[i] != NULL ; i++)
412 option_reference(&cat_list[i], (*append_list)[i], MDL);
413
414 tmp = i;
415
416 for (i = 0 ; new_list[i] != 0 ; i++)
417 option_reference(&cat_list[tmp++], new_list[i], MDL);
418
419 cat_list[tmp] = 0;
420
421 /* XXX: We cannot free the old list, because it may have been
422 * XXX: assigned from an outer configuration scope (or may be
423 * XXX: the static default setting).
424 */
425 *append_list = cat_list;
426
427 return;
428
429 /* REQUIRE can either start a policy statement or a
430 comma-separated list of names of required options. */
431 case REQUIRE:
432 next_token (&val, (unsigned *)0, cfile);
433 token = peek_token (&val, (unsigned *)0, cfile);
434 if (token == AUTHENTICATION) {
435 policy = P_REQUIRE;
436 goto do_policy;
437 }
438 parse_option_list (cfile, &config -> required_options);
439 return;
440
441 case IGNORE:
442 next_token (&val, (unsigned *)0, cfile);
443 policy = P_IGNORE;
444 goto do_policy;
445
446 case ACCEPT:
447 next_token (&val, (unsigned *)0, cfile);
448 policy = P_ACCEPT;
449 goto do_policy;
450
451 case PREFER:
452 next_token (&val, (unsigned *)0, cfile);
453 policy = P_PREFER;
454 goto do_policy;
455
456 case DONT:
457 next_token (&val, (unsigned *)0, cfile);
458 policy = P_DONT;
459 goto do_policy;
460
461 do_policy:
462 token = next_token (&val, (unsigned *)0, cfile);
463 if (token == AUTHENTICATION) {
464 if (policy != P_PREFER &&
465 policy != P_REQUIRE &&
466 policy != P_DONT) {
467 parse_warn (cfile,
468 "invalid authentication policy.");
469 skip_to_semi (cfile);
470 return;
471 }
472 config -> auth_policy = policy;
473 } else if (token != TOKEN_BOOTP) {
474 if (policy != P_PREFER &&
475 policy != P_IGNORE &&
476 policy != P_ACCEPT) {
477 parse_warn (cfile, "invalid bootp policy.");
478 skip_to_semi (cfile);
479 return;
480 }
481 config -> bootp_policy = policy;
482 } else {
483 parse_warn (cfile, "expecting a policy type.");
484 skip_to_semi (cfile);
485 return;
486 }
487 break;
488
489 case OPTION:
490 token = next_token (&val, (unsigned *)0, cfile);
491
492 token = peek_token (&val, (unsigned *)0, cfile);
493 if (token == SPACE) {
494 if (ip) {
495 parse_warn (cfile,
496 "option space definitions %s",
497 " may not be scoped.");
498 skip_to_semi (cfile);
499 break;
500 }
501 parse_option_space_decl (cfile);
502 return;
503 }
504
505 known = 0;
506 status = parse_option_name(cfile, 1, &known, &option);
507 if (status != ISC_R_SUCCESS || option == NULL)
508 return;
509
510 token = next_token (&val, (unsigned *)0, cfile);
511 if (token != CODE) {
512 parse_warn (cfile, "expecting \"code\" keyword.");
513 skip_to_semi (cfile);
514 option_dereference(&option, MDL);
515 return;
516 }
517 if (ip) {
518 parse_warn (cfile,
519 "option definitions may only appear in %s",
520 "the outermost scope.");
521 skip_to_semi (cfile);
522 option_dereference(&option, MDL);
523 return;
524 }
525
526 /*
527 * If the option was known, remove it from the code and name
528 * hash tables before redefining it.
529 */
530 if (known) {
531 option_name_hash_delete(option->universe->name_hash,
532 option->name, 0, MDL);
533 option_code_hash_delete(option->universe->code_hash,
534 &option->code, 0, MDL);
535 }
536
537 parse_option_code_definition(cfile, option);
538 option_dereference(&option, MDL);
539 return;
540
541 case MEDIA:
542 token = next_token (&val, (unsigned *)0, cfile);
543 parse_string_list (cfile, &config -> media, 1);
544 return;
545
546 case HARDWARE:
547 token = next_token (&val, (unsigned *)0, cfile);
548 if (ip) {
549 parse_hardware_param (cfile, &ip -> hw_address);
550 } else {
551 parse_warn (cfile, "hardware address parameter %s",
552 "not allowed here.");
553 skip_to_semi (cfile);
554 }
555 return;
556
557 case ANYCAST_MAC:
558 token = next_token(&val, NULL, cfile);
559 if (ip != NULL) {
560 parse_hardware_param(cfile, &ip->anycast_mac_addr);
561 } else {
562 parse_warn(cfile, "anycast mac address parameter "
563 "not allowed here.");
564 skip_to_semi (cfile);
565 }
566 return;
567
568 case REQUEST:
569 token = next_token (&val, (unsigned *)0, cfile);
570 if (config -> requested_options == default_requested_options)
571 config -> requested_options = NULL;
572 parse_option_list (cfile, &config -> requested_options);
573 return;
574
575 case TIMEOUT:
576 token = next_token (&val, (unsigned *)0, cfile);
577 parse_lease_time (cfile, &config -> timeout);
578 return;
579
580 case RETRY:
581 token = next_token (&val, (unsigned *)0, cfile);
582 parse_lease_time (cfile, &config -> retry_interval);
583 return;
584
585 case SELECT_TIMEOUT:
586 token = next_token (&val, (unsigned *)0, cfile);
587 parse_lease_time (cfile, &config -> select_interval);
588 return;
589
590 case OMAPI:
591 token = next_token (&val, (unsigned *)0, cfile);
592 token = next_token (&val, (unsigned *)0, cfile);
593 if (token != PORT) {
594 parse_warn (cfile,
595 "unexpected omapi subtype: %s", val);
596 skip_to_semi (cfile);
597 return;
598 }
599 token = next_token (&val, (unsigned *)0, cfile);
600 if (token != NUMBER) {
601 parse_warn (cfile, "invalid port number: `%s'", val);
602 skip_to_semi (cfile);
603 return;
604 }
605 tmp = atoi (val);
606 if (tmp < 0 || tmp > 65535)
607 parse_warn (cfile, "invalid omapi port %d.", tmp);
608 else if (config != &top_level_config)
609 parse_warn (cfile,
610 "omapi port only works at top level.");
611 else
612 config -> omapi_port = tmp;
613 parse_semi (cfile);
614 return;
615
616 case DO_FORWARD_UPDATE:
617 token = next_token (&val, (unsigned *)0, cfile);
618 token = next_token (&val, (unsigned *)0, cfile);
619 if (!strcasecmp (val, "on") ||
620 !strcasecmp (val, "true"))
621 config -> do_forward_update = 1;
622 else if (!strcasecmp (val, "off") ||
623 !strcasecmp (val, "false"))
624 config -> do_forward_update = 0;
625 else {
626 parse_warn (cfile, "expecting boolean value.");
627 skip_to_semi (cfile);
628 return;
629 }
630 parse_semi (cfile);
631 return;
632
633 case REBOOT:
634 token = next_token (&val, (unsigned *)0, cfile);
635 parse_lease_time (cfile, &config -> reboot_timeout);
636 return;
637
638 case BACKOFF_CUTOFF:
639 token = next_token (&val, (unsigned *)0, cfile);
640 parse_lease_time (cfile, &config -> backoff_cutoff);
641 return;
642
643 case INITIAL_INTERVAL:
644 token = next_token (&val, (unsigned *)0, cfile);
645 parse_lease_time (cfile, &config -> initial_interval);
646 return;
647
648 case SCRIPT:
649 token = next_token (&val, (unsigned *)0, cfile);
650 parse_string (cfile, &config -> script_name, (unsigned *)0);
651 return;
652
653 case VENDOR:
654 token = next_token (&val, (unsigned *)0, cfile);
655 token = next_token (&val, (unsigned *)0, cfile);
656 if (token != OPTION) {
657 parse_warn (cfile, "expecting 'vendor option space'");
658 skip_to_semi (cfile);
659 return;
660 }
661 token = next_token (&val, (unsigned *)0, cfile);
662 if (token != SPACE) {
663 parse_warn (cfile, "expecting 'vendor option space'");
664 skip_to_semi (cfile);
665 return;
666 }
667 token = next_token (&val, (unsigned *)0, cfile);
668 if (!is_identifier (token)) {
669 parse_warn (cfile, "expecting an identifier.");
670 skip_to_semi (cfile);
671 return;
672 }
673 config -> vendor_space_name = dmalloc (strlen (val) + 1, MDL);
674 if (!config -> vendor_space_name)
675 log_fatal ("no memory for vendor option space name.");
676 strcpy (config -> vendor_space_name, val);
677 for (i = 0; i < universe_count; i++)
678 if (!strcmp (universes [i] -> name,
679 config -> vendor_space_name))
680 break;
681 if (i == universe_count) {
682 log_error ("vendor option space %s not found.",
683 config -> vendor_space_name);
684 }
685 parse_semi (cfile);
686 return;
687
688 case INTERFACE:
689 token = next_token (&val, (unsigned *)0, cfile);
690 if (ip)
691 parse_warn (cfile, "nested interface declaration.");
692 parse_interface_declaration (cfile, config, (char *)0);
693 return;
694
695 case PSEUDO:
696 token = next_token (&val, (unsigned *)0, cfile);
697 token = next_token (&val, (unsigned *)0, cfile);
698 name = dmalloc (strlen (val) + 1, MDL);
699 if (!name)
700 log_fatal ("no memory for pseudo interface name");
701 strcpy (name, val);
702 parse_interface_declaration (cfile, config, name);
703 return;
704
705 case LEASE:
706 token = next_token (&val, (unsigned *)0, cfile);
707 parse_client_lease_statement (cfile, 1);
708 return;
709
710 case ALIAS:
711 token = next_token (&val, (unsigned *)0, cfile);
712 parse_client_lease_statement (cfile, 2);
713 return;
714
715 case REJECT:
716 token = next_token (&val, (unsigned *)0, cfile);
717 parse_reject_statement (cfile, config);
718 return;
719
720 default:
721 lose = 0;
722 stmt = (struct executable_statement *)0;
723 if (!parse_executable_statement (&stmt,
724 cfile, &lose, context_any)) {
725 if (!lose) {
726 parse_warn (cfile, "expecting a statement.");
727 skip_to_semi (cfile);
728 }
729 } else {
730 struct executable_statement **eptr, *sptr;
731 if (stmt &&
732 (stmt -> op == send_option_statement ||
733 (stmt -> op == on_statement &&
734 (stmt -> data.on.evtypes & ON_TRANSMISSION)))) {
735 eptr = &config -> on_transmission -> statements;
736 if (stmt -> op == on_statement) {
737 sptr = (struct executable_statement *)0;
738 executable_statement_reference
739 (&sptr,
740 stmt -> data.on.statements, MDL);
741 executable_statement_dereference (&stmt,
742 MDL);
743 executable_statement_reference (&stmt,
744 sptr,
745 MDL);
746 executable_statement_dereference (&sptr,
747 MDL);
748 }
749 } else
750 eptr = &config -> on_receipt -> statements;
751
752 if (stmt) {
753 for (; *eptr; eptr = &(*eptr) -> next)
754 ;
755 executable_statement_reference (eptr,
756 stmt, MDL);
757 }
758 return;
759 }
760 break;
761 }
762 parse_semi (cfile);
763 }
764
765 /* option-list :== option_name |
766 option_list COMMA option_name */
767
768 int
769 parse_option_list(struct parse *cfile, struct option ***list)
770 {
771 int ix;
772 int token;
773 const char *val;
774 pair p = (pair)0, q = (pair)0, r;
775 struct option *option = NULL;
776 isc_result_t status;
777
778 ix = 0;
779 do {
780 token = peek_token (&val, (unsigned *)0, cfile);
781 if (token == SEMI) {
782 token = next_token (&val, (unsigned *)0, cfile);
783 break;
784 }
785 if (!is_identifier (token)) {
786 parse_warn (cfile, "%s: expected option name.", val);
787 token = next_token (&val, (unsigned *)0, cfile);
788 skip_to_semi (cfile);
789 return 0;
790 }
791 status = parse_option_name(cfile, 0, NULL, &option);
792 if (status != ISC_R_SUCCESS || option == NULL) {
793 parse_warn (cfile, "%s: expected option name.", val);
794 return 0;
795 }
796 r = new_pair (MDL);
797 if (!r)
798 log_fatal ("can't allocate pair for option code.");
799 /* XXX: we should probably carry a reference across this */
800 r->car = (caddr_t)option;
801 option_dereference(&option, MDL);
802 r -> cdr = (pair)0;
803 if (p)
804 q -> cdr = r;
805 else
806 p = r;
807 q = r;
808 ++ix;
809 token = next_token (&val, (unsigned *)0, cfile);
810 } while (token == COMMA);
811 if (token != SEMI) {
812 parse_warn (cfile, "expecting semicolon.");
813 skip_to_semi (cfile);
814 return 0;
815 }
816 /* XXX we can't free the list here, because we may have copied
817 XXX it from an outer config state. */
818 *list = NULL;
819 if (ix) {
820 *list = dmalloc ((ix + 1) * sizeof(struct option *), MDL);
821 if (!*list)
822 log_error ("no memory for option list.");
823 else {
824 ix = 0;
825 for (q = p; q; q = q -> cdr)
826 option_reference(&(*list)[ix++],
827 (struct option *)q->car, MDL);
828 (*list)[ix] = NULL;
829 }
830 while (p) {
831 q = p -> cdr;
832 free_pair (p, MDL);
833 p = q;
834 }
835 }
836
837 return ix;
838 }
839
840 /* interface-declaration :==
841 INTERFACE string LBRACE client-declarations RBRACE */
842
843 void parse_interface_declaration (cfile, outer_config, name)
844 struct parse *cfile;
845 struct client_config *outer_config;
846 char *name;
847 {
848 int token;
849 const char *val;
850 struct client_state *client, **cp;
851 struct interface_info *ip = (struct interface_info *)0;
852
853 token = next_token (&val, (unsigned *)0, cfile);
854 if (token != STRING) {
855 parse_warn (cfile, "expecting interface name (in quotes).");
856 skip_to_semi (cfile);
857 return;
858 }
859
860 if (!interface_or_dummy (&ip, val))
861 log_fatal ("Can't allocate interface %s.", val);
862
863 /* If we were given a name, this is a pseudo-interface. */
864 if (name) {
865 make_client_state (&client);
866 client -> name = name;
867 client -> interface = ip;
868 for (cp = &ip -> client; *cp; cp = &((*cp) -> next))
869 ;
870 *cp = client;
871 } else {
872 if (!ip -> client) {
873 make_client_state (&ip -> client);
874 ip -> client -> interface = ip;
875 }
876 client = ip -> client;
877 }
878
879 if (!client -> config)
880 make_client_config (client, outer_config);
881
882 ip -> flags &= ~INTERFACE_AUTOMATIC;
883 interfaces_requested = 1;
884
885 token = next_token (&val, (unsigned *)0, cfile);
886 if (token != LBRACE) {
887 parse_warn (cfile, "expecting left brace.");
888 skip_to_semi (cfile);
889 return;
890 }
891
892 do {
893 token = peek_token (&val, (unsigned *)0, cfile);
894 if (token == END_OF_FILE) {
895 parse_warn (cfile,
896 "unterminated interface declaration.");
897 return;
898 }
899 if (token == RBRACE)
900 break;
901 parse_client_statement (cfile, ip, client -> config);
902 } while (1);
903 token = next_token (&val, (unsigned *)0, cfile);
904 }
905
906 int interface_or_dummy (struct interface_info **pi, const char *name)
907 {
908 struct interface_info *i;
909 struct interface_info *ip = (struct interface_info *)0;
910 isc_result_t status;
911
912 /* Find the interface (if any) that matches the name. */
913 for (i = interfaces; i; i = i -> next) {
914 if (!strcmp (i -> name, name)) {
915 interface_reference (&ip, i, MDL);
916 break;
917 }
918 }
919
920 /* If it's not a real interface, see if it's on the dummy list. */
921 if (!ip) {
922 for (ip = dummy_interfaces; ip; ip = ip -> next) {
923 if (!strcmp (ip -> name, name)) {
924 interface_reference (&ip, i, MDL);
925 break;
926 }
927 }
928 }
929
930 /* If we didn't find an interface, make a dummy interface as
931 a placeholder. */
932 if (!ip) {
933 if ((status = interface_allocate (&ip, MDL)) != ISC_R_SUCCESS)
934 log_fatal ("Can't record interface %s: %s",
935 name, isc_result_totext (status));
936
937 if (strlen(name) >= sizeof(ip->name)) {
938 interface_dereference(&ip, MDL);
939 return 0;
940 }
941 strcpy(ip->name, name);
942
943 if (dummy_interfaces) {
944 interface_reference (&ip -> next,
945 dummy_interfaces, MDL);
946 interface_dereference (&dummy_interfaces, MDL);
947 }
948 interface_reference (&dummy_interfaces, ip, MDL);
949 }
950 if (pi)
951 status = interface_reference (pi, ip, MDL);
952 else
953 status = ISC_R_FAILURE;
954 interface_dereference (&ip, MDL);
955 if (status != ISC_R_SUCCESS)
956 return 0;
957 return 1;
958 }
959
960 void make_client_state (state)
961 struct client_state **state;
962 {
963 *state = ((struct client_state *)dmalloc (sizeof **state, MDL));
964 if (!*state)
965 log_fatal ("no memory for client state\n");
966 memset (*state, 0, sizeof **state);
967 }
968
969 void make_client_config (client, config)
970 struct client_state *client;
971 struct client_config *config;
972 {
973 client -> config = (((struct client_config *)
974 dmalloc (sizeof (struct client_config), MDL)));
975 if (!client -> config)
976 log_fatal ("no memory for client config\n");
977 memcpy (client -> config, config, sizeof *config);
978 if (!clone_group (&client -> config -> on_receipt,
979 config -> on_receipt, MDL) ||
980 !clone_group (&client -> config -> on_transmission,
981 config -> on_transmission, MDL))
982 log_fatal ("no memory for client state groups.");
983 }
984
985 /* client-lease-statement :==
986 LBRACE client-lease-declarations RBRACE
987
988 client-lease-declarations :==
989 <nil> |
990 client-lease-declaration |
991 client-lease-declarations client-lease-declaration */
992
993
994 void parse_client_lease_statement (cfile, is_static)
995 struct parse *cfile;
996 int is_static;
997 {
998 struct client_lease *lease, *lp, *pl, *next;
999 struct interface_info *ip = (struct interface_info *)0;
1000 int token;
1001 const char *val;
1002 struct client_state *client = (struct client_state *)0;
1003
1004 token = next_token (&val, (unsigned *)0, cfile);
1005 if (token != LBRACE) {
1006 parse_warn (cfile, "expecting left brace.");
1007 skip_to_semi (cfile);
1008 return;
1009 }
1010
1011 lease = ((struct client_lease *)
1012 dmalloc (sizeof (struct client_lease), MDL));
1013 if (!lease)
1014 log_fatal ("no memory for lease.\n");
1015 memset (lease, 0, sizeof *lease);
1016 lease -> is_static = is_static;
1017 if (!option_state_allocate (&lease -> options, MDL))
1018 log_fatal ("no memory for lease options.\n");
1019
1020 do {
1021 token = peek_token (&val, (unsigned *)0, cfile);
1022 if (token == END_OF_FILE) {
1023 parse_warn (cfile, "unterminated lease declaration.");
1024 return;
1025 }
1026 if (token == RBRACE)
1027 break;
1028 parse_client_lease_declaration (cfile, lease, &ip, &client);
1029 } while (1);
1030 token = next_token (&val, (unsigned *)0, cfile);
1031
1032 /* If the lease declaration didn't include an interface
1033 declaration that we recognized, it's of no use to us. */
1034 if (!ip) {
1035 destroy_client_lease (lease);
1036 return;
1037 }
1038
1039 /* Make sure there's a client state structure... */
1040 if (!ip -> client) {
1041 make_client_state (&ip -> client);
1042 ip -> client -> interface = ip;
1043 }
1044 if (!client)
1045 client = ip -> client;
1046
1047 /* If this is an alias lease, it doesn't need to be sorted in. */
1048 if (is_static == 2) {
1049 ip -> client -> alias = lease;
1050 return;
1051 }
1052
1053 /* The new lease may supersede a lease that's not the
1054 active lease but is still on the lease list, so scan the
1055 lease list looking for a lease with the same address, and
1056 if we find it, toss it. */
1057 pl = (struct client_lease *)0;
1058 for (lp = client -> leases; lp; lp = next) {
1059 next = lp -> next;
1060 if (lp -> address.len == lease -> address.len &&
1061 !memcmp (lp -> address.iabuf, lease -> address.iabuf,
1062 lease -> address.len)) {
1063 if (pl)
1064 pl -> next = next;
1065 else
1066 client -> leases = next;
1067 destroy_client_lease (lp);
1068 break;
1069 } else
1070 pl = lp;
1071 }
1072
1073 /* If this is a preloaded lease, just put it on the list of recorded
1074 leases - don't make it the active lease. */
1075 if (is_static) {
1076 lease -> next = client -> leases;
1077 client -> leases = lease;
1078 return;
1079 }
1080
1081 /* The last lease in the lease file on a particular interface is
1082 the active lease for that interface. Of course, we don't know
1083 what the last lease in the file is until we've parsed the whole
1084 file, so at this point, we assume that the lease we just parsed
1085 is the active lease for its interface. If there's already
1086 an active lease for the interface, and this lease is for the same
1087 ip address, then we just toss the old active lease and replace
1088 it with this one. If this lease is for a different address,
1089 then if the old active lease has expired, we dump it; if not,
1090 we put it on the list of leases for this interface which are
1091 still valid but no longer active. */
1092 if (client -> active) {
1093 if (client -> active -> expiry < cur_time)
1094 destroy_client_lease (client -> active);
1095 else if (client -> active -> address.len ==
1096 lease -> address.len &&
1097 !memcmp (client -> active -> address.iabuf,
1098 lease -> address.iabuf,
1099 lease -> address.len))
1100 destroy_client_lease (client -> active);
1101 else {
1102 client -> active -> next = client -> leases;
1103 client -> leases = client -> active;
1104 }
1105 }
1106 client -> active = lease;
1107
1108 /* phew. */
1109 }
1110
1111 /* client-lease-declaration :==
1112 BOOTP |
1113 INTERFACE string |
1114 FIXED_ADDR ip_address |
1115 FILENAME string |
1116 SERVER_NAME string |
1117 OPTION option-decl |
1118 RENEW time-decl |
1119 REBIND time-decl |
1120 EXPIRE time-decl |
1121 KEY id */
1122
1123 void parse_client_lease_declaration (cfile, lease, ipp, clientp)
1124 struct parse *cfile;
1125 struct client_lease *lease;
1126 struct interface_info **ipp;
1127 struct client_state **clientp;
1128 {
1129 int token;
1130 const char *val;
1131 struct interface_info *ip;
1132 struct option_cache *oc;
1133 struct client_state *client = (struct client_state *)0;
1134
1135 switch (next_token (&val, (unsigned *)0, cfile)) {
1136 case KEY:
1137 token = next_token (&val, (unsigned *)0, cfile);
1138 if (token != STRING && !is_identifier (token)) {
1139 parse_warn (cfile, "expecting key name.");
1140 skip_to_semi (cfile);
1141 break;
1142 }
1143 if (omapi_auth_key_lookup_name (&lease -> key, val) !=
1144 ISC_R_SUCCESS)
1145 parse_warn (cfile, "unknown key %s", val);
1146 parse_semi (cfile);
1147 break;
1148 case TOKEN_BOOTP:
1149 lease -> is_bootp = 1;
1150 break;
1151
1152 case INTERFACE:
1153 token = next_token (&val, (unsigned *)0, cfile);
1154 if (token != STRING) {
1155 parse_warn (cfile,
1156 "expecting interface name (in quotes).");
1157 skip_to_semi (cfile);
1158 break;
1159 }
1160 if (!interface_or_dummy (ipp, val))
1161 log_fatal ("Can't allocate interface %s.", val);
1162 break;
1163
1164 case NAME:
1165 token = next_token (&val, (unsigned *)0, cfile);
1166 ip = *ipp;
1167 if (!ip) {
1168 parse_warn (cfile, "state name precedes interface.");
1169 break;
1170 }
1171 for (client = ip -> client; client; client = client -> next)
1172 if (client -> name && !strcmp (client -> name, val))
1173 break;
1174 if (!client)
1175 parse_warn (cfile,
1176 "lease specified for unknown pseudo.");
1177 *clientp = client;
1178 break;
1179
1180 case FIXED_ADDR:
1181 if (!parse_ip_addr (cfile, &lease -> address))
1182 return;
1183 break;
1184
1185 case MEDIUM:
1186 parse_string_list (cfile, &lease -> medium, 0);
1187 return;
1188
1189 case FILENAME:
1190 parse_string (cfile, &lease -> filename, (unsigned *)0);
1191 return;
1192
1193 case SERVER_NAME:
1194 parse_string (cfile, &lease -> server_name, (unsigned *)0);
1195 return;
1196
1197 case RENEW:
1198 lease -> renewal = parse_date (cfile);
1199 return;
1200
1201 case REBIND:
1202 lease -> rebind = parse_date (cfile);
1203 return;
1204
1205 case EXPIRE:
1206 lease -> expiry = parse_date (cfile);
1207 return;
1208
1209 case OPTION:
1210 oc = (struct option_cache *)0;
1211 if (parse_option_decl (&oc, cfile)) {
1212 save_option(oc->option->universe, lease->options, oc);
1213 option_cache_dereference (&oc, MDL);
1214 }
1215 return;
1216
1217 default:
1218 parse_warn (cfile, "expecting lease declaration.");
1219 skip_to_semi (cfile);
1220 break;
1221 }
1222 token = next_token (&val, (unsigned *)0, cfile);
1223 if (token != SEMI) {
1224 parse_warn (cfile, "expecting semicolon.");
1225 skip_to_semi (cfile);
1226 }
1227 }
1228
1229 /* Parse a default-duid ""; statement.
1230 */
1231 static void
1232 parse_client_default_duid(struct parse *cfile)
1233 {
1234 struct data_string new_duid;
1235 const char *val = NULL;
1236 unsigned len;
1237 int token;
1238
1239 memset(&new_duid, 0, sizeof(new_duid));
1240
1241 token = next_token(&val, &len, cfile);
1242 if (token != STRING) {
1243 parse_warn(cfile, "Expected DUID string.");
1244 skip_to_semi(cfile);
1245 return;
1246 }
1247
1248 if (len <= 2) {
1249 parse_warn(cfile, "Invalid DUID contents.");
1250 skip_to_semi(cfile);
1251 return;
1252 }
1253
1254 if (!buffer_allocate(&new_duid.buffer, len, MDL)) {
1255 parse_warn(cfile, "Out of memory parsing default DUID.");
1256 skip_to_semi(cfile);
1257 return;
1258 }
1259 new_duid.data = new_duid.buffer->data;
1260 new_duid.len = len;
1261
1262 memcpy(new_duid.buffer->data, val, len);
1263
1264 /* Rotate the last entry into place. */
1265 if (default_duid.buffer != NULL)
1266 data_string_forget(&default_duid, MDL);
1267 data_string_copy(&default_duid, &new_duid, MDL);
1268 data_string_forget(&new_duid, MDL);
1269
1270 parse_semi(cfile);
1271 }
1272
1273 /* Parse a lease6 {} construct. The v6 client is a little different
1274 * than the v4 client today, in that it only retains one lease, the
1275 * active lease, and discards any less recent information. It may
1276 * be useful in the future to cache additional information, but it
1277 * is not worth the effort for the moment.
1278 */
1279 static void
1280 parse_client6_lease_statement(struct parse *cfile)
1281 {
1282 #if !defined(DHCPv6)
1283 parse_warn(cfile, "No DHCPv6 support.");
1284 skip_to_semi(cfile);
1285 #else /* defined(DHCPv6) */
1286 struct option_cache *oc = NULL;
1287 struct dhc6_lease *lease;
1288 struct dhc6_ia **ia;
1289 struct client_state *client = NULL;
1290 struct interface_info *iface = NULL;
1291 struct data_string ds;
1292 const char *val;
1293 unsigned len;
1294 int token, has_ia, no_semi, has_name;
1295
1296 token = next_token(NULL, NULL, cfile);
1297 if (token != LBRACE) {
1298 parse_warn(cfile, "Expecting open curly brace.");
1299 skip_to_semi(cfile);
1300 return;
1301 }
1302
1303 lease = dmalloc(sizeof(*lease), MDL);
1304 if (lease == NULL) {
1305 parse_warn(cfile, "Unable to allocate lease state.");
1306 skip_to_rbrace(cfile, 1);
1307 return;
1308 }
1309
1310 option_state_allocate(&lease->options, MDL);
1311 if (lease->options == NULL) {
1312 parse_warn(cfile, "Unable to allocate option cache.");
1313 skip_to_rbrace(cfile, 1);
1314 dfree(lease, MDL);
1315 return;
1316 }
1317
1318 has_ia = 0;
1319 has_name = 0;
1320 ia = &lease->bindings;
1321 token = next_token(&val, NULL, cfile);
1322 while (token != RBRACE) {
1323 no_semi = 0;
1324
1325 switch(token) {
1326 case IA_NA:
1327 *ia = parse_client6_ia_na_statement(cfile);
1328 if (*ia != NULL) {
1329 ia = &(*ia)->next;
1330 has_ia = 1;
1331 }
1332
1333 no_semi = 1;
1334
1335 break;
1336
1337 case IA_TA:
1338 *ia = parse_client6_ia_ta_statement(cfile);
1339 if (*ia != NULL) {
1340 ia = &(*ia)->next;
1341 has_ia = 1;
1342 }
1343
1344 no_semi = 1;
1345
1346 break;
1347
1348 case IA_PD:
1349 *ia = parse_client6_ia_pd_statement(cfile);
1350 if (*ia != NULL) {
1351 ia = &(*ia)->next;
1352 has_ia = 1;
1353 }
1354
1355 no_semi = 1;
1356
1357 break;
1358
1359 case INTERFACE:
1360 if (iface != NULL) {
1361 parse_warn(cfile, "Multiple interface names?");
1362 skip_to_semi(cfile);
1363 no_semi = 1;
1364 break;
1365 }
1366
1367 token = next_token(&val, &len, cfile);
1368 if (token != STRING) {
1369 strerror:
1370 parse_warn(cfile, "Expecting a string.");
1371 skip_to_semi(cfile);
1372 no_semi = 1;
1373 break;
1374 }
1375
1376 for (iface = interfaces ; iface != NULL ;
1377 iface = iface->next) {
1378 if (strcmp(iface->name, val) == 0)
1379 break;
1380 }
1381
1382 if (iface == NULL) {
1383 parse_warn(cfile, "Unknown interface.");
1384 break;
1385 }
1386
1387 break;
1388
1389 case NAME:
1390 has_name = 1;
1391
1392 if (client != NULL) {
1393 parse_warn(cfile, "Multiple state names?");
1394 skip_to_semi(cfile);
1395 no_semi = 1;
1396 break;
1397 }
1398
1399 if (iface == NULL) {
1400 parse_warn(cfile, "Client name without "
1401 "interface.");
1402 skip_to_semi(cfile);
1403 no_semi = 1;
1404 break;
1405 }
1406
1407 token = next_token(&val, &len, cfile);
1408 if (token != STRING)
1409 goto strerror;
1410
1411 for (client = iface->client ; client != NULL ;
1412 client = client->next) {
1413 if ((client->name != NULL) &&
1414 (strcmp(client->name, val) == 0))
1415 break;
1416 }
1417
1418 if (client == NULL) {
1419 parse_warn(cfile, "Unknown client state %s.",
1420 val);
1421 break;
1422 }
1423
1424 break;
1425
1426 case OPTION:
1427 if (parse_option_decl(&oc, cfile)) {
1428 save_option(oc->option->universe,
1429 lease->options, oc);
1430 option_cache_dereference(&oc, MDL);
1431 }
1432 no_semi = 1;
1433 break;
1434
1435 case TOKEN_RELEASED:
1436 case TOKEN_ABANDONED:
1437 lease->released = ISC_TRUE;
1438 break;
1439
1440 default:
1441 parse_warn(cfile, "Unexpected token, %s.", val);
1442 no_semi = 1;
1443 skip_to_semi(cfile);
1444 break;
1445 }
1446
1447 if (!no_semi)
1448 parse_semi(cfile);
1449
1450 token = next_token(&val, NULL, cfile);
1451
1452 if (token == END_OF_FILE) {
1453 parse_warn(cfile, "Unexpected end of file.");
1454 break;
1455 }
1456 }
1457
1458 if (!has_ia) {
1459 log_debug("Lease with no IA's discarded from lease db.");
1460 dhc6_lease_destroy(&lease, MDL);
1461 return;
1462 }
1463
1464 if (iface == NULL)
1465 parse_warn(cfile, "Lease has no interface designation.");
1466 else if (!has_name && (client == NULL)) {
1467 for (client = iface->client ; client != NULL ;
1468 client = client->next) {
1469 if (client->name == NULL)
1470 break;
1471 }
1472 }
1473
1474 if (client == NULL) {
1475 parse_warn(cfile, "No matching client state.");
1476 dhc6_lease_destroy(&lease, MDL);
1477 return;
1478 }
1479
1480 /* Fetch Preference option from option cache. */
1481 memset(&ds, 0, sizeof(ds));
1482 oc = lookup_option(&dhcpv6_universe, lease->options, D6O_PREFERENCE);
1483 if ((oc != NULL) &&
1484 evaluate_option_cache(&ds, NULL, NULL, NULL, lease->options,
1485 NULL, &global_scope, oc, MDL)) {
1486 if (ds.len != 1) {
1487 log_error("Invalid length of DHCPv6 Preference option "
1488 "(%d != 1)", ds.len);
1489 data_string_forget(&ds, MDL);
1490 dhc6_lease_destroy(&lease, MDL);
1491 return;
1492 } else
1493 lease->pref = ds.data[0];
1494
1495 data_string_forget(&ds, MDL);
1496 }
1497
1498 /* Fetch server-id option from option cache. */
1499 oc = lookup_option(&dhcpv6_universe, lease->options, D6O_SERVERID);
1500 if ((oc == NULL) ||
1501 !evaluate_option_cache(&lease->server_id, NULL, NULL, NULL,
1502 lease->options, NULL, &global_scope, oc,
1503 MDL) ||
1504 (lease->server_id.len == 0)) {
1505 /* This should be impossible... */
1506 log_error("Invalid SERVERID option cache.");
1507 dhc6_lease_destroy(&lease, MDL);
1508 return;
1509 }
1510
1511 if (client->active_lease != NULL)
1512 dhc6_lease_destroy(&client->active_lease, MDL);
1513
1514 client->active_lease = lease;
1515 #endif /* defined(DHCPv6) */
1516 }
1517
1518 /* Parse an ia_na object from the client lease.
1519 */
1520 #ifdef DHCPv6
1521 static struct dhc6_ia *
1522 parse_client6_ia_na_statement(struct parse *cfile)
1523 {
1524 struct data_string id;
1525 struct option_cache *oc = NULL;
1526 struct dhc6_ia *ia;
1527 struct dhc6_addr **addr;
1528 const char *val;
1529 int token, no_semi;
1530
1531 ia = dmalloc(sizeof(*ia), MDL);
1532 if (ia == NULL) {
1533 parse_warn(cfile, "Out of memory allocating IA_NA state.");
1534 skip_to_semi(cfile);
1535 return NULL;
1536 }
1537 ia->ia_type = D6O_IA_NA;
1538
1539 /* Get IAID. */
1540 memset(&id, 0, sizeof(id));
1541 if (parse_cshl(&id, cfile)) {
1542 if (id.len == 4)
1543 memcpy(ia->iaid, id.data, 4);
1544 else {
1545 parse_warn(cfile, "Expecting IAID of length 4, got %d.",
1546 id.len);
1547 skip_to_semi(cfile);
1548 dfree(ia, MDL);
1549 return NULL;
1550 }
1551 data_string_forget(&id, MDL);
1552 } else {
1553 parse_warn(cfile, "Expecting IAID.");
1554 skip_to_semi(cfile);
1555 dfree(ia, MDL);
1556 return NULL;
1557 }
1558
1559 token = next_token(NULL, NULL, cfile);
1560 if (token != LBRACE) {
1561 parse_warn(cfile, "Expecting open curly brace.");
1562 skip_to_semi(cfile);
1563 dfree(ia, MDL);
1564 return NULL;
1565 }
1566
1567 option_state_allocate(&ia->options, MDL);
1568 if (ia->options == NULL) {
1569 parse_warn(cfile, "Unable to allocate option state.");
1570 skip_to_rbrace(cfile, 1);
1571 dfree(ia, MDL);
1572 return NULL;
1573 }
1574
1575 addr = &ia->addrs;
1576 token = next_token(&val, NULL, cfile);
1577 while (token != RBRACE) {
1578 no_semi = 0;
1579
1580 switch (token) {
1581 case STARTS:
1582 token = next_token(&val, NULL, cfile);
1583 if (token == NUMBER) {
1584 ia->starts = atoi(val);
1585 } else {
1586 parse_warn(cfile, "Expecting a number.");
1587 skip_to_semi(cfile);
1588 no_semi = 1;
1589 }
1590 break;
1591
1592 case RENEW:
1593 token = next_token(&val, NULL, cfile);
1594 if (token == NUMBER) {
1595 ia->renew = atoi(val);
1596 } else {
1597 parse_warn(cfile, "Expecting a number.");
1598 skip_to_semi(cfile);
1599 no_semi = 1;
1600 }
1601 break;
1602
1603 case REBIND:
1604 token = next_token(&val, NULL, cfile);
1605 if (token == NUMBER) {
1606 ia->rebind = atoi(val);
1607 } else {
1608 parse_warn(cfile, "Expecting a number.");
1609 skip_to_semi(cfile);
1610 no_semi = 1;
1611 }
1612 break;
1613
1614 case IAADDR:
1615 *addr = parse_client6_iaaddr_statement(cfile);
1616
1617 if (*addr != NULL)
1618 addr = &(*addr)->next;
1619
1620 no_semi = 1;
1621
1622 break;
1623
1624 case OPTION:
1625 if (parse_option_decl(&oc, cfile)) {
1626 save_option(oc->option->universe,
1627 ia->options, oc);
1628 option_cache_dereference(&oc, MDL);
1629 }
1630 no_semi = 1;
1631 break;
1632
1633 default:
1634 parse_warn(cfile, "Unexpected token.");
1635 no_semi = 1;
1636 skip_to_semi(cfile);
1637 break;
1638 }
1639
1640 if (!no_semi)
1641 parse_semi(cfile);
1642
1643 token = next_token(&val, NULL, cfile);
1644
1645 if (token == END_OF_FILE) {
1646 parse_warn(cfile, "Unexpected end of file.");
1647 break;
1648 }
1649 }
1650
1651 return ia;
1652 }
1653 #endif /* DHCPv6 */
1654
1655 /* Parse an ia_ta object from the client lease.
1656 */
1657 #ifdef DHCPv6
1658 static struct dhc6_ia *
1659 parse_client6_ia_ta_statement(struct parse *cfile)
1660 {
1661 struct data_string id;
1662 struct option_cache *oc = NULL;
1663 struct dhc6_ia *ia;
1664 struct dhc6_addr **addr;
1665 const char *val;
1666 int token, no_semi;
1667
1668 ia = dmalloc(sizeof(*ia), MDL);
1669 if (ia == NULL) {
1670 parse_warn(cfile, "Out of memory allocating IA_TA state.");
1671 skip_to_semi(cfile);
1672 return NULL;
1673 }
1674 ia->ia_type = D6O_IA_TA;
1675
1676 /* Get IAID. */
1677 memset(&id, 0, sizeof(id));
1678 if (parse_cshl(&id, cfile)) {
1679 if (id.len == 4)
1680 memcpy(ia->iaid, id.data, 4);
1681 else {
1682 parse_warn(cfile, "Expecting IAID of length 4, got %d.",
1683 id.len);
1684 skip_to_semi(cfile);
1685 dfree(ia, MDL);
1686 return NULL;
1687 }
1688 data_string_forget(&id, MDL);
1689 } else {
1690 parse_warn(cfile, "Expecting IAID.");
1691 skip_to_semi(cfile);
1692 dfree(ia, MDL);
1693 return NULL;
1694 }
1695
1696 token = next_token(NULL, NULL, cfile);
1697 if (token != LBRACE) {
1698 parse_warn(cfile, "Expecting open curly brace.");
1699 skip_to_semi(cfile);
1700 dfree(ia, MDL);
1701 return NULL;
1702 }
1703
1704 option_state_allocate(&ia->options, MDL);
1705 if (ia->options == NULL) {
1706 parse_warn(cfile, "Unable to allocate option state.");
1707 skip_to_rbrace(cfile, 1);
1708 dfree(ia, MDL);
1709 return NULL;
1710 }
1711
1712 addr = &ia->addrs;
1713 token = next_token(&val, NULL, cfile);
1714 while (token != RBRACE) {
1715 no_semi = 0;
1716
1717 switch (token) {
1718 case STARTS:
1719 token = next_token(&val, NULL, cfile);
1720 if (token == NUMBER) {
1721 ia->starts = atoi(val);
1722 } else {
1723 parse_warn(cfile, "Expecting a number.");
1724 skip_to_semi(cfile);
1725 no_semi = 1;
1726 }
1727 break;
1728
1729 /* No RENEW or REBIND */
1730
1731 case IAADDR:
1732 *addr = parse_client6_iaaddr_statement(cfile);
1733
1734 if (*addr != NULL)
1735 addr = &(*addr)->next;
1736
1737 no_semi = 1;
1738
1739 break;
1740
1741 case OPTION:
1742 if (parse_option_decl(&oc, cfile)) {
1743 save_option(oc->option->universe,
1744 ia->options, oc);
1745 option_cache_dereference(&oc, MDL);
1746 }
1747 no_semi = 1;
1748 break;
1749
1750 default:
1751 parse_warn(cfile, "Unexpected token.");
1752 no_semi = 1;
1753 skip_to_semi(cfile);
1754 break;
1755 }
1756
1757 if (!no_semi)
1758 parse_semi(cfile);
1759
1760 token = next_token(&val, NULL, cfile);
1761
1762 if (token == END_OF_FILE) {
1763 parse_warn(cfile, "Unexpected end of file.");
1764 break;
1765 }
1766 }
1767
1768 return ia;
1769 }
1770 #endif /* DHCPv6 */
1771
1772 /* Parse an ia_pd object from the client lease.
1773 */
1774 #ifdef DHCPv6
1775 static struct dhc6_ia *
1776 parse_client6_ia_pd_statement(struct parse *cfile)
1777 {
1778 struct data_string id;
1779 struct option_cache *oc = NULL;
1780 struct dhc6_ia *ia;
1781 struct dhc6_addr **pref;
1782 const char *val;
1783 int token, no_semi;
1784
1785 ia = dmalloc(sizeof(*ia), MDL);
1786 if (ia == NULL) {
1787 parse_warn(cfile, "Out of memory allocating IA_PD state.");
1788 skip_to_semi(cfile);
1789 return NULL;
1790 }
1791 ia->ia_type = D6O_IA_PD;
1792
1793 /* Get IAID. */
1794 memset(&id, 0, sizeof(id));
1795 if (parse_cshl(&id, cfile)) {
1796 if (id.len == 4)
1797 memcpy(ia->iaid, id.data, 4);
1798 else {
1799 parse_warn(cfile, "Expecting IAID of length 4, got %d.",
1800 id.len);
1801 skip_to_semi(cfile);
1802 dfree(ia, MDL);
1803 return NULL;
1804 }
1805 data_string_forget(&id, MDL);
1806 } else {
1807 parse_warn(cfile, "Expecting IAID.");
1808 skip_to_semi(cfile);
1809 dfree(ia, MDL);
1810 return NULL;
1811 }
1812
1813 token = next_token(NULL, NULL, cfile);
1814 if (token != LBRACE) {
1815 parse_warn(cfile, "Expecting open curly brace.");
1816 skip_to_semi(cfile);
1817 dfree(ia, MDL);
1818 return NULL;
1819 }
1820
1821 option_state_allocate(&ia->options, MDL);
1822 if (ia->options == NULL) {
1823 parse_warn(cfile, "Unable to allocate option state.");
1824 skip_to_rbrace(cfile, 1);
1825 dfree(ia, MDL);
1826 return NULL;
1827 }
1828
1829 pref = &ia->addrs;
1830 token = next_token(&val, NULL, cfile);
1831 while (token != RBRACE) {
1832 no_semi = 0;
1833
1834 switch (token) {
1835 case STARTS:
1836 token = next_token(&val, NULL, cfile);
1837 if (token == NUMBER) {
1838 ia->starts = atoi(val);
1839 } else {
1840 parse_warn(cfile, "Expecting a number.");
1841 skip_to_semi(cfile);
1842 no_semi = 1;
1843 }
1844 break;
1845
1846 case RENEW:
1847 token = next_token(&val, NULL, cfile);
1848 if (token == NUMBER) {
1849 ia->renew = atoi(val);
1850 } else {
1851 parse_warn(cfile, "Expecting a number.");
1852 skip_to_semi(cfile);
1853 no_semi = 1;
1854 }
1855 break;
1856
1857 case REBIND:
1858 token = next_token(&val, NULL, cfile);
1859 if (token == NUMBER) {
1860 ia->rebind = atoi(val);
1861 } else {
1862 parse_warn(cfile, "Expecting a number.");
1863 skip_to_semi(cfile);
1864 no_semi = 1;
1865 }
1866 break;
1867
1868 case IAPREFIX:
1869 *pref = parse_client6_iaprefix_statement(cfile);
1870
1871 if (*pref != NULL)
1872 pref = &(*pref)->next;
1873
1874 no_semi = 1;
1875
1876 break;
1877
1878 case OPTION:
1879 if (parse_option_decl(&oc, cfile)) {
1880 save_option(oc->option->universe,
1881 ia->options, oc);
1882 option_cache_dereference(&oc, MDL);
1883 }
1884 no_semi = 1;
1885 break;
1886
1887 default:
1888 parse_warn(cfile, "Unexpected token.");
1889 no_semi = 1;
1890 skip_to_semi(cfile);
1891 break;
1892 }
1893
1894 if (!no_semi)
1895 parse_semi(cfile);
1896
1897 token = next_token(&val, NULL, cfile);
1898
1899 if (token == END_OF_FILE) {
1900 parse_warn(cfile, "Unexpected end of file.");
1901 break;
1902 }
1903 }
1904
1905 return ia;
1906 }
1907 #endif /* DHCPv6 */
1908
1909 /* Parse an iaaddr {} structure. */
1910 #ifdef DHCPv6
1911 static struct dhc6_addr *
1912 parse_client6_iaaddr_statement(struct parse *cfile)
1913 {
1914 struct option_cache *oc = NULL;
1915 struct dhc6_addr *addr;
1916 const char *val;
1917 int token, no_semi;
1918
1919 addr = dmalloc(sizeof(*addr), MDL);
1920 if (addr == NULL) {
1921 parse_warn(cfile, "Unable to allocate IAADDR state.");
1922 skip_to_semi(cfile);
1923 return NULL;
1924 }
1925
1926 /* Get IP address. */
1927 if (!parse_ip6_addr(cfile, &addr->address)) {
1928 skip_to_semi(cfile);
1929 dfree(addr, MDL);
1930 return NULL;
1931 }
1932
1933 token = next_token(NULL, NULL, cfile);
1934 if (token != LBRACE) {
1935 parse_warn(cfile, "Expecting open curly bracket.");
1936 skip_to_semi(cfile);
1937 dfree(addr, MDL);
1938 return NULL;
1939 }
1940
1941 option_state_allocate(&addr->options, MDL);
1942 if (addr->options == NULL) {
1943 parse_warn(cfile, "Unable to allocate option state.");
1944 skip_to_semi(cfile);
1945 dfree(addr, MDL);
1946 return NULL;
1947 }
1948
1949 token = next_token(&val, NULL, cfile);
1950 while (token != RBRACE) {
1951 no_semi = 0;
1952
1953 switch (token) {
1954 case STARTS:
1955 token = next_token(&val, NULL, cfile);
1956 if (token == NUMBER) {
1957 addr->starts = atoi(val);
1958 } else {
1959 parse_warn(cfile, "Expecting a number.");
1960 skip_to_semi(cfile);
1961 no_semi = 1;
1962 }
1963 break;
1964
1965 case PREFERRED_LIFE:
1966 token = next_token(&val, NULL, cfile);
1967 if (token == NUMBER) {
1968 addr->preferred_life = atoi(val);
1969 } else {
1970 parse_warn(cfile, "Expecting a number.");
1971 skip_to_semi(cfile);
1972 no_semi = 1;
1973 }
1974 break;
1975
1976 case MAX_LIFE:
1977 token = next_token(&val, NULL, cfile);
1978 if (token == NUMBER) {
1979 addr->max_life = atoi(val);
1980 } else {
1981 parse_warn(cfile, "Expecting a number.");
1982 skip_to_semi(cfile);
1983 no_semi = 1;
1984 }
1985 break;
1986
1987 case OPTION:
1988 if (parse_option_decl(&oc, cfile)) {
1989 save_option(oc->option->universe,
1990 addr->options, oc);
1991 option_cache_dereference(&oc, MDL);
1992 }
1993 no_semi = 1;
1994 break;
1995
1996 default:
1997 parse_warn(cfile, "Unexpected token.");
1998 skip_to_rbrace(cfile, 1);
1999 no_semi = 1;
2000 break;
2001 }
2002
2003 if (!no_semi)
2004 parse_semi(cfile);
2005
2006 token = next_token(&val, NULL, cfile);
2007 if (token == END_OF_FILE) {
2008 parse_warn(cfile, "Unexpected end of file.");
2009 break;
2010 }
2011 }
2012
2013 return addr;
2014 }
2015 #endif /* DHCPv6 */
2016
2017 /* Parse an iaprefix {} structure. */
2018 #ifdef DHCPv6
2019 static struct dhc6_addr *
2020 parse_client6_iaprefix_statement(struct parse *cfile)
2021 {
2022 struct option_cache *oc = NULL;
2023 struct dhc6_addr *pref;
2024 const char *val;
2025 int token, no_semi;
2026
2027 pref = dmalloc(sizeof(*pref), MDL);
2028 if (pref == NULL) {
2029 parse_warn(cfile, "Unable to allocate IAPREFIX state.");
2030 skip_to_semi(cfile);
2031 return NULL;
2032 }
2033
2034 /* Get IP prefix. */
2035 if (!parse_ip6_prefix(cfile, &pref->address, &pref->plen)) {
2036 skip_to_semi(cfile);
2037 dfree(pref, MDL);
2038 return NULL;
2039 }
2040
2041 token = next_token(NULL, NULL, cfile);
2042 if (token != LBRACE) {
2043 parse_warn(cfile, "Expecting open curly bracket.");
2044 skip_to_semi(cfile);
2045 dfree(pref, MDL);
2046 return NULL;
2047 }
2048
2049 option_state_allocate(&pref->options, MDL);
2050 if (pref->options == NULL) {
2051 parse_warn(cfile, "Unable to allocate option state.");
2052 skip_to_semi(cfile);
2053 dfree(pref, MDL);
2054 return NULL;
2055 }
2056
2057 token = next_token(&val, NULL, cfile);
2058 while (token != RBRACE) {
2059 no_semi = 0;
2060
2061 switch (token) {
2062 case STARTS:
2063 token = next_token(&val, NULL, cfile);
2064 if (token == NUMBER) {
2065 pref->starts = atoi(val);
2066 } else {
2067 parse_warn(cfile, "Expecting a number.");
2068 skip_to_semi(cfile);
2069 no_semi = 1;
2070 }
2071 break;
2072
2073 case PREFERRED_LIFE:
2074 token = next_token(&val, NULL, cfile);
2075 if (token == NUMBER) {
2076 pref->preferred_life = atoi(val);
2077 } else {
2078 parse_warn(cfile, "Expecting a number.");
2079 skip_to_semi(cfile);
2080 no_semi = 1;
2081 }
2082 break;
2083
2084 case MAX_LIFE:
2085 token = next_token(&val, NULL, cfile);
2086 if (token == NUMBER) {
2087 pref->max_life = atoi(val);
2088 } else {
2089 parse_warn(cfile, "Expecting a number.");
2090 skip_to_semi(cfile);
2091 no_semi = 1;
2092 }
2093 break;
2094
2095 case OPTION:
2096 if (parse_option_decl(&oc, cfile)) {
2097 save_option(oc->option->universe,
2098 pref->options, oc);
2099 option_cache_dereference(&oc, MDL);
2100 }
2101 no_semi = 1;
2102 break;
2103
2104 default:
2105 parse_warn(cfile, "Unexpected token.");
2106 skip_to_rbrace(cfile, 1);
2107 no_semi = 1;
2108 break;
2109 }
2110
2111 if (!no_semi)
2112 parse_semi(cfile);
2113
2114 token = next_token(&val, NULL, cfile);
2115 if (token == END_OF_FILE) {
2116 parse_warn(cfile, "Unexpected end of file.");
2117 break;
2118 }
2119 }
2120
2121 return pref;
2122 }
2123 #endif /* DHCPv6 */
2124
2125 void parse_string_list (cfile, lp, multiple)
2126 struct parse *cfile;
2127 struct string_list **lp;
2128 int multiple;
2129 {
2130 int token;
2131 const char *val;
2132 struct string_list *cur, *tmp;
2133
2134 /* Find the last medium in the media list. */
2135 if (*lp) {
2136 for (cur = *lp; cur -> next; cur = cur -> next)
2137 ;
2138 } else {
2139 cur = (struct string_list *)0;
2140 }
2141
2142 do {
2143 token = next_token (&val, (unsigned *)0, cfile);
2144 if (token != STRING) {
2145 parse_warn (cfile, "Expecting media options.");
2146 skip_to_semi (cfile);
2147 return;
2148 }
2149
2150 tmp = ((struct string_list *)
2151 dmalloc (strlen (val) + sizeof (struct string_list),
2152 MDL));
2153 if (!tmp)
2154 log_fatal ("no memory for string list entry.");
2155
2156 strcpy (tmp -> string, val);
2157 tmp -> next = (struct string_list *)0;
2158
2159 /* Store this medium at the end of the media list. */
2160 if (cur)
2161 cur -> next = tmp;
2162 else
2163 *lp = tmp;
2164 cur = tmp;
2165
2166 token = next_token (&val, (unsigned *)0, cfile);
2167 } while (multiple && token == COMMA);
2168
2169 if (token != SEMI) {
2170 parse_warn (cfile, "expecting semicolon.");
2171 skip_to_semi (cfile);
2172 }
2173 }
2174
2175 void parse_reject_statement (cfile, config)
2176 struct parse *cfile;
2177 struct client_config *config;
2178 {
2179 int token;
2180 const char *val;
2181 struct iaddrmatch match;
2182 struct iaddrmatchlist *list;
2183 int i;
2184
2185 do {
2186 if (!parse_ip_addr_with_subnet (cfile, &match)) {
2187 /* no warn: parser will have reported what's wrong */
2188 skip_to_semi (cfile);
2189 return;
2190 }
2191
2192 /* check mask is not all zeros (because that would
2193 * reject EVERY address). This check could be
2194 * simplified if we assume that the mask *always*
2195 * represents a prefix .. but perhaps it might be
2196 * useful to have a mask which is not a proper prefix
2197 * (perhaps for ipv6?). The following is almost as
2198 * efficient as inspection of match.mask.iabuf[0] when
2199 * it IS a true prefix, and is more general when it is
2200 * not.
2201 */
2202
2203 for (i=0 ; i < match.mask.len ; i++) {
2204 if (match.mask.iabuf[i]) {
2205 break;
2206 }
2207 }
2208
2209 if (i == match.mask.len) {
2210 /* oops we found all zeros */
2211 parse_warn(cfile, "zero-length prefix is not permitted "
2212 "for reject statement");
2213 skip_to_semi(cfile);
2214 return;
2215 }
2216
2217 list = dmalloc(sizeof(struct iaddrmatchlist), MDL);
2218 if (!list)
2219 log_fatal ("no memory for reject list!");
2220
2221 list->match = match;
2222 list->next = config->reject_list;
2223 config->reject_list = list;
2224
2225 token = next_token (&val, (unsigned *)0, cfile);
2226 } while (token == COMMA);
2227
2228 if (token != SEMI) {
2229 parse_warn (cfile, "expecting semicolon.");
2230 skip_to_semi (cfile);
2231 }
2232 }
2233
2234 /* allow-deny-keyword :== BOOTP
2235 | BOOTING
2236 | DYNAMIC_BOOTP
2237 | UNKNOWN_CLIENTS */
2238
2239 int parse_allow_deny (oc, cfile, flag)
2240 struct option_cache **oc;
2241 struct parse *cfile;
2242 int flag;
2243 {
2244 parse_warn (cfile, "allow/deny/ignore not permitted here.");
2245 skip_to_semi (cfile);
2246 return 0;
2247 }
2248