diff --git a/CHANGES b/CHANGES index c78e6e9d92..3eba0cb3e7 100644 --- a/CHANGES +++ b/CHANGES @@ -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] diff --git a/bin/named/include/named/query.h b/bin/named/include/named/query.h index 1019b92953..2f65df3b79 100644 --- a/bin/named/include/named/query.h +++ b/bin/named/include/named/query.h @@ -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 #include +#include #include @@ -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); diff --git a/bin/named/query.c b/bin/named/query.c index eb847edb2b..083fa77e36 100644 --- a/bin/named/query.c +++ b/bin/named/query.c @@ -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 #endif +#include #include #include #include @@ -62,6 +63,17 @@ #include #include +#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); /* diff --git a/bin/named/server.c b/bin/named/server.c index 50dbfb6d0e..f4bbaf2c16 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -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 #endif +#include #include #include #include @@ -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) diff --git a/bin/tests/system/conf.sh.in b/bin/tests/system/conf.sh.in index 86d9c93fcb..88ed23de6b 100644 --- a/bin/tests/system/conf.sh.in +++ b/bin/tests/system/conf.sh.in @@ -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" diff --git a/bin/tests/system/dns64/clean.sh b/bin/tests/system/dns64/clean.sh new file mode 100644 index 0000000000..ceb282bc86 --- /dev/null +++ b/bin/tests/system/dns64/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh + + +rm -f ns1/K* +rm -f ns1/signed.db* +rm -f ns1/dsset-signed. diff --git a/bin/tests/system/dns64/ns1/example.db b/bin/tests/system/dns64/ns1/example.db new file mode 100644 index 0000000000..d7055b2b3c --- /dev/null +++ b/bin/tests/system/dns64/ns1/example.db @@ -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 diff --git a/bin/tests/system/dns64/ns1/named.conf b/bin/tests/system/dns64/ns1/named.conf new file mode 100644 index 0000000000..d7fb997ae4 --- /dev/null +++ b/bin/tests/system/dns64/ns1/named.conf @@ -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"; diff --git a/bin/tests/system/dns64/ns1/root.db b/bin/tests/system/dns64/ns1/root.db new file mode 100644 index 0000000000..ea8f86ae88 --- /dev/null +++ b/bin/tests/system/dns64/ns1/root.db @@ -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 diff --git a/bin/tests/system/dns64/ns1/sign.sh b/bin/tests/system/dns64/ns1/sign.sh new file mode 100644 index 0000000000..cd7814b34d --- /dev/null +++ b/bin/tests/system/dns64/ns1/sign.sh @@ -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 diff --git a/bin/tests/system/dns64/ns2/named.conf b/bin/tests/system/dns64/ns2/named.conf new file mode 100644 index 0000000000..495025a291 --- /dev/null +++ b/bin/tests/system/dns64/ns2/named.conf @@ -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"; +}; diff --git a/bin/tests/system/dns64/setup.sh b/bin/tests/system/dns64/setup.sh new file mode 100644 index 0000000000..8b9dbc3210 --- /dev/null +++ b/bin/tests/system/dns64/setup.sh @@ -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 diff --git a/bin/tests/system/dns64/tests.sh b/bin/tests/system/dns64/tests.sh new file mode 100644 index 0000000000..1fedc7d9a8 --- /dev/null +++ b/bin/tests/system/dns64/tests.sh @@ -0,0 +1,1248 @@ +#!/bin/sh +# +# 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: tests.sh,v 1.2 2010/12/08 02:46:15 marka Exp $ + +SYSTEMTESTTOP=.. +. $SYSTEMTESTTOP/conf.sh + +status=0 +n=0 + +rm -f dig.out.* + +DIGOPTS="+tcp +noadd +nosea +nostat +nocmd -p 5300" + +for conf in conf/good*.conf +do + echo "I:checking that $conf is accepted ($n)" + ret=0 + $CHECKCONF "$conf" || ret=1 + n=`expr $n + 1` + if [ $ret != 0 ]; then echo "I:failed"; fi + status=`expr $status + $ret` +done + +for conf in conf/bad*.conf +do + echo "I:checking that $conf is rejected ($n)" + ret=0 + $CHECKCONF "$conf" >/dev/null && ret=1 + n=`expr $n + 1` + if [ $ret != 0 ]; then echo "I:failed"; fi + status=`expr $status + $ret` +done + +# Check the example. domain + +echo "I: checking non-excluded AAAA lookup works ($n)" +ret=0 +$DIG $DIGOPTS aaaa-only.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking excluded only AAAA lookup works ($n)" +ret=0 +$DIG $DIGOPTS excluded-only.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 0," dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking excluded AAAA and non-mapped A lookup works ($n)" +ret=0 +$DIG $DIGOPTS excluded-bad-a.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 0," dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking excluded only AAAA and mapped A lookup works ($n)" +ret=0 +$DIG $DIGOPTS excluded-good-a.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001:aaaa::1.2.3.4" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking partially excluded only AAAA lookup works ($n)" +ret=0 +$DIG $DIGOPTS partially-excluded-only.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::3" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking partially-excluded AAAA and non-mapped A lookup works ($n)" +ret=0 +$DIG $DIGOPTS partially-excluded-bad-a.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking partially-excluded only AAAA and mapped A lookup works ($n)" +ret=0 +$DIG $DIGOPTS partially-excluded-good-a.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::1" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking AAAA only lookup works ($n)" +ret=0 +$DIG $DIGOPTS aaaa-only.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking A only lookup works ($n)" +ret=0 +$DIG $DIGOPTS a-only.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001:aaaa::102:305" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking A and AAAA lookup works ($n)" +ret=0 +$DIG $DIGOPTS a-and-aaaa.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::1" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking non-mapped A lookup works ($n)" +ret=0 +$DIG $DIGOPTS a-not-mapped.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking NODATA AAAA lookup works ($n)" +ret=0 +$DIG $DIGOPTS mx-only.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking non-existent AAAA lookup works ($n)" +ret=0 +$DIG $DIGOPTS non-existent.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking non-excluded AAAA via CNAME lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-aaaa-only.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking excluded only AAAA via CNAME lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-excluded-only.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking excluded AAAA and non-mapped A via CNAME lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-excluded-bad-a.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking excluded only AAAA and mapped A via CNAME lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-excluded-good-a.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001:aaaa::1.2.3.4" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking AAAA only via CNAME lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-aaaa-only.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking A only via CNAME lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-a-only.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001:aaaa::102:305" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking A and AAAA via CNAME lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-a-and-aaaa.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::1" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking non-mapped A via CNAME lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-a-not-mapped.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1 +grep "CNAME a-not-mapped.example." dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking NODATA AAAA via CNAME lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-mx-only.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1 +grep "CNAME mx-only.example." dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking non-existent AAAA via CNAME lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-non-existent.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +# Check the example. domain recursive only + +echo "I: checking non-excluded AAAA lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS aaaa-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking excluded only AAAA lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS excluded-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 0," dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking excluded AAAA and non-mapped A lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS excluded-bad-a.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 0," dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking excluded only AAAA and mapped A lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS excluded-good-a.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001:bbbb::1.2.3.4" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking partially excluded only AAAA lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS partially-excluded-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::3" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking partially-excluded AAAA and non-mapped A lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS partially-excluded-bad-a.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking partially-excluded only AAAA and mapped A lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS partially-excluded-good-a.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::1" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking AAAA only lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS aaaa-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking A only lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS a-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001:bbbb::102:305" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking A and AAAA lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS a-and-aaaa.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::1" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking non-mapped A lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS a-not-mapped.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking NODATA AAAA lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS mx-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking non-existent AAAA lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS non-existent.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking non-excluded AAAA via CNAME lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS cname-aaaa-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking excluded only AAAA via CNAME lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS cname-excluded-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking excluded AAAA and non-mapped A via CNAME lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS cname-excluded-bad-a.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking excluded only AAAA and mapped A via CNAME lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS cname-excluded-good-a.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 2," dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001:bbbb::102:304" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking AAAA only via CNAME lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS cname-aaaa-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking A only via CNAME lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS cname-a-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001:bbbb::102:305" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking A and AAAA via CNAME lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS cname-a-and-aaaa.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::1" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking non-mapped A via CNAME lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS cname-a-not-mapped.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1 +grep "CNAME a-not-mapped.example." dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking NODATA AAAA via CNAME lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS cname-mx-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1 +grep "CNAME mx-only.example." dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking non-existent AAAA via CNAME lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS cname-non-existent.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +# Check the example. domain recursive only w/o recursion + +echo "I: checking non-excluded AAAA lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec aaaa-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking excluded only AAAA lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec excluded-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001:eeee::3" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking excluded AAAA and non-mapped A lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec excluded-bad-a.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001:eeee::2" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking excluded only AAAA and mapped A lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec excluded-good-a.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001:eeee::1" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking partially excluded only AAAA lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec partially-excluded-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 2," dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001:eeee:" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::3" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking partially-excluded AAAA and non-mapped A lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec partially-excluded-bad-a.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 2," dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001:eeee:" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking partially-excluded only AAAA and mapped A lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec partially-excluded-good-a.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 2," dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001:eeee:" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::1" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking AAAA only lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec aaaa-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking A only lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec a-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 0," dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking A and AAAA lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec a-and-aaaa.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::1" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking non-mapped A lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec a-not-mapped.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking NODATA AAAA lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec mx-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking non-existent AAAA lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec non-existent.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking non-excluded AAAA via CNAME lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec cname-aaaa-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking excluded only AAAA via CNAME lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec cname-excluded-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 2," dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001:eeee::3" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking excluded AAAA and non-mapped A via CNAME lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec cname-excluded-bad-a.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 2," dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001:eeee::2" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking excluded only AAAA and mapped A via CNAME lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec cname-excluded-good-a.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 2," dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001:eeee::1" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking AAAA only via CNAME lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec cname-aaaa-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking A only via CNAME lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec cname-a-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1 +grep "CNAME a-only.example." dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking A and AAAA via CNAME lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec cname-a-and-aaaa.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::1" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking non-mapped A via CNAME lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec cname-a-not-mapped.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1 +grep "CNAME a-not-mapped.example." dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking NODATA AAAA via CNAME lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec cname-mx-only.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1 +grep "CNAME mx-only.example." dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking non-existent AAAA via CNAME lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec cname-non-existent.example. @10.53.0.1 -b 10.53.0.1 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +# Check the example. domain from non client + +echo "I: checking non-excluded AAAA from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS aaaa-only.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking excluded only AAAA from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS excluded-only.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001:eeee::3" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking excluded AAAA and non-mapped A from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS excluded-bad-a.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001:eeee::2" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking excluded only AAAA and mapped A from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS excluded-good-a.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001:eeee::1" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking AAAA only from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS aaaa-only.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking A only from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS a-only.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking A and AAAA from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS a-and-aaaa.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::1" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking non-mapped A from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS a-not-mapped.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking NODATA AAAA from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS mx-only.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking non-existent AAAA from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS non-existent.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking non-excluded AAAA via CNAME from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-aaaa-only.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking excluded only AAAA via CNAME from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-excluded-only.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001:eeee::3" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking excluded AAAA and non-mapped A via CNAME from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-excluded-bad-a.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001:eeee::2" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking excluded only AAAA and mapped A via CNAME from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-excluded-good-a.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001:eeee::1" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking AAAA only via CNAME from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-aaaa-only.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking A only via CNAME from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-a-only.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking A and AAAA via CNAME from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-a-and-aaaa.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::1" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking non-mapped A via CNAME from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-a-not-mapped.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1 +grep "CNAME a-not-mapped.example." dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking NODATA AAAA via CNAME from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-mx-only.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1 +grep "CNAME mx-only.example." dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking non-existent AAAA via CNAME from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-non-existent.example. @10.53.0.2 -b 10.53.0.3 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +# Check the signed. domain + +echo "I: checking non-excluded AAAA lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS aaaa-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking excluded only AAAA lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS excluded-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 0," dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking excluded AAAA and non-mapped A lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS excluded-bad-a.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 0," dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking excluded only AAAA and mapped A lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS excluded-good-a.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001:aaaa::102:304" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking AAAA only lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS aaaa-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking A only lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS a-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001:aaaa::102:305" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking A and AAAA lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS a-and-aaaa.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::1" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking non-mapped A lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS a-not-mapped.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking NODATA AAAA lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS mx-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking non-existent AAAA lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS non-existent.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking non-excluded AAAA via CNAME lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS cname-aaaa-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking excluded only AAAA via CNAME lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS cname-excluded-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking excluded AAAA and non-mapped A via CNAME lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS cname-excluded-bad-a.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking excluded only AAAA and mapped A via CNAME lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS cname-excluded-good-a.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001:aaaa::102:304" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking AAAA only via CNAME lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS cname-aaaa-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking A only via CNAME lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS cname-a-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001:aaaa::102:305" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking A and AAAA via CNAME lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS cname-a-and-aaaa.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::1" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking non-mapped A via CNAME lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS cname-a-not-mapped.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1 +grep "CNAME a-not-mapped.signed." dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking NODATA AAAA via CNAME lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS cname-mx-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1 +grep "CNAME mx-only.signed." dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking non-existent AAAA via CNAME lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS cname-non-existent.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +# Check the signed. domain +echo "I: checking non-excluded AAAA lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec aaaa-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking excluded only AAAA lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec excluded-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001:eeee::3" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking excluded AAAA and non-mapped A lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec excluded-bad-a.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001:eeee::2" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking excluded only AAAA and mapped A lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec excluded-good-a.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001:eeee::1" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking AAAA only lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec aaaa-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking A only lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec a-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 0," dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking A and AAAA lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec a-and-aaaa.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::1" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking non-mapped A lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec a-not-mapped.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking NODATA AAAA lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec mx-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking non-existent AAAA lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec non-existent.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking non-excluded AAAA via CNAME lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec cname-aaaa-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking excluded only AAAA via CNAME lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec cname-excluded-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001:eeee::3" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking excluded AAAA and non-mapped A via CNAME lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec cname-excluded-bad-a.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001:eeee::2" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking excluded only AAAA and mapped A via CNAME lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec cname-excluded-good-a.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001:eeee::1" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking AAAA only via CNAME lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec cname-aaaa-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking A only via CNAME lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec cname-a-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 2," dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001:aaaa::102:305" dig.out.ns2.test$n > /dev/null && ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking A and AAAA via CNAME lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec cname-a-and-aaaa.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "2001::1" dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking non-mapped A via CNAME lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec cname-a-not-mapped.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 2" dig.out.ns2.test$n > /dev/null || ret=1 +grep "CNAME a-not-mapped.signed." dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking NODATA AAAA via CNAME lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec cname-mx-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 2," dig.out.ns2.test$n > /dev/null || ret=1 +grep "CNAME mx-only.signed." dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I: checking non-existent AAAA via CNAME lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec cname-non-existent.signed. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1 +grep "ANSWER: 2," dig.out.ns2.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I:exit status: $status" +exit $status diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml index b8e2f9b52b..4717284b15 100644 --- a/doc/arm/Bv9ARM-book.xml +++ b/doc/arm/Bv9ARM-book.xml @@ -18,7 +18,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> - + BIND 9 Administrator Reference Manual @@ -5120,6 +5120,14 @@ badresp:1,adberr:0,findfail:0,valfail:0] match-mapped-addresses yes_or_no; filter-aaaa-on-v4 ( yes_or_no | break-dnssec ); filter-aaaa { address_match_list }; + dns64 IPv6-prefix { + clients { address_match_list }; + mapped { address_match_list }; + exclude { address_match_list }; + suffix IPv6-address; + recursion-only yes_or_no; + break-dnssec yes_or_no; + }; ; preferred-glue ( A | AAAA | NONE ); edns-udp-size number; max-udp-size number; @@ -5710,6 +5718,63 @@ options { + + dns64 + + + This directive instructs named 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 + dns64 defines one DNS64 prefix. + Multiple DNS64 prefixes can be defined. + + + Compatible IPv6 prefixes have lengths of 32, 40, 48, 56, + 64 and 96 as per RFC 6052. + + + Each dns64 supports a optional + clients acl which defines which clients + see this directive. If not defined it defaults to + any;. + + + Each dns64 supports a optional + mapped acl which selects which + IPv4 addresses are to be mapped are in the corresponding + A RRset. If not defined it defaults to + any;. + + + Each dns64 supports a optional + exclude 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. + + + A optional suffix can also + be defined to set the bits trailing the mapped + IPv4 address bits. By default these bits are + set to ::. The bits + matching the prefix and mapped IPv4 address + must be zero. + + + 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 ::; + }; + + + + diff --git a/doc/misc/options b/doc/misc/options index 85d5607eba..ae6761f9c8 100644 --- a/doc/misc/options +++ b/doc/misc/options @@ -100,6 +100,14 @@ options { directory ; disable-algorithms { ; ... }; disable-empty-zone ; + dns64 { + break-dnssec ; + clients { ; ... }; + exclude { ; ... }; + mapped { ; ... }; + recursive-only ; + suffix ; + }; dnssec-accept-expired ; dnssec-dnskey-kskonly ; dnssec-enable ; @@ -303,6 +311,14 @@ view { dlz { database ; }; + dns64 { + break-dnssec ; + clients { ; ... }; + exclude { ; ... }; + mapped { ; ... }; + recursive-only ; + suffix ; + }; dnssec-accept-expired ; dnssec-dnskey-kskonly ; dnssec-enable ; diff --git a/lib/bind9/check.c b/lib/bind9/check.c index a7903b34d2..aa1e8e4b8b 100644 --- a/lib/bind9/check.c +++ b/lib/bind9/check.c @@ -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); diff --git a/lib/dns/Makefile.in b/lib/dns/Makefile.in index 25e129d175..5e26cd9bc2 100644 --- a/lib/dns/Makefile.in +++ b/lib/dns/Makefile.in @@ -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 \ diff --git a/lib/dns/dns64.c b/lib/dns/dns64.c new file mode 100644 index 0000000000..0fcfeaa451 --- /dev/null +++ b/lib/dns/dns64.c @@ -0,0 +1,282 @@ +/* + * Copyright + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +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); +} diff --git a/lib/dns/include/dns/dns64.h b/lib/dns/include/dns/dns64.h new file mode 100644 index 0000000000..041aa4a418 --- /dev/null +++ b/lib/dns/include/dns/dns64.h @@ -0,0 +1,161 @@ +/* + * Copyright + */ + +#ifndef DNS_DNS64_H +#define DNS_DNS64_H 1 + +#include + +#include + +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: + * + * + * + * If 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 */ diff --git a/lib/dns/include/dns/types.h b/lib/dns/include/dns/types.h index 34c2c9a21c..fef4d7a3f3 100644 --- a/lib/dns/include/dns/types.h +++ b/lib/dns/include/dns/types.h @@ -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; diff --git a/lib/dns/include/dns/view.h b/lib/dns/include/dns/view.h index 6835910f3f..c044f655bd 100644 --- a/lib/dns/include/dns/view.h +++ b/lib/dns/include/dns/view.h @@ -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, diff --git a/lib/dns/view.c b/lib/dns/view.c index 8ca7513661..025308e8f3 100644 --- a/lib/dns/view.c +++ b/lib/dns/view.c @@ -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 #include #include +#include #include #include #include @@ -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); diff --git a/lib/isc/mem.c b/lib/isc/mem.c index 4d3b0b623d..9dbd3e1811 100644 --- a/lib/isc/mem.c +++ b/lib/isc/mem.c @@ -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); diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index 6f680bde41..260b615e7e 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -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 },