diff options
Diffstat (limited to 'contrib/isc-dhcp/client/clparse.c')
| -rw-r--r-- | contrib/isc-dhcp/client/clparse.c | 1011 |
1 files changed, 0 insertions, 1011 deletions
diff --git a/contrib/isc-dhcp/client/clparse.c b/contrib/isc-dhcp/client/clparse.c deleted file mode 100644 index 9af7744f8765..000000000000 --- a/contrib/isc-dhcp/client/clparse.c +++ /dev/null @@ -1,1011 +0,0 @@ -/* clparse.c - - 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''. - */ - -#ifndef lint -static char copyright[] = -"$Id: clparse.c,v 1.13.2.5 2000/07/20 05:06:40 mellon Exp $ Copyright (c) 1997 The Internet Software Consortium. All rights reserved.\n"; -#endif /* not lint */ - -#include "dhcpd.h" -#include "dhctoken.h" - -struct client_config top_level_config; - -char client_script_name [] = "/etc/dhclient-script"; - -/* client-conf-file :== client-declarations EOF - client-declarations :== <nil> - | client-declaration - | client-declarations client-declaration */ - -int read_client_conf () -{ - FILE *cfile; - char *val; - int token; - struct client_config *config; - struct interface_info *ip; - - 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, - (struct interface_info *)0, - &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 = (struct client_config *)0; - for (ip = interfaces; ip; ip = ip -> next) { - if (!ip -> client) { - ip -> client = (struct client_state *) - malloc (sizeof (struct client_state)); - if (!ip -> client) - error ("no memory for client state."); - memset (ip -> client, 0, sizeof *(ip -> client)); - } - if (!ip -> client -> config) { - if (!config) { - config = (struct client_config *) - malloc (sizeof (struct client_config)); - if (!config) - error ("no memory for client config."); - memcpy (config, &top_level_config, - sizeof top_level_config); - } - ip -> 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 () -{ - 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) { - warn ("Corrupt lease file - possible data loss!"); - skip_to_semi (cfile); - break; - } else - parse_client_lease_statement (cfile, 0); - - } while (1); -} - -/* 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 (cfile, ip, config) - 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 (cfile, buf, max) - 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 (cfile, 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: expected option name."); - 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 (cfile, outer_config) - 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); - - ip -> flags &= ~INTERFACE_AUTOMATIC; - interfaces_requested = 1; - - 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 (name) - char *name; -{ - struct interface_info *ip; - - /* Find the interface (if any) that matches the name. */ - for (ip = interfaces; ip; ip = ip -> next) { - if (!strcmp (ip -> name, name)) - break; - } - - /* If it's not a real interface, see if it's on the dummy list. */ - if (!ip) { - for (ip = dummy_interfaces; ip; ip = ip -> next) { - if (!strcmp (ip -> name, name)) - break; - } - } - - /* If we didn't find an interface, make a dummy interface as - a placeholder. */ - if (!ip) { - ip = ((struct interface_info *)malloc (sizeof *ip)); - if (!ip) - error ("Insufficient memory to record interface %s", - name); - memset (ip, 0, sizeof *ip); - strcpy (ip -> name, name); - ip -> next = dummy_interfaces; - dummy_interfaces = ip; - } - return ip; -} - -void make_client_state (ip) - struct interface_info *ip; -{ - ip -> client = - ((struct client_state *)malloc (sizeof *(ip -> client))); - if (!ip -> client) - error ("no memory for state on %s\n", ip -> name); - memset (ip -> client, 0, sizeof *(ip -> client)); -} - -void make_client_config (ip, config) - struct interface_info *ip; - struct client_config *config; -{ - ip -> client -> config = - ((struct client_config *) - malloc (sizeof (struct client_config))); - if (!ip -> client -> config) - error ("no memory for config for %s\n", 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 (cfile, is_static) - 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 = (struct client_lease *)malloc (sizeof (struct client_lease)); - if (!lease) - error ("no memory for lease.\n"); - memset (lease, 0, sizeof *lease); - lease -> is_static = is_static; - - ip = (struct interface_info *)0; - - 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 = (struct client_lease *)0; - 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 (cfile, lease, ipp) - 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 (cfile, options) - 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 (struct option *)0; - } - vendor = malloc (strlen (val) + 1); - if (!vendor) - error ("no memory for vendor information."); - strcpy (vendor, val); - 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 (struct option *)0; - } - - /* 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 (struct option *)0; - } - } 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 (struct option *)0; - } - - /* 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 (struct option *)0; - } - len = strlen (val); - if (hunkix + len + 1 > sizeof hunkbuf) { - parse_warn ("option data buffer %s", - "overflow"); - skip_to_semi (cfile); - return (struct option *)0; - } - memcpy (&hunkbuf [hunkix], val, len + 1); - nul_term = 1; - hunkix += len; - break; - - case 'I': /* IP address. */ - if (!parse_ip_addr (cfile, &ip_addr)) - return (struct option *)0; - len = ip_addr.len; - dp = ip_addr.iabuf; - - alloc: - if (hunkix + len > sizeof hunkbuf) { - parse_warn ("option data buffer %s", - "overflow"); - skip_to_semi (cfile); - return (struct option *)0; - } - 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 (struct option *)0; - } - 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 (struct option *)0; - } - 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: - warn ("Bad format %c in parse_option_param.", - *fmt); - skip_to_semi (cfile); - return (struct option *)0; - } - } - token = next_token (&val, cfile); - } while (*fmt == 'A' && token == COMMA); - - if (token != SEMI) { - parse_warn ("semicolon expected."); - skip_to_semi (cfile); - return (struct option *)0; - } - - options [option -> code].data = - (unsigned char *)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 (cfile, lp, multiple) - 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) - ; - } else { - cur = (struct string_list *)0; - } - - do { - token = next_token (&val, cfile); - if (token != STRING) { - parse_warn ("Expecting media options."); - skip_to_semi (cfile); - return; - } - - tmp = (struct string_list *)malloc (strlen (val) + 1 + - sizeof - (struct string_list *)); - if (!tmp) - error ("no memory for string list entry."); - - strcpy (tmp -> string, val); - tmp -> next = (struct string_list *)0; - - /* 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 (cfile, config) - 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 = (struct iaddrlist *)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); - } -} |
