]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
3993. [func] Dig now supports EDNS negotiation by default.
authorMark Andrews <marka@isc.org>
Thu, 30 Oct 2014 12:13:12 +0000 (23:13 +1100)
committerMark Andrews <marka@isc.org>
Thu, 30 Oct 2014 12:13:12 +0000 (23:13 +1100)
                        (dig +[no]ednsnegotiation). [RT #37604]

CHANGES
bin/dig/dig.c
bin/dig/dig.docbook
bin/dig/dighost.c
bin/dig/include/dig/dig.h
bin/tests/system/ednscompliance/tests.sh
doc/arm/notes.xml

diff --git a/CHANGES b/CHANGES
index 0b5a2de328ab48d7bd0886aa4ba4279da300c726..83680886ff166f22bb91ec46b642c2c4de618226 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+3993.  [func]          Dig now supports EDNS negotiation by default.
+                       (dig +[no]ednsnegotiation). [RT #37604]
+
 3992.  [func]          DiG can now send queries without questions
                        (dig +header-only). [RT #37599]
 
index 2a00b058d889318c145a28c720ed2b7fa950cbec..725c5203dd5e75e807f1a3685aabe6144a646d8c 100644 (file)
@@ -195,6 +195,7 @@ help(void) {
 "                 +ednsflags=###      (Set EDNS flag bits)\n"
 "                 +ednsopt=###[:value] (Send specified EDNS option)\n"
 "                 +noednsopt          (Clear list of +ednsopt options)\n"
+"                 +[no]ednsnegotiation (Set EDNS version negotiation)\n"
 "                 +[no]search         (Set whether to use searchlist)\n"
 "                 +[no]showsearch     (Search with intermediate results)\n"
 "                 +[no]defname        (Ditto)\n"
@@ -981,6 +982,10 @@ plus_option(char *option, isc_boolean_t is_batchfile,
                                                              "ednsflags");
                                                lookup->ednsflags = num;
                                                break;
+                                       case 'n':
+                                               FULLCHECK("ednsnegotiation");
+                                               lookup->ednsneg = state;
+                                               break;
                                        case 'o':
                                                FULLCHECK("ednsopt");
                                                if (!state) {
index 24fba64ee21659e02e5f220cd4459cdf5c9ba64b..5a376be8200e77328c2fe2f06292c47721b8e31b 100644 (file)
          </listitem>
        </varlistentry>
 
+       <varlistentry>
+         <term><option>+[no]ednsnegotiation</option></term>
+         <listitem>
+           <para>
+             Enable / disable EDNS version negotiation. By default
+             EDNS version negotiation is enabled.
+           </para>
+         </listitem>
+       </varlistentry>
+
        <varlistentry>
          <term><option>+[no]ednsopt[=code[:value]]</option></term>
          <listitem>
index 7d418804fd22aa1c0ba822a45625543b88c81b8f..a171358f9393f04f09ede1d6a86e8f8d5e08f0a8 100644 (file)
@@ -832,6 +832,7 @@ make_empty_lookup(void) {
 #endif
        looknew->ednsopts = NULL;
        looknew->ednsoptscnt = 0;
+       looknew->ednsneg = ISC_TRUE;
        looknew->dscp = -1;
        dns_fixedname_init(&looknew->fdomain);
        ISC_LINK_INIT(looknew, link);
@@ -889,6 +890,7 @@ clone_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
 #endif
        looknew->ednsopts = lookold->ednsopts;
        looknew->ednsoptscnt = lookold->ednsoptscnt;
+       looknew->ednsneg = lookold->ednsneg;
 #ifdef DIG_SIGCHASE
        looknew->sigchase = lookold->sigchase;
 #if DIG_SIGCHASE_TD
@@ -3468,6 +3470,10 @@ process_opt(dig_lookup_t *l, dns_message_t *msg) {
 }
 #endif
 
+static int
+ednsvers(dns_rdataset_t *opt) {
+       return ((opt->ttl >> 16) & 0xff);
+}
 
 /*%
  * Event handler for recv complete.  Perform whatever actions are necessary,
@@ -3497,6 +3503,7 @@ recv_done(isc_task_t *task, isc_event_t *event) {
        isc_region_t r;
        isc_buffer_t *buf = NULL;
 #endif
+       int newedns;
 
        UNUSED(task);
        INSIST(!free_now);
@@ -3728,6 +3735,25 @@ recv_done(isc_task_t *task, isc_event_t *event) {
                                goto udp_mismatch;
                }
        }
+       if (msg->rcode == dns_rcode_badvers && msg->opt != NULL &&
+           (newedns = ednsvers(msg->opt)) < l->edns && l->ednsneg) {
+               /*
+                * Add minimum EDNS version required checks here if needed.
+                */
+               if (l->comments)
+                       printf(";; BADVERS, retrying with EDNS version %u.\n",
+                              newedns);
+               l->edns = newedns;
+               n = requeue_lookup(l, ISC_TRUE);
+               n->origin = query->lookup->origin;
+               dns_message_destroy(&msg);
+               isc_event_free(&event);
+               clear_query(query);
+               cancel_lookup(l);
+               check_next_lookup(l);
+               UNLOCK_LOOKUP;
+               return;
+       }
        if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0 &&
            !l->ignore && !l->tcp_mode) {
                if (l->comments)
index 435e8d539c24182ad7f0cf2b82b334194a44c4a9..7c23c74fb9fdeb7ed3eea246a86b5c9545bbce06 100644 (file)
@@ -136,7 +136,8 @@ struct dig_lookup {
                sit,
 #endif
                nsid,   /*% Name Server ID (RFC 5001) */
-               header_only;
+               header_only,
+               ednsneg;
 #ifdef DIG_SIGCHASE
 isc_boolean_t  sigchase;
 #if DIG_SIGCHASE_TD
index ab958de00c901e1a62000552788a58ce6b8dd7e7..310f8211f61632543cfe55d407e5d5f7979a5c06 100644 (file)
@@ -48,7 +48,7 @@ status=`expr $status + $ret`
 n=`expr $n + 1`
 echo "I:Unknown EDNS version ($n)"
 ret=0 reason=
-$DIG -p 5300 @10.53.0.1 +norec +edns=100 soa $zone > dig.out$n
+$DIG -p 5300 @10.53.0.1 +norec +edns=100 +noednsneg soa $zone > dig.out$n
 grep "status: BADVERS," dig.out$n > /dev/null || { ret=1; reason="status"; }
 grep "EDNS: version: 0," dig.out$n > /dev/null || { ret=1; reason="version"; }
 grep "IN.SOA." dig.out$n > /dev/null && { ret=1; reaons="soa"; }
@@ -69,7 +69,7 @@ status=`expr $status + $ret`
 n=`expr $n + 1`
 echo "I:Unknown EDNS version + option ($n)"
 ret=0 reason=
-$DIG -p 5300 @10.53.0.1 +norec +edns=100 +ednsopt=100 soa $zone > dig.out$n
+$DIG -p 5300 @10.53.0.1 +norec +edns=100 +noednsneg +ednsopt=100 soa $zone > dig.out$n
 grep "status: BADVERS," dig.out$n > /dev/null || { ret=1; reason="status"; }
 grep "EDNS: version: 0," dig.out$n > /dev/null || { ret=1; reason="version"; }
 grep "; OPT=100" dig.out$n > /dev/null && { ret=1; reason="option"; }
@@ -91,7 +91,7 @@ status=`expr $status + $ret`
 n=`expr $n + 1`
 echo "I:Unknown EDNS version + flag ($n)"
 ret=0 reason=
-$DIG -p 5300 @10.53.0.1 +norec +edns=100 +ednsflags=0x80 soa $zone > dig.out$n
+$DIG -p 5300 @10.53.0.1 +norec +edns=100 +noednsneg +ednsflags=0x80 soa $zone > dig.out$n
 grep "status: BADVERS," dig.out$n > /dev/null || { ret=1; reason="status"; }
 grep "EDNS: version: 0," dig.out$n > /dev/null || { ret=1; reason="version"; }
 grep "EDNS:.*MBZ" dig.out$n > /dev/null > /dev/null && { ret=1; reason="mbz"; }
@@ -100,5 +100,15 @@ if [ $ret != 0 ]; then echo "I:failed $reason"; fi
 status=`expr $status + $ret`
 n=`expr $n + 1`
 
+echo "I:DiG's EDNS negotiation ($n)"
+ret=0 reason=
+$DIG -p 5300 @10.53.0.1 +norec +edns=100 soa $zone > dig.out$n
+grep "status: NOERROR," dig.out$n > /dev/null || { ret=1; reason="status"; }
+grep "EDNS: version: 0," dig.out$n > /dev/null || { ret=1; reason="version"; }
+grep "IN.SOA." dig.out$n > /dev/null || { ret=1; reason="soa"; }
+if [ $ret != 0 ]; then echo "I:failed $reason"; fi
+status=`expr $status + $ret`
+n=`expr $n + 1`
+
 echo "I:exit status: $status"
 exit $status
index 52480d4e045ccff74a413feb6fa017e8e0995a93..c88756e2f75f72e8edc5b1991af773d7b1f696f6 100644 (file)
           yet-to-be-defined EDNS flags in DNS requests.
        </para>
       </listitem>
+      <listitem>
+       <para>
+         <command>dig +[no]ednsnegotiation</command> can now be used enable /
+         disable EDNS version negotiation.
+       </para>
+      </listitem>
       <listitem>
        <para>
           <command>dig +header-only</command> can now be used to send