Commit 30e6ea9d authored by Brian Wellington's avatar Brian Wellington
Browse files

405. [func] Add support for selective forwarding (forward zones)

parent 21f710a0
405. [func] Add support for selective forwarding (forward zones)
404. [bug] The request library didn't completely work with IPv6.
403. [bug] "host" did not use the search list.
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: lwresd.c,v 1.13 2000/08/01 01:11:50 tale Exp $ */
/* $Id: lwresd.c,v 1.14 2000/08/24 22:15:26 bwelling Exp $ */
/*
* Main program for the Lightweight Resolver Daemon.
......@@ -40,6 +40,7 @@
#include <dns/cache.h>
#include <dns/db.h>
#include <dns/dispatch.h>
#include <dns/forward.h>
#include <dns/log.h>
#include <dns/resolver.h>
#include <dns/result.h>
......@@ -268,14 +269,16 @@ ns_lwresd_createview(ns_lwresd_t *lwresd, dns_view_t **viewp) {
if (ISC_LIST_HEAD(forwarders) != NULL) {
isc_sockaddr_t *sa;
dns_resolver_setforwarders(view->resolver, &forwarders);
dns_resolver_setfwdpolicy(view->resolver, dns_fwdpolicy_only);
result = dns_fwdtable_add(view->fwdtable, dns_rootname,
&forwarders, dns_fwdpolicy_only);
sa = ISC_LIST_HEAD(forwarders);
while (sa != NULL) {
ISC_LIST_UNLINK(forwarders, sa, link);
isc_mem_put(lwresd->mctx, sa, sizeof (*sa));
sa = ISC_LIST_HEAD(forwarders);
}
if (result != ISC_R_SUCCESS)
goto out;
}
dns_view_freeze(view);
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: server.c,v 1.215 2000/08/24 19:02:06 gson Exp $ */
/* $Id: server.c,v 1.216 2000/08/24 22:15:28 bwelling Exp $ */
#include <config.h>
......@@ -35,6 +35,7 @@
#include <dns/confparser.h>
#include <dns/db.h>
#include <dns/dispatch.h>
#include <dns/forward.h>
#include <dns/journal.h>
#include <dns/keytable.h>
#include <dns/peer.h>
......@@ -107,6 +108,11 @@ ns_listenlist_fromconfig(dns_c_lstnlist_t *clist, dns_c_ctx_t *cctx,
dns_aclconfctx_t *actx,
isc_mem_t *mctx, ns_listenlist_t **target);
static isc_result_t
configure_forward(dns_c_ctx_t *cctx, dns_c_zone_t *czone, dns_c_view_t *cview,
dns_view_t *view, dns_name_t *origin,
dns_c_iplist_t *forwarders);
/*
* Configure a single view ACL at '*aclp'. Get its configuration by
* calling 'getvcacl' (for per-view configuration) and maybe 'getscacl'
......@@ -401,13 +407,8 @@ configure_view(dns_view_t *view, dns_c_ctx_t *cctx, dns_c_view_t *cview,
isc_result_t result;
isc_uint32_t cleaning_interval;
dns_tsig_keyring_t *ring;
dns_c_forw_t forward;
dns_c_iplist_t *forwarders;
dns_fwdpolicy_t fwdpolicy;
isc_sockaddrlist_t addresses;
isc_sockaddr_t *sa, *next_sa;
dns_view_t *pview = NULL; /* Production view */
unsigned int i;
isc_mem_t *cmctx;
dns_dispatch_t *dispatch4 = NULL;
dns_dispatch_t *dispatch6 = NULL;
......@@ -415,7 +416,6 @@ configure_view(dns_view_t *view, dns_c_ctx_t *cctx, dns_c_view_t *cview,
REQUIRE(DNS_VIEW_VALID(view));
ISC_LIST_INIT(addresses);
cmctx = NULL;
RWLOCK(&view->conflock, isc_rwlocktype_write);
......@@ -508,37 +508,9 @@ configure_view(dns_view_t *view, dns_c_ctx_t *cctx, dns_c_view_t *cview,
dns_c_view_getforwarders(cview, &forwarders) == ISC_R_SUCCESS) ||
(dns_c_ctx_getforwarders(cctx, &forwarders) == ISC_R_SUCCESS))
{
fwdpolicy = dns_fwdpolicy_first;
/*
* Ugh. Convert between list formats.
*/
for (i = 0; i < forwarders->nextidx; i++) {
sa = isc_mem_get(view->mctx, sizeof *sa);
if (sa == NULL) {
result = ISC_R_NOMEMORY;
goto cleanup;
}
*sa = forwarders->ips[i];
isc_sockaddr_setport(sa, port);
ISC_LINK_INIT(sa, link);
ISC_LIST_APPEND(addresses, sa, link);
}
INSIST(!ISC_LIST_EMPTY(addresses));
result = configure_forward(cctx, NULL, cview, view,
dns_rootname, forwarders);
dns_c_iplist_detach(&forwarders);
CHECK(dns_resolver_setforwarders(view->resolver, &addresses));
/*
* XXXRTH The configuration type 'dns_c_forw_t' should be
* eliminated.
*/
if ((cview != NULL &&
dns_c_view_getforward(cview, &forward) == ISC_R_SUCCESS)
|| dns_c_ctx_getforward(cctx, &forward) == ISC_R_SUCCESS) {
INSIST(forward == dns_c_forw_first ||
forward == dns_c_forw_only);
if (forward == dns_c_forw_only)
fwdpolicy = dns_fwdpolicy_only;
}
CHECK(dns_resolver_setfwdpolicy(view->resolver, fwdpolicy));
}
/*
......@@ -704,13 +676,6 @@ configure_view(dns_view_t *view, dns_c_ctx_t *cctx, dns_c_view_t *cview,
cleanup:
RWUNLOCK(&view->conflock, isc_rwlocktype_write);
for (sa = ISC_LIST_HEAD(addresses);
sa != NULL;
sa = next_sa) {
next_sa = ISC_LIST_NEXT(sa, link);
isc_mem_put(view->mctx, sa, sizeof *sa);
}
if (cmctx != NULL)
isc_mem_detach(&cmctx);
......@@ -931,6 +896,74 @@ configure_hints(dns_view_t *view, const char *filename) {
return (result);
}
static isc_result_t
configure_forward(dns_c_ctx_t *cctx, dns_c_zone_t *czone, dns_c_view_t *cview,
dns_view_t *view, dns_name_t *origin,
dns_c_iplist_t *forwarders)
{
dns_c_forw_t forward;
dns_fwdpolicy_t fwdpolicy;
isc_sockaddrlist_t addresses;
isc_sockaddr_t *sa;
isc_result_t result;
in_port_t port;
unsigned int i;
result = dns_c_ctx_getport(cctx, &port);
if (result != ISC_R_SUCCESS)
port = 53;
ISC_LIST_INIT(addresses);
if (forwarders != NULL) {
for (i = 0; i < forwarders->nextidx; i++) {
sa = isc_mem_get(view->mctx, sizeof(isc_sockaddr_t));
if (sa == NULL) {
result = ISC_R_NOMEMORY;
goto cleanup;
}
*sa = forwarders->ips[i];
isc_sockaddr_setport(sa, port);
ISC_LINK_INIT(sa, link);
ISC_LIST_APPEND(addresses, sa, link);
}
}
if (ISC_LIST_EMPTY(addresses))
fwdpolicy = dns_fwdpolicy_none;
else
fwdpolicy = dns_fwdpolicy_first;
if ((czone != NULL &&
dns_c_zone_getforward(czone, &forward) == ISC_R_SUCCESS) ||
(cview != NULL &&
dns_c_view_getforward(cview, &forward) == ISC_R_SUCCESS) ||
dns_c_ctx_getforward(cctx, &forward) == ISC_R_SUCCESS)
{
INSIST(forward == dns_c_forw_first ||
forward == dns_c_forw_only);
if (forward == dns_c_forw_only)
fwdpolicy = dns_fwdpolicy_only;
}
result = dns_fwdtable_add(view->fwdtable, origin, &addresses,
fwdpolicy);
if (result != ISC_R_SUCCESS)
goto cleanup;
result = ISC_R_SUCCESS;
cleanup:
while (!ISC_LIST_EMPTY(addresses)) {
sa = ISC_LIST_HEAD(addresses);
ISC_LIST_UNLINK(addresses, sa, link);
isc_mem_put(view->mctx, sa, sizeof(isc_sockaddr_t));
}
return (result);
}
/*
* Find an existing view matching the name and class of 'cview'
* in 'viewlist', or create a new one and add it to the list.
......@@ -1064,16 +1097,12 @@ configure_zone(dns_c_ctx_t *cctx, dns_c_zone_t *czone, dns_c_view_t *cview,
}
/*
* "forward zones" aren't zones either. Eventually we'll
* translate this syntax into the appropriate selective forwarding
* configuration.
* "forward zones" aren't zones either. Translate this syntax into
* the appropriate selective forwarding configuration and return.
*/
if (czone->ztype == dns_c_zone_forward) {
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
"forward zone '%s': forward zones are not supported in this release",
corigin);
result = ISC_R_SUCCESS;
result = configure_forward(cctx, czone, cview, view, origin,
czone->u.fzone.forwarders);
goto cleanup;
}
......
......@@ -13,7 +13,7 @@
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# $Id: Makefile.in,v 1.98 2000/08/22 00:54:57 bwelling Exp $
# $Id: Makefile.in,v 1.99 2000/08/24 22:15:29 bwelling Exp $
srcdir = @srcdir@
VPATH = @srcdir@
......@@ -119,7 +119,7 @@ DNSSAFEOBJS = sec/dnssafe/ahchdig.@O@ sec/dnssafe/ahchencr.@O@ \
OBJS = a6.@O@ acl.@O@ aclconf.@O@ adb.@O@ byaddr.@O@ \
cache.@O@ callbacks.@O@ compress.@O@ \
db.@O@ dbiterator.@O@ dbtable.@O@ dispatch.@O@ dnssec.@O@ \
journal.@O@ keytable.@O@ lib.@O@ log.@O@ \
forward.@O@ journal.@O@ keytable.@O@ lib.@O@ log.@O@ \
master.@O@ masterdump.@O@ message.@O@ \
name.@O@ ncache.@O@ nxt.@O@ peer.@O@ \
rbt.@O@ rbtdb.@O@ rbtdb64.@O@ rdata.@O@ rdatalist.@O@ \
......@@ -134,7 +134,7 @@ OBJS = a6.@O@ acl.@O@ aclconf.@O@ adb.@O@ byaddr.@O@ \
SRCS = a6.c acl.c aclconf.c adb.c byaddr.c \
cache.c callbacks.c compress.c \
db.c dbiterator.c dbtable.c dispatch.c dnssec.c \
journal.c keytable.c lib.c log.c \
forward.c journal.c keytable.c lib.c log.c \
master.c masterdump.c message.c \
name.c ncache.c nxt.c peer.c \
rbt.c rbtdb.c rbtdb64.c rdata.c rdatalist.c \
......
/*
* 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: forward.c,v 1.1 2000/08/24 22:15:30 bwelling Exp $ */
#include <config.h>
#include <isc/magic.h>
#include <isc/mem.h>
#include <isc/rwlock.h>
#include <isc/sockaddr.h>
#include <isc/util.h>
#include <dns/forward.h>
#include <dns/rbt.h>
#include <dns/result.h>
#include <dns/types.h>
struct dns_fwdtable {
/* Unlocked. */
unsigned int magic;
isc_mem_t *mctx;
isc_rwlock_t rwlock;
/* Locked by lock. */
dns_rbt_t *table;
};
#define FWDTABLEMAGIC 0x46776454U /* FwdT */
#define VALID_FWDTABLE(ft) ISC_MAGIC_VALID(ft, FWDTABLEMAGIC)
static void
auto_detach(void *, void *);
isc_result_t
dns_fwdtable_create(isc_mem_t *mctx, dns_fwdtable_t **fwdtablep) {
dns_fwdtable_t *fwdtable;
isc_result_t result;
REQUIRE(fwdtablep != NULL && *fwdtablep == NULL);
fwdtable = isc_mem_get(mctx, sizeof(dns_fwdtable_t));
if (fwdtable == NULL)
return (ISC_R_NOMEMORY);
fwdtable->table = NULL;
result = dns_rbt_create(mctx, auto_detach, fwdtable, &fwdtable->table);
if (result != ISC_R_SUCCESS)
goto cleanup_fwdtable;
result = isc_rwlock_init(&fwdtable->rwlock, 0, 0);
if (result != ISC_R_SUCCESS) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"isc_rwlock_init() failed: %s",
isc_result_totext(result));
result = ISC_R_UNEXPECTED;
goto cleanup_rbt;
}
fwdtable->mctx = NULL;
isc_mem_attach(mctx, &fwdtable->mctx);
fwdtable->magic = FWDTABLEMAGIC;
*fwdtablep = fwdtable;
return (ISC_R_SUCCESS);
cleanup_rbt:
dns_rbt_destroy(&fwdtable->table);
cleanup_fwdtable:
isc_mem_put(mctx, fwdtable, sizeof(dns_fwdtable_t));
return (result);
}
isc_result_t
dns_fwdtable_add(dns_fwdtable_t *fwdtable, dns_name_t *name,
isc_sockaddrlist_t *addrs, dns_fwdpolicy_t fwdpolicy)
{
isc_result_t result;
dns_forwarders_t *forwarders;
isc_sockaddr_t *sa, *nsa;
REQUIRE(VALID_FWDTABLE(fwdtable));
forwarders = isc_mem_get(fwdtable->mctx, sizeof(dns_forwarders_t));
if (forwarders == NULL)
return (ISC_R_NOMEMORY);
ISC_LIST_INIT(forwarders->addrs);
for (sa = ISC_LIST_HEAD(*addrs);
sa != NULL;
sa = ISC_LIST_NEXT(sa, link))
{
nsa = isc_mem_get(fwdtable->mctx, sizeof(isc_sockaddr_t));
if (nsa == NULL) {
result = ISC_R_NOMEMORY;
goto cleanup;
}
*nsa = *sa;
ISC_LINK_INIT(nsa, link);
ISC_LIST_APPEND(forwarders->addrs, nsa, link);
}
forwarders->fwdpolicy = fwdpolicy;
RWLOCK(&fwdtable->rwlock, isc_rwlocktype_write);
result = dns_rbt_addname(fwdtable->table, name, forwarders);
RWUNLOCK(&fwdtable->rwlock, isc_rwlocktype_write);
if (result != ISC_R_SUCCESS)
goto cleanup;
return (ISC_R_SUCCESS);
cleanup:
while (!ISC_LIST_EMPTY(forwarders->addrs)) {
sa = ISC_LIST_HEAD(forwarders->addrs);
ISC_LIST_UNLINK(forwarders->addrs, sa, link);
isc_mem_put(fwdtable->mctx, sa, sizeof(isc_sockaddr_t));
}
isc_mem_put(fwdtable->mctx, forwarders, sizeof(dns_forwarders_t));
return (result);
}
isc_result_t
dns_fwdtable_find(dns_fwdtable_t *fwdtable, dns_name_t *name,
dns_forwarders_t **forwardersp)
{
isc_result_t result;
REQUIRE(VALID_FWDTABLE(fwdtable));
RWLOCK(&fwdtable->rwlock, isc_rwlocktype_read);
result = dns_rbt_findname(fwdtable->table, name, 0, NULL,
(void **)forwardersp);
if (result == DNS_R_PARTIALMATCH)
result = ISC_R_SUCCESS;
RWUNLOCK(&fwdtable->rwlock, isc_rwlocktype_read);
return (result);
}
void
dns_fwdtable_destroy(dns_fwdtable_t **fwdtablep) {
dns_fwdtable_t *fwdtable;
isc_mem_t *mctx = mctx;
REQUIRE(fwdtablep != NULL && VALID_FWDTABLE(*fwdtablep));
fwdtable = *fwdtablep;
dns_rbt_destroy(&fwdtable->table);
isc_rwlock_destroy(&fwdtable->rwlock);
fwdtable->magic = 0;
mctx = fwdtable->mctx;
isc_mem_put(mctx, fwdtable, sizeof(dns_fwdtable_t));
isc_mem_detach(&mctx);
*fwdtablep = NULL;
}
/***
*** Private
***/
static void
auto_detach(void *data, void *arg) {
dns_forwarders_t *forwarders = data;
dns_fwdtable_t *fwdtable = arg;
isc_sockaddr_t *sa;
UNUSED(arg);
while (!ISC_LIST_EMPTY(forwarders->addrs)) {
sa = ISC_LIST_HEAD(forwarders->addrs);
ISC_LIST_UNLINK(forwarders->addrs, sa, link);
isc_mem_put(fwdtable->mctx, sa, sizeof(isc_sockaddr_t));
}
isc_mem_put(fwdtable->mctx, forwarders, sizeof(dns_forwarders_t));
}
/*
* 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: forward.h,v 1.1 2000/08/24 22:15:36 bwelling Exp $ */
#ifndef DNS_FORWARD_H
#define DNS_FORWARD_H 1
#include <isc/lang.h>
#include <isc/result.h>
#include <dns/types.h>
ISC_LANG_BEGINDECLS
struct dns_forwarders {
isc_sockaddrlist_t addrs;
dns_fwdpolicy_t fwdpolicy;
};
isc_result_t
dns_fwdtable_create(isc_mem_t *mctx, dns_fwdtable_t **fwdtablep);
/*
* Creates a new forwarding table.
*
* Requires:
* mctx is a valid memory context.
* fwdtablep != NULL && *fwdtablep == NULL
*
* Returns:
* ISC_R_SUCCESS
* ISC_R_NOMEMORY
*/
isc_result_t
dns_fwdtable_add(dns_fwdtable_t *fwdtable, dns_name_t *name,
isc_sockaddrlist_t *addrs, dns_fwdpolicy_t policy);
/*
* Adds an entry to the forwarding table. The entry associates
* a domain with a list of forwarders and a forwarding policy. The
* addrs list is copied if not empty, so the caller should free its copy.
*
* Requires:
* fwdtable is a valid forwarding table.
* name is a valid name
* addrs is a valid list of sockaddrs, which may be empty.
*
* Returns:
* ISC_R_SUCCESS
* ISC_R_NOMEMORY
*/
isc_result_t
dns_fwdtable_find(dns_fwdtable_t *fwdtable, dns_name_t *name,
dns_forwarders_t **forwardersp);
/*
* Finds a domain in the forwarding table. The closest matching parent
* domain is returned.
*
* Requires:
* fwdtable is a valid forwarding table.
* name is a valid name
* forwardersp != NULL && *forwardersp == NULL
*
* Returns:
* ISC_R_SUCCESS
* ISC_R_NOTFOUND
*/
void
dns_fwdtable_destroy(dns_fwdtable_t **fwdtablep);
/*
* Destroys a forwarding table.
*
* Requires:
* fwtablep != NULL && *fwtablep != NULL
*
* Ensures:
* all memory associated with the forwarding table is freed.
*/
ISC_LANG_ENDDECLS
#endif /* DNS_FORWARD_H */
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: resolver.h,v 1.31 2000/08/01 01:24:39 tale Exp $ */
/* $Id: resolver.h,v 1.32 2000/08/24 22:15:36 bwelling Exp $ */
#ifndef DNS_RESOLVER_H
#define DNS_RESOLVER_H 1
......@@ -141,40 +141,6 @@ dns_resolver_create(dns_view_t *view,
* Anything else Failure.
*/
isc_result_t
dns_resolver_setforwarders(dns_resolver_t *res,
isc_sockaddrlist_t *forwarders);
/*
* Set the default forwarders to be used by the resolver.
*
* Requires:
*
* 'res' is a valid, unfrozen resolver.
*
* 'forwarders' is a valid nonempty list.
*
* Returns:
*
* ISC_R_SUCCESS
* ISC_R_NOMEMORY
*/
isc_result_t
dns_resolver_setfwdpolicy(dns_resolver_t *res, dns_fwdpolicy_t fwdpolicy);
/*
* Set the default forwarding policy to be used by the resolver.
*
* Requires:
*
* 'res' is a valid, unfrozen resolver.
*
* 'fwdpolicy' is a valid dns_fwdpolicy_t.
*
* Returns:
*
* ISC_R_SUCCESS
*/
void
dns_resolver_freeze(dns_resolver_t *res);
/*
......@@ -182,9 +148,8 @@ dns_resolver_freeze(dns_resolver_t *res);
*
* Notes:
*
* Certain configuration changes, e.g. setting forwarders,
* cannot be made after the resolver is frozen. Fetches
* cannot be created until the resolver is frozen.
* Certain configuration changes cannot be made after the resolver
* is frozen. Fetches cannot be created until the resolver is frozen.
*
* Requires:
*
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: types.h,v 1.92 2000/08/15 03:33:52 marka Exp $ */
/* $Id: types.h,v 1.93 2000/08/24 22:15:37 bwelling Exp $ */
#ifndef DNS_TYPES_H
#define DNS_TYPES_H 1
......@@ -59,6 +59,7 @@ typedef struct dns_dispentry dns_dispentry_t;