2981. [func] Partial DNS64 support (AAAA synthesis). [RT #21991]

This commit is contained in:
Mark Andrews 2010-12-08 02:46:17 +00:00
parent b59e6107bf
commit e334405421
24 changed files with 2914 additions and 49 deletions

View file

@ -1,3 +1,5 @@
2981. [func] Partial DNS64 support (AAAA synthesis). [RT #21991]
2980. [bug] named didn't properly handle UPDATES that changed the
TTL of the NSEC3PARAM RRset. [RT #22363]

View file

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: query.h,v 1.42 2010/09/24 08:31:23 tbox Exp $ */
/* $Id: query.h,v 1.43 2010/12/08 02:46:15 marka Exp $ */
#ifndef NAMED_QUERY_H
#define NAMED_QUERY_H 1
@ -27,6 +27,7 @@
#include <isc/netaddr.h>
#include <dns/types.h>
#include <dns/rdataset.h>
#include <named/types.h>
@ -57,6 +58,12 @@ struct ns_query {
isc_bufferlist_t namebufs;
ISC_LIST(ns_dbversion_t) activeversions;
ISC_LIST(ns_dbversion_t) freeversions;
dns_rdataset_t * dns64_aaaa;
dns_rdataset_t * dns64_sigaaaa;
isc_boolean_t * dns64_aaaaok;
unsigned int dns64_aaaaoklen;
unsigned int dns64_options;
unsigned int dns64_ttl;
};
#define NS_QUERYATTR_RECURSIONOK 0x0001
@ -73,6 +80,9 @@ struct ns_query {
#define NS_QUERYATTR_NOADDITIONAL 0x0800
#define NS_QUERYATTR_CACHEACLOKVALID 0x1000
#define NS_QUERYATTR_CACHEACLOK 0x2000
#define NS_QUERYATTR_DNS64 0x4000
#define NS_QUERYATTR_DNS64EXCLUDE 0x8000
isc_result_t
ns_query_init(ns_client_t *client);

View file

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: query.c,v 1.346 2010/09/24 05:09:02 marka Exp $ */
/* $Id: query.c,v 1.347 2010/12/08 02:46:15 marka Exp $ */
/*! \file */
@ -34,6 +34,7 @@
#ifdef DLZ
#include <dns/dlz.h>
#endif
#include <dns/dns64.h>
#include <dns/dnssec.h>
#include <dns/events.h>
#include <dns/message.h>
@ -62,6 +63,17 @@
#include <named/sortlist.h>
#include <named/xfrout.h>
#if 0
/*
* It has been recommended that DNS64 be changed to return excluded
* AAAA addresses if DNS64 synthesis does not occur. This minimises
* the impact on the lookup results. While most DNS AAAA lookups are
* done to send IP packets to a host, not all of them are and filtering
* excluded addresses has a negative impact on those uses.
*/
#define dns64_bis_return_excluded_addresses 1
#endif
/*% Partial answer? */
#define PARTIALANSWER(c) (((c)->query.attributes & \
NS_QUERYATTR_PARTIALANSWER) != 0)
@ -92,6 +104,12 @@
/*% Secure? */
#define SECURE(c) (((c)->query.attributes & \
NS_QUERYATTR_SECURE) != 0)
/*% DNS64 A lookup? */
#define DNS64(c) (((c)->query.attributes & \
NS_QUERYATTR_DNS64) != 0)
#define DNS64EXCLUDE(c) (((c)->query.attributes & \
NS_QUERYATTR_DNS64EXCLUDE) != 0)
/*% No QNAME Proof? */
#define NOQNAME(r) (((r)->attributes & \
@ -251,6 +269,19 @@ ns_query_cancel(ns_client_t *client) {
UNLOCK(&client->query.fetchlock);
}
static inline void
query_putrdataset(ns_client_t *client, dns_rdataset_t **rdatasetp) {
dns_rdataset_t *rdataset = *rdatasetp;
CTRACE("query_putrdataset");
if (rdataset != NULL) {
if (dns_rdataset_isassociated(rdataset))
dns_rdataset_disassociate(rdataset);
dns_message_puttemprdataset(client->message, rdatasetp);
}
CTRACE("query_putrdataset: done");
}
static inline void
query_reset(ns_client_t *client, isc_boolean_t everything) {
isc_buffer_t *dbuf, *dbuf_next;
@ -285,6 +316,18 @@ query_reset(ns_client_t *client, isc_boolean_t everything) {
if (client->query.authzone != NULL)
dns_zone_detach(&client->query.authzone);
if (client->query.dns64_aaaa != NULL)
query_putrdataset(client, &client->query.dns64_aaaa);
if (client->query.dns64_sigaaaa != NULL)
query_putrdataset(client, &client->query.dns64_sigaaaa);
if (client->query.dns64_aaaaok != NULL) {
isc_mem_put(client->mctx, client->query.dns64_aaaaok,
client->query.dns64_aaaaoklen *
sizeof(isc_boolean_t));
client->query.dns64_aaaaok = NULL;
client->query.dns64_aaaaoklen = 0;
}
query_freefreeversions(client, everything);
for (dbuf = ISC_LIST_HEAD(client->query.namebufs);
@ -311,12 +354,13 @@ query_reset(ns_client_t *client, isc_boolean_t everything) {
client->query.restarts = 0;
client->query.timerset = ISC_FALSE;
client->query.origqname = NULL;
client->query.qname = NULL;
client->query.dboptions = 0;
client->query.fetchoptions = 0;
client->query.gluedb = NULL;
client->query.authdbset = ISC_FALSE;
client->query.isreferral = ISC_FALSE;
client->query.dns64_options = 0;
client->query.dns64_ttl = ISC_UINT32_MAX;
}
static void
@ -473,20 +517,6 @@ query_newrdataset(ns_client_t *client) {
return (rdataset);
}
static inline void
query_putrdataset(ns_client_t *client, dns_rdataset_t **rdatasetp) {
dns_rdataset_t *rdataset = *rdatasetp;
CTRACE("query_putrdataset");
if (rdataset != NULL) {
if (dns_rdataset_isassociated(rdataset))
dns_rdataset_disassociate(rdataset);
dns_message_puttemprdataset(client->message, rdatasetp);
}
CTRACE("query_putrdataset: done");
}
static inline isc_result_t
query_newdbversion(ns_client_t *client, unsigned int n) {
unsigned int i;
@ -549,6 +579,10 @@ ns_query_init(ns_client_t *client) {
client->query.authzone = NULL;
client->query.authdbset = ISC_FALSE;
client->query.isreferral = ISC_FALSE;
client->query.dns64_aaaa = NULL;
client->query.dns64_sigaaaa = NULL;
client->query.dns64_aaaaok = NULL;
client->query.dns64_aaaaoklen = 0;
query_reset(client, ISC_FALSE);
result = query_newdbversion(client, 3);
if (result != ISC_R_SUCCESS) {
@ -1958,6 +1992,323 @@ query_addrdataset(ns_client_t *client, dns_name_t *fname,
CTRACE("query_addrdataset: done");
}
static isc_result_t
query_dns64(ns_client_t *client, dns_name_t **namep, dns_rdataset_t *rdataset,
dns_rdataset_t *sigrdataset, isc_buffer_t *dbuf,
dns_section_t section)
{
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;
/*%
* To the current response for 'client', add the answer RRset
* '*rdatasetp' and an optional signature set '*sigrdatasetp', with
* owner name '*namep', to section 'section', unless they are
* already there. Also add any pertinent additional data.
*
* If 'dbuf' is not NULL, then '*namep' is the name whose data is
* stored in 'dbuf'. In this case, query_addrrset() guarantees that
* when it returns the name will either have been kept or released.
*/
CTRACE("query_dns64");
name = *namep;
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,
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;
*/
CTRACE("query_dns64: dns_message_findname succeeded: done");
if (dbuf != NULL)
query_releasename(client, namep);
return (ISC_R_SUCCESS);
} else if (result == DNS_R_NXDOMAIN) {
/*
* The name doesn't exist.
*/
if (dbuf != NULL)
query_keepname(client, name, dbuf);
dns_message_addname(client->message, name, section);
*namep = NULL;
mname = name;
} else {
RUNTIME_CHECK(result == DNS_R_NXRRSET);
if (dbuf != NULL)
query_releasename(client, namep);
}
if (rdataset->trust != dns_trust_secure &&
(section == DNS_SECTION_ANSWER ||
section == DNS_SECTION_AUTHORITY))
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(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_rdataset_init(dns64_rdataset);
dns_rdatalist_init(dns64_rdatalist);
dns64_rdatalist->rdclass = dns_rdataclass_in;
dns64_rdatalist->type = dns_rdatatype_aaaa;
if (client->query.dns64_ttl != ISC_UINT32_MAX)
dns64_rdatalist->ttl = ISC_MIN(rdataset->ttl,
client->query.dns64_ttl);
else
dns64_rdatalist->ttl = ISC_MIN(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 (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset))
flags |= DNS_DNS64_DNSSEC;
for (result = dns_rdataset_first(rdataset);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(rdataset)) {
for (dns64 = ISC_LIST_HEAD(client->view->dns64);
dns64 != NULL; dns64 = dns_dns64_next(dns64)) {
dns_rdataset_current(rdataset, &rdata);
isc__buffer_availableregion(buffer, &r);
INSIST(r.length >= 16);
result = dns_dns64_aaaafroma(dns64, &netaddr,
client->signer,
&ns_g_server->aclenv,
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;
client->query.attributes |= NS_QUERYATTR_NOADDITIONAL;
dns64_rdataset->trust = rdataset->trust;
query_addrdataset(client, mname, dns64_rdataset);
dns64_rdataset = NULL;
dns64_rdatalist = NULL;
dns_message_takebuffer(client->message, &buffer);
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);
}
CTRACE("query_dns64: done");
return (result);
}
static void
query_filter64(ns_client_t *client, dns_name_t **namep,
dns_rdataset_t *rdataset, isc_buffer_t *dbuf,
dns_section_t section)
{
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;
CTRACE("query_filter64");
INSIST(client->query.dns64_aaaaok != NULL);
INSIST(client->query.dns64_aaaaoklen == dns_rdataset_count(rdataset));
name = *namep;
mname = NULL;
buffer = NULL;
myrdata = NULL;
myrdataset = NULL;
myrdatalist = NULL;
result = dns_message_findname(client->message, section,
name, dns_rdatatype_aaaa,
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;
*/
CTRACE("query_filter64: dns_message_findname succeeded: done");
if (dbuf != NULL)
query_releasename(client, namep);
return;
} else if (result == DNS_R_NXDOMAIN) {
mname = name;
*namep = NULL;
} else {
RUNTIME_CHECK(result == DNS_R_NXRRSET);
if (dbuf != NULL)
query_releasename(client, namep);
dbuf = NULL;
}
if (rdataset->trust != dns_trust_secure &&
(section == DNS_SECTION_ANSWER ||
section == DNS_SECTION_AUTHORITY))
client->query.attributes &= ~NS_QUERYATTR_SECURE;
result = isc_buffer_allocate(client->mctx, &buffer,
16 * dns_rdataset_count(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_rdataset_init(myrdataset);
dns_rdatalist_init(myrdatalist);
myrdatalist->rdclass = dns_rdataclass_in;
myrdatalist->type = dns_rdatatype_aaaa;
myrdatalist->ttl = rdataset->ttl;
i = 0;
for (result = dns_rdataset_first(rdataset);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(rdataset)) {
if (!client->query.dns64_aaaaok[i++])
continue;
dns_rdataset_current(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;
client->query.attributes |= NS_QUERYATTR_NOADDITIONAL;
if (mname == name) {
if (dbuf != NULL)
query_keepname(client, name, dbuf);
dns_message_addname(client->message, name, section);
dbuf = NULL;
}
myrdataset->trust = rdataset->trust;
query_addrdataset(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 (dbuf != NULL)
query_releasename(client, &name);
CTRACE("query_filter64: done");
}
static void
query_addrrset(ns_client_t *client, dns_name_t **namep,
dns_rdataset_t **rdatasetp, dns_rdataset_t **sigrdatasetp,
@ -2036,7 +2387,7 @@ query_addrrset(ns_client_t *client, dns_name_t **namep,
static inline isc_result_t
query_addsoa(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version,
isc_boolean_t zero_ttl, isc_boolean_t isassociated)
unsigned int override_ttl, isc_boolean_t isassociated)
{
dns_name_t *name;
dns_dbnode_t *node;
@ -2119,10 +2470,11 @@ query_addsoa(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version,
if (result != ISC_R_SUCCESS)
goto cleanup;
if (zero_ttl) {
rdataset->ttl = 0;
if (override_ttl != ISC_UINT32_MAX &&
override_ttl < rdataset->ttl) {
rdataset->ttl = override_ttl;
if (sigrdataset != NULL)
sigrdataset->ttl = 0;
sigrdataset->ttl = override_ttl;
}
/*
@ -3718,6 +4070,53 @@ is_v4_client(ns_client_t *client) {
}
#endif
static isc_boolean_t
dns64_aaaaok(ns_client_t *client, dns_rdataset_t *rdataset,
dns_rdataset_t *sigrdataset)
{
isc_netaddr_t netaddr;
dns_dns64_t *dns64 = ISC_LIST_HEAD(client->view->dns64);
unsigned int flags = 0;
unsigned int i, count;
isc_boolean_t *aaaaok;
INSIST(client->query.dns64_aaaaok == NULL);
INSIST(client->query.dns64_aaaaoklen == 0);
INSIST(client->query.dns64_aaaa == NULL);
INSIST(client->query.dns64_sigaaaa == NULL);
if (dns64 == NULL)
return (ISC_TRUE);
if (RECURSIONOK(client))
flags |= DNS_DNS64_RECURSIVE;
if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset))
flags |= DNS_DNS64_DNSSEC;
count = dns_rdataset_count(rdataset);
aaaaok = isc_mem_get(client->mctx, sizeof(isc_boolean_t) * count);
isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
if (dns_dns64_aaaaok(dns64, &netaddr, client->signer,
&ns_g_server->aclenv, flags, rdataset,
aaaaok, count)) {
for (i = 0; i < count; i++) {
if (aaaaok != NULL && !aaaaok[i]) {
client->query.dns64_aaaaok = aaaaok;
client->query.dns64_aaaaoklen = count;
break;
}
}
if (i == count)
isc_mem_put(client->mctx, aaaaok,
sizeof(isc_boolean_t) * count);
return (ISC_TRUE);
}
isc_mem_put(client->mctx, aaaaok, sizeof(isc_boolean_t) * count);
return (ISC_FALSE);
}
/*
* Do the bulk of query processing for the current query of 'client'.
* If 'event' is non-NULL, we are returning from recursion and 'qtype'
@ -3753,6 +4152,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
dns_rdataset_t *noqname;
isc_boolean_t resuming;
int line = -1;
isc_boolean_t dns64_exclude, dns64;
CTRACE("query_find");
@ -3778,6 +4178,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
zone = NULL;
need_wildcardproof = ISC_FALSE;
empty_wild = ISC_FALSE;
dns64_exclude = dns64 = ISC_FALSE;
options = 0;
resuming = ISC_FALSE;
is_zone = ISC_FALSE;
@ -3787,7 +4188,6 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
* We're returning from recursion. Restore the query context
* and resume.
*/
want_restart = ISC_FALSE;
authoritative = ISC_FALSE;
@ -3800,6 +4200,14 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
node = event->node;
rdataset = event->rdataset;
sigrdataset = event->sigrdataset;
if (DNS64(client)) {
client->query.attributes &= ~NS_QUERYATTR_DNS64;
dns64 = ISC_TRUE;
}
if (DNS64EXCLUDE(client)) {
client->query.attributes &= ~NS_QUERYATTR_DNS64EXCLUDE;
dns64_exclude = ISC_TRUE;
}
/*
* We'll need some resources...
@ -3823,7 +4231,6 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
result = event->result;
resuming = ISC_TRUE;
goto resume;
}
@ -4029,10 +4436,16 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
if (RECURSIONOK(client)) {
result = query_recurse(client, qtype,
NULL, NULL, resuming);
if (result == ISC_R_SUCCESS)
if (result == ISC_R_SUCCESS) {
client->query.attributes |=
NS_QUERYATTR_RECURSING;
else
if (dns64)
client->query.attributes |=
NS_QUERYATTR_DNS64;
if (dns64_exclude)
client->query.attributes |=
NS_QUERYATTR_DNS64EXCLUDE;
} else
RECURSE_ERROR(result);
goto cleanup;
} else {
@ -4205,13 +4618,28 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
result = query_recurse(client, qtype,
NULL, NULL,
resuming);
else if (dns64)
result = query_recurse(client,
dns_rdatatype_a,
NULL, NULL,
resuming);
else
result = query_recurse(client, qtype,
fname, rdataset,
resuming);
if (result == ISC_R_SUCCESS)
if (result == ISC_R_SUCCESS) {
client->query.attributes |=
NS_QUERYATTR_RECURSING;
if (dns64)
client->query.attributes |=
NS_QUERYATTR_DNS64;
if (dns64_exclude)
client->query.attributes |=
NS_QUERYATTR_DNS64EXCLUDE;
} else if (result == DNS_R_DUPLICATE ||
result == DNS_R_DROP)
QUERY_ERROR(result);
else
RECURSE_ERROR(result);
} else {
@ -4251,11 +4679,74 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
}
}
goto cleanup;
case DNS_R_EMPTYNAME:
result = DNS_R_NXRRSET;
/* FALLTHROUGH */
case DNS_R_NXRRSET:
nxrrset:
INSIST(is_zone);
#ifdef dns64_bis_return_excluded_addresses
if (dns64)
#else
if (dns64 && !dns64_exclude)
#endif
{
/*
* Restore the answers from the previous AAAA lookup.
*/
if (rdataset != NULL)
query_putrdataset(client, &rdataset);
if (sigrdataset != NULL)
query_putrdataset(client, &sigrdataset);
rdataset = client->query.dns64_aaaa;
sigrdataset = client->query.dns64_sigaaaa;
if (fname == NULL) {
dbuf = query_getnamebuf(client);
if (dbuf == NULL) {
QUERY_ERROR(DNS_R_SERVFAIL);
goto cleanup;
}
fname = query_newname(client, dbuf, &b);
if (fname == NULL) {
QUERY_ERROR(DNS_R_SERVFAIL);
goto cleanup;
}
}
dns_name_copy(client->query.qname, fname, NULL);
client->query.dns64_aaaa = NULL;
client->query.dns64_sigaaaa = NULL;
dns64 = ISC_FALSE;
#ifdef dns64_bis_return_excluded_addresses
/*
* Resume the diverted processing of the AAAA response?
*/
if (dns64_excluded)
break;
#endif
} else if (result == DNS_R_NXRRSET &&
!ISC_LIST_EMPTY(client->view->dns64) &&
client->message->rdclass == dns_rdataclass_in &&
qtype == dns_rdatatype_aaaa)
{
/*
* Look to see if there are A records for this
* name.
*/
INSIST(client->query.dns64_aaaa == NULL);
INSIST(client->query.dns64_sigaaaa == NULL);
client->query.dns64_aaaa = rdataset;
client->query.dns64_sigaaaa = sigrdataset;
query_releasename(client, &fname);
dns_db_detachnode(db, &node);
rdataset = NULL;
sigrdataset = NULL;
type = qtype = dns_rdatatype_a;
dns64 = ISC_TRUE;
goto db_find;
}
result = DNS_R_NXRRSET;
/*
* Look for a NSEC3 record if we don't have a NSEC record.
*/
@ -4348,7 +4839,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
/*
* Add SOA.
*/
result = query_addsoa(client, db, version, ISC_FALSE,
result = query_addsoa(client, db, version, ISC_UINT32_MAX,
dns_rdataset_isassociated(rdataset));
if (result != ISC_R_SUCCESS) {
QUERY_ERROR(result);
@ -4397,10 +4888,11 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
zone != NULL &&
#endif
dns_zone_getzeronosoattl(zone))
result = query_addsoa(client, db, version, ISC_TRUE,
result = query_addsoa(client, db, version, 0,
dns_rdataset_isassociated(rdataset));
else
result = query_addsoa(client, db, version, ISC_FALSE,
result = query_addsoa(client, db, version,
ISC_UINT32_MAX,
dns_rdataset_isassociated(rdataset));
if (result != ISC_R_SUCCESS) {
QUERY_ERROR(result);
@ -4431,6 +4923,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
case DNS_R_NCACHENXDOMAIN:
case DNS_R_NCACHENXRRSET:
ncache_nxrrset:
INSIST(!is_zone);
authoritative = ISC_FALSE;
/*
@ -4446,6 +4939,66 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
client->message->rdclass == dns_rdataclass_in &&
dns_name_countlabels(fname) == 7)
warn_rfc1918(client, fname, rdataset);
#ifdef dns64_bis_return_excluded_addresses
if (dns64)
#else
if (dns64 && !dns64_exclude)
#endif
{
/*
* Restore the answers from the previous AAAA lookup.
*/
if (rdataset != NULL)
query_putrdataset(client, &rdataset);
if (sigrdataset != NULL)
query_putrdataset(client, &sigrdataset);
rdataset = client->query.dns64_aaaa;
sigrdataset = client->query.dns64_sigaaaa;
if (fname == NULL) {
dbuf = query_getnamebuf(client);
if (dbuf == NULL) {
QUERY_ERROR(DNS_R_SERVFAIL);
goto cleanup;
}
fname = query_newname(client, dbuf, &b);
if (fname == NULL) {
QUERY_ERROR(DNS_R_SERVFAIL);
goto cleanup;
}
}
dns_name_copy(client->query.qname, fname, NULL);
client->query.dns64_aaaa = NULL;
client->query.dns64_sigaaaa = NULL;
dns64 = ISC_FALSE;
#ifdef dns64_bis_return_excluded_addresses
if (dns64_excluded)
break;
#endif
} else if (result == DNS_R_NCACHENXRRSET &&
!ISC_LIST_EMPTY(client->view->dns64) &&
client->message->rdclass == dns_rdataclass_in &&
qtype == dns_rdatatype_aaaa)
{
/*
* Look to see if there are A records for this
* name.
*/
INSIST(client->query.dns64_aaaa == NULL);
INSIST(client->query.dns64_sigaaaa == NULL);
client->query.dns64_aaaa = rdataset;
client->query.dns64_sigaaaa = sigrdataset;
client->query.dns64_ttl = rdataset->ttl;
query_releasename(client, &fname);
dns_db_detachnode(db, &node);
rdataset = NULL;
sigrdataset = NULL;
fname = NULL;
type = qtype = dns_rdatatype_a;
dns64 = ISC_TRUE;
goto db_find;
}
/*
* We don't call query_addrrset() because we don't need any
* of its extra features (and things would probably break!).
@ -4831,7 +5384,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
* Add SOA.
*/
result = query_addsoa(client, db, version,
ISC_FALSE, ISC_FALSE);
ISC_UINT32_MAX,
ISC_FALSE);
if (result == ISC_R_SUCCESS)
result = ISC_R_NOMORE;
} else {
@ -4937,6 +5491,32 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
}
}
#endif
/*
* Check to see if the AAAA RRset has non-excluded addresses
* in it. If not look for a A RRset.
*/
INSIST(client->query.dns64_aaaaok == NULL);
if (qtype == dns_rdatatype_aaaa && !dns64_exclude &&
!ISC_LIST_EMPTY(client->view->dns64) &&
client->message->rdclass == dns_rdataclass_in &&
!dns64_aaaaok(client, rdataset, sigrdataset)) {
/*
* Look to see if there are A records for this
* name.
*/
client->query.dns64_aaaa = rdataset;
client->query.dns64_sigaaaa = sigrdataset;
client->query.dns64_ttl = rdataset->ttl;
query_releasename(client, &fname);
dns_db_detachnode(db, &node);
rdataset = NULL;
sigrdataset = NULL;
type = qtype = dns_rdatatype_a;
dns64_exclude = dns64 = ISC_TRUE;
goto db_find;
}
if (sigrdataset != NULL)
sigrdatasetp = &sigrdataset;
else
@ -4952,8 +5532,43 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
dns_name_equal(client->query.qname, dns_rootname))
client->query.attributes &= ~NS_QUERYATTR_NOADDITIONAL;
query_addrrset(client, &fname, &rdataset, sigrdatasetp, dbuf,
DNS_SECTION_ANSWER);
if (dns64) {
qtype = type = dns_rdatatype_aaaa;
result = query_dns64(client, &fname, rdataset,
sigrdataset, dbuf,
DNS_SECTION_ANSWER);
dns_rdataset_disassociate(rdataset);
dns_message_puttemprdataset(client->message, &rdataset);
if (result == ISC_R_NOMORE) {
#ifndef dns64_bis_return_excluded_addresses
if (dns64_exclude) {
if (!is_zone)
goto cleanup;
/*
* Add a fake the SOA record.
*/
result = query_addsoa(client, db,
version, 600,
ISC_FALSE);
goto cleanup;
}
#endif
if (is_zone)
goto nxrrset;
else
goto ncache_nxrrset;
} else if (result != ISC_R_SUCCESS) {
eresult = result;
goto cleanup;
}
} else if (client->query.dns64_aaaaok != NULL) {
query_filter64(client, &fname, rdataset, dbuf,
DNS_SECTION_ANSWER);
query_putrdataset(client, &rdataset);
} else
query_addrrset(client, &fname, &rdataset,
sigrdatasetp, dbuf, DNS_SECTION_ANSWER);
if (noqname != NULL)
query_addnoqnameproof(client, noqname);
/*

View file

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: server.c,v 1.587 2010/12/02 23:22:41 marka Exp $ */
/* $Id: server.c,v 1.588 2010/12/08 02:46:15 marka Exp $ */
/*! \file */
@ -63,6 +63,7 @@
#ifdef DLZ
#include <dns/dlz.h>
#endif
#include <dns/dns64.h>
#include <dns/forward.h>
#include <dns/journal.h>
#include <dns/keytable.h>
@ -1356,6 +1357,7 @@ configure_view(dns_view_t *view, cfg_parser_t* parser,
isc_boolean_t zero_no_soattl;
cfg_parser_t *newzones_parser = NULL;
cfg_obj_t *nzfconf = NULL;
dns_acl_t *clients = NULL, *mapped = NULL, *excluded = NULL;
REQUIRE(DNS_VIEW_VALID(view));
@ -1618,6 +1620,89 @@ configure_view(dns_view_t *view, cfg_parser_t* parser,
INSIST(result == ISC_R_SUCCESS);
zero_no_soattl = cfg_obj_asboolean(obj);
obj = NULL;
result = ns_config_get(maps, "dns64", &obj);
if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") &&
strcmp(view->name, "_meta")) {
const cfg_listelt_t *element;
isc_netaddr_t na, suffix, *sp;
unsigned int prefixlen;
for (element = cfg_list_first(obj);
element != NULL;
element = cfg_list_next(element))
{
const cfg_obj_t *map = cfg_listelt_value(element);
dns_dns64_t *dns64 = NULL;
unsigned int dns64options = 0;
cfg_obj_asnetprefix(cfg_map_getname(map), &na,
&prefixlen);
obj = NULL;
(void)cfg_map_get(map, "suffix", &obj);
if (obj != NULL) {
sp = &suffix;
isc_netaddr_fromsockaddr(sp,
cfg_obj_assockaddr(obj));
} else
sp = NULL;
clients = mapped = excluded = NULL;
obj = NULL;
(void)cfg_map_get(map, "clients", &obj);
if (obj != NULL) {
result = cfg_acl_fromconfig(obj, config,
ns_g_lctx, actx,
mctx, 0, &clients);
if (result != ISC_R_SUCCESS)
goto cleanup;
}
obj = NULL;
(void)cfg_map_get(map, "mapped", &obj);
if (obj != NULL) {
result = cfg_acl_fromconfig(obj, config,
ns_g_lctx, actx,
mctx, 0, &mapped);
if (result != ISC_R_SUCCESS)
goto cleanup;
}
obj = NULL;
(void)cfg_map_get(map, "exclude", &obj);
if (obj != NULL) {
result = cfg_acl_fromconfig(obj, config,
ns_g_lctx, actx,
mctx, 0, &excluded);
if (result != ISC_R_SUCCESS)
goto cleanup;
}
obj = NULL;
(void)cfg_map_get(map, "recursive-only", &obj);
if (obj != NULL && cfg_obj_asboolean(obj))
dns64options |= DNS_DNS64_RECURSIVE_ONLY;
obj = NULL;
(void)cfg_map_get(map, "break-dnssec", &obj);
if (obj != NULL && cfg_obj_asboolean(obj))
dns64options |= DNS_DNS64_BREAK_DNSSEC;
result = dns_dns64_create(mctx, &na, prefixlen, sp,
clients, mapped, excluded,
dns64options, &dns64);
if (result != ISC_R_SUCCESS)
goto cleanup;
dns_dns64_append(&view->dns64, dns64);
view->dns64cnt++;
if (clients != NULL)
dns_acl_detach(&clients);
if (mapped != NULL)
dns_acl_detach(&mapped);
if (excluded != NULL)
dns_acl_detach(&excluded);
}
}
obj = NULL;
result = ns_config_get(maps, "dnssec-accept-expired", &obj);
INSIST(result == ISC_R_SUCCESS);
@ -2518,6 +2603,12 @@ configure_view(dns_view_t *view, cfg_parser_t* parser,
result = ISC_R_SUCCESS;
cleanup:
if (clients != NULL)
dns_acl_detach(&clients);
if (mapped != NULL)
dns_acl_detach(&mapped);
if (excluded != NULL)
dns_acl_detach(&excluded);
if (ring != NULL)
dns_tsigkeyring_destroy(&ring);
if (zone != NULL)

View file

@ -15,7 +15,7 @@
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
# $Id: conf.sh.in,v 1.53 2010/12/07 02:53:33 marka Exp $
# $Id: conf.sh.in,v 1.54 2010/12/08 02:46:15 marka Exp $
#
# Common configuration data for system tests, to be sourced into
@ -53,7 +53,7 @@ JOURNALPRINT=$TOP/bin/tools/named-journalprint
# load on the machine to make it unusable to other users.
# v6synth
SUBDIRS="acl allow_query addzone autosign cacheclean checkconf checknames
dlv @DLZ_SYSTEM_TEST@ dnssec forward glue ixfr limits lwresd
dlv @DLZ_SYSTEM_TEST@ dns64 dnssec forward glue ixfr limits lwresd
masterfile masterformat metadata notify nsupdate pending pkcs11
resolver rrsetorder sortlist smartsign stub tkey unknown upforwd
views xfer xferquota zonechecks"

View file

@ -0,0 +1,6 @@
#!/bin/sh
rm -f ns1/K*
rm -f ns1/signed.db*
rm -f ns1/dsset-signed.

View file

@ -0,0 +1,36 @@
; Copyright
$TTL 3600
@ SOA ns1 marka.isc.org. 0 0 0 0 1200
@ NS ns1
ns1 A 10.53.0.1
excluded-good-a AAAA 2001:eeee::1
A 1.2.3.4
excluded-bad-a AAAA 2001:eeee::2
A 10.0.0.1
excluded-only AAAA 2001:eeee::3
partially-excluded-good-a AAAA 2001:eeee::1
AAAA 2001::1
A 1.2.3.4
partially-excluded-bad-a AAAA 2001:eeee::2
AAAA 2001::2
A 10.0.0.1
partially-excluded-only AAAA 2001:eeee::3
AAAA 2001::3
a-only A 1.2.3.5
a-and-aaaa AAAA 2001::1
A 1.2.3.6
aaaa-only AAAA 2001::2
a-not-mapped A 10.0.0.2
mx-only MX 10 ns.example.
cname-excluded-good-a CNAME excluded-good-a
cname-excluded-bad-a CNAME excluded-bad-a
cname-excluded-only CNAME excluded-only
cname-partial-excluded-good-a CNAME partial-excluded-good-a
cname-partial-excluded-bad-a CNAME partial-excluded-bad-a
cname-partial-excluded-only CNAME partial-excluded-only
cname-a-only CNAME a-only
cname-a-and-aaaa CNAME a-and-aaaa
cname-aaaa-only CNAME aaaa-only
cname-a-not-mapped CNAME a-not-mapped
cname-mx-only CNAME mx-only
cname-non-existent CNAME non-existent

View file

@ -0,0 +1,63 @@
/*
* Copyright (C) 2004, 2006, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: named.conf,v 1.2 2010/12/08 02:46:15 marka Exp $ */
// NS1
controls { /* empty */ };
acl rfc1918 { 10/8; 192.168/16; 172.16/12; };
options {
query-source address 10.53.0.1;
notify-source 10.53.0.1;
transfer-source 10.53.0.1;
port 5300;
pid-file "named.pid";
listen-on { 10.53.0.1; };
listen-on-v6 { none; };
allow-recursion { 10.53.0.1; };
notify yes;
dnssec-enable yes;
dnssec-validation yes;
dns64 2001:bbbb::/96 {
clients { any; };
mapped { !rfc1918; any; };
exclude { 2001:eeee::/32; 64:FF9B::/96; ::ffff:0000:0000/96; };
suffix ::;
recursive-only yes;
};
};
zone "." {
type master;
file "root.db";
};
zone "example" {
type master;
file "example.db";
};
zone "signed" {
type master;
file "signed.db.signed";
};
// include "trusted.conf";

View file

@ -0,0 +1,9 @@
; Copyright
$TTL 3600
@ SOA a.root-servers.nil. marka.isc.org. 0 0 0 0 0
@ NS a.root-servers.nil.
a.root-servers.nil. A 10.53.0.1
example NS ns1.example.
ns1.example. A 10.53.0.1
signed NS ns1.example.
ns1.signed. A 10.53.0.1

View file

@ -0,0 +1,34 @@
#!/bin/sh -e
#
# Copyright (C) 2004, 2006-2010 Internet Systems Consortium, Inc. ("ISC")
# Copyright (C) 2000-2003 Internet Software Consortium.
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
# $Id: sign.sh,v 1.2 2010/12/08 02:46:16 marka Exp $
SYSTEMTESTTOP=../..
. $SYSTEMTESTTOP/conf.sh
RANDFILE=../random.data
zone=signed
infile=example.db
zonefile=signed.db
key1=`$KEYGEN -q -r $RANDFILE $zone`
key2=`$KEYGEN -q -r $RANDFILE -fk $zone`
cat $infile $key1.key $key2.key > $zonefile
$SIGNER -P -g -r $RANDFILE -o $zone $zonefile > /dev/null

View file

@ -0,0 +1,57 @@
/*
* Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: named.conf,v 1.2 2010/12/08 02:46:16 marka Exp $ */
// NS2
controls { /* empty */ };
acl rfc1918 { 10/8; 192.168/16; 172.16/12; };
options {
query-source address 10.53.0.2;
notify-source 10.53.0.2;
transfer-source 10.53.0.2;
port 5300;
pid-file "named.pid";
listen-on { 10.53.0.2; };
listen-on-v6 { none; };
recursion yes;
notify yes;
dnssec-enable yes;
dnssec-validation yes;
dns64 2001:aaaa::/96 {
clients { 10.53.0.2; };
mapped { !rfc1918; any; };
exclude { 2001:eeee::/32; 64:FF9B::/96; ::ffff:0000:0000/96; };
suffix ::;
};
dns64 64:FF9B::/96 {
clients { 10.53.0.1; };
mapped { !192.228.79.201; !rfc1918; any; };
exclude { 64:FF9B::/96; ::ffff:0000:0000/96; };
suffix ::;
};
};
zone "." {
type hint;
file "../../common/root.hint";
};

View file

@ -0,0 +1,24 @@
#!/bin/sh -e
#
# Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
# Copyright (C) 2000, 2001 Internet Software Consortium.
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
# $Id: setup.sh,v 1.2 2010/12/08 02:46:15 marka Exp $
../../../tools/genrandom 400 random.data
sh clean.sh
cd ns1 && sh sign.sh

File diff suppressed because it is too large Load diff

View file

@ -18,7 +18,7 @@
- PERFORMANCE OF THIS SOFTWARE.
-->
<!-- File: $Id: Bv9ARM-book.xml,v 1.465 2010/09/21 19:47:57 ebersman Exp $ -->
<!-- File: $Id: Bv9ARM-book.xml,v 1.466 2010/12/08 02:46:16 marka Exp $ -->
<book xmlns:xi="http://www.w3.org/2001/XInclude">
<title>BIND 9 Administrator Reference Manual</title>
@ -5120,6 +5120,14 @@ badresp:1,adberr:0,findfail:0,valfail:0]
<optional> match-mapped-addresses <replaceable>yes_or_no</replaceable>; </optional>
<optional> filter-aaaa-on-v4 ( <replaceable>yes_or_no</replaceable> | <replaceable>break-dnssec</replaceable> ); </optional>
<optional> filter-aaaa { <replaceable>address_match_list</replaceable> }; </optional>
<optional> dns64 <replaceable>IPv6-prefix</replaceable> {
<optional> clients { <replaceable>address_match_list</replaceable> }; </optional>
<optional> mapped { <replaceable>address_match_list</replaceable> }; </optional>
<optional> exclude { <replaceable>address_match_list</replaceable> }; </optional>
<optional> suffix IPv6-address; </optional>
<optional> recursion-only <replaceable>yes_or_no</replaceable>; </optional>
<optional> break-dnssec <replaceable>yes_or_no</replaceable>; </optional>
}; </optional>;
<optional> preferred-glue ( <replaceable>A</replaceable> | <replaceable>AAAA</replaceable> | <replaceable>NONE</replaceable> ); </optional>
<optional> edns-udp-size <replaceable>number</replaceable>; </optional>
<optional> max-udp-size <replaceable>number</replaceable>; </optional>
@ -5710,6 +5718,63 @@ options {
</listitem>
</varlistentry>
<varlistentry>
<term><command>dns64</command></term>
<listitem>
<para>
This directive instructs <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 a NAT64. Each
<command>dns64</command> 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>
Each <command>dns64</command> supports a optional
<command>clients</command> acl which defines which clients
see this directive. If not defined it defaults to
<userinput>any;</userinput>.
</para>
<para>
Each <command>dns64</command> supports a optional
<command>mapped</command> acl which selects which
IPv4 addresses are to be mapped are in the corresponding
A RRset. If not defined it defaults to
<userinput>any;</userinput>.
</para>
<para>
Each <command>dns64</command> supports a optional
<command>exclude</command> acl which selects which
IPv6 addresses will be ignored for the purposes
of determining if dns64 is to be applied. Any
non matching address will prevent any further
DNS64 processing from occuring for this client.
</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>
<programlisting>
acl rfc1918 { 10/8; 192.168/16; 172.16/12; };
dns64 64:FF9B::/96 {
clients { any; };
mapped { !rfc1918; any; };
exclude { 64:FF9B::/96; ::ffff:0000:0000/96; };
suffix ::;
};
</programlisting>
</listitem>
</varlistentry>
</variablelist>
<sect3 id="boolean_options">

View file

@ -100,6 +100,14 @@ options {
directory <quoted_string>;
disable-algorithms <string> { <string>; ... };
disable-empty-zone <string>;
dns64 <netprefix> {
break-dnssec <boolean>;
clients { <address_match_element>; ... };
exclude { <address_match_element>; ... };
mapped { <address_match_element>; ... };
recursive-only <boolean>;
suffix <ipv6_address>;
};
dnssec-accept-expired <boolean>;
dnssec-dnskey-kskonly <boolean>;
dnssec-enable <boolean>;
@ -303,6 +311,14 @@ view <string> <optional_class> {
dlz <string> {
database <string>;
};
dns64 <netprefix> {
break-dnssec <boolean>;
clients { <address_match_element>; ... };
exclude { <address_match_element>; ... };
mapped { <address_match_element>; ... };
recursive-only <boolean>;
suffix <ipv6_address>;
};
dnssec-accept-expired <boolean>;
dnssec-dnskey-kskonly <boolean>;
dnssec-enable <boolean>;

View file

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: check.c,v 1.120 2010/08/11 18:14:19 each Exp $ */
/* $Id: check.c,v 1.121 2010/12/08 02:46:16 marka Exp $ */
/*! \file */
@ -418,6 +418,106 @@ check_viewacls(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions,
return (result);
}
static const unsigned char zeros[16];
static isc_result_t
check_dns64(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions,
const cfg_obj_t *config, isc_log_t *logctx, isc_mem_t *mctx)
{
isc_result_t result = ISC_R_SUCCESS;
const cfg_obj_t *dns64 = NULL;
const cfg_obj_t *options;
const cfg_listelt_t *element;
const cfg_obj_t *map, *obj;
isc_netaddr_t na, sa;
unsigned int prefixlen;
int nbytes;
int i;
static const char *acls[] = { "client", "exclude", "mapped", NULL};
if (voptions != NULL)
cfg_map_get(voptions, "dns64", &dns64);
if (config != NULL && dns64 == NULL) {
options = NULL;
cfg_map_get(config, "options", &options);
if (options != NULL)
cfg_map_get(options, "dns64", &dns64);
}
if (dns64 == NULL)
return (ISC_R_SUCCESS);
for (element = cfg_list_first(dns64);
element != NULL;
element = cfg_list_next(element))
{
map = cfg_listelt_value(element);
obj = cfg_map_getname(map);
cfg_obj_asnetprefix(obj, &na, &prefixlen);
if (na.family != AF_INET6) {
cfg_obj_log(map, logctx, ISC_LOG_ERROR,
"dns64 requires a IPv6 prefix");
result = ISC_R_FAILURE;
continue;
}
if (prefixlen != 32 && prefixlen != 40 && prefixlen != 48 &&
prefixlen != 56 && prefixlen != 64 && prefixlen != 96) {
cfg_obj_log(map, logctx, ISC_LOG_ERROR,
"bad prefix length %u [32/40/48/56/64/96]",
prefixlen);
result = ISC_R_FAILURE;
continue;
}
for (i = 0; acls[i] != NULL; i++) {
obj = NULL;
(void)cfg_map_get(map, acls[i], &obj);
if (obj != NULL) {
dns_acl_t *acl = NULL;
isc_result_t tresult;
tresult = cfg_acl_fromconfig(obj, config,
logctx, actx,
mctx, 0, &acl);
if (acl != NULL)
dns_acl_detach(&acl);
if (tresult != ISC_R_SUCCESS)
result = tresult;
}
}
obj = NULL;
(void)cfg_map_get(map, "suffix", &obj);
if (obj != NULL) {
isc_netaddr_fromsockaddr(&sa, cfg_obj_assockaddr(obj));
if (sa.family != AF_INET6) {
cfg_obj_log(map, logctx, ISC_LOG_ERROR,
"dns64 requires a IPv6 suffix");
result = ISC_R_FAILURE;
continue;
}
nbytes = prefixlen / 8 + 4;
if (prefixlen >= 32 && prefixlen <= 64)
nbytes++;
if (memcmp(sa.type.in6.s6_addr, zeros, nbytes) != 0) {
char netaddrbuf[ISC_NETADDR_FORMATSIZE];
isc_netaddr_format(&sa, netaddrbuf,
sizeof(netaddrbuf));
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
"bad suffix '%s' leading "
"%u octets not zeros",
netaddrbuf, nbytes);
result = ISC_R_FAILURE;
}
}
}
return (result);
}
/*
* Check allow-recursion and allow-recursion-on acls, and also log a
* warning if they're inconsistent with the "recursion" option.
@ -2101,6 +2201,10 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
if (tresult != ISC_R_SUCCESS)
result = tresult;
tresult = check_dns64(&actx, voptions, config, logctx, mctx);
if (tresult != ISC_R_SUCCESS)
result = tresult;
cfg_aclconfctx_clear(&actx);
return (result);

View file

@ -13,7 +13,7 @@
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
# $Id: Makefile.in,v 1.171 2010/06/09 23:50:58 tbox Exp $
# $Id: Makefile.in,v 1.172 2010/12/08 02:46:16 marka Exp $
srcdir = @srcdir@
VPATH = @srcdir@
@ -57,8 +57,9 @@ DSTOBJS = @DST_EXTRA_OBJS@ @OPENSSLLINKOBJS@ \
DNSOBJS = acache.@O@ acl.@O@ adb.@O@ byaddr.@O@ \
cache.@O@ callbacks.@O@ compress.@O@ \
db.@O@ dbiterator.@O@ dbtable.@O@ diff.@O@ dispatch.@O@ \
dlz.@O@ dnssec.@O@ ds.@O@ forward.@O@ iptable.@O@ journal.@O@ \
keydata.@O@ keytable.@O@ lib.@O@ log.@O@ lookup.@O@ \
dlz.@O@ dns64.@O@ dnssec.@O@ ds.@O@ forward.@O@ iptable.@O@ \
journal.@O@ keydata.@O@ keytable.@O@ \
lib.@O@ log.@O@ lookup.@O@ \
master.@O@ masterdump.@O@ message.@O@ \
name.@O@ ncache.@O@ nsec.@O@ nsec3.@O@ order.@O@ peer.@O@ \
portlist.@O@ private.@O@ \
@ -85,7 +86,7 @@ DSTSRCS = @DST_EXTRA_SRCS@ @OPENSSLLINKSRCS@ \
DNSSRCS = acache.c acl.c adb.c byaddr.c \
cache.c callbacks.c compress.c \
db.c dbiterator.c dbtable.c diff.c dispatch.c \
dlz.c dnssec.c ds.c forward.c iptable.c journal.c \
dlz.c dns64.c dnssec.c ds.c forward.c iptable.c journal.c \
keydata.c keytable.c lib.c log.c lookup.c \
master.c masterdump.c message.c \
name.c ncache.c nsec.c nsec3.c order.c peer.c portlist.c \

282
lib/dns/dns64.c Normal file
View file

@ -0,0 +1,282 @@
/*
* Copyright
*/
#include <config.h>
#include <isc/list.h>
#include <isc/mem.h>
#include <isc/netaddr.h>
#include <isc/string.h>
#include <isc/util.h>
#include <dns/acl.h>
#include <dns/dns64.h>
#include <dns/rdata.h>
#include <dns/rdataset.h>
#include <dns/result.h>
struct dns_dns64 {
unsigned char bits[16]; /*
* Prefix + suffix bits.
*/
dns_acl_t * clients; /*
* Which clients get mapped
* addresses.
*/
dns_acl_t * mapped; /*
* IPv4 addresses to be mapped.
*/
dns_acl_t * excluded; /*
* IPv6 addresses that are
* treated as not existing.
*/
unsigned int prefixlen; /*
* Start of mapped address.
*/
unsigned int flags;
isc_mem_t * mctx;
ISC_LINK(dns_dns64_t) link;
};
isc_result_t
dns_dns64_create(isc_mem_t *mctx, isc_netaddr_t *prefix,
unsigned int prefixlen, isc_netaddr_t *suffix,
dns_acl_t *clients, dns_acl_t *mapped, dns_acl_t *excluded,
unsigned int flags, dns_dns64_t **dns64)
{
dns_dns64_t *new;
unsigned int nbytes = 16;
REQUIRE(prefix != NULL && prefix->family == AF_INET6);
/* Legal prefix lengths from draft-ietf-behave-address-format-04. */
REQUIRE(prefixlen == 32 || prefixlen == 40 || prefixlen == 48 ||
prefixlen == 56 || prefixlen == 64 || prefixlen == 96);
REQUIRE(isc_netaddr_prefixok(prefix, prefixlen) == ISC_R_SUCCESS);
REQUIRE(dns64 != NULL && *dns64 == NULL);
if (suffix != NULL) {
static const unsigned char zeros[16];
REQUIRE(prefix->family == AF_INET6);
nbytes = prefixlen / 8 + 4;
/* Bits 64-71 are zeros. draft-ietf-behave-address-format-04 */
if (prefixlen >= 32 && prefixlen <= 64)
nbytes++;
REQUIRE(memcmp(suffix->type.in6.s6_addr, zeros, nbytes) == 0);
}
new = isc_mem_get(mctx, sizeof(dns_dns64_t));
if (new == NULL)
return (ISC_R_NOMEMORY);
memset(new->bits, 0, sizeof(new->bits));
memcpy(new->bits, prefix->type.in6.s6_addr, prefixlen / 8);
if (suffix != NULL)
memcpy(new->bits + nbytes, suffix->type.in6.s6_addr + nbytes,
16 - nbytes);
new->clients = NULL;
if (clients != NULL)
dns_acl_attach(clients, &new->clients);
new->mapped = NULL;
if (mapped != NULL)
dns_acl_attach(mapped, &new->mapped);
new->excluded = NULL;
if (excluded != NULL)
dns_acl_attach(excluded, &new->excluded);
new->prefixlen = prefixlen;
new->flags = flags;
ISC_LINK_INIT(new, link);
new->mctx = NULL;
isc_mem_attach(mctx, &new->mctx);
*dns64 = new;
return (ISC_R_SUCCESS);
};
void
dns_dns64_destroy(dns_dns64_t **dns64p) {
dns_dns64_t *dns64;
REQUIRE(dns64p != NULL && *dns64p != NULL);
dns64 = *dns64p;
*dns64p = NULL;
REQUIRE(!ISC_LINK_LINKED(dns64, link));
if (dns64->clients != NULL)
dns_acl_detach(&dns64->clients);
if (dns64->mapped != NULL)
dns_acl_detach(&dns64->mapped);
if (dns64->excluded != NULL)
dns_acl_detach(&dns64->excluded);
isc_mem_putanddetach(&dns64->mctx, dns64, sizeof(*dns64));
}
isc_result_t
dns_dns64_aaaafroma(const dns_dns64_t *dns64, const isc_netaddr_t *reqaddr,
const dns_name_t *reqsigner, const dns_aclenv_t *env,
unsigned int flags, unsigned char *a, unsigned char *aaaa)
{
unsigned int nbytes, i;
isc_result_t result;
int match;
if ((dns64->flags & DNS_DNS64_RECURSIVE_ONLY) != 0 &&
(flags & DNS_DNS64_RECURSIVE) == 0)
return (DNS_R_DISALLOWED);
if ((dns64->flags & DNS_DNS64_BREAK_DNSSEC) == 0 &&
(flags & DNS_DNS64_DNSSEC) != 0)
return (DNS_R_DISALLOWED);
if (dns64->clients != NULL) {
result = dns_acl_match(reqaddr, reqsigner, dns64->clients, env,
&match, NULL);
if (result != ISC_R_SUCCESS)
return (result);
if (match <= 0)
return (DNS_R_DISALLOWED);
}
if (dns64->mapped != NULL) {
struct in_addr ina;
isc_netaddr_t netaddr;
memcpy(&ina.s_addr, a, 4);
isc_netaddr_fromin(&netaddr, &ina);
result = dns_acl_match(&netaddr, NULL, dns64->mapped, env,
&match, NULL);
if (result != ISC_R_SUCCESS)
return (result);
if (match <= 0)
return (DNS_R_DISALLOWED);
}
nbytes = dns64->prefixlen / 8;
INSIST(nbytes <= 12);
/* Copy prefix. */
memcpy(aaaa, dns64->bits, nbytes);
/* Copy mapped address. */
for (i = 0; i < 4U; i++) {
aaaa[nbytes++] = a[i];
/* Bits 64-71 are zeros. draft-ietf-behave-address-format-04 */
if (nbytes == 8)
aaaa[nbytes++] = 0;
}
/* Copy suffix. */
memcpy(aaaa + nbytes, dns64->bits + nbytes, 16 - nbytes);
return (ISC_R_SUCCESS);
}
dns_dns64_t *
dns_dns64_next(dns_dns64_t *dns64) {
dns64 = ISC_LIST_NEXT(dns64, link);
return (dns64);
}
void
dns_dns64_append(dns_dns64list_t *list, dns_dns64_t *dns64) {
ISC_LIST_APPEND(*list, dns64, link);
}
void
dns_dns64_unlink(dns_dns64list_t *list, dns_dns64_t *dns64) {
ISC_LIST_UNLINK(*list, dns64, link);
}
isc_boolean_t
dns_dns64_aaaaok(const dns_dns64_t *dns64, const isc_netaddr_t *reqaddr,
const dns_name_t *reqsigner, const dns_aclenv_t *env,
unsigned int flags, dns_rdataset_t *rdataset,
isc_boolean_t *aaaaok, size_t aaaaoklen)
{
struct in6_addr in6;
isc_netaddr_t netaddr;
isc_result_t result;
int match;
isc_boolean_t answer = ISC_FALSE;
isc_boolean_t found = ISC_FALSE;
unsigned int i, ok;
REQUIRE(rdataset != NULL);
REQUIRE(rdataset->type == dns_rdatatype_aaaa);
REQUIRE(rdataset->rdclass == dns_rdataclass_in);
if (aaaaok != NULL)
REQUIRE(aaaaoklen == dns_rdataset_count(rdataset));
for (;dns64 != NULL; dns64 = ISC_LIST_NEXT(dns64, link)) {
if ((dns64->flags & DNS_DNS64_RECURSIVE_ONLY) != 0 &&
(flags & DNS_DNS64_RECURSIVE) == 0)
continue;
if ((dns64->flags & DNS_DNS64_BREAK_DNSSEC) == 0 &&
(flags & DNS_DNS64_DNSSEC) != 0)
continue;
/*
* Work out if this dns64 structure applies to this client.
*/
if (dns64->clients != NULL) {
result = dns_acl_match(reqaddr, reqsigner,
dns64->clients, env,
&match, NULL);
if (result != ISC_R_SUCCESS)
continue;
if (match <= 0)
continue;
}
if (!found && aaaaok != NULL) {
for (i = 0; i < aaaaoklen; i++)
aaaaok[i] = ISC_FALSE;
}
found = ISC_TRUE;
/*
* If we are not excluding any addresses then any AAAA
* will do.
*/
if (dns64->excluded == NULL) {
answer = ISC_TRUE;
for (i = 0; i < aaaaoklen; i++)
aaaaok[i] = ISC_TRUE;
goto done;
}
i = 0; ok = 0;
for (result = dns_rdataset_first(rdataset);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(rdataset)) {
dns_rdata_t rdata = DNS_RDATA_INIT;
if (aaaaok == NULL || !aaaaok[i]) {
dns_rdataset_current(rdataset, &rdata);
memcpy(&in6.s6_addr, rdata.data, 16);
isc_netaddr_fromin6(&netaddr, &in6);
result = dns_acl_match(&netaddr, NULL,
dns64->excluded,
env, &match, NULL);
if (result == ISC_R_SUCCESS && match <= 0) {
answer = ISC_TRUE;
if (aaaaok == NULL)
goto done;
aaaaok[i] = ISC_TRUE;
ok++;
}
} else
ok++;
i++;
}
/*
* Are all addresses ok?
*/
if (aaaaok != NULL && ok == aaaaoklen)
goto done;
}
done:
if (!found && aaaaok != NULL) {
for (i = 0; i < aaaaoklen; i++)
aaaaok[i] = ISC_TRUE;
}
return (found ? answer : ISC_TRUE);
}

161
lib/dns/include/dns/dns64.h Normal file
View file

@ -0,0 +1,161 @@
/*
* Copyright
*/
#ifndef DNS_DNS64_H
#define DNS_DNS64_H 1
#include <isc/lang.h>
#include <dns/types.h>
ISC_LANG_BEGINDECLS
/*
* dns_dns64_create() flags.
*/
#define DNS_DNS64_RECURSIVE_ONLY 0x01 /* If set then this record
* only applies to recursive
* queries.
*/
#define DNS_DNS64_BREAK_DNSSEC 0x02 /* If set then still perform
* DNSSEC synthesis even
* though the result would
* fail validation.
*/
/*
* dns_dns64_aaaaok() and dns_dns64_aaaafroma() flags.
*/
#define DNS_DNS64_RECURSIVE 0x01 /* Recursive query. */
#define DNS_DNS64_DNSSEC 0x02 /* DNSSEC sensitive query. */
isc_result_t
dns_dns64_create(isc_mem_t *mctx, isc_netaddr_t *prefix,
unsigned int prefixlen, isc_netaddr_t *suffix,
dns_acl_t *client, dns_acl_t *mapped, dns_acl_t *excluded,
unsigned int flags, dns_dns64_t **dns64);
/*
* Create a dns64 record which is used to identify the set of clients
* it applies to and how to perform the DNS64 synthesis.
*
* 'prefix' and 'prefixlen' defined the leading bits of the AAAA records
* to be synthesised. 'suffix' defines the bits after the A records bits.
* If suffix is NULL zeros will be used for these bits. 'client' defines
* for which clients this record applies. If 'client' is NULL then all
* clients apply. 'mapped' defines which A records are candidated for
* mapping. If 'mapped' is NULL then all A records will be mapped.
* 'excluded' defines which AAAA are to be treated as non-existent for the
* purposed of determining whether to perform syntesis. If 'excluded' is
* NULL then no AAAA records prevent synthesis.
*
* If DNS_DNS64_RECURSIVE_ONLY is set then the record will only match if
* DNS_DNS64_RECURSIVE is set when calling dns_dns64_aaaaok() and
* dns_dns64_aaaafroma().
*
* If DNS_DNS64_BREAK_DNSSEC is set then the record will still apply if
* DNS_DNS64_DNSSEC is set when calling dns_dns64_aaaaok() and
* dns_dns64_aaaafroma() otherwise the record will be ignored.
*
* Requires:
* 'mctx' to be valid.
* 'prefix' to be valid and the address family to AF_INET6.
* 'prefixlen' to be one of 32, 40, 48, 56, 72 and 96.
* the bits not covered by prefixlen in prefix to
* be zero.
* 'suffix' to be NULL or the address family be set to AF_INET6
* and the leading 'prefixlen' + 32 bits of the 'suffix'
* to be zero. If 'prefixlen' is 40, 48 or 56 then the
* the leading 'prefixlen' + 40 bits of 'suffix' must be
* zero.
* 'client' to be NULL or a valid acl.
* 'mapped' to be NULL or a valid acl.
* 'exculded' to be NULL or a valid acl.
*
* Returns:
* ISC_R_SUCCESS
* ISC_R_NOMEMORY
*/
void
dns_dns64_destroy(dns_dns64_t **dns64p);
/*
* Destroys a dns64 record.
*
* Requires the record to not be linked.
*/
isc_result_t
dns_dns64_aaaafroma(const dns_dns64_t *dns64, const isc_netaddr_t *reqaddr,
const dns_name_t *reqsigner, const dns_aclenv_t *env,
unsigned int flags, unsigned char *a, unsigned char *aaaa);
/*
* dns_dns64_aaaafroma() determines whether to perform a DNS64 address
* synthesis from 'a' based on 'dns64', 'reqaddr', 'reqsigner', 'env',
* 'flags' and 'aaaa'. If synthesis is performed then the result is
* written to '*aaaa'.
*
* The synthesised address will be of the form:
*
* <prefix bits><a bits><suffix bits>
*
* If <a bits> straddle bits 64-71 of the AAAA record, then 8 zero bits will
* be inserted at bits 64-71.
*
* Requires:
* 'dns64' to be valid.
* 'reqaddr' to be valid.
* 'reqsigner' to be NULL or valid.
* 'env' to be valid.
* 'a' to point to a IPv4 address in network order.
* 'aaaa' to point to a IPv6 address buffer in network order.
*
* Returns:
* ISC_R_SUCCESS if synthesis was performed.
* DNS_R_DISALLOWED if there is no match.
*/
dns_dns64_t *
dns_dns64_next(dns_dns64_t *dns64);
/*
* Return the next dns64 record in the list.
*/
void
dns_dns64_append(dns_dns64list_t *list, dns_dns64_t *dns64);
/*
* Append the dns64 record to the list.
*/
void
dns_dns64_unlink(dns_dns64list_t *list, dns_dns64_t *dns64);
/*
* Unlink the dns64 record from the list.
*/
isc_boolean_t
dns_dns64_aaaaok(const dns_dns64_t *dns64, const isc_netaddr_t *reqaddr,
const dns_name_t *reqsigner, const dns_aclenv_t *env,
unsigned int flags, dns_rdataset_t *rdataset,
isc_boolean_t *aaaaok, size_t aaaaoklen);
/*
* Determine if there are any non-excluded AAAA records in from the
* matching dns64 records in the list starting at 'dns64'. If there
* is a non-exluded address return ISC_TRUE. If all addresses are
* excluded in the matched records return ISC_FALSE. If no records
* match then return ISC_TRUE.
*
* If aaaaok is defined then dns_dns64_aaaaok() return a array of which
* addresses in 'rdataset' were deemed to not be exclude by any matching
* record. If there are no matching records then all entries are set
* to ISC_TRUE.
*
* Requires
* 'rdataset' to be valid and to be for type AAAA and class IN.
* 'aaaaoklen' must match the number of records in 'rdataset'
* if 'aaaaok' in non NULL.
*/
ISC_LANG_ENDDECLS
#endif /* DNS_DNS64_H */

View file

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: types.h,v 1.142 2010/06/22 03:58:38 marka Exp $ */
/* $Id: types.h,v 1.143 2010/12/08 02:46:16 marka Exp $ */
#ifndef DNS_TYPES_H
#define DNS_TYPES_H 1
@ -67,6 +67,8 @@ typedef struct dns_dispatchevent dns_dispatchevent_t;
typedef struct dns_dispatchlist dns_dispatchlist_t;
typedef struct dns_dispatchmgr dns_dispatchmgr_t;
typedef struct dns_dispentry dns_dispentry_t;
typedef struct dns_dns64 dns_dns64_t;
typedef ISC_LIST(dns_dns64_t) dns_dns64list_t;
typedef struct dns_dnsseckey dns_dnsseckey_t;
typedef ISC_LIST(dns_dnsseckey_t) dns_dnsseckeylist_t;
typedef struct dns_dumpctx dns_dumpctx_t;

View file

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: view.h,v 1.127 2010/09/24 05:09:03 marka Exp $ */
/* $Id: view.h,v 1.128 2010/12/08 02:46:16 marka Exp $ */
#ifndef DNS_VIEW_H
#define DNS_VIEW_H 1
@ -158,6 +158,8 @@ struct dns_view {
isc_uint16_t maxudp;
dns_v4_aaaa_t v4_aaaa;
dns_acl_t * v4_aaaa_acl;
dns_dns64list_t dns64;
unsigned int dns64cnt;
/*
* Configurable data for server use only,

View file

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: view.c,v 1.170 2010/09/24 05:09:03 marka Exp $ */
/* $Id: view.c,v 1.171 2010/12/08 02:46:16 marka Exp $ */
/*! \file */
@ -34,6 +34,7 @@
#include <dns/cache.h>
#include <dns/db.h>
#include <dns/dlz.h>
#include <dns/dns64.h>
#include <dns/dnssec.h>
#include <dns/events.h>
#include <dns/forward.h>
@ -145,6 +146,8 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
view->resstats = NULL;
view->resquerystats = NULL;
view->cacheshared = ISC_FALSE;
ISC_LIST_INIT(view->dns64);
view->dns64cnt = 0;
/*
* Initialize configuration data with default values.
@ -256,6 +259,8 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
static inline void
destroy(dns_view_t *view) {
dns_dns64_t *dns64;
REQUIRE(!ISC_LINK_LINKED(view, link));
REQUIRE(isc_refcount_current(&view->references) == 0);
REQUIRE(view->weakrefs == 0);
@ -373,6 +378,12 @@ destroy(dns_view_t *view) {
dns_stats_detach(&view->resquerystats);
if (view->secroots_priv != NULL)
dns_keytable_detach(&view->secroots_priv);
for (dns64 = ISC_LIST_HEAD(view->dns64);
dns64 != NULL;
dns64 = ISC_LIST_HEAD(view->dns64)) {
dns_dns64_unlink(&view->dns64, dns64);
dns_dns64_destroy(&dns64);
}
#ifdef BIND9
if (view->managed_keys != NULL)
dns_zone_detach(&view->managed_keys);

View file

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: mem.c,v 1.159 2010/08/11 23:46:42 tbox Exp $ */
/* $Id: mem.c,v 1.160 2010/12/08 02:46:16 marka Exp $ */
/*! \file */
@ -1273,7 +1273,7 @@ isc___mem_get(isc_mem_t *ctx0, size_t size FLARG) {
REQUIRE(VALID_CONTEXT(ctx));
if ((isc_mem_debugging & (ISC_MEM_DEBUGSIZE|ISC_MEM_DEBUGCTX)) != 0)
return (isc_mem_allocate((isc_mem_t *)ctx, size));
return (isc__mem_allocate(ctx0, size FLARG_PASS));
if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
MCTXLOCK(ctx, &ctx->lock);

View file

@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: namedconf.c,v 1.123 2010/08/11 18:14:20 each Exp $ */
/* $Id: namedconf.c,v 1.124 2010/12/08 02:46:17 marka Exp $ */
/*! \file */
@ -984,6 +984,31 @@ static cfg_type_t cfg_type_lookaside = {
&cfg_rep_tuple, lookaside_fields
};
/*
* DNS64.
*/
static cfg_clausedef_t
dns64_clauses[] = {
{ "clients", &cfg_type_bracketed_aml, 0 },
{ "mapped", &cfg_type_bracketed_aml, 0 },
{ "exclude", &cfg_type_bracketed_aml, 0 },
{ "suffix", &cfg_type_netaddr6, 0 },
{ "recursive-only", &cfg_type_boolean, 0 },
{ "break-dnssec", &cfg_type_boolean, 0 },
{ NULL, NULL, 0 },
};
static cfg_clausedef_t *
dns64_clausesets[] = {
dns64_clauses,
NULL
};
static cfg_type_t cfg_type_dns64 = {
"dns64", cfg_parse_netprefix_map, cfg_print_map, cfg_doc_map,
&cfg_rep_map, dns64_clausesets
};
/*%
* Clauses that can be found within the 'view' statement,
* with defaults in the 'options' statement.
@ -1013,6 +1038,7 @@ view_clauses[] = {
{ "disable-algorithms", &cfg_type_disablealgorithm,
CFG_CLAUSEFLAG_MULTI },
{ "disable-empty-zone", &cfg_type_astring, CFG_CLAUSEFLAG_MULTI },
{ "dns64", &cfg_type_dns64, CFG_CLAUSEFLAG_MULTI },
{ "dnssec-accept-expired", &cfg_type_boolean, 0 },
{ "dnssec-enable", &cfg_type_boolean, 0 },
{ "dnssec-lookaside", &cfg_type_lookaside, CFG_CLAUSEFLAG_MULTI },