summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Nagy <mnagy@redhat.com>2009-02-10 18:56:23 +0100
committerMartin Nagy <mnagy@redhat.com>2009-02-12 15:39:48 +0100
commit1167840b16883acdc4ab47b1ef8c69d8ed7a33d8 (patch)
tree6262f4797ed514d2069bbfe71f7410219bd0e1ad
parentc0aff53501ad45dba1425951a8cc2cd3d1697a8d (diff)
downloadldap_driver_testing-1167840b16883acdc4ab47b1ef8c69d8ed7a33d8.tar.gz
ldap_driver_testing-1167840b16883acdc4ab47b1ef8c69d8ed7a33d8.tar.xz
ldap_driver_testing-1167840b16883acdc4ab47b1ef8c69d8ed7a33d8.zip
Add zone manager.
Zone manager will take care of periodical checks for new zones and will add them when they appear. For now, zones are only added at start time, no periodical checks yet.
-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_ */