+4576. [func] The RPZ implementation has been substantially
+ refactored for improved performance and reliability.
+ [RT #43449]
+
4575. [security] DNS64 with "break-dnssec yes;" can result in an
assertion failure. (CVE-2017-3136) [RT #44653]
static isc_result_t
configure_rpz_zone(dns_view_t *view, const cfg_listelt_t *element,
isc_boolean_t recursive_only_def, dns_ttl_t ttl_def,
- const dns_rpz_zone_t *old, isc_boolean_t *old_rpz_okp)
+ isc_uint32_t minupdateint_def, const dns_rpz_zone_t *old,
+ isc_boolean_t *old_rpz_okp)
{
const cfg_obj_t *rpz_obj, *obj;
const char *str;
- dns_rpz_zone_t *new;
+ dns_rpz_zone_t *zone = NULL;
isc_result_t result;
dns_rpz_num_t rpz_num;
return (ISC_R_FAILURE);
}
- new = isc_mem_get(view->rpzs->mctx, sizeof(*new));
- if (new == NULL) {
- cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
- "no memory for response policy zones");
- return (ISC_R_NOMEMORY);
- }
-
- memset(new, 0, sizeof(*new));
- result = isc_refcount_init(&new->refs, 1);
+ result = dns_rpz_new_zone(view->rpzs, &zone);
if (result != ISC_R_SUCCESS) {
- isc_mem_put(view->rpzs->mctx, new, sizeof(*new));
+ cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
+ "Error creating new RPZ zone : %s",
+ isc_result_totext(result));
return (result);
}
- dns_name_init(&new->origin, NULL);
- dns_name_init(&new->client_ip, NULL);
- dns_name_init(&new->ip, NULL);
- dns_name_init(&new->nsdname, NULL);
- dns_name_init(&new->nsip, NULL);
- dns_name_init(&new->passthru, NULL);
- dns_name_init(&new->drop, NULL);
- dns_name_init(&new->tcp_only, NULL);
- dns_name_init(&new->cname, NULL);
- new->num = view->rpzs->p.num_zones++;
- view->rpzs->zones[new->num] = new;
obj = cfg_tuple_get(rpz_obj, "recursive-only");
if (cfg_obj_isvoid(obj) ? recursive_only_def : cfg_obj_asboolean(obj)) {
- view->rpzs->p.no_rd_ok &= ~DNS_RPZ_ZBIT(new->num);
+ view->rpzs->p.no_rd_ok &= ~DNS_RPZ_ZBIT(zone->num);
} else {
- view->rpzs->p.no_rd_ok |= DNS_RPZ_ZBIT(new->num);
+ view->rpzs->p.no_rd_ok |= DNS_RPZ_ZBIT(zone->num);
}
obj = cfg_tuple_get(rpz_obj, "log");
if (!cfg_obj_isvoid(obj) && !cfg_obj_asboolean(obj)) {
- view->rpzs->p.no_log |= DNS_RPZ_ZBIT(new->num);
+ view->rpzs->p.no_log |= DNS_RPZ_ZBIT(zone->num);
} else {
- view->rpzs->p.no_log &= ~DNS_RPZ_ZBIT(new->num);
+ view->rpzs->p.no_log &= ~DNS_RPZ_ZBIT(zone->num);
}
obj = cfg_tuple_get(rpz_obj, "max-policy-ttl");
if (cfg_obj_isuint32(obj)) {
- new->max_policy_ttl = cfg_obj_asuint32(obj);
+ zone->max_policy_ttl = cfg_obj_asuint32(obj);
+ } else {
+ zone->max_policy_ttl = ttl_def;
+ }
+
+ obj = cfg_tuple_get(rpz_obj, "min-update-interval");
+ if (cfg_obj_isuint32(obj)) {
+ zone->min_update_int = cfg_obj_asuint32(obj);
} else {
- new->max_policy_ttl = ttl_def;
+ zone->min_update_int = minupdateint_def;
}
- if (*old_rpz_okp && new->max_policy_ttl != old->max_policy_ttl)
+
+ if (*old_rpz_okp && zone->max_policy_ttl != old->max_policy_ttl)
*old_rpz_okp = ISC_FALSE;
str = cfg_obj_asstring(cfg_tuple_get(rpz_obj, "zone name"));
- result = configure_rpz_name(view, rpz_obj, &new->origin, str, "zone");
+ result = configure_rpz_name(view, rpz_obj, &zone->origin, str, "zone");
if (result != ISC_R_SUCCESS)
return (result);
- if (dns_name_equal(&new->origin, dns_rootname)) {
+ if (dns_name_equal(&zone->origin, dns_rootname)) {
cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
"invalid zone name '%s'", str);
return (DNS_R_EMPTYLABEL);
}
for (rpz_num = 0; rpz_num < view->rpzs->p.num_zones-1; ++rpz_num) {
if (dns_name_equal(&view->rpzs->zones[rpz_num]->origin,
- &new->origin)) {
+ &zone->origin)) {
cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
"duplicate '%s'", str);
result = DNS_R_DUPLICATE;
return (result);
}
}
- if (*old_rpz_okp && !dns_name_equal(&old->origin, &new->origin))
+ if (*old_rpz_okp && !dns_name_equal(&old->origin, &zone->origin))
*old_rpz_okp = ISC_FALSE;
- result = configure_rpz_name2(view, rpz_obj, &new->client_ip,
- DNS_RPZ_CLIENT_IP_ZONE, &new->origin);
+ result = configure_rpz_name2(view, rpz_obj, &zone->client_ip,
+ DNS_RPZ_CLIENT_IP_ZONE, &zone->origin);
if (result != ISC_R_SUCCESS)
return (result);
- result = configure_rpz_name2(view, rpz_obj, &new->ip,
- DNS_RPZ_IP_ZONE, &new->origin);
+ result = configure_rpz_name2(view, rpz_obj, &zone->ip,
+ DNS_RPZ_IP_ZONE, &zone->origin);
if (result != ISC_R_SUCCESS)
return (result);
- result = configure_rpz_name2(view, rpz_obj, &new->nsdname,
- DNS_RPZ_NSDNAME_ZONE, &new->origin);
+ result = configure_rpz_name2(view, rpz_obj, &zone->nsdname,
+ DNS_RPZ_NSDNAME_ZONE, &zone->origin);
if (result != ISC_R_SUCCESS)
return (result);
- result = configure_rpz_name2(view, rpz_obj, &new->nsip,
- DNS_RPZ_NSIP_ZONE, &new->origin);
+ result = configure_rpz_name2(view, rpz_obj, &zone->nsip,
+ DNS_RPZ_NSIP_ZONE, &zone->origin);
if (result != ISC_R_SUCCESS)
return (result);
- result = configure_rpz_name(view, rpz_obj, &new->passthru,
+ result = configure_rpz_name(view, rpz_obj, &zone->passthru,
DNS_RPZ_PASSTHRU_NAME, "name");
if (result != ISC_R_SUCCESS)
return (result);
- result = configure_rpz_name(view, rpz_obj, &new->drop,
+ result = configure_rpz_name(view, rpz_obj, &zone->drop,
DNS_RPZ_DROP_NAME, "name");
if (result != ISC_R_SUCCESS)
return (result);
- result = configure_rpz_name(view, rpz_obj, &new->tcp_only,
+ result = configure_rpz_name(view, rpz_obj, &zone->tcp_only,
DNS_RPZ_TCP_ONLY_NAME, "name");
if (result != ISC_R_SUCCESS)
return (result);
obj = cfg_tuple_get(rpz_obj, "policy");
if (cfg_obj_isvoid(obj)) {
- new->policy = DNS_RPZ_POLICY_GIVEN;
+ zone->policy = DNS_RPZ_POLICY_GIVEN;
} else {
str = cfg_obj_asstring(cfg_tuple_get(obj, "policy name"));
- new->policy = dns_rpz_str2policy(str);
- INSIST(new->policy != DNS_RPZ_POLICY_ERROR);
- if (new->policy == DNS_RPZ_POLICY_CNAME) {
+ zone->policy = dns_rpz_str2policy(str);
+ INSIST(zone->policy != DNS_RPZ_POLICY_ERROR);
+ if (zone->policy == DNS_RPZ_POLICY_CNAME) {
str = cfg_obj_asstring(cfg_tuple_get(obj, "cname"));
- result = configure_rpz_name(view, rpz_obj, &new->cname,
+ result = configure_rpz_name(view, rpz_obj, &zone->cname,
str, "cname");
if (result != ISC_R_SUCCESS)
return (result);
}
}
- if (*old_rpz_okp && (new->policy != old->policy ||
- !dns_name_equal(&old->cname, &new->cname)))
+ if (*old_rpz_okp && (zone->policy != old->policy ||
+ !dns_name_equal(&old->cname, &zone->cname)))
*old_rpz_okp = ISC_FALSE;
return (ISC_R_SUCCESS);
const cfg_obj_t *sub_obj;
isc_boolean_t recursive_only_def;
dns_ttl_t ttl_def;
- dns_rpz_zones_t *new;
+ isc_uint32_t minupdateint_def;
+ dns_rpz_zones_t *zones;
const dns_rpz_zones_t *old;
dns_view_t *pview;
const dns_rpz_zone_t *old_zone;
if (zone_element == NULL)
return (ISC_R_SUCCESS);
- result = dns_rpz_new_zones(&view->rpzs, view->mctx);
+ result = dns_rpz_new_zones(&view->rpzs, view->mctx,
+ ns_g_taskmgr, ns_g_timermgr);
if (result != ISC_R_SUCCESS)
return (result);
- new = view->rpzs;
+
+ zones = view->rpzs;
sub_obj = cfg_tuple_get(rpz_obj, "recursive-only");
if (!cfg_obj_isvoid(sub_obj) &&
sub_obj = cfg_tuple_get(rpz_obj, "break-dnssec");
if (!cfg_obj_isvoid(sub_obj) &&
cfg_obj_asboolean(sub_obj))
- new->p.break_dnssec = ISC_TRUE;
+ zones->p.break_dnssec = ISC_TRUE;
else
- new->p.break_dnssec = ISC_FALSE;
+ zones->p.break_dnssec = ISC_FALSE;
sub_obj = cfg_tuple_get(rpz_obj, "max-policy-ttl");
if (cfg_obj_isuint32(sub_obj))
else
ttl_def = DNS_RPZ_MAX_TTL_DEFAULT;
+ sub_obj = cfg_tuple_get(rpz_obj, "min-update-interval");
+ if (cfg_obj_isuint32(sub_obj))
+ minupdateint_def = cfg_obj_asuint32(sub_obj);
+ else
+ minupdateint_def = DNS_RPZ_MINUPDATEINT_DEF;
+
sub_obj = cfg_tuple_get(rpz_obj, "min-ns-dots");
if (cfg_obj_isuint32(sub_obj))
- new->p.min_ns_labels = cfg_obj_asuint32(sub_obj) + 1;
+ zones->p.min_ns_labels = cfg_obj_asuint32(sub_obj) + 1;
else
- new->p.min_ns_labels = 2;
+ zones->p.min_ns_labels = 2;
sub_obj = cfg_tuple_get(rpz_obj, "qname-wait-recurse");
if (cfg_obj_isvoid(sub_obj) || cfg_obj_asboolean(sub_obj))
- new->p.qname_wait_recurse = ISC_TRUE;
+ zones->p.qname_wait_recurse = ISC_TRUE;
else
- new->p.qname_wait_recurse = ISC_FALSE;
+ zones->p.qname_wait_recurse = ISC_FALSE;
sub_obj = cfg_tuple_get(rpz_obj, "nsip-wait-recurse");
if (cfg_obj_isvoid(sub_obj) || cfg_obj_asboolean(sub_obj))
- new->p.nsip_wait_recurse = ISC_TRUE;
+ zones->p.nsip_wait_recurse = ISC_TRUE;
else
- new->p.nsip_wait_recurse = ISC_FALSE;
+ zones->p.nsip_wait_recurse = ISC_FALSE;
pview = NULL;
result = dns_viewlist_find(&ns_g_server->viewlist,
}
result = configure_rpz_zone(view, zone_element,
recursive_only_def, ttl_def,
- old_zone, old_rpz_okp);
+ minupdateint_def, old_zone,
+ old_rpz_okp);
if (result != ISC_R_SUCCESS) {
if (pview != NULL)
dns_view_detach(&pview);
* zones are unchanged, then use the same policy data.
* Data for individual zones that must be reloaded will be merged.
*/
- if (old != NULL && memcmp(&old->p, &new->p, sizeof(new->p)) != 0)
+ if (old != NULL && memcmp(&old->p, &zones->p, sizeof(zones->p)) != 0)
*old_rpz_okp = ISC_FALSE;
if (*old_rpz_okp) {
dns_rpz_detach_rpzs(&view->rpzs);
}
-static void
-rpz_attach(dns_db_t *db, dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num) {
- sampledb_t *sampledb = (sampledb_t *) db;
-
- REQUIRE(VALID_SAMPLEDB(sampledb));
-
- dns_db_rpz_attach(sampledb->rbtdb, rpzs, rpz_num);
-}
-
-static isc_result_t
-rpz_ready(dns_db_t *db) {
- sampledb_t *sampledb = (sampledb_t *) db;
-
- REQUIRE(VALID_SAMPLEDB(sampledb));
-
- return (dns_db_rpz_ready(sampledb->rbtdb));
-}
-
static isc_result_t
findnodeext(dns_db_t *db, const dns_name_t *name,
isc_boolean_t create, dns_clientinfomethods_t *methods,
resigned,
isdnssec,
getrrsetstats,
- rpz_attach,
- rpz_ready,
+ NULL,
+ NULL,
findnodeext,
findext,
setcachestats,
}
min-ns-dots 0
qname-wait-recurse yes
+ min-update-interval 0
;
};
forward only;
forwarders { 10.53.0.3; };
- response-policy { zone "policy1"; };
+ response-policy { zone "policy1" min-update-interval 0; };
};
key rndc_key {
listen-on { 10.53.0.7; };
listen-on-v6 { none; };
- response-policy { zone "policy2"; } qname-wait-recurse no;
+ response-policy { zone "policy2"; }
+ qname-wait-recurse no
+ min-update-interval 0;
};
key rndc_key {
echo "I:starting resolver using named.$TESTNAME.conf"
cp -f ns2/named.$TESTNAME.conf ns2/named.conf
$PERL $SYSTEMTESTTOP/start.pl --noclean --restart . ns2
+ sleep 3
}
run_query() {
statement in the <filename>named.conf</filename> file:
</para>
-<programlisting><command>options {</command>
- [ <command>attach-cache</command> <replaceable>cache_name</replaceable> ; ]
- [ <command>version</command> <replaceable>version_string</replaceable> ; ]
- [ <command>hostname</command> <replaceable>hostname_string</replaceable> ; ]
- [ <command>server-id</command> <replaceable>server_id_string</replaceable> ; ]
- [ <command>directory</command> <replaceable>path_name</replaceable> ; ]
- [ <command>dnstap {</command> <replaceable>message_type</replaceable> ; ... <command>}</command> ; ]
- [ <command>dnstap-output</command> ( <option>file</option> | <option>unix</option> ) <replaceable>path_name</replaceable> [ <command>size</command> <replaceable>size_spec</replaceable> ] [ <command>versions</command> ( <replaceable>number</replaceable> | <option>unlimited</option> ) ] ; ]
- [ <command>dnstap-identity</command> ( <replaceable>string</replaceable> | <option>hostname</option> | <option>none</option> ) ; ]
- [ <command>dnstap-version</command> ( <replaceable>string</replaceable> | <option>none</option> ) ; ]
- [ <command>fstrm-set-buffer-hint</command> <replaceable>number</replaceable> ; ]
- [ <command>fstrm-set-flush-timeout</command> <replaceable>number</replaceable> ; ]
- [ <command>fstrm-set-input-queue-size</command> <replaceable>number</replaceable> ; ]
- [ <command>fstrm-set-output-notify-threshold</command> <replaceable>number</replaceable> ; ]
- [ <command>fstrm-set-output-queue-model</command> ( <option>mpsc</option> | <option>spsc</option> ) ; ]
- [ <command>fstrm-set-output-queue-size</command> <replaceable>number</replaceable> ; ]
- [ <command>fstrm-set-reopen-interval</command> <replaceable>number</replaceable> ; ]
- [ <command>geoip-directory</command> <replaceable>path_name</replaceable> ; ]
- [ <command>key-directory</command> <replaceable>path_name</replaceable> ; ]
- [ <command>managed-keys-directory</command> <replaceable>path_name</replaceable> ; ]
- [ <command>named-xfer</command> <replaceable>path_name</replaceable> ; ]
- [ <command>tkey-gssapi-keytab</command> <replaceable>path_name</replaceable> ; ]
- [ <command>tkey-gssapi-credential</command> <replaceable>principal</replaceable> ; ]
- [ <command>tkey-domain</command> <replaceable>domain_name</replaceable> ; ]
- [ <command>tkey-dhkey</command> <replaceable>key_name</replaceable> <replaceable>key_tag</replaceable> ; ]
- [ <command>cache-file</command> <replaceable>path_name</replaceable> ; ]
- [ <command>dump-file</command> <replaceable>path_name</replaceable> ; ]
- [ <command>bindkeys-file</command> <replaceable>path_name</replaceable> ; ]
- [ <command>lock-file</command> <replaceable>path_name</replaceable> ; ]
- [ <command>secroots-file</command> <replaceable>path_name</replaceable> ; ]
- [ <command>session-keyfile</command> <replaceable>path_name</replaceable> ; ]
- [ <command>session-keyname</command> <replaceable>key_name</replaceable> ; ]
- [ <command>session-keyalg</command> <replaceable>algorithm_id</replaceable> ; ]
- [ <command>memstatistics</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>memstatistics-file</command> <replaceable>path_name</replaceable> ; ]
- [ <command>pid-file</command> <replaceable>path_name</replaceable> ; ]
- [ <command>recursing-file</command> <replaceable>path_name</replaceable> ; ]
- [ <command>statistics-file</command> <replaceable>path_name</replaceable> ; ]
- [ <command>zone-statistics</command> ( <option>full</option> | <option>terse</option> | <option>none</option> ) ; ]
- [ <command>auth-nxdomain</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>nxdomain-redirect</command> <replaceable>string</replaceable> ; ]
- [ <command>deallocate-on-exit</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>dialup</command> <replaceable>dialup_option</replaceable> ; ]
- [ <command>fake-iquery</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>fetch-glue</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>flush-zones-on-shutdown</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>has-old-clients</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>host-statistics</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>host-statistics-max</command> <replaceable>number</replaceable> ; ]
- [ <command>minimal-any</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>minimal-responses</command> ( <replaceable>yes_or_no</replaceable> | <option>no-auth</option> | <option>no-auth-recursive</option> ) ; ]
- [ <command>multiple-cnames</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>notify</command> ( <replaceable>yes_or_no</replaceable> | <option>explicit</option> | <option>master-only</option> ) ; ]
- [ <command>recursion</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>send-cookie</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>require-server-cookie</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>cookie-algorithm</command> <replaceable>algorithm_id</replaceable> ; ]
- [ <command>cookie-secret</command> <replaceable>secret_string</replaceable> ; ]
- [ <command>nocookie-udp-size</command> <replaceable>number</replaceable> ; ]
- [ <command>request-nsid</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>rfc2308-type1</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>use-id-pool</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>maintain-ixfr-base</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>ixfr-from-differences</command> ( <replaceable>yes_or_no</replaceable> | <option>master</option> | <option>slave</option> ) ; ]
- [ <command>auto-dnssec</command> ( <option>allow</option> | <option>maintain</option> | <option>off</option> ) ; ]
- [ <command>dnssec-enable</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>dnssec-validation</command> ( <replaceable>yes_or_no</replaceable> | <option>auto</option> ) ; ]
- [ <command>dnssec-lookaside</command> ( <option>auto</option> | <option>no</option> | <replaceable>domain</replaceable> trust-anchor <replaceable>domain</replaceable> ) ; ]
- [ <command>dnssec-must-be-secure</command> <replaceable>domain yes_or_no</replaceable> ; ]
- [ <command>dnssec-accept-expired</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>forward</command> ( <option>only</option> | <option>first</option> ) ; ]
- [ <command>forwarders {</command>
- ( <replaceable>ip_addr</replaceable> [ <command>port</command> <replaceable>ip_port</replaceable> ] [ <command>dscp</command> <replaceable>ip_dscp</replaceable> ] ; )
- ...
- <command>}</command> ; ]
- [ <command>dual-stack-servers</command> [ <command>port</command> <replaceable>ip_port</replaceable> ] [ <command>dscp</command> <replaceable>ip_dscp</replaceable> ] <command>{</command>
- ( ( <replaceable>domain_name</replaceable> | <replaceable>ip_addr</replaceable> ) [ <command>port</command> <replaceable>ip_port</replaceable> ] [ <command>dscp</command> <replaceable>ip_dscp</replaceable> ] ; )
- ...
- <command>}</command> ; ]
- [ <command>check-names</command> ( <option>master</option> | <option>slave</option> | <option>response</option> )
- ( <option>warn</option> | <option>fail</option> | <option>ignore</option> ) ; ]
- [ <command>check-dup-records</command> ( <option>warn</option> | <option>fail</option> | <option>ignore</option> ) ; ]
- [ <command>check-mx</command> ( <option>warn</option> | <option>fail</option> | <option>ignore</option> ) ; ]
- [ <command>check-wildcard</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>check-integrity</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>check-mx-cname</command> ( <option>warn</option> | <option>fail</option> | <option>ignore</option> ) ; ]
- [ <command>check-srv-cname</command> ( <option>warn</option> | <option>fail</option> | <option>ignore</option> ) ; ]
- [ <command>check-sibling</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>check-spf</command> ( <option>warn</option> | <option>ignore</option> ) ; ]
- [ <command>allow-new-zones</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>allow-notify {</command> <replaceable>address_match_list</replaceable> <command>}</command> ; ]
- [ <command>allow-query {</command> <replaceable>address_match_list</replaceable> <command>}</command> ; ]
- [ <command>allow-query-on {</command> <replaceable>address_match_list</replaceable> <command>}</command> ; ]
- [ <command>allow-query-cache {</command> <replaceable>address_match_list</replaceable> <command>}</command> ; ]
- [ <command>allow-query-cache-on {</command> <replaceable>address_match_list</replaceable> <command>}</command> ; ]
- [ <command>allow-transfer {</command> <replaceable>address_match_list</replaceable> <command>}</command> ; ]
- [ <command>allow-recursion {</command> <replaceable>address_match_list</replaceable> <command>}</command> ; ]
- [ <command>allow-recursion-on {</command> <replaceable>address_match_list</replaceable> <command>}</command> ; ]
- [ <command>allow-update {</command> <replaceable>address_match_list</replaceable> <command>}</command> ]
- [ <command>allow-update-forwarding {</command> <replaceable>address_match_list</replaceable> <command>}</command> ; ]
- [ <command>automatic-interface-scan</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>geoip-use-ecs</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>update-check-ksk</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>dnssec-update-mode</command> ( <option>maintain</option> | <option>no-resign</option> ) ; ]
- [ <command>dnssec-dnskey-kskonly</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>dnssec-loadkeys-interval</command> <replaceable>number</replaceable> ; ]
- [ <command>dnssec-secure-to-insecure</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>try-tcp-refresh</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>allow-v6-synthesis {</command> <replaceable>address_match_list</replaceable> <command>}</command> ; ]
- [ <command>blackhole {</command> <replaceable>address_match_list</replaceable> <command>}</command> ; ]
- [ <command>keep-response-order {</command> <replaceable>address_match_list</replaceable> <command>}</command> ; ]
- [ <command>no-case-compress {</command> <replaceable>address_match_list</replaceable> <command>}</command> ; ]
- [ <command>message-compression</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>use-v4-udp-ports {</command> <replaceable>port_list</replaceable> <command>}</command> ; ]
- [ <command>avoid-v4-udp-ports {</command> <replaceable>port_list</replaceable> <command>}</command> ; ]
- [ <command>use-v6-udp-ports {</command> <replaceable>port_list</replaceable> <command>}</command> ; ]
- [ <command>avoid-v6-udp-ports {</command> <replaceable>port_list</replaceable> <command>}</command> ; ]
- [ <command>listen-on</command> [ <command>port</command> <replaceable>ip_port</replaceable> ] [ <command>dscp</command> <replaceable>ip_dscp</replaceable> ] <command>{</command> <replaceable>address_match_list</replaceable> <command>}</command> ; ]
- [ <command>listen-on-v6</command> [ <command>port</command> <replaceable>ip_port</replaceable> ] [ <command>dscp</command> <replaceable>ip_dscp</replaceable> ] <command>{</command> <replaceable>address_match_list</replaceable> <command>}</command> ; ]
- [ <command>query-source</command> ( [ <command>address</command> ] ( <replaceable>ip4_addr</replaceable> | <option>*</option> ) )
- [ <command>port</command> ( <replaceable>ip_port</replaceable> | <option>*</option> ) ] [ <command>dscp</command> <replaceable>ip_dscp</replaceable> ] ] ;
- [ <command>query-source-v6</command> ( [ <command>address</command> ] ( <replaceable>ip6_addr</replaceable> | <option>*</option> ) )
- [ <command>port</command> ( <replaceable>ip_port</replaceable> | <option>*</option> ) ] [ <command>dscp</command> <replaceable>ip_dscp</replaceable> ] ] ;
- [ <command>use-queryport-pool</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>queryport-pool-ports</command> <replaceable>number</replaceable> ; ]
- [ <command>queryport-pool-updateinterval</command> <replaceable>number</replaceable> ; ]
- [ <command>max-records</command> <replaceable>number</replaceable> ; ]
- [ <command>max-transfer-time-in</command> <replaceable>number</replaceable> ; ]
- [ <command>max-transfer-time-out</command> <replaceable>number</replaceable> ; ]
- [ <command>max-transfer-idle-in</command> <replaceable>number</replaceable> ; ]
- [ <command>max-transfer-idle-out</command> <replaceable>number</replaceable> ; ]
- [ <command>reserved-sockets</command> <replaceable>number</replaceable> ; ]
- [ <command>recursive-clients</command> <replaceable>number</replaceable> ; ]
- [ <command>tcp-clients</command> <replaceable>number</replaceable> ; ]
- [ <command>clients-per-query</command> <replaceable>number</replaceable> ; ]
- [ <command>max-clients-per-query</command> <replaceable>number</replaceable> ; ]
- [ <command>fetches-per-server</command> <replaceable>number</replaceable> [ ( <option>drop</option> | <option>fail</option> ) ] ; ]
- [ <command>fetches-per-zone</command> <replaceable>number</replaceable> [ ( <option>drop</option> | <option>fail</option> ) ] ; ]
- [ <command>fetch-quota-params</command> <replaceable>number fixedpoint fixedpoint fixedpoint</replaceable> ; ]
- [ <command>notify-rate</command> <replaceable>number</replaceable> ; ]
- [ <command>startup-notify-rate</command> <replaceable>number</replaceable> ; ]
- [ <command>serial-query-rate</command> <replaceable>number</replaceable> ; ]
- [ <command>serial-queries</command> <replaceable>number</replaceable> ; ]
- [ <command>tcp-listen-queue</command> <replaceable>number</replaceable> ; ]
- [ <command>tcp-initial-timeout</command> <replaceable>number</replaceable>; ]
- [ <command>tcp-idle-timeout</command> <replaceable>number</replaceable>; ]
- [ <command>tcp-keepalive-timeout</command> <replaceable>number</replaceable>; ]
- [ <command>tcp-advertised-timeout</command> <replaceable>number</replaceable>; ]
- [ <command>transfer-format</command> ( <option>one-answer</option> | <option>many-answers</option> ) ; ]
- [ <command>transfer-message-size</command> <replaceable>number</replaceable> ; ]
- [ <command>transfers-in</command> <replaceable>number</replaceable> ; ]
- [ <command>transfers-out</command> <replaceable>number</replaceable> ; ]
- [ <command>transfers-per-ns</command> <replaceable>number</replaceable> ; ]
- [ <command>transfer-source</command> ( <replaceable>ip4_addr</replaceable> | <option>*</option> )
- [ <command>port</command> <replaceable>ip_port</replaceable> ] [ <command>dscp</command> <replaceable>ip_dscp</replaceable> ] ; ]
- [ <command>transfer-source-v6</command> ( <replaceable>ip6_addr</replaceable> | <option>*</option> )
- [ <command>port</command> <replaceable>ip_port</replaceable> ] [ <command>dscp</command> <replaceable>ip_dscp</replaceable> ] ; ]
- [ <command>alt-transfer-source</command> ( <replaceable>ip4_addr</replaceable> | <option>*</option> )
- [ <command>port</command> <replaceable>ip_port</replaceable> ] [ <command>dscp</command> <replaceable>ip_dscp</replaceable> ] ; ]
- [ <command>alt-transfer-source-v6</command> ( <replaceable>ip6_addr</replaceable> | <option>*</option> )
- [ <command>port</command> <replaceable>ip_port</replaceable> ] [ <command>dscp</command> <replaceable>ip_dscp</replaceable> ] ; ]
- [ <command>use-alt-transfer-source</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>notify-delay</command> <replaceable>seconds</replaceable> ; ]
- [ <command>notify-source</command> ( <replaceable>ip4_addr</replaceable> | <option>*</option> )
- [ <command>port</command> <replaceable>ip_port</replaceable> ] [ <command>dscp</command> <replaceable>ip_dscp</replaceable> ] ; ]
- [ <command>notify-source-v6</command> ( <replaceable>ip6_addr</replaceable> | <option>*</option> )
- [ <command>port</command> <replaceable>ip_port</replaceable> ] [ <command>dscp</command> <replaceable>ip_dscp</replaceable> ] ; ]
- [ <command>notify-to-soa</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>also-notify</command> [ <command>port</command> <replaceable>ip_port</replaceable>] [ <command>dscp</command> <replaceable>ip_dscp</replaceable>] <command>{</command>
- ( <replaceable>masters</replaceable> | <replaceable>ip_addr</replaceable> [ <command>port</command> <replaceable>ip_port</replaceable> ] ) [ <command>key</command> <replaceable>key_name</replaceable> ] ;
- ...
- <command>}</command> ; ]
- [ <command>max-ixfr-log-size</command> <replaceable>number</replaceable> ; ]
- [ <command>max-journal-size</command> <replaceable>size_spec</replaceable> ; ]
- [ <command>coresize</command> <replaceable>size_spec</replaceable> ; ]
- [ <command>datasize</command> <replaceable>size_spec</replaceable> ; ]
- [ <command>files</command> <replaceable>size_spec</replaceable> ; ]
- [ <command>stacksize</command> <replaceable>size_spec</replaceable> ; ]
- [ <command>cleaning-interval</command> <replaceable>number</replaceable> ; ]
- [ <command>heartbeat-interval</command> <replaceable>number</replaceable> ; ]
- [ <command>interface-interval</command> <replaceable>number</replaceable> ; ]
- [ <command>statistics-interval</command> <replaceable>number</replaceable> ; ]
- [ <command>topology {</command> <replaceable>address_match_list</replaceable> <command>}</command> ; ]
- [ <command>sortlist {</command> <replaceable>address_match_list</replaceable> <command>}</command> ; ]
- [ <command>rrset-order {</command> <replaceable>order_spec</replaceable> ; ... <command>}</command> ; ]
- [ <command>lame-ttl</command> <replaceable>number</replaceable> ; ]
- [ <command>max-ncache-ttl</command> <replaceable>number</replaceable> ; ]
- [ <command>max-cache-ttl</command> <replaceable>number</replaceable> ; ]
- [ <command>max-zone-ttl</command> ( <option>unlimited</option> | <replaceable>number</replaceable> ) ; ]
- [ <command>serial-update-method</command> ( <option>increment</option> | <option>unixtime</option> | <option>date</option> ) ; ]
- [ <command>servfail-ttl</command> <replaceable>number</replaceable> ; ]
- [ <command>sig-validity-interval</command> <replaceable>number</replaceable> [<replaceable>number</replaceable>] ; ]
- [ <command>sig-signing-nodes</command> <replaceable>number</replaceable> ; ]
- [ <command>sig-signing-signatures</command> <replaceable>number</replaceable> ; ]
- [ <command>sig-signing-type</command> <replaceable>number</replaceable> ; ]
- [ <command>min-roots</command> <replaceable>number</replaceable> ; ]
- [ <command>use-ixfr</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>provide-ixfr</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>request-ixfr</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>request-expire</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>treat-cr-as-space</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>min-refresh-time</command> <replaceable>number</replaceable> ; ]
- [ <command>max-refresh-time</command> <replaceable>number</replaceable> ; ]
- [ <command>min-retry-time</command> <replaceable>number</replaceable> ; ]
- [ <command>max-retry-time</command> <replaceable>number</replaceable> ; ]
- [ <command>nta-lifetime</command> <replaceable>duration</replaceable> ; ]
- [ <command>nta-recheck</command> <replaceable>duration</replaceable> ; ]
- [ <command>port</command> <replaceable>ip_port</replaceable> ; ]
- [ <command>dscp</command> <replaceable>ip_dscp</replaceable> ; ]
- [ <command>additional-from-auth</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>additional-from-cache</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>random-device</command> <replaceable>path_name</replaceable> ; ]
- [ <command>max-cache-size</command> <replaceable>size_or_percent</replaceable> ; ]
- [ <command>match-mapped-addresses</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>filter-aaaa-on-v4</command> ( <replaceable>yes_or_no</replaceable> | <option>break-dnssec</option> ) ; ]
- [ <command>filter-aaaa-on-v6</command> ( <replaceable>yes_or_no</replaceable> | <option>break-dnssec</option> ) ; ]
- [ <command>filter-aaaa {</command> <replaceable>address_match_list</replaceable> <command>}</command> ; ]
- [ <command>dns64</command> <replaceable>ipv6-prefix</replaceable> <command>{</command>
- [ <command>clients {</command> <replaceable>address_match_list</replaceable> <command>}</command> ; ]
- [ <command>mapped {</command> <replaceable>address_match_list</replaceable> <command>}</command> ; ]
- [ <command>exclude {</command> <replaceable>address_match_list</replaceable> <command>}</command> ; ]
- [ <command>suffix</command> <replaceable>ip6-address</replaceable> ; ]
- [ <command>recursive-only</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>break-dnssec</command> <replaceable>yes_or_no</replaceable> ; ]
- <command>}</command> ; ]
- [ <command>dns64-server</command> <replaceable>name</replaceable> ]
- [ <command>dns64-contact</command> <replaceable>name</replaceable> ]
- [ <command>preferred-glue</command> ( <option>A</option> | <option>AAAA</option> | <option>none</option> ); ]
- [ <command>edns-udp-size</command> <replaceable>number</replaceable> ; ]
- [ <command>max-udp-size</command> <replaceable>number</replaceable> ; ]
- [ <command>response-padding</command> { <replaceable>address_match_list</replaceable> } block-size <replaceable>number</replaceable> ; ]
- [ <command>max-rsa-exponent-size</command> <replaceable>number</replaceable> ; ]
- [ <command>root-delegation-only</command> [ <command>exclude {</command> <replaceable>namelist</replaceable> <command>}</command> ] ; ]
- [ <command>querylog</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>disable-algorithms</command> <replaceable>domain</replaceable> <command>{</command> <replaceable>algorithm</replaceable> ; ... <command>}</command> ; ]
- [ <command>disable-ds-digests</command> <replaceable>domain</replaceable> <command>{</command> <replaceable>digest_type</replaceable> ; ... <command>}</command> ; ]
- [ <command>acache-enable</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>acache-cleaning-interval</command> <replaceable>number</replaceable> ; ]
- [ <command>max-acache-size</command> <replaceable>size_spec</replaceable> ; ]
- [ <command>max-recursion-depth</command> <replaceable>number</replaceable> ; ]
- [ <command>max-recursion-queries</command> <replaceable>number</replaceable> ; ]
- [ <command>masterfile-format</command> ( <option>text</option> | <option>raw</option> | <option>map</option> ) ; ]
- [ <command>masterfile-style</command> ( <option>relative</option> | <option>full</option> ) ; ]
- [ <command>empty-server</command> <replaceable>name</replaceable> ; ]
- [ <command>empty-contact</command> <replaceable>name</replaceable> ; ]
- [ <command>empty-zones-enable</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>disable-empty-zone</command> <replaceable>zone_name</replaceable> ; ]
- [ <command>zero-no-soa-ttl</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>zero-no-soa-ttl-cache</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>resolver-query-timeout</command> <replaceable>number</replaceable> ; ]
- [ <command>deny-answer-addresses {</command> <replaceable>address_match_list</replaceable> <command>}</command>
- [ <command>except-from {</command> <replaceable>namelist</replaceable> <command>}</command> ] ; ]
- [ <command>deny-answer-aliases {</command> <replaceable>namelist</replaceable> <command>}</command>
- [ <command>except-from {</command> <replaceable>namelist</replaceable> <command>}</command> ] ; ]
- [ <command>prefetch</command> <replaceable>number</replaceable> [ <replaceable>number</replaceable> ] ; ]
- [ <command>rate-limit {</command>
- [ <command>responses-per-second</command> <replaceable>number</replaceable> ; ]
- [ <command>referrals-per-second</command> <replaceable>number</replaceable> ; ]
- [ <command>nodata-per-second</command> <replaceable>number</replaceable> ; ]
- [ <command>nxdomains-per-second</command> <replaceable>number</replaceable> ; ]
- [ <command>errors-per-second</command> <replaceable>number</replaceable> ; ]
- [ <command>all-per-second</command> <replaceable>number</replaceable> ; ]
- [ <command>window</command> <replaceable>number</replaceable> ; ]
- [ <command>log-only</command> <replaceable>yes_or_no</replaceable> ; ]
- [ <command>qps-scale</command> <replaceable>number</replaceable> ; ]
- [ <command>ipv4-prefix-length</command> <replaceable>number</replaceable> ; ]
- [ <command>ipv6-prefix-length</command> <replaceable>number</replaceable> ; ]
- [ <command>slip</command> <replaceable>number</replaceable> ; ]
- [ <command>exempt-clients {</command> <replaceable>address_match_list</replaceable> <command>}</command> ; ]
- [ <command>max-table-size</command> <replaceable>number</replaceable> ; ]
- [ <command>min-table-size</command> <replaceable>number</replaceable> ; ]
- <command>}</command> ; ]
- [ <command>response-policy {</command>
- <command>zone</command> <replaceable>zone_name</replaceable>
- [ <command>policy</command> ( given | disabled | passthru | drop |
- tcp-only | nxdomain | nodata | cname <replaceable>domain</replaceable> ) ]
- [ <command>recursive-only</command> <replaceable>yes_or_no</replaceable> ]
- [ <command>log</command> <replaceable>yes_or_no</replaceable> ]
- [ <command>max-policy-ttl</command> <replaceable>number</replaceable> ] ;
- ...
- <command>}</command> [ <command>recursive-only</command> <replaceable>yes_or_no</replaceable> ]
- [ <command>max-policy-ttl</command> <replaceable>number</replaceable> ]
- [ <command>break-dnssec</command> <replaceable>yes_or_no</replaceable> ]
- [ <command>min-ns-dots</command> <replaceable>number</replaceable> ]
- [ <command>nsip-wait-recurse</command> <replaceable>yes_or_no</replaceable> ]
- [ <command>qname-wait-recurse</command> <replaceable>yes_or_no</replaceable> ] ; ]
- [ <command>catalog-zones {</command>
- <command>zone</command> <replaceable>quoted_string</replaceable>
- [ <option>default-masters</option> [ <command>port</command> <replaceable>ip_port</replaceable> ] [ <command>dscp</command> <replaceable>ip_dscp</replaceable> ] <command>{</command>
- ( <replaceable>masters_list</replaceable> | <replaceable>ip_addr</replaceable> [<command>port</command> <replaceable>ip_port</replaceable>] [ <command>key</command> <replaceable>key_name</replaceable>] ) ;
- ...
- <command>}</command> ]
- [ <command>zone-directory</command> <replaceable>path_name</replaceable> ]
- [ <command>in-memory</command> <replaceable>yes_or_no</replaceable> ]
- [ <command>min-update-interval</command> <replaceable>interval</replaceable> ] ;
- ...
- <command>}</command> ; ]
- [ <command>v6-bias</command> <replaceable>number</replaceable> ; ]
-<command>}</command> ; ]
+<programlisting><command>options</command> {
+ <optional> attach-cache <replaceable>cache_name</replaceable>; </optional>
+ <optional> version <replaceable>version_string</replaceable>; </optional>
+ <optional> hostname <replaceable>hostname_string</replaceable>; </optional>
+ <optional> server-id <replaceable>server_id_string</replaceable>; </optional>
+ <optional> directory <replaceable>path_name</replaceable>; </optional>
+ <optional> dnstap { <replaceable>message_type</replaceable>; ... }; </optional>
+ <optional> dnstap-output ( <literal>file</literal> | <literal>unix</literal> ) <replaceable>path_name</replaceable>; </optional>
+ <optional> dnstap-identity ( <replaceable>string</replaceable> | <literal>hostname</literal> | <literal>none</literal> ); </optional>
+ <optional> dnstap-version ( <replaceable>string</replaceable> | <literal>none</literal> ); </optional>
+ <optional> fstrm-set-buffer-hint <replaceable>number</replaceable> ; </optional>
+ <optional> fstrm-set-flush-timeout <replaceable>number</replaceable> ; </optional>
+ <optional> fstrm-set-input-queue-size <replaceable>number</replaceable> ; </optional>
+ <optional> fstrm-set-output-notify-threshold <replaceable>number</replaceable> ; </optional>
+ <optional> fstrm-set-output-queue-model ( <replaceable>mpsc</replaceable> |
+ <replaceable>spsc</replaceable> ) ; </optional>
+ <optional> fstrm-set-output-queue-size <replaceable>number</replaceable> ; </optional>
+ <optional> fstrm-set-reopen-interval <replaceable>number</replaceable> ; </optional>
+ <optional> geoip-directory <replaceable>path_name</replaceable>; </optional>
+ <optional> key-directory <replaceable>path_name</replaceable>; </optional>
+ <optional> managed-keys-directory <replaceable>path_name</replaceable>; </optional>
+ <optional> named-xfer <replaceable>path_name</replaceable>; </optional>
+ <optional> tkey-gssapi-keytab <replaceable>path_name</replaceable>; </optional>
+ <optional> tkey-gssapi-credential <replaceable>principal</replaceable>; </optional>
+ <optional> tkey-domain <replaceable>domainname</replaceable>; </optional>
+ <optional> tkey-dhkey <replaceable>key_name</replaceable> <replaceable>key_tag</replaceable>; </optional>
+ <optional> cache-file <replaceable>path_name</replaceable>; </optional>
+ <optional> dump-file <replaceable>path_name</replaceable>; </optional>
+ <optional> bindkeys-file <replaceable>path_name</replaceable>; </optional>
+ <optional> lock-file <replaceable>path_name</replaceable>; </optional>
+ <optional> secroots-file <replaceable>path_name</replaceable>; </optional>
+ <optional> session-keyfile <replaceable>path_name</replaceable>; </optional>
+ <optional> session-keyname <replaceable>key_name</replaceable>; </optional>
+ <optional> session-keyalg <replaceable>algorithm_id</replaceable>; </optional>
+ <optional> memstatistics <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> memstatistics-file <replaceable>path_name</replaceable>; </optional>
+ <optional> pid-file <replaceable>path_name</replaceable>; </optional>
+ <optional> recursing-file <replaceable>path_name</replaceable>; </optional>
+ <optional> statistics-file <replaceable>path_name</replaceable>; </optional>
+ <optional> zone-statistics <replaceable>full</replaceable> | <replaceable>terse</replaceable> | <replaceable>none</replaceable>; </optional>
+ <optional> auth-nxdomain <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> nxdomain-redirect <replaceable>string</replaceable>; </optional>
+ <optional> deallocate-on-exit <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> dialup <replaceable>dialup_option</replaceable>; </optional>
+ <optional> fake-iquery <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> fetch-glue <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> flush-zones-on-shutdown <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> has-old-clients <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> host-statistics <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> host-statistics-max <replaceable>number</replaceable>; </optional>
+ <optional> minimal-any <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> minimal-responses (<replaceable>yes_or_no</replaceable> | <constant>no-auth</constant> | <constant>no-auth-recursive</constant>); </optional>
+ <optional> multiple-cnames <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> notify <replaceable>yes_or_no</replaceable> | <replaceable>explicit</replaceable> | <replaceable>master-only</replaceable>; </optional>
+ <optional> recursion <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> send-cookie <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> require-server-cookie <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> cookie-algorithm <replaceable>algorithm_id</replaceable>; </optional>
+ <optional> cookie-secret <replaceable>secret_string</replaceable>; </optional>
+ <optional> nocookie-udp-size <replaceable>number</replaceable> ; </optional>
+ <optional> request-nsid <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> rfc2308-type1 <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> use-id-pool <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> maintain-ixfr-base <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> ixfr-from-differences (<replaceable>yes_or_no</replaceable> | <constant>master</constant> | <constant>slave</constant>); </optional>
+ <optional> auto-dnssec <constant>allow</constant>|<constant>maintain</constant>|<constant>off</constant>; </optional>
+ <optional> dnssec-enable <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> dnssec-validation (<replaceable>yes_or_no</replaceable> | <constant>auto</constant>); </optional>
+ <optional> dnssec-lookaside ( <replaceable>auto</replaceable> |
+ <replaceable>no</replaceable> |
+ <replaceable>domain</replaceable> trust-anchor <replaceable>domain</replaceable> ); </optional>
+ <optional> dnssec-must-be-secure <replaceable>domain yes_or_no</replaceable>; </optional>
+ <optional> dnssec-accept-expired <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> forward ( <replaceable>only</replaceable> | <replaceable>first</replaceable> ); </optional>
+ <optional> forwarders { <optional> <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; ... </optional> }; </optional>
+ <optional> dual-stack-servers <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> {
+ ( <replaceable>domain_name</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> |
+ <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional>) ;
+ ... }; </optional>
+ <optional> check-names ( <replaceable>master</replaceable> | <replaceable>slave</replaceable> | <replaceable>response</replaceable> )
+ ( <replaceable>warn</replaceable> | <replaceable>fail</replaceable> | <replaceable>ignore</replaceable> ); </optional>
+ <optional> check-dup-records ( <replaceable>warn</replaceable> | <replaceable>fail</replaceable> | <replaceable>ignore</replaceable> ); </optional>
+ <optional> check-mx ( <replaceable>warn</replaceable> | <replaceable>fail</replaceable> | <replaceable>ignore</replaceable> ); </optional>
+ <optional> check-wildcard <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> check-integrity <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> check-mx-cname ( <replaceable>warn</replaceable> | <replaceable>fail</replaceable> | <replaceable>ignore</replaceable> ); </optional>
+ <optional> check-srv-cname ( <replaceable>warn</replaceable> | <replaceable>fail</replaceable> | <replaceable>ignore</replaceable> ); </optional>
+ <optional> check-sibling <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> check-spf ( <replaceable>warn</replaceable> | <replaceable>ignore</replaceable> ); </optional>
+ <optional> allow-new-zones { <replaceable>yes_or_no</replaceable> }; </optional>
+ <optional> allow-notify { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> allow-query { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> allow-query-on { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> allow-query-cache { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> allow-query-cache-on { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> allow-transfer { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> allow-recursion { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> allow-recursion-on { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> allow-update { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> allow-update-forwarding { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> automatic-interface-scan { <replaceable>yes_or_no</replaceable> }; </optional>
+ <optional> geoip-use-ecs <replaceable>yes_or_no</replaceable>;</optional>
+ <optional> update-check-ksk <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> dnssec-update-mode ( <replaceable>maintain</replaceable> | <replaceable>no-resign</replaceable> ); </optional>
+ <optional> dnssec-dnskey-kskonly <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> dnssec-loadkeys-interval <replaceable>number</replaceable>; </optional>
+ <optional> dnssec-secure-to-insecure <replaceable>yes_or_no</replaceable> ;</optional>
+ <optional> try-tcp-refresh <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> allow-v6-synthesis { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> blackhole { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> keep-response-order { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> no-case-compress { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> message-compression <replaceable>yes_or_no</replaceable> ; </optional>
+ <optional> use-v4-udp-ports { <replaceable>port_list</replaceable> }; </optional>
+ <optional> avoid-v4-udp-ports { <replaceable>port_list</replaceable> }; </optional>
+ <optional> use-v6-udp-ports { <replaceable>port_list</replaceable> }; </optional>
+ <optional> avoid-v6-udp-ports { <replaceable>port_list</replaceable> }; </optional>
+ <optional> listen-on <optional> port <replaceable>ip_port</replaceable> </optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> listen-on-v6 <optional> port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional>
+{ <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> query-source ( ( <replaceable>ip4_addr</replaceable> | <replaceable>*</replaceable> )
+ <optional> port ( <replaceable>ip_port</replaceable> | <replaceable>*</replaceable> ) </optional>
+ <optional> dscp <replaceable>ip_dscp</replaceable></optional> |
+ <optional> address ( <replaceable>ip4_addr</replaceable> | <replaceable>*</replaceable> ) </optional>
+ <optional> port ( <replaceable>ip_port</replaceable> | <replaceable>*</replaceable> ) </optional> )
+ <optional> dscp <replaceable>ip_dscp</replaceable></optional> ; </optional>
+ <optional> query-source-v6 ( ( <replaceable>ip6_addr</replaceable> | <replaceable>*</replaceable> )
+ <optional> port ( <replaceable>ip_port</replaceable> | <replaceable>*</replaceable> ) </optional>
+ <optional> dscp <replaceable>ip_dscp</replaceable></optional> |
+ <optional> address ( <replaceable>ip6_addr</replaceable> | <replaceable>*</replaceable> ) </optional>
+ <optional> port ( <replaceable>ip_port</replaceable> | <replaceable>*</replaceable> ) </optional> )
+ <optional> dscp <replaceable>ip_dscp</replaceable></optional> ; </optional>
+ <optional> use-queryport-pool <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> queryport-pool-ports <replaceable>number</replaceable>; </optional>
+ <optional> queryport-pool-updateinterval <replaceable>number</replaceable>; </optional>
+ <optional> max-transfer-time-in <replaceable>number</replaceable>; </optional>
+ <optional> max-transfer-time-out <replaceable>number</replaceable>; </optional>
+ <optional> max-transfer-idle-in <replaceable>number</replaceable>; </optional>
+ <optional> max-transfer-idle-out <replaceable>number</replaceable>; </optional>
+ <optional> reserved-sockets <replaceable>number</replaceable>; </optional>
+ <optional> recursive-clients <replaceable>number</replaceable>; </optional>
+ <optional> tcp-clients <replaceable>number</replaceable>; </optional>
+ <optional> clients-per-query <replaceable>number</replaceable> ; </optional>
+ <optional> max-clients-per-query <replaceable>number</replaceable> ; </optional>
+ <optional> fetches-per-server <replaceable>number</replaceable> <optional><replaceable>(drop | fail)</replaceable></optional>; </optional>
+ <optional> fetch-quota-params <replaceable>number fixedpoint fixedpoint fixedpoint</replaceable> ; </optional>
+ <optional> fetches-per-zone <replaceable>number</replaceable> <optional><replaceable>(drop | fail)</replaceable></optional>; </optional>
+ <optional> notify-rate <replaceable>number</replaceable>; </optional>
+ <optional> startup-notify-rate <replaceable>number</replaceable>; </optional>
+ <optional> serial-query-rate <replaceable>number</replaceable>; </optional>
+ <optional> serial-queries <replaceable>number</replaceable>; </optional>
+ <optional> tcp-listen-queue <replaceable>number</replaceable>; </optional>
+ <optional> transfer-format <replaceable>( one-answer | many-answers )</replaceable>; </optional>
+ <optional> transfer-message-size <replaceable>number</replaceable>; </optional>
+ <optional> transfers-in <replaceable>number</replaceable>; </optional>
+ <optional> transfers-out <replaceable>number</replaceable>; </optional>
+ <optional> transfers-per-ns <replaceable>number</replaceable>; </optional>
+ <optional> transfer-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; </optional>
+ <optional> transfer-source-v6 (<replaceable>ip6_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; </optional>
+ <optional> alt-transfer-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; </optional>
+ <optional> alt-transfer-source-v6 (<replaceable>ip6_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; </optional>
+ <optional> use-alt-transfer-source <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> notify-delay <replaceable>seconds</replaceable> ; </optional>
+ <optional> notify-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; </optional>
+ <optional> notify-source-v6 (<replaceable>ip6_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; </optional>
+ <optional> notify-to-soa <replaceable>yes_or_no</replaceable> ; </optional>
+ <optional> also-notify <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> { ( <replaceable>masters</replaceable> | <replaceable>ip_addr</replaceable>
+ <optional>port <replaceable>ip_port</replaceable></optional> ) <optional>key <replaceable>keyname</replaceable></optional> ; ... }; </optional>
+ <optional> max-ixfr-log-size <replaceable>number</replaceable>; </optional>
+ <optional> max-journal-size <replaceable>size_spec</replaceable>; </optional>
+ <optional> coresize <replaceable>size_spec</replaceable> ; </optional>
+ <optional> datasize <replaceable>size_spec</replaceable> ; </optional>
+ <optional> files <replaceable>size_spec</replaceable> ; </optional>
+ <optional> stacksize <replaceable>size_spec</replaceable> ; </optional>
+ <optional> cleaning-interval <replaceable>number</replaceable>; </optional>
+ <optional> heartbeat-interval <replaceable>number</replaceable>; </optional>
+ <optional> interface-interval <replaceable>number</replaceable>; </optional>
+ <optional> statistics-interval <replaceable>number</replaceable>; </optional>
+ <optional> topology { <replaceable>address_match_list</replaceable> }</optional>;
+ <optional> sortlist { <replaceable>address_match_list</replaceable> }</optional>;
+ <optional> rrset-order { <replaceable>order_spec</replaceable> ; <optional> <replaceable>order_spec</replaceable> ; ... </optional> </optional> };
+ <optional> lame-ttl <replaceable>number</replaceable>; </optional>
+ <optional> max-ncache-ttl <replaceable>number</replaceable>; </optional>
+ <optional> max-cache-ttl <replaceable>number</replaceable>; </optional>
+ <optional> max-zone-ttl ( <constant>unlimited</constant> | <replaceable>number</replaceable> ; </optional>
+ <optional> serial-update-method <constant>increment</constant>|<constant>unixtime</constant>|<constant>date</constant>; </optional>
+ <optional> servfail-ttl <replaceable>number</replaceable>; </optional>
+ <optional> sig-validity-interval <replaceable>number</replaceable> <optional><replaceable>number</replaceable></optional> ; </optional>
+ <optional> sig-signing-nodes <replaceable>number</replaceable> ; </optional>
+ <optional> sig-signing-signatures <replaceable>number</replaceable> ; </optional>
+ <optional> sig-signing-type <replaceable>number</replaceable> ; </optional>
+ <optional> min-roots <replaceable>number</replaceable>; </optional>
+ <optional> use-ixfr <replaceable>yes_or_no</replaceable> ; </optional>
+ <optional> provide-ixfr <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> request-ixfr <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> request-expire <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> treat-cr-as-space <replaceable>yes_or_no</replaceable> ; </optional>
+ <optional> min-refresh-time <replaceable>number</replaceable> ; </optional>
+ <optional> max-refresh-time <replaceable>number</replaceable> ; </optional>
+ <optional> min-retry-time <replaceable>number</replaceable> ; </optional>
+ <optional> max-retry-time <replaceable>number</replaceable> ; </optional>
+ <optional> nta-lifetime <replaceable>duration</replaceable> ; </optional>
+ <optional> nta-recheck <replaceable>duration</replaceable> ; </optional>
+ <optional> port <replaceable>ip_port</replaceable>; </optional>
+ <optional> dscp <replaceable>ip_dscp</replaceable></optional> ;
+ <optional> additional-from-auth <replaceable>yes_or_no</replaceable> ; </optional>
+ <optional> additional-from-cache <replaceable>yes_or_no</replaceable> ; </optional>
+ <optional> random-device <replaceable>path_name</replaceable> ; </optional>
+ <optional> max-cache-size <replaceable>size_or_percent</replaceable> ; </optional>
+ <optional> match-mapped-addresses <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> filter-aaaa-on-v4 ( <replaceable>yes_or_no</replaceable> | <replaceable>break-dnssec</replaceable> ); </optional>
+ <optional> filter-aaaa-on-v6 ( <replaceable>yes_or_no</replaceable> | <replaceable>break-dnssec</replaceable> ); </optional>
+ <optional> filter-aaaa { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> dns64 <replaceable>ipv6-prefix</replaceable> {
+ <optional> clients { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> mapped { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> exclude { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> suffix <replaceable>IPv6-address</replaceable>; </optional>
+ <optional> recursive-only <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> break-dnssec <replaceable>yes_or_no</replaceable>; </optional>
+ }; </optional>;
+ <optional> dns64-server <replaceable>name</replaceable> </optional>
+ <optional> dns64-contact <replaceable>name</replaceable> </optional>
+ <optional> preferred-glue ( <replaceable>A</replaceable> | <replaceable>AAAA</replaceable> | <replaceable>NONE</replaceable> ); </optional>
+ <optional> edns-udp-size <replaceable>number</replaceable>; </optional>
+ <optional> max-udp-size <replaceable>number</replaceable>; </optional>
+ <optional> max-rsa-exponent-size <replaceable>number</replaceable>; </optional>
+ <optional> root-delegation-only <optional> exclude { <replaceable>namelist</replaceable> } </optional> ; </optional>
+ <optional> querylog <replaceable>yes_or_no</replaceable> ; </optional>
+ <optional> disable-algorithms <replaceable>domain</replaceable> { <replaceable>algorithm</replaceable>;
+ <optional> <replaceable>algorithm</replaceable>; </optional> }; </optional>
+ <optional> disable-ds-digests <replaceable>domain</replaceable> { <replaceable>digest_type</replaceable>;
+ <optional> <replaceable>digest_type</replaceable>; </optional> }; </optional>
+ <optional> acache-enable <replaceable>yes_or_no</replaceable> ; </optional>
+ <optional> acache-cleaning-interval <replaceable>number</replaceable>; </optional>
+ <optional> max-acache-size <replaceable>size_spec</replaceable> ; </optional>
+ <optional> max-recursion-depth <replaceable>number</replaceable> ; </optional>
+ <optional> max-recursion-queries <replaceable>number</replaceable> ; </optional>
+ <optional> masterfile-format
+ (<constant>text</constant>|<constant>raw</constant>|<constant>map</constant>) ; </optional>
+ <optional> masterfile-style
+ (<constant>relative</constant>|<constant>full</constant>) ; </optional>
+ <optional> empty-server <replaceable>name</replaceable> ; </optional>
+ <optional> empty-contact <replaceable>name</replaceable> ; </optional>
+ <optional> empty-zones-enable <replaceable>yes_or_no</replaceable> ; </optional>
+ <optional> disable-empty-zone <replaceable>zone_name</replaceable> ; </optional>
+ <optional> zero-no-soa-ttl <replaceable>yes_or_no</replaceable> ; </optional>
+ <optional> zero-no-soa-ttl-cache <replaceable>yes_or_no</replaceable> ; </optional>
+ <optional> resolver-query-timeout <replaceable>number</replaceable> ; </optional>
+ <optional> deny-answer-addresses { <replaceable>address_match_list</replaceable> } <optional> except-from { <replaceable>namelist</replaceable> } </optional>;</optional>
+ <optional> deny-answer-aliases { <replaceable>namelist</replaceable> } <optional> except-from { <replaceable>namelist</replaceable> } </optional>;</optional>
+ <optional> prefetch <replaceable>number</replaceable> <optional><replaceable>number</replaceable></optional> ; </optional>
+
+ <optional> rate-limit {
+ <optional> responses-per-second <replaceable>number</replaceable> ; </optional>
+ <optional> referrals-per-second <replaceable>number</replaceable> ; </optional>
+ <optional> nodata-per-second <replaceable>number</replaceable> ; </optional>
+ <optional> nxdomains-per-second <replaceable>number</replaceable> ; </optional>
+ <optional> errors-per-second <replaceable>number</replaceable> ; </optional>
+ <optional> all-per-second <replaceable>number</replaceable> ; </optional>
+ <optional> window <replaceable>number</replaceable> ; </optional>
+ <optional> log-only <replaceable>yes_or_no</replaceable> ; </optional>
+ <optional> qps-scale <replaceable>number</replaceable> ; </optional>
+ <optional> ipv4-prefix-length <replaceable>number</replaceable> ; </optional>
+ <optional> ipv6-prefix-length <replaceable>number</replaceable> ; </optional>
+ <optional> slip <replaceable>number</replaceable> ; </optional>
+ <optional> exempt-clients { <replaceable>address_match_list</replaceable> } ; </optional>
+ <optional> max-table-size <replaceable>number</replaceable> ; </optional>
+ <optional> min-table-size <replaceable>number</replaceable> ; </optional>
+ } ; </optional>
+ <optional> response-policy {
+ zone <replaceable>zone_name</replaceable>
+ <optional> policy <replaceable>(given | disabled | passthru | drop |
+ tcp-only | nxdomain | nodata | cname domain</replaceable>) </optional>
+ <optional> recursive-only <replaceable>yes_or_no</replaceable> </optional>
+ <optional> log <replaceable>yes_or_no</replaceable> </optional>
+ <optional> max-policy-ttl <replaceable>number</replaceable> </optional>
+ <optional> min-update-interval <replaceable>number</replaceable> </optional>
+ ; <optional>...</optional>
+ } <optional> recursive-only <replaceable>yes_or_no</replaceable> </optional>
+ <optional> max-policy-ttl <replaceable>number</replaceable> </optional>
+ <optional> min-update-interval <replaceable>number</replaceable> </optional>
+ <optional> break-dnssec <replaceable>yes_or_no</replaceable> </optional>
+ <optional> min-ns-dots <replaceable>number</replaceable> </optional>
+ <optional> nsip-wait-recurse <replaceable>yes_or_no</replaceable> </optional>
+ <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>
</section>
turn off rewrite logging for a particular response policy
zone. By default, all rewrites are logged.
</para>
+
+ <para>
+ Updates to RPZ zones are processed asynchronously; if there
+ is more than one update pending they are bundled together.
+ If an update to a RPZ 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>
</section>
<section xml:id="rrl"><info><title>Response Rate Limiting</title></info>
<itemizedlist>
<listitem>
<para>
+ The Response Policy Zone (RPZ) implementation has been
+ substantially refactored: updates to the RPZ summary
+ database are no longer directly performed by the zone
+ database but by a separate function that is called when
+ a policy zone is updated. This improves both performance
+ and reliability when policy zones receive frequent updates.
+ Summary database updates can be rate-limited by using the
+ <command>min-update-interval</command> option in a
+ <command>response-policy</command> statement. [RT #43449]
+ </para>
+ </listitem>
+ <listitem>
+ <para>
<command>dnstap</command> now stores both the local and remote
addresses for all messages, instead of only the remote address.
The default output format for <command>dnstap-read</command> has
response-padding { <address_match_element>; ... } block-size
<integer>;
response-policy { zone <quoted_string> [ log <boolean> ] [
- max-policy-ttl <integer> ] [ policy ( cname | disabled | drop |
- given | no-op | nodata | nxdomain | passthru | tcp-only
- <quoted_string> ) ] [ recursive-only <boolean> ]; ... } [
- break-dnssec <boolean> ] [ max-policy-ttl <integer> ] [
+ max-policy-ttl <integer> ] [ min-update-interval <integer> ] [
+ policy ( cname | disabled | drop | given | no-op | nodata |
+ nxdomain | passthru | tcp-only <quoted_string> ) ] [
+ recursive-only <boolean> ]; ... } [ break-dnssec <boolean> ] [
+ max-policy-ttl <integer> ] [ min-update-interval <integer> ] [
min-ns-dots <integer> ] [ nsip-wait-recurse <boolean> ] [
qname-wait-recurse <boolean> ] [ recursive-only <boolean> ];
rfc2308-type1 <boolean>; // not yet implemented
response-padding { <address_match_element>; ... } block-size
<integer>;
response-policy { zone <quoted_string> [ log <boolean> ] [
- max-policy-ttl <integer> ] [ policy ( cname | disabled | drop |
- given | no-op | nodata | nxdomain | passthru | tcp-only
- <quoted_string> ) ] [ recursive-only <boolean> ]; ... } [
- break-dnssec <boolean> ] [ max-policy-ttl <integer> ] [
+ max-policy-ttl <integer> ] [ min-update-interval <integer> ] [
+ policy ( cname | disabled | drop | given | no-op | nodata |
+ nxdomain | passthru | tcp-only | <quoted_string> ) ] [
+ recursive-only <boolean> ]; ... } [ break-dnssec <boolean> ] [
+ max-policy-ttl <integer> ] [ min-update-interval <integer> ] [
min-ns-dots <integer> ] [ nsip-wait-recurse <boolean> ] [
qname-wait-recurse <boolean> ] [ recursive-only <boolean> ];
rfc2308-type1 <boolean>; // not yet implemented
* it is dealing with a database that understands response policy zones.
*/
void
-dns_db_rpz_attach(dns_db_t *db, dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num) {
+dns_db_rpz_attach(dns_db_t *db, void *rpzs, isc_uint8_t rpz_num) {
REQUIRE(db->methods->rpz_attach != NULL);
(db->methods->rpz_attach)(db, rpzs, rpz_num);
}
#include <dns/name.h>
#include <dns/rdata.h>
#include <dns/rdataset.h>
-#include <dns/rpz.h>
#include <dns/types.h>
ISC_LANG_BEGINDECLS
dns_dbversion_t *version);
isc_boolean_t (*isdnssec)(dns_db_t *db);
dns_stats_t *(*getrrsetstats)(dns_db_t *db);
- void (*rpz_attach)(dns_db_t *db, dns_rpz_zones_t *rpzs,
- dns_rpz_num_t rpz_num);
+ void (*rpz_attach)(dns_db_t *db, void *rpzs,
+ isc_uint8_t rpz_num);
isc_result_t (*rpz_ready)(dns_db_t *db);
isc_result_t (*findnodeext)(dns_db_t *db, const dns_name_t *name,
isc_boolean_t create,
*/
void
-dns_db_rpz_attach(dns_db_t *db, dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num);
+dns_db_rpz_attach(dns_db_t *db, void *rpzs, isc_uint8_t rpz_num)
+ ISC_DEPRECATED;
/*%<
* Attach the response policy information for a view to a database for a
* zone for the view.
*/
isc_result_t
-dns_db_rpz_ready(dns_db_t *db);
+dns_db_rpz_ready(dns_db_t *db)
+ ISC_DEPRECATED;
/*%<
* Finish loading a response policy zone.
*/
#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_RPZUPDATED (ISC_EVENTCLASS_DNS + 57)
#define DNS_EVENT_FIRSTEVENT (ISC_EVENTCLASS_DNS + 0)
#define DNS_EVENT_LASTEVENT (ISC_EVENTCLASS_DNS + 65535)
#include <isc/lang.h>
#include <isc/refcount.h>
#include <isc/rwlock.h>
+#include <isc/ht.h>
+#include <isc/time.h>
+#include <isc/event.h>
+#include <isc/timer.h>
#include <dns/fixedname.h>
#include <dns/rdata.h>
#define DNS_RPZ_DROP_NAME DNS_RPZ_PREFIX"drop"
#define DNS_RPZ_TCP_ONLY_NAME DNS_RPZ_PREFIX"tcp-only"
-
typedef isc_uint8_t dns_rpz_prefix_t;
typedef enum {
* A single response policy zone.
*/
typedef struct dns_rpz_zone dns_rpz_zone_t;
+typedef struct dns_rpz_zones dns_rpz_zones_t;
+
struct dns_rpz_zone {
- isc_refcount_t refs;
- dns_rpz_num_t num; /* ordinal in list of policy zones */
- dns_name_t origin; /* Policy zone name */
- dns_name_t client_ip; /* DNS_RPZ_CLIENT_IP_ZONE.origin. */
- dns_name_t ip; /* DNS_RPZ_IP_ZONE.origin. */
- dns_name_t nsdname; /* DNS_RPZ_NSDNAME_ZONE.origin */
- dns_name_t nsip; /* DNS_RPZ_NSIP_ZONE.origin. */
- dns_name_t passthru; /* DNS_RPZ_PASSTHRU_NAME. */
- dns_name_t drop; /* DNS_RPZ_DROP_NAME. */
- dns_name_t tcp_only; /* DNS_RPZ_TCP_ONLY_NAME. */
- dns_name_t cname; /* override value for ..._CNAME */
- dns_ttl_t max_policy_ttl;
+ isc_refcount_t refs;
+ dns_rpz_num_t num; /* ordinal in list of policy zones */
+ dns_name_t origin; /* Policy zone name */
+ dns_name_t client_ip; /* DNS_RPZ_CLIENT_IP_ZONE.origin. */
+ dns_name_t ip; /* DNS_RPZ_IP_ZONE.origin. */
+ dns_name_t nsdname; /* DNS_RPZ_NSDNAME_ZONE.origin */
+ dns_name_t nsip; /* DNS_RPZ_NSIP_ZONE.origin. */
+ dns_name_t passthru; /* DNS_RPZ_PASSTHRU_NAME. */
+ dns_name_t drop; /* DNS_RPZ_DROP_NAME. */
+ dns_name_t tcp_only; /* DNS_RPZ_TCP_ONLY_NAME. */
+ dns_name_t cname; /* override value for ..._CNAME */
+ dns_ttl_t max_policy_ttl;
dns_rpz_policy_t policy; /* DNS_RPZ_POLICY_GIVEN or override */
+
+ isc_uint32_t min_update_int;/* minimal interval between updates */
+ isc_ht_t *nodes; /* entries in zone */
+ dns_rpz_zones_t *rpzs; /* owner */
+ isc_time_t lastupdated; /* last time the zone was processed */
+ isc_boolean_t updatepending; /* there is an update pending/waiting */
+ isc_boolean_t updaterunning; /* there is an update running */
+ dns_db_t *db; /* zones database */
+ dns_dbversion_t *dbversion; /* version we will be updating to */
+ dns_db_t *updb; /* zones database we're working on */
+ dns_dbversion_t *updbversion; /* version we're currently working on */
+ dns_dbiterator_t *updbit; /* iterator to use when updating */
+ isc_ht_t *newnodes; /* entries in zone being updated */
+ isc_boolean_t db_registered; /* is the notify event registered? */
+ isc_timer_t *updatetimer;
+ isc_event_t updateevent;
};
/*
/*
* Response policy zones known to a view.
*/
-typedef struct dns_rpz_zones dns_rpz_zones_t;
struct dns_rpz_zones {
dns_rpz_popt_t p;
dns_rpz_zone_t *zones[DNS_RPZ_MAX_ZONES];
dns_rpz_triggers_t total_triggers;
isc_mem_t *mctx;
+ isc_taskmgr_t *taskmgr;
+ isc_timermgr_t *timermgr;
+ isc_task_t *updater;
isc_refcount_t refs;
/*
* One lock for short term read-only search that guarantees the
#define DNS_RPZ_TTL_DEFAULT 5
#define DNS_RPZ_MAX_TTL_DEFAULT DNS_RPZ_TTL_DEFAULT
+#define DNS_RPZ_MINUPDATEINT_DEF 60
/*
* So various response policy zone messages can be turned up or down.
dns_name_t *selfname);
isc_result_t
-dns_rpz_new_zones(dns_rpz_zones_t **rpzsp, isc_mem_t *mctx);
+dns_rpz_new_zones(dns_rpz_zones_t **rpzsp, isc_mem_t *mctx,
+ isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr);
+
+isc_result_t
+dns_rpz_new_zone(dns_rpz_zones_t *rpzs, dns_rpz_zone_t **rpzp);
+
+isc_result_t
+dns_rpz_dbupdate_callback(dns_db_t *db, void *fn_arg);
void
dns_rpz_attach_rpzs(dns_rpz_zones_t *source, dns_rpz_zones_t **target);
isc_result_t
dns_rpz_beginload(dns_rpz_zones_t **load_rpzsp,
- dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num);
+ dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num)
+ ISC_DEPRECATED;
isc_result_t
dns_rpz_ready(dns_rpz_zones_t *rpzs,
- dns_rpz_zones_t **load_rpzsp, dns_rpz_num_t rpz_num);
+ dns_rpz_zones_t **load_rpzsp, dns_rpz_num_t rpz_num)
+ ISC_DEPRECATED;
isc_result_t
dns_rpz_add(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num,
#include <dns/nsec.h>
#include <dns/nsec3.h>
#include <dns/rbt.h>
-#include <dns/rpz.h>
#include <dns/rdata.h>
#include <dns/rdataset.h>
#include <dns/rdatasetiter.h>
#define resign_insert resign_insert64
#define resign_sooner resign_sooner64
#define resigned resigned64
-#define rpz_attach rpz_attach64
-#define rpz_ready rpz_ready64
#define serialize serialize64
#define set_index set_index64
#define set_ttl set_ttl64
dns_rbt_t * tree;
dns_rbt_t * nsec;
dns_rbt_t * nsec3;
- dns_rpz_zones_t *rpzs;
- dns_rpz_num_t rpz_num;
- dns_rpz_zones_t *load_rpzs;
/* Unlocked */
unsigned int quantum;
if (rbtdb->cachestats != NULL)
isc_stats_detach(&rbtdb->cachestats);
- if (rbtdb->load_rpzs != NULL) {
- /*
- * We must be cleaning up after a failed zone loading.
- */
- REQUIRE(rbtdb->rpzs != NULL &&
- rbtdb->rpz_num < rbtdb->rpzs->p.num_zones);
- dns_rpz_detach_rpzs(&rbtdb->load_rpzs);
- }
- if (rbtdb->rpzs != NULL) {
- REQUIRE(rbtdb->rpz_num < rbtdb->rpzs->p.num_zones);
- dns_rpz_detach_rpzs(&rbtdb->rpzs);
- }
-
isc_mem_put(rbtdb->common.mctx, rbtdb->node_locks,
rbtdb->node_lock_count * sizeof(rbtdb_nodelock_t));
isc_rwlock_destroy(&rbtdb->tree_lock);
dns_fixedname_t fname;
dns_name_t *name;
isc_result_t result = ISC_R_UNEXPECTED;
- unsigned int node_has_rpz;
INSIST(!ISC_LINK_LINKED(node, deadlink));
name = dns_fixedname_name(&fname);
dns_rbt_fullnamefromnode(node, name);
- node_has_rpz = node->rpz;
result = dns_rbt_deletenode(rbtdb->tree, node, ISC_FALSE);
- if (result == ISC_R_SUCCESS &&
- rbtdb->rpzs != NULL && node_has_rpz)
- dns_rpz_delete(rbtdb->rpzs, rbtdb->rpz_num, name);
break;
case DNS_RBT_NSEC_HAS_NSEC:
dns_fixedname_init(&fname);
isc_result_totext(result));
}
}
- node_has_rpz = node->rpz;
result = dns_rbt_deletenode(rbtdb->tree, node, ISC_FALSE);
- if (result == ISC_R_SUCCESS &&
- rbtdb->rpzs != NULL && node_has_rpz)
- dns_rpz_delete(rbtdb->rpzs, rbtdb->rpz_num, name);
break;
case DNS_RBT_NSEC_NSEC:
result = dns_rbt_deletenode(rbtdb->nsec, node, ISC_FALSE);
reactivate_node(rbtdb, node, locktype);
- /*
- * Always try to add the policy zone data, because this node might
- * already have been implicitly created by the previous addition of
- * a longer domain. A common example is adding *.example.com
- * (implicitly creating example.com) followed by explicitly adding
- * example.com.
- */
- if (create && rbtdb->rpzs != NULL && tree == rbtdb->tree) {
- dns_fixedname_t fnamef;
- dns_name_t *fname;
-
- dns_fixedname_init(&fnamef);
- fname = dns_fixedname_name(&fnamef);
- dns_rbt_fullnamefromnode(node, fname);
- result = dns_rpz_add(rbtdb->rpzs, rbtdb->rpz_num, fname);
- if (result == ISC_R_SUCCESS)
- node->rpz = 1;
- if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
- /*
- * It is too late to give up, so merely complain.
- */
- isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
- DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
- "dns_rpz_add(): %s",
- isc_result_totext(result));
- }
- }
-
RWUNLOCK(&rbtdb->tree_lock, locktype);
*nodep = (dns_dbnode_t *)node;
return (result);
}
-/*
- * Connect this RBTDB to the response policy zone summary data for the view.
- */
-static void
-rpz_attach(dns_db_t *db, dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num) {
- dns_rbtdb_t * rbtdb;
-
- rbtdb = (dns_rbtdb_t *)db;
- REQUIRE(VALID_RBTDB(rbtdb));
-
- RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
- REQUIRE(rbtdb->rpzs == NULL && rbtdb->rpz_num == DNS_RPZ_INVALID_NUM);
- dns_rpz_attach_rpzs(rpzs, &rbtdb->rpzs);
- rbtdb->rpz_num = rpz_num;
- RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
-}
-
-/*
- * Enable this RBTDB as a response policy zone.
- */
-static isc_result_t
-rpz_ready(dns_db_t *db) {
- dns_rbtdb_t * rbtdb;
- isc_result_t result;
-
- rbtdb = (dns_rbtdb_t *)db;
- REQUIRE(VALID_RBTDB(rbtdb));
-
- RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
- if (rbtdb->rpzs == NULL) {
- INSIST(rbtdb->rpz_num == DNS_RPZ_INVALID_NUM);
- result = ISC_R_SUCCESS;
- } else {
- result = dns_rpz_ready(rbtdb->rpzs, &rbtdb->load_rpzs,
- rbtdb->rpz_num);
- }
- RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
- return (result);
-}
static isc_result_t
cache_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
loadnode(dns_rbtdb_t *rbtdb, const dns_name_t *name, dns_rbtnode_t **nodep,
isc_boolean_t hasnsec)
{
- isc_result_t noderesult, rpzresult, nsecresult, tmpresult;
+ isc_result_t noderesult, nsecresult, tmpresult;
dns_rbtnode_t *nsecnode = NULL, *node = NULL;
noderesult = dns_rbt_addnode(rbtdb->tree, name, &node);
- if (rbtdb->rpzs != NULL &&
- (noderesult == ISC_R_SUCCESS || noderesult == ISC_R_EXISTS)) {
- rpzresult = dns_rpz_add(rbtdb->load_rpzs, rbtdb->rpz_num,
- name);
- if (rpzresult == ISC_R_SUCCESS) {
- node->rpz = 1;
- } else if (noderesult != ISC_R_EXISTS) {
- /*
- * Remove the node we just added above.
- */
- tmpresult = dns_rbt_deletenode(rbtdb->tree, node,
- ISC_FALSE);
- if (tmpresult != ISC_R_SUCCESS)
- isc_log_write(dns_lctx,
- DNS_LOGCATEGORY_DATABASE,
- DNS_LOGMODULE_CACHE,
- ISC_LOG_WARNING,
- "loading_addrdataset: "
- "dns_rbt_deletenode: %s after "
- "dns_rbt_addnode(NSEC): %s",
- isc_result_totext(tmpresult),
- isc_result_totext(ISC_R_SUCCESS));
- noderesult = rpzresult;
- }
- }
if (!hasnsec)
goto done;
if (noderesult == ISC_R_EXISTS) {
}
if (noderesult == ISC_R_SUCCESS) {
- unsigned int node_has_rpz;
/*
* Remove the node we just added above.
*/
- node_has_rpz = node->rpz;
tmpresult = dns_rbt_deletenode(rbtdb->tree, node, ISC_FALSE);
- if (tmpresult == ISC_R_SUCCESS) {
- /*
- * Clean rpz entries added above.
- */
- if (rbtdb->rpzs != NULL && node_has_rpz)
- dns_rpz_delete(rbtdb->load_rpzs,
- rbtdb->rpz_num, name);
- } else {
+ if (tmpresult != ISC_R_SUCCESS) {
isc_log_write(dns_lctx,
DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_CACHE,
RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_write);
- if (rbtdb->rpzs != NULL) {
- isc_result_t result;
-
- result = dns_rpz_beginload(&rbtdb->load_rpzs,
- rbtdb->rpzs, rbtdb->rpz_num);
- if (result != ISC_R_SUCCESS) {
- isc_mem_put(rbtdb->common.mctx, loadctx,
- sizeof(*loadctx));
- return (result);
- }
- }
-
REQUIRE((rbtdb->attributes & (RBTDB_ATTR_LOADED|RBTDB_ATTR_LOADING))
== 0);
rbtdb->attributes |= RBTDB_ATTR_LOADING;
resigned,
isdnssec,
NULL,
- rpz_attach,
- rpz_ready,
+ NULL,
+ NULL,
NULL,
NULL,
NULL,
}
rbtdb->attributes = 0;
rbtdb->task = NULL;
- rbtdb->rpzs = NULL;
- rbtdb->load_rpzs = NULL;
- rbtdb->rpz_num = DNS_RPZ_INVALID_NUM;
/*
* Version Initialization.
#include <isc/rwlock.h>
#include <isc/stdlib.h>
#include <isc/string.h>
+#include <isc/task.h>
#include <isc/util.h>
#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/events.h>
#include <dns/fixedname.h>
#include <dns/log.h>
#include <dns/rdata.h>
#include <dns/rdataset.h>
#include <dns/rdatastruct.h>
+#include <dns/rdatasetiter.h>
#include <dns/result.h>
#include <dns/rbt.h>
#include <dns/rpz.h>
* 5 labels all of which are numbers, and a prefix between 1 and 32.
*/
+/*
+ * Nodes hashtable calculation parameters
+ */
+#define DNS_RPZ_HTSIZE_MAX 24
+#define DNS_RPZ_HTSIZE_DIV 3
+
+/*
+ * Maximum number of nodes to process per quantum
+ */
+#define DNS_RPZ_QUANTUM 1024
+
+static void
+dns_rpz_update_from_db(dns_rpz_zone_t *rpz);
+
+static void
+dns_rpz_update_taskaction(isc_task_t *task, isc_event_t *event);
/*
* Use a private definition of IPv6 addresses because s6_addr32 is not
* The node lacked relevant data,
* but will have it now.
*/
- cur->set.client_ip |= tgt_set->client_ip;
+ cur->set.client_ip |=
+ tgt_set->client_ip;
cur->set.ip |= tgt_set->ip;
cur->set.nsip |= tgt_set->nsip;
set_sum_pair(cur);
* Get ready for a new set of policy zones.
*/
isc_result_t
-dns_rpz_new_zones(dns_rpz_zones_t **rpzsp, isc_mem_t *mctx) {
- dns_rpz_zones_t *new;
+dns_rpz_new_zones(dns_rpz_zones_t **rpzsp, isc_mem_t *mctx,
+ isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr)
+{
+ dns_rpz_zones_t *zones;
isc_result_t result;
REQUIRE(rpzsp != NULL && *rpzsp == NULL);
- *rpzsp = NULL;
+ zones = isc_mem_get(mctx, sizeof(*zones));
+ if (zones == NULL)
+ return (ISC_R_NOMEMORY);
+ memset(zones, 0, sizeof(*zones));
- new = isc_mem_get(mctx, sizeof(*new));
- if (new == NULL)
+ result = isc_rwlock_init(&zones->search_lock, 0, 0);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_rwlock;
+
+ result = isc_mutex_init(&zones->maint_lock);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_mutex;
+
+ result = isc_refcount_init(&zones->refs, 1);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_refcount;
+
+ result = dns_rbt_create(mctx, rpz_node_deleter, mctx, &zones->rbt);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_rbt;
+
+ result = isc_task_create(taskmgr, 0, &zones->updater);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_task;
+
+ isc_mem_attach(mctx, &zones->mctx);
+ zones->timermgr = timermgr;
+ zones->taskmgr = taskmgr;
+
+ *rpzsp = zones;
+ return (ISC_R_SUCCESS);
+
+cleanup_task:
+ dns_rbt_destroy(&zones->rbt);
+
+cleanup_rbt:
+ isc_refcount_decrement(&zones->refs, NULL);
+ isc_refcount_destroy(&zones->refs);
+
+cleanup_refcount:
+ DESTROYLOCK(&zones->maint_lock);
+
+cleanup_mutex:
+ isc_rwlock_destroy(&zones->search_lock);
+
+cleanup_rwlock:
+ isc_mem_put(mctx, zones, sizeof(*zones));
+
+ return (result);
+}
+
+isc_result_t
+dns_rpz_new_zone(dns_rpz_zones_t *rpzs, dns_rpz_zone_t **rpzp) {
+ dns_rpz_zone_t *zone;
+ isc_result_t result;
+
+ REQUIRE(rpzp != NULL && *rpzp == NULL);
+ REQUIRE(rpzs != NULL);
+ if (rpzs->p.num_zones >= DNS_RPZ_MAX_ZONES) {
+ return (ISC_R_NOSPACE);
+ }
+
+ zone = isc_mem_get(rpzs->mctx, sizeof(*zone));
+ if (zone == NULL) {
return (ISC_R_NOMEMORY);
- memset(new, 0, sizeof(*new));
+ }
+
+ memset(zone, 0, sizeof(*zone));
+ result = isc_refcount_init(&zone->refs, 1);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_refcount;
+
+ result = isc_timer_create(rpzs->timermgr, isc_timertype_inactive,
+ NULL, NULL, rpzs->updater,
+ dns_rpz_update_taskaction,
+ zone, &zone->updatetimer);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_timer;
+
+ /*
+ * This will never be used, but costs us nothing and
+ * simplifies update_from_db
+ */
+
+ result = isc_ht_init(&zone->nodes, rpzs->mctx, 1);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_ht;
+
+ dns_name_init(&zone->origin, NULL);
+ dns_name_init(&zone->client_ip, NULL);
+ dns_name_init(&zone->ip, NULL);
+ dns_name_init(&zone->nsdname, NULL);
+ dns_name_init(&zone->nsip, NULL);
+ dns_name_init(&zone->passthru, NULL);
+ dns_name_init(&zone->drop, NULL);
+ dns_name_init(&zone->tcp_only, NULL);
+ dns_name_init(&zone->cname, NULL);
+
+ isc_time_settoepoch(&zone->lastupdated);
+ zone->updatepending = ISC_FALSE;
+ zone->updaterunning = ISC_FALSE;
+ zone->db = NULL;
+ zone->dbversion = NULL;
+ zone->updb = NULL;
+ zone->updbversion = NULL;
+ zone->updbit = NULL;
+ zone->rpzs = rpzs;
+ zone->db_registered = ISC_FALSE;
+
+ zone->num = rpzs->p.num_zones++;
+ rpzs->zones[zone->num] = zone;
+
+ *rpzp = zone;
+
+ return (ISC_R_SUCCESS);
+
+cleanup_ht:
+ isc_timer_detach(&zone->updatetimer);
+
+cleanup_timer:
+ isc_refcount_decrement(&zone->refs, NULL);
+ isc_refcount_destroy(&zone->refs);
+
+cleanup_refcount:
+ isc_mem_put(zone->rpzs->mctx, zone, sizeof(*zone));
+
+ return (result);
+}
+
+isc_result_t
+dns_rpz_dbupdate_callback(dns_db_t *db, void *fn_arg) {
+ dns_rpz_zone_t *zone = (dns_rpz_zone_t *) fn_arg;
+ isc_time_t now;
+ isc_uint64_t tdiff;
+ isc_result_t result = ISC_R_SUCCESS;
+ char dname[DNS_NAME_FORMATSIZE];
+
+ REQUIRE(DNS_DB_VALID(db));
+ REQUIRE(zone != NULL);
+
+ LOCK(&zone->rpzs->maint_lock);
+ REQUIRE(zone->db_registered);
+
+
+ /* New zone came as AXFR */
+ if (zone->db != NULL && zone->db != db) {
+ /* We need to clean up the old DB */
+ if (zone->dbversion != NULL)
+ dns_db_closeversion(zone->db, &zone->dbversion,
+ ISC_FALSE);
+ dns_db_updatenotify_unregister(zone->db,
+ dns_rpz_dbupdate_callback,
+ zone);
+ dns_db_detach(&zone->db);
+ }
+
+ if (zone->db == NULL) {
+ RUNTIME_CHECK(zone->dbversion == NULL);
+ dns_db_attach(db, &zone->db);
+ }
+
+ if (!zone->updatepending && !zone->updaterunning) {
+ zone->updatepending = ISC_TRUE;
+ isc_time_now(&now);
+ tdiff = isc_time_microdiff(&now, &zone->lastupdated) / 1000000;
+ if (tdiff < zone->min_update_int) {
+ isc_uint64_t defer = zone->min_update_int - tdiff;
+ isc_interval_t interval;
+ dns_name_format(&zone->origin, dname,
+ DNS_NAME_FORMATSIZE);
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MASTER, ISC_LOG_INFO,
+ "rpz: %s: new zone version came "
+ "too soon, deferring update for "
+ "%llu seconds", dname, defer);
+ isc_interval_set(&interval, defer, 0);
+ dns_db_currentversion(zone->db, &zone->dbversion);
+ result = isc_timer_reset(zone->updatetimer,
+ isc_timertype_once,
+ NULL, &interval, ISC_TRUE);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ } else {
+ isc_event_t *event;
+
+ dns_db_currentversion(zone->db, &zone->dbversion);
+ ISC_EVENT_INIT(&zone->updateevent,
+ sizeof(zone->updateevent), 0, NULL,
+ DNS_EVENT_RPZUPDATED,
+ dns_rpz_update_taskaction,
+ zone, zone, NULL, NULL);
+ event = &zone->updateevent;
+ isc_task_send(zone->rpzs->updater, &event);
+ }
+ } else {
+ zone->updatepending = ISC_TRUE;
+ dns_name_format(&zone->origin, dname, DNS_NAME_FORMATSIZE);
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MASTER, ISC_LOG_DEBUG(3),
+ "rpz: %s: update already queued or running", dname);
+ if (zone->dbversion != NULL)
+ dns_db_closeversion(zone->db, &zone->dbversion,
+ ISC_FALSE);
+ dns_db_currentversion(zone->db, &zone->dbversion);
+ }
+
+ cleanup:
+ UNLOCK(&zone->rpzs->maint_lock);
+
+ return (result);
+}
+
+static void
+dns_rpz_update_taskaction(isc_task_t *task, isc_event_t *event) {
+ isc_result_t result;
+ dns_rpz_zone_t *zone;
+
+ REQUIRE(event != NULL);
+ REQUIRE(event->ev_arg != NULL);
+
+ UNUSED(task);
+ zone = (dns_rpz_zone_t *) event->ev_arg;
+ LOCK(&zone->rpzs->maint_lock);
+ zone->updatepending = ISC_FALSE;
+ zone->updaterunning = ISC_TRUE;
+ dns_rpz_update_from_db(zone);
+ result = isc_timer_reset(zone->updatetimer, isc_timertype_inactive,
+ NULL, NULL, ISC_TRUE);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ result = isc_time_now(&zone->lastupdated);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ UNLOCK(&zone->rpzs->maint_lock);
+ isc_event_free(&event);
+}
+
+static isc_result_t
+setup_update(dns_rpz_zone_t *rpz) {
+ isc_result_t result;
+ char domain[DNS_NAME_FORMATSIZE];
+ unsigned int nodecount;
+ uint32_t hashsize;
+
+ dns_name_format(&rpz->origin, domain, DNS_NAME_FORMATSIZE);
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MASTER, ISC_LOG_INFO,
+ "rpz: %s: reload start", domain);
+
+ nodecount = dns_db_nodecount(rpz->updb);
+ hashsize = 1;
+ while (nodecount != 0 &&
+ hashsize <= (DNS_RPZ_HTSIZE_MAX + DNS_RPZ_HTSIZE_DIV))
+ {
+ hashsize++;
+ nodecount >>=1;
+ }
+
+ if (hashsize > DNS_RPZ_HTSIZE_DIV)
+ hashsize -= DNS_RPZ_HTSIZE_DIV;
+
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MASTER, ISC_LOG_INFO,
+ "rpz: %s: using hashtable size %d",
+ domain, hashsize);
- result = isc_rwlock_init(&new->search_lock, 0, 0);
+ result = isc_ht_init(&rpz->newnodes, rpz->rpzs->mctx, hashsize);
if (result != ISC_R_SUCCESS) {
- isc_mem_put(mctx, new, sizeof(*new));
- return (result);
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
+ "rpz: %s: failed to initialize hashtable - %s",
+ domain, isc_result_totext(result));
+ goto cleanup;
}
- result = isc_mutex_init(&new->maint_lock);
+ result = dns_db_createiterator(rpz->updb, DNS_DB_NONSEC3, &rpz->updbit);
if (result != ISC_R_SUCCESS) {
- isc_rwlock_destroy(&new->search_lock);
- isc_mem_put(mctx, new, sizeof(*new));
- return (result);
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
+ "rpz: %s: failed to create DB iterator - %s",
+ domain, isc_result_totext(result));
+ goto cleanup;
}
- result = isc_refcount_init(&new->refs, 1);
+ result = dns_dbiterator_first(rpz->updbit);
if (result != ISC_R_SUCCESS) {
- DESTROYLOCK(&new->maint_lock);
- isc_rwlock_destroy(&new->search_lock);
- isc_mem_put(mctx, new, sizeof(*new));
- return (result);
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
+ "rpz: %s: failed to get db iterator - %s",
+ domain, isc_result_totext(result));
+ goto cleanup;
}
- result = dns_rbt_create(mctx, rpz_node_deleter, mctx, &new->rbt);
+ cleanup:
if (result != ISC_R_SUCCESS) {
- isc_refcount_decrement(&new->refs, NULL);
- isc_refcount_destroy(&new->refs);
- DESTROYLOCK(&new->maint_lock);
- isc_rwlock_destroy(&new->search_lock);
- isc_mem_put(mctx, new, sizeof(*new));
- return (result);
+ if (rpz->updbit != NULL)
+ dns_dbiterator_destroy(&rpz->updbit);
+ if (rpz->newnodes != NULL)
+ isc_ht_destroy(&rpz->newnodes);
+ dns_db_closeversion(rpz->updb, &rpz->updbversion, ISC_FALSE);
}
- isc_mem_attach(mctx, &new->mctx);
+ return (result);
+}
- *rpzsp = new;
- return (ISC_R_SUCCESS);
+static void
+finish_update(dns_rpz_zone_t *rpz) {
+ isc_result_t result;
+ isc_ht_t *tmpht = NULL;
+ isc_ht_iter_t *iter = NULL;
+ dns_fixedname_t fname;
+ char dname[DNS_NAME_FORMATSIZE];
+ dns_name_t *name;
+
+ /*
+ * Iterate over old ht with existing nodes deleted to delete
+ * deleted nodes from RPZ
+ */
+ result = isc_ht_iter_create(rpz->nodes, &iter);
+ if (result != ISC_R_SUCCESS) {
+ char domain[DNS_NAME_FORMATSIZE];
+
+ dns_name_format(&rpz->origin, domain, DNS_NAME_FORMATSIZE);
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
+ "rpz: %s: failed to create HT iterator - %s",
+ domain, isc_result_totext(result));
+ goto cleanup;
+ }
+
+ dns_fixedname_init(&fname);
+ name = dns_fixedname_name(&fname);
+
+ for (result = isc_ht_iter_first(iter);
+ result == ISC_R_SUCCESS;
+ result = isc_ht_iter_delcurrent_next(iter))
+ {
+ isc_region_t region;
+ unsigned char *key;
+ size_t keysize;
+
+ isc_ht_iter_currentkey(iter, &key, &keysize);
+ region.base = key;
+ region.length = keysize;
+ dns_name_fromregion(name, ®ion);
+ dns_rpz_delete(rpz->rpzs, rpz->num, name);
+ }
+
+ tmpht = rpz->nodes;
+ rpz->nodes = rpz->newnodes;
+ rpz->newnodes = tmpht;
+
+ LOCK(&rpz->rpzs->maint_lock);
+ rpz->updaterunning = ISC_FALSE;
+ /*
+ * If there's an update pending schedule it
+ */
+ if (rpz->updatepending == ISC_TRUE) {
+ isc_uint64_t defer = rpz->min_update_int;
+ isc_interval_t interval;
+ dns_name_format(&rpz->origin, dname,
+ DNS_NAME_FORMATSIZE);
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MASTER, ISC_LOG_INFO,
+ "rpz: %s: new zone version came "
+ "too soon, deferring update for "
+ "%llu seconds", dname, defer);
+ isc_interval_set(&interval, defer, 0);
+ result = isc_timer_reset(rpz->updatetimer,
+ isc_timertype_once,
+ NULL, &interval, ISC_TRUE);
+ }
+ UNLOCK(&rpz->rpzs->maint_lock);
+
+cleanup:
+ if (iter != NULL)
+ isc_ht_iter_destroy(&iter);
+}
+
+static void
+update_quantum(isc_task_t *task, isc_event_t *event) {
+ isc_result_t result = ISC_R_SUCCESS;
+ dns_dbnode_t *node = NULL;
+ dns_rpz_zone_t *rpz;
+ char domain[DNS_NAME_FORMATSIZE];
+ dns_fixedname_t fixname;
+ dns_name_t *name;
+ int count = 0;
+
+ UNUSED(task);
+
+ REQUIRE(event != NULL);
+ REQUIRE(event->ev_arg != NULL);
+
+ rpz = (dns_rpz_zone_t *) event->ev_arg;
+ isc_event_free(&event);
+
+ REQUIRE(rpz->updbit != NULL);
+ REQUIRE(rpz->newnodes != NULL);
+
+ dns_fixedname_init(&fixname);
+ name = dns_fixedname_name(&fixname);
+
+ dns_name_format(&rpz->origin, domain, DNS_NAME_FORMATSIZE);
+
+ while (result == ISC_R_SUCCESS && count++ < DNS_RPZ_QUANTUM) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ dns_rdatasetiter_t *rdsiter = NULL;
+
+ result = dns_dbiterator_current(rpz->updbit, &node, name);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
+ "rpz: %s: failed to get dbiterator - %s",
+ domain, isc_result_totext(result));
+ dns_db_detachnode(rpz->updb, &node);
+ break;
+ }
+
+ result = dns_db_allrdatasets(rpz->updb, node, rpz->updbversion, 0,
+ &rdsiter);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
+ "rpz: %s: failed to fetch "
+ "rrdatasets - %s",
+ domain, isc_result_totext(result));
+ dns_db_detachnode(rpz->updb, &node);
+ break;
+ }
+
+ result = dns_rdatasetiter_first(rdsiter);
+ dns_rdatasetiter_destroy(&rdsiter);
+ if (result != ISC_R_SUCCESS) { /* empty non-terminal */
+ if (result != ISC_R_NOMORE)
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
+ "rpz: %s: error %s while creating "
+ "rdatasetiter",
+ domain, isc_result_totext(result));
+ dns_db_detachnode(rpz->updb, &node);
+ result = dns_dbiterator_next(rpz->updbit);
+ continue;
+ }
+
+ result = isc_ht_add(rpz->newnodes, name->ndata,
+ name->length, rpz);
+ if (result != ISC_R_SUCCESS) {
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
+ "rpz: %s, adding node %s to HT error %s",
+ domain, namebuf,
+ isc_result_totext(result));
+ dns_db_detachnode(rpz->updb, &node);
+ result = dns_dbiterator_next(rpz->updbit);
+ continue;
+ }
+
+ result = isc_ht_find(rpz->nodes, name->ndata,
+ name->length, NULL);
+ if (result == ISC_R_SUCCESS) {
+ isc_ht_delete(rpz->nodes, name->ndata, name->length);
+ } else { /* not found */
+ result = dns_rpz_add(rpz->rpzs, rpz->num, name);
+ if (result != ISC_R_SUCCESS) {
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MASTER,
+ ISC_LOG_ERROR,
+ "rpz: %s: adding node %s "
+ "to RPZ error %s",
+ domain, namebuf,
+ isc_result_totext(result));
+ } else {
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MASTER,
+ ISC_LOG_DEBUG(3),
+ "rpz: %s: adding node %s",
+ domain, namebuf);
+ }
+ }
+
+ dns_db_detachnode(rpz->updb, &node);
+ result = dns_dbiterator_next(rpz->updbit);
+ }
+
+ if (result == ISC_R_SUCCESS) {
+ isc_event_t *nevent;
+ /*
+ * Pause the iterator so that the DB is not locked
+ */
+ dns_dbiterator_pause(rpz->updbit);
+ /*
+ * We finished a quantum; trigger the next one and return
+ */
+ ISC_EVENT_INIT(&rpz->updateevent,
+ sizeof(rpz->updateevent), 0, NULL,
+ DNS_EVENT_RPZUPDATED,
+ update_quantum,
+ rpz, rpz, NULL, NULL);
+ nevent = &rpz->updateevent;
+ isc_task_send(rpz->rpzs->updater, &nevent);
+ return;
+ } else if (result == ISC_R_NOMORE) {
+ /*
+ * All done.
+ */
+ finish_update(rpz);
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MASTER, ISC_LOG_INFO,
+ "rpz: %s: reload done", domain);
+ }
+
+ /*
+ * If we're here, we've either finished or something went wrong,
+ * so clean up.
+ */
+ if (rpz->updbit != NULL)
+ dns_dbiterator_destroy(&rpz->updbit);
+ if (rpz->newnodes != NULL)
+ isc_ht_destroy(&rpz->newnodes);
+ dns_db_closeversion(rpz->updb, &rpz->updbversion, ISC_FALSE);
+ dns_db_detach(&rpz->updb);
+}
+
+static void
+dns_rpz_update_from_db(dns_rpz_zone_t *rpz) {
+ isc_result_t result;
+ isc_event_t *event;
+
+ REQUIRE(rpz != NULL);
+ REQUIRE(DNS_DB_VALID(rpz->db));
+ REQUIRE(rpz->updb == NULL);
+ REQUIRE(rpz->updbversion == NULL);
+ REQUIRE(rpz->updbit == NULL);
+ REQUIRE(rpz->newnodes == NULL);
+
+ dns_db_attach(rpz->db, &rpz->updb);
+ rpz->updbversion = rpz->dbversion;
+ rpz->dbversion = NULL;
+
+ result = setup_update(rpz);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+
+ event = &rpz->updateevent;
+ ISC_EVENT_INIT(&rpz->updateevent, sizeof(rpz->updateevent),
+ 0, NULL, DNS_EVENT_RPZUPDATED,
+ update_quantum, rpz, rpz, NULL, NULL);
+ isc_task_send(rpz->rpzs->updater, &event);
+ return;
+
+ cleanup:
+ if (rpz->updbit != NULL)
+ dns_dbiterator_destroy(&rpz->updbit);
+ if (rpz->newnodes != NULL)
+ isc_ht_destroy(&rpz->newnodes);
+ dns_db_closeversion(rpz->updb, &rpz->updbversion, ISC_FALSE);
+ dns_db_detach(&rpz->updb);
}
/*
dns_name_free(&rpz->tcp_only, rpzs->mctx);
if (dns_name_dynamic(&rpz->cname))
dns_name_free(&rpz->cname, rpzs->mctx);
+ if (rpz->db_registered)
+ dns_db_updatenotify_unregister(rpz->db,
+ dns_rpz_dbupdate_callback, rpz);
+ if (rpz->dbversion != NULL)
+ dns_db_closeversion(rpz->db, &rpz->dbversion,
+ ISC_FALSE);
+ if (rpz->db)
+ dns_db_detach(&rpz->db);
+ isc_ht_destroy(&rpz->nodes);
+ isc_timer_detach(&rpz->updatetimer);
isc_mem_put(rpzs->mctx, rpz, sizeof(*rpz));
}
DESTROYLOCK(&rpzs->maint_lock);
isc_rwlock_destroy(&rpzs->search_lock);
isc_refcount_destroy(&rpzs->refs);
+ isc_task_destroy(&rpzs->updater);
isc_mem_putanddetach(&rpzs->mctx, rpzs, sizeof(*rpzs));
}
}
/*
- * Create empty summary database to load one zone.
- * The RBTDB write tree lock must be held.
+ * Deprecated and removed.
*/
isc_result_t
dns_rpz_beginload(dns_rpz_zones_t **load_rpzsp,
dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num)
{
- dns_rpz_zones_t *load_rpzs;
- dns_rpz_zone_t *rpz;
- dns_rpz_zbits_t tgt;
- isc_result_t result;
-
- REQUIRE(rpz_num < rpzs->p.num_zones);
- rpz = rpzs->zones[rpz_num];
- REQUIRE(rpz != NULL);
-
- /*
- * When reloading a zone, there are usually records among the summary
- * data for the zone. Some of those records might be deleted by the
- * reloaded zone data. To deal with that case:
- * reload the new zone data into a new blank summary database
- * if the reload fails, discard the new summary database
- * if the new zone data is acceptable, copy the records for the
- * other zones into the new summary CIDR and RBT databases
- * and replace the old summary databases with the new, and
- * correct the triggers and have values for the updated
- * zone.
- *
- * At the first attempt to load a zone, there is no summary data
- * for the zone and so no records that need to be deleted.
- * This is also the most common case of policy zone loading.
- * Most policy zone maintenance should be by incremental changes
- * and so by the addition and deletion of individual records.
- * Detect that case and load records the first time into the
- * operational summary database
- */
- tgt = DNS_RPZ_ZBIT(rpz_num);
- LOCK(&rpzs->maint_lock);
- RWLOCK(&rpzs->search_lock, isc_rwlocktype_write);
- if ((rpzs->load_begun & tgt) == 0) {
- /*
- * There is no existing version of the target zone.
- */
- rpzs->load_begun |= tgt;
- dns_rpz_attach_rpzs(rpzs, load_rpzsp);
- } else {
- /*
- * Setup the new RPZ struct with empty summary trees.
- */
- result = dns_rpz_new_zones(load_rpzsp, rpzs->mctx);
- if (result != ISC_R_SUCCESS)
- return (result);
- load_rpzs = *load_rpzsp;
- /*
- * Initialize some members so that dns_rpz_add() works.
- */
- load_rpzs->p.num_zones = rpzs->p.num_zones;
- memset(&load_rpzs->triggers, 0, sizeof(load_rpzs->triggers));
- load_rpzs->zones[rpz_num] = rpz;
- isc_refcount_increment(&rpz->refs, NULL);
- }
-
- RWUNLOCK(&rpzs->search_lock, isc_rwlocktype_write);
- UNLOCK(&rpzs->maint_lock);
+ UNUSED(load_rpzsp);
+ UNUSED(rpzs);
+ UNUSED(rpz_num);
- return (ISC_R_SUCCESS);
+ return (ISC_R_NOTIMPLEMENTED);
}
/*
- * This function updates "have" bits and also the qname_skip_recurse
- * mask. It must be called when holding a write lock on rpzs->search_lock.
- */
-static void
-fix_triggers(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num) {
- dns_rpz_num_t n;
- dns_rpz_triggers_t old_totals;
- dns_rpz_zbits_t zbit;
- char namebuf[DNS_NAME_FORMATSIZE];
-
- /*
- * rpzs->total_triggers is only used to log a message below.
- */
-
- memmove(&old_totals, &rpzs->total_triggers, sizeof(old_totals));
- memset(&rpzs->total_triggers, 0, sizeof(rpzs->total_triggers));
-
-#define SET_TRIG(n, zbit, type) \
- if (rpzs->triggers[n].type == 0U) { \
- rpzs->have.type &= ~zbit; \
- } else { \
- rpzs->total_triggers.type += rpzs->triggers[n].type; \
- rpzs->have.type |= zbit; \
- }
-
- for (n = 0; n < rpzs->p.num_zones; ++n) {
- zbit = DNS_RPZ_ZBIT(n);
- SET_TRIG(n, zbit, client_ipv4);
- SET_TRIG(n, zbit, client_ipv6);
- SET_TRIG(n, zbit, qname);
- SET_TRIG(n, zbit, ipv4);
- SET_TRIG(n, zbit, ipv6);
- SET_TRIG(n, zbit, nsdname);
- SET_TRIG(n, zbit, nsipv4);
- SET_TRIG(n, zbit, nsipv6);
- }
-
-#undef SET_TRIG
-
- fix_qname_skip_recurse(rpzs);
-
- dns_name_format(&rpzs->zones[rpz_num]->origin,
- namebuf, sizeof(namebuf));
- isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
- DNS_LOGMODULE_RBTDB, DNS_RPZ_INFO_LEVEL,
- "(re)loading policy zone '%s' changed from"
- " %lu to %lu qname, %lu to %lu nsdname,"
- " %lu to %lu IP, %lu to %lu NSIP,"
- " %lu to %lu CLIENTIP entries",
- namebuf,
- (unsigned long) old_totals.qname,
- (unsigned long) rpzs->total_triggers.qname,
- (unsigned long) old_totals.nsdname,
- (unsigned long) rpzs->total_triggers.nsdname,
- (unsigned long) old_totals.ipv4 + old_totals.ipv6,
- (unsigned long) (rpzs->total_triggers.ipv4 +
- rpzs->total_triggers.ipv6),
- (unsigned long) old_totals.nsipv4 + old_totals.nsipv6,
- (unsigned long) (rpzs->total_triggers.nsipv4 +
- rpzs->total_triggers.nsipv6),
- (unsigned long) old_totals.client_ipv4 +
- old_totals.client_ipv6,
- (unsigned long) (rpzs->total_triggers.client_ipv4 +
- rpzs->total_triggers.client_ipv6));
-}
-
-/*
- * Finish loading one zone. This function is called during a commit when
- * a RPZ zone loading is complete. The RBTDB write tree lock must be
- * held.
- *
- * Here, rpzs is a pointer to the view's common rpzs
- * structure. *load_rpzsp is a rpzs structure that is local to the
- * RBTDB, which is used during a single zone's load.
- *
- * During the zone load, i.e., between dns_rpz_beginload() and
- * dns_rpz_ready(), only the zone that is being loaded updates
- * *load_rpzsp. These updates in the summary databases inside load_rpzsp
- * are made only for the rpz_num (and corresponding bit) of that
- * zone. Nothing else reads or writes *load_rpzsp. The view's common
- * rpzs is used during this time for queries.
- *
- * When zone loading is complete and we arrive here, the parts of the
- * summary databases (CIDR and nsdname+qname RBT trees) from the view's
- * common rpzs struct have to be merged into the summary databases of
- * *load_rpzsp, as the summary databases of the view's common rpzs
- * struct may have changed during the time the zone was being loaded.
- *
- * The function below carries out the merge. During the merge, it holds
- * the maint_lock of the view's common rpzs struct so that it is not
- * updated while the merging is taking place.
- *
- * After the merging is carried out, *load_rpzsp contains the most
- * current state of the rpzs structure, i.e., the summary trees contain
- * data for the new zone that was just loaded, as well as all other
- * zones.
- *
- * Pointers to the summary databases of *load_rpzsp (CIDR and
- * nsdname+qname RBT trees) are then swapped into the view's common rpz
- * struct, so that the query path can continue using it. During the
- * swap, the search_lock of the view's common rpz struct is acquired so
- * that queries are paused while this swap occurs.
- *
- * The trigger counts for the new zone are also copied into the view's
- * common rpz struct, and some other summary counts and masks are
- * updated.
+ * Deprecated and removed.
*/
isc_result_t
dns_rpz_ready(dns_rpz_zones_t *rpzs,
dns_rpz_zones_t **load_rpzsp, dns_rpz_num_t rpz_num)
{
- dns_rpz_zones_t *load_rpzs;
- const dns_rpz_cidr_node_t *cnode, *next_cnode, *parent_cnode;
- dns_rpz_cidr_node_t *found;
- dns_rpz_zbits_t new_bit;
- dns_rpz_addr_zbits_t new_ip;
- dns_rbt_t *rbt;
- dns_rbtnodechain_t chain;
- dns_rbtnode_t *nmnode;
- dns_rpz_nm_data_t *nm_data, new_data;
- dns_fixedname_t labelf, originf, namef;
- dns_name_t *label, *origin, *name;
- isc_result_t result;
-
- INSIST(rpzs != NULL);
- LOCK(&rpzs->maint_lock);
- load_rpzs = *load_rpzsp;
- INSIST(load_rpzs != NULL);
-
- if (load_rpzs == rpzs) {
- /*
- * This is a successful initial zone loading, perhaps
- * for a new instance of a view.
- */
- RWLOCK(&rpzs->search_lock, isc_rwlocktype_write);
- fix_triggers(rpzs, rpz_num);
- RWUNLOCK(&rpzs->search_lock, isc_rwlocktype_write);
- UNLOCK(&rpzs->maint_lock);
- dns_rpz_detach_rpzs(load_rpzsp);
- return (ISC_R_SUCCESS);
- }
-
- LOCK(&load_rpzs->maint_lock);
- RWLOCK(&load_rpzs->search_lock, isc_rwlocktype_write);
+ UNUSED(rpzs);
+ UNUSED(load_rpzsp);
+ UNUSED(rpz_num);
- /*
- * Unless there is only one policy zone, copy the other policy zones
- * from the old policy structure to the new summary databases.
- */
- if (rpzs->p.num_zones > 1) {
- new_bit = ~DNS_RPZ_ZBIT(rpz_num);
-
- /*
- * Copy to the radix tree.
- */
- for (cnode = rpzs->cidr; cnode != NULL; cnode = next_cnode) {
- new_ip.ip = cnode->set.ip & new_bit;
- new_ip.client_ip = cnode->set.client_ip & new_bit;
- new_ip.nsip = cnode->set.nsip & new_bit;
- if (new_ip.client_ip != 0 ||
- new_ip.ip != 0 ||
- new_ip.nsip != 0) {
- result = search(load_rpzs,
- &cnode->ip, cnode->prefix,
- &new_ip, ISC_TRUE, &found);
- if (result == ISC_R_NOMEMORY)
- goto unlock_and_detach;
- INSIST(result == ISC_R_SUCCESS);
- }
- /*
- * Do down and to the left as far as possible.
- */
- next_cnode = cnode->child[0];
- if (next_cnode != NULL)
- continue;
- /*
- * Go up until we find a branch to the right where
- * we previously took the branch to the left.
- */
- for (;;) {
- parent_cnode = cnode->parent;
- if (parent_cnode == NULL)
- break;
- if (parent_cnode->child[0] == cnode) {
- next_cnode = parent_cnode->child[1];
- if (next_cnode != NULL)
- break;
- }
- cnode = parent_cnode;
- }
- }
-
- /*
- * Copy to the summary RBT.
- */
- dns_fixedname_init(&namef);
- name = dns_fixedname_name(&namef);
- dns_fixedname_init(&labelf);
- label = dns_fixedname_name(&labelf);
- dns_fixedname_init(&originf);
- origin = dns_fixedname_name(&originf);
- dns_rbtnodechain_init(&chain, NULL);
- result = dns_rbtnodechain_first(&chain, rpzs->rbt, NULL, NULL);
- while (result == DNS_R_NEWORIGIN || result == ISC_R_SUCCESS) {
- result = dns_rbtnodechain_current(&chain, label, origin,
- &nmnode);
- INSIST(result == ISC_R_SUCCESS);
- nm_data = nmnode->data;
- if (nm_data != NULL) {
- new_data.set.qname = (nm_data->set.qname &
- new_bit);
- new_data.set.ns = nm_data->set.ns & new_bit;
- new_data.wild.qname = (nm_data->wild.qname &
- new_bit);
- new_data.wild.ns = nm_data->wild.ns & new_bit;
- if (new_data.set.qname != 0 ||
- new_data.set.ns != 0 ||
- new_data.wild.qname != 0 ||
- new_data.wild.ns != 0) {
- result = dns_name_concatenate(label,
- origin, name, NULL);
- INSIST(result == ISC_R_SUCCESS);
- result = add_nm(load_rpzs, name,
- &new_data);
- if (result != ISC_R_SUCCESS)
- goto unlock_and_detach;
- }
- }
- result = dns_rbtnodechain_next(&chain, NULL, NULL);
- }
- if (result != ISC_R_NOMORE && result != ISC_R_NOTFOUND) {
- isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
- DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
- "dns_rpz_ready(): unexpected %s",
- isc_result_totext(result));
- goto unlock_and_detach;
- }
- }
-
- /*
- * Exchange the summary databases.
- */
- RWLOCK(&rpzs->search_lock, isc_rwlocktype_write);
-
- rpzs->triggers[rpz_num] = load_rpzs->triggers[rpz_num];
- fix_triggers(rpzs, rpz_num);
-
- found = rpzs->cidr;
- rpzs->cidr = load_rpzs->cidr;
- load_rpzs->cidr = found;
-
- rbt = rpzs->rbt;
- rpzs->rbt = load_rpzs->rbt;
- load_rpzs->rbt = rbt;
-
- RWUNLOCK(&rpzs->search_lock, isc_rwlocktype_write);
-
- result = ISC_R_SUCCESS;
-
- unlock_and_detach:
- UNLOCK(&rpzs->maint_lock);
- RWUNLOCK(&load_rpzs->search_lock, isc_rwlocktype_write);
- UNLOCK(&load_rpzs->maint_lock);
- dns_rpz_detach_rpzs(load_rpzsp);
- return (result);
+ return (ISC_R_NOTIMPLEMENTED);
}
/*
REQUIRE(rpzs != NULL && rpz_num < rpzs->p.num_zones);
rpz = rpzs->zones[rpz_num];
REQUIRE(rpz != NULL);
+ RWLOCK(&rpzs->search_lock, isc_rwlocktype_write);
rpz_type = type_from_name(rpz, src_name);
- LOCK(&rpzs->maint_lock);
- RWLOCK(&rpzs->search_lock, isc_rwlocktype_write);
switch (rpz_type) {
case DNS_RPZ_TYPE_QNAME:
case DNS_RPZ_TYPE_BAD:
break;
}
-
RWUNLOCK(&rpzs->search_lock, isc_rwlocktype_write);
- UNLOCK(&rpzs->maint_lock);
+
return (result);
}
tgt->set.nsip &= ~tgt_set.nsip;
set_sum_pair(tgt);
- adj_trigger_cnt(rpzs, rpz_num, rpz_type, &tgt_ip, tgt_prefix, ISC_FALSE);
+ adj_trigger_cnt(rpzs, rpz_num, rpz_type, &tgt_ip, tgt_prefix,
+ ISC_FALSE);
/*
* We might need to delete 2 nodes.
result = dns_rbt_deletenode(rpzs->rbt, nmnode, ISC_FALSE);
if (result != ISC_R_SUCCESS) {
/*
- * bin/tests/system/rpz/tests.sh looks for "rpz.*failed".
+ * bin/tests/system/rpz/tests.sh looks for
+ * "rpz.*failed".
*/
dns_name_format(src_name, namebuf, sizeof(namebuf));
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
rpz = rpzs->zones[rpz_num];
REQUIRE(rpz != NULL);
- rpz_type = type_from_name(rpz, src_name);
-
- LOCK(&rpzs->maint_lock);
RWLOCK(&rpzs->search_lock, isc_rwlocktype_write);
+ rpz_type = type_from_name(rpz, src_name);
+
switch (rpz_type) {
case DNS_RPZ_TYPE_QNAME:
case DNS_RPZ_TYPE_NSDNAME:
}
RWUNLOCK(&rpzs->search_lock, isc_rwlocktype_write);
- UNLOCK(&rpzs->maint_lock);
}
/*
dns_rpz_have_t have;
int i;
- LOCK(&rpzs->maint_lock);
+ RWLOCK(&rpzs->search_lock, isc_rwlocktype_read);
have = rpzs->have;
- UNLOCK(&rpzs->maint_lock);
+ RWUNLOCK(&rpzs->search_lock, isc_rwlocktype_read);
/*
* Convert IP address to CIDR tree key.
dns_rpz_add
dns_rpz_attach_rpzs
dns_rpz_beginload
+dns_rpz_dbupdate_callback
dns_rpz_decode_cname
dns_rpz_delete
dns_rpz_detach_rpzs
dns_rpz_find_ip
dns_rpz_find_name
+dns_rpz_new_zone
dns_rpz_new_zones
dns_rpz_policy2str
dns_rpz_ready
*/
void
dns_zone_rpz_enable_db(dns_zone_t *zone, dns_db_t *db) {
- if (zone->rpz_num != DNS_RPZ_INVALID_NUM) {
- REQUIRE(zone->rpzs != NULL);
- dns_db_rpz_attach(db, zone->rpzs, zone->rpz_num);
- }
+ isc_result_t result;
+ if (zone->rpz_num == DNS_RPZ_INVALID_NUM)
+ return;
+ REQUIRE(zone->rpzs != NULL);
+ zone->rpzs->zones[zone->rpz_num]->db_registered = ISC_TRUE;
+ result = dns_db_updatenotify_register(db,
+ dns_rpz_dbupdate_callback,
+ zone->rpzs->zones[zone->rpz_num]);
+ REQUIRE(result == ISC_R_SUCCESS);
}
void
if (result != ISC_R_SUCCESS)
goto cleanup;
} else {
- result = dns_db_rpz_ready(db);
- if (result != ISC_R_SUCCESS)
- goto cleanup;
zone_attachdb(zone, db);
ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
DNS_ZONE_SETFLAG(zone,
if (inline_raw(zone))
REQUIRE(LOCKED_ZONE(zone->secure));
- result = dns_db_rpz_ready(db);
- if (result != ISC_R_SUCCESS)
- return (result);
-
result = zone_get_from_db(zone, db, &nscount, &soacount,
NULL, NULL, NULL, NULL, NULL, NULL);
if (result == ISC_R_SUCCESS) {
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;
+ memcmp(key, node->key, keysize) == 0)
+ {
+ if (valuep != NULL)
+ *valuep = node->value;
return (ISC_R_SUCCESS);
}
node = node->next;
/*%
* Find a node matching 'key'/'keysize' in hashtable 'ht';
- * if found, set 'value' to its value
+ * if found, set '*valuep' to its value. (If 'valuep' is NULL,
+ * then simply return SUCCESS or NOTFOUND to indicate whether the
+ * key exists in the hashtable.)
*
* Requires:
* \li 'ht' is a valid hashtable
* zone <string> [ policy (given|disabled|passthru|drop|tcp-only|
* nxdomain|nodata|cname <domain> ) ]
* [ recursive-only yes|no ] [ log yes|no ]
- * [ max-policy-ttl number ] ;
+ * [ max-policy-ttl number ] [ min-update-interval number ] ;
* } [ recursive-only yes|no ] [ max-policy-ttl number ]
+ * [ min-update-interval number ]
* [ break-dnssec yes|no ] [ min-ns-dots number ]
* [ qname-wait-recurse yes|no ] ;
*/
{ "zone name", &cfg_type_rpz_zone, 0 },
{ "log", &cfg_type_boolean, 0 },
{ "max-policy-ttl", &cfg_type_uint32, 0 },
+ { "min-update-interval", &cfg_type_uint32, 0 },
{ "policy", &cfg_type_rpz_policy, 0 },
{ "recursive-only", &cfg_type_boolean, 0 },
{ NULL, NULL, 0 }
{ "zone list", &cfg_type_rpz_list, 0 },
{ "break-dnssec", &cfg_type_boolean, 0 },
{ "max-policy-ttl", &cfg_type_uint32, 0 },
+ { "min-update-interval", &cfg_type_uint32, 0 },
{ "min-ns-dots", &cfg_type_uint32, 0 },
{ "nsip-wait-recurse", &cfg_type_boolean, 0 },
{ "qname-wait-recurse", &cfg_type_boolean, 0 },