diff --git a/SOURCES/bind-9.9-dist-native-pkcs11.patch b/SOURCES/bind-9.9-dist-native-pkcs11.patch index 9e6f846..36c0ea4 100644 --- a/SOURCES/bind-9.9-dist-native-pkcs11.patch +++ b/SOURCES/bind-9.9-dist-native-pkcs11.patch @@ -134,10 +134,10 @@ index 64e1846..cfb5628 100644 CWARNINGS = diff --git a/bin/named-pkcs11/Makefile.in b/bin/named-pkcs11/Makefile.in -index 3a54437..32c5242 100644 +index 8b9e87a..5b7d939 100644 --- a/bin/named-pkcs11/Makefile.in +++ b/bin/named-pkcs11/Makefile.in -@@ -47,26 +47,26 @@ DLZDRIVER_INCLUDES = @DLZ_DRIVER_INCLUDES@ +@@ -45,26 +45,26 @@ DLZDRIVER_INCLUDES = @DLZ_DRIVER_INCLUDES@ DLZDRIVER_LIBS = @DLZ_DRIVER_LIBS@ CINCLUDES = -I${srcdir}/include -I${srcdir}/unix/include -I. \ @@ -171,7 +171,7 @@ index 3a54437..32c5242 100644 LWRESDEPLIBS = ../../lib/lwres/liblwres.@A@ BIND9DEPLIBS = ../../lib/bind9/libbind9.@A@ -@@ -75,15 +75,15 @@ DEPLIBS = ${LWRESDEPLIBS} ${DNSDEPLIBS} ${BIND9DEPLIBS} \ +@@ -73,15 +73,15 @@ DEPLIBS = ${LWRESDEPLIBS} ${DNSDEPLIBS} ${BIND9DEPLIBS} \ LIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} \ ${ISCCFGLIBS} ${ISCCCLIBS} ${ISCLIBS} \ @@ -190,7 +190,7 @@ index 3a54437..32c5242 100644 GEOIPLINKOBJS = geoip.@O@ -@@ -94,8 +94,7 @@ OBJS = builtin.@O@ client.@O@ config.@O@ control.@O@ \ +@@ -92,8 +92,7 @@ OBJS = builtin.@O@ client.@O@ config.@O@ control.@O@ \ tkeyconf.@O@ tsigconf.@O@ update.@O@ xfrout.@O@ \ zoneconf.@O@ \ lwaddr.@O@ lwresd.@O@ lwdclient.@O@ lwderror.@O@ lwdgabn.@O@ \ @@ -200,7 +200,7 @@ index 3a54437..32c5242 100644 UOBJS = unix/os.@O@ unix/dlz_dlopen_driver.@O@ -@@ -110,8 +109,7 @@ SRCS = builtin.c client.c config.c control.c \ +@@ -108,8 +107,7 @@ SRCS = builtin.c client.c config.c control.c \ tkeyconf.c tsigconf.c update.c xfrout.c \ zoneconf.c \ lwaddr.c lwresd.c lwdclient.c lwderror.c lwdgabn.c \ @@ -210,7 +210,7 @@ index 3a54437..32c5242 100644 MANPAGES = named.8 lwresd.8 named.conf.5 -@@ -146,7 +144,7 @@ config.@O@: config.c bind.keys.h +@@ -145,7 +143,7 @@ config.@O@: config.c bind.keys.h -DNS_SYSCONFDIR=\"${sysconfdir}\" \ -c ${srcdir}/config.c @@ -219,7 +219,7 @@ index 3a54437..32c5242 100644 export MAKE_SYMTABLE="yes"; \ export BASEOBJS="${OBJS} ${UOBJS}"; \ ${FINALBUILDCMD} -@@ -177,15 +175,9 @@ statschannel.@O@: bind9.xsl.h bind9.ver3.xsl.h +@@ -176,15 +174,9 @@ statschannel.@O@: bind9.xsl.h bind9.ver3.xsl.h installdirs: $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir} @@ -239,10 +239,10 @@ index 3a54437..32c5242 100644 @DLZ_DRIVER_RULES@ diff --git a/bin/named/Makefile.in b/bin/named/Makefile.in -index 3a54437..bc5be2a 100644 +index 8b9e87a..5ba3f56 100644 --- a/bin/named/Makefile.in +++ b/bin/named/Makefile.in -@@ -51,7 +51,7 @@ CINCLUDES = -I${srcdir}/include -I${srcdir}/unix/include -I. \ +@@ -49,7 +49,7 @@ CINCLUDES = -I${srcdir}/include -I${srcdir}/unix/include -I. \ ${ISCCFG_INCLUDES} ${ISCCC_INCLUDES} ${ISC_INCLUDES} \ ${DLZDRIVER_INCLUDES} ${DBDRIVER_INCLUDES} @DST_OPENSSL_INC@ @@ -273,10 +273,10 @@ index 15d3fb5..32cc753 100644 DEPLIBS = ${ISCDEPLIBS} diff --git a/configure.in b/configure.in -index 5b56172..9bb9a2a 100644 +index 5c79d6d..6c08de9 100644 --- a/configure.in +++ b/configure.in -@@ -656,10 +656,10 @@ AC_ARG_WITH(pkcs11, +@@ -659,10 +659,10 @@ AC_ARG_WITH(pkcs11, openssldirs="/usr /usr/local /usr/local/ssl /usr/pkg /usr/sfw" if test "$use_openssl" = "auto" then @@ -291,7 +291,7 @@ index 5b56172..9bb9a2a 100644 for d in $openssldirs do if test -f $d/include/openssl/opensslv.h -@@ -668,7 +668,7 @@ then +@@ -671,7 +671,7 @@ then break fi done @@ -300,7 +300,7 @@ index 5b56172..9bb9a2a 100644 fi OPENSSL_ECDSA="" OPENSSL_GOST="" -@@ -727,11 +727,11 @@ case "$use_openssl" in +@@ -730,11 +730,11 @@ case "$use_openssl" in If you don't want OpenSSL, use --without-openssl]) ;; *) @@ -317,7 +317,7 @@ index 5b56172..9bb9a2a 100644 if test "$use_openssl" = "yes" then # User did not specify a path - guess it -@@ -1011,6 +1011,7 @@ AC_SUBST(OPENSSL_ECDSA) +@@ -1014,6 +1014,7 @@ AC_SUBST(OPENSSL_ECDSA) AC_SUBST(OPENSSL_GOST) DNS_CRYPTO_LIBS="$DNS_CRYPTO_LIBS $DNS_OPENSSL_LIBS" @@ -325,7 +325,7 @@ index 5b56172..9bb9a2a 100644 # # Use OpenSSL for hash functions -@@ -1192,7 +1193,7 @@ case "$use_pkcs11" in +@@ -1195,7 +1196,7 @@ case "$use_pkcs11" in esac AC_SUBST(PKCS11_PROVIDER) @@ -334,7 +334,7 @@ index 5b56172..9bb9a2a 100644 PKCS11_ECDSA="" PKCS11_GOST="" AC_MSG_CHECKING(for native PKCS11) -@@ -1200,7 +1201,7 @@ AC_MSG_CHECKING(for native PKCS11) +@@ -1203,7 +1204,7 @@ AC_MSG_CHECKING(for native PKCS11) case "$want_native_pkcs11" in yes) AC_MSG_RESULT(using native PKCS11 crypto) @@ -343,7 +343,7 @@ index 5b56172..9bb9a2a 100644 PKCS11LINKOBJS='${PKCS11LINKOBJS}' PKCS11LINKSRCS='${PKCS11LINKSRCS}' PKCS11_TEST=pkcs11 -@@ -1237,6 +1238,7 @@ esac +@@ -1240,6 +1241,7 @@ esac AC_SUBST(PKCS11LINKOBJS) AC_SUBST(PKCS11LINKSRCS) AC_SUBST(CRYPTO) @@ -351,7 +351,7 @@ index 5b56172..9bb9a2a 100644 AC_SUBST(PKCS11_ECDSA) AC_SUBST(PKCS11_GOST) AC_SUBST(PKCS11_TEST) -@@ -1528,12 +1530,13 @@ AC_SUBST(USE_GSSAPI) +@@ -1531,12 +1533,13 @@ AC_SUBST(USE_GSSAPI) AC_SUBST(DST_GSSAPI_INC) AC_SUBST(DNS_GSSAPI_LIBS) DNS_CRYPTO_LIBS="$DNS_GSSAPI_LIBS $DNS_CRYPTO_LIBS" @@ -366,7 +366,7 @@ index 5b56172..9bb9a2a 100644 # # was --with-randomdev specified? -@@ -4010,7 +4013,10 @@ AC_CONFIG_FILES([ +@@ -4014,7 +4017,10 @@ AC_CONFIG_FILES([ bin/confgen/unix/Makefile bin/dig/Makefile bin/dnssec/Makefile @@ -377,7 +377,7 @@ index 5b56172..9bb9a2a 100644 bin/named/unix/Makefile bin/nsupdate/Makefile bin/pkcs11/Makefile -@@ -4091,11 +4097,19 @@ AC_CONFIG_FILES([ +@@ -4097,11 +4103,19 @@ AC_CONFIG_FILES([ lib/dns/include/dns/Makefile lib/dns/include/dst/Makefile lib/dns/tests/Makefile @@ -397,7 +397,7 @@ index 5b56172..9bb9a2a 100644 lib/export/irs/Makefile lib/export/irs/include/Makefile lib/export/irs/include/irs/Makefile -@@ -4109,6 +4123,16 @@ AC_CONFIG_FILES([ +@@ -4115,6 +4129,16 @@ AC_CONFIG_FILES([ lib/export/isc/unix/Makefile lib/export/isc/unix/include/Makefile lib/export/isc/unix/include/isc/Makefile @@ -414,7 +414,7 @@ index 5b56172..9bb9a2a 100644 lib/export/isccfg/Makefile lib/export/isccfg/include/Makefile lib/export/isccfg/include/isccfg/Makefile -@@ -4137,6 +4161,24 @@ AC_CONFIG_FILES([ +@@ -4143,6 +4167,24 @@ AC_CONFIG_FILES([ lib/isc/unix/include/Makefile lib/isc/unix/include/isc/Makefile lib/isc/unix/include/pkcs11/Makefile @@ -453,7 +453,7 @@ index 8dc1d38..8e48d5e 100644 @BIND9_MAKE_RULES@ diff --git a/lib/dns-pkcs11/Makefile.in b/lib/dns-pkcs11/Makefile.in -index 0cc82f1..cb830db 100644 +index ae316c5..1a79768 100644 --- a/lib/dns-pkcs11/Makefile.in +++ b/lib/dns-pkcs11/Makefile.in @@ -27,16 +27,16 @@ top_srcdir = @top_srcdir@ @@ -477,9 +477,9 @@ index 0cc82f1..cb830db 100644 LIBS = @LIBS@ -@@ -136,27 +136,27 @@ dynamic_db.@O@: dynamic_db.c - -DDYNDB_LIBDIR=\"@libdir@/bind/\" \ - -c ${srcdir}/dynamic_db.c +@@ -131,24 +131,24 @@ version.@O@: version.c + -DLIBAGE=${LIBAGE} \ + -c ${srcdir}/version.c -libdns.@SA@: ${OBJS} +libdns-pkcs11.@SA@: ${OBJS} @@ -492,8 +492,7 @@ index 0cc82f1..cb830db 100644 - ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libdns.la -rpath ${libdir} \ + ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libdns-pkcs11.la -rpath ${libdir} \ -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \ -- ${OBJS} ${ISCLIBS} @DNS_CRYPTO_LIBS@ ${LIBS} -+ ${OBJS} ${ISCLIBS} @DNS_CRYPTO_PK11_LIBS@ ${LIBS} + ${OBJS} ${ISCLIBS} @DNS_CRYPTO_LIBS@ ${LIBS} -timestamp: libdns.@A@ +timestamp: libdns-pkcs11.@A@ @@ -507,12 +506,8 @@ index 0cc82f1..cb830db 100644 + ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} libdns-pkcs11.@A@ ${DESTDIR}${libdir} clean distclean:: -- rm -f libdns.@A@ timestamp -+ rm -f libdns-pkcs11.@A@ timestamp - rm -f gen code.h include/dns/enumtype.h include/dns/enumclass.h - rm -f include/dns/rdatastruct.h - -@@ -186,7 +186,7 @@ code.h: gen + rm -f libdns.@A@ timestamp +@@ -181,7 +181,7 @@ code.h: gen ./gen -s ${srcdir} > code.h gen: gen.c @@ -535,7 +530,7 @@ index 1fd7216..a8a1342 100644 @BIND9_MAKE_RULES@ diff --git a/lib/export/dns-pkcs11/Makefile.in b/lib/export/dns-pkcs11/Makefile.in -index 54e4e39..71c6b25 100644 +index 887acb9..0f8abd3 100644 --- a/lib/export/dns-pkcs11/Makefile.in +++ b/lib/export/dns-pkcs11/Makefile.in @@ -15,7 +15,7 @@ @@ -569,7 +564,7 @@ index 54e4e39..71c6b25 100644 LIBS = @LIBS@ -@@ -114,29 +114,29 @@ version.@O@: ${srcdir}/version.c +@@ -118,29 +118,29 @@ version.@O@: ${srcdir}/version.c -DLIBAGE=${LIBAGE} \ -c ${srcdir}/version.c @@ -607,7 +602,7 @@ index 54e4e39..71c6b25 100644 rm -f include/dns/rdatastruct.h diff --git a/lib/export/isc-pkcs11/Makefile.in b/lib/export/isc-pkcs11/Makefile.in -index a5f8bd0..7655a9b 100644 +index 4f4a9f7..f8224e7 100644 --- a/lib/export/isc-pkcs11/Makefile.in +++ b/lib/export/isc-pkcs11/Makefile.in @@ -15,7 +15,7 @@ diff --git a/SOURCES/bind-96-dyndb.patch b/SOURCES/bind-96-dyndb.patch deleted file mode 100644 index 7593059..0000000 --- a/SOURCES/bind-96-dyndb.patch +++ /dev/null @@ -1,729 +0,0 @@ -diff -up bind-9.9.2/bin/named/main.c.dyndb bind-9.9.2/bin/named/main.c ---- bind-9.9.2/bin/named/main.c.dyndb 2012-09-27 02:35:19.000000000 +0200 -+++ bind-9.9.2/bin/named/main.c 2012-10-11 13:13:10.626497598 +0200 -@@ -45,6 +45,7 @@ - #include - - #include -+#include - #include - #include - #include -diff -up bind-9.9.2/bin/named/server.c.dyndb bind-9.9.2/bin/named/server.c ---- bind-9.9.2/bin/named/server.c.dyndb 2012-09-27 02:35:19.000000000 +0200 -+++ bind-9.9.2/bin/named/server.c 2012-10-11 13:13:10.630497590 +0200 -@@ -63,6 +63,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -1161,6 +1162,72 @@ configure_peer(const cfg_obj_t *cpeer, i - } - - static isc_result_t -+configure_dynamic_db(const cfg_obj_t *dynamic_db, isc_mem_t *mctx, -+ const dns_dyndb_arguments_t *dyndb_args) -+{ -+ isc_result_t result; -+ const cfg_obj_t *obj; -+ const cfg_obj_t *options; -+ const cfg_listelt_t *element; -+ const char *name; -+ const char *libname; -+ const char **argv = NULL; -+ unsigned int i; -+ unsigned int len; -+ -+ /* Get the name of the database. */ -+ obj = cfg_tuple_get(dynamic_db, "name"); -+ name = cfg_obj_asstring(obj); -+ -+ /* Get options. */ -+ options = cfg_tuple_get(dynamic_db, "options"); -+ -+ /* Get library name. */ -+ obj = NULL; -+ CHECK(cfg_map_get(options, "library", &obj)); -+ libname = cfg_obj_asstring(obj); -+ -+ /* Create a list of arguments. */ -+ obj = NULL; -+ result = cfg_map_get(options, "arg", &obj); -+ if (result == ISC_R_NOTFOUND) -+ len = 0; -+ else if (result == ISC_R_SUCCESS) -+ len = cfg_list_length(obj, isc_boolean_false); -+ else -+ goto cleanup; -+ -+ /* Account for the last terminating NULL. */ -+ len++; -+ -+ argv = isc_mem_allocate(mctx, len * sizeof(const char *)); -+ if (argv == NULL) { -+ result = ISC_R_NOMEMORY; -+ goto cleanup; -+ } -+ for (element = cfg_list_first(obj), i = 0; -+ element != NULL; -+ element = cfg_list_next(element), i++) -+ { -+ REQUIRE(i < len); -+ -+ obj = cfg_listelt_value(element); -+ argv[i] = cfg_obj_asstring(obj); -+ } -+ REQUIRE(i < len); -+ argv[i] = NULL; -+ -+ CHECK(dns_dynamic_db_load(libname, name, mctx, argv, dyndb_args)); -+ -+cleanup: -+ if (argv != NULL) -+ isc_mem_free(mctx, argv); -+ -+ return result; -+} -+ -+ -+static isc_result_t - disable_algorithms(const cfg_obj_t *disabled, dns_resolver_t *resolver) { - isc_result_t result; - const cfg_obj_t *algorithms; -@@ -1586,6 +1653,7 @@ configure_view(dns_view_t *view, cfg_obj - const cfg_obj_t *dlz; - unsigned int dlzargc; - char **dlzargv; -+ const cfg_obj_t *dynamic_db_list; - const cfg_obj_t *disabled; - const cfg_obj_t *obj; - const cfg_listelt_t *element; -@@ -1816,6 +1884,8 @@ configure_view(dns_view_t *view, cfg_obj - } - } - -+ -+ - /* - * Obtain configuration parameters that affect the decision of whether - * we can reuse/share an existing cache. -@@ -2721,6 +2791,37 @@ configure_view(dns_view_t *view, cfg_obj - dns_view_setrootdelonly(view, ISC_FALSE); - - /* -+ * Configure dynamic databases. -+ */ -+ dynamic_db_list = NULL; -+ if (voptions != NULL) -+ (void)cfg_map_get(voptions, "dynamic-db", &dynamic_db_list); -+ else -+ (void)cfg_map_get(config, "dynamic-db", &dynamic_db_list); -+ element = cfg_list_first(dynamic_db_list); -+ if (element != NULL) { -+ dns_dyndb_arguments_t *args; -+ -+ args = dns_dyndb_arguments_create(mctx); -+ if (args == NULL) { -+ result = ISC_R_NOMEMORY; -+ goto cleanup; -+ } -+ dns_dyndb_set_view(args, view); -+ dns_dyndb_set_zonemgr(args, ns_g_server->zonemgr); -+ dns_dyndb_set_task(args, ns_g_server->task); -+ dns_dyndb_set_timermgr(args, ns_g_timermgr); -+ while (element != NULL) { -+ obj = cfg_listelt_value(element); -+ CHECK(configure_dynamic_db(obj, mctx, args)); -+ -+ element = cfg_list_next(element); -+ } -+ -+ dns_dyndb_arguments_destroy(mctx, args); -+ } -+ -+ /* - * Setup automatic empty zones. If recursion is off then - * they are disabled by default. - */ -@@ -4388,6 +4489,7 @@ load_configuration(const char *filename, - cfg_aclconfctx_detach(&ns_g_aclconfctx); - CHECK(cfg_aclconfctx_create(ns_g_mctx, &ns_g_aclconfctx)); - -+ dns_dynamic_db_cleanup(ISC_FALSE); - /* - * Parse the global default pseudo-config file. - */ -@@ -5493,6 +5595,8 @@ shutdown_server(isc_task_t *task, isc_ev - dns_view_detach(&view); - } - -+ dns_dynamic_db_cleanup(ISC_TRUE); -+ - while ((nsc = ISC_LIST_HEAD(server->cachelist)) != NULL) { - ISC_LIST_UNLINK(server->cachelist, nsc, link); - dns_cache_detach(&nsc->cache); -diff -up bind-9.9.2/lib/dns/dynamic_db.c.dyndb bind-9.9.2/lib/dns/dynamic_db.c ---- bind-9.9.2/lib/dns/dynamic_db.c.dyndb 2012-10-11 13:13:10.630497590 +0200 -+++ bind-9.9.2/lib/dns/dynamic_db.c 2012-10-11 13:13:10.630497590 +0200 -@@ -0,0 +1,366 @@ -+/* -+ * 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. -+ */ -+ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#if HAVE_DLFCN_H -+#include -+#endif -+ -+#ifndef DYNDB_LIBDIR -+#define DYNDB_LIBDIR "" -+#endif -+ -+#define CHECK(op) \ -+ do { result = (op); \ -+ if (result != ISC_R_SUCCESS) goto cleanup; \ -+ } while (0) -+ -+ -+typedef isc_result_t (*register_func_t)(isc_mem_t *mctx, const char *name, -+ const char * const *argv, -+ const dns_dyndb_arguments_t *dyndb_args); -+typedef void (*destroy_func_t)(void); -+ -+typedef struct dyndb_implementation dyndb_implementation_t; -+ -+struct dyndb_implementation { -+ isc_mem_t *mctx; -+ void *handle; -+ register_func_t register_function; -+ destroy_func_t destroy_function; -+ LINK(dyndb_implementation_t) link; -+}; -+ -+struct dns_dyndb_arguments { -+ dns_view_t *view; -+ dns_zonemgr_t *zmgr; -+ isc_task_t *task; -+ isc_timermgr_t *timermgr; -+}; -+ -+/* List of implementations. Locked by dyndb_lock. */ -+static LIST(dyndb_implementation_t) dyndb_implementations; -+/* Locks dyndb_implementations. */ -+static isc_mutex_t dyndb_lock; -+static isc_once_t once = ISC_ONCE_INIT; -+ -+static void -+dyndb_initialize(void) { -+ RUNTIME_CHECK(isc_mutex_init(&dyndb_lock) == ISC_R_SUCCESS); -+ INIT_LIST(dyndb_implementations); -+} -+ -+ -+#if HAVE_DLFCN_H -+static isc_result_t -+load_symbol(void *handle, const char *symbol_name, void **symbolp) -+{ -+ const char *errmsg; -+ void *symbol; -+ -+ REQUIRE(handle != NULL); -+ REQUIRE(symbolp != NULL && *symbolp == NULL); -+ -+ symbol = dlsym(handle, symbol_name); -+ if (symbol == NULL) { -+ errmsg = dlerror(); -+ if (errmsg == NULL) -+ errmsg = "returned function pointer is NULL"; -+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, -+ DNS_LOGMODULE_DYNDB, ISC_LOG_ERROR, -+ "failed to lookup symbol %s: %s", -+ symbol_name, errmsg); -+ return ISC_R_FAILURE; -+ } -+ dlerror(); -+ -+ *symbolp = symbol; -+ -+ return ISC_R_SUCCESS; -+} -+ -+static isc_result_t -+load_library(isc_mem_t *mctx, const char *filename, dyndb_implementation_t **impp) -+{ -+ isc_result_t result; -+ size_t module_size; -+ isc_buffer_t *module_buf = NULL; -+ isc_region_t module_region; -+ void *handle = NULL; -+ dyndb_implementation_t *imp; -+ register_func_t register_function = NULL; -+ destroy_func_t destroy_function = NULL; -+ -+ REQUIRE(impp != NULL && *impp == NULL); -+ -+ /* Build up the full path. */ -+ module_size = strlen(DYNDB_LIBDIR) + strlen(filename) + 1; -+ CHECK(isc_buffer_allocate(mctx, &module_buf, module_size)); -+ isc_buffer_putstr(module_buf, DYNDB_LIBDIR); -+ isc_buffer_putstr(module_buf, filename); -+ isc_buffer_putuint8(module_buf, 0); -+ isc_buffer_region(module_buf, &module_region); -+ -+ handle = dlopen((char *)module_region.base, RTLD_LAZY); -+ if (handle == NULL) { -+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, -+ DNS_LOGMODULE_DYNDB, ISC_LOG_ERROR, -+ "failed to dynamically load driver '%s': %s", -+ filename, dlerror()); -+ result = ISC_R_FAILURE; -+ goto cleanup; -+ } -+ dlerror(); -+ -+ CHECK(load_symbol(handle, "dynamic_driver_init", -+ (void **)®ister_function)); -+ CHECK(load_symbol(handle, "dynamic_driver_destroy", -+ (void **)&destroy_function)); -+ -+ imp = isc_mem_get(mctx, sizeof(dyndb_implementation_t)); -+ if (imp == NULL) { -+ result = ISC_R_NOMEMORY; -+ goto cleanup; -+ } -+ -+ imp->mctx = NULL; -+ isc_mem_attach(mctx, &imp->mctx); -+ imp->handle = handle; -+ imp->register_function = register_function; -+ imp->destroy_function = destroy_function; -+ INIT_LINK(imp, link); -+ -+ *impp = imp; -+ -+cleanup: -+ if (result != ISC_R_SUCCESS && handle != NULL) -+ dlclose(handle); -+ if (module_buf != NULL) -+ isc_buffer_free(&module_buf); -+ -+ return result; -+} -+ -+static void -+unload_library(dyndb_implementation_t **impp) -+{ -+ dyndb_implementation_t *imp; -+ -+ REQUIRE(impp != NULL && *impp != NULL); -+ -+ imp = *impp; -+ -+ isc_mem_putanddetach(&imp->mctx, imp, sizeof(dyndb_implementation_t)); -+ -+ *impp = NULL; -+} -+ -+#else /* HAVE_DLFCN_H */ -+static isc_result_t -+load_library(isc_mem_t *mctx, const char *filename, dyndb_implementation_t **impp) -+{ -+ UNUSED(mctx); -+ UNUSED(filename); -+ UNUSED(impp); -+ -+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DYNDB, -+ ISC_LOG_ERROR, -+ "dynamic database support is not implemented") -+ -+ return ISC_R_NOTIMPLEMENTED; -+} -+ -+static void -+unload_library(dyndb_implementation_t **impp) -+{ -+ dyndb_implementation_t *imp; -+ -+ REQUIRE(impp != NULL && *impp != NULL); -+ -+ imp = *impp; -+ -+ isc_mem_putanddetach(&imp->mctx, imp, sizeof(dyndb_implementation_t)); -+ -+ *impp = NULL; -+} -+#endif /* HAVE_DLFCN_H */ -+ -+isc_result_t -+dns_dynamic_db_load(const char *libname, const char *name, isc_mem_t *mctx, -+ const char * const *argv, -+ const dns_dyndb_arguments_t *dyndb_args) -+{ -+ isc_result_t result; -+ dyndb_implementation_t *implementation = NULL; -+ -+ RUNTIME_CHECK(isc_once_do(&once, dyndb_initialize) == ISC_R_SUCCESS); -+ -+ CHECK(load_library(mctx, libname, &implementation)); -+ CHECK(implementation->register_function(mctx, name, argv, dyndb_args)); -+ -+ LOCK(&dyndb_lock); -+ APPEND(dyndb_implementations, implementation, link); -+ UNLOCK(&dyndb_lock); -+ -+ return ISC_R_SUCCESS; -+ -+cleanup: -+ if (implementation != NULL) -+ unload_library(&implementation); -+ -+ return result; -+} -+ -+void -+dns_dynamic_db_cleanup(isc_boolean_t exiting) -+{ -+ dyndb_implementation_t *elem; -+ dyndb_implementation_t *prev; -+ -+ RUNTIME_CHECK(isc_once_do(&once, dyndb_initialize) == ISC_R_SUCCESS); -+ -+ LOCK(&dyndb_lock); -+ elem = TAIL(dyndb_implementations); -+ while (elem != NULL) { -+ prev = PREV(elem, link); -+ UNLINK(dyndb_implementations, elem, link); -+ elem->destroy_function(); -+ unload_library(&elem); -+ elem = prev; -+ } -+ UNLOCK(&dyndb_lock); -+ -+ if (exiting == ISC_TRUE) -+ isc_mutex_destroy(&dyndb_lock); -+} -+ -+dns_dyndb_arguments_t * -+dns_dyndb_arguments_create(isc_mem_t *mctx) -+{ -+ dns_dyndb_arguments_t *args; -+ -+ args = isc_mem_get(mctx, sizeof(*args)); -+ if (args != NULL) -+ memset(args, 0, sizeof(*args)); -+ -+ return args; -+} -+ -+void -+dns_dyndb_arguments_destroy(isc_mem_t *mctx, dns_dyndb_arguments_t *args) -+{ -+ REQUIRE(args != NULL); -+ -+ dns_dyndb_set_view(args, NULL); -+ dns_dyndb_set_zonemgr(args, NULL); -+ dns_dyndb_set_task(args, NULL); -+ dns_dyndb_set_timermgr(args, NULL); -+ -+ isc_mem_put(mctx, args, sizeof(*args)); -+} -+ -+void -+dns_dyndb_set_view(dns_dyndb_arguments_t *args, dns_view_t *view) -+{ -+ REQUIRE(args != NULL); -+ -+ if (args->view != NULL) -+ dns_view_detach(&args->view); -+ if (view != NULL) -+ dns_view_attach(view, &args->view); -+} -+ -+dns_view_t * -+dns_dyndb_get_view(dns_dyndb_arguments_t *args) -+{ -+ REQUIRE(args != NULL); -+ -+ return args->view; -+} -+ -+void -+dns_dyndb_set_zonemgr(dns_dyndb_arguments_t *args, dns_zonemgr_t *zmgr) -+{ -+ REQUIRE(args != NULL); -+ -+ if (args->zmgr != NULL) -+ dns_zonemgr_detach(&args->zmgr); -+ if (zmgr != NULL) -+ dns_zonemgr_attach(zmgr, &args->zmgr); -+} -+ -+dns_zonemgr_t * -+dns_dyndb_get_zonemgr(dns_dyndb_arguments_t *args) -+{ -+ REQUIRE(args != NULL); -+ -+ return args->zmgr; -+} -+ -+void -+dns_dyndb_set_task(dns_dyndb_arguments_t *args, isc_task_t *task) -+{ -+ REQUIRE(args != NULL); -+ -+ if (args->task != NULL) -+ isc_task_detach(&args->task); -+ if (task != NULL) -+ isc_task_attach(task, &args->task); -+} -+ -+isc_task_t * -+dns_dyndb_get_task(dns_dyndb_arguments_t *args) -+{ -+ REQUIRE(args != NULL); -+ -+ return args->task; -+} -+ -+void -+dns_dyndb_set_timermgr(dns_dyndb_arguments_t *args, isc_timermgr_t *timermgr) -+{ -+ REQUIRE(args != NULL); -+ -+ args->timermgr = timermgr; -+} -+ -+isc_timermgr_t * -+dns_dyndb_get_timermgr(dns_dyndb_arguments_t *args) -+{ -+ REQUIRE(args != NULL); -+ -+ return args->timermgr; -+} -diff -up bind-9.9.2/lib/dns/include/dns/dynamic_db.h.dyndb bind-9.9.2/lib/dns/include/dns/dynamic_db.h ---- bind-9.9.2/lib/dns/include/dns/dynamic_db.h.dyndb 2012-10-11 13:13:10.631497588 +0200 -+++ bind-9.9.2/lib/dns/include/dns/dynamic_db.h 2012-10-11 13:13:10.631497588 +0200 -@@ -0,0 +1,50 @@ -+/* -+ * 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. -+ */ -+ -+ -+#ifndef DYNAMIC_DB_H -+#define DYNAMIC_DB_H -+ -+#include -+ -+#include -+ -+/* -+ * TODO: -+ * Reformat the prototypes. -+ * Add annotated comments. -+ */ -+ -+isc_result_t dns_dynamic_db_load(const char *libname, const char *name, -+ isc_mem_t *mctx, const char * const *argv, -+ const dns_dyndb_arguments_t *dyndb_args); -+ -+void dns_dynamic_db_cleanup(isc_boolean_t exiting); -+ -+dns_dyndb_arguments_t *dns_dyndb_arguments_create(isc_mem_t *mctx); -+void dns_dyndb_arguments_destroy(isc_mem_t *mctx, dns_dyndb_arguments_t *args); -+ -+void dns_dyndb_set_view(dns_dyndb_arguments_t *args, dns_view_t *view); -+dns_view_t *dns_dyndb_get_view(dns_dyndb_arguments_t *args); -+void dns_dyndb_set_zonemgr(dns_dyndb_arguments_t *args, dns_zonemgr_t *zmgr); -+dns_zonemgr_t *dns_dyndb_get_zonemgr(dns_dyndb_arguments_t *args); -+void dns_dyndb_set_task(dns_dyndb_arguments_t *args, isc_task_t *task); -+isc_task_t *dns_dyndb_get_task(dns_dyndb_arguments_t *args); -+void dns_dyndb_set_timermgr(dns_dyndb_arguments_t *args, -+ isc_timermgr_t *timermgr); -+isc_timermgr_t *dns_dyndb_get_timermgr(dns_dyndb_arguments_t *args); -+ -+#endif -diff -up bind-9.9.2/lib/dns/include/dns/log.h.dyndb bind-9.9.2/lib/dns/include/dns/log.h ---- bind-9.9.2/lib/dns/include/dns/log.h.dyndb 2012-09-27 02:35:19.000000000 +0200 -+++ bind-9.9.2/lib/dns/include/dns/log.h 2012-10-11 13:13:45.309399482 +0200 -@@ -76,6 +76,7 @@ LIBDNS_EXTERNAL_DATA extern isc_logmodul - #define DNS_LOGMODULE_DLZ (&dns_modules[26]) - #define DNS_LOGMODULE_DNSSEC (&dns_modules[27]) - #define DNS_LOGMODULE_CRYPTO (&dns_modules[28]) -+#define DNS_LOGMODULE_DYNDB (&dns_modules[29]) - - ISC_LANG_BEGINDECLS - -diff -up bind-9.9.2/lib/dns/include/dns/Makefile.in.dyndb bind-9.9.2/lib/dns/include/dns/Makefile.in ---- bind-9.9.2/lib/dns/include/dns/Makefile.in.dyndb 2012-09-27 02:35:19.000000000 +0200 -+++ bind-9.9.2/lib/dns/include/dns/Makefile.in 2012-10-11 13:13:10.632497587 +0200 -@@ -22,7 +22,7 @@ top_srcdir = @top_srcdir@ - @BIND9_VERSION@ - - HEADERS = acl.h adb.h byaddr.h cache.h callbacks.h cert.h compress.h \ -- clientinfo.h db.h dbiterator.h dbtable.h diff.h dispatch.h \ -+ clientinfo.h db.h dbiterator.h dbtable.h diff.h dispatch.h dynamic_db.h \ - dlz.h dnssec.h ds.h events.h fixedname.h iptable.h journal.h \ - keyflags.h keytable.h keyvalues.h lib.h log.h \ - master.h masterdump.h message.h name.h ncache.h nsec.h \ -diff -up bind-9.9.2/lib/dns/include/dns/types.h.dyndb bind-9.9.2/lib/dns/include/dns/types.h ---- bind-9.9.2/lib/dns/include/dns/types.h.dyndb 2012-09-27 02:35:19.000000000 +0200 -+++ bind-9.9.2/lib/dns/include/dns/types.h 2012-10-11 13:13:10.632497587 +0200 -@@ -60,6 +60,7 @@ typedef struct dns_dbtable dns_dbtable - typedef void dns_dbversion_t; - typedef struct dns_dlzimplementation dns_dlzimplementation_t; - typedef struct dns_dlzdb dns_dlzdb_t; -+typedef struct dns_dyndb_arguments dns_dyndb_arguments_t; - typedef struct dns_sdlzimplementation dns_sdlzimplementation_t; - typedef struct dns_decompress dns_decompress_t; - typedef struct dns_dispatch dns_dispatch_t; -diff -up bind-9.9.2/lib/dns/log.c.dyndb bind-9.9.2/lib/dns/log.c ---- bind-9.9.2/lib/dns/log.c.dyndb 2012-09-27 02:35:19.000000000 +0200 -+++ bind-9.9.2/lib/dns/log.c 2012-10-11 13:15:15.085414483 +0200 -@@ -82,6 +82,7 @@ LIBDNS_EXTERNAL_DATA isc_logmodule_t dns - { "dns/dlz", 0 }, - { "dns/dnssec", 0 }, - { "dns/crypto", 0 }, -+ { "dns/dynamic_db", 0 }, - { NULL, 0 } - }; - -diff -up bind-9.9.2/lib/dns/Makefile.in.dyndb bind-9.9.2/lib/dns/Makefile.in ---- bind-9.9.2/lib/dns/Makefile.in.dyndb 2012-10-11 13:13:10.605497637 +0200 -+++ bind-9.9.2/lib/dns/Makefile.in 2012-10-11 13:13:10.633497585 +0200 -@@ -59,7 +59,7 @@ DNSOBJS = acache.@O@ acl.@O@ adb.@O@ bya - cache.@O@ callbacks.@O@ clientinfo.@O@ compress.@O@ \ - db.@O@ dbiterator.@O@ dbtable.@O@ diff.@O@ dispatch.@O@ \ - dlz.@O@ dns64.@O@ dnssec.@O@ ds.@O@ forward.@O@ iptable.@O@ \ -- journal.@O@ keydata.@O@ keytable.@O@ \ -+ dynamic_db.@O@ journal.@O@ keydata.@O@ keytable.@O@ \ - lib.@O@ log.@O@ lookup.@O@ \ - master.@O@ masterdump.@O@ message.@O@ \ - name.@O@ ncache.@O@ nsec.@O@ nsec3.@O@ order.@O@ peer.@O@ \ -@@ -88,7 +88,7 @@ DNSSRCS = acache.c acl.c adb.c byaddr.c - cache.c callbacks.c clientinfo.c compress.c \ - db.c dbiterator.c dbtable.c diff.c dispatch.c \ - dlz.c dns64.c dnssec.c ds.c forward.c iptable.c journal.c \ -- keydata.c keytable.c lib.c log.c lookup.c \ -+ dynamic_db.c keydata.c keytable.c lib.c log.c lookup.c \ - master.c masterdump.c message.c \ - name.c ncache.c nsec.c nsec3.c order.c peer.c portlist.c \ - rbt.c rbtdb.c rbtdb64.c rcode.c rdata.c rdatalist.c \ -@@ -119,6 +119,11 @@ version.@O@: version.c - -DLIBAGE=${LIBAGE} \ - -c ${srcdir}/version.c - -+dynamic_db.@O@: dynamic_db.c -+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \ -+ -DDYNDB_LIBDIR=\"@libdir@/bind/\" \ -+ -c ${srcdir}/dynamic_db.c -+ - libdns.@SA@: ${OBJS} - ${AR} ${ARFLAGS} $@ ${OBJS} - ${RANLIB} $@ -diff -up bind-9.9.2/lib/isccfg/namedconf.c.dyndb bind-9.9.2/lib/isccfg/namedconf.c ---- bind-9.9.2/lib/isccfg/namedconf.c.dyndb 2012-09-27 02:35:19.000000000 +0200 -+++ bind-9.9.2/lib/isccfg/namedconf.c 2012-10-11 13:13:10.634497583 +0200 -@@ -89,6 +89,7 @@ static cfg_type_t cfg_type_controls; - static cfg_type_t cfg_type_controls_sockaddr; - static cfg_type_t cfg_type_destinationlist; - static cfg_type_t cfg_type_dialuptype; -+static cfg_type_t cfg_type_dynamic_db; - static cfg_type_t cfg_type_ixfrdifftype; - static cfg_type_t cfg_type_key; - static cfg_type_t cfg_type_logfile; -@@ -871,6 +872,7 @@ namedconf_or_view_clauses[] = { - { "zone", &cfg_type_zone, CFG_CLAUSEFLAG_MULTI }, - /* only 1 DLZ per view allowed */ - { "dlz", &cfg_type_dynamically_loadable_zones, 0 }, -+ { "dynamic-db", &cfg_type_dynamic_db, CFG_CLAUSEFLAG_MULTI }, - { "server", &cfg_type_server, CFG_CLAUSEFLAG_MULTI }, - { "trusted-keys", &cfg_type_dnsseckeys, CFG_CLAUSEFLAG_MULTI }, - { "managed-keys", &cfg_type_managedkeys, CFG_CLAUSEFLAG_MULTI }, -@@ -1983,6 +1985,40 @@ static cfg_type_t cfg_type_dialuptype = - &cfg_rep_string, dialup_enums - }; - -+/* -+ * Dynamic database clauses. -+ */ -+ -+static cfg_clausedef_t -+dynamic_db_clauses[] = { -+ { "library", &cfg_type_qstring, 0 }, -+ { "arg", &cfg_type_qstring, CFG_CLAUSEFLAG_MULTI }, -+ { NULL, NULL, 0 } -+}; -+ -+static cfg_clausedef_t * -+dynamic_db_clausesets[] = { -+ dynamic_db_clauses, -+ NULL -+}; -+ -+static cfg_type_t cfg_type_dynamic_db_opts = { -+ "dynamically_loadable_zones_opts", cfg_parse_map, -+ cfg_print_map, cfg_doc_map, &cfg_rep_map, -+ dynamic_db_clausesets -+}; -+ -+static cfg_tuplefielddef_t dynamic_db_fields[] = { -+ { "name", &cfg_type_astring, 0 }, -+ { "options", &cfg_type_dynamic_db_opts, 0 }, -+ { NULL, NULL, 0 } -+}; -+ -+static cfg_type_t cfg_type_dynamic_db = { -+ "dynamic_db", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, -+ &cfg_rep_tuple, dynamic_db_fields -+}; -+ - static const char *notify_enums[] = { "explicit", "master-only", NULL }; - static isc_result_t - parse_notify_type(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { diff --git a/SOURCES/bind-99-dyndb-rh1142150.patch b/SOURCES/bind-99-dyndb-rh1142150.patch deleted file mode 100644 index 0ff2fbf..0000000 --- a/SOURCES/bind-99-dyndb-rh1142150.patch +++ /dev/null @@ -1,114 +0,0 @@ -From 1f6c240231fcb9fe8bc4a28f3359201c2a1d8465 Mon Sep 17 00:00:00 2001 -From: Tomas Hozza -Date: Wed, 17 Sep 2014 20:00:39 +0200 -Subject: [PATCH] Fix for BZ #1142150 - -Signed-off-by: Tomas Hozza ---- - bin/named/server.c | 14 +++++++++----- - lib/dns/dynamic_db.c | 12 ++++++++++-- - lib/dns/include/dns/dynamic_db.h | 2 +- - 3 files changed, 20 insertions(+), 8 deletions(-) - -diff --git a/bin/named/server.c b/bin/named/server.c -index ee04dda..6f8b0f0 100644 ---- a/bin/named/server.c -+++ b/bin/named/server.c -@@ -1302,6 +1302,12 @@ configure_dynamic_db(const cfg_obj_t *dynamic_db, isc_mem_t *mctx, - CHECK(dns_dynamic_db_load(libname, name, mctx, argv, dyndb_args)); - - cleanup: -+ -+ 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)); - if (argv != NULL) - isc_mem_free(mctx, argv); - -@@ -2165,6 +2171,7 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, - unsigned int query_timeout, ndisp; - struct cfg_context *nzctx; - dns_rpz_zone_t *rpz; -+ dns_dyndb_arguments_t *args = NULL; - - REQUIRE(DNS_VIEW_VALID(view)); - -@@ -3330,8 +3337,6 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, - (void)cfg_map_get(config, "dynamic-db", &dynamic_db_list); - element = cfg_list_first(dynamic_db_list); - if (element != NULL) { -- dns_dyndb_arguments_t *args; -- - args = dns_dyndb_arguments_create(mctx); - if (args == NULL) { - result = ISC_R_NOMEMORY; -@@ -3344,11 +3349,8 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, - while (element != NULL) { - obj = cfg_listelt_value(element); - CHECK(configure_dynamic_db(obj, mctx, args)); -- - element = cfg_list_next(element); - } -- -- dns_dyndb_arguments_destroy(mctx, args); - } - - /* -@@ -3536,6 +3538,8 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, - - if (cache != NULL) - dns_cache_detach(&cache); -+ if (args != NULL) -+ dns_dyndb_arguments_destroy(mctx, &args); - - return (result); - } -diff --git a/lib/dns/dynamic_db.c b/lib/dns/dynamic_db.c -index bf83161..a0d26eb 100644 ---- a/lib/dns/dynamic_db.c -+++ b/lib/dns/dynamic_db.c -@@ -280,9 +280,15 @@ dns_dyndb_arguments_create(isc_mem_t *mctx) - } - - void --dns_dyndb_arguments_destroy(isc_mem_t *mctx, dns_dyndb_arguments_t *args) -+dns_dyndb_arguments_destroy(isc_mem_t *mctx, dns_dyndb_arguments_t **argsp) - { -- REQUIRE(args != NULL); -+ dns_dyndb_arguments_t *args; -+ -+ REQUIRE(argsp != NULL); -+ -+ args = *argsp; -+ if (args == NULL) -+ return; - - dns_dyndb_set_view(args, NULL); - dns_dyndb_set_zonemgr(args, NULL); -@@ -290,6 +296,8 @@ dns_dyndb_arguments_destroy(isc_mem_t *mctx, dns_dyndb_arguments_t *args) - dns_dyndb_set_timermgr(args, NULL); - - isc_mem_put(mctx, args, sizeof(*args)); -+ -+ *argsp = NULL; - } - - void -diff --git a/lib/dns/include/dns/dynamic_db.h b/lib/dns/include/dns/dynamic_db.h -index 673ad4b..5ecee0e 100644 ---- a/lib/dns/include/dns/dynamic_db.h -+++ b/lib/dns/include/dns/dynamic_db.h -@@ -35,7 +35,7 @@ isc_result_t dns_dynamic_db_load(const char *libname, const char *name, - void dns_dynamic_db_cleanup(isc_boolean_t exiting); - - dns_dyndb_arguments_t *dns_dyndb_arguments_create(isc_mem_t *mctx); --void dns_dyndb_arguments_destroy(isc_mem_t *mctx, dns_dyndb_arguments_t *args); -+void dns_dyndb_arguments_destroy(isc_mem_t *mctx, dns_dyndb_arguments_t **argsp); - - void dns_dyndb_set_view(dns_dyndb_arguments_t *args, dns_view_t *view); - dns_view_t *dns_dyndb_get_view(dns_dyndb_arguments_t *args); --- -1.9.3 - diff --git a/SOURCES/bind99-CVE-2016-2775.patch b/SOURCES/bind99-CVE-2016-2775.patch new file mode 100644 index 0000000..bc5ac47 --- /dev/null +++ b/SOURCES/bind99-CVE-2016-2775.patch @@ -0,0 +1,66 @@ +From 062b04898be720ed0855efc192847fcbc667b3e1 Mon Sep 17 00:00:00 2001 +From: Mark Andrews +Date: Thu, 7 Jul 2016 12:52:47 +1000 +Subject: [PATCH] 4406. [bug] getrrsetbyname with a non absolute + name could trigger a infinite recursion bug in lwresd + and named with lwres configured if when combined + with a search list entry the resulting name is + too long. [RT #42694] + +(cherry picked from commit 38cc2d14e218e536e0102fa70deef99461354232) +--- + bin/named/lwdgrbn.c | 16 ++++++++++------ + bin/tests/system/lwresd/lwtest.c | 8 ++++++++ + 2 files changed, 18 insertions(+), 6 deletions(-) + +diff --git a/bin/named/lwdgrbn.c b/bin/named/lwdgrbn.c +index 584ab25..37211eb 100644 +--- a/bin/named/lwdgrbn.c ++++ b/bin/named/lwdgrbn.c +@@ -403,14 +403,18 @@ start_lookup(ns_lwdclient_t *client) { + INSIST(client->lookup == NULL); + + dns_fixedname_init(&absname); +- result = ns_lwsearchctx_current(&client->searchctx, +- dns_fixedname_name(&absname)); ++ + /* +- * This will return failure if relative name + suffix is too long. +- * In this case, just go on to the next entry in the search path. ++ * Perform search across all search domains until success ++ * is returned. Return in case of failure. + */ +- if (result != ISC_R_SUCCESS) +- start_lookup(client); ++ while (ns_lwsearchctx_current(&client->searchctx, ++ dns_fixedname_name(&absname)) != ISC_R_SUCCESS) { ++ if (ns_lwsearchctx_next(&client->searchctx) != ISC_R_SUCCESS) { ++ ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE); ++ return; ++ } ++ } + + result = dns_lookup_create(cm->mctx, + dns_fixedname_name(&absname), +diff --git a/bin/tests/system/lwresd/lwtest.c b/bin/tests/system/lwresd/lwtest.c +index 02647cb..c2be95d 100644 +--- a/bin/tests/system/lwresd/lwtest.c ++++ b/bin/tests/system/lwresd/lwtest.c +@@ -768,6 +768,14 @@ main(void) { + test_getrrsetbyname("e.example1.", 1, 46, 2, 0, 1); + test_getrrsetbyname("", 1, 1, 0, 0, 0); + ++ test_getrrsetbyname("123456789.123456789.123456789.123456789." ++ "123456789.123456789.123456789.123456789." ++ "123456789.123456789.123456789.123456789." ++ "123456789.123456789.123456789.123456789." ++ "123456789.123456789.123456789.123456789." ++ "123456789.123456789.123456789.123456789." ++ "123456789", 1, 1, 0, 0, 0); ++ + if (fails == 0) + printf("I:ok\n"); + return (fails); +-- +2.7.4 + diff --git a/SOURCES/bind99-CVE-2017-3142+3143.patch b/SOURCES/bind99-CVE-2017-3142+3143.patch deleted file mode 100644 index a0190f4..0000000 --- a/SOURCES/bind99-CVE-2017-3142+3143.patch +++ /dev/null @@ -1,497 +0,0 @@ -diff --git a/lib/dns/dnssec.c b/lib/dns/dnssec.c -index 00a0080..336c4da 100644 ---- a/lib/dns/dnssec.c -+++ b/lib/dns/dnssec.c -@@ -982,6 +982,8 @@ dns_dnssec_verifymessage(isc_buffer_t *source, dns_message_t *msg, - mctx = msg->mctx; - - msg->verify_attempted = 1; -+ msg->verified_sig = 0; -+ msg->sig0status = dns_tsigerror_badsig; - - if (is_response(msg)) { - if (msg->query.base == NULL) -@@ -1076,6 +1078,7 @@ dns_dnssec_verifymessage(isc_buffer_t *source, dns_message_t *msg, - } - - msg->verified_sig = 1; -+ msg->sig0status = dns_rcode_noerror; - - dst_context_destroy(&ctx); - dns_rdata_freestruct(&sig); -diff --git a/lib/dns/message.c b/lib/dns/message.c -index 1417067..0621175 100644 ---- a/lib/dns/message.c -+++ b/lib/dns/message.c -@@ -3052,12 +3052,19 @@ dns_message_signer(dns_message_t *msg, dns_name_t *signer) { - - result = dns_rdata_tostruct(&rdata, &tsig, NULL); - INSIST(result == ISC_R_SUCCESS); -- if (msg->tsigstatus != dns_rcode_noerror) -+ if (msg->verified_sig && -+ msg->tsigstatus == dns_rcode_noerror && -+ tsig.error == dns_rcode_noerror) -+ { -+ result = ISC_R_SUCCESS; -+ } else if ((!msg->verified_sig) || -+ (msg->tsigstatus != dns_rcode_noerror)) -+ { - result = DNS_R_TSIGVERIFYFAILURE; -- else if (tsig.error != dns_rcode_noerror) -+ } else { -+ INSIST(tsig.error != dns_rcode_noerror); - result = DNS_R_TSIGERRORSET; -- else -- result = ISC_R_SUCCESS; -+ } - dns_rdata_freestruct(&tsig); - - if (msg->tsigkey == NULL) { -diff --git a/lib/dns/tsig.c b/lib/dns/tsig.c -index 3239bff..7b91d1e 100644 ---- a/lib/dns/tsig.c -+++ b/lib/dns/tsig.c -@@ -941,11 +941,20 @@ dns_tsig_sign(dns_message_t *msg) { - isc_buffer_putuint48(&otherbuf, tsig.timesigned); - } - -- if (key->key != NULL && tsig.error != dns_tsigerror_badsig) { -+ if ((key->key != NULL) && -+ (tsig.error != dns_tsigerror_badsig) && -+ (tsig.error != dns_tsigerror_badkey)) -+ { - unsigned char header[DNS_MESSAGE_HEADERLEN]; - isc_buffer_t headerbuf; - isc_uint16_t digestbits; - -+ /* -+ * If it is a response, we assume that the request MAC -+ * has validated at this point. This is why we include a -+ * MAC length > 0 in the reply. -+ */ -+ - ret = dst_context_create3(key->key, mctx, - DNS_LOGCATEGORY_DNSSEC, - ISC_TRUE, &ctx); -@@ -953,7 +962,7 @@ dns_tsig_sign(dns_message_t *msg) { - return (ret); - - /* -- * If this is a response, digest the query signature. -+ * If this is a response, digest the request's MAC. - */ - if (response) { - dns_rdata_t querytsigrdata = DNS_RDATA_INIT; -@@ -1083,6 +1092,17 @@ dns_tsig_sign(dns_message_t *msg) { - dst_context_destroy(&ctx); - digestbits = dst_key_getbits(key->key); - if (digestbits != 0) { -+ /* -+ * XXXRAY: Is this correct? What is the -+ * expected behavior when digestbits is not an -+ * integral multiple of 8? It looks like bytes -+ * should either be (digestbits/8) or -+ * (digestbits+7)/8. -+ * -+ * In any case, for current algorithms, -+ * digestbits are an integral multiple of 8, so -+ * it has the same effect as (digestbits/8). -+ */ - unsigned int bytes = (digestbits + 1) / 8; - if (response && bytes < querytsig.siglen) - bytes = querytsig.siglen; -@@ -1196,6 +1216,8 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, - REQUIRE(tsigkey == NULL || VALID_TSIG_KEY(tsigkey)); - - msg->verify_attempted = 1; -+ msg->verified_sig = 0; -+ msg->tsigstatus = dns_tsigerror_badsig; - - if (msg->tcp_continuation) { - if (tsigkey == NULL || msg->querytsig == NULL) -@@ -1294,19 +1316,6 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, - key = tsigkey->key; - - /* -- * Is the time ok? -- */ -- if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) { -- msg->tsigstatus = dns_tsigerror_badtime; -- tsig_log(msg->tsigkey, 2, "signature has expired"); -- return (DNS_R_CLOCKSKEW); -- } else if (now + msg->timeadjust < tsig.timesigned - tsig.fudge) { -- msg->tsigstatus = dns_tsigerror_badtime; -- tsig_log(msg->tsigkey, 2, "signature is in the future"); -- return (DNS_R_CLOCKSKEW); -- } -- -- /* - * Check digest length. - */ - alg = dst_key_alg(key); -@@ -1315,31 +1324,19 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, - return (ret); - if (alg == DST_ALG_HMACMD5 || alg == DST_ALG_HMACSHA1 || - alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 || -- alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512) { -- isc_uint16_t digestbits = dst_key_getbits(key); -+ alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512) -+ { - if (tsig.siglen > siglen) { -- tsig_log(msg->tsigkey, 2, "signature length to big"); -+ tsig_log(msg->tsigkey, 2, "signature length too big"); - return (DNS_R_FORMERR); - } - if (tsig.siglen > 0 && -- (tsig.siglen < 10 || tsig.siglen < ((siglen + 1) / 2))) { -+ (tsig.siglen < 10 || tsig.siglen < ((siglen + 1) / 2))) -+ { - tsig_log(msg->tsigkey, 2, - "signature length below minimum"); - return (DNS_R_FORMERR); - } -- if (tsig.siglen > 0 && digestbits != 0 && -- tsig.siglen < ((digestbits + 1) / 8)) { -- msg->tsigstatus = dns_tsigerror_badtrunc; -- tsig_log(msg->tsigkey, 2, -- "truncated signature length too small"); -- return (DNS_R_TSIGVERIFYFAILURE); -- } -- if (tsig.siglen > 0 && digestbits == 0 && -- tsig.siglen < siglen) { -- msg->tsigstatus = dns_tsigerror_badtrunc; -- tsig_log(msg->tsigkey, 2, "signature length too small"); -- return (DNS_R_TSIGVERIFYFAILURE); -- } - } - - if (tsig.siglen > 0) { -@@ -1451,34 +1448,92 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, - - ret = dst_context_verify(ctx, &sig_r); - if (ret == DST_R_VERIFYFAILURE) { -- msg->tsigstatus = dns_tsigerror_badsig; - ret = DNS_R_TSIGVERIFYFAILURE; - tsig_log(msg->tsigkey, 2, - "signature failed to verify(1)"); - goto cleanup_context; -- } else if (ret != ISC_R_SUCCESS) -+ } else if (ret != ISC_R_SUCCESS) { - goto cleanup_context; -- -- dst_context_destroy(&ctx); -+ } - } else if (tsig.error != dns_tsigerror_badsig && - tsig.error != dns_tsigerror_badkey) { -- msg->tsigstatus = dns_tsigerror_badsig; - tsig_log(msg->tsigkey, 2, "signature was empty"); - return (DNS_R_TSIGVERIFYFAILURE); - } - -- msg->tsigstatus = dns_rcode_noerror; -+ /* -+ * Here at this point, the MAC has been verified. Even if any of -+ * the following code returns a TSIG error, the reply will be -+ * signed and WILL always include the request MAC in the digest -+ * computation. -+ */ -+ -+ /* -+ * Is the time ok? -+ */ -+ if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) { -+ msg->tsigstatus = dns_tsigerror_badtime; -+ tsig_log(msg->tsigkey, 2, "signature has expired"); -+ ret = DNS_R_CLOCKSKEW; -+ goto cleanup_context; -+ } else if (now + msg->timeadjust < tsig.timesigned - tsig.fudge) { -+ msg->tsigstatus = dns_tsigerror_badtime; -+ tsig_log(msg->tsigkey, 2, "signature is in the future"); -+ ret = DNS_R_CLOCKSKEW; -+ goto cleanup_context; -+ } -+ -+ if ( -+#ifndef PK11_MD5_DISABLE -+ alg == DST_ALG_HMACMD5 || -+#endif -+ alg == DST_ALG_HMACSHA1 || -+ alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 || -+ alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512) -+ { -+ isc_uint16_t digestbits = dst_key_getbits(key); -+ -+ /* -+ * XXXRAY: Is this correct? What is the expected -+ * behavior when digestbits is not an integral multiple -+ * of 8? It looks like bytes should either be -+ * (digestbits/8) or (digestbits+7)/8. -+ * -+ * In any case, for current algorithms, digestbits are -+ * an integral multiple of 8, so it has the same effect -+ * as (digestbits/8). -+ */ -+ if (tsig.siglen > 0 && digestbits != 0 && -+ tsig.siglen < ((digestbits + 1) / 8)) -+ { -+ msg->tsigstatus = dns_tsigerror_badtrunc; -+ tsig_log(msg->tsigkey, 2, -+ "truncated signature length too small"); -+ ret = DNS_R_TSIGVERIFYFAILURE; -+ goto cleanup_context; -+ } -+ if (tsig.siglen > 0 && digestbits == 0 && -+ tsig.siglen < siglen) -+ { -+ msg->tsigstatus = dns_tsigerror_badtrunc; -+ tsig_log(msg->tsigkey, 2, "signature length too small"); -+ ret = DNS_R_TSIGVERIFYFAILURE; -+ goto cleanup_context; -+ } -+ } - - if (tsig.error != dns_rcode_noerror) { -+ msg->tsigstatus = tsig.error; - if (tsig.error == dns_tsigerror_badtime) -- return (DNS_R_CLOCKSKEW); -+ ret = DNS_R_CLOCKSKEW; - else -- return (DNS_R_TSIGERRORSET); -+ ret = DNS_R_TSIGERRORSET; -+ goto cleanup_context; - } - -+ msg->tsigstatus = dns_rcode_noerror; - msg->verified_sig = 1; -- -- return (ISC_R_SUCCESS); -+ ret = ISC_R_SUCCESS; - - cleanup_context: - if (ctx != NULL) -@@ -1503,6 +1558,8 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { - isc_uint16_t addcount, id; - isc_boolean_t has_tsig = ISC_FALSE; - isc_mem_t *mctx; -+ unsigned int siglen; -+ unsigned int alg; - - REQUIRE(source != NULL); - REQUIRE(msg != NULL); -@@ -1510,12 +1567,16 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { - REQUIRE(msg->tcp_continuation == 1); - REQUIRE(msg->querytsig != NULL); - -+ msg->verified_sig = 0; -+ msg->tsigstatus = dns_tsigerror_badsig; -+ - if (!is_response(msg)) - return (DNS_R_EXPECTEDRESPONSE); - - mctx = msg->mctx; - - tsigkey = dns_message_gettsigkey(msg); -+ key = tsigkey->key; - - /* - * Extract and parse the previous TSIG -@@ -1548,7 +1609,8 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { - * Do the key name and algorithm match that of the query? - */ - if (!dns_name_equal(keyname, &tsigkey->name) || -- !dns_name_equal(&tsig.algorithm, &querytsig.algorithm)) { -+ !dns_name_equal(&tsig.algorithm, &querytsig.algorithm)) -+ { - msg->tsigstatus = dns_tsigerror_badkey; - ret = DNS_R_TSIGVERIFYFAILURE; - tsig_log(msg->tsigkey, 2, -@@ -1557,27 +1619,40 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { - } - - /* -- * Is the time ok? -+ * Check digest length. - */ -- isc_stdtime_get(&now); -- -- if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) { -- msg->tsigstatus = dns_tsigerror_badtime; -- tsig_log(msg->tsigkey, 2, "signature has expired"); -- ret = DNS_R_CLOCKSKEW; -- goto cleanup_querystruct; -- } else if (now + msg->timeadjust < -- tsig.timesigned - tsig.fudge) { -- msg->tsigstatus = dns_tsigerror_badtime; -- tsig_log(msg->tsigkey, 2, -- "signature is in the future"); -- ret = DNS_R_CLOCKSKEW; -+ alg = dst_key_alg(key); -+ ret = dst_key_sigsize(key, &siglen); -+ if (ret != ISC_R_SUCCESS) - goto cleanup_querystruct; -+ if ( -+#ifndef PK11_MD5_DISABLE -+ alg == DST_ALG_HMACMD5 || -+#endif -+ alg == DST_ALG_HMACSHA1 || -+ alg == DST_ALG_HMACSHA224 || -+ alg == DST_ALG_HMACSHA256 || -+ alg == DST_ALG_HMACSHA384 || -+ alg == DST_ALG_HMACSHA512) -+ { -+ if (tsig.siglen > siglen) { -+ tsig_log(tsigkey, 2, -+ "signature length too big"); -+ ret = DNS_R_FORMERR; -+ goto cleanup_querystruct; -+ } -+ if (tsig.siglen > 0 && -+ (tsig.siglen < 10 || -+ tsig.siglen < ((siglen + 1) / 2))) -+ { -+ tsig_log(tsigkey, 2, -+ "signature length below minimum"); -+ ret = DNS_R_FORMERR; -+ goto cleanup_querystruct; -+ } - } - } - -- key = tsigkey->key; -- - if (msg->tsigctx == NULL) { - ret = dst_context_create3(key, mctx, - DNS_LOGCATEGORY_DNSSEC, -@@ -1670,10 +1745,12 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { - sig_r.length = tsig.siglen; - if (tsig.siglen == 0) { - if (tsig.error != dns_rcode_noerror) { -- if (tsig.error == dns_tsigerror_badtime) -+ msg->tsigstatus = tsig.error; -+ if (tsig.error == dns_tsigerror_badtime) { - ret = DNS_R_CLOCKSKEW; -- else -+ } else { - ret = DNS_R_TSIGERRORSET; -+ } - } else { - tsig_log(msg->tsigkey, 2, - "signature is empty"); -@@ -1684,29 +1761,111 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { - - ret = dst_context_verify(msg->tsigctx, &sig_r); - if (ret == DST_R_VERIFYFAILURE) { -- msg->tsigstatus = dns_tsigerror_badsig; - tsig_log(msg->tsigkey, 2, - "signature failed to verify(2)"); - ret = DNS_R_TSIGVERIFYFAILURE; - goto cleanup_context; -+ } else if (ret != ISC_R_SUCCESS) { -+ goto cleanup_context; - } -- else if (ret != ISC_R_SUCCESS) -+ -+ /* -+ * Here at this point, the MAC has been verified. Even -+ * if any of the following code returns a TSIG error, -+ * the reply will be signed and WILL always include the -+ * request MAC in the digest computation. -+ */ -+ -+ /* -+ * Is the time ok? -+ */ -+ isc_stdtime_get(&now); -+ -+ if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) { -+ msg->tsigstatus = dns_tsigerror_badtime; -+ tsig_log(msg->tsigkey, 2, "signature has expired"); -+ ret = DNS_R_CLOCKSKEW; -+ goto cleanup_context; -+ } else if (now + msg->timeadjust < -+ tsig.timesigned - tsig.fudge) -+ { -+ msg->tsigstatus = dns_tsigerror_badtime; -+ tsig_log(msg->tsigkey, 2, -+ "signature is in the future"); -+ ret = DNS_R_CLOCKSKEW; - goto cleanup_context; -+ } - -- dst_context_destroy(&msg->tsigctx); -+ alg = dst_key_alg(key); -+ ret = dst_key_sigsize(key, &siglen); -+ if (ret != ISC_R_SUCCESS) -+ goto cleanup_context; -+ if ( -+#ifndef PK11_MD5_DISABLE -+ alg == DST_ALG_HMACMD5 || -+#endif -+ alg == DST_ALG_HMACSHA1 || -+ alg == DST_ALG_HMACSHA224 || -+ alg == DST_ALG_HMACSHA256 || -+ alg == DST_ALG_HMACSHA384 || -+ alg == DST_ALG_HMACSHA512) -+ { -+ isc_uint16_t digestbits = dst_key_getbits(key); -+ -+ /* -+ * XXXRAY: Is this correct? What is the -+ * expected behavior when digestbits is not an -+ * integral multiple of 8? It looks like bytes -+ * should either be (digestbits/8) or -+ * (digestbits+7)/8. -+ * -+ * In any case, for current algorithms, -+ * digestbits are an integral multiple of 8, so -+ * it has the same effect as (digestbits/8). -+ */ -+ if (tsig.siglen > 0 && digestbits != 0 && -+ tsig.siglen < ((digestbits + 1) / 8)) -+ { -+ msg->tsigstatus = dns_tsigerror_badtrunc; -+ tsig_log(msg->tsigkey, 2, -+ "truncated signature length " -+ "too small"); -+ ret = DNS_R_TSIGVERIFYFAILURE; -+ goto cleanup_context; -+ } -+ if (tsig.siglen > 0 && digestbits == 0 && -+ tsig.siglen < siglen) -+ { -+ msg->tsigstatus = dns_tsigerror_badtrunc; -+ tsig_log(msg->tsigkey, 2, -+ "signature length too small"); -+ ret = DNS_R_TSIGVERIFYFAILURE; -+ goto cleanup_context; -+ } -+ } -+ -+ if (tsig.error != dns_rcode_noerror) { -+ msg->tsigstatus = tsig.error; -+ if (tsig.error == dns_tsigerror_badtime) -+ ret = DNS_R_CLOCKSKEW; -+ else -+ ret = DNS_R_TSIGERRORSET; -+ goto cleanup_context; -+ } - } - - msg->tsigstatus = dns_rcode_noerror; -- return (ISC_R_SUCCESS); -+ msg->verified_sig = 1; -+ ret = ISC_R_SUCCESS; - - cleanup_context: -- dst_context_destroy(&msg->tsigctx); -+ if (msg->tsigctx != NULL) -+ dst_context_destroy(&msg->tsigctx); - - cleanup_querystruct: - dns_rdata_freestruct(&querytsig); - - return (ret); -- - } - - isc_result_t diff --git a/SOURCES/bind99-buildfix.patch b/SOURCES/bind99-buildfix.patch deleted file mode 100644 index 39d710f..0000000 --- a/SOURCES/bind99-buildfix.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -up bind-9.9.4b1/bin/tests/system/Makefile.in.buildfix bind-9.9.4b1/bin/tests/system/Makefile.in ---- bind-9.9.4b1/bin/tests/system/Makefile.in.buildfix 2013-07-15 11:02:23.354667876 +0200 -+++ bind-9.9.4b1/bin/tests/system/Makefile.in 2013-07-15 11:04:19.109587522 +0200 -@@ -21,7 +21,7 @@ top_srcdir = @top_srcdir@ - - @BIND9_MAKE_INCLUDES@ - --SUBDIRS = dlzexternal filter-aaaa lwresd rpz rrl \ -+SUBDIRS = filter-aaaa lwresd rpz rrl \ - rsabigexponent tkey tsiggss - TARGETS = - diff --git a/SOURCES/bind99-coverity-fixes2.patch b/SOURCES/bind99-coverity-fixes2.patch new file mode 100644 index 0000000..14dab6c --- /dev/null +++ b/SOURCES/bind99-coverity-fixes2.patch @@ -0,0 +1,44 @@ +From 1f3ac11cb4ecfab52f517ebf78493b0f05318be2 Mon Sep 17 00:00:00 2001 +From: Evan Hunt +Date: Mon, 16 Jun 2014 15:31:04 -0700 +Subject: [PATCH] [v9_9] null terminate strings for coverity + +--- + bin/dig/dig.c | 1 + + bin/tests/system/dlzexternal/driver.c | 6 ++++++ + 2 files changed, 7 insertions(+) + +diff --git a/bin/dig/dig.c b/bin/dig/dig.c +index 8a5fead..6af0964 100644 +--- a/bin/dig/dig.c ++++ b/bin/dig/dig.c +@@ -1453,6 +1453,7 @@ dash_option(char *option, char *next, dig_lookup_t **lookup, + ip6_int, ISC_FALSE) == ISC_R_SUCCESS) { + strncpy((*lookup)->textname, textname, + sizeof((*lookup)->textname)); ++ (*lookup)->textname[sizeof((*lookup)->textname)-1] = 0; + debug("looking up %s", (*lookup)->textname); + (*lookup)->trace_root = ISC_TF((*lookup)->trace || + (*lookup)->ns_search_only); +diff --git a/bin/tests/system/dlzexternal/driver.c b/bin/tests/system/dlzexternal/driver.c +index 053c25a..f99ac14 100644 +--- a/bin/tests/system/dlzexternal/driver.c ++++ b/bin/tests/system/dlzexternal/driver.c +@@ -133,8 +133,14 @@ add_name(struct dlz_example_data *state, struct record *list, + return (ISC_R_NOSPACE); + + strncpy(list[i].name, name, sizeof(list[i].name)); ++ list[i].name[sizeof(list[i].name) - 1] = '\0'; ++ + strncpy(list[i].type, type, sizeof(list[i].type)); ++ list[i].type[sizeof(list[i].type) - 1] = '\0'; ++ + strncpy(list[i].data, data, sizeof(list[i].data)); ++ list[i].data[sizeof(list[i].data) - 1] = '\0'; ++ + list[i].ttl = ttl; + + return (ISC_R_SUCCESS); +-- +2.9.3 + diff --git a/SOURCES/bind99-dyndb.patch b/SOURCES/bind99-dyndb.patch new file mode 100644 index 0000000..a021ef8 --- /dev/null +++ b/SOURCES/bind99-dyndb.patch @@ -0,0 +1,5176 @@ +From a86e8e75d0ac3266756df18575e16baff7743ccd Mon Sep 17 00:00:00 2001 +From: Evan Hunt +Date: Mon, 28 Sep 2015 23:12:35 -0700 +Subject: [PATCH] merge dyndb +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +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] + +(cherry picked from commit a00f9e2f50675bd43cc6a9fe2669709162a2ccb4) + +Make backport compilable + +add missing libraries + +(cherry picked from commit ac6bb3dd36149bc51e0367eba7c50e15dc076c9b) + +(cherry picked from commit ab8b419a797fae25f441273aca3ec18d8d0c1106) + +address linking issues + +(cherry picked from commit 1a0e5b0504576a17a99817d9eef10c4937ef0d63) + +silence compiler warnings + +(cherry picked from commit 0d990f57aefcb3a2e82a91367fc600ccf69eea63) + +remove deadcode; move NULL assignment arlier + +(cherry picked from commit 30f8d5e386a283c7e3a24683b78e489881c16c34) + +Updated WIN32 files (rt40877) +Use only differences in dyndb files, do not update win32 projects + +(cherry picked from commit 343aeac7176d28c4a1b9d246b1f7311b4cd5da7d) + +remove unnecessary return + +(cherry picked from commit 7f79448198139145cebc2540188b16b1861b98c5) + +add missing dependancy + +(cherry picked from commit 97e9fc9e53039c141e1a14adab0865a04225848a) + +4386.[bug]Remove shadowed overmem function/variable. [RT #42706] + +(cherry picked from commit 96beefd76f597b77d4fcd51f8d766e5e59a2d216) + +update dyndb_init inline documentationi [RT #43050] + +(cherry picked from commit 8c2c6b8b42766c8221c79bd43680dbfbaed17147) + +[master] fix dyndb issues; isc_errno_toresult() + +4445. [cleanup] isc_errno_toresult() can now be used to call the + formerly private function isc__errno2result(). + [RT #43050] + +4444. [bug] Fixed some issues related to dyndb: A bug caused + braces to be omitted when passing configuration text + from named.conf to a dyndb driver, and there was a + use-after-free in the sample dyndb driver. [RT #43050] + +Patch for dyndb driver submitted by Petr Spacek at Red Hat. + +(cherry picked from commit 3390d74e33385337631b19e68760025e0ca5d6ec) + +[master] pass source file and line to dyndb load function + +4455. [cleanup] Allow dyndb modules to correctly log the filename + and line number when processing configuration text + from named.conf. [RT #43050] + +(cherry picked from commit 02fb764681d145e4607c59280a48617013e886ac) + +install isc/errno.h + +(cherry picked from commit dec17fb66215d0b02ff9a5810658cdcd0215d240) + +4493. [bug] bin/tests/system/dyndb/driver/Makefile.in should use + SO_TARGETS. [RT# 43336] + +(cherry picked from commit c910fc24ce2aad5fa9e9a2d304f818fd8e996e6f) + +Include dyndb in tests building + +(picked by hand from master commit 93c211afc97e7a072c12ef346581065e4065ff15) + +Do not test type of a pointer + +Skip DEEPBIND - works only with shared library, but works. And fix dyndb test + +Backported to 9.9.4 + +Include commandline.c in export libraries + +Signed-off-by: Petr Menšík +--- + COPYRIGHT | 17 +- + bin/named/Makefile.in | 3 +- + bin/named/main.c | 1 + + bin/named/server.c | 68 ++- + bin/tests/Makefile.in | 2 - + bin/tests/system/Makefile.in | 2 +- + bin/tests/system/checkconf/good.conf | 9 + + bin/tests/system/conf.sh.in | 4 +- + bin/tests/system/dlzexternal/tests.sh | 2 - + bin/tests/system/dyndb/Makefile.in | 26 + + bin/tests/system/dyndb/clean.sh | 25 + + bin/tests/system/dyndb/driver/.gitignore | 1 + + bin/tests/system/dyndb/driver/AUTHORS | 8 + + bin/tests/system/dyndb/driver/COPYING | 15 + + bin/tests/system/dyndb/driver/Makefile.in | 60 +++ + bin/tests/system/dyndb/driver/README | 65 +++ + bin/tests/system/dyndb/driver/db.c | 848 ++++++++++++++++++++++++++++++ + bin/tests/system/dyndb/driver/db.h | 15 + + bin/tests/system/dyndb/driver/driver.c | 143 +++++ + bin/tests/system/dyndb/driver/instance.c | 161 ++++++ + bin/tests/system/dyndb/driver/instance.h | 47 ++ + bin/tests/system/dyndb/driver/lock.c | 56 ++ + bin/tests/system/dyndb/driver/lock.h | 17 + + bin/tests/system/dyndb/driver/log.c | 21 + + bin/tests/system/dyndb/driver/log.h | 27 + + bin/tests/system/dyndb/driver/syncptr.c | 265 ++++++++++ + bin/tests/system/dyndb/driver/syncptr.h | 15 + + bin/tests/system/dyndb/driver/util.h | 57 ++ + bin/tests/system/dyndb/driver/zone.c | 192 +++++++ + bin/tests/system/dyndb/driver/zone.h | 15 + + bin/tests/system/dyndb/ns1/named.conf | 42 ++ + bin/tests/system/dyndb/prereq.sh | 21 + + bin/tests/system/dyndb/tests.sh | 155 ++++++ + configure | 7 +- + configure.in | 3 + + doc/arm/Bv9ARM-book.xml | 2 + + doc/arm/dyndb.xml | 105 ++++ + lib/dns/Makefile.in | 8 +- + lib/dns/dlz.c | 64 +-- + lib/dns/dyndb.c | 486 +++++++++++++++++ + lib/dns/include/dns/Makefile.in | 4 +- + lib/dns/include/dns/dyndb.h | 166 ++++++ + lib/dns/include/dns/log.h | 1 + + lib/dns/include/dns/types.h | 1 + + lib/dns/lib.c | 4 +- + lib/dns/log.c | 1 + + lib/dns/win32/libdns.def | 4 + + lib/export/isc/Makefile.in | 6 +- + lib/isc/Makefile.in | 8 +- + lib/isc/commandline.c | 60 +++ + lib/isc/hash.c | 28 +- + lib/isc/include/isc/Makefile.in | 4 +- + lib/isc/include/isc/commandline.h | 18 +- + lib/isc/include/isc/errno.h | 25 + + lib/isc/include/isc/hash.h | 4 +- + lib/isc/include/isc/lex.h | 21 +- + lib/isc/lex.c | 110 +++- + lib/isc/tests/Makefile.in | 11 +- + lib/isc/tests/errno_test.c | 102 ++++ + lib/isc/unix/Makefile.in | 8 +- + lib/isc/unix/errno.c | 21 + + lib/isc/unix/errno2result.c | 14 +- + lib/isc/unix/errno2result.h | 7 +- + lib/isc/win32/Makefile.in | 8 +- + lib/isc/win32/errno.c | 18 + + lib/isc/win32/errno2result.c | 14 +- + lib/isc/win32/errno2result.h | 5 +- + lib/isc/win32/libisc.def | 2 + + lib/isc/win32/libisc.dsp | 8 + + lib/isc/win32/libisc.mak | 23 + + lib/isc/win32/socket.c | 4 +- + lib/isccfg/include/isccfg/grammar.h | 1 + + lib/isccfg/namedconf.c | 18 + + lib/isccfg/parser.c | 46 ++ + 74 files changed, 3703 insertions(+), 152 deletions(-) + create mode 100644 bin/tests/system/dyndb/Makefile.in + create mode 100644 bin/tests/system/dyndb/clean.sh + create mode 100644 bin/tests/system/dyndb/driver/.gitignore + create mode 100644 bin/tests/system/dyndb/driver/AUTHORS + create mode 100644 bin/tests/system/dyndb/driver/COPYING + create mode 100644 bin/tests/system/dyndb/driver/Makefile.in + create mode 100644 bin/tests/system/dyndb/driver/README + create mode 100644 bin/tests/system/dyndb/driver/db.c + create mode 100644 bin/tests/system/dyndb/driver/db.h + create mode 100644 bin/tests/system/dyndb/driver/driver.c + create mode 100644 bin/tests/system/dyndb/driver/instance.c + create mode 100644 bin/tests/system/dyndb/driver/instance.h + create mode 100644 bin/tests/system/dyndb/driver/lock.c + create mode 100644 bin/tests/system/dyndb/driver/lock.h + create mode 100644 bin/tests/system/dyndb/driver/log.c + create mode 100644 bin/tests/system/dyndb/driver/log.h + create mode 100644 bin/tests/system/dyndb/driver/syncptr.c + create mode 100644 bin/tests/system/dyndb/driver/syncptr.h + create mode 100644 bin/tests/system/dyndb/driver/util.h + create mode 100644 bin/tests/system/dyndb/driver/zone.c + create mode 100644 bin/tests/system/dyndb/driver/zone.h + create mode 100644 bin/tests/system/dyndb/ns1/named.conf + create mode 100644 bin/tests/system/dyndb/prereq.sh + create mode 100644 bin/tests/system/dyndb/tests.sh + create mode 100644 doc/arm/dyndb.xml + create mode 100644 lib/dns/dyndb.c + create mode 100644 lib/dns/include/dns/dyndb.h + create mode 100644 lib/isc/include/isc/errno.h + create mode 100644 lib/isc/tests/errno_test.c + create mode 100644 lib/isc/unix/errno.c + create mode 100644 lib/isc/win32/errno.c + +diff --git a/COPYRIGHT b/COPYRIGHT +index 525c222..137db13 100644 +--- a/COPYRIGHT ++++ b/COPYRIGHT +@@ -161,7 +161,7 @@ POSSIBILITY OF SUCH DAMAGE. + + ----------------------------------------------------------------------------- + +-Copyright (c) 1997 - 2003 Kungliga Tekniska H�gskolan ++Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + (Royal Institute of Technology, Stockholm, Sweden). + All rights reserved. + +@@ -516,3 +516,18 @@ 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. +diff --git a/bin/named/Makefile.in b/bin/named/Makefile.in +index cd65777..8ec9ad7 100644 +--- a/bin/named/Makefile.in ++++ b/bin/named/Makefile.in +@@ -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@ +@@ -138,6 +136,7 @@ config.@O@: config.c bind.keys.h + ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \ + -DVERSION=\"${VERSION}\" \ + -DSRCID=\"${SRCID}\" \ ++ -DDYNDB_LIBDIR=\"@libdir@/bind\" \ + -DNS_LOCALSTATEDIR=\"${localstatedir}\" \ + -DNS_SYSCONFDIR=\"${sysconfdir}\" \ + -c ${srcdir}/config.c +diff --git a/bin/named/main.c b/bin/named/main.c +index 6e12847..d26783f 100644 +--- a/bin/named/main.c ++++ b/bin/named/main.c +@@ -45,6 +45,7 @@ + #include + + #include ++#include + #include + #include + #include +diff --git a/bin/named/server.c b/bin/named/server.c +index daa5b0e..6260f8f 100644 +--- a/bin/named/server.c ++++ b/bin/named/server.c +@@ -30,6 +30,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -64,6 +65,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1243,6 +1245,33 @@ configure_peer(const cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) { + } + + 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), ++ cfg_obj_file(obj), cfg_obj_line(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; + const cfg_obj_t *algorithms; +@@ -2058,6 +2087,7 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, + 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; + const cfg_listelt_t *element; +@@ -2097,6 +2127,7 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, + unsigned int query_timeout, ndisp; + struct cfg_context *nzctx; + dns_rpz_zone_t *rpz; ++ dns_dyndbctx_t *dctx = NULL; + + REQUIRE(DNS_VIEW_VALID(view)); + +@@ -2317,7 +2348,8 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, + 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; +@@ -3261,6 +3293,31 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, + 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. + */ +@@ -3445,6 +3502,8 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, + + if (cache != NULL) + dns_cache_detach(&cache); ++ if (dctx != NULL) ++ dns_dyndb_destroyctx(&dctx); + + return (result); + } +@@ -4915,6 +4974,11 @@ load_configuration(const char *filename, ns_server_t *server, + 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. + */ + if (first_time) { +@@ -6043,6 +6107,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); +diff --git a/bin/tests/Makefile.in b/bin/tests/Makefile.in +index 2020bf4..8477ae5 100644 +--- a/bin/tests/Makefile.in ++++ b/bin/tests/Makefile.in +@@ -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@ +diff --git a/bin/tests/system/Makefile.in b/bin/tests/system/Makefile.in +index f7bcc26..af8b82c 100644 +--- a/bin/tests/system/Makefile.in ++++ b/bin/tests/system/Makefile.in +@@ -21,7 +21,7 @@ top_srcdir = @top_srcdir@ + + @BIND9_MAKE_INCLUDES@ + +-SUBDIRS = dlzexternal filter-aaaa lwresd rpz rrl \ ++SUBDIRS = dlzexternal dyndb filter-aaaa lwresd rpz rrl \ + rsabigexponent tkey tsiggss + TARGETS = + +diff --git a/bin/tests/system/checkconf/good.conf b/bin/tests/system/checkconf/good.conf +index 5444fdd..a6310cd 100644 +--- a/bin/tests/system/checkconf/good.conf ++++ b/bin/tests/system/checkconf/good.conf +@@ -104,3 +104,12 @@ view "second" { + dnssec-validation auto; + zone-statistics full; + }; ++dyndb "name" "library.so" { ++ this; ++ \}; ++ is a { ++ "test" { \{ of; the; }; ++ } bracketed; ++ "text \""; ++ system; ++}; +diff --git a/bin/tests/system/conf.sh.in b/bin/tests/system/conf.sh.in +index c40e8f1..eb02236 100644 +--- a/bin/tests/system/conf.sh.in ++++ b/bin/tests/system/conf.sh.in +@@ -60,8 +60,8 @@ SAMPLE=$TOP/lib/export/samples/sample + # v6synth + SUBDIRS="acl additional allow_query addzone autosign builtin + cacheclean checkconf @CHECKDS@ checknames checkzone @COVERAGE@ +- database dlv dlvauto dlz dlzexternal dname dns64 dnssec ecdsa +- formerr forward glue gost ixfr inline limits logfileconfig ++ database dlv dlvauto dlz dlzexternal dname dns64 dnssec dyndb ++ ecdsa formerr forward glue gost ixfr inline limits logfileconfig + lwresd masterfile masterformat metadata notify nsupdate pending + @PKCS11_TEST@ redirect resolver rndc rpz rrl rrsetorder rsabigexponent + smartsign sortlist spf staticstub stub tkey tsig tsiggss unknown +diff --git a/bin/tests/system/dlzexternal/tests.sh b/bin/tests/system/dlzexternal/tests.sh +index bd2eeac..103d4c9 100644 +--- a/bin/tests/system/dlzexternal/tests.sh ++++ b/bin/tests/system/dlzexternal/tests.sh +@@ -1,6 +1,4 @@ + #!/bin/sh +-# tests for TSIG-GSS updates +- + SYSTEMTESTTOP=.. + . $SYSTEMTESTTOP/conf.sh + +diff --git a/bin/tests/system/dyndb/Makefile.in b/bin/tests/system/dyndb/Makefile.in +new file mode 100644 +index 0000000..c7792f2 +--- /dev/null ++++ b/bin/tests/system/dyndb/Makefile.in +@@ -0,0 +1,26 @@ ++# 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@ +diff --git a/bin/tests/system/dyndb/clean.sh b/bin/tests/system/dyndb/clean.sh +new file mode 100644 +index 0000000..2273396 +--- /dev/null ++++ b/bin/tests/system/dyndb/clean.sh +@@ -0,0 +1,25 @@ ++#!/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.* +diff --git a/bin/tests/system/dyndb/driver/.gitignore b/bin/tests/system/dyndb/driver/.gitignore +new file mode 100644 +index 0000000..c3af857 +--- /dev/null ++++ b/bin/tests/system/dyndb/driver/.gitignore +@@ -0,0 +1 @@ ++lib/ +diff --git a/bin/tests/system/dyndb/driver/AUTHORS b/bin/tests/system/dyndb/driver/AUTHORS +new file mode 100644 +index 0000000..acc109c +--- /dev/null ++++ b/bin/tests/system/dyndb/driver/AUTHORS +@@ -0,0 +1,8 @@ ++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 ++Jiri Kuncar ++Martin Nagy ++Petr Spacek +diff --git a/bin/tests/system/dyndb/driver/COPYING b/bin/tests/system/dyndb/driver/COPYING +new file mode 100644 +index 0000000..08d4d77 +--- /dev/null ++++ b/bin/tests/system/dyndb/driver/COPYING +@@ -0,0 +1,15 @@ ++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. +diff --git a/bin/tests/system/dyndb/driver/Makefile.in b/bin/tests/system/dyndb/driver/Makefile.in +new file mode 100644 +index 0000000..e23c563 +--- /dev/null ++++ b/bin/tests/system/dyndb/driver/Makefile.in +@@ -0,0 +1,60 @@ ++# 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@ ++ ++SO_TARGETS = lib/sample.@SO@ ++TARGETS = @SO_TARGETS@ ++ ++@BIND9_MAKE_RULES@ ++ ++CFLAGS = @CFLAGS@ @SO_CFLAGS@ ++SO_LDFLAGS = @LDFLAGS@ ++ ++lib/sample.@SO@: sample.@SO@ ++ $(SHELL) ${top_srcdir}/mkinstalldirs `pwd`/lib ++ ${LIBTOOL_MODE_INSTALL} ${INSTALL} sample.@SO@ `pwd`/lib ++ ++sample.@SO@: ${OBJS} ${DNSDEPLIBS} ${ISCDEPLIBS} ++ ${LIBTOOL_MODE_LINK} @SO_LD@ ${SO_LDFLAGS} -o $@ ${OBJS} \ ++ ${DNSLIBS} ${ISCLIBS} @DNS_CRYPTO_LIBS@ ${LIBS} ++ ++clean distclean:: ++ rm -f ${OBJS} sample.so lib/sample.so +diff --git a/bin/tests/system/dyndb/driver/README b/bin/tests/system/dyndb/driver/README +new file mode 100644 +index 0000000..9aac0a6 +--- /dev/null ++++ b/bin/tests/system/dyndb/driver/README +@@ -0,0 +1,65 @@ ++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. +diff --git a/bin/tests/system/dyndb/driver/db.c b/bin/tests/system/dyndb/driver/db.c +new file mode 100644 +index 0000000..d2ca023 +--- /dev/null ++++ b/bin/tests/system/dyndb/driver/db.c +@@ -0,0 +1,848 @@ ++/* ++ * Database API implementation. The interface is defined in lib/dns/db.h. ++ * ++ * dns_db_*() calls on database instances backed by this driver use ++ * struct sampledb_methods to find appropriate function implementation. ++ * ++ * This example re-uses RBT DB implementation from original BIND and blindly ++ * proxies most of dns_db_*() calls to this underlying RBT DB. ++ * See struct sampledb below. ++ * ++ * Copyright (C) 2009-2015 Red Hat ; see COPYRIGHT for license ++ */ ++#include ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "db.h" ++#include "instance.h" ++#include "syncptr.h" ++#include "util.h" ++ ++#define SAMPLEDB_MAGIC ISC_MAGIC('S', 'M', 'D', 'B') ++#define VALID_SAMPLEDB(sampledb) \ ++ ((sampledb) != NULL && (sampledb)->common.impmagic == SAMPLEDB_MAGIC) ++ ++struct sampledb { ++ dns_db_t common; ++ isc_refcount_t refs; ++ sample_instance_t *inst; ++ ++ /* ++ * Internal RBT database implementation provided by BIND. ++ * Most dns_db_* calls (find(), createiterator(), etc.) ++ * are blindly forwarded to this RBT DB. ++ */ ++ dns_db_t *rbtdb; ++}; ++ ++typedef struct sampledb sampledb_t; ++ ++/* ++ * Get full DNS name from the node. ++ * ++ * @warning ++ * The code silently expects that "node" came from RBTDB and thus ++ * assumption dns_dbnode_t (from RBTDB) == dns_rbtnode_t is correct. ++ * ++ * This should work as long as we use only RBTDB and nothing else. ++ */ ++static isc_result_t ++sample_name_fromnode(dns_dbnode_t *node, dns_name_t *name) { ++ dns_rbtnode_t *rbtnode = (dns_rbtnode_t *) node; ++ return (dns_rbt_fullnamefromnode(rbtnode, name)); ++} ++ ++static void ++attach(dns_db_t *source, dns_db_t **targetp) { ++ sampledb_t *sampledb = (sampledb_t *)source; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ isc_refcount_increment(&sampledb->refs, NULL); ++ *targetp = source; ++} ++ ++static void ++free_sampledb(sampledb_t *sampledb) { ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ dns_db_detach(&sampledb->rbtdb); ++ dns_name_free(&sampledb->common.origin, sampledb->common.mctx); ++ isc_mem_putanddetach(&sampledb->common.mctx, sampledb, sizeof(*sampledb)); ++} ++ ++static void ++detach(dns_db_t **dbp) { ++ sampledb_t *sampledb = (sampledb_t *)(*dbp); ++ unsigned int refs; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ isc_refcount_decrement(&sampledb->refs, &refs); ++ if (refs == 0) ++ free_sampledb(sampledb); ++ *dbp = NULL; ++} ++ ++/* ++ * This method should never be called, because DB is "persistent". ++ * See ispersistent() function. It means that database do not need to be ++ * loaded in the usual sense. ++ */ ++static isc_result_t ++beginload(dns_db_t *db, dns_addrdatasetfunc_t *addp, dns_dbload_t **dbloadp) { ++ UNUSED(db); ++ UNUSED(addp); ++ UNUSED(dbloadp); ++ ++ fatal_error("current implementation should never call beginload()"); ++ ++ /* Not reached */ ++ return (ISC_R_SUCCESS); ++} ++ ++/* ++ * This method should never be called, because DB is "persistent". ++ * See ispersistent() function. It means that database do not need to be ++ * loaded in the usual sense. ++ */ ++static isc_result_t ++endload(dns_db_t *db, dns_dbload_t **dbloadp) { ++ UNUSED(db); ++ UNUSED(dbloadp); ++ ++ fatal_error("current implementation should never call endload()"); ++ ++ /* Not reached */ ++ return (ISC_R_SUCCESS); ++} ++ ++#if 0 ++static isc_result_t ++serialize(dns_db_t *db, dns_dbversion_t *version, FILE *file) { ++ sampledb_t *sampledb = (sampledb_t *) db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ return (dns_db_serialize(sampledb->rbtdb, version, file)); ++} ++#endif ++ ++static isc_result_t ++dump(dns_db_t *db, dns_dbversion_t *version, const char *filename, ++ dns_masterformat_t masterformat) ++{ ++ ++ UNUSED(db); ++ UNUSED(version); ++ UNUSED(filename); ++ UNUSED(masterformat); ++ ++ fatal_error("current implementation should never call dump()"); ++ ++ /* Not reached */ ++ return (ISC_R_SUCCESS); ++} ++ ++static void ++currentversion(dns_db_t *db, dns_dbversion_t **versionp) { ++ sampledb_t *sampledb = (sampledb_t *)db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ dns_db_currentversion(sampledb->rbtdb, versionp); ++} ++ ++static isc_result_t ++newversion(dns_db_t *db, dns_dbversion_t **versionp) { ++ sampledb_t *sampledb = (sampledb_t *)db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ return (dns_db_newversion(sampledb->rbtdb, versionp)); ++} ++ ++static void ++attachversion(dns_db_t *db, dns_dbversion_t *source, ++ dns_dbversion_t **targetp) ++{ ++ sampledb_t *sampledb = (sampledb_t *)db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ dns_db_attachversion(sampledb->rbtdb, source, targetp); ++} ++ ++static void ++closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) { ++ sampledb_t *sampledb = (sampledb_t *)db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ dns_db_closeversion(sampledb->rbtdb, versionp, commit); ++} ++ ++static isc_result_t ++findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, ++ dns_dbnode_t **nodep) ++{ ++ sampledb_t *sampledb = (sampledb_t *) db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ return (dns_db_findnode(sampledb->rbtdb, name, create, nodep)); ++} ++ ++static isc_result_t ++find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, ++ dns_rdatatype_t type, unsigned int options, isc_stdtime_t now, ++ dns_dbnode_t **nodep, dns_name_t *foundname, dns_rdataset_t *rdataset, ++ dns_rdataset_t *sigrdataset) ++{ ++ sampledb_t *sampledb = (sampledb_t *) db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ return (dns_db_find(sampledb->rbtdb, name, version, type, ++ options, now, nodep, foundname, ++ rdataset, sigrdataset)); ++} ++ ++static isc_result_t ++findzonecut(dns_db_t *db, dns_name_t *name, unsigned int options, ++ isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname, ++ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) ++{ ++ sampledb_t *sampledb = (sampledb_t *) db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ return (dns_db_findzonecut(sampledb->rbtdb, name, options, ++ now, nodep, foundname, rdataset, ++ sigrdataset)); ++} ++ ++static void ++attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) { ++ sampledb_t *sampledb = (sampledb_t *) db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ dns_db_attachnode(sampledb->rbtdb, source, targetp); ++ ++} ++ ++static void ++detachnode(dns_db_t *db, dns_dbnode_t **targetp) { ++ sampledb_t *sampledb = (sampledb_t *) db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ dns_db_detachnode(sampledb->rbtdb, targetp); ++} ++ ++static isc_result_t ++expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) { ++ sampledb_t *sampledb = (sampledb_t *) db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ return (dns_db_expirenode(sampledb->rbtdb, node, now)); ++} ++ ++static void ++printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) { ++ sampledb_t *sampledb = (sampledb_t *) db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ dns_db_printnode(sampledb->rbtdb, node, out); ++} ++ ++static isc_result_t ++createiterator(dns_db_t *db, unsigned int options, ++ dns_dbiterator_t **iteratorp) ++{ ++ sampledb_t *sampledb = (sampledb_t *) db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ return (dns_db_createiterator(sampledb->rbtdb, options, iteratorp)); ++} ++ ++static isc_result_t ++findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, ++ dns_rdatatype_t type, dns_rdatatype_t covers, isc_stdtime_t now, ++ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) ++{ ++ sampledb_t *sampledb = (sampledb_t *) db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ return (dns_db_findrdataset(sampledb->rbtdb, node, version, type, ++ covers, now, rdataset, sigrdataset)); ++} ++ ++static isc_result_t ++allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, ++ isc_stdtime_t now, dns_rdatasetiter_t **iteratorp) ++{ ++ sampledb_t *sampledb = (sampledb_t *) db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ return (dns_db_allrdatasets(sampledb->rbtdb, node, version, ++ now, iteratorp)); ++} ++ ++static isc_result_t ++addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, ++ isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options, ++ dns_rdataset_t *addedrdataset) ++{ ++ sampledb_t *sampledb = (sampledb_t *) db; ++ isc_result_t result; ++ dns_fixedname_t name; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ dns_fixedname_init(&name); ++ CHECK(dns_db_addrdataset(sampledb->rbtdb, node, version, now, ++ rdataset, options, addedrdataset)); ++ if (rdataset->type == dns_rdatatype_a || ++ rdataset->type == dns_rdatatype_aaaa) { ++ CHECK(sample_name_fromnode(node, dns_fixedname_name(&name))); ++ CHECK(syncptrs(sampledb->inst, dns_fixedname_name(&name), ++ rdataset, DNS_DIFFOP_ADD)); ++ } ++ ++cleanup: ++ return (result); ++} ++ ++static isc_result_t ++subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, ++ dns_rdataset_t *rdataset, unsigned int options, ++ dns_rdataset_t *newrdataset) ++{ ++ sampledb_t *sampledb = (sampledb_t *) db; ++ isc_result_t result; ++ dns_fixedname_t name; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ dns_fixedname_init(&name); ++ result = dns_db_subtractrdataset(sampledb->rbtdb, node, version, ++ rdataset, options, newrdataset); ++ if (result != ISC_R_SUCCESS && result != DNS_R_NXRRSET) ++ goto cleanup; ++ ++ if (rdataset->type == dns_rdatatype_a || ++ rdataset->type == dns_rdatatype_aaaa) { ++ CHECK(sample_name_fromnode(node, dns_fixedname_name(&name))); ++ CHECK(syncptrs(sampledb->inst, dns_fixedname_name(&name), ++ rdataset, DNS_DIFFOP_DEL)); ++ } ++ ++cleanup: ++ return (result); ++} ++ ++/* ++ * deleterdataset() function is not used during DNS update processing so syncptr ++ * implementation is left as an exercise to the reader. ++ */ ++static isc_result_t ++deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, ++ dns_rdatatype_t type, dns_rdatatype_t covers) ++{ ++ sampledb_t *sampledb = (sampledb_t *) db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ return (dns_db_deleterdataset(sampledb->rbtdb, node, version, ++ type, covers)); ++} ++ ++static isc_boolean_t ++issecure(dns_db_t *db) { ++ sampledb_t *sampledb = (sampledb_t *) db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ return (dns_db_issecure(sampledb->rbtdb)); ++} ++ ++static unsigned int ++nodecount(dns_db_t *db) { ++ sampledb_t *sampledb = (sampledb_t *) db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ return (dns_db_nodecount(sampledb->rbtdb)); ++} ++ ++/* ++ * The database does not need to be loaded from disk or written to disk. ++ * Always return ISC_TRUE. ++ */ ++static isc_boolean_t ++ispersistent(dns_db_t *db) { ++ UNUSED(db); ++ ++ return (ISC_TRUE); ++} ++ ++static void ++overmem(dns_db_t *db, isc_boolean_t over) { ++ sampledb_t *sampledb = (sampledb_t *) db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ dns_db_overmem(sampledb->rbtdb, over); ++} ++ ++static void ++settask(dns_db_t *db, isc_task_t *task) { ++ sampledb_t *sampledb = (sampledb_t *) db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ dns_db_settask(sampledb->rbtdb, task); ++} ++ ++static isc_result_t ++getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) { ++ sampledb_t *sampledb = (sampledb_t *) db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ return (dns_db_getoriginnode(sampledb->rbtdb, nodep)); ++} ++ ++static void ++transfernode(dns_db_t *db, dns_dbnode_t **sourcep, dns_dbnode_t **targetp) { ++ sampledb_t *sampledb = (sampledb_t *) db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ dns_db_transfernode(sampledb->rbtdb, sourcep, targetp); ++ ++} ++ ++static isc_result_t ++getnsec3parameters(dns_db_t *db, dns_dbversion_t *version, ++ dns_hash_t *hash, isc_uint8_t *flags, ++ isc_uint16_t *iterations, ++ unsigned char *salt, size_t *salt_length) ++{ ++ sampledb_t *sampledb = (sampledb_t *) db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ return (dns_db_getnsec3parameters(sampledb->rbtdb, version, ++ hash, flags, iterations, ++ salt, salt_length)); ++ ++} ++ ++static isc_result_t ++findnsec3node(dns_db_t *db, dns_name_t *name, isc_boolean_t create, ++ dns_dbnode_t **nodep) ++{ ++ sampledb_t *sampledb = (sampledb_t *) db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ return (dns_db_findnsec3node(sampledb->rbtdb, name, create, nodep)); ++} ++ ++static isc_result_t ++setsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, isc_stdtime_t resign) ++{ ++ sampledb_t *sampledb = (sampledb_t *) db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ return (dns_db_setsigningtime(sampledb->rbtdb, rdataset, resign)); ++} ++ ++static isc_result_t ++getsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, dns_name_t *name) ++{ ++ sampledb_t *sampledb = (sampledb_t *) db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ return (dns_db_getsigningtime(sampledb->rbtdb, rdataset, name)); ++} ++ ++static void ++resigned(dns_db_t *db, dns_rdataset_t *rdataset, dns_dbversion_t *version) { ++ sampledb_t *sampledb = (sampledb_t *) db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ dns_db_resigned(sampledb->rbtdb, rdataset, version); ++} ++ ++static isc_boolean_t ++isdnssec(dns_db_t *db) { ++ sampledb_t *sampledb = (sampledb_t *) db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ return (dns_db_isdnssec(sampledb->rbtdb)); ++} ++ ++static dns_stats_t * ++getrrsetstats(dns_db_t *db) { ++ sampledb_t *sampledb = (sampledb_t *) db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ return (dns_db_getrrsetstats(sampledb->rbtdb)); ++ ++} ++ ++static isc_result_t ++rpz_enabled(dns_db_t *db, dns_rpz_st_t *st) { ++ sampledb_t *sampledb = (sampledb_t *) db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ return dns_db_rpz_enabled(sampledb->rbtdb, st); ++} ++ ++static void ++rpz_findips(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type, ++ dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version, ++ dns_rdataset_t *ardataset, dns_rpz_st_t *st, ++ dns_name_t *query_qname) { ++ sampledb_t *sampledb = (sampledb_t *) db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ dns_db_rpz_findips(rpz, rpz_type, zone, db, version, ardataset, st, query_qname); ++} ++ ++#if 0 ++static void ++rpz_attach(dns_db_t *db, dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num) { ++ sampledb_t *sampledb = (sampledb_t *) db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ dns_db_rpz_attach(sampledb->rbtdb, rpzs, rpz_num); ++} ++ ++static isc_result_t ++rpz_ready(dns_db_t *db) { ++ sampledb_t *sampledb = (sampledb_t *) db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ return (dns_db_rpz_ready(sampledb->rbtdb)); ++} ++#endif ++ ++static isc_result_t ++findnodeext(dns_db_t *db, dns_name_t *name, ++ isc_boolean_t create, dns_clientinfomethods_t *methods, ++ dns_clientinfo_t *clientinfo, dns_dbnode_t **nodep) ++{ ++ sampledb_t *sampledb = (sampledb_t *) db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ return (dns_db_findnodeext(sampledb->rbtdb, name, create, ++ methods, clientinfo, nodep)); ++} ++ ++static isc_result_t ++findext(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, ++ dns_rdatatype_t type, unsigned int options, isc_stdtime_t now, ++ dns_dbnode_t **nodep, dns_name_t *foundname, ++ dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo, ++ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) ++{ ++ sampledb_t *sampledb = (sampledb_t *) db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ return (dns_db_findext(sampledb->rbtdb, name, version, type, ++ options, now, nodep, foundname, methods, ++ clientinfo, rdataset, sigrdataset)); ++} ++ ++#if 0 ++static isc_result_t ++setcachestats(dns_db_t *db, isc_stats_t *stats) { ++ sampledb_t *sampledb = (sampledb_t *) db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ return (dns_db_setcachestats(sampledb->rbtdb, stats)); ++} ++ ++static unsigned int ++hashsize(dns_db_t *db) { ++ sampledb_t *sampledb = (sampledb_t *) db; ++ ++ REQUIRE(VALID_SAMPLEDB(sampledb)); ++ ++ return (dns_db_hashsize(sampledb->rbtdb)); ++} ++#endif ++ ++/* ++ * DB interface definition. Database driver uses this structure to ++ * determine which implementation of dns_db_*() function to call. ++ */ ++static dns_dbmethods_t sampledb_methods = { ++ attach, ++ detach, ++ beginload, ++ endload, ++// serialize, ++ dump, ++ currentversion, ++ newversion, ++ attachversion, ++ closeversion, ++ findnode, ++ find, ++ findzonecut, ++ attachnode, ++ detachnode, ++ expirenode, ++ printnode, ++ createiterator, ++ findrdataset, ++ allrdatasets, ++ addrdataset, ++ subtractrdataset, ++ deleterdataset, ++ issecure, ++ nodecount, ++ ispersistent, ++ overmem, ++ settask, ++ getoriginnode, ++ transfernode, ++ getnsec3parameters, ++ findnsec3node, ++ setsigningtime, ++ getsigningtime, ++ resigned, ++ isdnssec, ++ getrrsetstats, ++ rpz_enabled, ++ rpz_findips, ++ findnodeext, ++ findext, ++#if 0 ++ setcachestats, ++ hashsize ++#endif ++}; ++ ++/* Auxiliary driver functions. */ ++ ++/* ++ * Auxiliary functions add_*() create minimal database which can be loaded. ++ * This is necessary because this driver create empty 'fake' zone which ++ * is not loaded from disk so there is no way for user to supply SOA, NS and A ++ * records. ++ * ++ * Following functions were copied from BIND 9.10.2rc1 named/server.c, ++ * credit goes to ISC. ++ */ ++static isc_result_t ++add_soa(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name, ++ dns_name_t *origin, dns_name_t *contact) ++{ ++ dns_dbnode_t *node = NULL; ++ dns_rdata_t rdata = DNS_RDATA_INIT; ++ dns_rdatalist_t rdatalist; ++ dns_rdataset_t rdataset; ++ isc_result_t result; ++ unsigned char buf[DNS_SOA_BUFFERSIZE]; ++ ++ dns_rdataset_init(&rdataset); ++ dns_rdatalist_init(&rdatalist); ++ CHECK(dns_soa_buildrdata(origin, contact, dns_db_class(db), ++ 0, 28800, 7200, 604800, 86400, buf, &rdata)); ++ rdatalist.type = rdata.type; ++ rdatalist.covers = 0; ++ rdatalist.rdclass = rdata.rdclass; ++ rdatalist.ttl = 86400; ++ ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); ++ CHECK(dns_rdatalist_tordataset(&rdatalist, &rdataset)); ++ CHECK(dns_db_findnode(db, name, ISC_TRUE, &node)); ++ CHECK(dns_db_addrdataset(db, node, version, 0, &rdataset, 0, NULL)); ++ cleanup: ++ if (node != NULL) ++ dns_db_detachnode(db, &node); ++ return (result); ++} ++ ++ ++static isc_result_t ++add_ns(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name, ++ dns_name_t *nsname) ++{ ++ dns_dbnode_t *node = NULL; ++ dns_rdata_ns_t ns; ++ dns_rdata_t rdata = DNS_RDATA_INIT; ++ dns_rdatalist_t rdatalist; ++ dns_rdataset_t rdataset; ++ isc_result_t result; ++ isc_buffer_t b; ++ unsigned char buf[DNS_NAME_MAXWIRE]; ++ ++ isc_buffer_init(&b, buf, sizeof(buf)); ++ ++ dns_rdataset_init(&rdataset); ++ dns_rdatalist_init(&rdatalist); ++ ns.common.rdtype = dns_rdatatype_ns; ++ ns.common.rdclass = dns_db_class(db); ++ ns.mctx = NULL; ++ dns_name_init(&ns.name, NULL); ++ dns_name_clone(nsname, &ns.name); ++ CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db), dns_rdatatype_ns, ++ &ns, &b)); ++ rdatalist.type = rdata.type; ++ rdatalist.covers = 0; ++ rdatalist.rdclass = rdata.rdclass; ++ rdatalist.ttl = 86400; ++ ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); ++ CHECK(dns_rdatalist_tordataset(&rdatalist, &rdataset)); ++ CHECK(dns_db_findnode(db, name, ISC_TRUE, &node)); ++ CHECK(dns_db_addrdataset(db, node, version, 0, &rdataset, 0, NULL)); ++ cleanup: ++ if (node != NULL) ++ dns_db_detachnode(db, &node); ++ return (result); ++} ++ ++static isc_result_t ++add_a(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name, ++ struct in_addr addr) ++{ ++ dns_dbnode_t *node = NULL; ++ dns_rdata_in_a_t a; ++ dns_rdata_t rdata = DNS_RDATA_INIT; ++ dns_rdatalist_t rdatalist; ++ dns_rdataset_t rdataset; ++ isc_result_t result; ++ isc_buffer_t b; ++ unsigned char buf[DNS_NAME_MAXWIRE]; ++ ++ isc_buffer_init(&b, buf, sizeof(buf)); ++ ++ dns_rdataset_init(&rdataset); ++ dns_rdatalist_init(&rdatalist); ++ a.common.rdtype = dns_rdatatype_a; ++ a.common.rdclass = dns_db_class(db); ++ a.in_addr = addr; ++ CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db), dns_rdatatype_a, ++ &a, &b)); ++ rdatalist.type = rdata.type; ++ rdatalist.covers = 0; ++ rdatalist.rdclass = rdata.rdclass; ++ rdatalist.ttl = 86400; ++ ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); ++ CHECK(dns_rdatalist_tordataset(&rdatalist, &rdataset)); ++ CHECK(dns_db_findnode(db, name, ISC_TRUE, &node)); ++ CHECK(dns_db_addrdataset(db, node, version, 0, &rdataset, 0, NULL)); ++ cleanup: ++ if (node != NULL) ++ dns_db_detachnode(db, &node); ++ return (result); ++} ++ ++/* ++ * Driver-specific implementation of dns_db_create(). ++ * ++ * @param[in] argv Database-specific parameters from dns_db_create(). ++ * @param[in] driverarg Driver-specific parameter from dns_db_register(). ++ */ ++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) ++{ ++ sampledb_t *sampledb = NULL; ++ isc_result_t result; ++ dns_dbversion_t *version = NULL; ++ struct in_addr a_addr; ++ ++ REQUIRE(type == dns_dbtype_zone); ++ REQUIRE(rdclass == dns_rdataclass_in); ++ REQUIRE(argc == 0); ++ REQUIRE(argv != NULL); ++ REQUIRE(driverarg != NULL); /* pointer to driver instance */ ++ REQUIRE(dbp != NULL && *dbp == NULL); ++ ++ UNUSED(driverarg); /* no driver-specific configuration */ ++ ++ a_addr.s_addr = 0x0100007fU; ++ ++ CHECKED_MEM_GET_PTR(mctx, sampledb); ++ ZERO_PTR(sampledb); ++ ++ isc_mem_attach(mctx, &sampledb->common.mctx); ++ dns_name_init(&sampledb->common.origin, NULL); ++ isc_ondestroy_init(&sampledb->common.ondest); ++ ++ sampledb->common.magic = DNS_DB_MAGIC; ++ sampledb->common.impmagic = SAMPLEDB_MAGIC; ++ ++ sampledb->common.methods = &sampledb_methods; ++ sampledb->common.attributes = 0; ++ sampledb->common.rdclass = rdclass; ++ ++ CHECK(dns_name_dupwithoffsets(origin, mctx, &sampledb->common.origin)); ++ ++ CHECK(isc_refcount_init(&sampledb->refs, 1)); ++ ++ /* Translate instance name to instance pointer. */ ++ sampledb->inst = driverarg; ++ ++ /* Create internal instance of RBT DB implementation from BIND. */ ++ CHECK(dns_db_create(mctx, "rbt", origin, dns_dbtype_zone, ++ dns_rdataclass_in, 0, NULL, &sampledb->rbtdb)); ++ ++ /* Create fake SOA, NS, and A records to make database loadable. */ ++ CHECK(dns_db_newversion(sampledb->rbtdb, &version)); ++ CHECK(add_soa(sampledb->rbtdb, version, origin, origin, origin)); ++ CHECK(add_ns(sampledb->rbtdb, version, origin, origin)); ++ CHECK(add_a(sampledb->rbtdb, version, origin, a_addr)); ++ dns_db_closeversion(sampledb->rbtdb, &version, ISC_TRUE); ++ ++ *dbp = (dns_db_t *)sampledb; ++ ++ return (ISC_R_SUCCESS); ++ ++cleanup: ++ if (sampledb != NULL) { ++ if (dns_name_dynamic(&sampledb->common.origin)) ++ dns_name_free(&sampledb->common.origin, mctx); ++ ++ isc_mem_putanddetach(&sampledb->common.mctx, sampledb, ++ sizeof(*sampledb)); ++ } ++ ++ return (result); ++} +diff --git a/bin/tests/system/dyndb/driver/db.h b/bin/tests/system/dyndb/driver/db.h +new file mode 100644 +index 0000000..80693a7 +--- /dev/null ++++ b/bin/tests/system/dyndb/driver/db.h +@@ -0,0 +1,15 @@ ++/** ++ * 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_ */ +diff --git a/bin/tests/system/dyndb/driver/driver.c b/bin/tests/system/dyndb/driver/driver.c +new file mode 100644 +index 0000000..11e6743 +--- /dev/null ++++ b/bin/tests/system/dyndb/driver/driver.c +@@ -0,0 +1,143 @@ ++/* ++ * 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 {} 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 ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#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] parameters User-defined parameters from dyndb section as one ++ * string. The example above will have ++ * params = "param1 param2"; ++ * @param[in] file The name of the file from which the parameters ++ * were read. ++ * @param[in] line The line number from which the parameters were read. ++ * @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 char *file, unsigned long line, ++ 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_lctx) { ++ 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; ++ ++ log_write(ISC_LOG_DEBUG(9), ++ "loading params for dyndb '%s' from %s:%lu", ++ name, file, line); ++ ++ /* 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); ++} +diff --git a/bin/tests/system/dyndb/driver/instance.c b/bin/tests/system/dyndb/driver/instance.c +new file mode 100644 +index 0000000..f2207b9 +--- /dev/null ++++ b/bin/tests/system/dyndb/driver/instance.c +@@ -0,0 +1,161 @@ ++/* ++ * 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 ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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, ++ dns_name_t *z1, dns_name_t *z2) ++{ ++ isc_result_t result; ++ int i; ++ ++ REQUIRE(argv != NULL); ++ REQUIRE(z1 != NULL); ++ REQUIRE(z2 != NULL); ++ ++ for (i = 0; i < argc; i++) { ++ log_info("param: '%s'", argv[i]); ++ } ++ log_info("number of params: %d", i); ++ ++ if (argc != 2) { ++ log_error("exactly two parameters " ++ "(absolute zone names) are required"); ++ result = ISC_R_FAILURE; ++ goto cleanup; ++ } ++ CHECK(dns_name_fromstring2(z1, argv[0], dns_rootname, 0, mctx)); ++ CHECK(dns_name_fromstring2(z2, argv[1], dns_rootname, 0, mctx)); ++ ++ result = ISC_R_SUCCESS; ++ ++cleanup: ++ return (result); ++} ++ ++/* ++ * Initialize new driver instance. It will not create zones until ++ * load_sample_instance_zones() is called. ++ */ ++isc_result_t ++new_sample_instance(isc_mem_t *mctx, const char *db_name, ++ int argc, char **argv, const dns_dyndbctx_t *dctx, ++ sample_instance_t **sample_instp) ++{ ++ isc_result_t result; ++ sample_instance_t *inst = NULL; ++ ++ REQUIRE(sample_instp != NULL && *sample_instp == NULL); ++ ++ CHECKED_MEM_GET_PTR(mctx, inst); ++ ZERO_PTR(inst); ++ isc_mem_attach(mctx, &inst->mctx); ++ ++ inst->db_name = isc_mem_strdup(mctx, db_name); ++ if (inst->db_name == NULL) { ++ result = ISC_R_NOMEMORY; ++ goto cleanup; ++ } ++ ++ dns_fixedname_init(&inst->zone1_fn); ++ inst->zone1_name = dns_fixedname_name(&inst->zone1_fn); ++ ++ dns_fixedname_init(&inst->zone2_fn); ++ inst->zone2_name = dns_fixedname_name(&inst->zone2_fn); ++ ++ CHECK(parse_params(mctx, argc, argv, ++ inst->zone1_name, inst->zone2_name)); ++ ++ dns_view_attach(dctx->view, &inst->view); ++ dns_zonemgr_attach(dctx->zmgr, &inst->zmgr); ++ isc_task_attach(dctx->task, &inst->task); ++ ++ /* Register new DNS DB implementation. */ ++ CHECK(dns_db_register(db_name, create_db, inst, mctx, &inst->db_imp)); ++ ++ *sample_instp = inst; ++ result = ISC_R_SUCCESS; ++ ++cleanup: ++ if (result != ISC_R_SUCCESS) ++ destroy_sample_instance(&inst); ++ return (result); ++} ++ ++/* ++ * Create empty zones, add fake SOA, NS, and A records, load fake zones ++ * and add them to inst->view. ++ */ ++isc_result_t ++load_sample_instance_zones(sample_instance_t *inst) { ++ isc_result_t result; ++ ++ CHECK(create_zone(inst, inst->zone1_name, &inst->zone1)); ++ CHECK(activate_zone(inst, inst->zone1)); ++ ++ CHECK(create_zone(inst, inst->zone2_name, &inst->zone2)); ++ CHECK(activate_zone(inst, inst->zone2)); ++ ++cleanup: ++ return (result); ++} ++ ++void ++destroy_sample_instance(sample_instance_t **instp) { ++ sample_instance_t *inst; ++ REQUIRE(instp != NULL); ++ ++ inst = *instp; ++ if (inst == NULL) ++ return; ++ ++ if (inst->db_name != NULL) ++ isc_mem_free(inst->mctx, inst->db_name); ++ if (inst->zone1 != NULL) ++ dns_zone_detach(&inst->zone1); ++ if (inst->zone2 != NULL) ++ dns_zone_detach(&inst->zone2); ++ if (inst->db_imp != NULL) ++ dns_db_unregister(&inst->db_imp); ++ ++ dns_view_detach(&inst->view); ++ dns_zonemgr_detach(&inst->zmgr); ++ isc_task_detach(&inst->task); ++ ++ MEM_PUT_AND_DETACH(inst); ++ ++ *instp = NULL; ++} +diff --git a/bin/tests/system/dyndb/driver/instance.h b/bin/tests/system/dyndb/driver/instance.h +new file mode 100644 +index 0000000..ff0f5c3 +--- /dev/null ++++ b/bin/tests/system/dyndb/driver/instance.h +@@ -0,0 +1,47 @@ ++/** ++ * Driver instance object. ++ * ++ * Copyright (C) 2009-2015 Red Hat ; see COPYRIGHT for license ++ */ ++ ++#ifndef _LD_INSTANCE_H_ ++#define _LD_INSTANCE_H_ ++ ++#include ++#include ++#include ++ ++struct sample_instance { ++ isc_mem_t *mctx; ++ char *db_name; ++ dns_dbimplementation_t *db_imp; ++ ++ /* These are needed for zone creation. */ ++ dns_view_t *view; ++ dns_zonemgr_t *zmgr; ++ isc_task_t *task; ++ isc_boolean_t exiting; ++ ++ dns_zone_t *zone1; ++ dns_fixedname_t zone1_fn; ++ dns_name_t *zone1_name; ++ ++ dns_zone_t *zone2; ++ dns_fixedname_t zone2_fn; ++ dns_name_t *zone2_name; ++}; ++ ++typedef struct sample_instance sample_instance_t; ++ ++isc_result_t ++new_sample_instance(isc_mem_t *mctx, const char *db_name, ++ int argc, char **argv, const dns_dyndbctx_t *dctx, ++ sample_instance_t **sample_instp); ++ ++isc_result_t ++load_sample_instance_zones(sample_instance_t *inst); ++ ++void ++destroy_sample_instance(sample_instance_t **sample_instp); ++ ++#endif /* !_LD_INSTANCE_H_ */ +diff --git a/bin/tests/system/dyndb/driver/lock.c b/bin/tests/system/dyndb/driver/lock.c +new file mode 100644 +index 0000000..c97c490 +--- /dev/null ++++ b/bin/tests/system/dyndb/driver/lock.c +@@ -0,0 +1,56 @@ ++/* ++ * Copyright (C) 2014-2015 Red Hat ; see COPYRIGHT for license ++ */ ++ ++#include ++ ++#include ++#include ++ ++#include "lock.h" ++ ++/* ++ * Lock BIND dispatcher and allow only single task to run. ++ * ++ * @warning ++ * All calls to isc_task_beginexclusive() have to operate on the same task ++ * otherwise it would not be possible to distinguish recursive locking ++ * from real conflict on the dispatcher lock. ++ * For this reason this wrapper function always works with inst->task. ++ * As a result, this function have to be be called only from inst->task. ++ * ++ * Recursive locking is allowed. Auxiliary variable pointed to by "statep" ++ * stores information if last run_exclusive_enter() operation really locked ++ * something or if the lock was called recursively and was no-op. ++ * ++ * The pair (inst, state) used for run_exclusive_enter() has to be ++ * used for run_exclusive_exit(). ++ * ++ * @param[in] inst The instance with the only task which is allowed to run. ++ * @param[in,out] statep Lock state: ISC_R_SUCCESS or ISC_R_LOCKBUSY ++ */ ++void ++run_exclusive_enter(sample_instance_t *inst, isc_result_t *statep) { ++ REQUIRE(statep != NULL); ++ REQUIRE(*statep == ISC_R_IGNORE); ++ ++ *statep = isc_task_beginexclusive(inst->task); ++ RUNTIME_CHECK(*statep == ISC_R_SUCCESS || *statep == ISC_R_LOCKBUSY); ++} ++ ++/* ++ * Exit task-exclusive mode. ++ * ++ * @param[in] inst The instance used for previous run_exclusive_enter() call. ++ * @param[in] state Lock state as returned by run_exclusive_enter(). ++ */ ++void ++run_exclusive_exit(sample_instance_t *inst, isc_result_t state) { ++ if (state == ISC_R_SUCCESS) ++ isc_task_endexclusive(inst->task); ++ else ++ /* Unlocking recursive lock or the lock was never locked. */ ++ INSIST(state == ISC_R_LOCKBUSY || state == ISC_R_IGNORE); ++ ++ return; ++} +diff --git a/bin/tests/system/dyndb/driver/lock.h b/bin/tests/system/dyndb/driver/lock.h +new file mode 100644 +index 0000000..35c9c84 +--- /dev/null ++++ b/bin/tests/system/dyndb/driver/lock.h +@@ -0,0 +1,17 @@ ++/* ++ * Copyright (C) 2014-2015 Red Hat ; see COPYRIGHT for license ++ */ ++ ++#ifndef LOCK_H_ ++#define LOCK_H_ ++ ++#include "instance.h" ++#include "util.h" ++ ++void ++run_exclusive_enter(sample_instance_t *inst, isc_result_t *statep); ++ ++void ++run_exclusive_exit(sample_instance_t *inst, isc_result_t state); ++ ++#endif /* LOCK_H_ */ +diff --git a/bin/tests/system/dyndb/driver/log.c b/bin/tests/system/dyndb/driver/log.c +new file mode 100644 +index 0000000..2238c7e +--- /dev/null ++++ b/bin/tests/system/dyndb/driver/log.c +@@ -0,0 +1,21 @@ ++/* ++ * Copyright (C) 2009-2015 Red Hat ; see COPYRIGHT for license ++ */ ++ ++#include ++ ++#include ++ ++#include ++ ++#include "log.h" ++ ++void ++log_write(int level, const char *format, ...) { ++ va_list args; ++ ++ va_start(args, format); ++ isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DYNDB, ++ level, format, args); ++ va_end(args); ++} +diff --git a/bin/tests/system/dyndb/driver/log.h b/bin/tests/system/dyndb/driver/log.h +new file mode 100644 +index 0000000..27b38c8 +--- /dev/null ++++ b/bin/tests/system/dyndb/driver/log.h +@@ -0,0 +1,27 @@ ++/* ++ * Copyright (C) 2009--2015 Red Hat ; see COPYRIGHT for license ++ */ ++ ++#ifndef _LD_LOG_H_ ++#define _LD_LOG_H_ ++ ++#include ++#include ++#include ++ ++#define fatal_error(...) \ ++ isc_error_fatal(__FILE__, __LINE__, __VA_ARGS__) ++ ++#define log_error_r(fmt, ...) \ ++ log_error(fmt ": %s", ##__VA_ARGS__, dns_result_totext(result)) ++ ++#define log_error(format, ...) \ ++ log_write(ISC_LOG_ERROR, format, ##__VA_ARGS__) ++ ++#define log_info(format, ...) \ ++ log_write(ISC_LOG_INFO, format, ##__VA_ARGS__) ++ ++void ++log_write(int level, const char *format, ...) ISC_FORMAT_PRINTF(2, 3); ++ ++#endif /* !_LD_LOG_H_ */ +diff --git a/bin/tests/system/dyndb/driver/syncptr.c b/bin/tests/system/dyndb/driver/syncptr.c +new file mode 100644 +index 0000000..2191bae +--- /dev/null ++++ b/bin/tests/system/dyndb/driver/syncptr.c +@@ -0,0 +1,265 @@ ++/* ++ * Automatic A/AAAA/PTR record synchronization. ++ * ++ * Copyright (C) 2009-2015 Red Hat ; see COPYRIGHT for license ++ */ ++ ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "instance.h" ++#include "syncptr.h" ++#include "util.h" ++ ++/* Almost random value. See eventclass.h */ ++#define SYNCPTR_WRITE_EVENT (ISC_EVENTCLASS(1025) + 1) ++ ++/* ++ * Event used for making changes to reverse zones. ++ */ ++typedef struct syncptrevent syncptrevent_t; ++struct syncptrevent { ++ ISC_EVENT_COMMON(syncptrevent_t); ++ isc_mem_t *mctx; ++ dns_zone_t *zone; ++ dns_diff_t diff; ++ dns_fixedname_t ptr_target_name; /* referenced by owner name in tuple */ ++ isc_buffer_t b; /* referenced by target name in tuple */ ++ unsigned char buf[DNS_NAME_MAXWIRE]; ++}; ++ ++/* ++ * Write diff generated in syncptr() to reverse zone. ++ * ++ * This function will be called asynchronously and syncptr() will not get ++ * any result from it. ++ * ++ */ ++static void ++syncptr_write(isc_task_t *task, isc_event_t *event) { ++ syncptrevent_t *pevent = (syncptrevent_t *)event; ++ dns_dbversion_t *version = NULL; ++ dns_db_t *db = NULL; ++ isc_result_t result; ++ ++ REQUIRE(event->ev_type == SYNCPTR_WRITE_EVENT); ++ ++ UNUSED(task); ++ ++ CHECK(dns_zone_getdb(pevent->zone, &db)); ++ CHECK(dns_db_newversion(db, &version)); ++ CHECK(dns_diff_apply(&pevent->diff, db, version)); ++ ++cleanup: ++ if (db != NULL) { ++ if (version != NULL) ++ dns_db_closeversion(db, &version, ISC_TRUE); ++ dns_db_detach(&db); ++ } ++ dns_zone_detach(&pevent->zone); ++ dns_diff_clear(&pevent->diff); ++ isc_event_free(&event); ++} ++ ++/* ++ * Find a reverse zone for given IP address. ++ * ++ * @param[in] rdata IP address as A/AAAA record ++ * @param[out] name Owner name for the PTR record ++ * @param[out] zone DNS zone for reverse record matching the IP address ++ * ++ * @retval ISC_R_SUCCESS DNS name derived from given IP address belongs to an ++ * reverse zone managed by this driver instance. ++ * PTR record synchronization can continue. ++ * @retval ISC_R_NOTFOUND Suitable reverse zone was not found because it ++ * does not exist or is not managed by this driver. ++ */ ++static isc_result_t ++syncptr_find_zone(sample_instance_t *inst, dns_rdata_t *rdata, ++ dns_name_t *name, dns_zone_t **zone) ++{ ++ isc_result_t result; ++ isc_netaddr_t isc_ip; /* internal net address representation */ ++ dns_rdata_in_a_t ipv4; ++ dns_rdata_in_aaaa_t ipv6; ++ ++ REQUIRE(inst != NULL); ++ REQUIRE(zone != NULL && *zone == NULL); ++ ++ switch (rdata->type) { ++ case dns_rdatatype_a: ++ CHECK(dns_rdata_tostruct(rdata, &ipv4, inst->mctx)); ++ isc_netaddr_fromin(&isc_ip, &ipv4.in_addr); ++ break; ++ ++ case dns_rdatatype_aaaa: ++ CHECK(dns_rdata_tostruct(rdata, &ipv6, inst->mctx)); ++ isc_netaddr_fromin6(&isc_ip, &ipv6.in6_addr); ++ break; ++ ++ default: ++ fatal_error("unsupported address type 0x%x", rdata->type); ++ break; ++ } ++ ++ /* ++ * Convert IP address to PTR owner name. ++ * ++ * @example ++ * 192.168.0.1 -> 1.0.168.192.in-addr.arpa ++ */ ++ CHECK(dns_byaddr_createptrname2(&isc_ip, 0, name)); ++ ++ /* Find a zone containing owner name of the PTR record. */ ++ result = dns_zt_find(inst->view->zonetable, name, 0, NULL, zone); ++ if (result == DNS_R_PARTIALMATCH) ++ result = ISC_R_SUCCESS; ++ else if (result != ISC_R_SUCCESS) ++ goto cleanup; ++ ++ /* Make sure that the zone is managed by this driver. */ ++ if (*zone != inst->zone1 && *zone != inst->zone2) { ++ dns_zone_detach(zone); ++ result = ISC_R_NOTFOUND; ++ } ++ ++cleanup: ++ if (rdata->type == dns_rdatatype_a) ++ dns_rdata_freestruct(&ipv4); ++ else ++ dns_rdata_freestruct(&ipv6); ++ ++ return (result); ++} ++ ++/* ++ * Generate update event for PTR record to reflect change in A/AAAA record. ++ * ++ * @pre Reverse zone is managed by this driver. ++ * ++ * @param[in] a_name DNS domain of modified A/AAAA record ++ * @param[in] af Address family ++ * @param[in] ip_str IP address as a string (IPv4 or IPv6) ++ * @param[in] mod_op LDAP_MOD_DELETE if A/AAAA record is being deleted ++ * or LDAP_MOD_ADD if A/AAAA record is being added. ++ * ++ * @retval ISC_R_SUCCESS Event for PTR record update was generated and send. ++ * Change to reverse zone will be done asynchronously. ++ * @retval other Synchronization failed - reverse doesn't exist, ++ * is not managed by this driver instance, ++ * memory allocation error, etc. ++ */ ++static isc_result_t ++syncptr(sample_instance_t *inst, dns_name_t *name, ++ dns_rdata_t *addr_rdata, dns_ttl_t ttl, dns_diffop_t op) ++{ ++ isc_result_t result; ++ isc_mem_t *mctx = inst->mctx; ++ dns_fixedname_t ptr_name; ++ dns_zone_t *ptr_zone = NULL; ++ dns_rdata_ptr_t ptr_struct; ++ dns_rdata_t ptr_rdata = DNS_RDATA_INIT; ++ dns_difftuple_t *tp = NULL; ++ isc_task_t *task = NULL; ++ syncptrevent_t *pevent = NULL; ++ ++ dns_fixedname_init(&ptr_name); ++ DNS_RDATACOMMON_INIT(&ptr_struct, dns_rdatatype_ptr, dns_rdataclass_in); ++ dns_name_init(&ptr_struct.ptr, NULL); ++ ++ pevent = (syncptrevent_t *)isc_event_allocate(inst->mctx, inst, ++ SYNCPTR_WRITE_EVENT, ++ syncptr_write, NULL, ++ sizeof(syncptrevent_t)); ++ if (pevent == NULL) { ++ result = ISC_R_NOMEMORY; ++ goto cleanup; ++ } ++ isc_buffer_init(&pevent->b, pevent->buf, sizeof(pevent->buf)); ++ dns_fixedname_init(&pevent->ptr_target_name); ++ ++ /* Check if reverse zone is managed by this driver */ ++ result = syncptr_find_zone(inst, addr_rdata, ++ dns_fixedname_name(&ptr_name), &ptr_zone); ++ if (result != ISC_R_SUCCESS) { ++ log_error_r("PTR record synchonization skipped: reverse zone " ++ "is not managed by driver instance '%s'", ++ inst->db_name); ++ goto cleanup; ++ } ++ ++ /* Reverse zone is managed by this driver, prepare PTR record */ ++ pevent->zone = NULL; ++ dns_zone_attach(ptr_zone, &pevent->zone); ++ CHECK(dns_name_copy(name, dns_fixedname_name(&pevent->ptr_target_name), ++ NULL)); ++ dns_name_clone(dns_fixedname_name(&pevent->ptr_target_name), ++ &ptr_struct.ptr); ++ dns_diff_init(inst->mctx, &pevent->diff); ++ CHECK(dns_rdata_fromstruct(&ptr_rdata, dns_rdataclass_in, ++ dns_rdatatype_ptr, &ptr_struct, &pevent->b)); ++ ++ /* Create diff */ ++ CHECK(dns_difftuple_create(mctx, op, dns_fixedname_name(&ptr_name), ++ ttl, &ptr_rdata, &tp)); ++ dns_diff_append(&pevent->diff, &tp); ++ ++ /* ++ * Send update event to the reverse zone. ++ * It will be processed asynchronously. ++ */ ++ dns_zone_gettask(ptr_zone, &task); ++ isc_task_send(task, (isc_event_t **)&pevent); ++ ++cleanup: ++ if (ptr_zone != NULL) ++ dns_zone_detach(&ptr_zone); ++ if (tp != NULL) ++ dns_difftuple_free(&tp); ++ if (task != NULL) ++ isc_task_detach(&task); ++ if (pevent != NULL) ++ isc_event_free((isc_event_t **)&pevent); ++ ++ return (result); ++} ++ ++/* ++ * Generate update event for every rdata in rdataset. ++ * ++ * @param[in] name Owner name for A/AAAA records in rdataset. ++ * @param[in] rdataset A/AAAA records. ++ * @param[in] op DNS_DIFFOP_ADD / DNS_DIFFOP_DEL for adding / deleting ++ * the rdata ++ */ ++isc_result_t ++syncptrs(sample_instance_t *inst, dns_name_t *name, ++ dns_rdataset_t *rdataset, dns_diffop_t op) ++{ ++ isc_result_t result; ++ dns_rdata_t rdata = DNS_RDATA_INIT; ++ ++ for (result = dns_rdataset_first(rdataset); ++ result == ISC_R_SUCCESS; ++ result = dns_rdataset_next(rdataset)) { ++ dns_rdataset_current(rdataset, &rdata); ++ result = syncptr(inst, name, &rdata, rdataset->ttl, op); ++ if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) ++ goto cleanup; ++ } ++ if (result == ISC_R_NOMORE) ++ result = ISC_R_SUCCESS; ++ ++cleanup: ++ return (result); ++} +diff --git a/bin/tests/system/dyndb/driver/syncptr.h b/bin/tests/system/dyndb/driver/syncptr.h +new file mode 100644 +index 0000000..2f9b3a6 +--- /dev/null ++++ b/bin/tests/system/dyndb/driver/syncptr.h +@@ -0,0 +1,15 @@ ++/* ++ * Sync PTR records ++ * ++ * Copyright (C) 2014-2015 Red Hat ; see COPYRIGHT for license ++ */ ++ ++#ifndef SYNCPTR_H_ ++#define SYNCPTR_H_ ++ ++#include ++isc_result_t ++syncptrs(sample_instance_t *inst, dns_name_t *name, dns_rdataset_t *rdataset, ++ dns_diffop_t op); ++ ++#endif /* SYNCPTR_H_ */ +diff --git a/bin/tests/system/dyndb/driver/util.h b/bin/tests/system/dyndb/driver/util.h +new file mode 100644 +index 0000000..2a00fe3 +--- /dev/null ++++ b/bin/tests/system/dyndb/driver/util.h +@@ -0,0 +1,57 @@ ++/* ++ * Memory allocation and error handling utilities. ++ * ++ * Copyright (C) 2009-2015 Red Hat ; see COPYRIGHT for license ++ */ ++ ++#ifndef _LD_UTIL_H_ ++#define _LD_UTIL_H_ ++ ++#include ++#include ++ ++#include "log.h" ++ ++#define CLEANUP_WITH(result_code) \ ++ do { \ ++ result = (result_code); \ ++ goto cleanup; \ ++ } while(0) ++ ++#define CHECK(op) \ ++ do { \ ++ result = (op); \ ++ if (result != ISC_R_SUCCESS) \ ++ goto cleanup; \ ++ } while (0) ++ ++#define CHECKED_MEM_GET(m, target_ptr, s) \ ++ do { \ ++ (target_ptr) = isc_mem_get((m), (s)); \ ++ if ((target_ptr) == NULL) { \ ++ result = ISC_R_NOMEMORY; \ ++ log_error("Memory allocation failed"); \ ++ goto cleanup; \ ++ } \ ++ } while (0) ++ ++#define CHECKED_MEM_GET_PTR(m, target_ptr) \ ++ CHECKED_MEM_GET(m, target_ptr, sizeof(*(target_ptr))) ++ ++#define CHECKED_MEM_STRDUP(m, source, target) \ ++ do { \ ++ (target) = isc_mem_strdup((m), (source)); \ ++ if ((target) == NULL) { \ ++ result = ISC_R_NOMEMORY; \ ++ log_error("Memory allocation failed"); \ ++ goto cleanup; \ ++ } \ ++ } while (0) ++ ++#define ZERO_PTR(ptr) memset((ptr), 0, sizeof(*(ptr))) ++ ++#define MEM_PUT_AND_DETACH(target_ptr) \ ++ isc_mem_putanddetach(&(target_ptr)->mctx, target_ptr, \ ++ sizeof(*(target_ptr))) ++ ++#endif /* !_LD_UTIL_H_ */ +diff --git a/bin/tests/system/dyndb/driver/zone.c b/bin/tests/system/dyndb/driver/zone.c +new file mode 100644 +index 0000000..88bd967 +--- /dev/null ++++ b/bin/tests/system/dyndb/driver/zone.c +@@ -0,0 +1,192 @@ ++/* ++ * Zone management. ++ * ++ * Copyright (C) 2009-2015 Red Hat ; see COPYRIGHT for license ++ */ ++ ++#include ++ ++#include ++ ++#include ++#include ++#include ++ ++#include "util.h" ++#include "instance.h" ++#include "lock.h" ++#include "log.h" ++#include "zone.h" ++ ++extern const char *impname; ++ ++/* ++ * Create a new zone with origin 'name'. The zone stay invisible to clients ++ * until it is explicitly added to a view. ++ */ ++isc_result_t ++create_zone(sample_instance_t * const inst, dns_name_t * const name, ++ dns_zone_t ** const rawp) ++{ ++ isc_result_t result; ++ dns_zone_t *raw = NULL; ++ const char *zone_argv[1]; ++ char zone_name[DNS_NAME_FORMATSIZE]; ++ dns_acl_t *acl_any = NULL; ++ ++ REQUIRE(inst != NULL); ++ REQUIRE(name != NULL); ++ REQUIRE(rawp != NULL && *rawp == NULL); ++ ++ zone_argv[0] = inst->db_name; ++ ++ log_info("debug isc_mem_debugging(%p)=%X", &isc_mem_debugging, isc_mem_debugging); ++ CHECK(dns_zone_create(&raw, inst->mctx)); ++ CHECK(dns_zone_setorigin(raw, name)); ++ dns_zone_setclass(raw, dns_rdataclass_in); ++ dns_zone_settype(raw, dns_zone_master); ++ CHECK(dns_zone_setdbtype(raw, 1, zone_argv)); ++ CHECK(dns_zonemgr_managezone(inst->zmgr, raw)); ++ ++ /* This is completely insecure - use some sensible values instead! */ ++ CHECK(dns_acl_any(inst->mctx, &acl_any)); ++ dns_zone_setupdateacl(raw, acl_any); ++ dns_zone_setqueryacl(raw, acl_any); ++ dns_zone_setxfracl(raw, acl_any); ++ dns_acl_detach(&acl_any); ++ ++ *rawp = raw; ++ return (ISC_R_SUCCESS); ++ ++cleanup: ++ dns_name_format(name, zone_name, DNS_NAME_FORMATSIZE); ++ log_error_r("failed to create new zone '%s'", zone_name); ++ ++ if (raw != NULL) { ++ if (dns_zone_getmgr(raw) != NULL) ++ dns_zonemgr_releasezone(inst->zmgr, raw); ++ dns_zone_detach(&raw); ++ } ++ if (acl_any != NULL) ++ dns_acl_detach(&acl_any); ++ ++ return (result); ++} ++ ++/* ++ * Add zone to the view defined in inst->view. This will make the zone visible ++ * to clients. ++ */ ++static isc_result_t ++publish_zone(sample_instance_t *inst, dns_zone_t *zone) { ++ isc_result_t result; ++ isc_boolean_t freeze = ISC_FALSE; ++ dns_zone_t *zone_in_view = NULL; ++ dns_view_t *view_in_zone = NULL; ++ isc_result_t lock_state = ISC_R_IGNORE; ++ ++ REQUIRE(inst != NULL); ++ REQUIRE(zone != NULL); ++ ++ /* Return success if the zone is already in the view as expected. */ ++ result = dns_view_findzone(inst->view, dns_zone_getorigin(zone), ++ &zone_in_view); ++ if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) ++ goto cleanup; ++ ++ view_in_zone = dns_zone_getview(zone); ++ if (view_in_zone != NULL) { ++ /* Zone has a view set -> view should contain the same zone. */ ++ if (zone_in_view == zone) { ++ /* Zone is already published in the right view. */ ++ CLEANUP_WITH(ISC_R_SUCCESS); ++ } else if (view_in_zone != inst->view) { ++ /* ++ * Un-published inactive zone will have ++ * inst->view in zone but will not be present ++ * in the view itself. ++ */ ++ dns_zone_log(zone, ISC_LOG_ERROR, ++ "zone->view doesn't " ++ "match data in the view"); ++ CLEANUP_WITH(ISC_R_UNEXPECTED); ++ } ++ } ++ ++ if (zone_in_view != NULL) { ++ dns_zone_log(zone, ISC_LOG_ERROR, ++ "cannot publish zone: view already " ++ "contains another zone with this name"); ++ CLEANUP_WITH(ISC_R_UNEXPECTED); ++ } ++ ++ run_exclusive_enter(inst, &lock_state); ++ if (inst->view->frozen) { ++ freeze = ISC_TRUE; ++ dns_view_thaw(inst->view); ++ } ++ ++ dns_zone_setview(zone, inst->view); ++ CHECK(dns_view_addzone(inst->view, zone)); ++ ++cleanup: ++ if (zone_in_view != NULL) ++ dns_zone_detach(&zone_in_view); ++ if (freeze) ++ dns_view_freeze(inst->view); ++ run_exclusive_exit(inst, lock_state); ++ ++ return (result); ++} ++ ++/* ++ * @warning Never call this on raw part of in-line secure zone, call it only ++ * on the secure zone! ++ */ ++static isc_result_t ++load_zone(dns_zone_t *zone) { ++ isc_result_t result; ++ isc_boolean_t zone_dynamic; ++ isc_uint32_t serial; ++ ++ result = dns_zone_load(zone); ++ if (result != ISC_R_SUCCESS && result != DNS_R_UPTODATE ++ && result != DNS_R_DYNAMIC && result != DNS_R_CONTINUE) ++ goto cleanup; ++ zone_dynamic = (result == DNS_R_DYNAMIC); ++ ++ CHECK(dns_zone_getserial2(zone, &serial)); ++ dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u", serial); ++ ++ if (zone_dynamic) ++ dns_zone_notify(zone); ++ ++cleanup: ++ return (result); ++} ++ ++/* ++ * Add zone to view and call dns_zone_load(). ++ */ ++isc_result_t ++activate_zone(sample_instance_t *inst, dns_zone_t *raw) { ++ isc_result_t result; ++ ++ /* ++ * Zone has to be published *before* zone load ++ * otherwise it will race with zone->view != NULL check ++ * in zone_maintenance() in zone.c. ++ */ ++ result = publish_zone(inst, raw); ++ if (result != ISC_R_SUCCESS) { ++ dns_zone_log(raw, ISC_LOG_ERROR, ++ "cannot add zone to view: %s", ++ dns_result_totext(result)); ++ goto cleanup; ++ } ++ ++ CHECK(load_zone(raw)); ++ ++cleanup: ++ return (result); ++} +diff --git a/bin/tests/system/dyndb/driver/zone.h b/bin/tests/system/dyndb/driver/zone.h +new file mode 100644 +index 0000000..a862691 +--- /dev/null ++++ b/bin/tests/system/dyndb/driver/zone.h +@@ -0,0 +1,15 @@ ++/* ++ * Copyright (C) 2014-2015 Red Hat ; see COPYRIGHT for license ++ */ ++ ++#ifndef ZONE_H_ ++#define ZONE_H_ ++ ++isc_result_t ++create_zone(sample_instance_t * const inst, dns_name_t * const name, ++ dns_zone_t ** const rawp); ++ ++isc_result_t ++activate_zone(sample_instance_t *inst, dns_zone_t *raw); ++ ++#endif /* ZONE_H_ */ +diff --git a/bin/tests/system/dyndb/ns1/named.conf b/bin/tests/system/dyndb/ns1/named.conf +new file mode 100644 +index 0000000..a4f334b +--- /dev/null ++++ b/bin/tests/system/dyndb/ns1/named.conf +@@ -0,0 +1,42 @@ ++/* ++ * 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. ++ */ ++ ++controls { }; ++ ++options { ++ query-source address 10.53.0.1; ++ notify-source 10.53.0.1; ++ transfer-source 10.53.0.1; ++ port 5300; ++ pid-file "named.pid"; ++ session-keyfile "session.key"; ++ listen-on { 10.53.0.1; 127.0.0.1; }; ++ listen-on-v6 { none; }; ++ recursion no; ++ notify yes; ++}; ++ ++key rndc_key { ++ secret "1234abcd8765"; ++ algorithm hmac-sha256; ++}; ++ ++controls { ++ inet 10.53.0.1 port 9953 allow { any; } keys { rndc_key; }; ++}; ++ ++dyndb sample "../driver/lib/sample.so" { ipv4.example.nil. in-addr.arpa. }; ++dyndb sample2 "../driver/lib/sample.so" { ipv6.example.nil. 8.b.d.0.1.0.0.2.ip6.arpa. }; +diff --git a/bin/tests/system/dyndb/prereq.sh b/bin/tests/system/dyndb/prereq.sh +new file mode 100644 +index 0000000..fe7ef71 +--- /dev/null ++++ b/bin/tests/system/dyndb/prereq.sh +@@ -0,0 +1,21 @@ ++#!/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. ++ ++../dlzexternal/dlopen || { ++ echo "I:dlopen() not supported - skipping dyndb test" ++ exit 255 ++} ++exit 0 +diff --git a/bin/tests/system/dyndb/tests.sh b/bin/tests/system/dyndb/tests.sh +new file mode 100644 +index 0000000..590b70b +--- /dev/null ++++ b/bin/tests/system/dyndb/tests.sh +@@ -0,0 +1,155 @@ ++#!/bin/sh ++# ++# Copyright (C) 2010-2014 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. ++ ++SYSTEMTESTTOP=.. ++. $SYSTEMTESTTOP/conf.sh ++ ++status=0 ++n=0 ++ ++DIGOPTS="@10.53.0.1 -p 5300" ++ ++newtest() { ++ n=`expr $n + 1` ++ echo "${1} (${n})" ++ ret=0 ++} ++ ++test_add() { ++ host="$1" ++ type="$2" ++ ip="$3" ++ ++ cat < ns1/update.txt ++server 10.53.0.1 5300 ++ttl 86400 ++update add $host $type $ip ++send ++EOF ++ ++ newtest "I:adding $host $type $ip" ++ $NSUPDATE ns1/update.txt > /dev/null 2>&1 || { ++ [ "$should_fail" ] || \ ++ echo "I:update failed for $host $type $ip" ++ return 1 ++ } ++ ++ out=`$DIG $DIGOPTS +noall +answer -t $type -q $host` ++ echo $out > added.a.out.$n ++ lines=`echo "$out" | grep "$ip" | wc -l` ++ [ $lines -eq 1 ] || { ++ [ "$should_fail" ] || \ ++ echo "I:dig output incorrect for $host $type $cmd: $out" ++ return 1 ++ } ++ ++ out=`$DIG $DIGOPTS +noall +answer -x $ip` ++ echo $out > added.ptr.out.$n ++ lines=`echo "$out" | grep "$host" | wc -l` ++ [ $lines -eq 1 ] || { ++ [ "$should_fail" ] || \ ++ echo "I:dig reverse output incorrect for $host $type $cmd: $out" ++ return 1 ++ } ++ ++ return 0 ++} ++ ++test_del() { ++ host="$1" ++ type="$2" ++ ++ ip=`$DIG $DIGOPTS +short $host $type` ++ ++ cat < ns1/update.txt ++server 10.53.0.1 5300 ++update del $host $type ++send ++EOF ++ ++ newtest "I:deleting $host $type (was $ip)" ++ $NSUPDATE ns1/update.txt > /dev/null 2>&1 || { ++ [ "$should_fail" ] || \ ++ echo "I:update failed deleting $host $type" ++ return 1 ++ } ++ ++ out=`$DIG $DIGOPTS +noall +answer -t $type -q $host` ++ echo $out > deleted.a.out.$n ++ lines=`echo "$out" | grep "$ip" | wc -l` ++ [ $lines -eq 0 ] || { ++ [ "$should_fail" ] || \ ++ echo "I:dig output incorrect for $host $type $cmd: $out" ++ return 1 ++ } ++ ++ out=`$DIG $DIGOPTS +noall +answer -x $ip` ++ echo $out > deleted.ptr.out.$n ++ lines=`echo "$out" | grep "$host" | wc -l` ++ [ $lines -eq 0 ] || { ++ [ "$should_fail" ] || \ ++ echo "I:dig reverse output incorrect for $host $type $cmd: $out" ++ return 1 ++ } ++ ++ return 0 ++} ++ ++test_add test1.ipv4.example.nil. A "10.53.0.10" || ret=1 ++status=`expr $status + $ret` ++ ++test_add test2.ipv4.example.nil. A "10.53.0.11" || ret=1 ++status=`expr $status + $ret` ++ ++test_add test3.ipv4.example.nil. A "10.53.0.12" || ret=1 ++status=`expr $status + $ret` ++ ++test_add test4.ipv6.example.nil. AAAA "2001:db8::1" || ret=1 ++status=`expr $status + $ret` ++ ++test_del test1.ipv4.example.nil. A || ret=1 ++status=`expr $status + $ret` ++ ++test_del test2.ipv4.example.nil. A || ret=1 ++status=`expr $status + $ret` ++ ++test_del test3.ipv4.example.nil. A || ret=1 ++status=`expr $status + $ret` ++ ++test_del test4.ipv6.example.nil. AAAA || ret=1 ++status=`expr $status + $ret` ++ ++newtest "I:checking parameter logging" ++grep "loading params for dyndb 'sample' from .*named.conf:41" ns1/named.run > /dev/null || ret=1 ++grep "loading params for dyndb 'sample2' from .*named.conf:42" ns1/named.run > /dev/null || ret=1 ++status=`expr $status + $ret` ++ ++echo "I:checking dyndb still works after reload" ++$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953 reload 2>&1 | sed 's/^/I:ns1 /' ++ ++test_add test5.ipv4.example.nil. A "10.53.0.10" || ret=1 ++status=`expr $status + $ret` ++ ++test_add test6.ipv6.example.nil. AAAA "2001:db8::1" || ret=1 ++status=`expr $status + $ret` ++ ++test_del test5.ipv4.example.nil. A || ret=1 ++status=`expr $status + $ret` ++ ++test_del test6.ipv6.example.nil. AAAA || ret=1 ++status=`expr $status + $ret` ++ ++exit $status +diff --git a/configure b/configure +index 2a53adf..c62da63 100755 +--- a/configure ++++ b/configure +@@ -162,7 +162,7 @@ + # + # ----------------------------------------------------------------------------- + # +-# Copyright (c) 1997 - 2003 Kungliga Tekniska H�gskolan ++# Copyright (c) 1997 - 2003 Kungliga Tekniska H�gskolan + # (Royal Institute of Technology, Stockholm, Sweden). + # All rights reserved. + # +@@ -19784,6 +19784,7 @@ $as_echo "#define ISC_DLZ_DLOPEN 1" >>confdefs.h + + fi + fi ++CFLAGS="$CFLAGS $SO_CFLAGS" + + + +@@ -20594,7 +20595,7 @@ ac_config_commands="$ac_config_commands chmod" + # elsewhere if there's a good reason for doing so. + # + +-ac_config_files="$ac_config_files make/Makefile make/mkdep Makefile bin/Makefile bin/check/Makefile bin/confgen/Makefile bin/confgen/unix/Makefile bin/dig/Makefile bin/dnssec/Makefile bin/named/Makefile bin/named/unix/Makefile bin/nsupdate/Makefile bin/pkcs11/Makefile bin/python/Makefile bin/python/dnssec-checkds.py bin/python/dnssec-coverage.py bin/rndc/Makefile bin/tests/Makefile bin/tests/atomic/Makefile bin/tests/db/Makefile bin/tests/dst/Makefile bin/tests/dst/Kdh.+002+18602.key bin/tests/dst/Kdh.+002+18602.private bin/tests/dst/Kdh.+002+48957.key bin/tests/dst/Kdh.+002+48957.private bin/tests/dst/Ktest.+001+00002.key bin/tests/dst/Ktest.+001+54622.key bin/tests/dst/Ktest.+001+54622.private bin/tests/dst/Ktest.+003+23616.key bin/tests/dst/Ktest.+003+23616.private bin/tests/dst/Ktest.+003+49667.key bin/tests/dst/dst_2_data bin/tests/dst/t2_data_1 bin/tests/dst/t2_data_2 bin/tests/dst/t2_dsasig bin/tests/dst/t2_rsasig bin/tests/hashes/Makefile bin/tests/headerdep_test.sh bin/tests/master/Makefile bin/tests/mem/Makefile bin/tests/names/Makefile bin/tests/net/Makefile bin/tests/rbt/Makefile bin/tests/resolver/Makefile bin/tests/sockaddr/Makefile bin/tests/system/Makefile bin/tests/system/conf.sh bin/tests/system/dlz/prereq.sh bin/tests/system/dlzexternal/Makefile bin/tests/system/dlzexternal/ns1/named.conf bin/tests/system/ecdsa/prereq.sh bin/tests/system/filter-aaaa/Makefile bin/tests/system/gost/prereq.sh bin/tests/system/lwresd/Makefile bin/tests/system/rpz/Makefile bin/tests/system/rrl/Makefile bin/tests/system/rsabigexponent/Makefile bin/tests/system/tkey/Makefile bin/tests/system/tsiggss/Makefile bin/tests/tasks/Makefile bin/tests/timers/Makefile bin/tests/virtual-time/Makefile bin/tests/virtual-time/conf.sh bin/tools/Makefile contrib/check-secure-delegation.pl contrib/zone-edit.sh doc/Makefile doc/arm/Makefile doc/doxygen/Doxyfile doc/doxygen/Makefile doc/doxygen/doxygen-input-filter doc/misc/Makefile doc/xsl/Makefile doc/xsl/isc-docbook-chunk.xsl doc/xsl/isc-docbook-html.xsl doc/xsl/isc-docbook-latex.xsl doc/xsl/isc-manpage.xsl isc-config.sh lib/Makefile lib/bind9/Makefile lib/bind9/include/Makefile lib/bind9/include/bind9/Makefile lib/dns/Makefile lib/dns/include/Makefile lib/dns/include/dns/Makefile lib/dns/include/dst/Makefile lib/dns/tests/Makefile lib/export/Makefile lib/export/dns/Makefile lib/export/dns/include/Makefile lib/export/dns/include/dns/Makefile lib/export/dns/include/dst/Makefile lib/export/irs/Makefile lib/export/irs/include/Makefile lib/export/irs/include/irs/Makefile lib/export/isc/$thread_dir/Makefile lib/export/isc/$thread_dir/include/Makefile lib/export/isc/$thread_dir/include/isc/Makefile lib/export/isc/Makefile lib/export/isc/include/Makefile lib/export/isc/include/isc/Makefile lib/export/isc/nls/Makefile lib/export/isc/unix/Makefile lib/export/isc/unix/include/Makefile lib/export/isc/unix/include/isc/Makefile lib/export/isccfg/Makefile lib/export/isccfg/include/Makefile lib/export/isccfg/include/isccfg/Makefile lib/export/samples/Makefile lib/export/samples/Makefile-postinstall lib/irs/Makefile lib/irs/include/Makefile lib/irs/include/irs/Makefile lib/irs/include/irs/netdb.h lib/irs/include/irs/platform.h lib/isc/$arch/Makefile lib/isc/$arch/include/Makefile lib/isc/$arch/include/isc/Makefile lib/isc/$thread_dir/Makefile lib/isc/$thread_dir/include/Makefile lib/isc/$thread_dir/include/isc/Makefile lib/isc/Makefile lib/isc/include/Makefile lib/isc/include/isc/Makefile lib/isc/include/isc/platform.h lib/isc/tests/Makefile lib/isc/nls/Makefile lib/isc/unix/Makefile lib/isc/unix/include/Makefile lib/isc/unix/include/isc/Makefile lib/isccc/Makefile lib/isccc/include/Makefile lib/isccc/include/isccc/Makefile lib/isccfg/Makefile lib/isccfg/include/Makefile lib/isccfg/include/isccfg/Makefile lib/lwres/Makefile lib/lwres/include/Makefile lib/lwres/include/lwres/Makefile lib/lwres/include/lwres/netdb.h lib/lwres/include/lwres/platform.h lib/lwres/man/Makefile lib/lwres/unix/Makefile lib/lwres/unix/include/Makefile lib/lwres/unix/include/lwres/Makefile lib/tests/Makefile lib/tests/include/Makefile lib/tests/include/tests/Makefile unit/Makefile unit/unittest.sh" ++ac_config_files="$ac_config_files make/Makefile make/mkdep Makefile bin/Makefile bin/check/Makefile bin/confgen/Makefile bin/confgen/unix/Makefile bin/dig/Makefile bin/dnssec/Makefile bin/named/Makefile bin/named/unix/Makefile bin/nsupdate/Makefile bin/pkcs11/Makefile bin/python/Makefile bin/python/dnssec-checkds.py bin/python/dnssec-coverage.py bin/rndc/Makefile bin/tests/Makefile bin/tests/atomic/Makefile bin/tests/db/Makefile bin/tests/dst/Makefile bin/tests/dst/Kdh.+002+18602.key bin/tests/dst/Kdh.+002+18602.private bin/tests/dst/Kdh.+002+48957.key bin/tests/dst/Kdh.+002+48957.private bin/tests/dst/Ktest.+001+00002.key bin/tests/dst/Ktest.+001+54622.key bin/tests/dst/Ktest.+001+54622.private bin/tests/dst/Ktest.+003+23616.key bin/tests/dst/Ktest.+003+23616.private bin/tests/dst/Ktest.+003+49667.key bin/tests/dst/dst_2_data bin/tests/dst/t2_data_1 bin/tests/dst/t2_data_2 bin/tests/dst/t2_dsasig bin/tests/dst/t2_rsasig bin/tests/hashes/Makefile bin/tests/headerdep_test.sh bin/tests/master/Makefile bin/tests/mem/Makefile bin/tests/names/Makefile bin/tests/net/Makefile bin/tests/rbt/Makefile bin/tests/resolver/Makefile bin/tests/sockaddr/Makefile bin/tests/system/Makefile bin/tests/system/conf.sh bin/tests/system/dlz/prereq.sh bin/tests/system/dlzexternal/Makefile bin/tests/system/dlzexternal/ns1/named.conf bin/tests/system/dyndb/Makefile bin/tests/system/dyndb/driver/Makefile bin/tests/system/ecdsa/prereq.sh bin/tests/system/filter-aaaa/Makefile bin/tests/system/gost/prereq.sh bin/tests/system/lwresd/Makefile bin/tests/system/rpz/Makefile bin/tests/system/rrl/Makefile bin/tests/system/rsabigexponent/Makefile bin/tests/system/tkey/Makefile bin/tests/system/tsiggss/Makefile bin/tests/tasks/Makefile bin/tests/timers/Makefile bin/tests/virtual-time/Makefile bin/tests/virtual-time/conf.sh bin/tools/Makefile contrib/check-secure-delegation.pl contrib/zone-edit.sh doc/Makefile doc/arm/Makefile doc/doxygen/Doxyfile doc/doxygen/Makefile doc/doxygen/doxygen-input-filter doc/misc/Makefile doc/xsl/Makefile doc/xsl/isc-docbook-chunk.xsl doc/xsl/isc-docbook-html.xsl doc/xsl/isc-docbook-latex.xsl doc/xsl/isc-manpage.xsl isc-config.sh lib/Makefile lib/bind9/Makefile lib/bind9/include/Makefile lib/bind9/include/bind9/Makefile lib/dns/Makefile lib/dns/include/Makefile lib/dns/include/dns/Makefile lib/dns/include/dst/Makefile lib/dns/tests/Makefile lib/export/Makefile lib/export/dns/Makefile lib/export/dns/include/Makefile lib/export/dns/include/dns/Makefile lib/export/dns/include/dst/Makefile lib/export/irs/Makefile lib/export/irs/include/Makefile lib/export/irs/include/irs/Makefile lib/export/isc/$thread_dir/Makefile lib/export/isc/$thread_dir/include/Makefile lib/export/isc/$thread_dir/include/isc/Makefile lib/export/isc/Makefile lib/export/isc/include/Makefile lib/export/isc/include/isc/Makefile lib/export/isc/nls/Makefile lib/export/isc/unix/Makefile lib/export/isc/unix/include/Makefile lib/export/isc/unix/include/isc/Makefile lib/export/isccfg/Makefile lib/export/isccfg/include/Makefile lib/export/isccfg/include/isccfg/Makefile lib/export/samples/Makefile lib/export/samples/Makefile-postinstall lib/irs/Makefile lib/irs/include/Makefile lib/irs/include/irs/Makefile lib/irs/include/irs/netdb.h lib/irs/include/irs/platform.h lib/isc/$arch/Makefile lib/isc/$arch/include/Makefile lib/isc/$arch/include/isc/Makefile lib/isc/$thread_dir/Makefile lib/isc/$thread_dir/include/Makefile lib/isc/$thread_dir/include/isc/Makefile lib/isc/Makefile lib/isc/include/Makefile lib/isc/include/isc/Makefile lib/isc/include/isc/platform.h lib/isc/tests/Makefile lib/isc/nls/Makefile lib/isc/unix/Makefile lib/isc/unix/include/Makefile lib/isc/unix/include/isc/Makefile lib/isccc/Makefile lib/isccc/include/Makefile lib/isccc/include/isccc/Makefile lib/isccfg/Makefile lib/isccfg/include/Makefile lib/isccfg/include/isccfg/Makefile lib/lwres/Makefile lib/lwres/include/Makefile lib/lwres/include/lwres/Makefile lib/lwres/include/lwres/netdb.h lib/lwres/include/lwres/platform.h lib/lwres/man/Makefile lib/lwres/unix/Makefile lib/lwres/unix/include/Makefile lib/lwres/unix/include/lwres/Makefile lib/tests/Makefile lib/tests/include/Makefile lib/tests/include/tests/Makefile unit/Makefile unit/unittest.sh" + + + # +@@ -21637,6 +21638,8 @@ do + "bin/tests/system/dlz/prereq.sh") CONFIG_FILES="$CONFIG_FILES bin/tests/system/dlz/prereq.sh" ;; + "bin/tests/system/dlzexternal/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/dlzexternal/Makefile" ;; + "bin/tests/system/dlzexternal/ns1/named.conf") CONFIG_FILES="$CONFIG_FILES bin/tests/system/dlzexternal/ns1/named.conf" ;; ++ "bin/tests/system/dyndb/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/dyndb/Makefile" ;; ++ "bin/tests/system/dyndb/driver/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/dyndb/driver/Makefile" ;; + "bin/tests/system/ecdsa/prereq.sh") CONFIG_FILES="$CONFIG_FILES bin/tests/system/ecdsa/prereq.sh" ;; + "bin/tests/system/filter-aaaa/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/filter-aaaa/Makefile" ;; + "bin/tests/system/gost/prereq.sh") CONFIG_FILES="$CONFIG_FILES bin/tests/system/gost/prereq.sh" ;; +diff --git a/configure.in b/configure.in +index 24eafb7..e8c68fc 100644 +--- a/configure.in ++++ b/configure.in +@@ -3755,6 +3755,7 @@ if test "$dlopen" = "yes"; then + [Define to allow building of objects for dlopen().]) + fi + fi ++CFLAGS="$CFLAGS $SO_CFLAGS" + + AC_SUBST(SO) + AC_SUBST(SO_CFLAGS) +@@ -3960,6 +3961,8 @@ AC_CONFIG_FILES([ + bin/tests/system/dlz/prereq.sh + bin/tests/system/dlzexternal/Makefile + bin/tests/system/dlzexternal/ns1/named.conf ++ bin/tests/system/dyndb/Makefile ++ bin/tests/system/dyndb/driver/Makefile + bin/tests/system/ecdsa/prereq.sh + bin/tests/system/filter-aaaa/Makefile + bin/tests/system/gost/prereq.sh +diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml +index bd42e11..16b50a3 100644 +--- a/doc/arm/Bv9ARM-book.xml ++++ b/doc/arm/Bv9ARM-book.xml +@@ -2384,6 +2384,8 @@ options { + + + ++ ++ + + IPv6 Support in <acronym>BIND</acronym> 9 + +diff --git a/doc/arm/dyndb.xml b/doc/arm/dyndb.xml +new file mode 100644 +index 0000000..4d92b22 +--- /dev/null ++++ b/doc/arm/dyndb.xml +@@ -0,0 +1,105 @@ ++ ++ ++ ++ ++ DynDB (Dynamic Database) ++ ++ DynDB is an extension to BIND 9 which, like DLZ ++ (see ), allows zone data to be ++ retrieved from an external database. Unlike DLZ, a DynDB module ++ provides a full-featured BIND zone database interface. Where ++ DLZ translates DNS queries into real-time database lookups, ++ resulting in relatively poor query performance, and is unable ++ to handle DNSSEC-signed data due to its limited API, a DynDB ++ module can pre-load an in-memory database from the external ++ data source, providing the same performance and functionality ++ as zones served natively by BIND. ++ ++ ++ A DynDB module supporting LDAP has been created by Red Hat ++ and is available from ++ https://fedorahosted.org/bind-dyndb-ldap/. ++ ++ ++ A sample DynDB module for testing and developer guidance ++ is included with the BIND source code, in the directory ++ bin/tests/system/dyndb/driver. ++ ++ ++ ++ Configuring DynDB ++ ++ A DynDB database is configured with a dyndb ++ statement in named.conf: ++ ++ ++ dyndb example "driver.so" { ++ parameters ++ }; ++ ++ ++ The file driver.so is a DynDB module which ++ implements the full DNS database API. Multiple ++ dyndb statements can be specified, to load ++ different drivers or multiple instances of the same driver. ++ Zones provided by a DynDB module are added to the view's zone ++ table, and are treated as normal authoritative zones when BIND ++ is responding to queries. Zone configuration is handled internally ++ by the DynDB module. ++ ++ ++ The parameters are passed as an opaque ++ string to the DynDB module's initialization routine. Configuration ++ syntax will differ depending on the driver. ++ ++ ++ ++ Sample DynDB Module ++ ++ For guidance in implementation of DynDB modules, the directory ++ bin/tests/system/dyndb/driver. ++ contains a basic DynDB module. ++ The example sets up two zones, whose names are passed ++ to the module as arguments in the dyndb ++ statement: ++ ++ ++ dyndb sample "sample.so" { example.nil. arpa. }; ++ ++ ++ In the above example, the module is configured to create a zone ++ "example.nil", which can answer queries and AXFR requests, and ++ accept DDNS updates. At runtime, prior to any updates, the zone ++ contains an SOA, NS, and a single A record at the apex: ++ ++ ++ example.nil. 86400 IN SOA example.nil. example.nil. ( ++ 0 28800 7200 604800 86400 ++ ) ++ example.nil. 86400 IN NS example.nil. ++ example.nil. 86400 IN A 127.0.0.1 ++ ++ ++ When the zone is updated dynamically, the DynDB module will determine ++ whether the updated RR is an address (i.e., type A or AAAA) and if ++ so, it will automatically update the corresponding PTR record in a ++ reverse zone. (Updates are not stored permanently; all updates are ++ lost when the server is restarted.) ++ ++ ++ +diff --git a/lib/dns/Makefile.in b/lib/dns/Makefile.in +index 909250f..2efcc5a 100644 +--- a/lib/dns/Makefile.in ++++ b/lib/dns/Makefile.in +@@ -60,8 +60,8 @@ RRLOBJS = rrl.@O@ + DNSOBJS = acache.@O@ acl.@O@ adb.@O@ byaddr.@O@ \ + cache.@O@ callbacks.@O@ clientinfo.@O@ compress.@O@ \ + db.@O@ dbiterator.@O@ dbtable.@O@ diff.@O@ dispatch.@O@ \ +- dlz.@O@ dns64.@O@ dnssec.@O@ ds.@O@ forward.@O@ iptable.@O@ \ +- journal.@O@ keydata.@O@ keytable.@O@ \ ++ dlz.@O@ dns64.@O@ dnssec.@O@ ds.@O@ dyndb.@O@ forward.@O@ \ ++ iptable.@O@ journal.@O@ keydata.@O@ keytable.@O@ \ + lib.@O@ log.@O@ lookup.@O@ \ + master.@O@ masterdump.@O@ message.@O@ \ + name.@O@ ncache.@O@ nsec.@O@ nsec3.@O@ order.@O@ peer.@O@ \ +@@ -93,8 +93,8 @@ DSTSRCS = @DST_EXTRA_SRCS@ @OPENSSLLINKSRCS@ @PKCS11LINKSRCS@ \ + DNSSRCS = acache.c acl.c adb.c byaddr.c \ + cache.c callbacks.c clientinfo.c compress.c \ + db.c dbiterator.c dbtable.c diff.c dispatch.c \ +- dlz.c dns64.c dnssec.c ds.c forward.c iptable.c journal.c \ +- keydata.c keytable.c lib.c log.c lookup.c \ ++ dlz.c dns64.c dnssec.c ds.c dyndb.c forward.c iptable.c \ ++ journal.c keydata.c keytable.c lib.c log.c lookup.c \ + master.c masterdump.c message.c \ + name.c ncache.c nsec.c nsec3.c order.c peer.c portlist.c \ + rbt.c rbtdb.c rbtdb64.c rcode.c rdata.c rdatalist.c \ +diff --git a/lib/dns/dlz.c b/lib/dns/dlz.c +index 19c600c..ffcd23f 100644 +--- a/lib/dns/dlz.c ++++ b/lib/dns/dlz.c +@@ -69,6 +69,7 @@ + + + #include ++#include + #include + #include + #include +@@ -400,67 +401,6 @@ dns_dlzregister(const char *drivername, const dns_dlzmethods_t *methods, + } + + /*% +- * Helper function for dns_dlzstrtoargv(). +- * Pardon the gratuitous recursion. +- */ +-static isc_result_t +-dns_dlzstrtoargvsub(isc_mem_t *mctx, char *s, unsigned int *argcp, +- char ***argvp, unsigned int n) +-{ +- isc_result_t result; +- +- restart: +- /* Discard leading whitespace. */ +- while (*s == ' ' || *s == '\t') +- s++; +- +- if (*s == '\0') { +- /* We have reached the end of the string. */ +- *argcp = n; +- *argvp = isc_mem_get(mctx, n * sizeof(char *)); +- if (*argvp == NULL) +- return (ISC_R_NOMEMORY); +- } else { +- char *p = s; +- while (*p != ' ' && *p != '\t' && *p != '\0' && *p != '{') { +- if (*p == '\n') { +- *p = ' '; +- goto restart; +- } +- p++; +- } +- +- /* do "grouping", items between { and } are one arg */ +- if (*p == '{') { +- char *t = p; +- /* +- * shift all characters to left by 1 to get rid of '{' +- */ +- while (*t != '\0') { +- t++; +- *(t-1) = *t; +- } +- while (*p != '\0' && *p != '}') { +- p++; +- } +- /* get rid of '}' character */ +- if (*p == '}') { +- *p = '\0'; +- p++; +- } +- /* normal case, no "grouping" */ +- } else if (*p != '\0') +- *p++ = '\0'; +- +- result = dns_dlzstrtoargvsub(mctx, p, argcp, argvp, n + 1); +- if (result != ISC_R_SUCCESS) +- return (result); +- (*argvp)[n] = s; +- } +- return (ISC_R_SUCCESS); +-} +- +-/*% + * Tokenize the string "s" into whitespace-separated words, + * return the number of words in '*argcp' and an array + * of pointers to the words in '*argvp'. The caller +@@ -471,7 +411,7 @@ isc_result_t + dns_dlzstrtoargv(isc_mem_t *mctx, char *s, + unsigned int *argcp, char ***argvp) + { +- return(dns_dlzstrtoargvsub(mctx, s, argcp, argvp, 0)); ++ return(isc_commandline_strtoargv(mctx, s, argcp, argvp, 0)); + } + + /*% +diff --git a/lib/dns/dyndb.c b/lib/dns/dyndb.c +new file mode 100644 +index 0000000..76b77f0 +--- /dev/null ++++ b/lib/dns/dyndb.c +@@ -0,0 +1,486 @@ ++/* ++ * 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. ++ */ ++ ++ ++#include ++ ++#if HAVE_DLFCN_H ++#include ++#elif _WIN32 ++#include ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define CHECK(op) \ ++ do { result = (op); \ ++ if (result != ISC_R_SUCCESS) goto cleanup; \ ++ } while (0) ++ ++ ++typedef struct dyndb_implementation dyndb_implementation_t; ++struct dyndb_implementation { ++ isc_mem_t *mctx; ++ void *handle; ++ dns_dyndb_register_t *register_func; ++ dns_dyndb_destroy_t *destroy_func; ++ char *name; ++ void *inst; ++ LINK(dyndb_implementation_t) link; ++}; ++ ++/* ++ * List of dyndb implementations. Locked by dyndb_lock. ++ * ++ * These are stored here so they can be cleaned up on shutdown. ++ * (The order in which they are stored is not important.) ++ */ ++static LIST(dyndb_implementation_t) dyndb_implementations; ++ ++/* Locks dyndb_implementations. */ ++static isc_mutex_t dyndb_lock; ++static isc_once_t once = ISC_ONCE_INIT; ++ ++static void ++dyndb_initialize(void) { ++ RUNTIME_CHECK(isc_mutex_init(&dyndb_lock) == ISC_R_SUCCESS); ++ INIT_LIST(dyndb_implementations); ++} ++ ++static dyndb_implementation_t * ++impfind(const char *name) { ++ dyndb_implementation_t *imp; ++ ++ for (imp = ISC_LIST_HEAD(dyndb_implementations); ++ imp != NULL; ++ imp = ISC_LIST_NEXT(imp, link)) ++ if (strcasecmp(name, imp->name) == 0) ++ return (imp); ++ return (NULL); ++} ++ ++#if HAVE_DLFCN_H ++static isc_result_t ++load_symbol(void *handle, const char *filename, ++ const char *symbol_name, void **symbolp) ++{ ++ const char *errmsg; ++ void *symbol; ++ ++ REQUIRE(handle != NULL); ++ REQUIRE(symbolp != NULL && *symbolp == NULL); ++ ++ symbol = dlsym(handle, symbol_name); ++ if (symbol == NULL) { ++ errmsg = dlerror(); ++ if (errmsg == NULL) ++ errmsg = "returned function pointer is NULL"; ++ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, ++ DNS_LOGMODULE_DYNDB, ISC_LOG_ERROR, ++ "failed to lookup symbol %s in " ++ "dyndb module '%s': %s", ++ symbol_name, filename, errmsg); ++ return (ISC_R_FAILURE); ++ } ++ dlerror(); ++ ++ *symbolp = symbol; ++ ++ return (ISC_R_SUCCESS); ++} ++ ++static isc_result_t ++load_library(isc_mem_t *mctx, const char *filename, const char *instname, ++ dyndb_implementation_t **impp) ++{ ++ isc_result_t result; ++ void *handle = NULL; ++ dyndb_implementation_t *imp = NULL; ++ dns_dyndb_register_t *register_func = NULL; ++ dns_dyndb_destroy_t *destroy_func = NULL; ++ dns_dyndb_version_t *version_func = NULL; ++ int version, flags; ++ ++ REQUIRE(impp != NULL && *impp == NULL); ++ ++ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, ++ DNS_LOGMODULE_DYNDB, ISC_LOG_INFO, ++ "loading DynDB instance '%s' driver '%s'", ++ instname, filename); ++ ++ flags = RTLD_NOW|RTLD_LOCAL; ++#if 0 ++ // Need to access the daemon variables from the plugin, not local copies ++#ifdef RTLD_DEEPBIND ++ flags |= RTLD_DEEPBIND; ++#endif ++#endif ++ ++ handle = dlopen(filename, flags); ++ if (handle == NULL) ++ CHECK(ISC_R_FAILURE); ++ ++ /* Clear dlerror */ ++ dlerror(); ++ ++ CHECK(load_symbol(handle, filename, "dyndb_version", ++ (void **)&version_func)); ++ ++ version = version_func(NULL); ++ if (version < (DNS_DYNDB_VERSION - DNS_DYNDB_AGE) || ++ version > DNS_DYNDB_VERSION) ++ { ++ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, ++ DNS_LOGMODULE_DYNDB, ISC_LOG_ERROR, ++ "driver API version mismatch: %d/%d", ++ version, DNS_DYNDB_VERSION); ++ CHECK(ISC_R_FAILURE); ++ } ++ ++ CHECK(load_symbol(handle, filename, "dyndb_init", ++ (void **)®ister_func)); ++ CHECK(load_symbol(handle, filename, "dyndb_destroy", ++ (void **)&destroy_func)); ++ ++ imp = isc_mem_get(mctx, sizeof(dyndb_implementation_t)); ++ if (imp == NULL) ++ CHECK(ISC_R_NOMEMORY); ++ ++ imp->mctx = NULL; ++ isc_mem_attach(mctx, &imp->mctx); ++ imp->handle = handle; ++ imp->register_func = register_func; ++ imp->destroy_func = destroy_func; ++ imp->name = isc_mem_strdup(mctx, instname); ++ if (imp->name == NULL) ++ CHECK(ISC_R_NOMEMORY); ++ ++ imp->inst = NULL; ++ INIT_LINK(imp, link); ++ ++ *impp = imp; ++ imp = NULL; ++ ++cleanup: ++ if (result != ISC_R_SUCCESS) ++ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, ++ DNS_LOGMODULE_DYNDB, ISC_LOG_ERROR, ++ "failed to dynamically load instance '%s' " ++ "driver '%s': %s (%s)", instname, filename, ++ dlerror(), isc_result_totext(result)); ++ if (imp != NULL) ++ isc_mem_putanddetach(&imp->mctx, imp, sizeof(dyndb_implementation_t)); ++ if (result != ISC_R_SUCCESS && handle != NULL) ++ dlclose(handle); ++ ++ return (result); ++} ++ ++static void ++unload_library(dyndb_implementation_t **impp) { ++ dyndb_implementation_t *imp; ++ ++ REQUIRE(impp != NULL && *impp != NULL); ++ ++ imp = *impp; ++ ++ isc_mem_free(imp->mctx, imp->name); ++ isc_mem_putanddetach(&imp->mctx, imp, sizeof(dyndb_implementation_t)); ++ ++ *impp = NULL; ++} ++#elif _WIN32 ++static isc_result_t ++load_symbol(HMODULE handle, const char *filename, ++ const char *symbol_name, void **symbolp) ++{ ++ void *symbol; ++ ++ REQUIRE(handle != NULL); ++ REQUIRE(symbolp != NULL && *symbolp == NULL); ++ ++ symbol = GetProcAddress(handle, symbol_name); ++ if (symbol == NULL) { ++ int errstatus = GetLastError(); ++ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, ++ DNS_LOGMODULE_DYNDB, ISC_LOG_ERROR, ++ "failed to lookup symbol %s in " ++ "dyndb module '%s': %d", ++ symbol_name, filename, errstatus); ++ return (ISC_R_FAILURE); ++ } ++ ++ *symbolp = symbol; ++ ++ return (ISC_R_SUCCESS); ++} ++ ++static isc_result_t ++load_library(isc_mem_t *mctx, const char *filename, const char *instname, ++ dyndb_implementation_t **impp) ++{ ++ isc_result_t result; ++ HMODULE handle; ++ dyndb_implementation_t *imp = NULL; ++ dns_dyndb_register_t *register_func = NULL; ++ dns_dyndb_destroy_t *destroy_func = NULL; ++ dns_dyndb_version_t *version_func = NULL; ++ int version; ++ ++ REQUIRE(impp != NULL && *impp == NULL); ++ ++ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, ++ DNS_LOGMODULE_DYNDB, ISC_LOG_INFO, ++ "loading DynDB instance '%s' driver '%s'", ++ instname, filename); ++ ++ handle = LoadLibraryA(filename); ++ if (handle == NULL) ++ CHECK(ISC_R_FAILURE); ++ ++ CHECK(load_symbol(handle, filename, "dyndb_version", ++ (void **)&version_func)); ++ ++ version = version_func(NULL); ++ if (version < (DNS_DYNDB_VERSION - DNS_DYNDB_AGE) || ++ version > DNS_DYNDB_VERSION) ++ { ++ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, ++ DNS_LOGMODULE_DYNDB, ISC_LOG_ERROR, ++ "driver API version mismatch: %d/%d", ++ version, DNS_DYNDB_VERSION); ++ CHECK(ISC_R_FAILURE); ++ } ++ ++ CHECK(load_symbol(handle, filename, "dyndb_init", ++ (void **)®ister_func)); ++ CHECK(load_symbol(handle, filename, "dyndb_destroy", ++ (void **)&destroy_func)); ++ ++ imp = isc_mem_get(mctx, sizeof(dyndb_implementation_t)); ++ if (imp == NULL) ++ CHECK(ISC_R_NOMEMORY); ++ ++ imp->mctx = NULL; ++ isc_mem_attach(mctx, &imp->mctx); ++ imp->handle = handle; ++ imp->register_func = register_func; ++ imp->destroy_func = destroy_func; ++ imp->name = isc_mem_strdup(mctx, instname); ++ if (imp->name == NULL) ++ CHECK(ISC_R_NOMEMORY); ++ ++ imp->inst = NULL; ++ INIT_LINK(imp, link); ++ ++ *impp = imp; ++ imp = NULL; ++ ++cleanup: ++ if (result != ISC_R_SUCCESS) ++ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, ++ DNS_LOGMODULE_DYNDB, ISC_LOG_ERROR, ++ "failed to dynamically load instance '%s' " ++ "driver '%s': %d (%s)", instname, filename, ++ GetLastError(), isc_result_totext(result)); ++ if (imp != NULL) ++ isc_mem_putanddetach(&imp->mctx, imp, sizeof(dyndb_implementation_t)); ++ if (result != ISC_R_SUCCESS && handle != NULL) ++ FreeLibrary(handle); ++ ++ return (result); ++} ++ ++static void ++unload_library(dyndb_implementation_t **impp) { ++ dyndb_implementation_t *imp; ++ ++ REQUIRE(impp != NULL && *impp != NULL); ++ ++ imp = *impp; ++ ++ isc_mem_free(imp->mctx, imp->name); ++ isc_mem_putanddetach(&imp->mctx, imp, sizeof(dyndb_implementation_t)); ++ ++ *impp = NULL; ++} ++#else /* HAVE_DLFCN_H || _WIN32 */ ++static isc_result_t ++load_library(isc_mem_t *mctx, const char *filename, const char *instname, ++ dyndb_implementation_t **impp) ++{ ++ UNUSED(mctx); ++ UNUSED(filename); ++ UNUSED(instname); ++ UNUSED(impp); ++ ++ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DYNDB, ++ ISC_LOG_ERROR, ++ "dynamic database support is not implemented") ++ ++ return (ISC_R_NOTIMPLEMENTED); ++} ++ ++static void ++unload_library(dyndb_implementation_t **impp) ++{ ++ dyndb_implementation_t *imp; ++ ++ REQUIRE(impp != NULL && *impp != NULL); ++ ++ imp = *impp; ++ ++ if (imp->handle != NULL) ++ dlclose(imp->handle); ++ ++ isc_mem_putanddetach(&imp->mctx, imp, sizeof(dyndb_implementation_t)); ++ ++ *impp = NULL; ++} ++#endif /* HAVE_DLFCN_H */ ++ ++isc_result_t ++dns_dyndb_load(const char *libname, const char *name, const char *parameters, ++ const char *file, unsigned long line, isc_mem_t *mctx, ++ const dns_dyndbctx_t *dctx) ++{ ++ isc_result_t result; ++ dyndb_implementation_t *implementation = NULL; ++ ++ REQUIRE(DNS_DYNDBCTX_VALID(dctx)); ++ REQUIRE(name != NULL); ++ ++ RUNTIME_CHECK(isc_once_do(&once, dyndb_initialize) == ISC_R_SUCCESS); ++ ++ LOCK(&dyndb_lock); ++ ++ /* duplicate instance names are not allowed */ ++ if (impfind(name) != NULL) ++ CHECK(ISC_R_EXISTS); ++ ++ CHECK(load_library(mctx, libname, name, &implementation)); ++ CHECK(implementation->register_func(mctx, name, parameters, file, line, ++ dctx, &implementation->inst)); ++ ++ APPEND(dyndb_implementations, implementation, link); ++ result = ISC_R_SUCCESS; ++ ++cleanup: ++ if (result != ISC_R_SUCCESS) ++ if (implementation != NULL) ++ unload_library(&implementation); ++ ++ UNLOCK(&dyndb_lock); ++ return (result); ++} ++ ++void ++dns_dyndb_cleanup(isc_boolean_t exiting) { ++ dyndb_implementation_t *elem; ++ dyndb_implementation_t *prev; ++ ++ RUNTIME_CHECK(isc_once_do(&once, dyndb_initialize) == ISC_R_SUCCESS); ++ ++ LOCK(&dyndb_lock); ++ elem = TAIL(dyndb_implementations); ++ while (elem != NULL) { ++ prev = PREV(elem, link); ++ UNLINK(dyndb_implementations, elem, link); ++ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, ++ DNS_LOGMODULE_DYNDB, ISC_LOG_INFO, ++ "unloading DynDB instance '%s'", elem->name); ++ elem->destroy_func(&elem->inst); ++ ENSURE(elem->inst == NULL); ++ unload_library(&elem); ++ elem = prev; ++ } ++ UNLOCK(&dyndb_lock); ++ ++ if (exiting == ISC_TRUE) ++ isc_mutex_destroy(&dyndb_lock); ++} ++ ++isc_result_t ++dns_dyndb_createctx(isc_mem_t *mctx, isc_hash_t *hctx, isc_log_t *lctx, ++ dns_view_t *view, dns_zonemgr_t *zmgr, ++ isc_task_t *task, isc_timermgr_t *tmgr, ++ dns_dyndbctx_t **dctxp) { ++ dns_dyndbctx_t *dctx; ++ ++ REQUIRE(dctxp != NULL && *dctxp == NULL); ++ ++ dctx = isc_mem_get(mctx, sizeof(*dctx)); ++ if (dctx == NULL) ++ return (ISC_R_NOMEMORY); ++ ++ memset(dctx, 0, sizeof(*dctx)); ++ if (view != NULL) ++ dns_view_attach(view, &dctx->view); ++ if (zmgr != NULL) ++ dns_zonemgr_attach(zmgr, &dctx->zmgr); ++ if (task != NULL) ++ isc_task_attach(task, &dctx->task); ++ dctx->timermgr = tmgr; ++ dctx->hctx = hctx; ++ dctx->lctx = lctx; ++ dctx->refvar = &isc_lctx; ++ ++ isc_mem_attach(mctx, &dctx->mctx); ++ dctx->magic = DNS_DYNDBCTX_MAGIC; ++ ++ *dctxp = dctx; ++ ++ return (ISC_R_SUCCESS); ++} ++ ++void ++dns_dyndb_destroyctx(dns_dyndbctx_t **dctxp) { ++ dns_dyndbctx_t *dctx; ++ ++ REQUIRE(dctxp != NULL && DNS_DYNDBCTX_VALID(*dctxp)); ++ ++ dctx = *dctxp; ++ *dctxp = NULL; ++ ++ dctx->magic = 0; ++ ++ if (dctx->view != NULL) ++ dns_view_detach(&dctx->view); ++ if (dctx->zmgr != NULL) ++ dns_zonemgr_detach(&dctx->zmgr); ++ if (dctx->task != NULL) ++ isc_task_detach(&dctx->task); ++ dctx->timermgr = NULL; ++ dctx->lctx = NULL; ++ ++ isc_mem_putanddetach(&dctx->mctx, dctx, sizeof(*dctx)); ++} +diff --git a/lib/dns/include/dns/Makefile.in b/lib/dns/include/dns/Makefile.in +index 832db46..a37b35e 100644 +--- a/lib/dns/include/dns/Makefile.in ++++ b/lib/dns/include/dns/Makefile.in +@@ -23,8 +23,8 @@ top_srcdir = @top_srcdir@ + + HEADERS = acl.h adb.h byaddr.h cache.h callbacks.h cert.h compress.h \ + clientinfo.h db.h dbiterator.h dbtable.h diff.h dispatch.h \ +- dlz.h dnssec.h ds.h events.h fixedname.h iptable.h journal.h \ +- keyflags.h keytable.h keyvalues.h lib.h log.h \ ++ dlz.h dyndb.h dnssec.h ds.h events.h fixedname.h iptable.h \ ++ journal.h keyflags.h keytable.h keyvalues.h lib.h log.h \ + master.h masterdump.h message.h name.h ncache.h nsec.h \ + peer.h portlist.h private.h rbt.h rcode.h \ + rdata.h rdataclass.h rdatalist.h rdataset.h rdatasetiter.h \ +diff --git a/lib/dns/include/dns/dyndb.h b/lib/dns/include/dns/dyndb.h +new file mode 100644 +index 0000000..832ff27 +--- /dev/null ++++ b/lib/dns/include/dns/dyndb.h +@@ -0,0 +1,166 @@ ++/* ++ * Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC") ++ * 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 AUTHORS DISCLAIM ALL WARRANTIES WITH ++ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY ++ * AND FITNESS. IN NO EVENT SHALL AUTHORS 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. ++ */ ++ ++#ifndef DNS_DYNDB_H ++#define DNS_DYNDB_H ++ ++#include ++ ++#include ++ ++ISC_LANG_BEGINDECLS ++ ++/*! ++ * \brief ++ * Context for intializing a dyndb module. ++ * ++ * This structure passes pointers to globals to which a dyndb ++ * module will need access -- the server memory context, hash ++ * context, log context, etc. The structure doesn't persist ++ * beyond configuring the dyndb module. The module's register function ++ * should attach to all reference-counted variables and its destroy ++ * function should detach from them. ++ */ ++struct dns_dyndbctx { ++ unsigned int magic; ++ isc_mem_t *mctx; ++ isc_hash_t *hctx; ++ isc_log_t *lctx; ++ dns_view_t *view; ++ dns_zonemgr_t *zmgr; ++ isc_task_t *task; ++ isc_timermgr_t *timermgr; ++ void *refvar; ++}; ++ ++#define DNS_DYNDBCTX_MAGIC ISC_MAGIC('D', 'd', 'b', 'c') ++#define DNS_DYNDBCTX_VALID(d) ISC_MAGIC_VALID(d, DNS_DYNDBCTX_MAGIC) ++ ++/* ++ * API version ++ * ++ * When the API changes, increment DNS_DYNDB_VERSION. If the ++ * change is backward-compatible (e.g., adding a new function call ++ * but not changing or removing an old one), increment DNS_DYNDB_AGE; ++ * if not, set DNS_DYNDB_AGE to 0. ++ */ ++#ifndef DNS_DYNDB_VERSION ++#define DNS_DYNDB_VERSION 1 ++#define DNS_DYNDB_AGE 0 ++#endif ++ ++typedef isc_result_t dns_dyndb_register_t(isc_mem_t *mctx, ++ const char *name, ++ const char *parameters, ++ const char *file, ++ unsigned long line, ++ const dns_dyndbctx_t *dctx, ++ void **instp); ++/*% ++ * Called when registering a new driver instance. 'name' must be unique. ++ * 'parameters' contains the driver configuration text. 'dctx' is the ++ * initialization context set up in dns_dyndb_createctx(). ++ * ++ * '*instp' must be set to the driver instance handle if the functino ++ * is successful. ++ * ++ * Returns: ++ *\li #ISC_R_SUCCESS ++ *\li #ISC_R_NOMEMORY ++ *\li Other errors are possible ++ */ ++ ++typedef void dns_dyndb_destroy_t(void **instp); ++/*% ++ * Destroy a driver instance. Dereference any reference-counted ++ * variables passed in 'dctx' and 'inst' in the register function. ++ * ++ * \c *instp must be set to \c NULL by the function before it returns. ++ */ ++ ++typedef int dns_dyndb_version_t(unsigned int *flags); ++/*% ++ * Return the API version number a dyndb module was compiled with. ++ * ++ * If the returned version number is no greater than than ++ * DNS_DYNDB_VERSION, and no less than DNS_DYNDB_VERSION - DNS_DYNDB_AGE, ++ * then the module is API-compatible with named. ++ * ++ * 'flags' is currently unused and may be NULL, but could be used in ++ * the future to pass back driver capabilities or other information. ++ */ ++ ++isc_result_t ++dns_dyndb_load(const char *libname, const char *name, const char *parameters, ++ const char *file, unsigned long line, isc_mem_t *mctx, ++ const dns_dyndbctx_t *dctx); ++/*% ++ * Load a dyndb module. ++ * ++ * This loads a dyndb module using dlopen() or equivalent, calls its register ++ * function (see dns_dyndb_register_t above), and if successful, adds ++ * the instance handle to a list of dyndb instances so it can be cleaned ++ * up later. ++ * ++ * 'file' and 'line' can be used to indicate the name of the file and ++ * the line number from which the parameters were taken, so that logged ++ * error messages, if any, will display the correct locations. ++ * ++ * Returns: ++ *\li #ISC_R_SUCCESS ++ *\li #ISC_R_NOMEMORY ++ *\li Other errors are possible ++ */ ++ ++void ++dns_dyndb_cleanup(isc_boolean_t exiting); ++/*% ++ * Shut down and destroy all running dyndb modules. ++ * ++ * 'exiting' indicates whether the server is shutting down, ++ * as opposed to merely being reconfigured. ++ */ ++ ++isc_result_t ++dns_dyndb_createctx(isc_mem_t *mctx, isc_hash_t *hctx, isc_log_t *lctx, ++ dns_view_t *view, dns_zonemgr_t *zmgr, ++ isc_task_t *task, isc_timermgr_t *tmgr, ++ dns_dyndbctx_t **dctxp); ++/*% ++ * Create a dyndb initialization context structure, with ++ * pointers to structures in the server that the dyndb module will ++ * need to access (view, zone manager, memory context, hash context, ++ * etc). This structure is expected to last only until all dyndb ++ * modules have been loaded and initialized; after that it will be ++ * destroyed with dns_dyndb_destroyctx(). ++ * ++ * Returns: ++ *\li #ISC_R_SUCCESS ++ *\li #ISC_R_NOMEMORY ++ *\li Other errors are possible ++ */ ++ ++void ++dns_dyndb_destroyctx(dns_dyndbctx_t **dctxp); ++/*% ++ * Destroys a dyndb initialization context structure; all ++ * reference-counted members are detached and the structure is freed. ++ */ ++ ++ISC_LANG_ENDDECLS ++ ++#endif /* DNS_DYNDB_H */ +diff --git a/lib/dns/include/dns/log.h b/lib/dns/include/dns/log.h +index e8c8c10..a3b7e5a 100644 +--- a/lib/dns/include/dns/log.h ++++ b/lib/dns/include/dns/log.h +@@ -77,6 +77,7 @@ LIBDNS_EXTERNAL_DATA extern isc_logmodule_t dns_modules[]; + #define DNS_LOGMODULE_DLZ (&dns_modules[26]) + #define DNS_LOGMODULE_DNSSEC (&dns_modules[27]) + #define DNS_LOGMODULE_CRYPTO (&dns_modules[28]) ++#define DNS_LOGMODULE_DYNDB (&dns_modules[29]) + + ISC_LANG_BEGINDECLS + +diff --git a/lib/dns/include/dns/types.h b/lib/dns/include/dns/types.h +index 76167c2..5dc03de 100644 +--- a/lib/dns/include/dns/types.h ++++ b/lib/dns/include/dns/types.h +@@ -60,6 +60,7 @@ typedef struct dns_dbtable dns_dbtable_t; + typedef void dns_dbversion_t; + typedef struct dns_dlzimplementation dns_dlzimplementation_t; + typedef struct dns_dlzdb dns_dlzdb_t; ++typedef struct dns_dyndbctx dns_dyndbctx_t; + typedef struct dns_sdlzimplementation dns_sdlzimplementation_t; + typedef struct dns_decompress dns_decompress_t; + typedef struct dns_dispatch dns_dispatch_t; +diff --git a/lib/dns/lib.c b/lib/dns/lib.c +index df16fa2..da86efd 100644 +--- a/lib/dns/lib.c ++++ b/lib/dns/lib.c +@@ -160,7 +160,9 @@ dns_lib_shutdown(void) { + return; + + dst_lib_destroy(); +- isc_hash_destroy(); ++ ++ if (isc_hashctx != NULL) ++ isc_hash_destroy(); + #ifndef BIND9 + dns_ecdb_unregister(&dbimp); + #endif +diff --git a/lib/dns/log.c b/lib/dns/log.c +index 75e0d79..ff9ca65 100644 +--- a/lib/dns/log.c ++++ b/lib/dns/log.c +@@ -83,6 +83,7 @@ LIBDNS_EXTERNAL_DATA isc_logmodule_t dns_modules[] = { + { "dns/dlz", 0 }, + { "dns/dnssec", 0 }, + { "dns/crypto", 0 }, ++ { "dns/dyndb", 0 }, + { NULL, 0 } + }; + +diff --git a/lib/dns/win32/libdns.def b/lib/dns/win32/libdns.def +index 7661f80..5e20491 100644 +--- a/lib/dns/win32/libdns.def ++++ b/lib/dns/win32/libdns.def +@@ -230,6 +230,10 @@ dns_dnsseckey_destroy + dns_ds_buildrdata + dns_ds_digest_supported + dns_dumpctx_detach ++dns_dyndb_load ++dns_dyndb_cleanup ++dns_dyndb_createctx ++dns_dyndb_destroyctx + dns_fwdtable_add + dns_fwdtable_create + dns_fwdtable_destroy +diff --git a/lib/export/isc/Makefile.in b/lib/export/isc/Makefile.in +index a5f8bd0..4f4a9f7 100644 +--- a/lib/export/isc/Makefile.in ++++ b/lib/export/isc/Makefile.in +@@ -64,8 +64,8 @@ WIN32OBJS = win32/condition.@O@ win32/dir.@O@ win32/file.@O@ \ + # Alphabetically + OBJS = @ISC_EXTRA_OBJS@ \ + assertions.@O@ backtrace.@O@ backtrace-emptytbl.@O@ base32.@O@ \ +- base64.@O@ buffer.@O@ bufferlist.@O@ counter.@O@ \ +- error.@O@ event.@O@ \ ++ base64.@O@ buffer.@O@ bufferlist.@O@ commandline.@O@ \ ++ counter.@O@ error.@O@ event.@O@ \ + hash.@O@ hex.@O@ hmacmd5.@O@ hmacsha.@O@ \ + inet_aton.@O@ iterated_hash.@O@ lex.@O@ lfsr.@O@ log.@O@ \ + md5.@O@ mutexblock.@O@ netaddr.@O@ netscope.@O@ \ +@@ -86,7 +86,7 @@ ISCDRIVERSRCS = mem.c task.c lib.c timer.c heap.c + + SRCS = @ISC_EXTRA_SRCS@ \ + assertions.c backtrace.c backtrace-emptytbl.c base32.c \ +- base64.c buffer.c bufferlist.c counter.c \ ++ base64.c buffer.c bufferlist.c counter.c commandline.c \ + error.c event.c \ + hash.c hex.c hmacmd5.c hmacsha.c \ + inet_aton.c iterated_hash.c lex.c log.c lfsr.c \ +diff --git a/lib/isc/Makefile.in b/lib/isc/Makefile.in +index df62ec9..4d3a0af 100644 +--- a/lib/isc/Makefile.in ++++ b/lib/isc/Makefile.in +@@ -37,7 +37,7 @@ CWARNINGS = + + # Alphabetically + UNIXOBJS = @ISC_ISCIPV6_O@ @ISC_ISCPK11_API_O@ \ +- unix/app.@O@ unix/dir.@O@ unix/entropy.@O@ \ ++ unix/app.@O@ unix/dir.@O@ unix/entropy.@O@ unix/errno.@O@ \ + unix/errno2result.@O@ unix/file.@O@ unix/fsaccess.@O@ \ + unix/interfaceiter.@O@ unix/keyboard.@O@ unix/net.@O@ \ + unix/os.@O@ unix/resource.@O@ unix/socket.@O@ unix/stdio.@O@ \ +@@ -49,9 +49,9 @@ THREADOPTOBJS = @ISC_THREAD_DIR@/condition.@O@ @ISC_THREAD_DIR@/mutex.@O@ + + THREADOBJS = @THREADOPTOBJS@ @ISC_THREAD_DIR@/thread.@O@ + +-WIN32OBJS = win32/condition.@O@ win32/dir.@O@ win32/file.@O@ \ +- win32/fsaccess.@O@ win32/once.@O@ win32/stdtime.@O@ \ +- win32/thread.@O@ win32/time.@O@ ++WIN32OBJS = win32/condition.@O@ win32/dir.@O@ win32/errno.@O@ \ ++ win32/file.@O@ win32/fsaccess.@O@ win32/once.@O@ \ ++ win32/stdtime.@O@ win32/thread.@O@ win32/time.@O@ + + # Alphabetically + OBJS = @ISC_EXTRA_OBJS@ @ISC_PK11_O@ @ISC_PK11_RESULT_O@ \ +diff --git a/lib/isc/commandline.c b/lib/isc/commandline.c +index aca1203..26ad23c 100644 +--- a/lib/isc/commandline.c ++++ b/lib/isc/commandline.c +@@ -68,6 +68,7 @@ + #include + + #include ++#include + #include + #include + #include +@@ -223,3 +224,62 @@ isc_commandline_parse(int argc, char * const *argv, const char *options) { + + return (isc_commandline_option); + } ++ ++isc_result_t ++isc_commandline_strtoargv(isc_mem_t *mctx, char *s, unsigned int *argcp, ++ char ***argvp, unsigned int n) ++{ ++ isc_result_t result; ++ ++ restart: ++ /* Discard leading whitespace. */ ++ while (*s == ' ' || *s == '\t') ++ s++; ++ ++ if (*s == '\0') { ++ /* We have reached the end of the string. */ ++ *argcp = n; ++ *argvp = isc_mem_get(mctx, n * sizeof(char *)); ++ if (*argvp == NULL) ++ return (ISC_R_NOMEMORY); ++ } else { ++ char *p = s; ++ while (*p != ' ' && *p != '\t' && *p != '\0' && *p != '{') { ++ if (*p == '\n') { ++ *p = ' '; ++ goto restart; ++ } ++ p++; ++ } ++ ++ /* do "grouping", items between { and } are one arg */ ++ if (*p == '{') { ++ char *t = p; ++ /* ++ * shift all characters to left by 1 to get rid of '{' ++ */ ++ while (*t != '\0') { ++ t++; ++ *(t-1) = *t; ++ } ++ while (*p != '\0' && *p != '}') { ++ p++; ++ } ++ /* get rid of '}' character */ ++ if (*p == '}') { ++ *p = '\0'; ++ p++; ++ } ++ /* normal case, no "grouping" */ ++ } else if (*p != '\0') ++ *p++ = '\0'; ++ ++ result = isc_commandline_strtoargv(mctx, p, ++ argcp, argvp, n + 1); ++ if (result != ISC_R_SUCCESS) ++ return (result); ++ (*argvp)[n] = s; ++ } ++ ++ return (ISC_R_SUCCESS); ++} +diff --git a/lib/isc/hash.c b/lib/isc/hash.c +index f1d68c7..c3712e6 100644 +--- a/lib/isc/hash.c ++++ b/lib/isc/hash.c +@@ -15,8 +15,6 @@ + * PERFORMANCE OF THIS SOFTWARE. + */ + +-/* $Id: hash.c,v 1.16 2009/09/01 00:22:28 jinmei Exp $ */ +- + /*! \file + * Some portion of this code was derived from universal hash function + * libraries of Rice University. +@@ -101,7 +99,8 @@ struct isc_hash { + + static isc_mutex_t createlock; + static isc_once_t once = ISC_ONCE_INIT; +-static isc_hash_t *hash = NULL; ++ ++LIBISC_EXTERNAL_DATA isc_hash_t *isc_hashctx = NULL; + + static unsigned char maptolower[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, +@@ -224,14 +223,15 @@ isc_hash_create(isc_mem_t *mctx, isc_entropy_t *entropy, size_t limit) { + isc_result_t result = ISC_R_SUCCESS; + + REQUIRE(mctx != NULL); +- INSIST(hash == NULL); ++ INSIST(isc_hashctx == NULL); + + RUNTIME_CHECK(isc_once_do(&once, initialize_lock) == ISC_R_SUCCESS); + + LOCK(&createlock); + +- if (hash == NULL) +- result = isc_hash_ctxcreate(mctx, entropy, limit, &hash); ++ if (isc_hashctx == NULL) ++ result = isc_hash_ctxcreate(mctx, entropy, limit, ++ &isc_hashctx); + + UNLOCK(&createlock); + +@@ -283,9 +283,9 @@ isc_hash_ctxinit(isc_hash_t *hctx) { + + void + isc_hash_init() { +- INSIST(hash != NULL && VALID_HASH(hash)); ++ INSIST(isc_hashctx != NULL && VALID_HASH(isc_hashctx)); + +- isc_hash_ctxinit(hash); ++ isc_hash_ctxinit(isc_hashctx); + } + + void +@@ -350,12 +350,12 @@ void + isc_hash_destroy() { + unsigned int refs; + +- INSIST(hash != NULL && VALID_HASH(hash)); ++ INSIST(isc_hashctx != NULL && VALID_HASH(isc_hashctx)); + +- isc_refcount_decrement(&hash->refcnt, &refs); ++ isc_refcount_decrement(&isc_hashctx->refcnt, &refs); + INSIST(refs == 0); + +- destroy(&hash); ++ destroy(&isc_hashctx); + } + + static inline unsigned int +@@ -397,8 +397,8 @@ unsigned int + isc_hash_calc(const unsigned char *key, unsigned int keylen, + isc_boolean_t case_sensitive) + { +- INSIST(hash != NULL && VALID_HASH(hash)); +- REQUIRE(keylen <= hash->limit); ++ INSIST(isc_hashctx != NULL && VALID_HASH(isc_hashctx)); ++ REQUIRE(keylen <= isc_hashctx->limit); + +- return (hash_calc(hash, key, keylen, case_sensitive)); ++ return (hash_calc(isc_hashctx, key, keylen, case_sensitive)); + } +diff --git a/lib/isc/include/isc/Makefile.in b/lib/isc/include/isc/Makefile.in +index 38af3f9..7ca1170 100644 +--- a/lib/isc/include/isc/Makefile.in ++++ b/lib/isc/include/isc/Makefile.in +@@ -27,8 +27,8 @@ top_srcdir = @top_srcdir@ + # install target below. + # + HEADERS = app.h assertions.h base64.h bind9.h bitstring.h boolean.h \ +- buffer.h bufferlist.h commandline.h counter.h entropy.h error.h event.h \ +- eventclass.h file.h formatcheck.h fsaccess.h \ ++ buffer.h bufferlist.h commandline.h counter.h entropy.h errno.h \ ++ error.h event.h eventclass.h file.h formatcheck.h fsaccess.h \ + hash.h heap.h hex.h hmacmd5.h hmacsha.h \ + httpd.h \ + interfaceiter.h @ISC_IPV6_H@ iterated_hash.h lang.h lex.h \ +diff --git a/lib/isc/include/isc/commandline.h b/lib/isc/include/isc/commandline.h +index 384640a..d35ccbf 100644 +--- a/lib/isc/include/isc/commandline.h ++++ b/lib/isc/include/isc/commandline.h +@@ -15,8 +15,6 @@ + * PERFORMANCE OF THIS SOFTWARE. + */ + +-/* $Id: commandline.h,v 1.16 2007/06/19 23:47:18 tbox Exp $ */ +- + #ifndef ISC_COMMANDLINE_H + #define ISC_COMMANDLINE_H 1 + +@@ -25,6 +23,7 @@ + #include + #include + #include ++#include + + /*% Index into parent argv vector. */ + LIBISC_EXTERNAL_DATA extern int isc_commandline_index; +@@ -41,9 +40,22 @@ LIBISC_EXTERNAL_DATA extern isc_boolean_t isc_commandline_reset; + + ISC_LANG_BEGINDECLS + +-/*% parse command line */ + int + isc_commandline_parse(int argc, char * const *argv, const char *options); ++/*%< ++ * Parse a command line (similar to getopt()) ++ */ ++ ++isc_result_t ++isc_commandline_strtoargv(isc_mem_t *mctx, char *s, unsigned int *argcp, ++ char ***argvp, unsigned int n); ++/*%< ++ * Tokenize the string "s" into whitespace-separated words, ++ * returning the number of words in '*argcp' and an array ++ * of pointers to the words in '*argvp'. The caller ++ * must free the array using isc_mem_free(). The string ++ * is modified in-place. ++ */ + + ISC_LANG_ENDDECLS + +diff --git a/lib/isc/include/isc/errno.h b/lib/isc/include/isc/errno.h +new file mode 100644 +index 0000000..47ec90f +--- /dev/null ++++ b/lib/isc/include/isc/errno.h +@@ -0,0 +1,25 @@ ++/* ++ * Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC") ++ * ++ * This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this ++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. ++ */ ++ ++#ifndef ISC_ERRNO_H ++#define ISC_ERRNO_H 1 ++ ++/*! \file isc/file.h */ ++ ++#include ++ ++ISC_LANG_BEGINDECLS ++ ++isc_result_t ++isc_errno_toresult(int err); ++/*!< ++ * \brief Convert a POSIX errno value to an ISC result code. ++ */ ++ISC_LANG_ENDDECLS ++ ++#endif /* ISC_ERRNO_H */ +diff --git a/lib/isc/include/isc/hash.h b/lib/isc/include/isc/hash.h +index ca04b4e..5ef1e4c 100644 +--- a/lib/isc/include/isc/hash.h ++++ b/lib/isc/include/isc/hash.h +@@ -15,8 +15,6 @@ + * PERFORMANCE OF THIS SOFTWARE. + */ + +-/* $Id: hash.h,v 1.12 2009/01/17 23:47:43 tbox Exp $ */ +- + #ifndef ISC_HASH_H + #define ISC_HASH_H 1 + +@@ -81,6 +79,8 @@ + ***/ + ISC_LANG_BEGINDECLS + ++LIBDNS_EXTERNAL_DATA extern isc_hash_t *isc_hashctx; ++ + isc_result_t + isc_hash_ctxcreate(isc_mem_t *mctx, isc_entropy_t *entropy, unsigned int limit, + isc_hash_t **hctx); +diff --git a/lib/isc/include/isc/lex.h b/lib/isc/include/isc/lex.h +index 8612150..6ce1465 100644 +--- a/lib/isc/include/isc/lex.h ++++ b/lib/isc/include/isc/lex.h +@@ -90,6 +90,7 @@ ISC_LANG_BEGINDECLS + #define ISC_LEXOPT_ESCAPE 0x100 /*%< Recognize escapes. */ + #define ISC_LEXOPT_QSTRINGMULTILINE 0x200 /*%< Allow multiline "" strings */ + #define ISC_LEXOPT_OCTAL 0x400 /*%< Expect a octal number. */ ++#define ISC_LEXOPT_BTEXT 0x800 /*%< Bracketed text. */ + /*@}*/ + /*@{*/ + /*! +@@ -122,7 +123,8 @@ typedef enum { + isc_tokentype_eof = 5, + isc_tokentype_initialws = 6, + isc_tokentype_special = 7, +- isc_tokentype_nomore = 8 ++ isc_tokentype_nomore = 8, ++ isc_tokentype_btext = 8 + } isc_tokentype_t; + + typedef union { +@@ -412,6 +414,23 @@ isc_lex_setsourcename(isc_lex_t *lex, const char *name); + * \li #ISC_R_NOTFOUND - there are no sources. + */ + ++isc_result_t ++isc_lex_setsourceline(isc_lex_t *lex, unsigned long line); ++/*%< ++ * Assigns a new line number to the input source. This can be used ++ * when parsing a buffer that's been excerpted from the middle a file, ++ * allowing logged messages to display the correct line number, ++ * rather than the line number within the buffer. ++ * ++ * Requires: ++ * ++ * \li 'lex' is a valid lexer. ++ * ++ * Returns: ++ * \li #ISC_R_SUCCESS ++ * \li #ISC_R_NOTFOUND - there are no sources. ++ */ ++ + isc_boolean_t + isc_lex_isfile(isc_lex_t *lex); + /*%< +diff --git a/lib/isc/lex.c b/lib/isc/lex.c +index 1dc2332..46fec84 100644 +--- a/lib/isc/lex.c ++++ b/lib/isc/lex.c +@@ -62,6 +62,7 @@ struct isc_lex { + unsigned int comments; + isc_boolean_t comment_ok; + isc_boolean_t last_was_eol; ++ unsigned int brace_count; + unsigned int paren_count; + unsigned int saved_paren_count; + isc_lexspecials_t specials; +@@ -110,6 +111,7 @@ isc_lex_create(isc_mem_t *mctx, size_t max_token, isc_lex_t **lexp) { + lex->comments = 0; + lex->comment_ok = ISC_TRUE; + lex->last_was_eol = ISC_TRUE; ++ lex->brace_count = 0; + lex->paren_count = 0; + lex->saved_paren_count = 0; + memset(lex->specials, 0, 256); +@@ -309,7 +311,8 @@ typedef enum { + lexstate_ccomment, + lexstate_ccommentend, + lexstate_eatline, +- lexstate_qstring ++ lexstate_qstring, ++ lexstate_btext + } lexstate; + + #define IWSEOL (ISC_LEXOPT_INITIALWS | ISC_LEXOPT_EOL) +@@ -392,10 +395,17 @@ isc_lex_gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *tokenp) { + source->at_eof) + { + if ((options & ISC_LEXOPT_DNSMULTILINE) != 0 && +- lex->paren_count != 0) { ++ lex->paren_count != 0) ++ { + lex->paren_count = 0; + return (ISC_R_UNBALANCED); + } ++ if ((options & ISC_LEXOPT_BTEXT) != 0 && ++ lex->brace_count != 0) ++ { ++ lex->brace_count = 0; ++ return (ISC_R_UNBALANCED); ++ } + if ((options & ISC_LEXOPT_EOF) != 0) { + tokenp->type = isc_tokentype_eof; + return (ISC_R_SUCCESS); +@@ -507,6 +517,12 @@ isc_lex_gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *tokenp) { + result = ISC_R_UNBALANCED; + goto done; + } ++ if ((options & ISC_LEXOPT_BTEXT) != 0 && ++ lex->brace_count != 0) { ++ lex->brace_count = 0; ++ result = ISC_R_UNBALANCED; ++ goto done; ++ } + if ((options & ISC_LEXOPT_EOF) == 0) { + result = ISC_R_EOF; + goto done; +@@ -539,21 +555,34 @@ isc_lex_gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *tokenp) { + } else if (lex->specials[c]) { + lex->last_was_eol = ISC_FALSE; + if ((c == '(' || c == ')') && +- (options & ISC_LEXOPT_DNSMULTILINE) != 0) { ++ (options & ISC_LEXOPT_DNSMULTILINE) != 0) ++ { + if (c == '(') { + if (lex->paren_count == 0) + options &= ~IWSEOL; + lex->paren_count++; + } else { + if (lex->paren_count == 0) { +- result = ISC_R_UNBALANCED; +- goto done; ++ result = ++ ISC_R_UNBALANCED; ++ goto done; + } + lex->paren_count--; + if (lex->paren_count == 0) +- options = +- saved_options; ++ options = saved_options; ++ } ++ continue; ++ } else if (c == '{' && ++ (options & ISC_LEXOPT_BTEXT) != 0) ++ { ++ if (lex->brace_count != 0) { ++ result = ISC_R_UNBALANCED; ++ goto done; + } ++ lex->brace_count++; ++ options &= ~IWSEOL; ++ state = lexstate_btext; ++ no_comments = ISC_TRUE; + continue; + } + tokenp->type = isc_tokentype_special; +@@ -769,6 +798,55 @@ isc_lex_gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *tokenp) { + remaining--; + } + break; ++ case lexstate_btext: ++ if (c == EOF) { ++ result = ISC_R_UNEXPECTEDEND; ++ goto done; ++ } ++ if (c == '{') { ++ if (escaped) { ++ escaped = ISC_FALSE; ++ } else { ++ lex->brace_count++; ++ } ++ } else if (c == '}') { ++ if (escaped) { ++ escaped = ISC_FALSE; ++ } else { ++ INSIST(lex->brace_count > 0); ++ lex->brace_count--; ++ } ++ ++ if (lex->brace_count == 0) { ++ tokenp->type = isc_tokentype_btext; ++ tokenp->value.as_textregion.base = ++ lex->data; ++ tokenp->value.as_textregion.length = ++ (unsigned int) (lex->max_token - ++ remaining); ++ no_comments = ISC_FALSE; ++ done = ISC_TRUE; ++ break; ++ } ++ } ++ ++ if (c == '\\' && !escaped) ++ escaped = ISC_TRUE; ++ else ++ escaped = ISC_FALSE; ++ ++ if (remaining == 0U) { ++ result = grow_data(lex, &remaining, ++ &curr, &prev); ++ if (result != ISC_R_SUCCESS) ++ goto done; ++ } ++ INSIST(remaining > 0U); ++ prev = curr; ++ *curr++ = c; ++ *curr = '\0'; ++ remaining--; ++ break; + default: + FATAL_ERROR(__FILE__, __LINE__, + isc_msgcat_get(isc_msgcat, ISC_MSGSET_LEX, +@@ -895,7 +973,6 @@ isc_lex_getlasttokentext(isc_lex_t *lex, isc_token_t *tokenp, isc_region_t *r) + source->ignored; + } + +- + char * + isc_lex_getsourcename(isc_lex_t *lex) { + inputsource *source; +@@ -922,7 +999,6 @@ isc_lex_getsourceline(isc_lex_t *lex) { + return (source->line); + } + +- + isc_result_t + isc_lex_setsourcename(isc_lex_t *lex, const char *name) { + inputsource *source; +@@ -932,7 +1008,7 @@ isc_lex_setsourcename(isc_lex_t *lex, const char *name) { + source = HEAD(lex->sources); + + if (source == NULL) +- return(ISC_R_NOTFOUND); ++ return (ISC_R_NOTFOUND); + newname = isc_mem_strdup(lex->mctx, name); + if (newname == NULL) + return (ISC_R_NOMEMORY); +@@ -941,6 +1017,20 @@ isc_lex_setsourcename(isc_lex_t *lex, const char *name) { + return (ISC_R_SUCCESS); + } + ++isc_result_t ++isc_lex_setsourceline(isc_lex_t *lex, unsigned long line) { ++ inputsource *source; ++ ++ REQUIRE(VALID_LEX(lex)); ++ source = HEAD(lex->sources); ++ ++ if (source == NULL) ++ return (ISC_R_NOTFOUND); ++ ++ source->line = line; ++ return (ISC_R_SUCCESS); ++} ++ + isc_boolean_t + isc_lex_isfile(isc_lex_t *lex) { + inputsource *source; +diff --git a/lib/isc/tests/Makefile.in b/lib/isc/tests/Makefile.in +index 564d3cd..f04396e 100644 +--- a/lib/isc/tests/Makefile.in ++++ b/lib/isc/tests/Makefile.in +@@ -12,8 +12,6 @@ + # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + # PERFORMANCE OF THIS SOFTWARE. + +-# $Id$ +- + srcdir = @srcdir@ + VPATH = @srcdir@ + top_srcdir = @top_srcdir@ +@@ -37,13 +35,14 @@ LIBS = @LIBS@ @ATFLIBS@ + OBJS = isctest.@O@ + SRCS = isctest.c taskpool_test.c socket_test.c hash_test.c \ + sockaddr_test.c symtab_test.c task_test.c queue_test.c \ +- parse_test.c pool_test.c regex_test.c safe_test.c ++ parse_test.c pool_test.c regex_test.c safe_test.c \ ++ errno_test.c + + SUBDIRS = + TARGETS = taskpool_test@EXEEXT@ socket_test@EXEEXT@ hash_test@EXEEXT@ \ + sockaddr_test@EXEEXT@ symtab_test@EXEEXT@ task_test@EXEEXT@ \ + queue_test@EXEEXT@ parse_test@EXEEXT@ pool_test@EXEEXT@ \ +- regex_test@EXEEXT@ safe_test@EXEEXT@ ++ regex_test@EXEEXT@ safe_test@EXEEXT@ errno_test@EXEEXT@ + + @BIND9_MAKE_RULES@ + +@@ -91,6 +90,10 @@ safe_test@EXEEXT@: safe_test.@O@ ${ISCDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + safe_test.@O@ ${ISCLIBS} ${LIBS} + ++ ++errno_test@EXEEXT@: errno_test.@O@ ${ISCDEPLIBS} ++ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ ++ errno_test.@O@ ${ISCLIBS} ${LIBS} + unit:: + sh ${top_srcdir}/unit/unittest.sh + +diff --git a/lib/isc/tests/errno_test.c b/lib/isc/tests/errno_test.c +new file mode 100644 +index 0000000..253a857 +--- /dev/null ++++ b/lib/isc/tests/errno_test.c +@@ -0,0 +1,102 @@ ++/* ++ * Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC") ++ * ++ * This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this ++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. ++ */ ++ ++#include ++ ++#include ++#include ++ ++#include ++ ++#include ++#include ++ ++typedef struct { ++ int err; ++ isc_result_t result; ++} testpair_t; ++ ++testpair_t testpair[] = { ++ { EPERM, ISC_R_NOPERM }, ++ { ENOENT, ISC_R_FILENOTFOUND }, ++ { EIO, ISC_R_IOERROR }, ++ { EBADF, ISC_R_INVALIDFILE }, ++ { ENOMEM, ISC_R_NOMEMORY }, ++ { EACCES, ISC_R_NOPERM }, ++ { EEXIST, ISC_R_FILEEXISTS }, ++ { ENOTDIR, ISC_R_INVALIDFILE }, ++ { EINVAL, ISC_R_INVALIDFILE }, ++ { ENFILE, ISC_R_TOOMANYOPENFILES }, ++ { EMFILE, ISC_R_TOOMANYOPENFILES }, ++ { EPIPE, ISC_R_CONNECTIONRESET }, ++ { ENAMETOOLONG, ISC_R_INVALIDFILE }, ++ { ELOOP, ISC_R_INVALIDFILE }, ++#ifdef EOVERFLOW ++ { EOVERFLOW, ISC_R_RANGE }, ++#endif ++#ifdef EAFNOSUPPORT ++ { EAFNOSUPPORT, ISC_R_FAMILYNOSUPPORT }, ++#endif ++#ifdef EADDRINUSE ++ { EADDRINUSE, ISC_R_ADDRINUSE }, ++#endif ++ { EADDRNOTAVAIL, ISC_R_ADDRNOTAVAIL }, ++#ifdef ENETDOWN ++ { ENETDOWN, ISC_R_NETDOWN }, ++#endif ++#ifdef ENETUNREACH ++ { ENETUNREACH, ISC_R_NETUNREACH }, ++#endif ++#ifdef ECONNABORTED ++ { ECONNABORTED, ISC_R_CONNECTIONRESET }, ++#endif ++#ifdef ECONNRESET ++ { ECONNRESET, ISC_R_CONNECTIONRESET }, ++#endif ++#ifdef ENOBUFS ++ { ENOBUFS, ISC_R_NORESOURCES }, ++#endif ++#ifdef ENOTCONN ++ { ENOTCONN, ISC_R_NOTCONNECTED }, ++#endif ++#ifdef ETIMEDOUT ++ { ETIMEDOUT, ISC_R_TIMEDOUT }, ++#endif ++ { ECONNREFUSED, ISC_R_CONNREFUSED }, ++#ifdef EHOSTDOWN ++ { EHOSTDOWN, ISC_R_HOSTDOWN }, ++#endif ++#ifdef EHOSTUNREACH ++ { EHOSTUNREACH, ISC_R_HOSTUNREACH }, ++#endif ++ { 0, ISC_R_UNEXPECTED } ++}; ++ ++ATF_TC(isc_errno_toresult); ++ATF_TC_HEAD(isc_errno_toresult, tc) { ++ atf_tc_set_md_var(tc, "descr", "convert errno to ISC result"); ++} ++ATF_TC_BODY(isc_errno_toresult, tc) { ++ isc_result_t result, expect; ++ size_t i; ++ ++ for (i = 0; i < sizeof(testpair)/sizeof(testpair[0]); i++) { ++ result = isc_errno_toresult(testpair[i].err); ++ expect = testpair[i].result; ++ ATF_CHECK(result == expect); ++ } ++} ++ ++/* ++ * Main ++ */ ++ATF_TP_ADD_TCS(tp) { ++ ATF_TP_ADD_TC(tp, isc_errno_toresult); ++ return (atf_no_error()); ++} ++ +diff --git a/lib/isc/unix/Makefile.in b/lib/isc/unix/Makefile.in +index 0595fa2..8f32119 100644 +--- a/lib/isc/unix/Makefile.in ++++ b/lib/isc/unix/Makefile.in +@@ -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.44 2009/12/05 23:31:41 each Exp $ +- + srcdir = @srcdir@ + VPATH = @srcdir@ + top_srcdir = @top_srcdir@ +@@ -30,14 +28,14 @@ CWARNINGS = + + # Alphabetically + OBJS = @ISC_IPV6_O@ @ISC_PK11_API_O@ \ +- app.@O@ dir.@O@ entropy.@O@ errno2result.@O@ file.@O@ \ +- fsaccess.@O@ interfaceiter.@O@ keyboard.@O@ net.@O@ \ ++ app.@O@ dir.@O@ entropy.@O@ errno.@O@ errno2result.@O@ \ ++ file.@O@ fsaccess.@O@ interfaceiter.@O@ keyboard.@O@ net.@O@ \ + os.@O@ resource.@O@ socket.@O@ stdio.@O@ stdtime.@O@ \ + strerror.@O@ syslog.@O@ time.@O@ + + # Alphabetically + SRCS = @ISC_IPV6_C@ @ISC_PK11_API_C@ \ +- app.c dir.c entropy.c errno2result.c file.c \ ++ app.c dir.c entropy.c errno.c errno2result.c file.c \ + fsaccess.c interfaceiter.c keyboard.c net.c \ + os.c resource.c socket.c stdio.c stdtime.c \ + strerror.c syslog.c time.c +diff --git a/lib/isc/unix/errno.c b/lib/isc/unix/errno.c +new file mode 100644 +index 0000000..c5f1c56 +--- /dev/null ++++ b/lib/isc/unix/errno.c +@@ -0,0 +1,21 @@ ++/* ++ * Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC") ++ * ++ * This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this ++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. ++ */ ++ ++/*! \file */ ++ ++#include ++ ++#include ++#include ++ ++#include "errno2result.h" ++ ++isc_result_t ++isc_errno_toresult(int err) { ++ return (isc___errno2result(err, ISC_FALSE, 0, 0)); ++} +diff --git a/lib/isc/unix/errno2result.c b/lib/isc/unix/errno2result.c +index 2951ef8..2309794 100644 +--- a/lib/isc/unix/errno2result.c ++++ b/lib/isc/unix/errno2result.c +@@ -34,7 +34,9 @@ + * not already there. + */ + isc_result_t +-isc___errno2result(int posixerrno, const char *file, unsigned int line) { ++isc___errno2result(int posixerrno, isc_boolean_t dolog, ++ const char *file, unsigned int line) ++{ + char strbuf[ISC_STRERRORSIZE]; + + switch (posixerrno) { +@@ -108,10 +110,12 @@ isc___errno2result(int posixerrno, const char *file, unsigned int line) { + case ECONNREFUSED: + return (ISC_R_CONNREFUSED); + default: +- isc__strerror(posixerrno, strbuf, sizeof(strbuf)); +- UNEXPECTED_ERROR(file, line, "unable to convert errno " +- "to isc_result: %d: %s", +- posixerrno, strbuf); ++ if (dolog) { ++ isc__strerror(posixerrno, strbuf, sizeof(strbuf)); ++ UNEXPECTED_ERROR(file, line, "unable to convert errno " ++ "to isc_result: %d: %s", ++ posixerrno, strbuf); ++ } + /* + * XXXDCL would be nice if perhaps this function could + * return the system's error string, so the caller +diff --git a/lib/isc/unix/errno2result.h b/lib/isc/unix/errno2result.h +index 1e49ed1..9c6b052 100644 +--- a/lib/isc/unix/errno2result.h ++++ b/lib/isc/unix/errno2result.h +@@ -15,8 +15,6 @@ + * PERFORMANCE OF THIS SOFTWARE. + */ + +-/* $Id$ */ +- + #ifndef UNIX_ERRNO2RESULT_H + #define UNIX_ERRNO2RESULT_H 1 + +@@ -31,10 +29,11 @@ + + ISC_LANG_BEGINDECLS + +-#define isc__errno2result(x) isc___errno2result(x, __FILE__, __LINE__) ++#define isc__errno2result(x) isc___errno2result(x, ISC_TRUE, __FILE__, __LINE__) + + isc_result_t +-isc___errno2result(int posixerrno, const char *file, unsigned int line); ++isc___errno2result(int posixerrno, isc_boolean_t dolog, ++ const char *file, unsigned int line); + + ISC_LANG_ENDDECLS + +diff --git a/lib/isc/win32/Makefile.in b/lib/isc/win32/Makefile.in +index c129e31..9cd717d 100644 +--- a/lib/isc/win32/Makefile.in ++++ b/lib/isc/win32/Makefile.in +@@ -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.14 2009/12/05 23:31:41 each Exp $ +- + srcdir = @srcdir@ + VPATH = @srcdir@ + top_srcdir = @top_srcdir@ +@@ -27,11 +25,11 @@ CDEFINES = + CWARNINGS = + + # Alphabetically +-OBJS = condition.@O@ dir.@O@ file.@O@ fsaccess.@O@ once.@O@ \ +- stdtime.@O@ thread.@O@ time.@O@ ++OBJS = condition.@O@ dir.@O@ errno.@O@ file.@O@ fsaccess.@O@ \ ++ once.@O@ stdtime.@O@ thread.@O@ time.@O@ + + # Alphabetically +-SRCS = condition.c dir.c file.c once.c fsaccess.c \ ++SRCS = condition.c dir.c errno.c file.c once.c fsaccess.c \ + stdtime.c thread.c time.c + + SUBDIRS = include +diff --git a/lib/isc/win32/errno.c b/lib/isc/win32/errno.c +new file mode 100644 +index 0000000..5c45496 +--- /dev/null ++++ b/lib/isc/win32/errno.c +@@ -0,0 +1,18 @@ ++/* ++ * Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC") ++ * ++ * This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this ++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. ++ */ ++ ++/*! \file */ ++ ++#include ++ ++#include "errno2result.h" ++ ++isc_result_t ++isc_errno_toresult(int err) { ++ return (isc__errno2resultx(err, ISC_FALSE, 0, 0)); ++} +diff --git a/lib/isc/win32/errno2result.c b/lib/isc/win32/errno2result.c +index c3d54d6..c9a3ab5 100644 +--- a/lib/isc/win32/errno2result.c ++++ b/lib/isc/win32/errno2result.c +@@ -32,7 +32,9 @@ + * not already there. + */ + isc_result_t +-isc__errno2resultx(int posixerrno, const char *file, int line) { ++isc__errno2resultx(int posixerrno, isc_boolean_t dolog, ++ const char *file, int line) ++{ + char strbuf[ISC_STRERRORSIZE]; + + switch (posixerrno) { +@@ -99,9 +101,13 @@ isc__errno2resultx(int posixerrno, const char *file, int line) { + case WSAENOBUFS: + return (ISC_R_NORESOURCES); + default: +- isc__strerror(posixerrno, strbuf, sizeof(strbuf)); +- UNEXPECTED_ERROR(file, line, "unable to convert errno " +- "to isc_result: %d: %s", posixerrno, strbuf); ++ if (dolog) { ++ isc__strerror(posixerrno, strbuf, sizeof(strbuf)); ++ UNEXPECTED_ERROR(file, line, ++ "unable to convert errno " ++ "to isc_result: %d: %s", ++ posixerrno, strbuf); ++ } + /* + * XXXDCL would be nice if perhaps this function could + * return the system's error string, so the caller +diff --git a/lib/isc/win32/errno2result.h b/lib/isc/win32/errno2result.h +index 41682db..cc9115e 100644 +--- a/lib/isc/win32/errno2result.h ++++ b/lib/isc/win32/errno2result.h +@@ -30,10 +30,11 @@ + ISC_LANG_BEGINDECLS + + #define isc__errno2result(posixerrno) \ +- isc__errno2resultx(posixerrno, __FILE__, __LINE__) ++ isc__errno2resultx(posixerrno, ISC_TRUE, __FILE__, __LINE__) + + isc_result_t +-isc__errno2resultx(int posixerrno, const char *file, int line); ++isc__errno2resultx(int posixerrno, isc_boolean_t dolog, ++ const char *file, int line); + + ISC_LANG_ENDDECLS + +diff --git a/lib/isc/win32/libisc.def b/lib/isc/win32/libisc.def +index 0c7a829..d7d2243 100644 +--- a/lib/isc/win32/libisc.def ++++ b/lib/isc/win32/libisc.def +@@ -183,6 +183,7 @@ isc_buffer_reinit + isc_bufferlist_availablecount + isc_bufferlist_usedcount + isc_commandline_parse ++isc_commandline_strtoargv + isc_condition_broadcast + isc_condition_destroy + isc_condition_init +@@ -258,6 +259,7 @@ isc_hash_ctxdetach + isc_hash_ctxinit + isc_hash_destroy + isc_hash_init ++isc_hashctx + isc_heap_create + isc_heap_decreased + isc_heap_delete +diff --git a/lib/isc/win32/libisc.dsp b/lib/isc/win32/libisc.dsp +index 0f14a89..156e23b 100644 +--- a/lib/isc/win32/libisc.dsp ++++ b/lib/isc/win32/libisc.dsp +@@ -115,6 +115,10 @@ SOURCE=.\entropy.c + # End Source File + # Begin Source File + ++SOURCE=.\errno.c ++# End Source File ++# Begin Source File ++ + SOURCE=.\errno2result.c + # End Source File + # Begin Source File +@@ -267,6 +271,10 @@ SOURCE=..\include\isc\entropy.h + # End Source File + # Begin Source File + ++SOURCE=..\include\isc\errno.h ++# End Source File ++# Begin Source File ++ + SOURCE=.\errno2result.h + # End Source File + # Begin Source File +diff --git a/lib/isc/win32/libisc.mak b/lib/isc/win32/libisc.mak +index 96e44e4..5923693 100644 +--- a/lib/isc/win32/libisc.mak ++++ b/lib/isc/win32/libisc.mak +@@ -128,6 +128,7 @@ CLEAN : + -@erase "$(INTDIR)\dir.obj" + -@erase "$(INTDIR)\DLLMain.obj" + -@erase "$(INTDIR)\entropy.obj" ++ -@erase "$(INTDIR)\errno.obj" + -@erase "$(INTDIR)\errno2result.obj" + -@erase "$(INTDIR)\error.obj" + -@erase "$(INTDIR)\event.obj" +@@ -219,6 +220,7 @@ LINK32_OBJS= \ + "$(INTDIR)\dir.obj" \ + "$(INTDIR)\DLLMain.obj" \ + "$(INTDIR)\entropy.obj" \ ++ "$(INTDIR)\errno.obj" \ + "$(INTDIR)\errno2result.obj" \ + "$(INTDIR)\file.obj" \ + "$(INTDIR)\fsaccess.obj" \ +@@ -341,6 +343,8 @@ CLEAN : + -@erase "$(INTDIR)\DLLMain.sbr" + -@erase "$(INTDIR)\entropy.obj" + -@erase "$(INTDIR)\entropy.sbr" ++ -@erase "$(INTDIR)\errno.obj" ++ -@erase "$(INTDIR)\errno.sbr" + -@erase "$(INTDIR)\errno2result.obj" + -@erase "$(INTDIR)\errno2result.sbr" + -@erase "$(INTDIR)\error.obj" +@@ -497,6 +501,7 @@ BSC32_SBRS= \ + "$(INTDIR)\dir.sbr" \ + "$(INTDIR)\DLLMain.sbr" \ + "$(INTDIR)\entropy.sbr" \ ++ "$(INTDIR)\errno.sbr" \ + "$(INTDIR)\errno2result.sbr" \ + "$(INTDIR)\file.sbr" \ + "$(INTDIR)\fsaccess.sbr" \ +@@ -588,6 +593,7 @@ LINK32_OBJS= \ + "$(INTDIR)\dir.obj" \ + "$(INTDIR)\DLLMain.obj" \ + "$(INTDIR)\entropy.obj" \ ++ "$(INTDIR)\errno.obj" \ + "$(INTDIR)\errno2result.obj" \ + "$(INTDIR)\file.obj" \ + "$(INTDIR)\fsaccess.obj" \ +@@ -793,6 +799,23 @@ SOURCE=.\entropy.c + + !ENDIF + ++SOURCE=.\errno.c ++ ++!IF "$(CFG)" == "libisc - @PLATFORM@ Release" ++ ++ ++"$(INTDIR)\errno.obj" : $(SOURCE) "$(INTDIR)" ++ ++ ++!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" ++ ++ ++"$(INTDIR)\errno.obj" "$(INTDIR)\errno.sbr" : $(SOURCE) "$(INTDIR)" ++ ++ ++!ENDIF ++ ++ + SOURCE=.\errno2result.c + + !IF "$(CFG)" == "libisc - Win32 Release" +diff --git a/lib/isc/win32/socket.c b/lib/isc/win32/socket.c +index f015974..5455dbf 100644 +--- a/lib/isc/win32/socket.c ++++ b/lib/isc/win32/socket.c +@@ -2480,7 +2480,7 @@ SocketIoThread(LPVOID ThreadContext) { + * Did the I/O operation complete? + */ + errstatus = GetLastError(); +- isc_result = isc__errno2resultx(errstatus, __FILE__, __LINE__); ++ isc_result = isc__errno2result(errstatus); + + LOCK(&sock->lock); + CONSISTENT(sock); +@@ -2532,7 +2532,7 @@ SocketIoThread(LPVOID ThreadContext) { + goto wait_again; + } else { + errstatus = GetLastError(); +- isc_result = isc__errno2resultx(errstatus, __FILE__, __LINE__); ++ isc_result = isc__errno2result(errstatus); + socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0, + "restart_accept() failed: errstatus=%d isc_result=%d", + errstatus, isc_result); +diff --git a/lib/isccfg/include/isccfg/grammar.h b/lib/isccfg/include/isccfg/grammar.h +index 2d7080c..7df760a 100644 +--- a/lib/isccfg/include/isccfg/grammar.h ++++ b/lib/isccfg/include/isccfg/grammar.h +@@ -266,6 +266,7 @@ LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_uint64; + LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_qstring; + LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_astring; + LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_ustring; ++LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_bracketed_text; + LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_sockaddr; + LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_netaddr; + LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_netaddr4; +diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c +index 1527575..62fcc96 100644 +--- a/lib/isccfg/namedconf.c ++++ b/lib/isccfg/namedconf.c +@@ -126,6 +126,7 @@ static cfg_type_t cfg_type_zoneopts; + static cfg_type_t cfg_type_dynamically_loadable_zones; + static cfg_type_t cfg_type_dynamically_loadable_zones_opts; + static cfg_type_t cfg_type_v4_aaaa; ++static cfg_type_t cfg_type_dyndb; + + /* + * Clauses that can be found in a 'dynamically loadable zones' statement +@@ -897,6 +898,7 @@ namedconf_or_view_clauses[] = { + { "zone", &cfg_type_zone, CFG_CLAUSEFLAG_MULTI }, + /* only 1 DLZ per view allowed */ + { "dlz", &cfg_type_dynamically_loadable_zones, 0 }, ++ { "dyndb", &cfg_type_dyndb, CFG_CLAUSEFLAG_MULTI }, + { "server", &cfg_type_server, CFG_CLAUSEFLAG_MULTI }, + { "trusted-keys", &cfg_type_dnsseckeys, CFG_CLAUSEFLAG_MULTI }, + { "managed-keys", &cfg_type_managedkeys, CFG_CLAUSEFLAG_MULTI }, +@@ -1706,6 +1708,22 @@ static cfg_type_t cfg_type_dynamically_loadable_zones_opts = { + }; + + /*% ++ * The "dyndb" statement syntax. ++ */ ++ ++static cfg_tuplefielddef_t dyndb_fields[] = { ++ { "name", &cfg_type_astring, 0 }, ++ { "library", &cfg_type_qstring, 0 }, ++ { "parameters", &cfg_type_bracketed_text, 0 }, ++ { NULL, NULL, 0 } ++}; ++ ++static cfg_type_t cfg_type_dyndb = { ++ "dyndb", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, ++ &cfg_rep_tuple, dyndb_fields ++}; ++ ++/*% + * Clauses that can be found within the 'key' statement. + */ + static cfg_clausedef_t +diff --git a/lib/isccfg/parser.c b/lib/isccfg/parser.c +index de0fa31..5dc1653 100644 +--- a/lib/isccfg/parser.c ++++ b/lib/isccfg/parser.c +@@ -762,6 +762,42 @@ cfg_parse_astring(cfg_parser_t *pctx, const cfg_type_t *type, + return (result); + } + ++static isc_result_t ++parse_btext(cfg_parser_t *pctx, const cfg_type_t *type, ++ cfg_obj_t **ret) ++{ ++ isc_result_t result; ++ UNUSED(type); ++ ++ CHECK(cfg_gettoken(pctx, ISC_LEXOPT_BTEXT)); ++ if (pctx->token.type != isc_tokentype_btext) { ++ cfg_parser_error(pctx, CFG_LOG_NEAR, ++ "expected bracketed text"); ++ return (ISC_R_UNEXPECTEDTOKEN); ++ } ++ return (create_string(pctx, ++ TOKEN_STRING(pctx), ++ &cfg_type_bracketed_text, ++ ret)); ++ cleanup: ++ return (result); ++} ++ ++static void ++print_btext(cfg_printer_t *pctx, const cfg_obj_t *obj) { ++ cfg_print_cstr(pctx, "{"); ++ cfg_print_chars(pctx, obj->value.string.base, obj->value.string.length); ++ print_close(pctx); ++} ++ ++static void ++doc_btext(cfg_printer_t *pctx, const cfg_type_t *type) { ++ UNUSED(type); ++ ++ cfg_print_cstr(pctx, "{ }"); ++} ++ ++ + isc_boolean_t + cfg_is_enum(const char *s, const char *const *enums) { + const char * const *p; +@@ -855,6 +891,16 @@ cfg_type_t cfg_type_astring = { + }; + + /* ++ * Text enclosed in brackets. Used to pass a block of configuration ++ * text to dynamic library or external application. Checked for ++ * bracket balance, but not otherwise parsed. ++ */ ++cfg_type_t cfg_type_bracketed_text = { ++ "bracketed_text", parse_btext, print_btext, doc_btext, ++ &cfg_rep_string, NULL ++}; ++ ++/* + * Booleans + */ + +-- +2.9.3 + diff --git a/SOURCES/bind99-rh1220594-geoip.patch b/SOURCES/bind99-rh1220594-geoip.patch index a6c3d08..3e65b99 100644 --- a/SOURCES/bind99-rh1220594-geoip.patch +++ b/SOURCES/bind99-rh1220594-geoip.patch @@ -1,4 +1,4 @@ -From 7af058d28da052c9fb03083f6c4de1f9af564d08 Mon Sep 17 00:00:00 2001 +From 34c87ea385ff013ca2f2058b884f53886065a4a3 Mon Sep 17 00:00:00 2001 From: Tomas Hozza Date: Wed, 13 Apr 2016 09:57:31 +0200 Subject: [PATCH] Added support for GeoIP @@ -11,7 +11,7 @@ Signed-off-by: Tomas Hozza bin/named/include/named/globals.h | 5 + bin/named/interfacemgr.c | 3 + bin/named/server.c | 38 +- - bin/tests/system/Makefile.in | 3 +- + bin/tests/system/Makefile.in | 2 +- bin/tests/system/conf.sh.in | 2 +- bin/tests/system/geoip/Makefile.in | 55 ++ bin/tests/system/geoip/clean.sh | 23 + @@ -54,16 +54,16 @@ Signed-off-by: Tomas Hozza lib/dns/Makefile.in | 8 +- lib/dns/acl.c | 23 +- lib/dns/geoip.c | 820 ++++++++++++++++++++++++++ - lib/dns/include/dns/Makefile.in | 2 +- + lib/dns/include/dns/Makefile.in | 6 +- lib/dns/include/dns/acl.h | 24 +- lib/dns/include/dns/geoip.h | 119 ++++ lib/dns/tests/Makefile.in | 9 +- lib/dns/tests/geoip_test.c | 694 ++++++++++++++++++++++ - lib/export/dns/Makefile.in | 18 +- + lib/export/dns/Makefile.in | 6 +- lib/isccfg/aclconf.c | 361 +++++++++++- lib/isccfg/include/isccfg/aclconf.h | 6 + lib/isccfg/namedconf.c | 129 +++- - 58 files changed, 4673 insertions(+), 40 deletions(-) + 58 files changed, 4671 insertions(+), 33 deletions(-) create mode 100644 bin/named/geoip.c create mode 100644 bin/named/include/named/geoip.h create mode 100644 bin/tests/system/geoip/Makefile.in @@ -106,10 +106,10 @@ Signed-off-by: Tomas Hozza create mode 100644 lib/dns/tests/geoip_test.c diff --git a/bin/named/Makefile.in b/bin/named/Makefile.in -index cd65777..3a54437 100644 +index 8ec9ad7..8b9e87a 100644 --- a/bin/named/Makefile.in +++ b/bin/named/Makefile.in -@@ -85,8 +85,10 @@ SUBDIRS = unix +@@ -83,8 +83,10 @@ SUBDIRS = unix TARGETS = named@EXEEXT@ lwresd@EXEEXT@ @@ -121,7 +121,7 @@ index cd65777..3a54437 100644 listenlist.@O@ log.@O@ logconf.@O@ main.@O@ notify.@O@ \ query.@O@ server.@O@ sortlist.@O@ statschannel.@O@ \ tkeyconf.@O@ tsigconf.@O@ update.@O@ xfrout.@O@ \ -@@ -99,8 +101,10 @@ UOBJS = unix/os.@O@ unix/dlz_dlopen_driver.@O@ +@@ -97,8 +99,10 @@ UOBJS = unix/os.@O@ unix/dlz_dlopen_driver.@O@ SYMOBJS = symtbl.@O@ @@ -362,10 +362,10 @@ index 9206ebb..4f6b0f3 100644 mgr->references = 1; mgr->magic = IFMGR_MAGIC; diff --git a/bin/named/server.c b/bin/named/server.c -index 5e94660..24b31c3 100644 +index 6260f8f..e3ffc2e 100644 --- a/bin/named/server.c +++ b/bin/named/server.c -@@ -98,6 +98,7 @@ +@@ -99,6 +99,7 @@ #include #include #include @@ -373,7 +373,7 @@ index 5e94660..24b31c3 100644 #include #include #include -@@ -113,6 +114,9 @@ +@@ -114,6 +115,9 @@ #include #include #endif @@ -383,7 +383,7 @@ index 5e94660..24b31c3 100644 #ifndef PATH_MAX #define PATH_MAX 1024 -@@ -3841,6 +3845,10 @@ create_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist, +@@ -3795,6 +3799,10 @@ create_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist, if (result != ISC_R_SUCCESS) return (result); @@ -394,7 +394,7 @@ index 5e94660..24b31c3 100644 ISC_LIST_APPEND(*viewlist, view, link); dns_view_attach(view, viewp); return (ISC_R_SUCCESS); -@@ -5164,6 +5172,24 @@ load_configuration(const char *filename, ns_server_t *server, +@@ -5122,6 +5130,24 @@ load_configuration(const char *filename, ns_server_t *server, } isc__socketmgr_setreserved(ns_g_socketmgr, reserved); @@ -419,7 +419,7 @@ index 5e94660..24b31c3 100644 /* * Configure various server options. */ -@@ -6176,6 +6202,10 @@ shutdown_server(isc_task_t *task, isc_event_t *event) { +@@ -6134,6 +6160,10 @@ shutdown_server(isc_task_t *task, isc_event_t *event) { if (server->blackholeacl != NULL) dns_acl_detach(&server->blackholeacl); @@ -430,7 +430,7 @@ index 5e94660..24b31c3 100644 dns_db_detach(&server->in_roothints); isc_task_endexclusive(server->task); -@@ -6197,7 +6227,6 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) { +@@ -6155,7 +6185,6 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) { server->task = NULL; /* Initialize configuration data with default values. */ @@ -438,7 +438,7 @@ index 5e94660..24b31c3 100644 result = isc_quota_init(&server->xfroutquota, 10); RUNTIME_CHECK(result == ISC_R_SUCCESS); result = isc_quota_init(&server->tcpquota, 10); -@@ -6205,9 +6234,16 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) { +@@ -6163,9 +6192,16 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) { result = isc_quota_init(&server->recursionquota, 100); RUNTIME_CHECK(result == ISC_R_SUCCESS); @@ -456,21 +456,20 @@ index 5e94660..24b31c3 100644 server->zonemgr = NULL; server->interfacemgr = NULL; diff --git a/bin/tests/system/Makefile.in b/bin/tests/system/Makefile.in -index 1479824..5e3c63e 100644 +index af8b82c..0c7fdff 100644 --- a/bin/tests/system/Makefile.in +++ b/bin/tests/system/Makefile.in -@@ -21,8 +21,7 @@ top_srcdir = @top_srcdir@ +@@ -21,7 +21,7 @@ top_srcdir = @top_srcdir@ @BIND9_MAKE_INCLUDES@ --SUBDIRS = filter-aaaa lwresd rpz rrl \ -- rsabigexponent tkey tsiggss -+SUBDIRS = filter-aaaa geoip lwresd rpz rrl rsabigexponent tkey tsiggss +-SUBDIRS = dlzexternal dyndb filter-aaaa lwresd rpz rrl \ ++SUBDIRS = dlzexternal dyndb filter-aaaa geoip lwresd rpz rrl \ + rsabigexponent tkey tsiggss TARGETS = - @BIND9_MAKE_RULES@ diff --git a/bin/tests/system/conf.sh.in b/bin/tests/system/conf.sh.in -index c40e8f1..c3beac1 100644 +index eb02236..6df4734 100644 --- a/bin/tests/system/conf.sh.in +++ b/bin/tests/system/conf.sh.in @@ -65,7 +65,7 @@ SUBDIRS="acl additional allow_query addzone autosign builtin @@ -2800,7 +2799,7 @@ index f2eb59a..6ed8381 100644 #undef HAVE_GSSAPI_GSSAPI_H diff --git a/configure.in b/configure.in -index 24eafb7..5b56172 100644 +index e8c68fc..71e90c1 100644 --- a/configure.in +++ b/configure.in @@ -1252,6 +1252,99 @@ if test "$have_clock_gt" = "yes"; then @@ -2903,8 +2902,8 @@ index 24eafb7..5b56172 100644 AC_MSG_CHECKING(for GSSAPI library) AC_ARG_WITH(gssapi, [ --with-gssapi=PATH Specify path for system-supplied GSSAPI [[default=yes]]], -@@ -3962,6 +4055,7 @@ AC_CONFIG_FILES([ - bin/tests/system/dlzexternal/ns1/named.conf +@@ -3965,6 +4058,7 @@ AC_CONFIG_FILES([ + bin/tests/system/dyndb/driver/Makefile bin/tests/system/ecdsa/prereq.sh bin/tests/system/filter-aaaa/Makefile + bin/tests/system/geoip/Makefile @@ -2912,10 +2911,10 @@ index 24eafb7..5b56172 100644 bin/tests/system/lwresd/Makefile bin/tests/system/rpz/Makefile diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml -index bd42e11..92c7b72 100644 +index 16b50a3..b79bfa0 100644 --- a/doc/arm/Bv9ARM-book.xml +++ b/doc/arm/Bv9ARM-book.xml -@@ -3410,6 +3410,62 @@ $ORIGIN 0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa. +@@ -3412,6 +3412,62 @@ $ORIGIN 0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa. @@ -2978,7 +2977,7 @@ index bd42e11..92c7b72 100644 <command>controls</command> Statement Grammar -@@ -4690,6 +4746,7 @@ badresp:1,adberr:0,findfail:0,valfail:0] +@@ -4692,6 +4748,7 @@ badresp:1,adberr:0,findfail:0,valfail:0] hostname hostname_string; server-id server_id_string; directory path_name; @@ -2986,7 +2985,7 @@ index bd42e11..92c7b72 100644 key-directory path_name; managed-keys-directory path_name; named-xfer path_name; -@@ -5046,6 +5103,21 @@ badresp:1,adberr:0,findfail:0,valfail:0] +@@ -5048,6 +5105,21 @@ badresp:1,adberr:0,findfail:0,valfail:0] @@ -3009,7 +3008,7 @@ index bd42e11..92c7b72 100644 diff --git a/lib/dns/Makefile.in b/lib/dns/Makefile.in -index 41fac95..0cc82f1 100644 +index 2efcc5a..ae316c5 100644 --- a/lib/dns/Makefile.in +++ b/lib/dns/Makefile.in @@ -56,6 +56,8 @@ DSTOBJS = @DST_EXTRA_OBJS@ @OPENSSLLINKOBJS@ @PKCS11LINKOBJS@ \ @@ -3945,18 +3944,22 @@ index 0000000..5387ebb +#endif +} diff --git a/lib/dns/include/dns/Makefile.in b/lib/dns/include/dns/Makefile.in -index 56172e9..1836fa3 100644 +index a37b35e..2fcbd1e 100644 --- a/lib/dns/include/dns/Makefile.in +++ b/lib/dns/include/dns/Makefile.in -@@ -23,7 +23,7 @@ top_srcdir = @top_srcdir@ +@@ -23,9 +23,9 @@ top_srcdir = @top_srcdir@ HEADERS = acl.h adb.h byaddr.h cache.h callbacks.h cert.h compress.h \ - clientinfo.h db.h dbiterator.h dbtable.h diff.h dispatch.h dynamic_db.h \ -- dlz.h dnssec.h ds.h events.h fixedname.h iptable.h journal.h \ -+ dlz.h dnssec.h ds.h events.h fixedname.h geoip.h iptable.h journal.h \ - keyflags.h keytable.h keyvalues.h lib.h log.h \ - master.h masterdump.h message.h name.h ncache.h nsec.h \ + clientinfo.h db.h dbiterator.h dbtable.h diff.h dispatch.h \ +- dlz.h dyndb.h dnssec.h ds.h events.h fixedname.h iptable.h \ +- journal.h keyflags.h keytable.h keyvalues.h lib.h log.h \ +- master.h masterdump.h message.h name.h ncache.h nsec.h \ ++ dlz.h dyndb.h dnssec.h ds.h events.h fixedname.h geoip.h \ ++ iptable.h journal.h keyflags.h keytable.h keyvalues.h lib.h \ ++ log.h master.h masterdump.h message.h name.h ncache.h nsec.h \ peer.h portlist.h private.h rbt.h rcode.h \ + rdata.h rdataclass.h rdatalist.h rdataset.h rdatasetiter.h \ + rdataslab.h rdatatype.h request.h resolver.h result.h \ diff --git a/lib/dns/include/dns/acl.h b/lib/dns/include/dns/acl.h index f4fc4a3..2c3bb37 100644 --- a/lib/dns/include/dns/acl.h @@ -4885,10 +4888,10 @@ index 0000000..ad983b0 +} + diff --git a/lib/export/dns/Makefile.in b/lib/export/dns/Makefile.in -index e10bf59..54e4e39 100644 +index e10bf59..887acb9 100644 --- a/lib/export/dns/Makefile.in +++ b/lib/export/dns/Makefile.in -@@ -67,8 +65,9 @@ DNSOBJS = acl.@O@ adb.@O@ byaddr.@O@ \ +@@ -67,8 +67,9 @@ DNSOBJS = acl.@O@ adb.@O@ byaddr.@O@ \ tcpmsg.@O@ time.@O@ tsec.@O@ tsig.@O@ ttl.@O@ \ validator.@O@ version.@O@ view.@O@ PORTDNSOBJS = ecdb.@O@ @@ -4899,7 +4902,7 @@ index e10bf59..54e4e39 100644 # Alphabetically -@@ -96,8 +93,9 @@ DNSSRCS = acl.c adb.c byaddr.c \ +@@ -96,8 +97,9 @@ DNSSRCS = acl.c adb.c byaddr.c \ tcpmsg.c time.c tsec.c tsig.c ttl.c \ validator.c version.c view.c PORTDNSSRCS = ecdb.c @@ -5350,7 +5353,7 @@ index 38ab9f6..3fb66f9 100644 } cfg_aclconfctx_t; diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c -index acaef2b..f5ff8e3 100644 +index 62fcc96..1867506 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -82,6 +82,17 @@ doc_keyvalue(cfg_printer_t *pctx, const cfg_type_t *type); @@ -5381,7 +5384,7 @@ index acaef2b..f5ff8e3 100644 { "has-old-clients", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE }, { "heartbeat-interval", &cfg_type_uint32, 0 }, { "host-statistics", &cfg_type_boolean, CFG_CLAUSEFLAG_NOTIMP }, -@@ -2126,6 +2140,102 @@ static cfg_type_t cfg_type_optional_keyref = { +@@ -2108,6 +2122,102 @@ static cfg_type_t cfg_type_optional_keyref = { doc_optional_keyvalue, &cfg_rep_string, &key_kw }; @@ -5484,7 +5487,7 @@ index acaef2b..f5ff8e3 100644 /*% * A "controls" statement is represented as a map with the multivalued * "inet" and "unix" clauses. -@@ -2269,7 +2379,9 @@ static cfg_type_t cfg_type_statschannels = { +@@ -2251,7 +2361,9 @@ static cfg_type_t cfg_type_statschannels = { * An optional class, as used in view and zone statements. */ static isc_result_t @@ -5495,7 +5498,7 @@ index acaef2b..f5ff8e3 100644 isc_result_t result; UNUSED(type); CHECK(cfg_peektoken(pctx, 0)); -@@ -2392,6 +2504,16 @@ parse_addrmatchelt(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) +@@ -2374,6 +2486,16 @@ parse_addrmatchelt(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) if (pctx->token.type == isc_tokentype_string && (strcasecmp(TOKEN_STRING(pctx), "key") == 0)) { CHECK(cfg_parse_obj(pctx, &cfg_type_keyref, ret)); @@ -5512,7 +5515,7 @@ index acaef2b..f5ff8e3 100644 } else { if (cfg_lookingat_netaddr(pctx, CFG_ADDR_V4OK | CFG_ADDR_V4PREFIXOK | -@@ -2405,7 +2527,8 @@ parse_addrmatchelt(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) +@@ -2387,7 +2509,8 @@ parse_addrmatchelt(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) } else if (pctx->token.type == isc_tokentype_special) { if (pctx->token.value.as_char == '{') { /* Nested match list. */ @@ -5522,7 +5525,7 @@ index acaef2b..f5ff8e3 100644 } else if (pctx->token.value.as_char == '!') { CHECK(cfg_gettoken(pctx, 0)); /* read "!" */ CHECK(cfg_parse_obj(pctx, &cfg_type_negated, ret)); -@@ -2429,7 +2552,7 @@ parse_addrmatchelt(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) +@@ -2411,7 +2534,7 @@ parse_addrmatchelt(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) */ static cfg_tuplefielddef_t negated_fields[] = { @@ -5532,5 +5535,5 @@ index acaef2b..f5ff8e3 100644 }; -- -2.5.5 +2.9.3 diff --git a/SOURCES/bind99-rh1392362.patch b/SOURCES/bind99-rh1392362.patch new file mode 100644 index 0000000..a936c1f --- /dev/null +++ b/SOURCES/bind99-rh1392362.patch @@ -0,0 +1,41 @@ +From 3acf8e092f95233bc3d854e161569487dce83ba2 Mon Sep 17 00:00:00 2001 +From: Mark Andrews +Date: Fri, 3 Feb 2017 14:22:03 +1100 +Subject: [PATCH] 4567. [port] Call getprotobyname and getservbyname prior to + calling chroot so that shared libraries get loaded. [RT #44537] + +--- + lib/isc/unix/dir.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/lib/isc/unix/dir.c b/lib/isc/unix/dir.c +index 0d64778..ee80f41 100644 +--- a/lib/isc/unix/dir.c ++++ b/lib/isc/unix/dir.c +@@ -31,6 +31,7 @@ + + #include + #include ++#include + #include + #include + +@@ -172,6 +173,15 @@ isc_dir_chroot(const char *dirname) { + REQUIRE(dirname != NULL); + + #ifdef HAVE_CHROOT ++ /* ++ * Try to use getservbyname and getprotobyname before chroot. ++ * If WKS records are used in a zone under chroot, Name Service Switch ++ * may fail to load library in chroot. ++ * Do not report errors if it fails, we do not need any result now. ++ */ ++ if (getprotobyname("udp")) ++ (void)getservbyname("domain", "udp"); ++ + if (chroot(dirname) < 0 || chdir("/") < 0) + return (isc__errno2result(errno)); + +-- +2.9.3 + diff --git a/SOURCES/bind99-rh1416304.patch b/SOURCES/bind99-rh1416304.patch new file mode 100644 index 0000000..34a9c23 --- /dev/null +++ b/SOURCES/bind99-rh1416304.patch @@ -0,0 +1,139 @@ +From e7a2611c555e03314ac4f7960044b05cce040364 Mon Sep 17 00:00:00 2001 +From: Mark Andrews +Date: Thu, 31 Jul 2014 11:38:11 +1000 +Subject: [PATCH] 3905. [bug] Address deadlock between view.c and adb.c. [RT + #36341] +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Original-commit: 5e746ab61ed8158f784b86111fef95581a08b7dd +Signed-off-by: Petr Menšík +--- + lib/dns/adb.c | 57 +++++++++++++++++++++++++++++++++++++++++---------------- + 1 file changed, 41 insertions(+), 16 deletions(-) + +diff --git a/lib/dns/adb.c b/lib/dns/adb.c +index a6da94d..ac89e66 100644 +--- a/lib/dns/adb.c ++++ b/lib/dns/adb.c +@@ -15,8 +15,6 @@ + * PERFORMANCE OF THIS SOFTWARE. + */ + +-/* $Id: adb.c,v 1.264 2011/12/05 17:10:51 each Exp $ */ +- + /*! \file + * + * \note +@@ -157,7 +155,7 @@ struct dns_adb { + unsigned int *entry_refcnt; + + isc_event_t cevent; +- isc_boolean_t cevent_sent; ++ isc_boolean_t cevent_out; + isc_boolean_t shutting_down; + isc_eventlist_t whenshutdown; + isc_event_t growentries; +@@ -322,6 +320,7 @@ static inline isc_boolean_t unlink_entry(dns_adb_t *, dns_adbentry_t *); + static isc_boolean_t kill_name(dns_adbname_t **, isc_eventtype_t); + static void water(void *, int); + static void dump_entry(FILE *, dns_adbentry_t *, isc_boolean_t, isc_stdtime_t); ++static void shutdown_task(isc_task_t *task, isc_event_t *ev); + + /* + * MUST NOT overlap DNS_ADBFIND_* flags! +@@ -1499,10 +1498,13 @@ check_exit(dns_adb_t *adb) { + * If there aren't any external references either, we're + * done. Send the control event to initiate shutdown. + */ +- INSIST(!adb->cevent_sent); /* Sanity check. */ ++ INSIST(!adb->cevent_out); /* Sanity check. */ ++ ISC_EVENT_INIT(&adb->cevent, sizeof(adb->cevent), 0, NULL, ++ DNS_EVENT_ADBCONTROL, shutdown_task, adb, ++ adb, NULL, NULL); + event = &adb->cevent; + isc_task_send(adb->task, &event); +- adb->cevent_sent = ISC_TRUE; ++ adb->cevent_out = ISC_TRUE; + } + } + +@@ -2431,10 +2433,9 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr, + adb->view = view; + adb->taskmgr = taskmgr; + adb->next_cleanbucket = 0; +- ISC_EVENT_INIT(&adb->cevent, sizeof(adb->cevent), 0, NULL, +- DNS_EVENT_ADBCONTROL, shutdown_task, adb, +- adb, NULL, NULL); +- adb->cevent_sent = ISC_FALSE; ++ ISC_EVENT_INIT(&adb->cevent, sizeof(adb->cevent), ++ 0, NULL, 0, NULL, NULL, NULL, NULL, NULL); ++ adb->cevent_out = ISC_FALSE; + adb->shutting_down = ISC_FALSE; + ISC_LIST_INIT(adb->whenshutdown); + +@@ -2468,7 +2469,7 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr, + "intializing table sizes to %u\n", + nbuckets[11]); + adb->nentries = nbuckets[11]; +- adb->nnames= nbuckets[11]; ++ adb->nnames = nbuckets[11]; + + } + +@@ -2741,9 +2742,28 @@ dns_adb_whenshutdown(dns_adb_t *adb, isc_task_t *task, isc_event_t **eventp) { + UNLOCK(&adb->lock); + } + ++static void ++shutdown_stage2(isc_task_t *task, isc_event_t *event) { ++ dns_adb_t *adb; ++ ++ UNUSED(task); ++ ++ adb = event->ev_arg; ++ INSIST(DNS_ADB_VALID(adb)); ++ ++ LOCK(&adb->lock); ++ INSIST(adb->shutting_down); ++ adb->cevent_out = ISC_FALSE; ++ (void)shutdown_names(adb); ++ (void)shutdown_entries(adb); ++ if (dec_adb_irefcnt(adb)) ++ check_exit(adb); ++ UNLOCK(&adb->lock); ++} ++ + void + dns_adb_shutdown(dns_adb_t *adb) { +- isc_boolean_t need_check_exit; ++ isc_event_t *event; + + /* + * Shutdown 'adb'. +@@ -2754,11 +2774,16 @@ dns_adb_shutdown(dns_adb_t *adb) { + if (!adb->shutting_down) { + adb->shutting_down = ISC_TRUE; + isc_mem_setwater(adb->mctx, water, adb, 0, 0); +- need_check_exit = shutdown_names(adb); +- if (!need_check_exit) +- need_check_exit = shutdown_entries(adb); +- if (need_check_exit) +- check_exit(adb); ++ /* ++ * Isolate shutdown_names and shutdown_entries calls. ++ */ ++ inc_adb_irefcnt(adb); ++ ISC_EVENT_INIT(&adb->cevent, sizeof(adb->cevent), 0, NULL, ++ DNS_EVENT_ADBCONTROL, shutdown_stage2, adb, ++ adb, NULL, NULL); ++ adb->cevent_out = ISC_TRUE; ++ event = &adb->cevent; ++ isc_task_send(adb->task, &event); + } + + UNLOCK(&adb->lock); +-- +2.9.3 + diff --git a/SOURCES/named-chroot.service b/SOURCES/named-chroot.service index 55bf507..4459336 100644 --- a/SOURCES/named-chroot.service +++ b/SOURCES/named-chroot.service @@ -12,12 +12,13 @@ After=named-chroot-setup.service [Service] Type=forking +Environment=NAMEDCONF=/etc/named.conf EnvironmentFile=-/etc/sysconfig/named Environment=KRB5_KTNAME=/etc/named.keytab PIDFile=/var/named/chroot/run/named/named.pid -ExecStartPre=/bin/bash -c 'if [ ! "$DISABLE_ZONE_CHECKING" == "yes" ]; then /usr/sbin/named-checkconf -t /var/named/chroot -z /etc/named.conf; else echo "Checking of zone files is disabled"; fi' -ExecStart=/usr/sbin/named -u named -t /var/named/chroot $OPTIONS +ExecStartPre=/bin/bash -c 'if [ ! "$DISABLE_ZONE_CHECKING" == "yes" ]; then /usr/sbin/named-checkconf -t /var/named/chroot -z "$NAMEDCONF"; else echo "Checking of zone files is disabled"; fi' +ExecStart=/usr/sbin/named -u named -c ${NAMEDCONF} -t /var/named/chroot $OPTIONS ExecReload=/bin/sh -c '/usr/sbin/rndc reload > /dev/null 2>&1 || /bin/kill -HUP $MAINPID' diff --git a/SOURCES/named-pkcs11.service b/SOURCES/named-pkcs11.service index e522ec3..c1a19d1 100644 --- a/SOURCES/named-pkcs11.service +++ b/SOURCES/named-pkcs11.service @@ -8,12 +8,13 @@ After=named-setup-rndc.service [Service] Type=forking +Environment=NAMEDCONF=/etc/named.conf EnvironmentFile=-/etc/sysconfig/named Environment=KRB5_KTNAME=/etc/named.keytab PIDFile=/run/named/named.pid -ExecStartPre=/bin/bash -c 'if [ ! "$DISABLE_ZONE_CHECKING" == "yes" ]; then /usr/sbin/named-checkconf -z /etc/named.conf; else echo "Checking of zone files is disabled"; fi' -ExecStart=/usr/sbin/named-pkcs11 -u named $OPTIONS +ExecStartPre=/bin/bash -c 'if [ ! "$DISABLE_ZONE_CHECKING" == "yes" ]; then /usr/sbin/named-checkconf -z "$NAMEDCONF"; else echo "Checking of zone files is disabled"; fi' +ExecStart=/usr/sbin/named-pkcs11 -u named -c ${NAMEDCONF} $OPTIONS ExecReload=/bin/sh -c '/usr/sbin/rndc reload > /dev/null 2>&1 || /bin/kill -HUP $MAINPID' diff --git a/SOURCES/named-sdb-chroot.service b/SOURCES/named-sdb-chroot.service index 2e42646..1fe742d 100644 --- a/SOURCES/named-sdb-chroot.service +++ b/SOURCES/named-sdb-chroot.service @@ -12,12 +12,13 @@ After=named-sdb-chroot-setup.service [Service] Type=forking +Environment=NAMEDCONF=/etc/named.conf EnvironmentFile=-/etc/sysconfig/named Environment=KRB5_KTNAME=/etc/named.keytab PIDFile=/var/named/chroot_sdb/run/named/named.pid -ExecStartPre=/bin/bash -c 'if [ ! "$DISABLE_ZONE_CHECKING" == "yes" ]; then /usr/sbin/named-checkconf -t /var/named/chroot_sdb -z /etc/named.conf; else echo "Checking of zone files is disabled"; fi' -ExecStart=/usr/sbin/named-sdb -u named -t /var/named/chroot_sdb $OPTIONS +ExecStartPre=/bin/bash -c 'if [ ! "$DISABLE_ZONE_CHECKING" == "yes" ]; then /usr/sbin/named-checkconf -t /var/named/chroot_sdb -z "$NAMEDCONF"; else echo "Checking of zone files is disabled"; fi' +ExecStart=/usr/sbin/named-sdb -u named -c ${NAMEDCONF} -t /var/named/chroot_sdb $OPTIONS ExecReload=/bin/sh -c '/usr/sbin/rndc reload > /dev/null 2>&1 || /bin/kill -HUP $MAINPID' diff --git a/SOURCES/named-sdb.service b/SOURCES/named-sdb.service index bb58bca..67867ea 100644 --- a/SOURCES/named-sdb.service +++ b/SOURCES/named-sdb.service @@ -8,12 +8,13 @@ After=named-setup-rndc.service [Service] Type=forking +Environment=NAMEDCONF=/etc/named.conf EnvironmentFile=-/etc/sysconfig/named Environment=KRB5_KTNAME=/etc/named.keytab PIDFile=/run/named/named.pid -ExecStartPre=/bin/bash -c 'if [ ! "$DISABLE_ZONE_CHECKING" == "yes" ]; then /usr/sbin/named-checkconf -z /etc/named.conf; else echo "Checking of zone files is disabled"; fi' -ExecStart=/usr/sbin/named-sdb -u named $OPTIONS +ExecStartPre=/bin/bash -c 'if [ ! "$DISABLE_ZONE_CHECKING" == "yes" ]; then /usr/sbin/named-checkconf -z "$NAMEDCONF"; else echo "Checking of zone files is disabled"; fi' +ExecStart=/usr/sbin/named-sdb -u named -c ${NAMEDCONF} $OPTIONS ExecReload=/bin/sh -c '/usr/sbin/rndc reload > /dev/null 2>&1 || /bin/kill -HUP $MAINPID' diff --git a/SOURCES/named.service b/SOURCES/named.service index f8198fd..90a6a32 100644 --- a/SOURCES/named.service +++ b/SOURCES/named.service @@ -8,12 +8,13 @@ After=named-setup-rndc.service [Service] Type=forking +Environment=NAMEDCONF=/etc/named.conf EnvironmentFile=-/etc/sysconfig/named Environment=KRB5_KTNAME=/etc/named.keytab PIDFile=/run/named/named.pid -ExecStartPre=/bin/bash -c 'if [ ! "$DISABLE_ZONE_CHECKING" == "yes" ]; then /usr/sbin/named-checkconf -z /etc/named.conf; else echo "Checking of zone files is disabled"; fi' -ExecStart=/usr/sbin/named -u named $OPTIONS +ExecStartPre=/bin/bash -c 'if [ ! "$DISABLE_ZONE_CHECKING" == "yes" ]; then /usr/sbin/named-checkconf -z "$NAMEDCONF"; else echo "Checking of zone files is disabled"; fi' +ExecStart=/usr/sbin/named -u named -c ${NAMEDCONF} $OPTIONS ExecReload=/bin/sh -c '/usr/sbin/rndc reload > /dev/null 2>&1 || /bin/kill -HUP $MAINPID' diff --git a/SOURCES/named.sysconfig b/SOURCES/named.sysconfig index 2326043..3394d23 100644 --- a/SOURCES/named.sysconfig +++ b/SOURCES/named.sysconfig @@ -4,6 +4,10 @@ # OPTIONS="whatever" -- These additional options will be passed to named # at startup. Don't add -t here, enable proper # -chroot.service unit file. +# Use of parameter -c is not supported here. Extend +# systemd named*.service instead. For more +# information please read the following KB article: +# https://access.redhat.com/articles/2986001 # # DISABLE_ZONE_CHECKING -- By default, service file calls named-checkzone # utility for every zone to ensure all zones are diff --git a/SOURCES/setup-named-chroot.sh b/SOURCES/setup-named-chroot.sh index e0247e1..d7de36a 100755 --- a/SOURCES/setup-named-chroot.sh +++ b/SOURCES/setup-named-chroot.sh @@ -2,7 +2,8 @@ ROOTDIR_MOUNT='/etc/localtime /etc/named /etc/pki/dnssec-keys /etc/named.root.key /etc/named.conf /etc/named.dnssec.keys /etc/named.rfc1912.zones /etc/rndc.conf /etc/rndc.key -/usr/lib64/bind /usr/lib/bind /etc/named.iscdlv.key /run/named /var/named' +/usr/lib64/bind /usr/lib/bind /etc/named.iscdlv.key /run/named /var/named +/etc/protocols /etc/services' usage() { diff --git a/SPECS/bind.spec b/SPECS/bind.spec index ce97592..79a6f63 100644 --- a/SPECS/bind.spec +++ b/SPECS/bind.spec @@ -25,7 +25,7 @@ Summary: The Berkeley Internet Name Domain (BIND) DNS (Domain Name System) serv Name: bind License: ISC Version: 9.9.4 -Release: 50%{?PATCHVER}%{?PREVER}%{?dist}.1 +Release: 50%{?PATCHVER}%{?PREVER}%{?dist} Epoch: 32 Url: http://www.isc.org/products/BIND/ Buildroot:%{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) @@ -80,7 +80,8 @@ Patch112:bind97-rh645544.patch Patch119:bind97-rh693982.patch Patch123:bind98-rh735103.patch Patch124:nslookup-norec.patch -Patch125:bind99-buildfix.patch +# FIXME: This disables dlzexternal, which I will enable later again +# Make tests on all architectures and disable it Patch127:bind99-forward.patch Patch130:bind-9.9.1-P2-dlz-libdb.patch Patch131:bind-9.9.1-P2-multlib-conflict.patch @@ -114,22 +115,34 @@ Patch164:bind99-rh1259514.patch Patch165:bind99-rh1306610.patch Patch166:bind99-rh1220594-geoip.patch Patch167:bind99-automatic-interface-scanning-rh1294506.patch +# commit 51bcc28543ce205f7af238ef2f3889ef020a0961 ISC 4467 patch168:bind99-CVE-2016-2776.patch +# commit bbb7c613b3e41495db627909660334695b48e60b ISC 4489 patch169:bind99-CVE-2016-8864.patch +# commit d372472f604d45f85b3bbae5d6f523fb561a8823 ISC 4508 patch170:bind99-CVE-2016-9131.patch +# commit a14b7f0187315767a1fa855f116fe937a7b402e3 ISC 4510 patch171:bind99-CVE-2016-9147.patch +# commit 69cb8ebf157183d9c36a9813f945348dd81b521f ISC 4517 Patch172:bind99-CVE-2016-9444.patch +# commit 2c74ad28efe5710ad04562c6f9902bc48d3be0ed ISC 4530 Patch173:bind99-rt43779.patch +# commit 062b04898be720ed0855efc192847fcbc667b3e1 ISC 4406 +Patch174:bind99-CVE-2016-2775.patch # ISC 4557 -Patch174:bind99-CVE-2017-3135.patch +Patch175:bind99-CVE-2017-3135.patch # ISC 4558 -Patch175:bind99-rt44318.patch +Patch176:bind99-rt44318.patch +# commit c550e75ade4ceb4ece96f660292799519a5c3183 ISC 4567 +Patch177:bind99-rh1392362.patch +# commit 1f3ac11cb4ecfab52f517ebf78493b0f05318be2 +Patch178:bind99-coverity-fixes2.patch # ISC 4575 -Patch176:bind99-CVE-2017-3136.patch +Patch179:bind99-CVE-2017-3136.patch # ISC 4578 -Patch177:bind99-CVE-2017-3137.patch -# ISC 4643 -Patch178: bind99-CVE-2017-3142+3143.patch +Patch180:bind99-CVE-2017-3137.patch +# commit 5e746ab61ed8158f784b86111fef95581a08b7dd ISC 3905 +Patch181:bind99-rh1416304.patch # Native PKCS#11 functionality from 9.10 Patch150:bind-9.9-allow_external_dnskey.patch @@ -144,8 +157,7 @@ Patch62: bind-9.5-sdb-sqlite-bld.patch # needs inpection Patch17: bind-9.3.2b1-fix_sdb_ldap.patch -Patch104: bind-96-dyndb.patch -Patch105: bind-99-dyndb-rh1142150.patch +Patch104: bind99-dyndb.patch # IDN paches Patch73: bind-9.5-libidn.patch @@ -196,6 +208,7 @@ tools for verifying that the DNS server is operating properly. Summary: Bind with native PKCS#11 functionality for crypto Group: System Environment/Daemons Requires: bind = %{epoch}:%{version}-%{release} +Requires: bind-libs = %{epoch}:%{version}-%{release} Requires: bind-pkcs11-libs = %{epoch}:%{version}-%{release} %description pkcs11 @@ -354,8 +367,6 @@ Based on the code from Jan "Yenya" Kasprzak %patch5 -p1 -b .nonexec %patch10 -p1 -b .PIE %patch16 -p1 -b .redhat_doc -%patch104 -p1 -b .dyndb -%patch105 -p1 -b .dyndb_rh1142150 %ifnarch alpha ia64 %patch72 -p1 -b .64bit %endif @@ -376,7 +387,6 @@ Based on the code from Jan "Yenya" Kasprzak pushd bin/dig %patch124 -p0 -b .nslookup-norec popd -%patch125 -p1 -b .buildfix %patch127 -p1 -b .forward %patch130 -p1 -b .libdb %patch131 -p1 -b .multlib-conflict @@ -410,6 +420,7 @@ popd %patch163 -p1 -b .rh1291185 %patch164 -p1 -b .rh1259514 %patch165 -p1 -b .rh1306610-caa +%patch104 -p1 -b .dyndb # GeoIP support %patch166 -p1 -b .rh1220594-geoip @@ -423,11 +434,14 @@ tar -xf %{SOURCE48} -C bin/tests/system/geoip/data %patch171 -p1 -b .CVE-2016-9147 %patch172 -p1 -b .CVE-2016-9444 %patch173 -p1 -b .rt43779 -%patch174 -p1 -b .CVE-2017-3135 -%patch175 -p1 -b .rt44318 -%patch176 -p1 -b .CVE-2017-3136 -%patch177 -p1 -b .CVE-2017-3137 -%patch178 -p1 -b .CVE-2017-3142+3143 +%patch174 -p1 -b .CVE-2016-2775 +%patch175 -p1 -b .CVE-2017-3135 +%patch176 -p1 -b .rt44318 +%patch177 -p1 -b .rh1392362 +%patch178 -p1 -b .coverity2 +%patch179 -p1 -b .CVE-2017-3136 +%patch180 -p1 -b .CVE-2017-3137 +%patch181 -p1 -b .rh1416304 # Override upstream builtin keys cp -fp %{SOURCE29} bind.keys @@ -1038,15 +1052,17 @@ rm -rf ${RPM_BUILD_ROOT} %dir %{chroot_prefix}/var %dir %{chroot_prefix}/run %dir %{chroot_prefix}/var/named -%dir %{chroot_prefix}/%{_libdir}/bind %ghost %config(noreplace) %{chroot_prefix}/etc/named.conf +%defattr(-,root,root,-) +%dir %{chroot_prefix}/usr +%dir %{chroot_prefix}/%{_libdir} +%dir %{chroot_prefix}/%{_libdir}/bind %defattr(0660,named,named,0770) -%dir %{chroot_prefix}/run/named %dir %{chroot_prefix}/var/tmp %dir %{chroot_prefix}/var/log +%defattr(-,named,named,-) +%dir %{chroot_prefix}/run/named %{chroot_prefix}/var/run -%dir %{chroot_prefix}/usr -%dir %{chroot_prefix}/%{_libdir} %if %{SDB} %files sdb-chroot @@ -1067,15 +1083,17 @@ rm -rf ${RPM_BUILD_ROOT} %dir %{chroot_sdb_prefix}/var %dir %{chroot_sdb_prefix}/run %dir %{chroot_sdb_prefix}/var/named -%dir %{chroot_sdb_prefix}/%{_libdir}/bind %ghost %config(noreplace) %{chroot_sdb_prefix}/etc/named.conf +%defattr(-,root,root,-) +%dir %{chroot_sdb_prefix}/usr +%dir %{chroot_sdb_prefix}/%{_libdir} +%dir %{chroot_sdb_prefix}/%{_libdir}/bind %defattr(0660,named,named,0770) -%dir %{chroot_sdb_prefix}/run/named %dir %{chroot_sdb_prefix}/var/tmp %dir %{chroot_sdb_prefix}/var/log +%defattr(-,named,named,-) +%dir %{chroot_sdb_prefix}/run/named %{chroot_sdb_prefix}/var/run -%dir %{chroot_sdb_prefix}/usr -%dir %{chroot_sdb_prefix}/%{_libdir} %endif %if %{PKCS11} @@ -1110,24 +1128,44 @@ rm -rf ${RPM_BUILD_ROOT} %endif %changelog -* Fri Jun 30 2017 Petr Menšík - 32:9.9.4-50.1 -- Bump again above RHEL-7.4 - -* Thu Jun 29 2017 Petr Menšík - 32:9.9.4-38.5 -- Fix CVE-2017-3142 and CVE-2017-3143 +* Mon May 22 2017 Petr Menšík - 32:9.9.4-50 +- Update root servers and trust anchor (#1452635) -* Thu Jun 01 2017 Petr Menšík - 32:9.9.4-38.4 -- Update root servers and trust anchor (#1459649) +* Thu Apr 20 2017 Petr Menšík - 32:9.9.4-49 +- Address deadlock between view.c and adb.c (#1416304) -* Wed Apr 12 2017 Petr Menšík - 32:9.9.4-38.3 +* Tue Apr 11 2017 Petr Menšík - 32:9.9.4-48 - Fix CVE-2017-3136 (ISC change 4575) - Fix CVE-2017-3137 (ISC change 4578) -* Wed Feb 08 2017 Petr Menšík - 32:9.9.4-38.2 +* Wed Mar 29 2017 Petr Menšík - 32:9.9.4-47 +- Simplify change of used config file, point to KB article (#1271315) + +* Tue Mar 28 2017 Petr Menšík - 32:9.9.4-46 +- Make comment how to use different config file (#1271315) + +* Thu Mar 16 2017 Petr Menšík - 32:9.9.4-45 +- Install again dns/dlz.h skipped in rebase +- Fixed coverity warnings on reenabled test dlzexternal + +* Tue Mar 14 2017 Petr Menšík - 32:9.9.4-44 +- Backported new upstream dyndb interface, removed dynamic_db (#1393886) + +* Mon Feb 27 2017 Petr Menšík - 32:9.9.4-43 +- Do not warn on WKS patch (#1392362) + +* Tue Feb 21 2017 Petr Menšík - 32:9.9.4-42 +- Support WKS records in chroot + +* Wed Feb 08 2017 Petr Menšík - 32:9.9.4-41 - Fix CVE-2017-3135 (ISC change 4557) - Fix and test caching CNAME before DNAME (ISC change 4558) -* Mon Jan 09 2017 Petr Menšík - 32:9.9.4-38.1 +* Fri Jan 20 2017 Petr Menšík - 32:9.9.4-40 +- Fix possible infinite loop in start_lookup (CVE-2016-2775) +- Do not change lib permissions in chroot (#1392531) + +* Mon Jan 09 2017 Petr Menšík - 32:9.9.4-39 - Fix CVE-2016-9131 (ISC change 4508) - Fix CVE-2016-9147 (ISC change 4510) - Fix regression introduced by CVE-2016-8864 (ISC change 4530)