summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Markwalder <tmark@isc.org>2016-11-01 14:53:31 -0400
committerThomas Markwalder <tmark@isc.org>2016-11-01 14:53:31 -0400
commit9a38d0fef30279ab18ce3a1da23ec72a766662e1 (patch)
tree6ef5fb4930e7779b4193c72b1c8ee90d11c08caf
parent85241f1f27d8b368f2603e51fb68961490a0bced (diff)
downloadisc-dhcp-9a38d0fef30279ab18ce3a1da23ec72a766662e1.tar.gz
[v4_1_esv] DHCPINFORM response now includes options down to the pool scope
Manually merged in rt43219.
-rw-r--r--RELNOTES6
-rw-r--r--server/dhcp.c115
2 files changed, 71 insertions, 50 deletions
diff --git a/RELNOTES b/RELNOTES
index a4f96afb..387cc4f2 100644
--- a/RELNOTES
+++ b/RELNOTES
@@ -69,6 +69,12 @@ by Eric Young (eay@cryptsoft.com).
the issue; and Norm for suggesting a solution.
[ISC-Bugs #41358]
+- When replying to a DHCPINFORM, the server will now include options specified
+ at the pool scope, provided the ciaddr field of the DHCPINFORM is populated.
+ Prior to this the server only evaluated options down to the subnet scope.
+ Thanks to Fernando Soto at BlueCat Networks for reporting the issue.
+ [ISC-Bugs #43219]
+
Changes since 4.1-ESV-R14b1
- None
diff --git a/server/dhcp.c b/server/dhcp.c
index 88baa0d4..9d01f02d 100644
--- a/server/dhcp.c
+++ b/server/dhcp.c
@@ -54,7 +54,7 @@ static int site_code_min;
static int find_min_site_code(struct universe *);
static isc_result_t lowest_site_code(const void *, unsigned, void *);
-static const char *dhcp_type_names [] = {
+static const char *dhcp_type_names [] = {
"DHCPDISCOVER",
"DHCPOFFER",
"DHCPREQUEST",
@@ -85,13 +85,13 @@ dhcp (struct packet *packet) {
if (!locate_network(packet) &&
packet->packet_type != DHCPREQUEST &&
- packet->packet_type != DHCPINFORM &&
+ packet->packet_type != DHCPINFORM &&
packet->packet_type != DHCPLEASEQUERY) {
const char *s;
char typebuf[32];
errmsg = "unknown network segment";
bad_packet:
-
+
if (packet->packet_type > 0 &&
packet->packet_type <= dhcp_type_name_max) {
s = dhcp_type_names[packet->packet_type - 1];
@@ -100,7 +100,7 @@ dhcp (struct packet *packet) {
sprintf(typebuf, "type %d", packet->packet_type);
s = typebuf;
}
-
+
log_info("%s from %s via %s: %s", s,
(packet->raw->htype
? print_hw_addr(packet->raw->htype,
@@ -333,7 +333,7 @@ void dhcpdiscover (packet, ms_nulltp)
/* If we didn't find a lease, try to allocate one... */
if (!lease) {
if (!allocate_lease (&lease, packet,
- packet -> shared_network -> pools,
+ packet -> shared_network -> pools,
&peer_has_leases)) {
if (peer_has_leases)
log_error ("%s: peer holds all free leases",
@@ -633,7 +633,7 @@ void dhcprequest (packet, ms_nulltp, ip_lease)
(packet -> raw -> ciaddr.s_addr &&
packet -> raw -> giaddr.s_addr) ||
(have_requested_addr && !packet -> raw -> ciaddr.s_addr)) {
-
+
/* If we don't know where it came from but we do know
where it claims to have come from, it didn't come
from there. */
@@ -818,7 +818,7 @@ void dhcprelease (packet, ms_nulltp)
/* If we found a lease, release it. */
if (lease && lease -> ends > cur_time) {
release_lease (lease, packet);
- }
+ }
log_info ("%s", msgbuf);
#if defined(FAILOVER_PROTOCOL)
out:
@@ -975,6 +975,7 @@ void dhcpinform (packet, ms_nulltp)
isc_boolean_t zeroed_ciaddr;
struct interface_info *interface;
int result;
+ struct lease* cip_lease = NULL;
/* The client should set ciaddr to its IP address, but apparently
it's common for clients not to do this, so we'll use their IP
@@ -1061,14 +1062,28 @@ void dhcpinform (packet, ms_nulltp)
memset (&raw, 0, sizeof raw);
outgoing.raw = &raw;
- /* Execute statements in scope starting with the subnet scope. */
- if (subnet)
- execute_statements_in_scope ((struct binding_value **)0,
- packet, (struct lease *)0,
- (struct client_state *)0,
- packet -> options, options,
- &global_scope, subnet -> group,
- (struct group *)0);
+ if (subnet) {
+ /* If we have ciaddr, find its lease so we can find its pool. */
+ if (zeroed_ciaddr == ISC_FALSE) {
+ find_lease_by_ip_addr (&cip_lease, cip, MDL);
+ }
+
+ /* Execute statements starting at the pool scope if we can
+ * otherwise the subnet scope is a far as we can go. */
+ execute_statements_in_scope((struct binding_value **)0,
+ packet, (struct lease *)0,
+ (struct client_state *)0,
+ packet->options, options,
+ &global_scope,
+ (cip_lease != NULL &&
+ cip_lease->pool != NULL ?
+ cip_lease->pool->group :
+ subnet->group), NULL);
+
+ if (cip_lease) {
+ lease_dereference (&cip_lease, MDL);
+ }
+ }
/* Execute statements in the class scopes. */
for (i = packet -> class_count; i > 0; i--) {
@@ -1090,7 +1105,7 @@ void dhcpinform (packet, ms_nulltp)
i = d1.len;
if (i >= sizeof(raw.file)) {
log_info("file name longer than packet field "
- "truncated - field: %lu name: %d %.*s",
+ "truncated - field: %lu name: %d %.*s",
(unsigned long)sizeof(raw.file), i, i,
d1.data);
i = sizeof(raw.file);
@@ -1110,7 +1125,7 @@ void dhcpinform (packet, ms_nulltp)
i = d1.len;
if (i >= sizeof(raw.sname)) {
log_info("server name longer than packet field "
- "truncated - field: %lu name: %d %.*s",
+ "truncated - field: %lu name: %d %.*s",
(unsigned long)sizeof(raw.sname), i, i,
d1.data);
i = sizeof(raw.sname);
@@ -1371,7 +1386,7 @@ void nak_lease (packet, cip)
&i, 0, MDL);
save_option (&dhcp_universe, options, oc);
option_cache_dereference (&oc, MDL);
-
+
/* Set DHCP_MESSAGE to whatever the message is */
if (!option_cache_allocate (&oc, MDL)) {
log_error ("No memory for DHCPNAK message type.");
@@ -1397,7 +1412,7 @@ void nak_lease (packet, cip)
* option even for NAKS by calling setup_server_source_address().
* This function will set up an options list from the global
* and subnet scopes before trying to get the source address.
- *
+ *
* Otherwise we simply call get_server_source_address()
* directly, without a server options list, this means
* we'll get the source address from the interface address.
@@ -1767,7 +1782,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
} while (1);
}
}
-
+
/* Make sure this packet satisfies the configured minimum
number of seconds. */
@@ -1871,7 +1886,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
if (host)
host_dereference (&host, MDL);
return;
- }
+ }
/* Drop the request if it's not allowed for this client. */
if (!offer &&
@@ -1889,7 +1904,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
if (host)
host_dereference (&host, MDL);
return;
- }
+ }
/* Drop the request if booting is specifically denied. */
oc = lookup_option (&server_universe, state -> options,
@@ -1991,7 +2006,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
host_dereference (&host, MDL);
return;
}
-
+
/* Use the ip address of the lease that we finally found in
the database. */
lt -> ip_addr = lease -> ip_addr;
@@ -2098,7 +2113,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
if (lease_time < 0 /* XXX */
|| lease_time > max_lease_time)
lease_time = max_lease_time;
-
+
min_lease_time = DEFAULT_MIN_LEASE_TIME;
if (min_lease_time > max_lease_time)
min_lease_time = max_lease_time;
@@ -2173,7 +2188,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
}
/* a client requests an address which is not yet active*/
- if (lease->pool && lease->pool->valid_from &&
+ if (lease->pool && lease->pool->valid_from &&
cur_time < lease->pool->valid_from) {
/* NAK leases before pool activation date */
cip.len = 4;
@@ -2184,7 +2199,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
if (host)
host_dereference (&host, MDL);
return;
-
+
}
/* CC:
@@ -2202,7 +2217,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
A min-lease-time of 6 seconds effectively switches over
all clients in this pool very quickly.
*/
-
+
if (lease->pool && lease->pool->valid_until) {
if (cur_time >= lease->pool->valid_until) {
/* NAK leases after pool expiration date */
@@ -2219,7 +2234,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
if (lease_time > remaining_time)
lease_time = remaining_time;
}
-
+
if (lease_time < min_lease_time) {
if (min_lease_time)
lease_time = min_lease_time;
@@ -2737,7 +2752,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
}
/* Use the name of the host declaration if there is one
- and no hostname has otherwise been provided, and if the
+ and no hostname has otherwise been provided, and if the
use-host-decl-name flag is set. */
use_host_decl_name(packet, lease, state->options);
@@ -2752,9 +2767,9 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
lookup_option (&server_universe, state->options, j), MDL)) {
struct in_addr ia;
struct hostent *h;
-
+
memcpy (&ia, lease -> ip_addr.iabuf, 4);
-
+
h = gethostbyaddr ((char *)&ia, sizeof ia, AF_INET);
if (!h)
log_error ("No hostname for %s", inet_ntoa (ia));
@@ -2801,7 +2816,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
save_option (&dhcp_universe,
state -> options, oc);
}
- option_cache_dereference (&oc, MDL);
+ option_cache_dereference (&oc, MDL);
}
}
}
@@ -2913,7 +2928,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
if (!(lease->flags & STATIC_LEASE) &&
(!offer || (offer == DHCPACK)))
delayed_ack_enqueue(lease);
- else
+ else
#endif
dhcp_reply(lease);
}
@@ -2934,7 +2949,7 @@ delayed_ack_enqueue(struct lease *lease)
{
struct leasequeue *q;
- if (!write_lease(lease))
+ if (!write_lease(lease))
return;
if (free_ackqueue) {
q = free_ackqueue;
@@ -2950,7 +2965,7 @@ delayed_ack_enqueue(struct lease *lease)
lease_reference(&q->lease, lease, MDL);
q->next = ackqueue_head;
ackqueue_head = q;
- if (!ackqueue_tail)
+ if (!ackqueue_tail)
ackqueue_tail = q;
else
q->next->prev = q;
@@ -3023,7 +3038,7 @@ delayed_acks_timer(void *foo)
*/
/* process from bottom to retain packet order */
- for (ack = ackqueue_tail ; ack ; ack = p) {
+ for (ack = ackqueue_tail ; ack ; ack = p) {
p = ack->prev;
#if defined(FAILOVER_PROTOCOL)
@@ -3062,7 +3077,7 @@ void
relinquish_ackqueue(void)
{
struct leasequeue *q, *n;
-
+
for (q = ackqueue_head ; q ; q = n) {
n = q->next;
dfree(q, MDL);
@@ -3108,9 +3123,9 @@ void dhcp_reply (lease)
if (sizeof raw.file > state -> filename.len)
memset (&raw.file [state -> filename.len], 0,
(sizeof raw.file) - state -> filename.len);
- else
+ else
log_info("file name longer than packet field "
- "truncated - field: %lu name: %d %.*s",
+ "truncated - field: %lu name: %d %.*s",
(unsigned long)sizeof(raw.file),
state->filename.len, state->filename.len,
state->filename.data);
@@ -3127,9 +3142,9 @@ void dhcp_reply (lease)
if (sizeof raw.sname > state -> server_name.len)
memset (&raw.sname [state -> server_name.len], 0,
(sizeof raw.sname) - state -> server_name.len);
- else
+ else
log_info("server name longer than packet field "
- "truncated - field: %lu name: %d %.*s",
+ "truncated - field: %lu name: %d %.*s",
(unsigned long)sizeof(raw.sname),
state->server_name.len,
state->server_name.len,
@@ -3373,7 +3388,7 @@ int find_lease (struct lease **lp,
cip.len = 4;
memcpy (cip.iabuf, d1.data, cip.len);
data_string_forget (&d1, MDL);
- } else
+ } else
cip.len = 0;
}
@@ -4028,7 +4043,7 @@ int mockup_lease (struct lease **lp, struct packet *packet,
{
struct lease *lease = (struct lease *)0;
struct host_decl *rhp = (struct host_decl *)0;
-
+
if (lease_allocate (&lease, MDL) != ISC_R_SUCCESS)
return 0;
if (host_reference (&rhp, hp, MDL) != ISC_R_SUCCESS) {
@@ -4107,7 +4122,7 @@ int allocate_lease (struct lease **lp, struct packet *packet,
/*
* In normal operation, we never want to touch
- * the peer's leases. In partner-down
+ * the peer's leases. In partner-down
* operation, we need to be able to pick up
* the peer's leases after STOS+MCLT.
*/
@@ -4257,7 +4272,7 @@ int permitted (packet, permit_list)
!packet -> packet_type)
return 1;
break;
-
+
case permit_class:
for (i = 0; i < packet -> class_count; i++) {
if (p -> class == packet -> classes [i])
@@ -4393,8 +4408,8 @@ get_server_source_address(struct in_addr *from,
option_num = DHO_DHCP_SERVER_IDENTIFIER;
oc = lookup_option(&dhcp_universe, options, option_num);
if (oc != NULL) {
- if (evaluate_option_cache(&d, packet, NULL, NULL,
- packet->options, options,
+ if (evaluate_option_cache(&d, packet, NULL, NULL,
+ packet->options, options,
&global_scope, oc, MDL)) {
if (d.len == sizeof(*from)) {
found = ISC_TRUE;
@@ -4429,7 +4444,7 @@ get_server_source_address(struct in_addr *from,
if (make_const_data(&oc->expression,
(unsigned char *)a, sizeof(*a),
0, allocate, MDL)) {
- option_code_hash_lookup(&oc->option,
+ option_code_hash_lookup(&oc->option,
dhcp_universe.code_hash,
&option_num, 0, MDL);
save_option(&dhcp_universe, out_options, oc);
@@ -4443,7 +4458,7 @@ get_server_source_address(struct in_addr *from,
/*
* Set up an option state list to try and find a server option.
* We don't go through all possible options - in particualr we
- * skip the hosts and we don't include the lease to avoid
+ * skip the hosts and we don't include the lease to avoid
* making changes to it. This means that we won't get the
* correct server id if the admin puts them on hosts or
* builds the server id with information from the lease.
@@ -4452,7 +4467,7 @@ get_server_source_address(struct in_addr *from,
* sort out server id mismatch in failover) and requires
* configuration by the admin, it should be okay.
*/
-
+
void
setup_server_source_address(struct in_addr *from,
struct option_state *options,