diff options
Diffstat (limited to 'server/ddns.c')
-rw-r--r-- | server/ddns.c | 275 |
1 files changed, 154 insertions, 121 deletions
diff --git a/server/ddns.c b/server/ddns.c index b1683c3..2387e04 100644 --- a/server/ddns.c +++ b/server/ddns.c @@ -125,10 +125,17 @@ ddns_updates(struct packet *packet, struct lease *lease, struct lease *old, } /* assume that we shall update both the A and ptr records */ ddns_cb->flags = DDNS_UPDATE_ADDR | DDNS_UPDATE_PTR; - + + /* + * For v4 we flag static leases so we don't try + * and manipulate the lease later. For v6 we don't + * get static leases and don't need to flag them. + */ if (lease != NULL) { scope = &(lease->scope); ddns_cb->address = lease->ip_addr; + if (lease->flags & STATIC_LEASE) + ddns_cb->flags |= DDNS_STATIC_LEASE; } else if (lease6 != NULL) { scope = &(lease6->scope); memcpy(ddns_cb->address.iabuf, lease6->addr.s6_addr, 16); @@ -725,6 +732,13 @@ ddns_update_lease_text(dhcp_ddns_cb_t *ddns_cb, struct in6_addr addr; struct data_string lease_dhcid; + /* + * If the lease was static (for a fixed address) + * we don't need to do any work. + */ + if (ddns_cb->flags & DDNS_STATIC_LEASE) + return (ISC_R_SUCCESS); + if (inscope != NULL) { scope = inscope; } else if (ddns_cb->address.len == 4) { @@ -838,8 +852,10 @@ update_lease_failed(struct lease *lease, sprintf(reason, "unknown"); sprintf(lease_address, "unknown"); - /* let's pretend that everything is ok, so we can continue for - for information gathering purposes */ + /* + * let's pretend that everything is ok, so we can continue for + * information gathering purposes + */ if (ddns_cb != NULL) { strncpy(lease_address, piaddr(ddns_cb->address), @@ -890,133 +906,138 @@ update_lease_failed(struct lease *lease, void safe_lease_update(struct lease *lease, - struct iasubopt *lease6, dhcp_ddns_cb_t *oldcb, dhcp_ddns_cb_t *newcb, const char *file, int line) { - char addrbuf[MAX_ADDRESS_STRING_LEN]; + if (lease == NULL) { + /* should never get here */ + log_fatal("Impossible condition at %s:%d (called from %s:%d).", + MDL, file, line); + } - if (lease != NULL) { - if ( (lease->ddns_cb == NULL) && (newcb == NULL) ) { - /* - * Trying to clean up pointer that is already null. We - * are most likely trying to update wrong lease here. - */ + if ( (lease->ddns_cb == NULL) && (newcb == NULL) ) { + /* + * Trying to clean up pointer that is already null. We + * are most likely trying to update wrong lease here. + */ - /* - * this error message pops out during every DNS Update - * for fixed leases. It is enabled only for debugging - * DNS Updates. Investigation pending. - */ -#if defined (DEBUG_DNS_UPDATES) - log_error("%s(%d): Invalid lease update. Tried to " - "clear already NULL DDNS control block " - "pointer for lease %s.", - file, line, piaddr(lease->ip_addr) ); -#endif + /* + * Previously this error message popped out during + * DNS update for fixed leases. As we no longer + * try to update the lease for a fixed (static) lease + * this should not be a problem. + */ + log_error("%s(%d): Invalid lease update. Tried to " + "clear already NULL DDNS control block " + "pointer for lease %s.", + file, line, piaddr(lease->ip_addr) ); #if defined (DNS_UPDATES_MEMORY_CHECKS) - update_lease_failed(lease, NULL, oldcb, newcb, file, - line); + update_lease_failed(lease, NULL, oldcb, newcb, file, line); #endif - /* - * May not reach this: update_lease_failed calls - * log_fatal. - */ - return; - } + /* + * May not reach this: update_lease_failed calls + * log_fatal. + */ + return; + } - if ( (lease->ddns_cb != NULL) && (lease->ddns_cb != oldcb) ) { - /* - * There is existing cb structure, but it differs from - * what we expected to see there. Most likely we are - * trying to update wrong lease. - */ - log_error("%s(%d): Failed to update internal lease " - "structure with DDNS control block. Existing" - " ddns_cb structure does not match " - "expectations.IPv4=%s, old ddns_cb=%p, tried" - "to update to new ddns_cb=%p", file, line, - piaddr(lease->ip_addr), oldcb, newcb); + if ( (lease->ddns_cb != NULL) && (lease->ddns_cb != oldcb) ) { + /* + * There is existing cb structure, but it differs from + * what we expected to see there. Most likely we are + * trying to update wrong lease. + */ + log_error("%s(%d): Failed to update internal lease " + "structure with DDNS control block. Existing" + " ddns_cb structure does not match " + "expectations.IPv4=%s, old ddns_cb=%p, tried" + "to update to new ddns_cb=%p", file, line, + piaddr(lease->ip_addr), oldcb, newcb); #if defined (DNS_UPDATES_MEMORY_CHECKS) - update_lease_failed(lease, NULL, oldcb, newcb, file, - line); + update_lease_failed(lease, NULL, oldcb, newcb, file, line); #endif - /* - * May not reach this: update_lease_failed calls - * log_fatal. - */ - return; - } - /* additional IPv4 specific checks may be added here */ + /* + * May not reach this: update_lease_failed calls + * log_fatal. + */ + return; + } - /* update the lease */ - lease->ddns_cb = newcb; - } else if (lease6 != NULL) { - if ( (lease6->ddns_cb == NULL) && (newcb == NULL) ) { - inet_ntop(AF_INET6, &lease6->addr, addrbuf, - MAX_ADDRESS_STRING_LEN); - /* - * Trying to clean up pointer that is already null. We - * are most likely trying to update wrong lease here. - */ -#if defined (DEBUG_DNS_UPDATES) - log_error("%s(%d): Failed to update internal lease " - "structure. Tried to clear already NULL " - "DDNS control block pointer for lease %s.", - file, line, addrbuf); -#endif + /* additional IPv4 specific checks may be added here */ + + /* update the lease */ + lease->ddns_cb = newcb; +} + +void +safe_lease6_update(struct iasubopt *lease6, + dhcp_ddns_cb_t *oldcb, + dhcp_ddns_cb_t *newcb, + const char *file, int line) +{ + char addrbuf[MAX_ADDRESS_STRING_LEN]; + + if (lease6 == NULL) { + /* should never get here */ + log_fatal("Impossible condition at %s:%d (called from %s:%d).", + MDL, file, line); + } + + if ( (lease6->ddns_cb == NULL) && (newcb == NULL) ) { + inet_ntop(AF_INET6, &lease6->addr, addrbuf, + MAX_ADDRESS_STRING_LEN); + /* + * Trying to clean up pointer that is already null. We + * are most likely trying to update wrong lease here. + */ + log_error("%s(%d): Failed to update internal lease " + "structure. Tried to clear already NULL " + "DDNS control block pointer for lease %s.", + file, line, addrbuf); #if defined (DNS_UPDATES_MEMORY_CHECKS) - update_lease_failed(NULL, lease6, oldcb, newcb, file, - line); + update_lease_failed(NULL, lease6, oldcb, newcb, file, line); #endif - /* - * May not reach this: update_lease_failed calls - * log_fatal. - */ - return; - } + /* + * May not reach this: update_lease_failed calls + * log_fatal. + */ + return; + } - if ( (lease6->ddns_cb != NULL) && (lease6->ddns_cb != oldcb) ) { - /* - * there is existing cb structure, but it differs from - * what we expected to see there. Most likely we are - * trying to update wrong lease. - */ - inet_ntop(AF_INET6, &lease6->addr, addrbuf, - MAX_ADDRESS_STRING_LEN); + if ( (lease6->ddns_cb != NULL) && (lease6->ddns_cb != oldcb) ) { + /* + * there is existing cb structure, but it differs from + * what we expected to see there. Most likely we are + * trying to update wrong lease. + */ + inet_ntop(AF_INET6, &lease6->addr, addrbuf, + MAX_ADDRESS_STRING_LEN); - log_error("%s(%d): Failed to update internal lease " - "structure with DDNS control block. Existing" - " ddns_cb structure does not match " - "expectations.IPv6=%s, old ddns_cb=%p, tried" - "to update to new ddns_cb=%p", file, line, - addrbuf, oldcb, newcb); + log_error("%s(%d): Failed to update internal lease " + "structure with DDNS control block. Existing" + " ddns_cb structure does not match " + "expectations.IPv6=%s, old ddns_cb=%p, tried" + "to update to new ddns_cb=%p", file, line, + addrbuf, oldcb, newcb); #if defined (DNS_UPDATES_MEMORY_CHECKS) - update_lease_failed(NULL, lease6, oldcb, newcb, file, - line); + update_lease_failed(NULL, lease6, oldcb, newcb, file, line); #endif - /* - * May not reach this: update_lease_failed calls - * log_fatal. - */ - return; - } - /* additional IPv6 specific checks may be added here */ - - /* update the lease */ - lease6->ddns_cb = newcb; - - } else { - /* should never get here */ - log_fatal("Impossible condition at %s:%d (called from %s:%d).", - MDL, file, line); + /* + * May not reach this: update_lease_failed calls + * log_fatal. + */ + return; } + /* additional IPv6 specific checks may be added here */ + + /* update the lease */ + lease6->ddns_cb = newcb; } /* @@ -1042,7 +1063,7 @@ ddns_update_lease_ptr(struct lease *lease, const char * file, int line) { char ddns_address[MAX_ADDRESS_STRING_LEN]; - sprintf(ddns_address, "uknown"); + sprintf(ddns_address, "unknown"); if (ddns_cb) { strncpy(ddns_address, piaddr(ddns_cb->address), MAX_ADDRESS_STRING_LEN); @@ -1052,14 +1073,23 @@ ddns_update_lease_ptr(struct lease *lease, file, line, ddns_cb, ddns_address ); #endif + /* + * If the lease was static (for a fixed address) + * we don't need to do any work. + */ + if (ddns_cb->flags & DDNS_STATIC_LEASE) { +#if defined (DEBUG_DNS_UPDATES) + log_info("lease is static, returning"); +#endif + return (ISC_R_SUCCESS); + } + if (lease != NULL) { - safe_lease_update(lease, NULL, ddns_cb, ddns_cb_set, + safe_lease_update(lease, ddns_cb, ddns_cb_set, file, line); - /* lease->ddns_cb = ddns_cb_set; */ } else if (lease6 != NULL) { - safe_lease_update(NULL, lease6, ddns_cb, ddns_cb_set, + safe_lease6_update(lease6, ddns_cb, ddns_cb_set, file, line); - /* lease6->ddns_cb = ddns_cb_set; */ } else if (ddns_cb->address.len == 4) { struct lease *find_lease = NULL; if (find_lease_by_ip_addr(&find_lease, @@ -1070,17 +1100,14 @@ ddns_update_lease_ptr(struct lease *lease, find_lease); #endif - /* find_lease->ddns_cb = ddns_cb_set; */ - safe_lease_update(find_lease, NULL, ddns_cb, + safe_lease_update(find_lease, ddns_cb, ddns_cb_set, file, line); lease_dereference(&find_lease, MDL); } else { -#if defined (DEBUG_DNS_UPDATES) log_error("%s(%d): ddns_update_lease_ptr failed. " - "Lease for %s not found. (Is it static lease?)", + "Lease for %s not found.", file, line, piaddr(ddns_cb->address)); -#endif #if defined (DNS_UPDATES_MEMORY_CHECKS) update_lease_failed(NULL, NULL, ddns_cb, ddns_cb_set, @@ -1119,7 +1146,7 @@ ddns_update_lease_ptr(struct lease *lease, return(ISC_R_FAILURE); } - if (iasubopt_hash_lookup(&find_lease6, pool->leases, + if (iasubopt_hash_lookup(&find_lease6, pool->leases, &addr, 16, MDL)) { find_lease6->ddns_cb = ddns_cb_set; iasubopt_dereference(&find_lease6, MDL); @@ -1591,18 +1618,24 @@ ddns_removals(struct lease *lease, } else if ((lease6 != NULL) && (lease6->ddns_cb != NULL)) { ddns_cancel(lease6->ddns_cb); lease6->ddns_cb = NULL; - } else - goto cleanup; + } /* allocate our control block */ ddns_cb = ddns_cb_alloc(MDL); if (ddns_cb == NULL) { goto cleanup; } - + + /* + * For v4 we flag static leases so we don't try + * and manipulate the lease later. For v6 we don't + * get static leases and don't need to flag them. + */ if (lease != NULL) { scope = &(lease->scope); ddns_cb->address = lease->ip_addr; + if (lease->flags & STATIC_LEASE) + ddns_cb->flags |= DDNS_STATIC_LEASE; } else if (lease6 != NULL) { scope = &(lease6->scope); memcpy(&ddns_cb->address.iabuf, lease6->addr.s6_addr, 16); @@ -1618,7 +1651,7 @@ ddns_removals(struct lease *lease, goto cleanup; /* Assume that we are removing both records */ - ddns_cb->flags = DDNS_UPDATE_ADDR | DDNS_UPDATE_PTR; + ddns_cb->flags |= DDNS_UPDATE_ADDR | DDNS_UPDATE_PTR; /* and that we want to do the add call */ execute_add = ISC_R_SUCCESS; |