summaryrefslogtreecommitdiff
path: root/sbin/dhclient/clparse.c
diff options
context:
space:
mode:
Diffstat (limited to 'sbin/dhclient/clparse.c')
-rw-r--r--sbin/dhclient/clparse.c938
1 files changed, 0 insertions, 938 deletions
diff --git a/sbin/dhclient/clparse.c b/sbin/dhclient/clparse.c
deleted file mode 100644
index 2777902c7767..000000000000
--- a/sbin/dhclient/clparse.c
+++ /dev/null
@@ -1,938 +0,0 @@
-/* $OpenBSD: clparse.c,v 1.18 2004/09/15 18:15:18 henning Exp $ */
-
-/* Parser for dhclient config and lease files... */
-
-/*
- * Copyright (c) 1997 The Internet Software Consortium.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of The Internet Software Consortium nor the names
- * of its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
- * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * This software has been written for the Internet Software Consortium
- * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
- * Enterprises. To learn more about the Internet Software Consortium,
- * see ``http://www.vix.com/isc''. To learn more about Vixie
- * Enterprises, see ``http://www.vix.com''.
- */
-
-#include "dhcpd.h"
-#include "dhctoken.h"
-
-struct client_config top_level_config;
-struct interface_info *dummy_interfaces;
-extern struct interface_info *ifi;
-
-char client_script_name[] = "/sbin/dhclient-script";
-
-/*
- * client-conf-file :== client-declarations EOF
- * client-declarations :== <nil>
- * | client-declaration
- * | client-declarations client-declaration
- */
-int
-read_client_conf(void)
-{
- FILE *cfile;
- char *val;
- int token;
- struct client_config *config;
-
- new_parse(path_dhclient_conf);
-
- /* Set up the initial dhcp option universe. */
- initialize_universes();
-
- /* Initialize the top level client configuration. */
- memset(&top_level_config, 0, sizeof(top_level_config));
-
- /* Set some defaults... */
- top_level_config.timeout = 60;
- top_level_config.select_interval = 0;
- top_level_config.reboot_timeout = 10;
- top_level_config.retry_interval = 300;
- top_level_config.backoff_cutoff = 15;
- top_level_config.initial_interval = 3;
- top_level_config.bootp_policy = ACCEPT;
- top_level_config.script_name = client_script_name;
- top_level_config.requested_options
- [top_level_config.requested_option_count++] = DHO_SUBNET_MASK;
- top_level_config.requested_options
- [top_level_config.requested_option_count++] = DHO_BROADCAST_ADDRESS;
- top_level_config.requested_options
- [top_level_config.requested_option_count++] = DHO_TIME_OFFSET;
- top_level_config.requested_options
- [top_level_config.requested_option_count++] = DHO_ROUTERS;
- top_level_config.requested_options
- [top_level_config.requested_option_count++] = DHO_DOMAIN_NAME;
- top_level_config.requested_options
- [top_level_config.requested_option_count++] =
- DHO_DOMAIN_NAME_SERVERS;
- top_level_config.requested_options
- [top_level_config.requested_option_count++] = DHO_HOST_NAME;
-
- if ((cfile = fopen(path_dhclient_conf, "r")) != NULL) {
- do {
- token = peek_token(&val, cfile);
- if (token == EOF)
- break;
- parse_client_statement(cfile, NULL, &top_level_config);
- } while (1);
- token = next_token(&val, cfile); /* Clear the peek buffer */
- fclose(cfile);
- }
-
- /*
- * Set up state and config structures for clients that don't
- * have per-interface configuration declarations.
- */
- config = NULL;
- if (!ifi->client) {
- ifi->client = malloc(sizeof(struct client_state));
- if (!ifi->client)
- error("no memory for client state.");
- memset(ifi->client, 0, sizeof(*(ifi->client)));
- }
- if (!ifi->client->config) {
- if (!config) {
- config = malloc(sizeof(struct client_config));
- if (!config)
- error("no memory for client config.");
- memcpy(config, &top_level_config,
- sizeof(top_level_config));
- }
- ifi->client->config = config;
- }
-
- return (!warnings_occurred);
-}
-
-/*
- * lease-file :== client-lease-statements EOF
- * client-lease-statements :== <nil>
- * | client-lease-statements LEASE client-lease-statement
- */
-void
-read_client_leases(void)
-{
- FILE *cfile;
- char *val;
- int token;
-
- new_parse(path_dhclient_db);
-
- /* Open the lease file. If we can't open it, just return -
- we can safely trust the server to remember our state. */
- if ((cfile = fopen(path_dhclient_db, "r")) == NULL)
- return;
- do {
- token = next_token(&val, cfile);
- if (token == EOF)
- break;
- if (token != LEASE) {
- warning("Corrupt lease file - possible data loss!");
- skip_to_semi(cfile);
- break;
- } else
- parse_client_lease_statement(cfile, 0);
-
- } while (1);
- fclose(cfile);
-}
-
-/*
- * client-declaration :==
- * SEND option-decl |
- * DEFAULT option-decl |
- * SUPERSEDE option-decl |
- * PREPEND option-decl |
- * APPEND option-decl |
- * hardware-declaration |
- * REQUEST option-list |
- * REQUIRE option-list |
- * TIMEOUT number |
- * RETRY number |
- * REBOOT number |
- * SELECT_TIMEOUT number |
- * SCRIPT string |
- * interface-declaration |
- * LEASE client-lease-statement |
- * ALIAS client-lease-statement
- */
-void
-parse_client_statement(FILE *cfile, struct interface_info *ip,
- struct client_config *config)
-{
- int token;
- char *val;
- struct option *option;
-
- switch (next_token(&val, cfile)) {
- case SEND:
- parse_option_decl(cfile, &config->send_options[0]);
- return;
- case DEFAULT:
- option = parse_option_decl(cfile, &config->defaults[0]);
- if (option)
- config->default_actions[option->code] = ACTION_DEFAULT;
- return;
- case SUPERSEDE:
- option = parse_option_decl(cfile, &config->defaults[0]);
- if (option)
- config->default_actions[option->code] =
- ACTION_SUPERSEDE;
- return;
- case APPEND:
- option = parse_option_decl(cfile, &config->defaults[0]);
- if (option)
- config->default_actions[option->code] = ACTION_APPEND;
- return;
- case PREPEND:
- option = parse_option_decl(cfile, &config->defaults[0]);
- if (option)
- config->default_actions[option->code] = ACTION_PREPEND;
- return;
- case MEDIA:
- parse_string_list(cfile, &config->media, 1);
- return;
- case HARDWARE:
- if (ip)
- parse_hardware_param(cfile, &ip->hw_address);
- else {
- parse_warn("hardware address parameter %s",
- "not allowed here.");
- skip_to_semi(cfile);
- }
- return;
- case REQUEST:
- config->requested_option_count =
- parse_option_list(cfile, config->requested_options);
- return;
- case REQUIRE:
- memset(config->required_options, 0,
- sizeof(config->required_options));
- parse_option_list(cfile, config->required_options);
- return;
- case TIMEOUT:
- parse_lease_time(cfile, &config->timeout);
- return;
- case RETRY:
- parse_lease_time(cfile, &config->retry_interval);
- return;
- case SELECT_TIMEOUT:
- parse_lease_time(cfile, &config->select_interval);
- return;
- case REBOOT:
- parse_lease_time(cfile, &config->reboot_timeout);
- return;
- case BACKOFF_CUTOFF:
- parse_lease_time(cfile, &config->backoff_cutoff);
- return;
- case INITIAL_INTERVAL:
- parse_lease_time(cfile, &config->initial_interval);
- return;
- case SCRIPT:
- config->script_name = parse_string(cfile);
- return;
- case INTERFACE:
- if (ip)
- parse_warn("nested interface declaration.");
- parse_interface_declaration(cfile, config);
- return;
- case LEASE:
- parse_client_lease_statement(cfile, 1);
- return;
- case ALIAS:
- parse_client_lease_statement(cfile, 2);
- return;
- case REJECT:
- parse_reject_statement(cfile, config);
- return;
- default:
- parse_warn("expecting a statement.");
- skip_to_semi(cfile);
- break;
- }
- token = next_token(&val, cfile);
- if (token != SEMI) {
- parse_warn("semicolon expected.");
- skip_to_semi(cfile);
- }
-}
-
-int
-parse_X(FILE *cfile, u_int8_t *buf, int max)
-{
- int token;
- char *val;
- int len;
-
- token = peek_token(&val, cfile);
- if (token == NUMBER_OR_NAME || token == NUMBER) {
- len = 0;
- do {
- token = next_token(&val, cfile);
- if (token != NUMBER && token != NUMBER_OR_NAME) {
- parse_warn("expecting hexadecimal constant.");
- skip_to_semi(cfile);
- return (0);
- }
- convert_num(&buf[len], val, 16, 8);
- if (len++ > max) {
- parse_warn("hexadecimal constant too long.");
- skip_to_semi(cfile);
- return (0);
- }
- token = peek_token(&val, cfile);
- if (token == COLON)
- token = next_token(&val, cfile);
- } while (token == COLON);
- val = (char *)buf;
- } else if (token == STRING) {
- token = next_token(&val, cfile);
- len = strlen(val);
- if (len + 1 > max) {
- parse_warn("string constant too long.");
- skip_to_semi(cfile);
- return (0);
- }
- memcpy(buf, val, len + 1);
- } else {
- parse_warn("expecting string or hexadecimal data");
- skip_to_semi(cfile);
- return (0);
- }
- return (len);
-}
-
-/*
- * option-list :== option_name |
- * option_list COMMA option_name
- */
-int
-parse_option_list(FILE *cfile, u_int8_t *list)
-{
- int ix, i;
- int token;
- char *val;
-
- ix = 0;
- do {
- token = next_token(&val, cfile);
- if (!is_identifier(token)) {
- parse_warn("expected option name.");
- skip_to_semi(cfile);
- return (0);
- }
- for (i = 0; i < 256; i++)
- if (!strcasecmp(dhcp_options[i].name, val))
- break;
-
- if (i == 256) {
- parse_warn("%s: unexpected option name.", val);
- skip_to_semi(cfile);
- return (0);
- }
- list[ix++] = i;
- if (ix == 256) {
- parse_warn("%s: too many options.", val);
- skip_to_semi(cfile);
- return (0);
- }
- token = next_token(&val, cfile);
- } while (token == COMMA);
- if (token != SEMI) {
- parse_warn("expecting semicolon.");
- skip_to_semi(cfile);
- return (0);
- }
- return (ix);
-}
-
-/*
- * interface-declaration :==
- * INTERFACE string LBRACE client-declarations RBRACE
- */
-void
-parse_interface_declaration(FILE *cfile, struct client_config *outer_config)
-{
- int token;
- char *val;
- struct interface_info *ip;
-
- token = next_token(&val, cfile);
- if (token != STRING) {
- parse_warn("expecting interface name (in quotes).");
- skip_to_semi(cfile);
- return;
- }
-
- ip = interface_or_dummy(val);
-
- if (!ip->client)
- make_client_state(ip);
-
- if (!ip->client->config)
- make_client_config(ip, outer_config);
-
- token = next_token(&val, cfile);
- if (token != LBRACE) {
- parse_warn("expecting left brace.");
- skip_to_semi(cfile);
- return;
- }
-
- do {
- token = peek_token(&val, cfile);
- if (token == EOF) {
- parse_warn("unterminated interface declaration.");
- return;
- }
- if (token == RBRACE)
- break;
- parse_client_statement(cfile, ip, ip->client->config);
- } while (1);
- token = next_token(&val, cfile);
-}
-
-struct interface_info *
-interface_or_dummy(char *name)
-{
- struct interface_info *ip;
-
- /* Find the interface (if any) that matches the name. */
- if (!strcmp(ifi->name, name))
- return (ifi);
-
- /* If it's not a real interface, see if it's on the dummy list. */
- for (ip = dummy_interfaces; ip; ip = ip->next)
- if (!strcmp(ip->name, name))
- return (ip);
-
- /*
- * If we didn't find an interface, make a dummy interface as a
- * placeholder.
- */
- ip = malloc(sizeof(*ip));
- if (!ip)
- error("Insufficient memory to record interface %s", name);
- memset(ip, 0, sizeof(*ip));
- strlcpy(ip->name, name, IFNAMSIZ);
- ip->next = dummy_interfaces;
- dummy_interfaces = ip;
- return (ip);
-}
-
-void
-make_client_state(struct interface_info *ip)
-{
- ip->client = malloc(sizeof(*(ip->client)));
- if (!ip->client)
- error("no memory for state on %s", ip->name);
- memset(ip->client, 0, sizeof(*(ip->client)));
-}
-
-void
-make_client_config(struct interface_info *ip, struct client_config *config)
-{
- ip->client->config = malloc(sizeof(struct client_config));
- if (!ip->client->config)
- error("no memory for config for %s", ip->name);
- memset(ip->client->config, 0, sizeof(*(ip->client->config)));
- memcpy(ip->client->config, config, sizeof(*config));
-}
-
-/*
- * client-lease-statement :==
- * RBRACE client-lease-declarations LBRACE
- *
- * client-lease-declarations :==
- * <nil> |
- * client-lease-declaration |
- * client-lease-declarations client-lease-declaration
- */
-void
-parse_client_lease_statement(FILE *cfile, int is_static)
-{
- struct client_lease *lease, *lp, *pl;
- struct interface_info *ip;
- int token;
- char *val;
-
- token = next_token(&val, cfile);
- if (token != LBRACE) {
- parse_warn("expecting left brace.");
- skip_to_semi(cfile);
- return;
- }
-
- lease = malloc(sizeof(struct client_lease));
- if (!lease)
- error("no memory for lease.");
- memset(lease, 0, sizeof(*lease));
- lease->is_static = is_static;
-
- ip = NULL;
-
- do {
- token = peek_token(&val, cfile);
- if (token == EOF) {
- parse_warn("unterminated lease declaration.");
- return;
- }
- if (token == RBRACE)
- break;
- parse_client_lease_declaration(cfile, lease, &ip);
- } while (1);
- token = next_token(&val, cfile);
-
- /* If the lease declaration didn't include an interface
- * declaration that we recognized, it's of no use to us.
- */
- if (!ip) {
- free_client_lease(lease);
- return;
- }
-
- /* Make sure there's a client state structure... */
- if (!ip->client)
- make_client_state(ip);
-
- /* If this is an alias lease, it doesn't need to be sorted in. */
- if (is_static == 2) {
- ip->client->alias = lease;
- return;
- }
-
- /*
- * The new lease may supersede a lease that's not the active
- * lease but is still on the lease list, so scan the lease list
- * looking for a lease with the same address, and if we find it,
- * toss it.
- */
- pl = NULL;
- for (lp = ip->client->leases; lp; lp = lp->next) {
- if (lp->address.len == lease->address.len &&
- !memcmp(lp->address.iabuf, lease->address.iabuf,
- lease->address.len)) {
- if (pl)
- pl->next = lp->next;
- else
- ip->client->leases = lp->next;
- free_client_lease(lp);
- break;
- }
- }
-
- /*
- * If this is a preloaded lease, just put it on the list of
- * recorded leases - don't make it the active lease.
- */
- if (is_static) {
- lease->next = ip->client->leases;
- ip->client->leases = lease;
- return;
- }
-
- /*
- * The last lease in the lease file on a particular interface is
- * the active lease for that interface. Of course, we don't
- * know what the last lease in the file is until we've parsed
- * the whole file, so at this point, we assume that the lease we
- * just parsed is the active lease for its interface. If
- * there's already an active lease for the interface, and this
- * lease is for the same ip address, then we just toss the old
- * active lease and replace it with this one. If this lease is
- * for a different address, then if the old active lease has
- * expired, we dump it; if not, we put it on the list of leases
- * for this interface which are still valid but no longer
- * active.
- */
- if (ip->client->active) {
- if (ip->client->active->expiry < cur_time)
- free_client_lease(ip->client->active);
- else if (ip->client->active->address.len ==
- lease->address.len &&
- !memcmp(ip->client->active->address.iabuf,
- lease->address.iabuf, lease->address.len))
- free_client_lease(ip->client->active);
- else {
- ip->client->active->next = ip->client->leases;
- ip->client->leases = ip->client->active;
- }
- }
- ip->client->active = lease;
-
- /* Phew. */
-}
-
-/*
- * client-lease-declaration :==
- * BOOTP |
- * INTERFACE string |
- * FIXED_ADDR ip_address |
- * FILENAME string |
- * SERVER_NAME string |
- * OPTION option-decl |
- * RENEW time-decl |
- * REBIND time-decl |
- * EXPIRE time-decl
- */
-void
-parse_client_lease_declaration(FILE *cfile, struct client_lease *lease,
- struct interface_info **ipp)
-{
- int token;
- char *val;
- struct interface_info *ip;
-
- switch (next_token(&val, cfile)) {
- case BOOTP:
- lease->is_bootp = 1;
- break;
- case INTERFACE:
- token = next_token(&val, cfile);
- if (token != STRING) {
- parse_warn("expecting interface name (in quotes).");
- skip_to_semi(cfile);
- break;
- }
- ip = interface_or_dummy(val);
- *ipp = ip;
- break;
- case FIXED_ADDR:
- if (!parse_ip_addr(cfile, &lease->address))
- return;
- break;
- case MEDIUM:
- parse_string_list(cfile, &lease->medium, 0);
- return;
- case FILENAME:
- lease->filename = parse_string(cfile);
- return;
- case SERVER_NAME:
- lease->server_name = parse_string(cfile);
- return;
- case RENEW:
- lease->renewal = parse_date(cfile);
- return;
- case REBIND:
- lease->rebind = parse_date(cfile);
- return;
- case EXPIRE:
- lease->expiry = parse_date(cfile);
- return;
- case OPTION:
- parse_option_decl(cfile, lease->options);
- return;
- default:
- parse_warn("expecting lease declaration.");
- skip_to_semi(cfile);
- break;
- }
- token = next_token(&val, cfile);
- if (token != SEMI) {
- parse_warn("expecting semicolon.");
- skip_to_semi(cfile);
- }
-}
-
-struct option *
-parse_option_decl(FILE *cfile, struct option_data *options)
-{
- char *val;
- int token;
- u_int8_t buf[4];
- u_int8_t hunkbuf[1024];
- int hunkix = 0;
- char *vendor;
- char *fmt;
- struct universe *universe;
- struct option *option;
- struct iaddr ip_addr;
- u_int8_t *dp;
- int len;
- int nul_term = 0;
-
- token = next_token(&val, cfile);
- if (!is_identifier(token)) {
- parse_warn("expecting identifier after option keyword.");
- if (token != SEMI)
- skip_to_semi(cfile);
- return (NULL);
- }
- if ((vendor = strdup(val)) == NULL)
- error("no memory for vendor information.");
-
- token = peek_token(&val, cfile);
- if (token == DOT) {
- /* Go ahead and take the DOT token... */
- token = next_token(&val, cfile);
-
- /* The next token should be an identifier... */
- token = next_token(&val, cfile);
- if (!is_identifier(token)) {
- parse_warn("expecting identifier after '.'");
- if (token != SEMI)
- skip_to_semi(cfile);
- return (NULL);
- }
-
- /* Look up the option name hash table for the specified
- vendor. */
- universe = ((struct universe *)hash_lookup(&universe_hash,
- (unsigned char *)vendor, 0));
- /* If it's not there, we can't parse the rest of the
- declaration. */
- if (!universe) {
- parse_warn("no vendor named %s.", vendor);
- skip_to_semi(cfile);
- return (NULL);
- }
- } else {
- /* Use the default hash table, which contains all the
- standard dhcp option names. */
- val = vendor;
- universe = &dhcp_universe;
- }
-
- /* Look up the actual option info... */
- option = (struct option *)hash_lookup(universe->hash,
- (unsigned char *)val, 0);
-
- /* If we didn't get an option structure, it's an undefined option. */
- if (!option) {
- if (val == vendor)
- parse_warn("no option named %s", val);
- else
- parse_warn("no option named %s for vendor %s",
- val, vendor);
- skip_to_semi(cfile);
- return (NULL);
- }
-
- /* Free the initial identifier token. */
- free(vendor);
-
- /* Parse the option data... */
- do {
- for (fmt = option->format; *fmt; fmt++) {
- if (*fmt == 'A')
- break;
- switch (*fmt) {
- case 'X':
- len = parse_X(cfile, &hunkbuf[hunkix],
- sizeof(hunkbuf) - hunkix);
- hunkix += len;
- break;
- case 't': /* Text string... */
- token = next_token(&val, cfile);
- if (token != STRING) {
- parse_warn("expecting string.");
- skip_to_semi(cfile);
- return (NULL);
- }
- len = strlen(val);
- if (hunkix + len + 1 > sizeof(hunkbuf)) {
- parse_warn("option data buffer %s",
- "overflow");
- skip_to_semi(cfile);
- return (NULL);
- }
- memcpy(&hunkbuf[hunkix], val, len + 1);
- nul_term = 1;
- hunkix += len;
- break;
- case 'I': /* IP address. */
- if (!parse_ip_addr(cfile, &ip_addr))
- return (NULL);
- len = ip_addr.len;
- dp = ip_addr.iabuf;
-alloc:
- if (hunkix + len > sizeof(hunkbuf)) {
- parse_warn("option data buffer "
- "overflow");
- skip_to_semi(cfile);
- return (NULL);
- }
- memcpy(&hunkbuf[hunkix], dp, len);
- hunkix += len;
- break;
- case 'L': /* Unsigned 32-bit integer... */
- case 'l': /* Signed 32-bit integer... */
- token = next_token(&val, cfile);
- if (token != NUMBER) {
-need_number:
- parse_warn("expecting number.");
- if (token != SEMI)
- skip_to_semi(cfile);
- return (NULL);
- }
- convert_num(buf, val, 0, 32);
- len = 4;
- dp = buf;
- goto alloc;
- case 's': /* Signed 16-bit integer. */
- case 'S': /* Unsigned 16-bit integer. */
- token = next_token(&val, cfile);
- if (token != NUMBER)
- goto need_number;
- convert_num(buf, val, 0, 16);
- len = 2;
- dp = buf;
- goto alloc;
- case 'b': /* Signed 8-bit integer. */
- case 'B': /* Unsigned 8-bit integer. */
- token = next_token(&val, cfile);
- if (token != NUMBER)
- goto need_number;
- convert_num(buf, val, 0, 8);
- len = 1;
- dp = buf;
- goto alloc;
- case 'f': /* Boolean flag. */
- token = next_token(&val, cfile);
- if (!is_identifier(token)) {
- parse_warn("expecting identifier.");
-bad_flag:
- if (token != SEMI)
- skip_to_semi(cfile);
- return (NULL);
- }
- if (!strcasecmp(val, "true") ||
- !strcasecmp(val, "on"))
- buf[0] = 1;
- else if (!strcasecmp(val, "false") ||
- !strcasecmp(val, "off"))
- buf[0] = 0;
- else {
- parse_warn("expecting boolean.");
- goto bad_flag;
- }
- len = 1;
- dp = buf;
- goto alloc;
- default:
- warning("Bad format %c in parse_option_param.",
- *fmt);
- skip_to_semi(cfile);
- return (NULL);
- }
- }
- token = next_token(&val, cfile);
- } while (*fmt == 'A' && token == COMMA);
-
- if (token != SEMI) {
- parse_warn("semicolon expected.");
- skip_to_semi(cfile);
- return (NULL);
- }
-
- options[option->code].data = malloc(hunkix + nul_term);
- if (!options[option->code].data)
- error("out of memory allocating option data.");
- memcpy(options[option->code].data, hunkbuf, hunkix + nul_term);
- options[option->code].len = hunkix;
- return (option);
-}
-
-void
-parse_string_list(FILE *cfile, struct string_list **lp, int multiple)
-{
- int token;
- char *val;
- struct string_list *cur, *tmp;
-
- /* Find the last medium in the media list. */
- if (*lp)
- for (cur = *lp; cur->next; cur = cur->next)
- ; /* nothing */
- else
- cur = NULL;
-
- do {
- token = next_token(&val, cfile);
- if (token != STRING) {
- parse_warn("Expecting media options.");
- skip_to_semi(cfile);
- return;
- }
-
- tmp = new_string_list(strlen(val) + 1);
- if (tmp == NULL)
- error("no memory for string list entry.");
- strlcpy(tmp->string, val, strlen(val) + 1);
- tmp->next = NULL;
-
- /* Store this medium at the end of the media list. */
- if (cur)
- cur->next = tmp;
- else
- *lp = tmp;
- cur = tmp;
-
- token = next_token(&val, cfile);
- } while (multiple && token == COMMA);
-
- if (token != SEMI) {
- parse_warn("expecting semicolon.");
- skip_to_semi(cfile);
- }
-}
-
-void
-parse_reject_statement(FILE *cfile, struct client_config *config)
-{
- int token;
- char *val;
- struct iaddr addr;
- struct iaddrlist *list;
-
- do {
- if (!parse_ip_addr(cfile, &addr)) {
- parse_warn("expecting IP address.");
- skip_to_semi(cfile);
- return;
- }
-
- list = malloc(sizeof(struct iaddrlist));
- if (!list)
- error("no memory for reject list!");
-
- list->addr = addr;
- list->next = config->reject_list;
- config->reject_list = list;
-
- token = next_token(&val, cfile);
- } while (token == COMMA);
-
- if (token != SEMI) {
- parse_warn("expecting semicolon.");
- skip_to_semi(cfile);
- }
-}