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