diff options
Diffstat (limited to 'server/ddns.c')
-rw-r--r-- | server/ddns.c | 174 |
1 files changed, 108 insertions, 66 deletions
diff --git a/server/ddns.c b/server/ddns.c index 74021fcd..4fc85aae 100644 --- a/server/ddns.c +++ b/server/ddns.c @@ -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. */ @@ -492,22 +479,68 @@ ddns_updates(struct packet *packet, struct lease *lease, struct lease *old, } /* + * 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); } } |