mirror of
https://gitlab.isc.org/isc-projects/dhcp
synced 2025-08-31 06:15:55 +00:00
moved to client/
This commit is contained in:
898
clparse.c
898
clparse.c
@@ -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);
|
||||
}
|
||||
}
|
163
dhclient.8
163
dhclient.8
@@ -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
|
1617
dhclient.c
1617
dhclient.c
File diff suppressed because it is too large
Load Diff
@@ -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.
|
@@ -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
|
||||
|
||||
|
Reference in New Issue
Block a user