diff options
author | Adam Tkac <atkac@redhat.com> | 2009-03-04 07:41:34 -0500 |
---|---|---|
committer | Martin Nagy <mnagy@redhat.com> | 2009-03-16 17:59:52 +0100 |
commit | eb177ee306596112f87c258edfe8ab98491ead03 (patch) | |
tree | 6939bca3e36580c7b0d87747ebd9282522a78f0e | |
parent | 07cbc887415530826581fb53fe215f8f7b1e959a (diff) | |
download | ldap_driver_testing-eb177ee306596112f87c258edfe8ab98491ead03.tar.gz ldap_driver_testing-eb177ee306596112f87c258edfe8ab98491ead03.tar.xz ldap_driver_testing-eb177ee306596112f87c258edfe8ab98491ead03.zip |
Implement addrdataset function.
-rw-r--r-- | ldap_driver.c | 226 |
1 files changed, 219 insertions, 7 deletions
diff --git a/ldap_driver.c b/ldap_driver.c index 9f80337..dfb7852 100644 --- a/ldap_driver.c +++ b/ldap_driver.c @@ -18,14 +18,17 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include <isc/buffer.h> #include <isc/mem.h> #include <isc/refcount.h> #include <isc/util.h> #include <dns/db.h> #include <dns/rdata.h> +#include <dns/rdataclass.h> #include <dns/rdatalist.h> #include <dns/rdataset.h> +#include <dns/rdatatype.h> #include <dns/result.h> #include <dns/types.h> @@ -69,6 +72,95 @@ static void *ldapdb_version = &dummy; static void free_ldapdb(ldapdb_t *ldapdb); static void detachnode(dns_db_t *db, dns_dbnode_t **targetp); +static isc_result_t +write_to_ldap(dns_name_t *owner, ldapdb_t *ldapdb, dns_rdatalist_t *rdlist) +{ + dns_rdata_t *rdata; + /* TODO - MINTSIZ is already defined in ldap_helper.c */ + #define MINTSIZ (65535 - 12 - 1 - 2 - 2 - 4 - 2) + isc_buffer_t *rdatatext = NULL; + isc_buffer_t *ownertext = NULL; + isc_buffer_t *classtext = NULL; + isc_buffer_t *typetext = NULL; + isc_result_t result; + /* Temporary and ugly debug hack. Should be MINTSIZ */ + char buf[1024]; + + result = isc_buffer_allocate(ldapdb->common.mctx, &rdatatext, 19999); + + if (result != ISC_R_SUCCESS) + return result; + + result = isc_buffer_allocate(ldapdb->common.mctx, &ownertext, + DNS_NAME_MAXWIRE + 1); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = isc_buffer_allocate(ldapdb->common.mctx, &classtext, + sizeof("CLASS65535")); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = isc_buffer_allocate(ldapdb->common.mctx, &typetext, + sizeof("TYPE65535")); + if (result != ISC_R_SUCCESS) + goto cleanup; + + rdata = HEAD(rdlist->rdata); + while (rdata != NULL) { + /* Debug hacking... Probably might be reused. */ + result = dns_name_totext(owner, ISC_FALSE, ownertext); + if (result != ISC_R_SUCCESS) + goto cleanup; + + *((char *)ownertext->base + isc_buffer_usedlength(ownertext)) = '\0'; + + result = dns_rdataclass_totext(rdlist->rdclass, classtext); + if (result != ISC_R_SUCCESS) + goto cleanup; + + *((char *)classtext->base + isc_buffer_usedlength(classtext)) = '\0'; + + result = dns_rdatatype_totext(rdlist->type, typetext); + if (result != ISC_R_SUCCESS) + goto cleanup; + + *((char *)typetext->base + isc_buffer_usedlength(typetext)) = '\0'; + + result = dns_rdata_totext(rdata, NULL, rdatatext); + if (result != ISC_R_SUCCESS) + goto cleanup; + + INSIST(isc_buffer_usedlength(rdatatext) < 1024); + memcpy(buf, rdatatext->base, 1024); + buf[isc_buffer_usedlength(rdatatext)] = '\0'; + log_debug(2, "Modifying %s %s %s %s.", ownertext->base, + classtext->base, typetext->base, buf); + rdata = NEXT(rdata, link); + } + +cleanup: + + if (typetext != NULL) + isc_buffer_free(&typetext); + + if (classtext != NULL) + isc_buffer_free(&classtext); + + if (ownertext != NULL) + isc_buffer_free(&ownertext); + + isc_buffer_free(&rdatatext); + + return result; +} + +static isc_result_t +remove_from_ldap(dns_name_t *owner, ldapdb_t *ldapdb, dns_rdatalist_t *rdlist) +{ + return write_to_ldap(owner, ldapdb, rdlist); +} + /* ldapdbnode_t functions */ static isc_result_t ldapdbnode_create(isc_mem_t *mctx, dns_name_t *owner, ldapdbnode_t **nodep) @@ -545,20 +637,136 @@ allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, return ISC_R_NOTIMPLEMENTED; } +/* + * Remove duplicates between rdlists. If rm_from1 == true then remove rdata + * from the first rdatalist. same rdata are removed from rdlist1 or 2 and are + * returned in diff. + */ +static void +rdatalist_removedups(dns_rdatalist_t *rdlist1, dns_rdatalist_t *rdlist2, + isc_boolean_t rm_from1, + dns_rdatalist_t *diff) +{ + dns_rdata_t *rdata1, *rdata2; + + rdata1 = HEAD(rdlist1->rdata); + while (rdata1 != NULL) { + rdata2 = HEAD(rdlist2->rdata); + while (rdata2 != NULL) { + if (dns_rdata_compare(rdata1, rdata2) == 0) { + /* same rdata has been found */ + if (rm_from1) { + APPEND(diff->rdata, rdata1, link); + ISC_LIST_UNLINK(rdlist1->rdata, rdata1, + link); + } else { + APPEND(diff->rdata, rdata2, link); + ISC_LIST_UNLINK(rdlist2->rdata, rdata2, + link); + } + break; + } + rdata2 = NEXT(rdata2, link); + } + rdata1 = NEXT(rdata1, link); + } +} + static isc_result_t addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options, dns_rdataset_t *addedrdataset) { - UNUSED(db); - UNUSED(node); - UNUSED(version); + ldapdbnode_t *ldapdbnode = (ldapdbnode_t *) node; + ldapdb_t *ldapdb = (ldapdb_t *) db; + dns_rdatalist_t *rdlist = NULL, *new_rdlist = NULL; + dns_rdatalist_t *found_rdlist = NULL; + dns_rdatalist_t diff; + isc_result_t result; + isc_boolean_t rdatalist_exists = ISC_FALSE; + UNUSED(now); - UNUSED(rdataset); - UNUSED(options); + UNUSED(db); UNUSED(addedrdataset); - return ISC_R_NOTIMPLEMENTED; + REQUIRE(VALID_LDAPDBNODE(ldapdbnode)); + /* version == NULL is valid only for cache databases */ + REQUIRE(version == ldapdb_version); + REQUIRE((options & DNS_DBADD_FORCE) == 0); + + dns_rdatalist_init(&diff); + + result = dns_rdatalist_fromrdataset(rdataset, &rdlist); + INSIST(result == ISC_R_SUCCESS); + INSIST(rdlist->rdclass == dns_rdataclass_in); + + result = rdatalist_clone(ldapdb->common.mctx, rdlist, &new_rdlist); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = ldapdb_rdatalist_findrdatatype(&ldapdbnode->rdatalist, + rdlist->type, &found_rdlist); + if (result == ISC_R_SUCCESS) { + rdatalist_exists = ISC_TRUE; + + if (rdlist->ttl != found_rdlist->ttl) { + /* + * TODO: support it. When supported handle + * DNS_DBADD_EXACTTTL option well. + */ + log_error("Multiple TTLs for one name are not " + "supported"); + result = ISC_R_NOTIMPLEMENTED; + goto cleanup; + } + + if ((options & DNS_DBADD_MERGE) != 0 || + (options & DNS_DBADD_EXACT) != 0) { + rdatalist_removedups(found_rdlist, new_rdlist, + ISC_FALSE, &diff); + + if ((options & DNS_DBADD_MERGE) != 0) + free_rdatalist(ldapdb->common.mctx, &diff); + else if (rdatalist_length(&diff) != 0) { + free_rdatalist(ldapdb->common.mctx, &diff); + result = DNS_R_NOTEXACT; + goto cleanup; + } + } else { + /* Replace existing rdataset */ + free_rdatalist(ldapdb->common.mctx, found_rdlist); + } + } + + result = write_to_ldap(&ldapdbnode->owner, ldapdb, new_rdlist); + if (result != ISC_R_SUCCESS) + goto cleanup; + + if (addedrdataset != NULL) { + result = dns_rdatalist_tordataset(new_rdlist, addedrdataset); + /* Use strong condition here, returns only SUCCESS */ + INSIST(result == ISC_R_SUCCESS); + } + + if (rdatalist_exists) { + ISC_LIST_APPENDLIST(found_rdlist->rdata, new_rdlist->rdata, + link); + isc_mem_put(ldapdb->common.mctx, new_rdlist, + sizeof(*new_rdlist)); + } else + APPEND(ldapdbnode->rdatalist, new_rdlist, link); + + + return ISC_R_SUCCESS; + +cleanup: + if (new_rdlist != NULL) { + free_rdatalist(ldapdb->common.mctx, new_rdlist); + isc_mem_put(ldapdb->common.mctx, new_rdlist, + sizeof(*new_rdlist)); + } + + return result; } static isc_result_t @@ -573,6 +781,8 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, UNUSED(options); UNUSED(newrdataset); + REQUIRE("subtractrdataset" == NULL); + return ISC_R_NOTIMPLEMENTED; } @@ -586,6 +796,8 @@ deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, UNUSED(type); UNUSED(covers); + REQUIRE("deleterdataset" == NULL); + return ISC_R_NOTIMPLEMENTED; } @@ -594,7 +806,7 @@ issecure(dns_db_t *db) { UNUSED(db); - return ISC_R_NOTIMPLEMENTED; + return ISC_FALSE; } static unsigned int |