mirror of
https://gitlab.isc.org/isc-projects/dhcp
synced 2025-09-03 07:45:20 +00:00
[master] dhcpd (-6) now supports update-static-leases
Merges in rt34097.
This commit is contained in:
12
RELNOTES
12
RELNOTES
@@ -284,6 +284,18 @@ dhcp-users@lists.isc.org.
|
|||||||
- Corrected some minor coverity issues: CID 1426059, 1426058, and 1426057.
|
- Corrected some minor coverity issues: CID 1426059, 1426058, and 1426057.
|
||||||
[ISC-Bugs #46836]
|
[ISC-Bugs #46836]
|
||||||
|
|
||||||
|
- The server (-6) now honors the parameter, update-static-leases, for static
|
||||||
|
(fixed-address6) DHCPv6 leases. It is worth noting that because stateful
|
||||||
|
data is not retained by the server for static leases, each time a client
|
||||||
|
requests or renews a static lease, the server will perform DDNS updates for
|
||||||
|
it. This may have significant performance implications for environments
|
||||||
|
with many clients that request or renew static leases often. Similarly,
|
||||||
|
the DNS entries will not be removed by server when a client issues a RELEASE
|
||||||
|
nor if the lease is deleted from the configuration. In such cases the DNS
|
||||||
|
entries must be removed manually. This feature is disabled by default.
|
||||||
|
[ISC-Bugs #34097]
|
||||||
|
[ISC-Bugs #41054]
|
||||||
|
|
||||||
Changes since 4.3.6 (Bugs):
|
Changes since 4.3.6 (Bugs):
|
||||||
|
|
||||||
- Corrected an issue where the server would return a client's previously
|
- Corrected an issue where the server would return a client's previously
|
||||||
|
@@ -594,9 +594,16 @@ ddns_cb_free(dhcp_ddns_cb_t *ddns_cb, const char *file, int line)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Should be freed by now, check just in case. */
|
/* Should be freed by now, check just in case. */
|
||||||
if (ddns_cb->transaction != NULL)
|
if (ddns_cb->transaction != NULL) {
|
||||||
log_error("Impossible memory leak at %s:%d (attempt to free "
|
log_error("Impossible memory leak at %s:%d (attempt to free "
|
||||||
"DDNS Control Block before transaction).", MDL);
|
"DDNS Control Block before transaction).", MDL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Should be freed by now, check just in case. */
|
||||||
|
if (ddns_cb->fixed6_ia) {
|
||||||
|
log_error("Possible memory leak at %s:%d (attempt to free "
|
||||||
|
"DDNS Control Block before fxed6_ia).", MDL);
|
||||||
|
}
|
||||||
|
|
||||||
dfree(ddns_cb, file, line);
|
dfree(ddns_cb, file, line);
|
||||||
}
|
}
|
||||||
|
@@ -1646,6 +1646,7 @@ struct iasubopt {
|
|||||||
|
|
||||||
/* space for the on * executable statements */
|
/* space for the on * executable statements */
|
||||||
struct on_star on_star;
|
struct on_star on_star;
|
||||||
|
int static_lease;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ia_xx {
|
struct ia_xx {
|
||||||
@@ -1818,6 +1819,7 @@ typedef struct dhcp_ddns_cb {
|
|||||||
dns_rdataclass_t dhcid_class;
|
dns_rdataclass_t dhcid_class;
|
||||||
dns_rdataclass_t other_dhcid_class;
|
dns_rdataclass_t other_dhcid_class;
|
||||||
char *lease_tag;
|
char *lease_tag;
|
||||||
|
struct ia_xx *fixed6_ia;
|
||||||
} dhcp_ddns_cb_t;
|
} dhcp_ddns_cb_t;
|
||||||
|
|
||||||
extern struct ipv6_pool **pools;
|
extern struct ipv6_pool **pools;
|
||||||
|
@@ -57,6 +57,25 @@ static void copy_conflict_flags(u_int16_t *target, u_int16_t source);
|
|||||||
|
|
||||||
static void ddns_fwd_srv_add3(dhcp_ddns_cb_t *ddns_cb, isc_result_t eresult);
|
static void ddns_fwd_srv_add3(dhcp_ddns_cb_t *ddns_cb, isc_result_t eresult);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ddns_cb_free() is part of common lib, while ia_* routines are known
|
||||||
|
* only in the server. Use this wrapper instead of ddns_cb_free() directly.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
destroy_ddns_cb(struct dhcp_ddns_cb *ddns_cb, char* file, int line) {
|
||||||
|
if (!ddns_cb) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ddns_cb->fixed6_ia) {
|
||||||
|
ia_dereference(&ddns_cb->fixed6_ia, MDL);
|
||||||
|
}
|
||||||
|
|
||||||
|
ddns_cb_free(ddns_cb, file, line);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* DN: No way of checking that there is enough space in a data_string's
|
/* DN: No way of checking that there is enough space in a data_string's
|
||||||
buffer. Be certain to allocate enough!
|
buffer. Be certain to allocate enough!
|
||||||
TL: This is why the expression evaluation code allocates a *new*
|
TL: This is why the expression evaluation code allocates a *new*
|
||||||
@@ -153,6 +172,13 @@ ddns_updates(struct packet *packet, struct lease *lease, struct lease *old,
|
|||||||
scope = &(lease6->scope);
|
scope = &(lease6->scope);
|
||||||
memcpy(ddns_cb->address.iabuf, lease6->addr.s6_addr, 16);
|
memcpy(ddns_cb->address.iabuf, lease6->addr.s6_addr, 16);
|
||||||
ddns_cb->address.len = 16;
|
ddns_cb->address.len = 16;
|
||||||
|
|
||||||
|
if (lease6->static_lease) {
|
||||||
|
/* We add a reference to keep ia && iasubopt alive
|
||||||
|
* since static v6s are retained anywhere */
|
||||||
|
ia_reference(&ddns_cb->fixed6_ia, lease6->ia, MDL);
|
||||||
|
ddns_cb->flags |= DDNS_STATIC_LEASE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
memset (&d1, 0, sizeof(d1));
|
memset (&d1, 0, sizeof(d1));
|
||||||
@@ -754,7 +780,7 @@ ddns_updates(struct packet *packet, struct lease *lease, struct lease *old,
|
|||||||
* Final cleanup.
|
* Final cleanup.
|
||||||
*/
|
*/
|
||||||
if (ddns_cb != NULL) {
|
if (ddns_cb != NULL) {
|
||||||
ddns_cb_free(ddns_cb, MDL);
|
destroy_ddns_cb(ddns_cb, MDL);
|
||||||
}
|
}
|
||||||
|
|
||||||
data_string_forget(&d1, MDL);
|
data_string_forget(&d1, MDL);
|
||||||
@@ -1296,7 +1322,7 @@ ddns_ptr_add(dhcp_ddns_cb_t *ddns_cb,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ddns_update_lease_ptr(NULL, NULL, ddns_cb, NULL, MDL);
|
ddns_update_lease_ptr(NULL, NULL, ddns_cb, NULL, MDL);
|
||||||
ddns_cb_free(ddns_cb, MDL);
|
destroy_ddns_cb(ddns_cb, MDL);
|
||||||
/*
|
/*
|
||||||
* A single DDNS operation may require several calls depending on
|
* A single DDNS operation may require several calls depending on
|
||||||
* the current state as the prerequisites for the first message
|
* the current state as the prerequisites for the first message
|
||||||
@@ -1362,7 +1388,7 @@ ddns_ptr_remove(dhcp_ddns_cb_t *ddns_cb,
|
|||||||
|
|
||||||
ddns_update_lease_ptr(NULL, NULL, ddns_cb, NULL, MDL);
|
ddns_update_lease_ptr(NULL, NULL, ddns_cb, NULL, MDL);
|
||||||
ddns_fwd_srv_connector(NULL, NULL, NULL, ddns_cb->next_op, result);
|
ddns_fwd_srv_connector(NULL, NULL, NULL, ddns_cb->next_op, result);
|
||||||
ddns_cb_free(ddns_cb, MDL);
|
destroy_ddns_cb(ddns_cb, MDL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1476,7 +1502,7 @@ ddns_fwd_srv_add2(dhcp_ddns_cb_t *ddns_cb,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ddns_update_lease_ptr(NULL, NULL, ddns_cb, NULL, MDL);
|
ddns_update_lease_ptr(NULL, NULL, ddns_cb, NULL, MDL);
|
||||||
ddns_cb_free(ddns_cb, MDL);
|
destroy_ddns_cb(ddns_cb, MDL);
|
||||||
/*
|
/*
|
||||||
* A single DDNS operation may require several calls depending on
|
* A single DDNS operation may require several calls depending on
|
||||||
* the current state as the prerequisites for the first message
|
* the current state as the prerequisites for the first message
|
||||||
@@ -1551,7 +1577,7 @@ ddns_fwd_srv_add1(dhcp_ddns_cb_t *ddns_cb,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ddns_update_lease_ptr(NULL, NULL, ddns_cb, NULL, MDL);
|
ddns_update_lease_ptr(NULL, NULL, ddns_cb, NULL, MDL);
|
||||||
ddns_cb_free(ddns_cb, MDL);
|
destroy_ddns_cb(ddns_cb, MDL);
|
||||||
/*
|
/*
|
||||||
* A single DDNS operation may require several calls depending on
|
* A single DDNS operation may require several calls depending on
|
||||||
* the current state as the prerequisites for the first message
|
* the current state as the prerequisites for the first message
|
||||||
@@ -1636,7 +1662,7 @@ ddns_fwd_srv_add3(dhcp_ddns_cb_t *ddns_cb,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ddns_update_lease_ptr(NULL, NULL, ddns_cb, NULL, MDL);
|
ddns_update_lease_ptr(NULL, NULL, ddns_cb, NULL, MDL);
|
||||||
ddns_cb_free(ddns_cb, MDL);
|
destroy_ddns_cb(ddns_cb, MDL);
|
||||||
/*
|
/*
|
||||||
* A single DDNS operation may require several calls depending on
|
* A single DDNS operation may require several calls depending on
|
||||||
* the current state as the prerequisites for the first message
|
* the current state as the prerequisites for the first message
|
||||||
@@ -1694,7 +1720,7 @@ ddns_fwd_srv_connector(struct lease *lease,
|
|||||||
if (result == ISC_R_SUCCESS) {
|
if (result == ISC_R_SUCCESS) {
|
||||||
ddns_update_lease_ptr(lease, lease6, ddns_cb, ddns_cb, MDL);
|
ddns_update_lease_ptr(lease, lease6, ddns_cb, ddns_cb, MDL);
|
||||||
} else {
|
} else {
|
||||||
ddns_cb_free(ddns_cb, MDL);
|
destroy_ddns_cb(ddns_cb, MDL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -1762,7 +1788,7 @@ ddns_fwd_srv_rem2(dhcp_ddns_cb_t *ddns_cb,
|
|||||||
|
|
||||||
ddns_update_lease_ptr(NULL, NULL, ddns_cb, NULL, MDL);
|
ddns_update_lease_ptr(NULL, NULL, ddns_cb, NULL, MDL);
|
||||||
ddns_fwd_srv_connector(NULL, NULL, NULL, ddns_cb->next_op, eresult);
|
ddns_fwd_srv_connector(NULL, NULL, NULL, ddns_cb->next_op, eresult);
|
||||||
ddns_cb_free(ddns_cb, MDL);
|
destroy_ddns_cb(ddns_cb, MDL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1866,7 +1892,7 @@ ddns_fwd_srv_rem1(dhcp_ddns_cb_t *ddns_cb,
|
|||||||
|
|
||||||
ddns_update_lease_ptr(NULL, NULL, ddns_cb, NULL, MDL);
|
ddns_update_lease_ptr(NULL, NULL, ddns_cb, NULL, MDL);
|
||||||
ddns_fwd_srv_connector(NULL, NULL, NULL, ddns_cb->next_op, eresult);
|
ddns_fwd_srv_connector(NULL, NULL, NULL, ddns_cb->next_op, eresult);
|
||||||
ddns_cb_free(ddns_cb, MDL);
|
destroy_ddns_cb(ddns_cb, MDL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*%<
|
/*%<
|
||||||
@@ -1952,7 +1978,7 @@ ddns_removals(struct lease *lease,
|
|||||||
} else {
|
} else {
|
||||||
/* Remvoval, check and remove updates */
|
/* Remvoval, check and remove updates */
|
||||||
if (ddns_cb->next_op != NULL) {
|
if (ddns_cb->next_op != NULL) {
|
||||||
ddns_cb_free(ddns_cb->next_op, MDL);
|
destroy_ddns_cb(ddns_cb->next_op, MDL);
|
||||||
ddns_cb->next_op = NULL;
|
ddns_cb->next_op = NULL;
|
||||||
}
|
}
|
||||||
#if defined (DEBUG_DNS_UPDATES)
|
#if defined (DEBUG_DNS_UPDATES)
|
||||||
@@ -1980,7 +2006,7 @@ ddns_removals(struct lease *lease,
|
|||||||
} else {
|
} else {
|
||||||
/* Remvoval, check and remove updates */
|
/* Remvoval, check and remove updates */
|
||||||
if (ddns_cb->next_op != NULL) {
|
if (ddns_cb->next_op != NULL) {
|
||||||
ddns_cb_free(ddns_cb->next_op, MDL);
|
destroy_ddns_cb(ddns_cb->next_op, MDL);
|
||||||
ddns_cb->next_op = NULL;
|
ddns_cb->next_op = NULL;
|
||||||
}
|
}
|
||||||
#if defined (DEBUG_DNS_UPDATES)
|
#if defined (DEBUG_DNS_UPDATES)
|
||||||
@@ -2191,7 +2217,7 @@ ddns_removals(struct lease *lease,
|
|||||||
*/
|
*/
|
||||||
ddns_fwd_srv_connector(lease, lease6, scope, add_ddns_cb, execute_add);
|
ddns_fwd_srv_connector(lease, lease6, scope, add_ddns_cb, execute_add);
|
||||||
if (ddns_cb != NULL)
|
if (ddns_cb != NULL)
|
||||||
ddns_cb_free(ddns_cb, MDL);
|
destroy_ddns_cb(ddns_cb, MDL);
|
||||||
|
|
||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
|
@@ -3379,13 +3379,15 @@ statement
|
|||||||
.PP
|
.PP
|
||||||
The \fIupdate-static-leases\fR flag, if enabled, causes the DHCP
|
The \fIupdate-static-leases\fR flag, if enabled, causes the DHCP
|
||||||
server to do DNS updates for clients even if those clients are being
|
server to do DNS updates for clients even if those clients are being
|
||||||
assigned their IP address using a \fIfixed-address\fR statement - that
|
assigned their IP address using a \fIfixed-address\fR or
|
||||||
is, the client is being given a static assignment. It is not
|
\fIfixed-address6\fR statement - that is, the client is being given a
|
||||||
recommended because the DHCP server has no way to tell that the update
|
static assignment. It is not recommended because the DHCP server has
|
||||||
has been done, and therefore will not delete the record when it is not
|
no way to tell that the update has been done, and therefore will not
|
||||||
in use. Also, the server must attempt the update each time the
|
delete the record when it is not in use. Also, the server must attempt
|
||||||
client renews its lease, which could have a significant performance
|
the update each time the client renews its lease, which could have a
|
||||||
impact in environments that place heavy demands on the DHCP server.
|
significant performance impact in environments that place heavy demands
|
||||||
|
on the DHCP server. This feature is supported for both DHCPv4 and DHCPv6,
|
||||||
|
and update modes standard or interim. It is disabled by default.
|
||||||
.RE
|
.RE
|
||||||
.PP
|
.PP
|
||||||
The
|
The
|
||||||
|
@@ -185,6 +185,10 @@ static void shorten_lifetimes(struct reply_state *reply, struct iasubopt *lease,
|
|||||||
static void write_to_packet(struct reply_state *reply, unsigned ia_cursor);
|
static void write_to_packet(struct reply_state *reply, unsigned ia_cursor);
|
||||||
static const char *iasubopt_plen_str(struct iasubopt *lease);
|
static const char *iasubopt_plen_str(struct iasubopt *lease);
|
||||||
|
|
||||||
|
#ifdef NSUPDATE
|
||||||
|
static void ddns_update_static6(struct reply_state* reply);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef DHCP4o6
|
#ifdef DHCP4o6
|
||||||
/*
|
/*
|
||||||
* \brief Omapi I/O handler
|
* \brief Omapi I/O handler
|
||||||
@@ -2227,7 +2231,10 @@ reply_process_ia_na(struct reply_state *reply, struct option_cache *ia) {
|
|||||||
|
|
||||||
/* Write the lease out in wire-format to the outbound buffer */
|
/* Write the lease out in wire-format to the outbound buffer */
|
||||||
write_to_packet(reply, ia_cursor);
|
write_to_packet(reply, ia_cursor);
|
||||||
|
#ifdef NSUPDATE
|
||||||
|
/* Performs DDNS updates if we're configured to do them */
|
||||||
|
ddns_update_static6(reply);
|
||||||
|
#endif
|
||||||
if ((reply->buf.reply.msg_type == DHCPV6_REPLY) &&
|
if ((reply->buf.reply.msg_type == DHCPV6_REPLY) &&
|
||||||
(reply->on_star.on_commit != NULL)) {
|
(reply->on_star.on_commit != NULL)) {
|
||||||
execute_statements(NULL, reply->packet, NULL, NULL,
|
execute_statements(NULL, reply->packet, NULL, NULL,
|
||||||
@@ -8448,4 +8455,66 @@ const char *iasubopt_plen_str(struct iasubopt *lease) {
|
|||||||
return (prefix_buf);
|
return (prefix_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef NSUPDATE
|
||||||
|
/*
|
||||||
|
* Initiates DDNS updates for static v6 leases if configured to do so.
|
||||||
|
*
|
||||||
|
* The function, which must be called after the IA has been written to the
|
||||||
|
* packet, adds an iasubopt to the IA for static lease. This is done so we
|
||||||
|
* have an iasubopt to pass into ddns_updates(). A reference to the IA is
|
||||||
|
* added to the DDNS control block to ensure it and it's iasubopt remain in
|
||||||
|
* scope until the update is complete.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void ddns_update_static6(struct reply_state* reply) {
|
||||||
|
struct iasubopt *iasub = NULL;
|
||||||
|
struct binding_scope *scope = NULL;
|
||||||
|
struct option_cache *oc = NULL;
|
||||||
|
|
||||||
|
oc = lookup_option(&server_universe, reply->opt_state, SV_DDNS_UPDATES);
|
||||||
|
if ((oc != NULL) &&
|
||||||
|
(evaluate_boolean_option_cache(NULL, reply->packet, NULL, NULL,
|
||||||
|
reply->packet->options,
|
||||||
|
reply->opt_state, NULL,
|
||||||
|
oc, MDL) == 0)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
oc = lookup_option(&server_universe, reply->opt_state,
|
||||||
|
SV_UPDATE_STATIC_LEASES);
|
||||||
|
if ((oc == NULL) ||
|
||||||
|
(evaluate_boolean_option_cache(NULL, reply->packet,
|
||||||
|
NULL, NULL,
|
||||||
|
reply->packet->options,
|
||||||
|
reply->opt_state, NULL,
|
||||||
|
oc, MDL) == 0)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iasubopt_allocate(&iasub, MDL) != ISC_R_SUCCESS) {
|
||||||
|
log_fatal("No memory for iasubopt.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ia_add_iasubopt(reply->ia, iasub, MDL) != ISC_R_SUCCESS) {
|
||||||
|
log_fatal("Could not add iasubopt.");
|
||||||
|
}
|
||||||
|
|
||||||
|
ia_reference(&iasub->ia, reply->ia, MDL);
|
||||||
|
|
||||||
|
memcpy(iasub->addr.s6_addr, reply->fixed.data, 16);
|
||||||
|
iasub->plen = 0;
|
||||||
|
iasub->prefer = MAX_TIME;
|
||||||
|
iasub->valid = MAX_TIME;
|
||||||
|
iasub->static_lease = 1;
|
||||||
|
|
||||||
|
if (!binding_scope_allocate(&scope, MDL)) {
|
||||||
|
log_fatal("Out of memory for binding scope.");
|
||||||
|
}
|
||||||
|
|
||||||
|
binding_scope_reference(&iasub->scope, scope, MDL);
|
||||||
|
|
||||||
|
ddns_updates(reply->packet, NULL, NULL, iasub, NULL, reply->opt_state);
|
||||||
|
}
|
||||||
|
#endif /* NSUPDATE */
|
||||||
|
|
||||||
#endif /* DHCPv6 */
|
#endif /* DHCPv6 */
|
||||||
|
Reference in New Issue
Block a user