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

- Support new generalized option_state usage.

- Do vendor encapsulation if configured.
This commit is contained in:
Ted Lemon
1999-04-05 16:46:13 +00:00
parent 822d95c9df
commit 951323fef5

View File

@@ -22,7 +22,7 @@
#ifndef lint #ifndef lint
static char copyright[] = static char copyright[] =
"$Id: dhcp.c,v 1.84 1999/03/25 22:07:54 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n"; "$Id: dhcp.c,v 1.85 1999/04/05 16:46:13 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */ #endif /* not lint */
#include "dhcpd.h" #include "dhcpd.h"
@@ -118,11 +118,11 @@ void dhcprequest (packet)
int status; int status;
char msgbuf [1024]; char msgbuf [1024];
oc = lookup_option (packet -> options.dhcp_hash, oc = lookup_option (&dhcp_universe, packet -> options,
DHO_DHCP_REQUESTED_ADDRESS); DHO_DHCP_REQUESTED_ADDRESS);
memset (&data, 0, sizeof data); memset (&data, 0, sizeof data);
if (oc && if (oc &&
evaluate_option_cache (&data, packet, &packet -> options, oc)) { evaluate_option_cache (&data, packet, packet -> options, oc)) {
cip.len = 4; cip.len = 4;
memcpy (cip.iabuf, data.data, 4); memcpy (cip.iabuf, data.data, 4);
data_string_forget (&data, "dhcprequest"); data_string_forget (&data, "dhcprequest");
@@ -254,7 +254,7 @@ void dhcprelease (packet)
/* DHCPRELEASE must not specify address in requested-address /* DHCPRELEASE must not specify address in requested-address
option, but old protocol specs weren't explicit about this, option, but old protocol specs weren't explicit about this,
so let it go. */ so let it go. */
if ((oc = lookup_option (packet -> options.dhcp_hash, if ((oc = lookup_option (&dhcp_universe, packet -> options,
DHO_DHCP_REQUESTED_ADDRESS))) { DHO_DHCP_REQUESTED_ADDRESS))) {
log_info ("DHCPRELEASE from %s specified requested-address.", log_info ("DHCPRELEASE from %s specified requested-address.",
print_hw_addr (packet -> raw -> htype, print_hw_addr (packet -> raw -> htype,
@@ -262,11 +262,11 @@ void dhcprelease (packet)
packet -> raw -> chaddr)); packet -> raw -> chaddr));
} }
oc = lookup_option (packet -> options.dhcp_hash, oc = lookup_option (&dhcp_universe, packet -> options,
DHO_DHCP_CLIENT_IDENTIFIER); DHO_DHCP_CLIENT_IDENTIFIER);
memset (&data, 0, sizeof data); memset (&data, 0, sizeof data);
if (oc && if (oc &&
evaluate_option_cache (&data, packet, &packet -> options, oc)) { evaluate_option_cache (&data, packet, packet -> options, oc)) {
lease = find_lease_by_uid (data.data, data.len); lease = find_lease_by_uid (data.data, data.len);
data_string_forget (&data, "dhcprelease"); data_string_forget (&data, "dhcprelease");
} else } else
@@ -307,11 +307,11 @@ void dhcpdecline (packet)
struct data_string data; struct data_string data;
/* DHCPDECLINE must specify address. */ /* DHCPDECLINE must specify address. */
if (!(oc = lookup_option (packet -> options.dhcp_hash, if (!(oc = lookup_option (&dhcp_universe, packet -> options,
DHO_DHCP_REQUESTED_ADDRESS))) DHO_DHCP_REQUESTED_ADDRESS)))
return; return;
memset (&data, 0, sizeof data); memset (&data, 0, sizeof data);
if (!evaluate_option_cache (&data, packet, &packet -> options, oc)) if (!evaluate_option_cache (&data, packet, packet -> options, oc))
return; return;
cip.len = 4; cip.len = 4;
@@ -354,11 +354,11 @@ void nak_lease (packet, cip)
struct hardware hto; struct hardware hto;
int i; int i;
struct data_string data; struct data_string data;
struct option_state options; struct option_state *options = (struct option_state *)0;
struct expression *expr; struct expression *expr;
struct option_cache *oc = (struct option_cache *)0; struct option_cache *oc = (struct option_cache *)0;
memset (&options, 0, sizeof options); option_state_allocate (&options, "nak_lease");
memset (&outgoing, 0, sizeof outgoing); memset (&outgoing, 0, sizeof outgoing);
memset (&raw, 0, sizeof raw); memset (&raw, 0, sizeof raw);
outgoing.raw = &raw; outgoing.raw = &raw;
@@ -366,20 +366,23 @@ void nak_lease (packet, cip)
/* Set DHCP_MESSAGE_TYPE to DHCPNAK */ /* Set DHCP_MESSAGE_TYPE to DHCPNAK */
if (!option_cache_allocate (&oc, "nak_lease")) { if (!option_cache_allocate (&oc, "nak_lease")) {
log_error ("No memory for DHCPNAK message type."); log_error ("No memory for DHCPNAK message type.");
option_state_dereference (&options, "nak_lease");
return; return;
} }
if (!make_const_data (&oc -> expression, &nak, sizeof nak, 0, 0)) { if (!make_const_data (&oc -> expression, &nak, sizeof nak, 0, 0)) {
log_error ("No memory for expr_const expression."); log_error ("No memory for expr_const expression.");
option_cache_dereference (&oc, "nak_lease"); option_cache_dereference (&oc, "nak_lease");
option_state_dereference (&options, "nak_lease");
return; return;
} }
oc -> option = dhcp_universe.options [DHO_DHCP_MESSAGE_TYPE]; oc -> option = dhcp_universe.options [DHO_DHCP_MESSAGE_TYPE];
save_option (options.dhcp_hash, oc); save_option (&dhcp_universe, options, oc);
option_cache_dereference (&oc, "nak_lease"); option_cache_dereference (&oc, "nak_lease");
/* Set DHCP_MESSAGE to whatever the message is */ /* Set DHCP_MESSAGE to whatever the message is */
if (!option_cache_allocate (&oc, "nak_lease")) { if (!option_cache_allocate (&oc, "nak_lease")) {
log_error ("No memory for DHCPNAK message type."); log_error ("No memory for DHCPNAK message type.");
option_state_dereference (&options, "nak_lease");
return; return;
} }
if (!make_const_data (&oc -> expression, if (!make_const_data (&oc -> expression,
@@ -387,21 +390,23 @@ void nak_lease (packet, cip)
strlen (dhcp_message), 1, 0)) { strlen (dhcp_message), 1, 0)) {
log_error ("No memory for expr_const expression."); log_error ("No memory for expr_const expression.");
option_cache_dereference (&oc, "nak_lease"); option_cache_dereference (&oc, "nak_lease");
option_state_dereference (&options, "nak_lease");
return; return;
} }
oc -> option = dhcp_universe.options [DHO_DHCP_MESSAGE]; oc -> option = dhcp_universe.options [DHO_DHCP_MESSAGE];
save_option (options.dhcp_hash, oc); save_option (&dhcp_universe, options, oc);
option_cache_dereference (&oc, "nak_lease"); option_cache_dereference (&oc, "nak_lease");
/* Do not use the client's requested parameter list. */ /* Do not use the client's requested parameter list. */
delete_option (packet -> options.dhcp_hash, delete_option (&dhcp_universe, packet -> options,
DHO_DHCP_PARAMETER_REQUEST_LIST); DHO_DHCP_PARAMETER_REQUEST_LIST);
/* Set up the option buffer... */ /* Set up the option buffer... */
outgoing.packet_length = outgoing.packet_length =
cons_options (packet, outgoing.raw, 0, &options, cons_options (packet, outgoing.raw, 0, options,
packet -> agent_options, 0, 0, 0, 0, 0, 0,
(struct data_string *)0); (struct data_string *)0);
option_state_dereference (&options, "nak_lease");
/* memset (&raw.ciaddr, 0, sizeof raw.ciaddr);*/ /* memset (&raw.ciaddr, 0, sizeof raw.ciaddr);*/
raw.siaddr = packet -> interface -> primary_address; raw.siaddr = packet -> interface -> primary_address;
@@ -508,14 +513,13 @@ void ack_lease (packet, lease, offer, when, msg)
state = new_lease_state ("ack_lease"); state = new_lease_state ("ack_lease");
if (!state) if (!state)
log_fatal ("unable to allocate lease state!"); log_fatal ("unable to allocate lease state!");
memset (state, 0, sizeof *state);
/* Replace the old lease hostname with the new one, if it's changed. */ /* Replace the old lease hostname with the new one, if it's changed. */
oc = lookup_option (packet -> options.dhcp_hash, DHO_HOST_NAME); oc = lookup_option (&dhcp_universe, packet -> options, DHO_HOST_NAME);
memset (&d1, 0, sizeof d1); memset (&d1, 0, sizeof d1);
if (oc) if (oc)
s1 = evaluate_option_cache (&d1, packet, s1 = evaluate_option_cache (&d1, packet,
&packet -> options, oc); packet -> options, oc);
if (oc && status && if (oc && status &&
lease -> client_hostname && lease -> client_hostname &&
strlen (lease -> client_hostname) == d1.len && strlen (lease -> client_hostname) == d1.len &&
@@ -539,20 +543,17 @@ void ack_lease (packet, lease, offer, when, msg)
lease -> client_hostname = 0; lease -> client_hostname = 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. */ /* Steal the agent options from the packet. */
if (packet -> options.agent_options) { if (packet -> options -> universes [agent_universe.index]) {
state -> options.agent_options = state -> options -> universes [agent_universe.index] =
packet -> options.agent_options; packet -> options -> universes [agent_universe.index];
packet -> options.agent_options = (struct agent_options *)0; packet -> options -> universes [agent_universe.index] =
(struct agent_options *)0;
} }
/* Execute statements in scope starting with the pool group. */ /* Execute statements in scope starting with the pool group. */
execute_statements_in_scope (packet, &state -> options, execute_statements_in_scope (packet, state -> options,
&state -> options, state -> options,
lease -> subnet -> group, lease -> subnet -> group,
(struct group *)0); (struct group *)0);
@@ -560,8 +561,8 @@ void ack_lease (packet, lease, offer, when, msg)
if (offer) { if (offer) {
for (i = packet -> class_count; i > 0; i--) { for (i = packet -> class_count; i > 0; i--) {
execute_statements_in_scope execute_statements_in_scope
(packet, &state -> options, (packet, state -> options,
&state -> options, state -> options,
packet -> classes [i - 1] -> group, packet -> classes [i - 1] -> group,
(lease -> pool (lease -> pool
? lease -> pool -> group ? lease -> pool -> group
@@ -571,16 +572,16 @@ void ack_lease (packet, lease, offer, when, msg)
/* If the lease is from a pool, run the pool scope. */ /* If the lease is from a pool, run the pool scope. */
if (lease -> pool) if (lease -> pool)
execute_statements_in_scope (packet, &state -> options, execute_statements_in_scope (packet, state -> options,
&state -> options, state -> options,
lease -> pool -> group, lease -> pool -> group,
lease -> subnet -> group); lease -> subnet -> group);
/* If we have a host_decl structure, run the options associated /* If we have a host_decl structure, run the options associated
with its group. */ with its group. */
if (lease -> host) if (lease -> host)
execute_statements_in_scope (packet, &state -> options, execute_statements_in_scope (packet, state -> options,
&state -> options, state -> options,
lease -> host -> group, lease -> host -> group,
(lease -> pool (lease -> pool
? lease -> pool -> group ? lease -> pool -> group
@@ -589,14 +590,15 @@ void ack_lease (packet, lease, offer, when, msg)
/* Make sure this packet satisfies the configured minimum /* Make sure this packet satisfies the configured minimum
number of seconds. */ number of seconds. */
if (offer == DHCPOFFER && if (offer == DHCPOFFER &&
(oc = lookup_option (state -> options.server_hash, (oc = lookup_option (&server_universe, state -> options,
SV_MIN_SECS))) { SV_MIN_SECS))) {
if (evaluate_option_cache (&d1, packet, if (evaluate_option_cache (&d1, packet,
&packet -> options, oc)) { packet -> options, oc)) {
if (d1.len && packet -> raw -> secs < d1.data [0]) { if (d1.len && packet -> raw -> secs < d1.data [0]) {
data_string_forget (&d1, "ack_lease"); data_string_forget (&d1, "ack_lease");
log_info ("%s: %d secs < %d", log_info ("%s: %d secs < %d",
packet -> raw -> secs, d1.data [0]); packet -> raw -> secs, d1.data [0]);
free_lease_state (state, "ack_lease");
return; return;
} }
data_string_forget (&d1, "ack_lease"); data_string_forget (&d1, "ack_lease");
@@ -612,11 +614,11 @@ void ack_lease (packet, lease, offer, when, msg)
has no fixed IP address. If there is one, hang has no fixed IP address. If there is one, hang
it off the lease so that its option definitions it off the lease so that its option definitions
can be used. */ can be used. */
oc = lookup_option (packet -> options.dhcp_hash, oc = lookup_option (&dhcp_universe, packet -> options,
DHO_DHCP_CLIENT_IDENTIFIER); DHO_DHCP_CLIENT_IDENTIFIER);
if (oc && if (oc &&
evaluate_option_cache (&d1, packet, evaluate_option_cache (&d1, packet,
&packet -> options, oc)) { packet -> options, oc)) {
hp = find_hosts_by_uid (d1.data, d1.len); hp = find_hosts_by_uid (d1.data, d1.len);
data_string_forget (&d1, "dhcpdiscover"); data_string_forget (&d1, "dhcpdiscover");
if (!hp) if (!hp)
@@ -635,13 +637,14 @@ void ack_lease (packet, lease, offer, when, msg)
/* Drop the request if it's not allowed for this client. */ /* Drop the request if it's not allowed for this client. */
if (!lease -> host && if (!lease -> host &&
(oc = lookup_option (state -> options.server_hash, (oc = lookup_option (&server_universe, state -> options,
SV_BOOT_UNKNOWN_CLIENTS))) { SV_BOOT_UNKNOWN_CLIENTS))) {
if (evaluate_option_cache (&d1, packet, if (evaluate_option_cache (&d1, packet,
&packet -> options, oc)) { packet -> options, oc)) {
if (d1.len && !d1.data [0]) { if (d1.len && !d1.data [0]) {
log_info ("%s: unknown", msg); log_info ("%s: unknown", msg);
data_string_forget (&d1, "ack_lease"); data_string_forget (&d1, "ack_lease");
free_lease_state (state, "ack_lease");
return; return;
} }
data_string_forget (&d1, "ack_lease"); /* mmm, C... */ data_string_forget (&d1, "ack_lease"); /* mmm, C... */
@@ -650,13 +653,14 @@ void ack_lease (packet, lease, offer, when, msg)
/* Drop the request if it's not allowed for this client. */ /* Drop the request if it's not allowed for this client. */
if (!offer && if (!offer &&
(oc = lookup_option (state -> options.server_hash, (oc = lookup_option (&server_universe, state -> options,
SV_ALLOW_BOOTP))) { SV_ALLOW_BOOTP))) {
if (evaluate_option_cache (&d1, packet, if (evaluate_option_cache (&d1, packet,
&packet -> options, oc)) { packet -> options, oc)) {
if (d1.len && !d1.data [0]) { if (d1.len && !d1.data [0]) {
data_string_forget (&d1, "ack_lease"); data_string_forget (&d1, "ack_lease");
log_info ("%s: bootp disallowed", msg); log_info ("%s: bootp disallowed", msg);
free_lease_state (state, "ack_lease");
return; return;
} }
data_string_forget (&d1, "ack_lease"); data_string_forget (&d1, "ack_lease");
@@ -664,12 +668,14 @@ void ack_lease (packet, lease, offer, when, msg)
} }
/* Drop the request if booting is specifically denied. */ /* Drop the request if booting is specifically denied. */
oc = lookup_option (state -> options.server_hash, SV_ALLOW_BOOTING); oc = lookup_option (&server_universe, state -> options,
SV_ALLOW_BOOTING);
if (oc && if (oc &&
evaluate_option_cache (&d1, packet, &packet -> options, oc)) { evaluate_option_cache (&d1, packet, packet -> options, oc)) {
if (d1.len && !d1.data [0]) { if (d1.len && !d1.data [0]) {
log_info ("%s: booting disallowed", msg); log_info ("%s: booting disallowed", msg);
data_string_forget (&d1, "ack_lease"); data_string_forget (&d1, "ack_lease");
free_lease_state (state, "ack_lease");
return; return;
} }
data_string_forget (&d1, "ack_lease"); data_string_forget (&d1, "ack_lease");
@@ -705,6 +711,7 @@ void ack_lease (packet, lease, offer, when, msg)
if (i == packet -> class_count) { if (i == packet -> class_count) {
log_info ("%s: no available billing", log_info ("%s: no available billing",
msg); msg);
free_lease_state (state, "ack_lease");
return; return;
} }
} }
@@ -712,16 +719,17 @@ void ack_lease (packet, lease, offer, when, msg)
} }
/* Figure out the filename. */ /* Figure out the filename. */
oc = lookup_option (state -> options.server_hash, SV_FILENAME); oc = lookup_option (&server_universe, state -> options, SV_FILENAME);
if (oc) if (oc)
evaluate_option_cache (&state -> filename, evaluate_option_cache (&state -> filename,
packet, &packet -> options, oc); packet, packet -> options, oc);
/* Choose a server name as above. */ /* Choose a server name as above. */
oc = lookup_option (state -> options.server_hash, SV_SERVER_NAME); oc = lookup_option (&server_universe, state -> options,
SV_SERVER_NAME);
if (oc) if (oc)
evaluate_option_cache (&state -> server_name, packet, evaluate_option_cache (&state -> server_name, packet,
&packet -> options, oc); packet -> options, oc);
/* At this point, we have a lease that we can offer the client. /* At this point, we have a lease that we can offer the client.
Now we construct a lease structure that contains what we want, Now we construct a lease structure that contains what we want,
@@ -739,10 +747,10 @@ void ack_lease (packet, lease, offer, when, msg)
dynamic BOOTP lease, its duration must be infinite. */ dynamic BOOTP lease, its duration must be infinite. */
if (offer) { if (offer) {
default_lease_time = DEFAULT_DEFAULT_LEASE_TIME; default_lease_time = DEFAULT_DEFAULT_LEASE_TIME;
if ((oc = lookup_option (state -> options.server_hash, if ((oc = lookup_option (&server_universe, state -> options,
SV_DEFAULT_LEASE_TIME))) { SV_DEFAULT_LEASE_TIME))) {
if (evaluate_option_cache (&d1, packet, if (evaluate_option_cache (&d1, packet,
&packet -> options, oc)) { packet -> options, oc)) {
if (d1.len == sizeof (u_int32_t)) if (d1.len == sizeof (u_int32_t))
default_lease_time = default_lease_time =
getULong (d1.data); getULong (d1.data);
@@ -750,20 +758,21 @@ void ack_lease (packet, lease, offer, when, msg)
} }
} }
if ((oc = lookup_option (packet -> options.dhcp_hash, if ((oc = lookup_option (&dhcp_universe, packet -> options,
DHO_DHCP_LEASE_TIME))) DHO_DHCP_LEASE_TIME)))
s1 = evaluate_option_cache (&d1, packet, s1 = evaluate_option_cache (&d1, packet,
&packet -> options, oc); packet -> options, oc);
else else
s1 = 0; s1 = 0;
if (s1 && d1.len == sizeof (u_int32_t)) { if (s1 && d1.len == sizeof (u_int32_t)) {
lease_time = getULong (d1.data); lease_time = getULong (d1.data);
data_string_forget (&d1, "ack_lease"); data_string_forget (&d1, "ack_lease");
max_lease_time = DEFAULT_MAX_LEASE_TIME; max_lease_time = DEFAULT_MAX_LEASE_TIME;
if ((oc = lookup_option (state -> options.server_hash, if ((oc = lookup_option (&server_universe,
state -> options,
SV_MAX_LEASE_TIME))) { SV_MAX_LEASE_TIME))) {
if (evaluate_option_cache (&d1, packet, if (evaluate_option_cache (&d1, packet,
&packet -> options, packet -> options,
oc)) { oc)) {
if (d1.len == sizeof (u_int32_t)) if (d1.len == sizeof (u_int32_t))
max_lease_time = max_lease_time =
@@ -782,10 +791,10 @@ void ack_lease (packet, lease, offer, when, msg)
} }
min_lease_time = DEFAULT_MIN_LEASE_TIME; min_lease_time = DEFAULT_MIN_LEASE_TIME;
if ((oc = lookup_option (state -> options.server_hash, if ((oc = lookup_option (&server_universe, state -> options,
SV_MIN_LEASE_TIME))) { SV_MIN_LEASE_TIME))) {
if (evaluate_option_cache (&d1, packet, if (evaluate_option_cache (&d1, packet,
&packet -> options, oc)) { packet -> options, oc)) {
if (d1.len == sizeof (u_int32_t)) if (d1.len == sizeof (u_int32_t))
min_lease_time = getULong (d1.data); min_lease_time = getULong (d1.data);
data_string_forget (&d1, "ack_lease"); data_string_forget (&d1, "ack_lease");
@@ -807,20 +816,20 @@ void ack_lease (packet, lease, offer, when, msg)
} else { } else {
lease_time = MAX_TIME - cur_time; lease_time = MAX_TIME - cur_time;
if ((oc = lookup_option (state -> options.server_hash, if ((oc = lookup_option (&server_universe, state -> options,
SV_BOOTP_LEASE_LENGTH))) { SV_BOOTP_LEASE_LENGTH))) {
if (evaluate_option_cache (&d1, packet, if (evaluate_option_cache (&d1, packet,
&packet -> options, oc)) { packet -> options, oc)) {
if (d1.len == sizeof (u_int32_t)) if (d1.len == sizeof (u_int32_t))
lease_time = getULong (d1.data); lease_time = getULong (d1.data);
data_string_forget (&d1, "ack_lease"); data_string_forget (&d1, "ack_lease");
} }
} }
if ((oc = lookup_option (state -> options.server_hash, if ((oc = lookup_option (&server_universe, state -> options,
SV_BOOTP_LEASE_CUTOFF))) { SV_BOOTP_LEASE_CUTOFF))) {
if (evaluate_option_cache (&d1, packet, if (evaluate_option_cache (&d1, packet,
&packet -> options, oc)) { packet -> options, oc)) {
if (d1.len == sizeof (u_int32_t)) if (d1.len == sizeof (u_int32_t))
lease_time = (getULong (d1.data) - lease_time = (getULong (d1.data) -
cur_time); cur_time);
@@ -835,10 +844,10 @@ void ack_lease (packet, lease, offer, when, msg)
lt.timestamp = cur_time; lt.timestamp = cur_time;
/* Record the uid, if given... */ /* Record the uid, if given... */
oc = lookup_option (packet -> options.dhcp_hash, oc = lookup_option (&dhcp_universe, packet -> options,
DHO_DHCP_CLIENT_IDENTIFIER); DHO_DHCP_CLIENT_IDENTIFIER);
if (oc && if (oc &&
evaluate_option_cache (&d1, packet, &packet -> options, oc)) { evaluate_option_cache (&d1, packet, packet -> options, oc)) {
if (d1.len <= sizeof lt.uid_buf) { if (d1.len <= sizeof lt.uid_buf) {
memcpy (lt.uid_buf, d1.data, d1.len); memcpy (lt.uid_buf, d1.data, d1.len);
lt.uid = lt.uid_buf; lt.uid = lt.uid_buf;
@@ -851,7 +860,7 @@ void ack_lease (packet, lease, offer, when, msg)
"ack_lease"); "ack_lease");
/* XXX inelegant */ /* XXX inelegant */
if (!lt.uid) if (!lt.uid)
log_fatal ("can't allocate memory for large uid."); log_fatal ("no memory for large uid.");
memcpy (lt.uid, d1.data, lt.uid_len); memcpy (lt.uid, d1.data, lt.uid_len);
} }
data_string_forget (&d1, "ack_lease"); data_string_forget (&d1, "ack_lease");
@@ -884,6 +893,7 @@ void ack_lease (packet, lease, offer, when, msg)
if (!(supersede_lease (lease, &lt, !offer || offer == DHCPACK) if (!(supersede_lease (lease, &lt, !offer || offer == DHCPACK)
|| (offer && offer != DHCPACK))) { || (offer && offer != DHCPACK))) {
log_info ("%s: database update failed", msg); log_info ("%s: database update failed", msg);
free_lease_state (state, "ack_lease");
return; return;
} }
} }
@@ -894,10 +904,10 @@ void ack_lease (packet, lease, offer, when, msg)
/* Set a flag if this client is a lame Microsoft client that NUL /* Set a flag if this client is a lame Microsoft client that NUL
terminates string options and expects us to do likewise. */ terminates string options and expects us to do likewise. */
lease -> flags &= ~MS_NULL_TERMINATION; lease -> flags &= ~MS_NULL_TERMINATION;
if ((oc = lookup_option (packet -> options.dhcp_hash, if ((oc = lookup_option (&dhcp_universe, packet -> options,
DHO_HOST_NAME))) { DHO_HOST_NAME))) {
if (evaluate_option_cache (&d1, packet, if (evaluate_option_cache (&d1, packet,
&packet -> options, oc)) { packet -> options, oc)) {
if (d1.data [d1.len - 1] == '\0') if (d1.data [d1.len - 1] == '\0')
lease -> flags |= MS_NULL_TERMINATION; lease -> flags |= MS_NULL_TERMINATION;
data_string_forget (&d1, "ack_lease"); data_string_forget (&d1, "ack_lease");
@@ -915,21 +925,15 @@ void ack_lease (packet, lease, offer, when, msg)
/* Get the Maximum Message Size option from the packet, if one /* Get the Maximum Message Size option from the packet, if one
was sent. */ was sent. */
oc = lookup_option (packet -> options.dhcp_hash, oc = lookup_option (&dhcp_universe, packet -> options,
DHO_DHCP_MAX_MESSAGE_SIZE); DHO_DHCP_MAX_MESSAGE_SIZE);
if (oc && if (oc &&
evaluate_option_cache (&d1, packet, &packet -> options, oc)) { evaluate_option_cache (&d1, packet, packet -> options, oc)) {
if (d1.len == sizeof (u_int16_t)) if (d1.len == sizeof (u_int16_t))
state -> max_message_size = getUShort (d1.data); state -> max_message_size = getUShort (d1.data);
data_string_forget (&d1, "ack_lease"); data_string_forget (&d1, "ack_lease");
} }
/* Steal the agent options from the packet. */
if (packet -> agent_options) {
state -> agent_options = packet -> agent_options;
packet -> agent_options = (struct agent_options *)0;
}
/* Now, if appropriate, put in DHCP-specific options that /* Now, if appropriate, put in DHCP-specific options that
override those. */ override those. */
if (state -> offer) { if (state -> offer) {
@@ -941,12 +945,14 @@ void ack_lease (packet, lease, offer, when, msg)
option_tag_size, 0, 0)) { option_tag_size, 0, 0)) {
oc -> option = oc -> option =
dhcp_universe.options [i]; dhcp_universe.options [i];
save_option (state -> options.dhcp_hash, oc); save_option (&dhcp_universe,
state -> options, oc);
} }
option_cache_dereference (&oc, "ack_lease"); option_cache_dereference (&oc, "ack_lease");
} }
i = DHO_DHCP_SERVER_IDENTIFIER; i = DHO_DHCP_SERVER_IDENTIFIER;
if (!(oc = lookup_option (state -> options.dhcp_hash, i))) { if (!(oc = lookup_option (&dhcp_universe,
state -> options, i))) {
use_primary: use_primary:
oc = (struct option_cache *)0; oc = (struct option_cache *)0;
if (option_cache_allocate (&oc, "ack_lease")) { if (option_cache_allocate (&oc, "ack_lease")) {
@@ -958,9 +964,8 @@ void ack_lease (packet, lease, offer, when, msg)
0, 0)) { 0, 0)) {
oc -> option = oc -> option =
dhcp_universe.options [i]; dhcp_universe.options [i];
save_option save_option (&dhcp_universe,
(state -> options.dhcp_hash, state -> options, oc);
oc);
} }
option_cache_dereference (&oc, "ack_lease"); option_cache_dereference (&oc, "ack_lease");
} }
@@ -971,7 +976,7 @@ void ack_lease (packet, lease, offer, when, msg)
state -> from.len); state -> from.len);
} else { } else {
if (evaluate_option_cache (&d1, packet, if (evaluate_option_cache (&d1, packet,
&packet -> options, oc)) { packet -> options, oc)) {
if (!d1.len || if (!d1.len ||
d1.len > sizeof state -> from.iabuf) d1.len > sizeof state -> from.iabuf)
goto use_primary; goto use_primary;
@@ -988,7 +993,7 @@ void ack_lease (packet, lease, offer, when, msg)
putULong ((unsigned char *)&state -> expiry, putULong ((unsigned char *)&state -> expiry,
offered_lease_time); offered_lease_time);
i = DHO_DHCP_LEASE_TIME; i = DHO_DHCP_LEASE_TIME;
if (lookup_option (state -> options.dhcp_hash, i)) if (lookup_option (&dhcp_universe, state -> options, i))
log_error ("dhcp-lease-time option for %s overridden.", log_error ("dhcp-lease-time option for %s overridden.",
inet_ntoa (state -> ciaddr)); inet_ntoa (state -> ciaddr));
oc = (struct option_cache *)0; oc = (struct option_cache *)0;
@@ -997,7 +1002,8 @@ void ack_lease (packet, lease, offer, when, msg)
(unsigned char *)&state -> expiry, (unsigned char *)&state -> expiry,
sizeof state -> expiry, 0, 0)) { sizeof state -> expiry, 0, 0)) {
oc -> option = dhcp_universe.options [i]; oc -> option = dhcp_universe.options [i];
save_option (state -> options.dhcp_hash, oc); save_option (&dhcp_universe,
state -> options, oc);
} }
option_cache_dereference (&oc, "ack_lease"); option_cache_dereference (&oc, "ack_lease");
} }
@@ -1007,9 +1013,9 @@ void ack_lease (packet, lease, offer, when, msg)
putULong ((unsigned char *)&state -> renewal, putULong ((unsigned char *)&state -> renewal,
offered_lease_time); offered_lease_time);
i = DHO_DHCP_RENEWAL_TIME; i = DHO_DHCP_RENEWAL_TIME;
if (lookup_option (state -> options.dhcp_hash, i)) if (lookup_option (&dhcp_universe, state -> options, i))
log_error ("dhcp-renewal-time option for %s overridden.", log_error ("overriding dhcp-renewal-time for %s.",
inet_ntoa (state -> ciaddr)); inet_ntoa (state -> ciaddr));
oc = (struct option_cache *)0; oc = (struct option_cache *)0;
if (option_cache_allocate (&oc, "ack_lease")) { if (option_cache_allocate (&oc, "ack_lease")) {
if (make_const_data (&oc -> expression, if (make_const_data (&oc -> expression,
@@ -1017,7 +1023,8 @@ void ack_lease (packet, lease, offer, when, msg)
&state -> renewal, &state -> renewal,
sizeof state -> renewal, 0, 0)) { sizeof state -> renewal, 0, 0)) {
oc -> option = dhcp_universe.options [i]; oc -> option = dhcp_universe.options [i];
save_option (state -> options.dhcp_hash, oc); save_option (&dhcp_universe,
state -> options, oc);
} }
option_cache_dereference (&oc, "ack_lease"); option_cache_dereference (&oc, "ack_lease");
} }
@@ -1028,8 +1035,8 @@ void ack_lease (packet, lease, offer, when, msg)
putULong ((unsigned char *)&state -> rebind, putULong ((unsigned char *)&state -> rebind,
offered_lease_time); offered_lease_time);
i = DHO_DHCP_REBINDING_TIME; i = DHO_DHCP_REBINDING_TIME;
if (lookup_option (state -> options.dhcp_hash, i)) if (lookup_option (&dhcp_universe, state -> options, i))
log_error ("dhcp-rebinding-time option for %s overridden.", log_error ("overriding dhcp-rebinding-time for %s.",
inet_ntoa (state -> ciaddr)); inet_ntoa (state -> ciaddr));
oc = (struct option_cache *)0; oc = (struct option_cache *)0;
if (option_cache_allocate (&oc, "ack_lease")) { if (option_cache_allocate (&oc, "ack_lease")) {
@@ -1037,7 +1044,8 @@ void ack_lease (packet, lease, offer, when, msg)
(unsigned char *)&state -> rebind, (unsigned char *)&state -> rebind,
sizeof state -> rebind, 0, 0)) { sizeof state -> rebind, 0, 0)) {
oc -> option = dhcp_universe.options [i]; oc -> option = dhcp_universe.options [i];
save_option (state -> options.dhcp_hash, oc); save_option (&dhcp_universe,
state -> options, oc);
} }
option_cache_dereference (&oc, "ack_lease"); option_cache_dereference (&oc, "ack_lease");
} }
@@ -1046,14 +1054,15 @@ void ack_lease (packet, lease, offer, when, msg)
/* Use the subnet mask from the subnet declaration if no other /* Use the subnet mask from the subnet declaration if no other
mask has been provided. */ mask has been provided. */
i = DHO_SUBNET_MASK; i = DHO_SUBNET_MASK;
if (!lookup_option (state -> options.dhcp_hash, i)) { if (!lookup_option (&dhcp_universe, state -> options, i)) {
if (option_cache_allocate (&oc, "ack_lease")) { if (option_cache_allocate (&oc, "ack_lease")) {
if (make_const_data (&oc -> expression, if (make_const_data (&oc -> expression,
lease -> subnet -> netmask.iabuf, lease -> subnet -> netmask.iabuf,
lease -> subnet -> netmask.len, lease -> subnet -> netmask.len,
0, 0)) { 0, 0)) {
oc -> option = dhcp_universe.options [i]; oc -> option = dhcp_universe.options [i];
save_option (state -> options.dhcp_hash, oc); save_option (&dhcp_universe,
state -> options, oc);
} }
option_cache_dereference (&oc, "ack_lease"); option_cache_dereference (&oc, "ack_lease");
} }
@@ -1064,12 +1073,12 @@ void ack_lease (packet, lease, offer, when, msg)
use-host-decl-name flag is set. */ use-host-decl-name flag is set. */
i = DHO_HOST_NAME; i = DHO_HOST_NAME;
j = SV_USE_HOST_DECL_NAMES; j = SV_USE_HOST_DECL_NAMES;
if (!lookup_option (state -> options.dhcp_hash, i) && if (!lookup_option (&dhcp_universe, state -> options, i) &&
lease -> host && lease -> host -> name && lease -> host && lease -> host -> name &&
(evaluate_boolean_option_cache (evaluate_boolean_option_cache
(packet, &packet -> options, (packet, packet -> options,
(lookup_option (lookup_option
(state -> options.server_hash, j))))) { (&server_universe, state -> options, j))))) {
oc = (struct option_cache *)0; oc = (struct option_cache *)0;
if (option_cache_allocate (&oc, "ack_lease")) { if (option_cache_allocate (&oc, "ack_lease")) {
if (make_const_data (&oc -> expression, if (make_const_data (&oc -> expression,
@@ -1078,7 +1087,8 @@ void ack_lease (packet, lease, offer, when, msg)
strlen (lease -> host -> name), strlen (lease -> host -> name),
1, 0)) { 1, 0)) {
oc -> option = dhcp_universe.options [i]; oc -> option = dhcp_universe.options [i];
save_option (state -> options.dhcp_hash, oc); save_option (&dhcp_universe,
state -> options, oc);
} }
option_cache_dereference (&oc, "ack_lease"); option_cache_dereference (&oc, "ack_lease");
} }
@@ -1087,10 +1097,10 @@ void ack_lease (packet, lease, offer, when, msg)
/* If we don't have a hostname yet, and we've been asked to do /* If we don't have a hostname yet, and we've been asked to do
a reverse lookup to find the hostname, do it. */ a reverse lookup to find the hostname, do it. */
j = SV_GET_LEASE_HOSTNAMES; j = SV_GET_LEASE_HOSTNAMES;
if (!lookup_option (state -> options.dhcp_hash, i) && if (!lookup_option (&dhcp_universe, state -> options, i) &&
(evaluate_boolean_option_cache (evaluate_boolean_option_cache
(packet, &packet -> options, (packet, packet -> options,
lookup_option (state -> options.server_hash, j)))) { lookup_option (&server_universe, state -> options, j)))) {
struct in_addr ia; struct in_addr ia;
struct hostent *h; struct hostent *h;
@@ -1109,9 +1119,8 @@ void ack_lease (packet, lease, offer, when, msg)
1, 1)) { 1, 1)) {
oc -> option = oc -> option =
dhcp_universe.options [i]; dhcp_universe.options [i];
save_option save_option (&dhcp_universe,
(state -> options.dhcp_hash, state -> options, oc);
oc);
} }
option_cache_dereference (&oc, "ack_lease"); option_cache_dereference (&oc, "ack_lease");
} }
@@ -1123,11 +1132,11 @@ void ack_lease (packet, lease, offer, when, msg)
so if the local router does proxy arp, you win. */ so if the local router does proxy arp, you win. */
if (evaluate_boolean_option_cache if (evaluate_boolean_option_cache
(packet, &state -> options, (packet, state -> options,
lookup_option (state -> options.server_hash, lookup_option (&server_universe, state -> options,
SV_USE_LEASE_ADDR_FOR_DEFAULT_ROUTE))) { SV_USE_LEASE_ADDR_FOR_DEFAULT_ROUTE))) {
i = DHO_ROUTERS; i = DHO_ROUTERS;
oc = lookup_option (state -> options.dhcp_hash, i); oc = lookup_option (&dhcp_universe, state -> options, i);
if (!oc) { if (!oc) {
oc = (struct option_cache *)0; oc = (struct option_cache *)0;
if (option_cache_allocate (&oc, "ack_lease")) { if (option_cache_allocate (&oc, "ack_lease")) {
@@ -1137,9 +1146,8 @@ void ack_lease (packet, lease, offer, when, msg)
0, 0)) { 0, 0)) {
oc -> option = oc -> option =
dhcp_universe.options [i]; dhcp_universe.options [i];
save_option save_option (&dhcp_universe,
(state -> options.dhcp_hash, state -> options, oc);
oc);
} }
} }
} }
@@ -1147,16 +1155,37 @@ void ack_lease (packet, lease, offer, when, msg)
option_cache_dereference (&oc, "ack_lease"); option_cache_dereference (&oc, "ack_lease");
} }
/* If we've been given a vendor option space, and there's something
in it, and we weren't given a vendor-encapsulated-options option,
then cons one up. */
i = DHO_VENDOR_ENCAPSULATED_OPTIONS;
j = SV_VENDOR_OPTION_SPACE;
if (!lookup_option (&dhcp_universe, state -> options, i) &&
(oc = lookup_option (&server_universe, state -> options, j)) &&
evaluate_option_cache (&d1,
packet, state -> options, oc)) {
oc = (struct option_cache *)0;
if (option_cache_allocate (&oc, "ack_lease")) {
if (make_encapsulation (&oc -> expression, &d1)) {
oc -> option = dhcp_universe.options [i];
save_option (&dhcp_universe,
state -> options, oc);
}
option_cache_dereference (&oc, "ack_lease");
}
data_string_forget (&d1, "ack_lease");
}
/* If the client has provided a list of options that it wishes /* If the client has provided a list of options that it wishes
returned, use it to prioritize. Otherwise, prioritize returned, use it to prioritize. Otherwise, prioritize
based on the default priority list. */ based on the default priority list. */
oc = lookup_option (packet -> options.dhcp_hash, oc = lookup_option (&dhcp_universe, packet -> options,
DHO_DHCP_PARAMETER_REQUEST_LIST); DHO_DHCP_PARAMETER_REQUEST_LIST);
if (oc) if (oc)
evaluate_option_cache (&state -> parameter_request_list, evaluate_option_cache (&state -> parameter_request_list,
packet, &packet -> options, oc); packet, packet -> options, oc);
#ifdef DEBUG_PACKET #ifdef DEBUG_PACKET
dump_packet (packet); dump_packet (packet);
@@ -1252,8 +1281,7 @@ void dhcp_reply (lease)
/* Insert such options as will fit into the buffer. */ /* Insert such options as will fit into the buffer. */
packet_length = cons_options ((struct packet *)0, &raw, packet_length = cons_options ((struct packet *)0, &raw,
state -> max_message_size, state -> max_message_size,
&state -> options, state -> options,
state -> agent_options,
bufs, nulltp, bootpp, bufs, nulltp, bootpp,
&state -> parameter_request_list); &state -> parameter_request_list);
@@ -1263,7 +1291,8 @@ void dhcp_reply (lease)
/* Figure out the address of the next server. */ /* Figure out the address of the next server. */
raw.siaddr = state -> ip -> primary_address; raw.siaddr = state -> ip -> primary_address;
if ((oc = if ((oc =
lookup_option (state -> options.server_hash, SV_NEXT_SERVER))) { lookup_option (&server_universe,
state -> options, SV_NEXT_SERVER))) {
if (evaluate_option_cache (&d1, (struct packet *)0, if (evaluate_option_cache (&d1, (struct packet *)0,
(struct option_state *)0, oc)) { (struct option_state *)0, oc)) {
/* If there was more than one answer, /* If there was more than one answer,
@@ -1279,8 +1308,6 @@ void dhcp_reply (lease)
* now that we're done with them. * now that we're done with them.
*/ */
option_state_dereference (&state -> options);
raw.giaddr = state -> giaddr; raw.giaddr = state -> giaddr;
raw.xid = state -> xid; raw.xid = state -> xid;
@@ -1404,11 +1431,11 @@ struct lease *find_lease (packet, share, ours)
int status; int status;
/* Look up the requested address. */ /* Look up the requested address. */
oc = lookup_option (packet -> options.dhcp_hash, oc = lookup_option (&dhcp_universe, packet -> options,
DHO_DHCP_REQUESTED_ADDRESS); DHO_DHCP_REQUESTED_ADDRESS);
memset (&d1, 0, sizeof d1); memset (&d1, 0, sizeof d1);
if (oc && if (oc &&
evaluate_option_cache (&d1, packet, &packet -> options, oc)) { evaluate_option_cache (&d1, packet, packet -> options, oc)) {
cip.len = 4; cip.len = 4;
memcpy (cip.iabuf, d1.data, cip.len); memcpy (cip.iabuf, d1.data, cip.len);
data_string_forget (&d1, "find_lease"); data_string_forget (&d1, "find_lease");
@@ -1420,12 +1447,12 @@ struct lease *find_lease (packet, share, ours)
/* Try to find a host or lease that's been assigned to the /* Try to find a host or lease that's been assigned to the
specified unique client identifier. */ specified unique client identifier. */
oc = lookup_option (packet -> options.dhcp_hash, oc = lookup_option (&dhcp_universe, packet -> options,
DHO_DHCP_CLIENT_IDENTIFIER); DHO_DHCP_CLIENT_IDENTIFIER);
memset (&client_identifier, 0, sizeof client_identifier); memset (&client_identifier, 0, sizeof client_identifier);
if (oc && if (oc &&
evaluate_option_cache (&client_identifier, evaluate_option_cache (&client_identifier,
packet, &packet -> options, oc)) { packet, packet -> options, oc)) {
/* Remember this for later. */ /* Remember this for later. */
have_client_identifier = 1; have_client_identifier = 1;
@@ -1513,7 +1540,7 @@ struct lease *find_lease (packet, share, ours)
continue; continue;
} }
if ((uid_lease -> pool -> prohibit_list && if ((uid_lease -> pool -> prohibit_list &&
permitted (packet, uid_lease -> pool -> prohibit_list)) || permitted (packet, uid_lease -> pool -> prohibit_list)) ||
(uid_lease -> pool -> permit_list && (uid_lease -> pool -> permit_list &&
!permitted (packet, uid_lease -> pool -> permit_list))) { !permitted (packet, uid_lease -> pool -> permit_list))) {
#if defined (DEBUG_FIND_LEASE) #if defined (DEBUG_FIND_LEASE)