Commit febaa091 authored by Andreas Gustafsson's avatar Andreas Gustafsson

551. [func] Implemented the 'sortlist' option.

parent 9a6314a0
551. [func] Implemented the 'sortlist' option.
550. [func] Support unknown rdata types and classes.
549. [bug] "make" did not immediately abort the build when a
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: query.c,v 1.143 2000/11/09 19:55:16 mws Exp $ */
/* $Id: query.c,v 1.144 2000/11/10 03:16:14 gson Exp $ */
#include <config.h>
......@@ -2097,6 +2097,147 @@ do { \
want_restart = ISC_FALSE; \
} while (0)
/*
* Extract a network address from the RDATA of an A or AAAA
* record.
*
* Returns:
* ISC_R_SUCCESS
* ISC_R_NOTIMPLEMENTED The rdata is not a known address type.
*/
static isc_result_t
rdata_tonetaddr(dns_rdata_t *rdata, isc_netaddr_t *netaddr) {
struct in_addr ina;
struct in6_addr in6a;
switch (rdata->type) {
case dns_rdatatype_a:
INSIST(rdata->length == 4);
memcpy(&ina.s_addr, rdata->data, 4);
isc_netaddr_fromin(netaddr, &ina);
return (ISC_R_SUCCESS);
case dns_rdatatype_aaaa:
INSIST(rdata->length == 16);
memcpy(in6a.s6_addr, rdata->data, 16);
isc_netaddr_fromin6(netaddr, &in6a);
return (ISC_R_SUCCESS);
default:
return (ISC_R_NOTIMPLEMENTED);
}
}
/*
* Find the sort order of 'rdata' in the topology-like
* ACL forming the second element in a 2-element top-level
* sortlist statement.
*/
static int
sortlist_order_2element(dns_rdata_t *rdata, void *arg) {
dns_acl_t *sortacl = (dns_acl_t *) arg;
isc_netaddr_t netaddr;
int match;
if (rdata_tonetaddr(rdata, &netaddr) != ISC_R_SUCCESS)
return (INT_MAX);
(void)dns_acl_match(&netaddr, NULL, sortacl,
&ns_g_server->aclenv,
&match, NULL);
if (match > 0)
return (match);
else
return (INT_MAX - (-match));
}
/*
* Find the sort order of 'rdata' in the matching element
* of a 1-element top-level sortlist statement.
*/
static int
sortlist_order_1element(dns_rdata_t *rdata, void *arg) {
dns_aclelement_t *matchelt = (dns_aclelement_t *) arg;
isc_netaddr_t netaddr;
if (rdata_tonetaddr(rdata, &netaddr) != ISC_R_SUCCESS)
return (INT_MAX);
if (dns_aclelement_match(&netaddr, NULL, matchelt,
&ns_g_server->aclenv,
NULL)) {
return (0);
} else {
return (INT_MAX);
}
}
/*
* Find the sortlist element that applies to 'client',
* store data identifying it in '*data', and set up
* the sortlist info in in client->message appropriately.
*
* '*data' must persist until the message has been rendered.
*/
static void
setup_sortlist(ns_client_t *client) {
isc_netaddr_t netaddr;
dns_acl_t *acl = client->view->sortlist;
unsigned int i;
if (acl == NULL)
goto dont_sort;
isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
for (i = 0; i < acl->length; i++) {
/*
* 'e' refers to the current 'top level statement'
* in the sortlist (see ARM).
*/
dns_aclelement_t *e = &acl->elements[i];
dns_aclelement_t *matchelt = NULL;
dns_acl_t *inner;
if (e->type != dns_aclelementtype_nestedacl)
goto dont_sort;
inner = e->u.nestedacl;
if (inner->length < 1 || inner->length > 2)
goto dont_sort;
if (inner->elements[0].negative)
goto dont_sort;
if (dns_aclelement_match(&netaddr, client->signer,
&inner->elements[0],
&ns_g_server->aclenv,
&matchelt)) {
if (inner->length == 2) {
dns_aclelement_t *elt1 = &inner->elements[1];
if (elt1->type != dns_aclelementtype_nestedacl)
goto dont_sort;
dns_message_setsortorder(client->message,
sortlist_order_2element,
elt1->u.nestedacl);
return;
} else {
INSIST(matchelt != NULL);
dns_message_setsortorder(client->message,
sortlist_order_1element,
matchelt);
return;
}
}
}
/* No match; don't sort. */
dont_sort:
dns_message_setsortorder(client->message, NULL, NULL);
return;
}
static void
query_find(ns_client_t *client, dns_fetchevent_t *event) {
dns_db_t *db, *zdb;
......@@ -3009,10 +3150,13 @@ query_find(ns_client_t *client, dns_fetchevent_t *event) {
ns_client_detach(&client);
} else if (!RECURSING(client)) {
/*
* We are done. Make a final tweak to the AA bit if the
* auth-nxdomain config option says so, then send the
* response.
* We are done. Set up sortlist data for the message
* rendering code, make a final tweak to the AA bit if the
* auth-nxdomain config option says so, then render and
* send the response.
*/
setup_sortlist(client);
if (client->message->rcode == dns_rcode_nxdomain &&
client->view->auth_nxdomain == ISC_TRUE)
client->message->flags |= DNS_MESSAGEFLAG_AA;
......
#!/bin/sh
#
# Copyright (C) 2000 Internet Software Consortium.
#
# Permission to use, copy, modify, and 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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS
# ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
# CONSORTIUM 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: clean.sh,v 1.1 2000/11/10 03:16:16 gson Exp $
rm -f *.dig *.good
; Copyright (C) 2000 Internet Software Consortium.
;
; Permission to use, copy, modify, and 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 INTERNET SOFTWARE CONSORTIUM
; DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
; INTERNET SOFTWARE CONSORTIUM 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: example.db,v 1.1 2000/11/10 03:16:16 gson Exp $
$TTL 300 ; 5 minutes
@ IN SOA ns2.example. hostmaster.example. (
2000042795 ; serial
20 ; refresh (20 seconds)
20 ; retry (20 seconds)
1814400 ; expire (3 weeks)
3600 ; minimum (1 hour)
)
example. NS ns1.example.
ns2.example. A 10.53.0.1
; Let's see what the sortlist picks out of this...
a A 1.1.1.1
a A 1.1.1.2
a A 192.168.3.1
a A 1.1.1.3
a A 192.168.1.1
a A 1.1.1.4
b A 10.53.0.1
b A 10.53.0.2
b A 10.53.0.3
b A 10.53.0.4
b A 10.53.0.5
/*
* Copyright (C) 2000 Internet Software Consortium.
*
* Permission to use, copy, modify, and 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 INTERNET SOFTWARE CONSORTIUM
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* INTERNET SOFTWARE CONSORTIUM 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 2000/11/10 03:16:16 gson Exp $ */
options {
query-source address 10.53.0.1;
port 5300;
pid-file "named.pid";
listen-on { 10.53.0.1; };
listen-on-v6 { none; };
recursion no;
notify yes;
sortlist {
{ 10.53.0.1; // IF 10.53.0.1
{ // THEN first fit on the
192.168.3/24; // following nets
{ 192.168.2/24; 192.168.1/24; }; }; };
{ { 10.53.0.2; 10.53.0.3; }; }; // Prefer self
};
};
zone "." {
type master;
file "root.db";
};
zone "example" {
type master;
file "example.db";
};
; Copyright (C) 2000 Internet Software Consortium.
;
; Permission to use, copy, modify, and 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 INTERNET SOFTWARE CONSORTIUM
; DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
; INTERNET SOFTWARE CONSORTIUM 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: root.db,v 1.1 2000/11/10 03:16:16 gson Exp $
$TTL 300
. IN SOA gson.nominum.com. a.root.servers.nil. (
2000042100 ; serial
600 ; refresh
600 ; retry
1200 ; expire
600 ; minimum
)
. NS a.root-servers.nil.
a.root-servers.nil. A 10.53.0.1
example. NS ns2.example.
ns2.example. A 10.53.0.2
#!/bin/sh
#
# Copyright (C) 2000 Internet Software Consortium.
#
# Permission to use, copy, modify, and 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 INTERNET SOFTWARE CONSORTIUM
# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# INTERNET SOFTWARE CONSORTIUM 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: tests.sh,v 1.1 2000/11/10 03:16:16 gson Exp $
SYSTEMTESTTOP=..
. $SYSTEMTESTTOP/conf.sh
status=0
echo "I:test 2-element sortlist statement"
cat <<EOF >test1.good
a.example. 300 IN A 192.168.3.1
a.example. 300 IN A 192.168.1.1
EOF
$DIG +tcp +noadd +nosea +nostat +noquest +noauth +nocomm +nocmd a.example. \
@10.53.0.1 -b 10.53.0.1 -p 5300 | head -2 >test1.dig
# Note that this can't use digcomp.pl because here, the ordering of the
# result RRs is significant.
diff test1.dig test1.good || status=1
echo "I:test 1-element sortlist statement"
for n in 2 3
do
cat <<EOF >test2.good
b.example. 300 IN A 10.53.0.$n
EOF
$DIG +tcp +noadd +nosea +nostat +noquest +noauth +nocomm +nocmd \
b.example. \
@10.53.0.1 -b 10.53.0.$n -p 5300 | head -1 >test2.dig
diff test2.dig test2.good || status=1
done
echo "I:exit status: $status"
exit $status
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: acl.c,v 1.14 2000/08/11 01:53:46 gson Exp $ */
/* $Id: acl.c,v 1.15 2000/11/10 03:16:16 gson Exp $ */
#include <config.h>
......@@ -130,84 +130,17 @@ dns_acl_match(isc_netaddr_t *reqaddr,
int *match,
dns_aclelement_t **matchelt)
{
isc_result_t result;
unsigned int i;
int indirectmatch;
REQUIRE(reqaddr != NULL);
REQUIRE(matchelt == NULL || *matchelt == NULL);
for (i = 0; i < acl->length; i++) {
dns_aclelement_t *e = &acl->elements[i];
dns_acl_t *inner = NULL;
switch (e->type) {
case dns_aclelementtype_ipprefix:
if (isc_netaddr_eqprefix(reqaddr,
&e->u.ip_prefix.address,
e->u.ip_prefix.prefixlen))
goto matched;
break;
case dns_aclelementtype_keyname:
if (reqsigner != NULL &&
dns_name_equal(reqsigner, &e->u.keyname))
goto matched;
break;
case dns_aclelementtype_nestedacl:
inner = e->u.nestedacl;
nested:
result = dns_acl_match(reqaddr, reqsigner,
inner,
env,
&indirectmatch, matchelt);
if (result != ISC_R_SUCCESS)
return (result);
/*
* Treat negative matches in indirect ACLs as
* "no match".
* That way, a negated indirect ACL will never become
* a surprise positive match through double negation.
* XXXDCL this should be documented.
*/
if (indirectmatch > 0)
goto matched;
/*
* A negative indirect match may have set *matchelt,
* but we don't want it set when we return.
*/
if (matchelt != NULL)
*matchelt = NULL;
break;
case dns_aclelementtype_any:
matched:
if (dns_aclelement_match(reqaddr, reqsigner, e, env, matchelt)) {
*match = e->negative ? -(i+1) : (i+1);
if (matchelt != NULL)
*matchelt = e;
return (ISC_R_SUCCESS);
case dns_aclelementtype_localhost:
if (env != NULL && env->localhost != NULL) {
inner = env->localhost;
goto nested;
} else {
break;
}
case dns_aclelementtype_localnets:
if (env != NULL && env->localnets != NULL) {
inner = env->localnets;
goto nested;
} else {
break;
}
default:
INSIST(0);
break;
}
}
/* No match. */
......@@ -215,6 +148,89 @@ dns_acl_match(isc_netaddr_t *reqaddr,
return (ISC_R_SUCCESS);
}
isc_boolean_t
dns_aclelement_match(isc_netaddr_t *reqaddr,
dns_name_t *reqsigner,
dns_aclelement_t *e,
dns_aclenv_t *env,
dns_aclelement_t **matchelt)
{
dns_acl_t *inner = NULL;
int indirectmatch;
isc_result_t result;
switch (e->type) {
case dns_aclelementtype_ipprefix:
if (isc_netaddr_eqprefix(reqaddr,
&e->u.ip_prefix.address,
e->u.ip_prefix.prefixlen))
goto matched;
break;
case dns_aclelementtype_keyname:
if (reqsigner != NULL &&
dns_name_equal(reqsigner, &e->u.keyname))
goto matched;
break;
case dns_aclelementtype_nestedacl:
inner = e->u.nestedacl;
nested:
result = dns_acl_match(reqaddr, reqsigner,
inner,
env,
&indirectmatch, matchelt);
if (result != ISC_R_SUCCESS)
return (result);
/*
* Treat negative matches in indirect ACLs as
* "no match".
* That way, a negated indirect ACL will never become
* a surprise positive match through double negation.
* XXXDCL this should be documented.
*/
if (indirectmatch > 0)
goto matchelt_set;
/*
* A negative indirect match may have set *matchelt,
* but we don't want it set when we return.
*/
if (matchelt != NULL)
*matchelt = NULL;
break;
case dns_aclelementtype_any:
matched:
if (matchelt != NULL)
*matchelt = e;
matchelt_set:
return (ISC_TRUE);
case dns_aclelementtype_localhost:
if (env != NULL && env->localhost != NULL) {
inner = env->localhost;
goto nested;
} else {
break;
}
case dns_aclelementtype_localnets:
if (env != NULL && env->localnets != NULL) {
inner = env->localnets;
goto nested;
} else {
break;
}
default:
INSIST(0);
break;
}
return (ISC_FALSE);
}
void
dns_acl_attach(dns_acl_t *source, dns_acl_t **target) {
REQUIRE(DNS_ACL_VALID(source));
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: confctx.c,v 1.99 2000/11/08 03:53:13 marka Exp $ */
/* $Id: confctx.c,v 1.100 2000/11/10 03:16:21 gson Exp $ */
#include <config.h>
......@@ -515,13 +515,6 @@ dns_c_checkconfig(dns_c_ctx_t *cfg)
"option 'topology' is deprecated");
}
if (dns_c_ctx_getsortlist(cfg, &ipml) != ISC_R_NOTFOUND) {
dns_c_ipmatchlist_detach(&ipml);
isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG,
DNS_LOGMODULE_CONFIG, ISC_LOG_WARNING,
"option 'sortlist' is not yet implemented");
}
if (dns_c_ctx_getrrsetorderlist(cfg, &olist) != ISC_R_NOTFOUND) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_CONFIG,
DNS_LOGMODULE_CONFIG, ISC_LOG_WARNING,
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: acl.h,v 1.14 2000/11/07 23:43:23 bwelling Exp $ */
/* $Id: acl.h,v 1.15 2000/11/10 03:16:23 gson Exp $ */
#ifndef DNS_ACL_H
#define DNS_ACL_H 1
......@@ -167,6 +167,21 @@ dns_acl_match(isc_netaddr_t *reqaddr,
* ISC_R_SUCCESS Always succeeds.
*/
isc_boolean_t
dns_aclelement_match(isc_netaddr_t *reqaddr,
dns_name_t *reqsigner,
dns_aclelement_t *e,
dns_aclenv_t *env,
dns_aclelement_t **matchelt);
/*
* Like dns_acl_match, but matches against the single ACL element 'e'
* rather than a complete list and returns ISC_TRUE iff it matched.
* To determine whether the match was prositive or negative, the
* caller should examine e->negative. Since the element 'e' may be
* a reference to a named ACL or a nested ACL, the matching element
* returned through 'matchelt' is not necessarily 'e' itself.
*/
ISC_LANG_ENDDECLS
#endif /* DNS_ACL_H */
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: message.h,v 1.80 2000/11/10 03:13:03 gson Exp $ */
/* $Id: message.h,v 1.81 2000/11/10 03:16:24 gson Exp $ */