diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | ldap_driver.c | 85 | ||||
-rw-r--r-- | ldap_helper.c | 200 | ||||
-rw-r--r-- | ldap_helper.h | 10 | ||||
-rw-r--r-- | zone_manager.c | 202 | ||||
-rw-r--r-- | zone_manager.h | 34 |
6 files changed, 449 insertions, 84 deletions
@@ -6,7 +6,7 @@ LIBMINOR = 0 LIBNAME = libdnsldap.so.$(LIBMAJOR).$(LIBMINOR).0 LIBSONAME = libdnsldap.so.$(LIBMAJOR) OBJS = ldap_driver.o semaphore.o ldap_convert.o ldap_helper.o log.o settings.o -OBJS += str.o +OBJS += str.o zone_manager.o CFLAGS := -Wall -Wextra -pedantic -std=c99 -g -fPIC $(CFLAGS) diff --git a/ldap_driver.c b/ldap_driver.c index 70751ab..b032bf0 100644 --- a/ldap_driver.c +++ b/ldap_driver.c @@ -32,6 +32,7 @@ #include "ldap_helper.h" #include "log.h" #include "util.h" +#include "zone_manager.h" #define LDAPDB_MAGIC ISC_MAGIC('L', 'D', 'P', 'D') #define VALID_LDAPDB(ldapdb) \ @@ -42,20 +43,10 @@ LDAPDBNODE_MAGIC) typedef struct { - ldap_db_t *ldap_db; -} ldapdb_data_t; - -typedef struct { dns_db_t common; isc_refcount_t refs; isc_mutex_t lock; /* convert to isc_rwlock_t ? */ - /* - * XXX LDAP: - * - * Add connection specification here - probably pointer to one shared - * connection info for multiple zones? Will be used by all - * ldapdb_methods to take information from LDAP. - */ + ldap_db_t *ldap_db; } ldapdb_t; typedef struct { @@ -67,10 +58,10 @@ typedef struct { static int dummy; static void *ldapdb_version = &dummy; -static ldapdb_data_t driver_data; -static void -detachnode(dns_db_t *db, dns_dbnode_t **targetp); +static void free_ldapdb(ldapdb_t *ldapdb); +static void detachnode(dns_db_t *db, dns_dbnode_t **targetp); + /* ldapdbnode_t functions */ static isc_result_t @@ -133,12 +124,18 @@ detach(dns_db_t **dbp) isc_refcount_decrement(&ldapdb->refs, &refs); - if (refs != 0) { - *dbp = NULL; - return; - } + if (refs == 0) + free_ldapdb(ldapdb); - /* Clean all ldapdb_t stuff here */ + *dbp = NULL; +} + +static void +free_ldapdb(ldapdb_t *ldapdb) +{ + DESTROYLOCK(&ldapdb->lock); + dns_name_free(&ldapdb->common.origin, ldapdb->common.mctx); + isc_mem_putanddetach(&ldapdb->common.mctx, ldapdb, sizeof(*ldapdb)); } static isc_result_t @@ -246,6 +243,7 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, ldapdb_rdatalist_t rdatalist; ldapdbnode_t *node = NULL; + log_func_enter_args("name=%s, create=%d", name->ndata, create); REQUIRE(VALID_LDAPDB(ldapdb)); result = ldapdb_rdatalist_get(ldapdb->common.mctx, name, &rdatalist); @@ -273,10 +271,15 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, *nodep = node; + log_func_exit_result(ISC_R_SUCCESS); + return ISC_R_SUCCESS; cleanup: ldapdb_rdatalist_destroy(ldapdb->common.mctx, &rdatalist); + + log_func_exit_result(result); + return result; } @@ -298,6 +301,8 @@ find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, UNUSED(options); UNUSED(sigrdataset); + log_func_enter(); + REQUIRE(VALID_LDAPDB(ldapdb)); /* XXX not yet implemented */ @@ -409,7 +414,10 @@ detachnode(dns_db_t *db, dns_dbnode_t **targetp) if (refs == 0) { ldapdb_rdatalist_destroy(ldapdb->common.mctx, &node->rdatalist); dns_name_free(&node->owner, ldapdb->common.mctx); + isc_mem_put(ldapdb->common.mctx, node, sizeof(*node)); } + + *targetp = NULL; } static isc_result_t @@ -691,7 +699,7 @@ ldapdb_create(isc_mem_t *mctx, dns_name_t *name, dns_dbtype_t type, UNUSED(driverarg); /* Currently we don't need any data */ - /* LDAP server has to be specified at least */ + /* Database implementation name and name pointing to ldap_db_t */ REQUIRE(argc > 0); REQUIRE(type == dns_dbtype_zone); @@ -712,6 +720,7 @@ ldapdb_create(isc_mem_t *mctx, dns_name_t *name, dns_dbtype_t type, goto clean_ldapdb; isc_ondestroy_init(&ldapdb->common.ondest); + ldapdb->common.mctx = NULL; isc_mem_attach(mctx, &ldapdb->common.mctx); result = isc_mutex_init(&ldapdb->lock); @@ -722,14 +731,9 @@ ldapdb_create(isc_mem_t *mctx, dns_name_t *name, dns_dbtype_t type, if (result != ISC_R_SUCCESS) goto clean_lock; - /* - * XXX LDAP: - * - * Now we have to setup connection info. Parameters passed in - * configuration file are in arg && argv. So use them and setup - * per-zone connection (will be used by ldapdb_methods). Parameters were - * passed by ldap zone manager and by dns_zone_setdbtype method. - */ + result = manager_get_ldap_db(argv[0], &ldapdb->ldap_db); + if (result != ISC_R_SUCCESS) + goto clean_lock; ldapdb->common.magic = DNS_DB_MAGIC; ldapdb->common.impmagic = LDAPDB_MAGIC; @@ -743,22 +747,28 @@ clean_lock: clean_origin: dns_name_free(&ldapdb->common.origin, mctx); clean_ldapdb: - isc_mem_put(mctx, ldapdb, sizeof(*ldapdb)); + isc_mem_putanddetach(&ldapdb->common.mctx, ldapdb, sizeof(*ldapdb)); return result; } static dns_dbimplementation_t *ldapdb_imp; -static const char *ldapdb_impname = "dynamic-ldap"; +const char *ldapdb_impname = "dynamic-ldap"; + isc_result_t dynamic_driver_init(isc_mem_t *mctx, const char *name, const char * const *argv, - dns_view_t *view) + dns_view_t *view, dns_zonemgr_t *zmgr) { isc_result_t result; + ldap_db_t *ldap_db; + REQUIRE(mctx != NULL); + REQUIRE(name != NULL); REQUIRE(argv != NULL); - UNUSED(view); + REQUIRE(view != NULL); + + ldap_db = NULL; log_debug(2, "Registering dynamic ldap driver for %s.", name); @@ -769,6 +779,7 @@ dynamic_driver_init(isc_mem_t *mctx, const char *name, const char * const *argv, i++; } + /* Register new DNS DB implementation. */ result = dns_db_register(ldapdb_impname, &ldapdb_create, NULL, mctx, &ldapdb_imp); if (result == ISC_R_EXISTS) @@ -777,9 +788,8 @@ dynamic_driver_init(isc_mem_t *mctx, const char *name, const char * const *argv, if (result != ISC_R_SUCCESS) return result; - CHECK(new_ldap_db(mctx, &driver_data.ldap_db, argv)); - - get_zone_list(driver_data.ldap_db); + CHECK(new_ldap_db(mctx, view, &ldap_db, argv)); + CHECK(manager_add_db_instance(mctx, name, ldap_db, zmgr)); /* * XXX now fetch all zones and initialize ldap zone manager @@ -806,6 +816,9 @@ dynamic_driver_init(isc_mem_t *mctx, const char *name, const char * const *argv, return ISC_R_SUCCESS; cleanup: + if (ldap_db != NULL) + destroy_ldap_db(&ldap_db); + return result; } @@ -813,5 +826,5 @@ void dynamic_driver_destroy(void) { dns_db_unregister(&ldapdb_imp); - destroy_ldap_db(&driver_data.ldap_db); + destroy_manager(); } diff --git a/ldap_helper.c b/ldap_helper.c index 011ab96..d5561c8 100644 --- a/ldap_helper.c +++ b/ldap_helper.c @@ -1,7 +1,7 @@ /* Authors: Martin Nagy <mnagy@redhat.com> * Adam Tkac <atkac@redhat.com> * - * Copyright (C) 2008 Red Hat + * Copyright (C) 2008, 2009 Red Hat * see file 'COPYING' for use and warranty information * * This program is free software; you can redistribute it and/or @@ -24,6 +24,8 @@ #include <dns/rdatatype.h> #include <dns/result.h> #include <dns/ttl.h> +#include <dns/view.h> +#include <dns/zone.h> #include <isc/buffer.h> #include <isc/lex.h> @@ -38,6 +40,7 @@ #include <string.h> #include <strings.h> +#include "ldap_convert.h" #include "ldap_helper.h" #include "log.h" #include "semaphore.h" @@ -69,9 +72,12 @@ struct ldap_auth_pair { /* These are typedefed in ldap_helper.h */ struct ldap_db { isc_mem_t *mctx; + dns_view_t *view; + /* List of LDAP connections. */ semaphore_t conn_semaphore; LIST(ldap_instance_t) conn_list; + /* Settings. */ ld_string_t *host; ld_string_t *base; @@ -88,16 +94,21 @@ struct ldap_instance { LDAP *handle; LDAPMessage *result; + + /* Temporary stuff. */ LDAPMessage *entry; BerElement *ber; char *attribute; char **values; + char *dn; }; /* * Constants. */ +extern const char *ldapdb_impname; + /* Supported authentication types. */ const ldap_auth_pair_t supported_ldap_auth[] = { { AUTH_NONE, "none" }, @@ -115,6 +126,8 @@ const ldap_auth_pair_t supported_ldap_auth[] = { static isc_result_t new_ldap_instance(ldap_db_t *ldap_db, ldap_instance_t **ldap_instp); static void destroy_ldap_instance(ldap_instance_t **ldap_instp); +static isc_result_t add_or_modify_zone(ldap_db_t *ldap_db, const char *dn, + const char *db_name, dns_zonemgr_t *zmgr); static ldap_instance_t * get_connection(ldap_db_t *ldap_db); static void put_connection(ldap_instance_t *ldap_inst); static isc_result_t ldap_connect(ldap_instance_t *ldap_inst); @@ -125,9 +138,11 @@ static const LDAPMessage *next_entry(ldap_instance_t *inst); static const char *next_attribute(ldap_instance_t *inst); static const char *get_attribute(ldap_instance_t *inst); static char **get_values(ldap_instance_t *inst); +static const char *get_dn(ldap_instance_t *inst); isc_result_t -new_ldap_db(isc_mem_t *mctx, ldap_db_t **ldap_dbp, const char * const *argv) +new_ldap_db(isc_mem_t *mctx, dns_view_t *view, ldap_db_t **ldap_dbp, + const char * const *argv) { unsigned int i; isc_result_t result; @@ -141,6 +156,7 @@ new_ldap_db(isc_mem_t *mctx, ldap_db_t **ldap_dbp, const char * const *argv) }; REQUIRE(mctx != NULL); + REQUIRE(view != NULL); REQUIRE(ldap_dbp != NULL && *ldap_dbp == NULL); ldap_db = isc_mem_get(mctx, sizeof(ldap_db_t)); @@ -148,9 +164,11 @@ new_ldap_db(isc_mem_t *mctx, ldap_db_t **ldap_dbp, const char * const *argv) return ISC_R_NOMEMORY; ZERO_PTR(ldap_db); - memset(ldap_db, 0, sizeof(ldap_db_t)); isc_mem_attach(mctx, &ldap_db->mctx); + ldap_db->view = view; + /* commented out for now, cause named to hang */ + //dns_view_attach(view, &ldap_db->view); INIT_LIST(ldap_db->conn_list); ldap_db->auth_method = AUTH_NONE; /* todo: should be in settings */ @@ -211,6 +229,9 @@ destroy_ldap_db(ldap_db_t **ldap_dbp) str_destroy(&ldap_db->base); semaphore_destroy(&ldap_db->conn_semaphore); + /* commented out for now, causes named to hang */ + //dns_view_detach(&ldap_db->view); + isc_mem_putanddetach(&ldap_db->mctx, ldap_db, sizeof(ldap_db_t)); *ldap_dbp = NULL; @@ -230,7 +251,6 @@ new_ldap_instance(ldap_db_t *ldap_db, ldap_instance_t **ldap_instp) return ISC_R_NOMEMORY; ZERO_PTR(ldap_inst); - memset(ldap_inst, 0, sizeof(ldap_instance_t)); ldap_inst->database = ldap_db; INIT_LINK(ldap_inst, link); @@ -272,6 +292,102 @@ destroy_ldap_instance(ldap_instance_t **ldap_instp) *ldap_instp = NULL; } +/* TODO: Delete old zones. */ +isc_result_t +refresh_zones_from_ldap(ldap_db_t *ldap_db, const char *name, + dns_zonemgr_t *zmgr) +{ + isc_result_t result = ISC_R_SUCCESS; + ldap_instance_t *ldap_inst; + char *attrs[] = { + "idnsName", NULL + }; + + REQUIRE(ldap_db != NULL); + REQUIRE(name != NULL); + + log_debug(2, "refreshing list of zones"); + + ldap_inst = get_connection(ldap_db); + + ldap_query(ldap_inst, LDAP_SCOPE_SUBTREE, attrs, 0, + "(objectClass=idnsZone)"); + + while (next_entry(ldap_inst)) + CHECK(add_or_modify_zone(ldap_db, get_dn(ldap_inst), name, zmgr)); + +cleanup: + put_connection(ldap_inst); + + log_debug(2, "finished refreshing list of zones"); + + return result; +} + +static isc_result_t +add_or_modify_zone(ldap_db_t *ldap_db, const char *dn, const char *db_name, + dns_zonemgr_t *zmgr) +{ + isc_result_t result; + dns_zone_t *zone; + dns_name_t name; + const char *argv[2]; + + REQUIRE(ldap_db != NULL); + REQUIRE(dn != NULL); + REQUIRE(db_name != NULL); + + log_func_enter(); + + argv[0] = ldapdb_impname; + argv[1] = db_name; + + zone = NULL; + dns_name_init(&name, NULL); + + CHECK(dn_to_dnsname(ldap_db->mctx, dn, str_buf(ldap_db->base), &name)); + + /* If the zone doesn't exist, create it. */ + result = dns_view_findzone(ldap_db->view, &name, &zone); + if (result == ISC_R_NOTFOUND) { + CHECK(dns_zone_create(&zone, ldap_db->mctx)); + dns_zone_setview(zone, ldap_db->view); + CHECK(dns_zone_setorigin(zone, &name)); + dns_zone_setclass(zone, dns_rdataclass_in); + dns_zone_settype(zone, dns_zone_master); + CHECK(dns_zone_setdbtype(zone, 2, argv)); + log_func_va("adding zone %s", dn); + CHECK(dns_zonemgr_managezone(zmgr, zone)); + CHECK(dns_view_addzone(ldap_db->view, zone)); + } else if (result != ISC_R_SUCCESS) { + goto cleanup; + } + + /* + * ACLs: + * dns_zone_setqueryacl() + * dns_zone_setqueryonacl() + * dns_zone_setupdateacl() + * dns_zone_setforwardacl() + * dns_zone_setxfracl() + */ + + /* + * maybe? + * dns_zone_setnotifytype() + * dns_zone_setalsonotify() + */ + +cleanup: + dns_name_free(&name, ldap_db->mctx); + if (zone != NULL) + dns_zone_detach(&zone); + + log_func_exit_result(result); + + return result; +} + isc_result_t ldapdb_rdatalist_findrdatatype(ldapdb_rdatalist_t *rdatalist, dns_rdatatype_t rdtype, @@ -322,7 +438,7 @@ ldapdb_rdatalist_get(isc_mem_t *mctx, dns_name_t *name, /* Max type length definitions, from lib/dns/master.c */ #define MINTSIZ (65535 - 12 - 1 - 2 - 2 - 4 - 2) - #define TOKENSIZ (8*1024) + #define TOKENSIZ (8*1024) /* Could be smaller */ isc_lex_t *lex = NULL; isc_result_t result; @@ -340,6 +456,8 @@ ldapdb_rdatalist_get(isc_mem_t *mctx, dns_name_t *name, REQUIRE(name != NULL); REQUIRE(rdatalist != NULL); + log_func_enter(); + /* * Get info from ldap - name, type, class, TTL + value. Try avoid * ENOMEM as much as possible, if nothing found return ISC_R_NOTFOUND @@ -357,7 +475,7 @@ ldapdb_rdatalist_get(isc_mem_t *mctx, dns_name_t *name, INIT_LIST(*rdatalist); - for (;0;) { + for (int i = 0; i < 1; i++) { /* * Note: if rdclass_text and rdtype_text are ttl_text are allocated * free() them correctly before break and before next iteration! @@ -373,7 +491,8 @@ ldapdb_rdatalist_get(isc_mem_t *mctx, dns_name_t *name, /* Everything else than IN class is pretty bad */ INSIST(rdclass == dns_rdataclass_in); - rdtype_text.base = "a"; + //rdtype_text.base = "a"; + rdtype_text.base = "ns"; rdtype_text.length = strlen(rdtype_text.base); result = dns_rdatatype_fromtext(&rdtype, &rdtype_text); if (result != ISC_R_SUCCESS) { @@ -391,7 +510,8 @@ ldapdb_rdatalist_get(isc_mem_t *mctx, dns_name_t *name, } /* put record in master file format here */ - rdata_text.base = "192.168.1.1"; + //rdata_text.base = "192.168.1.1"; + rdata_text.base = "wolverine.englab.brq.redhat.com."; rdata_text.length = strlen(rdata_text.base); isc_buffer_init(&lexbuffer, rdata_text.base, rdata_text.length); @@ -429,6 +549,7 @@ ldapdb_rdatalist_get(isc_mem_t *mctx, dns_name_t *name, rdata = isc_mem_get(mctx, sizeof(*rdata)); if (rdata == NULL) goto for_cleanup1; + dns_rdata_init(rdata); rdatamem.length = isc_buffer_usedlength(&target); rdatamem.base = isc_mem_get(mctx, rdatamem.length); @@ -452,6 +573,7 @@ ldapdb_rdatalist_get(isc_mem_t *mctx, dns_name_t *name, rdlist->type = rdtype; rdlist->ttl = ttl; APPEND(*rdatalist, rdlist, link); + result = ISC_R_SUCCESS; } else { /* * Use strong condition here, we are not allowing @@ -481,40 +603,11 @@ cleanup: isc_mem_put(mctx, targetmem, MINTSIZ); isc_lex_destroy(&lex); + log_func_exit_result(result); + return result; } -void -get_zone_list(ldap_db_t *ldap_db) -{ - ldap_instance_t *ldap_inst; - int i; - char **vals; - char *attrs[] = { - "idnsName", "idnsSOAmName", "idnsSOArName", "idnsSOAserial", - "idnsSOArefresh", "idnsSOAretry", "idnsSOAexpire", - "idnsSOAminimum", NULL - }; - ldap_inst = get_connection(ldap_db); - - ldap_query(ldap_inst, LDAP_SCOPE_SUBTREE, attrs, 0, - "(objectClass=idnsZone)"); - - log_error("list of ldap values:"); - while (next_entry(ldap_inst)) { - while (next_attribute(ldap_inst)) { - vals = get_values(ldap_inst); - for (i = 0; vals[i] != NULL; i++) { - log_error("attribute %s: %s", - get_attribute(ldap_inst), - vals[i]); - } - } - } - log_error("end of ldap values"); - - put_connection(ldap_inst); -} static ldap_instance_t * get_connection(ldap_db_t *ldap_db) @@ -531,7 +624,7 @@ get_connection(ldap_db_t *ldap_db) RUNTIME_CHECK(ldap_inst != NULL); - /* todo: find a clever way to not really require this */ + /* TODO: find a clever way to not really require this */ str_copy(ldap_inst->base, ldap_db->base); return ldap_inst; @@ -540,6 +633,10 @@ get_connection(ldap_db_t *ldap_db) static void put_connection(ldap_instance_t *ldap_inst) { + if (ldap_inst->dn) { + ldap_memfree(ldap_inst->dn); + ldap_inst->dn = NULL; + } if (ldap_inst->values) { ldap_value_free(ldap_inst->values); ldap_inst->values = NULL; @@ -573,16 +670,16 @@ ldap_query(ldap_instance_t *ldap_inst, int scope, char **attrs, str_vsprintf(ldap_inst->query_string, filter, ap); va_end(ap); - log_error("Querying '%s' with '%s'", str_buf(ldap_inst->base), - str_buf(ldap_inst->query_string)); + log_debug(2, "querying '%s' with '%s'", str_buf(ldap_inst->base), + str_buf(ldap_inst->query_string)); ret = ldap_search_ext_s(ldap_inst->handle, str_buf(ldap_inst->base), scope, str_buf(ldap_inst->query_string), attrs, attrsonly, NULL, NULL, NULL, LDAP_NO_LIMIT, &ldap_inst->result); - log_error("Result: %d", ldap_count_entries(ldap_inst->handle, - ldap_inst->result)); + log_debug(2, "entry count: %d", ldap_count_entries(ldap_inst->handle, + ldap_inst->result)); return ISC_R_SUCCESS; } @@ -644,6 +741,21 @@ get_values(ldap_instance_t *inst) return inst->values; } +static const char * +get_dn(ldap_instance_t *inst) +{ + if (inst->dn) { + ldap_memfree(inst->dn); + inst->dn = NULL; + } + + if (inst->handle && inst->entry) + inst->dn = ldap_get_dn(inst->handle, inst->entry); + + return inst->dn; + +} + #if 0 static const char * next_value(ldap_instance_t *inst) diff --git a/ldap_helper.h b/ldap_helper.h index 4324fdd..fe2478b 100644 --- a/ldap_helper.h +++ b/ldap_helper.h @@ -1,7 +1,7 @@ /* Authors: Martin Nagy <mnagy@redhat.com> * Adam Tkac <atkac@redhat.com> * - * Copyright (C) 2008 Red Hat + * Copyright (C) 2008, 2009 Red Hat * see file 'COPYING' for use and warranty information * * This program is free software; you can redistribute it and/or @@ -19,6 +19,9 @@ */ #ifndef _LD_LDAP_HELPER_H_ +#define _LD_LDAP_HELPER_H_ + +#include <isc/util.h> typedef struct ldap_db ldap_db_t; typedef struct ldap_instance ldap_instance_t; @@ -73,9 +76,10 @@ isc_result_t ldapdb_rdatalist_get(isc_mem_t *mctx, dns_name_t *name, * DNS_R_PARTIALMATCH */ -isc_result_t new_ldap_db(isc_mem_t *mctx, ldap_db_t **ldap_dbp, +isc_result_t new_ldap_db(isc_mem_t *mctx, dns_view_t *view, ldap_db_t **ldap_dbp, const char * const *argv); void destroy_ldap_db(ldap_db_t **ldap_db); -void get_zone_list(ldap_db_t *ldap_db); +isc_result_t refresh_zones_from_ldap(ldap_db_t *ldap_db, const char *name, + dns_zonemgr_t *zmgr); #endif /* !_LD_LDAP_HELPER_H_ */ diff --git a/zone_manager.c b/zone_manager.c new file mode 100644 index 0000000..e5fee22 --- /dev/null +++ b/zone_manager.c @@ -0,0 +1,202 @@ +/* Authors: Martin Nagy <mnagy@redhat.com> + * + * Copyright (C) 2009 Red Hat + * see file 'COPYING' for use and warranty information + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 only + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <isc/mem.h> +#include <isc/once.h> +#include <isc/result.h> +#include <isc/util.h> + +#include <dns/view.h> +#include <dns/zone.h> + +#include "ldap_convert.h" +#include "ldap_helper.h" +#include "log.h" +#include "util.h" +#include "zone_manager.h" + +struct db_instance { + isc_mem_t *mctx; + char *name; + ldap_db_t *ldap_db; + dns_zonemgr_t *dns_zone_manager; + LINK(db_instance_t) link; +}; + +static isc_once_t initialize_once = ISC_ONCE_INIT; +static isc_mutex_t instance_list_lock; +static LIST(db_instance_t) instance_list; + +static void initialize_manager(void); +static void destroy_db_instance(db_instance_t **db_instp); +static isc_result_t find_db_instance(const char *name, db_instance_t **instance); + + +static void +initialize_manager(void) +{ + INIT_LIST(instance_list); + isc_mutex_init(&instance_list_lock); +} + +void +destroy_manager(void) +{ + db_instance_t *db_inst; + db_instance_t *next; + + isc_once_do(&initialize_once, initialize_manager); + + LOCK(&instance_list_lock); + db_inst = HEAD(instance_list); + while (db_inst != NULL) { + next = NEXT(db_inst, link); + UNLINK(instance_list, db_inst, link); + destroy_db_instance(&db_inst); + db_inst = next; + } + UNLOCK(&instance_list_lock); +} + +static void +destroy_db_instance(db_instance_t **db_instp) +{ + db_instance_t *db_inst; + + REQUIRE(db_instp != NULL && *db_instp != NULL); + + db_inst = *db_instp; + + destroy_ldap_db(&db_inst->ldap_db); + if (db_inst->name != NULL) + isc_mem_free(db_inst->mctx, db_inst->name); + + isc_mem_putanddetach(&db_inst->mctx, db_inst, sizeof(*db_inst)); + + *db_instp = NULL; +} + +isc_result_t +manager_add_db_instance(isc_mem_t *mctx, const char *name, ldap_db_t *ldap_db, + dns_zonemgr_t *zmgr) +{ + isc_result_t result; + db_instance_t *db_inst; + + REQUIRE(mctx != NULL); + REQUIRE(name != NULL); + REQUIRE(ldap_db != NULL); + REQUIRE(zmgr != NULL); + + isc_once_do(&initialize_once, initialize_manager); + + db_inst = NULL; + + result = find_db_instance(name, &db_inst); + if (result == ISC_R_SUCCESS) { + db_inst = NULL; + result = ISC_R_FAILURE; + log_error("'%s' already exists", name); + goto cleanup; + } else { + result = ISC_R_SUCCESS; + } + + CHECKED_MEM_GET_PTR(mctx, db_inst); + CHECKED_MEM_STRDUP(mctx, name, db_inst->name); + db_inst->mctx = NULL; + isc_mem_attach(mctx, &db_inst->mctx); + db_inst->ldap_db = ldap_db; + db_inst->dns_zone_manager = zmgr; + + LOCK(&instance_list_lock); + APPEND(instance_list, db_inst, link); + UNLOCK(&instance_list_lock); + + refresh_zones_from_ldap(ldap_db, name, zmgr); + + return ISC_R_SUCCESS; + +cleanup: + if (db_inst != NULL) + destroy_db_instance(&db_inst); + + return result; +} + +void +manager_refresh_zones(void) +{ + db_instance_t *db_inst; + + LOCK(&instance_list_lock); + db_inst = HEAD(instance_list); + while (db_inst != NULL) { + refresh_zones_from_ldap(db_inst->ldap_db, db_inst->name, + db_inst->dns_zone_manager); + db_inst = NEXT(db_inst, link); + } + + UNLOCK(&instance_list_lock); +} + +isc_result_t +manager_get_ldap_db(const char *name, ldap_db_t **ldap_db) +{ + isc_result_t result; + db_instance_t *db_inst; + + REQUIRE(name != NULL); + REQUIRE(ldap_db != NULL); + + isc_once_do(&initialize_once, initialize_manager); + + db_inst = NULL; + CHECK(find_db_instance(name, &db_inst)); + + *ldap_db = db_inst->ldap_db; + +cleanup: + return result; +} + +static isc_result_t +find_db_instance(const char *name, db_instance_t **instance) +{ + db_instance_t *iterator; + + REQUIRE(name != NULL); + REQUIRE(instance != NULL && *instance == NULL); + + LOCK(&instance_list_lock); + iterator = HEAD(instance_list); + while (iterator != NULL) { + if (strcmp(name, iterator->name) == 0) + break; + iterator = NEXT(iterator, link); + } + UNLOCK(&instance_list_lock); + + if (iterator != NULL) { + *instance = iterator; + return ISC_R_SUCCESS; + } + + return ISC_R_NOTFOUND; +} diff --git a/zone_manager.h b/zone_manager.h new file mode 100644 index 0000000..930605b --- /dev/null +++ b/zone_manager.h @@ -0,0 +1,34 @@ +/* Authors: Martin Nagy <mnagy@redhat.com> + * + * Copyright (C) 2009 Red Hat + * see file 'COPYING' for use and warranty information + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 only + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _LD_ZONE_MANAGER_H_ +#define _LD_ZONE_MANAGER_H_ + +#include <dns/types.h> + +#include "ldap_helper.h" + +typedef struct db_instance db_instance_t; + +void destroy_manager(void); +isc_result_t manager_add_db_instance(isc_mem_t *mctx, const char *name, + ldap_db_t *ldap_db, dns_zonemgr_t *zmgr); +isc_result_t manager_get_ldap_db(const char *name, ldap_db_t **ldap_db); + +#endif /* !_LD_ZONE_MANAGER_H_ */ |