Hello, this patch set adds meta-database which is one of prerequisites for other work.
These changes should not be user-visible. You might compile the plugin with CFLAGS="-DMETADB_DEBUG" and check contect of /tmp/metadb.db after BIND shutdown. Please see https://fedorahosted.org/bind-dyndb-ldap/ticket/151 https://fedorahosted.org/bind-dyndb-ldap/wiki/Design/MetaDB for further information and let me know if you can help you somehow. -- Petr^2 Spacek
From cb7f1aef90d356b195ddae46e3841627234e9208 Mon Sep 17 00:00:00 2001 From: Petr Spacek <pspa...@redhat.com> Date: Wed, 29 Apr 2015 11:13:41 +0200 Subject: [PATCH] Add LDAP UUID -> meta-database name mapping function. https://fedorahosted.org/bind-dyndb-ldap/ticket/151 --- configure.ac | 2 ++ src/Makefile.am | 2 ++ src/mldap.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/mldap.h | 11 ++++++++++ 4 files changed, 83 insertions(+) create mode 100644 src/mldap.c create mode 100644 src/mldap.h diff --git a/configure.ac b/configure.ac index 9026f6d70fb008813681ab3f3eb51e9e2fec7be0..d7e64772e43a743d75d1b63b05fabe45acefb12d 100644 --- a/configure.ac +++ b/configure.ac @@ -73,6 +73,8 @@ AC_CHECK_LIB([ldap], [ldap_initialize], [], AC_MSG_ERROR([Install OpenLDAP development files])) AC_CHECK_LIB([krb5], [krb5_cc_initialize], [], AC_MSG_ERROR([Install Kerberos 5 development files])) +AC_CHECK_LIB([uuid], [uuid_unparse], [], + AC_MSG_ERROR([Install UUID library development files])) # Check version of libdns AC_MSG_CHECKING([libdns version]) diff --git a/src/Makefile.am b/src/Makefile.am index 73aa8a3afa1bea0e63a0ac04ca13f58e4ad512cf..68ddba87582e0e590e51ad05782d18a8fdcfbcd0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -13,6 +13,7 @@ HDRS = \ ldap_helper.h \ lock.h \ log.h \ + mldap.h \ rbt_helper.h \ rdlist.h \ semaphore.h \ @@ -38,6 +39,7 @@ ldap_la_SOURCES = \ ldap_helper.c \ lock.c \ log.c \ + mldap.c \ rbt_helper.c \ rdlist.c \ semaphore.c \ diff --git a/src/mldap.c b/src/mldap.c new file mode 100644 index 0000000000000000000000000000000000000000..0b2d0db43624131fc569b05e1492fbc6a7f68c30 --- /dev/null +++ b/src/mldap.c @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2015 bind-dyndb-ldap authors; see COPYING for license + * + * Meta-database for LDAP-specific information which are not represented in + * DNS data. + */ + +#include <ldap.h> +#include <stddef.h> +#include <uuid/uuid.h> + +#include <isc/result.h> +#include <isc/util.h> + +#include <dns/name.h> + +#include "mldap.h" +#include "util.h" + +/* name "ldap.uuid." */ +static unsigned char uuid_rootname_ndata[] + = { 4, 'u', 'u', 'i', 'd', 4, 'l', 'd', 'a', 'p', 0 }; +static unsigned char uuid_rootname_offsets[] = { 0, 5, 10 }; +static dns_name_t uuid_rootname = +{ + DNS_NAME_MAGIC, + uuid_rootname_ndata, + sizeof(uuid_rootname_ndata), + sizeof(uuid_rootname_offsets), + DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, + uuid_rootname_offsets, + NULL, + { (void *)-1, (void *)-1 }, + { NULL, NULL } +}; + +/** + * Convert UUID to "01234567-89ab-cdef-0123-456789abcdef.uuid.ldap." DNS name. + * + * @param[in] beruuid + * @param[out] nameuuid + */ +void +ldap_uuid_to_mname(struct berval *beruuid, dns_name_t *nameuuid) { + /* UUID string representation according to RFC 4122 section 3 */ + char label_buf[sizeof("01234567-89ab-cdef-0123-456789abcdef") + 1]; + /* uncompressed label format, length 36 octets; RFC 1034 section 3.1 */ + label_buf[0] = 36; + + isc_region_t label_reg; + label_reg.base = (unsigned char *)label_buf; + label_reg.length = sizeof(label_buf) - 1; /* omit final \0 */ + + dns_name_t relative_name; + DNS_NAME_INIT(&relative_name, NULL); + + /* RFC 4530 section 2.1 format = 16 octets is required */ + REQUIRE(beruuid != NULL && beruuid->bv_len == 16); + + /* fill-in string representation into label buffer */ + uuid_unparse((*(const uuid_t *) beruuid->bv_val), label_buf + 1); + dns_name_fromregion(&relative_name, &label_reg); + + INSIST(dns_name_concatenate(&relative_name, &uuid_rootname, + nameuuid, NULL) == ISC_R_SUCCESS); + + return; +} diff --git a/src/mldap.h b/src/mldap.h new file mode 100644 index 0000000000000000000000000000000000000000..dcf2556326ccea5037b32e71ab5da216f0f44ba4 --- /dev/null +++ b/src/mldap.h @@ -0,0 +1,11 @@ +/* + * Copyright (C) 2015 bind-dyndb-ldap authors; see COPYING for license + */ + +#ifndef SRC_MLDAP_H_ +#define SRC_MLDAP_H_ + +void +ldap_uuid_to_mname(struct berval *beruuid, dns_name_t *nameuuid); + +#endif /* SRC_MLDAP_H_ */ -- 2.1.0
From 7c556a58ff4fb919c089f3f65ad2ed8d415a1fa0 Mon Sep 17 00:00:00 2001 From: Petr Spacek <pspa...@redhat.com> Date: Tue, 12 May 2015 13:04:41 +0200 Subject: [PATCH] Add basic infratructure for generic meta-database. https://fedorahosted.org/bind-dyndb-ldap/ticket/151 --- src/Makefile.am | 2 + src/metadb.c | 256 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/metadb.h | 52 ++++++++++++ 3 files changed, 310 insertions(+) create mode 100644 src/metadb.c create mode 100644 src/metadb.h diff --git a/src/Makefile.am b/src/Makefile.am index 68ddba87582e0e590e51ad05782d18a8fdcfbcd0..aaa72063230a34d9aa0fca4b799309a89815db09 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -13,6 +13,7 @@ HDRS = \ ldap_helper.h \ lock.h \ log.h \ + metadb.h \ mldap.h \ rbt_helper.h \ rdlist.h \ @@ -39,6 +40,7 @@ ldap_la_SOURCES = \ ldap_helper.c \ lock.c \ log.c \ + metadb.c \ mldap.c \ rbt_helper.c \ rdlist.c \ diff --git a/src/metadb.c b/src/metadb.c new file mode 100644 index 0000000000000000000000000000000000000000..bbde3a85fed233ad35a2c81f0c0dbf0b530638df --- /dev/null +++ b/src/metadb.c @@ -0,0 +1,256 @@ +/* + * Copyright (C) 2015 bind-dyndb-ldap authors; see COPYING for license + * + * Meta-database for information which are not represented in DNS data. + */ + +#include <isc/mutex.h> +#include <isc/util.h> + +#include <dns/db.h> +#include <dns/rdatalist.h> + +#include "metadb.h" +#include "util.h" + +struct metadb { + isc_mem_t *mctx; + dns_db_t *rbtdb; + + /** Upcoming RBTDB version. */ + dns_dbversion_t *newversion; + + /** + * Guard for newversion. Only one RBTDB version can be open + * for writing at any time. See functions newversion and closeversion. + */ + isc_mutex_t newversion_lock; +}; + +/** + * Initialize new empty meta-database backed by RBT DB. + */ +isc_result_t +metadb_new(isc_mem_t *mctx, metadb_t **mdbp) { + isc_result_t result; + metadb_t *mdb = NULL; + isc_boolean_t lock_ready = ISC_FALSE; + + REQUIRE(mdbp != NULL && *mdbp == NULL); + + CHECKED_MEM_GET_PTR(mctx, mdb); + ZERO_PTR(mdb); + + isc_mem_attach(mctx, &mdb->mctx); + + CHECK(isc_mutex_init(&mdb->newversion_lock)); + lock_ready = ISC_TRUE; + CHECK(dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone, + dns_rdataclass_in, 0, NULL, &mdb->rbtdb)); + + *mdbp = mdb; + return result; + +cleanup: + if (mdb != NULL) { + if (lock_ready == ISC_TRUE) + RUNTIME_CHECK(isc_mutex_destroy(&mdb->newversion_lock) + == ISC_R_SUCCESS); + MEM_PUT_AND_DETACH(mdb); + } + return result; +} + +/** + * Destroy meta-database. + * All write-able versions have to be closed before calling destroy(). + */ +void +metadb_destroy(metadb_t **mdbp) { + metadb_t *mdb; + + REQUIRE(mdbp != NULL && *mdbp != NULL); + + mdb = *mdbp; + +#ifdef METADB_DEBUG + dns_db_dump(mdb->rbtdb, NULL, "/tmp/mdb.db"); +#endif + dns_db_detach(&mdb->rbtdb); + RUNTIME_CHECK(isc_mutex_destroy(&mdb->newversion_lock) == ISC_R_SUCCESS); + MEM_PUT_AND_DETACH(mdb); + + *mdbp = NULL; +} + +/** + * Open new metaDB version for writing. + * + * @warning metaDB should be modified only from single thread! + * + * @waning Only one writeable version can be open at any time. Purpose of the + * lock is to detect misuse and prevent immediate crashes + * but it does not change properties of underlying RBT DB. + */ +isc_result_t +metadb_newversion(metadb_t *mdb) { + isc_result_t result; + + if (isc_mutex_trylock(&mdb->newversion_lock) != ISC_R_SUCCESS) { + log_bug("mdb newversion_lock is not open"); + LOCK(&mdb->newversion_lock); + } + CHECK(dns_db_newversion(mdb->rbtdb, &mdb->newversion)); + +cleanup: + if (result != ISC_R_SUCCESS) + UNLOCK(&mdb->newversion_lock); + return result; +} + +/** + * Close writeable metaDB version and commit/discard all changes. + * + * @pre All metaDB nodes have to be closed before calling + * closeversion(commit = ISC_TRUE). + */ +void +metadb_closeversion(metadb_t *mdb, isc_boolean_t commit) { + UNLOCK(&mdb->newversion_lock); + dns_db_closeversion(mdb->rbtdb, &mdb->newversion, commit); +} + +/** + * Close metaDB node and detach associated DB version. All changes will be lost + * if this was the last reference to particular metaDB version. + */ +void +metadb_node_close(metadb_node_t **nodep) { + metadb_node_t *node; + + REQUIRE(nodep != NULL); + + node = *nodep; + if (node == NULL) + return; + + if (node->rbtdb != NULL) { + if (node->dbnode != NULL) + dns_db_detachnode(node->rbtdb, &node->dbnode); + if (node->version != NULL) + dns_db_closeversion(node->rbtdb, &node->version, + ISC_FALSE); + dns_db_detach(&node->rbtdb); + } + MEM_PUT_AND_DETACH(node); + *nodep = NULL; +} + +/** + * Create new "metaDB node" structure and attach underlying RBT DB node to it. + * + * @param[in] version Underlying RBTDB version to use. + * @param[in] mname Name of the node in metaDB. E.g. '1234.uuid.ldap.' + * @param[in] create RBTDB node will be created if it does not exist. + * @param[out] nodep Resulting "metaDB node" structure. It has to be freed + * using metadb_node_close(). + */ +static isc_result_t +metadb_node_init(metadb_t *mdb, dns_dbversion_t *ver, dns_name_t *mname, + isc_boolean_t create, metadb_node_t **nodep) { + isc_result_t result; + metadb_node_t *node = NULL; + + REQUIRE(nodep != NULL && *nodep == NULL); + + CHECKED_MEM_GET_PTR(mdb->mctx, node); + ZERO_PTR(node); + + isc_mem_attach(mdb->mctx, &node->mctx); + dns_db_attach(mdb->rbtdb, &node->rbtdb); + dns_db_attachversion(mdb->rbtdb, ver, &node->version); + CHECK(dns_db_findnode(mdb->rbtdb, mname, create, &node->dbnode)); + + *nodep = node; + return ISC_R_SUCCESS; + +cleanup: + metadb_node_close(&node); + return result; +} + +/** + * Create new "metaDB node" structure and attach current read-only version of + * RBT DB to it. + * + * @param[in] mname Name of the node in metaDB. E.g. '1234.uuid.ldap.' + * @param[out] nodep Resulting "metaDB node" structure. Node has to be freed + * using metadb_node_close(). + */ +isc_result_t +metadb_readnode_open(metadb_t *mdb, dns_name_t *mname, metadb_node_t **nodep) { + isc_result_t result; + dns_dbversion_t *ver = NULL; + + dns_db_currentversion(mdb->rbtdb, &ver); + CHECK(metadb_node_init(mdb, ver, mname, ISC_FALSE, nodep)); + +cleanup: + dns_db_closeversion(mdb->rbtdb, &ver, ISC_FALSE); + return result; +} + +/** + * Create new "metaDB node" structure and attach current writeable version of + * RBT DB to it. + * + * @param[in] mname Name of the node in metaDB. E.g. '1234.uuid.ldap.' + * @param[out] nodep Resulting "metaDB node" structure. Node has to be freed + * using metadb_node_close(). + * + * @pre MetaDB was opened by newversion(). + */ +isc_result_t +metadb_writenode_create(metadb_t *mdb, dns_name_t *mname, metadb_node_t **nodep) { + isc_result_t result; + dns_dbversion_t *ver = NULL; + + INSIST(mdb->newversion != NULL); + dns_db_attachversion(mdb->rbtdb, mdb->newversion, &ver); + CHECK(metadb_node_init(mdb, ver, mname, ISC_TRUE, nodep)); + +cleanup: + dns_db_closeversion(mdb->rbtdb, &ver, ISC_FALSE); + return result; +} + +/** + * Store rdata into metaDB node and overwrite all existing values for RR type + * specified in rdata. + * + * @pre Node was created by metadb_writenode_create(). + */ +isc_result_t +metadb_rdata_store(dns_rdata_t *rdata, metadb_node_t *node) { + isc_result_t result; + dns_rdatalist_t rdatalist; + dns_rdataset_t rdataset; + + dns_rdatalist_init(&rdatalist); + rdatalist.rdclass = rdata->rdclass; + rdatalist.type = rdata->type; + dns_rdataset_init(&rdataset); + APPEND(rdatalist.rdata, rdata, link); + + RUNTIME_CHECK(dns_rdatalist_tordataset(&rdatalist, &rdataset) + == ISC_R_SUCCESS); + /* DNS_DBADD_MERGE flag is not set - old rdataset will be replaced. */ + CHECK(dns_db_addrdataset(node->rbtdb, node->dbnode, node->version, 0, &rdataset, 0, NULL)); + +cleanup: + if (dns_rdataset_isassociated(&rdataset)) + dns_rdataset_disassociate(&rdataset); + if (result == DNS_R_UNCHANGED) + result = ISC_R_SUCCESS; + return result; +} diff --git a/src/metadb.h b/src/metadb.h new file mode 100644 index 0000000000000000000000000000000000000000..c49ac0dc2db46b8e62820d2e907b77bf82e59c2f --- /dev/null +++ b/src/metadb.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2015 bind-dyndb-ldap authors; see COPYING for license + * + * Meta-database for information which are not represented in DNS data. + */ + +#ifndef SRC_METADB_H_ +#define SRC_METADB_H_ + +#include "util.h" + + +/** + * All-in-one structure for metaDB operations. Version guarantees that node + * content visible to metadb_node user will not change asynchronously + * as long as metaDB 'version' is modified in the same thread. + */ +struct metadb_node { + isc_mem_t *mctx; + dns_db_t *rbtdb; + dns_dbversion_t *version; + dns_dbnode_t *dbnode; +}; + +typedef struct metadb_node metadb_node_t; +typedef struct metadb metadb_t; + +isc_result_t +metadb_new(isc_mem_t *mctx, metadb_t **dbp) ATTR_CHECKRESULT ATTR_NONNULLS; + +void +metadb_destroy(metadb_t **dbp); + +isc_result_t ATTR_CHECKRESULT ATTR_NONNULLS +metadb_newversion(metadb_t *mdb); + +void ATTR_NONNULLS +metadb_closeversion(metadb_t *mdb, isc_boolean_t commit); + +isc_result_t ATTR_CHECKRESULT ATTR_NONNULLS +metadb_readnode_open(metadb_t *mdb, dns_name_t *mname, metadb_node_t **nodep); + +isc_result_t ATTR_CHECKRESULT ATTR_NONNULLS +metadb_writenode_create(metadb_t *mdb, dns_name_t *mname, metadb_node_t **nodep); + +isc_result_t ATTR_CHECKRESULT ATTR_NONNULLS +metadb_rdata_store(dns_rdata_t *rdata, metadb_node_t *node); + +void ATTR_NONNULLS +metadb_node_close(metadb_node_t **nodep); + +#endif /* SRC_METADB_H_ */ -- 2.1.0
From 3c49145a7834c9913deb076cb74d18ecb8992a65 Mon Sep 17 00:00:00 2001 From: Petr Spacek <pspa...@redhat.com> Date: Tue, 12 May 2015 13:25:18 +0200 Subject: [PATCH] Add static (compile-time) assert macro. --- src/util.h | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/util.h b/src/util.h index 69b5d2a0a0803d8194a255638777d06654fa80ea..1f92df8e900bc0871cec5245ad51967d8642c537 100644 --- a/src/util.h +++ b/src/util.h @@ -127,4 +127,38 @@ extern isc_boolean_t verbose_checks; /* from settings.c */ #define ATTR_CHECKRESULT #endif +/* + * Static (compile-time) assert for C: + * C99 doesn't require support for "sizeof" in preprocessor conditionals so + * we can't do something like #if (sizeof(my_struct) != 512). + * + * This macro has no runtime side affects as it just defines an enum whose name + * depends on the current line, and whose value will give a divide by zero error + * at compile time if the assertion is false. + * + * Taken from + * http://www.pixelbeat.org/programming/gcc/static_assert.html + * version 10 Feb 2015. Padraig Brady told me that it is licensed under + * "GNU All-Permissive License": + * + * Copying and distribution of this file, with or without modification, + * are permitted in any medium without royalty provided the copyright notice + * and this notice are preserved. This code is offered as-is, + * without any warranty. + */ +#define ASSERT_CONCAT_(a, b) a##b +#define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b) +/* These can't be used after statements in c89. */ +#ifdef __COUNTER__ + #define STATIC_ASSERT(e, m) \ + ;enum { ASSERT_CONCAT(static_assert_, __COUNTER__) = 1/(!!(e)) } +#else + /* This can't be used twice on the same line so ensure if using in headers + * that the headers are not included twice (by wrapping in #ifndef...#endif) + * Note it doesn't cause an issue when used on same line of separate modules + * compiled with gcc -combine -fwhole-program. */ + #define STATIC_ASSERT(e, m) \ + ;enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1/(!!(e)) } +#endif + #endif /* !_LD_UTIL_H_ */ -- 2.1.0
From 3f05f0378bc9d7ae273cc7b707e39165f457c960 Mon Sep 17 00:00:00 2001 From: Petr Spacek <pspa...@redhat.com> Date: Tue, 12 May 2015 13:27:43 +0200 Subject: [PATCH] Add basic infratructure for LDAP meta-database. https://fedorahosted.org/bind-dyndb-ldap/ticket/151 --- src/mldap.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/mldap.h | 16 +++++++++++++++- 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/src/mldap.c b/src/mldap.c index 0b2d0db43624131fc569b05e1492fbc6a7f68c30..057247497366e20ce19c008bae4495ca96ee1ee6 100644 --- a/src/mldap.c +++ b/src/mldap.c @@ -12,8 +12,12 @@ #include <isc/result.h> #include <isc/util.h> +#include <dns/db.h> +#include <dns/enumclass.h> #include <dns/name.h> +#include <dns/types.h> +#include "metadb.h" #include "mldap.h" #include "util.h" @@ -34,6 +38,63 @@ static dns_name_t uuid_rootname = { NULL, NULL } }; +struct mldapdb { + isc_mem_t *mctx; + metadb_t *mdb; + isc_uint32_t generation; +}; + + +isc_result_t +mldap_new(isc_mem_t *mctx, mldapdb_t **mldapp) { + isc_result_t result; + mldapdb_t *mldap = NULL; + + REQUIRE(mldapp != NULL && *mldapp == NULL); + + CHECKED_MEM_GET_PTR(mctx, mldap); + ZERO_PTR(mldap); + isc_mem_attach(mctx, &mldap->mctx); + + CHECK(metadb_new(mctx, &mldap->mdb)); + mldap->generation = 0; + + *mldapp = mldap; + return result; + +cleanup: + metadb_destroy(&mldap->mdb); + MEM_PUT_AND_DETACH(mldap); + return result; +} + +void +mldap_destroy(mldapdb_t **mldapp) { + mldapdb_t *mldap; + + REQUIRE(mldapp != NULL && *mldapp != NULL); + + mldap = *mldapp; + if (mldap == NULL) + return; + + metadb_destroy(&mldap->mdb); + MEM_PUT_AND_DETACH(mldap); + + *mldapp = NULL; +} + + +isc_result_t +mldap_newversion(mldapdb_t *mldap) { + return metadb_newversion(mldap->mdb); +} + +void +mldap_closeversion(mldapdb_t *mldap, isc_boolean_t commit) { + return metadb_closeversion(mldap->mdb, commit); +} + /** * Convert UUID to "01234567-89ab-cdef-0123-456789abcdef.uuid.ldap." DNS name. * diff --git a/src/mldap.h b/src/mldap.h index dcf2556326ccea5037b32e71ab5da216f0f44ba4..e14964619a7ac50a248d00ff414cf11d5b056989 100644 --- a/src/mldap.h +++ b/src/mldap.h @@ -5,7 +5,21 @@ #ifndef SRC_MLDAP_H_ #define SRC_MLDAP_H_ +#include "metadb.h" +#include "util.h" + +typedef struct mldapdb mldapdb_t; + +isc_result_t ATTR_CHECKRESULT ATTR_NONNULLS +mldap_new(isc_mem_t *mctx, mldapdb_t **dbp); + void -ldap_uuid_to_mname(struct berval *beruuid, dns_name_t *nameuuid); +mldap_destroy(mldapdb_t **dbp); + +isc_result_t ATTR_CHECKRESULT ATTR_NONNULLS +mldap_newversion(mldapdb_t *mldap); + +void ATTR_NONNULLS +mldap_closeversion(mldapdb_t *mldap, isc_boolean_t commit); #endif /* SRC_MLDAP_H_ */ -- 2.1.0
From f6cf9e49d5f5c9a8863e872c80a2bb3cae2fe1f4 Mon Sep 17 00:00:00 2001 From: Petr Spacek <pspa...@redhat.com> Date: Tue, 12 May 2015 13:28:32 +0200 Subject: [PATCH] Add functions for populating LDAP meta-database. https://fedorahosted.org/bind-dyndb-ldap/ticket/151 --- src/mldap.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- src/mldap.h | 6 ++++ 2 files changed, 116 insertions(+), 1 deletion(-) diff --git a/src/mldap.c b/src/mldap.c index 057247497366e20ce19c008bae4495ca96ee1ee6..2b06ec6a11d6ada37aea1bee177b3201d16be7e2 100644 --- a/src/mldap.c +++ b/src/mldap.c @@ -9,14 +9,16 @@ #include <stddef.h> #include <uuid/uuid.h> +#include <isc/boolean.h> +#include <isc/net.h> #include <isc/result.h> -#include <isc/util.h> #include <dns/db.h> #include <dns/enumclass.h> #include <dns/name.h> #include <dns/types.h> +#include "ldap_entry.h" #include "metadb.h" #include "mldap.h" #include "util.h" @@ -127,3 +129,110 @@ ldap_uuid_to_mname(struct berval *beruuid, dns_name_t *nameuuid) { return; } + +STATIC_ASSERT((sizeof(ldap_entryclass_t) <= sizeof(struct in6_addr)), \ + "ldap_entryclass_t is too big for AAAA rdata type"); +/** + * ldap_entryclass_t is stored inside AAAA record type + */ +static isc_result_t +mldap_class_store(ldap_entryclass_t class, metadb_node_t *node) { + unsigned char buff[sizeof(struct in6_addr)]; + isc_region_t region = { .base = buff, .length = sizeof(buff) }; + dns_rdata_t rdata; + + dns_rdata_init(&rdata); + memset(buff, 0, sizeof(buff)); + + /* Bytes should be in network-order but we do not care because: + * 1) It is used only internally. 2) Class is unsigned char. */ + memcpy(buff, &class, sizeof(class)); + dns_rdata_fromregion(&rdata, dns_rdataclass_in, dns_rdatatype_aaaa, + ®ion); + + return metadb_rdata_store(&rdata, node); +} + + +STATIC_ASSERT((sizeof(((mldapdb_t *)0)->generation) == sizeof(struct in_addr)), \ + "mldapdb_t->generation is too big for A rdata type"); +/** + * mldapdb_t->generation is stored inside A record type + */ +static isc_result_t +mldap_generation_store(mldapdb_t *mldap, metadb_node_t *node) { + isc_result_t result; + unsigned char buff[sizeof(mldap->generation)]; + isc_region_t region = { .base = buff, .length = sizeof(buff) }; + dns_rdata_t rdata; + + dns_rdata_init(&rdata); + + /* Bytes should be in network-order but we do not care because: + * 1) It is used only internally and always compared on this machine. */ + memcpy(buff, &mldap->generation, sizeof(mldap->generation)); + dns_rdata_fromregion(&rdata, dns_rdataclass_in, dns_rdatatype_a, ®ion); + CHECK(metadb_rdata_store(&rdata, node)); + +cleanup: + return result; +} + +/** + * FQDN and zone name are stored inside RP record type + */ +isc_result_t +mldap_dnsname_store(dns_name_t *fqdn, dns_name_t *zone, metadb_node_t *node) { + isc_result_t result; + dns_rdata_rp_t rp; + dns_rdata_t rdata; + unsigned char wirebuf[2 * DNS_NAME_MAXWIRE]; + isc_buffer_t rdatabuf; + + REQUIRE(fqdn != NULL); + REQUIRE(zone != NULL); + + dns_rdata_init(&rdata); + DNS_RDATACOMMON_INIT(&rp, dns_rdatatype_rp, dns_rdataclass_in); + isc_buffer_init(&rdatabuf, wirebuf, sizeof(wirebuf)); + + /* Bytes should be in network-order but we do not care because: + * 1) It is used only internally and always compared on this machine. */ + rp.mail = *fqdn; + rp.text = *zone; + CHECK(dns_rdata_fromstruct(&rdata, dns_rdataclass_in, dns_rdatatype_rp, + &rp, &rdatabuf)); + CHECK(metadb_rdata_store(&rdata, node)); + +cleanup: + return result; +} + +/** + * Store information from LDAP entry into meta-database. + */ +isc_result_t +mldap_entry_create(ldap_entry_t *entry, mldapdb_t *mldap, metadb_node_t **nodep) { + isc_result_t result; + ldap_entryclass_t class; + metadb_node_t *node = NULL; + DECLARE_BUFFERED_NAME(mname); + + REQUIRE(nodep != NULL && *nodep == NULL); + + INIT_BUFFERED_NAME(mname); + + ldap_uuid_to_mname(entry->uuid, &mname); + CHECK(metadb_writenode_create(mldap->mdb, &mname, &node)); + + CHECK(ldap_entry_getclass(entry, &class)); + CHECK(mldap_class_store(class, node)); + CHECK(mldap_generation_store(mldap, node)); + + *nodep = node; + +cleanup: + if (result != ISC_R_SUCCESS) + metadb_node_close(&node); + return result; +} diff --git a/src/mldap.h b/src/mldap.h index e14964619a7ac50a248d00ff414cf11d5b056989..a0e9b7372ea8d114178ced1d1e2ffcfd4eb00bfc 100644 --- a/src/mldap.h +++ b/src/mldap.h @@ -22,4 +22,10 @@ mldap_newversion(mldapdb_t *mldap); void ATTR_NONNULLS mldap_closeversion(mldapdb_t *mldap, isc_boolean_t commit); +isc_result_t ATTR_CHECKRESULT ATTR_NONNULLS +mldap_entry_create(ldap_entry_t *entry, mldapdb_t *mldap, metadb_node_t **nodep); + +isc_result_t ATTR_CHECKRESULT ATTR_NONNULLS +mldap_dnsname_store(dns_name_t *fqdn, dns_name_t *zone, metadb_node_t *node); + #endif /* SRC_MLDAP_H_ */ -- 2.1.0
From 8a84ac99110164e00d44d158dc4ee375a77004f0 Mon Sep 17 00:00:00 2001 From: Petr Spacek <pspa...@redhat.com> Date: Tue, 12 May 2015 14:01:47 +0200 Subject: [PATCH] Add meta-LDAP database to LDAP instance. https://fedorahosted.org/bind-dyndb-ldap/ticket/151 --- src/ldap_helper.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ldap_helper.c b/src/ldap_helper.c index be64f8207f3f35a4f639e4ebebe30319aad06e67..a25cad855fd088e04692198a3ce5e98c6dd55010 100644 --- a/src/ldap_helper.c +++ b/src/ldap_helper.c @@ -80,6 +80,7 @@ #include "ldap_helper.h" #include "lock.h" #include "log.h" +#include "mldap.h" #include "rdlist.h" #include "semaphore.h" #include "settings.h" @@ -182,6 +183,7 @@ struct ldap_instance { dns_forwarders_t orig_global_forwarders; /* from named.conf */ sync_ctx_t *sctx; + mldapdb_t *mldapdb; }; struct ldap_pool { @@ -559,6 +561,7 @@ new_ldap_instance(isc_mem_t *mctx, const char *db_name, CHECK(zr_create(mctx, ldap_inst, ldap_inst->global_settings, &ldap_inst->zone_register)); CHECK(fwdr_create(ldap_inst->mctx, &ldap_inst->fwd_register)); + CHECK(mldap_new(mctx, &ldap_inst->mldapdb)); CHECK(isc_mutex_init(&ldap_inst->kinit_lock)); @@ -652,6 +655,7 @@ destroy_ldap_instance(ldap_instance_t **ldap_instp) /* Unregister all zones already registered in BIND. */ zr_destroy(&ldap_inst->zone_register); fwdr_destroy(&ldap_inst->fwd_register); + mldap_destroy(&ldap_inst->mldapdb); ldap_pool_destroy(&ldap_inst->pool); dns_view_detach(&ldap_inst->view); -- 2.1.0
From 77418d2a585d41f1bc3743db100203c662a6cdc8 Mon Sep 17 00:00:00 2001 From: Petr Spacek <pspa...@redhat.com> Date: Tue, 12 May 2015 14:03:47 +0200 Subject: [PATCH] Add LDAP UUID to LDAP entry structure. https://fedorahosted.org/bind-dyndb-ldap/ticket/151 --- src/ldap_entry.c | 6 ++++-- src/ldap_entry.h | 4 ++-- src/ldap_helper.c | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/ldap_entry.c b/src/ldap_entry.c index 5551e664255f029aefe276ec5bbdee7e6add7e8b..e11c6f17ca3920582e272d0b8a9fa54ad05797be 100644 --- a/src/ldap_entry.c +++ b/src/ldap_entry.c @@ -137,7 +137,7 @@ cleanup: */ isc_result_t ldap_entry_create(isc_mem_t *mctx, LDAP *ld, LDAPMessage *ldap_entry, - ldap_entry_t **entryp) + struct berval *uuid, ldap_entry_t **entryp) { isc_result_t result; ldap_attribute_t *attr = NULL; @@ -151,7 +151,6 @@ ldap_entry_create(isc_mem_t *mctx, LDAP *ld, LDAPMessage *ldap_entry, REQUIRE(*entryp == NULL); CHECK(ldap_entry_init(mctx, &entry)); - entry->ldap_entry = ldap_entry; for (attribute = ldap_first_attribute(ld, ldap_entry, &ber); attribute != NULL; @@ -173,6 +172,7 @@ ldap_entry_create(isc_mem_t *mctx, LDAP *ld, LDAPMessage *ldap_entry, log_ldap_error(ld, "unable to get entry DN"); CLEANUP_WITH(ISC_R_FAILURE); } + entry->uuid = ber_dupbv(NULL, uuid); *entryp = entry; @@ -202,6 +202,8 @@ ldap_entry_destroy(isc_mem_t *mctx, ldap_entry_t **entryp) ldap_attributelist_destroy(mctx, &entry->attrs); if (entry->dn != NULL) ldap_memfree(entry->dn); + if (entry->uuid != NULL) + ber_bvfree(entry->uuid); if (entry->lex != NULL) { isc_lex_close(entry->lex); isc_lex_destroy(&entry->lex); diff --git a/src/ldap_entry.h b/src/ldap_entry.h index 635b58f235e4bf43cb0195833c87acc9618fabf6..1f8748988775e8f446179abab6af9c2f9952d30f 100644 --- a/src/ldap_entry.h +++ b/src/ldap_entry.h @@ -49,8 +49,8 @@ typedef LIST(ldap_attribute_t) ldap_attributelist_t; typedef struct ldap_entry ldap_entry_t; typedef LIST(ldap_entry_t) ldap_entrylist_t; struct ldap_entry { - LDAPMessage *ldap_entry; char *dn; + struct berval *uuid; ldap_attribute_t *lastattr; ldap_attributelist_t attrs; LINK(ldap_entry_t) link; @@ -104,7 +104,7 @@ ldap_entrylist_append(isc_mem_t *mctx, LDAP *ld, LDAPMessage *msg, */ isc_result_t ldap_entry_create(isc_mem_t *mctx, LDAP *ld, LDAPMessage *ldap_entry, - ldap_entry_t **entryp) ATTR_NONNULLS ATTR_CHECKRESULT; + struct berval *uuid, ldap_entry_t **entryp) ATTR_NONNULLS ATTR_CHECKRESULT; void ldap_entry_destroy(isc_mem_t *mctx, ldap_entry_t **entryp) ATTR_NONNULLS; diff --git a/src/ldap_helper.c b/src/ldap_helper.c index a25cad855fd088e04692198a3ce5e98c6dd55010..9046353351038cd06f90a59a13c96309cc18c42c 100644 --- a/src/ldap_helper.c +++ b/src/ldap_helper.c @@ -4368,7 +4368,7 @@ int ldap_sync_search_entry ( return LDAP_SUCCESS; CHECK(sync_concurr_limit_wait(inst->sctx)); - CHECK(ldap_entry_create(inst->mctx, ls->ls_ld, msg, &entry)); + CHECK(ldap_entry_create(inst->mctx, ls->ls_ld, msg, entryUUID, &entry)); syncrepl_update(inst, entry, phase); #ifdef RBTDB_DEBUG if (++count % 100 == 0) -- 2.1.0
From efb2b01d9080ca2314e74bf4313b7f45c18ddf57 Mon Sep 17 00:00:00 2001 From: Petr Spacek <pspa...@redhat.com> Date: Wed, 13 May 2015 14:00:34 +0200 Subject: [PATCH] Store object class, generation number, and DNS names into meta-LDAP DB. https://fedorahosted.org/bind-dyndb-ldap/ticket/151 --- src/ldap_helper.c | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/src/ldap_helper.c b/src/ldap_helper.c index 9046353351038cd06f90a59a13c96309cc18c42c..0f089169852b7c74f9ee3ef655bd14f2a5fa091a 100644 --- a/src/ldap_helper.c +++ b/src/ldap_helper.c @@ -80,6 +80,7 @@ #include "ldap_helper.h" #include "lock.h" #include "log.h" +#include "metadb.h" #include "mldap.h" #include "rdlist.h" #include "semaphore.h" @@ -4357,31 +4358,56 @@ int ldap_sync_search_entry ( ldap_instance_t *inst = ls->ls_private; ldap_entry_t *entry = NULL; isc_result_t result; + metadb_node_t *node = NULL; + isc_boolean_t mdb_write = ISC_FALSE; + ldap_entryclass_t class; + DECLARE_BUFFERED_NAME(fqdn); + DECLARE_BUFFERED_NAME(zone_name); + #ifdef RBTDB_DEBUG static unsigned int count = 0; #endif - /* TODO: Use this for UUID->DN mapping and MODDN detection. */ - UNUSED(entryUUID); - if (inst->exiting) return LDAP_SUCCESS; + INIT_BUFFERED_NAME(fqdn); + INIT_BUFFERED_NAME(zone_name); + CHECK(sync_concurr_limit_wait(inst->sctx)); CHECK(ldap_entry_create(inst->mctx, ls->ls_ld, msg, entryUUID, &entry)); + if (phase == LDAP_SYNC_CAPI_ADD || phase == LDAP_SYNC_CAPI_MODIFY) { + CHECK(mldap_newversion(inst->mldapdb)); + mdb_write = ISC_TRUE; + CHECK(mldap_entry_create(entry, inst->mldapdb, &node)); + CHECK(ldap_entry_getclass(entry, &class)); + if ((class & LDAP_ENTRYCLASS_CONFIG) == 0) { + CHECK(dn_to_dnsname(inst->mctx, entry->dn, + &fqdn, &zone_name, NULL)); + CHECK(mldap_dnsname_store(&fqdn, &zone_name, node)); + } + metadb_node_close(&node); + mldap_closeversion(inst->mldapdb, ISC_TRUE); + } syncrepl_update(inst, entry, phase); #ifdef RBTDB_DEBUG if (++count % 100 == 0) log_info("ldap_sync_search_entry: %u entries read; inuse: %zd", count, isc_mem_inuse(inst->mctx)); #endif cleanup: if (result != ISC_R_SUCCESS) { + if (mdb_write == ISC_TRUE) + mldap_closeversion(inst->mldapdb, ISC_FALSE); log_error_r("ldap_sync_search_entry failed"); sync_concurr_limit_signal(inst->sctx); /* TODO: Add 'tainted' flag to the LDAP instance. */ } + if (dns_name_dynamic(&fqdn)) + dns_name_free(&fqdn, inst->mctx); + if (dns_name_dynamic(&zone_name)) + dns_name_free(&zone_name, inst->mctx); /* Following return code will never reach upper layers. * It is limitation in ldap_sync_init() and ldap_sync_poll() -- 2.1.0
From da3a3ad4c184ec5d6bb99caf3955eae56a3e3995 Mon Sep 17 00:00:00 2001 From: Petr Spacek <pspa...@redhat.com> Date: Thu, 14 May 2015 11:35:02 +0200 Subject: [PATCH] Move typedefs to types.h to avoid cross-include problems. https://fedorahosted.org/bind-dyndb-ldap/ticket/151 --- src/acl.h | 1 - src/ldap_convert.h | 3 ++- src/ldap_driver.c | 1 + src/ldap_entry.c | 3 +++ src/ldap_entry.h | 2 +- src/ldap_helper.h | 4 ++-- src/lock.c | 1 + src/lock.h | 2 +- src/mldap.h | 4 +++- src/settings.h | 1 - src/types.h | 3 +++ src/zone_manager.h | 2 +- 12 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/acl.h b/src/acl.h index e438132f623b4efb2c3e2d595b1d83065f8583dc..b6603a2a5e2ad4cf57311160f80754a434c68cff 100644 --- a/src/acl.h +++ b/src/acl.h @@ -21,7 +21,6 @@ #ifndef _LD_ACL_H_ #define _LD_ACL_H_ -#include "ldap_entry.h" #include "types.h" #include <dns/acl.h> diff --git a/src/ldap_convert.h b/src/ldap_convert.h index daa0db0b311dd51c05ade688715550d9f70759ac..112aaac4426f7e2229c040e1202df324278bbfb6 100644 --- a/src/ldap_convert.h +++ b/src/ldap_convert.h @@ -22,10 +22,11 @@ #define _LD_LDAP_CONVERT_H_ #include <dns/types.h> +#include <dns/rbt.h> #include <dns/rdatatype.h> #include "str.h" -#include "zone_register.h" +#include "types.h" #define LDAP_ATTR_FORMATSIZE 32 /* "expected" maximum attribute name length */ #define LDAP_RDATATYPE_SUFFIX "Record" diff --git a/src/ldap_driver.c b/src/ldap_driver.c index 8b78c960cfb05cc0f4c0fb50e3fbdaa9cfdcae50..931f57324211a2cefdfbd3a620a31a75340a82a7 100644 --- a/src/ldap_driver.c +++ b/src/ldap_driver.c @@ -54,6 +54,7 @@ #include "rdlist.h" #include "util.h" #include "zone_manager.h" +#include "zone_register.h" #ifdef HAVE_VISIBILITY #define VISIBLE __attribute__((__visibility__("default"))) diff --git a/src/ldap_entry.c b/src/ldap_entry.c index e11c6f17ca3920582e272d0b8a9fa54ad05797be..49bc2f0865ebad53841f592da63be977b3c1aca0 100644 --- a/src/ldap_entry.c +++ b/src/ldap_entry.c @@ -32,8 +32,11 @@ #include "ldap_convert.h" #include "ldap_entry.h" +#include "mldap.h" +#include "metadb.h" #include "str.h" #include "util.h" +#include "zone_register.h" /* Represents values associated with LDAP attribute */ static void ATTR_NONNULLS diff --git a/src/ldap_entry.h b/src/ldap_entry.h index 1f8748988775e8f446179abab6af9c2f9952d30f..6fc3cbd8e31141d3deff606d6831f5797c3d8be3 100644 --- a/src/ldap_entry.h +++ b/src/ldap_entry.h @@ -29,6 +29,7 @@ #include "fwd_register.h" #include "util.h" #include "str.h" +#include "types.h" #define LDAP_DEPRECATED 1 #include <ldap.h> @@ -46,7 +47,6 @@ typedef struct ldap_attribute ldap_attribute_t; typedef LIST(ldap_attribute_t) ldap_attributelist_t; /* Represents LDAP entry and it's attributes */ -typedef struct ldap_entry ldap_entry_t; typedef LIST(ldap_entry_t) ldap_entrylist_t; struct ldap_entry { char *dn; diff --git a/src/ldap_helper.h b/src/ldap_helper.h index 834b30d5b5b4bf61ebee561734998ce0b442f081..7e328226eb34c956b8e17015ad1a3516a2a11dd3 100644 --- a/src/ldap_helper.h +++ b/src/ldap_helper.h @@ -22,13 +22,13 @@ #ifndef _LD_LDAP_HELPER_H_ #define _LD_LDAP_HELPER_H_ -#include "settings.h" #include "types.h" -#include "zone_register.h" #include <isc/eventclass.h> #include <isc/util.h> +#include <ldap.h> + #define LDAPDB_EVENTCLASS ISC_EVENTCLASS(0xDDDD) isc_result_t ldapdb_rdatalist_findrdatatype(ldapdb_rdatalist_t *rdatalist, diff --git a/src/lock.c b/src/lock.c index b6b2e9fe828bee54f7c2637eafdb9b15080ba663..fb00927843de2e24d7a63d0ef0be7200341cc691 100644 --- a/src/lock.c +++ b/src/lock.c @@ -22,6 +22,7 @@ #include <isc/util.h> #include "lock.h" +#include "ldap_helper.h" /** * Lock BIND dispatcher and allow only single task to run. diff --git a/src/lock.h b/src/lock.h index ed271646703115126dbea184a406fd0a6405ccdc..2d0ebbd6af7647944553452e93cb5523e9887c1a 100644 --- a/src/lock.h +++ b/src/lock.h @@ -21,8 +21,8 @@ #ifndef LOCK_H_ #define LOCK_H_ -#include "ldap_helper.h" #include "util.h" +#include "types.h" void ATTR_NONNULLS run_exclusive_enter(ldap_instance_t *inst, isc_result_t *statep); diff --git a/src/mldap.h b/src/mldap.h index a0e9b7372ea8d114178ced1d1e2ffcfd4eb00bfc..a44c2648c5aa16d97c04babd55951af25e608d29 100644 --- a/src/mldap.h +++ b/src/mldap.h @@ -5,10 +5,12 @@ #ifndef SRC_MLDAP_H_ #define SRC_MLDAP_H_ +#include <ldap.h> + #include "metadb.h" +#include "types.h" #include "util.h" -typedef struct mldapdb mldapdb_t; isc_result_t ATTR_CHECKRESULT ATTR_NONNULLS mldap_new(isc_mem_t *mctx, mldapdb_t **dbp); diff --git a/src/settings.h b/src/settings.h index 610e4283254873ae63cfd7059d64f125ebe74ad9..300b714d922c7caa8cfe7bda553e709e5b41db32 100644 --- a/src/settings.h +++ b/src/settings.h @@ -33,7 +33,6 @@ #define SETTING_SET_NAME_ZONE "LDAP idnsZone object" typedef struct setting setting_t; -typedef struct settings_set settings_set_t; /* Make sure that cases in get_value_ptr() are synchronized */ typedef enum { diff --git a/src/types.h b/src/types.h index 1ca1411d1d29ce1e8475a3f9fa888519e08a730a..047612f30c875b731c320fd1e540f5c5cb39b206 100644 --- a/src/types.h +++ b/src/types.h @@ -48,5 +48,8 @@ typedef struct enum_txt_assoc { typedef struct ldap_instance ldap_instance_t; typedef struct zone_register zone_register_t; +typedef struct mldapdb mldapdb_t; +typedef struct ldap_entry ldap_entry_t; +typedef struct settings_set settings_set_t; #endif /* !_LD_TYPES_H_ */ diff --git a/src/zone_manager.h b/src/zone_manager.h index 556e66c25e3e0ef4cc74bc870a510e7f302ed2c3..ee4a094594b0ea9bb0650a41edaba6dd4571bae7 100644 --- a/src/zone_manager.h +++ b/src/zone_manager.h @@ -24,7 +24,7 @@ #include <dns/types.h> -#include "ldap_helper.h" +#include "types.h" typedef struct db_instance db_instance_t; -- 2.1.0
From f05db549465129588469d274f4d30e7223f8b3ce Mon Sep 17 00:00:00 2001 From: Petr Spacek <pspa...@redhat.com> Date: Thu, 14 May 2015 12:33:24 +0200 Subject: [PATCH] Add functions for reading from generic meta-database. https://fedorahosted.org/bind-dyndb-ldap/ticket/151 --- src/metadb.c | 34 ++++++++++++++++++++++++++++++++++ src/metadb.h | 4 ++++ 2 files changed, 38 insertions(+) diff --git a/src/metadb.c b/src/metadb.c index bbde3a85fed233ad35a2c81f0c0dbf0b530638df..b9caf24b261139add9bd0e003c7878fb188b4803 100644 --- a/src/metadb.c +++ b/src/metadb.c @@ -254,3 +254,37 @@ cleanup: result = ISC_R_SUCCESS; return result; } + +/** + * Get rdataset of given type from metaDB. + * + * Caller has to call dns_rdataset_dissociate() on the returned rdataset. + * Rdata will become invalid after dns_rdataset_dissociate() call. + * + * Note: It is not possible to directly return rdata without rdataset because + * there would be no way how to dissociate rdataset. + * + * @pre Node was created by metadb_writenode_create() or metadb_readnode_open(). + * @pre rdatataset is valid diassociated rdataset. + * + * @post Rdataset is an associated rdataset with exactly one rdata instance. + * Rdata can be obtained using dns_rdadaset_current(). + */ +isc_result_t +metadb_rdataset_get(metadb_node_t *node, dns_rdatatype_t rrtype, + dns_rdataset_t *rdataset) { + isc_result_t result; + + REQUIRE(dns_rdataset_isassociated(rdataset) == ISC_FALSE); + + CHECK(dns_db_findrdataset(node->rbtdb, node->dbnode, node->version, + rrtype, 0, 0, rdataset, NULL)); + /* Exactly one RR is expected in metaDB. */ + INSIST(dns_rdataset_count(rdataset) == 1); + INSIST(dns_rdataset_first(rdataset) == ISC_R_SUCCESS); + +cleanup: + if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(rdataset)) + dns_rdataset_disassociate(rdataset); + return result; +} diff --git a/src/metadb.h b/src/metadb.h index c49ac0dc2db46b8e62820d2e907b77bf82e59c2f..f1869d87b72f2c3dad8c0b1a7311b3578673c135 100644 --- a/src/metadb.h +++ b/src/metadb.h @@ -46,6 +46,10 @@ metadb_writenode_create(metadb_t *mdb, dns_name_t *mname, metadb_node_t **nodep) isc_result_t ATTR_CHECKRESULT ATTR_NONNULLS metadb_rdata_store(dns_rdata_t *rdata, metadb_node_t *node); +isc_result_t ATTR_CHECKRESULT ATTR_NONNULLS +metadb_rdataset_get(metadb_node_t *node, dns_rdatatype_t rrtype, + dns_rdataset_t *rdataset); + void ATTR_NONNULLS metadb_node_close(metadb_node_t **nodep); -- 2.1.0
From 71a5e1133c6e4db0cf8831b6300a111af4e91a28 Mon Sep 17 00:00:00 2001 From: Petr Spacek <pspa...@redhat.com> Date: Thu, 14 May 2015 12:36:12 +0200 Subject: [PATCH] Add functions for reading from meta-LDAP database. https://fedorahosted.org/bind-dyndb-ldap/ticket/151 --- src/mldap.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/mldap.h | 9 ++++++++ 2 files changed, 82 insertions(+) diff --git a/src/mldap.c b/src/mldap.c index 2b06ec6a11d6ada37aea1bee177b3201d16be7e2..4eea4b6588ea7df4d14405ed8349add7ac911d48 100644 --- a/src/mldap.c +++ b/src/mldap.c @@ -153,6 +153,31 @@ mldap_class_store(ldap_entryclass_t class, metadb_node_t *node) { return metadb_rdata_store(&rdata, node); } +isc_result_t +mldap_class_get(metadb_node_t *node, ldap_entryclass_t *classp) { + isc_result_t result; + dns_rdataset_t rdataset; + dns_rdata_t rdata; + isc_region_t region; + + REQUIRE(classp != NULL); + + dns_rdata_init(&rdata); + dns_rdataset_init(&rdataset); + + CHECK(metadb_rdataset_get(node, dns_rdatatype_aaaa, &rdataset)); + dns_rdataset_current(&rdataset, &rdata); + dns_rdata_toregion(&rdata, ®ion); + /* Bytes should be in network-order but we do not care because: + * 1) It is used only internally. 2) Class is unsigned char. */ + memcpy(classp, region.base, sizeof(*classp)); + +cleanup: + if (dns_rdataset_isassociated(&rdataset)) + dns_rdataset_disassociate(&rdataset); + return result; +} + STATIC_ASSERT((sizeof(((mldapdb_t *)0)->generation) == sizeof(struct in_addr)), \ "mldapdb_t->generation is too big for A rdata type"); @@ -209,6 +234,39 @@ cleanup: } /** + * Retrieve FQDN and zone name from RP record in metaDB. + * @param[in] node + * @param[out] fqdn + * @param[out] zone + * + * @pre DNS names fqdn and zone have dedicated buffer. + */ +isc_result_t +mldap_dnsname_get(metadb_node_t *node, dns_name_t *fqdn, dns_name_t *zone) { + isc_result_t result; + dns_rdata_rp_t rp; + dns_rdataset_t rdataset; + dns_rdata_t rdata; + + REQUIRE(fqdn != NULL); + REQUIRE(zone != NULL); + + dns_rdataset_init(&rdataset); + dns_rdata_init(&rdata); + + CHECK(metadb_rdataset_get(node, dns_rdatatype_rp, &rdataset)); + dns_rdataset_current(&rdataset, &rdata); + CHECK(dns_rdata_tostruct(&rdata, &rp, NULL)); + CHECK(dns_name_copy(&rp.mail, fqdn, NULL)); + CHECK(dns_name_copy(&rp.text, zone, NULL)); + +cleanup: + if (dns_rdataset_isassociated(&rdataset)) + dns_rdataset_disassociate(&rdataset); + return result; +} + +/** * Store information from LDAP entry into meta-database. */ isc_result_t @@ -236,3 +294,18 @@ cleanup: metadb_node_close(&node); return result; } + +/** + * Open metaLDAP entry for reading. + * All notes about metadb_readnode_open() apply equally here. + */ +isc_result_t +mldap_entry_read(mldapdb_t *mldap, struct berval *uuid, metadb_node_t **nodep) { + DECLARE_BUFFERED_NAME(mname); + + INIT_BUFFERED_NAME(mname); + + ldap_uuid_to_mname(uuid, &mname); + + return metadb_readnode_open(mldap->mdb, &mname, nodep); +} diff --git a/src/mldap.h b/src/mldap.h index a44c2648c5aa16d97c04babd55951af25e608d29..8312a638416c1f8b17b7293c32b071f1b3f71665 100644 --- a/src/mldap.h +++ b/src/mldap.h @@ -25,9 +25,18 @@ void ATTR_NONNULLS mldap_closeversion(mldapdb_t *mldap, isc_boolean_t commit); isc_result_t ATTR_CHECKRESULT ATTR_NONNULLS +mldap_entry_read(mldapdb_t *mldap, struct berval *uuid, metadb_node_t **nodep); + +isc_result_t ATTR_CHECKRESULT ATTR_NONNULLS mldap_entry_create(ldap_entry_t *entry, mldapdb_t *mldap, metadb_node_t **nodep); isc_result_t ATTR_CHECKRESULT ATTR_NONNULLS +mldap_class_get(metadb_node_t *node, ldap_entryclass_t *class); + +isc_result_t ATTR_CHECKRESULT ATTR_NONNULLS +mldap_dnsname_get(metadb_node_t *node, dns_name_t *fqdn, dns_name_t *zone); + +isc_result_t ATTR_CHECKRESULT ATTR_NONNULLS mldap_dnsname_store(dns_name_t *fqdn, dns_name_t *zone, metadb_node_t *node); #endif /* SRC_MLDAP_H_ */ -- 2.1.0
From 6556ea2034300cc41b24d5593b6773b623f54cf7 Mon Sep 17 00:00:00 2001 From: Petr Spacek <pspa...@redhat.com> Date: Thu, 14 May 2015 13:35:27 +0200 Subject: [PATCH] Use information from metaDB for LDAP object deletion. https://fedorahosted.org/bind-dyndb-ldap/ticket/151 --- src/ldap_entry.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/ldap_entry.h | 5 ++++ src/ldap_helper.c | 15 +++++++++++- 3 files changed, 87 insertions(+), 1 deletion(-) diff --git a/src/ldap_entry.c b/src/ldap_entry.c index 49bc2f0865ebad53841f592da63be977b3c1aca0..7e77cc2bd73e3ffad0c62dddf9978779fbf6dada 100644 --- a/src/ldap_entry.c +++ b/src/ldap_entry.c @@ -136,6 +136,74 @@ cleanup: } /** + * Create fake LDAP entry with values from metaDB. No attributes will be + * present in the fake entry. + * + * @param[in] mldap + * @param[in] uuid LDAP entry UUID + * @param[out] entryp Resulting entry. Caller has to free it. + * + * @warning fake entry->dn might be inaccurate + */ +isc_result_t +ldap_entry_reconstruct(isc_mem_t *mctx, zone_register_t *zr, + const char *ldap_base, mldapdb_t *mldap, + struct berval *uuid, ldap_entry_t **entryp) { + isc_result_t result; + ldap_entry_t *entry = NULL; + ld_string_t *str = NULL; + metadb_node_t *node = NULL; + ldap_entryclass_t class; + DECLARE_BUFFERED_NAME(fqdn); + DECLARE_BUFFERED_NAME(zone_name); + + INIT_BUFFERED_NAME(fqdn); + INIT_BUFFERED_NAME(zone_name); + + CHECK(str_new(mctx, &str)); + result = mldap_entry_read(mldap, uuid, &node); + if (result != ISC_R_SUCCESS) { + log_bug("protocol violation: " + "attempt to reconstruct non-existing entry"); + goto cleanup; + } + CHECK(ldap_entry_init(mctx, &entry)); + + entry->uuid = ber_dupbv(NULL, uuid); + if (entry->uuid == NULL) + CLEANUP_WITH(ISC_R_NOMEMORY); + + CHECK(mldap_class_get(node, &class)); + /* create fake DN from remembered DNS names and object class */ + if ((class & LDAP_ENTRYCLASS_CONFIG) != 0) { + /* idnsConfig objects do not have DNS name */ + CHECK(str_cat_char(str, ldap_base)); + } else { + CHECK(mldap_dnsname_get(node, &fqdn, &zone_name)); + if ((class & + (LDAP_ENTRYCLASS_MASTER | LDAP_ENTRYCLASS_FORWARD)) != 0) { + INSIST(dns_name_equal(dns_rootname, &zone_name) + == ISC_TRUE); + CHECK(dnsname_to_dn(zr, &fqdn, &fqdn, str)); + } else if ((class & LDAP_ENTRYCLASS_RR) != 0) { + CHECK(dnsname_to_dn(zr, &fqdn, &zone_name, str)); + } + } + entry->dn = ldap_strdup(str_buf(str)); + if (entry->dn == NULL) + CLEANUP_WITH(ISC_R_NOMEMORY); + + *entryp = entry; + +cleanup: + if (result != ISC_R_SUCCESS) + ldap_entry_destroy(mctx, &entry); + metadb_node_close(&node); + str_destroy(&str); + return result; +} + +/** * Allocate new ldap_entry and fill it with data from LDAPMessage. */ isc_result_t diff --git a/src/ldap_entry.h b/src/ldap_entry.h index 6fc3cbd8e31141d3deff606d6831f5797c3d8be3..ac7d1ee537232052e4fbdbcfd3016c1f72a74489 100644 --- a/src/ldap_entry.h +++ b/src/ldap_entry.h @@ -106,6 +106,11 @@ isc_result_t ldap_entry_create(isc_mem_t *mctx, LDAP *ld, LDAPMessage *ldap_entry, struct berval *uuid, ldap_entry_t **entryp) ATTR_NONNULLS ATTR_CHECKRESULT; +isc_result_t +ldap_entry_reconstruct(isc_mem_t *mctx, zone_register_t *zr, const char *ldap_base, + mldapdb_t *mldap, struct berval *uuid, + ldap_entry_t **entryp) ATTR_NONNULLS ATTR_CHECKRESULT; + void ldap_entry_destroy(isc_mem_t *mctx, ldap_entry_t **entryp) ATTR_NONNULLS; diff --git a/src/ldap_helper.c b/src/ldap_helper.c index 0f089169852b7c74f9ee3ef655bd14f2a5fa091a..1c8e49ed8983f7d016f2cdb73f06c8bac783fba1 100644 --- a/src/ldap_helper.c +++ b/src/ldap_helper.c @@ -4361,6 +4361,7 @@ int ldap_sync_search_entry ( metadb_node_t *node = NULL; isc_boolean_t mdb_write = ISC_FALSE; ldap_entryclass_t class; + const char *ldap_base = NULL; DECLARE_BUFFERED_NAME(fqdn); DECLARE_BUFFERED_NAME(zone_name); @@ -4375,8 +4376,9 @@ int ldap_sync_search_entry ( INIT_BUFFERED_NAME(zone_name); CHECK(sync_concurr_limit_wait(inst->sctx)); - CHECK(ldap_entry_create(inst->mctx, ls->ls_ld, msg, entryUUID, &entry)); if (phase == LDAP_SYNC_CAPI_ADD || phase == LDAP_SYNC_CAPI_MODIFY) { + CHECK(ldap_entry_create(inst->mctx, ls->ls_ld, msg, entryUUID, + &entry)); CHECK(mldap_newversion(inst->mldapdb)); mdb_write = ISC_TRUE; CHECK(mldap_entry_create(entry, inst->mldapdb, &node)); @@ -4388,6 +4390,16 @@ int ldap_sync_search_entry ( } metadb_node_close(&node); mldap_closeversion(inst->mldapdb, ISC_TRUE); + + } else if (phase == LDAP_SYNC_CAPI_DELETE) { + INSIST(setting_get_str("base", inst->local_settings, + &ldap_base) == ISC_R_SUCCESS); + CHECK(ldap_entry_reconstruct(inst->mctx, inst->zone_register, + ldap_base, inst->mldapdb, entryUUID, + &entry)); + } else { + log_bug("syncrepl phase %x is not supported", phase); + CLEANUP_WITH(ISC_R_NOTIMPLEMENTED); } syncrepl_update(inst, entry, phase); #ifdef RBTDB_DEBUG @@ -4404,6 +4416,7 @@ cleanup: sync_concurr_limit_signal(inst->sctx); /* TODO: Add 'tainted' flag to the LDAP instance. */ } + metadb_node_close(&node); if (dns_name_dynamic(&fqdn)) dns_name_free(&fqdn, inst->mctx); if (dns_name_dynamic(&zone_name)) -- 2.1.0
From 4fb7bd42609c2b6a4ffbdf6f3a1e58e00d84fa1e Mon Sep 17 00:00:00 2001 From: Petr Spacek <pspa...@redhat.com> Date: Tue, 12 May 2015 14:22:25 +0200 Subject: [PATCH] Rename ldap_entry_create() to ldap_entry_parse(). https://fedorahosted.org/bind-dyndb-ldap/ticket/151 --- src/ldap_entry.c | 2 +- src/ldap_entry.h | 2 +- src/ldap_helper.c | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/ldap_entry.c b/src/ldap_entry.c index 7e77cc2bd73e3ffad0c62dddf9978779fbf6dada..dc986c6771c28ab8a4c4c3d50b6f9f6c8593358b 100644 --- a/src/ldap_entry.c +++ b/src/ldap_entry.c @@ -207,7 +207,7 @@ cleanup: * Allocate new ldap_entry and fill it with data from LDAPMessage. */ isc_result_t -ldap_entry_create(isc_mem_t *mctx, LDAP *ld, LDAPMessage *ldap_entry, +ldap_entry_parse(isc_mem_t *mctx, LDAP *ld, LDAPMessage *ldap_entry, struct berval *uuid, ldap_entry_t **entryp) { isc_result_t result; diff --git a/src/ldap_entry.h b/src/ldap_entry.h index ac7d1ee537232052e4fbdbcfd3016c1f72a74489..5953aaef9f994ae9323aa4fca9c35aa5611a75e4 100644 --- a/src/ldap_entry.h +++ b/src/ldap_entry.h @@ -103,7 +103,7 @@ ldap_entrylist_append(isc_mem_t *mctx, LDAP *ld, LDAPMessage *msg, * Creates ldap_entry_t from message "result" received via "ld" connection */ isc_result_t -ldap_entry_create(isc_mem_t *mctx, LDAP *ld, LDAPMessage *ldap_entry, +ldap_entry_parse(isc_mem_t *mctx, LDAP *ld, LDAPMessage *ldap_entry, struct berval *uuid, ldap_entry_t **entryp) ATTR_NONNULLS ATTR_CHECKRESULT; isc_result_t diff --git a/src/ldap_helper.c b/src/ldap_helper.c index 1c8e49ed8983f7d016f2cdb73f06c8bac783fba1..4294488589f0f24fd88e1d05a1c1d9e7c11f8a9c 100644 --- a/src/ldap_helper.c +++ b/src/ldap_helper.c @@ -4377,7 +4377,7 @@ int ldap_sync_search_entry ( CHECK(sync_concurr_limit_wait(inst->sctx)); if (phase == LDAP_SYNC_CAPI_ADD || phase == LDAP_SYNC_CAPI_MODIFY) { - CHECK(ldap_entry_create(inst->mctx, ls->ls_ld, msg, entryUUID, + CHECK(ldap_entry_parse(inst->mctx, ls->ls_ld, msg, entryUUID, &entry)); CHECK(mldap_newversion(inst->mldapdb)); mdb_write = ISC_TRUE; @@ -4401,6 +4401,7 @@ int ldap_sync_search_entry ( log_bug("syncrepl phase %x is not supported", phase); CLEANUP_WITH(ISC_R_NOTIMPLEMENTED); } + syncrepl_update(inst, entry, phase); #ifdef RBTDB_DEBUG if (++count % 100 == 0) -- 2.1.0
From 3f11f82f2d2c88f50417d75c2d4d70a9563daabf Mon Sep 17 00:00:00 2001 From: Petr Spacek <pspa...@redhat.com> Date: Tue, 12 May 2015 15:21:00 +0200 Subject: [PATCH] Replace ldap_entry_parseclass() by LDAP entry struct member variable. https://fedorahosted.org/bind-dyndb-ldap/ticket/151 --- src/ldap_entry.c | 21 +++++++++++++++------ src/ldap_entry.h | 13 ++----------- src/ldap_helper.c | 16 +++++----------- src/mldap.c | 4 +--- 4 files changed, 23 insertions(+), 31 deletions(-) diff --git a/src/ldap_entry.c b/src/ldap_entry.c index dc986c6771c28ab8a4c4c3d50b6f9f6c8593358b..6156bd09c95ef451d68638137a978baffea84849 100644 --- a/src/ldap_entry.c +++ b/src/ldap_entry.c @@ -38,6 +38,15 @@ #include "util.h" #include "zone_register.h" +/* + * ldap_entry_parseclass + * + * Get entry class (bitwise OR of the LDAP_ENTRYCLASS_*). Note that + * you must ldap_search for objectClass attribute! + */ +static isc_result_t ATTR_NONNULLS ATTR_CHECKRESULT +ldap_entry_parseclass(ldap_entry_t *entry, ldap_entryclass_t *class); + /* Represents values associated with LDAP attribute */ static void ATTR_NONNULLS ldap_valuelist_destroy(isc_mem_t *mctx, ldap_valuelist_t *values) @@ -153,7 +162,6 @@ ldap_entry_reconstruct(isc_mem_t *mctx, zone_register_t *zr, ldap_entry_t *entry = NULL; ld_string_t *str = NULL; metadb_node_t *node = NULL; - ldap_entryclass_t class; DECLARE_BUFFERED_NAME(fqdn); DECLARE_BUFFERED_NAME(zone_name); @@ -173,19 +181,19 @@ ldap_entry_reconstruct(isc_mem_t *mctx, zone_register_t *zr, if (entry->uuid == NULL) CLEANUP_WITH(ISC_R_NOMEMORY); - CHECK(mldap_class_get(node, &class)); + CHECK(mldap_class_get(node, &entry->class)); /* create fake DN from remembered DNS names and object class */ - if ((class & LDAP_ENTRYCLASS_CONFIG) != 0) { + if ((entry->class & LDAP_ENTRYCLASS_CONFIG) != 0) { /* idnsConfig objects do not have DNS name */ CHECK(str_cat_char(str, ldap_base)); } else { CHECK(mldap_dnsname_get(node, &fqdn, &zone_name)); - if ((class & + if ((entry->class & (LDAP_ENTRYCLASS_MASTER | LDAP_ENTRYCLASS_FORWARD)) != 0) { INSIST(dns_name_equal(dns_rootname, &zone_name) == ISC_TRUE); CHECK(dnsname_to_dn(zr, &fqdn, &fqdn, str)); - } else if ((class & LDAP_ENTRYCLASS_RR) != 0) { + } else if ((entry->class & LDAP_ENTRYCLASS_RR) != 0) { CHECK(dnsname_to_dn(zr, &fqdn, &zone_name, str)); } } @@ -244,6 +252,7 @@ ldap_entry_parse(isc_mem_t *mctx, LDAP *ld, LDAPMessage *ldap_entry, CLEANUP_WITH(ISC_R_FAILURE); } entry->uuid = ber_dupbv(NULL, uuid); + CHECK(ldap_entry_parseclass(entry, &entry->class)); *entryp = entry; @@ -426,7 +435,7 @@ cleanup: } isc_result_t -ldap_entry_getclass(ldap_entry_t *entry, ldap_entryclass_t *class) +ldap_entry_parseclass(ldap_entry_t *entry, ldap_entryclass_t *class) { ldap_valuelist_t values; ldap_value_t *val; diff --git a/src/ldap_entry.h b/src/ldap_entry.h index 5953aaef9f994ae9323aa4fca9c35aa5611a75e4..9c0d882c2e0e26d947f6881721f7450bca9a1068 100644 --- a/src/ldap_entry.h +++ b/src/ldap_entry.h @@ -47,10 +47,12 @@ typedef struct ldap_attribute ldap_attribute_t; typedef LIST(ldap_attribute_t) ldap_attributelist_t; /* Represents LDAP entry and it's attributes */ +typedef unsigned char ldap_entryclass_t; typedef LIST(ldap_entry_t) ldap_entrylist_t; struct ldap_entry { char *dn; struct berval *uuid; + ldap_entryclass_t class; ldap_attribute_t *lastattr; ldap_attributelist_t attrs; LINK(ldap_entry_t) link; @@ -78,8 +80,6 @@ struct ldap_attribute { #define DEFAULT_TTL 86400 -typedef unsigned char ldap_entryclass_t; - /* Max type length definitions, from lib/dns/master.c */ #define TOKENSIZ (8*1024) @@ -136,15 +136,6 @@ isc_result_t ldap_entry_getfakesoa(ldap_entry_t *entry, const char *fake_mname, ld_string_t *target) ATTR_NONNULLS ATTR_CHECKRESULT; -/* - * ldap_entry_getclass - * - * Get entry class (bitwise OR of the LDAP_ENTRYCLASS_*). Note that - * you must ldap_search for objectClass attribute! - */ -isc_result_t -ldap_entry_getclass(ldap_entry_t *entry, ldap_entryclass_t *class) ATTR_NONNULLS ATTR_CHECKRESULT; - isc_result_t ldap_entry_guessclass(dns_name_t *entry_name, isc_boolean_t iszone, fwd_register_t *fwd_register, ldap_entryclass_t *class) diff --git a/src/ldap_helper.c b/src/ldap_helper.c index 4294488589f0f24fd88e1d05a1c1d9e7c11f8a9c..72823cedec32b6a895c1f2da126896d466f4211f 100644 --- a/src/ldap_helper.c +++ b/src/ldap_helper.c @@ -2589,7 +2589,6 @@ ldap_parse_rrentry(isc_mem_t *mctx, ldap_entry_t *entry, dns_name_t *origin, { isc_result_t result; dns_rdataclass_t rdclass; - ldap_entryclass_t objclass; dns_ttl_t ttl; dns_rdatatype_t rdtype; dns_rdata_t *rdata = NULL; @@ -2602,8 +2601,7 @@ ldap_parse_rrentry(isc_mem_t *mctx, ldap_entry_t *entry, dns_name_t *origin, REQUIRE(EMPTY(*rdatalist)); CHECK(str_new(mctx, &data_buf)); - CHECK(ldap_entry_getclass(entry, &objclass)); - if ((objclass & LDAP_ENTRYCLASS_MASTER) != 0) + if ((entry->class & LDAP_ENTRYCLASS_MASTER) != 0) CHECK(add_soa_record(mctx, origin, entry, rdatalist, fake_mname)); rdclass = ldap_entry_getrdclass(entry); @@ -3705,7 +3703,6 @@ update_zone(isc_task_t *task, isc_event_t *event) ldap_syncreplevent_t *pevent = (ldap_syncreplevent_t *)event; isc_result_t result ; ldap_instance_t *inst = NULL; - ldap_entryclass_t objclass; isc_mem_t *mctx; dns_name_t prevname; dns_name_t currname; @@ -3724,11 +3721,10 @@ update_zone(isc_task_t *task, isc_event_t *event) if (SYNCREPL_DEL(pevent->chgtype)) { CHECK(ldap_delete_zone(inst, pevent->dn, ISC_TRUE, ISC_FALSE)); } else { - CHECK(ldap_entry_getclass(entry, &objclass)); - if (objclass & LDAP_ENTRYCLASS_MASTER) + if (entry->class & LDAP_ENTRYCLASS_MASTER) CHECK(ldap_parse_master_zoneentry(entry, NULL, inst, task)); - else if (objclass & LDAP_ENTRYCLASS_FORWARD) + else if (entry->class & LDAP_ENTRYCLASS_FORWARD) CHECK(ldap_parse_fwd_zoneentry(entry, inst)); } @@ -4146,7 +4142,7 @@ syncrepl_update(ldap_instance_t *inst, ldap_entry_t *entry, int chgtype) switch (chgtype) { case LDAP_SYNC_CAPI_ADD: case LDAP_SYNC_CAPI_MODIFY: - CHECK(ldap_entry_getclass(entry, &class)); + class = entry->class; break; default: @@ -4360,7 +4356,6 @@ int ldap_sync_search_entry ( isc_result_t result; metadb_node_t *node = NULL; isc_boolean_t mdb_write = ISC_FALSE; - ldap_entryclass_t class; const char *ldap_base = NULL; DECLARE_BUFFERED_NAME(fqdn); DECLARE_BUFFERED_NAME(zone_name); @@ -4382,8 +4377,7 @@ int ldap_sync_search_entry ( CHECK(mldap_newversion(inst->mldapdb)); mdb_write = ISC_TRUE; CHECK(mldap_entry_create(entry, inst->mldapdb, &node)); - CHECK(ldap_entry_getclass(entry, &class)); - if ((class & LDAP_ENTRYCLASS_CONFIG) == 0) { + if ((entry->class & LDAP_ENTRYCLASS_CONFIG) == 0) { CHECK(dn_to_dnsname(inst->mctx, entry->dn, &fqdn, &zone_name, NULL)); CHECK(mldap_dnsname_store(&fqdn, &zone_name, node)); diff --git a/src/mldap.c b/src/mldap.c index 4eea4b6588ea7df4d14405ed8349add7ac911d48..3195ad89f1eb51d72bb0e2487a913a6e871466b4 100644 --- a/src/mldap.c +++ b/src/mldap.c @@ -272,7 +272,6 @@ cleanup: isc_result_t mldap_entry_create(ldap_entry_t *entry, mldapdb_t *mldap, metadb_node_t **nodep) { isc_result_t result; - ldap_entryclass_t class; metadb_node_t *node = NULL; DECLARE_BUFFERED_NAME(mname); @@ -283,8 +282,7 @@ mldap_entry_create(ldap_entry_t *entry, mldapdb_t *mldap, metadb_node_t **nodep) ldap_uuid_to_mname(entry->uuid, &mname); CHECK(metadb_writenode_create(mldap->mdb, &mname, &node)); - CHECK(ldap_entry_getclass(entry, &class)); - CHECK(mldap_class_store(class, node)); + CHECK(mldap_class_store(entry->class, node)); CHECK(mldap_generation_store(mldap, node)); *nodep = node; -- 2.1.0
From 31eca2f3971368e0fb7c75722ea47c23d18cd8d7 Mon Sep 17 00:00:00 2001 From: Petr Spacek <pspa...@redhat.com> Date: Tue, 12 May 2015 15:49:27 +0200 Subject: [PATCH] Add pre-parsed DNS names to LDAP entry structure. All LDAP objects except idnsConfig need a DNS name anyway. This is a step towards removal of dependency on entry->dn field which is unavailable for deleted objects. https://fedorahosted.org/bind-dyndb-ldap/ticket/151 --- src/ldap_entry.c | 34 +++++++++++++++++++++++++--------- src/ldap_entry.h | 3 +++ 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/src/ldap_entry.c b/src/ldap_entry.c index 6156bd09c95ef451d68638137a978baffea84849..165d034cc4a15b0867b2dbbef74f16d6b9a97d51 100644 --- a/src/ldap_entry.c +++ b/src/ldap_entry.c @@ -131,6 +131,8 @@ ldap_entry_init(isc_mem_t *mctx, ldap_entry_t **entryp) { ZERO_PTR(entry); INIT_LIST(entry->attrs); INIT_LINK(entry, link); + INIT_BUFFERED_NAME(entry->fqdn); + INIT_BUFFERED_NAME(entry->zone_name); CHECKED_MEM_GET(mctx, entry->rdata_target_mem, DNS_RDATA_MAXLENGTH); CHECK(isc_lex_create(mctx, TOKENSIZ, &entry->lex)); @@ -162,11 +164,6 @@ ldap_entry_reconstruct(isc_mem_t *mctx, zone_register_t *zr, ldap_entry_t *entry = NULL; ld_string_t *str = NULL; metadb_node_t *node = NULL; - DECLARE_BUFFERED_NAME(fqdn); - DECLARE_BUFFERED_NAME(zone_name); - - INIT_BUFFERED_NAME(fqdn); - INIT_BUFFERED_NAME(zone_name); CHECK(str_new(mctx, &str)); result = mldap_entry_read(mldap, uuid, &node); @@ -187,14 +184,15 @@ ldap_entry_reconstruct(isc_mem_t *mctx, zone_register_t *zr, /* idnsConfig objects do not have DNS name */ CHECK(str_cat_char(str, ldap_base)); } else { - CHECK(mldap_dnsname_get(node, &fqdn, &zone_name)); + CHECK(mldap_dnsname_get(node, &entry->fqdn, &entry->zone_name)); if ((entry->class & (LDAP_ENTRYCLASS_MASTER | LDAP_ENTRYCLASS_FORWARD)) != 0) { - INSIST(dns_name_equal(dns_rootname, &zone_name) + INSIST(dns_name_equal(dns_rootname, &entry->zone_name) == ISC_TRUE); - CHECK(dnsname_to_dn(zr, &fqdn, &fqdn, str)); + CHECK(dnsname_to_dn(zr, &entry->fqdn, &entry->fqdn, str)); } else if ((entry->class & LDAP_ENTRYCLASS_RR) != 0) { - CHECK(dnsname_to_dn(zr, &fqdn, &zone_name, str)); + CHECK(dnsname_to_dn(zr, &entry->fqdn, &entry->zone_name, + str)); } } entry->dn = ldap_strdup(str_buf(str)); @@ -223,6 +221,8 @@ ldap_entry_parse(isc_mem_t *mctx, LDAP *ld, LDAPMessage *ldap_entry, char *attribute; BerElement *ber = NULL; ldap_entry_t *entry = NULL; + isc_boolean_t has_zone_dn; + isc_boolean_t has_zone_class; REQUIRE(ld != NULL); REQUIRE(ldap_entry != NULL); @@ -254,6 +254,18 @@ ldap_entry_parse(isc_mem_t *mctx, LDAP *ld, LDAPMessage *ldap_entry, entry->uuid = ber_dupbv(NULL, uuid); CHECK(ldap_entry_parseclass(entry, &entry->class)); + if ((entry->class & + (LDAP_ENTRYCLASS_MASTER | LDAP_ENTRYCLASS_FORWARD + | LDAP_ENTRYCLASS_RR)) != 0) + CHECK(dn_to_dnsname(mctx, entry->dn, &entry->fqdn, + &entry->zone_name, &has_zone_dn)); + else + has_zone_dn = ISC_FALSE; + has_zone_class = ISC_TF(entry->class & (LDAP_ENTRYCLASS_MASTER + | LDAP_ENTRYCLASS_FORWARD)); + CHECK(dn_want_zone(__func__, entry->dn, has_zone_dn, has_zone_class)); + + *entryp = entry; cleanup: @@ -284,6 +296,10 @@ ldap_entry_destroy(isc_mem_t *mctx, ldap_entry_t **entryp) ldap_memfree(entry->dn); if (entry->uuid != NULL) ber_bvfree(entry->uuid); + if (dns_name_dynamic(&entry->fqdn)) + dns_name_free(&entry->fqdn, mctx); + if (dns_name_dynamic(&entry->zone_name)) + dns_name_free(&entry->zone_name, mctx); if (entry->lex != NULL) { isc_lex_close(entry->lex); isc_lex_destroy(&entry->lex); diff --git a/src/ldap_entry.h b/src/ldap_entry.h index 9c0d882c2e0e26d947f6881721f7450bca9a1068..606fe8894579dc527e3a1723de51d5f9b700dd5d 100644 --- a/src/ldap_entry.h +++ b/src/ldap_entry.h @@ -53,6 +53,9 @@ struct ldap_entry { char *dn; struct berval *uuid; ldap_entryclass_t class; + DECLARE_BUFFERED_NAME(fqdn); + DECLARE_BUFFERED_NAME(zone_name); + ldap_attribute_t *lastattr; ldap_attributelist_t attrs; LINK(ldap_entry_t) link; -- 2.1.0
From 6187b1a4f1179d4d98d29a40d7e293c2f5ef2089 Mon Sep 17 00:00:00 2001 From: Petr Spacek <pspa...@redhat.com> Date: Wed, 13 May 2015 11:06:09 +0200 Subject: [PATCH] Adapt update_record() to use pre-parsed DNS names in LDAP entry. https://fedorahosted.org/bind-dyndb-ldap/ticket/151 --- src/ldap_helper.c | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/src/ldap_helper.c b/src/ldap_helper.c index 72823cedec32b6a895c1f2da126896d466f4211f..97ef857e01cf8a463bde885042319378389cdbb7 100644 --- a/src/ldap_helper.c +++ b/src/ldap_helper.c @@ -3833,7 +3833,6 @@ update_record(isc_task_t *task, isc_event_t *event) isc_boolean_t zone_reloaded = ISC_FALSE; isc_uint32_t serial; ldap_entry_t *entry = pevent->entry; - isc_boolean_t iszone; const char *fake_mname = NULL; dns_db_t *rbtdb = NULL; @@ -3859,29 +3858,23 @@ update_record(isc_task_t *task, isc_event_t *event) INIT_LIST(rdatalist); /* Convert domain name from text to struct dns_name_t. */ - dns_name_t name; - dns_name_t origin; dns_name_t prevname; dns_name_t prevorigin; - dns_name_init(&name, NULL); - dns_name_init(&origin, NULL); dns_name_init(&prevname, NULL); dns_name_init(&prevorigin, NULL); CHECK(manager_get_ldap_instance(pevent->dbname, &inst)); - CHECK(dn_to_dnsname(mctx, pevent->dn, &name, &origin, &iszone)); - INSIST(iszone == ISC_FALSE); - CHECK(zr_get_zone_ptr(inst->zone_register, &origin, &raw, &secure)); + CHECK(zr_get_zone_ptr(inst->zone_register, &entry->zone_name, &raw, &secure)); zone_found = ISC_TRUE; update_restart: rbtdb = NULL; ldapdb = NULL; ldapdb_rdatalist_destroy(mctx, &rdatalist); - CHECK(zr_get_zone_dbs(inst->zone_register, &origin, &ldapdb, &rbtdb)); + CHECK(zr_get_zone_dbs(inst->zone_register, &entry->zone_name, &ldapdb, &rbtdb)); CHECK(dns_db_newversion(ldapdb, &version)); - CHECK(dns_db_findnode(rbtdb, &name, ISC_TRUE, &node)); + CHECK(dns_db_findnode(rbtdb, &entry->fqdn, ISC_TRUE, &node)); result = dns_db_allrdatasets(rbtdb, node, version, 0, &rbt_rds_iterator); if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) goto cleanup; @@ -3931,12 +3924,12 @@ update_restart: pevent->dn); CHECK(setting_get_str("fake_mname", inst->local_settings, &fake_mname)); - CHECK(ldap_parse_rrentry(mctx, entry, &origin, fake_mname, + CHECK(ldap_parse_rrentry(mctx, entry, &entry->zone_name, fake_mname, &rdatalist)); } if (rbt_rds_iterator != NULL) { - CHECK(diff_ldap_rbtdb(mctx, &name, &rdatalist, + CHECK(diff_ldap_rbtdb(mctx, &entry->fqdn, &rdatalist, rbt_rds_iterator, &diff)); dns_rdatasetiter_destroy(&rbt_rds_iterator); } @@ -3950,7 +3943,7 @@ update_restart: dns_zone_log(raw, ISC_LOG_DEBUG(5), "writing new zone serial %u to LDAP", serial); - result = ldap_replace_serial(inst, &origin, serial); + result = ldap_replace_serial(inst, &entry->zone_name, serial); if (result != ISC_R_SUCCESS) dns_zone_log(raw, ISC_LOG_ERROR, "serial (%u) write back to LDAP failed", @@ -4032,12 +4025,8 @@ cleanup: if (inst != NULL) { sync_concurr_limit_signal(inst->sctx); - if (dns_name_dynamic(&name)) - dns_name_free(&name, inst->mctx); if (dns_name_dynamic(&prevname)) dns_name_free(&prevname, inst->mctx); - if (dns_name_dynamic(&origin)) - dns_name_free(&origin, inst->mctx); if (dns_name_dynamic(&prevorigin)) dns_name_free(&prevorigin, inst->mctx); } -- 2.1.0
From cc4dda573db838e4bf26f194984f92309e8c8923 Mon Sep 17 00:00:00 2001 From: Petr Spacek <pspa...@redhat.com> Date: Wed, 13 May 2015 11:16:01 +0200 Subject: [PATCH] Adapt ldap_parse_fwd_zoneentry() to use pre-parsed DNS names in LDAP entry. https://fedorahosted.org/bind-dyndb-ldap/ticket/151 --- src/ldap_helper.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/src/ldap_helper.c b/src/ldap_helper.c index 97ef857e01cf8a463bde885042319378389cdbb7..6454f9817977b832becd27b3aeaec97d3c640052 100644 --- a/src/ldap_helper.c +++ b/src/ldap_helper.c @@ -1769,52 +1769,44 @@ static isc_result_t ATTR_NONNULLS ATTR_CHECKRESULT ldap_parse_fwd_zoneentry(ldap_entry_t *entry, ldap_instance_t *inst) { const char *dn; - dns_name_t name; ldap_valuelist_t values; - isc_boolean_t iszone; char name_txt[DNS_NAME_FORMATSIZE]; isc_result_t result; REQUIRE(entry != NULL); REQUIRE(inst != NULL); - dns_name_init(&name, NULL); - /* Derive the DNS name of the zone from the DN. */ dn = entry->dn; - CHECK(dn_to_dnsname(inst->mctx, dn, &name, NULL, &iszone)); - INSIST(iszone == ISC_TRUE); CHECK(ldap_entry_getvalues(entry, "idnsZoneActive", &values)); if (HEAD(values) != NULL && strcasecmp(HEAD(values)->value, "TRUE") != 0) { /* Zone is not active */ - result = ldap_delete_zone2(inst, &name, ISC_TRUE, ISC_FALSE); + result = ldap_delete_zone2(inst, &entry->fqdn, + ISC_TRUE, ISC_FALSE); goto cleanup; } /* Zone is active */ - result = configure_zone_forwarders(entry, inst, &name); + result = configure_zone_forwarders(entry, inst, &entry->fqdn); if (result != ISC_R_DISABLED && result != ISC_R_SUCCESS) { log_error_r("forward zone '%s': could not configure forwarding", dn); goto cleanup; } - result = fwdr_add_zone(inst->fwd_register, &name); + result = fwdr_add_zone(inst->fwd_register, &entry->fqdn); if (result != ISC_R_EXISTS && result != ISC_R_SUCCESS) { - dns_name_format(&name, name_txt, DNS_NAME_FORMATSIZE); + dns_name_format(&entry->fqdn, name_txt, DNS_NAME_FORMATSIZE); log_error_r("failed to add forward zone '%s' " "to the forwarding register", name_txt); goto cleanup; } result = ISC_R_SUCCESS; - dns_name_format(&name, name_txt, DNS_NAME_FORMATSIZE); + dns_name_format(&entry->fqdn, name_txt, DNS_NAME_FORMATSIZE); log_info("forward zone '%s': loaded", name_txt); cleanup: - if (dns_name_dynamic(&name)) - dns_name_free(&name, inst->mctx); - return result; } -- 2.1.0
From 4bce8e6c64e527e47e5bb51adedc04e05695c5ce Mon Sep 17 00:00:00 2001 From: Petr Spacek <pspa...@redhat.com> Date: Wed, 13 May 2015 11:28:11 +0200 Subject: [PATCH] Adapt update_zone() to use pre-parsed DNS names in LDAP entry. https://fedorahosted.org/bind-dyndb-ldap/ticket/151 --- src/ldap_helper.c | 32 ++------------------------------ 1 file changed, 2 insertions(+), 30 deletions(-) diff --git a/src/ldap_helper.c b/src/ldap_helper.c index 6454f9817977b832becd27b3aeaec97d3c640052..38bf37736beabb6f5246bbca9c5bed9c85fb2b0e 100644 --- a/src/ldap_helper.c +++ b/src/ldap_helper.c @@ -1387,28 +1387,6 @@ cleanup: return result; } -/* Delete zone */ -static isc_result_t ATTR_NONNULLS ATTR_CHECKRESULT -ldap_delete_zone(ldap_instance_t *inst, const char *dn, isc_boolean_t lock, - isc_boolean_t preserve_forwarding) -{ - isc_result_t result; - isc_boolean_t iszone; - dns_name_t name; - dns_name_init(&name, NULL); - - CHECK(dn_to_dnsname(inst->mctx, dn, &name, NULL, &iszone)); - INSIST(iszone == ISC_TRUE); - - result = ldap_delete_zone2(inst, &name, lock, preserve_forwarding); - -cleanup: - if (dns_name_dynamic(&name)) - dns_name_free(&name, inst->mctx); - - return result; -} - /** * Remove zone from view but let the zone object intact. The same zone object * can be re-published later using publish_zone(). @@ -3697,21 +3675,17 @@ update_zone(isc_task_t *task, isc_event_t *event) ldap_instance_t *inst = NULL; isc_mem_t *mctx; dns_name_t prevname; - dns_name_t currname; ldap_entry_t *entry = pevent->entry; - isc_boolean_t iszone; mctx = pevent->mctx; - dns_name_init(&currname, NULL); dns_name_init(&prevname, NULL); CHECK(manager_get_ldap_instance(pevent->dbname, &inst)); INSIST(task == inst->task); /* For task-exclusive mode */ - CHECK(dn_to_dnsname(inst->mctx, pevent->dn, &currname, NULL, &iszone)); - INSIST(iszone == ISC_TRUE); if (SYNCREPL_DEL(pevent->chgtype)) { - CHECK(ldap_delete_zone(inst, pevent->dn, ISC_TRUE, ISC_FALSE)); + CHECK(ldap_delete_zone2(inst, &entry->fqdn, + ISC_TRUE, ISC_FALSE)); } else { if (entry->class & LDAP_ENTRYCLASS_MASTER) CHECK(ldap_parse_master_zoneentry(entry, NULL, inst, @@ -3750,8 +3724,6 @@ cleanup: if (inst != NULL) { sync_concurr_limit_signal(inst->sctx); sync_event_signal(inst->sctx, event); - if (dns_name_dynamic(&currname)) - dns_name_free(&currname, inst->mctx); if (dns_name_dynamic(&prevname)) dns_name_free(&prevname, inst->mctx); } -- 2.1.0
From 3641ce90df42da414fe62b87be569224afc1bdc6 Mon Sep 17 00:00:00 2001 From: Petr Spacek <pspa...@redhat.com> Date: Wed, 13 May 2015 11:38:49 +0200 Subject: [PATCH] Adapt ldap_parse_master_zoneentry() to use pre-parsed DNS names in LDAP entry. https://fedorahosted.org/bind-dyndb-ldap/ticket/151 --- src/ldap_helper.c | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/src/ldap_helper.c b/src/ldap_helper.c index 38bf37736beabb6f5246bbca9c5bed9c85fb2b0e..8d21fbf839bca9c28b7bfbce65b9aa76038cacd7 100644 --- a/src/ldap_helper.c +++ b/src/ldap_helper.c @@ -2284,17 +2284,15 @@ ldap_parse_master_zoneentry(ldap_entry_t * const entry, dns_db_t * const olddb, { const char *dn; ldap_valuelist_t values; - dns_name_t name; dns_zone_t *raw = NULL; dns_zone_t *secure = NULL; dns_zone_t *toview = NULL; isc_result_t result; isc_result_t lock_state = ISC_R_IGNORE; isc_boolean_t new_zone = ISC_FALSE; isc_boolean_t want_secure = ISC_FALSE; isc_boolean_t configured = ISC_FALSE; isc_boolean_t activity_changed; - isc_boolean_t iszone; isc_boolean_t isactive = ISC_FALSE; settings_set_t *zone_settings = NULL; isc_boolean_t ldap_writeback; @@ -2312,16 +2310,13 @@ ldap_parse_master_zoneentry(ldap_entry_t * const entry, dns_db_t * const olddb, REQUIRE(task == inst->task); /* For task-exclusive mode */ dns_diff_init(inst->mctx, &diff); - dns_name_init(&name, NULL); /* Derive the dns name of the zone from the DN. */ dn = entry->dn; - CHECK(dn_to_dnsname(inst->mctx, dn, &name, NULL, &iszone)); - INSIST(iszone == ISC_TRUE); run_exclusive_enter(inst, &lock_state); - result = configure_zone_forwarders(entry, inst, &name); + result = configure_zone_forwarders(entry, inst, &entry->fqdn); if (result != ISC_R_SUCCESS && result != ISC_R_DISABLED) goto cleanup; @@ -2333,9 +2328,10 @@ ldap_parse_master_zoneentry(ldap_entry_t * const entry, dns_db_t * const olddb, == 0); /* Check if we are already serving given zone */ - result = zr_get_zone_ptr(inst->zone_register, &name, &raw, &secure); + result = zr_get_zone_ptr(inst->zone_register, &entry->fqdn, + &raw, &secure); if (result == ISC_R_NOTFOUND || result == DNS_R_PARTIALMATCH) { - CHECK(create_zone(inst, dn, &name, olddb, want_secure, + CHECK(create_zone(inst, dn, &entry->fqdn, olddb, want_secure, &raw, &secure)); new_zone = ISC_TRUE; log_debug(2, "created zone %s: raw %p; secure %p", dn, raw, @@ -2349,20 +2345,21 @@ ldap_parse_master_zoneentry(ldap_entry_t * const entry, dns_db_t * const olddb, else dns_zone_log(secure, ISC_LOG_INFO, "downgrading zone to insecure"); - CHECK(zone_security_change(entry, &name, inst, task)); + CHECK(zone_security_change(entry, &entry->fqdn, inst, task)); goto cleanup; } else { /* Zone exists and it's security status is unchanged. */ INSIST(olddb == NULL); } - CHECK(zr_get_zone_settings(inst->zone_register, &name, &zone_settings)); + CHECK(zr_get_zone_settings(inst->zone_register, &entry->fqdn, + &zone_settings)); CHECK(zone_master_reconfigure(entry, zone_settings, raw, secure, task)); /* synchronize zone origin with LDAP */ - CHECK(zr_get_zone_dbs(inst->zone_register, &name, &ldapdb, &rbtdb)); + CHECK(zr_get_zone_dbs(inst->zone_register, &entry->fqdn, &ldapdb, &rbtdb)); CHECK(dns_db_newversion(ldapdb, &version)); sync_state_get(inst->sctx, &sync_state); - CHECK(zone_sync_apex(inst, entry, name, sync_state, new_zone, + CHECK(zone_sync_apex(inst, entry, entry->fqdn, sync_state, new_zone, ldapdb, rbtdb, version, &diff, &new_serial, &ldap_writeback, &data_changed)); @@ -2375,7 +2372,7 @@ ldap_parse_master_zoneentry(ldap_entry_t * const entry, dns_db_t * const olddb, if (ldap_writeback == ISC_TRUE) { dns_zone_log(raw, ISC_LOG_DEBUG(5), "writing new zone serial " "%u to LDAP", new_serial); - result = ldap_replace_serial(inst, &name, new_serial); + result = ldap_replace_serial(inst, &entry->fqdn, new_serial); if (result != ISC_R_SUCCESS) dns_zone_log(raw, ISC_LOG_ERROR, "serial (%u) write back to LDAP failed", @@ -2421,7 +2418,7 @@ ldap_parse_master_zoneentry(ldap_entry_t * const entry, dns_db_t * const olddb, CHECK(publish_zone(task, inst, toview)); CHECK(load_zone(toview, ISC_FALSE)); } else if (activity_changed == ISC_TRUE) { /* Zone was deactivated */ - CHECK(unpublish_zone(inst, &name, entry->dn)); + CHECK(unpublish_zone(inst, &entry->fqdn, entry->dn)); dns_zone_log(toview, ISC_LOG_INFO, "zone deactivated " "and removed from view"); } @@ -2439,13 +2436,12 @@ cleanup: log_error_r("zone '%s': publishing failed, rolling back due to", entry->dn); /* TODO: verify this */ - result = ldap_delete_zone2(inst, &name, ISC_TRUE, ISC_FALSE); + result = ldap_delete_zone2(inst, &entry->fqdn, + ISC_TRUE, ISC_FALSE); if (result != ISC_R_SUCCESS) log_error_r("zone '%s': rollback failed: ", entry->dn); } run_exclusive_exit(inst, lock_state); - if (dns_name_dynamic(&name)) - dns_name_free(&name, inst->mctx); if (raw != NULL) dns_zone_detach(&raw); if (secure != NULL) -- 2.1.0
From aac8522b32405c0f37c6d12aa50033bd604f7e43 Mon Sep 17 00:00:00 2001 From: Petr Spacek <pspa...@redhat.com> Date: Thu, 14 May 2015 14:02:41 +0200 Subject: [PATCH] Adapt ldap_sync_search_entry() to use pre-parsed DNS names in LDAP entry. https://fedorahosted.org/bind-dyndb-ldap/ticket/151 --- src/ldap_helper.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/src/ldap_helper.c b/src/ldap_helper.c index 8d21fbf839bca9c28b7bfbce65b9aa76038cacd7..951e873832e273165fe25c2f9d7b0fd5c9168bc7 100644 --- a/src/ldap_helper.c +++ b/src/ldap_helper.c @@ -4306,31 +4306,24 @@ int ldap_sync_search_entry ( metadb_node_t *node = NULL; isc_boolean_t mdb_write = ISC_FALSE; const char *ldap_base = NULL; - DECLARE_BUFFERED_NAME(fqdn); - DECLARE_BUFFERED_NAME(zone_name); #ifdef RBTDB_DEBUG static unsigned int count = 0; #endif if (inst->exiting) return LDAP_SUCCESS; - INIT_BUFFERED_NAME(fqdn); - INIT_BUFFERED_NAME(zone_name); - CHECK(sync_concurr_limit_wait(inst->sctx)); if (phase == LDAP_SYNC_CAPI_ADD || phase == LDAP_SYNC_CAPI_MODIFY) { CHECK(ldap_entry_parse(inst->mctx, ls->ls_ld, msg, entryUUID, &entry)); CHECK(mldap_newversion(inst->mldapdb)); mdb_write = ISC_TRUE; CHECK(mldap_entry_create(entry, inst->mldapdb, &node)); - if ((entry->class & LDAP_ENTRYCLASS_CONFIG) == 0) { - CHECK(dn_to_dnsname(inst->mctx, entry->dn, - &fqdn, &zone_name, NULL)); - CHECK(mldap_dnsname_store(&fqdn, &zone_name, node)); - } + if ((entry->class & LDAP_ENTRYCLASS_CONFIG) == 0) + CHECK(mldap_dnsname_store(&entry->fqdn, + &entry->zone_name, node)); metadb_node_close(&node); mldap_closeversion(inst->mldapdb, ISC_TRUE); @@ -4361,10 +4354,6 @@ cleanup: /* TODO: Add 'tainted' flag to the LDAP instance. */ } metadb_node_close(&node); - if (dns_name_dynamic(&fqdn)) - dns_name_free(&fqdn, inst->mctx); - if (dns_name_dynamic(&zone_name)) - dns_name_free(&zone_name, inst->mctx); /* Following return code will never reach upper layers. * It is limitation in ldap_sync_init() and ldap_sync_poll() -- 2.1.0
From f095fdf2c81037e4d4ceb4bd2eda6662be0e4530 Mon Sep 17 00:00:00 2001 From: Petr Spacek <pspa...@redhat.com> Date: Thu, 14 May 2015 17:17:30 +0200 Subject: [PATCH] Adapt syncrepl_update() to use pre-parsed DNS names and metadata in LDAP entry. https://fedorahosted.org/bind-dyndb-ldap/ticket/151 --- src/ldap_entry.c | 26 ------------------------ src/ldap_entry.h | 5 ----- src/ldap_helper.c | 60 ++++++++++--------------------------------------------- 3 files changed, 11 insertions(+), 80 deletions(-) diff --git a/src/ldap_entry.c b/src/ldap_entry.c index 165d034cc4a15b0867b2dbbef74f16d6b9a97d51..437b31dcca974ee9341560a72b48d69d0ec9b8b9 100644 --- a/src/ldap_entry.c +++ b/src/ldap_entry.c @@ -498,32 +498,6 @@ ldap_entry_parseclass(ldap_entry_t *entry, ldap_entryclass_t *class) return ISC_R_SUCCESS; } -/** - * Infer entry class from auxiliary information. - * - * This is a fallback method for cases where objectClass values - * are not available. - * - * TODO: Object class information should be stored in UUID database - * (once we have it). - */ -isc_result_t -ldap_entry_guessclass(dns_name_t *entry_name, isc_boolean_t iszone, - fwd_register_t *fwd_register, ldap_entryclass_t *class) { - REQUIRE(class != NULL); - - if (iszone == ISC_TRUE) { - if (fwdr_zone_ispresent(fwd_register, entry_name) - == ISC_R_SUCCESS) - *class = LDAP_ENTRYCLASS_FORWARD; - else /* master zone */ - *class = (LDAP_ENTRYCLASS_MASTER | LDAP_ENTRYCLASS_RR); - } else - *class = LDAP_ENTRYCLASS_RR; - - return ISC_R_SUCCESS; -} - isc_result_t ldap_attr_firstvalue(ldap_attribute_t *attr, ld_string_t *str) { diff --git a/src/ldap_entry.h b/src/ldap_entry.h index 606fe8894579dc527e3a1723de51d5f9b700dd5d..2ccdcc42a5b5196791f0842c35f2b6a60155e3a7 100644 --- a/src/ldap_entry.h +++ b/src/ldap_entry.h @@ -140,11 +140,6 @@ ldap_entry_getfakesoa(ldap_entry_t *entry, const char *fake_mname, ld_string_t *target) ATTR_NONNULLS ATTR_CHECKRESULT; isc_result_t -ldap_entry_guessclass(dns_name_t *entry_name, isc_boolean_t iszone, - fwd_register_t *fwd_register, ldap_entryclass_t *class) - ATTR_NONNULLS ATTR_CHECKRESULT; - -isc_result_t ldap_attr_firstvalue(ldap_attribute_t *attr, ld_string_t *str) ATTR_NONNULLS ATTR_CHECKRESULT; /* diff --git a/src/ldap_helper.c b/src/ldap_helper.c index 951e873832e273165fe25c2f9d7b0fd5c9168bc7..592eadb9911f90bbdc58149eb62edcbedef34795 100644 --- a/src/ldap_helper.c +++ b/src/ldap_helper.c @@ -4050,72 +4050,40 @@ cleanup: static void ATTR_NONNULLS syncrepl_update(ldap_instance_t *inst, ldap_entry_t *entry, int chgtype) { - ldap_entryclass_t class = LDAP_ENTRYCLASS_NONE; isc_result_t result = ISC_R_SUCCESS; ldap_syncreplevent_t *pevent = NULL; isc_event_t *wait_event = NULL; - dns_name_t entry_name; - dns_name_t entry_origin; dns_name_t *zone_name = NULL; dns_zone_t *zone_ptr = NULL; char *dn = NULL; char *dbname = NULL; - const char *ldap_base = NULL; - isc_boolean_t isbase; - isc_boolean_t iszone; isc_mem_t *mctx = NULL; isc_taskaction_t action = NULL; isc_task_t *task = NULL; sync_state_t sync_state; + REQUIRE(entry->class != LDAP_ENTRYCLASS_NONE); + log_debug(20, "syncrepl change type: " /*"none%d,"*/ "add%d, del%d, mod%d", /* moddn%d", */ /* !SYNCREPL_ANY(chgtype), */ SYNCREPL_ADD(chgtype), SYNCREPL_DEL(chgtype), SYNCREPL_MOD(chgtype)/*, SYNCREPL_MODDN(chgtype) */ ); isc_mem_attach(inst->mctx, &mctx); - dns_name_init(&entry_name, NULL); - dns_name_init(&entry_origin, NULL); CHECKED_MEM_STRDUP(mctx, entry->dn, dn); CHECKED_MEM_STRDUP(mctx, inst->db_name, dbname); - /* TODO: handle object class inference properly - via UUID database */ - CHECK(setting_get_str("base", inst->local_settings, &ldap_base)); - CHECK(ldap_dn_compare(ldap_base, entry->dn, &isbase)); - if (isbase == ISC_TRUE) { - class = LDAP_ENTRYCLASS_CONFIG; - iszone = ISC_FALSE; - } else { - CHECK(dn_to_dnsname(inst->mctx, dn, &entry_name, &entry_origin, - &iszone)); - switch (chgtype) { - case LDAP_SYNC_CAPI_ADD: - case LDAP_SYNC_CAPI_MODIFY: - class = entry->class; - break; - default: - /* deleted entry doesn't contain objectClass, so - * we need to find if the entry is zone or not - * in other way */ - CHECK(ldap_entry_guessclass(&entry_name, iszone, - inst->fwd_register, - &class)); - break; - } - } - REQUIRE(class != LDAP_ENTRYCLASS_NONE); - - if (class & LDAP_ENTRYCLASS_MASTER) - zone_name = &entry_name; + if (entry->class & LDAP_ENTRYCLASS_MASTER) + zone_name = &entry->fqdn; else - zone_name = &entry_origin; + zone_name = &entry->zone_name; /* Process ordinary records in parallel but serialize operations on * master zone objects. * See discussion about run_exclusive_begin() function in lock.c. */ - if ((class & LDAP_ENTRYCLASS_RR) != 0 && - (class & LDAP_ENTRYCLASS_MASTER) == 0) { + if ((entry->class & LDAP_ENTRYCLASS_RR) != 0 && + (entry->class & LDAP_ENTRYCLASS_MASTER) == 0) { result = zr_get_zone_ptr(inst->zone_register, zone_name, &zone_ptr, NULL); if (result == ISC_R_SUCCESS && dns_zone_getmgr(zone_ptr) != NULL) @@ -4141,21 +4109,19 @@ syncrepl_update(ldap_instance_t *inst, ldap_entry_t *entry, int chgtype) } */ - if ((class & LDAP_ENTRYCLASS_CONFIG) != 0) + if ((entry->class & LDAP_ENTRYCLASS_CONFIG) != 0) action = update_config; - else if ((class & LDAP_ENTRYCLASS_MASTER) != 0) + else if ((entry->class & LDAP_ENTRYCLASS_MASTER) != 0) action = update_zone; - else if ((class & LDAP_ENTRYCLASS_FORWARD) != 0) + else if ((entry->class & LDAP_ENTRYCLASS_FORWARD) != 0) action = update_zone; - else if ((class & LDAP_ENTRYCLASS_RR) != 0) + else if ((entry->class & LDAP_ENTRYCLASS_RR) != 0) action = update_record; else { log_error("unsupported objectClass: dn '%s'", dn); result = ISC_R_NOTIMPLEMENTED; goto cleanup; } - CHECK(dn_want_zone(__func__, dn, iszone, - ISC_TF(class & (LDAP_ENTRYCLASS_MASTER | LDAP_ENTRYCLASS_FORWARD)))); /* All events for single zone are handled by one task, so we don't * need to spend time with normal records. */ @@ -4191,10 +4157,6 @@ syncrepl_update(ldap_instance_t *inst, ldap_entry_t *entry, int chgtype) CHECK(sync_event_wait(inst->sctx, wait_event)); cleanup: - if (dns_name_dynamic(&entry_name)) - dns_name_free(&entry_name, inst->mctx); - if (dns_name_dynamic(&entry_origin)) - dns_name_free(&entry_origin, inst->mctx); if (zone_ptr != NULL) dns_zone_detach(&zone_ptr); if (result != ISC_R_SUCCESS) -- 2.1.0
From aed476b4f9b0a3a340a386ae74487f0fa35ac1a4 Mon Sep 17 00:00:00 2001 From: Petr Spacek <pspa...@redhat.com> Date: Thu, 14 May 2015 18:13:55 +0200 Subject: [PATCH] Add function for node deletion from generic meta-database. https://fedorahosted.org/bind-dyndb-ldap/ticket/151 --- src/metadb.c | 40 ++++++++++++++++++++++++++++++++++++++++ src/metadb.h | 3 +++ 2 files changed, 43 insertions(+) diff --git a/src/metadb.c b/src/metadb.c index b9caf24b261139add9bd0e003c7878fb188b4803..e36f28190cf16527715320d876feab7089f54e83 100644 --- a/src/metadb.c +++ b/src/metadb.c @@ -9,6 +9,7 @@ #include <dns/db.h> #include <dns/rdatalist.h> +#include <dns/rdatasetiter.h> #include "metadb.h" #include "util.h" @@ -147,6 +148,45 @@ metadb_node_close(metadb_node_t **nodep) { } /** + * Delete all RRsets in given metaDB node. + */ +isc_result_t +metadb_node_delete(metadb_node_t **nodep) { + isc_result_t result; + metadb_node_t *node; + dns_rdatasetiter_t *iter = NULL; + dns_rdataset_t rdataset; + + REQUIRE(nodep != NULL && *nodep != NULL); + node = *nodep; + + dns_rdataset_init(&rdataset); + CHECK(dns_db_allrdatasets(node->rbtdb, node->dbnode, node->version, 0, + &iter)); + + for (result = dns_rdatasetiter_first(iter); + result == ISC_R_SUCCESS; + result = dns_rdatasetiter_next(iter)) { + + dns_rdatasetiter_current(iter, &rdataset); + CHECK(dns_db_deleterdataset(node->rbtdb, node->dbnode, + node->version, rdataset.type, 0)); + dns_rdataset_disassociate(&rdataset); + } + if (result == ISC_R_NOMORE) + result = ISC_R_SUCCESS; + +cleanup: + if (dns_rdataset_isassociated(&rdataset)) + dns_rdataset_disassociate(&rdataset); + if (iter != NULL) + dns_rdatasetiter_destroy(&iter); + if (result == ISC_R_SUCCESS) + metadb_node_close(nodep); + return result; +} + +/** * Create new "metaDB node" structure and attach underlying RBT DB node to it. * * @param[in] version Underlying RBTDB version to use. diff --git a/src/metadb.h b/src/metadb.h index f1869d87b72f2c3dad8c0b1a7311b3578673c135..681535d26b56692e422c44f40ffd7d43880ba406 100644 --- a/src/metadb.h +++ b/src/metadb.h @@ -53,4 +53,7 @@ metadb_rdataset_get(metadb_node_t *node, dns_rdatatype_t rrtype, void ATTR_NONNULLS metadb_node_close(metadb_node_t **nodep); +isc_result_t ATTR_NONNULLS +metadb_node_delete(metadb_node_t **nodep); + #endif /* SRC_METADB_H_ */ -- 2.1.0
From 7cd3861c0cee6709d54c94af7514ca9280aed617 Mon Sep 17 00:00:00 2001 From: Petr Spacek <pspa...@redhat.com> Date: Thu, 14 May 2015 18:14:38 +0200 Subject: [PATCH] Add ability to open existing metaDB node for writing. https://fedorahosted.org/bind-dyndb-ldap/ticket/151 --- src/metadb.c | 30 ++++++++++++++++++++++++++---- src/metadb.h | 3 +++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/metadb.c b/src/metadb.c index e36f28190cf16527715320d876feab7089f54e83..610df5a50d5b4ce02d584e8b78f7a9bf74ab159a 100644 --- a/src/metadb.c +++ b/src/metadb.c @@ -220,8 +220,8 @@ cleanup: } /** - * Create new "metaDB node" structure and attach current read-only version of - * RBT DB to it. + * Associate "metaDB node" structure with existing node in current read-only + * version of RBT DB. * * @param[in] mname Name of the node in metaDB. E.g. '1234.uuid.ldap.' * @param[out] nodep Resulting "metaDB node" structure. Node has to be freed @@ -241,8 +241,7 @@ cleanup: } /** - * Create new "metaDB node" structure and attach current writeable version of - * RBT DB to it. + * Create new "metaDB node" in current writeable version of metaDB. * * @param[in] mname Name of the node in metaDB. E.g. '1234.uuid.ldap.' * @param[out] nodep Resulting "metaDB node" structure. Node has to be freed @@ -265,6 +264,29 @@ cleanup: } /** + * Open existing "metaDB node" in current writeable version of metaDB. + * + * @param[in] mname Name of the node in metaDB. E.g. '1234.uuid.ldap.' + * @param[out] nodep Resulting "metaDB node" structure. Node has to be freed + * using metadb_node_close(). + * + * @pre MetaDB was opened by newversion(). + */ +isc_result_t +metadb_writenode_open(metadb_t *mdb, dns_name_t *mname, metadb_node_t **nodep) { + isc_result_t result; + dns_dbversion_t *ver = NULL; + + INSIST(mdb->newversion != NULL); + dns_db_attachversion(mdb->rbtdb, mdb->newversion, &ver); + CHECK(metadb_node_init(mdb, ver, mname, ISC_FALSE, nodep)); + +cleanup: + dns_db_closeversion(mdb->rbtdb, &ver, ISC_FALSE); + return result; +} + +/** * Store rdata into metaDB node and overwrite all existing values for RR type * specified in rdata. * diff --git a/src/metadb.h b/src/metadb.h index 681535d26b56692e422c44f40ffd7d43880ba406..d6e3490f65a4bdd616e7567f86a875415b9d4c10 100644 --- a/src/metadb.h +++ b/src/metadb.h @@ -44,6 +44,9 @@ isc_result_t ATTR_CHECKRESULT ATTR_NONNULLS metadb_writenode_create(metadb_t *mdb, dns_name_t *mname, metadb_node_t **nodep); isc_result_t ATTR_CHECKRESULT ATTR_NONNULLS +metadb_writenode_open(metadb_t *mdb, dns_name_t *mname, metadb_node_t **nodep); + +isc_result_t ATTR_CHECKRESULT ATTR_NONNULLS metadb_rdata_store(dns_rdata_t *rdata, metadb_node_t *node); isc_result_t ATTR_CHECKRESULT ATTR_NONNULLS -- 2.1.0
From ce007b262a6fad987491a25a9f57772ee1237c54 Mon Sep 17 00:00:00 2001 From: Petr Spacek <pspa...@redhat.com> Date: Thu, 14 May 2015 18:20:06 +0200 Subject: [PATCH] Add function for node deletion to meta-LDAP database API. https://fedorahosted.org/bind-dyndb-ldap/ticket/151 --- src/mldap.c | 21 +++++++++++++++++++++ src/mldap.h | 3 +++ 2 files changed, 24 insertions(+) diff --git a/src/mldap.c b/src/mldap.c index 3195ad89f1eb51d72bb0e2487a913a6e871466b4..71de3c58d9816bc91dc4311f73433e278ffac312 100644 --- a/src/mldap.c +++ b/src/mldap.c @@ -307,3 +307,24 @@ mldap_entry_read(mldapdb_t *mldap, struct berval *uuid, metadb_node_t **nodep) { return metadb_readnode_open(mldap->mdb, &mname, nodep); } + +/** + * Delete metaLDAP entry. + * All notes about metadb_writenode_open() apply equally here. + */ +isc_result_t +mldap_entry_delete(mldapdb_t *mldap, struct berval *uuid) { + isc_result_t result; + metadb_node_t *node = NULL; + DECLARE_BUFFERED_NAME(mname); + + INIT_BUFFERED_NAME(mname); + + ldap_uuid_to_mname(uuid, &mname); + + CHECK(metadb_writenode_open(mldap->mdb, &mname, &node)); + CHECK(metadb_node_delete(&node)); + +cleanup: + return result; +} diff --git a/src/mldap.h b/src/mldap.h index 8312a638416c1f8b17b7293c32b071f1b3f71665..752ab28b2da956817ad27c9c928863bc9e601c0c 100644 --- a/src/mldap.h +++ b/src/mldap.h @@ -31,6 +31,9 @@ isc_result_t ATTR_CHECKRESULT ATTR_NONNULLS mldap_entry_create(ldap_entry_t *entry, mldapdb_t *mldap, metadb_node_t **nodep); isc_result_t ATTR_CHECKRESULT ATTR_NONNULLS +mldap_entry_delete(mldapdb_t *mldap, struct berval *uuid); + +isc_result_t ATTR_CHECKRESULT ATTR_NONNULLS mldap_class_get(metadb_node_t *node, ldap_entryclass_t *class); isc_result_t ATTR_CHECKRESULT ATTR_NONNULLS -- 2.1.0
From 0b405088eaf00a79bb02aec854785054f13eec23 Mon Sep 17 00:00:00 2001 From: Petr Spacek <pspa...@redhat.com> Date: Thu, 14 May 2015 18:21:12 +0200 Subject: [PATCH] Delete metadata about objects deleted from LDAP. https://fedorahosted.org/bind-dyndb-ldap/ticket/151 --- src/ldap_helper.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/ldap_helper.c b/src/ldap_helper.c index 592eadb9911f90bbdc58149eb62edcbedef34795..8922141724c4351db9435fd73e91756d60606390 100644 --- a/src/ldap_helper.c +++ b/src/ldap_helper.c @@ -4047,7 +4047,7 @@ cleanup: return result; } -static void ATTR_NONNULLS +static isc_result_t ATTR_NONNULLS ATTR_CHECKRESULT syncrepl_update(ldap_instance_t *inst, ldap_entry_t *entry, int chgtype) { isc_result_t result = ISC_R_SUCCESS; @@ -4176,6 +4176,7 @@ cleanup: if (task != NULL) isc_task_detach(&task); } + return result; } #define CHECK_EXIT \ @@ -4266,56 +4267,63 @@ int ldap_sync_search_entry ( ldap_entry_t *entry = NULL; isc_result_t result; metadb_node_t *node = NULL; - isc_boolean_t mdb_write = ISC_FALSE; + isc_boolean_t mldap_open = ISC_FALSE; const char *ldap_base = NULL; #ifdef RBTDB_DEBUG static unsigned int count = 0; #endif if (inst->exiting) return LDAP_SUCCESS; + CHECK(mldap_newversion(inst->mldapdb)); + mldap_open = ISC_TRUE; + CHECK(sync_concurr_limit_wait(inst->sctx)); if (phase == LDAP_SYNC_CAPI_ADD || phase == LDAP_SYNC_CAPI_MODIFY) { CHECK(ldap_entry_parse(inst->mctx, ls->ls_ld, msg, entryUUID, &entry)); - CHECK(mldap_newversion(inst->mldapdb)); - mdb_write = ISC_TRUE; CHECK(mldap_entry_create(entry, inst->mldapdb, &node)); if ((entry->class & LDAP_ENTRYCLASS_CONFIG) == 0) CHECK(mldap_dnsname_store(&entry->fqdn, &entry->zone_name, node)); + /* commit new entry into metaLDAP DB before something breaks */ metadb_node_close(&node); mldap_closeversion(inst->mldapdb, ISC_TRUE); + mldap_open = ISC_FALSE; } else if (phase == LDAP_SYNC_CAPI_DELETE) { INSIST(setting_get_str("base", inst->local_settings, &ldap_base) == ISC_R_SUCCESS); CHECK(ldap_entry_reconstruct(inst->mctx, inst->zone_register, ldap_base, inst->mldapdb, entryUUID, &entry)); + CHECK(mldap_entry_delete(inst->mldapdb, entryUUID)); + /* do not commit into DB until syncrepl_update finished */ } else { log_bug("syncrepl phase %x is not supported", phase); CLEANUP_WITH(ISC_R_NOTIMPLEMENTED); } - syncrepl_update(inst, entry, phase); + CHECK(syncrepl_update(inst, entry, phase)); + /* commit eventual deletion if the syncrepl event was sent */ + #ifdef RBTDB_DEBUG if (++count % 100 == 0) log_info("ldap_sync_search_entry: %u entries read; inuse: %zd", count, isc_mem_inuse(inst->mctx)); #endif cleanup: + metadb_node_close(&node); + if (mldap_open == ISC_TRUE) + mldap_closeversion(inst->mldapdb, ISC_TF(result == ISC_R_SUCCESS)); if (result != ISC_R_SUCCESS) { - if (mdb_write == ISC_TRUE) - mldap_closeversion(inst->mldapdb, ISC_FALSE); log_error_r("ldap_sync_search_entry failed"); sync_concurr_limit_signal(inst->sctx); /* TODO: Add 'tainted' flag to the LDAP instance. */ } - metadb_node_close(&node); /* Following return code will never reach upper layers. * It is limitation in ldap_sync_init() and ldap_sync_poll() -- 2.1.0
-- Manage your subscription for the Freeipa-devel mailing list: https://www.redhat.com/mailman/listinfo/freeipa-devel Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code