Commit a00f9e2f authored by Evan Hunt's avatar Evan Hunt

[master] merge dyndb

4224.	[func]		Added support for "dyndb", a new interface for loading
			zone data from an external database, developed by
			Red Hat for the FreeIPA project.

			DynDB drivers fully implement the BIND database
			API, and are capable of significantly better
			performance and functionality than DLZ drivers,
			while taking advantage of advanced database
			features not available in BIND such as multi-master
			replication.

			Thanks to Adam Tkac and Petr Spacek of Red Hat.
			[RT #35271]
parent 4d085258
4224. [func] Added support for "dyndb", a new interface for loading
zone data from an external database, developed by
Red Hat for the FreeIPA project.
DynDB drivers fully implement the BIND database
API, and are capable of significantly better
performance and functionality than DLZ drivers,
while taking advantage of advanced database
features not available in BIND such as multi-master
replication.
Thanks to Adam Tkac and Petr Spacek of Red Hat.
[RT #35271]
4223. [func] Add support for setting max-cache-size to percentage
of available physical memory, set default to 90%.
[RT #38442]
......
......@@ -536,3 +536,18 @@ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
Copyright (C) 2008-2011 Red Hat, Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND Red Hat DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL Red Hat BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
......@@ -13,8 +13,6 @@
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
# $Id: Makefile.in,v 1.116 2011/03/10 23:47:49 tbox Exp $
srcdir = @srcdir@
VPATH = @srcdir@
top_srcdir = @top_srcdir@
......@@ -136,6 +134,7 @@ config.@O@: config.c
${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \
-DVERSION=\"${VERSION}\" \
-DSRCID=\"${SRCID}\" \
-DDYNDB_LIBDIR=\"@libdir@/bind\" \
-DNS_LOCALSTATEDIR=\"${localstatedir}\" \
-DNS_SYSCONFDIR=\"${sysconfdir}\" \
-c ${srcdir}/config.c
......
......@@ -43,6 +43,7 @@
#include <isccc/result.h>
#include <dns/dispatch.h>
#include <dns/dyndb.h>
#include <dns/name.h>
#include <dns/result.h>
#include <dns/view.h>
......
......@@ -29,6 +29,7 @@
#include <isc/aes.h>
#include <isc/app.h>
#include <isc/base64.h>
#include <isc/commandline.h>
#include <isc/dir.h>
#include <isc/entropy.h>
#include <isc/file.h>
......@@ -68,6 +69,7 @@
#include <dns/dispatch.h>
#include <dns/dlz.h>
#include <dns/dns64.h>
#include <dns/dyndb.h>
#include <dns/forward.h>
#include <dns/journal.h>
#include <dns/keytable.h>
......@@ -1349,6 +1351,32 @@ configure_peer(const cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) {
return (result);
}
static isc_result_t
configure_dyndb(const cfg_obj_t *dyndb, isc_mem_t *mctx,
const dns_dyndbctx_t *dctx)
{
isc_result_t result = ISC_R_SUCCESS;
const cfg_obj_t *obj;
const char *name, *library;
/* Get the name of the dyndb instance and the library path . */
name = cfg_obj_asstring(cfg_tuple_get(dyndb, "name"));
library = cfg_obj_asstring(cfg_tuple_get(dyndb, "library"));
obj = cfg_tuple_get(dyndb, "parameters");
if (obj != NULL)
result = dns_dyndb_load(library, name,
cfg_obj_asstring(obj), mctx, dctx);
if (result != ISC_R_SUCCESS)
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
"dynamic database '%s' configuration failed: %s",
name, isc_result_totext(result));
return (result);
}
static isc_result_t
disable_algorithms(const cfg_obj_t *disabled, dns_resolver_t *resolver) {
isc_result_t result;
......@@ -2397,6 +2425,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
const cfg_obj_t *dlz;
unsigned int dlzargc;
char **dlzargv;
const cfg_obj_t *dyndb_list;
const cfg_obj_t *disabled;
const cfg_obj_t *obj, *obj2;
const cfg_listelt_t *element;
......@@ -2438,6 +2467,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
ns_cfgctx_t *nzctx;
isc_boolean_t old_rpz_ok = ISC_FALSE;
isc_dscp_t dscp4 = -1, dscp6 = -1;
dns_dyndbctx_t *dctx = NULL;
REQUIRE(DNS_VIEW_VALID(view));
......@@ -2636,7 +2666,8 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
goto cleanup;
}
result = dns_dlzstrtoargv(mctx, s, &dlzargc, &dlzargv);
result = isc_commandline_strtoargv(mctx, s, &dlzargc,
&dlzargv, 0);
if (result != ISC_R_SUCCESS) {
isc_mem_free(mctx, s);
goto cleanup;
......@@ -3785,6 +3816,31 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
} else
dns_view_setrootdelonly(view, ISC_FALSE);
/*
* Load DynDB modules.
*/
dyndb_list = NULL;
if (voptions != NULL)
(void)cfg_map_get(voptions, "dyndb", &dyndb_list);
else
(void)cfg_map_get(config, "dyndb", &dyndb_list);
for (element = cfg_list_first(dyndb_list);
element != NULL;
element = cfg_list_next(element))
{
const cfg_obj_t *dyndb = cfg_listelt_value(element);
if (dctx == NULL)
CHECK(dns_dyndb_createctx(mctx, isc_hashctx,
ns_g_lctx, view,
ns_g_server->zonemgr,
ns_g_server->task,
ns_g_timermgr, &dctx));
CHECK(configure_dyndb(dyndb, mctx, dctx));
}
/*
* Setup automatic empty zones. If recursion is off then
* they are disabled by default.
......@@ -3983,6 +4039,8 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
if (cache != NULL)
dns_cache_detach(&cache);
if (dctx != NULL)
dns_dyndb_destroyctx(&dctx);
return (result);
}
......@@ -5634,6 +5692,11 @@ load_configuration(const char *filename, ns_server_t *server,
cfg_aclconfctx_detach(&ns_g_aclconfctx);
CHECK(cfg_aclconfctx_create(ns_g_mctx, &ns_g_aclconfctx));
/*
* Shut down all dyndb instances.
*/
dns_dyndb_cleanup(ISC_FALSE);
/*
* Parse the global default pseudo-config file.
*/
......@@ -6922,6 +6985,8 @@ shutdown_server(isc_task_t *task, isc_event_t *event) {
dns_view_detach(&view);
}
dns_dyndb_cleanup(ISC_TRUE);
while ((nsc = ISC_LIST_HEAD(server->cachelist)) != NULL) {
ISC_LIST_UNLINK(server->cachelist, nsc, link);
dns_cache_detach(&nsc->cache);
......
......@@ -13,8 +13,6 @@
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
# $Id: Makefile.in,v 1.145 2011/02/03 05:41:53 marka Exp $
srcdir = @srcdir@
VPATH = @srcdir@
top_srcdir = @top_srcdir@
......@@ -42,8 +40,9 @@ LWRESDEPLIBS = ../../lib/lwres/liblwres.@A@
LIBS = @LIBS@
SUBDIRS = atomic db dst master mem hashes names net rbt resolver \
sockaddr tasks timers system @PKCS11_TOOLS@
SUBDIRS = atomic db dst master mem hashes names \
net rbt resolver sockaddr tasks timers system \
@PKCS11_TOOLS@
# Test programs that are built by default:
# cfg_test is needed for regenerating doc/misc/options
......
......@@ -13,15 +13,13 @@
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
# $Id: Makefile.in,v 1.38 2011/11/01 18:35:53 each Exp $
srcdir = @srcdir@
VPATH = @srcdir@
top_srcdir = @top_srcdir@
@BIND9_MAKE_INCLUDES@
SUBDIRS = builtin dlzexternal filter-aaaa geoip lwresd pipelined \
SUBDIRS = builtin dlzexternal dyndb filter-aaaa geoip lwresd pipelined \
resolver rndc rpz rsabigexponent statistics tkey tsiggss
TARGETS =
......
......@@ -14,8 +14,6 @@
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
# tests for TSIG-GSS updates
SYSTEMTESTTOP=..
. $SYSTEMTESTTOP/conf.sh
......
# Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
srcdir = @srcdir@
VPATH = @srcdir@
top_srcdir = @top_srcdir@
@BIND9_VERSION@
@BIND9_MAKE_INCLUDES@
SUBDIRS = driver
TARGETS =
@BIND9_MAKE_RULES@
#!/bin/sh
#
# Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
#
# Clean up after dyndb tests.
#
rm -f ns1/named.memstats
rm -f ns1/update.txt
rm -f added.a.out.*
rm -f added.ptr.out.*
rm -f deleted.a.out.*
rm -f deleted.ptr.out.*
This sample driver is based on bind-dyndb-ldap project and small portions
of code from ISC BIND 9.10.
Authors listed in alphabetical order:
Adam Tkac <atkac@redhat.com>
Jiri Kuncar <jkuncar@redhat.com>
Martin Nagy <mnagy@redhat.com>
Petr Spacek <pspacek@redhat.com>
Copyright (C) 2009-2015 Red Hat
Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC")
Copyright (C) 1999-2003 Internet Software Consortium.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND AUTHORS DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
# Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
srcdir = @srcdir@
VPATH = @srcdir@
top_srcdir = @top_srcdir@
@BIND9_MAKE_INCLUDES@
CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES}
CDEFINES =
CWARNINGS =
DNSLIBS = ../../../../../lib/dns/libdns.@A@
ISCLIBS = ../../../../../lib/isc/libisc.@A@
DNSDEPLIBS = ../../../../../lib/dns/libdns.@A@
ISCDEPLIBS = ../../../../../lib/isc/libisc.@A@
DEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS}
LIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@
SRCS = db.c driver.c instance.c \
lock.c log.c syncptr.c zone.c
OBJS = db.@O@ driver.@O@ instance.@O@ \
lock.@O@ log.@O@ syncptr.@O@ zone.@O@
TARGETS = sample.@SO@
@BIND9_MAKE_RULES@
CFLAGS = @CFLAGS@ @SO_CFLAGS@
SO_LDFLAGS = @LDFLAGS@ @SO_LDFLAGS@
sample.@SO@: ${OBJS}
${LIBTOOL_MODE_LINK} @SO_LD@ ${SO_LDFLAGS} -o $@ ${OBJS} \
${DNSLIBS} ${ISCLIBS}
clean distclean::
rm -f ${OBJS} sample.so
To use the Dynamic DB sample driver, run named and check the log.
$ cd testing
$ named -gc named.conf
You should be able to see something like:
zone test/IN: loaded serial 0
zone arpa/IN: loaded serial 0
This means that the sample driver created empty zones "test." and
"arpa." as defined by "arg" parameters in named.conf.
$ dig @localhost test.
should work as usual and you should be able to see the dummy zone with
NS record pointing to the zone apex and A record with 127.0.0.1:
;; ANSWER SECTION:
test. 86400 IN A 127.0.0.1
test. 86400 IN NS test.
test. 86400 IN SOA test. test. 0 28800 7200 604800 86400
This driver creates two empty zones and allows query/transfer/update to
all IP addresses for demonstration purposes.
The driver wraps the RBT database implementation used natively by BIND,
and modifies the addrdataset() and substractrdataset() functions to do
additional work during dynamic updates.
A dynamic update modifies the target zone as usual. After that, the
driver detects whether the modified RR was of type A or AAAA, and if so,
attempts to appropriately generate or delete a matching PTR record in
one of the two zones managed by the driver.
E.g.:
$ nsupdate
> update add a.test. 300 IN A 192.0.2.1
> send
will add the A record
a.test. 300 IN A 192.0.2.1
and also automatically generate the PTR record
1.2.0.192.in-addr.arpa. 300 IN PTR a.test.
AXFR and RR deletion via dynamic updates should work as usual. Deletion
of a type A or AAAA record should delete the corresponding PTR record
too.
The zone is stored only in memory, and all changes will be lost on
reload/reconfig.
Hints for code readers:
- Driver initialization starts in driver.c: dyndb_init() function.
- New database implementation is registered by calling dns_db_register()
and passing a function pointer to it. This sample uses the function
create_db() to initialize the database.
- Zones are created later in instance.c: load_sample_instance_zones().
- Database entry points are in structure db.c: dns_dbmethods_t
sampledb_methods
- sampledb_methods points to an implementation of the database interface.
See the db.c: addrdataset() implementation and look at how the RBT
database instance is wrapped into an additional layer of logic.
This diff is collapsed.
/**
* Database API implementation.
*
* Copyright (C) 2015 Red Hat ; see COPYRIGHT for license
*/
#ifndef DB_H_
#define DB_H_
isc_result_t
create_db(isc_mem_t *mctx, dns_name_t *origin, dns_dbtype_t type,
dns_rdataclass_t rdclass, unsigned int argc, char *argv[],
void *driverarg, dns_db_t **dbp);
#endif /* DB_H_ */
/*
* Driver API implementation and main entry point for BIND.
*
* BIND calls dyndb_version() before loading, dyndb_init() during startup
* and dyndb_destroy() during shutdown.
*
* It is completely up to implementation what to do.
*
* dyndb <name> <driver> {} sections in named.conf are independent so
* driver init() and destroy() functions are called independently for
* each section even if they reference the same driver/library. It is
* up to driver implementation to detect and catch this situation if
* it is undesirable.
*
* Copyright (C) 2009-2015 Red Hat ; see COPYRIGHT for license
*/
#include <config.h>
#include <isc/commandline.h>
#include <isc/hash.h>
#include <isc/mem.h>
#include <isc/lib.h>
#include <isc/util.h>
#include <dns/db.h>
#include <dns/dyndb.h>
#include <dns/lib.h>
#include <dns/types.h>
#include "db.h"
#include "log.h"
#include "instance.h"
#include "util.h"
dns_dyndb_destroy_t dyndb_destroy;
dns_dyndb_register_t dyndb_init;
dns_dyndb_version_t 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] argc Number of arg parameters
* definition. The example above will have
* argc = 2;
* @param[in] argv User-defined strings from arg parameters in dyndb
* definition. The example above will have
* argv[0] = "param1";
* argv[1] = "param2";
* @param[out] instp Pointer to instance-specific data (for one dyndb section).
*/
isc_result_t
dyndb_init(isc_mem_t *mctx, const char *name, const char *parameters,
const dns_dyndbctx_t *dctx, void **instp)
{
isc_result_t result;
unsigned int argc;
char **argv = NULL;
char *s = NULL;
sample_instance_t *sample_inst = NULL;
REQUIRE(name != NULL);
REQUIRE(dctx != NULL);
/*
* 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);
}
if (isc_hashctx != NULL && isc_hashctx != dctx->hctx)
isc_hash_ctxdetach(&isc_hashctx);
isc_hashctx = dctx->hctx;
s = isc_mem_strdup(mctx, parameters);
if (s == NULL) {
result = ISC_R_NOMEMORY;
goto cleanup;
}
result = isc_commandline_strtoargv(mctx, s, &argc, &argv, 0);
if (result != ISC_R_SUCCESS)
goto cleanup;
/* Finally, create the instance. */
CHECK(new_sample_instance(mctx, name, argc, argv, dctx, &sample_inst));
/*
* This is an example so we create and load zones
* right now. This step can be arbitrarily postponed.
*/
CHECK(load_sample_instance_zones(sample_inst));
*instp = sample_inst;
cleanup:
if (s != NULL)
isc_mem_free(mctx, s);
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).
*/
void
dyndb_destroy(void **instp) {
destroy_sample_instance((sample_instance_t **)instp);
}
/*
* Driver version is called when loading the driver to ensure there
* is no API mismatch betwen the driver and the caller.
*/
int
dyndb_version(unsigned int *flags) {
UNUSED(flags);
return (DNS_DYNDB_VERSION);
}
/*
* Driver instance object.
*
* One instance is equivalent to dynamic-db section in named.conf.
* This module parses arguments and provide high-level operations
* instance init/zone load/instance destroy.
*
* Copyright (C) 2008-2015 Red Hat ; see COPYRIGHT for license
*/
#include <config.h>
#include <isc/task.h>
#include <isc/util.h>
#include <dns/db.h>
#include <dns/dyndb.h>
#include <dns/fixedname.h>
#include <dns/name.h>
#include <dns/view.h>
#include <dns/zone.h>
#include "db.h"
#include "util.h"
#include "instance.h"
#include "log.h"
#include "zone.h"
/*
* Parse parameters and convert them to zone names. Caller has to deallocate
* resulting DNS names.
*
* @param[in] argv NULL-terminated string array of length 2 (excluding NULL)
* Each string has to be a valid DNS name.
* @param[out] z1 Zone name from argv[0]
* @param[out] z2 Zone name from argv[1]
*/
static isc_result_t
parse_params(isc_mem_t *mctx, int argc, char **argv,