[Freeipa-devel] [PATCH] bind-dyndb-ldap: Don't leave empty nodes in LDAP after DDNS update

Adam Tkac atkac at redhat.com
Wed Jan 12 12:37:12 UTC 2011


Hello,

bind-dyndb-ldap currently leaves empty nodes in LDAP when the last
DNS resource record associated with the node was removed:

Before DDNS update:

dn: idnsName=test,idnsName=example.com,ou=dns,dc=example,dc=com
aRecord: 1.1.1.1
dNSTTL: 1111
objectClass: idnsRecord
idnsName: test

After DDNS update (removal of "test.example.com A 1.1.1.1" record):

dn: idnsName=test,idnsName=example.com,ou=dns,dc=example,dc=com
dNSTTL: 1111
objectClass: idnsRecord
idnsName: test

As you can see this node is empty and useless.

With the patch the whole node is removed.

Comments are welcomed.

Regards, Adam

-- 
Adam Tkac, Red Hat, Inc.
-------------- next part --------------
>From 03f770ee1fa781092395c06f48888f7dd2059e90 Mon Sep 17 00:00:00 2001
From: Adam Tkac <atkac at redhat.com>
Date: Mon, 10 Jan 2011 15:25:40 +0100
Subject: [PATCH] Delete node from LDAP if there is no RR associated with the name.

If the last DNS resource record associated with the name is removed
then remove the whole node from LDAP.

Solves https://fedorahosted.org/bind-dyndb-ldap/ticket/1.

Signed-off-by: Adam Tkac <atkac at redhat.com>
---
 src/ldap_driver.c |   14 +++++++++++++-
 src/ldap_helper.c |   29 ++++++++++++++++++-----------
 src/ldap_helper.h |    2 +-
 3 files changed, 32 insertions(+), 13 deletions(-)

diff --git a/src/ldap_driver.c b/src/ldap_driver.c
index 965877c..9c1da40 100644
--- a/src/ldap_driver.c
+++ b/src/ldap_driver.c
@@ -787,6 +787,7 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
 	dns_rdatalist_t *rdlist;
 	dns_rdatalist_t diff;
 	isc_result_t result;
+	isc_boolean_t delete_node = ISC_FALSE;
 
 	REQUIRE(version == ldapdb_version);
 
@@ -822,7 +823,18 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
 		goto cleanup;
 	}
 
-	CHECK(remove_from_ldap(&ldapdbnode->owner, ldapdb->ldap_inst, &diff));
+	/*
+	 * If there is only one rdatalist in the node with no rdata
+	 * it means all resource records associated with the node's DNS
+	 * name (owner) was deleted. So delete the whole node from the
+	 * LDAP.
+	 */
+	if (HEAD(ldapdbnode->rdatalist) == TAIL(ldapdbnode->rdatalist) &&
+	    HEAD((HEAD(ldapdbnode->rdatalist))->rdata) == NULL)
+		delete_node = ISC_TRUE;
+
+	CHECK(remove_from_ldap(&ldapdbnode->owner, ldapdb->ldap_inst, &diff,
+			       delete_node));
 	CHECK(discard_from_cache(ldapdb->ldap_cache, &ldapdbnode->owner));
 
 	if (newrdataset != NULL) {
diff --git a/src/ldap_helper.c b/src/ldap_helper.c
index 67f6567..a6235b3 100644
--- a/src/ldap_helper.c
+++ b/src/ldap_helper.c
@@ -259,7 +259,7 @@ static isc_result_t ldap_query(ldap_connection_t *ldap_conn, const char *base,
 
 /* Functions for writing to LDAP. */
 static isc_result_t ldap_modify_do(ldap_connection_t *ldap_conn, const char *dn,
-		LDAPMod **mods);
+		LDAPMod **mods, isc_result_t delete_node);
 static isc_result_t ldap_rdttl_to_ldapmod(isc_mem_t *mctx,
 		dns_rdatalist_t *rdlist, LDAPMod **changep);
 static isc_result_t ldap_rdatalist_to_ldapmod(isc_mem_t *mctx,
@@ -269,7 +269,7 @@ static isc_result_t ldap_rdata_to_char_array(isc_mem_t *mctx,
 		dns_rdata_t *rdata_head, char ***valsp);
 static void free_char_array(isc_mem_t *mctx, char ***valsp);
 static isc_result_t modify_ldap_common(dns_name_t *owner, ldap_instance_t *ldap_inst,
-		dns_rdatalist_t *rdlist, int mod_op);
+		dns_rdatalist_t *rdlist, int mod_op, isc_boolean_t delete_node);
 
 isc_result_t
 new_ldap_instance(isc_mem_t *mctx, const char *db_name,
@@ -1732,7 +1732,8 @@ handle_connection_error(ldap_connection_t *ldap_conn, isc_result_t *result)
 
 /* FIXME: Handle the case where the LDAP handle is NULL -> try to reconnect. */
 static isc_result_t
-ldap_modify_do(ldap_connection_t *ldap_conn, const char *dn, LDAPMod **mods)
+ldap_modify_do(ldap_connection_t *ldap_conn, const char *dn, LDAPMod **mods,
+	       isc_boolean_t delete_node)
 {
 	int ret;
 	int err_code;
@@ -1742,9 +1743,14 @@ ldap_modify_do(ldap_connection_t *ldap_conn, const char *dn, LDAPMod **mods)
 	REQUIRE(dn != NULL);
 	REQUIRE(mods != NULL);
 
-	log_debug(2, "writing to '%s'", dn);
+	if (delete_node) {
+		log_debug(2, "deleting whole node: '%s'", dn);
+		ret = ldap_delete_ext_s(ldap_conn->handle, dn, NULL, NULL);
+	} else {
+		log_debug(2, "writing to '%s'", dn);
+		ret = ldap_modify_ext_s(ldap_conn->handle, dn, mods, NULL, NULL);
+	}
 
-	ret = ldap_modify_ext_s(ldap_conn->handle, dn, mods, NULL, NULL);
 	if (ret == LDAP_SUCCESS)
 		return ISC_R_SUCCESS;
 
@@ -1990,14 +1996,14 @@ modify_soa_record(ldap_connection_t *ldap_conn, const char *zone_dn,
 
 	dns_rdata_freestruct((void *)&soa);
 
-	return ldap_modify_do(ldap_conn, zone_dn, changep);
+	return ldap_modify_do(ldap_conn, zone_dn, changep, ISC_FALSE);
 
 #undef SET_LDAP_MOD
 }
 
 static isc_result_t
 modify_ldap_common(dns_name_t *owner, ldap_instance_t *ldap_inst,
-		   dns_rdatalist_t *rdlist, int mod_op)
+		   dns_rdatalist_t *rdlist, int mod_op, isc_boolean_t delete_node)
 {
 	isc_result_t result;
 	isc_mem_t *mctx = ldap_inst->mctx;
@@ -2025,7 +2031,7 @@ modify_ldap_common(dns_name_t *owner, ldap_instance_t *ldap_inst,
 		CHECK(ldap_rdttl_to_ldapmod(mctx, rdlist, &change[1]));
 	}
 
-	CHECK(ldap_modify_do(ldap_conn, str_buf(owner_dn), change));
+	CHECK(ldap_modify_do(ldap_conn, str_buf(owner_dn), change, delete_node));
 
 cleanup:
 	put_connection(ldap_conn);
@@ -2039,12 +2045,13 @@ cleanup:
 isc_result_t
 write_to_ldap(dns_name_t *owner, ldap_instance_t *ldap_inst, dns_rdatalist_t *rdlist)
 {
-	return modify_ldap_common(owner, ldap_inst, rdlist, LDAP_MOD_ADD);
+	return modify_ldap_common(owner, ldap_inst, rdlist, LDAP_MOD_ADD, ISC_FALSE);
 }
 
 isc_result_t
 remove_from_ldap(dns_name_t *owner, ldap_instance_t *ldap_inst,
-		 dns_rdatalist_t *rdlist)
+		 dns_rdatalist_t *rdlist, isc_boolean_t delete_node)
 {
-	return modify_ldap_common(owner, ldap_inst, rdlist, LDAP_MOD_DELETE);
+	return modify_ldap_common(owner, ldap_inst, rdlist, LDAP_MOD_DELETE,
+				  delete_node);
 }
diff --git a/src/ldap_helper.h b/src/ldap_helper.h
index 594af43..887a059 100644
--- a/src/ldap_helper.h
+++ b/src/ldap_helper.h
@@ -105,6 +105,6 @@ refresh_zones_from_ldap(ldap_instance_t *ldap_inst, isc_boolean_t create);
 isc_result_t write_to_ldap(dns_name_t *owner, ldap_instance_t *ldap_inst,
 		dns_rdatalist_t *rdlist);
 isc_result_t remove_from_ldap(dns_name_t *owner, ldap_instance_t *ldap_inst,
-		dns_rdatalist_t *rdlist);
+		dns_rdatalist_t *rdlist, isc_boolean_t delete_node);
 
 #endif /* !_LD_LDAP_HELPER_H_ */
-- 
1.7.3.4



More information about the Freeipa-devel mailing list