mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-22 01:59:26 +00:00
4376. [experimental] Added support for Catalog Zones, a new method for
provisioning secondary servers in which a list of zones to be served is stored in a DNS zone and can be propagated to slaves via AXFR/IXFR. [RT #41581] 4375. [func] Add support for automatic reallocation of isc_buffer to isc_buffer_put* functions. [RT #42394]
This commit is contained in:
parent
bfe9697f92
commit
7a00d69909
3
.gitignore
vendored
3
.gitignore
vendored
@ -55,3 +55,6 @@ unit/atf-src/test-programs/sh_helpers
|
||||
# ccc-analyzer store its results in .plist directories
|
||||
*.plist/
|
||||
*~
|
||||
.project
|
||||
.cproject
|
||||
.settings
|
||||
|
8
CHANGES
8
CHANGES
@ -1,3 +1,11 @@
|
||||
4376. [experimental] Added support for Catalog Zones, a new method for
|
||||
provisioning secondary servers in which a list of
|
||||
zones to be served is stored in a DNS zone and can
|
||||
be propagated to slaves via AXFR/IXFR. [RT #41581]
|
||||
|
||||
4375. [func] Add support for automatic reallocation of isc_buffer
|
||||
to isc_buffer_put* functions. [RT #42394]
|
||||
|
||||
4374. [bug] Use SAVE/RESTORE macros in query.c to reduce the
|
||||
probability of reference counting errors as seen
|
||||
in 4365. [RT #42405]
|
||||
|
@ -576,9 +576,7 @@ get_masters_def(const cfg_obj_t *cctx, const char *name,
|
||||
|
||||
isc_result_t
|
||||
ns_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list,
|
||||
isc_mem_t *mctx, isc_sockaddr_t **addrsp,
|
||||
isc_dscp_t **dscpsp, dns_name_t ***keysp,
|
||||
isc_uint32_t *countp)
|
||||
isc_mem_t *mctx, dns_ipkeylist_t *ipkl)
|
||||
{
|
||||
isc_uint32_t addrcount = 0, dscpcount = 0, keycount = 0, i = 0;
|
||||
isc_uint32_t listcount = 0, l = 0, j;
|
||||
@ -601,10 +599,10 @@ ns_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list,
|
||||
isc_dscp_t dscp;
|
||||
} *stack = NULL;
|
||||
|
||||
REQUIRE(addrsp != NULL && *addrsp == NULL);
|
||||
REQUIRE(dscpsp != NULL && *dscpsp == NULL);
|
||||
REQUIRE(keysp != NULL && *keysp == NULL);
|
||||
REQUIRE(countp != NULL);
|
||||
REQUIRE(ipkl != NULL);
|
||||
REQUIRE(ipkl->addrs == NULL);
|
||||
REQUIRE(ipkl->keys == NULL);
|
||||
REQUIRE(ipkl->dscps == NULL);
|
||||
|
||||
/*
|
||||
* Get system defaults.
|
||||
@ -857,10 +855,10 @@ ns_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list,
|
||||
|
||||
INSIST(keycount == addrcount);
|
||||
|
||||
*addrsp = addrs;
|
||||
*dscpsp = dscps;
|
||||
*keysp = keys;
|
||||
*countp = addrcount;
|
||||
ipkl->addrs = addrs;
|
||||
ipkl->dscps = dscps;
|
||||
ipkl->keys = keys;
|
||||
ipkl->count = addrcount;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
@ -886,37 +884,6 @@ ns_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list,
|
||||
return (result);
|
||||
}
|
||||
|
||||
void
|
||||
ns_config_putipandkeylist(isc_mem_t *mctx, isc_sockaddr_t **addrsp,
|
||||
isc_dscp_t **dscpsp, dns_name_t ***keysp,
|
||||
isc_uint32_t count)
|
||||
{
|
||||
unsigned int i;
|
||||
dns_name_t **keys;
|
||||
|
||||
REQUIRE(addrsp != NULL && *addrsp != NULL);
|
||||
REQUIRE(dscpsp == NULL || *dscpsp != NULL);
|
||||
REQUIRE(keysp != NULL && *keysp != NULL);
|
||||
|
||||
keys = *keysp;
|
||||
|
||||
isc_mem_put(mctx, *addrsp, count * sizeof(isc_sockaddr_t));
|
||||
if (dscpsp != NULL)
|
||||
isc_mem_put(mctx, *dscpsp, count * sizeof(isc_dscp_t));
|
||||
for (i = 0; i < count; i++) {
|
||||
if (keys[i] == NULL)
|
||||
continue;
|
||||
if (dns_name_dynamic(keys[i]))
|
||||
dns_name_free(keys[i], mctx);
|
||||
isc_mem_put(mctx, keys[i], sizeof(dns_name_t));
|
||||
}
|
||||
isc_mem_put(mctx, *keysp, count * sizeof(dns_name_t *));
|
||||
*addrsp = NULL;
|
||||
if (dscpsp != NULL)
|
||||
*dscpsp = NULL;
|
||||
*keysp = NULL;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
ns_config_getport(const cfg_obj_t *config, in_port_t *portp) {
|
||||
const cfg_obj_t *maps[3];
|
||||
|
@ -31,11 +31,11 @@ isc_result_t
|
||||
ns_config_parsedefaults(cfg_parser_t *parser, cfg_obj_t **conf);
|
||||
|
||||
isc_result_t
|
||||
ns_config_get(cfg_obj_t const * const *maps, const char* name,
|
||||
ns_config_get(cfg_obj_t const * const *maps, const char *name,
|
||||
const cfg_obj_t **obj);
|
||||
|
||||
isc_result_t
|
||||
ns_checknames_get(const cfg_obj_t **maps, const char* name,
|
||||
ns_checknames_get(const cfg_obj_t **maps, const char *name,
|
||||
const cfg_obj_t **obj);
|
||||
|
||||
int
|
||||
@ -64,14 +64,7 @@ ns_config_putiplist(isc_mem_t *mctx, isc_sockaddr_t **addrsp,
|
||||
|
||||
isc_result_t
|
||||
ns_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list,
|
||||
isc_mem_t *mctx, isc_sockaddr_t **addrsp,
|
||||
isc_dscp_t **dscpp, dns_name_t ***keys,
|
||||
isc_uint32_t *countp);
|
||||
|
||||
void
|
||||
ns_config_putipandkeylist(isc_mem_t *mctx, isc_sockaddr_t **addrsp,
|
||||
isc_dscp_t **dscpsp, dns_name_t ***keys,
|
||||
isc_uint32_t count);
|
||||
isc_mem_t *mctx, dns_ipkeylist_t *ipkl);
|
||||
|
||||
isc_result_t
|
||||
ns_config_getport(const cfg_obj_t *config, in_port_t *portp);
|
||||
|
@ -283,6 +283,16 @@ options {
|
||||
check-mx-cname ( fail | warn | ignore );
|
||||
check-srv-cname ( fail | warn | ignore );
|
||||
cache-file <replaceable>quoted_string</replaceable>; // test option
|
||||
catalog-zones {
|
||||
zone <replaceable>quoted_string</replaceable>
|
||||
<optional> default-masters
|
||||
<optional>port <replaceable>ip_port</replaceable></optional>
|
||||
<optional>dscp <replaceable>ip_dscp</replaceable></optional>
|
||||
{ ( <replaceable>masters_list</replaceable> | <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> <optional>key <replaceable>key</replaceable></optional> ) ; <optional>...</optional> }</optional>
|
||||
<optional>in-memory <replaceable>yes_or_no</replaceable></optional>
|
||||
<optional>min-update-interval <replaceable>interval</replaceable></optional>
|
||||
; ... };
|
||||
;
|
||||
suppress-initial-notify <replaceable>boolean</replaceable>; // not yet implemented
|
||||
preferred-glue <replaceable>string</replaceable>;
|
||||
dual-stack-servers <optional> port <replaceable>integer</replaceable> </optional> {
|
||||
|
@ -65,11 +65,13 @@
|
||||
#include <dns/adb.h>
|
||||
#include <dns/badcache.h>
|
||||
#include <dns/cache.h>
|
||||
#include <dns/catz.h>
|
||||
#include <dns/db.h>
|
||||
#include <dns/dispatch.h>
|
||||
#include <dns/dlz.h>
|
||||
#include <dns/dns64.h>
|
||||
#include <dns/dyndb.h>
|
||||
#include <dns/events.h>
|
||||
#include <dns/forward.h>
|
||||
#include <dns/journal.h>
|
||||
#include <dns/keytable.h>
|
||||
@ -275,6 +277,19 @@ typedef struct {
|
||||
isc_refcount_t refs;
|
||||
} ns_zoneload_t;
|
||||
|
||||
typedef struct {
|
||||
ns_server_t *server;
|
||||
} catz_cb_data_t;
|
||||
|
||||
typedef struct catz_chgzone_event {
|
||||
ISC_EVENT_COMMON(struct catz_chgzone_event);
|
||||
dns_catz_entry_t *entry;
|
||||
dns_catz_zone_t *origin;
|
||||
dns_view_t *view;
|
||||
catz_cb_data_t *cbd;
|
||||
isc_boolean_t mod;
|
||||
} catz_chgzone_event_t;
|
||||
|
||||
/*
|
||||
* These zones should not leak onto the Internet.
|
||||
*/
|
||||
@ -1990,12 +2005,439 @@ configure_rpz(dns_view_t *view, const cfg_obj_t *rpz_obj,
|
||||
"updated RPZ policy: version %d",
|
||||
view->rpzs->rpz_ver);
|
||||
}
|
||||
|
||||
if (pview != NULL)
|
||||
dns_view_detach(&pview);
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static void
|
||||
catz_addmodzone_taskaction(isc_task_t *task, isc_event_t *event0) {
|
||||
catz_chgzone_event_t *ev = (catz_chgzone_event_t *) event0;
|
||||
isc_result_t result;
|
||||
isc_buffer_t namebuf;
|
||||
isc_buffer_t *confbuf;
|
||||
char nameb[DNS_NAME_FORMATSIZE];
|
||||
const cfg_obj_t *zlist = NULL;
|
||||
cfg_obj_t *zoneconf = NULL;
|
||||
cfg_obj_t *zoneobj = NULL;
|
||||
ns_cfgctx_t *cfg;
|
||||
dns_zone_t *zone = NULL;
|
||||
|
||||
cfg = (ns_cfgctx_t *) ev->view->new_zone_config;
|
||||
if (cfg == NULL) {
|
||||
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
|
||||
NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
|
||||
"catz: allow-new-zones statement missing from "
|
||||
"config; cannot add zone from the catalog");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
isc_buffer_init(&namebuf, nameb, DNS_NAME_FORMATSIZE);
|
||||
dns_name_totext(dns_catz_entry_getname(ev->entry), ISC_TRUE, &namebuf);
|
||||
isc_buffer_putuint8(&namebuf, 0);
|
||||
|
||||
/* Zone shouldn't already exist */
|
||||
result = dns_zt_find(ev->view->zonetable,
|
||||
dns_catz_entry_getname(ev->entry), 0, NULL, &zone);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
|
||||
NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
|
||||
"catz: zone \"%s\" already exists", nameb);
|
||||
goto cleanup;
|
||||
} else if (result == DNS_R_PARTIALMATCH) {
|
||||
/* Create our sub-zone anyway */
|
||||
dns_zone_detach(&zone);
|
||||
zone = NULL;
|
||||
} else if (result != ISC_R_NOTFOUND) {
|
||||
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
|
||||
NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
|
||||
"catz: error \"%s\" while trying to "
|
||||
"add zone \"%s\"",
|
||||
isc_result_totext(result), nameb);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Create a config for new zone */
|
||||
confbuf = NULL;
|
||||
dns_catz_generate_zonecfg(ev->origin, ev->entry, &confbuf);
|
||||
cfg_parser_reset(cfg->add_parser);
|
||||
result = cfg_parse_buffer2(cfg->add_parser, confbuf, "catz",
|
||||
&cfg_type_addzoneconf, &zoneconf);
|
||||
isc_buffer_free(&confbuf);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
|
||||
NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
|
||||
"catz: error \"%s\" while trying to generate "
|
||||
"config for zone \"%s\"",
|
||||
isc_result_totext(result), nameb);
|
||||
goto cleanup;
|
||||
}
|
||||
CHECK(cfg_map_get(zoneconf, "zone", &zlist));
|
||||
if (!cfg_obj_islist(zlist))
|
||||
CHECK(ISC_R_FAILURE);
|
||||
|
||||
/* For now we only support adding one zone at a time */
|
||||
zoneobj = cfg_listelt_value(cfg_list_first(zlist));
|
||||
|
||||
/* Mark view unfrozen so that zone can be added */
|
||||
|
||||
result = isc_task_beginexclusive(task);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
dns_view_thaw(ev->view);
|
||||
result = configure_zone(cfg->config, zoneobj, cfg->vconfig,
|
||||
ev->cbd->server->mctx, ev->view, NULL,
|
||||
cfg->actx, ISC_TRUE, ISC_FALSE, ev->mod);
|
||||
dns_view_freeze(ev->view);
|
||||
isc_task_endexclusive(task);
|
||||
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
|
||||
NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
|
||||
"catz: failed to configure zone \"%s\" - %d",
|
||||
nameb, result);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Is it there yet? */
|
||||
CHECK(dns_zt_find(ev->view->zonetable,
|
||||
dns_catz_entry_getname(ev->entry), 0, NULL, &zone));
|
||||
|
||||
/*
|
||||
* Load the zone from the master file. If this fails, we'll
|
||||
* need to undo the configuration we've done already.
|
||||
*/
|
||||
result = dns_zone_loadnew(zone);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
dns_db_t *dbp = NULL;
|
||||
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
|
||||
NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
|
||||
"catz: dns_zone_loadnew() failed "
|
||||
"with %s; reverting.",
|
||||
isc_result_totext(result));
|
||||
|
||||
/* If the zone loaded partially, unload it */
|
||||
if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) {
|
||||
dns_db_detach(&dbp);
|
||||
dns_zone_unload(zone);
|
||||
}
|
||||
|
||||
/* Remove the zone from the zone table */
|
||||
dns_zt_unmount(ev->view->zonetable, zone);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Flag the zone as having been added at runtime */
|
||||
dns_zone_setadded(zone, ISC_TRUE);
|
||||
|
||||
cleanup:
|
||||
if (zone != NULL)
|
||||
dns_zone_detach(&zone);
|
||||
if (zoneconf != NULL)
|
||||
cfg_obj_destroy(cfg->add_parser, &zoneconf);
|
||||
dns_catz_entry_detach(ev->origin, &ev->entry);
|
||||
dns_catz_zone_detach(&ev->origin);
|
||||
dns_view_detach(&ev->view);
|
||||
isc_event_free(ISC_EVENT_PTR(&ev));
|
||||
}
|
||||
|
||||
static void
|
||||
catz_delzone_taskaction(isc_task_t *task, isc_event_t *event0) {
|
||||
catz_chgzone_event_t *ev = (catz_chgzone_event_t *) event0;
|
||||
isc_result_t result;
|
||||
dns_zone_t *zone = NULL;
|
||||
dns_db_t *dbp = NULL;
|
||||
char cname[DNS_NAME_FORMATSIZE];
|
||||
const char * file;
|
||||
|
||||
result = isc_task_beginexclusive(task);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
|
||||
dns_name_format(dns_catz_entry_getname(ev->entry), cname,
|
||||
DNS_NAME_FORMATSIZE);
|
||||
result = dns_zt_find(ev->view->zonetable,
|
||||
dns_catz_entry_getname(ev->entry), 0, NULL, &zone);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
|
||||
NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
|
||||
"catz: catz_delzone_taskaction: "
|
||||
"zone '%s' not found", cname);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* TODO make other flag for CZ zones */
|
||||
/* TODO2 make sure that we delete only 'own' zones */
|
||||
if (!dns_zone_getadded(zone)) {
|
||||
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
|
||||
NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
|
||||
"catz: catz_delzone_taskaction: "
|
||||
"zone '%s' is not a dynamically added zone",
|
||||
cname);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Stop answering for this zone */
|
||||
if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) {
|
||||
dns_db_detach(&dbp);
|
||||
dns_zone_unload(zone);
|
||||
}
|
||||
|
||||
CHECK(dns_zt_unmount(ev->view->zonetable, zone));
|
||||
file = dns_zone_getfile(zone);
|
||||
isc_file_remove(file);
|
||||
|
||||
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
|
||||
NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
|
||||
"catz: catz_delzone_taskaction: "
|
||||
"zone '%s' deleted", cname);
|
||||
cleanup:
|
||||
isc_task_endexclusive(task);
|
||||
if (zone != NULL)
|
||||
dns_zone_detach(&zone);
|
||||
dns_catz_entry_detach(ev->origin, &ev->entry);
|
||||
dns_catz_zone_detach(&ev->origin);
|
||||
dns_view_detach(&ev->view);
|
||||
isc_event_free(ISC_EVENT_PTR(&ev));
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
catz_create_chg_task(dns_catz_entry_t *entry, dns_catz_zone_t *origin,
|
||||
dns_view_t *view, isc_taskmgr_t *taskmgr, void *udata,
|
||||
isc_eventtype_t type)
|
||||
{
|
||||
catz_chgzone_event_t *event;
|
||||
isc_task_t *task;
|
||||
isc_result_t result;
|
||||
isc_taskaction_t action;
|
||||
|
||||
switch (type) {
|
||||
case DNS_EVENT_CATZADDZONE:
|
||||
case DNS_EVENT_CATZMODZONE:
|
||||
action = catz_addmodzone_taskaction;
|
||||
break;
|
||||
case DNS_EVENT_CATZDELZONE:
|
||||
action = catz_delzone_taskaction;
|
||||
break;
|
||||
default:
|
||||
REQUIRE(0);
|
||||
}
|
||||
|
||||
event = (catz_chgzone_event_t *) isc_event_allocate(view->mctx, origin,
|
||||
type, action, NULL,
|
||||
sizeof(*event));
|
||||
if (event == NULL)
|
||||
return (ISC_R_NOMEMORY);
|
||||
|
||||
event->cbd = (catz_cb_data_t *) udata;
|
||||
event->entry = NULL;
|
||||
event->origin = NULL;
|
||||
event->view = NULL;
|
||||
event->mod = ISC_TF(type == DNS_EVENT_CATZMODZONE);
|
||||
dns_catz_entry_attach(entry, &event->entry);
|
||||
dns_catz_zone_attach(origin, &event->origin);
|
||||
dns_view_attach(view, &event->view);
|
||||
|
||||
task = NULL;
|
||||
result = isc_taskmgr_excltask(taskmgr, &task);
|
||||
REQUIRE(result == ISC_R_SUCCESS);
|
||||
isc_task_send(task, ISC_EVENT_PTR(&event));
|
||||
isc_task_detach(&task);
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
catz_addzone(dns_catz_entry_t *entry, dns_catz_zone_t *origin,
|
||||
dns_view_t *view, isc_taskmgr_t *taskmgr, void *udata)
|
||||
{
|
||||
return (catz_create_chg_task(entry, origin, view, taskmgr, udata,
|
||||
DNS_EVENT_CATZADDZONE));
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
catz_delzone(dns_catz_entry_t *entry, dns_catz_zone_t *origin,
|
||||
dns_view_t *view, isc_taskmgr_t *taskmgr, void *udata)
|
||||
{
|
||||
return (catz_create_chg_task(entry, origin, view, taskmgr, udata,
|
||||
DNS_EVENT_CATZDELZONE));
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
catz_modzone(dns_catz_entry_t *entry, dns_catz_zone_t *origin,
|
||||
dns_view_t *view, isc_taskmgr_t *taskmgr, void *udata)
|
||||
{
|
||||
return (catz_create_chg_task(entry, origin, view, taskmgr, udata,
|
||||
DNS_EVENT_CATZMODZONE));
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
configure_catz_zone(dns_view_t *view, const cfg_obj_t *config,
|
||||
const cfg_listelt_t *element)
|
||||
{
|
||||
const cfg_obj_t *catz_obj, *obj;
|
||||
dns_catz_zone_t *zone = NULL;
|
||||
const char *str;
|
||||
isc_result_t result;
|
||||
dns_name_t origin;
|
||||
dns_catz_options_t *opts;
|
||||
dns_view_t *pview = NULL;
|
||||
|
||||
dns_name_init(&origin, NULL);
|
||||
catz_obj = cfg_listelt_value(element);
|
||||
|
||||
str = cfg_obj_asstring(cfg_tuple_get(catz_obj, "zone name"));
|
||||
|
||||
result = dns_name_fromstring(&origin, str, DNS_NAME_DOWNCASE,
|
||||
view->mctx);
|
||||
if (result == ISC_R_SUCCESS && dns_name_equal(&origin, dns_rootname))
|
||||
result = DNS_R_EMPTYLABEL;
|
||||
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
cfg_obj_log(catz_obj, ns_g_lctx, DNS_CATZ_ERROR_LEVEL,
|
||||
"catz: invalid zone name '%s'", str);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
result = dns_catz_add_zone(view->catzs, &origin, &zone);
|
||||
if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
|
||||
cfg_obj_log(catz_obj, ns_g_lctx, DNS_CATZ_ERROR_LEVEL,
|
||||
"catz: unable to create catalog zone '%s', "
|
||||
"error %s",
|
||||
str, isc_result_totext(result));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (result == ISC_R_EXISTS) {
|
||||
isc_ht_iter_t *it = NULL;
|
||||
|
||||
result = dns_viewlist_find(&ns_g_server->viewlist,
|
||||
view->name,
|
||||
view->rdclass, &pview);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
|
||||
/*
|
||||
* xxxwpk todo: reconfigure the zone!!!!
|
||||
*/
|
||||
cfg_obj_log(catz_obj, ns_g_lctx, DNS_CATZ_ERROR_LEVEL,
|
||||
"catz: catalog zone '%s' will not be reconfigured",
|
||||
str);
|
||||
/*
|
||||
* We have to walk through all the member zones and attach
|
||||
* them to current view
|
||||
*/
|
||||
result = dns_catz_get_iterator(zone, &it);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
cfg_obj_log(catz_obj, ns_g_lctx, DNS_CATZ_ERROR_LEVEL,
|
||||
"catz: unable to create iterator");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
for (result = isc_ht_iter_first(it);
|
||||
result == ISC_R_SUCCESS;
|
||||
result = isc_ht_iter_next(it))
|
||||
{
|
||||
dns_name_t *name = NULL;
|
||||
dns_zone_t *dnszone = NULL;
|
||||
dns_catz_entry_t *entry = NULL;
|
||||
isc_result_t tresult;
|
||||
|
||||
isc_ht_iter_current(it, (void **) &entry);
|
||||
name = dns_catz_entry_getname(entry);
|
||||
|
||||
tresult = dns_view_findzone(pview, name, &dnszone);
|
||||
RUNTIME_CHECK(tresult == ISC_R_SUCCESS);
|
||||
|
||||
dns_zone_setview(dnszone, view);
|
||||
if (view->acache != NULL)
|
||||
dns_zone_setacache(dnszone, view->acache);
|
||||
dns_view_addzone(view, dnszone);
|
||||
}
|
||||
|
||||
isc_ht_iter_destroy(&it);
|
||||
|
||||
result = ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
dns_catz_zone_resetdefoptions(zone);
|
||||
opts = dns_catz_zone_getdefoptions(zone);
|
||||
|
||||
obj = cfg_tuple_get(catz_obj, "default-masters");
|
||||
if (obj != NULL)
|
||||
result = ns_config_getipandkeylist(config, obj,
|
||||
view->mctx, &opts->masters);
|
||||
|
||||
obj = cfg_tuple_get(catz_obj, "in-memory");
|
||||
if (obj != NULL && cfg_obj_isboolean(obj))
|
||||
opts->in_memory = cfg_obj_asboolean(obj);
|
||||
|
||||
obj = cfg_tuple_get(catz_obj, "min-update-interval");
|
||||
if (obj != NULL && cfg_obj_isuint32(obj))
|
||||
opts->min_update_interval = cfg_obj_asuint32(obj);
|
||||
|
||||
cleanup:
|
||||
if (pview != NULL)
|
||||
dns_view_detach(&pview);
|
||||
dns_name_free(&origin, view->mctx);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
static catz_cb_data_t ns_catz_cbdata;
|
||||
static dns_catz_zonemodmethods_t ns_catz_zonemodmethods = {
|
||||
catz_addzone,
|
||||
catz_modzone,
|
||||
catz_delzone,
|
||||
&ns_catz_cbdata
|
||||
};
|
||||
|
||||
static isc_result_t
|
||||
configure_catz(dns_view_t *view, const cfg_obj_t *config,
|
||||
const cfg_obj_t *catz_obj)
|
||||
{
|
||||
const cfg_listelt_t *zone_element;
|
||||
const dns_catz_zones_t *old = NULL;
|
||||
dns_view_t *pview = NULL;
|
||||
isc_result_t result;
|
||||
|
||||
/* xxxwpk TODO do it cleaner, once, somewhere */
|
||||
ns_catz_cbdata.server = ns_g_server;
|
||||
|
||||
zone_element = cfg_list_first(cfg_tuple_get(catz_obj, "zone list"));
|
||||
if (zone_element == NULL)
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
CHECK(dns_catz_new_zones(&view->catzs, &ns_catz_zonemodmethods,
|
||||
view->mctx, ns_g_taskmgr, ns_g_timermgr));
|
||||
|
||||
result = dns_viewlist_find(&ns_g_server->viewlist, view->name,
|
||||
view->rdclass, &pview);
|
||||
if (result == ISC_R_SUCCESS)
|
||||
old = pview->catzs;
|
||||
|
||||
if (old != NULL) {
|
||||
dns_catz_catzs_detach(&view->catzs);
|
||||
dns_catz_catzs_attach(pview->catzs, &view->catzs);
|
||||
dns_catz_prereconfig(view->catzs);
|
||||
}
|
||||
|
||||
while (zone_element != NULL) {
|
||||
CHECK(configure_catz_zone(view, config, zone_element));
|
||||
zone_element = cfg_list_next(zone_element);
|
||||
}
|
||||
|
||||
if (old != NULL)
|
||||
dns_catz_postreconfig(view->catzs);
|
||||
|
||||
result = ISC_R_SUCCESS;
|
||||
|
||||
cleanup:
|
||||
if (pview != NULL)
|
||||
dns_view_detach(&pview);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
#define CHECK_RRL(cond, pat, val1, val2) \
|
||||
do { \
|
||||
if (!(cond)) { \
|
||||
@ -2693,6 +3135,12 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
|
||||
CHECK(configure_rpz(view, obj, &old_rpz_ok));
|
||||
}
|
||||
|
||||
obj = NULL;
|
||||
if (view->rdclass == dns_rdataclass_in && need_hints &&
|
||||
ns_config_get(maps, "catalog-zones", &obj) == ISC_R_SUCCESS) {
|
||||
CHECK(configure_catz(view, config, obj));
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure the zones.
|
||||
*/
|
||||
@ -4574,6 +5022,7 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
|
||||
dns_rdataclass_t zclass;
|
||||
const char *ztypestr;
|
||||
dns_rpz_num_t rpz_num;
|
||||
isc_boolean_t zone_is_catz = ISC_FALSE;
|
||||
|
||||
options = NULL;
|
||||
(void)cfg_map_get(config, "options", &options);
|
||||
@ -4801,6 +5250,10 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
|
||||
break;
|
||||
}
|
||||
|
||||
if (view->catzs != NULL &&
|
||||
dns_catz_get_zone(view->catzs, origin) != NULL)
|
||||
zone_is_catz = ISC_TRUE;
|
||||
|
||||
/*
|
||||
* See if we can reuse an existing zone. This is
|
||||
* only possible if all of these are true:
|
||||
@ -4850,7 +5303,6 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
|
||||
CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone));
|
||||
dns_zone_setstats(zone, ns_g_server->zonestats);
|
||||
}
|
||||
|
||||
if (rpz_num != DNS_RPZ_INVALID_NUM) {
|
||||
result = dns_zone_rpz_enable(zone, view->rpzs, rpz_num);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
@ -4864,6 +5316,9 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
|
||||
}
|
||||
}
|
||||
|
||||
if (zone_is_catz)
|
||||
dns_zone_catz_enable(zone, view->catzs);
|
||||
|
||||
/*
|
||||
* If the zone contains a 'forwarders' statement, configure
|
||||
* selective forwarding.
|
||||
@ -4919,7 +5374,19 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
|
||||
* Add the zone to its view in the new view list.
|
||||
*/
|
||||
if (!modify)
|
||||
CHECK(dns_view_addzone(view, zone));
|
||||
CHECK(dns_view_addzone(view, zone));
|
||||
|
||||
if (zone_is_catz) {
|
||||
/*
|
||||
* force catz reload if the zone is loaded;
|
||||
* if it's not it'll get reloaded on zone load
|
||||
*/
|
||||
dns_db_t *db = NULL;
|
||||
|
||||
tresult = dns_zone_getdb(zone, &db);
|
||||
if (tresult == ISC_R_SUCCESS)
|
||||
dns_catz_dbupdate_callback(db, view->catzs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure that zone keys are reloaded on reconfig
|
||||
@ -5684,6 +6151,20 @@ setup_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
|
||||
if (result == ISC_R_SUCCESS)
|
||||
allow = cfg_obj_asboolean(nz);
|
||||
|
||||
/*
|
||||
* A non-empty catalog-zones statement implies allow-new-zones
|
||||
*/
|
||||
if (!allow) {
|
||||
const cfg_obj_t *cz = NULL;
|
||||
result = ns_config_get(maps, "catalog-zones", &cz);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
const cfg_listelt_t *e =
|
||||
cfg_list_first(cfg_tuple_get(cz, "zone list"));
|
||||
if (e != NULL)
|
||||
allow = ISC_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!allow) {
|
||||
dns_view_setnewzones(view, ISC_FALSE, NULL, NULL);
|
||||
return (ISC_R_SUCCESS);
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
#include <dns/acl.h>
|
||||
#include <dns/db.h>
|
||||
#include <dns/ipkeylist.h>
|
||||
#include <dns/fixedname.h>
|
||||
#include <dns/log.h>
|
||||
#include <dns/name.h>
|
||||
@ -805,9 +806,6 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
|
||||
const char *filename = NULL;
|
||||
const char *dupcheck;
|
||||
dns_notifytype_t notifytype = dns_notifytype_yes;
|
||||
isc_sockaddr_t *addrs;
|
||||
isc_dscp_t *dscps;
|
||||
dns_name_t **keynames;
|
||||
isc_uint32_t count;
|
||||
unsigned int dbargc;
|
||||
char **dbargv;
|
||||
@ -1149,23 +1147,19 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
|
||||
(notifytype == dns_notifytype_masteronly &&
|
||||
ztype == dns_zone_master)))
|
||||
{
|
||||
isc_uint32_t addrcount;
|
||||
addrs = NULL;
|
||||
keynames = NULL;
|
||||
dscps = NULL;
|
||||
dns_ipkeylist_t ipkl;
|
||||
ipkl.count = 0;
|
||||
ipkl.addrs = NULL;
|
||||
ipkl.dscps = NULL;
|
||||
ipkl.keys = NULL;
|
||||
RETERR(ns_config_getipandkeylist(config, obj, mctx,
|
||||
&addrs, &dscps,
|
||||
&keynames,
|
||||
&addrcount));
|
||||
result = dns_zone_setalsonotifydscpkeys(zone, addrs,
|
||||
dscps, keynames,
|
||||
addrcount);
|
||||
if (addrcount != 0)
|
||||
ns_config_putipandkeylist(mctx, &addrs, &dscps,
|
||||
&keynames, addrcount);
|
||||
else
|
||||
INSIST(addrs == NULL && dscps == NULL &&
|
||||
keynames == NULL);
|
||||
&ipkl));
|
||||
result = dns_zone_setalsonotifydscpkeys(zone,
|
||||
ipkl.addrs,
|
||||
ipkl.dscps,
|
||||
ipkl.keys,
|
||||
ipkl.count);
|
||||
dns_ipkeylist_clear(mctx, &ipkl);
|
||||
RETERR(result);
|
||||
} else
|
||||
RETERR(dns_zone_setalsonotify(zone, NULL, 0));
|
||||
@ -1628,19 +1622,19 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
|
||||
obj = NULL;
|
||||
(void)cfg_map_get(zoptions, "masters", &obj);
|
||||
if (obj != NULL) {
|
||||
addrs = NULL;
|
||||
dscps = NULL;
|
||||
keynames = NULL;
|
||||
dns_ipkeylist_t ipkl;
|
||||
ipkl.count = 0;
|
||||
ipkl.addrs = NULL;
|
||||
ipkl.dscps = NULL;
|
||||
ipkl.keys = NULL;
|
||||
RETERR(ns_config_getipandkeylist(config, obj, mctx,
|
||||
&addrs, &dscps,
|
||||
&keynames, &count));
|
||||
result = dns_zone_setmasterswithkeys(mayberaw, addrs,
|
||||
keynames, count);
|
||||
if (count != 0)
|
||||
ns_config_putipandkeylist(mctx, &addrs, &dscps,
|
||||
&keynames, count);
|
||||
else
|
||||
INSIST(addrs == NULL && keynames == NULL);
|
||||
&ipkl));
|
||||
result = dns_zone_setmasterswithkeys(mayberaw,
|
||||
ipkl.addrs,
|
||||
ipkl.keys,
|
||||
ipkl.count);
|
||||
dns_ipkeylist_clear(mctx, &ipkl);
|
||||
RETERR(result);
|
||||
} else
|
||||
result = dns_zone_setmasters(mayberaw, NULL, 0);
|
||||
RETERR(result);
|
||||
|
23
bin/tests/system/catz/clean.sh
Normal file
23
bin/tests/system/catz/clean.sh
Normal file
@ -0,0 +1,23 @@
|
||||
# Copyright (C) 2014-2016 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.
|
||||
|
||||
rm -f dig.out.*
|
||||
rm -f nsupdate.out.*
|
||||
rm -f ns*/named.memstats
|
||||
rm -f ns*/named.run
|
||||
rm -f ns*/named.lock
|
||||
rm -f ns{1,2}/*dom*example.db
|
||||
rm -f ns{1,2}/catalog.example.db
|
||||
rm -f ns*/*.jnl
|
||||
rm -f ns*/*.nzf
|
3
bin/tests/system/catz/ns1/catalog.example.db.in
Normal file
3
bin/tests/system/catz/ns1/catalog.example.db.in
Normal file
@ -0,0 +1,3 @@
|
||||
@ 3600 SOA . . 1 86400 3600 86400 3600
|
||||
@ 3600 IN NS invalid.
|
||||
version IN TXT "1"
|
43
bin/tests/system/catz/ns1/named.conf
Normal file
43
bin/tests/system/catz/ns1/named.conf
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2011, 2013, 2016 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.
|
||||
*/
|
||||
|
||||
include "../../common/rndc.key";
|
||||
|
||||
controls {
|
||||
inet 10.53.0.1 port 9953 allow { any; } keys { rndc_key; };
|
||||
};
|
||||
|
||||
options {
|
||||
query-source address 10.53.0.1;
|
||||
notify-source 10.53.0.1;
|
||||
transfer-source 10.53.0.1;
|
||||
port 5300;
|
||||
allow-new-zones yes;
|
||||
pid-file "named.pid";
|
||||
listen-on { 10.53.0.1; };
|
||||
listen-on-v6 { none; };
|
||||
notify no;
|
||||
recursion no;
|
||||
};
|
||||
|
||||
zone "catalog.example" {
|
||||
type master;
|
||||
file "catalog.example.db";
|
||||
allow-transfer { any; };
|
||||
allow-update { any; };
|
||||
also-notify { 10.53.0.2; };
|
||||
notify explicit;
|
||||
};
|
43
bin/tests/system/catz/ns2/named.conf
Normal file
43
bin/tests/system/catz/ns2/named.conf
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2011, 2013, 2016 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.
|
||||
*/
|
||||
|
||||
include "../../common/rndc.key";
|
||||
|
||||
controls {
|
||||
inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; };
|
||||
};
|
||||
|
||||
options {
|
||||
query-source address 10.53.0.2;
|
||||
notify-source 10.53.0.2;
|
||||
transfer-source 10.53.0.2;
|
||||
port 5300;
|
||||
pid-file "named.pid";
|
||||
listen-on { 10.53.0.2; };
|
||||
listen-on-v6 { none; };
|
||||
notify no;
|
||||
recursion no;
|
||||
serial-query-rate 100;
|
||||
catalog-zones {
|
||||
zone "catalog.example" default-masters { 10.53.0.1; };
|
||||
};
|
||||
};
|
||||
|
||||
zone "catalog.example" {
|
||||
type slave;
|
||||
file "catalog.example.db";
|
||||
masters { 10.53.0.1; };
|
||||
};
|
2
bin/tests/system/catz/ns3/dom4.example.db
Normal file
2
bin/tests/system/catz/ns3/dom4.example.db
Normal file
@ -0,0 +1,2 @@
|
||||
@ 3600 IN SOA . . 1 3600 3600 3600 3600
|
||||
@ IN NS invalid.
|
41
bin/tests/system/catz/ns3/named.conf
Normal file
41
bin/tests/system/catz/ns3/named.conf
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2011, 2013, 2016 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.
|
||||
*/
|
||||
|
||||
include "../../common/rndc.key";
|
||||
|
||||
controls {
|
||||
inet 10.53.0.3 port 9953 allow { any; } keys { rndc_key; };
|
||||
};
|
||||
|
||||
options {
|
||||
query-source address 10.53.0.3;
|
||||
notify-source 10.53.0.3;
|
||||
transfer-source 10.53.0.3;
|
||||
port 5300;
|
||||
pid-file "named.pid";
|
||||
listen-on { 10.53.0.3; };
|
||||
listen-on-v6 { none; };
|
||||
notify no;
|
||||
recursion no;
|
||||
};
|
||||
|
||||
zone "dom4.example" {
|
||||
type master;
|
||||
file "dom4.example.db";
|
||||
allow-transfer { any; };
|
||||
allow-update { any; };
|
||||
notify explicit;
|
||||
};
|
22
bin/tests/system/catz/setup.sh
Normal file
22
bin/tests/system/catz/setup.sh
Normal file
@ -0,0 +1,22 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (C) 2012-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.
|
||||
|
||||
SYSTEMTESTTOP=..
|
||||
. $SYSTEMTESTTOP/conf.sh
|
||||
|
||||
$SHELL clean.sh
|
||||
|
||||
cat ns1/catalog.example.db.in > ns1/catalog.example.db
|
305
bin/tests/system/catz/tests.sh
Normal file
305
bin/tests/system/catz/tests.sh
Normal file
@ -0,0 +1,305 @@
|
||||
#!/bin/sh -x
|
||||
#
|
||||
# Copyright (C) 2014-2016 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
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I:checking that dom1.example is not served by master ($n)"
|
||||
ret=0
|
||||
$DIG soa dom1.example @10.53.0.1 -p 5300 > dig.out.test$n
|
||||
grep "status: REFUSED" dig.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I:Adding a domain dom1.example to master via RNDC ($n)"
|
||||
ret=0
|
||||
echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" > ns1/dom1.example.db
|
||||
echo "@ IN NS invalid." >> ns1/dom1.example.db
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953 addzone dom1.example '{type master; file "dom1.example.db";};' || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I:checking that dom1.example is now served by master ($n)"
|
||||
ret=0
|
||||
$DIG soa dom1.example @10.53.0.1 -p 5300 > dig.out.test$n
|
||||
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
cur=`awk 'BEGIN {l=0} /^/ {l++} END { print l }' ns2/named.run`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I:Adding domain dom1.example to catalog zone ($n)"
|
||||
ret=0
|
||||
$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
|
||||
server 10.53.0.1 5300
|
||||
update add e721433b6160b450260d4f54b3ec8bab30cb3b83.zones.catalog.example 3600 IN PTR dom1.example.
|
||||
send
|
||||
END
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I:waiting for slave to sync up ($n)"
|
||||
ret=1
|
||||
try=0
|
||||
while test $try -lt 45
|
||||
do
|
||||
sleep 1
|
||||
sed -n "$cur,"'$p' < ns2/named.run | grep "catz: adding zone 'dom1.example' from catalog 'catalog.example'" > /dev/null && {
|
||||
ret=0
|
||||
break
|
||||
}
|
||||
try=`expr $try + 1`
|
||||
done
|
||||
try=0
|
||||
while test $try -lt 45
|
||||
do
|
||||
sleep 1
|
||||
sed -n "$cur,"'$p' < ns2/named.run | grep "transfer of 'dom1.example/IN' from 10.53.0.1#5300: Transfer status: success" > /dev/null && {
|
||||
ret=0
|
||||
break
|
||||
}
|
||||
try=`expr $try + 1`
|
||||
done
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I:checking that dom1.example is served by slave ($n)"
|
||||
ret=0
|
||||
$DIG soa dom1.example @10.53.0.2 -p 5300 > dig.out.test$n
|
||||
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I:Removing domain dom1.example from catalog zone ($n)"
|
||||
ret=0
|
||||
$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
|
||||
server 10.53.0.1 5300
|
||||
update delete e721433b6160b450260d4f54b3ec8bab30cb3b83.zones.catalog.example
|
||||
send
|
||||
END
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I:waiting for slave to sync up ($n)"
|
||||
ret=1
|
||||
try=0
|
||||
while test $try -lt 45
|
||||
do
|
||||
sleep 1
|
||||
sed -n "$cur,"'$p' < ns2/named.run | grep "catz: deleting zone 'dom1.example' from catalog 'catalog.example'" > /dev/null && {
|
||||
ret=0
|
||||
break
|
||||
}
|
||||
try=`expr $try + 1`
|
||||
done
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I:checking that dom1.example is not served by slave ($n)"
|
||||
ret=0
|
||||
$DIG soa dom1.example @10.53.0.2 -p 5300 > dig.out.test$n
|
||||
grep "status: REFUSED" dig.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I:Adding a domain dom2.example to master via RNDC ($n)"
|
||||
ret=0
|
||||
echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" > ns1/dom2.example.db
|
||||
echo "@ IN NS invalid." >> ns1/dom2.example.db
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953 addzone dom2.example '{type master; file "dom2.example.db";};' || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I:Adding domains dom2.example, dom3.example and some trash to catalog zone ($n)"
|
||||
ret=0
|
||||
$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
|
||||
server 10.53.0.1 5300
|
||||
update add 636722929740e507aaf27c502812fc395d30fb17.zones.catalog.example 3600 IN PTR dom2.example.
|
||||
update add b901f492f3ebf6c1e5b597e51766f02f0479eb03.zones.catalog.example 3600 IN PTR dom3.example.
|
||||
update add e721433b6160b450260d4f54b3ec8bab30cb3b83.zones.catalog.example 3600 IN NS foo.bar.
|
||||
update add trash.catalog.example 3600 IN A 1.2.3.4
|
||||
update add trash2.foo.catalog.example 3600 IN A 1.2.3.4
|
||||
update add trash3.zones.catalog.example 3600 IN NS a.dom2.example.
|
||||
send
|
||||
END
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I:checking that dom3.example is not served by master ($n)"
|
||||
ret=0
|
||||
$DIG soa dom3.example @10.53.0.1 -p 5300 > dig.out.test$n
|
||||
grep "status: REFUSED" dig.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I:Adding a domain dom3.example to master via RNDC ($n)"
|
||||
ret=0
|
||||
echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" > ns1/dom3.example.db
|
||||
echo "@ IN NS invalid." >> ns1/dom3.example.db
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953 addzone dom3.example '{type master; file "dom3.example.db"; also-notify { 10.53.0.2; }; };' || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I:checking that dom3.example is served by master ($n)"
|
||||
ret=0
|
||||
$DIG soa dom2.example @10.53.0.1 -p 5300 > dig.out.test$n
|
||||
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I:waiting for slave to sync up ($n)"
|
||||
ret=1
|
||||
try=0
|
||||
while test $try -lt 45
|
||||
do
|
||||
sleep 1
|
||||
sed -n "$cur,"'$p' < ns2/named.run | grep "catz: adding zone 'dom3.example' from catalog 'catalog.example'" > /dev/null && {
|
||||
ret=0
|
||||
break
|
||||
}
|
||||
try=`expr $try + 1`
|
||||
done
|
||||
try=0
|
||||
while test $try -lt 45
|
||||
do
|
||||
sleep 1
|
||||
sed -n "$cur,"'$p' < ns2/named.run | grep "transfer of 'dom3.example/IN' from 10.53.0.1#5300: Transfer status: success" > /dev/null && {
|
||||
ret=0
|
||||
break
|
||||
}
|
||||
try=`expr $try + 1`
|
||||
done
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I:checking that dom3.example is served by slave ($n)"
|
||||
ret=0
|
||||
$DIG soa dom3.example @10.53.0.2 -p 5300 > dig.out.test$n
|
||||
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I:Adding dom4.example with 'masters' defined and a random label ($n)"
|
||||
ret=0
|
||||
$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
|
||||
server 10.53.0.1 5300
|
||||
update add somerandomlabel.zones.catalog.example 3600 IN PTR dom4.example.
|
||||
update add masters.somerandomlabel.zones.catalog.example 3600 IN A 10.53.0.3
|
||||
send
|
||||
END
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I:waiting for slave to sync up ($n)"
|
||||
ret=1
|
||||
try=0
|
||||
while test $try -lt 45
|
||||
do
|
||||
sleep 1
|
||||
sed -n "$cur,"'$p' < ns2/named.run | grep "catz: adding zone 'dom4.example' from catalog 'catalog.example'" > /dev/null && {
|
||||
ret=0
|
||||
break
|
||||
}
|
||||
try=`expr $try + 1`
|
||||
done
|
||||
try=0
|
||||
while test $try -lt 45
|
||||
do
|
||||
sleep 1
|
||||
sed -n "$cur,"'$p' < ns2/named.run | grep "transfer of 'dom4.example/IN' from 10.53.0.3#5300: Transfer status: success" > /dev/null && {
|
||||
ret=0
|
||||
break
|
||||
}
|
||||
try=`expr $try + 1`
|
||||
done
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I:checking that dom4.example is served by slave ($n)"
|
||||
ret=0
|
||||
$DIG soa dom4.example @10.53.0.2 -p 5300 > dig.out.test$n
|
||||
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I:Removing domain dom2.example from catalog zone ($n)"
|
||||
ret=0
|
||||
$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
|
||||
server 10.53.0.1 5300
|
||||
update delete 636722929740e507aaf27c502812fc395d30fb17.zones.catalog.example
|
||||
send
|
||||
END
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I:waiting for slave to sync up ($n)"
|
||||
ret=1
|
||||
try=0
|
||||
while test $try -lt 45
|
||||
do
|
||||
sleep 1
|
||||
sed -n "$cur,"'$p' < ns2/named.run | grep "catz: deleting zone 'dom2.example' from catalog 'catalog.example'" > /dev/null && {
|
||||
ret=0
|
||||
break
|
||||
}
|
||||
try=`expr $try + 1`
|
||||
done
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I:checking that dom2.example is not served by slave ($n)"
|
||||
ret=0
|
||||
$DIG soa dom2.example @10.53.0.2 -p 5300 > dig.out.test$n
|
||||
grep "status: REFUSED" dig.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I:checking that dom3.example is still served by slave ($n)"
|
||||
ret=0
|
||||
$DIG soa dom3.example @10.53.0.2 -p 5300 > dig.out.test$n
|
||||
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:exit status: $status"
|
||||
exit $status
|
@ -68,7 +68,7 @@ RANDFILE=$TOP/bin/tests/system/random.data
|
||||
# load on the machine to make it unusable to other users.
|
||||
# v6synth
|
||||
SUBDIRS="acl additional allow_query addzone autosign builtin
|
||||
cacheclean case checkconf @CHECKDS@ checknames checkzone
|
||||
cacheclean case catz checkconf @CHECKDS@ checknames checkzone
|
||||
cookie @COVERAGE@ database digdelv dlv dlvauto dlz dlzexternal
|
||||
dname dns64 dnssec dsdigest dscp @DNSTAP@ dyndb ecdsa ednscompliance
|
||||
emptyzones fetchlimit filter-aaaa formerr forward geoip glue gost
|
||||
|
@ -2373,6 +2373,8 @@ options {
|
||||
|
||||
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="dyndb.xml"/>
|
||||
|
||||
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="catz.xml"/>
|
||||
|
||||
<section xml:id="ipv6"><info><title>IPv6 Support in <acronym>BIND</acronym> 9</title></info>
|
||||
<para>
|
||||
<acronym>BIND</acronym> 9 fully supports all currently
|
||||
@ -4674,6 +4676,16 @@ badresp:1,adberr:0,findfail:0,valfail:0]
|
||||
<optional> qname-wait-recurse <replaceable>yes_or_no</replaceable> </optional>
|
||||
<optional> automatic-interface-scan <replaceable>yes_or_no</replaceable> </optional>
|
||||
; </optional>
|
||||
<optional> catalog-zones {
|
||||
zone <replaceable>quoted_string</replaceable>
|
||||
<optional> default-masters
|
||||
<optional>port <replaceable>ip_port</replaceable></optional>
|
||||
<optional>dscp <replaceable>ip_dscp</replaceable></optional>
|
||||
{ ( <replaceable>masters_list</replaceable> | <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> <optional>key <replaceable>key</replaceable></optional> ) ; <optional>...</optional> }</optional>
|
||||
<optional>in-memory <replaceable>yes_or_no</replaceable></optional>
|
||||
<optional>min-update-interval <replaceable>interval</replaceable></optional>
|
||||
; <optional>...</optional> };
|
||||
; </optional>
|
||||
<optional>v6-bias <replaceable>number</replaceable> ; </optional>
|
||||
};
|
||||
</programlisting>
|
||||
|
Binary file not shown.
229
doc/arm/catz.xml
Normal file
229
doc/arm/catz.xml
Normal file
@ -0,0 +1,229 @@
|
||||
<!--
|
||||
- Copyright (C) 2016 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.
|
||||
-->
|
||||
<section xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="catz-info"><info><title>Catalog Zones</title></info>
|
||||
|
||||
<para>
|
||||
A "catalog zone" is a special DNS zone that contains a list of
|
||||
other zones to be served, along with their configuration parameters.
|
||||
Zones listed in a catalog zone are called "member zones".
|
||||
When a catalog zone is loaded or transferred to a slave server
|
||||
which supports this functionality, the slave server will create
|
||||
the member zones automatically. When the catalog zone is updated
|
||||
is updated (for example, to add or delete member zones, or change
|
||||
their configuration aprameters) those changes are immediately put
|
||||
into effect. Because the catalog zone is a normal DNS zone, these
|
||||
configuration changes can be propagated using the standard AXFR/IXFR
|
||||
zone transfer mechanism.
|
||||
</para>
|
||||
<para>
|
||||
Catalog zones' format and behavior are specified as an internet draft
|
||||
for interoperability among DNS implementations. As of this release, the
|
||||
latest revision of the DNS catalog zones draft can be found here:
|
||||
https://datatracker.ietf.org/doc/draft-muks-dnsop-dns-catalog-zones/
|
||||
</para>
|
||||
|
||||
<section><info><title>Principle of Operation</title></info>
|
||||
<para>
|
||||
Normally, if a zone is to be served by a slave server, the
|
||||
<filename>named.conf</filename> file on the server must list the
|
||||
zone, or the zone must be added using <command>rndc addzone</command>.
|
||||
In environments with a large number of slave servers and/or where
|
||||
the zones being served are changing frequently, the overhead involved
|
||||
in maintaining consistent zone configuration on all the slave
|
||||
servers can be significant.
|
||||
</para>
|
||||
<para>
|
||||
A catalog zone is a way to ease this administrative burden. It is a
|
||||
DNS zone that lists member zones that should be served by slave servers.
|
||||
When a slave server receives an update to the catalog zone, it adds,
|
||||
removes, or reconfigures member zones based on the data received.
|
||||
</para>
|
||||
<para>
|
||||
To use a catalog zone, it must first be set up as a normal zone on
|
||||
the master and the on slave servers that will be configured to use
|
||||
it. It must also be added to a <option>catalog-zones</option> list
|
||||
in the <option>options</option> or <option>view</option> statement
|
||||
in <filename>named.conf</filename>. (This is comparable to the way
|
||||
a policy zone is configured as a normal zone and also listed in
|
||||
a <option>response-policy</option> statement.)
|
||||
</para>
|
||||
<para>
|
||||
To use the catalog zone feature to serve a new member zone:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
Set up the the member zone to be served on the master as normal.
|
||||
This could be done by editing <filename>named.conf</filename>,
|
||||
or by running <command>rndc addzone</command>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Add an entry to the catalog zone for the new member zone.
|
||||
This could be done by editing the catalog zone's master file
|
||||
and running <command>rndc reload</command>, or by updating
|
||||
the zone using <command>nsupdate</command>.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
The change to the catalog zone will be propagated from the master to all
|
||||
slaves using the normal AXFR/IXFR mechanism. When the slave receives the
|
||||
update to the catalog zone, it will detect the entry for the new member
|
||||
zone, create an instance of of that zone on the slave server, and point
|
||||
that instance to the <option>masters</option> specified in the catalog
|
||||
zone data. The newly created member zone is a normal slave zone, so
|
||||
BIND will immediately initiate a transfer of zone contents from the
|
||||
master. Once complete, the slave will start serving the member zone.
|
||||
</para>
|
||||
<para>
|
||||
Removing a member zone from a slave server requires nothing more than
|
||||
deleting the member zone's entry in the catalog zone. The change to the
|
||||
catalog cone is propagated to the slave server using the normal AXFR/IXFR
|
||||
transfer mechanism. The slave server, on processing the update, will
|
||||
notice that the member zone has been removed. It will stop serving the
|
||||
zone and remove it froms its list of configured zones. (Removing the
|
||||
member zone from the master server has to be done in the normal way,
|
||||
by editing the configuration file or running
|
||||
<command>rndc delzone</command>.)
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section><info><title>Configuring Catalog Zones</title></info>
|
||||
<para>
|
||||
Catalog zones are configured with a <command>catalog-zones</command>
|
||||
statement in the <literal>options</literal> or <literal>view</literal>
|
||||
section of <filename>named.conf</filename>. For example,
|
||||
</para>
|
||||
<screen>
|
||||
catalog-zones {
|
||||
zone "catalog.example" default-masters { 10.53.0.1; } in-memory true min-update-interval 10;
|
||||
};
|
||||
</screen>
|
||||
<para>
|
||||
This statement specifies that the zone
|
||||
<literal>catalog.example</literal> is a catalog zone. This zone must be
|
||||
properly configured in the same view. In most configurations, it would
|
||||
be a slave zone.
|
||||
</para>
|
||||
<para>
|
||||
The <option>default-masters</option> option defines the default masters
|
||||
for member zones listed in a catalog zone. This can be overriden by
|
||||
options within a catalog zone. If no such options are included, then
|
||||
member zones will transfer their contents from the servers listed in
|
||||
this option.
|
||||
</para>
|
||||
<para>
|
||||
The <option>in-memory</option> option, if set to <literal>yes</literal>,
|
||||
causes member zones to be stored only in memory. This is functionally
|
||||
equivalent to configuring a slave zone without a <option>file</option>.
|
||||
option. The default is <literal>no</literal>; member zones' content
|
||||
will be stored locally in a file whose name is automatically generated
|
||||
from the view name, catalog zone name, and member zone name.
|
||||
</para>
|
||||
<para>
|
||||
The <option>min-update-interval</option> option sets the minimum
|
||||
interval between processing of updates to catalog zones, in seconds.
|
||||
If an update to a catalog zone (for example, via IXFR) happens less
|
||||
than <option>min-update-interval</option> seconds after the most
|
||||
recent update, then the changes will not be carried out until this
|
||||
interval has elapsed. The default is <literal>5</literal> seconds.
|
||||
</para>
|
||||
<para>
|
||||
Catalog zones are defined on a per-view basis. Configuring a non-empty
|
||||
<option>catalog-zones</option> statement in a view will automatically
|
||||
turn on <option>allow-new-zones</option> for that view. (Note: this
|
||||
means <command>rndc addzone</command> and <command>rndc delzone</command>
|
||||
will also work in any view that supports catalog zones.)
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section><info><title>Catalog Zone format</title></info>
|
||||
<para>
|
||||
A catalog zone is a regular DNS zone; therefore, it has to have a
|
||||
single <literal>SOA</literal> and at least one <literal>NS</literal>
|
||||
record.
|
||||
</para>
|
||||
<para>
|
||||
A record stating the version of the catalog zone format is
|
||||
also required. If the version number listed is not supported by
|
||||
the server, then a catalog zone may not be used by that server.
|
||||
</para>
|
||||
<screen>
|
||||
catalog.example. IN SOA . . 2016022901 900 600 86400 1
|
||||
catalog.example. IN NS nsexample.
|
||||
version.catalog.example. IN TXT "1"
|
||||
</screen>
|
||||
<para>
|
||||
Note that this record must have the domain name
|
||||
version.<replaceable>catalog-zone-name</replaceable>. This illustrates
|
||||
how the meaning of data stored in a catalog zone is indicated by the
|
||||
the domain name label immediately before the catalog zone domain.
|
||||
</para>
|
||||
<para>
|
||||
Catalog zones can contain a set of global options that are applied to
|
||||
all member zones, overriding the settings for the catalog zone
|
||||
in the configuration file. Currently only the "masters" option
|
||||
is supported:
|
||||
<!-- TODO masters IN MX (with TSIG), allow-query, allow-tranfer -->
|
||||
</para>
|
||||
<screen>
|
||||
masters.catalog.example IN A 192.0.2.1
|
||||
masters.catalog.example IN AAAA 2001:db8::1
|
||||
</screen>
|
||||
<para>
|
||||
(Note that if more than one server is defined, the order in which
|
||||
they are used is undefined. The above example could correspond to
|
||||
a zone configured with
|
||||
<option>masters { 192.0.2.1; 2001:db8::1; };</option>
|
||||
or with
|
||||
<option>masters { 2001:db8::1; 192.0.2.1; };</option>.
|
||||
There is currently no way to force a particular ordering.)
|
||||
</para>
|
||||
<para>
|
||||
A member zone is added by including a <literal>PTR</literal>
|
||||
resource record in the <literal>zones</literal> sub-domain of the
|
||||
catalog zone. The record label is a <literal>SHA-1</literal> hash
|
||||
of the member zone name in wire format. The target of the PTR
|
||||
record is the member zone name. For example, to add the member
|
||||
zone <literal>domain.example</literal>:
|
||||
</para>
|
||||
<screen>
|
||||
5960775ba382e7a4e09263fc06e7c00569b6a05c.zones.catalog.example IN PTR domain.example.
|
||||
</screen>
|
||||
<para>
|
||||
The hash is necessary to identify options for a specific member
|
||||
zone. The member zone-specific options are defined the same way as
|
||||
global options, but in the member zone subdomain:
|
||||
</para>
|
||||
<screen>
|
||||
masters.5960775ba382e7a4e09263fc06e7c00569b6a05c.zones.catalog.example IN A 192.0.2.2
|
||||
masters.5960775ba382e7a4e09263fc06e7c00569b6a05c.zones.catalog.example IN AAAA 2001:db8::2
|
||||
</screen>
|
||||
<para>
|
||||
As would be expected, options defined for a specific zone override
|
||||
the global options defined in the catalog zone. These in turn override
|
||||
the global options defined in the <literal>catalog-zones</literal>
|
||||
statement in the configuration file.
|
||||
</para>
|
||||
<para>
|
||||
(Note that none of the global records an option will be inherited if
|
||||
any records are defined for that option for the specific zone. For
|
||||
example, if the zone had a <literal>masters</literal> record of type
|
||||
A but not AAAA, then it would <emphasis>not</emphasis> inherit the
|
||||
type AAAA record from the global option.)
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
@ -54,6 +54,35 @@
|
||||
|
||||
<section xml:id="relnotes_features"><info><title>New Features</title></info>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
A new method of provisioning secondary servers called
|
||||
"Catalog Zones" has been added. This is an implementation of
|
||||
<link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="https://datatracker.ietf.org/doc/draft-muks-dnsop-dns-catalog-zones/">
|
||||
draft-muks-dnsop-dns-catalog-zones/
|
||||
</link>.
|
||||
</para>
|
||||
<para>
|
||||
A catalog zone is a regular DNS zone which contains a list
|
||||
of "member zones", along with the configuration options for
|
||||
each of those zones. When a server is configured to use a
|
||||
catalog zone, all the zones listed in the catalog zone are
|
||||
added to the local server as slave zones. When the catalog
|
||||
zone is updated (e.g., by adding or removing zones, or
|
||||
changing configuration options for existing zones) those
|
||||
changes will be put into effect. Since the catalog zone is
|
||||
itself a DNS zone, this means configuration changes can be
|
||||
propagated to slaves using the standard AXFR/IXFR update
|
||||
mechanism.
|
||||
</para>
|
||||
<para>
|
||||
This feature should be considered experimental. It currently
|
||||
supports only basic features; more advanced features such as
|
||||
ACLs and TSIG keys are not yet supported. Example catalog
|
||||
zone configurations can be found in the Chapter 9 of the
|
||||
BIND Administrator Reference Manual.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Added rndc python module.
|
||||
|
@ -65,11 +65,11 @@ DNSTAPOBJS = dnstap.@O@ dnstap.pb-c.@O@
|
||||
|
||||
# Alphabetically
|
||||
DNSOBJS = acache.@O@ acl.@O@ adb.@O@ badcache.@O@ byaddr.@O@ \
|
||||
cache.@O@ callbacks.@O@ clientinfo.@O@ compress.@O@ \
|
||||
cache.@O@ callbacks.@O@ catz.@O@ clientinfo.@O@ compress.@O@ \
|
||||
db.@O@ dbiterator.@O@ dbtable.@O@ diff.@O@ dispatch.@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@ \
|
||||
ipkeylist.@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@ nta.@O@ \
|
||||
order.@O@ peer.@O@ portlist.@O@ private.@O@ \
|
||||
@ -108,8 +108,8 @@ DNSSRCS = acache.c acl.c adb.c badcache. 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 dyndb.c forward.c \
|
||||
iptable.c journal.c keydata.c keytable.c lib.c log.c \
|
||||
lookup.c master.c masterdump.c message.c \
|
||||
ipkeylist.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 nta.c \
|
||||
order.c peer.c portlist.c \
|
||||
rbt.c rbtdb.c rbtdb64.c rcode.c rdata.c rdatalist.c \
|
||||
|
@ -583,7 +583,7 @@ initialize_action(void) {
|
||||
}
|
||||
|
||||
/*
|
||||
* Called via isc_radix_walk() to find IP table nodes that are
|
||||
* Called via isc_radix_process() to find IP table nodes that are
|
||||
* insecure.
|
||||
*/
|
||||
static void
|
||||
|
1474
lib/dns/catz.c
Normal file
1474
lib/dns/catz.c
Normal file
File diff suppressed because it is too large
Load Diff
72
lib/dns/db.c
72
lib/dns/db.c
@ -15,8 +15,6 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
/***
|
||||
@ -307,6 +305,8 @@ dns_db_beginload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
|
||||
|
||||
isc_result_t
|
||||
dns_db_endload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
|
||||
dns_dbonupdatelistener_t *listener;
|
||||
|
||||
/*
|
||||
* Finish loading 'db'.
|
||||
*/
|
||||
@ -315,6 +315,11 @@ dns_db_endload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
|
||||
REQUIRE(DNS_CALLBACK_VALID(callbacks));
|
||||
REQUIRE(callbacks->add_private != NULL);
|
||||
|
||||
for (listener = ISC_LIST_HEAD(db->update_listeners);
|
||||
listener != NULL;
|
||||
listener = ISC_LIST_NEXT(listener, link))
|
||||
listener->onupdate(db, listener->onupdate_arg);
|
||||
|
||||
return ((db->methods->endload)(db, callbacks));
|
||||
}
|
||||
|
||||
@ -330,7 +335,8 @@ dns_db_load2(dns_db_t *db, const char *filename, dns_masterformat_t format) {
|
||||
|
||||
isc_result_t
|
||||
dns_db_load3(dns_db_t *db, const char *filename, dns_masterformat_t format,
|
||||
unsigned int options) {
|
||||
unsigned int options)
|
||||
{
|
||||
isc_result_t result, eresult;
|
||||
dns_rdatacallbacks_t callbacks;
|
||||
|
||||
@ -445,6 +451,7 @@ void
|
||||
dns_db_closeversion(dns_db_t *db, dns_dbversion_t **versionp,
|
||||
isc_boolean_t commit)
|
||||
{
|
||||
dns_dbonupdatelistener_t *listener;
|
||||
|
||||
/*
|
||||
* Close version '*versionp'.
|
||||
@ -456,6 +463,13 @@ dns_db_closeversion(dns_db_t *db, dns_dbversion_t **versionp,
|
||||
|
||||
(db->methods->closeversion)(db, versionp, commit);
|
||||
|
||||
if (commit == ISC_TRUE) {
|
||||
for (listener = ISC_LIST_HEAD(db->update_listeners);
|
||||
listener != NULL;
|
||||
listener = ISC_LIST_NEXT(listener, link))
|
||||
listener->onupdate(db, listener->onupdate_arg);
|
||||
}
|
||||
|
||||
ENSURE(*versionp == NULL);
|
||||
}
|
||||
|
||||
@ -1043,3 +1057,55 @@ dns_db_rpz_ready(dns_db_t *db) {
|
||||
return (ISC_R_SUCCESS);
|
||||
return ((db->methods->rpz_ready)(db));
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach a notify-on-update function the database
|
||||
*/
|
||||
isc_result_t
|
||||
dns_db_updatenotify_register(dns_db_t *db,
|
||||
dns_dbupdate_callback_t fn,
|
||||
void *fn_arg)
|
||||
{
|
||||
dns_dbonupdatelistener_t *listener;
|
||||
|
||||
REQUIRE(db != NULL);
|
||||
REQUIRE(fn != NULL);
|
||||
|
||||
listener = isc_mem_get(db->mctx, sizeof(dns_dbonupdatelistener_t));
|
||||
if (listener == NULL)
|
||||
return (ISC_R_NOMEMORY);
|
||||
|
||||
listener->onupdate = fn;
|
||||
listener->onupdate_arg = fn_arg;
|
||||
|
||||
ISC_LINK_INIT(listener, link);
|
||||
ISC_LIST_APPEND(db->update_listeners, listener, link);
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_db_updatenotify_unregister(dns_db_t *db,
|
||||
dns_dbupdate_callback_t fn,
|
||||
void *fn_arg)
|
||||
{
|
||||
dns_dbonupdatelistener_t *listener;
|
||||
|
||||
REQUIRE(db != NULL);
|
||||
|
||||
for (listener = ISC_LIST_HEAD(db->update_listeners);
|
||||
listener != NULL;
|
||||
listener = ISC_LIST_NEXT(listener, link))
|
||||
{
|
||||
if ((listener->onupdate == fn) &&
|
||||
(listener->onupdate_arg == fn_arg))
|
||||
{
|
||||
ISC_LIST_UNLINK(db->update_listeners, listener, link);
|
||||
isc_mem_put(db->mctx, listener,
|
||||
sizeof(dns_dbonupdatelistener_t));
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
return (ISC_R_NOTFOUND);
|
||||
}
|
||||
|
465
lib/dns/include/dns/catz.h
Normal file
465
lib/dns/include/dns/catz.h
Normal file
@ -0,0 +1,465 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2016 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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DNS_CATZ_H
|
||||
#define DNS_CATZ_H 1
|
||||
|
||||
#include <isc/ht.h>
|
||||
#include <isc/lang.h>
|
||||
#include <isc/refcount.h>
|
||||
#include <isc/rwlock.h>
|
||||
#include <isc/time.h>
|
||||
#include <isc/timer.h>
|
||||
|
||||
#include <dns/db.h>
|
||||
#include <dns/fixedname.h>
|
||||
#include <dns/ipkeylist.h>
|
||||
#include <dns/rdata.h>
|
||||
#include <dns/types.h>
|
||||
|
||||
ISC_LANG_BEGINDECLS
|
||||
|
||||
#define DNS_CATZ_ERROR_LEVEL ISC_LOG_WARNING
|
||||
#define DNS_CATZ_INFO_LEVEL ISC_LOG_INFO
|
||||
#define DNS_CATZ_DEBUG_LEVEL1 ISC_LOG_DEBUG(1)
|
||||
#define DNS_CATZ_DEBUG_LEVEL2 ISC_LOG_DEBUG(2)
|
||||
#define DNS_CATZ_DEBUG_LEVEL3 ISC_LOG_DEBUG(3)
|
||||
#define DNS_CATZ_DEBUG_QUIET (DNS_CATZ_DEBUG_LEVEL3+1)
|
||||
|
||||
/*
|
||||
* Catalog Zones functions and structures.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Options for a member zone in a catalog
|
||||
*/
|
||||
struct dns_catz_entry_options {
|
||||
/*
|
||||
* Options that can be overriden in catalog zone
|
||||
*/
|
||||
/* masters definition */
|
||||
dns_ipkeylist_t masters;
|
||||
|
||||
/*
|
||||
* Options that are only set in named.conf
|
||||
*/
|
||||
/* zone should not be stored on disk (no 'file' statement in def */
|
||||
isc_boolean_t in_memory;
|
||||
/*
|
||||
* Minimal interval between catalog zone updates, if a new version
|
||||
* of catalog zone is received before this time the update will be
|
||||
* postponed. This is a global option for the whole catalog zone.
|
||||
*/
|
||||
isc_uint32_t min_update_interval;
|
||||
};
|
||||
|
||||
void
|
||||
dns_catz_options_init(dns_catz_options_t *options);
|
||||
/*%<
|
||||
* Initialize 'options' to NULL values.
|
||||
*
|
||||
* Requires:
|
||||
* \li options to be non NULL
|
||||
*/
|
||||
|
||||
void
|
||||
dns_catz_options_free(dns_catz_options_t *options, isc_mem_t *mctx);
|
||||
/*%<
|
||||
* Free 'options' contents into 'mctx'. ('options' itself is not freed.)
|
||||
*
|
||||
* Requires:
|
||||
* \li options to be non NULL
|
||||
* \li mctx to be a valid memory context
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_catz_options_copy(isc_mem_t *mctx, const dns_catz_options_t *opts,
|
||||
dns_catz_options_t *nopts);
|
||||
/*%<
|
||||
* Duplicate 'opts' into 'nopts', allocating space from 'mctx'
|
||||
*
|
||||
* Requires:
|
||||
* \li 'mctx' to be a valid memory context
|
||||
* \li 'options' to be non NULL and valid options
|
||||
* \li 'nopts' to be non NULL
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_catz_options_setdefault(isc_mem_t *mctx, const dns_catz_options_t *defaults,
|
||||
dns_catz_options_t *opts);
|
||||
/*%<
|
||||
* Replace empty values in 'opts' with values from 'defaults'
|
||||
*
|
||||
* Requires:
|
||||
* \li mctx to be a valid memory context
|
||||
* \li defaults to be non NULL and valid options
|
||||
* \li opts to be non NULL
|
||||
*/
|
||||
|
||||
dns_name_t *
|
||||
dns_catz_entry_getname(dns_catz_entry_t *entry);
|
||||
/*%<
|
||||
* Get domain name for 'entry'
|
||||
*
|
||||
* Requires:
|
||||
* \li entry to be non NULL
|
||||
*
|
||||
* Returns:
|
||||
* \li domain name for entry
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_catz_entry_new(isc_mem_t *mctx, const dns_name_t *domain,
|
||||
dns_catz_entry_t **nentryp);
|
||||
/*%<
|
||||
* Allocate a new catz_entry on 'mctx', with the name 'domain'
|
||||
*
|
||||
* Requires:
|
||||
* \li mctx to be a valid memory context
|
||||
* \li domain to be valid dns_name or NULL
|
||||
* \li nentryp to be non NULL, *nentryp to be NULL
|
||||
*
|
||||
* Returns:
|
||||
* \li ISC_R_SUCCESS on success
|
||||
* \li ISC_R_NOMEMORY on allocation failure
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_catz_entry_copy(dns_catz_zone_t *zone, const dns_catz_entry_t *entry,
|
||||
dns_catz_entry_t **nentryp);
|
||||
/*%<
|
||||
* Allocate a new catz_entry and deep copy 'entry' into 'nentryp'.
|
||||
*
|
||||
* Requires:
|
||||
* \li mctx to be a valid memory context
|
||||
* \li entry to be non NULL
|
||||
* \li nentryp to be non NULL, *nentryp to be NULL
|
||||
*
|
||||
* Returns:
|
||||
* \li ISC_R_SUCCESS on success
|
||||
* \li ISC_R_NOMEMORY on allocation failure
|
||||
*/
|
||||
|
||||
void
|
||||
dns_catz_entry_attach(dns_catz_entry_t *entry, dns_catz_entry_t **entryp);
|
||||
/*%<
|
||||
* Attach an entry
|
||||
*
|
||||
* Requires:
|
||||
* \li entry is not NULL
|
||||
* \li entryp is not NULL, *entryp is NULL
|
||||
*/
|
||||
|
||||
void
|
||||
dns_catz_entry_detach(dns_catz_zone_t *zone, dns_catz_entry_t **entryp);
|
||||
/*%<
|
||||
* Detach an entry, free if no further references
|
||||
*
|
||||
* Requires:
|
||||
* \li zone is not NULL
|
||||
* \li entryp is not NULL, *entryp is not NULL
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_catz_entry_validate(const dns_catz_entry_t *entry);
|
||||
/*%<
|
||||
* Validate whether entry is correct.
|
||||
* (NOT YET IMPLEMENTED: always returns true)
|
||||
*/
|
||||
|
||||
isc_boolean_t
|
||||
dns_catz_entry_cmp(const dns_catz_entry_t *ea, const dns_catz_entry_t *eb);
|
||||
/*%<
|
||||
* Deep compare two entries
|
||||
*
|
||||
* Requires:
|
||||
* \li ea is not NULL
|
||||
* \li eb is not NULL
|
||||
*
|
||||
* Returns:
|
||||
* \li ISC_TRUE if entries are the same
|
||||
* \li ISC_FALSE if the entries differ
|
||||
*/
|
||||
|
||||
void
|
||||
dns_catz_zone_attach(dns_catz_zone_t *zone, dns_catz_zone_t **zonep);
|
||||
/*%<
|
||||
* Attach a catzone
|
||||
*
|
||||
* Requires:
|
||||
* \li zone is not NULL
|
||||
* \li zonep is not NULL, *zonep is NULL
|
||||
*/
|
||||
|
||||
void
|
||||
dns_catz_zone_detach(dns_catz_zone_t** zonep);
|
||||
/*%<
|
||||
* Detach a zone, free if no further references
|
||||
*
|
||||
* Requires:
|
||||
* \li zonep is not NULL, *zonep is not NULL
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_catz_new_zone(dns_catz_zones_t *catzs, dns_catz_zone_t **zonep,
|
||||
const dns_name_t *name);
|
||||
/*%<
|
||||
* Allocate a new catz zone on catzs mctx
|
||||
*
|
||||
* Requires:
|
||||
* \li catzs is not NULL
|
||||
* \li zonep is not NULL, *zonep is NULL
|
||||
* \li name is not NULL
|
||||
*
|
||||
*/
|
||||
|
||||
dns_name_t *
|
||||
dns_catz_zone_getname(dns_catz_zone_t *zone);
|
||||
/*%<
|
||||
* Get catalog zone name
|
||||
*
|
||||
* Requires:
|
||||
* \li zone is not NULL
|
||||
*/
|
||||
|
||||
dns_catz_options_t *
|
||||
dns_catz_zone_getdefoptions(dns_catz_zone_t *zone);
|
||||
/*%<
|
||||
* Get default member zone options for catalog zone 'zone'
|
||||
*
|
||||
* Requires:
|
||||
* \li zone is not NULL
|
||||
*/
|
||||
|
||||
void
|
||||
dns_catz_zone_resetdefoptions(dns_catz_zone_t *zone);
|
||||
/*%<
|
||||
* Reset the default member zone options for catalog zone 'zone' to
|
||||
* the default values.
|
||||
*
|
||||
* Requires:
|
||||
* \li zone is not NULL
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_catz_zones_merge(dns_catz_zone_t *target, dns_catz_zone_t *newzone);
|
||||
/*%<
|
||||
* Merge 'newzone' into 'target', calling addzone/delzone/modzone
|
||||
* (from zone->catzs->zmm) for appropriate member zones.
|
||||
*
|
||||
* Requires:
|
||||
* \li orig is not NULL
|
||||
* \li newzone is not NULL, *newzone is not NULL
|
||||
*
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_catz_update_process(dns_catz_zones_t *catzs, dns_catz_zone_t *zone,
|
||||
dns_name_t *src_name, dns_rdataset_t *rdataset);
|
||||
/*%<
|
||||
* Process a single rdataset from a catalog zone 'zone' update, src_name is the
|
||||
* record name.
|
||||
*
|
||||
* Requires:
|
||||
* \li catzs is not NULL
|
||||
* \li zone is not NULL
|
||||
* \li src_name is not NULL
|
||||
* \li rdataset is valid
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_catz_generate_masterfilename(dns_catz_zone_t *zone, dns_catz_entry_t *entry,
|
||||
isc_buffer_t **buffer);
|
||||
/*%<
|
||||
* Generate master file name and put it into *buffer (might be reallocated).
|
||||
* The general format of the file name is:
|
||||
* __catz__catalog.zone.name__member_zone_name.db
|
||||
* But if it's too long it's shortened to:
|
||||
* __catz__unique_hash_generated_from_the_above.db
|
||||
*
|
||||
* Requires:
|
||||
* \li zone is not NULL
|
||||
* \li entry is not NULL
|
||||
* \li buffer is not NULL and *buffer is not NULL
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_catz_generate_zonecfg(dns_catz_zone_t *zone, dns_catz_entry_t *entry,
|
||||
isc_buffer_t **buf);
|
||||
/*%<
|
||||
* Generate a zone config entry (in text form) from dns_catz_entry and puts
|
||||
* it into *buf. buf might be reallocated.
|
||||
*
|
||||
* Requires:
|
||||
* \li zone is not NULL
|
||||
* \li entry is not NULL
|
||||
* \li buf is not NULL
|
||||
* \li *buf is NULL
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* Methods provided by named to dynamically modify the member zones */
|
||||
/* xxxwpk TODO config! */
|
||||
struct dns_catz_zonemodmethods {
|
||||
isc_result_t (*addzone)(dns_catz_entry_t *entry, dns_catz_zone_t *origin,
|
||||
dns_view_t *view, isc_taskmgr_t *taskmgr, void *udata);
|
||||
isc_result_t (*modzone)(dns_catz_entry_t *entry, dns_catz_zone_t *origin,
|
||||
dns_view_t *view, isc_taskmgr_t *taskmgr, void *udata);
|
||||
isc_result_t (*delzone)(dns_catz_entry_t *entry, dns_catz_zone_t *origin,
|
||||
dns_view_t *view, isc_taskmgr_t *task, void *udata);
|
||||
void * udata;
|
||||
};
|
||||
|
||||
|
||||
isc_result_t
|
||||
dns_catz_new_zones(dns_catz_zones_t **catzsp, dns_catz_zonemodmethods_t *zmm,
|
||||
isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
|
||||
isc_timermgr_t *timermgr);
|
||||
/*%<
|
||||
* Allocate a new catz_zones object, a collection storing all catalog zones
|
||||
* for a view.
|
||||
*
|
||||
* Requires:
|
||||
* \li catzsp is not NULL, *catzsp is NULL
|
||||
* \li zmm is not NULL
|
||||
*
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_catz_add_zone(dns_catz_zones_t *catzs, const dns_name_t *name,
|
||||
dns_catz_zone_t **catzp);
|
||||
/*%<
|
||||
* Allocate a new catz named 'name' and put it in 'catzs' collection.
|
||||
*
|
||||
* Requires:
|
||||
* \li catzs is not NULL
|
||||
* \li name is not NULL
|
||||
* \li zonep is not NULL, *zonep is NULL
|
||||
*
|
||||
*/
|
||||
|
||||
dns_catz_zone_t *
|
||||
dns_catz_get_zone(dns_catz_zones_t *catzs, const dns_name_t *name);
|
||||
/*%<
|
||||
* Returns a zone named 'name' from collection 'catzs'
|
||||
*
|
||||
* Requires:
|
||||
* \li catzs is not NULL
|
||||
* \li name is not NULL
|
||||
*/
|
||||
|
||||
void
|
||||
dns_catz_catzs_attach(dns_catz_zones_t *catzs, dns_catz_zones_t **catzsp);
|
||||
/*%<
|
||||
* Attach 'catzs' to 'catzsp'
|
||||
*
|
||||
* Requires:
|
||||
* \li catzs is not NULL
|
||||
* \li catzsp is not NULL, *catzsp is NULL
|
||||
*/
|
||||
|
||||
void
|
||||
dns_catz_catzs_detach(dns_catz_zones_t **catzsp);
|
||||
/*%<
|
||||
* Detach 'catzsp', free if no further references
|
||||
*
|
||||
* Requires:
|
||||
* \li catzsp is not NULL, *catzsp is not NULL
|
||||
*/
|
||||
|
||||
void
|
||||
dns_catz_catzs_set_view(dns_catz_zones_t *catzs, dns_view_t *view);
|
||||
/*%<
|
||||
* Set a view for catzs
|
||||
*
|
||||
* Requires:
|
||||
* \li catzs is not NULL
|
||||
* \li catzs->view is NULL or catzs->view == view
|
||||
*/
|
||||
|
||||
|
||||
isc_result_t
|
||||
dns_catz_dbupdate_callback(dns_db_t *db, void *fn_arg);
|
||||
/*%<
|
||||
* Callback for update of catalog zone database.
|
||||
* If there was no catalog zone update recently it launches an
|
||||
* update_taskaction immediately.
|
||||
* If there was an update recently it schedules update_taskaction for some time
|
||||
* in the future.
|
||||
* If there is an update scheduled it replaces old db version with a new one.
|
||||
*
|
||||
* Requires:
|
||||
* \li db is a valid database
|
||||
* \li fn_arg is not NULL (casted to dns_catz_zones_t*)
|
||||
*/
|
||||
|
||||
void
|
||||
dns_catz_update_taskaction(isc_task_t *task, isc_event_t *event);
|
||||
/*%<
|
||||
* Task that launches dns_catz_update_from_db
|
||||
*
|
||||
* Requires:
|
||||
* \li event is not NULL
|
||||
*/
|
||||
|
||||
void
|
||||
dns_catz_update_from_db(dns_db_t *db, dns_catz_zones_t *catzs);
|
||||
/*%<
|
||||
* Process an updated database for a catalog zone.
|
||||
* It creates a new catz, iterates over database to fill it with content, and
|
||||
* then merges new catz into old catz.
|
||||
*
|
||||
* Requires:
|
||||
* \li db is a valid DB
|
||||
* \li catzs is not NULL
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
dns_catz_prereconfig(dns_catz_zones_t *catzs);
|
||||
/*%<
|
||||
* Called before reconfig, clears 'active' flag on all the zones in set
|
||||
*
|
||||
* Requires:
|
||||
* \li catzs is not NULL
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
dns_catz_postreconfig(dns_catz_zones_t *catzs);
|
||||
/*%<
|
||||
* Called after reconfig, walks through all zones in set, removes those
|
||||
* inactive and force reload of those with changed configuration.
|
||||
*
|
||||
* Requires:
|
||||
* \li catzs is not NULL
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_catz_get_iterator(dns_catz_zone_t *catz, isc_ht_iter_t **itp);
|
||||
/*%<
|
||||
* Get the hashtable iterator on catalog zone members, point '*itp' to it.
|
||||
*
|
||||
* Returns:
|
||||
* \li #ISC_R_SUCCESS -- success
|
||||
* \li Any other value -- failure
|
||||
*/
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
||||
#endif /* DNS_CATZ_H_ */
|
@ -203,6 +203,9 @@ typedef isc_result_t
|
||||
unsigned int argc, char *argv[], void *driverarg,
|
||||
dns_db_t **dbp);
|
||||
|
||||
typedef isc_result_t
|
||||
(*dns_dbupdate_callback_t)(dns_db_t *db, void *fn_arg);
|
||||
|
||||
#define DNS_DB_MAGIC ISC_MAGIC('D','N','S','D')
|
||||
#define DNS_DB_VALID(db) ISC_MAGIC_VALID(db, DNS_DB_MAGIC)
|
||||
|
||||
@ -216,19 +219,26 @@ typedef isc_result_t
|
||||
* invariants.
|
||||
*/
|
||||
struct dns_db {
|
||||
unsigned int magic;
|
||||
unsigned int impmagic;
|
||||
dns_dbmethods_t * methods;
|
||||
isc_uint16_t attributes;
|
||||
dns_rdataclass_t rdclass;
|
||||
dns_name_t origin;
|
||||
isc_ondestroy_t ondest;
|
||||
isc_mem_t * mctx;
|
||||
unsigned int magic;
|
||||
unsigned int impmagic;
|
||||
dns_dbmethods_t * methods;
|
||||
isc_uint16_t attributes;
|
||||
dns_rdataclass_t rdclass;
|
||||
dns_name_t origin;
|
||||
isc_ondestroy_t ondest;
|
||||
isc_mem_t * mctx;
|
||||
ISC_LIST(dns_dbonupdatelistener_t) update_listeners;
|
||||
};
|
||||
|
||||
#define DNS_DBATTR_CACHE 0x01
|
||||
#define DNS_DBATTR_STUB 0x02
|
||||
|
||||
struct dns_dbonupdatelistener {
|
||||
dns_dbupdate_callback_t onupdate;
|
||||
void * onupdate_arg;
|
||||
ISC_LINK(dns_dbonupdatelistener_t) link;
|
||||
};
|
||||
|
||||
/*@{*/
|
||||
/*%
|
||||
* Options that can be specified for dns_db_find().
|
||||
@ -1624,6 +1634,35 @@ dns_db_rpz_ready(dns_db_t *db);
|
||||
* Finish loading a response policy zone.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_db_updatenotify_register(dns_db_t *db,
|
||||
dns_dbupdate_callback_t fn,
|
||||
void *fn_arg);
|
||||
/*%<
|
||||
* Register a notify-on-update callback function to a database.
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
* \li 'db' is a valid database
|
||||
* \li 'db' does not have an update callback registered
|
||||
* \li 'fn' is not NULL
|
||||
*
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_db_updatenotify_unregister(dns_db_t *db,
|
||||
dns_dbupdate_callback_t fn,
|
||||
void *fn_arg);
|
||||
/*%<
|
||||
* Unregister a notify-on-update callback.
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
* \li 'db' is a valid database
|
||||
* \li 'db' has update callback registered
|
||||
*
|
||||
*/
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
||||
#endif /* DNS_DB_H */
|
||||
|
@ -80,6 +80,10 @@
|
||||
#define DNS_EVENT_KEYDONE (ISC_EVENTCLASS_DNS + 50)
|
||||
#define DNS_EVENT_SETNSEC3PARAM (ISC_EVENTCLASS_DNS + 51)
|
||||
#define DNS_EVENT_SETSERIAL (ISC_EVENTCLASS_DNS + 52)
|
||||
#define DNS_EVENT_CATZUPDATED (ISC_EVENTCLASS_DNS + 53)
|
||||
#define DNS_EVENT_CATZADDZONE (ISC_EVENTCLASS_DNS + 54)
|
||||
#define DNS_EVENT_CATZMODZONE (ISC_EVENTCLASS_DNS + 55)
|
||||
#define DNS_EVENT_CATZDELZONE (ISC_EVENTCLASS_DNS + 56)
|
||||
|
||||
#define DNS_EVENT_FIRSTEVENT (ISC_EVENTCLASS_DNS + 0)
|
||||
#define DNS_EVENT_LASTEVENT (ISC_EVENTCLASS_DNS + 65535)
|
||||
|
61
lib/dns/include/dns/ipkeylist.h
Normal file
61
lib/dns/include/dns/ipkeylist.h
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (C) 2016 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.
|
||||
*/
|
||||
|
||||
#ifndef DNS_IPKEYLIST_H
|
||||
#define DNS_IPKEYLIST_H 1
|
||||
|
||||
#include <isc/types.h>
|
||||
#include <dns/types.h>
|
||||
|
||||
/*%
|
||||
* A structure holding a list of addresses, dscps and keys. Used to
|
||||
* store masters for a slave zone, created by parsing config options.
|
||||
*/
|
||||
struct dns_ipkeylist {
|
||||
isc_sockaddr_t *addrs;
|
||||
isc_dscp_t *dscps;
|
||||
dns_name_t **keys;
|
||||
isc_uint32_t count;
|
||||
};
|
||||
|
||||
void
|
||||
dns_ipkeylist_clear(isc_mem_t *mctx, dns_ipkeylist_t *ipkl);
|
||||
/*%<
|
||||
* Free `ipkl` contents using `mctx`.
|
||||
*
|
||||
* After this call, `ipkl` is a freshly cleared structure with all
|
||||
* pointers set to `NULL` and count set to 0.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'mctx' to be a valid memory context.
|
||||
*\li 'ipkl' to be non NULL and have its members `addrs` and `keys`
|
||||
* allocated. 'dscps' might be NULL.
|
||||
*/
|
||||
|
||||
void
|
||||
dns_ipkeylist_copy(isc_mem_t *mctx, const dns_ipkeylist_t *src,
|
||||
dns_ipkeylist_t *dst);
|
||||
/*%<
|
||||
* Deep copy `src` into empty `dst`, allocating `dst`'s contents.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'mctx' to be a valid memory context.
|
||||
*\li 'src' to be non NULL
|
||||
*\li 'dst' to be non NULL and point to an empty \ref dns_ipkeylist_t
|
||||
* with all pointers set to `NULL` and count set to 0.
|
||||
*/
|
||||
|
||||
#endif
|
@ -391,7 +391,7 @@ dns_rbt_addnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnode_t **nodep);
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_rbt_findname(dns_rbt_t *rbt, dns_name_t *name, unsigned int options,
|
||||
dns_rbt_findname(dns_rbt_t *rbt, const dns_name_t *name, unsigned int options,
|
||||
dns_name_t *foundname, void **data);
|
||||
/*%<
|
||||
* Get the data pointer associated with 'name'.
|
||||
@ -430,7 +430,7 @@ dns_rbt_findname(dns_rbt_t *rbt, dns_name_t *name, unsigned int options,
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, dns_name_t *foundname,
|
||||
dns_rbt_findnode(dns_rbt_t *rbt, const dns_name_t *name, dns_name_t *foundname,
|
||||
dns_rbtnode_t **node, dns_rbtnodechain_t *chain,
|
||||
unsigned int options, dns_rbtfindcallback_t callback,
|
||||
void *callback_arg);
|
||||
|
@ -45,6 +45,12 @@ typedef struct dns_adbfind dns_adbfind_t;
|
||||
typedef ISC_LIST(dns_adbfind_t) dns_adbfindlist_t;
|
||||
typedef struct dns_badcache dns_badcache_t;
|
||||
typedef struct dns_byaddr dns_byaddr_t;
|
||||
typedef struct dns_catz_zonemodmethods dns_catz_zonemodmethods_t;
|
||||
typedef struct dns_catz_entry_options dns_catz_options_t;
|
||||
typedef struct dns_catz_entry dns_catz_entry_t;
|
||||
typedef struct dns_catz_zone dns_catz_zone_t;
|
||||
typedef struct dns_catz_changed dns_catz_changed_t;
|
||||
typedef struct dns_catz_zones dns_catz_zones_t;
|
||||
typedef struct dns_client dns_client_t;
|
||||
typedef void dns_clientrestrans_t;
|
||||
typedef void dns_clientreqtrans_t;
|
||||
@ -57,6 +63,7 @@ typedef struct dns_dbimplementation dns_dbimplementation_t;
|
||||
typedef struct dns_dbiterator dns_dbiterator_t;
|
||||
typedef void dns_dbload_t;
|
||||
typedef void dns_dbnode_t;
|
||||
typedef struct dns_dbonupdatelistener dns_dbonupdatelistener_t;
|
||||
typedef struct dns_dbtable dns_dbtable_t;
|
||||
typedef void dns_dbversion_t;
|
||||
typedef struct dns_dlzimplementation dns_dlzimplementation_t;
|
||||
@ -146,6 +153,7 @@ typedef struct dns_zone dns_zone_t;
|
||||
typedef ISC_LIST(dns_zone_t) dns_zonelist_t;
|
||||
typedef struct dns_zonemgr dns_zonemgr_t;
|
||||
typedef struct dns_zt dns_zt_t;
|
||||
typedef struct dns_ipkeylist dns_ipkeylist_t;
|
||||
|
||||
/*
|
||||
* If we are not using GSSAPI, define the types we use as opaque types here.
|
||||
|
@ -70,6 +70,7 @@
|
||||
#include <isc/stdtime.h>
|
||||
|
||||
#include <dns/acl.h>
|
||||
#include <dns/catz.h>
|
||||
#include <dns/clientinfo.h>
|
||||
#include <dns/dnstap.h>
|
||||
#include <dns/fixedname.h>
|
||||
@ -178,6 +179,7 @@ struct dns_view {
|
||||
dns_dns64list_t dns64;
|
||||
unsigned int dns64cnt;
|
||||
dns_rpz_zones_t *rpzs;
|
||||
dns_catz_zones_t *catzs;
|
||||
dns_dlzdblist_t dlz_searched;
|
||||
dns_dlzdblist_t dlz_unsearched;
|
||||
isc_uint32_t fail_ttl;
|
||||
|
@ -15,8 +15,6 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef DNS_ZONE_H
|
||||
#define DNS_ZONE_H 1
|
||||
|
||||
@ -32,6 +30,7 @@
|
||||
#include <isc/lang.h>
|
||||
#include <isc/rwlock.h>
|
||||
|
||||
#include <dns/catz.h>
|
||||
#include <dns/master.h>
|
||||
#include <dns/masterdump.h>
|
||||
#include <dns/rdatastruct.h>
|
||||
@ -2393,6 +2392,30 @@ dns_zone_rpz_enable_db(dns_zone_t *zone, dns_db_t *db);
|
||||
dns_rpz_num_t
|
||||
dns_zone_get_rpz_num(dns_zone_t *zone);
|
||||
|
||||
void
|
||||
dns_zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs);
|
||||
/*%<
|
||||
* Enable zone as catalog zone.
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
* \li 'zone' is a valid zone object
|
||||
* \li 'catzs' is not NULL
|
||||
* \li prior to calling, zone->catzs is NULL or is equal to 'catzs'
|
||||
*/
|
||||
|
||||
void
|
||||
dns_zone_catz_enable_db(dns_zone_t *zone, dns_db_t *db);
|
||||
/*%<
|
||||
* If 'zone' is a catalog zone, then set up a notify-on-update trigger
|
||||
* in its database. (If not a catalog zone, this function has no effect.)
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
* \li 'zone' is a valid zone object
|
||||
* \li 'db' is not NULL
|
||||
*/
|
||||
|
||||
void
|
||||
dns_zone_setstatlevel(dns_zone_t *zone, dns_zonestat_level_t level);
|
||||
|
||||
|
@ -90,7 +90,7 @@ dns_zt_unmount(dns_zt_t *zt, dns_zone_t *zone);
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_zt_find(dns_zt_t *zt, dns_name_t *name, unsigned int options,
|
||||
dns_zt_find(dns_zt_t *zt, const dns_name_t *name, unsigned int options,
|
||||
dns_name_t *foundname, dns_zone_t **zone);
|
||||
/*%<
|
||||
* Find the best match for 'name' in 'zt'. If foundname is non NULL
|
||||
|
92
lib/dns/ipkeylist.c
Normal file
92
lib/dns/ipkeylist.c
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (C) 2016 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.
|
||||
*/
|
||||
|
||||
#include <isc/mem.h>
|
||||
#include <isc/sockaddr.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <dns/ipkeylist.h>
|
||||
#include <dns/name.h>
|
||||
|
||||
void
|
||||
dns_ipkeylist_clear(isc_mem_t *mctx, dns_ipkeylist_t *ipkl) {
|
||||
isc_uint32_t i;
|
||||
|
||||
REQUIRE(ipkl != NULL);
|
||||
REQUIRE(ipkl->addrs != NULL);
|
||||
REQUIRE(ipkl->keys != NULL);
|
||||
|
||||
if (ipkl->count == 0)
|
||||
return;
|
||||
|
||||
isc_mem_put(mctx, ipkl->addrs, ipkl->count * sizeof(isc_sockaddr_t));
|
||||
if (ipkl->dscps != NULL)
|
||||
isc_mem_put(mctx, ipkl->dscps,
|
||||
ipkl->count * sizeof(isc_dscp_t));
|
||||
for (i = 0; i < ipkl->count; i++) {
|
||||
if (ipkl->keys[i] == NULL)
|
||||
continue;
|
||||
if (dns_name_dynamic(ipkl->keys[i]))
|
||||
dns_name_free(ipkl->keys[i], mctx);
|
||||
isc_mem_put(mctx, ipkl->keys[i], sizeof(dns_name_t));
|
||||
}
|
||||
isc_mem_put(mctx, ipkl->keys, ipkl->count * sizeof(dns_name_t *));
|
||||
ipkl->count = 0;
|
||||
ipkl->addrs = NULL;
|
||||
ipkl->dscps = NULL;
|
||||
ipkl->keys = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
dns_ipkeylist_copy(isc_mem_t *mctx, const dns_ipkeylist_t *src,
|
||||
dns_ipkeylist_t *dst)
|
||||
{
|
||||
isc_uint32_t i;
|
||||
|
||||
REQUIRE(dst != NULL);
|
||||
REQUIRE(dst->count == 0 &&
|
||||
dst->addrs == NULL && dst->keys == NULL && dst->dscps == NULL);
|
||||
|
||||
if (src->count == 0)
|
||||
return;
|
||||
|
||||
dst->count = src->count;
|
||||
|
||||
dst->addrs = isc_mem_get(mctx,
|
||||
src->count * sizeof(isc_sockaddr_t));
|
||||
memmove(dst->addrs, src->addrs,
|
||||
src->count * sizeof(isc_sockaddr_t));
|
||||
|
||||
if (src->dscps != NULL) {
|
||||
dst->dscps = isc_mem_get(mctx,
|
||||
src->count * sizeof(isc_dscp_t));
|
||||
memmove(dst->dscps, src->dscps,
|
||||
src->count * sizeof(isc_dscp_t));
|
||||
}
|
||||
|
||||
if (src->keys != NULL) {
|
||||
dst->keys = isc_mem_get(mctx, src->count * sizeof(dns_name_t *));
|
||||
for (i = 0; i < src->count; i++) {
|
||||
if (src->keys[i] != NULL) {
|
||||
dst->keys[i] = isc_mem_get(mctx,
|
||||
sizeof(dns_name_t));
|
||||
dns_name_dup(src->keys[i], mctx, dst->keys[i]);
|
||||
} else {
|
||||
dst->keys[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1566,9 +1566,13 @@ dns_name_totext2(const dns_name_t *name, unsigned int options,
|
||||
if (nlen != 0 && trem == 0)
|
||||
return (ISC_R_NOSPACE);
|
||||
|
||||
if (!saw_root || omit_final_dot)
|
||||
if (!saw_root || omit_final_dot) {
|
||||
trem++;
|
||||
|
||||
tdata--;
|
||||
}
|
||||
if (trem > 0) {
|
||||
*tdata = 0;
|
||||
}
|
||||
isc_buffer_add(target, tlen - trem);
|
||||
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
|
@ -1457,7 +1457,7 @@ dns_rbt_addname(dns_rbt_t *rbt, dns_name_t *name, void *data) {
|
||||
* Find the node for "name" in the tree of trees.
|
||||
*/
|
||||
isc_result_t
|
||||
dns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, dns_name_t *foundname,
|
||||
dns_rbt_findnode(dns_rbt_t *rbt, const dns_name_t *name, dns_name_t *foundname,
|
||||
dns_rbtnode_t **node, dns_rbtnodechain_t *chain,
|
||||
unsigned int options, dns_rbtfindcallback_t callback,
|
||||
void *callback_arg)
|
||||
@ -1988,7 +1988,7 @@ dns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, dns_name_t *foundname,
|
||||
* Get the data pointer associated with 'name'.
|
||||
*/
|
||||
isc_result_t
|
||||
dns_rbt_findname(dns_rbt_t *rbt, dns_name_t *name, unsigned int options,
|
||||
dns_rbt_findname(dns_rbt_t *rbt, const dns_name_t *name, unsigned int options,
|
||||
dns_name_t *foundname, void **data) {
|
||||
dns_rbtnode_t *node = NULL;
|
||||
isc_result_t result;
|
||||
|
@ -1159,6 +1159,7 @@ free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log, isc_event_t *event) {
|
||||
char buf[DNS_NAME_FORMATSIZE];
|
||||
dns_rbt_t **treep;
|
||||
isc_time_t start;
|
||||
dns_dbonupdatelistener_t *listener, *listener_next;
|
||||
|
||||
if (IS_CACHE(rbtdb) && rbtdb->common.rdclass == dns_rdataclass_in)
|
||||
overmem((dns_db_t *)rbtdb, (isc_boolean_t)-1);
|
||||
@ -1317,6 +1318,16 @@ free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log, isc_event_t *event) {
|
||||
isc_file_munmap(rbtdb->mmap_location,
|
||||
(size_t) rbtdb->mmap_size);
|
||||
|
||||
for (listener = ISC_LIST_HEAD(rbtdb->common.update_listeners);
|
||||
listener != NULL;
|
||||
listener = listener_next)
|
||||
{
|
||||
listener_next = ISC_LIST_NEXT(listener, link);
|
||||
ISC_LIST_UNLINK(rbtdb->common.update_listeners, listener, link);
|
||||
isc_mem_put(rbtdb->common.mctx, listener,
|
||||
sizeof(dns_dbonupdatelistener_t));
|
||||
}
|
||||
|
||||
isc_mem_putanddetach(&rbtdb->common.mctx, rbtdb, sizeof(*rbtdb));
|
||||
isc_ondestroy_notify(&ondest, rbtdb);
|
||||
}
|
||||
@ -8166,6 +8177,8 @@ dns_rbtdb_create
|
||||
rbtdb->common.rdclass = rdclass;
|
||||
rbtdb->common.mctx = NULL;
|
||||
|
||||
ISC_LIST_INIT(rbtdb->common.update_listeners);
|
||||
|
||||
result = RBTDB_INITLOCK(&rbtdb->lock);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_rbtdb;
|
||||
|
@ -229,6 +229,7 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
|
||||
view->v6_aaaa = dns_aaaa_ok;
|
||||
view->aaaa_acl = NULL;
|
||||
view->rpzs = NULL;
|
||||
view->catzs = NULL;
|
||||
dns_fixedname_init(&view->dlv_fixed);
|
||||
view->managed_keys = NULL;
|
||||
view->redirect = NULL;
|
||||
@ -379,6 +380,8 @@ destroy(dns_view_t *view) {
|
||||
dns_rrl_view_destroy(view);
|
||||
if (view->rpzs != NULL)
|
||||
dns_rpz_detach_rpzs(&view->rpzs);
|
||||
if (view->catzs != NULL)
|
||||
dns_catz_catzs_detach(&view->catzs);
|
||||
for (dlzdb = ISC_LIST_HEAD(view->dlz_searched);
|
||||
dlzdb != NULL;
|
||||
dlzdb = ISC_LIST_HEAD(view->dlz_searched)) {
|
||||
@ -578,6 +581,9 @@ view_flushanddetach(dns_view_t **viewp, isc_boolean_t flush) {
|
||||
if (view->flush)
|
||||
dns_zone_flush(rdzone);
|
||||
}
|
||||
if (view->catzs != NULL) {
|
||||
dns_catz_catzs_detach(&view->catzs);
|
||||
}
|
||||
done = all_done(view);
|
||||
UNLOCK(&view->lock);
|
||||
|
||||
|
@ -109,6 +109,28 @@ dns_cache_setcachesize
|
||||
dns_cache_setcleaninginterval
|
||||
dns_cache_setfilename
|
||||
dns_cache_updatestats
|
||||
dns_catz_catzs_attach
|
||||
dns_catz_catzs_detach
|
||||
dns_catz_catzs_set_view
|
||||
dns_catz_dbupdate_callback
|
||||
dns_catz_entry_attach
|
||||
dns_catz_entry_cmp
|
||||
dns_catz_entry_detach
|
||||
dns_catz_entry_getname
|
||||
dns_catz_entry_validate
|
||||
dns_catz_get_iterator
|
||||
dns_catz_get_zone
|
||||
dns_catz_options_clear
|
||||
dns_catz_options_init
|
||||
dns_catz_postreconfig
|
||||
dns_catz_prereconfig
|
||||
dns_catz_update_from_db
|
||||
dns_catz_update_taskaction
|
||||
dns_catz_zone_attach
|
||||
dns_catz_zone_detach
|
||||
dns_catz_zone_getdefoptions
|
||||
dns_catz_zone_getname
|
||||
dns_catz_zones_merge
|
||||
dns_cert_fromtext
|
||||
dns_cert_totext
|
||||
dns_client_addtrustedkey
|
||||
@ -209,6 +231,8 @@ dns_db_settask
|
||||
dns_db_subtractrdataset
|
||||
dns_db_transfernode
|
||||
dns_db_unregister
|
||||
dns_db_updatenotify_register
|
||||
dns_db_updatenotify_unregister
|
||||
dns_dbiterator_current
|
||||
dns_dbiterator_destroy
|
||||
dns_dbiterator_first
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <dns/callbacks.h>
|
||||
#include <dns/catz.h>
|
||||
#include <dns/db.h>
|
||||
#include <dns/diff.h>
|
||||
#include <dns/events.h>
|
||||
@ -279,8 +280,10 @@ axfr_makedb(dns_xfrin_ctx_t *xfr, dns_db_t **dbp) {
|
||||
xfr->rdclass,
|
||||
0, NULL, /* XXX guess */
|
||||
dbp);
|
||||
if (result == ISC_R_SUCCESS)
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
dns_zone_rpz_enable_db(xfr->zone, *dbp);
|
||||
dns_zone_catz_enable_db(xfr->zone, *dbp);
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include <dns/acl.h>
|
||||
#include <dns/adb.h>
|
||||
#include <dns/callbacks.h>
|
||||
#include <dns/catz.h>
|
||||
#include <dns/db.h>
|
||||
#include <dns/dbiterator.h>
|
||||
#include <dns/dlz.h>
|
||||
@ -380,6 +381,11 @@ struct dns_zone {
|
||||
dns_rpz_zones_t *rpzs;
|
||||
dns_rpz_num_t rpz_num;
|
||||
|
||||
/*%
|
||||
* catalog zone data
|
||||
*/
|
||||
dns_catz_zones_t *catzs;
|
||||
|
||||
/*%
|
||||
* Serial number update method.
|
||||
*/
|
||||
@ -1036,6 +1042,9 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
|
||||
zone->automatic = ISC_FALSE;
|
||||
zone->rpzs = NULL;
|
||||
zone->rpz_num = DNS_RPZ_INVALID_NUM;
|
||||
|
||||
zone->catzs = NULL;
|
||||
|
||||
ISC_LIST_INIT(zone->forwards);
|
||||
zone->raw = NULL;
|
||||
zone->secure = NULL;
|
||||
@ -1170,6 +1179,9 @@ zone_free(dns_zone_t *zone) {
|
||||
dns_rpz_detach_rpzs(&zone->rpzs);
|
||||
zone->rpz_num = DNS_RPZ_INVALID_NUM;
|
||||
}
|
||||
if (zone->catzs != NULL) {
|
||||
dns_catz_catzs_detach(&zone->catzs);
|
||||
}
|
||||
zone_freedbargs(zone);
|
||||
RUNTIME_CHECK(dns_zone_setmasterswithkeys(zone, NULL, NULL, 0)
|
||||
== ISC_R_SUCCESS);
|
||||
@ -1748,6 +1760,34 @@ dns_zone_rpz_enable_db(dns_zone_t *zone, dns_db_t *db) {
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dns_zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs) {
|
||||
REQUIRE(DNS_ZONE_VALID(zone));
|
||||
REQUIRE(catzs != NULL);
|
||||
|
||||
LOCK_ZONE(zone);
|
||||
INSIST(zone->catzs == NULL || zone->catzs == catzs);
|
||||
dns_catz_catzs_set_view(catzs, zone->view);
|
||||
if (zone->catzs == NULL)
|
||||
dns_catz_catzs_attach(catzs, &zone->catzs);
|
||||
UNLOCK_ZONE(zone);
|
||||
}
|
||||
|
||||
/*
|
||||
* If a zone is a catalog zone, attach it to update notification in database.
|
||||
*/
|
||||
void
|
||||
dns_zone_catz_enable_db(dns_zone_t *zone, dns_db_t *db) {
|
||||
REQUIRE(DNS_ZONE_VALID(zone));
|
||||
REQUIRE(db != NULL);
|
||||
|
||||
if (zone->catzs != NULL) {
|
||||
dns_db_updatenotify_register(db, dns_catz_dbupdate_callback,
|
||||
zone->catzs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static isc_boolean_t
|
||||
zone_touched(dns_zone_t *zone) {
|
||||
isc_result_t result;
|
||||
@ -2344,6 +2384,7 @@ zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
|
||||
unsigned int options;
|
||||
|
||||
dns_zone_rpz_enable_db(zone, db);
|
||||
dns_zone_catz_enable_db(zone, db);
|
||||
options = get_master_options(zone);
|
||||
if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS))
|
||||
options |= DNS_MASTER_MANYERRORS;
|
||||
|
@ -155,7 +155,7 @@ dns_zt_unmount(dns_zt_t *zt, dns_zone_t *zone) {
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_zt_find(dns_zt_t *zt, dns_name_t *name, unsigned int options,
|
||||
dns_zt_find(dns_zt_t *zt, const dns_name_t *name, unsigned int options,
|
||||
dns_name_t *foundname, dns_zone_t **zonep)
|
||||
{
|
||||
isc_result_t result;
|
||||
|
@ -57,8 +57,8 @@ OBJS = @ISC_EXTRA_OBJS@ @ISC_PK11_O@ @ISC_PK11_RESULT_O@ \
|
||||
aes.@O@ assertions.@O@ backtrace.@O@ base32.@O@ base64.@O@ \
|
||||
bind9.@O@ buffer.@O@ bufferlist.@O@ \
|
||||
commandline.@O@ counter.@O@ crc64.@O@ error.@O@ event.@O@ \
|
||||
hash.@O@ heap.@O@ hex.@O@ hmacmd5.@O@ hmacsha.@O@ \
|
||||
httpd.@O@ inet_aton.@O@ iterated_hash.@O@ \
|
||||
hash.@O@ ht.@O@ heap.@O@ hex.@O@ hmacmd5.@O@ \
|
||||
hmacsha.@O@ httpd.@O@ inet_aton.@O@ iterated_hash.@O@ \
|
||||
lex.@O@ lfsr.@O@ lib.@O@ log.@O@ \
|
||||
md5.@O@ mem.@O@ mutexblock.@O@ \
|
||||
netaddr.@O@ netscope.@O@ pool.@O@ ondestroy.@O@ \
|
||||
@ -77,8 +77,8 @@ CHACHASRCS = chacha_private.h
|
||||
SRCS = @ISC_EXTRA_SRCS@ @ISC_PK11_C@ @ISC_PK11_RESULT_C@ \
|
||||
aes.c assertions.c backtrace.c base32.c base64.c bind9.c \
|
||||
buffer.c bufferlist.c commandline.c counter.c crc64.c \
|
||||
error.c event.c heap.c hex.c hmacmd5.c hmacsha.c \
|
||||
httpd.c inet_aton.c iterated_hash.c \
|
||||
error.c event.c hash.c ht.c heap.c hex.c hmacmd5.c \
|
||||
hmacsha.c httpd.c inet_aton.c iterated_hash.c \
|
||||
lex.c lfsr.c lib.c log.c \
|
||||
md5.c mem.c mutexblock.c \
|
||||
netaddr.c netscope.c pool.c ondestroy.c \
|
||||
|
@ -60,6 +60,7 @@ isc_buffer_reinit(isc_buffer_t *b, void *base, unsigned int length) {
|
||||
*/
|
||||
REQUIRE(b->length <= length);
|
||||
REQUIRE(base != NULL);
|
||||
REQUIRE(b->autore = ISC_FALSE);
|
||||
|
||||
(void)memmove(base, b->base, b->length);
|
||||
b->base = base;
|
||||
@ -79,6 +80,13 @@ isc__buffer_invalidate(isc_buffer_t *b) {
|
||||
ISC__BUFFER_INVALIDATE(b);
|
||||
}
|
||||
|
||||
void
|
||||
isc_buffer_setautorealloc(isc_buffer_t *b, isc_boolean_t enable) {
|
||||
REQUIRE(ISC_BUFFER_VALID(b));
|
||||
REQUIRE(b->mctx != NULL);
|
||||
b->autore = enable;
|
||||
}
|
||||
|
||||
void
|
||||
isc__buffer_region(isc_buffer_t *b, isc_region_t *r) {
|
||||
/*
|
||||
@ -279,8 +287,13 @@ isc_buffer_getuint8(isc_buffer_t *b) {
|
||||
|
||||
void
|
||||
isc__buffer_putuint8(isc_buffer_t *b, isc_uint8_t val) {
|
||||
isc_result_t result;
|
||||
REQUIRE(ISC_BUFFER_VALID(b));
|
||||
REQUIRE(b->used + 1 <= b->length);
|
||||
if (b->autore) {
|
||||
result = isc_buffer_reserve(&b, 1);
|
||||
REQUIRE(result == ISC_R_SUCCESS);
|
||||
}
|
||||
REQUIRE(isc_buffer_availablelength(b) >= 1);
|
||||
|
||||
ISC__BUFFER_PUTUINT8(b, val);
|
||||
}
|
||||
@ -308,16 +321,26 @@ isc_buffer_getuint16(isc_buffer_t *b) {
|
||||
|
||||
void
|
||||
isc__buffer_putuint16(isc_buffer_t *b, isc_uint16_t val) {
|
||||
isc_result_t result;
|
||||
REQUIRE(ISC_BUFFER_VALID(b));
|
||||
REQUIRE(b->used + 2 <= b->length);
|
||||
if (b->autore) {
|
||||
result = isc_buffer_reserve(&b, 2);
|
||||
REQUIRE(result == ISC_R_SUCCESS);
|
||||
}
|
||||
REQUIRE(isc_buffer_availablelength(b) >= 2);
|
||||
|
||||
ISC__BUFFER_PUTUINT16(b, val);
|
||||
}
|
||||
|
||||
void
|
||||
isc__buffer_putuint24(isc_buffer_t *b, isc_uint32_t val) {
|
||||
isc_result_t result;
|
||||
REQUIRE(ISC_BUFFER_VALID(b));
|
||||
REQUIRE(b->used + 3 <= b->length);
|
||||
if (b->autore) {
|
||||
result = isc_buffer_reserve(&b, 3);
|
||||
REQUIRE(result == ISC_R_SUCCESS);
|
||||
}
|
||||
REQUIRE(isc_buffer_availablelength(b) >= 3);
|
||||
|
||||
ISC__BUFFER_PUTUINT24(b, val);
|
||||
}
|
||||
@ -347,8 +370,13 @@ isc_buffer_getuint32(isc_buffer_t *b) {
|
||||
|
||||
void
|
||||
isc__buffer_putuint32(isc_buffer_t *b, isc_uint32_t val) {
|
||||
isc_result_t result;
|
||||
REQUIRE(ISC_BUFFER_VALID(b));
|
||||
REQUIRE(b->used + 4 <= b->length);
|
||||
if (b->autore == ISC_TRUE) {
|
||||
result = isc_buffer_reserve(&b, 4);
|
||||
REQUIRE(result == ISC_R_SUCCESS);
|
||||
}
|
||||
REQUIRE(isc_buffer_availablelength(b) >= 4);
|
||||
|
||||
ISC__BUFFER_PUTUINT32(b, val);
|
||||
}
|
||||
@ -380,11 +408,16 @@ isc_buffer_getuint48(isc_buffer_t *b) {
|
||||
|
||||
void
|
||||
isc__buffer_putuint48(isc_buffer_t *b, isc_uint64_t val) {
|
||||
isc_result_t result;
|
||||
isc_uint16_t valhi;
|
||||
isc_uint32_t vallo;
|
||||
|
||||
REQUIRE(ISC_BUFFER_VALID(b));
|
||||
REQUIRE(b->used + 6 <= b->length);
|
||||
if (b->autore == ISC_TRUE) {
|
||||
result = isc_buffer_reserve(&b, 6);
|
||||
REQUIRE(result == ISC_R_SUCCESS);
|
||||
}
|
||||
REQUIRE(isc_buffer_availablelength(b) >= 6);
|
||||
|
||||
valhi = (isc_uint16_t)(val >> 32);
|
||||
vallo = (isc_uint32_t)(val & 0xFFFFFFFF);
|
||||
@ -396,8 +429,13 @@ void
|
||||
isc__buffer_putmem(isc_buffer_t *b, const unsigned char *base,
|
||||
unsigned int length)
|
||||
{
|
||||
isc_result_t result;
|
||||
REQUIRE(ISC_BUFFER_VALID(b));
|
||||
REQUIRE(b->used + length <= b->length);
|
||||
if (b->autore == ISC_TRUE) {
|
||||
result = isc_buffer_reserve(&b, length);
|
||||
REQUIRE(result == ISC_R_SUCCESS);
|
||||
}
|
||||
REQUIRE(isc_buffer_availablelength(b) >= length);
|
||||
|
||||
ISC__BUFFER_PUTMEM(b, base, length);
|
||||
}
|
||||
@ -406,6 +444,7 @@ void
|
||||
isc__buffer_putstr(isc_buffer_t *b, const char *source) {
|
||||
unsigned int l;
|
||||
unsigned char *cp;
|
||||
isc_result_t result;
|
||||
|
||||
REQUIRE(ISC_BUFFER_VALID(b));
|
||||
REQUIRE(source != NULL);
|
||||
@ -414,8 +453,11 @@ isc__buffer_putstr(isc_buffer_t *b, const char *source) {
|
||||
* Do not use ISC__BUFFER_PUTSTR(), so strlen is only done once.
|
||||
*/
|
||||
l = strlen(source);
|
||||
|
||||
REQUIRE(l <= isc_buffer_availablelength(b));
|
||||
if (b->autore == ISC_TRUE) {
|
||||
result = isc_buffer_reserve(&b, l);
|
||||
REQUIRE(result == ISC_R_SUCCESS);
|
||||
}
|
||||
REQUIRE(isc_buffer_availablelength(b) >= l);
|
||||
|
||||
cp = isc_buffer_used(b);
|
||||
memmove(cp, source, l);
|
||||
@ -448,16 +490,21 @@ isc_buffer_allocate(isc_mem_t *mctx, isc_buffer_t **dynbuffer,
|
||||
unsigned int length)
|
||||
{
|
||||
isc_buffer_t *dbuf;
|
||||
|
||||
unsigned char * bdata;
|
||||
REQUIRE(dynbuffer != NULL);
|
||||
REQUIRE(*dynbuffer == NULL);
|
||||
|
||||
dbuf = isc_mem_get(mctx, length + sizeof(isc_buffer_t));
|
||||
dbuf = isc_mem_get(mctx, sizeof(isc_buffer_t));
|
||||
if (dbuf == NULL)
|
||||
return (ISC_R_NOMEMORY);
|
||||
|
||||
isc_buffer_init(dbuf, ((unsigned char *)dbuf) + sizeof(isc_buffer_t),
|
||||
length);
|
||||
bdata = isc_mem_get(mctx, length);
|
||||
if (bdata == NULL) {
|
||||
isc_mem_put(mctx, dbuf, sizeof(isc_buffer_t));
|
||||
return (ISC_R_NOMEMORY);
|
||||
}
|
||||
|
||||
isc_buffer_init(dbuf, bdata, length);
|
||||
dbuf->mctx = mctx;
|
||||
|
||||
ENSURE(ISC_BUFFER_VALID(dbuf));
|
||||
@ -469,7 +516,7 @@ isc_buffer_allocate(isc_mem_t *mctx, isc_buffer_t **dynbuffer,
|
||||
|
||||
isc_result_t
|
||||
isc_buffer_reallocate(isc_buffer_t **dynbuffer, unsigned int length) {
|
||||
isc_buffer_t *dbuf;
|
||||
unsigned char *bdata;
|
||||
|
||||
REQUIRE(dynbuffer != NULL);
|
||||
REQUIRE(ISC_BUFFER_VALID(*dynbuffer));
|
||||
@ -483,18 +530,16 @@ isc_buffer_reallocate(isc_buffer_t **dynbuffer, unsigned int length) {
|
||||
* it doesn't remap pages, but does ordinary copy. So is
|
||||
* isc_mem_reallocate(), which has additional issues.
|
||||
*/
|
||||
dbuf = isc_mem_get((*dynbuffer)->mctx, length + sizeof(isc_buffer_t));
|
||||
if (dbuf == NULL)
|
||||
bdata = isc_mem_get((*dynbuffer)->mctx, length);
|
||||
if (bdata == NULL)
|
||||
return (ISC_R_NOMEMORY);
|
||||
|
||||
memmove(dbuf, *dynbuffer, (*dynbuffer)->length + sizeof(isc_buffer_t));
|
||||
isc_mem_put(dbuf->mctx, *dynbuffer,
|
||||
(*dynbuffer)->length + sizeof(isc_buffer_t));
|
||||
memmove(bdata, (*dynbuffer)->base, (*dynbuffer)->length);
|
||||
isc_mem_put((*dynbuffer)->mctx, (*dynbuffer)->base,
|
||||
(*dynbuffer)->length);
|
||||
|
||||
dbuf->base = ((unsigned char *)dbuf) + sizeof(isc_buffer_t);
|
||||
dbuf->length = length;
|
||||
|
||||
*dynbuffer = dbuf;
|
||||
(*dynbuffer)->base = bdata;
|
||||
(*dynbuffer)->length = length;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
@ -530,7 +575,6 @@ isc_buffer_reserve(isc_buffer_t **dynbuffer, unsigned int size) {
|
||||
|
||||
void
|
||||
isc_buffer_free(isc_buffer_t **dynbuffer) {
|
||||
unsigned int real_length;
|
||||
isc_buffer_t *dbuf;
|
||||
isc_mem_t *mctx;
|
||||
|
||||
@ -540,11 +584,10 @@ isc_buffer_free(isc_buffer_t **dynbuffer) {
|
||||
|
||||
dbuf = *dynbuffer;
|
||||
*dynbuffer = NULL; /* destroy external reference */
|
||||
|
||||
real_length = dbuf->length + sizeof(isc_buffer_t);
|
||||
mctx = dbuf->mctx;
|
||||
dbuf->mctx = NULL;
|
||||
isc_buffer_invalidate(dbuf);
|
||||
|
||||
isc_mem_put(mctx, dbuf, real_length);
|
||||
isc_mem_put(mctx, dbuf->base, dbuf->length);
|
||||
isc_buffer_invalidate(dbuf);
|
||||
isc_mem_put(mctx, dbuf, sizeof(isc_buffer_t));
|
||||
}
|
||||
|
339
lib/isc/ht.c
Normal file
339
lib/isc/ht.c
Normal file
@ -0,0 +1,339 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <isc/hash.h>
|
||||
#include <isc/ht.h>
|
||||
#include <isc/types.h>
|
||||
#include <isc/magic.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/result.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
|
||||
typedef struct isc_ht_node isc_ht_node_t;
|
||||
|
||||
#define ISC_HT_MAGIC ISC_MAGIC('H', 'T', 'a', 'b')
|
||||
#define ISC_HT_VALID(ht) ISC_MAGIC_VALID(ht, ISC_HT_MAGIC)
|
||||
|
||||
struct isc_ht_node {
|
||||
void *value;
|
||||
isc_ht_node_t *next;
|
||||
size_t keysize;
|
||||
unsigned char key[];
|
||||
};
|
||||
|
||||
struct isc_ht {
|
||||
unsigned int magic;
|
||||
isc_mem_t *mctx;
|
||||
size_t size;
|
||||
size_t mask;
|
||||
unsigned int count;
|
||||
isc_ht_node_t **table;
|
||||
};
|
||||
|
||||
struct isc_ht_iter {
|
||||
isc_ht_t *ht;
|
||||
isc_uint32_t i;
|
||||
isc_ht_node_t *cur;
|
||||
};
|
||||
|
||||
isc_result_t
|
||||
isc_ht_init(isc_ht_t **htp, isc_mem_t *mctx, isc_uint8_t bits) {
|
||||
isc_ht_t *ht = NULL;
|
||||
isc_uint32_t i;
|
||||
|
||||
REQUIRE(htp != NULL && *htp == NULL);
|
||||
REQUIRE(mctx != NULL);
|
||||
REQUIRE(bits >= 1 && bits <= (sizeof(size_t)*8 - 1));
|
||||
|
||||
ht = isc_mem_get(mctx, sizeof(struct isc_ht));
|
||||
if (ht == NULL) {
|
||||
return (ISC_R_NOMEMORY);
|
||||
}
|
||||
|
||||
ht->mctx = NULL;
|
||||
isc_mem_attach(mctx, &ht->mctx);
|
||||
|
||||
ht->size = (1<<bits);
|
||||
ht->mask = (1<<bits)-1;
|
||||
ht->count = 0;
|
||||
|
||||
ht->table = isc_mem_get(ht->mctx, ht->size * sizeof(isc_ht_node_t*));
|
||||
if (ht->table == NULL) {
|
||||
isc_mem_putanddetach(&ht->mctx, ht, sizeof(struct isc_ht));
|
||||
return (ISC_R_NOMEMORY);
|
||||
}
|
||||
|
||||
for (i = 0; i < ht->size; i++) {
|
||||
ht->table[i] = NULL;
|
||||
}
|
||||
|
||||
ht->magic = ISC_HT_MAGIC;
|
||||
|
||||
*htp = ht;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
void
|
||||
isc_ht_destroy(isc_ht_t **htp) {
|
||||
isc_ht_t *ht;
|
||||
isc_uint32_t i;
|
||||
|
||||
REQUIRE(htp != NULL);
|
||||
|
||||
ht = *htp;
|
||||
REQUIRE(ISC_HT_VALID(ht));
|
||||
|
||||
ht->magic = 0;
|
||||
|
||||
for (i = 0; i < ht->size; i++) {
|
||||
isc_ht_node_t *node = ht->table[i];
|
||||
while (node != NULL) {
|
||||
isc_ht_node_t *next = node->next;
|
||||
ht->count--;
|
||||
isc_mem_put(ht->mctx, node,
|
||||
sizeof(isc_ht_node_t) + node->keysize);
|
||||
node = next;
|
||||
}
|
||||
}
|
||||
|
||||
INSIST(ht->count == 0);
|
||||
|
||||
isc_mem_put(ht->mctx, ht->table, ht->size * sizeof(isc_ht_node_t*));
|
||||
isc_mem_putanddetach(&ht->mctx, ht, sizeof(struct isc_ht));
|
||||
|
||||
*htp = NULL;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_ht_add(isc_ht_t *ht, const unsigned char *key,
|
||||
isc_uint32_t keysize, void *value)
|
||||
{
|
||||
isc_ht_node_t *node;
|
||||
isc_uint32_t hash;
|
||||
|
||||
REQUIRE(ISC_HT_VALID(ht));
|
||||
REQUIRE(key != NULL && keysize > 0);
|
||||
|
||||
hash = isc_hash_function(key, keysize, ISC_TRUE, NULL);
|
||||
node = ht->table[hash & ht->mask];
|
||||
while (node != NULL) {
|
||||
if (keysize == node->keysize &&
|
||||
memcmp(key, node->key, keysize) == 0)
|
||||
{
|
||||
return (ISC_R_EXISTS);
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
node = isc_mem_get(ht->mctx, sizeof(isc_ht_node_t) + keysize);
|
||||
if (node == NULL) {
|
||||
return (ISC_R_NOMEMORY);
|
||||
}
|
||||
|
||||
memmove(node->key, key, keysize);
|
||||
node->keysize = keysize;
|
||||
node->next = ht->table[hash & ht->mask];
|
||||
node->value = value;
|
||||
|
||||
ht->count++;
|
||||
ht->table[hash & ht->mask] = node;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_ht_find(const isc_ht_t *ht, const unsigned char *key,
|
||||
isc_uint32_t keysize, void **valuep)
|
||||
{
|
||||
isc_ht_node_t *node;
|
||||
isc_uint32_t hash;
|
||||
|
||||
REQUIRE(ISC_HT_VALID(ht));
|
||||
REQUIRE(key != NULL && keysize > 0);
|
||||
REQUIRE(valuep != NULL);
|
||||
|
||||
hash = isc_hash_function(key, keysize, ISC_TRUE, NULL);
|
||||
node = ht->table[hash & ht->mask];
|
||||
while (node != NULL) {
|
||||
if (keysize == node->keysize &&
|
||||
memcmp(key, node->key, keysize) == 0)
|
||||
{
|
||||
*valuep = node->value;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
return (ISC_R_NOTFOUND);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_ht_delete(isc_ht_t *ht, const unsigned char *key, isc_uint32_t keysize) {
|
||||
isc_ht_node_t *node, *prev;
|
||||
isc_uint32_t hash;
|
||||
|
||||
REQUIRE(ISC_HT_VALID(ht));
|
||||
REQUIRE(key != NULL && keysize > 0);
|
||||
|
||||
prev = NULL;
|
||||
hash = isc_hash_function(key, keysize, ISC_TRUE, NULL);
|
||||
node = ht->table[hash & ht->mask];
|
||||
while (node != NULL) {
|
||||
if (keysize == node->keysize &&
|
||||
memcmp(key, node->key, keysize) == 0)
|
||||
{
|
||||
if (prev == NULL) {
|
||||
ht->table[hash & ht->mask] = node->next;
|
||||
} else {
|
||||
prev->next = node->next;
|
||||
}
|
||||
isc_mem_put(ht->mctx, node,
|
||||
sizeof(isc_ht_node_t) + node->keysize);
|
||||
ht->count--;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
prev = node;
|
||||
node = node->next;
|
||||
}
|
||||
return (ISC_R_NOTFOUND);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_ht_iter_create(isc_ht_t *ht, isc_ht_iter_t **itp) {
|
||||
isc_ht_iter_t *it;
|
||||
|
||||
REQUIRE(ISC_HT_VALID(ht));
|
||||
REQUIRE(itp != NULL && *itp == NULL);
|
||||
|
||||
if (ht->count == 0)
|
||||
return (ISC_R_NOMORE);
|
||||
|
||||
it = isc_mem_get(ht->mctx, sizeof(isc_ht_iter_t));
|
||||
if (it == NULL)
|
||||
return (ISC_R_NOMEMORY);
|
||||
|
||||
it->ht = ht;
|
||||
it->i = 0;
|
||||
it->cur = NULL;
|
||||
|
||||
*itp = it;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
void
|
||||
isc_ht_iter_destroy(isc_ht_iter_t **itp) {
|
||||
isc_ht_iter_t *it;
|
||||
isc_ht_t *ht;
|
||||
|
||||
REQUIRE(itp != NULL && *itp != NULL);
|
||||
|
||||
it = *itp;
|
||||
ht = it->ht;
|
||||
isc_mem_put(ht->mctx, it, sizeof(isc_ht_iter_t));
|
||||
|
||||
*itp = NULL;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_ht_iter_first(isc_ht_iter_t *it) {
|
||||
REQUIRE(it != NULL);
|
||||
|
||||
it->i = 0;
|
||||
while (it->i < it->ht->size && it->ht->table[it->i] == NULL)
|
||||
it->i++;
|
||||
|
||||
if(it->i == it->ht->size)
|
||||
return (ISC_R_NOMORE);
|
||||
|
||||
it->cur = it->ht->table[it->i];
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_ht_iter_next(isc_ht_iter_t *it) {
|
||||
REQUIRE(it != NULL);
|
||||
REQUIRE(it->cur != NULL);
|
||||
|
||||
it->cur = it->cur->next;
|
||||
if (it->cur == NULL) {
|
||||
while (it->i < it->ht->size && it->ht->table[it->i] == NULL)
|
||||
it->i++;
|
||||
if (it->i < it->ht->size)
|
||||
return (ISC_R_NOMORE);
|
||||
it->cur = it->ht->table[it->i];
|
||||
}
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
void
|
||||
isc_ht_iter_current(isc_ht_iter_t *it, void **valuep) {
|
||||
REQUIRE(it != NULL);
|
||||
REQUIRE(it->cur != NULL);
|
||||
*valuep = it->cur->value;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
isc_ht_count(isc_ht_t *ht) {
|
||||
REQUIRE(ISC_HT_VALID(ht));
|
||||
|
||||
return(ht->count);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_ht_walk(isc_ht_t *ht, isc_ht_walkfn walkfn, void *udata) {
|
||||
isc_uint32_t i;
|
||||
isc_result_t res;
|
||||
|
||||
REQUIRE(ISC_HT_VALID(ht));
|
||||
|
||||
for (i = 0; i < ht->size; i++) {
|
||||
isc_ht_node_t *cur = ht->table[i];
|
||||
isc_ht_node_t *prev = NULL;
|
||||
while (cur != NULL) {
|
||||
if (walkfn == NULL) {
|
||||
continue;
|
||||
}
|
||||
res = walkfn(udata, cur->key, cur->keysize, cur->value);
|
||||
if (res != ISC_R_SUCCESS && res != ISC_R_EXISTS) {
|
||||
return (res);
|
||||
}
|
||||
if (res == ISC_R_EXISTS) { /* remove this node */
|
||||
isc_ht_node_t *tmp = cur;
|
||||
cur = cur->next;
|
||||
if (prev == NULL) {
|
||||
ht->table[i] = cur;
|
||||
} else {
|
||||
prev->next = cur;
|
||||
}
|
||||
isc_mem_put(ht->mctx, tmp,
|
||||
sizeof(isc_ht_node_t) + tmp->keysize);
|
||||
ht->count--;
|
||||
} else {
|
||||
prev = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
@ -184,6 +184,8 @@ struct isc_buffer {
|
||||
ISC_LINK(isc_buffer_t) link;
|
||||
/*! private internal elements */
|
||||
isc_mem_t *mctx;
|
||||
/* automatically realloc buffer at put* */
|
||||
isc_boolean_t autore;
|
||||
};
|
||||
|
||||
/***
|
||||
@ -316,6 +318,16 @@ isc__buffer_invalidate(isc_buffer_t *b);
|
||||
* calling isc_buffer_init() on it will cause an assertion failure.
|
||||
*/
|
||||
|
||||
void
|
||||
isc_buffer_setautorealloc(isc_buffer_t *b, isc_boolean_t enable);
|
||||
/*!<
|
||||
* \brief Enable or disable autoreallocation on 'b'.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'b' is a valid dynamic buffer (b->mctx != NULL).
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
isc__buffer_region(isc_buffer_t *b, isc_region_t *r);
|
||||
/*!<
|
||||
@ -530,7 +542,8 @@ isc__buffer_putuint8(isc_buffer_t *b, isc_uint8_t val);
|
||||
* Requires:
|
||||
*\li 'b' is a valid buffer.
|
||||
*
|
||||
*\li The length of the unused region of 'b' is at least 1.
|
||||
*\li The length of the unused region of 'b' is at least 1
|
||||
* or the buffer has autoreallocation enabled.
|
||||
*
|
||||
* Ensures:
|
||||
*\li The used pointer in 'b' is advanced by 1.
|
||||
@ -546,7 +559,8 @@ isc_buffer_getuint16(isc_buffer_t *b);
|
||||
*
|
||||
*\li 'b' is a valid buffer.
|
||||
*
|
||||
*\li The length of the available region of 'b' is at least 2.
|
||||
*\li The length of the available region of 'b' is at least 2
|
||||
* or the buffer has autoreallocation enabled.
|
||||
*
|
||||
* Ensures:
|
||||
*
|
||||
@ -566,7 +580,8 @@ isc__buffer_putuint16(isc_buffer_t *b, isc_uint16_t val);
|
||||
* Requires:
|
||||
*\li 'b' is a valid buffer.
|
||||
*
|
||||
*\li The length of the unused region of 'b' is at least 2.
|
||||
*\li The length of the unused region of 'b' is at least 2
|
||||
* or the buffer has autoreallocation enabled.
|
||||
*
|
||||
* Ensures:
|
||||
*\li The used pointer in 'b' is advanced by 2.
|
||||
@ -602,7 +617,8 @@ isc__buffer_putuint32(isc_buffer_t *b, isc_uint32_t val);
|
||||
* Requires:
|
||||
*\li 'b' is a valid buffer.
|
||||
*
|
||||
*\li The length of the unused region of 'b' is at least 4.
|
||||
*\li The length of the unused region of 'b' is at least 4
|
||||
* or the buffer has autoreallocation enabled.
|
||||
*
|
||||
* Ensures:
|
||||
*\li The used pointer in 'b' is advanced by 4.
|
||||
@ -638,7 +654,8 @@ isc__buffer_putuint48(isc_buffer_t *b, isc_uint64_t val);
|
||||
* Requires:
|
||||
*\li 'b' is a valid buffer.
|
||||
*
|
||||
*\li The length of the unused region of 'b' is at least 6.
|
||||
*\li The length of the unused region of 'b' is at least 6
|
||||
* or the buffer has autoreallocation enabled.
|
||||
*
|
||||
* Ensures:
|
||||
*\li The used pointer in 'b' is advanced by 6.
|
||||
@ -653,7 +670,8 @@ isc__buffer_putuint24(isc_buffer_t *b, isc_uint32_t val);
|
||||
* Requires:
|
||||
*\li 'b' is a valid buffer.
|
||||
*
|
||||
* The length of the unused region of 'b' is at least 3.
|
||||
* The length of the unused region of 'b' is at least 3
|
||||
* or the buffer has autoreallocation enabled.
|
||||
*
|
||||
* Ensures:
|
||||
*\li The used pointer in 'b' is advanced by 3.
|
||||
@ -666,7 +684,8 @@ isc__buffer_putmem(isc_buffer_t *b, const unsigned char *base,
|
||||
* \brief Copy 'length' bytes of memory at 'base' into 'b'.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'b' is a valid buffer.
|
||||
*\li 'b' is a valid buffer, and it has at least 'length'
|
||||
* or the buffer has autoreallocation enabled.
|
||||
*
|
||||
*\li 'base' points to 'length' bytes of valid memory.
|
||||
*
|
||||
@ -682,7 +701,7 @@ isc__buffer_putstr(isc_buffer_t *b, const char *source);
|
||||
*
|
||||
*\li 'source' to be a valid NULL terminated string.
|
||||
*
|
||||
*\li strlen(source) <= isc_buffer_available(b)
|
||||
*\li strlen(source) <= isc_buffer_available(b) || b->mctx != NULL
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
@ -738,6 +757,7 @@ ISC_LANG_ENDDECLS
|
||||
(_b)->mctx = NULL; \
|
||||
ISC_LINK_INIT(_b, link); \
|
||||
(_b)->magic = ISC_BUFFER_MAGIC; \
|
||||
(_b)->autore = ISC_FALSE; \
|
||||
} while (0)
|
||||
|
||||
#define ISC__BUFFER_INITNULL(_b) ISC__BUFFER_INIT(_b, NULL, 0)
|
||||
|
@ -19,6 +19,7 @@
|
||||
#define ISC_HASH_H 1
|
||||
|
||||
#include <isc/types.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
/*****
|
||||
***** Module Info
|
||||
@ -105,7 +106,8 @@ isc_hash_create(isc_mem_t *mctx, isc_entropy_t *entropy, size_t limit);
|
||||
*/
|
||||
|
||||
void
|
||||
isc_hash_ctxattach(isc_hash_t *hctx, isc_hash_t **hctxp);
|
||||
isc_hash_ctxattach(isc_hash_t *hctx, isc_hash_t **hctxp)
|
||||
ISC_DEPRECATED;
|
||||
/*!<
|
||||
* \brief Attach to a hash object.
|
||||
*
|
||||
@ -113,7 +115,8 @@ isc_hash_ctxattach(isc_hash_t *hctx, isc_hash_t **hctxp);
|
||||
*/
|
||||
|
||||
void
|
||||
isc_hash_ctxdetach(isc_hash_t **hctxp);
|
||||
isc_hash_ctxdetach(isc_hash_t **hctxp)
|
||||
ISC_DEPRECATED;
|
||||
/*!<
|
||||
* \brief Detach from a hash object.
|
||||
*
|
||||
@ -158,10 +161,12 @@ isc_hash_init(void);
|
||||
/*@{*/
|
||||
unsigned int
|
||||
isc_hash_ctxcalc(isc_hash_t *hctx, const unsigned char *key,
|
||||
unsigned int keylen, isc_boolean_t case_sensitive);
|
||||
unsigned int keylen, isc_boolean_t case_sensitive)
|
||||
ISC_DEPRECATED;
|
||||
unsigned int
|
||||
isc_hash_calc(const unsigned char *key, unsigned int keylen,
|
||||
isc_boolean_t case_sensitive);
|
||||
isc_boolean_t case_sensitive)
|
||||
ISC_DEPRECATED;
|
||||
/*!<
|
||||
* \brief Calculate a hash value.
|
||||
*
|
||||
@ -183,7 +188,8 @@ isc_hash_calc(const unsigned char *key, unsigned int keylen,
|
||||
/*@}*/
|
||||
|
||||
void
|
||||
isc__hash_setvec(const isc_uint16_t *vec);
|
||||
isc__hash_setvec(const isc_uint16_t *vec)
|
||||
ISC_DEPRECATED;
|
||||
|
||||
/*!<
|
||||
* \brief Set the contents of the random vector used in hashing.
|
||||
|
167
lib/isc/include/isc/ht.h
Normal file
167
lib/isc/include/isc/ht.h
Normal file
@ -0,0 +1,167 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* ! \file */
|
||||
|
||||
#ifndef ISC_HT_H
|
||||
#define ISC_HT_H 1
|
||||
|
||||
#include <string.h>
|
||||
#include <isc/types.h>
|
||||
#include <isc/result.h>
|
||||
|
||||
typedef struct isc_ht isc_ht_t;
|
||||
typedef struct isc_ht_iter isc_ht_iter_t;
|
||||
|
||||
/*%
|
||||
* Initialize hashtable at *htp, using memory context and size of (1<<bits)
|
||||
*
|
||||
* Requires:
|
||||
*\li htp is not NULL
|
||||
*\li *htp is NULL
|
||||
*\li mctx is a valid memory context
|
||||
*\li bits >=1 && bits <=32
|
||||
*
|
||||
* Returns:
|
||||
*\li #ISC_R_NOMEMORY -- not enough memory to create pool
|
||||
*\li #ISC_R_SUCCESS -- all is well.
|
||||
*/
|
||||
isc_result_t
|
||||
isc_ht_init(isc_ht_t **htp, isc_mem_t *mctx, isc_uint8_t bits);
|
||||
|
||||
/*%
|
||||
* Destroy hashtable, freeing everything
|
||||
*
|
||||
* Requires:
|
||||
* \li *htp is valid hashtable
|
||||
*/
|
||||
void
|
||||
isc_ht_destroy(isc_ht_t **htp);
|
||||
|
||||
/*%
|
||||
* Add a node to hashtable, pointed by binary key 'key' of size 'keysize';
|
||||
* set its value to 'value'
|
||||
*
|
||||
* Requires:
|
||||
*\li ht is a valid hashtable
|
||||
*
|
||||
* Returns:
|
||||
*\li #ISC_R_NOMEMORY -- not enough memory to create pool
|
||||
*\li #ISC_R_EXISTS -- node of the same key already exists
|
||||
*\li #ISC_R_SUCCESS -- all is well.
|
||||
*/
|
||||
isc_result_t
|
||||
isc_ht_add(isc_ht_t *ht, const unsigned char *key, isc_uint32_t keysize,
|
||||
void *value);
|
||||
|
||||
/*%
|
||||
* Find a node matching 'key'/'keysize' in hashtable 'ht';
|
||||
* if found, set 'value' to its value
|
||||
*
|
||||
* Requires:
|
||||
* \li 'ht' is a valid hashtable
|
||||
*
|
||||
* Returns:
|
||||
* \li #ISC_R_SUCCESS -- success
|
||||
* \li #ISC_R_NOTFOUND -- key not found
|
||||
*/
|
||||
isc_result_t
|
||||
isc_ht_find(const isc_ht_t *ht, const unsigned char *key,
|
||||
isc_uint32_t keysize, void **valuep);
|
||||
|
||||
/*%
|
||||
* Delete node from hashtable
|
||||
* Requires:
|
||||
*\li ht is a valid hashtable
|
||||
*
|
||||
* Returns:
|
||||
*\li #ISC_R_NOTFOUND -- key not found
|
||||
*\li #ISC_R_SUCCESS -- all is well
|
||||
*/
|
||||
isc_result_t
|
||||
isc_ht_delete(isc_ht_t *ht, const unsigned char *key, isc_uint32_t keysize);
|
||||
|
||||
|
||||
typedef isc_result_t (*isc_ht_walkfn)(void *udata, const unsigned char *key,
|
||||
isc_uint32_t keysize, void *data);
|
||||
|
||||
/*%
|
||||
* Create an iterator for the hashtable; point '*itp' to it.
|
||||
*/
|
||||
isc_result_t
|
||||
isc_ht_iter_create(isc_ht_t *ht, isc_ht_iter_t **itp);
|
||||
|
||||
/*%
|
||||
* Destroy the iterator '*itp', set it to NULL
|
||||
*/
|
||||
void
|
||||
isc_ht_iter_destroy(isc_ht_iter_t **itp);
|
||||
|
||||
/*%
|
||||
* Set an iterator to the first entry.
|
||||
*
|
||||
* Returns:
|
||||
* \li #ISC_R_SUCCESS -- success
|
||||
* \li #ISC_R_NOMORE -- no data in the hashtable
|
||||
*/
|
||||
isc_result_t
|
||||
isc_ht_iter_first(isc_ht_iter_t *it);
|
||||
|
||||
/*%
|
||||
* Set an iterator to the next entry.
|
||||
*
|
||||
* Returns:
|
||||
* \li #ISC_R_SUCCESS -- success
|
||||
* \li #ISC_R_NOMORE -- end of hashtable reached
|
||||
*/
|
||||
isc_result_t
|
||||
isc_ht_iter_next(isc_ht_iter_t *it);
|
||||
|
||||
/*%
|
||||
* Set 'value' to the current value under the iterator
|
||||
*/
|
||||
void
|
||||
isc_ht_iter_current(isc_ht_iter_t *it, void **valuep);
|
||||
|
||||
/*%
|
||||
* Walks the hashtable, calling 'walkfn' on each node
|
||||
*
|
||||
* \li If 'walkfn' returns ISC_R_SUCCESS, walk is continued
|
||||
* \li If 'walkfn' returns ISC_R_EXISTS, walk is continued but the
|
||||
* node is removed
|
||||
* \li If 'walkfn' returns anything else, walk is aborted and function returns
|
||||
* this value
|
||||
*
|
||||
* Requires:
|
||||
* \li 'ht' is a valid hashtable
|
||||
* \li 'walkfn' is not NULL
|
||||
*
|
||||
* Returns:
|
||||
* \li #ISC_R_SUCCESS -- all is well
|
||||
* \li Any other, as returned by 'walkfn'
|
||||
*/
|
||||
isc_result_t
|
||||
isc_ht_walk(isc_ht_t *ht, isc_ht_walkfn walkfn, void *udata);
|
||||
|
||||
/*%
|
||||
* Returns the number of items in the hashtable.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'ht' is a valid hashtable
|
||||
*/
|
||||
unsigned int
|
||||
isc_ht_count(isc_ht_t *ht);
|
||||
#endif
|
@ -248,4 +248,13 @@
|
||||
*/
|
||||
#define TIME_NOW(tp) RUNTIME_CHECK(isc_time_now((tp)) == ISC_R_SUCCESS)
|
||||
|
||||
/*%
|
||||
* Misc.
|
||||
*/
|
||||
#ifdef __GNUC__
|
||||
#define ISC_DEPRECATED __attribute__((deprecated))
|
||||
#else
|
||||
#define ISC_DEPRECATED /* none */
|
||||
#endif /* __GNUC __ */
|
||||
|
||||
#endif /* ISC_UTIL_H */
|
||||
|
@ -675,7 +675,6 @@ mem_getunlocked(isc__mem_t *ctx, size_t size) {
|
||||
new_size = size;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there are no blocks in the free list for this size, get a chunk
|
||||
* of memory and then break it up into "new_size"-sized blocks, adding
|
||||
@ -687,9 +686,11 @@ mem_getunlocked(isc__mem_t *ctx, size_t size) {
|
||||
/*
|
||||
* The free list uses the "rounded-up" size "new_size".
|
||||
*/
|
||||
|
||||
ret = ctx->freelists[new_size];
|
||||
ctx->freelists[new_size] = ctx->freelists[new_size]->next;
|
||||
|
||||
|
||||
/*
|
||||
* The stats[] uses the _actual_ "size" requested by the
|
||||
* caller, with the caveat (in the code above) that "size" >= the
|
||||
|
@ -1723,7 +1723,10 @@ isc__task_beginexclusive(isc_task_t *task0) {
|
||||
isc__taskmgr_t *manager = task->manager;
|
||||
|
||||
REQUIRE(task->state == task_state_running);
|
||||
/* XXX: Require task == manager->excl? */
|
||||
/*
|
||||
* TODO REQUIRE(task == task->manager->excl);
|
||||
* it should be here, it fails on shutdown server->task
|
||||
*/
|
||||
|
||||
LOCK(&manager->lock);
|
||||
if (manager->exclusive_requested) {
|
||||
|
@ -41,7 +41,7 @@ SRCS = isctest.c taskpool_test.c socket_test.c hash_test.c \
|
||||
parse_test.c pool_test.c print_test.c regex_test.c \
|
||||
socket_test.c safe_test.c time_test.c aes_test.c \
|
||||
file_test.c buffer_test.c counter_test.c mem_test.c \
|
||||
result_test.c
|
||||
result_test.c ht_test.c
|
||||
|
||||
SUBDIRS =
|
||||
TARGETS = taskpool_test@EXEEXT@ socket_test@EXEEXT@ hash_test@EXEEXT@ \
|
||||
@ -51,7 +51,7 @@ TARGETS = taskpool_test@EXEEXT@ socket_test@EXEEXT@ hash_test@EXEEXT@ \
|
||||
print_test@EXEEXT@ regex_test@EXEEXT@ socket_test@EXEEXT@ \
|
||||
safe_test@EXEEXT@ time_test@EXEEXT@ aes_test@EXEEXT@ \
|
||||
file_test@EXEEXT@ buffer_test@EXEEXT@ counter_test@EXEEXT@ \
|
||||
mem_test@EXEEXT@ result_test@EXEEXT@
|
||||
mem_test@EXEEXT@ result_test@EXEEXT@ ht_test@EXEEXT@
|
||||
|
||||
@BIND9_MAKE_RULES@
|
||||
|
||||
@ -144,6 +144,10 @@ result_test@EXEEXT@: result_test.@O@ ${ISCDEPLIBS}
|
||||
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
|
||||
result_test.@O@ ${ISCLIBS} ${LIBS}
|
||||
|
||||
ht_test@EXEEXT@: ht_test.@O@ ${ISCDEPLIBS}
|
||||
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
|
||||
ht_test.@O@ ${ISCLIBS} ${LIBS}
|
||||
|
||||
unit::
|
||||
sh ${top_srcdir}/unit/unittest.sh
|
||||
|
||||
|
@ -135,11 +135,74 @@ ATF_TC_BODY(isc_buffer_reallocate, tc) {
|
||||
isc_test_end();
|
||||
}
|
||||
|
||||
ATF_TC(isc_buffer_dynamic);
|
||||
ATF_TC_HEAD(isc_buffer_dynamic, tc) {
|
||||
atf_tc_set_md_var(tc, "descr", "dynamic buffer automatic reallocation");
|
||||
}
|
||||
|
||||
ATF_TC_BODY(isc_buffer_dynamic, tc) {
|
||||
isc_result_t result;
|
||||
isc_buffer_t *b;
|
||||
size_t last_length = 10;
|
||||
int i;
|
||||
|
||||
result = isc_test_begin(NULL, ISC_TRUE);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
|
||||
b = NULL;
|
||||
result = isc_buffer_allocate(mctx, &b, last_length);
|
||||
ATF_CHECK_EQ(result, ISC_R_SUCCESS);
|
||||
ATF_REQUIRE(b != NULL);
|
||||
ATF_CHECK_EQ(b->length, last_length);
|
||||
|
||||
isc_buffer_setautorealloc(b, ISC_TRUE);
|
||||
|
||||
isc_buffer_putuint8(b, 1);
|
||||
|
||||
for (i = 0; i < 1000; i++) {
|
||||
isc_buffer_putstr(b, "thisisa24charslongstring");
|
||||
}
|
||||
ATF_CHECK(b->length-last_length >= 1000*24);
|
||||
last_length+=1000*24;
|
||||
|
||||
for (i = 0; i < 10000; i++) {
|
||||
isc_buffer_putuint8(b, 1);
|
||||
}
|
||||
|
||||
ATF_CHECK(b->length-last_length >= 10000*1);
|
||||
last_length += 10000*1;
|
||||
|
||||
for (i = 0; i < 10000; i++) {
|
||||
isc_buffer_putuint16(b, 1);
|
||||
}
|
||||
|
||||
ATF_CHECK(b->length-last_length >= 10000*2);
|
||||
|
||||
last_length += 10000*2;
|
||||
for (i = 0; i < 10000; i++) {
|
||||
isc_buffer_putuint24(b, 1);
|
||||
}
|
||||
ATF_CHECK(b->length-last_length >= 10000*3);
|
||||
|
||||
last_length+=10000*3;
|
||||
|
||||
for (i = 0; i < 10000; i++) {
|
||||
isc_buffer_putuint32(b, 1);
|
||||
}
|
||||
ATF_CHECK(b->length-last_length >= 10000*4);
|
||||
|
||||
|
||||
isc_buffer_free(&b);
|
||||
|
||||
isc_test_end();
|
||||
}
|
||||
|
||||
/*
|
||||
* Main
|
||||
*/
|
||||
ATF_TP_ADD_TCS(tp) {
|
||||
ATF_TP_ADD_TC(tp, isc_buffer_reserve);
|
||||
ATF_TP_ADD_TC(tp, isc_buffer_reallocate);
|
||||
ATF_TP_ADD_TC(tp, isc_buffer_dynamic);
|
||||
return (atf_no_error());
|
||||
}
|
||||
|
327
lib/isc/tests/ht_test.c
Normal file
327
lib/isc/tests/ht_test.c
Normal file
@ -0,0 +1,327 @@
|
||||
/*
|
||||
* Copyright (C) 2016 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.
|
||||
*/
|
||||
|
||||
/* ! \file */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <atf-c.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <isc/hash.h>
|
||||
#include <isc/ht.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
static void *
|
||||
default_memalloc(void *arg, size_t size) {
|
||||
UNUSED(arg);
|
||||
if (size == 0U)
|
||||
size = 1;
|
||||
return (malloc(size));
|
||||
}
|
||||
|
||||
static void
|
||||
default_memfree(void *arg, void *ptr) {
|
||||
UNUSED(arg);
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
|
||||
static void test_ht_full(int bits, int count) {
|
||||
isc_ht_t *ht = NULL;
|
||||
isc_result_t result;
|
||||
isc_mem_t *mctx = NULL;
|
||||
isc_int64_t i;
|
||||
|
||||
result = isc_mem_createx2(0, 0, default_memalloc, default_memfree,
|
||||
NULL, &mctx, 0);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
|
||||
isc_ht_init(&ht, mctx, bits);
|
||||
for (i = 1; i < count; i++) {
|
||||
/*
|
||||
* Note that the string we're snprintfing is always > 16 bytes
|
||||
* so we are always filling the key.
|
||||
*/
|
||||
unsigned char key[16];
|
||||
snprintf((char *)key, 16, "%lld key of a raw hashtable!!", i);
|
||||
result = isc_ht_add(ht, key, 16, (void *) i);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
for (i = 1; i < count; i++) {
|
||||
unsigned char key[16];
|
||||
void *f = NULL;
|
||||
snprintf((char *)key, 16, "%lld key of a raw hashtable!!", i);
|
||||
result = isc_ht_find(ht, key, 16, &f);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
ATF_REQUIRE_EQ(i, (isc_int64_t) f);
|
||||
}
|
||||
|
||||
for (i = 1; i < count; i++) {
|
||||
unsigned char key[16];
|
||||
snprintf((char *)key, 16, "%lld key of a raw hashtable!!", i);
|
||||
result = isc_ht_add(ht, key, 16, (void *) i);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_EXISTS);
|
||||
}
|
||||
|
||||
for (i = 1; i < count; i++) {
|
||||
char key[64];
|
||||
snprintf((char *)key, 64, "%lld key of a str hashtable!!", i);
|
||||
result = isc_ht_add(ht, (const unsigned char *) key,
|
||||
strlen(key), (void *) i);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
for (i = 1; i < count; i++) {
|
||||
unsigned char key[16];
|
||||
void *f = NULL;
|
||||
snprintf((char *)key, 16, "%lld KEY of a raw hashtable!!", i);
|
||||
result = isc_ht_find(ht, key, 16, &f);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_NOTFOUND);
|
||||
ATF_REQUIRE_EQ(f, NULL);
|
||||
}
|
||||
|
||||
for (i = 1; i < count; i++) {
|
||||
char key[64];
|
||||
void *f = NULL;
|
||||
snprintf((char *)key, 64, "%lld key of a str hashtable!!", i);
|
||||
result = isc_ht_find(ht, (const unsigned char *) key,
|
||||
strlen(key), &f);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
ATF_REQUIRE_EQ(f, (void *) i);
|
||||
}
|
||||
|
||||
for (i = 1; i < count; i++) {
|
||||
unsigned char key[16];
|
||||
void *f = NULL;
|
||||
snprintf((char *)key, 16, "%lld key of a raw hashtable!!", i);
|
||||
result = isc_ht_delete(ht, key, 16);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
result = isc_ht_find(ht, key, 16, &f);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_NOTFOUND);
|
||||
ATF_REQUIRE_EQ(f, NULL);
|
||||
}
|
||||
|
||||
for (i = 1; i < count; i++) {
|
||||
unsigned char key[16];
|
||||
snprintf((char *)key, 16, "%lld KEY of a raw hashtable!!", i);
|
||||
result = isc_ht_add(ht, key, 16, (void *) i);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
for (i = 1; i < count; i++) {
|
||||
char key[64];
|
||||
void *f = NULL;
|
||||
snprintf((char *)key, 64, "%lld key of a str hashtable!!", i);
|
||||
result = isc_ht_delete(ht, (const unsigned char *) key,
|
||||
strlen(key));
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
result = isc_ht_find(ht, (const unsigned char *) key,
|
||||
strlen(key), &f);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_NOTFOUND);
|
||||
ATF_REQUIRE_EQ(f, NULL);
|
||||
}
|
||||
|
||||
|
||||
for (i = 1; i < count; i++) {
|
||||
unsigned char key[16];
|
||||
void *f = NULL;
|
||||
snprintf((char *)key, 16, "%lld KEY of a raw hashtable!!", i);
|
||||
result = isc_ht_find(ht, key, 16, &f);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
ATF_REQUIRE_EQ(i, (isc_int64_t) f);
|
||||
}
|
||||
|
||||
for (i = 1; i < count; i++) {
|
||||
unsigned char key[16];
|
||||
void *f = NULL;
|
||||
snprintf((char *)key, 16, "%lld key of a raw hashtable!!", i);
|
||||
result = isc_ht_find(ht, key, 16, &f);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_NOTFOUND);
|
||||
ATF_REQUIRE_EQ(f, NULL);
|
||||
}
|
||||
|
||||
isc_ht_destroy(&ht);
|
||||
ATF_REQUIRE_EQ(ht, NULL);
|
||||
}
|
||||
|
||||
static isc_uint32_t walked = 0;
|
||||
|
||||
typedef enum {
|
||||
REGULAR,
|
||||
ERASEEVEN,
|
||||
ERASEODD,
|
||||
CRASH
|
||||
} walkmode_t;
|
||||
|
||||
static isc_result_t walker(void *udata, const unsigned char *key,
|
||||
isc_uint32_t keysize, void *data)
|
||||
{
|
||||
char mykey[16];
|
||||
isc_uint64_t ii = (isc_uint64_t) data;
|
||||
walkmode_t mode = (isc_uint64_t) udata;
|
||||
ATF_REQUIRE_EQ(keysize, 16);
|
||||
|
||||
snprintf(mykey, 16, "%lld key of a raw hashtable!!", ii);
|
||||
ATF_REQUIRE_EQ(memcmp(mykey, key, 16), 0);
|
||||
|
||||
walked++;
|
||||
switch (mode) {
|
||||
case REGULAR:
|
||||
break;
|
||||
case ERASEEVEN:
|
||||
if (ii % 2 == 0) {
|
||||
return (ISC_R_EXISTS);
|
||||
}
|
||||
break;
|
||||
case ERASEODD:
|
||||
if (ii % 2 != 0) {
|
||||
return (ISC_R_EXISTS);
|
||||
}
|
||||
break;
|
||||
case CRASH:
|
||||
if (walked == 100) {
|
||||
/* something as odd as possible */
|
||||
return (ISC_R_HOSTUNREACH);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static void test_ht_walk() {
|
||||
isc_ht_t *ht = NULL;
|
||||
isc_result_t result;
|
||||
isc_mem_t *mctx = NULL;
|
||||
isc_int64_t i;
|
||||
isc_uint32_t count = 10000;
|
||||
|
||||
result = isc_mem_createx2(0, 0, default_memalloc, default_memfree,
|
||||
NULL, &mctx, 0);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_ht_init(&ht, mctx, 16);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
ATF_REQUIRE(ht != NULL);
|
||||
for (i = 1; i <= count; i++) {
|
||||
/*
|
||||
* Note that the string we're snprintfing is always > 16 bytes
|
||||
* so we are always filling the key.
|
||||
*/
|
||||
unsigned char key[16];
|
||||
snprintf((char *)key, 16, "%lld key of a raw hashtable!!", i);
|
||||
result = isc_ht_add(ht, key, 16, (void *) i);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
walked = 0;
|
||||
result = isc_ht_walk(ht, walker, (void *) REGULAR);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
ATF_REQUIRE_EQ(walked, count);
|
||||
|
||||
walked = 0;
|
||||
result = isc_ht_walk(ht, walker, (void *) CRASH);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_HOSTUNREACH);
|
||||
ATF_REQUIRE_EQ(walked, 100);
|
||||
|
||||
walked = 0;
|
||||
result = isc_ht_walk(ht, walker, (void *) ERASEODD);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
ATF_REQUIRE_EQ(walked, count);
|
||||
|
||||
walked = 0;
|
||||
result = isc_ht_walk(ht, walker, (void *) ERASEEVEN);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
ATF_REQUIRE_EQ(walked, count/2);
|
||||
|
||||
walked = 0;
|
||||
result = isc_ht_walk(ht, walker, (void *) REGULAR);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
ATF_REQUIRE_EQ(walked, 0);
|
||||
|
||||
isc_ht_destroy(&ht);
|
||||
ATF_REQUIRE_EQ(ht, NULL);
|
||||
}
|
||||
|
||||
ATF_TC(isc_ht_20);
|
||||
ATF_TC_HEAD(isc_ht_20, tc) {
|
||||
atf_tc_set_md_var(tc, "descr", "20 bit, 2M elements test");
|
||||
}
|
||||
|
||||
ATF_TC_BODY(isc_ht_20, tc) {
|
||||
UNUSED(tc);
|
||||
test_ht_full(20, 2000000);
|
||||
}
|
||||
|
||||
|
||||
ATF_TC(isc_ht_8);
|
||||
ATF_TC_HEAD(isc_ht_8, tc) {
|
||||
atf_tc_set_md_var(tc, "descr", "8 bit, 20000 elements crowded test");
|
||||
}
|
||||
|
||||
ATF_TC_BODY(isc_ht_8, tc) {
|
||||
UNUSED(tc);
|
||||
test_ht_full(8, 20000);
|
||||
}
|
||||
|
||||
ATF_TC(isc_ht_1);
|
||||
ATF_TC_HEAD(isc_ht_1, tc) {
|
||||
atf_tc_set_md_var(tc, "descr", "1 bit, 100 elements corner case test");
|
||||
}
|
||||
|
||||
ATF_TC_BODY(isc_ht_1, tc) {
|
||||
UNUSED(tc);
|
||||
test_ht_full(1, 100);
|
||||
}
|
||||
|
||||
ATF_TC(isc_ht_32);
|
||||
ATF_TC_HEAD(isc_ht_32, tc) {
|
||||
atf_tc_set_md_var(tc, "descr", "32 bit, 10000 elements corner case test");
|
||||
}
|
||||
|
||||
ATF_TC_BODY(isc_ht_32, tc) {
|
||||
UNUSED(tc);
|
||||
test_ht_full(32, 10000);
|
||||
}
|
||||
|
||||
ATF_TC(isc_ht_walk);
|
||||
ATF_TC_HEAD(isc_ht_walk, tc) {
|
||||
atf_tc_set_md_var(tc, "descr", "hashtable walking");
|
||||
}
|
||||
|
||||
ATF_TC_BODY(isc_ht_walk, tc) {
|
||||
UNUSED(tc);
|
||||
test_ht_walk();
|
||||
}
|
||||
|
||||
/*
|
||||
* Main
|
||||
*/
|
||||
ATF_TP_ADD_TCS(tp) {
|
||||
ATF_TP_ADD_TC(tp, isc_ht_20);
|
||||
ATF_TP_ADD_TC(tp, isc_ht_8);
|
||||
ATF_TP_ADD_TC(tp, isc_ht_1);
|
||||
ATF_TP_ADD_TC(tp, isc_ht_32);
|
||||
ATF_TP_ADD_TC(tp, isc_ht_walk);
|
||||
return (atf_no_error());
|
||||
}
|
||||
|
@ -308,6 +308,13 @@ isc_hmacsha512_invalidate
|
||||
isc_hmacsha512_sign
|
||||
isc_hmacsha512_update
|
||||
isc_hmacsha512_verify
|
||||
isc_ht_init
|
||||
isc_ht_destroy
|
||||
isc_ht_find
|
||||
isc_ht_delete
|
||||
isc_ht_iter_get
|
||||
isc_ht_iter_inc
|
||||
isc_ht_iter_value
|
||||
isc_httpd_addheader
|
||||
isc_httpd_addheaderuint
|
||||
isc_httpd_response
|
||||
|
@ -1472,6 +1472,42 @@ static cfg_type_t cfg_type_rpz = {
|
||||
rpz_fields
|
||||
};
|
||||
|
||||
/*
|
||||
* Catalog zones
|
||||
*/
|
||||
static cfg_type_t cfg_type_catz_zone = {
|
||||
"zone", parse_keyvalue, print_keyvalue,
|
||||
doc_keyvalue, &cfg_rep_string,
|
||||
&zone_kw
|
||||
};
|
||||
|
||||
static cfg_tuplefielddef_t catz_zone_fields[] = {
|
||||
{ "zone name", &cfg_type_catz_zone, 0 },
|
||||
{ "default-masters", &cfg_type_namesockaddrkeylist, 0 },
|
||||
{ "in-memory", &cfg_type_boolean, 0 },
|
||||
{ "min-update-interval", &cfg_type_uint32, 0 },
|
||||
{ NULL, NULL, 0 }
|
||||
};
|
||||
static cfg_type_t cfg_type_catz_tuple = {
|
||||
"catz tuple", cfg_parse_kv_tuple,
|
||||
cfg_print_kv_tuple, cfg_doc_kv_tuple, &cfg_rep_tuple,
|
||||
catz_zone_fields
|
||||
};
|
||||
static cfg_type_t cfg_type_catz_list = {
|
||||
"zone list", cfg_parse_bracketed_list, cfg_print_bracketed_list,
|
||||
cfg_doc_bracketed_list, &cfg_rep_list,
|
||||
&cfg_type_catz_tuple
|
||||
};
|
||||
static cfg_tuplefielddef_t catz_fields[] = {
|
||||
{ "zone list", &cfg_type_catz_list, 0 },
|
||||
{ NULL, NULL, 0 }
|
||||
};
|
||||
static cfg_type_t cfg_type_catz = {
|
||||
"catz", cfg_parse_kv_tuple, cfg_print_kv_tuple,
|
||||
cfg_doc_kv_tuple, &cfg_rep_tuple, catz_fields
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* rate-limit
|
||||
@ -1627,6 +1663,7 @@ view_clauses[] = {
|
||||
{ "attach-cache", &cfg_type_astring, 0 },
|
||||
{ "auth-nxdomain", &cfg_type_boolean, CFG_CLAUSEFLAG_NEWDEFAULT },
|
||||
{ "cache-file", &cfg_type_qstring, 0 },
|
||||
{ "catalog-zones", &cfg_type_catz, 0 },
|
||||
{ "check-names", &cfg_type_checknames, CFG_CLAUSEFLAG_MULTI },
|
||||
{ "cleaning-interval", &cfg_type_uint32, 0 },
|
||||
{ "clients-per-query", &cfg_type_uint32, 0 },
|
||||
|
Loading…
x
Reference in New Issue
Block a user