Commit b860910b authored by Ted Lemon's avatar Ted Lemon

Incorporate a bunch of changes from Brian Murrell.

parent 00763cc1
......@@ -25,7 +25,7 @@
#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"
......@@ -36,7 +36,14 @@ static char copyright[] =
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. */
......@@ -183,90 +190,153 @@ char *ddns_fwd_name(lease, state, packet)
#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;
}
......@@ -417,93 +487,99 @@ return;
}
#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: */
......@@ -22,7 +22,7 @@
#ifndef lint
static char copyright[] =
"$Id: tree.c,v 1.51 1999/09/24 19:04:30 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. All rights reserved.\n";
"$Id: tree.c,v 1.52 1999/10/04 23:15:43 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
......@@ -575,15 +575,16 @@ int evaluate_boolean_expression (result, packet, lease, in_options,
log_debug("calling updateA(%s, %s, %d, lease)",
expr1.data , expr2.data, ttl);
#endif
updateA(expr1, expr2, ttl, lease);
updateA(&expr1, &expr2, ttl, lease);
} else if (rrtype.len == 3 &&
strncmp((const char *)rrtype.data, "ptr", 3) == 0) {
strncmp((const char *)rrtype.data,
"ptr", 3) == 0) {
#if defined (DEBUG_EXPRESSIONS)
log_debug ("%s updatePTR(%s, %s, %d, lease)",
"calling", expr1.data,
expr2.data, ttl);
#endif
updatePTR(expr1, expr2, ttl, lease);
updatePTR(&expr1, &expr2, ttl, lease);
}
*result = 1;
} else {
......@@ -2182,3 +2183,4 @@ int write_expression (file, expr, col, indent)
}
return col;
}
/* vim: set tabstop=8: */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment