dns_rdataset_disassociate(*rdatasetp);
}
+static void
+rpz_match_clear(dns_rpz_st_t *st)
+{
+ rpz_clean(&st->m.zone, &st->m.db, &st->m.node, &st->m.rdataset);
+ st->m.version = NULL;
+}
+
static inline isc_result_t
rpz_ready(ns_client_t *client, dns_zone_t **zonep, dns_db_t **dbp,
dns_dbnode_t **nodep, dns_rdataset_t **rdatasetp)
rpz_st_clear(ns_client_t *client) {
dns_rpz_st_t *st = client->query.rpz_st;
- rpz_clean(&st->m.zone, &st->m.db, &st->m.node, NULL);
- st->m.version = NULL;
if (st->m.rdataset != NULL)
query_putrdataset(client, &st->m.rdataset);
+ rpz_match_clear(st);
rpz_clean(NULL, &st->r.db, NULL, NULL);
if (st->r.ns_rdataset != NULL)
for (rpz = ISC_LIST_HEAD(client->view->rpz_zones);
rpz != NULL;
rpz = ISC_LIST_NEXT(rpz, link)) {
+ if (!RECURSIONOK(client) && rpz->recursive_only)
+ continue;
+
/*
* Do not check policy zones that cannot replace a policy
* already known to match.
* hit, if any. Note the domain name and quality of the
* best hit.
*/
- (void)dns_db_rpz_findips(rpz, rpz_type, zone, db, version,
- rdataset, st,
- client->query.rpz_st->qname);
+ dns_db_rpz_findips(rpz, rpz_type, zone, db, version,
+ rdataset, st, client->query.rpz_st->qname);
rpz_clean(&zone, &db, NULL, NULL);
}
return (ISC_R_SUCCESS);
*/
static isc_result_t
rpz_find(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qnamef,
- dns_name_t *sname, dns_rpz_type_t rpz_type, dns_zone_t **zonep,
- dns_db_t **dbp, dns_dbversion_t **versionp,
+ dns_name_t *sname, dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
+ dns_zone_t **zonep, dns_db_t **dbp, dns_dbversion_t **versionp,
dns_dbnode_t **nodep, dns_rdataset_t **rdatasetp,
dns_rpz_policy_t *policyp)
{
if (result != ISC_R_SUCCESS) {
dns_db_detachnode(*dbp, nodep);
rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, rpz_type,
- qnamef, "allrdatasets()", result);
+ qnamef, "allrdatasets() ", result);
*policyp = DNS_RPZ_POLICY_ERROR;
return (DNS_R_SERVFAIL);
}
if (result != ISC_R_SUCCESS) {
if (result != ISC_R_NOMORE) {
rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL,
- rpz_type, qnamef, "rdatasetiter",
+ rpz_type, qnamef, "rdatasetiter ",
result);
*policyp = DNS_RPZ_POLICY_ERROR;
return (DNS_R_SERVFAIL);
if ((*rdatasetp)->type != dns_rdatatype_cname) {
policy = DNS_RPZ_POLICY_RECORD;
} else {
- policy = dns_rpz_decode_cname(*rdatasetp, sname);
+ policy = dns_rpz_decode_cname(rpz, *rdatasetp, sname);
if ((policy == DNS_RPZ_POLICY_RECORD ||
policy == DNS_RPZ_POLICY_WILDCNAME) &&
qtype != dns_rdatatype_cname &&
for (rpz = ISC_LIST_HEAD(client->view->rpz_zones);
rpz != NULL;
rpz = ISC_LIST_NEXT(rpz, link)) {
+ if (!RECURSIONOK(client) && rpz->recursive_only)
+ continue;
+
/*
* Do not check policy zones that cannot replace a policy
* already known to match.
}
/*
- * See if the policy record exists.
+ * See if the policy record exists and get its policy.
*/
- result = rpz_find(client, qtype, rpz_qname, qname, rpz_type,
- &zone, &db, &version, &node, rdatasetp,
- &policy);
+ result = rpz_find(client, qtype, rpz_qname, qname, rpz,
+ rpz_type, &zone, &db, &version, &node,
+ rdatasetp, &policy);
switch (result) {
case DNS_R_NXDOMAIN:
case DNS_R_EMPTYNAME:
continue;
}
- rpz_clean(&st->m.zone, &st->m.db, &st->m.node,
- &st->m.rdataset);
+ rpz_match_clear(st);
st->m.rpz = rpz;
st->m.type = rpz_type;
st->m.prefix = 0;
trdataset = st->m.rdataset;
st->m.rdataset = *rdatasetp;
*rdatasetp = trdataset;
- st->m.ttl = st->m.rdataset->ttl;
+ st->m.ttl = ISC_MIN(st->m.rdataset->ttl,
+ rpz->max_policy_ttl);
} else {
- st->m.ttl = DNS_RPZ_TTL_DEFAULT;
+ st->m.ttl = ISC_MIN(DNS_RPZ_TTL_DEFAULT,
+ rpz->max_policy_ttl);
}
st->m.node = node;
node = NULL;
case DNS_R_BROKENCHAIN:
rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL3, DNS_RPZ_TYPE_QNAME,
client->query.qname,
- "stop on qresult in rpz_rewrite()",
+ "stop on qresult in rpz_rewrite() ",
qresult);
return (ISC_R_SUCCESS);
default:
rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, DNS_RPZ_TYPE_QNAME,
client->query.qname,
- "stop on unrecognized qresult in rpz_rewrite()",
+ "stop on unrecognized qresult in rpz_rewrite() ",
qresult);
return (ISC_R_SUCCESS);
}
if (st->m.policy == DNS_RPZ_POLICY_MISS ||
st->m.policy == DNS_RPZ_POLICY_PASSTHRU ||
st->m.policy == DNS_RPZ_POLICY_ERROR) {
- if (st->m.policy == DNS_RPZ_POLICY_PASSTHRU)
+ if (st->m.policy == DNS_RPZ_POLICY_PASSTHRU &&
+ result != DNS_R_DELEGATION)
rpz_log_rewrite(client, "", st->m.policy, st->m.type,
st->qname);
- rpz_clean(&st->m.zone, &st->m.db, &st->m.node, &st->m.rdataset);
+ rpz_match_clear(st);
}
if (st->m.policy == DNS_RPZ_POLICY_ERROR) {
st->m.type = DNS_RPZ_TYPE_BAD;
return (result);
}
+/*
+ * See if response policy zone rewriting is allowed a lack of interest
+ * by the client in DNSSEC or a lack of signatures.
+ */
+static isc_boolean_t
+rpz_ck_dnssec(ns_client_t *client, isc_result_t result,
+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
+{
+ dns_fixedname_t fixed;
+ dns_name_t *found;
+ dns_rdataset_t trdataset;
+ dns_rdatatype_t type;
+
+ if (client->view->rpz_break_dnssec)
+ return (ISC_TRUE);
+ /*
+ * sigrdataset == NULL if and only !WANTDNSSEC(client)
+ */
+ if (sigrdataset == NULL)
+ return (ISC_TRUE);
+ if (dns_rdataset_isassociated(sigrdataset))
+ return (ISC_FALSE);
+
+ /*
+ * We are happy to rewrite nothing.
+ */
+ if (rdataset == NULL || !dns_rdataset_isassociated(rdataset))
+ return (ISC_TRUE);
+ /*
+ * Do not rewrite if there is any sign of signatures.
+ */
+ if (rdataset->type == dns_rdatatype_nsec ||
+ rdataset->type == dns_rdatatype_nsec3 ||
+ rdataset->type == dns_rdatatype_rrsig)
+ return (ISC_FALSE);
+
+ /*
+ * Look for a signature in a negative cache rdataset.
+ */
+ if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) == 0)
+ return (ISC_TRUE);
+ dns_fixedname_init(&fixed);
+ found = dns_fixedname_name(&fixed);
+ dns_rdataset_init(&trdataset);
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset)) {
+ dns_ncache_current(rdataset, found, &trdataset);
+ type = trdataset.type;
+ dns_rdataset_disassociate(&trdataset);
+ if (type == dns_rdatatype_nsec ||
+ type == dns_rdatatype_nsec3 ||
+ type == dns_rdatatype_rrsig)
+ return (ISC_FALSE);
+ }
+ return (ISC_TRUE);
+}
+
/*
* Add a CNAME to the query response, including translating foo.evil.com and
* *.evil.com CNAME *.example.com
* Turn off DNSSEC because the results of a
* response policy zone cannot verify.
*/
- client->attributes &= ~NS_CLIENTATTR_WANTDNSSEC;
+ client->attributes &= ~(NS_CLIENTATTR_WANTDNSSEC |
+ DNS_MESSAGEFLAG_AD);
return (ISC_R_SUCCESS);
}
CTRACE("query_find: resume");
if (!ISC_LIST_EMPTY(client->view->rpz_zones) &&
- RECURSIONOK(client) && !RECURSING(client) &&
- (!WANTDNSSEC(client) || sigrdataset == NULL ||
- !dns_rdataset_isassociated(sigrdataset)) &&
+ (RECURSIONOK(client) || !client->view->rpz_recursive_only) &&
+ rpz_ck_dnssec(client, result, rdataset, sigrdataset) &&
+ !RECURSING(client) &&
(client->query.rpz_st == NULL ||
(client->query.rpz_st->state & DNS_RPZ_REWRITTEN) == 0) &&
!dns_name_equal(client->query.qname, dns_rootname)) {
break;
case DNS_RPZ_POLICY_RECORD:
result = rpz_st->m.result;
- if (type == dns_rdatatype_any &&
- result != DNS_R_CNAME &&
- dns_rdataset_isassociated(rdataset))
- dns_rdataset_disassociate(rdataset);
+ if (qtype == dns_rdatatype_any &&
+ result != DNS_R_CNAME) {
+ /*
+ * We will add all of the rdatasets of
+ * the node by iterating, setting the
+ * TTL then.
+ */
+ if (dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+ } else {
+ /*
+ * We will add this rdataset.
+ */
+ rdataset->ttl = ISC_MIN(rdataset->ttl,
+ rpz_st->m.ttl);
+ }
break;
case DNS_RPZ_POLICY_WILDCNAME:
result = dns_rdataset_first(rdataset);
* Turn off DNSSEC because the results of a
* response policy zone cannot verify.
*/
- client->attributes &= ~NS_CLIENTATTR_WANTDNSSEC;
+ client->attributes &= ~(NS_CLIENTATTR_WANTDNSSEC |
+ DNS_MESSAGEFLAG_AD);
query_putrdataset(client, &sigrdataset);
is_zone = ISC_TRUE;
rpz_log_rewrite(client, "", rpz_st->m.policy,
noqname = rdataset;
else
noqname = NULL;
+ rpz_st = client->query.rpz_st;
+ if (rpz_st != NULL)
+ rdataset->ttl = ISC_MIN(rdataset->ttl,
+ rpz_st->m.ttl);
query_addrrset(client,
fname != NULL ? &fname : &tname,
&rdataset, NULL,
*/
rpz_st = client->query.rpz_st;
if (rpz_st != NULL && (rpz_st->state & DNS_RPZ_RECURSING) == 0) {
- rpz_clean(&rpz_st->m.zone, &rpz_st->m.db, &rpz_st->m.node,
- &rpz_st->m.rdataset);
+ rpz_match_clear(rpz_st);
rpz_st->state &= ~DNS_RPZ_DONE_QNAME;
}
if (rdataset != NULL)
}
static isc_result_t
-configure_rpz(dns_view_t *view, const cfg_listelt_t *element) {
- const cfg_obj_t *rpz_obj, *policy_obj;
+configure_rpz(dns_view_t *view, const cfg_listelt_t *element,
+ isc_boolean_t recursive_only_def, dns_ttl_t ttl_def)
+{
+ const cfg_obj_t *rpz_obj, *policy_obj, *obj;
const char *str;
- dns_fixedname_t fixed;
- dns_name_t *origin;
dns_rpz_zone_t *old, *new;
dns_zone_t *zone = NULL;
isc_result_t result;
- unsigned int l1, l2;
new = isc_mem_get(view->mctx, sizeof(*new));
if (new == NULL) {
}
memset(new, 0, sizeof(*new));
- dns_name_init(&new->nsdname, NULL);
dns_name_init(&new->origin, NULL);
+ dns_name_init(&new->nsdname, NULL);
dns_name_init(&new->cname, NULL);
+ dns_name_init(&new->passthru, NULL);
ISC_LIST_INITANDAPPEND(view->rpz_zones, new, link);
rpz_obj = cfg_listelt_value(element);
if (cfg_obj_isvoid(policy_obj)) {
new->policy = DNS_RPZ_POLICY_GIVEN;
} else {
- str = cfg_obj_asstring(policy_obj);
+ str = cfg_obj_asstring(cfg_tuple_get(policy_obj,
+ "policy name"));
new->policy = dns_rpz_str2policy(str);
INSIST(new->policy != DNS_RPZ_POLICY_ERROR);
}
- dns_fixedname_init(&fixed);
- origin = dns_fixedname_name(&fixed);
- str = cfg_obj_asstring(cfg_tuple_get(rpz_obj, "name"));
- result = dns_name_fromstring(origin, str, DNS_NAME_DOWNCASE, NULL);
+ obj = cfg_tuple_get(rpz_obj, "recursive-only");
+ if (cfg_obj_isvoid(obj)) {
+ new->recursive_only = recursive_only_def;
+ } else {
+ new->recursive_only = cfg_obj_asboolean(obj);
+ }
+ if (!new->recursive_only)
+ view->rpz_recursive_only = ISC_FALSE;
+
+ obj = cfg_tuple_get(rpz_obj, "max-policy-ttl");
+ if (cfg_obj_isuint32(obj)) {
+ new->max_policy_ttl = cfg_obj_asuint32(obj);
+ } else {
+ new->max_policy_ttl = ttl_def;
+ }
+
+ str = cfg_obj_asstring(cfg_tuple_get(rpz_obj, "zone name"));
+ result = dns_name_fromstring(&new->origin, str, DNS_NAME_DOWNCASE,
+ view->mctx);
if (result != ISC_R_SUCCESS) {
cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
"invalid zone '%s'", str);
}
result = dns_name_fromstring2(&new->nsdname, DNS_RPZ_NSDNAME_ZONE,
- origin, DNS_NAME_DOWNCASE, view->mctx);
+ &new->origin, DNS_NAME_DOWNCASE,
+ view->mctx);
if (result != ISC_R_SUCCESS) {
cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
"invalid zone '%s'", str);
goto cleanup;
}
- /*
- * The origin is part of 'nsdname' so we don't need to keep it
- * seperately.
- */
- l1 = dns_name_countlabels(&new->nsdname);
- l2 = dns_name_countlabels(origin);
- dns_name_getlabelsequence(&new->nsdname, l1 - l2, l2, &new->origin);
+ result = dns_name_fromstring(&new->passthru, DNS_RPZ_PASSTHRU_ZONE,
+ DNS_NAME_DOWNCASE, view->mctx);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
+ "invalid zone '%s'", str);
+ goto cleanup;
+ }
- /*
- * Are we configured to with the reponse policy zone?
- */
result = dns_view_findzone(view, &new->origin, &zone);
if (result != ISC_R_SUCCESS) {
cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
"unknown zone '%s'", str);
goto cleanup;
}
-
if (dns_zone_gettype(zone) != dns_zone_master &&
dns_zone_gettype(zone) != dns_zone_slave) {
cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
}
if (new->policy == DNS_RPZ_POLICY_CNAME) {
- str = cfg_obj_asstring(cfg_tuple_get(rpz_obj, "cname"));
- result = dns_name_fromstring(&new->cname, str, 0, view->mctx);
+ str = cfg_obj_asstring(cfg_tuple_get(policy_obj, "cname"));
+ result = dns_name_fromstring(&new->cname, str,
+ DNS_NAME_DOWNCASE, view->mctx);
if (result != ISC_R_SUCCESS) {
cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
"invalid cname '%s'", str);
* Make the list of response policy zone names for views that
* are used for real lookups and so care about hints.
*/
- zonelist = NULL;
- if (view->rdclass == dns_rdataclass_in && need_hints) {
- obj = NULL;
- result = ns_config_get(maps, "response-policy", &obj);
- if (result == ISC_R_SUCCESS)
- cfg_map_get(obj, "zone", &zonelist);
- }
+ obj = NULL;
+ if (view->rdclass == dns_rdataclass_in && need_hints &&
+ ns_config_get(maps, "response-policy", &obj) == ISC_R_SUCCESS) {
+ const cfg_obj_t *recursive_only_obj;
+ const cfg_obj_t *break_dnssec_obj, *ttl_obj;
+ isc_boolean_t recursive_only_def;
+ dns_ttl_t ttl_def;
+
+ recursive_only_obj = cfg_tuple_get(obj, "recursive-only");
+ if (!cfg_obj_isvoid(recursive_only_obj) &&
+ !cfg_obj_asboolean(recursive_only_obj))
+ recursive_only_def = ISC_FALSE;
+ else
+ recursive_only_def = ISC_TRUE;
- if (zonelist != NULL) {
- for (element = cfg_list_first(zonelist);
+ break_dnssec_obj = cfg_tuple_get(obj, "break-dnssec");
+ if (!cfg_obj_isvoid(break_dnssec_obj) &&
+ cfg_obj_asboolean(break_dnssec_obj))
+ view->rpz_break_dnssec = ISC_TRUE;
+ else
+ view->rpz_break_dnssec = ISC_FALSE;
+
+ ttl_obj = cfg_tuple_get(obj, "max-policy-ttl");
+ if (cfg_obj_isuint32(ttl_obj))
+ ttl_def = cfg_obj_asuint32(ttl_obj);
+ else
+ ttl_def = DNS_RPZ_MAX_TTL_DEFAULT;
+
+ for (element = cfg_list_first(cfg_tuple_get(obj, "zone list"));
element != NULL;
element = cfg_list_next(element)) {
- result = configure_rpz(view, element);
+ result = configure_rpz(view, element,
+ recursive_only_def, ttl_def);
if (result != ISC_R_SUCCESS)
goto cleanup;
dns_rpz_set_need(ISC_TRUE);
# Clean up after rpz tests.
-rm -f proto.* dig.out* nsupdate.tmp
-rm -f */named.memstats */named.run */named.rpz */session.key
-rm -f ns3/bl*.db */*.jnl */*.core */*.pid
-rm -f ns2/signed-tld2.db
-rm -f ns2/K*.private ns2/K*.key dsset-*
+rm -f proto.* dsset-* random.data trusted.conf dig.out* nsupdate.tmp ns*/*tmp
+rm -f ns*/*.key ns*/*.private ns2/tld2s.db
+rm -f ns3/bl*.db ns*/*switch ns5/requests ns5/example.db ns5/bl.db ns5/*.perf
+rm -f */named.memstats */named.run */named.rpz */session.key
+rm -f */*.jnl */*.core */*.pid
; rewrite responses from this zone
tld2. NS ns.tld2.
ns.tld2. A 10.53.0.2
-ns2.tld2. A 10.53.0.2
-; rewrite responses from this zone unless dnssec requested
-signed-tld2. NS ns.signed-tld2.
-ns.signed-tld2. A 10.53.0.2
-ns2.signed-tld2. A 10.53.0.2
+; rewrite responses from this secure zone unless dnssec requested (DO=1)
+tld2s. NS ns.tld2.
; requests come from here
tld3. NS ns.tld3.
; rewrite responses from this zone
tld4. NS ns.tld4.
ns.tld4. A 10.53.0.4
-ns2.tld4. A 10.53.0.4
--- /dev/null
+; Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+;
+; Permission to use, copy, modify, and/or distribute this software for any
+; purpose with or without fee is hereby granted, provided that the above
+; copyright notice and this permission notice appear in all copies.
+;
+; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+; AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+; PERFORMANCE OF THIS SOFTWARE.
+
+; $Id: base-tld2s.db,v 1.1.2.1 2012/02/24 17:22:37 vjs Exp $
+
+
+; RPZ rewrite responses from this signed zone
+
+$TTL 120
+@ SOA tld2s. hostmaster.ns.tld2. ( 1 3600 1200 604800 60 )
+ NS ns
+ NS . ; check for RT 24985
+ns A 10.53.0.2
+
+
+a0-1 A 192.168.0.1
+a0-1-scname CNAME a0-1.tld2.
+
+a3-5 A 192.168.3.5
+
notify no;
};
+include "../trusted.conf";
zone "." { type hint; file "hints"; };
zone "tld2." {type master; file "tld2.db";};
zone "subsub.sub2.tld2." {type master; file "tld2.db";};
zone "sub3.tld2." {type master; file "tld2.db";};
zone "subsub.sub3.tld2." {type master; file "tld2.db";};
-zone "signed-tld2." {type master; file "signed-tld2.db";};
+
+zone "tld2s." {type master; file "tld2s.db";};
; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
; PERFORMANCE OF THIS SOFTWARE.
-; $Id: tld2.db,v 1.4 2011/10/13 01:32:33 vjs Exp $
+; $Id: tld2.db,v 1.4.4.2 2012/02/24 17:22:37 vjs Exp $
; RPZ rewrite responses from this zone
$TTL 120
@ SOA tld2. hostmaster.ns.tld2. ( 1 3600 1200 604800 60 )
NS ns
- NS ns2
NS . ; check for RT 24985
ns A 10.53.0.2
-ns2 A 10.53.0.2
txt-only TXT "txt-only-tld2"
a0-1 A 192.168.0.1
AAAA 2001:2::1
TXT "a0-1 tld2 text"
+a0-1-scname CNAME a0-1.tld2s.
+
a3-1 A 192.168.3.1
AAAA 2001:2:3::1
a5-4 A 192.168.5.4
TXT "a5-4 tld2 text"
+
+a6-1 A 192.168.6.1
+ TXT "a6-1 tld2 text"
+a6-2 A 192.168.6.2
+ TXT "a6-2 tld2 text"
; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
; PERFORMANCE OF THIS SOFTWARE.
-; $Id: base.db,v 1.6 2011/10/13 01:32:33 vjs Exp $
+; $Id: base.db,v 1.6.4.1 2011/10/15 23:03:38 vjs Exp $
; RPZ test
+; This basic file is copied to several zone files before being used.
+; Its contents are also changed with nsupdate
+
$TTL 120
@ SOA blx. hostmaster.ns.blx. ( 1 3600 1200 604800 60 )
- NS ns.tld.
+ NS ns
ns A 10.53.0.3
; Poke the radix tree a little.
; regression testing for some old crashes
-redirect IN A 127.0.0.1
-*.redirect IN A 127.0.0.1
-*.credirect IN CNAME google.com.
+redirect A 127.0.0.1
+*.redirect A 127.0.0.1
+*.credirect CNAME google.com.
NS ns
ns A 10.53.0.3
-; #18 in test1, crashed new ASSERT() in rbtdb.c
-c1 A 172.16.1.1
+; #24 in test1, crashed new ASSERT() in rbtdb.c
+c1 A 172.16.1.24
; #16 in test2, crashed new ASSERT() in rbtdb.c
c2 A 172.16.1.16
/* $Id: named.conf,v 1.5 2011/10/28 11:46:50 marka Exp $ */
+/*
+ * Main rpz test DNS server.
+ */
+
options {
query-source address 10.53.0.3;
notify-source 10.53.0.3;
notify no;
response-policy {
- zone "bl";
+ zone "bl" max-policy-ttl 100;
zone "bl-2";
- zone "bl-given" policy given;
+ zone "bl-given" policy given recursive-only yes;
zone "bl-passthru" policy passthru;
- zone "bl-no-op" policy no-op; # obsolete for passthru
+ zone "bl-no-op" policy no-op; # obsolete for passthru
zone "bl-disabled" policy disabled;
- zone "bl-nodata" policy nodata;
+ zone "bl-nodata" policy nodata recursive-only no;
zone "bl-nxdomain" policy nxdomain;
zone "bl-cname" policy cname txt-only.tld2.;
zone "bl-wildcname" policy cname *.tld4.;
};
+// include "../trusted.conf";
zone "." { type hint; file "hints"; };
zone "bl." {type master; file "bl.db";
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: named.conf,v 1.2 2011/10/13 04:53:06 marka Exp $ */
+/* $Id: named.conf,v 1.2.6.1 2012/02/24 17:22:37 vjs Exp $ */
controls { /* empty */ };
notify no;
};
+include "../trusted.conf";
zone "." { type hint; file "hints"; };
zone "tld4." {type master; file "tld4.db";};
; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
; PERFORMANCE OF THIS SOFTWARE.
-; $Id: tld4.db,v 1.2 2011/10/13 04:53:07 marka Exp $
+; $Id: tld4.db,v 1.2.6.1 2012/02/24 17:22:37 vjs Exp $
; RPZ rewrite responses from this zone
$TTL 120
@ SOA tld4. hostmaster.ns.tld4. ( 1 3600 1200 604800 60 )
NS ns
- NS ns2
ns A 10.53.0.4
-ns2 A 10.53.0.4
txt-only TXT "txt-only-tld4"
--- /dev/null
+; Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+;
+; Permission to use, copy, modify, and/or distribute this software for any
+; purpose with or without fee is hereby granted, provided that the above
+; copyright notice and this permission notice appear in all copies.
+;
+; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+; AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+; PERFORMANCE OF THIS SOFTWARE.
+
+; $Id: hints,v 1.1.2.1 2011/10/15 23:00:04 vjs Exp $
+
+
+. 0 NS ns1.
+ns1. 0 A 10.53.0.1
--- /dev/null
+/*
+ * Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: named.conf,v 1.1.2.2 2012/02/24 17:22:38 vjs Exp $ */
+
+
+/*
+ * Test rpz performance.
+ */
+
+options {
+ query-source address 10.53.0.5;
+ notify-source 10.53.0.5;
+ transfer-source 10.53.0.5;
+ port 5300;
+ pid-file "named.pid";
+ session-keyfile "session.key";
+ listen-on { 10.53.0.5; };
+ listen-on-v6 { none; };
+ notify no;
+
+ # Eventually turn rpz on.
+ include "rpz-switch";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-md5;
+};
+controls { inet 10.53.0.5 port 9953 allow { any; } keys { rndc_key; }; };
+
+
+include "../trusted.conf";
+zone "." {type hint; file "hints"; };
+
+zone "example.com." {type master; file "example.db"; };
+
+zone "bl." {type master; file "bl.db"; };
--- /dev/null
+#! /bin/sh
+#
+# Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+# $Id: qperf.sh,v 1.1.2.1 2011/10/15 23:03:37 vjs Exp $
+
+for QDIR in `echo "$PATH" | tr : ' '` ../../../../contrib/queryperf; do
+ QPERF=$QDIR/queryperf
+ if test -f $QPERF -a -x $QPERF; then
+ echo $QPERF
+ exit 0
+ fi
+done
+
+exit 0
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rpz.c,v 1.3 2011/01/13 04:59:24 tbox Exp $ */
+/* $Id: rpz.c,v 1.3.226.1 2011/10/15 23:03:37 vjs Exp $ */
#include <config.h>
#else
return (1);
#endif
- }
+ }
if (!strcasecmp(argv[1], "nsdname")) {
#ifdef ENABLE_RPZ_NSDNAME
#else
return (1);
#endif
- }
+ }
- fputs(USAGE, stderr);
- return (1);
+ fputs(USAGE, stderr);
+ return (1);
}
-#!/bin/sh
+#! /bin/sh
#
# Copyright (C) 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
#
# $Id: setup.sh,v 1.6 2012/01/07 23:46:53 tbox Exp $
+set -e
+
SYSTEMTESTTOP=..
. $SYSTEMTESTTOP/conf.sh
-. ./clean.sh
-# NO-OP is an obsolete synonym for PASSHTRU
+QPERF=`sh qperf.sh`
+
+sh clean.sh
+
+# set up test policy zones. bl-2 is used to check competing zones.
+# bl-{given,disabled,passthru,no-data,nxdomain,cname,wildcard,garden}
+# are used to check policy overrides in named.conf.
+# NO-OP is an obsolete synonym for PASSHTRU
for NM in '' -2 -given -disabled -passthru -no-op -nodata -nxdomain -cname -wildcname -garden; do
sed -e "/SOA/s/blx/bl$NM/g" ns3/base.db >ns3/bl$NM.db
done
+# sign the root and a zone in ns2
../../../tools/genrandom 400 random.data
-$KEYGEN -Kns2 -q -r random.data -3 signed-tld2. > /dev/null 2>&1
-$KEYGEN -Kns2 -q -r random.data -3fk signed-tld2. > /dev/null 2>&1
-$SIGNER -S -Kns2 -o signed-tld2. -f ns2/signed-tld2.db ns2/tld2.db > /dev/null 2>&1
+
+# $1=directory, $2=domain name, $3=input zone file, $4=output file
+signzone () {
+ KEYNAME=`$KEYGEN -q -r random.data -b 512 -K $1 $2`
+ cat $1/$3 $1/$KEYNAME.key > $1/tmp
+ $SIGNER -Pp -K $1 -o $2 -f $1/$4 $1/tmp >/dev/null
+ sed -n -e 's/\(.*\) IN DNSKEY \([0-9]\{1,\} [0-9]\{1,\} [0-9]\{1,\}\) \(.*\)/trusted-keys {"\1" \2 "\3";};/p' $1/$KEYNAME.key >>trusted.conf
+ rm dsset-$2 $1/tmp
+}
+signzone ns2 tld2s. base-tld2s.db tld2s.db
+
+
+# Performance checks.
+# First with rpz off.
+cat <<EOF >ns5/rpz-switch
+response-policy {zone "bl";}
+ recursive-only no
+ max-policy-ttl 90
+ break-dnssec yes;
+EOF
+
+cat <<EOF >ns5/example.db
+\$TTL 120
+@ SOA . hostmaster.ns.example. ( 1 3600 1200 604800 60 )
+ NS ns
+ns A 10.53.0.5
+EOF
+
+cat <<EOF >ns5/bl.db
+\$TTL 120
+@ SOA . hostmaster.ns.blperf. ( 1 3600 1200 604800 60 )
+ NS ns
+ns A 10.53.0.5
+
+; used only in failure for "recursive-only no" in #8 test5
+a3-5.tld2 CNAME *.
+; for "break-dnssec" in #9 test5
+a3-5.tld2s CNAME *.
+; for "max-policy-ttl 90" in test5
+a3-17.tld2 500 A 17.17.17.17
+
+; dummy NSDNAME policies to trigger lookups
+ns-1.example.com.rpz-nsdname CNAME .
+ns-2.example.com.rpz-nsdname CNAME .
+ns-3.example.com.rpz-nsdname CNAME .
+ns-4.example.com.rpz-nsdname CNAME .
+ns-5.example.com.rpz-nsdname CNAME .
+EOF
+
+if test -n "$QPERF"; then
+ # do not build the full zones if we will not use them to avoid the long
+ # time otherwise required to shut down the server
+ $PERL -e 'for ($val = 1; $val <= 65535; ++$val) {
+ printf("host-%d-%d\tA 192.168.%d.%d\n",
+ $val/256, $val%256, $val/256, $val%256);
+ }' >>ns5/example.db
+
+ echo >>ns5/bl.db
+ echo "; rewrite some names" >>ns5/bl.db
+ $PERL -e 'for ($val = 2; $val <= 65535; $val += 69) {
+ printf("host-%d.sub%d.example.com\tCNAME\t.\n", $val/256, $val%256);
+ }' >>ns5/bl.db
+
+ echo >>ns5/bl.db
+ echo "; rewrite with some not entirely trivial patricia trees" >>ns5/bl.db
+ $PERL -e 'for ($val = 3; $val <= 65535; $val += 69) {
+ printf("32.%d.%d.168.192.rpz-ip \tCNAME\t.\n",
+ $val%256, $val/256);
+ printf("32.%d.%d.168.192.rpz-nsip\tCNAME\t.\n",
+ ($val+1)%256, ($val+1)/256);
+ }' >>ns5/bl.db
+fi
+
+# some psuedo-random queryperf requests
+$PERL -e 'for ($cnt = $val = 1; $cnt <= 2000; ++$cnt) {
+ printf("host-%d.sub%d.example.com A\n", $val%256, $val/256);
+ $val = ($val * 9 + 32771) % 65536;
+ }' >ns5/requests
; QNAME tests
; NXDOMAIN
+; 2, 20, 25
update add a0-1.tld2.bl. 300 CNAME .
-update add a0-1.signed-tld2.bl. 300 CNAME .
-;
; NODATA
+; 3, 21
update add a3-1.tld2.bl. 300 CNAME *.
; and no assert-botch
-; 5
+; 5, 22
update add a3-2.tld2.bl. 300 DNAME example.com.
;
; NXDOMAIN for a4-2-cname.tld2 via its target a4-2.tld2.
;
; prefer the first conflicting zone
; 13
-update add a4-4.tld2.bl. 300 A 127.0.0.1
+update add a4-4.tld2.bl. 300 A 127.4.4.1
+update add a6-1.tld2.bl. 300 CNAME a6-1.tld2.
+update add a6-2.tld2.bl. 300 A 127.6.2.1
+update add a6-1.tld2.bl. 300 A 127.6.1.1
+update add a6-2.tld2.bl. 300 CNAME a6-2.tld2.
send
-update add a4-4.tld2.bl-2. 300 A 127.0.0.2
+update add a4-4.tld2.bl-2. 300 A 127.4.4.2
send
-;
+
; wildcard CNAME
-; 14
+; 16
update add a3-6.tld2.bl. 300 CNAME *.tld4.
-; 15
+; 17
update add *.sub1.tld2.bl. 300 CNAME *.tld4.
-; CNAME chains
-; 16
+; CNAME chain
+; 18
update add a4-5.tld2.bl. 300 A 127.0.0.16
-; 17
+; stop at first hit in CNAME chain
+; 19
update add a4-6.tld2.bl. 300 CNAME .
update add a4-6-cname.tld2.bl. 300 A 127.0.0.17
-
-; 18
+;
+; assert in rbtdb.c
+; 24
update add c1.crash2.tld3.bl. 300 CNAME .
-
+; DO=1 without signatures, DO=0 with signatures are rewritten
+; 26 - 27
+update add a0-1.tld2s.bl. 300 CNAME .
send
; single requests
; Separate update requests for distinct TLDs with blank lines or 'send'
; End the file with a blank line or 'send'
+; CNAME targets are absolute even without trailing "."
; IP tests
server 10.53.0.3 5300
; NODATA a3-1.tld2
+; 1
update add 32.1.3.168.192.rpz-ip.bl 300 CNAME *.
;
-; NXDOMAIN for 192.168.4.0/24, the network of a4-1.tld2
+; NXDOMAIN for 192.168.4.0/24, the network of a4-1.tld2 and a4-2.tld2
+; 4
update add 24.0.4.168.192.rpz-ip.bl 300 CNAME .
;
-; poke hole in NXDOMAIN CIDR block to leave a4-1.tld2 unchanged
+; old passthru in NXDOMAIN CIDR block to leave a4-1.tld2 unchanged
+; 3
update add 32.1.4.168.192.rpz-ip.bl 300 CNAME 32.1.4.168.192
;
; NODATA for a4-3.tld2
+; 8
update add 32.3.4.168.192.rpz-ip.bl 300 CNAME *.
;
; NXDOMAIN for IPv6 a3-1.tld2
+; 9
update add 128.1.zz.3.2.2001.rpz-ip.bl 300 CNAME .
;
; apply the policy with the lexically smallest address of 192.168.5.1
; to an RRset of more than one A RR
+; 11
update add 32.1.5.168.192.rpz-ip.bl 300 A 127.0.0.1
update add 32.2.5.168.192.rpz-ip.bl 300 A 127.0.0.2
;
; prefer first conflicting IP zone for a5-3.tld2
+; 12
update add 32.3.5.168.192.rpz-ip.bl 300 A 127.0.0.1
send
update add 32.3.5.168.192.rpz-ip.bl-2 300 A 127.0.0.2
send
; prefer QNAME to IP for a5-4.tld2
+; 13
update add 32.4.5.168.192.rpz-ip.bl 300 CNAME a12.tld2.
update add a5-4.tld2.bl 300 CNAME a14.tld4.
;
+; poke hole in NXDOMAIN CIDR block to leave a4-4.tld2 unchanged
+; 15
+update add 32.4.4.168.192.rpz-ip.bl 300 CNAME rpz-passthru.
+;
; assert in rbtdb.c
; 16
update add 32.16.1.16.172.rpz-ip.bl 300 CNAME .
; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
; PERFORMANCE OF THIS SOFTWARE.
-; $Id: test5,v 1.5 2011/10/13 01:32:33 vjs Exp $
+; $Id: test5,v 1.5.4.1 2012/02/24 17:22:37 vjs Exp $
; Use comment lines instead of blank lines to combine update requests into
server 10.53.0.3 5300
+; 1
update add a3-1.tld2.bl-given. 300 A 127.0.0.1
send
+; 2
update add a3-2.tld2.bl-passthru. 300 A 127.0.0.2
send
+; 3
update add a3-3.tld2.bl-no-op. 300 A 127.0.0.3
send
+; 4
update add a3-4.tld2.bl-disabled. 300 A 127.0.0.4
send
+; 5 - 8
update add a3-5.tld2.bl-nodata. 300 A 127.0.0.5
+; 9 - 10
+update add a3-5.tld2s.bl-nodata. 300 A 127.0.0.9
send
-update add a3-6.tld2.bl-nxdomain. 300 A 127.0.0.6
+; 11
+update add a3-6.tld2.bl-nxdomain. 300 A 127.0.0.11
send
-update add a3-7.tld2.bl-cname. 300 A 127.0.0.7
+; 12
+update add a3-7.tld2.bl-cname. 300 A 127.0.0.12
send
-update add a3-8.tld2.bl-wildcname. 300 A 127.0.0.8
-update add *.sub9.tld2.bl-wildcname. 300 A 127.0.1.9
+; 13
+update add a3-8.tld2.bl-wildcname. 300 A 127.0.0.13
+; 14
+update add *.sub9.tld2.bl-wildcname. 300 A 127.0.1.14
send
-update add a3-10.tld2.bl-garden. 300 A 127.0.0.10
+; 15
+update add a3-15.tld2.bl-garden. 300 A 127.0.0.15
+send
+; 16
+update add a3-16.tld2.bl. 300 A 127.0.0.16
send
SYSTEMTESTTOP=..
. $SYSTEMTESTTOP/conf.sh
-ns1=10.53.0.1 # root, defining the other two
-ns2=10.53.0.2 # server whose answers are rewritten
-ns3=10.53.0.3 # resolve that does the rewriting
-ns4=10.53.0.4 # another server that is rewritten
-
-RNDCCMD="$RNDC -c ../common/rndc.conf -s $ns3 -p 9953"
+ns=10.53.0
+ns1=$ns.1 # root, defining the others
+ns2=$ns.2 # server whose answers are rewritten
+ns3=$ns.3 # resolve that does the rewriting
+ns4=$ns.4 # another server that is rewritten
+ns5=$ns.5 # check performance with this server
HAVE_CORE=
trap 'exit 1' 1 2 15
+RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p 9953 -s"
+
digcmd () {
- #echo I:dig +noadd +noauth +nosearch +time=1 +tries=1 -p 5300 $* 1>&2
- $DIG +noadd +noauth +nosearch +time=1 +tries=1 -p 5300 $*
+ digcmd_args="+noadd +nosearch +time=1 +tries=1 -p 5300 $*"
+ if ! expr "$digcmd_args" : '.*@' >/dev/null; then
+ digcmd_args="$digcmd_args @$ns3"
+ fi
+ if ! expr "$digcmd_args" : '.*+[no]*auth' >/dev/null; then
+ digcmd_args="+noauth $digcmd_args"
+ fi
+ #echo I:dig $digcmd_args 1>&2
+ $DIG $digcmd_args
}
# set DIGNM=file name for dig output
}
restart () {
- $RNDCCMD stop >/dev/null 2>&1
- rm -f ns3/*.jnl
- for NM in ns3/bl*.db; do
- cp -f ns3/base.db $NM
- done
- (cd ..; $PERL start.pl --noclean --restart rpz ns3)
+ # try to ensure that the server really has stopped
+ # and won't mess with ns$1/name.pid
+ if test -z "$HAVE_CORE" -a -f ns$1/named.pid; then
+ $RNDCCMD $ns$1 halt >/dev/null 2>&1
+ if test -f ns$1/named.pid; then
+ sleep 1
+ PID=`cat ns$1/named.pid 2>/dev/null`
+ if test -n "$PID"; then
+ echo "I:killing ns$1 server $PID"
+ kill -9 $PID
+ fi
+ fi
+ fi
+ rm -f ns$1/*.jnl
+ if test -f ns$1/base.db; then
+ for NM in ns$1/bl*.db; do
+ cp -f ns$1/base.db $NM
+ done
+ fi
+ $PERL $SYSTEMTESTTOP/start.pl --noclean --restart . ns$1
load_db
}
+# $1=server and irrelevant args $2=error message
ckalive () {
- $RNDCCMD status >/dev/null 2>&1 && return 0
+ CKALIVE_NS=`expr "$1" : '.*@ns\([1-9]\).*'`
+ if test -z "$CKALIVE_NS"; then
+ CKALIVE_NS=3
+ fi
+ eval CKALIVE_IP=\$ns$CKALIVE_NS
+ $RNDCCMD $CKALIVE_IP status >/dev/null 2>&1 && return 0
HAVE_CORE=yes
- setret "$1"
- restart
+ setret "$2"
+ # restart the server to avoid stalling waiting for it to stop
+ restart $CKALIVE_NS
return 1
}
sed -e 's/[ ]add[ ]/ delete /' $TEST_FILE | $NSUPDATE
TEST_FILE=
fi
+ ckalive $ns3 "I:failed; ns3 server crashed and restarted"
+ if test "$status" -eq 0; then
+ # look for complaints from rpz.c
+ EMSGS=`grep -l 'invalid rpz' */*.run`
+ if test -n "$EMSGS"; then
+ setret "I:'invalid rpz' complaints in $EMSGS starting with:"
+ grep 'invalid rpz' */*.run | sed -e '4,$d' -e 's/^/I: /'
+ fi
+ # look for complaints from rpz.c and query.c
+ EMSGS=`grep -l 'rpz .*failed' */*.run`
+ if test -n "$EMSGS"; then
+ setret "I:'rpz failed' complaints in $EMSGS starting with:"
+ grep 'rpz .*failed' */*.run | sed -e '4,$d' -e 's/^/I: /'
+ fi
+ fi
status=`expr $status + $ret`
- ckalive "I:failed; server crashed"
GROUP_NM=
}
# $1=dig args $2=other dig output file
ckresult () {
- #ckalive "I:server crashed by 'dig $1'" || return 1
- if $PERL ../digcomp.pl $DIGNM $2 >/dev/null; then
+ #ckalive "$1" "I:server crashed by 'dig $1'" || return 1
+ if $PERL $SYSTEMTESTTOP/digcomp.pl $DIGNM $2 >/dev/null; then
rm -f ${DIGNM}*
return 0
fi
# check only that the server does not crash
# $1=target domain $2=optional query type
nocrash () {
- digcmd $* @$ns3 >/dev/null
- ckalive "I:server crashed by 'dig $*'"
+ digcmd $* >/dev/null
+ ckalive "$*" "I:server crashed by 'dig $*'"
}
# $1=target domain $2=optional query type
nxdomain () {
make_dignm
- digcmd +noauth $* @$ns3 \
- | sed -e 's/^[a-z].* IN CNAME /;xxx &/' >$DIGNM
+ digcmd $* \
+ | sed -e 's/^[a-z].* IN CNAME /;xxx &/' \
+ -e 's/^[a-z].* IN RRSIG /;xxx &/' \
+ >$DIGNM
ckresult "$*" proto.nxdomain
}
# $1=target domain $2=optional query type
nodata () {
make_dignm
- digcmd +noauth $* @$ns3 \
+ digcmd $* \
| sed -e 's/^[a-z].* IN CNAME /;xxx &/' >$DIGNM
ckresult "$*" proto.nodata
}
# check rewrite to an address
# modify the output so that it is easily compared, but save the original line
-# $1=IPv4 address, $2=target domain $3=optional query type
+# $1=IPv4 address $2=digcmd args $3=optional TTL
addr () {
ADDR=$1
- shift
- ADDR_ESC=`echo "$ADDR" | sed -e 's/\./\\\\./g'`
make_dignm
- digcmd +noauth $* @$ns3 >$DIGNM
- #ckalive "I:server crashed by 'dig $*'" || return
- if grep -i '^[a-z].* A '"$ADDR_ESC"'$' $DIGNM >/dev/null; then
- rm -f ${DIGNM}*
- return 0
+ digcmd $2 >$DIGNM
+ #ckalive "$2" "I:server crashed by 'dig $2'" || return 1
+ ADDR_ESC=`echo "$ADDR" | sed -e 's/\./\\\\./g'`
+ ADDR_TTL=`sed -n -e "s/^[-.a-z0-9]\{1,\} *\([0-9]*\) IN A\{1,4\} ${ADDR_ESC}\$/\1/p" $DIGNM`
+ if test -z "$ADDR_TTL"; then
+ setret "I:'dig $2' wrong; no address $ADDR record in $DIGNM"
+ return 1
fi
- setret "I:'dig $*' wrong; no A $ADDR record in $DIGNM $2"
+ if test -n "$3" && test "$ADDR_TTL" -ne "$3"; then
+ setret "I:'dig $2' wrong; TTL=$ADDR_TTL instead of $3 in $DIGNM"
+ return 1
+ fi
+ rm -f ${DIGNM}*
}
# check that a response is not rewritten
# $1=target domain $2=optional query type
nochange () {
make_dignm
- digcmd $* @$ns3 >$DIGNM
+ digcmd $* >$DIGNM
digcmd $* @$ns2 >${DIGNM}_OK
ckresult "$*" ${DIGNM}_OK && rm -f ${DIGNM}_OK
}
here () {
make_dignm
sed -e 's/^[ ]*//' >${DIGNM}_OK
- digcmd $* @$ns3 >$DIGNM
+ digcmd $* >$DIGNM
ckresult "$*" ${DIGNM}_OK
}
# make prototype files to check against rewritten results
-digcmd +noauth nonexistent @$ns2 >proto.nxdomain
-digcmd +noauth txt-only.tld2 @$ns2 >proto.nodata
+digcmd nonexistent @$ns2 >proto.nxdomain
+digcmd txt-only.tld2 @$ns2 >proto.nodata
status=0
start_group "QNAME rewrites" test1
-nochange .
-nxdomain a0-1.tld2
-nodata a3-1.tld2
-nodata a3-2.tld2
-nodata sub.a3-2.tld2 # 5 no crash on DNAME
+nochange . # 1 do not crash or rewrite root
+nxdomain a0-1.tld2 # 2
+nodata a3-1.tld2 # 3
+nodata a3-2.tld2 # 4 no crash on DNAME
+nodata sub.a3-2.tld2
nxdomain a4-2.tld2 # 6 rewrite based on CNAME target
nxdomain a4-2-cname.tld2 # 7
nodata a4-3-cname.tld2 # 8
addr 12.12.12.12 a4-1.sub2.tld2 # 10 A replacement with wildcard
addr 12.12.12.12 nxc1.sub1.tld2 # 11 replace NXDOMAIN with CNAME
addr 12.12.12.12 nxc2.sub1.tld2 # 12 replace NXDOMAIN with CNAME chain
-addr 127.0.0.1 a4-4.tld2 # 13 prefer 1st conflicting QNAME zone
-addr 56.56.56.56 a3-6.tld2 # 14 wildcard CNAME
-addr 57.57.57.57 a3-7.sub1.tld2 # 15 wildcard CNAME
-addr 127.0.0.16 a4-5-cname3.tld2 # 16 CNAME chain
-addr 127.0.0.17 a4-6-cname3.tld2 # 17 stop short in CNAME chain
-nxdomain c1.crash2.tld3 # 18 assert in rbtdb.c
-nochange a0-1.tld2 +norecurse
-nxdomain a0-1.tld2 +dnssec
-nxdomain a0-1.signed-tld2
-nochange a0-1.signed-tld2 +dnssec
+addr 127.4.4.1 a4-4.tld2 # 13 prefer 1st conflicting QNAME zone
+nochange a6-1.tld2 # 14
+addr 127.6.2.1 a6-2.tld2 # 15
+addr 56.56.56.56 a3-6.tld2 # 16 wildcard CNAME
+addr 57.57.57.57 a3-7.sub1.tld2 # 17 wildcard CNAME
+addr 127.0.0.16 a4-5-cname3.tld2 # 18 CNAME chain
+addr 127.0.0.17 a4-6-cname3.tld2 # 19 stop short in CNAME chain
+nochange a0-1.tld2 +norecurse # 20 check that RD=1 is required
+nochange a3-1.tld2 +norecurse # 21
+nochange a3-2.tld2 +norecurse # 22
+nochange sub.a3-2.tld2 +norecurse # 23
+nxdomain c1.crash2.tld3 # 24 assert in rbtdb.c
+nxdomain a0-1.tld2 +dnssec # 25 simple DO=1 without signatures
+nxdomain a0-1.tld2s # 26 simple DO=0 with signatures
+nochange a0-1.tld2s +dnssec # 27 simple DO=1 with signatures
+nxdomain a0-1s-cname.tld2s +dnssec # 28 DNSSEC too early in CNAME chain
+nochange a0-1-scname.tld2 +dnssec # 29 DNSSEC on target in CNAME chain
+nochange a0-1.tld2s srv +auth +dnssec # 30 no write for +DNSSEC and no record
+nxdomain a0-1.tld2s srv # 31
end_group
start_group "IP rewrites" test2
-nodata a3-1.tld2
-nochange a3-2.tld2
-nochange a4-1.tld2
-nxdomain a4-2.tld2
-nochange a4-2.tld2 -taaaa
-nochange a4-2.tld2 -ttxt
-nxdomain a4-2.tld2 -tany
-nodata a4-3.tld2
-nxdomain a3-1.tld2 -tAAAA
-nochange a4-1-aaaa.tld2 -tAAAA
+nodata a3-1.tld2 # 1 NODATA
+nochange a3-2.tld2 # 2 no policy record so no change
+nochange a4-1.tld2 # 3 obsolete PASSTHRU record style
+nxdomain a4-2.tld2 # 4
+nochange a4-2.tld2 -taaaa # 5 no A => no policy rewrite
+nochange a4-2.tld2 -ttxt # 6 no A => no policy rewrite
+nxdomain a4-2.tld2 -tany # 7 no A => no policy rewrite
+nodata a4-3.tld2 # 8
+nxdomain a3-1.tld2 -taaaa # 9 IPv6 policy
+nochange a4-1-aaaa.tld2 -taaaa # 10
addr 127.0.0.1 a5-1-2.tld2 # 11 prefer smallest policy address
addr 127.0.0.1 a5-3.tld2 # 12 prefer first conflicting IP zone
addr 14.14.14.14 a5-4.tld2 # 13 prefer QNAME to IP
+nochange a5-4.tld2 +norecurse # 14 check that RD=1 is required
+nochange a4-4.tld2 # 15 PASSTHRU
nxdomain c2.crash2.tld3 # 16 assert in rbtdb.c
end_group
if ./rpz nsdname; then
start_group "NSDNAME rewrites" test3
nochange a3-1.tld2
- nochange a3-1.tld2 +dnssec # 2 this once caused problems
+ nochange a3-1.tld2 +dnssec # 2 this once caused problems
nxdomain a3-1.sub1.tld2 # 3 NXDOMAIN *.sub1.tld2 by NSDNAME
nxdomain a3-1.subsub.sub1.tld2
nxdomain a3-1.subsub.sub1.tld2 -tany
fi
# policies in ./test5 overridden by response-policy{} in ns3/named.conf
+# and in ns5/named.conf
start_group "policy overrides" test5
addr 127.0.0.1 a3-1.tld2 # 1 bl-given
nochange a3-2.tld2 # 2 bl-passthru
nochange a3-3.tld2 # 3 bl-no-op obsolete for passthru
nochange a3-4.tld2 # 4 bl-disabled
nodata a3-5.tld2 # 5 bl-nodata
-nxdomain a3-6.tld2 # 6 bl-nxdomain
-here +noauth a3-7.tld2 -tany <<'EOF' # 7 bl_cname
+nodata a3-5.tld2 +norecurse # 6 bl-nodata recursive-only no
+nodata a3-5.tld2 # 7 bl-nodata
+nodata a3-5.tld2 +norecurse @$ns5 # 8 bl-nodata recursive-only no
+nodata a3-5.tld2s @$ns5 # 9 bl-nodata
+nodata a3-5.tld2s +dnssec @$ns5 # 10 bl-nodata break-dnssec
+nxdomain a3-6.tld2 # 11 bl-nxdomain
+here a3-7.tld2 -tany <<'EOF'
;; status: NOERROR, x
- a3-7.tld2. 300 IN CNAME txt-only.tld2.
- txt-only.tld2. 120 IN TXT "txt-only-tld2"
+ a3-7.tld2. x IN CNAME txt-only.tld2.
+ txt-only.tld2. x IN TXT "txt-only-tld2"
EOF
-addr 58.58.58.58 a3-8.tld2 # 8 bl_wildcname
-addr 59.59.59.59 a3-9.sub9.tld2 # 9 bl_wildcname
-addr 12.12.12.12 a3-10.tld2 # 10 bl-garden
+addr 58.58.58.58 a3-8.tld2 # 13 bl_wildcname
+addr 59.59.59.59 a3-9.sub9.tld2 # 14 bl_wildcname
+addr 12.12.12.12 a3-15.tld2 # 15 bl-garden via CNAME to a12.tld2
+addr 127.0.0.16 a3-16.tld2 100 # 16 bl max-policy-ttl 100
+addr 17.17.17.17 "a3-17.tld2 @$ns5" 90 # 17 ns5 bl max-policy-ttl 90
end_group
# check that miscellaneous bugs are still absent
done
end_group
-# restart the server to see if that creates a core file
+
+# superficial test for major performance bugs
+QPERF=`sh qperf.sh`
+if test -n "$QPERF"; then
+ perf () {
+ echo "I:checking performance $1"
+ # don't measure the costs of -d99
+ $RNDCCMD $ns5 notrace >/dev/null
+ $QPERF -1 -l2 -d ns5/requests -s $ns5 -p 5300 >ns5/$2.perf
+ ckalive $ns5 "I:failed; server #5 crashed"
+ }
+ trim () {
+ sed -n -e 's/.*Queries per second: *\([0-9]*\).*/\1/p' ns5/$1.perf
+ }
+
+ # Dry run to prime disk cache
+ # Otherwise a first test of either flavor is 25% low
+ perf 'to prime disk cache' rpz
+
+ # get queries/second with rpz
+ perf 'with rpz' rpz
+
+ # turn off rpz and measure queries/second again
+ # Don't wait for a clean stop. Clean stops of this server need seconds
+ # until the sockets are close. 5 or 10 seconds after that, the
+ # server really stops and deletes named.pid.
+ echo "# rpz off" >ns5/rpz-switch
+ PID=`cat ns5/named.pid`
+ test -z "$PID" || kill -9 "$PID"
+ $PERL $SYSTEMTESTTOP/start.pl --noclean --restart . ns5
+ perf 'without rpz' norpz
+
+ NORPZ=`trim norpz`
+ RPZ=`trim rpz`
+ echo "I:$RPZ qps with RPZ versus $NORPZ qps without"
+
+ # fail if RPZ costs more than 100%
+ NORPZ2=`expr "$NORPZ" / 2`
+ if test "$RPZ" -le "$NORPZ2"; then
+ echo "I:rpz $RPZ qps too far below non-RPZ $NORPZ qps"
+ status=`expr $status + 1`
+ fi
+else
+ echo "I:performance not checked; queryperf not available"
+fi
+
+
+# restart the main test RPZ server to see if that creates a core file
if test -z "$HAVE_CORE"; then
- $RNDCCMD halt
- restart
- test -s ns3/named.core && setret "I:found stray core file; memory leak?"
+ $PERL $SYSTEMTESTTOP/stop.pl . ns3
+ restart 3
+ HAVE_CORE=`find ns* -name '*core*' -print`
+ test -z "$HAVE_CORE" || setret "I:found $HAVE_CORE; memory leak?"
fi
+
echo "I:exit status: $status"
exit $status
<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> response-policy { <replaceable>zone_name</replaceable> <optional> policy given | disabled | passthru | nxdomain | nodata | cname <replaceable>domain</replaceable> </optional> ; } ; </optional>
+ <optional> response-policy { <replaceable>zone_name</replaceable>
+ <optional> policy given | disabled | passthru | nxdomain | nodata | cname <replaceable>domain</replaceable> </optional>
+ <optional> recursive-only <replaceable>yes_or_no</replaceable> </optional> <optional> max-policy-ttl <replaceable>number</replaceable> </optional> ;
+ } <optional> recursive-only <replaceable>yes_or_no</replaceable> </optional> <optional> max-policy-ttl <replaceable>number</replaceable> </optional>
+ <optional> break-dnssec <replaceable>yes_or_no</replaceable> </optional> ; </optional>
};
</programlisting>
<sect3>
<title>Response Policy Zone (RPZ) Rewriting</title>
<para>
- <acronym>BIND</acronym> 9 includes an intentionally limited
- mechanism to modify DNS responses for recursive requests
- somewhat similar to email anti-spam DNS blacklists.
+ <acronym>BIND</acronym> 9 includes a limited
+ mechanism to modify DNS responses for requests
+ analogous to email anti-spam DNS blacklists.
Responses can be changed to deny the existence of domains(NXDOMAIN),
deny the existence of IP addresses for domains (NODATA),
or contain other IP addresses or data.
</para>
<para>
- The actions encoded in a response policy zone (RPZ) are applied
- only to queries that ask for recursion (RD=1).
Response policy zones are named in the
<command>response-policy</command> option for the view or among the
global options if there is no response-policy option for the view.
</para>
<para>
- There are four kinds of RPZ records, QNAME, IP, NSIP,
+ Four policy triggers are encoded in RPZ records, QNAME, IP, NSIP,
and NSDNAME.
- QNAME records are applied to query names of requests and targets
+ QNAME RPZ records triggered by query names of requests and targets
of CNAME records resolved to generate the response.
The owner name of a QNAME RPZ record is the query name relativized
to the RPZ.
</para>
<para>
- The second kind of RPZ record, an IP policy record,
- is triggered by addresses in A and AAAA records
- for the ANSWER sections of responses.
- IP policy records have owner names that are
- subdomains of <userinput>rpz-ip</userinput> relativized to the
- RPZ origin name and encode an IP address or address block.
- IPv4 addresses are encoded as
+ The second kind of RPZ trigger is an IP address in an A and AAAA
+ record in the ANSWER section of a response.
+ IP address triggers are encoded in records that have owner names
+ that are subdomains of <userinput>rpz-ip</userinput> relativized
+ to the RPZ origin name and encode an IP address or address block.
+ IPv4 trigger addresses are represented as
<userinput>prefixlength.B4.B3.B2.B1.rpz-ip</userinput>.
The prefix length must be between 1 and 32.
All four bytes, B4, B3, B2, and B1, must be present.
</para>
<para>
- NSDNAME policy records match names of authoritative servers
- for the query name, a parent of the query name, a CNAME,
- or a parent of a CNAME.
+ NSDNAME triggers match names of authoritative servers
+ for the query name, a parent of the query name, a CNAME for
+ query name, or a parent of a CNAME.
They are encoded as subdomains of
<userinput>rpz-nsdomain</userinput> relativized
to the RPZ origin name.
</para>
<para>
- NSIP policy records match IP addresses in A and AAAA RRsets
- for domains that can be checked against NSDNAME policy records.
- The are encoded like IP policies except as subdomains of
+ NSIP triggers match IP addresses in A and
+ AAAA RRsets for domains that can be checked against NSDNAME
+ policy records.
+ NSIP triggers are encoded like IP triggers except as subdomains of
<userinput>rpz-nsip</userinput>.
</para>
<para>
The query response is checked against all RPZs, so
- two or more policy records can apply to a single response.
- Because DNS responses can be rewritten according by at most a
- single policy record, a single policy (other than
- <command>DISABLED</command> policies) must be chosen.
- Policies are chosen in the following order:
+ two or more policy records can be triggered by a response.
+ Because DNS responses can be rewritten according to at most one
+ policy record, a single record encoding an action (other than
+ <command>DISABLED</command> actions) must be chosen.
+ Triggers or the records that encode them are chosen in
+ the following order:
<itemizedlist>
- <listitem>Among applicable zones, use the RPZ that appears first
- in the response-policy option.
+ <listitem>Choose the triggered record in the zone that appears
+ first in the response-policy option.
</listitem>
- <listitem>Prefer QNAME to IP to NSDNAME to NSIP policy records
- in a single RPZ
+ <listitem>Prefer QNAME to IP to NSDNAME to NSIP triggers
+ in a single zone.
</listitem>
- <listitem>Among applicable NSDNAME policy records, prefer the
- policy record that matches the lexically smallest name
+ <listitem>Among NSDNAME triggers, prefer the
+ trigger that matches the smallest name under the DNSSEC ordering.
</listitem>
- <listitem>Among IP or NSIP policy records, prefer the record
+ <listitem>Among IP or NSIP triggers, prefer the trigger
with the longest prefix.
</listitem>
- <listitem>Among records with the same prefex length,
- prefer the IP or NSIP policy record that matches
+ <listitem>Among triggers with the same prefex length,
+ prefer the IP or NSIP trigger that matches
the smallest IP address.
</listitem>
</itemizedlist>
<para>
When the processing of a response is restarted to resolve
- DNAME or CNAME records and an applicable policy record set has
- not been found,
+ DNAME or CNAME records and a policy record set has
+ not been triggered,
all RPZs are again consulted for the DNAME or CNAME names
and addresses.
</para>
</para>
<para>
- RPZ record sets are special CNAME records or one or more
- of any types of DNS record except DNAME or DNSSEC.
- Except when a policy record is a CNAME, there can be more
- more than one record and more than one type
- in a set of policy records.
- Except for three kinds of CNAME records that are illegal except
- in policy zones, the records in a set are used in the response as if
- their owner name were the query name. They are copied to the
- response as dictated by their types.
+ RPZ record sets are sets of any types of DNS record except
+ DNAME or DNSSEC that encode actions or responses to queries.
<itemizedlist>
- <listitem>A CNAME whose target is the root domain (.)
- specifies the <command>NXDOMAIN</command> policy,
- which generates an NXDOMAIN response.
+ <listitem>The <command>NXDOMAIN</command> response is encoded
+ by a CNAME whose target is the root domain (.)
</listitem>
<listitem>A CNAME whose target is the wildcard top-level
- domain (*.) specifies the <command>NODATA</command> policy,
+ domain (*.) specifies the <command>NODATA</command> action,
which rewrites the response to NODATA or ANCOUNT=1.
</listitem>
- <listitem>A CNAME whose target is a wildcard hostname such
- as *.example.com is used normally after the astrisk (*)
+ <listitem>The <command>Local Data</command> action is
+ represented by a set ordinary DNS records that are used
+ to answer queries. Queries for record types not the
+ set are answered with NODATA.
+
+ A special form of local data is a CNAME whose target is a
+ wildcard such as *.example.com.
+ It is used as if were an ordinary CNAME after the astrisk (*)
has been replaced with the query name.
- These records are usually resolved with ordinary CNAMEs
- outside the policy zones. They can be useful for logging.
+ The purpose for this special form is query logging in the
+ walled garden's authority DNS server.
</listitem>
<listitem>The <command>PASSTHRU</command> policy is specified
- by a CNAME whose target is the variable part of its own
- owner name. It causes the response to not be rewritten
+ by a CNAME whose target is <command>rpz_passthru.</command>
+ It causes the response to not be rewritten
and is most often used to "poke holes" in policies for
CIDR blocks.
+ (A CNAME whose target is the variable part of its owner name
+ is an obsolete specification of the PASSTHRU policy.)
</listitem>
</itemizedlist>
</para>
<para>
- The policies specified in individual records
- in an RPZ can be overridden with a <command>policy</command> clause
- in the <command>response-policy</command> option.
+ The actions specified in an RPZ can be overridden with a
+ <command>policy</command> clause in the
+ <command>response-policy</command> option.
An organization using an RPZ provided by another organization might
use this mechanism to redirect domains to its own walled garden.
<itemizedlist>
- <listitem><command>GIVEN</command> says "do not override."
+ <listitem><command>GIVEN</command> says "do not override but
+ perform the action specified in the zone."
</listitem>
<listitem><command>DISABLED</command> causes policy records to do
nothing but log what they might have done.
The response to the DNS query will be written according to
- any matching policy records that are not disabled.
- Policy zones overridden with <command>DISABLED</command> should
- appear first, because they will often not be logged
- if a higher precedence policy is found first.
+ any triggered policy records that are not disabled.
+ Disabled policy zones should appear first,
+ because they will often not be logged
+ if a higher precedence trigger is found first.
</listitem>
<listitem><command>PASSTHRU</command> causes all policy records
to act as if they were CNAME records with targets the variable
</itemizedlist>
</para>
+ <para>
+ By default, the actions encoded in an RPZ are applied
+ only to queries that ask for recursion (RD=1).
+ That default can be changed for a single RPZ or all RPZs in a view
+ with a <command>recursive-only no</command> clause.
+ This feature is useful for serving the same zone files
+ both inside and outside an RFC 1918 cloud and using RPZ to
+ delete answers that would otherwise contain RFC 1918 values
+ on the externally visible name server or view.
+ </para>
+
+ <para>
+ Also by default, RPZ actions are applied only to DNS requests that
+ either do not request DNSSEC metadata (DO=0) or when no DNSSEC
+ records are available for request name in the original zone (not
+ the response policy zone).
+ This default can be changed for all RPZs in a view with a
+ <command>break-dnssec yes</command> clause.
+ In that case, RPZ actions are applied regardless of DNSSEC.
+ The name of the clause option reflects the fact that results
+ rewritten by RPZ actions cannot verify.
+ </para>
+
+ <para>
+ The TTL of a record modified by RPZ policies is set from the
+ TTL of the relevant record in policy zone. It is then limited
+ to a maximum value.
+ The <command>max-policy-ttl</command> clause changes that
+ maximum from its default of 5.
+ </para>
+
<para>
For example, you might use this option statement
</para>
AAAA 2001:2::1
; do not rewrite (PASSTHRU) OK.DOMAIN.COM
-ok.domain.com CNAME ok.domain.com.
+ok.domain.com CNAME rpz-passthru.
bzone.domain.com CNAME garden.example.com.
; IP policy records that rewrite all answers for 127/8 except 127.0.0.1
8.0.0.0.127.rpz-ip CNAME .
-32.1.0.0.127.rpz-ip CNAME 32.1.0.0.127. ; PASSTHRU for 127.0.0.1
+32.1.0.0.127.rpz-ip CNAME rpz-passthru.
; NSDNAME and NSIP policy records
ns.domain.com.rpz-nsdname CNAME .
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: db.c,v 1.99 2011/10/13 01:32:33 vjs Exp $ */
+/* $Id: db.c,v 1.99.4.1 2011/10/23 20:12:07 vjs Exp $ */
/*! \file */
(db->methods->rpz_enabled)(db, st);
}
-isc_result_t
+void
dns_db_rpz_findips(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
dns_rdataset_t *ardataset, dns_rpz_st_t *st,
dns_name_t *query_qname)
{
- if (db->methods->rpz_findips == NULL)
- return (ISC_R_NOTIMPLEMENTED);
- return ((db->methods->rpz_findips)(rpz, rpz_type, zone, db, version,
- ardataset, st, query_qname));
+ if (db->methods->rpz_findips != NULL)
+ (db->methods->rpz_findips)(rpz, rpz_type, zone, db, version,
+ ardataset, st, query_qname);
}
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: db.h,v 1.107 2011/10/13 01:32:34 vjs Exp $ */
+/* $Id: db.h,v 1.107.4.1 2011/10/23 20:12:08 vjs Exp $ */
#ifndef DNS_DB_H
#define DNS_DB_H 1
isc_boolean_t (*isdnssec)(dns_db_t *db);
dns_stats_t *(*getrrsetstats)(dns_db_t *db);
void (*rpz_enabled)(dns_db_t *db, dns_rpz_st_t *st);
- isc_result_t (*rpz_findips)(dns_rpz_zone_t *rpz,
+ void (*rpz_findips)(dns_rpz_zone_t *rpz,
dns_rpz_type_t rpz_type,
dns_zone_t *zone, dns_db_t *db,
dns_dbversion_t *version,
* DNS_RPZ_TYPE_NSDNAME records.
*/
-isc_result_t
+void
dns_db_rpz_findips(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
dns_rdataset_t *ardataset, dns_rpz_st_t *st,
* \li 'ardataset' is an A or AAAA rdataset of addresses to check
* \li 'found' specifies the previous best match if any or
* or NULL, an empty name, 0, DNS_RPZ_POLICY_MISS, and 0
- *
- * Returns:
- * \li #ISC_R_SUCCESS
- * \li #ISC_R_UNEXPECTED
*/
ISC_LANG_ENDDECLS
#define DNS_RPZ_IP_ZONE "rpz-ip"
#define DNS_RPZ_NSIP_ZONE "rpz-nsip"
#define DNS_RPZ_NSDNAME_ZONE "rpz-nsdname"
+#define DNS_RPZ_PASSTHRU_ZONE "rpz-passthru"
typedef isc_uint8_t dns_rpz_cidr_bits_t;
struct dns_rpz_zone {
ISC_LINK(dns_rpz_zone_t) link;
- int num;
+ int num; /* ordinal in list of policy zones */
dns_name_t origin; /* Policy zone name */
dns_name_t nsdname; /* DNS_RPZ_NSDNAME_ZONE.origin */
- dns_rpz_policy_t policy; /* DNS_RPZ_POLICY_GIVEN or override */
+ dns_name_t passthru;/* DNS_RPZ_PASSTHRU_ZONE. */
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_boolean_t recursive_only;
};
/*
} dns_rpz_st_t;
#define DNS_RPZ_TTL_DEFAULT 5
+#define DNS_RPZ_MAX_TTL_DEFAULT DNS_RPZ_TTL_DEFAULT
/*
* So various response policy zone messages can be turned up or down.
#define DNS_RPZ_DEBUG_LEVEL1 ISC_LOG_DEBUG(1)
#define DNS_RPZ_DEBUG_LEVEL2 ISC_LOG_DEBUG(2)
#define DNS_RPZ_DEBUG_LEVEL3 ISC_LOG_DEBUG(3)
+#define DNS_RPZ_DEBUG_QUIET (DNS_RPZ_DEBUG_LEVEL3+1)
const char *
dns_rpz_type2str(dns_rpz_type_t type);
dns_name_t *search_name, dns_rpz_cidr_bits_t *prefix);
dns_rpz_policy_t
-dns_rpz_decode_cname(dns_rdataset_t *, dns_name_t *selfname);
+dns_rpz_decode_cname(dns_rpz_zone_t *rpz, dns_rdataset_t *rdataset,
+ dns_name_t *selfname);
ISC_LANG_ENDDECLS
dns_dns64list_t dns64;
unsigned int dns64cnt;
ISC_LIST(dns_rpz_zone_t) rpz_zones;
+ isc_boolean_t rpz_recursive_only;
+ isc_boolean_t rpz_break_dnssec;
/*
* Configurable data for server use only,
* configured earlier than this policy zone and does not have a higher
* precedence type.
*/
-static isc_result_t
+static void
rpz_findips(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
dns_rdataset_t *ardataset, dns_rpz_st_t *st,
if (rbtdb->rpz_cidr == NULL) {
RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
- return (ISC_R_UNEXPECTED);
+ return;
}
dns_fixedname_init(&selfnamef);
dns_name_format(qname, namebuf, sizeof(namebuf));
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
- "rpz_findips findnode(%s): %s",
+ "rpz_findips findnode(%s) failed: %s",
namebuf, isc_result_totext(result));
continue;
}
if (zrdataset.type != dns_rdatatype_cname) {
rpz_policy = DNS_RPZ_POLICY_RECORD;
} else {
- rpz_policy = dns_rpz_decode_cname(&zrdataset,
+ rpz_policy = dns_rpz_decode_cname(rpz,
+ &zrdataset,
selfname);
if (rpz_policy == DNS_RPZ_POLICY_RECORD ||
rpz_policy == DNS_RPZ_POLICY_WILDCNAME)
st->m.type = rpz_type;
st->m.prefix = prefix;
st->m.policy = rpz_policy;
- st->m.ttl = ttl;
+ st->m.ttl = ISC_MIN(ttl, rpz->max_policy_ttl);
st->m.result = result;
dns_name_copy(qname, st->qname, NULL);
if ((rpz_policy == DNS_RPZ_POLICY_RECORD ||
}
RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
- return (ISC_R_SUCCESS);
}
#endif
isc_mem_t *mctx;
isc_boolean_t have_nsdname; /* zone has NSDNAME record */
dns_rpz_cidr_node_t *root;
- dns_name_t ip_name; /* RPZ_IP_ZONE.LOCALHOST. */
- dns_name_t nsip_name; /* RPZ_NSIP_ZONE.LOCALHOST. */
- dns_name_t nsdname_name; /* RPZ_NSDNAME_ZONE.LOCALHOST */
+ dns_name_t ip_name; /* RPZ_IP_ZONE.origin. */
+ dns_name_t nsip_name; /* RPZ_NSIP_ZONE.origin. */
+ dns_name_t nsdname_name; /* RPZ_NSDNAME_ZONE.origin */
};
static isc_boolean_t have_rpz_zones = ISC_FALSE;
str = "NODATA";
break;
case DNS_RPZ_POLICY_RECORD:
- str = "records";
+ str = "Local-Data";
break;
case DNS_RPZ_POLICY_CNAME:
case DNS_RPZ_POLICY_WILDCNAME:
ISC_LIST_UNLINK(view->rpz_zones, zone, link);
if (dns_name_dynamic(&zone->origin))
dns_name_free(&zone->origin, view->mctx);
+ if (dns_name_dynamic(&zone->passthru))
+ dns_name_free(&zone->passthru, view->mctx);
if (dns_name_dynamic(&zone->nsdname))
dns_name_free(&zone->nsdname, view->mctx);
if (dns_name_dynamic(&zone->cname))
}
static void
-badname(int level, dns_name_t *name, const char *comment) {
+badname(int level, dns_name_t *name, const char *str1, const char *str2) {
char printname[DNS_NAME_FORMATSIZE];
- if (isc_log_wouldlog(dns_lctx, level)) {
+ if (level < DNS_RPZ_DEBUG_QUIET
+ && isc_log_wouldlog(dns_lctx, level)) {
dns_name_format(name, printname, sizeof(printname));
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
DNS_LOGMODULE_RBTDB, level,
- "invalid rpz \"%s\"%s", printname, comment);
+ "invalid rpz IP address \"%s\"%s%s",
+ printname, str1, str2);
}
}
dns_rpz_type_t type, dns_rpz_cidr_key_t *tgt_ip,
dns_rpz_cidr_bits_t *tgt_prefix)
{
- isc_buffer_t buffer;
- unsigned char data[DNS_NAME_MAXWIRE+1];
+ isc_result_t result;
dns_fixedname_t fname;
- dns_name_t *name;
- const char *cp, *end;
+ dns_name_t *ipname;
+ char ipstr[DNS_NAME_FORMATSIZE];
+ const char *prefix_str, *cp, *end;
char *cp2;
int ip_labels;
dns_rpz_cidr_bits_t bits;
ip_labels -= dns_name_countlabels(&cidr->ip_name);
ip_labels--;
if (ip_labels < 1) {
- badname(level, src_name, ", too short");
+ badname(level, src_name, "; too short", "");
return (ISC_R_FAILURE);
}
/*
- * Get text for the IP address without RPZ_x_ZONE.rpz.LOCALHOST.
+ * Get text for the IP address
*/
dns_fixedname_init(&fname);
- name = dns_fixedname_name(&fname);
+ ipname = dns_fixedname_name(&fname);
dns_name_split(src_name, dns_name_countlabels(&cidr->ip_name),
- name, NULL);
- isc_buffer_init(&buffer, data, sizeof(data));
- dns_name_totext(name, ISC_TRUE, &buffer);
- isc_buffer_putuint8(&buffer, '\0');
- cp = isc_buffer_base(&buffer);
-
- prefix = strtoul(cp, &cp2, 10);
- if (prefix < 1U || prefix > 128U || *cp2 != '.') {
- badname(level, src_name, ", bad prefix length");
+ ipname, NULL);
+ dns_name_format(ipname, ipstr, sizeof(ipstr));
+ end = &ipstr[strlen(ipstr)+1];
+ prefix_str = ipstr;
+
+ prefix = strtoul(prefix_str, &cp2, 10);
+ if (*cp2 != '.') {
+ badname(level, src_name,
+ "; invalid leading prefix length", "");
+ return (ISC_R_FAILURE);
+ }
+ *cp2 = '\0';
+ if (prefix < 1U || prefix > 128U) {
+ badname(level, src_name,
+ "; invalid prefix length of ", prefix_str);
return (ISC_R_FAILURE);
}
cp = cp2+1;
- end = isc_buffer_used(&buffer);
if (ip_labels == 4 && !strchr(cp, 'z')) {
/*
* Convert an IPv4 address
* from the form "prefix.w.z.y.x"
*/
if (prefix > 32U) {
- badname(level, src_name, "; bad IPv4 prefix length");
+ badname(level, src_name,
+ "; invalid IPv4 prefix length of ", prefix_str);
return (ISC_R_FAILURE);
}
prefix += 96;
for (i = 0; i < 32; i += 8) {
l = strtoul(cp, &cp2, 10);
if (l > 255U || (*cp2 != '.' && *cp2 != '\0')) {
- badname(level, src_name, "; bad IPv4 address");
+ if (*cp2 == '.')
+ *cp2 = '\0';
+ badname(level, src_name,
+ "; invalid IPv4 octet ", cp);
return (ISC_R_FAILURE);
}
tgt_ip->w[3] |= l << i;
l = strtoul(cp, &cp2, 16);
if (l > 0xffffu ||
(*cp2 != '.' && *cp2 != '\0')) {
- badname(level, src_name, "");
+ if (*cp2 == '.')
+ *cp2 = '\0';
+ badname(level, src_name,
+ "; invalid IPv6 word ", cp);
return (ISC_R_FAILURE);
}
if ((i & 1) == 0)
}
}
if (cp != end) {
- badname(level, src_name, "");
+ badname(level, src_name, "", "");
return (ISC_R_FAILURE);
}
i = bits % DNS_RPZ_CIDR_WORD_BITS;
aword = tgt_ip->w[bits / DNS_RPZ_CIDR_WORD_BITS];
if ((aword & ~DNS_RPZ_WORD_MASK(i)) != 0) {
- badname(level, src_name, "; wrong prefix length");
+ badname(level, src_name,
+ "; too small prefix length of ", prefix_str);
return (ISC_R_FAILURE);
}
bits -= i;
}
/*
- * Convert the IPv6 address back to a canonical policy domain name
+ * Convert the address back to a canonical policy domain name
* to ensure that it is in canonical form.
*/
- if (ISC_R_SUCCESS != ip2name(cidr, tgt_ip, (dns_rpz_cidr_bits_t)prefix,
- type, NULL, name) ||
- !dns_name_equal(src_name, name)) {
- badname(level, src_name, "; not canonical");
+ result = ip2name(cidr, tgt_ip, (dns_rpz_cidr_bits_t) prefix,
+ type, NULL, ipname);
+ if (result != ISC_R_SUCCESS || !dns_name_equal(src_name, ipname)) {
+ badname(level, src_name, "; not canonical", "");
return (ISC_R_FAILURE);
}
*/
void
dns_rpz_cidr_addip(dns_rpz_cidr_t *cidr, dns_name_t *name) {
+ isc_result_t result;
dns_rpz_cidr_key_t tgt_ip;
dns_rpz_cidr_bits_t tgt_prefix;
dns_rpz_type_t type;
case DNS_RPZ_TYPE_BAD:
return;
}
- if (ISC_R_SUCCESS != name2ipkey(cidr, DNS_RPZ_ERROR_LEVEL, name,
- type, &tgt_ip, &tgt_prefix))
+ result = name2ipkey(cidr, DNS_RPZ_ERROR_LEVEL, name,
+ type, &tgt_ip, &tgt_prefix);
+ if (result != ISC_R_SUCCESS)
return;
- if (ISC_R_EXISTS == search(cidr, &tgt_ip, tgt_prefix, type,
- ISC_TRUE, NULL) &&
- isc_log_wouldlog(dns_lctx, DNS_RPZ_ERROR_LEVEL)) {
+ result = search(cidr, &tgt_ip, tgt_prefix, type, ISC_TRUE, NULL);
+ if (result == ISC_R_EXISTS &&
+ isc_log_wouldlog(dns_lctx, DNS_RPZ_ERROR_LEVEL))
+ {
char printname[DNS_NAME_FORMATSIZE];
dns_name_format(name, printname, sizeof(printname));
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
- "duplicate rpz name \"%s\"", printname);
+ "rpz add failed; \"%s\" is a duplicate name",
+ printname);
}
}
*/
void
dns_rpz_cidr_deleteip(dns_rpz_cidr_t *cidr, dns_name_t *name) {
+ isc_result_t result;
dns_rpz_cidr_key_t tgt_ip;
dns_rpz_cidr_bits_t tgt_prefix;
dns_rpz_type_t type;
/*
* Do not get excited about the deletion of interior rbt nodes.
*/
- if (ISC_R_SUCCESS != name2ipkey(cidr, DNS_RPZ_DEBUG_LEVEL3, name,
- type, &tgt_ip, &tgt_prefix))
+ result = name2ipkey(cidr, DNS_RPZ_DEBUG_QUIET, name,
+ type, &tgt_ip, &tgt_prefix);
+ if (result != ISC_R_SUCCESS)
return;
- if (ISC_R_SUCCESS != search(cidr, &tgt_ip, tgt_prefix, type,
- ISC_FALSE, &tgt)) {
- if (isc_log_wouldlog(dns_lctx, DNS_RPZ_ERROR_LEVEL)) {
- char printname[DNS_NAME_FORMATSIZE];
-
- dns_name_format(name, printname, sizeof(printname));
- isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
- DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
- "missing rpz node \"%s\"", printname);
- }
+
+ result = search(cidr, &tgt_ip, tgt_prefix, type, ISC_FALSE, &tgt);
+ if (result != ISC_R_SUCCESS) {
+ badname(DNS_RPZ_ERROR_LEVEL, name, "; missing rpz node", "");
return;
}
* Translate CNAME rdata to a QNAME response policy action.
*/
dns_rpz_policy_t
-dns_rpz_decode_cname(dns_rdataset_t *rdataset, dns_name_t *selfname) {
+dns_rpz_decode_cname(dns_rpz_zone_t *rpz, dns_rdataset_t *rdataset,
+ dns_name_t *selfname)
+{
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdata_cname_t cname;
isc_result_t result;
}
/*
- * 128.1.0.127.rpz-ip CNAME 128.1.0.0.127. means "do not rewrite"
+ * CNAME PASSTHRU.origin means "do not rewrite.
+ */
+ if (dns_name_equal(&cname.cname, &rpz->passthru))
+ return (DNS_RPZ_POLICY_PASSTHRU);
+
+ /*
+ * 128.1.0.127.rpz-ip CNAME 128.1.0.0.127. is obsolete PASSTHRU
*/
if (selfname != NULL && dns_name_equal(&cname.cname, selfname))
return (DNS_RPZ_POLICY_PASSTHRU);
view->v6_aaaa = dns_aaaa_ok;
view->aaaa_acl = NULL;
ISC_LIST_INIT(view->rpz_zones);
+ view->rpz_recursive_only = ISC_TRUE;
+ view->rpz_break_dnssec = ISC_FALSE;
dns_fixedname_init(&view->dlv_fixed);
view->managed_keys = NULL;
view->redirect = NULL;
-/*
+/*%
* response-policy {
* zone <string> [ policy (given|disabled|passthru|
- * nxdomain|nodata|cname <domain> ) ];
- * };
- *
- * this is a chimera of doc_optional_keyvalue() and cfg_doc_enum()
+ * nxdomain|nodata|cname <domain> ) ]
+ * [ recursive-only yes|no ]
+ * [ max-policy-ttl number ] ;
+ * } [ recursive-only yes|no ] [ break-dnssec yes|no ]
+ * [ max-policy-ttl number ] ;
*/
+
static void
-doc_rpz_policies(cfg_printer_t *pctx, const cfg_type_t *type) {
- const keyword_type_t *kw;
+doc_rpz_policy(cfg_printer_t *pctx, const cfg_type_t *type) {
const char * const *p;
-
- kw = type->of;
- cfg_print_chars(pctx, "[ ", 2);
- cfg_print_cstr(pctx, kw->name);
- cfg_print_chars(pctx, " ", 1);
-
+ /*
+ * This is cfg_doc_enum() without the trailing " )".
+ */
cfg_print_chars(pctx, "( ", 2);
- for (p = kw->type->of; *p != NULL; p++) {
+ for (p = type->of; *p != NULL; p++) {
cfg_print_cstr(pctx, *p);
if (p[1] != NULL)
cfg_print_chars(pctx, " | ", 3);
}
}
-/*
- * print_qstring() from parser.c
- */
-static void
-print_rpz_cname(cfg_printer_t *pctx, const cfg_obj_t *obj)
-{
- cfg_print_chars(pctx, "\"", 1);
- cfg_print_ustring(pctx, obj);
- cfg_print_chars(pctx, "\"", 1);
-}
-
static void
doc_rpz_cname(cfg_printer_t *pctx, const cfg_type_t *type) {
cfg_doc_terminal(pctx, type);
- cfg_print_chars(pctx, " ) ]", 4);
+ cfg_print_chars(pctx, " )", 2);
}
+/*
+ * Parse
+ * given|disabled|passthru|nxdomain|nodata|cname <domain>
+ */
static isc_result_t
-parse_rpz(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+cfg_parse_rpz_policy(cfg_parser_t *pctx, const cfg_type_t *type,
+ cfg_obj_t **ret)
+{
isc_result_t result;
- cfg_obj_t *obj = NULL;
- const cfg_tuplefielddef_t *fields = type->of;
+ cfg_obj_t *obj;
+ const cfg_tuplefielddef_t *fields;
CHECK(cfg_create_tuple(pctx, type, &obj));
+
+ fields = type->of;
CHECK(cfg_parse_obj(pctx, fields[0].type, &obj->value.tuple[0]));
- CHECK(cfg_parse_obj(pctx, fields[1].type, &obj->value.tuple[1]));
/*
* parse cname domain only after "policy cname"
*/
- if (cfg_obj_isvoid(obj->value.tuple[1]) ||
- strcasecmp("cname", cfg_obj_asstring(obj->value.tuple[1]))) {
- CHECK(cfg_parse_void(pctx, NULL, &obj->value.tuple[2]));
+ if (strcasecmp("cname", cfg_obj_asstring(obj->value.tuple[0])) != 0) {
+ CHECK(cfg_parse_void(pctx, NULL, &obj->value.tuple[1]));
} else {
- CHECK(cfg_parse_obj(pctx, fields[2].type, &obj->value.tuple[2]));
+ CHECK(cfg_parse_obj(pctx, fields[1].type,
+ &obj->value.tuple[1]));
}
*ret = obj;
return (result);
}
+/*
+ * Parse a tuple consisting of any kind of required field followed
+ * by 2 or more optional keyvalues that can be in any order.
+ */
+static isc_result_t
+cfg_parse_kv_tuple(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+ const cfg_tuplefielddef_t *fields, *f;
+ cfg_obj_t *obj;
+ int fn;
+ isc_result_t result;
+
+ obj = NULL;
+ CHECK(cfg_create_tuple(pctx, type, &obj));
+
+ /*
+ * The zone first field is required and always first.
+ */
+ fields = type->of;
+ CHECK(cfg_parse_obj(pctx, fields[0].type, &obj->value.tuple[0]));
+
+ for (;;) {
+ CHECK(cfg_peektoken(pctx, CFG_LEXOPT_QSTRING));
+ if (pctx->token.type != isc_tokentype_string)
+ break;
+
+ for (fn = 1, f = &fields[1]; ; ++fn, ++f) {
+ if (f->name == NULL) {
+ cfg_parser_error(pctx, 0, "unexpected '%s'",
+ TOKEN_STRING(pctx));
+ result = ISC_R_UNEXPECTEDTOKEN;
+ goto cleanup;
+ }
+ if (obj->value.tuple[fn] == NULL &&
+ strcasecmp(f->name, TOKEN_STRING(pctx)) == 0)
+ break;
+ }
+
+ CHECK(cfg_gettoken(pctx, 0));
+ CHECK(cfg_parse_obj(pctx, f->type, &obj->value.tuple[fn]));
+ }
+
+ for (fn = 1, f = &fields[1]; f->name != NULL; ++fn, ++f) {
+ if (obj->value.tuple[fn] == NULL)
+ CHECK(cfg_parse_void(pctx, NULL,
+ &obj->value.tuple[fn]));
+ }
+
+ *ret = obj;
+ return (ISC_R_SUCCESS);
+
+cleanup:
+ CLEANUP_OBJ(obj);
+ return (result);
+}
+
+static void
+cfg_print_kv_tuple(cfg_printer_t *pctx, const cfg_obj_t *obj) {
+ unsigned int i;
+ const cfg_tuplefielddef_t *fields, *f;
+ const cfg_obj_t *fieldobj;
+
+ fields = obj->type->of;
+ for (f = fields, i = 0; f->name != NULL; f++, i++) {
+ fieldobj = obj->value.tuple[i];
+ if (fieldobj->type->print == cfg_print_void)
+ continue;
+ if (i != 0) {
+ cfg_print_chars(pctx, " ", 1);
+ cfg_print_cstr(pctx, f->name);
+ cfg_print_chars(pctx, " ", 1);
+ }
+ cfg_print_obj(pctx, fieldobj);
+ }
+}
+
+static void
+cfg_doc_kv_tuple(cfg_printer_t *pctx, const cfg_type_t *type) {
+ const cfg_tuplefielddef_t *fields, *f;
+
+ fields = type->of;
+ for (f = fields; f->name != NULL; f++) {
+ if (f != fields) {
+ cfg_print_chars(pctx, " [ ", 3);
+ cfg_print_cstr(pctx, f->name);
+ if (f->type->doc != cfg_doc_void)
+ cfg_print_chars(pctx, " ", 1);
+ }
+ cfg_doc_obj(pctx, f->type);
+ if (f != fields)
+ cfg_print_chars(pctx, " ]", 2);
+ }
+}
+
+static keyword_type_t zone_kw = {"zone", &cfg_type_qstring};
+static cfg_type_t cfg_type_rpz_zone = {
+ "zone", parse_keyvalue, print_keyvalue,
+ doc_keyvalue, &cfg_rep_string,
+ &zone_kw
+};
static const char *rpz_policies[] = {
"given", "disabled", "passthru", "no-op", "nxdomain", "nodata",
"cname", NULL
};
-static cfg_type_t cfg_type_rpz_policylist = {
- "policies", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
- &cfg_rep_string, &rpz_policies
+static cfg_type_t cfg_type_rpz_policy_name = {
+ "policy name", cfg_parse_enum, cfg_print_ustring,
+ doc_rpz_policy, &cfg_rep_string,
+ &rpz_policies
};
-static keyword_type_t rpz_policies_kw = {
- "policy", &cfg_type_rpz_policylist
+static cfg_type_t cfg_type_rpz_cname = {
+ "quoted_string", cfg_parse_astring, NULL,
+ doc_rpz_cname, &cfg_rep_string,
+ NULL
};
-static cfg_type_t cfg_type_rpz_policy = {
- "optional_policy", parse_optional_keyvalue, print_keyvalue,
- doc_rpz_policies, &cfg_rep_string, &rpz_policies_kw
+static cfg_tuplefielddef_t rpz_policy_fields[] = {
+ { "policy name", &cfg_type_rpz_policy_name, 0 },
+ { "cname", &cfg_type_rpz_cname, 0 },
+ { NULL, NULL, 0 }
};
-static cfg_type_t cfg_type_cname = {
- "domain", cfg_parse_astring, print_rpz_cname, doc_rpz_cname,
- &cfg_rep_string, NULL
+static cfg_type_t cfg_type_rpz_policy = {
+ "policy tuple", cfg_parse_rpz_policy,
+ cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple,
+ rpz_policy_fields
};
-static cfg_tuplefielddef_t rpzone_fields[] = {
- { "name", &cfg_type_astring, 0 },
+static cfg_tuplefielddef_t rpz_zone_fields[] = {
+ { "zone name", &cfg_type_rpz_zone, 0 },
{ "policy", &cfg_type_rpz_policy, 0 },
- { "cname", &cfg_type_cname, 0 },
+ { "recursive-only", &cfg_type_boolean, 0 },
+ { "max-policy-ttl", &cfg_type_uint32, 0 },
{ NULL, NULL, 0 }
};
-static cfg_type_t cfg_type_rpzone = {
- "rpzone", parse_rpz, cfg_print_tuple, cfg_doc_tuple,
- &cfg_rep_tuple, rpzone_fields
+static cfg_type_t cfg_type_rpz_tuple = {
+ "rpz tuple", cfg_parse_kv_tuple,
+ cfg_print_kv_tuple, cfg_doc_kv_tuple, &cfg_rep_tuple,
+ rpz_zone_fields
};
-static cfg_clausedef_t rpz_clauses[] = {
- { "zone", &cfg_type_rpzone, CFG_CLAUSEFLAG_MULTI },
- { NULL, NULL, 0 }
+static cfg_type_t cfg_type_rpz_list = {
+ "zone list", cfg_parse_bracketed_list, cfg_print_bracketed_list,
+ cfg_doc_bracketed_list, &cfg_rep_list,
+ &cfg_type_rpz_tuple
};
-static cfg_clausedef_t *rpz_clausesets[] = {
- rpz_clauses,
- NULL
+static cfg_tuplefielddef_t rpz_fields[] = {
+ { "zone list", &cfg_type_rpz_list, 0 },
+ { "recursive-only", &cfg_type_boolean, 0 },
+ { "break-dnssec", &cfg_type_boolean, 0 },
+ { "max-policy-ttl", &cfg_type_uint32, 0 },
+ { NULL, NULL, 0 }
};
static cfg_type_t cfg_type_rpz = {
- "rpz", cfg_parse_map, cfg_print_map, cfg_doc_map,
- &cfg_rep_map, rpz_clausesets
+ "rpz", cfg_parse_kv_tuple,
+ cfg_print_kv_tuple, cfg_doc_kv_tuple, &cfg_rep_tuple,
+ rpz_fields
};
-
/*%
* dnssec-lookaside
*/
./bin/tests/system/rpz/clean.sh SH 2011,2012
./bin/tests/system/rpz/ns1/named.conf CONF-C 2011
./bin/tests/system/rpz/ns1/root.db ZONE 2011,2012
+./bin/tests/system/rpz/ns2/base-tld2s.db ZONE 2012
./bin/tests/system/rpz/ns2/hints ZONE 2011
./bin/tests/system/rpz/ns2/named.conf CONF-C 2011,2012
./bin/tests/system/rpz/ns2/tld2.db ZONE 2011
./bin/tests/system/rpz/ns3/crash2 X 2011
./bin/tests/system/rpz/ns3/hints ZONE 2011
./bin/tests/system/rpz/ns3/named.conf CONF-C 2011
-./bin/tests/system/rpz/ns4/hints X 2011
+./bin/tests/system/rpz/ns4/hints ZONE 2011
./bin/tests/system/rpz/ns4/named.conf CONF-C 2011
./bin/tests/system/rpz/ns4/tld4.db ZONE 2011
+./bin/tests/system/rpz/ns5/hints ZONE 2011
+./bin/tests/system/rpz/ns5/named.conf CONF-C 2012
+./bin/tests/system/rpz/qperf.sh SH 2012
./bin/tests/system/rpz/rpz.c C 2011
./bin/tests/system/rpz/setup.sh SH 2011,2012
./bin/tests/system/rpz/test1 X 2011,2012