File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dhcp / client / clparse.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Oct 9 09:06:54 2012 UTC (11 years, 11 months ago) by misho
Branches: dhcp, MAIN
CVS tags: v4_1_R7p0, v4_1_R7, v4_1_R4, HEAD
dhcp 4.1 r7

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>