#ifndef lint
static char copyright[] =
-"$Id: nsupdate.c,v 1.8 1999/09/16 01:14:52 mellon Exp $ Copyright (c) 1999 The Internet Software Consortium. All rights reserved.\n";
+"$Id: nsupdate.c,v 1.9 1999/10/04 23:14:58 mellon Exp $ Copyright (c) 1999 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
done. This can be done by figuring out the hostname.domain and revname
and then comparing them to the lease->ddns* values. Only make the changes
necessary which can be any combination and number of remove A, add A,
- remove PTR, add PTR */
+ remove PTR, add PTR.
+
+ Wed Sep 29 02:06:33 PDT 1999
+ SCRAP THAT! Let the DNS server determine whether an add/delete should
+ be done by giving it pre-requisites to the add/delete.
+ */
+
+#define NAME(x) (x) ? (char *)(x) : "(null)"
#if 0
/* Return the reverse name of a lease. */
#endif
return hostname;
}
-#endif
+#endif /* 0 */
-static int nsupdateA(hostname, ip_addr, ttl, opcode)
- char *hostname;
- unsigned char *ip_addr;
+int nsupdateA (hostname, ip_addr, ttl, opcode)
+ const char *hostname;
+ const unsigned char *ip_addr;
u_int32_t ttl;
- int opcode;
+ int opcode;
{
- int z;
- ns_updrec *u, *n;
+ int z;
+ ns_updrec *p, *u;
+
+ /* set up update section */
+ if (!(u = res_mkupdrec (S_UPDATE, hostname, C_IN, T_A, ttl)))
+ return 0;
+ u -> r_opcode = opcode;
+ u -> r_data = (char *)ip_addr;
+
+#if 0 /* no PREREQUISITES are needed for adds and deletes, as there is no zone
+ churn when you add a record that exists or delete a record that
+ doesn't exist */
+
+ /* set up the prerequisite section */
+ if (!(p = res_mkupdrec (S_PREREQ, hostname, C_IN, T_A, 0))) {
+ res_freeupdrec (u);
+ return 0;
+ }
+ p -> r_next = u;
+ p -> r_data = (char *)ip_addr;
+#endif
switch (opcode) {
- case ADD:
- if (!(u = res_mkupdrec(S_PREREQ, hostname, C_IN, T_A, 0)))
- return 0;
- u->r_opcode = NXRRSET; u->r_data = NULL; u->r_size = 0;
- if (!(n = res_mkupdrec(S_UPDATE, hostname, C_IN, T_A, ttl))) {
- res_freeupdrec(u);
+ case ADD:
+ if (!ip_addr) { /* can't have NULL ip_addr for an ADD */
+#if 0
+ res_freeupdrec (p);
+#endif
+ res_freeupdrec (u);
return 0;
}
- n->r_opcode = opcode;
- n->r_data = ip_addr;
- n->r_size = strlen((const char *)n->r_data);
- u->r_next = n;
- z = res_update(u);
- log_info("add %s: %s %d IN A %s",
- z == 1 ? "succeeded" : "failed", hostname, ttl,
- n->r_data);
- res_freeupdrec(u);
- res_freeupdrec(n);
-/* do we really need to do this? If so, it needs to be done elsewehere as
- this function is strictly for manipulating the A record
- if (z < 1)
- return 0;
-*/
- /* delete all PTR RRs with the same ip address. Wow! */
-/*
- if (!(u = res_mkupdrec(S_UPDATE, revname, C_IN, T_PTR, 0)))
- return 0;
- u->r_opcode = DELETE; u->r_data = NULL; u->r_size = 0;
- log_info("cleaning all PTR RRs for %s", revname);
- res_update(u);
- res_freeupdrec(u);
-*/
+#if 0
+ /* PREQUISITE: add only if the RR is not there already */
+ p -> r_opcode = NXRRSET;
+ p -> r_size = strlen ((const char *)p -> r_data);
+#endif
+ u -> r_size = strlen ((const char *)u -> r_data);
break;
- case DELETE:
- ttl = 0;
- if (!(u = res_mkupdrec(S_UPDATE, hostname, C_IN, T_A, ttl)))
- return 0;
- u->r_opcode = opcode;
- u->r_data = ip_addr;
- u->r_size = strlen((const char *)u->r_data);
- z = res_update(u);
- log_info("delete %s: %s %d IN A %s",
- z == 1 ? "succeeded" : "failed",
- hostname, ttl, u->r_data);
- res_freeupdrec(u);
+ case DELETE:
+ ttl = 0; /* delete updates ALWAYS have a 0 TTL */
+#if 0
+ /* PREQUISITE: delete only if the RR to be deleted is there */
+ p -> r_opcode = YXRRSET;
+#endif
+ /* NOTE: ip_addr could be NULL for a "DELETE all records" */
+ if (u -> r_data) {
+#if 0
+ p -> r_size = strlen ((const char *)n -> r_data);
+#endif
+ u -> r_size = strlen ((const char *)u -> r_data);
+ } else {
+#if 0
+ p -> r_size = 0;
+#endif
+ u -> r_size = 0;
+ }
break;
}
+ z = res_update (u);
+ log_info ("%s %s: %s %d IN A %s", opcode == ADD ? "add" : "delete",
+ z == 1 ? "succeeded" : "failed", NAME (hostname), ttl,
+ NAME (u -> r_data));
+#if 0
+ res_freeupdrec (p);
+#endif
+ res_freeupdrec (u);
return z;
}
-static int nsupdatePTR(revname, hostname, ttl, opcode)
- unsigned char *hostname;
- char *revname;
+int nsupdatePTR (revname, hostname, ttl, opcode)
+ const char *revname;
+ const unsigned char *hostname;
u_int32_t ttl;
- int opcode;
+ int opcode;
{
- int z;
- ns_updrec *u;
+ int z;
+ ns_updrec *u, *p;
- if (opcode == DELETE)
- ttl = 0;
- if (!(u = res_mkupdrec(S_UPDATE, revname, C_IN, T_PTR, ttl)))
+ /* set up update section */
+ if (!(u = res_mkupdrec (S_UPDATE, revname, C_IN, T_PTR, ttl)))
+ return 0;
+ u -> r_opcode = opcode;
+ u -> r_data = (char *)hostname;
+
+#if 0 /* don't need PREREQUISITES */
+ /* set up the prerequisite section */
+ if (!(p = res_mkupdrec (S_PREREQ, revname, C_IN, T_PTR, 0))) {
+ res_freeupdrec (u);
return 0;
- u->r_opcode = opcode;
- u->r_data = hostname;
- u->r_size = strlen((const char *)u->r_data);
+ }
+ p -> r_next = u;
+ p -> r_data = (char *)hostname;
+#endif
+
+ switch (opcode) {
+ case ADD:
+ if (!hostname) { /* can't have NULL ip_addr for an ADD */
+#if 0
+ res_freeupdrec (p);
+#endif
+ res_freeupdrec (u);
+ return 0;
+ }
+#if 0
+ /* PREQUISITE: add only if the RR is not there already */
+ p -> r_opcode = NXRRSET;
+ p -> r_size = strlen ((const char *)p -> r_data);
+#endif
+ u -> r_size = strlen ((const char *)u -> r_data);
+
+ break;
+ case DELETE:
+ ttl = 0; /* delete updates ALWAYS have a 0 TTL */
+#if 0
+ /* PREQUISITE: delete only if the RR to be deleted is there */
+ p->r_opcode = YXRRSET;
+ /* NOTE: hostname could be NULL for a "DELETE all records" */
+#endif
+ if (u -> r_data) {
+#if 0
+ p -> r_size = strlen ((const char *)p -> r_data);
+#endif
+ u -> r_size = strlen ((const char *)u -> r_data);
+ } else {
+#if 0
+ p -> r_size = 0;
+#endif
+ u -> r_size = 0;
+ }
+ break;
+ }
z = res_update(u);
- log_info("%s %s: %s %d IN PTR %s",
- opcode == ADD ? "add" :
- "delete", z == 1 ? "succeeded" : "failed",
- revname, ttl, hostname);
- res_freeupdrec(u);
+ log_info ("%s %s: %s %d IN PTR %s", opcode == ADD ? "add" :
+ "delete", z == 1 ? "succeeded" : "failed",
+ NAME (revname), ttl, NAME (u -> r_data));
+#if 0
+ res_freeupdrec (p);
+#endif
+ res_freeupdrec (u);
return z;
}
}
#endif
-/* public function to update an A record if needed */
-int updateA(struct data_string *lhs, struct data_string *rhs, unsigned int ttl,
- struct lease *lease)
+/* public function to update an A record */
+int updateA (lhs, rhs, ttl, lease)
+ const struct data_string *lhs;
+ const struct data_string *rhs;
+ unsigned int ttl;
+ struct lease *lease;
{
static char hostname[MAXDNAME];
static char ipaddr[MAXDNAME];
+ int y;
hostname[0] = '\0';
- strncat(hostname, (const char *)lhs->data, lhs->len);
- hostname[lhs->len] = '\0';
+ strncat(hostname, (const char *)lhs -> data, lhs -> len);
+ hostname[lhs -> len] = '\0';
ipaddr[0] = '\0';
- strncat(ipaddr, (const char *)rhs->data, rhs->len);
- ipaddr[rhs->len] = '\0';
-
- /* delete an existing A if the one to be added is different */
- if (lease -> ddns_fwd_name &&
- strcmp(hostname, lease -> ddns_fwd_name)) {
- int y;
- y=nsupdateA(lease -> ddns_fwd_name, ipaddr, 0, DELETE);
-
- if (y) {
- /* clear the forward DNS name pointer */
- if (lease -> ddns_fwd_name)
- dfree(lease -> ddns_fwd_name, "nsupdate");
- lease -> ddns_fwd_name = 0;
- }
- }
- /* only update if there is no A record there already */
- if (!lease -> ddns_fwd_name) {
- int y;
- y=nsupdateA(hostname, ipaddr, ttl, ADD);
- if (y < 1)
- return 0;
+ strncat(ipaddr, (const char *)rhs -> data, rhs -> len);
+ ipaddr[rhs -> len] = '\0';
+
+#if 0 /* Wrong! This causes zone churn on every DHCPREQUEST!
+ Besides, it is perfectly legal for a DHCP client to have more
+ than one lease, if (say) it was being served by two+ DHCP servers
+ serving the same subnet with different (i.e. disjoint) pools.
+ The right thing to do is have the A records cleaned by either a
+ DHCPRELEASE or the lease expiry. */
+
+ /* delete all existing A records for this host */
+ nsupdateA (hostname, NULL, 0, DELETE);
+#endif
- /* remember this in the lease structure for release */
- lease -> ddns_fwd_name = dmalloc(strlen(hostname) + 1,
- "nsupdate");
- strcpy (lease -> ddns_fwd_name, hostname);
- }
+ /* clear the forward DNS name pointer */
+ if (lease -> ddns_fwd_name)
+ dfree (lease -> ddns_fwd_name, "nsupdate");
+ lease -> ddns_fwd_name = 0;
+
+ y=nsupdateA (hostname, ipaddr, ttl, ADD);
+ if (y < 1)
+ return 0;
+
+ /* remember this in the lease structure for release */
+ lease -> ddns_fwd_name = dmalloc (strlen(hostname) + 1, "nsupdate");
+ strcpy (lease -> ddns_fwd_name, hostname);
return 1;
}
-/* public function to update an A record if needed */
-int updatePTR(struct data_string *lhs, struct data_string *rhs,
- unsigned int ttl, struct lease *lease)
+/* public function to update an PTR record */
+int updatePTR (lhs, rhs, ttl, lease)
+ const struct data_string *lhs;
+ const struct data_string *rhs;
+ unsigned int ttl;
+ struct lease *lease;
{
static char hostname[MAXDNAME];
static char revname[MAXDNAME];
+ int y;
revname[0] = '\0';
- strncat(revname, (const char *)lhs->data, lhs->len);
- revname[lhs->len] = '\0';
+ strncat(revname, (const char *)lhs -> data, lhs -> len);
+ revname[lhs -> len] = '\0';
hostname[0] = '\0';
- strncat(hostname, (const char *)rhs->data, rhs->len);
- hostname[rhs->len] = '\0';
-
- /* delete an existing PTR if the one to be added is different */
- if (lease -> ddns_rev_name &&
- strcmp(revname, lease -> ddns_rev_name)) {
- int y;
- y=nsupdatePTR(revname, hostname, 0, DELETE);
-
- if (y) {
- /* clear the reverse DNS name pointer */
- if (lease -> ddns_rev_name)
- dfree(lease -> ddns_rev_name, "nsupdate");
- lease -> ddns_rev_name = 0;
- }
- }
- /* only update if there is no PTR record there already */
- if (!lease -> ddns_rev_name) {
- int y;
- y=nsupdatePTR(revname, hostname, ttl, ADD);
- if (y < 1)
- return 0;
+ strncat(hostname, (const char *)rhs -> data, rhs -> len);
+ hostname[rhs -> len] = '\0';
+
+#if 0 /* Wrong! This causes zone churn on every DHCPREQUEST!
+ Besides, it is perfectly legal for a DHCP client to have more
+ than one lease, if (say) it was being served by two+ DHCP servers
+ serving the same subnet with different (i.e. disjoint) pools.
+ The right thing to do is have the PTR records cleaned by either a
+ DHCPRELEASE or the lease expiry. */
+
+ /* delete all existing PTR records */
+ nsupdatePTR (revname, NULL, 0, DELETE);
+#endif
- /* remember this in the lease structure for release */
- lease -> ddns_rev_name = dmalloc(strlen(revname) + 1,
- "nsupdate");
- strcpy (lease -> ddns_rev_name, revname);
- }
+ /* clear the reverse DNS name pointer */
+ if (lease -> ddns_rev_name)
+ dfree (lease -> ddns_rev_name, "nsupdate");
+ lease -> ddns_rev_name = 0;
+
+ y=nsupdatePTR (revname, hostname, ttl, ADD);
+ if (y < 1)
+ return 0;
+
+ /* remember this in the lease structure for release */
+ lease -> ddns_rev_name = dmalloc (strlen(revname) + 1, "nsupdate");
+ strcpy (lease -> ddns_rev_name, revname);
return 1;
}
#endif /* defined (NSUPDATE) */
+
+/* vim: set tabstop=8: */