2
0
mirror of https://gitlab.isc.org/isc-projects/dhcp synced 2025-08-31 06:15:55 +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

@@ -56,7 +56,7 @@
#ifndef lint
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 */
#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:
*
* 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;
} else {
freeit:
free_client_lease (lp);
destroy_client_lease (lp);
}
}
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 (!picked -> options [DHO_DHCP_MESSAGE_TYPE].len) {
if (!picked -> is_bootp) {
ip -> client -> new = picked;
/* Make up some lease expiry times
@@ -430,7 +449,7 @@ void state_selecting (ipp)
ip -> client -> xid = ip -> client -> packet.xid;
/* 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. */
send_request (ip);
@@ -444,6 +463,8 @@ void dhcpack (packet)
{
struct interface_info *ip = packet -> interface;
struct client_lease *lease;
struct option_cache *oc;
struct data_string ds;
int i;
/* 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);
/* Figure out the lease time. */
ip -> client -> new -> expiry =
getULong (ip -> client ->
new -> options [DHO_DHCP_LEASE_TIME].data);
oc = lookup_option (ip -> client -> new -> options.dhcp_hash,
DHO_DHCP_LEASE_TIME);
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;
otherwise figure it out according to the spec. */
if (ip -> client -> new -> options [DHO_DHCP_RENEWAL_TIME].len)
ip -> client -> new -> renewal =
getULong (ip -> client ->
new -> options [DHO_DHCP_RENEWAL_TIME].data);
else
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 -> expiry / 2;
/* Same deal with the rebind time. */
if (ip -> client -> new -> options [DHO_DHCP_REBINDING_TIME].len)
ip -> client -> new -> rebind =
getULong (ip -> client -> new ->
options [DHO_DHCP_REBINDING_TIME].data);
else
oc = lookup_option (ip -> client -> new -> options.dhcp_hash,
DHO_DHCP_REBINDING_TIME);
if (oc &&
evaluate_option_cache (&ds, packet,
&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 -> renewal +
ip -> client -> new -> renewal / 2 +
@@ -537,7 +595,7 @@ void bind_lease (ip)
/* Replace the old active lease with the new one. */
if (ip -> client -> active)
free_client_lease (ip -> client -> active);
destroy_client_lease (ip -> client -> active);
ip -> client -> active = ip -> client -> new;
ip -> client -> new = (struct client_lease *)0;
@@ -562,6 +620,9 @@ void state_bound (ipp)
void *ipp;
{
struct interface_info *ip = ipp;
int i;
struct option_cache *oc;
struct data_string ds;
ASSERT_STATE(state, S_BOUND);
@@ -569,12 +630,17 @@ void state_bound (ipp)
make_request (ip, ip -> client -> active);
ip -> client -> xid = ip -> client -> packet.xid;
if (ip -> client -> active ->
options [DHO_DHCP_SERVER_IDENTIFIER].len == 4) {
memcpy (ip -> client -> destination.iabuf,
ip -> client -> active ->
options [DHO_DHCP_SERVER_IDENTIFIER].data, 4);
ip -> client -> destination.len = 4;
memset (&ds, 0, sizeof ds);
oc = lookup_option (ip -> client -> active -> options.dhcp_hash,
DHO_DHCP_SERVER_IDENTIFIER);
if (oc &&
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;
} else
ip -> client -> destination = iaddr_broadcast;
} else
ip -> client -> destination = iaddr_broadcast;
@@ -671,9 +737,9 @@ void dhcpoffer (packet)
struct client_lease *lease, *lp;
int i;
int arp_timeout_needed, stop_selecting;
char *name = (packet -> options [DHO_DHCP_MESSAGE_TYPE].len
? "DHCPOFFER" : "BOOTREPLY");
char *name = packet -> packet_type ? "DHCPOFFER" : "BOOTREPLY";
struct iaddrlist *ap;
struct option_cache *oc;
#ifdef DEBUG_PACKET
dump_packet (packet);
@@ -696,11 +762,15 @@ void dhcpoffer (packet)
/* If this lease doesn't supply the minimum required parameters,
blow it off. */
for (i = 0; ip -> client -> config -> required_options [i]; i++) {
if (!packet -> options [ip -> client -> config ->
required_options [i]].len) {
note ("%s isn't satisfactory.", name);
return;
if (ip -> client -> config -> required_options) {
for (i = 0;
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);
return;
}
}
}
@@ -723,7 +793,7 @@ void dhcpoffer (packet)
/* If this lease was acquired through a BOOTREPLY, record that
fact. */
if (!packet -> options [DHO_DHCP_MESSAGE_TYPE].len)
if (!packet -> options_valid || !packet -> packet_type)
lease -> is_bootp = 1;
/* Record the medium under which this lease was offered. */
@@ -797,8 +867,10 @@ struct client_lease *packet_to_lease (packet)
{
struct client_lease *lease;
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) {
warn ("dhcpoffer: no memory to record lease.\n");
@@ -808,45 +880,38 @@ struct client_lease *packet_to_lease (packet)
memset (lease, 0, sizeof *lease);
/* Copy the lease options. */
for (i = 0; i < 256; i++) {
if (packet -> options [i].len) {
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 -> options = packet -> options;
memset (&packet -> options, 0, sizeof packet -> options);
lease -> address.len = sizeof (packet -> raw -> yiaddr);
memcpy (lease -> address.iabuf, &packet -> raw -> yiaddr,
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 ((!packet -> options [DHO_DHCP_OPTION_OVERLOAD].len ||
!(packet -> options [DHO_DHCP_OPTION_OVERLOAD].data [0] & 2)) &&
packet -> raw -> sname [0]) {
if (!(i & 2) && packet -> raw -> sname [0]) {
int len;
/* Don't count on the NUL terminator. */
for (len = 0; len < 64; len++)
if (!packet -> raw -> sname [len])
break;
lease -> server_name = malloc (len + 1);
lease -> server_name = dmalloc (len + 1, "packet_to_lease");
if (!lease -> server_name) {
warn ("dhcpoffer: no memory for filename.\n");
free_client_lease (lease);
destroy_client_lease (lease);
return (struct client_lease *)0;
} else {
memcpy (lease -> server_name,
@@ -856,18 +921,16 @@ struct client_lease *packet_to_lease (packet)
}
/* Ditto for the filename. */
if ((!packet -> options [DHO_DHCP_OPTION_OVERLOAD].len ||
!(packet -> options [DHO_DHCP_OPTION_OVERLOAD].data [0] & 1)) &&
packet -> raw -> file [0]) {
if ((i & 1) && packet -> raw -> file [0]) {
int len;
/* Don't count on the NUL terminator. */
for (len = 0; len < 64; len++)
if (!packet -> raw -> file [len])
break;
lease -> filename = malloc (len + 1);
lease -> filename = dmalloc (len + 1, "packet_to_lease");
if (!lease -> filename) {
warn ("dhcpoffer: no memory for filename.\n");
free_client_lease (lease);
destroy_client_lease (lease);
return (struct client_lease *)0;
} else {
memcpy (lease -> filename,
@@ -909,7 +972,7 @@ void dhcpnak (packet)
return;
}
free_client_lease (ip -> client -> active);
destroy_client_lease (ip -> client -> active);
ip -> client -> active = (struct client_lease *)0;
/* Stop sending DHCPREQUEST packets... */
@@ -1317,6 +1380,103 @@ void send_release (ipp)
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)
struct interface_info *ip;
struct client_lease *lease;
@@ -1324,67 +1484,20 @@ void make_discover (ip, lease)
struct dhcp_packet *raw;
unsigned char discover = DHCPDISCOVER;
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));
/* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */
i = DHO_DHCP_MESSAGE_TYPE;
options [i] = &option_elements [i];
options [i] -> value = &discover;
options [i] -> len = sizeof discover;
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;
}
}
make_client_options (ip, lease, &discover, (struct option_cache *)0,
lease ? &lease -> address : (struct iaddr *)0,
ip -> client -> config -> requested_options,
ip -> client -> config -> on_transmission,
&options);
/* Set up the option buffer... */
ip -> client -> packet_length =
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)
ip -> client -> packet_length = BOOTP_MIN_LEN;
@@ -1420,78 +1533,30 @@ void make_request (ip, lease)
{
unsigned char request = DHCPREQUEST;
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));
/* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
i = DHO_DHCP_MESSAGE_TYPE;
options [i] = &option_elements [i];
options [i] -> value = &request;
options [i] -> len = sizeof request;
options [i] -> buf_size = sizeof request;
options [i] -> timeout = 0xFFFFFFFF;
options [i] -> tree = (struct tree *)0;
if (ip -> client -> state == S_REQUESTING)
oc = lookup_option (lease -> options.dhcp_hash,
DHO_DHCP_SERVER_IDENTIFIER);
else
oc = (struct option_cache *)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 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;
}
}
make_client_options (ip, lease, &request, oc,
((ip -> client -> state == S_REQUESTING ||
ip -> client -> state == S_REBOOTING)
? &lease -> address
: (struct iaddr *)0),
ip -> client -> config -> requested_options,
ip -> client -> config -> on_transmission,
&options);
/* Set up the option buffer... */
ip -> client -> packet_length =
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)
ip -> client -> packet_length = BOOTP_MIN_LEN;
@@ -1535,62 +1600,22 @@ void make_decline (ip, lease)
{
unsigned char decline = DHCPDECLINE;
int i;
struct option_cache *oc;
struct tree_cache *options [256];
struct tree_cache message_type_tree;
struct tree_cache requested_address_tree;
struct tree_cache server_id_tree;
struct tree_cache client_id_tree;
struct option_state options;
memset (options, 0, sizeof options);
memset (&ip -> client -> packet, 0, sizeof (ip -> client -> packet));
/* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
i = DHO_DHCP_MESSAGE_TYPE;
options [i] = &message_type_tree;
options [i] -> value = &decline;
options [i] -> len = sizeof decline;
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;
}
oc = lookup_option (lease -> options.dhcp_hash,
DHO_DHCP_SERVER_IDENTIFIER);
make_client_options (ip, lease, &decline, oc,
&lease -> address, (u_int32_t *)0,
(struct executable_statement *)0, &options);
/* Set up the option buffer... */
ip -> client -> packet_length =
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)
ip -> client -> packet_length = BOOTP_MIN_LEN;
@@ -1626,37 +1651,22 @@ void make_release (ip, lease)
{
unsigned char request = DHCPRELEASE;
int i;
struct option_cache *oc;
struct tree_cache *options [256];
struct tree_cache message_type_tree;
struct tree_cache requested_address_tree;
struct tree_cache server_id_tree;
struct option_state options;
memset (options, 0, sizeof options);
memset (&ip -> client -> packet, 0, sizeof (ip -> client -> packet));
/* Set DHCP_MESSAGE_TYPE to DHCPRELEASE */
i = DHO_DHCP_MESSAGE_TYPE;
options [i] = &message_type_tree;
options [i] -> value = &request;
options [i] -> len = sizeof request;
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;
oc = lookup_option (lease -> options.dhcp_hash,
DHO_DHCP_SERVER_IDENTIFIER);
make_client_options (ip, lease, &request, oc,
&lease -> address, (u_int32_t *)0,
(struct executable_statement *)0, &options);
/* Set up the option buffer... */
ip -> client -> packet_length =
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)
ip -> client -> packet_length = BOOTP_MIN_LEN;
@@ -1685,20 +1695,17 @@ void make_release (ip, lease)
#endif
}
void free_client_lease (lease)
void destroy_client_lease (lease)
struct client_lease *lease;
{
int i;
if (lease -> server_name)
free (lease -> server_name);
dfree (lease -> server_name, "destroy_client_lease");
if (lease -> filename)
free (lease -> filename);
for (i = 0; i < 256; i++) {
if (lease -> options [i].len)
free (lease -> options [i].data);
}
free (lease);
dfree (lease -> filename, "destroy_client_lease");
option_state_dereference (&lease -> options);
free_client_lease (lease, "destroy_client_lease");
}
FILE *leaseFile;
@@ -1744,6 +1751,8 @@ void write_client_lease (ip, lease, rewrite)
int i;
struct tm *t;
static int leases_written;
struct option_cache *oc;
struct data_string ds;
if (!rewrite) {
if (leases_written++ > 20) {
@@ -1778,14 +1787,21 @@ void write_client_lease (ip, lease, rewrite)
if (lease -> medium)
fprintf (leaseFile, " medium \"%s\";\n",
lease -> medium -> string);
for (i = 0; i < 256; i++) {
if (lease -> options [i].len) {
fprintf (leaseFile,
" option %s %s;\n",
dhcp_options [i].name,
pretty_print_option
(i, lease -> options [i].data,
lease -> options [i].len, 1, 1));
for (i = 0; i < OPTION_HASH_SIZE; i++) {
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,
" 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;
{
int i;
u_int8_t dbuf [1500];
int len;
struct data_string data;
struct option_cache *oc;
fprintf (scriptFile, "%sip_address=\"%s\"\n",
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). */
if (lease -> options [DHO_SUBNET_MASK].len &&
(lease -> options [DHO_SUBNET_MASK].len <
sizeof lease -> address.iabuf)) {
struct iaddr netmask, subnet, broadcast;
memset (&data, 0, sizeof data);
oc = lookup_option (lease -> options.dhcp_hash, DHO_SUBNET_MASK);
if (oc && evaluate_option_cache (&data, (struct packet *)0,
&lease -> options, oc)) {
if (data.len > 3) {
struct iaddr netmask, subnet, broadcast;
memcpy (netmask.iabuf,
lease -> options [DHO_SUBNET_MASK].data,
lease -> options [DHO_SUBNET_MASK].len);
netmask.len = lease -> options [DHO_SUBNET_MASK].len;
memcpy (netmask.iabuf, data.data, data.len);
netmask.len = data.len;
data_string_forget (&data, "script_write_params");
subnet = subnet_number (lease -> address, netmask);
if (subnet.len) {
fprintf (scriptFile, "%snetwork_number=\"%s\";\n",
prefix, piaddr (subnet));
fprintf (scriptFile, "export %snetwork_number\n",
prefix);
subnet = subnet_number (lease -> address, netmask);
if (subnet.len) {
fprintf (scriptFile,
"%snetwork_number=\"%s\";\n",
prefix, piaddr (subnet));
fprintf (scriptFile,
"export %snetwork_number\n", prefix);
if (!lease -> options [DHO_BROADCAST_ADDRESS].len) {
broadcast = broadcast_addr (subnet, netmask);
if (broadcast.len) {
fprintf (scriptFile,
"%s%s=\"%s\";\n", prefix,
"broadcast_address",
piaddr (broadcast));
fprintf (scriptFile,
"export %s%s\n", prefix,
"broadcast_address");
oc = lookup_option (lease -> options.dhcp_hash,
DHO_BROADCAST_ADDRESS);
if (!oc ||
!evaluate_option_cache (&data,
(struct packet *)0,
&lease -> options,
oc)) {
broadcast = broadcast_addr (subnet,
netmask);
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);
fprintf (scriptFile, "export %sserver_name\n", prefix);
}
for (i = 0; i < 256; i++) {
u_int8_t *dp;
if (ip -> client -> config -> defaults [i].len) {
if (lease -> options [i].len) {
switch (ip -> client ->
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]);
execute_statements ((struct packet *)0, &lease -> options,
&lease -> options,
ip -> client -> config -> on_transmission);
for (i = 0; i < OPTION_HASH_SIZE; i++) {
pair hp;
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, dp, len, 0, 0));
fprintf (scriptFile, "export %s%s\n", prefix, s);
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",