#ifndef lint
static char copyright[] =
-"$Id: ddns.c,v 1.4 2001/01/04 00:08:16 mellon Exp $ Copyright (c) 2000-2001 The Internet Software Consortium. All rights reserved.\n";
+"$Id: ddns.c,v 1.5 2001/01/06 21:37:21 mellon Exp $ Copyright (c) 2000-2001 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
binding -> value -> value.data.len);
value -> data = value -> buffer -> data;
value -> len = binding -> value -> value.data.len;
-
- data_string_forget (&binding -> value -> value.data, MDL);
- data_string_copy (&binding -> value -> value.data, value, MDL);
}
return 1;
static ns_rcode ddns_update_a (struct data_string *ddns_fwd_name,
- struct data_string *ddns_address,
+ struct iaddr ddns_addr,
struct data_string *ddns_dhcid,
unsigned long ttl)
{
ns_updque updqueue;
ns_updrec *updrec;
ns_rcode result;
+ char ddns_address [16];
+
+ if (ddns_addr.len != 4)
+ return SERVFAIL;
+#ifndef NO_SNPRINTF
+ snprintf (ddns_address, 16, "%d.%d.%d.%d",
+ ddns_addr.iabuf[0], ddns_addr.iabuf[1],
+ ddns_addr.iabuf[2], ddns_addr.iabuf[3]);
+#else
+ sprintf (ddns_address, "%d.%d.%d.%d",
+ ddns_addr.iabuf[0], ddns_addr.iabuf[1],
+ ddns_addr.iabuf[2], ddns_addr.iabuf[3]);
+#endif
/*
* When a DHCP client or server intends to update an A RR, it first
C_IN, T_A, ttl);
if (!updrec) goto error;
- updrec -> r_data = ddns_address -> buffer -> data;
- updrec -> r_size = ddns_address -> len;
+ updrec -> r_data = ddns_address;
+ updrec -> r_size = strlen (ddns_address);
updrec -> r_opcode = ADD;
ISC_LIST_APPEND (updqueue, updrec, r_link);
C_IN, T_A, ttl);
if (!updrec) goto error;
- updrec -> r_data = ddns_address -> buffer -> data;
- updrec -> r_size = ddns_address -> len;
+ updrec -> r_data = ddns_address;
+ updrec -> r_size = strlen (ddns_address);
updrec -> r_opcode = ADD;
ISC_LIST_APPEND (updqueue, updrec, r_link);
static ns_rcode ddns_update_ptr (struct data_string *ddns_fwd_name,
struct data_string *ddns_rev_name,
- struct data_string *ddns_dhcid,
unsigned long ttl)
{
ns_updque updqueue;
ISC_LIST_APPEND (updqueue, updrec, r_link);
-
/*
* Add PTR RR.
*/
ISC_LIST_APPEND (updqueue, updrec, r_link);
-
- /*
- * Add DHCID RR.
- */
- updrec = minires_mkupdrec (S_UPDATE, ddns_rev_name -> data,
- C_IN, T_DHCID,ttl);
- if (!updrec) goto error;
-
- updrec -> r_data = ddns_dhcid -> buffer -> data;
- updrec -> r_size = ddns_dhcid -> len;
- updrec -> r_opcode = ADD;
-
- ISC_LIST_APPEND (updqueue, updrec, r_link);
-
-
/*
* Attempt to perform the update.
*/
static ns_rcode ddns_remove_a (struct data_string *ddns_fwd_name,
- struct data_string *ddns_address,
+ struct iaddr ddns_addr,
struct data_string *ddns_dhcid)
{
ns_updque updqueue;
ns_updrec *updrec;
ns_rcode result = SERVFAIL;
+ char ddns_address [16];
+
+ if (ddns_addr.len != 4)
+ return SERVFAIL;
+
+#ifndef NO_SNPRINTF
+ snprintf (ddns_address, 16, "%d.%d.%d.%d",
+ ddns_addr.iabuf[0], ddns_addr.iabuf[1],
+ ddns_addr.iabuf[2], ddns_addr.iabuf[3]);
+#else
+ sprintf (ddns_address, "%d.%d.%d.%d",
+ ddns_addr.iabuf[0], ddns_addr.iabuf[1],
+ ddns_addr.iabuf[2], ddns_addr.iabuf[3]);
+#endif
+
/*
* The entity chosen to handle the A record for this client (either the
C_IN, T_A, 0);
if (!updrec) goto error;
- updrec -> r_data = ddns_address -> buffer -> data;
- updrec -> r_size = ddns_address -> len;
+ updrec -> r_data = ddns_address;
+ updrec -> r_size = strlen (ddns_address);
updrec -> r_opcode = YXRRSET;
ISC_LIST_APPEND (updqueue, updrec, r_link);
C_IN, T_A, 0);
if (!updrec) goto error;
- updrec -> r_data = ddns_address -> buffer -> data;
- updrec -> r_size = ddns_address -> len;
+ updrec -> r_data = ddns_address;
+ updrec -> r_size = strlen (ddns_address);
updrec -> r_opcode = DELETE;
ISC_LIST_APPEND (updqueue, updrec, r_link);
-
- /*
- * Delete appropriate DHCID RR.
- */
- updrec = minires_mkupdrec (S_UPDATE, ddns_fwd_name -> data,
- C_IN, T_DHCID, 0);
- if (!updrec) goto error;
-
- updrec -> r_data = ddns_dhcid -> buffer -> data;
- updrec -> r_size = ddns_dhcid -> len;
- updrec -> r_opcode = DELETE;
-
- ISC_LIST_APPEND (updqueue, updrec, r_link);
-
-
/*
* Attempt to perform the update.
*/
* -- "Interaction between DHCP and DNS"
*/
+ if (result != NOERROR)
+ goto error;
+
+ while (!ISC_LIST_EMPTY (updqueue)) {
+ updrec = ISC_LIST_HEAD (updqueue);
+ ISC_LIST_UNLINK (updqueue, updrec, r_link);
+ minires_freeupdrec (updrec);
+ }
+
+ /* If the deletion of the A succeeded, and there are no A records
+ left for this domain, then we can blow away the DHCID record
+ as well. We can't blow away the DHCID record above because
+ it's possible that more than one A has been added to this
+ domain name. */
+ ISC_LIST_INIT (updqueue);
+
+ /*
+ * A RR does not exist.
+ */
+ updrec = minires_mkupdrec (S_PREREQ, ddns_fwd_name -> data,
+ C_IN, T_A, 0);
+ if (!updrec) goto error;
+
+ updrec -> r_data = (char *)0;
+ updrec -> r_size = 0;
+ updrec -> r_opcode = NXRRSET;
+
+ ISC_LIST_APPEND (updqueue, updrec, r_link);
+
+ /*
+ * Delete appropriate DHCID RR.
+ */
+ updrec = minires_mkupdrec (S_UPDATE, ddns_fwd_name -> data,
+ C_IN, T_DHCID, 0);
+ if (!updrec)
+ goto error;
+
+ updrec -> r_data = ddns_dhcid -> buffer -> data;
+ updrec -> r_size = ddns_dhcid -> len;
+ updrec -> r_opcode = DELETE;
+
+ ISC_LIST_APPEND (updqueue, updrec, r_link);
+
+ /*
+ * Attempt to perform the update.
+ */
+ result = minires_nupdate (&resolver_state, ISC_LIST_HEAD (updqueue));
+ print_dns_status ((int)result, &updqueue);
/* Fall through. */
error:
static ns_rcode ddns_remove_ptr (struct data_string *ddns_fwd_name,
- struct data_string *ddns_rev_name,
- struct data_string *ddns_dhcid)
+ struct data_string *ddns_rev_name)
{
ns_updque updqueue;
ns_updrec *updrec;
ISC_LIST_APPEND (updqueue, updrec, r_link);
-
- /*
- * Delete appropriate DHCID RR.
- */
- updrec = minires_mkupdrec (S_UPDATE, ddns_rev_name -> data,
- C_IN, T_DHCID, 0);
- if (!updrec) goto error;
-
- updrec -> r_data = ddns_dhcid -> buffer -> data;
- updrec -> r_size = ddns_dhcid -> len;
- updrec -> r_opcode = DELETE;
-
- ISC_LIST_APPEND (updqueue, updrec, r_link);
-
-
/*
* Attempt to perform the update.
*/
struct data_string ddns_domainname;
struct data_string ddns_fwd_name;
struct data_string ddns_rev_name;
- struct data_string ddns_address;
struct data_string ddns_dhcid;
unsigned len;
- unsigned ddns_address_len = 0;
struct data_string d1;
struct option_cache *oc;
int s1, s2;
memset (&ddns_domainname, 0, sizeof (ddns_domainname));
memset (&ddns_fwd_name, 0, sizeof (ddns_fwd_name));
memset (&ddns_rev_name, 0, sizeof (ddns_rev_name));
- memset (&ddns_address, 0, sizeof (ddns_address));
memset (&ddns_dhcid, 0, sizeof (ddns_dhcid));
}
}
-
- /*
- * Look up the lease IP address (as a string).
- */
- /* XXX.XXX.XXX.XXX\0 = 16 characters. */
- buffer_allocate (&ddns_address.buffer, 16, MDL);
-
-#ifndef NO_SNPRINTF
- snprintf (ddns_address.buffer -> data, 16,
- "%d.%d.%d.%d",
- lease -> ip_addr . iabuf[0],
- lease -> ip_addr . iabuf[1],
- lease -> ip_addr . iabuf[2],
- lease -> ip_addr . iabuf[3]);
-#else
- sprintf (ddns_address.buffer -> data,
- "%d.%d.%d.%d",
- lease -> ip_addr . iabuf[0],
- lease -> ip_addr . iabuf[1],
- lease -> ip_addr . iabuf[2],
- lease -> ip_addr . iabuf[3]);
-#endif
- ddns_address.data = ddns_address.buffer -> data;
- ddns_address.len = strlen (ddns_address.data);
- ddns_address.terminated = 1;
-
-
/*
* Look up the reverse IP name.
*/
data_string_forget (&d1, MDL);
}
-
/*
* Look up the DHCID value. (Should this be cached in the lease?)
*/
memset (&ddns_dhcid, 0, sizeof ddns_dhcid);
get_dhcid (&ddns_dhcid, lease);
-
/*
* Start the resolver, if necessary.
*/
resolver_inited = 1;
}
-
/*
* Perform updates.
*/
- if (ddns_fwd_name.len && ddns_address.len && ddns_dhcid.len)
- rcode1 = ddns_update_a(&ddns_fwd_name, &ddns_address,
- &ddns_dhcid, ddns_ttl);
+ if (ddns_fwd_name.len && ddns_dhcid.len)
+ rcode1 = ddns_update_a (&ddns_fwd_name, lease -> ip_addr,
+ &ddns_dhcid, ddns_ttl);
- if (ddns_fwd_name.len && ddns_rev_name.len && ddns_dhcid.len)
- rcode2 = ddns_update_ptr(&ddns_fwd_name, &ddns_rev_name,
- &ddns_dhcid, ddns_ttl);
+ if (rcode1 == NOERROR) {
+ if (ddns_fwd_name.len && ddns_rev_name.len && ddns_dhcid.len)
+ rcode2 = ddns_update_ptr (&ddns_fwd_name,
+ &ddns_rev_name, ddns_ttl);
+ } else
+ rcode2 = SERVFAIL;
/* minires_update() can return -1 under certain circumstances. */
if (rcode1 == -1)
if (rcode2 == -1)
rcode2 = SERVFAIL;
- if (rcode1 == NOERROR || rcode2 == NOERROR) {
+ if (rcode1 == NOERROR) {
bind_ds_value (&lease -> scope, "ddns-fwd-name",
&ddns_fwd_name);
bind_ds_value (&lease -> scope, "ddns-dhcid",
&ddns_dhcid);
}
- if (rcode1 == NOERROR) {
- bind_ds_value (&lease -> scope, "ddns-address",
- &ddns_address);
- }
+
if (rcode2 == NOERROR) {
bind_ds_value (&lease -> scope, "ddns-rev-name",
&ddns_rev_name);
data_string_forget (&ddns_domainname, MDL);
data_string_forget (&ddns_fwd_name, MDL);
data_string_forget (&ddns_rev_name, MDL);
- data_string_forget (&ddns_address, MDL);
data_string_forget (&ddns_dhcid, MDL);
return rcode1 == NOERROR || rcode2 == NOERROR;
{
struct data_string ddns_fwd_name;
struct data_string ddns_rev_name;
- struct data_string ddns_address;
struct data_string ddns_dhcid;
ns_rcode rcode;
struct binding *binding;
- if (ddns_update_style != 2)
- return 1;
-
/* No scope implies that DDNS has not been performed for this lease. */
if (!lease -> scope)
return 1;
*/
memset (&ddns_fwd_name, 0, sizeof (ddns_fwd_name));
memset (&ddns_rev_name, 0, sizeof (ddns_rev_name));
- memset (&ddns_address, 0, sizeof (ddns_address));
memset (&ddns_dhcid, 0, sizeof (ddns_dhcid));
- find_bound_string (&ddns_fwd_name, lease -> scope, "ddns-fwd-name");
- find_bound_string (&ddns_rev_name, lease -> scope, "ddns-rev-name");
- find_bound_string (&ddns_address, lease -> scope, "ddns-address");
- find_bound_string (&ddns_dhcid, lease -> scope, "ddns-dhcid");
+ /* If all the bindings aren't there (ddns-dhcid being the crucial
+ one), this isn't an interim or rfc3??? record, so we can't do
+ the delete using this mechanism. */
+ if (!find_bound_string (&ddns_fwd_name,
+ lease -> scope, "ddns-fwd-name") ||
+ !find_bound_string (&ddns_rev_name,
+ lease -> scope, "ddns-rev-name") ||
+ !find_bound_string (&ddns_dhcid, lease -> scope, "ddns-dhcid")) {
+ data_string_forget (&ddns_fwd_name, MDL);
+ data_string_forget (&ddns_rev_name, MDL);
+ data_string_forget (&ddns_dhcid, MDL);
+ return 1;
+ }
/*
* Start the resolver, if necessary.
resolver_inited = 1;
}
-
/*
* Perform removals.
*/
- if (ddns_fwd_name.len && ddns_address.len && ddns_dhcid.len) {
- rcode = ddns_remove_a (&ddns_fwd_name, &ddns_address,
+ if (ddns_fwd_name.len && ddns_dhcid.len) {
+ rcode = ddns_remove_a (&ddns_fwd_name, lease -> ip_addr,
&ddns_dhcid);
}
- if (ddns_fwd_name.len && ddns_rev_name.len && ddns_dhcid.len) {
- rcode = ddns_remove_ptr(&ddns_fwd_name, &ddns_rev_name,
- &ddns_dhcid);
+ if (rcode != NOERROR &&
+ ddns_fwd_name.len && ddns_rev_name.len) {
+ rcode = ddns_remove_ptr(&ddns_fwd_name, &ddns_rev_name);
}
unset (lease -> scope, "ddns-fwd-name");
unset (lease -> scope, "ddns-rev-name");
- unset (lease -> scope, "ddns-address");
unset (lease -> scope, "ddns-dhcid");
data_string_forget (&ddns_fwd_name, MDL);
data_string_forget (&ddns_rev_name, MDL);
- data_string_forget (&ddns_address, MDL);
data_string_forget (&ddns_dhcid, MDL);