]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
2732. [func] Add optional filter-aaaa-on-v4 option, available
authorEvan Hunt <each@isc.org>
Mon, 26 Oct 2009 23:14:54 +0000 (23:14 +0000)
committerEvan Hunt <each@isc.org>
Mon, 26 Oct 2009 23:14:54 +0000 (23:14 +0000)
if built with './configure --enable-filter-aaaa'.
Filters out AAAA answers to clients connecting
via IPv4.  (This is NOT recommended for general
use.) [RT #20339]

14 files changed:
CHANGES
bin/named/client.c
bin/named/config.c
bin/named/include/named/client.h
bin/named/include/named/server.h
bin/named/query.c
bin/named/server.c
config.h.in
configure.in
doc/arm/Bv9ARM-book.xml
lib/dns/include/dns/message.h
lib/dns/include/dns/types.h
lib/dns/message.c
lib/isccfg/namedconf.c

diff --git a/CHANGES b/CHANGES
index 2b9eb3e9fc12908a1e78ccde26691675baa1a0e5..c1b34cb2a78844dec6cecb7b45ab6180dab713d5 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,9 @@
+2732.  [func]          Add optional filter-aaaa-on-v4 option, available
+                       if built with './configure --enable-filter-aaaa'.
+                       Filters out AAAA answers to clients connecting
+                       via IPv4.  (This is NOT recommended for general
+                       use.) [RT #20339]
+
 2731.  [func]          Additional work on change 2709.  The key parser
                        will now ignore unrecognized fields when the
                        minor version number of the private key format
index 19fa2251b8c5f573513f894078993aa910bf9dd4..c92f0930a24f51bd2997fb4577cff6d13eec08d1 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: client.c,v 1.265 2009/05/07 09:41:21 fdupont Exp $ */
+/* $Id: client.c,v 1.266 2009/10/26 23:14:53 each Exp $ */
 
 #include <config.h>
 
@@ -918,7 +918,7 @@ ns_client_send(ns_client_t *client) {
        dns_compress_t cctx;
        isc_boolean_t cleanup_cctx = ISC_FALSE;
        unsigned char sendbuf[SEND_BUFFER_SIZE];
-       unsigned int dnssec_opts;
+       unsigned int render_opts;
        unsigned int preferred_glue;
        isc_boolean_t opt_included = ISC_FALSE;
 
@@ -930,10 +930,21 @@ ns_client_send(ns_client_t *client) {
                client->message->flags |= DNS_MESSAGEFLAG_RA;
 
        if ((client->attributes & NS_CLIENTATTR_WANTDNSSEC) != 0)
-               dnssec_opts = 0;
+               render_opts = 0;
        else
-               dnssec_opts = DNS_MESSAGERENDER_OMITDNSSEC;
-
+               render_opts = DNS_MESSAGERENDER_OMITDNSSEC;
+#ifdef ALLOW_FILTER_AAAA_ON_V4
+       /*
+        * filter-aaaa-on-v4 yes or break-dnssec option to suppress
+        * AAAA records
+        * We already know that request came via IPv4,
+        * that we have both AAAA and A records,
+        * and that we either have no signatures that the client wants
+        * or we are supposed to break DNSSEC.
+        */
+       if ((client->attributes & NS_CLIENTATTR_FILTER_AAAA) != 0)
+               render_opts |= DNS_MESSAGERENDER_FILTER_AAAA;
+#endif
        preferred_glue = 0;
        if (client->view != NULL) {
                if (client->view->preferred_glue == dns_rdatatype_a)
@@ -977,7 +988,7 @@ ns_client_send(ns_client_t *client) {
        result = dns_message_rendersection(client->message,
                                           DNS_SECTION_ANSWER,
                                           DNS_MESSAGERENDER_PARTIAL |
-                                          dnssec_opts);
+                                          render_opts);
        if (result == ISC_R_NOSPACE) {
                client->message->flags |= DNS_MESSAGEFLAG_TC;
                goto renderend;
@@ -987,7 +998,7 @@ ns_client_send(ns_client_t *client) {
        result = dns_message_rendersection(client->message,
                                           DNS_SECTION_AUTHORITY,
                                           DNS_MESSAGERENDER_PARTIAL |
-                                          dnssec_opts);
+                                          render_opts);
        if (result == ISC_R_NOSPACE) {
                client->message->flags |= DNS_MESSAGEFLAG_TC;
                goto renderend;
@@ -996,7 +1007,7 @@ ns_client_send(ns_client_t *client) {
                goto done;
        result = dns_message_rendersection(client->message,
                                           DNS_SECTION_ADDITIONAL,
-                                          preferred_glue | dnssec_opts);
+                                          preferred_glue | render_opts);
        if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE)
                goto done;
  renderend:
index 39a8ba7ac6e6329fe69c99cebd552d82ec81a139..4623482998c1e4402052c0d6c973974ba67dcc63 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: config.c,v 1.103 2009/10/10 01:47:59 each Exp $ */
+/* $Id: config.c,v 1.104 2009/10/26 23:14:53 each Exp $ */
 
 /*! \file */
 
@@ -158,6 +158,10 @@ options {\n\
        zero-no-soa-ttl-cache no;\n\
        nsec3-test-zone no;\n\
 "
+#ifdef ALLOW_FILTER_AAAA_ON_V4
+"      filter-aaaa-on-v4 no;\n\
+"
+#endif
 
 "      /* zone */\n\
        allow-query {any;};\n\
index f6956454e19c1302aad8a4c9c34cc0cd16bd0261..9fff31a822a07b8c2d0844a394a1cb27e2582f8e 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: client.h,v 1.90 2009/05/07 09:41:22 fdupont Exp $ */
+/* $Id: client.h,v 1.91 2009/10/26 23:14:53 each Exp $ */
 
 #ifndef NAMED_CLIENT_H
 #define NAMED_CLIENT_H 1
@@ -168,6 +168,10 @@ struct ns_client {
 #define NS_CLIENTATTR_MULTICAST                0x08 /*%< recv'd from multicast */
 #define NS_CLIENTATTR_WANTDNSSEC       0x10 /*%< include dnssec records */
 #define NS_CLIENTATTR_WANTNSID          0x20 /*%< include nameserver ID */
+#ifdef ALLOW_FILTER_AAAA_ON_V4
+#define NS_CLIENTATTR_FILTER_AAAA      0x40 /*%< suppress AAAAs */
+#define NS_CLIENTATTR_FILTER_AAAA_RC   0x80 /*%< recursing for A against AAAA */
+#endif
 
 extern unsigned int ns_client_requests;
 
index 83ba09afc2005472977bf4af616984faa071e1bf..75416d95a6e60c255119c70aff3a7e46b93ed52a 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: server.h,v 1.102 2009/10/12 20:48:11 each Exp $ */
+/* $Id: server.h,v 1.103 2009/10/26 23:14:53 each Exp $ */
 
 #ifndef NAMED_SERVER_H
 #define NAMED_SERVER_H 1
@@ -115,6 +115,9 @@ struct ns_server {
        dns_name_t              *session_keyname;
        unsigned int            session_keyalg;
        isc_uint16_t            session_keybits;
+#ifdef ALLOW_FILTER_AAAA_ON_V4
+       dns_v4_aaaa_t           v4_aaaa;
+#endif
 };
 
 #define NS_SERVER_MAGIC                        ISC_MAGIC('S','V','E','R')
index a0726f8eea0077404276b8af5048007560704c59..d15ac5a8e7676f4ba146751fd5ade5bcad342dc2 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: query.c,v 1.328 2009/10/24 04:38:19 marka Exp $ */
+/* $Id: query.c,v 1.329 2009/10/26 23:14:53 each Exp $ */
 
 /*! \file */
 
@@ -4637,6 +4637,20 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
        }
 
        if (type == dns_rdatatype_any) {
+#ifdef ALLOW_FILTER_AAAA_ON_V4
+               isc_boolean_t have_aaaa, have_a, have_sig;
+               
+               /*
+                * The filter-aaaa-on-v4 option should
+                * suppress AAAAs for IPv4 clients if there is an A.
+                * If we are not authoritative, assume there is a A
+                * even in if it is not in our cache.  This assumption could
+                * be wrong but it is a good bet.
+                */
+               have_aaaa = ISC_FALSE;
+               have_a = !authoritative;
+               have_sig = ISC_FALSE;
+#endif
                /*
                 * XXXRTH  Need to handle zonecuts with special case
                 * code.
@@ -4664,6 +4678,20 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
                result = dns_rdatasetiter_first(rdsiter);
                while (result == ISC_R_SUCCESS) {
                        dns_rdatasetiter_current(rdsiter, rdataset);
+#ifdef ALLOW_FILTER_AAAA_ON_V4
+                       /*
+                        * Notice the presence of A and AAAAs so
+                        * that AAAAs can be hidden from IPv4 clients.
+                        */
+                       if (ns_g_server->v4_aaaa != dns_v4_aaaa_ok &&
+                           client->peeraddr_valid &&
+                           client->peeraddr.type.sa.sa_family == AF_INET) {
+                               if (rdataset->type == dns_rdatatype_aaaa)
+                                       have_aaaa = ISC_TRUE;
+                               else if (rdataset->type == dns_rdatatype_a)
+                                       have_a = ISC_TRUE;
+                       }
+#endif
                        if (is_zone && qtype == dns_rdatatype_any &&
                            !dns_db_issecure(db) &&
                            dns_rdatatype_isdnssec(rdataset->type)) {
@@ -4675,6 +4703,10 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
                                dns_rdataset_disassociate(rdataset);
                        } else if ((qtype == dns_rdatatype_any ||
                             rdataset->type == qtype) && rdataset->type != 0) {
+#ifdef ALLOW_FILTER_AAAA_ON_V4
+                               if (dns_rdatatype_isdnssec(rdataset->type))
+                                       have_sig = ISC_TRUE;
+#endif
                                if (NOQNAME(rdataset) && WANTDNSSEC(client))
                                        noqname = rdataset;
                                else
@@ -4705,6 +4737,16 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
                        result = dns_rdatasetiter_next(rdsiter);
                }
 
+#ifdef ALLOW_FILTER_AAAA_ON_V4
+               /*
+                * Filter AAAAs if there is an A and there is no signature
+                * or we are supposed to break DNSSEC.
+                */
+               if (have_aaaa && have_a &&
+                   (!have_sig || !WANTDNSSEC(client) ||
+                    ns_g_server->v4_aaaa == dns_v4_aaaa_break_dnssec))
+                       client->attributes |= NS_CLIENTATTR_FILTER_AAAA;
+#endif
                if (fname != NULL)
                        dns_message_puttempname(client->message, &fname);
 
@@ -4766,6 +4808,90 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
                 * This is the "normal" case -- an ordinary question to which
                 * we know the answer.
                 */
+#ifdef ALLOW_FILTER_AAAA_ON_V4
+               /*
+                * Optionally hide AAAAs from IPv4 clients if there is an A.
+                * We add the AAAAs now, but might refuse to render them later
+                * after DNSSEC is figured out.
+                * This could be more efficient, but the whole idea is
+                * so fundamentally wrong, unavoidably inaccurate, and
+                * unneeded that it is best to keep it as short as possible.
+                */
+               if (ns_g_server->v4_aaaa != dns_v4_aaaa_ok &&
+                   client->peeraddr_valid &&
+                   client->peeraddr.type.sa.sa_family == AF_INET &&
+                   (!WANTDNSSEC(client) ||
+                    sigrdataset == NULL ||
+                    !dns_rdataset_isassociated(sigrdataset) ||
+                    ns_g_server->v4_aaaa == dns_v4_aaaa_break_dnssec)) {
+                       if (qtype == dns_rdatatype_aaaa) {
+                               trdataset = query_newrdataset(client);
+                               result = dns_db_findrdataset(db, node, version,
+                                                       dns_rdatatype_a, 0,
+                                                       client->now,
+                                                       trdataset, NULL);
+                               if (dns_rdataset_isassociated(trdataset))
+                                       dns_rdataset_disassociate(trdataset);
+                               query_putrdataset(client, &trdataset);
+
+                               /*
+                                * We have an AAAA but the A is not in our cache.
+                                * Assume any result other than DNS_R_DELEGATION
+                                * or ISC_R_NOTFOUND means there is no A and
+                                * so AAAAs are ok.
+                                * Assume there is no A if we can't recurse
+                                * for this client, although that could be
+                                * the wrong answer. What else can we do?
+                                * Besides, that we have the AAAA and are using
+                                * this mechanism suggests that we care more
+                                * about As than AAAAs and would have cached
+                                * the A if it existed.
+                                */
+                               if (result == ISC_R_SUCCESS) {
+                                       client->attributes |=
+                                                   NS_CLIENTATTR_FILTER_AAAA;
+
+                               } else if (authoritative ||
+                                          !RECURSIONOK(client) ||
+                                          (result != DNS_R_DELEGATION &&
+                                           result != ISC_R_NOTFOUND)) {
+                                       client->attributes &=
+                                                   ~NS_CLIENTATTR_FILTER_AAAA;
+                               } else {
+                                       /*
+                                        * This is an ugly kludge to recurse
+                                        * for the A and discard the result.
+                                        *
+                                        * Continue to add the AAAA now.
+                                        * We'll make a note to not render it
+                                        * if the recursion for the A succeeds.
+                                        */
+                                       result = query_recurse(client,
+                                                       dns_rdatatype_a,
+                                                       NULL, NULL, resuming);
+                                       if (result == ISC_R_SUCCESS) {
+                                           client->attributes |=
+                                                   NS_CLIENTATTR_FILTER_AAAA_RC;
+                                           client->query.attributes |=
+                                                       NS_QUERYATTR_RECURSING;
+                                       }
+                               }
+
+                       } else if (qtype == dns_rdatatype_a &&
+                                  (client->attributes &
+                                           NS_CLIENTATTR_FILTER_AAAA_RC) != 0) {
+                               client->attributes &=
+                                           ~NS_CLIENTATTR_FILTER_AAAA_RC;
+                               client->attributes |= 
+                                           NS_CLIENTATTR_FILTER_AAAA;
+                               dns_rdataset_disassociate(rdataset);
+                               if (sigrdataset != NULL &&
+                                   dns_rdataset_isassociated(sigrdataset))
+                                       dns_rdataset_disassociate(sigrdataset);
+                               goto cleanup;
+                       }
+               }
+#endif
                if (sigrdataset != NULL)
                        sigrdatasetp = &sigrdataset;
                else
index 268a60e478f09552bb1db29abaf819844a232815..6bedd20887e4fa3c2cca4bb9e714ddaee811f2e7 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: server.c,v 1.552 2009/10/20 03:15:06 marka Exp $ */
+/* $Id: server.c,v 1.553 2009/10/26 23:14:53 each Exp $ */
 
 /*! \file */
 
@@ -4355,6 +4355,25 @@ load_configuration(const char *filename, ns_server_t *server,
                server->flushonshutdown = ISC_FALSE;
        }
 
+#ifdef ALLOW_FILTER_AAAA_ON_V4
+       obj = NULL;
+       result = ns_config_get(maps, "filter-aaaa-on-v4", &obj);
+       INSIST(result == ISC_R_SUCCESS);
+       if (cfg_obj_isboolean(obj)) {
+               if (cfg_obj_asboolean(obj))
+                       server->v4_aaaa = dns_v4_aaaa_filter;
+               else
+                       server->v4_aaaa = dns_v4_aaaa_ok;
+       } else {
+               const char *v4_aaaastr = cfg_obj_asstring(obj);
+               if (strcasecmp(v4_aaaastr, "break-dnssec") == 0)
+                       server->v4_aaaa
+                                       = dns_v4_aaaa_break_dnssec;
+               else
+                       INSIST(0);
+       }
+
+#endif
        result = ISC_R_SUCCESS;
 
  cleanup:
index cc78c6d3186911d6a6b8bf739e2312c212e9d6c3..38f5a16101d734ed9f9fb64186770bbc6c987920 100644 (file)
@@ -16,7 +16,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: config.h.in,v 1.120 2009/09/01 18:40:25 jinmei Exp $ */
+/* $Id: config.h.in,v 1.121 2009/10/26 23:14:53 each Exp $ */
 
 /*! \file */
 
@@ -365,3 +365,7 @@ int sigwait(const unsigned int *set, int *sig);
 /* Define to empty if the keyword `volatile' does not work. Warning: valid
    code using `volatile' can become incorrect without. Disable with care. */
 #undef volatile
+
+/* Define to enable the "filter-aaaa-on-v4" option. */
+#undef ALLOW_FILTER_AAAA_ON_V4
+
index b36570d86cd8a6b0618652a1244b33d5083c5549..af79aad318ff948788a58ac49e593fb4ced9e86f 100644 (file)
@@ -18,7 +18,7 @@ AC_DIVERT_PUSH(1)dnl
 esyscmd([sed "s/^/# /" COPYRIGHT])dnl
 AC_DIVERT_POP()dnl
 
-AC_REVISION($Revision: 1.485 $)
+AC_REVISION($Revision: 1.486 $)
 
 AC_INIT(lib/dns/name.c)
 AC_PREREQ(2.59)
@@ -2641,6 +2641,25 @@ case "$enable_fixed" in
                ;;
 esac
 
+#
+# Activate "filter-aaaa-on-v4" or not?
+#
+AC_ARG_ENABLE(filter-aaaa,
+       [  --enable-filter-aaaa    enable filtering of AAAA records over IPv4
+                         [[default=no]]],
+                       enable_filter="$enableval",
+                       enable_filter="no")
+case "$enable_filter" in
+       yes)
+               AC_DEFINE(ALLOW_FILTER_AAAA_ON_V4, 1,
+                         [Define to enable the "filter-aaaa-on-v4" option.])
+               ;;
+       no)
+               ;;
+       *)
+               ;;
+esac
+
 #
 #  The following sets up how non-blocking i/o is established.
 #  Sunos, cygwin and solaris 2.x (x<5) require special handling.
index b5e16f595fdcb3b7eea3d68e50c00adc8b3a54ea..9ea53bccd9211c1eaa7a2289c10aaad4f6aa4cf8 100644 (file)
@@ -18,7 +18,7 @@
  - PERFORMANCE OF THIS SOFTWARE.
 -->
 
-<!-- File: $Id: Bv9ARM-book.xml,v 1.439 2009/10/22 03:43:16 each Exp $ -->
+<!-- File: $Id: Bv9ARM-book.xml,v 1.440 2009/10/26 23:14:53 each Exp $ -->
 <book xmlns:xi="http://www.w3.org/2001/XInclude">
   <title>BIND 9 Administrator Reference Manual</title>
 
@@ -5000,6 +5000,8 @@ badresp:1,adberr:0,findfail:0,valfail:0]
     <optional> random-device <replaceable>path_name</replaceable> ; </optional>
     <optional> max-cache-size <replaceable>size_spec</replaceable> ; </optional>
     <optional> match-mapped-addresses <replaceable>yes_or_no</replaceable>; </optional>
+    <optional> match-mapped-addresses <replaceable>yes_or_no</replaceable>; </optional>
+    <optional> disable-aaaa-on-v4-transport ( <replaceable>yes_or_no</replaceable> | <replaceable>break-dnssec</replaceable> ); </optional>
     <optional> preferred-glue ( <replaceable>A</replaceable> | <replaceable>AAAA</replaceable> | <replaceable>NONE</replaceable> ); </optional>
     <optional> edns-udp-size <replaceable>number</replaceable>; </optional>
     <optional> max-udp-size <replaceable>number</replaceable>; </optional>
@@ -6232,6 +6234,59 @@ options {
               </listitem>
             </varlistentry>
 
+            <varlistentry>
+              <term><command>filter-aaaa-on-v4</command></term>
+              <listitem>
+                <para>
+                  This option is only available when
+                  <acronym>BIND</acronym> 9 is compiled with the
+                  <userinput>--with-filter-aaaa</userinput> option on the
+                  "configure" command line.  It is intended to help the
+                  transition from IPv4 to IPv6 by not giving IPv6 addresses
+                  to DNS clients unless they have connections to the IPv6
+                  Internet.  This is not recommended unless absolutely
+                  necessary.  The default is <userinput>no</userinput>.
+                </para>
+                <para>
+                  If <userinput>yes</userinput>,
+                  the DNS client is at an IPv4 address,
+                  and if the response does not include DNSSEC signatures, 
+                  then all AAAA records are deleted from the response.
+                  This filtering applies to all responses and not only
+                  authoritative responses.
+                </para>
+                <para>
+                  If <userinput>break-dnssec</userinput>,
+                  then AAAA records are deleted even when dnssec is enabled.
+                  As suggested by the name, this makes the response not verify,
+                  because the DNSSEC protocol is designed detect deletions.
+                </para>
+                <para>
+                  This mechanism can erroneously cause other servers to 
+                 not give AAAA records to their clients.  
+                 A recursing server with both IPv6 and IPv4 network connections
+                 that queries an authoritative server using this mechanism
+                 via IPv4 will be denied AAAA records even if its client is
+                 using IPv6.
+                </para>
+                <para>
+                  This mechanism is applied to authoritative as well as
+                 non-authoritative records.
+                 A client using IPv4 that is not allowed recursion can
+                 erroneously be given AAAA records because the server is not
+                 allowed to check for A records.
+                </para>
+                <para>
+                 Some AAAA records are given to IPv4 clients in glue records.
+                 IPv4 clients that are servers can then erroneously
+                 answer requests for AAAA records received via IPv4.
+                </para>
+                <para>
+                 security
+                </para>
+              </listitem>
+            </varlistentry>
+
             <varlistentry>
               <term><command>ixfr-from-differences</command></term>
               <listitem>
index 044b0103dd46682e6d76773e4d2b88c52b533b08..da59409d546967c23e8d6f2b007e7f639f742f69 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: message.h,v 1.128 2009/09/01 00:22:26 jinmei Exp $ */
+/* $Id: message.h,v 1.129 2009/10/26 23:14:54 each Exp $ */
 
 #ifndef DNS_MESSAGE_H
 #define DNS_MESSAGE_H 1
@@ -173,6 +173,9 @@ typedef int dns_messagetextflag_t;
                                                      additional section. */
 #define DNS_MESSAGERENDER_PREFER_AAAA  0x0010  /*%< prefer AAAA records in
                                                  additional section. */
+#ifdef ALLOW_FILTER_AAAA_ON_V4
+#define DNS_MESSAGERENDER_FILTER_AAAA  0x0020  /*%< filter AAAA records */
+#endif 
 
 typedef struct dns_msgblock dns_msgblock_t;
 
index 79be222e105fa9b476d4873b1b24b197af145c35..46faaab982af2b00fc5bc267880ed58c03692b7d 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: types.h,v 1.136 2009/09/01 00:22:27 jinmei Exp $ */
+/* $Id: types.h,v 1.137 2009/10/26 23:14:54 each Exp $ */
 
 #ifndef DNS_TYPES_H
 #define DNS_TYPES_H 1
@@ -187,6 +187,15 @@ typedef enum {
        dns_masterformat_raw = 2
 } dns_masterformat_t;
 
+#ifdef ALLOW_FILTER_AAAA_ON_V4
+typedef enum {
+       dns_v4_aaaa_ok = 0,
+       dns_v4_aaaa_filter = 1,
+       dns_v4_aaaa_break_dnssec = 2
+} dns_v4_aaaa_t;
+
+#endif
+
 /*
  * These are generated by gen.c.
  */
index 302a75453d46dea102547f7725dab3359bea5a4a..d74382b5b04558969dc652e730a9cf10cd58560b 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: message.c,v 1.247 2009/01/17 23:47:42 tbox Exp $ */
+/* $Id: message.c,v 1.248 2009/10/26 23:14:54 each Exp $ */
 
 /*! \file */
 
@@ -1802,6 +1802,36 @@ wrong_priority(dns_rdataset_t *rds, int pass, dns_rdatatype_t preferred_glue) {
        return (ISC_TRUE);
 }
 
+#ifdef ALLOW_FILTER_AAAA_ON_V4
+/*
+ * Decide whether to not answer with an AAAA record and its RRSIG
+ */
+static inline isc_boolean_t
+norender_rdataset(const dns_rdataset_t *rdataset, unsigned int options)
+{
+       switch (rdataset->type) {
+       case dns_rdatatype_aaaa:
+               if ((options & DNS_MESSAGERENDER_FILTER_AAAA) == 0)
+                       return (ISC_FALSE);
+               break;
+
+       case dns_rdatatype_rrsig:
+               if ((options & DNS_MESSAGERENDER_FILTER_AAAA) == 0 ||
+                   rdataset->covers != dns_rdatatype_aaaa)
+                       return (ISC_FALSE);
+               break;
+
+       default:
+               return (ISC_FALSE);
+       }
+
+       if (rdataset->rdclass != dns_rdataclass_in)
+               return (ISC_FALSE);
+
+       return (ISC_TRUE);
+}
+
+#endif
 isc_result_t
 dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid,
                          unsigned int options)
@@ -1927,6 +1957,23 @@ dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid,
                                                      preferred_glue))
                                        goto next;
 
+#ifdef ALLOW_FILTER_AAAA_ON_V4
+                               /*
+                                * Suppress AAAAs if asked and we are
+                                * not doing DNSSEC or are breaking DNSSEC.
+                                * Say so in the AD bit if we break DNSSEC.
+                                */
+                               if (norender_rdataset(rdataset, options) &&
+                                   sectionid != DNS_SECTION_QUESTION) {
+                                       if (sectionid == DNS_SECTION_ANSWER ||
+                                           sectionid == DNS_SECTION_AUTHORITY)
+                                           msg->flags &= ~DNS_MESSAGEFLAG_AD;
+                                       if (OPTOUT(rdataset))
+                                           msg->flags &= ~DNS_MESSAGEFLAG_AD;
+                                       goto next;
+                               }
+
+#endif
                                st = *(msg->buffer);
 
                                count = 0;
index 96fac89dbafb12e2184edf8dc0fe1b7da62a7708..c38de43203dd0450b3eb6300a55012378ba9eeba 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: namedconf.c,v 1.109 2009/10/12 23:48:02 tbox Exp $ */
+/* $Id: namedconf.c,v 1.110 2009/10/26 23:14:54 each Exp $ */
 
 /*! \file */
 
@@ -120,6 +120,9 @@ static cfg_type_t cfg_type_zone;
 static cfg_type_t cfg_type_zoneopts;
 static cfg_type_t cfg_type_dynamically_loadable_zones;
 static cfg_type_t cfg_type_dynamically_loadable_zones_opts;
+#ifdef ALLOW_FILTER_AAAA_ON_V4
+static cfg_type_t cfg_type_v4_aaaa;
+#endif
 
 /*
  * Clauses that can be found in a 'dynamically loadable zones' statement
@@ -874,6 +877,9 @@ options_clauses[] = {
        { "use-ixfr", &cfg_type_boolean, 0 },
        { "version", &cfg_type_qstringornone, 0 },
        { "flush-zones-on-shutdown", &cfg_type_boolean, 0 },
+#ifdef ALLOW_FILTER_AAAA_ON_V4
+       { "filter-aaaa-on-v4", &cfg_type_v4_aaaa, 0 },
+#endif
        { NULL, NULL, 0 }
 };
 
@@ -1591,6 +1597,19 @@ static cfg_type_t cfg_type_ixfrdifftype = {
        &cfg_rep_string, ixfrdiff_enums,
 };
 
+#ifdef ALLOW_FILTER_AAAA_ON_V4
+static const char *v4_aaaa_enums[] = { "break-dnssec", NULL };
+static isc_result_t
+parse_v4_aaaa(cfg_parser_t *pctx, const cfg_type_t *type,
+                    cfg_obj_t **ret) {
+       return (parse_enum_or_other(pctx, type, &cfg_type_boolean, ret));
+}
+static cfg_type_t cfg_type_v4_aaaa = {
+       "v4_aaaa", parse_v4_aaaa, cfg_print_ustring,
+       doc_enum_or_other, &cfg_rep_string, v4_aaaa_enums,
+};
+
+#endif
 static keyword_type_t key_kw = { "key", &cfg_type_astring };
 
 LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_keyref = {