mirror of
https://gitlab.isc.org/isc-projects/dhcp
synced 2025-08-29 05:17:57 +00:00
Move a lot of packet discard code into ack_lease(), after we've evaluated the statements associated with a packet. Use new-style option processing. No more explicit user/vendor class support. Revamp lease time processing. Get client identifier directly from host declaration.
This commit is contained in:
parent
ece6ea338c
commit
b1dd98c948
687
server/dhcp.c
687
server/dhcp.c
@ -42,7 +42,7 @@
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"$Id: dhcp.c,v 1.63 1998/04/19 23:34:43 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. All rights reserved.\n";
|
||||
"$Id: dhcp.c,v 1.64 1998/06/25 03:56:24 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "dhcpd.h"
|
||||
@ -109,12 +109,6 @@ void dhcpdiscover (packet)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Make sure this packet satisfies the configured minimum
|
||||
number of seconds. */
|
||||
if (packet -> raw -> secs <
|
||||
packet -> shared_network -> group -> min_secs)
|
||||
return;
|
||||
|
||||
/* If we didn't find a lease, try to allocate one... */
|
||||
if (!lease) {
|
||||
lease = packet -> shared_network -> last_lease;
|
||||
@ -162,24 +156,7 @@ void dhcpdiscover (packet)
|
||||
}
|
||||
}
|
||||
|
||||
/* If this subnet won't boot unknown clients, ignore the
|
||||
request. */
|
||||
if (!lease -> host &&
|
||||
!lease -> subnet -> group -> boot_unknown_clients) {
|
||||
note ("Ignoring unknown client %s",
|
||||
print_hw_addr (packet -> raw -> htype,
|
||||
packet -> raw -> hlen,
|
||||
packet -> raw -> chaddr));
|
||||
} else if (lease -> host &&
|
||||
!lease -> host -> group -> allow_booting) {
|
||||
note ("Declining to boot client %s",
|
||||
lease -> host -> name
|
||||
? lease -> host -> name
|
||||
: print_hw_addr (packet -> raw -> htype,
|
||||
packet -> raw -> hlen,
|
||||
packet -> raw -> chaddr));
|
||||
} else
|
||||
ack_lease (packet, lease, DHCPOFFER, cur_time + 120);
|
||||
ack_lease (packet, lease, DHCPOFFER, cur_time + 120);
|
||||
}
|
||||
|
||||
void dhcprequest (packet)
|
||||
@ -422,32 +399,29 @@ void nak_lease (packet, cip)
|
||||
unsigned char nak = DHCPNAK;
|
||||
struct packet outgoing;
|
||||
struct hardware hto;
|
||||
int i;
|
||||
|
||||
struct tree_cache *options [256];
|
||||
struct tree_cache dhcpnak_tree;
|
||||
struct tree_cache dhcpmsg_tree;
|
||||
struct option_state options;
|
||||
|
||||
memset (options, 0, sizeof options);
|
||||
memset (&options, 0, sizeof options);
|
||||
memset (&outgoing, 0, sizeof outgoing);
|
||||
memset (&raw, 0, sizeof raw);
|
||||
outgoing.raw = &raw;
|
||||
|
||||
/* Set DHCP_MESSAGE_TYPE to DHCPNAK */
|
||||
options [DHO_DHCP_MESSAGE_TYPE] = &dhcpnak_tree;
|
||||
options [DHO_DHCP_MESSAGE_TYPE] -> value = &nak;
|
||||
options [DHO_DHCP_MESSAGE_TYPE] -> len = sizeof nak;
|
||||
options [DHO_DHCP_MESSAGE_TYPE] -> buf_size = sizeof nak;
|
||||
options [DHO_DHCP_MESSAGE_TYPE] -> timeout = 0xFFFFFFFF;
|
||||
options [DHO_DHCP_MESSAGE_TYPE] -> tree = (struct tree *)0;
|
||||
i = DHO_DHCP_MESSAGE_TYPE;
|
||||
options.dhcp_options [i] =
|
||||
option_cache (make_const_data (&nak, sizeof nak, 0, 0),
|
||||
dhcp_universe.options [i]);
|
||||
|
||||
/* Set DHCP_MESSAGE to whatever the message is */
|
||||
options [DHO_DHCP_MESSAGE] = &dhcpmsg_tree;
|
||||
options [DHO_DHCP_MESSAGE] -> value = (unsigned char *)dhcp_message;
|
||||
options [DHO_DHCP_MESSAGE] -> buf_size =
|
||||
options [DHO_DHCP_MESSAGE] -> len = strlen (dhcp_message);
|
||||
options [DHO_DHCP_MESSAGE] -> timeout = 0xFFFFFFFF;
|
||||
options [DHO_DHCP_MESSAGE] -> tree = (struct tree *)0;
|
||||
|
||||
i = DHO_DHCP_MESSAGE;
|
||||
options.server_options [i] =
|
||||
option_cache (make_const_data (dhcp_message,
|
||||
strlen (dhcp_message),
|
||||
1, 0),
|
||||
dhcp_universe.options [i]);
|
||||
|
||||
/* Do not use the client's requested parameter list. */
|
||||
packet -> options [DHO_DHCP_PARAMETER_REQUEST_LIST].len = 0;
|
||||
packet -> options [DHO_DHCP_PARAMETER_REQUEST_LIST].data =
|
||||
@ -455,8 +429,7 @@ void nak_lease (packet, cip)
|
||||
|
||||
/* Set up the option buffer... */
|
||||
outgoing.packet_length =
|
||||
cons_options (packet, outgoing.raw, 0,
|
||||
options, packet -> agent_options, 0, 0, 0);
|
||||
cons_options (packet, outgoing.raw, 0, &options, 0, 0, 0);
|
||||
|
||||
/* memset (&raw.ciaddr, 0, sizeof raw.ciaddr);*/
|
||||
raw.siaddr = packet -> interface -> primary_address;
|
||||
@ -544,9 +517,11 @@ void ack_lease (packet, lease, offer, when)
|
||||
struct lease_state *state;
|
||||
TIME lease_time;
|
||||
TIME offered_lease_time;
|
||||
struct data_string d1;
|
||||
TIME comp_lease_time;
|
||||
|
||||
struct class *vendor_class, *user_class;
|
||||
int i;
|
||||
int val;
|
||||
|
||||
/* If we're already acking this lease, don't do it again. */
|
||||
if (lease -> state) {
|
||||
@ -554,44 +529,7 @@ void ack_lease (packet, lease, offer, when)
|
||||
return;
|
||||
}
|
||||
|
||||
if (packet -> options [DHO_DHCP_CLASS_IDENTIFIER].len) {
|
||||
vendor_class =
|
||||
find_class (0,
|
||||
(char *)packet ->
|
||||
options [DHO_DHCP_CLASS_IDENTIFIER].data,
|
||||
packet ->
|
||||
options [DHO_DHCP_CLASS_IDENTIFIER].len);
|
||||
} else {
|
||||
vendor_class = (struct class *)0;
|
||||
}
|
||||
|
||||
if (packet -> options [DHO_DHCP_USER_CLASS_ID].len) {
|
||||
user_class =
|
||||
find_class (1,
|
||||
(char *)packet ->
|
||||
options [DHO_DHCP_USER_CLASS_ID].data,
|
||||
packet ->
|
||||
options [DHO_DHCP_USER_CLASS_ID].len);
|
||||
} else {
|
||||
user_class = (struct class *)0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is not a specific host entry, and either the
|
||||
* vendor class or user class (if they exist) deny booting,
|
||||
* then bug out.
|
||||
*/
|
||||
if (!lease -> host) {
|
||||
if (vendor_class && !vendor_class -> group -> allow_booting) {
|
||||
debug ("Booting denied by vendor class");
|
||||
return;
|
||||
}
|
||||
|
||||
if (user_class && !user_class -> group -> allow_booting) {
|
||||
debug ("Booting denied by user class");
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* XXX Process class restrictions. */
|
||||
|
||||
/* Allocate a lease state structure... */
|
||||
state = new_lease_state ("ack_lease");
|
||||
@ -624,24 +562,104 @@ void ack_lease (packet, lease, offer, when)
|
||||
lease -> client_hostname = 0;
|
||||
}
|
||||
|
||||
/* Choose a filename; first from the host_decl, if any, then from
|
||||
the user class, then from the vendor class. */
|
||||
if (lease -> host && lease -> host -> group -> filename)
|
||||
state -> filename = lease -> host -> group -> filename;
|
||||
else if (user_class && user_class -> group -> filename)
|
||||
state -> filename = user_class -> group -> filename;
|
||||
else if (vendor_class && vendor_class -> group -> filename)
|
||||
state -> filename = vendor_class -> group -> filename;
|
||||
else state -> filename = (char *)0;
|
||||
/* Process all of the executable statements associated with
|
||||
this lease. */
|
||||
memset (&state -> options, 0, sizeof state -> options);
|
||||
|
||||
/* Steal the agent options from the packet. */
|
||||
if (packet -> agent_options) {
|
||||
state -> options.agent_options = packet -> agent_options;
|
||||
packet -> agent_options = (struct agent_options *)0;
|
||||
}
|
||||
|
||||
/* Execute the subnet statements. */
|
||||
execute_statements_in_scope (packet, &state -> options,
|
||||
lease -> subnet -> group,
|
||||
(struct group *)0);
|
||||
|
||||
/* Vendor and user classes are only supported for DHCP clients. */
|
||||
if (state -> offer) {
|
||||
/* XXX process class stuff here. */
|
||||
}
|
||||
|
||||
/* If we have a host_decl structure, run the options associated
|
||||
with its group. */
|
||||
if (lease -> host)
|
||||
execute_statements_in_scope (packet, &state -> options,
|
||||
lease -> host -> group,
|
||||
lease -> subnet -> group);
|
||||
|
||||
/* Make sure this packet satisfies the configured minimum
|
||||
number of seconds. */
|
||||
if (state -> options.server_options [SV_MIN_SECS]) {
|
||||
d1 = evaluate_data_expression
|
||||
(packet,
|
||||
(state -> options.server_options
|
||||
[SV_MIN_SECS] -> expression));
|
||||
if (d1.len && packet -> raw -> secs < d1.data [0])
|
||||
return;
|
||||
}
|
||||
|
||||
/* Drop the request if it's not allowed for this client. */
|
||||
if (!lease -> host &&
|
||||
state -> options.server_options [SV_BOOT_UNKNOWN_CLIENTS]) {
|
||||
d1 = evaluate_data_expression
|
||||
(packet, (state -> options.server_options
|
||||
[SV_BOOT_UNKNOWN_CLIENTS] -> expression));
|
||||
if (d1.len && !d1.data [0]) {
|
||||
note ("Ignoring unknown client %s",
|
||||
print_hw_addr (packet -> raw -> htype,
|
||||
packet -> raw -> hlen,
|
||||
packet -> raw -> chaddr));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Drop the request if it's not allowed for this client. */
|
||||
if (!offer &&
|
||||
state -> options.server_options [SV_ALLOW_BOOTP]) {
|
||||
d1 = evaluate_data_expression
|
||||
(packet, (state -> options.server_options
|
||||
[SV_ALLOW_BOOTP] -> expression));
|
||||
if (d1.len && !d1.data [0]) {
|
||||
note ("Ignoring BOOTP client %s",
|
||||
print_hw_addr (packet -> raw -> htype,
|
||||
packet -> raw -> hlen,
|
||||
packet -> raw -> chaddr));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (state -> options.server_options [SV_ALLOW_BOOTING]) {
|
||||
d1 = evaluate_data_expression
|
||||
(packet, (state -> options.server_options
|
||||
[SV_ALLOW_BOOTING] -> expression));
|
||||
if (d1.len && !d1.data [0]) {
|
||||
note ("Declining to boot client %s",
|
||||
lease -> host -> name
|
||||
? lease -> host -> name
|
||||
: print_hw_addr (packet -> raw -> htype,
|
||||
packet -> raw -> hlen,
|
||||
packet -> raw -> chaddr));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Figure out the filename. */
|
||||
if (state -> options.server_options [SV_FILENAME])
|
||||
state -> filename =
|
||||
(evaluate_data_expression
|
||||
(packet,
|
||||
(state -> options.
|
||||
server_options [SV_FILENAME] -> expression)));
|
||||
|
||||
/* Choose a server name as above. */
|
||||
if (lease -> host && lease -> host -> group -> server_name)
|
||||
state -> server_name = lease -> host -> group -> server_name;
|
||||
else if (user_class && user_class -> group -> server_name)
|
||||
state -> server_name = user_class -> group -> server_name;
|
||||
else if (vendor_class && vendor_class -> group -> server_name)
|
||||
state -> server_name = vendor_class -> group -> server_name;
|
||||
else state -> server_name = (char *)0;
|
||||
if (state -> options.server_options [SV_SERVER_NAME])
|
||||
state -> server_name =
|
||||
(evaluate_data_expression
|
||||
(packet,
|
||||
(state -> options.
|
||||
server_options [SV_SERVER_NAME] -> expression)));
|
||||
|
||||
/* At this point, we have a lease that we can offer the client.
|
||||
Now we construct a lease structure that contains what we want,
|
||||
@ -659,70 +677,83 @@ void ack_lease (packet, lease, offer, when)
|
||||
/* Figure out how long a lease to assign. If this is a
|
||||
dynamic BOOTP lease, its duration must be infinite. */
|
||||
if (offer) {
|
||||
if (packet -> options [DHO_DHCP_LEASE_TIME].len == 4) {
|
||||
if (packet -> options [DHO_DHCP_LEASE_TIME].len ==
|
||||
sizeof (u_int32_t)) {
|
||||
lease_time = getULong
|
||||
(packet -> options [DHO_DHCP_LEASE_TIME].data);
|
||||
|
||||
/* Don't let the client ask for a longer lease than
|
||||
is supported for this subnet or host. */
|
||||
if (lease -> host &&
|
||||
lease -> host -> group -> max_lease_time) {
|
||||
if (lease_time >
|
||||
lease -> host -> group -> max_lease_time)
|
||||
lease_time = (lease -> host ->
|
||||
group -> max_lease_time);
|
||||
} else {
|
||||
if (lease_time >
|
||||
lease -> subnet -> group -> max_lease_time)
|
||||
lease_time = (lease -> subnet ->
|
||||
group -> max_lease_time);
|
||||
(packet -> options [DHO_DHCP_LEASE_TIME].data);
|
||||
comp_lease_time = DEFAULT_MAX_LEASE_TIME;
|
||||
i = SV_MAX_LEASE_TIME;
|
||||
if (state ->
|
||||
options.server_options [i]) {
|
||||
d1 = evaluate_data_expression
|
||||
(packet,
|
||||
state -> options.
|
||||
server_options [i] -> expression);
|
||||
if (d1.len == sizeof (u_int32_t))
|
||||
comp_lease_time = getULong (d1.data);
|
||||
}
|
||||
|
||||
/* Enforce the maximum lease length. */
|
||||
if (lease_time > comp_lease_time)
|
||||
lease_time = comp_lease_time;
|
||||
|
||||
} else {
|
||||
if (lease -> host
|
||||
&& lease -> host -> group -> default_lease_time)
|
||||
lease_time = (lease -> host ->
|
||||
group -> default_lease_time);
|
||||
else
|
||||
lease_time = (lease -> subnet ->
|
||||
group -> default_lease_time);
|
||||
i = SV_DEFAULT_LEASE_TIME;
|
||||
lease_time = DEFAULT_DEFAULT_LEASE_TIME;
|
||||
if (state ->
|
||||
options.server_options [i]) {
|
||||
d1 = evaluate_data_expression
|
||||
(packet,
|
||||
state -> options.
|
||||
server_options [i] -> expression);
|
||||
if (d1.len == sizeof (u_int32_t))
|
||||
lease_time = getULong (d1.data);
|
||||
}
|
||||
}
|
||||
|
||||
/* Enforce a minimum lease time, if specified. */
|
||||
if (lease -> host) {
|
||||
if (lease_time <
|
||||
lease -> host -> group -> min_lease_time)
|
||||
lease_time = (lease ->
|
||||
host -> group -> min_lease_time);
|
||||
} else {
|
||||
if (lease_time <
|
||||
lease -> subnet -> group -> min_lease_time)
|
||||
lease_time = (lease -> subnet ->
|
||||
group -> min_lease_time);
|
||||
i = SV_MIN_LEASE_TIME;
|
||||
comp_lease_time = DEFAULT_MIN_LEASE_TIME;
|
||||
if (state -> options.server_options [i]) {
|
||||
d1 = evaluate_data_expression
|
||||
(packet,
|
||||
state -> options.
|
||||
server_options [i] -> expression);
|
||||
if (d1.len == sizeof (u_int32_t))
|
||||
comp_lease_time = getULong (d1.data);
|
||||
}
|
||||
|
||||
if (lease_time < comp_lease_time)
|
||||
lease_time = comp_lease_time;
|
||||
|
||||
state -> offered_expiry = cur_time + lease_time;
|
||||
if (when)
|
||||
lt.ends = when;
|
||||
else
|
||||
lt.ends = state -> offered_expiry;
|
||||
} else {
|
||||
if (lease -> host &&
|
||||
lease -> host -> group -> bootp_lease_length)
|
||||
lt.ends = (cur_time +
|
||||
lease -> host ->
|
||||
group -> bootp_lease_length);
|
||||
else if (lease -> subnet -> group -> bootp_lease_length)
|
||||
lt.ends = (cur_time +
|
||||
lease -> subnet ->
|
||||
group -> bootp_lease_length);
|
||||
else if (lease -> host &&
|
||||
lease -> host -> group -> bootp_lease_cutoff)
|
||||
lt.ends = lease -> host -> group -> bootp_lease_cutoff;
|
||||
else
|
||||
lt.ends = (lease -> subnet ->
|
||||
group -> bootp_lease_cutoff);
|
||||
state -> offered_expiry = lt.ends;
|
||||
lease_time = MAX_TIME - cur_time;
|
||||
|
||||
i = SV_BOOTP_LEASE_LENGTH;
|
||||
if (state -> options.server_options [i]) {
|
||||
d1 = evaluate_data_expression
|
||||
(packet,
|
||||
state -> options.
|
||||
server_options [i] -> expression);
|
||||
if (d1.len == sizeof (u_int32_t))
|
||||
lease_time = getULong (d1.data);
|
||||
}
|
||||
|
||||
i = SV_BOOTP_LEASE_CUTOFF;
|
||||
if (state -> options.server_options [i]) {
|
||||
d1 = evaluate_data_expression
|
||||
(packet,
|
||||
state -> options.
|
||||
server_options [i] -> expression);
|
||||
if (d1.len == sizeof (u_int32_t))
|
||||
lease_time = getULong (d1.data) - cur_time;
|
||||
}
|
||||
|
||||
lt.ends = state -> offered_expiry = cur_time + lease_time;
|
||||
lt.flags = BOOTP_LEASE;
|
||||
}
|
||||
|
||||
@ -805,136 +836,58 @@ void ack_lease (packet, lease, offer, when)
|
||||
options [DHO_DHCP_MAX_MESSAGE_SIZE].data);
|
||||
}
|
||||
|
||||
/* Steal the agent options from the packet. */
|
||||
if (packet -> agent_options) {
|
||||
state -> agent_options = packet -> agent_options;
|
||||
packet -> agent_options = (struct agent_options *)0;
|
||||
}
|
||||
|
||||
/* Figure out what options to send to the client: */
|
||||
|
||||
/* Start out with the subnet options... */
|
||||
memcpy (state -> options,
|
||||
lease -> subnet -> group -> options,
|
||||
sizeof state -> options);
|
||||
|
||||
/* Vendor and user classes are only supported for DHCP clients. */
|
||||
if (state -> offer) {
|
||||
/* If we have a vendor class, install those options,
|
||||
superseding any subnet options. */
|
||||
if (vendor_class) {
|
||||
for (i = 0; i < 256; i++)
|
||||
if (vendor_class -> group -> options [i])
|
||||
state -> options [i] =
|
||||
(vendor_class -> group ->
|
||||
options [i]);
|
||||
}
|
||||
|
||||
/* If we have a user class, install those options,
|
||||
superseding any subnet and vendor class options. */
|
||||
if (user_class) {
|
||||
for (i = 0; i < 256; i++)
|
||||
if (user_class -> group -> options [i])
|
||||
state -> options [i] =
|
||||
(user_class -> group ->
|
||||
options [i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* If we have a host_decl structure, install the associated
|
||||
options, superseding anything that's in the way. */
|
||||
if (lease -> host) {
|
||||
for (i = 0; i < 256; i++)
|
||||
if (lease -> host -> group -> options [i])
|
||||
state -> options [i] = (lease -> host ->
|
||||
group -> options [i]);
|
||||
}
|
||||
|
||||
/* If we didn't get a hostname from an option somewhere, see if
|
||||
we can get one from the lease. */
|
||||
i = DHO_HOST_NAME;
|
||||
if (!state -> options [i] && lease -> hostname) {
|
||||
state -> options [i] = new_tree_cache ("hostname");
|
||||
state -> options [i] -> flags = TC_TEMPORARY;
|
||||
state -> options [i] -> value =
|
||||
(unsigned char *)lease -> hostname;
|
||||
state -> options [i] -> len = strlen (lease -> hostname);
|
||||
state -> options [i] -> buf_size = state -> options [i] -> len;
|
||||
state -> options [i] -> timeout = 0xFFFFFFFF;
|
||||
state -> options [i] -> tree = (struct tree *)0;
|
||||
}
|
||||
|
||||
/* Now, if appropriate, put in DHCP-specific options that
|
||||
override those. */
|
||||
if (state -> offer) {
|
||||
i = DHO_DHCP_MESSAGE_TYPE;
|
||||
state -> options [i] = new_tree_cache ("message-type");
|
||||
state -> options [i] -> flags = TC_TEMPORARY;
|
||||
state -> options [i] -> value = &state -> offer;
|
||||
state -> options [i] -> len = sizeof state -> offer;
|
||||
state -> options [i] -> buf_size = sizeof state -> offer;
|
||||
state -> options [i] -> timeout = 0xFFFFFFFF;
|
||||
state -> options [i] -> tree = (struct tree *)0;
|
||||
state -> options.dhcp_options [i] =
|
||||
option_cache (make_const_data (&state -> offer,
|
||||
sizeof state -> offer,
|
||||
0, 0),
|
||||
dhcp_universe.options [i]);
|
||||
|
||||
i = DHO_DHCP_SERVER_IDENTIFIER;
|
||||
if (!state -> options [i]) {
|
||||
state -> options [i] = new_tree_cache ("server-id");
|
||||
state -> options [i] -> value =
|
||||
(unsigned char *)&state ->
|
||||
ip -> primary_address;
|
||||
state -> options [i] -> len =
|
||||
sizeof state -> ip -> primary_address;
|
||||
state -> options [i] -> buf_size
|
||||
= state -> options [i] -> len;
|
||||
state -> options [i] -> timeout = 0xFFFFFFFF;
|
||||
state -> options [i] -> tree = (struct tree *)0;
|
||||
if (!state -> options.dhcp_options [i]) {
|
||||
state -> options.dhcp_options [i] =
|
||||
(option_cache
|
||||
(make_const_data
|
||||
((unsigned char *)
|
||||
&state -> ip -> primary_address,
|
||||
sizeof state -> ip -> primary_address,
|
||||
0, 0),
|
||||
dhcp_universe.options [i]));
|
||||
}
|
||||
|
||||
/* Sanity check the lease time. */
|
||||
if ((state -> offered_expiry - cur_time) < 15)
|
||||
offered_lease_time = (lease -> subnet ->
|
||||
group -> default_lease_time);
|
||||
else if (state -> offered_expiry - cur_time >
|
||||
lease -> subnet -> group -> max_lease_time)
|
||||
offered_lease_time = (lease -> subnet ->
|
||||
group -> max_lease_time);
|
||||
else
|
||||
offered_lease_time =
|
||||
state -> offered_expiry - cur_time;
|
||||
offered_lease_time =
|
||||
state -> offered_expiry - cur_time;
|
||||
|
||||
putULong ((unsigned char *)&state -> expiry,
|
||||
offered_lease_time);
|
||||
i = DHO_DHCP_LEASE_TIME;
|
||||
if (state -> options [i])
|
||||
if (state -> options.dhcp_options [i])
|
||||
warn ("dhcp-lease-time option for %s overridden.",
|
||||
inet_ntoa (state -> ciaddr));
|
||||
state -> options [i] = new_tree_cache ("lease-expiry");
|
||||
state -> options [i] -> flags = TC_TEMPORARY;
|
||||
state -> options [i] -> value =
|
||||
(unsigned char *)&state -> expiry;
|
||||
state -> options [i] -> len = sizeof state -> expiry;
|
||||
state -> options [i] -> buf_size = sizeof state -> expiry;
|
||||
state -> options [i] -> timeout = 0xFFFFFFFF;
|
||||
state -> options [i] -> tree = (struct tree *)0;
|
||||
state -> options.dhcp_options [i] =
|
||||
option_cache (make_const_data ((unsigned char *)
|
||||
&state -> expiry,
|
||||
sizeof state -> expiry,
|
||||
0, 0),
|
||||
dhcp_universe.options [i]);
|
||||
|
||||
/* Renewal time is lease time * 0.5. */
|
||||
offered_lease_time /= 2;
|
||||
putULong ((unsigned char *)&state -> renewal,
|
||||
offered_lease_time);
|
||||
i = DHO_DHCP_RENEWAL_TIME;
|
||||
if (state -> options [i])
|
||||
if (state -> options.dhcp_options [i])
|
||||
warn ("dhcp-renewal-time option for %s overridden.",
|
||||
inet_ntoa (state -> ciaddr));
|
||||
state -> options [i] = new_tree_cache ("renewal-time");
|
||||
state -> options [i] -> flags = TC_TEMPORARY;
|
||||
state -> options [i] -> value =
|
||||
(unsigned char *)&state -> renewal;
|
||||
state -> options [i] -> len = sizeof state -> renewal;
|
||||
state -> options [i] -> buf_size = sizeof state -> renewal;
|
||||
state -> options [i] -> timeout = 0xFFFFFFFF;
|
||||
state -> options [i] -> tree = (struct tree *)0;
|
||||
|
||||
state -> options.dhcp_options [i] =
|
||||
option_cache (make_const_data ((unsigned char *)
|
||||
&state -> renewal,
|
||||
sizeof state -> renewal,
|
||||
0, 0),
|
||||
dhcp_universe.options [i]);
|
||||
|
||||
/* Rebinding time is lease time * 0.875. */
|
||||
offered_lease_time += (offered_lease_time / 2
|
||||
@ -942,87 +895,95 @@ void ack_lease (packet, lease, offer, when)
|
||||
putULong ((unsigned char *)&state -> rebind,
|
||||
offered_lease_time);
|
||||
i = DHO_DHCP_REBINDING_TIME;
|
||||
if (state -> options [i])
|
||||
if (state -> options.dhcp_options [i])
|
||||
warn ("dhcp-rebinding-time option for %s overridden.",
|
||||
inet_ntoa (state -> ciaddr));
|
||||
state -> options [i] = new_tree_cache ("rebind-time");
|
||||
state -> options [i] -> flags = TC_TEMPORARY;
|
||||
state -> options [i] -> value =
|
||||
(unsigned char *)&state -> rebind;
|
||||
state -> options [i] -> len = sizeof state -> rebind;
|
||||
state -> options [i] -> buf_size = sizeof state -> rebind;
|
||||
state -> options [i] -> timeout = 0xFFFFFFFF;
|
||||
state -> options [i] -> tree = (struct tree *)0;
|
||||
|
||||
/* If we used the vendor class the client specified, we
|
||||
have to return it. */
|
||||
if (vendor_class) {
|
||||
i = DHO_DHCP_CLASS_IDENTIFIER;
|
||||
state -> options [i] =
|
||||
new_tree_cache ("class-identifier");
|
||||
state -> options [i] -> flags = TC_TEMPORARY;
|
||||
state -> options [i] -> value =
|
||||
(unsigned char *)vendor_class -> name;
|
||||
state -> options [i] -> len =
|
||||
strlen (vendor_class -> name);
|
||||
state -> options [i] -> buf_size =
|
||||
state -> options [i] -> len;
|
||||
state -> options [i] -> timeout = 0xFFFFFFFF;
|
||||
state -> options [i] -> tree = (struct tree *)0;
|
||||
}
|
||||
|
||||
/* If we used the user class the client specified, we
|
||||
have to return it. */
|
||||
if (user_class) {
|
||||
i = DHO_DHCP_USER_CLASS_ID;
|
||||
state -> options [i] = new_tree_cache ("user-class");
|
||||
state -> options [i] -> flags = TC_TEMPORARY;
|
||||
state -> options [i] -> value =
|
||||
(unsigned char *)user_class -> name;
|
||||
state -> options [i] -> len =
|
||||
strlen (user_class -> name);
|
||||
state -> options [i] -> buf_size =
|
||||
state -> options [i] -> len;
|
||||
state -> options [i] -> timeout = 0xFFFFFFFF;
|
||||
state -> options [i] -> tree = (struct tree *)0;
|
||||
}
|
||||
state -> options.dhcp_options [i] =
|
||||
option_cache (make_const_data ((unsigned char *)
|
||||
&state -> rebind,
|
||||
sizeof state -> rebind,
|
||||
0, 0),
|
||||
dhcp_universe.options [i]);
|
||||
}
|
||||
|
||||
/* Use the subnet mask from the subnet declaration if no other
|
||||
mask has been provided. */
|
||||
i = DHO_SUBNET_MASK;
|
||||
if (!state -> options [i]) {
|
||||
state -> options [i] = new_tree_cache ("subnet-mask");
|
||||
state -> options [i] -> flags = TC_TEMPORARY;
|
||||
state -> options [i] -> value =
|
||||
lease -> subnet -> netmask.iabuf;
|
||||
state -> options [i] -> len = lease -> subnet -> netmask.len;
|
||||
state -> options [i] -> buf_size =
|
||||
lease -> subnet -> netmask.len;
|
||||
state -> options [i] -> timeout = 0xFFFFFFFF;
|
||||
state -> options [i] -> tree = (struct tree *)0;
|
||||
if (!state -> options.dhcp_options [i]) {
|
||||
state -> options.dhcp_options [i] =
|
||||
(option_cache
|
||||
(make_const_data (lease -> subnet -> netmask.iabuf,
|
||||
lease -> subnet -> netmask.len,
|
||||
0, 0),
|
||||
dhcp_universe.options [i]));
|
||||
}
|
||||
|
||||
/* Use the hostname from the host declaration if there is one
|
||||
and no hostname has otherwise been provided, and if the
|
||||
use-host-decl-name flag is set. */
|
||||
i = DHO_HOST_NAME;
|
||||
if (!state -> options.dhcp_options [i] &&
|
||||
lease -> host && lease -> host -> name) {
|
||||
d1 = evaluate_data_expression
|
||||
(packet, (state -> options.server_options
|
||||
[SV_USE_HOST_DECL_NAMES] -> expression));
|
||||
if (d1.len && d1.data [0]) {
|
||||
state -> options.dhcp_options [i] =
|
||||
(option_cache
|
||||
(make_const_data (lease -> host -> name,
|
||||
strlen (lease ->
|
||||
host -> name),
|
||||
1, 0),
|
||||
dhcp_universe.options [i]));
|
||||
}
|
||||
}
|
||||
|
||||
/* If we don't have a hostname yet, and we've been asked to do
|
||||
a reverse lookup to find the hostname, do it. */
|
||||
if (!state -> options.dhcp_options [i]
|
||||
&& state -> options.server_options [SV_GET_LEASE_HOSTNAMES]) {
|
||||
d1 = evaluate_data_expression
|
||||
(packet, (state -> options.server_options
|
||||
[SV_GET_LEASE_HOSTNAMES] -> expression));
|
||||
if (d1.len && d1.data [0]) {
|
||||
struct in_addr ia;
|
||||
struct hostent *h;
|
||||
|
||||
memcpy (&ia, lease -> ip_addr.iabuf, 4);
|
||||
|
||||
h = gethostbyaddr ((char *)&ia, sizeof ia, AF_INET);
|
||||
if (!h)
|
||||
warn ("No hostname for %s", inet_ntoa (ia));
|
||||
else {
|
||||
state -> options.dhcp_options [i] =
|
||||
option_cache
|
||||
(make_const_data
|
||||
(h -> h_name,
|
||||
strlen (h -> h_name) + 1,
|
||||
1, 1),
|
||||
dhcp_universe.options [i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If so directed, use the leased IP address as the router address.
|
||||
This supposedly makes Win95 machines ARP for all IP addresses,
|
||||
so if the local router does proxy arp, you win. */
|
||||
if ((lease -> host &&
|
||||
lease -> host -> group -> use_lease_addr_for_default_route) ||
|
||||
(lease -> subnet -> group -> use_lease_addr_for_default_route)) {
|
||||
i = DHO_ROUTERS;
|
||||
|
||||
if (state -> options [i] &&
|
||||
state -> options [i] -> flags & TC_TEMPORARY)
|
||||
free_tree_cache (state -> options [i], "dhcp_reply");
|
||||
|
||||
state -> options [i] = new_tree_cache ("routers");
|
||||
state -> options [i] -> flags = TC_TEMPORARY;
|
||||
state -> options [i] -> value =
|
||||
lease -> ip_addr.iabuf;
|
||||
state -> options [i] -> len = lease -> ip_addr.len;
|
||||
state -> options [i] -> buf_size = lease -> ip_addr.len;
|
||||
state -> options [i] -> timeout = 0xFFFFFFFF;
|
||||
state -> options [i] -> tree = (struct tree *)0;
|
||||
i = SV_USE_LEASE_ADDR_FOR_DEFAULT_ROUTE;
|
||||
if (state -> options.server_options [i]) {
|
||||
d1 = evaluate_data_expression
|
||||
(packet,
|
||||
state -> options.server_options [i] -> expression);
|
||||
if (d1.len && d1.data) {
|
||||
i = DHO_ROUTERS;
|
||||
|
||||
state -> options.dhcp_options [i] =
|
||||
option_cache (make_const_data
|
||||
(lease -> ip_addr.iabuf,
|
||||
lease -> ip_addr.len, 0, 0),
|
||||
dhcp_universe.options [i]);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_PACKET
|
||||
@ -1058,6 +1019,7 @@ void dhcp_reply (lease)
|
||||
int nulltp, bootpp;
|
||||
struct agent_options *a, *na;
|
||||
struct option_tag *ot, *not;
|
||||
struct data_string d1;
|
||||
|
||||
if (!state)
|
||||
error ("dhcp_reply was supplied lease with no state!");
|
||||
@ -1067,16 +1029,28 @@ void dhcp_reply (lease)
|
||||
|
||||
/* Copy in the filename if given; otherwise, flag the filename
|
||||
buffer as available for options. */
|
||||
if (state -> filename)
|
||||
strncpy (raw.file, state -> filename, sizeof raw.file);
|
||||
else
|
||||
if (state -> filename.len && state -> filename.data) {
|
||||
memcpy (raw.file,
|
||||
state -> filename.data,
|
||||
state -> filename.len > sizeof raw.file
|
||||
? sizeof raw.file : state -> filename.len);
|
||||
if (sizeof raw.file > state -> filename.len)
|
||||
memset (&raw.file [state -> filename.len], 0,
|
||||
(sizeof raw.file) - state -> filename.len);
|
||||
} else
|
||||
bufs |= 1;
|
||||
|
||||
/* Copy in the server name if given; otherwise, flag the
|
||||
server_name buffer as available for options. */
|
||||
if (state -> server_name)
|
||||
strncpy (raw.sname, state -> server_name, sizeof raw.sname);
|
||||
else
|
||||
if (state -> server_name.len && state -> server_name.data) {
|
||||
memcpy (raw.sname,
|
||||
state -> server_name.data,
|
||||
state -> server_name.len > sizeof raw.sname
|
||||
? sizeof raw.sname : state -> server_name.len);
|
||||
if (sizeof raw.sname > state -> server_name.len)
|
||||
memset (&raw.sname [state -> server_name.len], 0,
|
||||
(sizeof raw.sname) - state -> server_name.len);
|
||||
} else
|
||||
bufs |= 2; /* XXX */
|
||||
|
||||
memcpy (raw.chaddr, lease -> hardware_addr.haddr, sizeof raw.chaddr);
|
||||
@ -1099,20 +1073,23 @@ void dhcp_reply (lease)
|
||||
/* Insert such options as will fit into the buffer. */
|
||||
packet_length = cons_options ((struct packet *)0, &raw,
|
||||
state -> max_message_size,
|
||||
state -> options,
|
||||
state -> agent_options,
|
||||
&state -> options,
|
||||
bufs, nulltp, bootpp);
|
||||
|
||||
/* Having done the cons_options(), we can release the tree_cache
|
||||
entries. */
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (state -> options [i] &&
|
||||
state -> options [i] -> flags & TC_TEMPORARY)
|
||||
free_tree_cache (state -> options [i], "dhcp_reply");
|
||||
if (state -> options.dhcp_options [i])
|
||||
free_option_cache (state -> options.dhcp_options [i],
|
||||
"dhcp_reply");
|
||||
if (state -> options.server_options [i])
|
||||
free_option_cache (state -> options.dhcp_options [i],
|
||||
"dhcp_reply");
|
||||
|
||||
}
|
||||
|
||||
/* We can also release the agent options, if any... */
|
||||
for (a = state -> agent_options; a; a = na) {
|
||||
for (a = state -> options.agent_options; a; a = na) {
|
||||
na = a -> next;
|
||||
for (ot = a -> first; ot; ot = not) {
|
||||
not = ot -> next;
|
||||
@ -1124,17 +1101,16 @@ void dhcp_reply (lease)
|
||||
memcpy (&raw.yiaddr, lease -> ip_addr.iabuf, 4);
|
||||
|
||||
/* Figure out the address of the next server. */
|
||||
if (lease -> host && lease -> host -> group -> next_server.len)
|
||||
memcpy (&raw.siaddr,
|
||||
lease -> host -> group -> next_server.iabuf, 4);
|
||||
else if (lease -> subnet -> group -> next_server.len)
|
||||
memcpy (&raw.siaddr,
|
||||
lease -> subnet -> group -> next_server.iabuf, 4);
|
||||
else if (lease -> subnet -> interface_address.len)
|
||||
memcpy (&raw.siaddr,
|
||||
lease -> subnet -> interface_address.iabuf, 4);
|
||||
else
|
||||
raw.siaddr = state -> ip -> primary_address;
|
||||
raw.siaddr = state -> ip -> primary_address;
|
||||
if (state -> options.server_options [SV_NEXT_SERVER]) {
|
||||
d1 = evaluate_data_expression
|
||||
((struct packet *)0,
|
||||
(state -> options.
|
||||
server_options [SV_NEXT_SERVER] -> expression));
|
||||
/* If there was more than one answer, take the first. */
|
||||
if (d1.len >= 4 && d1.data)
|
||||
memcpy (&raw.siaddr, d1.data, 4);
|
||||
}
|
||||
|
||||
raw.giaddr = state -> giaddr;
|
||||
|
||||
@ -1346,7 +1322,7 @@ struct lease *find_lease (packet, share, ours)
|
||||
int i = DHO_DHCP_CLIENT_IDENTIFIER;
|
||||
/* If for some reason the client has more than one lease
|
||||
on the subnet that matches its uid, pick the one that
|
||||
it asked for. If we have a host */
|
||||
it asked for. */
|
||||
if (packet -> options [i].data &&
|
||||
ip_lease -> uid_len == packet -> options [i].len &&
|
||||
!memcmp (packet -> options [i].data,
|
||||
@ -1501,17 +1477,8 @@ struct lease *mockup_lease (packet, share, hp)
|
||||
mock.next = mock.prev = (struct lease *)0;
|
||||
mock.shared_network = mock.subnet -> shared_network;
|
||||
mock.host = hp;
|
||||
|
||||
if (hp -> group -> options [DHO_DHCP_CLIENT_IDENTIFIER]) {
|
||||
mock.uid = hp -> group ->
|
||||
options [DHO_DHCP_CLIENT_IDENTIFIER] -> value;
|
||||
mock.uid_len = hp -> group ->
|
||||
options [DHO_DHCP_CLIENT_IDENTIFIER] -> len;
|
||||
} else {
|
||||
mock.uid = (unsigned char *)0;
|
||||
mock.uid_len = 0;
|
||||
}
|
||||
|
||||
mock.uid = hp -> client_identifier.data;
|
||||
mock.uid_len = hp -> client_identifier.len;
|
||||
mock.hardware_addr = hp -> interface;
|
||||
mock.starts = mock.timestamp = mock.ends = MIN_TIME;
|
||||
mock.flags = STATIC_LEASE;
|
||||
|
Loading…
x
Reference in New Issue
Block a user