Skip to content

Commit

Permalink
BIND 9.11: Port to new dyndb API.
Browse files Browse the repository at this point in the history
This is first step which allows the plugin to run.
It requires configuration in format
dyndb <name> <library> {
	{option1 value}
	{option2 value}
};

This will be improved in another patch.
  • Loading branch information
pspacek committed Nov 30, 2016
1 parent 8178f3c commit da9bc9b
Show file tree
Hide file tree
Showing 15 changed files with 180 additions and 384 deletions.
28 changes: 10 additions & 18 deletions README
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,9 @@
===============

The dynamic LDAP back-end is a plug-in for BIND that provides an LDAP
database back-end capabilities. For now, it requires that BIND is patched
to support dynamic loading of database back-ends. You can get a patch
for your version here:
database back-end capabilities. It requires dyndb interface which is present
in BIND versions >= 9.11.0rc1.

https://github.com/pspacek/bind-dynamic_db

Hopefully, the patch will once be included in the official BIND release.

BIND >= 9.9.0 is required.

2. Features
===========
Expand Down Expand Up @@ -309,19 +303,17 @@ Attributes:
5. Configuration
================

To configure dynamic loading of back-end, you must put a "dynamic-db"
To configure dynamic loading of back-end, you must put a "dyndb"
clause into your named.conf. The clause must then be followed by a
string denoting the name. The name is not that much important, it is
passed to the plug-in and might be used for example, for logging
purposes. Following after that is a set of options enclosed between
curly brackets.
string denoting the name of the instance and path to dyndb library.

The most important option here is "library". It names a shared object
file that will be opened and loaded. The "arg" option specifies a string
that is passed directly to the plugin. You can specify multiple "arg"
options. The LDAP back-end follows the convention that the first word of
this string is the name of the setting and the rest is the value.
The name is not that much important, it is passed to the plug-in
and is used for logging purposes and for naming working directories.

Library path must point to a shared object file that will be opened and loaded.

Name and library path have to be followed by set of options enclosed between
curly brackets.

5.1 Configuration options
-------------------------
Expand Down
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ AC_INIT([bind-dyndb-ldap], [10.1], [[email protected]])

AM_INIT_AUTOMAKE([-Wall foreign dist-bzip2])

AC_CONFIG_SRCDIR([src/zone_manager.h])
AC_CONFIG_SRCDIR([src/ldap_driver.c])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])

Expand Down
2 changes: 0 additions & 2 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ HDRS = \
types.h \
util.h \
zone.h \
zone_manager.h \
zone_register.h

ldap_la_SOURCES = \
Expand All @@ -53,7 +52,6 @@ ldap_la_SOURCES = \
syncrepl.c \
str.c \
zone.c \
zone_manager.c \
zone_register.c

ldap_la_CFLAGS = -Wall -Wextra @WERROR@ -std=gnu99 -O2
Expand Down
135 changes: 95 additions & 40 deletions src/ldap_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,17 @@
#endif

#include <isc/buffer.h>
#include <isc/commandline.h>
#include <isc/hash.h>
#include <isc/lib.h>
#include <isc/mem.h>
#include <isc/once.h>
#include <isc/refcount.h>
#include <isc/util.h>

#include <dns/db.h>
#include <dns/diff.h>
#include <dns/dynamic_db.h>
#include <dns/dyndb.h>
#include <dns/dbiterator.h>
#include <dns/rdata.h>
#include <dns/rdataclass.h>
Expand All @@ -29,12 +33,12 @@

#include <string.h> /* For memcpy */

#include "bindcfg.h"
#include "ldap_driver.h"
#include "ldap_helper.h"
#include "ldap_convert.h"
#include "log.h"
#include "util.h"
#include "zone_manager.h"
#include "zone_register.h"

#ifdef HAVE_VISIBILITY
Expand Down Expand Up @@ -918,18 +922,17 @@ ldapdb_associate(isc_mem_t *mctx, dns_name_t *name, dns_dbtype_t type,
void *driverarg, dns_db_t **dbp) {

isc_result_t result;
ldap_instance_t *ldap_inst = NULL;
ldap_instance_t *ldap_inst = driverarg;
zone_register_t *zr = NULL;

UNUSED(driverarg); /* Currently we don't need any data */

REQUIRE(ISCAPI_MCTX_VALID(mctx));
REQUIRE(argc == LDAP_DB_ARGC);
REQUIRE(type == LDAP_DB_TYPE);
REQUIRE(rdclass == LDAP_DB_RDATACLASS);
REQUIRE(argc == 0);
UNUSED(argv);
REQUIRE(driverarg != NULL);
REQUIRE(dbp != NULL && *dbp == NULL);

CHECK(manager_get_ldap_instance(argv[0], &ldap_inst));
zr = ldap_instance_getzr(ldap_inst);
if (zr == NULL)
CLEANUP_WITH(ISC_R_NOTFOUND);
Expand All @@ -942,19 +945,16 @@ ldapdb_associate(isc_mem_t *mctx, dns_name_t *name, dns_dbtype_t type,

isc_result_t
ldapdb_create(isc_mem_t *mctx, dns_name_t *name, dns_dbtype_t type,
dns_rdataclass_t rdclass, unsigned int argc, char *argv[],
void *driverarg, dns_db_t **dbp)
dns_rdataclass_t rdclass, void *driverarg, dns_db_t **dbp)
{
ldapdb_t *ldapdb = NULL;
isc_result_t result;
isc_boolean_t lock_ready = ISC_FALSE;

UNUSED(driverarg); /* Currently we don't need any data */

/* Database instance name. */
REQUIRE(argc == LDAP_DB_ARGC);
REQUIRE(type == LDAP_DB_TYPE);
REQUIRE(rdclass == LDAP_DB_RDATACLASS);
REQUIRE(driverarg != NULL);
REQUIRE(dbp != NULL && *dbp == NULL);

CHECKED_MEM_GET_PTR(mctx, ldapdb);
Expand All @@ -976,7 +976,7 @@ ldapdb_create(isc_mem_t *mctx, dns_name_t *name, dns_dbtype_t type,
CHECK(dns_name_dupwithoffsets(name, mctx, &ldapdb->common.origin));

CHECK(isc_refcount_init(&ldapdb->refs, 1));
CHECK(manager_get_ldap_instance(argv[0], &ldapdb->ldap_inst));
ldapdb->ldap_inst = driverarg;

CHECK(dns_db_create(mctx, "rbt", name, dns_dbtype_zone,
dns_rdataclass_in, 0, NULL, &ldapdb->rbtdb));
Expand All @@ -1000,50 +1000,105 @@ ldapdb_create(isc_mem_t *mctx, dns_name_t *name, dns_dbtype_t type,
return result;
}

static dns_dbimplementation_t *ldapdb_imp;
const char *ldapdb_impname = "dynamic-ldap";
static void
library_init(void)
{
log_info("bind-dyndb-ldap version " VERSION
" compiled at " __TIME__ " " __DATE__
", compiler " __VERSION__);
cfg_init_types();
}

/*
* Driver version is called when loading the driver to ensure there
* is no API mismatch betwen the driver and the caller.
*/
VISIBLE int
dyndb_version(unsigned int *flags) {
UNUSED(flags);

return (DNS_DYNDB_VERSION);
}

/*
* Driver init is called for each dyndb section in named.conf
* once during startup and then again on every reload.
*
* @code
* dyndb example-name "sample.so" { param1 param2 };
* @endcode
*
* @param[in] name User-defined string from dyndb "name" {}; definition
* in named.conf.
* The example above will have name = "example-name".
* @param[in] parameters User-defined parameters from dyndb section as one
* string. The example above will have
* params = "param1 param2";
* @param[out] instp Pointer to instance-specific data
* (for one dyndb section).
*/
VISIBLE isc_result_t
dynamic_driver_init(isc_mem_t *mctx, const char *name, const char * const *argv,
dns_dyndb_arguments_t *dyndb_args)
dyndb_init(isc_mem_t *mctx, const char *name, const char *parameters,
const char *file, unsigned long line, const dns_dyndbctx_t *dctx,
void **instp)
{
dns_dbimplementation_t *ldapdb_imp_new = NULL;
unsigned int argc;
char **argv = NULL;
char *tmps = NULL;
ldap_instance_t *inst = NULL;
isc_result_t result;
static isc_once_t library_init_once = ISC_ONCE_INIT;

REQUIRE(name != NULL);
REQUIRE(argv != NULL);
REQUIRE(dyndb_args != NULL);
REQUIRE(parameters != NULL);
REQUIRE(dctx != NULL);
REQUIRE(instp != NULL && *instp == NULL);

log_debug(2, "registering dynamic ldap driver for %s.", name);
RUNTIME_CHECK(isc_once_do(&library_init_once, library_init)
== ISC_R_SUCCESS);

/*
* We need to discover what rdataset methods does
* dns_rdatalist_tordataset use. We then make a copy for ourselves
* with the exception that we modify the disassociate method to free
* the rdlist we allocate for it in clone_rdatalist_to_rdataset().
* Depending on how dlopen() was called, we may not have
* access to named's global namespace, in which case we need
* to initialize libisc/libdns
*/
if (dctx->refvar != &isc_bind9) {
isc_lib_register();
isc_log_setcontext(dctx->lctx);
dns_log_setcontext(dctx->lctx);
}

/* Register new DNS DB implementation. */
result = dns_db_register(ldapdb_impname, &ldapdb_associate, NULL, mctx,
&ldapdb_imp_new);
if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS)
return result;
else if (result == ISC_R_SUCCESS)
ldapdb_imp = ldapdb_imp_new;
isc_hash_set_initializer(dctx->hashinit);

log_debug(2, "registering dynamic ldap driver for %s.", name);

tmps = isc_mem_strdup(mctx, parameters);
if (tmps == NULL) {
result = ISC_R_NOMEMORY;
goto cleanup;
}
CHECK(isc_commandline_strtoargv(mctx, tmps, &argc, &argv, 0));

/* Finally, create the instance. */
result = manager_create_db_instance(mctx, name, argv, dyndb_args);
CHECK(new_ldap_instance(mctx, name, argc, argv, dctx, &inst));
*instp = inst;

cleanup:
if (tmps != NULL)
isc_mem_free(mctx, tmps);
if (argv != NULL)
isc_mem_put(mctx, argv, argc * sizeof(*argv));

return result;
}

/*
* Driver destroy is called for every instance on every reload and then once
* during shutdown.
*
* @param[out] instp Pointer to instance-specific data (for one dyndb section).
*/
VISIBLE void
dynamic_driver_destroy(void)
{
/* Only unregister the implementation if it was registered by us. */
if (ldapdb_imp != NULL)
dns_db_unregister(&ldapdb_imp);

destroy_manager();
dyndb_destroy(void **instp) {
destroy_ldap_instance((ldap_instance_t **)instp);
}
8 changes: 6 additions & 2 deletions src/ldap_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,13 @@ typedef struct ldapdb ldapdb_t;

isc_result_t
ldapdb_create(isc_mem_t *mctx, dns_name_t *name, dns_dbtype_t type,
dns_rdataclass_t rdclass, unsigned int argc, char *argv[],
void *driverarg, dns_db_t **dbp) ATTR_NONNULL(1,2,6,8);
dns_rdataclass_t rdclass, void *driverarg, dns_db_t **dbp)
ATTR_NONNULL(1,2,5,6);

isc_result_t
ldapdb_associate(isc_mem_t *mctx, dns_name_t *name, dns_dbtype_t type,
dns_rdataclass_t rdclass, unsigned int argc, char *argv[],
void *driverarg, dns_db_t **dbp) ATTR_NONNULL(1,2,7,8);
dns_db_t *
ldapdb_get_rbtdb(dns_db_t *db) ATTR_NONNULLS;

Expand Down
Loading

0 comments on commit da9bc9b

Please sign in to comment.