From: Ted Lemon Date: Mon, 4 Oct 1999 23:15:43 +0000 (+0000) Subject: Incorporate a bunch of changes from Brian Murrell. X-Git-Tag: V3-BETA-1-PATCH-2~5^2~13 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b860910b3595cc93f79f3c7c6f9a7d8e0424c11d;p=thirdparty%2Fdhcp.git Incorporate a bunch of changes from Brian Murrell. --- diff --git a/common/nsupdate.c b/common/nsupdate.c index f6b214706..3945f8596 100644 --- a/common/nsupdate.c +++ b/common/nsupdate.c @@ -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: */ diff --git a/common/tree.c b/common/tree.c index 55bc6b464..0e6dbbd9c 100644 --- a/common/tree.c +++ b/common/tree.c @@ -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: */