2
0
mirror of https://gitlab.isc.org/isc-projects/dhcp synced 2025-09-05 00:35:41 +00:00

-n [master]

Add code to support the standards version of DDNS
This commit is contained in:
Shawn Routhier
2013-10-14 15:53:24 -07:00
parent 1d851cff2c
commit d7d9c0c7c3
38 changed files with 2630 additions and 2114 deletions

View File

@@ -38,6 +38,9 @@
#include "dst/md5.h"
#include <dns/result.h>
char *ddns_standard_tag = "ddns-dhcid";
char *ddns_interim_tag = "ddns-txt";
#ifdef NSUPDATE
static void ddns_fwd_srv_connector(struct lease *lease,
@@ -73,16 +76,13 @@ ddns_updates(struct packet *packet, struct lease *lease, struct lease *old,
struct data_string ddns_domainname;
struct data_string old_ddns_fwd_name;
struct data_string ddns_fwd_name;
//struct data_string ddns_rev_name;
struct data_string ddns_dhcid;
struct binding_scope **scope = NULL;
//struct iaddr addr;
struct data_string d1;
struct option_cache *oc;
int s1, s2;
int result = 0;
int server_updates_a = 1;
//int server_updates_ptr = 1;
struct buffer *bp = (struct buffer *)0;
int ignorep = 0, client_ignorep = 0;
int rev_name_len;
@@ -91,8 +91,9 @@ ddns_updates(struct packet *packet, struct lease *lease, struct lease *old,
dhcp_ddns_cb_t *ddns_cb;
int do_remove = 0;
if (ddns_update_style != 2)
return 0;
if ((ddns_update_style != DDNS_UPDATE_STYLE_STANDARD) &&
(ddns_update_style != DDNS_UPDATE_STYLE_INTERIM))
return (0);
/*
* sigh, I want to cancel any previous udpates before we do anything
@@ -151,7 +152,6 @@ ddns_updates(struct packet *packet, struct lease *lease, struct lease *old,
memset (&ddns_domainname, 0, sizeof (ddns_domainname));
memset (&old_ddns_fwd_name, 0, sizeof (ddns_fwd_name));
memset (&ddns_fwd_name, 0, sizeof (ddns_fwd_name));
//memset (&ddns_rev_name, 0, sizeof (ddns_rev_name));
memset (&ddns_dhcid, 0, sizeof (ddns_dhcid));
/* If we are allowed to accept the client's update of its own A
@@ -265,36 +265,23 @@ ddns_updates(struct packet *packet, struct lease *lease, struct lease *old,
goto in;
}
/* See if there's a DHCID on the lease, and if not
* then potentially look for 'on events' for ad-hoc ddns.
#if defined (DDNS_UPDATE_SLOW_TRANSITION)
/*
* If the slow transition code is enabled check to see
* if the stored type (standard or interim doesn't
* match the type currently in use. If it doesn't
* try to remove and replace the DNS record
*/
if (!find_bound_string(&ddns_dhcid, *scope, "ddns-txt") &&
(old != NULL)) {
/* If there's no DHCID, the update was probably
done with the old-style ad-hoc DDNS updates.
So if the expiry and release events look like
they're the same, run them. This should delete
the old DDNS data. */
if (old->on_star.on_expiry ==
old->on_star.on_release) {
execute_statements(NULL, NULL, lease, NULL,
NULL, NULL, scope,
old->on_star.on_expiry,
NULL);
if (old->on_star.on_expiry)
executable_statement_dereference
(&old->on_star.on_expiry,
MDL);
if (old->on_star.on_release)
executable_statement_dereference
(&old->on_star.on_release,
MDL);
/* Now, install the DDNS data the new way. */
goto in;
}
} else
if (((ddns_update_style == DDNS_UPDATE_STYLE_STANDARD) &&
find_bound_string(&ddns_dhcid, *scope, ddns_interim_tag)) ||
((ddns_update_style == DDNS_UPDATE_STYLE_INTERIM) &&
find_bound_string(&ddns_dhcid, *scope, ddns_standard_tag))) {
data_string_forget(&ddns_dhcid, MDL);
do_remove = 1;
goto in;
}
#endif
/* See if the administrator wants to do updates even
in cases where the update already appears to have been
done. */
@@ -491,23 +478,69 @@ ddns_updates(struct packet *packet, struct lease *lease, struct lease *old,
data_string_forget(&d1, MDL);
}
/*
* copy the string now so we can pass it to the dhcid routines
* via the ddns_cb pointer
*/
data_string_copy(&ddns_cb->fwd_name, &ddns_fwd_name, MDL);
/*
* If we are updating the A record, compute the DHCID value.
* We have two options for computing the DHCID value, the older
* interim version and the newer standard version. The interim
* has some issues but is left as is to avoid compatibility issues.
*
* We select the type of DHCID to construct and the information to
* use for the digest based on 4701 section 3.3
*/
if ((ddns_cb->flags & DDNS_UPDATE_ADDR) != 0) {
if (lease6 != NULL)
result = get_dhcid(&ddns_cb->dhcid, 2,
lease6->ia->iaid_duid.data,
lease6->ia->iaid_duid.len);
else if ((lease != NULL) && (lease->uid != NULL) &&
(lease->uid_len != 0))
result = get_dhcid (&ddns_cb->dhcid,
DHO_DHCP_CLIENT_IDENTIFIER,
lease -> uid, lease -> uid_len);
else if (lease != NULL)
result = get_dhcid (&ddns_cb->dhcid, 0,
lease -> hardware_addr.hbuf,
lease -> hardware_addr.hlen);
int ddns_type;
int ddns_len;
if (ddns_update_style == DDNS_UPDATE_STYLE_STANDARD) {
/* The standard style */
ddns_cb->lease_tag = ddns_standard_tag;
ddns_cb->dhcid_class = dns_rdatatype_dhcid;
ddns_type = 1;
ddns_len = 4;
} else {
/* The older interim style */
ddns_cb->lease_tag = ddns_interim_tag;
ddns_cb->dhcid_class = dns_rdatatype_txt;
/* for backwards compatibility */
ddns_type = DHO_DHCP_CLIENT_IDENTIFIER;
/* IAID incorrectly included */
ddns_len = 0;
}
if (lease6 != NULL) {
if (lease6->ia->iaid_duid.len < ddns_len)
goto badfqdn;
result = get_dhcid(ddns_cb, 2,
lease6->ia->iaid_duid.data + ddns_len,
lease6->ia->iaid_duid.len - ddns_len);
} else if ((lease != NULL) &&
(lease->uid != NULL) &&
(lease->uid_len != 0)) {
/* If this is standard check for an RFC 4361
* compliant client identifier
*/
if ((ddns_update_style == DDNS_UPDATE_STYLE_STANDARD) &&
(lease->uid[0] == 255)) {
if (lease->uid_len < 5)
goto badfqdn;
result = get_dhcid(ddns_cb, 2,
lease->uid + 5,
lease->uid_len - 5);
} else {
result = get_dhcid(ddns_cb, ddns_type,
lease->uid,
lease->uid_len);
}
} else if (lease != NULL)
result = get_dhcid(ddns_cb, 0,
lease->hardware_addr.hbuf,
lease->hardware_addr.hlen);
else
log_fatal("Impossible condition at %s:%d.", MDL);
@@ -519,8 +552,6 @@ ddns_updates(struct packet *packet, struct lease *lease, struct lease *old,
* Perform updates.
*/
data_string_copy(&ddns_cb->fwd_name, &ddns_fwd_name, MDL);
if (ddns_cb->flags && DDNS_UPDATE_ADDR) {
oc = lookup_option(&server_universe, options,
SV_DDNS_CONFLICT_DETECT);
@@ -713,8 +744,6 @@ ddns_updates(struct packet *packet, struct lease *lease, struct lease *old,
data_string_forget(&ddns_domainname, MDL);
data_string_forget(&old_ddns_fwd_name, MDL);
data_string_forget(&ddns_fwd_name, MDL);
//data_string_forget(&ddns_rev_name, MDL);
//data_string_forget(&ddns_dhcid, MDL);
if (bp)
buffer_dereference(&bp, MDL);
@@ -828,18 +857,21 @@ ddns_update_lease_text(dhcp_ddns_cb_t *ddns_cb,
case DDNS_STATE_ADD_FW_NXDOMAIN:
bind_ds_value(scope, "ddns-fwd-name", &ddns_cb->fwd_name);
/* convert from dns version to lease version of dhcid */
memset(&lease_dhcid, 0, sizeof(lease_dhcid));
dhcid_tolease(&ddns_cb->dhcid, &lease_dhcid);
bind_ds_value(scope, "ddns-txt", &lease_dhcid);
data_string_forget(&lease_dhcid, MDL);
if (ddns_cb->lease_tag == ddns_standard_tag) {
bind_ds_value(scope, ddns_standard_tag, &ddns_cb->dhcid);
} else {
/* convert from dns version to lease version of dhcid */
memset(&lease_dhcid, 0, sizeof(lease_dhcid));
dhcid_tolease(&ddns_cb->dhcid, &lease_dhcid);
bind_ds_value(scope, ddns_interim_tag, &lease_dhcid);
data_string_forget(&lease_dhcid, MDL);
}
break;
case DDNS_STATE_REM_FW_NXRR:
case DDNS_STATE_REM_FW_YXDHCID:
unset(*scope, "ddns-fwd-name");
unset(*scope, "ddns-txt");
unset(*scope, ddns_cb->lease_tag);
break;
}
@@ -1797,7 +1829,8 @@ ddns_removals(struct lease *lease,
if (*scope == NULL)
goto cleanup;
if (ddns_update_style != 2)
if ((ddns_update_style != DDNS_UPDATE_STYLE_STANDARD) &&
(ddns_update_style != DDNS_UPDATE_STYLE_INTERIM))
goto cleanup;
/* Assume that we are removing both records */
@@ -1829,15 +1862,22 @@ ddns_removals(struct lease *lease,
}
/*
* Find the ptr name and copy it to the control block. If we don't
* have it this isn't an interim or rfc3??? record so we can't delete
* Find the txt or dhcid tag and copy it to the control block. If we don't
* have one this isn't an interim or standard record so we can't delete
* the A record using this mechanism but we can delete the ptr record.
* In this case we will attempt to do any requested next step.
*/
memset(&leaseid, 0, sizeof(leaseid));
if (!find_bound_string (&leaseid, *scope, "ddns-txt")) {
ddns_cb->flags &= ~DDNS_UPDATE_ADDR;
} else {
if (find_bound_string (&leaseid, *scope, ddns_standard_tag)) {
/* We have a standard tag */
ddns_cb->lease_tag = ddns_standard_tag;
ddns_cb->dhcid_class = dns_rdatatype_dhcid;
data_string_copy(&ddns_cb->dhcid, &leaseid, MDL);
data_string_forget(&leaseid, MDL);
} else if (find_bound_string (&leaseid, *scope, ddns_interim_tag)) {
/* we have an interim tag */
ddns_cb->lease_tag = ddns_interim_tag;
ddns_cb->dhcid_class = dns_rdatatype_txt;
if (dhcid_fromlease(&ddns_cb->dhcid, &leaseid) !=
ISC_R_SUCCESS) {
/* We couldn't convert the dhcid from the lease
@@ -1847,7 +1887,9 @@ ddns_removals(struct lease *lease,
ddns_cb->flags &= ~DDNS_UPDATE_ADDR;
}
data_string_forget(&leaseid, MDL);
}
} else {
ddns_cb->flags &= ~DDNS_UPDATE_ADDR;
}
/*
* Find the rev name and copy it to the control block. If we don't
@@ -1894,7 +1936,7 @@ ddns_removals(struct lease *lease,
else {
/*remove info from scope */
unset(*scope, "ddns-fwd-name");
unset(*scope, "ddns-txt");
unset(*scope, ddns_cb->lease_tag);
}
}