diff options
author | Ted Lemon <source@isc.org> | 1997-02-22 12:59:29 +0000 |
---|---|---|
committer | Ted Lemon <source@isc.org> | 1997-02-22 12:59:29 +0000 |
commit | ed1d504ffb0987764e95fee023d30ddc690a0e2a (patch) | |
tree | c62eb52776d819cad8c4043d2afac373d334d018 | |
parent | 6e5382c00db22b9da5e4804970eb7e5754a9634c (diff) | |
download | isc-dhcp-ed1d504ffb0987764e95fee023d30ddc690a0e2a.tar.gz |
moved to client/
-rw-r--r-- | clparse.c | 898 | ||||
-rw-r--r-- | dhclient.8 | 163 | ||||
-rw-r--r-- | dhclient.c | 1617 | ||||
-rw-r--r-- | dhclient.conf.5 | 63 | ||||
-rw-r--r-- | dhclient.conf.cat5 | 66 |
5 files changed, 0 insertions, 2807 deletions
diff --git a/clparse.c b/clparse.c deleted file mode 100644 index 80ad82a5..00000000 --- a/clparse.c +++ /dev/null @@ -1,898 +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.4 1997/02/22 12:23:22 mellon Exp $ Copyright (c) 1997 The Internet Software Consortium. All rights reserved.\n"; -#endif /* not lint */ - -#include "dhcpd.h" -#include "dhctoken.h" - -static TIME parsed_time; - -/* 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; - int declaration = 0; - struct client_config *config; - struct client_state *state; - 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); - - if ((cfile = fopen (path_dhclient_conf, "r")) == NULL) - error ("Can't open %s: %m", path_dhclient_conf); - 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 */ - - /* 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 | - hardware-declaration | - REQUEST option-list | - REQUIRE option-list | - TIMEOUT number | - RETRY 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; - - switch (next_token (&val, cfile)) { - case SEND: - parse_option_decl (cfile, &config -> send_options [0]); - return; - - case DEFAULT: - parse_option_decl (cfile, &config -> defaults [0]); - 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 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; - - 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; - u_int8_t *s; - - 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 = 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 dummy_interface, *ip; - struct client_state dummy_state; - struct client_config dummy_config; - - 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 (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 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; - - /* The current 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; - } - } - /* phew. */ -} - -/* client-lease-declaration :== - 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; - char *t, *n; - struct interface_info *ip; - - switch (next_token (&val, cfile)) { - 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: - parse_ip_addr (cfile, &lease -> address); - 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); - } -} - -void parse_ip_addr (cfile, addr) - FILE *cfile; - struct iaddr *addr; -{ - char *val; - int token; - - addr -> len = 4; - parse_numeric_aggregate (cfile, addr -> iabuf, - &addr -> len, DOT, 10, 8); -} - -void 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; - char *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; - } - 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; - } - - /* Look up the option name hash table for the specified - vendor. */ - universe = (struct universe *)hash_lookup (&universe_hash, - 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; - } - } 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, 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; - } - - /* Free the initial identifier token. */ - free (vendor); - - /* Parse the option data... */ - do { - /* Set a flag if this is an array of a simple type (i.e., - not an array of pairs of IP addresses, or something - like that. */ - int uniform = option -> format [1] == 'A'; - - 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; - } - len = strlen (val); - if (hunkix + len + 1 > sizeof hunkbuf) { - parse_warn ("option data buffer %s", - "overflow"); - skip_to_semi (cfile); - return; - } - memcpy (&hunkbuf [hunkix], val, len + 1); - nul_term = 1; - hunkix += len; - break; - - case 'I': /* IP address. */ - parse_ip_addr (cfile, &ip_addr); - 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; - } - 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; - } - 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; - } - 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; - } - } - token = next_token (&val, cfile); - } while (*fmt == 'A' && token == COMMA); - - if (token != SEMI) { - parse_warn ("semicolon expected."); - skip_to_semi (cfile); - return; - } - - 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; -} - -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); - } -} diff --git a/dhclient.8 b/dhclient.8 deleted file mode 100644 index 6edd6a31..00000000 --- a/dhclient.8 +++ /dev/null @@ -1,163 +0,0 @@ -.\" dhclient.8 -.\" -.\" 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.isc.org/isc''. To learn more about Vixie -.\" Enterprises, see ``http://www.vix.com''. -.TH dhclient 8 -.SH NAME -dhcpd - Dynamic Host Configuration Protocol Client -.SH SYNOPSIS -.B dhclient -[ -.B -p -.I port -] -[ -.B -d -] -[ -.I if0 -[ -.I ...ifN -] -] -.SH DESCRIPTION -The Internet Software Consortium DHCP Client, dhclient, provides a -means for configuring one or more network interfaces using the Dynamic -Host Configuration Protocol, BOOTP protocol, or if these protocols -fail, by statically assigning an address. -.SH OPERATION -.PP -The DHCP protocol allows a host to contact a central server which -maintains a list of IP addresses which may be assigned on one or more -subnets. A DHCP client may request an address from this pool, and -then use it on a temporary basis for communication on network. The -DHCP protocol also provides a mechanism whereby a client can learn -important details about the network to which it is attached, such as -the location of a default router, the location of a name server, and -so on. -.PP -On startup, dhclient reads the -.IR dhclient.conf -for configuration instructions. It then gets a list of all the -network interfaces that are configured in the current system. For -each interface, it attempts to configure the interface using the DHCP -protocol. -.PP -In order to keep track of leases across system reboots and server -restarts, dhclient keeps a list of leases it has been assigned in the -dhclient.leases(5) file. On startup, after reading the dhclient.conf -file, dhclient reads the dhclient.leases file to refresh its memory -about what leases it has been assigned. -.PP -When a new lease is acquired, it is appended to the end of the -dhclient.leases file. In order to prevent the file from becoming -arbitrarily large, from time to time dhclient creates a new -dhclient.leases file from its in-core lease database. The old version -of the dhclient.leases file is retained under the name -.IR dhcpd.leases~ -until the next time dhclient rewrites the database. -.PP -Old leases are kept around in case the DHCP server is unavailable when -dhclient is first invoked (generally during the initial system boot -process). In that event, old leases from the dhclient.leases file -which have not yet expired are tested, and if they are determined to -be valid, they are used until either they expire or the DHCP server -becomes available. -.PP -A mobile host which may sometimes need to access a network on which no -DHCP server exists may be preloaded with a lease for a fixed -address on that network. When all attempts to contact a DHCP server -have failed, dhclient will try to validate the static lease, and if it -succeeds, will use that lease until it is restarted. -.PP -A mobile host may also travel to some networks on which DHCP is not -available but BOOTP is. In that case, it may be advantageous to -arrange with the network administrator for an entry on the BOOTP -database, so that the host can boot quickly on that network rather -than cycling through the list of old leases. -.SH COMMAND LINE -.PP -The names of the network interfaces that dhclient should attempt to -configure may be specified on the command line. If no interface names -are specified on the command line dhclient will identify all network -interfaces, elimininating non-broadcast interfaces if possible, and -attempt to configure each interface. -.PP -If dhclient should listen and transmit on a port other than the -standard (port 68), the -.B -p -flag may used. It should be followed by the udp port number that -dhclient should use. This is mostly useful for debugging purposes. -.PP -Dhclient will normally run in the foreground until it has configured -an interface, and then will revert to running in the background. -To run force dhclient to always run as a foreground process, the -.B -d -flag should be specified. This is useful when running dhclient under -a debugger, or when running it out of inittab on System V systems. -.PP -.SH CONFIGURATION -The syntax of the dhclient.conf(8) file is discussed seperately. -.SH FILES -.B ETCDIR/dhclient.conf, DBDIR/dhclient.leases, RUNDIR/dhclient.pid, -.B DBDIR/dhclient.leases~. -.SH SEE ALSO -dhcpd(8), dhcrelay(8), dhclient.conf(5), dhclient.leases(5) -.SH AUTHOR -.B dhclient(8) -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 -.B http://www.vix.com/isc. -To learn more about Vixie -Enterprises, see -.B http://www.vix.com. -.PP -This client was substantially modified and enhanced by Elliot Poger -for use on Linux while he was working on the MosquitoNet project at -Stanford. -.PP -The current version owes much to Elliot's Linux enhancements, but -was substantially reorganized and partially rewritten by Ted Lemon -so as to use the same networking framework that the Internet Software -Consortium DHCP server uses. Much system-specific configuration code -was moved into a shell script so that as support for more operating -systems is added, it will not be necessary to port and maintain -system-specific configuration code to these operating systems - instead, -the shell script can invoke the native tools to accomplish the same -purpose. -.PP diff --git a/dhclient.c b/dhclient.c deleted file mode 100644 index 150547b8..00000000 --- a/dhclient.c +++ /dev/null @@ -1,1617 +0,0 @@ -/* dhclient.c - - DHCP Client. */ - -/* - * Copyright (c) 1995, 1996, 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''. - * - * This client was substantially modified and enhanced by Elliot Poger - * for use on Linux while he was working on the MosquitoNet project at - * Stanford. - * - * The current version owes much to Elliot's Linux enhancements, but - * was substantially reorganized and partially rewritten by Ted Lemon - * so as to use the same networking framework that the Internet Software - * Consortium DHCP server uses. Much system-specific configuration code - * was moved into a shell script so that as support for more operating - * systems is added, it will not be necessary to port and maintain - * system-specific configuration code to these operating systems - instead, - * the shell script can invoke the native tools to accomplish the same - * purpose. - */ - -#ifndef lint -static char copyright[] = -"$Id: dhclient.c,v 1.26 1997/02/22 12:24:28 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; -#endif /* not lint */ - -#include "dhcpd.h" - -TIME cur_time; -TIME default_lease_time = 43200; /* 12 hours... */ -TIME max_lease_time = 86400; /* 24 hours... */ -struct tree_cache *global_options [256]; - -struct client_config top_level_config; - -char *path_dhclient_conf = _PATH_DHCLIENT_CONF; -char *path_dhclient_db = _PATH_DHCLIENT_DB; -char *path_dhclient_pid = _PATH_DHCLIENT_PID; - -int log_perror = 1; - -struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } }; -struct iaddr iaddr_any = { 4, { 0, 0, 0, 0 } }; -struct in_addr inaddr_any = { INADDR_ANY }; -struct sockaddr_in sockaddr_broadcast; - -/* ASSERT_STATE() does nothing now; it used to be - assert (state_is == state_shouldbe). */ -#define ASSERT_STATE(state_is, state_shouldbe) {} - -#ifdef USE_FALLBACK -struct interface_info fallback_interface; -#endif - -u_int16_t local_port; -u_int16_t remote_port; -int log_priority; -int no_daemon; - -static void usage PROTO ((void)); - -int main (argc, argv, envp) - int argc; - char **argv, **envp; -{ - int i; - struct servent *ent; - struct interface_info *ip; - -#ifdef SYSLOG_4_2 - openlog ("dhclient", LOG_NDELAY); - log_priority = LOG_DAEMON; -#else - openlog ("dhclient", LOG_NDELAY, LOG_DAEMON); -#endif - -#if !(defined (DEBUG) || defined (SYSLOG_4_2)) - setlogmask (LOG_UPTO (LOG_INFO)); -#endif - - for (i = 1; i < argc; i++) { - if (!strcmp (argv [i], "-p")) { - if (++i == argc) - usage (); - local_port = htons (atoi (argv [i])); - debug ("binding to user-specified port %d", - ntohs (local_port)); - } else if (!strcmp (argv [i], "-d")) { - no_daemon = 1; - } else if (argv [i][0] == '-') { - usage (); - } else { - struct interface_info *tmp = - ((struct interface_info *) - dmalloc (sizeof *tmp, "specified_interface")); - if (!tmp) - error ("Insufficient memory to %s %s", - "record interface", argv [i]); - memset (tmp, 0, sizeof *tmp); - strcpy (tmp -> name, argv [i]); - tmp -> next = interfaces; - tmp -> flags = INTERFACE_REQUESTED; - interfaces = tmp; - } - } - /* Default to the DHCP/BOOTP port. */ - if (!local_port) { - ent = getservbyname ("dhcpc", "udp"); - if (!ent) - local_port = htons (68); - else - local_port = ent -> s_port; - endservent (); - } - remote_port = htons (ntohs (local_port) - 1); /* XXX */ - - /* Get the current time... */ - GET_TIME (&cur_time); - - sockaddr_broadcast.sin_family = AF_INET; - sockaddr_broadcast.sin_len = sizeof sockaddr_broadcast; - sockaddr_broadcast.sin_port = remote_port; - sockaddr_broadcast.sin_addr.s_addr = INADDR_BROADCAST; -#ifdef HAVE_SA_LEN - sockaddr_broadcast.sin_len = sizeof sockaddr_broadcast; -#endif - - /* Discover all the network interfaces. */ - discover_interfaces (DISCOVER_UNCONFIGURED); - - /* Parse the dhclient.conf file. */ - read_client_conf (); - - /* Parse the lease database. */ - read_client_leases (); - - /* Rewrite the lease database... */ - rewrite_client_leases (); - - /* If no broadcast interfaces were discovered, call the script - and tell it so. */ - if (!interfaces) { - script_init ((struct interface_info *)0, "NBI", - (struct string_list *)0); - script_go ((struct interface_info *)0); - - /* Nothing more to do. */ - exit (0); - } else { - /* Call the script with the list of interfaces. */ - for (ip = interfaces; ip; ip = ip -> next) { - script_init (ip, "PREINIT", (struct string_list *)0); - if (ip -> client -> alias) - script_write_params (ip, "alias_", - ip -> client -> alias); - script_go (ip); - } - } - - /* At this point, all the interfaces that the script thinks - are relevant should be running, so now we once again call - discover_interfaces(), and this time ask it to actually set - up the interfaces. */ - discover_interfaces (DISCOVER_RUNNING); - - /* Start a configuration state machine for each interface. */ - for (ip = interfaces; ip; ip = ip -> next) { - srandom (cur_time + *(int *)&ip -> hw_address.haddr); - ip -> client -> state = S_INIT; - state_init (ip); - } - - /* Start dispatching packets and timeouts... */ - dispatch (1); - /*NOTREACHED*/ - return 0; -} - -static void usage () -{ - error ("Usage: dhclient [-c] [-p <port>] [interface]"); -} - -void cleanup () -{ -} - -void relay (ip, packet, length) - struct interface_info *ip; - struct dhcp_packet *packet; - int length; -{ -} - -/* Individual States: - * - * Each routine is called from the dhclient_state_machine() in one of - * these conditions: - * -> entering INIT state - * -> recvpacket_flag == 0: timeout in this state - * -> otherwise: received a packet in this state - * - * Return conditions as handled by dhclient_state_machine(): - * Returns 1, sendpacket_flag = 1: send packet, reset timer. - * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone). - * Returns 0: finish the nap which was interrupted for no good reason. - * - * Several per-interface variables are used to keep track of the process: - * active_lease: the lease that is being used on the interface - * (null pointer if not configured yet). - * offered_leases: leases corresponding to DHCPOFFER messages that have - * been sent to us by DHCP servers. - * acked_leases: leases corresponding to DHCPACK messages that have been - * sent to us by DHCP servers. - * sendpacket: DHCP packet we're trying to send. - * destination: IP address to send sendpacket to - * In addition, there are several relevant per-lease variables. - * T1_expiry, T2_expiry, lease_expiry: lease milestones - * In the active lease, these control the process of renewing the lease; - * In leases on the acked_leases list, this simply determines when we - * can no longer legitimately use the lease. - */ - -/* Called on startup and also when a lease has completely expired and - we've been unable to renew it. */ - -void state_init (ip) - struct interface_info *ip; -{ - ASSERT_STATE(state, S_INIT); - - /* Make a DHCPDISCOVER packet, and set appropriate per-interface - flags. */ - make_discover (ip, ip -> client -> active); - ip -> client -> xid = ip -> client -> packet.xid; - ip -> client -> destination = iaddr_broadcast; - ip -> client -> state = S_SELECTING; - ip -> client -> first_sending = cur_time; - ip -> client -> interval = 0; - - /* Add an immediate timeout to cause the first DHCPDISCOVER packet - to go out. */ - send_discover (ip); -} - -/* state_selecting is called when one or more DHCPOFFER packets have been - received and a configurable period of time has passed. */ - -void state_selecting (ip) - struct interface_info *ip; -{ - struct client_lease *lp, *next, *picked; - - ASSERT_STATE(state, S_SELECTING); - - /* Cancel state_selecting and send_discover timeouts, since either - one could have got us here. */ - cancel_timeout (state_selecting, ip); - cancel_timeout (send_discover, ip); - - /* We have received one or more DHCPOFFER packets. Currently, - the only criterion by which we judge leases is whether or - not we get a response when we arp for them. */ - picked = (struct client_lease *)0; - for (lp = ip -> client -> offered_leases; lp; lp = next) { - next = lp -> next; - - /* Check to see if we got an ARPREPLY for the address - in this particular lease. */ - if (!picked) { - script_init (ip, "ARPCHECK", lp -> medium); - script_write_params (ip, "check_", lp); - - /* If the ARPCHECK code detects another - machine using the offered address, it exits - nonzero. We need to send a DHCPDECLINE and - toss the lease. */ - if (script_go (ip)) { - make_decline (ip, lp); - send_decline (ip); - goto freeit; - } - picked = lp; - picked -> next = (struct client_lease *)0; - } else { - freeit: - free_client_lease (lp); - } - } - ip -> client -> offered_leases = (struct client_lease *)0; - - /* If we just tossed all the leases we were offered, go back - to square one. */ - if (!picked) { - send_discover (ip); - return; - } - - /* Go to the REQUESTING state. */ - ip -> client -> destination = iaddr_broadcast; - ip -> client -> state = S_REQUESTING; - ip -> client -> first_sending = cur_time; - ip -> client -> interval = 0; - - /* Make a DHCPREQUEST packet from the lease we picked. */ - make_request (ip, picked); - ip -> client -> xid = ip -> client -> packet.xid; - - /* Toss the lease we picked - we'll get it back in a DHCPACK. */ - free_client_lease (picked); - - /* Add an immediate timeout to send the first DHCPREQUEST packet. */ - send_request (ip); -} - -/* state_requesting is called when we receive a DHCPACK message after - having sent out one or more DHCPREQUEST packets. */ - -void dhcpack (packet) - struct packet *packet; -{ - struct interface_info *ip = packet -> interface; - struct client_lease *lease; - int i; - - note ("DHCPACK from %s", - print_hw_addr (packet -> raw -> htype, - packet -> raw -> hlen, - packet -> raw -> chaddr)); - - /* If we're not receptive to an offer right now, or if the offer - has an unrecognizable transaction id, then just drop it. */ - if (packet -> interface -> client -> xid != packet -> raw -> xid) { - note ("DHCPACK in wrong transaction."); - return; - } - - if (ip -> client -> state != S_REQUESTING && - ip -> client -> state != S_RENEWING && - ip -> client -> state != S_REBINDING) { - note ("DHCPACK in wrong state."); - return; - } - - lease = packet_to_lease (packet); - if (!lease) { - note ("packet_to_lease failed."); - return; - } - - ip -> client -> new = lease; - - /* Stop resending DHCPREQUEST. */ - cancel_timeout (send_request, ip); - - /* Figure out the lease time. */ - ip -> client -> new -> expiry = - getULong (ip -> client -> - new -> options [DHO_DHCP_LEASE_TIME].data); - - /* Take the server-provided renewal time if there is one; - otherwise figure it out according to the spec. */ - if (ip -> client -> new -> options [DHO_DHCP_RENEWAL_TIME].len) - ip -> client -> new -> renewal = - getULong (ip -> client -> - new -> options [DHO_DHCP_RENEWAL_TIME].data); - else - ip -> client -> new -> renewal = - ip -> client -> new -> expiry / 2; - - /* Same deal with the rebind time. */ - if (ip -> client -> new -> options [DHO_DHCP_REBINDING_TIME].len) - ip -> client -> new -> rebind = - getULong (ip -> client -> new -> - options [DHO_DHCP_REBINDING_TIME].data); - else - ip -> client -> new -> rebind = - ip -> client -> new -> renewal + - ip -> client -> new -> renewal / 2 + - ip -> client -> new -> renewal / 4; - - ip -> client -> new -> expiry += cur_time; - ip -> client -> new -> renewal += cur_time; - ip -> client -> new -> rebind += cur_time; - - /* Write out the new lease. */ - write_client_lease (ip, ip -> client -> new); - - /* Remember the medium. */ - ip -> client -> new -> medium = ip -> client -> medium; - - /* Run the client script with the new parameters. */ - script_init (ip, (ip -> client -> state == S_REQUESTING - ? "BOUND" - : (ip -> client -> state == S_RENEWING - ? "RENEW" - : "REBIND")), ip -> client -> new -> medium); - if (ip -> client -> active) - script_write_params (ip, "old_", ip -> client -> active); - script_write_params (ip, "new_", ip -> client -> new); - if (ip -> client -> alias) - script_write_params (ip, "alias_", ip -> client -> alias); - script_go (ip); - - /* Replace the old active lease with the new one. */ - if (ip -> client -> active) - free_client_lease (ip -> client -> active); - ip -> client -> active = ip -> client -> new; - ip -> client -> new = (struct client_lease *)0; - - /* Set up a timeout to start the renewal process. */ - add_timeout (ip -> client -> active -> renewal, - state_bound, ip); - - note ("bound: renewal in %d seconds.", - ip -> client -> active -> renewal - cur_time); - ip -> client -> state = S_BOUND; - reinitialize_interfaces (); - go_daemon (); -} - -/* state_bound is called when we've successfully bound to a particular - lease, but the renewal time on that lease has expired. We are - expected to unicast a DHCPREQUEST to the server that gave us our - original lease. */ - -void state_bound (ip) - struct interface_info *ip; -{ - ASSERT_STATE(state, S_BOUND); - - /* T1 has expired. */ - make_request (ip, ip -> client -> active); - ip -> client -> xid = ip -> client -> packet.xid; - - if (ip -> client -> active -> - options [DHO_DHCP_SERVER_IDENTIFIER].len == 4) { - memcpy (ip -> client -> destination.iabuf, - ip -> client -> active -> - options [DHO_DHCP_SERVER_IDENTIFIER].data, 4); - ip -> client -> destination.len = 4; - } else - ip -> client -> destination = iaddr_broadcast; - - ip -> client -> first_sending = cur_time; - ip -> client -> interval = 0; - ip -> client -> state = S_RENEWING; - - /* Send the first packet immediately. */ - send_request (ip); -} - -int commit_leases () -{ - return 0; -} - -int write_lease (lease) - struct lease *lease; -{ - return 0; -} - -void db_startup () -{ -} - -void bootp (packet) - struct packet *packet; -{ - note ("BOOTREPLY from %s", - print_hw_addr (packet -> raw -> htype, - packet -> raw -> hlen, - packet -> raw -> chaddr)); -} - -void dhcp (packet) - struct packet *packet; -{ - switch (packet -> packet_type) { - case DHCPOFFER: - dhcpoffer (packet); - break; - - case DHCPNAK: - dhcpnak (packet); - break; - - case DHCPACK: - dhcpack (packet); - break; - - default: - break; - } -} - -void dhcpoffer (packet) - struct packet *packet; -{ - struct interface_info *ip = packet -> interface; - struct client_lease *lease, *lp; - int i; - int arp_timeout_needed, stop_selecting; - - note ("DHCPOFFER from %s", - print_hw_addr (packet -> raw -> htype, - packet -> raw -> hlen, - packet -> raw -> chaddr)); - - -#ifdef DEBUG_PACKET - dump_packet (packet); -#endif - - /* If we're not receptive to an offer right now, or if the offer - has an unrecognizable transaction id, then just drop it. */ - if (ip -> client -> state != S_SELECTING || - packet -> interface -> client -> xid != packet -> raw -> xid) { - note ("DHCPOFFER in wrong transaction."); - return; - } - - /* If this lease doesn't supply the minimum required parameters, - blow it off. */ - for (i = 0; ip -> client -> config -> required_options [i]; i++) { - if (!packet -> options [ip -> client -> config -> - required_options [i]].len) { - note ("DHCPOFFER isn't satisfactory."); - return; - } - } - - /* If we've already seen this lease, don't record it again. */ - for (lease = ip -> client -> offered_leases; - lease; lease = lease -> next) { - if (lease -> address.len == sizeof packet -> raw -> yiaddr && - !memcmp (lease -> address.iabuf, - &packet -> raw -> yiaddr, lease -> address.len)) { - note ("DHCPOFFER already seen."); - return; - } - } - - lease = packet_to_lease (packet); - if (!lease) { - note ("packet_to_lease failed."); - return; - } - - /* Record the medium under which this lease was offered. */ - lease -> medium = ip -> client -> medium; - - /* Send out an ARP Request for the offered IP address. */ - script_init (ip, "ARPSEND", lease -> medium); - script_write_params (ip, "check_", lease); - /* If the script can't send an ARP request without waiting, - we'll be waiting when we do the ARPCHECK, so don't wait now. */ - if (script_go (ip)) - arp_timeout_needed = 0; - else - arp_timeout_needed = 2; - - /* Figure out when we're supposed to stop selecting. */ - stop_selecting = (ip -> client -> first_sending + - ip -> client -> config -> select_interval); - - /* If this is the lease we asked for, put it at the head of the - list, and don't mess with the arp request timeout. */ - if (lease -> address.len == ip -> client -> requested_address.len && - !memcmp (lease -> address.iabuf, - ip -> client -> requested_address.iabuf, - ip -> client -> requested_address.len)) { - lease -> next = ip -> client -> offered_leases; - ip -> client -> offered_leases = lease; - } else { - /* If we already have an offer, and arping for this - offer would take us past the selection timeout, - then don't extend the timeout - just hope for the - best. */ - if (ip -> client -> offered_leases && - (cur_time + arp_timeout_needed) > stop_selecting) - arp_timeout_needed = 0; - - /* Put the lease at the end of the list. */ - lease -> next = (struct client_lease *)0; - if (!ip -> client -> offered_leases) - ip -> client -> offered_leases = lease; - else { - for (lp = ip -> client -> offered_leases; lp -> next; - lp = lp -> next) - ; - lp -> next = lease; - } - } - - /* If we're supposed to stop selecting before we've had time - to wait for the ARPREPLY, add some delay to wait for - the ARPREPLY. */ - if (stop_selecting - cur_time < arp_timeout_needed) - stop_selecting = cur_time + arp_timeout_needed; - - /* If the selecting interval has expired, go immediately to - state_selecting(). Otherwise, time out into - state_selecting at the select interval. */ - if (stop_selecting <= 0) - state_selecting (ip); - else - add_timeout (stop_selecting, state_selecting, ip); -} - -/* Allocate a client_lease structure and initialize it from the parameters - in the specified packet. */ - -struct client_lease *packet_to_lease (packet) - struct packet *packet; -{ - struct client_lease *lease; - int i; - - lease = (struct client_lease *)malloc (sizeof (struct client_lease)); - - if (!lease) { - warn ("dhcpoffer: no memory to record lease.\n"); - return (struct client_lease *)0; - } - - memset (lease, 0, sizeof *lease); - - /* Copy the lease options. */ - for (i = 0; i < 256; i++) { - if (packet -> options [i].len) { - lease -> options [i].data = - malloc (packet -> options [i].len); - if (!lease -> options [i].data) { - warn ("dhcpoffer: no memory for option %d\n", - i); - free_client_lease (lease); - return (struct client_lease *)0; - } else { - memcpy (lease -> options [i].data, - packet -> options [i].data, - packet -> options [i].len); - lease -> options [i].len = - packet -> options [i].len; - } - } - } - - lease -> address.len = sizeof (packet -> raw -> yiaddr); - memcpy (lease -> address.iabuf, &packet -> raw -> yiaddr, - lease -> address.len); - - /* If the server name was filled out, copy it. */ - if ((!packet -> options [DHO_DHCP_OPTION_OVERLOAD].len || - !(packet -> options [DHO_DHCP_OPTION_OVERLOAD].data [0] & 2)) && - packet -> raw -> sname [0]) { - int len; - /* Don't count on the NUL terminator. */ - for (len = 0; len < 64; len++) - if (!packet -> raw -> sname [len]) - break; - lease -> server_name = malloc (len + 1); - if (!lease -> server_name) { - warn ("dhcpoffer: no memory for filename.\n"); - free_client_lease (lease); - return (struct client_lease *)0; - } else { - memcpy (lease -> server_name, - packet -> raw -> sname, len); - lease -> server_name [len] = 0; - } - } - - /* Ditto for the filename. */ - if ((!packet -> options [DHO_DHCP_OPTION_OVERLOAD].len || - !(packet -> options [DHO_DHCP_OPTION_OVERLOAD].data [0] & 1)) && - packet -> raw -> file [0]) { - int len; - /* Don't count on the NUL terminator. */ - for (len = 0; len < 64; len++) - if (!packet -> raw -> file [len]) - break; - lease -> filename = malloc (len + 1); - if (!lease -> filename) { - warn ("dhcpoffer: no memory for filename.\n"); - free_client_lease (lease); - return (struct client_lease *)0; - } else { - memcpy (lease -> filename, - packet -> raw -> file, len); - lease -> filename [len] = 0; - } - } - return lease; -} - -void dhcpnak (packet) - struct packet *packet; -{ - note ("DHCPNAK from %s", - print_hw_addr (packet -> raw -> htype, - packet -> raw -> hlen, - packet -> raw -> chaddr)); -} - -/* Send out a DHCPDISCOVER packet, and set a timeout to send out another - one after the right interval has expired. If we are past the renewal - (T1) interval but not yet past the rebind (T2) interval, unicast - the message; otherwise broadcast it. If the lease expires, go back to - the INIT state. */ - -void send_discover (ip) - struct interface_info *ip; -{ - int result; - int interval; - int increase = 1; - - /* Figure out how long it's been since we started transmitting. */ - interval = cur_time - ip -> client -> first_sending; - - /* If we're past the panic timeout, call the script and tell it - we haven't found anything for this interface yet. */ - if (interval > ip -> client -> config -> timeout) { - state_panic (ip); - return; - } - - /* If we're selecting media, try the whole list before doing - the exponential backoff, but if we've already received an - offer, stop looping, because we obviously have it right. */ - if (!ip -> client -> offered_leases && - ip -> client -> config -> media) { - int fail = 0; - again: - if (ip -> client -> medium) { - ip -> client -> medium = - ip -> client -> medium -> next; - increase = 0; - } - if (!ip -> client -> medium) { - if (fail) - error ("No valid media types for %s!", - ip -> name); - ip -> client -> medium = - ip -> client -> config -> media; - increase = 1; - } - - note ("Trying medium \"%s\" %d", - ip -> client -> medium -> string, increase); - script_init (ip, "MEDIUM", ip -> client -> medium); - if (script_go (ip)) { - goto again; - } - } - - /* If we're supposed to increase the interval, do so. If it's - currently zero (i.e., we haven't sent any packets yet), set - it to one; otherwise, add to it a random number between - zero and two times itself. On average, this means that it - will double with every transmission. */ - if (increase) { - if (!ip -> client -> interval) - ip -> client -> interval = 1; - else { - ip -> client -> interval += - random () % (2 * ip -> client -> interval); - } - - /* Don't backoff past 30 seconds. */ - if (ip -> client -> interval > 30) - ip -> client -> interval = - 15 + random () % ip -> client -> interval; - } else if (!ip -> client -> interval) - ip -> client -> interval = 1; - - /* If the backoff would take us to the panic timeout, just use that - as the interval. */ - if (cur_time + ip -> client -> interval > - ip -> client -> first_sending + ip -> client -> config -> timeout) - ip -> client -> interval = - (ip -> client -> first_sending + - ip -> client -> config -> timeout) - cur_time + 1; - - note ("DHCPDISCOVER on %s to %s port %d interval %ld", - ip -> name, - inet_ntoa (sockaddr_broadcast.sin_addr), - ntohs (sockaddr_broadcast.sin_port), ip -> client -> interval); - - /* Send out a packet. */ - result = send_packet (ip, (struct packet *)0, - &ip -> client -> packet, - ip -> client -> packet_length, - inaddr_any, &sockaddr_broadcast, - (struct hardware *)0); - if (result < 0) - warn ("send_packet: %m"); - - add_timeout (cur_time + ip -> client -> interval, send_discover, ip); -} - -/* state_panic gets called if we haven't received any offers in a preset - amount of time. When this happens, we try to use existing leases that - haven't yet expired, and failing that, we call the client script and - hope it can do something. */ - -void state_panic (ip) - struct interface_info *ip; -{ - struct client_lease *loop = ip -> client -> active; - struct client_lease *lp; - - note ("No DHCPOFFERS received."); - - /* Run through the list of leases and see if one can be used. */ - while (ip -> client -> active) { - if (ip -> client -> active -> expiry > cur_time) { - note ("Trying recorded lease %s", - piaddr (ip -> client -> active -> address)); - /* Run the client script with the existing - parameters. */ - script_init (ip, "TIMEOUT", - ip -> client -> active -> medium); - script_write_params (ip, "new_", - ip -> client -> active); - if (ip -> client -> alias) - script_write_params (ip, "alias_", - ip -> client -> alias); - - /* If the old lease is still good and doesn't - yet need renewal, go into BOUND state and - timeout at the renewal time. */ - if (!script_go (ip)) { - if (cur_time < - ip -> client -> active -> renewal) { - ip -> client -> state = S_BOUND; - note ("bound: renewal in %d seconds.", - ip -> client -> active -> renewal - - cur_time); - add_timeout ((ip -> client -> - active -> renewal), - state_bound, ip); - } else { - ip -> client -> state = S_BOUND; - note ("bound: immediate renewal."); - state_bound (ip); - } - reinitialize_interfaces (); - go_daemon (); - return; - } - } - - /* If there are no other leases, give up. */ - if (!ip -> client -> leases) { - ip -> client -> leases = ip -> client -> active; - ip -> client -> active = (struct client_lease *)0; - break; - } - - /* Otherwise, put the active lease at the end of the - lease list, and try another lease.. */ - for (lp = ip -> client -> leases; lp -> next; lp = lp -> next) - ; - lp -> next = ip -> client -> active; - lp -> next -> next = (struct client_lease *)0; - ip -> client -> active = ip -> client -> leases; - ip -> client -> leases = ip -> client -> leases -> next; - - /* If we already tried this lease, we've exhausted the - set of leases, so we might as well give up for - now. */ - if (ip -> client -> active == loop) - break; - } - - /* No leases were available, or what was available didn't work, so - tell the shell script that we failed to allocate an address, - and try again later. */ - note ("No working leases in persistent database - sleeping.\n"); - script_init (ip, "FAIL", (struct string_list *)0); - if (ip -> client -> alias) - script_write_params (ip, "alias_", ip -> client -> alias); - script_go (ip); - ip -> client -> state = S_INIT; - add_timeout (cur_time + ip -> client -> config -> retry_interval, - state_init, ip); -} - -void send_request (ip) - struct interface_info *ip; -{ - int result; - int interval; - struct sockaddr_in destination; - struct in_addr from; - - /* Figure out how long it's been since we started transmitting. */ - interval = cur_time - ip -> client -> first_sending; - - /* If the lease has expired, relinquish the address and go back - to the INIT state. */ - if (ip -> client -> state != S_REQUESTING && - cur_time > ip -> client -> active -> expiry) { - /* Run the client script with the new parameters. */ - script_init (ip, "EXPIRE", (struct string_list *)0); - script_write_params (ip, "old_", ip -> client -> active); - if (ip -> client -> alias) - script_write_params (ip, "alias_", - ip -> client -> alias); - script_go (ip); - - ip -> client -> state = S_INIT; - state_init (ip); - return; - } - - /* Do the exponential backoff... */ - if (!ip -> client -> interval) - ip -> client -> interval = 1; - else - ip -> client -> interval += - random () % (2 * ip -> client -> interval); - - /* Don't backoff past 30 seconds. */ - if (ip -> client -> interval > 30) - ip -> client -> interval = - 15 + random () % ip -> client -> interval; - - /* If the backoff would take us to the expiry time, just set the - timeout to the expiry time. */ - if (ip -> client -> state != S_REQUESTING && - cur_time + ip -> client -> interval > - ip -> client -> active -> expiry) - ip -> client -> interval = - ip -> client -> active -> expiry - cur_time + 1; - - /* If the lease T2 time has elapsed, or if we're not yet bound, - broadcast the DHCPREQUEST rather than unicasting. */ - if (ip -> client -> state == S_REQUESTING || - cur_time > ip -> client -> active -> rebind) - destination.sin_addr.s_addr = INADDR_BROADCAST; - else - memcpy (&destination.sin_addr.s_addr, - ip -> client -> destination.iabuf, - sizeof destination.sin_addr.s_addr); - destination.sin_port = remote_port; - destination.sin_family = AF_INET; -#ifdef HAVE_SA_LEN - destination.sin_len = sizeof destination; -#endif - - if (ip -> client -> state != S_REQUESTING) - memcpy (&from, ip -> client -> active -> address.iabuf, - sizeof from); - else - from.s_addr = INADDR_ANY; - - note ("DHCPREQUEST on %s to %s port %d", ip -> name, - inet_ntoa (destination.sin_addr), - ntohs (destination.sin_port)); - -#ifdef USE_FALLBACK - if (destination.sin_addr.s_addr != INADDR_BROADCAST) - result = send_fallback (&fallback_interface, - (struct packet *)0, - &ip -> client -> packet, - ip -> client -> packet_length, - from, &destination, - (struct hardware *)0); - else -#endif /* USE_FALLBACK */ - /* Send out a packet. */ - result = send_packet (ip, (struct packet *)0, - &ip -> client -> packet, - ip -> client -> packet_length, - from, &destination, - (struct hardware *)0); - - if (result < 0) - warn ("send_packet: %m"); - - add_timeout (cur_time + ip -> client -> interval, - send_request, ip); -} - -void send_decline (ip) - struct interface_info *ip; -{ - int result; - - note ("DHCPDECLINE on %s to %s port %d", ip -> name, - inet_ntoa (sockaddr_broadcast.sin_addr), - ntohs (sockaddr_broadcast.sin_port)); - - /* Send out a packet. */ - result = send_packet (ip, (struct packet *)0, - &ip -> client -> packet, - ip -> client -> packet_length, - inaddr_any, &sockaddr_broadcast, - (struct hardware *)0); - if (result < 0) - warn ("send_packet: %m"); -} - -void send_release (ip) - struct interface_info *ip; -{ - int result; - - note ("DHCPRELEASE on %s to %s port %d", ip -> name, - inet_ntoa (sockaddr_broadcast.sin_addr), - ntohs (sockaddr_broadcast.sin_port)); - - /* Send out a packet. */ - result = send_packet (ip, (struct packet *)0, - &ip -> client -> packet, - ip -> client -> packet_length, - inaddr_any, &sockaddr_broadcast, - (struct hardware *)0); - if (result < 0) - warn ("send_packet: %m"); -} - -void make_discover (ip, lease) - struct interface_info *ip; - struct client_lease *lease; -{ - struct dhcp_packet *raw; - unsigned char discover = DHCPDISCOVER; - - struct tree_cache *options [256]; - struct tree_cache message_type_tree; - struct tree_cache requested_options_tree; - struct tree_cache requested_address_tree; - - memset (options, 0, sizeof options); - memset (&ip -> client -> packet, 0, sizeof (ip -> client -> packet)); - - /* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */ - options [DHO_DHCP_MESSAGE_TYPE] = &message_type_tree; - message_type_tree.value = &discover; - message_type_tree.len = sizeof discover; - message_type_tree.buf_size = sizeof discover; - message_type_tree.timeout = 0xFFFFFFFF; - message_type_tree.tree = (struct tree *)0; - - /* Request the options we want */ - options [DHO_DHCP_PARAMETER_REQUEST_LIST] = &requested_options_tree; - requested_options_tree.value = - ip -> client -> config -> requested_options; - requested_options_tree.len = - ip -> client -> config -> requested_option_count; - requested_options_tree.buf_size = - ip -> client -> config -> requested_option_count; - requested_options_tree.timeout = 0xFFFFFFFF; - requested_options_tree.tree = (struct tree *)0; - - /* If we had an address, try to get it again. */ - if (lease) { - ip -> client -> requested_address = lease -> address; - options [DHO_DHCP_REQUESTED_ADDRESS] = &requested_address_tree; - requested_address_tree.value = lease -> address.iabuf; - requested_address_tree.len = lease -> address.len; - requested_address_tree.buf_size = lease -> address.len; - requested_address_tree.timeout = 0xFFFFFFFF; - requested_address_tree.tree = (struct tree *)0; - } else { - ip -> client -> requested_address.len = 0; - } - - /* Set up the option buffer... */ - ip -> client -> packet_length = - cons_options ((struct packet *)0, &ip -> client -> packet, - options, 0, 0); - - ip -> client -> packet.op = BOOTREQUEST; - ip -> client -> packet.htype = ip -> hw_address.htype; - ip -> client -> packet.hlen = ip -> hw_address.hlen; - ip -> client -> packet.hops = 0; - ip -> client -> packet.xid = random (); - ip -> client -> packet.secs = 0; /* filled in by send_discover. */ - ip -> client -> packet.flags = htons (BOOTP_BROADCAST); /* XXX */ - memset (&(ip -> client -> packet.ciaddr), - 0, sizeof ip -> client -> packet.ciaddr); - memset (&(ip -> client -> packet.yiaddr), - 0, sizeof ip -> client -> packet.yiaddr); - memset (&(ip -> client -> packet.siaddr), - 0, sizeof ip -> client -> packet.siaddr); - memset (&(ip -> client -> packet.giaddr), - 0, sizeof ip -> client -> packet.giaddr); - memcpy (ip -> client -> packet.chaddr, - ip -> hw_address.haddr, ip -> hw_address.hlen); - -#ifdef DEBUG_PACKET - dump_packet (sendpkt); - dump_raw ((unsigned char *)ip -> client -> packet, - sendpkt->packet_length); -#endif -} - - -void make_request (ip, lease) - struct interface_info *ip; - struct client_lease *lease; -{ - unsigned char request = DHCPREQUEST; - - struct tree_cache *options [256]; - struct tree_cache message_type_tree; - struct tree_cache requested_options_tree; - struct tree_cache requested_address_tree; - struct tree_cache server_id_tree; - - memset (options, 0, sizeof options); - memset (&ip -> client -> packet, 0, sizeof (ip -> client -> packet)); - - /* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */ - options [DHO_DHCP_MESSAGE_TYPE] = &message_type_tree; - message_type_tree.value = &request; - message_type_tree.len = sizeof request; - message_type_tree.buf_size = sizeof request; - message_type_tree.timeout = 0xFFFFFFFF; - message_type_tree.tree = (struct tree *)0; - - /* Request the options we want */ - options [DHO_DHCP_PARAMETER_REQUEST_LIST] = &requested_options_tree; - requested_options_tree.value = - ip -> client -> config -> requested_options; - requested_options_tree.len = - ip -> client -> config -> requested_option_count; - requested_options_tree.buf_size = - ip -> client -> config -> requested_option_count; - requested_options_tree.timeout = 0xFFFFFFFF; - requested_options_tree.tree = (struct tree *)0; - - /* Send back the server identifier... */ - options [DHO_DHCP_SERVER_IDENTIFIER] = &server_id_tree; - server_id_tree.value = - lease -> options [DHO_DHCP_SERVER_IDENTIFIER].data; - server_id_tree.len = - lease -> options [DHO_DHCP_SERVER_IDENTIFIER].len; - server_id_tree.buf_size = - lease -> options [DHO_DHCP_SERVER_IDENTIFIER].len; - server_id_tree.timeout = 0xFFFFFFFF; - server_id_tree.tree = (struct tree *)0; - - /* If we are requesting an address that hasn't yet been assigned - to us, use the DHCP Requested Address option. */ - if (ip -> client -> state == S_REQUESTING) { - ip -> client -> requested_address = lease -> address; - options [DHO_DHCP_REQUESTED_ADDRESS] = &requested_address_tree; - requested_address_tree.value = lease -> address.iabuf; - requested_address_tree.len = lease -> address.len; - requested_address_tree.buf_size = lease -> address.len; - requested_address_tree.timeout = 0xFFFFFFFF; - requested_address_tree.tree = (struct tree *)0; - } else { - ip -> client -> requested_address.len = 0; - } - - /* Set up the option buffer... */ - ip -> client -> packet_length = - cons_options ((struct packet *)0, &ip -> client -> packet, - options, 0, 0); - - ip -> client -> packet.op = BOOTREQUEST; - ip -> client -> packet.htype = ip -> hw_address.htype; - ip -> client -> packet.hlen = ip -> hw_address.hlen; - ip -> client -> packet.hops = 0; - ip -> client -> packet.xid = ip -> client -> xid; - ip -> client -> packet.secs = 0; /* Filled in by send_request. */ - ip -> client -> packet.flags = htons (BOOTP_BROADCAST); - - /* If we own the address we're requesting, put it in ciaddr; - otherwise set ciaddr to zero. */ - if (ip -> client -> state == S_BOUND || - ip -> client -> state == S_RENEWING || - ip -> client -> state == S_REBINDING) - memcpy (&ip -> client -> packet.ciaddr, - lease -> address.iabuf, lease -> address.len); - else - memset (&ip -> client -> packet.ciaddr, 0, - sizeof ip -> client -> packet.ciaddr); - - memset (&ip -> client -> packet.yiaddr, 0, - sizeof ip -> client -> packet.yiaddr); - memset (&ip -> client -> packet.siaddr, 0, - sizeof ip -> client -> packet.siaddr); - memset (&ip -> client -> packet.giaddr, 0, - sizeof ip -> client -> packet.giaddr); - memcpy (ip -> client -> packet.chaddr, - ip -> hw_address.haddr, ip -> hw_address.hlen); - -#ifdef DEBUG_PACKET - dump_packet (sendpkt); - dump_raw ((unsigned char *)ip -> client -> packet, sendpkt->packet_length); -#endif -} - -void make_decline (ip, lease) - struct interface_info *ip; - struct client_lease *lease; -{ - unsigned char decline = DHCPDECLINE; - - struct tree_cache *options [256]; - struct tree_cache message_type_tree; - struct tree_cache requested_address_tree; - struct tree_cache server_id_tree; - - memset (options, 0, sizeof options); - memset (&ip -> client -> packet, 0, sizeof (ip -> client -> packet)); - - /* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */ - options [DHO_DHCP_MESSAGE_TYPE] = &message_type_tree; - message_type_tree.value = &decline; - message_type_tree.len = sizeof decline; - message_type_tree.buf_size = sizeof decline; - message_type_tree.timeout = 0xFFFFFFFF; - message_type_tree.tree = (struct tree *)0; - - /* Send back the server identifier... */ - options [DHO_DHCP_SERVER_IDENTIFIER] = &server_id_tree; - server_id_tree.value = - lease -> options [DHO_DHCP_SERVER_IDENTIFIER].data; - server_id_tree.len = - lease -> options [DHO_DHCP_SERVER_IDENTIFIER].len; - server_id_tree.buf_size = - lease -> options [DHO_DHCP_SERVER_IDENTIFIER].len; - server_id_tree.timeout = 0xFFFFFFFF; - server_id_tree.tree = (struct tree *)0; - - /* Send back the address we're declining. */ - options [DHO_DHCP_REQUESTED_ADDRESS] = &requested_address_tree; - requested_address_tree.value = lease -> address.iabuf; - requested_address_tree.len = lease -> address.len; - requested_address_tree.buf_size = lease -> address.len; - requested_address_tree.timeout = 0xFFFFFFFF; - requested_address_tree.tree = (struct tree *)0; - - /* Set up the option buffer... */ - ip -> client -> packet_length = - cons_options ((struct packet *)0, &ip -> client -> packet, - options, 0, 0); - - ip -> client -> packet.op = BOOTREQUEST; - ip -> client -> packet.htype = ip -> hw_address.htype; - ip -> client -> packet.hlen = ip -> hw_address.hlen; - ip -> client -> packet.hops = 0; - ip -> client -> packet.xid = ip -> client -> xid; - ip -> client -> packet.secs = 0; /* Filled in by send_request. */ - ip -> client -> packet.flags = htons (BOOTP_BROADCAST); - - /* ciaddr must always be zero. */ - memset (&ip -> client -> packet.ciaddr, 0, - sizeof ip -> client -> packet.ciaddr); - memset (&ip -> client -> packet.yiaddr, 0, - sizeof ip -> client -> packet.yiaddr); - memset (&ip -> client -> packet.siaddr, 0, - sizeof ip -> client -> packet.siaddr); - memset (&ip -> client -> packet.giaddr, 0, - sizeof ip -> client -> packet.giaddr); - memcpy (ip -> client -> packet.chaddr, - ip -> hw_address.haddr, ip -> hw_address.hlen); - -#ifdef DEBUG_PACKET - dump_packet (sendpkt); - dump_raw ((unsigned char *)ip -> client -> packet, sendpkt->packet_length); -#endif -} - -void make_release (ip, lease) - struct interface_info *ip; - struct client_lease *lease; -{ - unsigned char request = DHCPRELEASE; - - struct tree_cache *options [256]; - struct tree_cache message_type_tree; - struct tree_cache requested_address_tree; - struct tree_cache server_id_tree; - - memset (options, 0, sizeof options); - memset (&ip -> client -> packet, 0, sizeof (ip -> client -> packet)); - - /* Set DHCP_MESSAGE_TYPE to DHCPRELEASE */ - options [DHO_DHCP_MESSAGE_TYPE] = &message_type_tree; - message_type_tree.value = &request; - message_type_tree.len = sizeof request; - message_type_tree.buf_size = sizeof request; - message_type_tree.timeout = 0xFFFFFFFF; - message_type_tree.tree = (struct tree *)0; - - /* Send back the server identifier... */ - options [DHO_DHCP_SERVER_IDENTIFIER] = &server_id_tree; - server_id_tree.value = - lease -> options [DHO_DHCP_SERVER_IDENTIFIER].data; - server_id_tree.len = - lease -> options [DHO_DHCP_SERVER_IDENTIFIER].len; - server_id_tree.buf_size = - lease -> options [DHO_DHCP_SERVER_IDENTIFIER].len; - server_id_tree.timeout = 0xFFFFFFFF; - server_id_tree.tree = (struct tree *)0; - - /* Set up the option buffer... */ - ip -> client -> packet_length = - cons_options ((struct packet *)0, &ip -> client -> packet, - options, 0, 0); - - ip -> client -> packet.op = BOOTREQUEST; - ip -> client -> packet.htype = ip -> hw_address.htype; - ip -> client -> packet.hlen = ip -> hw_address.hlen; - ip -> client -> packet.hops = 0; - ip -> client -> packet.xid = ip -> client -> packet.xid; - ip -> client -> packet.secs = 0; - ip -> client -> packet.flags = 0; - memcpy (&ip -> client -> packet.ciaddr, - lease -> address.iabuf, lease -> address.len); - memset (&ip -> client -> packet.yiaddr, 0, - sizeof ip -> client -> packet.yiaddr); - memset (&ip -> client -> packet.siaddr, 0, - sizeof ip -> client -> packet.siaddr); - memset (&ip -> client -> packet.giaddr, 0, - sizeof ip -> client -> packet.giaddr); - memcpy (ip -> client -> packet.chaddr, - ip -> hw_address.haddr, ip -> hw_address.hlen); - -#ifdef DEBUG_PACKET - dump_packet (sendpkt); - dump_raw ((unsigned char *)ip -> client -> packet, - ip -> client -> packet_length); -#endif -} - -void free_client_lease (lease) - struct client_lease *lease; -{ - int i; - - if (lease -> server_name) - free (lease -> server_name); - if (lease -> filename) - free (lease -> filename); - for (i = 0; i < 256; i++) { - if (lease -> options [i].len) - free (lease -> options [i].data); - } - free (lease); -} - -FILE *leaseFile; - -void rewrite_client_leases () -{ - struct interface_info *ip; - struct client_lease *lp; - - if (leaseFile) - fclose (leaseFile); - leaseFile = fopen (path_dhclient_db, "w"); - if (!leaseFile) - error ("can't create /var/db/dhclient.leases: %m"); - - /* Write out all the leases attached to configured interfaces that - we know about. */ - for (ip = interfaces; ip; ip = ip -> next) { - for (lp = ip -> client -> leases; lp; lp = lp -> next) { - write_client_lease (ip, lp); - } - if (ip -> client -> active) - write_client_lease (ip, ip -> client -> active); - } - - /* Write out any leases that are attached to interfaces that aren't - currently configured. */ - for (ip = dummy_interfaces; ip; ip = ip -> next) { - for (lp = ip -> client -> leases; lp; lp = lp -> next) { - write_client_lease (ip, lp); - } - if (ip -> client -> active) - write_client_lease (ip, ip -> client -> active); - } - fflush (leaseFile); -} - -void write_client_lease (ip, lease) - struct interface_info *ip; - struct client_lease *lease; -{ - int i; - struct tm *t; - - /* If the lease came from the config file, we don't need to stash - a copy in the lease database. */ - if (lease -> is_static) - return; - - if (!leaseFile) { /* XXX */ - leaseFile = fopen (path_dhclient_db, "w"); - if (!leaseFile) - error ("can't create /var/db/dhclient.leases: %m"); - } - - fprintf (leaseFile, "lease {\n"); - fprintf (leaseFile, " interface \"%s\";\n", ip -> name); - fprintf (leaseFile, " fixed-address %s;\n", - piaddr (lease -> address)); - if (lease -> filename) - fprintf (leaseFile, " filename \"%s\";\n", - lease -> filename); - if (lease -> server_name) - fprintf (leaseFile, " server-name \"%s\";\n", - lease -> filename); - if (lease -> medium) - fprintf (leaseFile, " medium \"%s\";\n", - lease -> medium -> string); - for (i = 0; i < 256; i++) { - if (lease -> options [i].len) { - fprintf (leaseFile, - " option %s %s;\n", - dhcp_options [i].name, - pretty_print_option - (i, lease -> options [i].data, - lease -> options [i].len, 1)); - } - } - t = gmtime (&lease -> renewal); - fprintf (leaseFile, - " renew %d %d/%d/%d %02d:%02d:%02d;\n", - t -> tm_wday, t -> tm_year + 1900, - t -> tm_mon + 1, t -> tm_mday, - t -> tm_hour, t -> tm_min, t -> tm_sec); - t = gmtime (&lease -> rebind); - fprintf (leaseFile, - " rebind %d %d/%d/%d %02d:%02d:%02d;\n", - t -> tm_wday, t -> tm_year + 1900, - t -> tm_mon + 1, t -> tm_mday, - t -> tm_hour, t -> tm_min, t -> tm_sec); - t = gmtime (&lease -> expiry); - fprintf (leaseFile, - " expire %d %d/%d/%d %02d:%02d:%02d;\n", - t -> tm_wday, t -> tm_year + 1900, - t -> tm_mon + 1, t -> tm_mday, - t -> tm_hour, t -> tm_min, t -> tm_sec); - fprintf (leaseFile, "}\n"); - fflush (leaseFile); -} - -/* Variables holding name of script and file pointer for writing to - script. Needless to say, this is not reentrant - only one script - can be invoked at a time. */ -char scriptName [256]; -FILE *scriptFile; - -void script_init (ip, reason, medium) - struct interface_info *ip; - char *reason; - struct string_list *medium; -{ - strcpy (scriptName, "/tmp/dcsXXXXXX"); - mktemp (scriptName); - - scriptFile = fopen (scriptName, "w"); - if (!scriptFile) - error ("can't write script file: %m"); - fprintf (scriptFile, "#!/bin/sh\n\n"); - if (ip) { - fprintf (scriptFile, "interface=\"%s\"\n", ip -> name); - fprintf (scriptFile, "export interface\n"); - } - if (medium) { - fprintf (scriptFile, "medium=\"%s\"\n", - ip -> client -> medium -> string); - fprintf (scriptFile, "export medium\n"); - } - fprintf (scriptFile, "reason=\"%s\"\n", reason); - fprintf (scriptFile, "export reason\n"); -} - -void script_write_params (ip, prefix, lease) - struct interface_info *ip; - char *prefix; - struct client_lease *lease; -{ - int i; - - fprintf (scriptFile, "%sip_address=\"%s\"\n", - prefix, piaddr (lease -> address)); - fprintf (scriptFile, "export %sip_address\n", prefix); - if (lease -> filename) { - fprintf (scriptFile, "%sfilename=\"%s\";\n", - prefix, lease -> filename); - fprintf (scriptFile, "export %sfilename\n", prefix); - } - if (lease -> server_name) { - fprintf (scriptFile, "%sserver_name=\"%s\";\n", - prefix, lease -> server_name); - fprintf (scriptFile, "export %sserver_name\n", prefix); - } - for (i = 0; i < 256; i++) { - if (lease -> options [i].len) { - char *s = dhcp_option_ev_name (&dhcp_options [i]); - fprintf (scriptFile, - "%s%s=\"%s\"\n", prefix, s, - pretty_print_option - (i, lease -> options [i].data, - lease -> options [i].len, 0)); - fprintf (scriptFile, "export %s%s\n", prefix, s); - } - } - fprintf (scriptFile, "%sexpiry=\"%d\"\n", - prefix, (int)lease -> expiry); /* XXX */ - fprintf (scriptFile, "export %sexpiry\n", prefix); -} - -int script_go (ip) - struct interface_info *ip; -{ - int rval; - - if (ip) - fprintf (scriptFile, "%s\n", - ip -> client -> config -> script_name); - else - fprintf (scriptFile, "%s\n", - top_level_config.script_name); - fprintf (scriptFile, "exit $?\n"); - fclose (scriptFile); - chmod (scriptName, 0700); - rval = system (scriptName); - /* unlink (scriptName); */ - return rval; -} - -char *dhcp_option_ev_name (option) - struct option *option; -{ - static char evbuf [256]; - int i; - - if (strlen (option -> name) + 1 > sizeof evbuf) - error ("option %s name is larger than static buffer."); - for (i = 0; option -> name [i]; i++) { - if (option -> name [i] == '-') - evbuf [i] = '_'; - else - evbuf [i] = option -> name [i]; - } - - evbuf [i] = 0; - return evbuf; -} - -void go_daemon () -{ - static int state = 0; - int pid; - - /* Don't become a daemon if the user requested otherwise. */ - if (no_daemon) - return; - - /* Only do it once. */ - if (state) - return; - state = 1; - - /* Stop logging to stderr... */ - log_perror = 0; - - /* Become a daemon... */ - if ((pid = fork ()) < 0) - error ("Can't fork daemon: %m"); - else if (pid) - exit (0); - /* Become session leader and get pid... */ - pid = setsid (); -} - diff --git a/dhclient.conf.5 b/dhclient.conf.5 deleted file mode 100644 index 25d5d8f2..00000000 --- a/dhclient.conf.5 +++ /dev/null @@ -1,63 +0,0 @@ -.\" dhclient.conf.5 -.\" -.\" 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.isc.org/isc''. To learn more about Vixie -.\" Enterprises, see ``http://www.vix.com''. -.TH dhcpd.conf 5 -.SH NAME -dhclient.conf - DHCP client configuration file -.SH DESCRIPTION -The dhclient.conf file contains configuration information for -.IR dhclient, -the Internet Software Consortium DHCP Client. -.PP -The dhclient.conf file is a free-form ASCII text file. It is parsed by -the recursive-descent parser built into dhclient. The file may contain -extra tabs and newlines for formatting purposes. Keywords in the file -are case-insensitive. Comments may be placed anywhere within the -file (except within quotes). Comments begin with the # character and -end at the end of the line. -.PP - \fBTHIS DOCUMENTATION IS NOT YET COMPLETE - SORRY\fR -.SH SEE ALSO -dhcpd.conf(5), dhclient.leases(5), -draft-ietf-dhc-options-1533update-04.txt, draft-ietf-dhc-dhcp-07.txt. -.SH AUTHOR -.B dhclient(8) -was written by Ted Lemon <mellon@vix.com> -under a contract with Vixie Labs. Funding -for this project was provided by the Internet Software Corporation. -Information about the Internet Software Consortium can be found at -.B http://www.isc.org/isc. diff --git a/dhclient.conf.cat5 b/dhclient.conf.cat5 deleted file mode 100644 index 519856c2..00000000 --- a/dhclient.conf.cat5 +++ /dev/null @@ -1,66 +0,0 @@ - - - -dhcpd.conf(5) dhcpd.conf(5) - - -NNAAMMEE - dhclient.conf - DHCP client configuration file - -DDEESSCCRRIIPPTTIIOONN - The dhclient.conf file contains configuration information - for _d_h_c_l_i_e_n_t_, the Internet Software Consortium DHCP - Client. - - The dhclient.conf file is a free-form ASCII text file. - It is parsed by the recursive-descent parser built into - dhclient. The file may contain extra tabs and newlines - for formatting purposes. Keywords in the file are case- - insensitive. Comments may be placed anywhere within the - file (except within quotes). Comments begin with the # - character and end at the end of the line. - - TTHHIISS DDOOCCUUMMEENNTTAATTIIOONN IISS NNOOTT YYEETT CCOOMMPPLLEETTEE -- SSOORRRRYY - -SSEEEE AALLSSOO - dhcpd.conf(5), dhclient.leases(5), draft-ietf-dhc- - options-1533update-04.txt, draft-ietf-dhc-dhcp-07.txt. - -AAUUTTHHOORR - ddhhcclliieenntt((88)) was written by Ted Lemon <mellon@vix.com> - under a contract with Vixie Labs. Funding for this pro- - ject was provided by the Internet Software Corporation. - Information about the Internet Software Consortium can be - found at hhttttpp::////wwwwww..iisscc..oorrgg//iisscc.. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - - |