summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--ldap_driver.c85
-rw-r--r--ldap_helper.c200
-rw-r--r--ldap_helper.h10
-rw-r--r--zone_manager.c202
-rw-r--r--zone_manager.h34
6 files changed, 449 insertions, 84 deletions
diff --git a/Makefile b/Makefile
index c22c3ea..672e5e0 100644
--- a/Makefile
+++ b/Makefile
@@ -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_ */