2
0
mirror of https://gitlab.isc.org/isc-projects/dhcp synced 2025-09-02 15:25:48 +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 &&
/* Take the server-provided renewal time if there is one; evaluate_option_cache (&ds, packet,
otherwise figure it out according to the spec. */ &ip -> client -> new -> options, oc)) {
if (ip -> client -> new -> options [DHO_DHCP_RENEWAL_TIME].len) if (ds.len > 3)
ip -> client -> new -> renewal = ip -> client -> new -> expiry = getULong (ds.data);
getULong (ip -> client ->
new -> options [DHO_DHCP_RENEWAL_TIME].data);
else else
ip -> client -> new -> expiry = 0;
data_string_forget (&ds, "dhcpack");
} else
ip -> client -> new -> expiry = 0;
if (!ip -> client -> new -> expiry) {
warn ("no expiry time on offered lease.");
/* XXX this is going to be bad - if this _does_
XXX happen, we should probably dynamically
XXX disqualify the DHCP server that gave us the
XXX bad packet from future selections and
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,
&ip -> client -> new -> options, oc)) {
if (ds.len > 3)
ip -> client -> new -> rebind = getULong (ds.data);
else 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,14 +630,19 @@ 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 -> active -> options, oc)) {
if (ds.len > 3) {
memcpy (ip -> client -> destination.iabuf, ds.data, 4);
ip -> client -> destination.len = 4; ip -> client -> destination.len = 4;
} else } else
ip -> client -> destination = iaddr_broadcast; ip -> client -> destination = iaddr_broadcast;
} else
ip -> client -> destination = iaddr_broadcast;
ip -> client -> first_sending = cur_time; ip -> client -> first_sending = cur_time;
ip -> client -> interval = ip -> client -> config -> initial_interval; ip -> client -> interval = ip -> client -> config -> initial_interval;
@@ -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,13 +762,17 @@ 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++) {
if (!lookup_option
(packet -> options.dhcp_hash,
ip -> client -> config -> required_options [i])) {
note ("%s isn't satisfactory.", name); note ("%s isn't satisfactory.", name);
return; return;
} }
} }
}
/* If we've already seen this lease, don't record it again. */ /* If we've already seen this lease, don't record it again. */
for (lease = ip -> client -> offered_leases; for (lease = ip -> client -> offered_leases;
@@ -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;
for (p = lease -> options.dhcp_hash [i]; p; p = p -> cdr) {
memset (&ds, 0, sizeof ds);
if (evaluate_option_cache (&ds, (struct packet *)0,
&lease -> options, oc)) {
fprintf (leaseFile, fprintf (leaseFile,
" option %s %s;\n", " option %s %s;\n",
dhcp_options [i].name, dhcp_options [i].name,
pretty_print_option pretty_print_option
(i, lease -> options [i].data, (i, ds.data, ds.len,
lease -> options [i].len, 1, 1)); 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,37 +1893,49 @@ 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,
&lease -> options, oc)) {
if (data.len > 3) {
struct iaddr netmask, subnet, broadcast; 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,
"%snetwork_number=\"%s\";\n",
prefix, piaddr (subnet)); prefix, piaddr (subnet));
fprintf (scriptFile, "export %snetwork_number\n", fprintf (scriptFile,
prefix); "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 (!oc ||
!evaluate_option_cache (&data,
(struct packet *)0,
&lease -> options,
oc)) {
broadcast = broadcast_addr (subnet,
netmask);
if (broadcast.len) { if (broadcast.len) {
fprintf (scriptFile, fprintf (scriptFile,
"%s%s=\"%s\";\n", prefix, "%s%s=\"%s\";\n",
prefix,
"broadcast_address", "broadcast_address",
piaddr (broadcast)); piaddr (broadcast));
fprintf (scriptFile, fprintf (scriptFile,
"export %s%s\n", prefix, "export %s%s\n",
prefix,
"broadcast_address"); "broadcast_address");
} }
} }
} }
} }
}
if (lease -> filename) { if (lease -> filename) {
fprintf (scriptFile, "%sfilename=\"%s\";\n", fprintf (scriptFile, "%sfilename=\"%s\";\n",
@@ -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:
dp = lease -> options [i].data;
len = lease -> options [i].len;
break;
case ACTION_SUPERSEDE:
supersede:
dp = ip -> client ->
config -> defaults [i].data;
len = ip -> client ->
config -> defaults [i].len;
break;
case ACTION_PREPEND:
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, for (i = 0; i < OPTION_HASH_SIZE; i++) {
pretty_print_option (i, dp, len, 0, 0)); pair hp;
fprintf (scriptFile, "export %s%s\n", prefix, s);
for (hp = lease -> options.dhcp_hash [i]; hp; hp = hp -> cdr) {
oc = (struct option_cache *)hp -> car;
if (evaluate_option_cache (&data, (struct packet *)0,
&lease -> options, oc)) {
if (data.len) {
char *s = (dhcp_option_ev_name
(oc -> option));
fprintf (scriptFile,
"%s%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