move DNS64 implementation into an external module
- dns64 implementation has been moved from query.c to the dns64 module. - the code in lib/dns/dns64.c has not yet been moved. - the module does not yet parse dns64 options in named.conf; that's still done by named. - the module does not have persistent storage; we still use the client object. - made more functions globally accessible so they can be called from modules: ns_query_lookup(), ns_query_addsoa(), ns_query_nodata(), ns_query_ncache(), ns_query_setorder().
This commit is contained in:
+1
-12
@@ -5300,15 +5300,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
|
||||
}
|
||||
|
||||
#ifdef HAVE_DLOPEN
|
||||
/*
|
||||
* XXX: because dns64 is still automatically configured,
|
||||
* we need to create a hooktable for every view regardless
|
||||
* of whether hook_list is set or not.
|
||||
*/
|
||||
#if 0
|
||||
if (plugin_list != NULL)
|
||||
#endif
|
||||
{
|
||||
if (plugin_list != NULL) {
|
||||
INSIST(view->hooktable == NULL);
|
||||
CHECK(ns_hooktable_create(view->mctx,
|
||||
(ns_hooktable_t **) &view->hooktable));
|
||||
@@ -5320,9 +5312,6 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
|
||||
CHECK(cfg_pluginlist_foreach(config, plugin_list, named_g_lctx,
|
||||
register_one_plugin, view));
|
||||
}
|
||||
|
||||
/* XXX: temporary initialization for built in dns64 hooks */
|
||||
ns__query_inithooks(view);
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
+18
-7
@@ -24,24 +24,32 @@ NSLIBS = ../../lib/ns/libns.@A@
|
||||
|
||||
LIBS =
|
||||
|
||||
SO_TARGETS = lib/filter-aaaa.@SO@
|
||||
SO_INSTALL = filter-aaaa.@SO@
|
||||
SO_TARGETS = lib/dns64.@SO@ lib/filter-aaaa.@SO@
|
||||
SO_INSTALL = dns64.@SO@ filter-aaaa.@SO@
|
||||
TARGETS = @SO_TARGETS@
|
||||
|
||||
SO_OBJS = filter-aaaa.@O@
|
||||
SO_SRCS = filter-aaaa.c
|
||||
SO_OBJS = dns64.@O@ filter-aaaa.@O@
|
||||
SO_SRCS = dns64.c filter-aaaa.c
|
||||
|
||||
CFLAGS = @CFLAGS@ @SO_CFLAGS@
|
||||
SO_LDFLAGS = @LDFLAGS@ @SO_LDFLAGS@
|
||||
|
||||
MANPAGES = filter-aaaa.8
|
||||
MANPAGES = dns64.8 filter-aaaa.8
|
||||
|
||||
HTMLPAGES = filter-aaaa.html
|
||||
HTMLPAGES = dns64.html filter-aaaa.html
|
||||
|
||||
MANOBJS = ${MANPAGES} ${HTMLPAGES}
|
||||
|
||||
@BIND9_MAKE_RULES@
|
||||
|
||||
lib/dns64.@SO@: dns64.@SO@
|
||||
$(SHELL) ${top_srcdir}/mkinstalldirs `pwd`/lib
|
||||
${LIBTOOL_MODE_INSTALL} ${INSTALL} dns64.@SO@ `pwd`/lib
|
||||
|
||||
dns64.@SO@: dns64.@O@
|
||||
${LIBTOOL_MODE_LINK} @SO_LD@ ${SO_LDFLAGS} -o $@ \
|
||||
dns64.@O@ ${LIBS}
|
||||
|
||||
lib/filter-aaaa.@SO@: filter-aaaa.@SO@
|
||||
$(SHELL) ${top_srcdir}/mkinstalldirs `pwd`/lib
|
||||
${LIBTOOL_MODE_INSTALL} ${INSTALL} filter-aaaa.@SO@ `pwd`/lib
|
||||
@@ -56,7 +64,7 @@ docclean manclean maintainer-clean::
|
||||
rm -f ${MANOBJS}
|
||||
|
||||
clean distclean::
|
||||
rm -f filter-aaaa.so
|
||||
rm -f dns64.@SO@ filter-aaaa.@SO@
|
||||
rm -f ${TARGETS} ${OBJS}
|
||||
|
||||
installdirs:
|
||||
@@ -73,7 +81,10 @@ install:: @SO_TARGETS@ installdirs
|
||||
fi \
|
||||
done
|
||||
${INSTALL_DATA} ${srcdir}/filter-aaaa.8 ${DESTDIR}${mandir}/man8
|
||||
${INSTALL_DATA} ${srcdir}/dns64.8 ${DESTDIR}${mandir}/man8
|
||||
|
||||
uninstall::
|
||||
${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${plugindir}/dns64.@SO@
|
||||
${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${plugindir}/filter-aaaa.@SO@
|
||||
rm -f ${DESTDIR}${mandir}/man8/dns64.8
|
||||
rm -f ${DESTDIR}${mandir}/man8/filter-aaaa.8
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
.\" Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
|
||||
.\"
|
||||
.\" This Source Code Form is subject to the terms of the Mozilla Public
|
||||
.\" License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
.\"
|
||||
.hy 0
|
||||
.ad l
|
||||
'\" t
|
||||
.\" Title: dns64.so
|
||||
.\" Author:
|
||||
.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
|
||||
.\" Date: 2018-11-30
|
||||
.\" Manual: BIND9
|
||||
.\" Source: ISC
|
||||
.\" Language: English
|
||||
.\"
|
||||
.TH "DNS64\&.SO" "8" "2018\-11\-30" "ISC" "BIND9"
|
||||
.\" -----------------------------------------------------------------
|
||||
.\" * Define some portability stuff
|
||||
.\" -----------------------------------------------------------------
|
||||
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
.\" http://bugs.debian.org/507673
|
||||
.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
|
||||
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
.ie \n(.g .ds Aq \(aq
|
||||
.el .ds Aq '
|
||||
.\" -----------------------------------------------------------------
|
||||
.\" * set default formatting
|
||||
.\" -----------------------------------------------------------------
|
||||
.\" disable hyphenation
|
||||
.nh
|
||||
.\" disable justification (adjust text to left margin only)
|
||||
.ad l
|
||||
.\" -----------------------------------------------------------------
|
||||
.\" * MAIN CONTENT STARTS HERE *
|
||||
.\" -----------------------------------------------------------------
|
||||
.SH "NAME"
|
||||
dns64.so \- perform DNS64 synthesis
|
||||
.SH "SYNOPSIS"
|
||||
.HP 24
|
||||
\fBplugin query "dns64\&.so"\fR [\fI{\ parameters\ }\fR];
|
||||
.SH "DESCRIPTION"
|
||||
.PP
|
||||
\fBdns64\&.so\fR
|
||||
is a query plugin module for
|
||||
\fBnamed\fR, enabling
|
||||
\fBnamed\fR
|
||||
to perform DNS64 address synthesis\&.
|
||||
.PP
|
||||
Until BIND 9\&.12, this feature was implemented natively in
|
||||
\fBnamed\fR
|
||||
and enabled with the
|
||||
\fBdns64\fR
|
||||
option\&. This option is now deprecated in
|
||||
named\&.conf, but can be passed as parameters to the
|
||||
\fBdns64\&.so\fR
|
||||
plugin, for example:
|
||||
.sp
|
||||
.if n \{\
|
||||
.RS 4
|
||||
.\}
|
||||
.nf
|
||||
acl rfc1918 { 10/8; 192\&.168/16; 172\&.16/12; };
|
||||
plugin query "/usr/local/lib/dns64\&.so" {
|
||||
dns64 64:FF9B::/96 {
|
||||
clients { any; };
|
||||
mapped { !rfc1918; any; };
|
||||
exclude { 64:FF9B::/96; ::ffff:0000:0000/96; };
|
||||
suffix ::;
|
||||
};
|
||||
dns64\-server "dns64\&.example\&.net\&.";
|
||||
dns64\-contact "hostmaster\&.example\&.net\&.";
|
||||
};
|
||||
.fi
|
||||
.if n \{\
|
||||
.RE
|
||||
.\}
|
||||
.PP
|
||||
This plugin enables
|
||||
\fBnamed\fR
|
||||
to return mapped IPv4 addresses to AAAA queries when there are no AAAA records\&. It is intended to be used in conjunction with NAT64\&.
|
||||
.PP
|
||||
Each
|
||||
\fBdns64\fR
|
||||
option defined in the plugin parameters defines one DNS64 prefix\&. Multiple DNS64 prefixes can be defined\&.
|
||||
.PP
|
||||
Compatible IPv6 prefixes have lengths of 32, 40, 48, 56, 64 and 96 as per RFC 6052\&.
|
||||
.PP
|
||||
Additionally a reverse IP6\&.ARPA zone will be created for the prefix to provide a mapping from the IP6\&.ARPA names to the corresponding IN\-ADDR\&.ARPA names using synthesized CNAMEs\&.
|
||||
\fBdns64\-server\fR
|
||||
and
|
||||
\fBdns64\-contact\fR
|
||||
can be used to specify the name of the server and contact for the zones\&. These are not settable on a per\-prefix basis\&.
|
||||
.PP
|
||||
Each
|
||||
\fBdns64\fR
|
||||
supports an optional
|
||||
\fBclients\fR
|
||||
ACL that determines which clients are affected by this directive\&. If not defined, it defaults to
|
||||
\fBany;\fR\&.
|
||||
.PP
|
||||
Each
|
||||
\fBdns64\fR
|
||||
supports an optional
|
||||
\fBmapped\fR
|
||||
ACL that selects which IPv4 addresses are to be mapped in the corresponding A RRset\&. If not defined it defaults to
|
||||
\fBany;\fR\&.
|
||||
.PP
|
||||
Normally, DNS64 won\*(Aqt apply to a domain name that owns one or more AAAA records; these records will simply be returned\&. The optional
|
||||
\fBexclude\fR
|
||||
ACL allows specification of a list of IPv6 addresses that will be ignored if they appear in a domain name\*(Aqs AAAA records, and DNS64 will be applied to any A records the domain name owns\&. If not defined,
|
||||
\fBexclude\fR
|
||||
defaults to ::ffff:0\&.0\&.0\&.0/96\&.
|
||||
.PP
|
||||
A optional
|
||||
\fBsuffix\fR
|
||||
can also be defined to set the bits trailing the mapped IPv4 address bits\&. By default these bits are set to
|
||||
\fB::\fR\&. The bits matching the prefix and mapped IPv4 address must be zero\&.
|
||||
.PP
|
||||
If
|
||||
\fBrecursive\-only\fR
|
||||
is set to
|
||||
\fByes\fR
|
||||
the DNS64 synthesis will only happen for recursive queries\&. The default is
|
||||
\fBno\fR\&.
|
||||
.PP
|
||||
If
|
||||
\fBbreak\-dnssec\fR
|
||||
is set to
|
||||
\fByes\fR
|
||||
the DNS64 synthesis will happen even if the result, if validated, would cause a DNSSEC validation failure\&. If this option is set to
|
||||
\fBno\fR
|
||||
(the default), the DO is set on the incoming query, and there are RRSIGs on the applicable records, then synthesis will not happen\&.
|
||||
.SH "SEE ALSO"
|
||||
.PP
|
||||
BIND 9 Administrator Reference Manual\&.
|
||||
.SH "AUTHOR"
|
||||
.PP
|
||||
\fBInternet Systems Consortium, Inc\&.\fR
|
||||
.SH "COPYRIGHT"
|
||||
.br
|
||||
Copyright \(co 2018 Internet Systems Consortium, Inc. ("ISC")
|
||||
.br
|
||||
@@ -0,0 +1,952 @@
|
||||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* See the COPYRIGHT file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <isc/buffer.h>
|
||||
#include <isc/hash.h>
|
||||
#include <isc/list.h>
|
||||
#include <isc/log.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/netaddr.h>
|
||||
#include <isc/region.h>
|
||||
#include <isc/result.h>
|
||||
#include <isc/types.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <ns/client.h>
|
||||
#include <ns/hooks.h>
|
||||
#include <ns/interfacemgr.h>
|
||||
#include <ns/log.h>
|
||||
#include <ns/query.h>
|
||||
#include <ns/types.h>
|
||||
|
||||
#include <dns/db.h>
|
||||
#include <dns/dns64.h>
|
||||
#include <dns/message.h>
|
||||
#include <dns/name.h>
|
||||
#include <dns/rdataset.h>
|
||||
#include <dns/rdatalist.h>
|
||||
#include <dns/result.h>
|
||||
#include <dns/types.h>
|
||||
#include <dns/view.h>
|
||||
|
||||
#define CHECK(op) \
|
||||
do { \
|
||||
result = (op); \
|
||||
if (result != ISC_R_SUCCESS) { \
|
||||
goto cleanup; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define QUERY_ERROR(qctx, r) \
|
||||
do { \
|
||||
qctx->result = r; \
|
||||
qctx->want_restart = false; \
|
||||
qctx->line = __LINE__; \
|
||||
} while (0)
|
||||
|
||||
#define SAVE(a, b) do { INSIST(a == NULL); a = b; b = NULL; } while (0)
|
||||
#define RESTORE(a, b) SAVE(a, b)
|
||||
|
||||
/*
|
||||
* Client attribute tests.
|
||||
*/
|
||||
/*% Recursion OK? */
|
||||
#define RECURSIONOK(c) (((c)->query.attributes & \
|
||||
NS_QUERYATTR_RECURSIONOK) != 0)
|
||||
/*% Want DNSSEC? */
|
||||
#define WANTDNSSEC(c) (((c)->attributes & \
|
||||
NS_CLIENTATTR_WANTDNSSEC) != 0)
|
||||
|
||||
#define DNS64(c) (((c)->query.attributes & \
|
||||
NS_QUERYATTR_DNS64) != 0)
|
||||
|
||||
#define DNS64EXCLUDE(c) (((c)->query.attributes & \
|
||||
NS_QUERYATTR_DNS64EXCLUDE) != 0)
|
||||
|
||||
static uint32_t
|
||||
dns64_ttl(dns_db_t *db, dns_dbversion_t *version);
|
||||
|
||||
static bool
|
||||
dns64_aaaaok(ns_client_t *client, dns_rdataset_t *rdataset,
|
||||
dns_rdataset_t *sigrdataset);
|
||||
|
||||
static isc_result_t
|
||||
dns64_synth(query_ctx_t *qctx);
|
||||
|
||||
static void
|
||||
dns64_filter(query_ctx_t *qctx);
|
||||
|
||||
/*
|
||||
* Hook registration structures: pointers to these structures will
|
||||
* be added to a hook table when this module is registered.
|
||||
*/
|
||||
static ns_hookresult_t
|
||||
dns64_qctx_initialize(void *arg, void *cbdata, isc_result_t *resp);
|
||||
static ns_hook_t dns64_init = {
|
||||
.action = dns64_qctx_initialize,
|
||||
};
|
||||
|
||||
static ns_hookresult_t
|
||||
dns64_respond_begin(void *arg, void *cbdata, isc_result_t *resp);
|
||||
static ns_hook_t dns64_respbegin = {
|
||||
.action = dns64_respond_begin,
|
||||
};
|
||||
|
||||
static ns_hookresult_t
|
||||
dns64_addanswer(void *arg, void *cbdata, isc_result_t *resp);
|
||||
static ns_hook_t dns64_addanswerbegin = {
|
||||
.action = dns64_addanswer,
|
||||
};
|
||||
|
||||
static ns_hookresult_t
|
||||
dns64_resume_restored(void *arg, void *cbdata, isc_result_t *resp);
|
||||
static ns_hook_t dns64_resumerest = {
|
||||
.action = dns64_resume_restored,
|
||||
};
|
||||
|
||||
static ns_hookresult_t
|
||||
dns64_notfound_recurse(void *arg, void *cbdata, isc_result_t *resp);
|
||||
static ns_hook_t dns64_nfrec = {
|
||||
.action = dns64_notfound_recurse,
|
||||
};
|
||||
|
||||
static ns_hookresult_t
|
||||
dns64_delegation_recurse(void *arg, void *cbdata, isc_result_t *resp);
|
||||
static ns_hook_t dns64_delrec = {
|
||||
.action = dns64_delegation_recurse,
|
||||
};
|
||||
|
||||
static ns_hookresult_t
|
||||
dns64_nodata_begin(void *arg, void *cbdata, isc_result_t *resp);
|
||||
static ns_hook_t dns64_nodata = {
|
||||
.action = dns64_nodata_begin,
|
||||
};
|
||||
|
||||
static ns_hookresult_t
|
||||
dns64_zerottl_recurse(void *arg, void *cbdata, isc_result_t *resp);
|
||||
static ns_hook_t dns64_zerottl = {
|
||||
.action = dns64_zerottl_recurse,
|
||||
};
|
||||
|
||||
static ns_hookresult_t
|
||||
dns64_qctx_destroy(void *arg, void *cbdata, isc_result_t *resp);
|
||||
static ns_hook_t dns64_destroy = {
|
||||
.action = dns64_qctx_destroy,
|
||||
};
|
||||
|
||||
/**
|
||||
** Support for parsing of parameters and configuration of the module.
|
||||
**/
|
||||
|
||||
/**
|
||||
** Mandatory plugin API functions:
|
||||
**
|
||||
** - plugin_check
|
||||
** - plugin_destroy
|
||||
** - plugin_register
|
||||
** - plugin_version
|
||||
**/
|
||||
|
||||
/*
|
||||
* Called by ns_plugin_register() to register hook actions into
|
||||
* a hook table.
|
||||
*/
|
||||
isc_result_t
|
||||
plugin_register(const char *parameters,
|
||||
const void *cfg, const char *cfg_file, unsigned long cfg_line,
|
||||
isc_mem_t *mctx, isc_log_t *lctx, void *actx,
|
||||
ns_hooktable_t *hooktable, void **instp)
|
||||
{
|
||||
|
||||
UNUSED(cfg);
|
||||
UNUSED(actx);
|
||||
UNUSED(instp);
|
||||
|
||||
isc_log_write(lctx, NS_LOGCATEGORY_GENERAL,
|
||||
NS_LOGMODULE_HOOKS, ISC_LOG_INFO,
|
||||
"loading 'dns64' "
|
||||
"module from %s:%lu, %s parameters",
|
||||
cfg_file, cfg_line, parameters != NULL ? "with" : "no");
|
||||
|
||||
ns_hook_add(hooktable, mctx,
|
||||
NS_QUERY_QCTX_INITIALIZED, &dns64_init);
|
||||
ns_hook_add(hooktable, mctx,
|
||||
NS_QUERY_RESPOND_BEGIN, &dns64_respbegin);
|
||||
ns_hook_add(hooktable, mctx,
|
||||
NS_QUERY_ADDANSWER_BEGIN, &dns64_addanswerbegin);
|
||||
ns_hook_add(hooktable, mctx,
|
||||
NS_QUERY_RESUME_RESTORED, &dns64_resumerest);
|
||||
ns_hook_add(hooktable, mctx,
|
||||
NS_QUERY_NOTFOUND_RECURSE, &dns64_nfrec);
|
||||
ns_hook_add(hooktable, mctx,
|
||||
NS_QUERY_DELEGATION_RECURSE_BEGIN, &dns64_delrec);
|
||||
ns_hook_add(hooktable, mctx,
|
||||
NS_QUERY_NODATA_BEGIN, &dns64_nodata);
|
||||
ns_hook_add(hooktable, mctx,
|
||||
NS_QUERY_ZEROTTL_RECURSE, &dns64_zerottl);
|
||||
ns_hook_add(hooktable, mctx,
|
||||
NS_QUERY_QCTX_DESTROYED, &dns64_destroy);
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
plugin_check(const char *parameters,
|
||||
const void *cfg, const char *cfg_file, unsigned long cfg_line,
|
||||
isc_mem_t *mctx, isc_log_t *lctx, void *actx)
|
||||
{
|
||||
UNUSED(parameters);
|
||||
UNUSED(cfg_file);
|
||||
UNUSED(cfg_line);
|
||||
UNUSED(cfg);
|
||||
UNUSED(mctx);
|
||||
UNUSED(lctx);
|
||||
UNUSED(actx);
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called by ns_plugins_free(); frees memory allocated by
|
||||
* the module when it was registered.
|
||||
*/
|
||||
void
|
||||
plugin_destroy(void **instp) {
|
||||
UNUSED(instp);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns plugin API version for compatibility checks.
|
||||
*/
|
||||
int
|
||||
plugin_version(void) {
|
||||
return (NS_PLUGIN_VERSION);
|
||||
}
|
||||
|
||||
/**
|
||||
** DNS64 feature implementation begins here.
|
||||
**/
|
||||
static uint32_t
|
||||
dns64_ttl(dns_db_t *db, dns_dbversion_t *version) {
|
||||
dns_dbnode_t *node = NULL;
|
||||
dns_rdata_soa_t soa;
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
dns_rdataset_t rdataset;
|
||||
isc_result_t result;
|
||||
uint32_t ttl = UINT32_MAX;
|
||||
|
||||
dns_rdataset_init(&rdataset);
|
||||
|
||||
result = dns_db_getoriginnode(db, &node);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
|
||||
0, 0, &rdataset, NULL);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
result = dns_rdataset_first(&rdataset);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
dns_rdataset_current(&rdataset, &rdata);
|
||||
result = dns_rdata_tostruct(&rdata, &soa, NULL);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
ttl = ISC_MIN(rdataset.ttl, soa.minimum);
|
||||
|
||||
cleanup:
|
||||
if (dns_rdataset_isassociated(&rdataset))
|
||||
dns_rdataset_disassociate(&rdataset);
|
||||
if (node != NULL)
|
||||
dns_db_detachnode(db, &node);
|
||||
return (ttl);
|
||||
}
|
||||
|
||||
static bool
|
||||
dns64_aaaaok(ns_client_t *client, dns_rdataset_t *rdataset,
|
||||
dns_rdataset_t *sigrdataset)
|
||||
{
|
||||
isc_netaddr_t netaddr;
|
||||
dns_aclenv_t *env = ns_interfacemgr_getaclenv(client->interface->mgr);
|
||||
dns_dns64_t *dns64 = ISC_LIST_HEAD(client->view->dns64);
|
||||
unsigned int flags = 0;
|
||||
unsigned int i, count;
|
||||
bool *aaaaok;
|
||||
|
||||
INSIST(client->dns64_aaaaok == NULL);
|
||||
INSIST(client->dns64_aaaaoklen == 0);
|
||||
INSIST(client->dns64_aaaa == NULL);
|
||||
INSIST(client->dns64_sigaaaa == NULL);
|
||||
|
||||
if (dns64 == NULL)
|
||||
return (true);
|
||||
|
||||
if (RECURSIONOK(client))
|
||||
flags |= DNS_DNS64_RECURSIVE;
|
||||
|
||||
if (WANTDNSSEC(client) && sigrdataset != NULL &&
|
||||
dns_rdataset_isassociated(sigrdataset))
|
||||
flags |= DNS_DNS64_DNSSEC;
|
||||
|
||||
count = dns_rdataset_count(rdataset);
|
||||
aaaaok = isc_mem_get(client->mctx, sizeof(bool) * count);
|
||||
|
||||
isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
|
||||
if (dns_dns64_aaaaok(dns64, &netaddr, client->signer,
|
||||
env, flags, rdataset, aaaaok, count))
|
||||
{
|
||||
for (i = 0; i < count; i++) {
|
||||
if (aaaaok != NULL && !aaaaok[i]) {
|
||||
SAVE(client->dns64_aaaaok, aaaaok);
|
||||
client->dns64_aaaaoklen = count;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (aaaaok != NULL)
|
||||
isc_mem_put(client->mctx, aaaaok,
|
||||
sizeof(bool) * count);
|
||||
return (true);
|
||||
}
|
||||
if (aaaaok != NULL)
|
||||
isc_mem_put(client->mctx, aaaaok,
|
||||
sizeof(bool) * count);
|
||||
return (NS_HOOK_CONTINUE);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
dns64_synth(query_ctx_t *qctx) {
|
||||
ns_client_t *client = qctx->client;
|
||||
dns_aclenv_t *env = ns_interfacemgr_getaclenv(client->interface->mgr);
|
||||
dns_name_t *name, *mname;
|
||||
dns_rdata_t *dns64_rdata;
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
dns_rdatalist_t *dns64_rdatalist;
|
||||
dns_rdataset_t *dns64_rdataset;
|
||||
dns_rdataset_t *mrdataset;
|
||||
isc_buffer_t *buffer;
|
||||
isc_region_t r;
|
||||
isc_result_t result;
|
||||
dns_view_t *view = client->view;
|
||||
isc_netaddr_t netaddr;
|
||||
dns_dns64_t *dns64;
|
||||
unsigned int flags = 0;
|
||||
const dns_section_t section = DNS_SECTION_ANSWER;
|
||||
|
||||
/*%
|
||||
* To the current response for 'qctx->client', add the answer RRset
|
||||
* '*rdatasetp' and an optional signature set '*sigrdatasetp', with
|
||||
* owner name '*namep', to the answer section, unless they are
|
||||
* already there. Also add any pertinent additional data.
|
||||
*
|
||||
* If 'qctx->dbuf' is not NULL, then 'qctx->fname' is the name
|
||||
* whose data is stored 'qctx->dbuf'. In this case,
|
||||
* query_addrrset() guarantees that when it returns the name
|
||||
* will either have been kept or released.
|
||||
*/
|
||||
qctx->qtype = qctx->type = dns_rdatatype_aaaa;
|
||||
|
||||
name = qctx->fname;
|
||||
mname = NULL;
|
||||
mrdataset = NULL;
|
||||
buffer = NULL;
|
||||
dns64_rdata = NULL;
|
||||
dns64_rdataset = NULL;
|
||||
dns64_rdatalist = NULL;
|
||||
result = dns_message_findname(client->message, section,
|
||||
name, dns_rdatatype_aaaa,
|
||||
qctx->rdataset->covers,
|
||||
&mname, &mrdataset);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
/*
|
||||
* We've already got an RRset of the given name and type.
|
||||
* There's nothing else to do;
|
||||
*/
|
||||
if (qctx->dbuf != NULL) {
|
||||
ns_client_releasename(client, &qctx->fname);
|
||||
}
|
||||
return (ISC_R_SUCCESS);
|
||||
} else if (result == DNS_R_NXDOMAIN) {
|
||||
/*
|
||||
* The name doesn't exist.
|
||||
*/
|
||||
if (qctx->dbuf != NULL) {
|
||||
ns_client_keepname(client, name, qctx->dbuf);
|
||||
}
|
||||
dns_message_addname(client->message, name, section);
|
||||
qctx->fname = NULL;
|
||||
mname = name;
|
||||
} else {
|
||||
RUNTIME_CHECK(result == DNS_R_NXRRSET);
|
||||
if (qctx->dbuf != NULL) {
|
||||
ns_client_releasename(client, &qctx->fname);
|
||||
}
|
||||
}
|
||||
|
||||
if (qctx->rdataset->trust != dns_trust_secure) {
|
||||
client->query.attributes &= ~NS_QUERYATTR_SECURE;
|
||||
}
|
||||
|
||||
isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
|
||||
|
||||
result = isc_buffer_allocate(client->mctx, &buffer,
|
||||
view->dns64cnt * 16 *
|
||||
dns_rdataset_count(qctx->rdataset));
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
result = dns_message_gettemprdataset(client->message,
|
||||
&dns64_rdataset);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
result = dns_message_gettemprdatalist(client->message,
|
||||
&dns64_rdatalist);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
dns_rdatalist_init(dns64_rdatalist);
|
||||
dns64_rdatalist->rdclass = dns_rdataclass_in;
|
||||
dns64_rdatalist->type = dns_rdatatype_aaaa;
|
||||
if (client->dns64_ttl != UINT32_MAX)
|
||||
dns64_rdatalist->ttl = ISC_MIN(qctx->rdataset->ttl,
|
||||
client->dns64_ttl);
|
||||
else
|
||||
dns64_rdatalist->ttl = ISC_MIN(qctx->rdataset->ttl, 600);
|
||||
|
||||
if (RECURSIONOK(client))
|
||||
flags |= DNS_DNS64_RECURSIVE;
|
||||
|
||||
/*
|
||||
* We use the signatures from the A lookup to set DNS_DNS64_DNSSEC
|
||||
* as this provides a easy way to see if the answer was signed.
|
||||
*/
|
||||
if (WANTDNSSEC(qctx->client) && qctx->sigrdataset != NULL &&
|
||||
dns_rdataset_isassociated(qctx->sigrdataset))
|
||||
flags |= DNS_DNS64_DNSSEC;
|
||||
|
||||
for (result = dns_rdataset_first(qctx->rdataset);
|
||||
result == ISC_R_SUCCESS;
|
||||
result = dns_rdataset_next(qctx->rdataset)) {
|
||||
for (dns64 = ISC_LIST_HEAD(client->view->dns64);
|
||||
dns64 != NULL; dns64 = dns_dns64_next(dns64)) {
|
||||
|
||||
dns_rdataset_current(qctx->rdataset, &rdata);
|
||||
isc_buffer_availableregion(buffer, &r);
|
||||
INSIST(r.length >= 16);
|
||||
result = dns_dns64_aaaafroma(dns64, &netaddr,
|
||||
client->signer, env, flags,
|
||||
rdata.data, r.base);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
dns_rdata_reset(&rdata);
|
||||
continue;
|
||||
}
|
||||
isc_buffer_add(buffer, 16);
|
||||
isc_buffer_remainingregion(buffer, &r);
|
||||
isc_buffer_forward(buffer, 16);
|
||||
result = dns_message_gettemprdata(client->message,
|
||||
&dns64_rdata);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
dns_rdata_init(dns64_rdata);
|
||||
dns_rdata_fromregion(dns64_rdata, dns_rdataclass_in,
|
||||
dns_rdatatype_aaaa, &r);
|
||||
ISC_LIST_APPEND(dns64_rdatalist->rdata, dns64_rdata,
|
||||
link);
|
||||
dns64_rdata = NULL;
|
||||
dns_rdata_reset(&rdata);
|
||||
}
|
||||
}
|
||||
if (result != ISC_R_NOMORE)
|
||||
goto cleanup;
|
||||
|
||||
if (ISC_LIST_EMPTY(dns64_rdatalist->rdata))
|
||||
goto cleanup;
|
||||
|
||||
result = dns_rdatalist_tordataset(dns64_rdatalist, dns64_rdataset);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
dns_rdataset_setownercase(dns64_rdataset, mname);
|
||||
client->query.attributes |= NS_QUERYATTR_NOADDITIONAL;
|
||||
dns64_rdataset->trust = qctx->rdataset->trust;
|
||||
|
||||
/* Add rdataset to mname */
|
||||
ISC_LIST_APPEND(mname->list, dns64_rdataset, link);
|
||||
|
||||
ns_query_setorder(client, mname, dns64_rdataset);
|
||||
|
||||
dns64_rdataset = NULL;
|
||||
dns64_rdatalist = NULL;
|
||||
dns_message_takebuffer(client->message, &buffer);
|
||||
|
||||
/*
|
||||
* XXX: this functionality will need to be restored
|
||||
* inc_stats(client, ns_statscounter_dns64);
|
||||
*/
|
||||
result = ISC_R_SUCCESS;
|
||||
|
||||
cleanup:
|
||||
if (buffer != NULL)
|
||||
isc_buffer_free(&buffer);
|
||||
|
||||
if (dns64_rdata != NULL)
|
||||
dns_message_puttemprdata(client->message, &dns64_rdata);
|
||||
|
||||
if (dns64_rdataset != NULL)
|
||||
dns_message_puttemprdataset(client->message, &dns64_rdataset);
|
||||
|
||||
if (dns64_rdatalist != NULL) {
|
||||
for (dns64_rdata = ISC_LIST_HEAD(dns64_rdatalist->rdata);
|
||||
dns64_rdata != NULL;
|
||||
dns64_rdata = ISC_LIST_HEAD(dns64_rdatalist->rdata))
|
||||
{
|
||||
ISC_LIST_UNLINK(dns64_rdatalist->rdata,
|
||||
dns64_rdata, link);
|
||||
dns_message_puttemprdata(client->message, &dns64_rdata);
|
||||
}
|
||||
dns_message_puttemprdatalist(client->message, &dns64_rdatalist);
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
static void
|
||||
dns64_filter(query_ctx_t *qctx) {
|
||||
ns_client_t *client = qctx->client;
|
||||
dns_name_t *name, *mname;
|
||||
dns_rdata_t *myrdata;
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
dns_rdatalist_t *myrdatalist;
|
||||
dns_rdataset_t *myrdataset;
|
||||
isc_buffer_t *buffer;
|
||||
isc_region_t r;
|
||||
isc_result_t result;
|
||||
unsigned int i;
|
||||
const dns_section_t section = DNS_SECTION_ANSWER;
|
||||
|
||||
INSIST(client->dns64_aaaaok != NULL);
|
||||
INSIST(client->dns64_aaaaoklen ==
|
||||
dns_rdataset_count(qctx->rdataset));
|
||||
|
||||
name = qctx->fname;
|
||||
mname = NULL;
|
||||
buffer = NULL;
|
||||
myrdata = NULL;
|
||||
myrdataset = NULL;
|
||||
myrdatalist = NULL;
|
||||
result = dns_message_findname(client->message, section,
|
||||
name, dns_rdatatype_aaaa,
|
||||
qctx->rdataset->covers,
|
||||
&mname, &myrdataset);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
/*
|
||||
* We've already got an RRset of the given name and type.
|
||||
* There's nothing else to do;
|
||||
*/
|
||||
if (qctx->dbuf != NULL) {
|
||||
ns_client_releasename(client, &qctx->fname);
|
||||
}
|
||||
return;
|
||||
} else if (result == DNS_R_NXDOMAIN) {
|
||||
mname = name;
|
||||
qctx->fname = NULL;
|
||||
} else {
|
||||
RUNTIME_CHECK(result == DNS_R_NXRRSET);
|
||||
if (qctx->dbuf != NULL) {
|
||||
ns_client_releasename(client, &qctx->fname);
|
||||
}
|
||||
qctx->dbuf = NULL;
|
||||
}
|
||||
|
||||
if (qctx->rdataset->trust != dns_trust_secure) {
|
||||
client->query.attributes &= ~NS_QUERYATTR_SECURE;
|
||||
}
|
||||
|
||||
result = isc_buffer_allocate(client->mctx, &buffer,
|
||||
16 * dns_rdataset_count(qctx->rdataset));
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
result = dns_message_gettemprdataset(client->message, &myrdataset);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
result = dns_message_gettemprdatalist(client->message, &myrdatalist);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
dns_rdatalist_init(myrdatalist);
|
||||
myrdatalist->rdclass = dns_rdataclass_in;
|
||||
myrdatalist->type = dns_rdatatype_aaaa;
|
||||
myrdatalist->ttl = qctx->rdataset->ttl;
|
||||
|
||||
i = 0;
|
||||
for (result = dns_rdataset_first(qctx->rdataset);
|
||||
result == ISC_R_SUCCESS;
|
||||
result = dns_rdataset_next(qctx->rdataset))
|
||||
{
|
||||
if (!client->dns64_aaaaok[i++])
|
||||
continue;
|
||||
dns_rdataset_current(qctx->rdataset, &rdata);
|
||||
INSIST(rdata.length == 16);
|
||||
isc_buffer_putmem(buffer, rdata.data, rdata.length);
|
||||
isc_buffer_remainingregion(buffer, &r);
|
||||
isc_buffer_forward(buffer, rdata.length);
|
||||
result = dns_message_gettemprdata(client->message, &myrdata);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
dns_rdata_init(myrdata);
|
||||
dns_rdata_fromregion(myrdata, dns_rdataclass_in,
|
||||
dns_rdatatype_aaaa, &r);
|
||||
ISC_LIST_APPEND(myrdatalist->rdata, myrdata, link);
|
||||
myrdata = NULL;
|
||||
dns_rdata_reset(&rdata);
|
||||
}
|
||||
if (result != ISC_R_NOMORE)
|
||||
goto cleanup;
|
||||
|
||||
result = dns_rdatalist_tordataset(myrdatalist, myrdataset);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
dns_rdataset_setownercase(myrdataset, name);
|
||||
client->query.attributes |= NS_QUERYATTR_NOADDITIONAL;
|
||||
if (mname == name) {
|
||||
if (qctx->dbuf != NULL) {
|
||||
ns_client_keepname(client, name, qctx->dbuf);
|
||||
}
|
||||
dns_message_addname(client->message, name,
|
||||
section);
|
||||
qctx->dbuf = NULL;
|
||||
}
|
||||
myrdataset->trust = qctx->rdataset->trust;
|
||||
|
||||
/* Add rdataset to mname */
|
||||
ISC_LIST_APPEND(mname->list, myrdataset, link);
|
||||
|
||||
ns_query_setorder(client, mname, myrdataset);
|
||||
|
||||
myrdataset = NULL;
|
||||
myrdatalist = NULL;
|
||||
dns_message_takebuffer(client->message, &buffer);
|
||||
|
||||
cleanup:
|
||||
if (buffer != NULL)
|
||||
isc_buffer_free(&buffer);
|
||||
|
||||
if (myrdata != NULL)
|
||||
dns_message_puttemprdata(client->message, &myrdata);
|
||||
|
||||
if (myrdataset != NULL)
|
||||
dns_message_puttemprdataset(client->message, &myrdataset);
|
||||
|
||||
if (myrdatalist != NULL) {
|
||||
for (myrdata = ISC_LIST_HEAD(myrdatalist->rdata);
|
||||
myrdata != NULL;
|
||||
myrdata = ISC_LIST_HEAD(myrdatalist->rdata))
|
||||
{
|
||||
ISC_LIST_UNLINK(myrdatalist->rdata, myrdata, link);
|
||||
dns_message_puttemprdata(client->message, &myrdata);
|
||||
}
|
||||
dns_message_puttemprdatalist(client->message, &myrdatalist);
|
||||
}
|
||||
if (qctx->dbuf != NULL) {
|
||||
ns_client_releasename(client, &name);
|
||||
}
|
||||
}
|
||||
|
||||
static ns_hookresult_t
|
||||
dns64_qctx_initialize(void *arg, void *cbdata, isc_result_t *resp) {
|
||||
UNUSED(arg);
|
||||
UNUSED(cbdata);
|
||||
|
||||
*resp = ISC_R_UNSET;
|
||||
return (NS_HOOK_CONTINUE);
|
||||
}
|
||||
|
||||
static ns_hookresult_t
|
||||
dns64_respond_begin(void *arg, void *cbdata, isc_result_t *resp) {
|
||||
query_ctx_t *qctx = (query_ctx_t *) arg;
|
||||
|
||||
UNUSED(cbdata);
|
||||
|
||||
/*
|
||||
* Check to see if the AAAA RRset has non-excluded addresses
|
||||
* in it. If not look for a A RRset.
|
||||
*/
|
||||
INSIST(qctx->client->dns64_aaaaok == NULL);
|
||||
|
||||
if (qctx->qtype == dns_rdatatype_aaaa && !qctx->dns64_exclude &&
|
||||
!ISC_LIST_EMPTY(qctx->view->dns64) &&
|
||||
qctx->client->message->rdclass == dns_rdataclass_in &&
|
||||
!dns64_aaaaok(qctx->client, qctx->rdataset, qctx->sigrdataset))
|
||||
{
|
||||
/*
|
||||
* Look to see if there are A records for this name.
|
||||
*/
|
||||
qctx->client->dns64_ttl = qctx->rdataset->ttl;
|
||||
SAVE(qctx->client->dns64_aaaa, qctx->rdataset);
|
||||
SAVE(qctx->client->dns64_sigaaaa, qctx->sigrdataset);
|
||||
ns_client_releasename(qctx->client, &qctx->fname);
|
||||
dns_db_detachnode(qctx->db, &qctx->node);
|
||||
qctx->type = qctx->qtype = dns_rdatatype_a;
|
||||
qctx->dns64_exclude = qctx->dns64 = true;
|
||||
|
||||
/*
|
||||
* XXX: we are depending here on DNS64
|
||||
* being reached before any other modules that
|
||||
* might set up recursion. In particular if
|
||||
* the filter-aaaa module runs first, there'll
|
||||
* be an assertion failure. We need to make this
|
||||
* order-indeendent.
|
||||
*/
|
||||
*resp = ns_query_lookup(qctx);
|
||||
return (NS_HOOK_RETURN);
|
||||
}
|
||||
|
||||
*resp = ISC_R_UNSET;
|
||||
return (NS_HOOK_CONTINUE);
|
||||
}
|
||||
|
||||
static ns_hookresult_t
|
||||
dns64_addanswer(void *arg, void *cbdata, isc_result_t *resp) {
|
||||
query_ctx_t *qctx = (query_ctx_t *) arg;
|
||||
|
||||
UNUSED(cbdata);
|
||||
|
||||
if (qctx->dns64) {
|
||||
isc_result_t result = dns64_synth(qctx);
|
||||
qctx->noqname = NULL;
|
||||
dns_rdataset_disassociate(qctx->rdataset);
|
||||
dns_message_puttemprdataset(qctx->client->message,
|
||||
&qctx->rdataset);
|
||||
if (result == ISC_R_NOMORE) {
|
||||
if (qctx->dns64_exclude) {
|
||||
if (!qctx->is_zone) {
|
||||
*resp = ns_query_done(qctx);
|
||||
return (NS_HOOK_RETURN);
|
||||
}
|
||||
/*
|
||||
* Add a fake SOA record.
|
||||
*/
|
||||
(void) ns_query_addsoa(qctx, 600,
|
||||
DNS_SECTION_AUTHORITY);
|
||||
*resp = ns_query_done(qctx);
|
||||
return (NS_HOOK_RETURN);
|
||||
}
|
||||
if (qctx->is_zone) {
|
||||
qctx->nxresult = DNS_R_NXDOMAIN;
|
||||
*resp = ns_query_nodata(qctx);
|
||||
} else {
|
||||
qctx->nxresult = DNS_R_NXDOMAIN;
|
||||
*resp = ns_query_ncache(qctx);
|
||||
}
|
||||
} else if (result != ISC_R_SUCCESS) {
|
||||
qctx->result = result;
|
||||
*resp = ns_query_done(qctx);
|
||||
} else {
|
||||
*resp = ISC_R_COMPLETE;
|
||||
}
|
||||
return (NS_HOOK_RETURN);
|
||||
} else if (qctx->client->dns64_aaaaok != NULL) {
|
||||
dns64_filter(qctx);
|
||||
ns_client_putrdataset(qctx->client, &qctx->rdataset);
|
||||
*resp = ISC_R_COMPLETE;
|
||||
return (NS_HOOK_RETURN);
|
||||
}
|
||||
|
||||
*resp = ISC_R_UNSET;
|
||||
return (NS_HOOK_CONTINUE);
|
||||
}
|
||||
|
||||
static ns_hookresult_t
|
||||
dns64_resume_restored(void *arg, void *cbdata, isc_result_t *resp) {
|
||||
query_ctx_t *qctx = (query_ctx_t *) arg;
|
||||
|
||||
UNUSED(cbdata);
|
||||
|
||||
if (DNS64(qctx->client)) {
|
||||
qctx->client->query.attributes &= ~NS_QUERYATTR_DNS64;
|
||||
qctx->dns64 = true;
|
||||
}
|
||||
|
||||
if (DNS64EXCLUDE(qctx->client)) {
|
||||
qctx->client->query.attributes &= ~NS_QUERYATTR_DNS64EXCLUDE;
|
||||
qctx->dns64_exclude = true;
|
||||
}
|
||||
|
||||
*resp = ISC_R_UNSET;
|
||||
return (NS_HOOK_CONTINUE);
|
||||
}
|
||||
|
||||
static ns_hookresult_t
|
||||
dns64_notfound_recurse(void *arg, void *cbdata, isc_result_t *resp) {
|
||||
query_ctx_t *qctx = (query_ctx_t *) arg;
|
||||
|
||||
UNUSED(cbdata);
|
||||
|
||||
if (qctx->dns64) {
|
||||
qctx->client->query.attributes |= NS_QUERYATTR_DNS64;
|
||||
}
|
||||
if (qctx->dns64_exclude) {
|
||||
qctx->client->query.attributes |= NS_QUERYATTR_DNS64EXCLUDE;
|
||||
}
|
||||
|
||||
*resp = ISC_R_UNSET;
|
||||
return (NS_HOOK_CONTINUE);
|
||||
}
|
||||
|
||||
static ns_hookresult_t
|
||||
dns64_delegation_recurse(void *arg, void *cbdata, isc_result_t *resp) {
|
||||
query_ctx_t *qctx = (query_ctx_t *) arg;
|
||||
|
||||
UNUSED(cbdata);
|
||||
|
||||
/*
|
||||
* Look up an A record so we can synthesize DNS64.
|
||||
*/
|
||||
if (qctx->dns64) {
|
||||
qctx->result = ns_query_recurse(qctx->client,
|
||||
dns_rdatatype_a,
|
||||
qctx->client->query.qname,
|
||||
NULL, NULL,
|
||||
qctx->resuming);
|
||||
qctx->client->query.attributes |= NS_QUERYATTR_RECURSING;
|
||||
if (qctx->result == ISC_R_SUCCESS) {
|
||||
qctx->client->query.attributes |= NS_QUERYATTR_DNS64;
|
||||
if (qctx->dns64_exclude) {
|
||||
qctx->client->query.attributes |=
|
||||
NS_QUERYATTR_DNS64EXCLUDE;
|
||||
}
|
||||
}
|
||||
*resp = ISC_R_COMPLETE;
|
||||
return (NS_HOOK_RETURN);
|
||||
}
|
||||
|
||||
*resp = ISC_R_UNSET;
|
||||
return (NS_HOOK_CONTINUE);
|
||||
}
|
||||
|
||||
static ns_hookresult_t
|
||||
dns64_nodata_begin(void *arg, void *cbdata, isc_result_t *resp) {
|
||||
query_ctx_t *qctx = (query_ctx_t *) arg;
|
||||
|
||||
UNUSED(cbdata);
|
||||
|
||||
if (qctx->dns64 && !qctx->dns64_exclude) {
|
||||
isc_buffer_t b;
|
||||
|
||||
/*
|
||||
* Restore the answers from the previous AAAA lookup.
|
||||
*/
|
||||
if (qctx->rdataset != NULL) {
|
||||
ns_client_putrdataset(qctx->client, &qctx->rdataset);
|
||||
}
|
||||
if (qctx->sigrdataset != NULL) {
|
||||
ns_client_putrdataset(qctx->client, &qctx->sigrdataset);
|
||||
}
|
||||
RESTORE(qctx->rdataset, qctx->client->dns64_aaaa);
|
||||
RESTORE(qctx->sigrdataset, qctx->client->dns64_sigaaaa);
|
||||
if (qctx->fname == NULL) {
|
||||
qctx->dbuf = ns_client_getnamebuf(qctx->client);
|
||||
if (qctx->dbuf == NULL) {
|
||||
QUERY_ERROR(qctx, DNS_R_SERVFAIL);
|
||||
*resp = ns_query_done(qctx);
|
||||
return (NS_HOOK_RETURN);
|
||||
}
|
||||
qctx->fname = ns_client_newname(qctx->client,
|
||||
qctx->dbuf, &b);
|
||||
if (qctx->fname == NULL) {
|
||||
QUERY_ERROR(qctx, DNS_R_SERVFAIL);
|
||||
*resp = ns_query_done(qctx);
|
||||
return (NS_HOOK_RETURN);
|
||||
}
|
||||
}
|
||||
dns_name_copy(qctx->client->query.qname, qctx->fname, NULL);
|
||||
qctx->dns64 = false;
|
||||
} else if ((qctx->nxresult == DNS_R_NXRRSET ||
|
||||
qctx->nxresult == DNS_R_NCACHENXRRSET) &&
|
||||
!ISC_LIST_EMPTY(qctx->view->dns64) &&
|
||||
!qctx->nxrewrite &&
|
||||
qctx->client->message->rdclass == dns_rdataclass_in &&
|
||||
qctx->qtype == dns_rdatatype_aaaa)
|
||||
{
|
||||
/*
|
||||
* Look to see if there are A records for this name.
|
||||
*/
|
||||
switch (qctx->nxresult) {
|
||||
case DNS_R_NCACHENXRRSET:
|
||||
/*
|
||||
* This is from the negative cache; if the ttl is
|
||||
* zero, we need to work out whether we have just
|
||||
* decremented to zero or there was no negative
|
||||
* cache ttl in the answer.
|
||||
*/
|
||||
if (qctx->rdataset->ttl != 0) {
|
||||
qctx->client->dns64_ttl = qctx->rdataset->ttl;
|
||||
break;
|
||||
}
|
||||
if (dns_rdataset_first(qctx->rdataset) == ISC_R_SUCCESS)
|
||||
qctx->client->dns64_ttl = 0;
|
||||
break;
|
||||
case DNS_R_NXRRSET:
|
||||
qctx->client->dns64_ttl =
|
||||
dns64_ttl(qctx->db, qctx->version);
|
||||
break;
|
||||
default:
|
||||
INSIST(0);
|
||||
ISC_UNREACHABLE();
|
||||
}
|
||||
|
||||
SAVE(qctx->client->dns64_aaaa, qctx->rdataset);
|
||||
SAVE(qctx->client->dns64_sigaaaa, qctx->sigrdataset);
|
||||
ns_client_releasename(qctx->client, &qctx->fname);
|
||||
dns_db_detachnode(qctx->db, &qctx->node);
|
||||
qctx->type = qctx->qtype = dns_rdatatype_a;
|
||||
qctx->dns64 = true;
|
||||
*resp = ns_query_lookup(qctx);
|
||||
return (NS_HOOK_RETURN);
|
||||
}
|
||||
|
||||
*resp = ISC_R_UNSET;
|
||||
return (NS_HOOK_CONTINUE);
|
||||
}
|
||||
|
||||
static ns_hookresult_t
|
||||
dns64_zerottl_recurse(void *arg, void *cbdata, isc_result_t *resp) {
|
||||
query_ctx_t *qctx = (query_ctx_t *) arg;
|
||||
|
||||
UNUSED(cbdata);
|
||||
|
||||
if (qctx->dns64) {
|
||||
qctx->client->query.attributes |= NS_QUERYATTR_DNS64;
|
||||
}
|
||||
if (qctx->dns64_exclude) {
|
||||
qctx->client->query.attributes |= NS_QUERYATTR_DNS64EXCLUDE;
|
||||
}
|
||||
|
||||
*resp = ISC_R_UNSET;
|
||||
return (NS_HOOK_CONTINUE);
|
||||
}
|
||||
|
||||
static ns_hookresult_t
|
||||
dns64_qctx_destroy(void *arg, void *cbdata, isc_result_t *resp) {
|
||||
UNUSED(arg);
|
||||
UNUSED(cbdata);
|
||||
|
||||
*resp = ISC_R_UNSET;
|
||||
return (NS_HOOK_CONTINUE);
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
<!--
|
||||
- Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
-
|
||||
- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-
|
||||
- See the COPYRIGHT file distributed with this work for additional
|
||||
- information regarding copyright ownership.
|
||||
-->
|
||||
|
||||
<!-- Converted by db4-upgrade version 1.0 -->
|
||||
<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.dns64">
|
||||
<info>
|
||||
<date>2018-11-30</date>
|
||||
</info>
|
||||
<refentryinfo>
|
||||
<corpname>ISC</corpname>
|
||||
<corpauthor>Internet Systems Consortium, Inc.</corpauthor>
|
||||
</refentryinfo>
|
||||
<refmeta>
|
||||
<refentrytitle><application>dns64.so</application></refentrytitle>
|
||||
<manvolnum>8</manvolnum>
|
||||
<refmiscinfo>BIND9</refmiscinfo>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname><application>dns64.so</application></refname>
|
||||
<refpurpose>perform DNS64 synthesis</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<docinfo>
|
||||
<copyright>
|
||||
<year>2018</year>
|
||||
<holder>Internet Systems Consortium, Inc. ("ISC")</holder>
|
||||
</copyright>
|
||||
</docinfo>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis sepchar=" ">
|
||||
<command>plugin query "dns64.so"</command>
|
||||
<arg choice="opt" rep="norepeat"><replaceable class="parameter">{ parameters }</replaceable></arg>;
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsection><info><title>DESCRIPTION</title></info>
|
||||
<para>
|
||||
<command>dns64.so</command> is a query plugin module for
|
||||
<command>named</command>, enabling <command>named</command>
|
||||
to perform DNS64 address synthesis.
|
||||
</para>
|
||||
<para>
|
||||
Until BIND 9.12, this feature was implemented natively in
|
||||
<command>named</command> and enabled with the
|
||||
<command>dns64</command> option.
|
||||
This option is now deprecated in <filename>named.conf</filename>,
|
||||
but can be passed as parameters to the
|
||||
<command>dns64.so</command> plugin, for example:
|
||||
</para>
|
||||
<programlisting>
|
||||
acl rfc1918 { 10/8; 192.168/16; 172.16/12; };
|
||||
|
||||
plugin query "/usr/local/lib/dns64.so" {
|
||||
dns64 64:FF9B::/96 {
|
||||
clients { any; };
|
||||
mapped { !rfc1918; any; };
|
||||
exclude { 64:FF9B::/96; ::ffff:0000:0000/96; };
|
||||
suffix ::;
|
||||
};
|
||||
|
||||
dns64-server "dns64.example.net.";
|
||||
dns64-contact "hostmaster.example.net.";
|
||||
};
|
||||
</programlisting>
|
||||
<para>
|
||||
This plugin enables <command>named</command> to
|
||||
return mapped IPv4 addresses to AAAA queries when
|
||||
there are no AAAA records. It is intended to be
|
||||
used in conjunction with NAT64.
|
||||
</para>
|
||||
<para>
|
||||
Each <command>dns64</command> option defined in the plugin
|
||||
parameters defines one DNS64 prefix. Multiple DNS64 prefixes
|
||||
can be defined.
|
||||
</para>
|
||||
<para>
|
||||
Compatible IPv6 prefixes have lengths of 32, 40, 48, 56,
|
||||
64 and 96 as per RFC 6052.
|
||||
</para>
|
||||
<para>
|
||||
Additionally a reverse IP6.ARPA zone will be created for
|
||||
the prefix to provide a mapping from the IP6.ARPA names
|
||||
to the corresponding IN-ADDR.ARPA names using synthesized
|
||||
CNAMEs. <command>dns64-server</command> and
|
||||
<command>dns64-contact</command> can be used to specify
|
||||
the name of the server and contact for the zones.
|
||||
These are not settable on a per-prefix basis.
|
||||
</para>
|
||||
<para>
|
||||
Each <command>dns64</command> supports an optional
|
||||
<command>clients</command> ACL that determines which
|
||||
clients are affected by this directive. If not defined,
|
||||
it defaults to <userinput>any;</userinput>.
|
||||
</para>
|
||||
<para>
|
||||
Each <command>dns64</command> supports an optional
|
||||
<command>mapped</command> ACL that selects which
|
||||
IPv4 addresses are to be mapped in the corresponding
|
||||
A RRset. If not defined it defaults to
|
||||
<userinput>any;</userinput>.
|
||||
</para>
|
||||
<para>
|
||||
Normally, DNS64 won't apply to a domain name that
|
||||
owns one or more AAAA records; these records will
|
||||
simply be returned. The optional
|
||||
<command>exclude</command> ACL allows specification
|
||||
of a list of IPv6 addresses that will be ignored
|
||||
if they appear in a domain name's AAAA records, and
|
||||
DNS64 will be applied to any A records the domain
|
||||
name owns. If not defined, <command>exclude</command>
|
||||
defaults to ::ffff:0.0.0.0/96.
|
||||
</para>
|
||||
<para>
|
||||
A optional <command>suffix</command> can also
|
||||
be defined to set the bits trailing the mapped
|
||||
IPv4 address bits. By default these bits are
|
||||
set to <userinput>::</userinput>. The bits
|
||||
matching the prefix and mapped IPv4 address
|
||||
must be zero.
|
||||
</para>
|
||||
<para>
|
||||
If <command>recursive-only</command> is set to
|
||||
<command>yes</command> the DNS64 synthesis will
|
||||
only happen for recursive queries. The default
|
||||
is <command>no</command>.
|
||||
</para>
|
||||
<para>
|
||||
If <command>break-dnssec</command> is set to
|
||||
<command>yes</command> the DNS64 synthesis will
|
||||
happen even if the result, if validated, would
|
||||
cause a DNSSEC validation failure. If this option
|
||||
is set to <command>no</command> (the default), the DO
|
||||
is set on the incoming query, and there are RRSIGs on
|
||||
the applicable records, then synthesis will not happen.
|
||||
</para>
|
||||
</refsection>
|
||||
|
||||
<refsection><info><title>SEE ALSO</title></info>
|
||||
<para>
|
||||
<citetitle>BIND 9 Administrator Reference Manual</citetitle>.
|
||||
</para>
|
||||
</refsection>
|
||||
|
||||
</refentry>
|
||||
@@ -0,0 +1,135 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<!--
|
||||
- Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
|
||||
-
|
||||
- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>dns64.so</title>
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
|
||||
<a name="man.dns64"></a><div class="titlepage"></div>
|
||||
<div class="refnamediv">
|
||||
<h2>Name</h2>
|
||||
<p><span class="application">dns64.so</span> — perform DNS64 synthesis</p>
|
||||
</div>
|
||||
<div class="refsynopsisdiv">
|
||||
<h2>Synopsis</h2>
|
||||
<div class="cmdsynopsis"><p><code class="command">plugin query "dns64.so"</code> [<em class="replaceable"><code>{ parameters }</code></em>];
|
||||
</p></div>
|
||||
</div>
|
||||
<div class="refsection">
|
||||
<a name="id-1.7"></a><h2>DESCRIPTION</h2>
|
||||
<p>
|
||||
<span class="command"><strong>dns64.so</strong></span> is a query plugin module for
|
||||
<span class="command"><strong>named</strong></span>, enabling <span class="command"><strong>named</strong></span>
|
||||
to perform DNS64 address synthesis.
|
||||
</p>
|
||||
<p>
|
||||
Until BIND 9.12, this feature was implemented natively in
|
||||
<span class="command"><strong>named</strong></span> and enabled with the
|
||||
<span class="command"><strong>dns64</strong></span> option.
|
||||
This option is now deprecated in <code class="filename">named.conf</code>,
|
||||
but can be passed as parameters to the
|
||||
<span class="command"><strong>dns64.so</strong></span> plugin, for example:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
acl rfc1918 { 10/8; 192.168/16; 172.16/12; };
|
||||
|
||||
plugin query "/usr/local/lib/dns64.so" {
|
||||
dns64 64:FF9B::/96 {
|
||||
clients { any; };
|
||||
mapped { !rfc1918; any; };
|
||||
exclude { 64:FF9B::/96; ::ffff:0000:0000/96; };
|
||||
suffix ::;
|
||||
};
|
||||
|
||||
dns64-server "dns64.example.net.";
|
||||
dns64-contact "hostmaster.example.net.";
|
||||
};
|
||||
</pre>
|
||||
<p>
|
||||
This plugin enables <span class="command"><strong>named</strong></span> to
|
||||
return mapped IPv4 addresses to AAAA queries when
|
||||
there are no AAAA records. It is intended to be
|
||||
used in conjunction with NAT64.
|
||||
</p>
|
||||
<p>
|
||||
Each <span class="command"><strong>dns64</strong></span> option defined in the plugin
|
||||
parameters defines one DNS64 prefix. Multiple DNS64 prefixes
|
||||
can be defined.
|
||||
</p>
|
||||
<p>
|
||||
Compatible IPv6 prefixes have lengths of 32, 40, 48, 56,
|
||||
64 and 96 as per RFC 6052.
|
||||
</p>
|
||||
<p>
|
||||
Additionally a reverse IP6.ARPA zone will be created for
|
||||
the prefix to provide a mapping from the IP6.ARPA names
|
||||
to the corresponding IN-ADDR.ARPA names using synthesized
|
||||
CNAMEs. <span class="command"><strong>dns64-server</strong></span> and
|
||||
<span class="command"><strong>dns64-contact</strong></span> can be used to specify
|
||||
the name of the server and contact for the zones.
|
||||
These are not settable on a per-prefix basis.
|
||||
</p>
|
||||
<p>
|
||||
Each <span class="command"><strong>dns64</strong></span> supports an optional
|
||||
<span class="command"><strong>clients</strong></span> ACL that determines which
|
||||
clients are affected by this directive. If not defined,
|
||||
it defaults to <strong class="userinput"><code>any;</code></strong>.
|
||||
</p>
|
||||
<p>
|
||||
Each <span class="command"><strong>dns64</strong></span> supports an optional
|
||||
<span class="command"><strong>mapped</strong></span> ACL that selects which
|
||||
IPv4 addresses are to be mapped in the corresponding
|
||||
A RRset. If not defined it defaults to
|
||||
<strong class="userinput"><code>any;</code></strong>.
|
||||
</p>
|
||||
<p>
|
||||
Normally, DNS64 won't apply to a domain name that
|
||||
owns one or more AAAA records; these records will
|
||||
simply be returned. The optional
|
||||
<span class="command"><strong>exclude</strong></span> ACL allows specification
|
||||
of a list of IPv6 addresses that will be ignored
|
||||
if they appear in a domain name's AAAA records, and
|
||||
DNS64 will be applied to any A records the domain
|
||||
name owns. If not defined, <span class="command"><strong>exclude</strong></span>
|
||||
defaults to ::ffff:0.0.0.0/96.
|
||||
</p>
|
||||
<p>
|
||||
A optional <span class="command"><strong>suffix</strong></span> can also
|
||||
be defined to set the bits trailing the mapped
|
||||
IPv4 address bits. By default these bits are
|
||||
set to <strong class="userinput"><code>::</code></strong>. The bits
|
||||
matching the prefix and mapped IPv4 address
|
||||
must be zero.
|
||||
</p>
|
||||
<p>
|
||||
If <span class="command"><strong>recursive-only</strong></span> is set to
|
||||
<span class="command"><strong>yes</strong></span> the DNS64 synthesis will
|
||||
only happen for recursive queries. The default
|
||||
is <span class="command"><strong>no</strong></span>.
|
||||
</p>
|
||||
<p>
|
||||
If <span class="command"><strong>break-dnssec</strong></span> is set to
|
||||
<span class="command"><strong>yes</strong></span> the DNS64 synthesis will
|
||||
happen even if the result, if validated, would
|
||||
cause a DNSSEC validation failure. If this option
|
||||
is set to <span class="command"><strong>no</strong></span> (the default), the DO
|
||||
is set on the incoming query, and there are RRSIGs on
|
||||
the applicable records, then synthesis will not happen.
|
||||
</p>
|
||||
</div>
|
||||
<div class="refsection">
|
||||
<a name="id-1.8"></a><h2>SEE ALSO</h2>
|
||||
<p>
|
||||
<em class="citetitle">BIND 9 Administrator Reference Manual</em>.
|
||||
</p>
|
||||
</div>
|
||||
</div></body>
|
||||
</html>
|
||||
@@ -34,6 +34,8 @@ options {
|
||||
};
|
||||
};
|
||||
|
||||
plugin query "../../../../plugins/lib/dns64.so";
|
||||
|
||||
zone "." {
|
||||
type master;
|
||||
file "root.db";
|
||||
|
||||
@@ -58,6 +58,8 @@ options {
|
||||
response-policy { zone "rpz"; };
|
||||
};
|
||||
|
||||
plugin query "../../../../plugins/lib/dns64.so";
|
||||
|
||||
zone "." {
|
||||
type hint;
|
||||
file "../../common/root.hint";
|
||||
|
||||
@@ -41,6 +41,8 @@ options {
|
||||
response-policy { zone "rpz"; };
|
||||
};
|
||||
|
||||
plugin query "../../../../plugins/lib/dns64.so";
|
||||
|
||||
zone "." {
|
||||
type hint;
|
||||
file "../../common/root.hint";
|
||||
|
||||
@@ -18106,6 +18106,7 @@ allow-query { !{ !10/8; any; }; key example; };
|
||||
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="../../bin/dnssec/dnssec-verify.docbook"/>
|
||||
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="../../bin/tools/dnstap-read.docbook"/>
|
||||
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="../../bin/plugins/filter-aaaa.docbook"/>
|
||||
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="../../bin/plugins/dns64.docbook"/>
|
||||
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="../../bin/dig/host.docbook"/>
|
||||
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="../../bin/tools/mdig.docbook"/>
|
||||
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="../../bin/check/named-checkconf.docbook"/>
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<!--
|
||||
- Copyright (C) 2000-2018 Internet Systems Consortium, Inc. ("ISC")
|
||||
-
|
||||
- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>dns64.so</title>
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
|
||||
<link rel="home" href="Bv9ARM.html" title="BIND 9 Administrator Reference Manual">
|
||||
<link rel="up" href="Bv9ARM.ch12.html" title="Manual pages">
|
||||
<link rel="prev" href="man.filter-aaaa.html" title="filter-aaaa.so">
|
||||
<link rel="next" href="man.host.html" title="host">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr><th colspan="3" align="center"><span class="application">dns64.so</span></th></tr>
|
||||
<tr>
|
||||
<td width="20%" align="left">
|
||||
<a accesskey="p" href="man.filter-aaaa.html">Prev</a> </td>
|
||||
<th width="60%" align="center">Manual pages</th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="man.host.html">Next</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
</div>
|
||||
<div class="refentry">
|
||||
<a name="man.dns64"></a><div class="titlepage"></div>
|
||||
<div class="refnamediv">
|
||||
<h2>Name</h2>
|
||||
<p><span class="application">dns64.so</span> — perform DNS64 synthesis</p>
|
||||
</div>
|
||||
<div class="refsynopsisdiv">
|
||||
<h2>Synopsis</h2>
|
||||
<div class="cmdsynopsis"><p><code class="command">hook query "dns64.so"</code> [<em class="replaceable"><code>{ parameters }</code></em>];
|
||||
</p></div>
|
||||
</div>
|
||||
<div class="refsection">
|
||||
<a name="id-1.13.20.7"></a><h2>DESCRIPTION</h2>
|
||||
<p>
|
||||
<span class="command"><strong>dns64.so</strong></span> is a query hook module for
|
||||
<span class="command"><strong>named</strong></span>, enabling <span class="command"><strong>named</strong></span>
|
||||
to perform DNS64 address synthesis.
|
||||
</p>
|
||||
<p>
|
||||
Until BIND 9.12, this feature was implemented natively in
|
||||
<span class="command"><strong>named</strong></span> and enabled with the
|
||||
<span class="command"><strong>dns64</strong></span> option.
|
||||
This option is now deprecated in <code class="filename">named.conf</code>,
|
||||
but can be passed as parameters to the
|
||||
<span class="command"><strong>dns64.so</strong></span> module, for example:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
acl rfc1918 { 10/8; 192.168/16; 172.16/12; };
|
||||
|
||||
plugin query "/usr/local/lib/dns64.so" {
|
||||
dns64 64:FF9B::/96 {
|
||||
clients { any; };
|
||||
mapped { !rfc1918; any; };
|
||||
exclude { 64:FF9B::/96; ::ffff:0000:0000/96; };
|
||||
suffix ::;
|
||||
};
|
||||
|
||||
dns64-server "dns64.example.net.";
|
||||
dns64-contact "hostmaster.example.net.";
|
||||
};
|
||||
</pre>
|
||||
<p>
|
||||
This plugin enables <span class="command"><strong>named</strong></span> to
|
||||
return mapped IPv4 addresses to AAAA queries when
|
||||
there are no AAAA records. It is intended to be
|
||||
used in conjunction with NAT64.
|
||||
</p>
|
||||
<p>
|
||||
Each <span class="command"><strong>dns64</strong></span> option defined in the plugin
|
||||
parameters defines one DNS64 prefix. Multiple DNS64 prefixes
|
||||
can be defined.
|
||||
</p>
|
||||
<p>
|
||||
Compatible IPv6 prefixes have lengths of 32, 40, 48, 56,
|
||||
64 and 96 as per RFC 6052.
|
||||
</p>
|
||||
<p>
|
||||
Additionally a reverse IP6.ARPA zone will be created for
|
||||
the prefix to provide a mapping from the IP6.ARPA names
|
||||
to the corresponding IN-ADDR.ARPA names using synthesized
|
||||
CNAMEs. <span class="command"><strong>dns64-server</strong></span> and
|
||||
<span class="command"><strong>dns64-contact</strong></span> can be used to specify
|
||||
the name of the server and contact for the zones.
|
||||
These are not settable on a per-prefix basis.
|
||||
</p>
|
||||
<p>
|
||||
Each <span class="command"><strong>dns64</strong></span> supports an optional
|
||||
<span class="command"><strong>clients</strong></span> ACL that determines which
|
||||
clients are affected by this directive. If not defined,
|
||||
it defaults to <strong class="userinput"><code>any;</code></strong>.
|
||||
</p>
|
||||
<p>
|
||||
Each <span class="command"><strong>dns64</strong></span> supports an optional
|
||||
<span class="command"><strong>mapped</strong></span> ACL that selects which
|
||||
IPv4 addresses are to be mapped in the corresponding
|
||||
A RRset. If not defined it defaults to
|
||||
<strong class="userinput"><code>any;</code></strong>.
|
||||
</p>
|
||||
<p>
|
||||
Normally, DNS64 won't apply to a domain name that
|
||||
owns one or more AAAA records; these records will
|
||||
simply be returned. The optional
|
||||
<span class="command"><strong>exclude</strong></span> ACL allows specification
|
||||
of a list of IPv6 addresses that will be ignored
|
||||
if they appear in a domain name's AAAA records, and
|
||||
DNS64 will be applied to any A records the domain
|
||||
name owns. If not defined, <span class="command"><strong>exclude</strong></span>
|
||||
defaults to ::ffff:0.0.0.0/96.
|
||||
</p>
|
||||
<p>
|
||||
A optional <span class="command"><strong>suffix</strong></span> can also
|
||||
be defined to set the bits trailing the mapped
|
||||
IPv4 address bits. By default these bits are
|
||||
set to <strong class="userinput"><code>::</code></strong>. The bits
|
||||
matching the prefix and mapped IPv4 address
|
||||
must be zero.
|
||||
</p>
|
||||
<p>
|
||||
If <span class="command"><strong>recursive-only</strong></span> is set to
|
||||
<span class="command"><strong>yes</strong></span> the DNS64 synthesis will
|
||||
only happen for recursive queries. The default
|
||||
is <span class="command"><strong>no</strong></span>.
|
||||
</p>
|
||||
<p>
|
||||
If <span class="command"><strong>break-dnssec</strong></span> is set to
|
||||
<span class="command"><strong>yes</strong></span> the DNS64 synthesis will
|
||||
happen even if the result, if validated, would
|
||||
cause a DNSSEC validation failure. If this option
|
||||
is set to <span class="command"><strong>no</strong></span> (the default), the DO
|
||||
is set on the incoming query, and there are RRSIGs on
|
||||
the applicable records, then synthesis will not happen.
|
||||
</p>
|
||||
</div>
|
||||
<div class="refsection">
|
||||
<a name="id-1.13.20.8"></a><h2>SEE ALSO</h2>
|
||||
<p>
|
||||
<em class="citetitle">BIND 9 Administrator Reference Manual</em>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr>
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left">
|
||||
<a accesskey="p" href="man.filter-aaaa.html">Prev</a> </td>
|
||||
<td width="20%" align="center"><a accesskey="u" href="Bv9ARM.ch12.html">Up</a></td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="man.host.html">Next</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">
|
||||
<span class="application">filter-aaaa.so</span> </td>
|
||||
<td width="20%" align="center"><a accesskey="h" href="Bv9ARM.html">Home</a></td>
|
||||
<td width="40%" align="right" valign="top"> host</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<p xmlns:db="http://docbook.org/ns/docbook" style="text-align: center;">BIND 9.13.4 (Development Release)</p>
|
||||
</body>
|
||||
</html>
|
||||
+8
-7
@@ -26,15 +26,16 @@
|
||||
in the future.
|
||||
</para>
|
||||
<para>
|
||||
The only plugin currently included in BIND is
|
||||
<filename>filter-aaaa.so</filename>, which replaces the
|
||||
<command>filter-aaaa</command> feature that previously existed natively
|
||||
The only plugins currently included in BIND are
|
||||
<filename>filter-aaaa.so</filename> and <filename>dns64.so</filename>,
|
||||
which replace the <command>filter-aaaa</command> and
|
||||
<command>dns64</command> features that previously existed natively
|
||||
as part of <command>named</command>.
|
||||
The code for this feature has been removed from <command>named</command>,
|
||||
and can no longer be configured using standard
|
||||
The code for these features has been removed from <command>named</command>,
|
||||
and they can no longer be configured using standard
|
||||
<filename>named.conf</filename> syntax, but linking in the
|
||||
<filename>filter-aaaa.so</filename> plugin provides identical
|
||||
functionality.
|
||||
<filename>filter-aaaa.so</filename> or <filename>dns64.so</filename>
|
||||
plugins provides identical functionality.
|
||||
</para>
|
||||
|
||||
<section><info><title>Configuring Plugins</title></info>
|
||||
|
||||
@@ -239,6 +239,43 @@ ns_query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname,
|
||||
* recursion completes.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
ns_query_lookup(query_ctx_t *qctx);
|
||||
/*%<
|
||||
* Perform a local database lookup, in either an authoritative or
|
||||
* cache database. If unable to answer, call ns_query_done(); otherwise
|
||||
* hand off processing to query_gotanswer().
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
ns_query_addsoa(query_ctx_t *qctx, dns_ttl_t ttl, dns_section_t section);
|
||||
/*%<
|
||||
* Add SOA to the authority section when sending negative responses
|
||||
* (or to the additional section if sending negative responses triggered
|
||||
* by RPZ rewriting.)
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
ns_query_nodata(query_ctx_t *qctx);
|
||||
/*%<
|
||||
* Handle authoritative NOERROR/NODATA responses.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
ns_query_ncache(query_ctx_t *qctx);
|
||||
/*%<
|
||||
* Handle negative cache responses, DNS_R_NCACHENXRRSET or
|
||||
* DNS_R_NCACHENXDOMAIN. (Note: may be called with other
|
||||
* result codes as a result of hook actions; for example,
|
||||
* DNS64 may call with DNS_R_NXOMAIN.)
|
||||
*/
|
||||
|
||||
void
|
||||
ns_query_setorder(ns_client_t *client, dns_name_t *name,
|
||||
dns_rdataset_t *rdataset);
|
||||
/*%<
|
||||
* Set the ordering for 'rdataset'.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
ns__query_sfcache(query_ctx_t *qctx);
|
||||
@@ -252,12 +289,4 @@ ns__query_start(query_ctx_t *qctx);
|
||||
* (Must not be used outside this module and its associated unit tests.)
|
||||
*/
|
||||
|
||||
/*
|
||||
* XXX:
|
||||
* Temporary function used to initialize the dns64 hooks,
|
||||
* which are currently hard-coded rather than loaded as a module.
|
||||
*/
|
||||
void
|
||||
ns__query_inithooks(dns_view_t *view);
|
||||
|
||||
#endif /* NS_QUERY_H */
|
||||
|
||||
+57
-933
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user