2
0
mirror of https://gitlab.isc.org/isc-projects/dhcp synced 2025-09-01 14:55:30 +00:00

Fix up all the option handling code to use evaluation instead of fixed data.

This commit is contained in:
Ted Lemon
1998-11-05 18:43:23 +00:00
parent a370b55d06
commit 02a015fb46
3 changed files with 1006 additions and 816 deletions

View File

@@ -42,7 +42,7 @@
#ifndef lint #ifndef lint
static char copyright[] = static char copyright[] =
"$Id: clparse.c,v 1.17 1998/10/22 04:52:23 mellon Exp $ Copyright (c) 1997 The Internet Software Consortium. All rights reserved.\n"; "$Id: clparse.c,v 1.18 1998/11/05 18:38:43 mellon Exp $ Copyright (c) 1997 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */ #endif /* not lint */
#include "dhcpd.h" #include "dhcpd.h"
@@ -52,6 +52,17 @@ static TIME parsed_time;
struct client_config top_level_config; struct client_config top_level_config;
u_int32_t default_requested_options [] = {
DHO_SUBNET_MASK,
DHO_BROADCAST_ADDRESS,
DHO_TIME_OFFSET,
DHO_ROUTERS,
DHO_DOMAIN_NAME,
DHO_DOMAIN_NAME_SERVERS,
DHO_HOST_NAME,
0
};
/* client-conf-file :== client-declarations EOF /* client-conf-file :== client-declarations EOF
client-declarations :== <nil> client-declarations :== <nil>
| client-declaration | client-declaration
@@ -84,32 +95,8 @@ int read_client_conf ()
top_level_config.initial_interval = 10; top_level_config.initial_interval = 10;
top_level_config.bootp_policy = ACCEPT; top_level_config.bootp_policy = ACCEPT;
top_level_config.script_name = "/etc/dhclient-script"; top_level_config.script_name = "/etc/dhclient-script";
top_level_config.requested_options top_level_config.requested_options = default_requested_options;
[top_level_config.requested_option_count++] = top_level_config.requested_lease = 7200;
DHO_SUBNET_MASK;
top_level_config.requested_options
[top_level_config.requested_option_count++] =
DHO_BROADCAST_ADDRESS;
top_level_config.requested_options
[top_level_config.requested_option_count++] =
DHO_TIME_OFFSET;
top_level_config.requested_options
[top_level_config.requested_option_count++] =
DHO_ROUTERS;
top_level_config.requested_options
[top_level_config.requested_option_count++] =
DHO_DOMAIN_NAME;
top_level_config.requested_options
[top_level_config.requested_option_count++] =
DHO_DOMAIN_NAME_SERVERS;
top_level_config.requested_options
[top_level_config.requested_option_count++] =
DHO_HOST_NAME;
top_level_config.requested_lease_time = 7200;
top_level_config.send_options.dhcp_options [DHO_DHCP_LEASE_TIME].data
= (unsigned char *)&top_level_config.requested_lease_time;
top_level_config.send_options.dhcp_options [DHO_DHCP_LEASE_TIME].len
= sizeof top_level_config.requested_lease_time;
if ((cfile = fopen (path_dhclient_conf, "r")) != NULL) { if ((cfile = fopen (path_dhclient_conf, "r")) != NULL) {
do { do {
@@ -144,12 +131,6 @@ int read_client_conf ()
error ("no memory for client config."); error ("no memory for client config.");
memcpy (config, &top_level_config, memcpy (config, &top_level_config,
sizeof top_level_config); sizeof top_level_config);
i = DHO_DHCP_LEASE_TIME;
config -> send_options.dhcp_options [i].data =
(unsigned char *)&config -> requested_lease_time;
top_level_config.send_options.dhcp_options [DHO_DHCP_LEASE_TIME].len
= sizeof top_level_config.requested_lease_time;
} }
ip -> client -> config = config; ip -> client -> config = config;
} }
@@ -215,19 +196,17 @@ void parse_client_statement (cfile, ip, config)
char *val; char *val;
struct option *option; struct option *option;
struct executable_statement *stmt, **p; struct executable_statement *stmt, **p;
enum statement op op; enum statement_op op;
switch (next_token (&val, cfile)) { switch (next_token (&val, cfile)) {
case SEND: case SEND:
p = &config -> on_tranmission; p = &config -> on_transmission;
op = send_option_statement; op = send_option_statement;
do_option: do_option:
token = next_token (&val, cfile); token = next_token (&val, cfile);
option = parse_option_name (cfile); option = parse_option_name (cfile);
if (!option) { if (!option)
*lose = 1; return;
return (struct executable_statement *)0;
}
stmt = parse_option_statement (cfile, 1, option, stmt = parse_option_statement (cfile, 1, option,
send_option_statement); send_option_statement);
for (; *p; p = &((*p) -> next)) for (; *p; p = &((*p) -> next))
@@ -271,14 +250,11 @@ void parse_client_statement (cfile, ip, config)
return; return;
case REQUEST: case REQUEST:
config -> requested_option_count = parse_option_list (cfile, &config -> requested_options);
parse_option_list (cfile, config -> requested_options);
return; return;
case REQUIRE: case REQUIRE:
memset (config -> required_options, 0, parse_option_list (cfile, &config -> required_options);
sizeof config -> required_options);
parse_option_list (cfile, config -> required_options);
return; return;
case TIMEOUT: case TIMEOUT:
@@ -390,13 +366,14 @@ int parse_X (cfile, buf, max)
/* option-list :== option_name | /* option-list :== option_name |
option_list COMMA option_name */ option_list COMMA option_name */
int parse_option_list (cfile, list) void parse_option_list (cfile, list)
FILE *cfile; FILE *cfile;
u_int8_t *list; u_int32_t **list;
{ {
int ix, i; int ix, i;
int token; int token;
char *val; char *val;
pair p = (pair)0, q, r;
ix = 0; ix = 0;
do { do {
@@ -404,7 +381,7 @@ int parse_option_list (cfile, list)
if (!is_identifier (token)) { if (!is_identifier (token)) {
parse_warn ("expected option name."); parse_warn ("expected option name.");
skip_to_semi (cfile); skip_to_semi (cfile);
return 0; return;
} }
for (i = 0; i < 256; i++) { for (i = 0; i < 256; i++) {
if (!strcasecmp (dhcp_options [i].name, val)) if (!strcasecmp (dhcp_options [i].name, val))
@@ -413,22 +390,42 @@ int parse_option_list (cfile, list)
if (i == 256) { if (i == 256) {
parse_warn ("%s: expected option name."); parse_warn ("%s: expected option name.");
skip_to_semi (cfile); skip_to_semi (cfile);
return 0; return;
}
list [ix++] = i;
if (ix == 256) {
parse_warn ("%s: too many options.", val);
skip_to_semi (cfile);
return 0;
} }
r = new_pair ("parse_option_list");
if (!r)
error ("can't allocate pair for option code.");
r -> car = (caddr_t)i;
r -> cdr = (pair)0;
if (p)
q -> cdr = r;
else
p = r;
q = r;
++ix;
token = next_token (&val, cfile); token = next_token (&val, cfile);
} while (token == COMMA); } while (token == COMMA);
if (token != SEMI) { if (token != SEMI) {
parse_warn ("expecting semicolon."); parse_warn ("expecting semicolon.");
skip_to_semi (cfile); skip_to_semi (cfile);
return 0; return;
}
if (*list)
dfree (*list, "parse_option_list");
*list = dmalloc (ix * sizeof **list, "parse_option_list");
if (!*list)
warn ("no memory for option list.");
else {
ix = 0;
for (q = p; q; q = q -> cdr)
(*list) [ix++] = (u_int32_t)q -> car;
(*list) [ix] = 0;
}
while (p) {
q = p -> cdr;
free_pair (p, "parse_option_list");
p = q;
} }
return ix;
} }
/* interface-declaration :== /* interface-declaration :==
@@ -589,7 +586,7 @@ void parse_client_lease_statement (cfile, is_static)
/* If the lease declaration didn't include an interface /* If the lease declaration didn't include an interface
declaration that we recognized, it's of no use to us. */ declaration that we recognized, it's of no use to us. */
if (!ip) { if (!ip) {
free_client_lease (lease); destroy_client_lease (lease);
return; return;
} }
@@ -616,7 +613,7 @@ void parse_client_lease_statement (cfile, is_static)
pl -> next = lp -> next; pl -> next = lp -> next;
else else
ip -> client -> leases = lp -> next; ip -> client -> leases = lp -> next;
free_client_lease (lp); destroy_client_lease (lp);
break; break;
} }
} }
@@ -642,13 +639,13 @@ void parse_client_lease_statement (cfile, is_static)
still valid but no longer active. */ still valid but no longer active. */
if (ip -> client -> active) { if (ip -> client -> active) {
if (ip -> client -> active -> expiry < cur_time) if (ip -> client -> active -> expiry < cur_time)
free_client_lease (ip -> client -> active); destroy_client_lease (ip -> client -> active);
else if (ip -> client -> active -> address.len == else if (ip -> client -> active -> address.len ==
lease -> address.len && lease -> address.len &&
!memcmp (ip -> client -> active -> address.iabuf, !memcmp (ip -> client -> active -> address.iabuf,
lease -> address.iabuf, lease -> address.iabuf,
lease -> address.len)) lease -> address.len))
free_client_lease (ip -> client -> active); destroy_client_lease (ip -> client -> active);
else { else {
ip -> client -> active -> next = ip -> client -> active -> next =
ip -> client -> leases; ip -> client -> leases;
@@ -680,6 +677,7 @@ void parse_client_lease_declaration (cfile, lease, ipp)
char *val; char *val;
char *t, *n; char *t, *n;
struct interface_info *ip; struct interface_info *ip;
struct option_cache *oc;
switch (next_token (&val, cfile)) { switch (next_token (&val, cfile)) {
case BOOTP: case BOOTP:
@@ -727,7 +725,14 @@ void parse_client_lease_declaration (cfile, lease, ipp)
return; return;
case OPTION: case OPTION:
parse_option_decl (cfile, lease -> options); oc = (struct option_cache *)0;
if (parse_option_decl (&oc, cfile)) {
/* XXX save_option here ought to account for the
XXX correct option universe, but it doesn't. */
save_option (lease -> options.dhcp_hash, oc);
option_cache_dereference
(&oc, "parse_client_lease_declaration");
}
return; return;
default: default:
@@ -742,9 +747,9 @@ void parse_client_lease_declaration (cfile, lease, ipp)
} }
} }
struct option *parse_option_decl (cfile, options) int parse_option_decl (oc, cfile)
struct option_cache **oc;
FILE *cfile; FILE *cfile;
struct option_data *options;
{ {
char *val; char *val;
int token; int token;
@@ -757,10 +762,11 @@ struct option *parse_option_decl (cfile, options)
u_int8_t *dp; u_int8_t *dp;
int len; int len;
int nul_term = 0; int nul_term = 0;
struct buffer *bp;
option = parse_option_name (cfile); option = parse_option_name (cfile);
if (!option) if (!option)
return; return 0;
/* Parse the option data... */ /* Parse the option data... */
do { do {
@@ -784,14 +790,14 @@ struct option *parse_option_decl (cfile, options)
if (token != STRING) { if (token != STRING) {
parse_warn ("expecting string."); parse_warn ("expecting string.");
skip_to_semi (cfile); skip_to_semi (cfile);
return (struct option *)0; return 0;
} }
len = strlen (val); len = strlen (val);
if (hunkix + len + 1 > sizeof hunkbuf) { if (hunkix + len + 1 > sizeof hunkbuf) {
parse_warn ("option data buffer %s", parse_warn ("option data buffer %s",
"overflow"); "overflow");
skip_to_semi (cfile); skip_to_semi (cfile);
return (struct option *)0; return 0;
} }
memcpy (&hunkbuf [hunkix], val, len + 1); memcpy (&hunkbuf [hunkix], val, len + 1);
nul_term = 1; nul_term = 1;
@@ -800,7 +806,7 @@ struct option *parse_option_decl (cfile, options)
case 'I': /* IP address. */ case 'I': /* IP address. */
if (!parse_ip_addr (cfile, &ip_addr)) if (!parse_ip_addr (cfile, &ip_addr))
return (struct option *)0; return 0;
len = ip_addr.len; len = ip_addr.len;
dp = ip_addr.iabuf; dp = ip_addr.iabuf;
@@ -809,7 +815,7 @@ struct option *parse_option_decl (cfile, options)
parse_warn ("option data buffer %s", parse_warn ("option data buffer %s",
"overflow"); "overflow");
skip_to_semi (cfile); skip_to_semi (cfile);
return (struct option *)0; return 0;
} }
memcpy (&hunkbuf [hunkix], dp, len); memcpy (&hunkbuf [hunkix], dp, len);
hunkix += len; hunkix += len;
@@ -823,7 +829,7 @@ struct option *parse_option_decl (cfile, options)
parse_warn ("expecting number."); parse_warn ("expecting number.");
if (token != SEMI) if (token != SEMI)
skip_to_semi (cfile); skip_to_semi (cfile);
return (struct option *)0; return 0;
} }
convert_num (buf, val, 0, 32); convert_num (buf, val, 0, 32);
len = 4; len = 4;
@@ -857,7 +863,7 @@ struct option *parse_option_decl (cfile, options)
bad_flag: bad_flag:
if (token != SEMI) if (token != SEMI)
skip_to_semi (cfile); skip_to_semi (cfile);
return (struct option *)0; return 0;
} }
if (!strcasecmp (val, "true") if (!strcasecmp (val, "true")
|| !strcasecmp (val, "on")) || !strcasecmp (val, "on"))
@@ -877,7 +883,7 @@ struct option *parse_option_decl (cfile, options)
warn ("Bad format %c in parse_option_param.", warn ("Bad format %c in parse_option_param.",
*fmt); *fmt);
skip_to_semi (cfile); skip_to_semi (cfile);
return (struct option *)0; return 0;
} }
} }
token = next_token (&val, cfile); token = next_token (&val, cfile);
@@ -886,16 +892,25 @@ struct option *parse_option_decl (cfile, options)
if (token != SEMI) { if (token != SEMI) {
parse_warn ("semicolon expected."); parse_warn ("semicolon expected.");
skip_to_semi (cfile); skip_to_semi (cfile);
return (struct option *)0; return 0;
} }
options [option -> code].data = bp = (struct buffer *)0;
(unsigned char *)malloc (hunkix + nul_term); if (!buffer_allocate (&bp, hunkix + nul_term, "parse_option_decl"))
if (!options [option -> code].data) error ("no memory to store option declaration.");
if (!bp -> data)
error ("out of memory allocating option data."); error ("out of memory allocating option data.");
memcpy (options [option -> code].data, hunkbuf, hunkix + nul_term); memcpy (bp -> data, hunkbuf, hunkix + nul_term);
options [option -> code].len = hunkix;
return option; if (!option_cache_allocate (oc, "parse_option_decl"))
error ("out of memory allocating option cache.");
(*oc) -> data.buffer = bp;
(*oc) -> data.data = &bp -> data [0];
(*oc) -> data.terminated = nul_term;
(*oc) -> data.len = hunkix;
(*oc) -> option = option;
return 1;
} }
void parse_string_list (cfile, lp, multiple) void parse_string_list (cfile, lp, multiple)

View File

@@ -56,7 +56,7 @@
#ifndef lint #ifndef lint
static char copyright[] = static char copyright[] =
"$Id: dhclient.c,v 1.49 1998/04/09 04:26:24 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; "$Id: dhclient.c,v 1.50 1998/11/05 18:39:04 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */ #endif /* not lint */
#include "dhcpd.h" #include "dhcpd.h"
@@ -259,6 +259,25 @@ void cleanup ()
{ {
} }
struct class *find_class (s)
char *s;
{
return (struct class *)0;
}
int check_collection (packet, collection)
struct packet *packet;
struct collection *collection;
{
return 0;
}
void classify (packet, class)
struct packet *packet;
struct class *class;
{
}
/* Individual States: /* Individual States:
* *
* Each routine is called from the dhclient_state_machine() in one of * Each routine is called from the dhclient_state_machine() in one of
@@ -389,7 +408,7 @@ void state_selecting (ipp)
picked -> next = (struct client_lease *)0; picked -> next = (struct client_lease *)0;
} else { } else {
freeit: freeit:
free_client_lease (lp); destroy_client_lease (lp);
} }
} }
ip -> client -> offered_leases = (struct client_lease *)0; ip -> client -> offered_leases = (struct client_lease *)0;
@@ -403,7 +422,7 @@ void state_selecting (ipp)
} }
/* If it was a BOOTREPLY, we can just take the address right now. */ /* If it was a BOOTREPLY, we can just take the address right now. */
if (!picked -> options [DHO_DHCP_MESSAGE_TYPE].len) { if (!picked -> is_bootp) {
ip -> client -> new = picked; ip -> client -> new = picked;
/* Make up some lease expiry times /* Make up some lease expiry times
@@ -430,7 +449,7 @@ void state_selecting (ipp)
ip -> client -> xid = ip -> client -> packet.xid; ip -> client -> xid = ip -> client -> packet.xid;
/* Toss the lease we picked - we'll get it back in a DHCPACK. */ /* Toss the lease we picked - we'll get it back in a DHCPACK. */
free_client_lease (picked); destroy_client_lease (picked);
/* Add an immediate timeout to send the first DHCPREQUEST packet. */ /* Add an immediate timeout to send the first DHCPREQUEST packet. */
send_request (ip); send_request (ip);
@@ -444,6 +463,8 @@ void dhcpack (packet)
{ {
struct interface_info *ip = packet -> interface; struct interface_info *ip = packet -> interface;
struct client_lease *lease; struct client_lease *lease;
struct option_cache *oc;
struct data_string ds;
int i; int i;
/* If we're not receptive to an offer right now, or if the offer /* If we're not receptive to an offer right now, or if the offer
@@ -479,26 +500,63 @@ void dhcpack (packet)
cancel_timeout (send_request, ip); cancel_timeout (send_request, ip);
/* Figure out the lease time. */ /* Figure out the lease time. */
ip -> client -> new -> expiry = oc = lookup_option (ip -> client -> new -> options.dhcp_hash,
getULong (ip -> client -> DHO_DHCP_LEASE_TIME);
new -> options [DHO_DHCP_LEASE_TIME].data); memset (&ds, 0, sizeof ds);
if (oc &&
evaluate_option_cache (&ds, packet,
&ip -> client -> new -> options, oc)) {
if (ds.len > 3)
ip -> client -> new -> expiry = getULong (ds.data);
else
ip -> client -> new -> expiry = 0;
data_string_forget (&ds, "dhcpack");
} else
ip -> client -> new -> expiry = 0;
/* Take the server-provided renewal time if there is one; if (!ip -> client -> new -> expiry) {
otherwise figure it out according to the spec. */ warn ("no expiry time on offered lease.");
if (ip -> client -> new -> options [DHO_DHCP_RENEWAL_TIME].len) /* XXX this is going to be bad - if this _does_
ip -> client -> new -> renewal = XXX happen, we should probably dynamically
getULong (ip -> client -> XXX disqualify the DHCP server that gave us the
new -> options [DHO_DHCP_RENEWAL_TIME].data); XXX bad packet from future selections and
else XXX then go back into the init state. */
state_init (ip);
return;
}
/* Take the server-provided renewal time if there is one. */
oc = lookup_option (ip -> client -> new -> options.dhcp_hash,
DHO_DHCP_RENEWAL_TIME);
if (oc &&
evaluate_option_cache (&ds, packet,
&ip -> client -> new -> options, oc)) {
if (ds.len > 3)
ip -> client -> new -> renewal = getULong (ds.data);
else
ip -> client -> new -> renewal = 0;
} else
ip -> client -> new -> renewal = 0;
/* If it wasn't specified by the server, calculate it. */
if (!ip -> client -> new -> renewal)
ip -> client -> new -> renewal = ip -> client -> new -> renewal =
ip -> client -> new -> expiry / 2; ip -> client -> new -> expiry / 2;
/* Same deal with the rebind time. */ /* Same deal with the rebind time. */
if (ip -> client -> new -> options [DHO_DHCP_REBINDING_TIME].len) oc = lookup_option (ip -> client -> new -> options.dhcp_hash,
ip -> client -> new -> rebind = DHO_DHCP_REBINDING_TIME);
getULong (ip -> client -> new -> if (oc &&
options [DHO_DHCP_REBINDING_TIME].data); evaluate_option_cache (&ds, packet,
else &ip -> client -> new -> options, oc)) {
if (ds.len > 3)
ip -> client -> new -> rebind = getULong (ds.data);
else
ip -> client -> new -> rebind = 0;
} else
ip -> client -> new -> rebind = 0;
if (!ip -> client -> new -> rebind)
ip -> client -> new -> rebind = ip -> client -> new -> rebind =
ip -> client -> new -> renewal + ip -> client -> new -> renewal +
ip -> client -> new -> renewal / 2 + ip -> client -> new -> renewal / 2 +
@@ -537,7 +595,7 @@ void bind_lease (ip)
/* Replace the old active lease with the new one. */ /* Replace the old active lease with the new one. */
if (ip -> client -> active) if (ip -> client -> active)
free_client_lease (ip -> client -> active); destroy_client_lease (ip -> client -> active);
ip -> client -> active = ip -> client -> new; ip -> client -> active = ip -> client -> new;
ip -> client -> new = (struct client_lease *)0; ip -> client -> new = (struct client_lease *)0;
@@ -562,6 +620,9 @@ void state_bound (ipp)
void *ipp; void *ipp;
{ {
struct interface_info *ip = ipp; struct interface_info *ip = ipp;
int i;
struct option_cache *oc;
struct data_string ds;
ASSERT_STATE(state, S_BOUND); ASSERT_STATE(state, S_BOUND);
@@ -569,12 +630,17 @@ void state_bound (ipp)
make_request (ip, ip -> client -> active); make_request (ip, ip -> client -> active);
ip -> client -> xid = ip -> client -> packet.xid; ip -> client -> xid = ip -> client -> packet.xid;
if (ip -> client -> active -> memset (&ds, 0, sizeof ds);
options [DHO_DHCP_SERVER_IDENTIFIER].len == 4) { oc = lookup_option (ip -> client -> active -> options.dhcp_hash,
memcpy (ip -> client -> destination.iabuf, DHO_DHCP_SERVER_IDENTIFIER);
ip -> client -> active -> if (oc &&
options [DHO_DHCP_SERVER_IDENTIFIER].data, 4); evaluate_option_cache (&ds, (struct packet *)0,
ip -> client -> destination.len = 4; &ip -> client -> active -> options, oc)) {
if (ds.len > 3) {
memcpy (ip -> client -> destination.iabuf, ds.data, 4);
ip -> client -> destination.len = 4;
} else
ip -> client -> destination = iaddr_broadcast;
} else } else
ip -> client -> destination = iaddr_broadcast; ip -> client -> destination = iaddr_broadcast;
@@ -671,9 +737,9 @@ void dhcpoffer (packet)
struct client_lease *lease, *lp; struct client_lease *lease, *lp;
int i; int i;
int arp_timeout_needed, stop_selecting; int arp_timeout_needed, stop_selecting;
char *name = (packet -> options [DHO_DHCP_MESSAGE_TYPE].len char *name = packet -> packet_type ? "DHCPOFFER" : "BOOTREPLY";
? "DHCPOFFER" : "BOOTREPLY");
struct iaddrlist *ap; struct iaddrlist *ap;
struct option_cache *oc;
#ifdef DEBUG_PACKET #ifdef DEBUG_PACKET
dump_packet (packet); dump_packet (packet);
@@ -696,11 +762,15 @@ void dhcpoffer (packet)
/* If this lease doesn't supply the minimum required parameters, /* If this lease doesn't supply the minimum required parameters,
blow it off. */ blow it off. */
for (i = 0; ip -> client -> config -> required_options [i]; i++) { if (ip -> client -> config -> required_options) {
if (!packet -> options [ip -> client -> config -> for (i = 0;
required_options [i]].len) { ip -> client -> config -> required_options [i]; i++) {
note ("%s isn't satisfactory.", name); if (!lookup_option
return; (packet -> options.dhcp_hash,
ip -> client -> config -> required_options [i])) {
note ("%s isn't satisfactory.", name);
return;
}
} }
} }
@@ -723,7 +793,7 @@ void dhcpoffer (packet)
/* If this lease was acquired through a BOOTREPLY, record that /* If this lease was acquired through a BOOTREPLY, record that
fact. */ fact. */
if (!packet -> options [DHO_DHCP_MESSAGE_TYPE].len) if (!packet -> options_valid || !packet -> packet_type)
lease -> is_bootp = 1; lease -> is_bootp = 1;
/* Record the medium under which this lease was offered. */ /* Record the medium under which this lease was offered. */
@@ -797,8 +867,10 @@ struct client_lease *packet_to_lease (packet)
{ {
struct client_lease *lease; struct client_lease *lease;
int i; int i;
struct option_cache *oc;
struct data_string data;
lease = (struct client_lease *)malloc (sizeof (struct client_lease)); lease = (struct client_lease *)new_client_lease ("packet_to_lease");
if (!lease) { if (!lease) {
warn ("dhcpoffer: no memory to record lease.\n"); warn ("dhcpoffer: no memory to record lease.\n");
@@ -808,45 +880,38 @@ struct client_lease *packet_to_lease (packet)
memset (lease, 0, sizeof *lease); memset (lease, 0, sizeof *lease);
/* Copy the lease options. */ /* Copy the lease options. */
for (i = 0; i < 256; i++) { lease -> options = packet -> options;
if (packet -> options [i].len) { memset (&packet -> options, 0, sizeof packet -> options);
lease -> options [i].data =
(unsigned char *)
malloc (packet -> options [i].len + 1);
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 -> options [i].data
[lease -> options [i].len] = 0;
}
}
}
lease -> address.len = sizeof (packet -> raw -> yiaddr); lease -> address.len = sizeof (packet -> raw -> yiaddr);
memcpy (lease -> address.iabuf, &packet -> raw -> yiaddr, memcpy (lease -> address.iabuf, &packet -> raw -> yiaddr,
lease -> address.len); lease -> address.len);
/* Figure out the overload flag. */
oc = lookup_option (lease -> options.dhcp_hash,
DHO_DHCP_OPTION_OVERLOAD);
memset (&data, 0, sizeof data);
if (oc &&
evaluate_option_cache (&data, packet, &lease -> options, oc)) {
if (data.len > 0)
i = data.data [0];
else
i = 0;
data_string_forget (&data, "packet_to_lease");
} else
i = 0;
/* If the server name was filled out, copy it. */ /* If the server name was filled out, copy it. */
if ((!packet -> options [DHO_DHCP_OPTION_OVERLOAD].len || if (!(i & 2) && packet -> raw -> sname [0]) {
!(packet -> options [DHO_DHCP_OPTION_OVERLOAD].data [0] & 2)) &&
packet -> raw -> sname [0]) {
int len; int len;
/* Don't count on the NUL terminator. */ /* Don't count on the NUL terminator. */
for (len = 0; len < 64; len++) for (len = 0; len < 64; len++)
if (!packet -> raw -> sname [len]) if (!packet -> raw -> sname [len])
break; break;
lease -> server_name = malloc (len + 1); lease -> server_name = dmalloc (len + 1, "packet_to_lease");
if (!lease -> server_name) { if (!lease -> server_name) {
warn ("dhcpoffer: no memory for filename.\n"); warn ("dhcpoffer: no memory for filename.\n");
free_client_lease (lease); destroy_client_lease (lease);
return (struct client_lease *)0; return (struct client_lease *)0;
} else { } else {
memcpy (lease -> server_name, memcpy (lease -> server_name,
@@ -856,18 +921,16 @@ struct client_lease *packet_to_lease (packet)
} }
/* Ditto for the filename. */ /* Ditto for the filename. */
if ((!packet -> options [DHO_DHCP_OPTION_OVERLOAD].len || if ((i & 1) && packet -> raw -> file [0]) {
!(packet -> options [DHO_DHCP_OPTION_OVERLOAD].data [0] & 1)) &&
packet -> raw -> file [0]) {
int len; int len;
/* Don't count on the NUL terminator. */ /* Don't count on the NUL terminator. */
for (len = 0; len < 64; len++) for (len = 0; len < 64; len++)
if (!packet -> raw -> file [len]) if (!packet -> raw -> file [len])
break; break;
lease -> filename = malloc (len + 1); lease -> filename = dmalloc (len + 1, "packet_to_lease");
if (!lease -> filename) { if (!lease -> filename) {
warn ("dhcpoffer: no memory for filename.\n"); warn ("dhcpoffer: no memory for filename.\n");
free_client_lease (lease); destroy_client_lease (lease);
return (struct client_lease *)0; return (struct client_lease *)0;
} else { } else {
memcpy (lease -> filename, memcpy (lease -> filename,
@@ -909,7 +972,7 @@ void dhcpnak (packet)
return; return;
} }
free_client_lease (ip -> client -> active); destroy_client_lease (ip -> client -> active);
ip -> client -> active = (struct client_lease *)0; ip -> client -> active = (struct client_lease *)0;
/* Stop sending DHCPREQUEST packets... */ /* Stop sending DHCPREQUEST packets... */
@@ -1317,6 +1380,103 @@ void send_release (ipp)
warn ("send_packet: %m"); warn ("send_packet: %m");
} }
void make_client_options (ip, lease, type, sid, rip, prl, statements,
options)
struct interface_info *ip;
struct client_lease *lease;
u_int8_t *type;
struct option_cache *sid;
struct iaddr *rip;
u_int32_t *prl;
struct executable_statement *statements;
struct option_state *options;
{
int i;
struct option_cache *oc;
struct buffer *bp = (struct buffer *)0;
memset (options, 0, sizeof *options);
/* Send the server identifier if provided. */
if (sid)
save_option (options -> dhcp_hash, sid);
/* Send the requested address if provided. */
if (rip) {
ip -> client -> requested_address = *rip;
if (!(make_const_option_cache
(&oc, (struct buffer **)0,
rip -> iabuf, rip -> len,
&dhcp_options [DHO_DHCP_REQUESTED_ADDRESS],
"make_client_options")))
warn ("can't make requested address option cache.");
else {
save_option (options -> dhcp_hash, oc);
option_cache_dereference (&oc, "make_client_options");
}
} else {
ip -> client -> requested_address.len = 0;
}
if (!(make_const_option_cache
(&oc, (struct buffer **)0,
type, 1, &dhcp_options [DHO_DHCP_MESSAGE_TYPE],
"make_client_options")))
warn ("can't make message type.");
else {
save_option (options -> dhcp_hash, oc);
option_cache_dereference (&oc, "make_client_options");
}
if (prl) {
/* Figure out how many parameters were requested. */
for (i = 0; prl [i]; i++)
;
if (!buffer_allocate (&bp, i, "make_client_options"))
warn ("can't make buffer for parameter request list.");
else {
for (i = 0; prl [i]; i++)
bp -> data [i] = prl [i];
if (!(make_const_option_cache
(&oc, &bp, (u_int8_t *)0, i,
&dhcp_options [DHO_DHCP_PARAMETER_REQUEST_LIST],
"make_client_options")))
warn ("can't make option cache");
else {
save_option (options -> dhcp_hash, oc);
option_cache_dereference
(&oc, "make_client_options");
}
}
}
if (!(oc = lookup_option (options -> dhcp_hash,
DHO_DHCP_LEASE_TIME))) {
if (!buffer_allocate (&bp, sizeof (u_int32_t),
"make_client_options"))
warn ("can't make buffer for requested lease time.");
else {
putULong (bp -> data,
ip -> client -> config -> requested_lease);
if (!(make_const_option_cache
(&oc, &bp, (u_int8_t *)0, sizeof (u_int32_t),
&dhcp_options [DHO_DHCP_LEASE_TIME],
"make_client_options")))
warn ("can't make option cache");
else {
save_option (options -> dhcp_hash, oc);
option_cache_dereference
(&oc, "make_client_options");
}
}
}
/* Run statements that need to be run on transmission. */
if (statements)
execute_statements ((struct packet *)0,
&lease -> options, options, statements);
}
void make_discover (ip, lease) void make_discover (ip, lease)
struct interface_info *ip; struct interface_info *ip;
struct client_lease *lease; struct client_lease *lease;
@@ -1324,67 +1484,20 @@ void make_discover (ip, lease)
struct dhcp_packet *raw; struct dhcp_packet *raw;
unsigned char discover = DHCPDISCOVER; unsigned char discover = DHCPDISCOVER;
int i; int i;
struct option_state options;
struct tree_cache *options [256];
struct tree_cache option_elements [256];
memset (option_elements, 0, sizeof option_elements);
memset (options, 0, sizeof options);
memset (&ip -> client -> packet, 0, sizeof (ip -> client -> packet)); memset (&ip -> client -> packet, 0, sizeof (ip -> client -> packet));
/* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */ make_client_options (ip, lease, &discover, (struct option_cache *)0,
i = DHO_DHCP_MESSAGE_TYPE; lease ? &lease -> address : (struct iaddr *)0,
options [i] = &option_elements [i]; ip -> client -> config -> requested_options,
options [i] -> value = &discover; ip -> client -> config -> on_transmission,
options [i] -> len = sizeof discover; &options);
options [i] -> buf_size = sizeof discover;
options [i] -> timeout = 0xFFFFFFFF;
options [i] -> tree = (struct tree *)0;
/* Request the options we want */
i = DHO_DHCP_PARAMETER_REQUEST_LIST;
options [i] = &option_elements [i];
options [i] -> value = ip -> client -> config -> requested_options;
options [i] -> len = ip -> client -> config -> requested_option_count;
options [i] -> buf_size =
ip -> client -> config -> requested_option_count;
options [i] -> timeout = 0xFFFFFFFF;
options [i] -> tree = (struct tree *)0;
/* If we had an address, try to get it again. */
if (lease) {
ip -> client -> requested_address = lease -> address;
i = DHO_DHCP_REQUESTED_ADDRESS;
options [i] = &option_elements [i];
options [i] -> value = lease -> address.iabuf;
options [i] -> len = lease -> address.len;
options [i] -> buf_size = lease -> address.len;
options [i] -> timeout = 0xFFFFFFFF;
options [i] -> tree = (struct tree *)0;
} else {
ip -> client -> requested_address.len = 0;
}
/* Send any options requested in the config file. */
for (i = 0; i < 256; i++) {
if (!options [i] &&
ip -> client -> config -> send_options [i].data) {
options [i] = &option_elements [i];
options [i] -> value = ip -> client -> config ->
send_options [i].data;
options [i] -> len = ip -> client -> config ->
send_options [i].len;
options [i] -> buf_size = ip -> client -> config ->
send_options [i].len;
options [i] -> timeout = 0xFFFFFFFF;
options [i] -> tree = (struct tree *)0;
}
}
/* Set up the option buffer... */ /* Set up the option buffer... */
ip -> client -> packet_length = ip -> client -> packet_length =
cons_options ((struct packet *)0, &ip -> client -> packet, 0, cons_options ((struct packet *)0, &ip -> client -> packet, 0,
options, (struct agent_options *)0, 0, 0, 0); &options, 0, 0, 0);
if (ip -> client -> packet_length < BOOTP_MIN_LEN) if (ip -> client -> packet_length < BOOTP_MIN_LEN)
ip -> client -> packet_length = BOOTP_MIN_LEN; ip -> client -> packet_length = BOOTP_MIN_LEN;
@@ -1420,78 +1533,30 @@ void make_request (ip, lease)
{ {
unsigned char request = DHCPREQUEST; unsigned char request = DHCPREQUEST;
int i; int i;
struct option_state options;
struct option_cache *oc;
struct tree_cache *options [256];
struct tree_cache option_elements [256];
memset (options, 0, sizeof options);
memset (&ip -> client -> packet, 0, sizeof (ip -> client -> packet)); memset (&ip -> client -> packet, 0, sizeof (ip -> client -> packet));
/* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */ if (ip -> client -> state == S_REQUESTING)
i = DHO_DHCP_MESSAGE_TYPE; oc = lookup_option (lease -> options.dhcp_hash,
options [i] = &option_elements [i]; DHO_DHCP_SERVER_IDENTIFIER);
options [i] -> value = &request; else
options [i] -> len = sizeof request; oc = (struct option_cache *)0;
options [i] -> buf_size = sizeof request;
options [i] -> timeout = 0xFFFFFFFF;
options [i] -> tree = (struct tree *)0;
/* Request the options we want */ make_client_options (ip, lease, &request, oc,
i = DHO_DHCP_PARAMETER_REQUEST_LIST; ((ip -> client -> state == S_REQUESTING ||
options [i] = &option_elements [i]; ip -> client -> state == S_REBOOTING)
options [i] -> value = ip -> client -> config -> requested_options; ? &lease -> address
options [i] -> len = ip -> client -> config -> requested_option_count; : (struct iaddr *)0),
options [i] -> buf_size = ip -> client -> config -> requested_options,
ip -> client -> config -> requested_option_count; ip -> client -> config -> on_transmission,
options [i] -> timeout = 0xFFFFFFFF; &options);
options [i] -> 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) {
/* Send back the server identifier... */
i = DHO_DHCP_SERVER_IDENTIFIER;
options [i] = &option_elements [i];
options [i] -> value = lease -> options [i].data;
options [i] -> len = lease -> options [i].len;
options [i] -> buf_size = lease -> options [i].len;
options [i] -> timeout = 0xFFFFFFFF;
options [i] -> tree = (struct tree *)0;
}
if (ip -> client -> state == S_REQUESTING ||
ip -> client -> state == S_REBOOTING) {
ip -> client -> requested_address = lease -> address;
i = DHO_DHCP_REQUESTED_ADDRESS;
options [i] = &option_elements [i];
options [i] -> value = lease -> address.iabuf;
options [i] -> len = lease -> address.len;
options [i] -> buf_size = lease -> address.len;
options [i] -> timeout = 0xFFFFFFFF;
options [i] -> tree = (struct tree *)0;
} else {
ip -> client -> requested_address.len = 0;
}
/* Send any options requested in the config file. */
for (i = 0; i < 256; i++) {
if (!options [i] &&
ip -> client -> config -> send_options [i].data) {
options [i] = &option_elements [i];
options [i] -> value = ip -> client -> config ->
send_options [i].data;
options [i] -> len = ip -> client -> config ->
send_options [i].len;
options [i] -> buf_size = ip -> client -> config ->
send_options [i].len;
options [i] -> timeout = 0xFFFFFFFF;
options [i] -> tree = (struct tree *)0;
}
}
/* Set up the option buffer... */ /* Set up the option buffer... */
ip -> client -> packet_length = ip -> client -> packet_length =
cons_options ((struct packet *)0, &ip -> client -> packet, 0, cons_options ((struct packet *)0, &ip -> client -> packet, 0,
options, (struct agent_options *)0, 0, 0, 0); &options, 0, 0, 0);
if (ip -> client -> packet_length < BOOTP_MIN_LEN) if (ip -> client -> packet_length < BOOTP_MIN_LEN)
ip -> client -> packet_length = BOOTP_MIN_LEN; ip -> client -> packet_length = BOOTP_MIN_LEN;
@@ -1535,62 +1600,22 @@ void make_decline (ip, lease)
{ {
unsigned char decline = DHCPDECLINE; unsigned char decline = DHCPDECLINE;
int i; int i;
struct option_cache *oc;
struct tree_cache *options [256]; struct option_state options;
struct tree_cache message_type_tree;
struct tree_cache requested_address_tree;
struct tree_cache server_id_tree;
struct tree_cache client_id_tree;
memset (options, 0, sizeof options);
memset (&ip -> client -> packet, 0, sizeof (ip -> client -> packet)); memset (&ip -> client -> packet, 0, sizeof (ip -> client -> packet));
/* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */ oc = lookup_option (lease -> options.dhcp_hash,
i = DHO_DHCP_MESSAGE_TYPE; DHO_DHCP_SERVER_IDENTIFIER);
options [i] = &message_type_tree; make_client_options (ip, lease, &decline, oc,
options [i] -> value = &decline; &lease -> address, (u_int32_t *)0,
options [i] -> len = sizeof decline; (struct executable_statement *)0, &options);
options [i] -> buf_size = sizeof decline;
options [i] -> timeout = 0xFFFFFFFF;
options [i] -> tree = (struct tree *)0;
/* Send back the server identifier... */
i = DHO_DHCP_SERVER_IDENTIFIER;
options [i] = &server_id_tree;
options [i] -> value = lease -> options [i].data;
options [i] -> len = lease -> options [i].len;
options [i] -> buf_size = lease -> options [i].len;
options [i] -> timeout = 0xFFFFFFFF;
options [i] -> tree = (struct tree *)0;
/* Send back the address we're declining. */
i = DHO_DHCP_REQUESTED_ADDRESS;
options [i] = &requested_address_tree;
options [i] -> value = lease -> address.iabuf;
options [i] -> len = lease -> address.len;
options [i] -> buf_size = lease -> address.len;
options [i] -> timeout = 0xFFFFFFFF;
options [i] -> tree = (struct tree *)0;
/* Send the uid if the user supplied one. */
i = DHO_DHCP_CLIENT_IDENTIFIER;
if (ip -> client -> config -> send_options [i].len) {
options [i] = &client_id_tree;
options [i] -> value = ip -> client -> config ->
send_options [i].data;
options [i] -> len = ip -> client -> config ->
send_options [i].len;
options [i] -> buf_size = ip -> client -> config ->
send_options [i].len;
options [i] -> timeout = 0xFFFFFFFF;
options [i] -> tree = (struct tree *)0;
}
/* Set up the option buffer... */ /* Set up the option buffer... */
ip -> client -> packet_length = ip -> client -> packet_length =
cons_options ((struct packet *)0, &ip -> client -> packet, 0, cons_options ((struct packet *)0, &ip -> client -> packet, 0,
options, (struct agent_options *)0, 0, 0, 0); &options, 0, 0, 0);
if (ip -> client -> packet_length < BOOTP_MIN_LEN) if (ip -> client -> packet_length < BOOTP_MIN_LEN)
ip -> client -> packet_length = BOOTP_MIN_LEN; ip -> client -> packet_length = BOOTP_MIN_LEN;
@@ -1626,37 +1651,22 @@ void make_release (ip, lease)
{ {
unsigned char request = DHCPRELEASE; unsigned char request = DHCPRELEASE;
int i; int i;
struct option_cache *oc;
struct tree_cache *options [256]; struct option_state options;
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)); memset (&ip -> client -> packet, 0, sizeof (ip -> client -> packet));
/* Set DHCP_MESSAGE_TYPE to DHCPRELEASE */ oc = lookup_option (lease -> options.dhcp_hash,
i = DHO_DHCP_MESSAGE_TYPE; DHO_DHCP_SERVER_IDENTIFIER);
options [i] = &message_type_tree; make_client_options (ip, lease, &request, oc,
options [i] -> value = &request; &lease -> address, (u_int32_t *)0,
options [i] -> len = sizeof request; (struct executable_statement *)0, &options);
options [i] -> buf_size = sizeof request;
options [i] -> timeout = 0xFFFFFFFF;
options [i] -> tree = (struct tree *)0;
/* Send back the server identifier... */
i = DHO_DHCP_SERVER_IDENTIFIER;
options [i] = &server_id_tree;
options [i] -> value = lease -> options [i].data;
options [i] -> len = lease -> options [i].len;
options [i] -> buf_size = lease -> options [i].len;
options [i] -> timeout = 0xFFFFFFFF;
options [i] -> tree = (struct tree *)0;
/* Set up the option buffer... */ /* Set up the option buffer... */
ip -> client -> packet_length = ip -> client -> packet_length =
cons_options ((struct packet *)0, &ip -> client -> packet, 0, cons_options ((struct packet *)0, &ip -> client -> packet, 0,
options, (struct agent_options *)0, 0, 0, 0); &options, 0, 0, 0);
if (ip -> client -> packet_length < BOOTP_MIN_LEN) if (ip -> client -> packet_length < BOOTP_MIN_LEN)
ip -> client -> packet_length = BOOTP_MIN_LEN; ip -> client -> packet_length = BOOTP_MIN_LEN;
@@ -1685,20 +1695,17 @@ void make_release (ip, lease)
#endif #endif
} }
void free_client_lease (lease) void destroy_client_lease (lease)
struct client_lease *lease; struct client_lease *lease;
{ {
int i; int i;
if (lease -> server_name) if (lease -> server_name)
free (lease -> server_name); dfree (lease -> server_name, "destroy_client_lease");
if (lease -> filename) if (lease -> filename)
free (lease -> filename); dfree (lease -> filename, "destroy_client_lease");
for (i = 0; i < 256; i++) { option_state_dereference (&lease -> options);
if (lease -> options [i].len) free_client_lease (lease, "destroy_client_lease");
free (lease -> options [i].data);
}
free (lease);
} }
FILE *leaseFile; FILE *leaseFile;
@@ -1744,6 +1751,8 @@ void write_client_lease (ip, lease, rewrite)
int i; int i;
struct tm *t; struct tm *t;
static int leases_written; static int leases_written;
struct option_cache *oc;
struct data_string ds;
if (!rewrite) { if (!rewrite) {
if (leases_written++ > 20) { if (leases_written++ > 20) {
@@ -1778,14 +1787,21 @@ void write_client_lease (ip, lease, rewrite)
if (lease -> medium) if (lease -> medium)
fprintf (leaseFile, " medium \"%s\";\n", fprintf (leaseFile, " medium \"%s\";\n",
lease -> medium -> string); lease -> medium -> string);
for (i = 0; i < 256; i++) { for (i = 0; i < OPTION_HASH_SIZE; i++) {
if (lease -> options [i].len) { pair p;
fprintf (leaseFile, for (p = lease -> options.dhcp_hash [i]; p; p = p -> cdr) {
" option %s %s;\n", memset (&ds, 0, sizeof ds);
dhcp_options [i].name, if (evaluate_option_cache (&ds, (struct packet *)0,
pretty_print_option &lease -> options, oc)) {
(i, lease -> options [i].data, fprintf (leaseFile,
lease -> options [i].len, 1, 1)); " option %s %s;\n",
dhcp_options [i].name,
pretty_print_option
(i, ds.data, ds.len,
1, 1));
data_string_forget (&ds,
"write_client_lease");
}
} }
} }
@@ -1863,8 +1879,8 @@ void script_write_params (ip, prefix, lease)
struct client_lease *lease; struct client_lease *lease;
{ {
int i; int i;
u_int8_t dbuf [1500]; struct data_string data;
int len; struct option_cache *oc;
fprintf (scriptFile, "%sip_address=\"%s\"\n", fprintf (scriptFile, "%sip_address=\"%s\"\n",
prefix, piaddr (lease -> address)); prefix, piaddr (lease -> address));
@@ -1877,33 +1893,45 @@ void script_write_params (ip, prefix, lease)
broadcast address, not the host address all zeroes broadcast address, not the host address all zeroes
broadcast address). */ broadcast address). */
if (lease -> options [DHO_SUBNET_MASK].len && memset (&data, 0, sizeof data);
(lease -> options [DHO_SUBNET_MASK].len < oc = lookup_option (lease -> options.dhcp_hash, DHO_SUBNET_MASK);
sizeof lease -> address.iabuf)) { if (oc && evaluate_option_cache (&data, (struct packet *)0,
struct iaddr netmask, subnet, broadcast; &lease -> options, oc)) {
if (data.len > 3) {
struct iaddr netmask, subnet, broadcast;
memcpy (netmask.iabuf, memcpy (netmask.iabuf, data.data, data.len);
lease -> options [DHO_SUBNET_MASK].data, netmask.len = data.len;
lease -> options [DHO_SUBNET_MASK].len); data_string_forget (&data, "script_write_params");
netmask.len = lease -> options [DHO_SUBNET_MASK].len;
subnet = subnet_number (lease -> address, netmask); subnet = subnet_number (lease -> address, netmask);
if (subnet.len) { if (subnet.len) {
fprintf (scriptFile, "%snetwork_number=\"%s\";\n", fprintf (scriptFile,
prefix, piaddr (subnet)); "%snetwork_number=\"%s\";\n",
fprintf (scriptFile, "export %snetwork_number\n", prefix, piaddr (subnet));
prefix); fprintf (scriptFile,
"export %snetwork_number\n", prefix);
if (!lease -> options [DHO_BROADCAST_ADDRESS].len) { oc = lookup_option (lease -> options.dhcp_hash,
broadcast = broadcast_addr (subnet, netmask); DHO_BROADCAST_ADDRESS);
if (broadcast.len) { if (!oc ||
fprintf (scriptFile, !evaluate_option_cache (&data,
"%s%s=\"%s\";\n", prefix, (struct packet *)0,
"broadcast_address", &lease -> options,
piaddr (broadcast)); oc)) {
fprintf (scriptFile, broadcast = broadcast_addr (subnet,
"export %s%s\n", prefix, netmask);
"broadcast_address"); if (broadcast.len) {
fprintf (scriptFile,
"%s%s=\"%s\";\n",
prefix,
"broadcast_address",
piaddr (broadcast));
fprintf (scriptFile,
"export %s%s\n",
prefix,
"broadcast_address");
}
} }
} }
} }
@@ -1919,84 +1947,33 @@ void script_write_params (ip, prefix, lease)
prefix, lease -> server_name); prefix, lease -> server_name);
fprintf (scriptFile, "export %sserver_name\n", prefix); fprintf (scriptFile, "export %sserver_name\n", prefix);
} }
for (i = 0; i < 256; i++) {
u_int8_t *dp;
if (ip -> client -> config -> defaults [i].len) { execute_statements ((struct packet *)0, &lease -> options,
if (lease -> options [i].len) { &lease -> options,
switch (ip -> client -> ip -> client -> config -> on_transmission);
config -> default_actions [i]) {
case ACTION_DEFAULT: for (i = 0; i < OPTION_HASH_SIZE; i++) {
dp = lease -> options [i].data; pair hp;
len = lease -> options [i].len;
break; for (hp = lease -> options.dhcp_hash [i]; hp; hp = hp -> cdr) {
case ACTION_SUPERSEDE: oc = (struct option_cache *)hp -> car;
supersede:
dp = ip -> client -> if (evaluate_option_cache (&data, (struct packet *)0,
config -> defaults [i].data; &lease -> options, oc)) {
len = ip -> client ->
config -> defaults [i].len; if (data.len) {
break; char *s = (dhcp_option_ev_name
case ACTION_PREPEND: (oc -> option));
len = (ip -> client ->
config -> defaults [i].len +
lease -> options [i].len);
if (len > sizeof dbuf) {
warn ("no space to %s %s",
"prepend option",
dhcp_options [i].name);
goto supersede;
}
dp = dbuf;
memcpy (dp,
ip -> client ->
config -> defaults [i].data,
ip -> client ->
config -> defaults [i].len);
memcpy (dp + ip -> client ->
config -> defaults [i].len,
lease -> options [i].data,
lease -> options [i].len);
break;
case ACTION_APPEND:
len = (ip -> client ->
config -> defaults [i].len +
lease -> options [i].len);
if (len > sizeof dbuf) {
warn ("no space to %s %s",
"prepend option",
dhcp_options [i].name);
goto supersede;
}
dp = dbuf;
memcpy (dp,
ip -> client ->
config -> defaults [i].data,
ip -> client ->
config -> defaults [i].len);
memcpy (dp + ip -> client ->
config -> defaults [i].len,
lease -> options [i].data,
lease -> options [i].len);
}
} else {
dp = ip -> client ->
config -> defaults [i].data;
len = ip -> client ->
config -> defaults [i].len;
}
} else if (lease -> options [i].len) {
len = lease -> options [i].len;
dp = lease -> options [i].data;
} else {
len = 0;
}
if (len) {
char *s = dhcp_option_ev_name (&dhcp_options [i]);
fprintf (scriptFile, "%s%s=\"%s\"\n", prefix, s, fprintf (scriptFile,
pretty_print_option (i, dp, len, 0, 0)); "%s%s=\"%s\"\n", prefix, s,
fprintf (scriptFile, "export %s%s\n", prefix, s); (pretty_print_option
(i, data.data, data.len,
0, 0)));
fprintf (scriptFile,
"export %s%s\n", prefix, s);
}
}
} }
} }
fprintf (scriptFile, "%sexpiry=\"%d\"\n", fprintf (scriptFile, "%sexpiry=\"%d\"\n",

File diff suppressed because it is too large Load Diff