]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
3812. [func] Dig now supports sending arbitary EDNS options from
authorMark Andrews <marka@isc.org>
Thu, 17 Apr 2014 23:52:12 +0000 (09:52 +1000)
committerMark Andrews <marka@isc.org>
Thu, 17 Apr 2014 23:52:12 +0000 (09:52 +1000)
                        the command line (+ednsopt=code[:value]). [RT #35584]

CHANGES
README
bin/dig/dig.c
bin/dig/dig.docbook
bin/dig/dighost.c
bin/dig/include/dig/dig.h

diff --git a/CHANGES b/CHANGES
index f99a130b56b88181f4ad092c2e7c846481905d04..94ea37ccb66a6d2fd944283cb63ae34b934753be 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+3812.  [func]          Dig now supports sending arbitary EDNS options from
+                       the command line (+ednsopt=code[:value]). [RT #35584]
+
 3811.  [func]          "serial-update-method date;" sets serial number
                        on dynamic update to today's date in YYYYMMDDNN
                        format. (Thanks to Bradley Forschinger.) [RT #24903]
diff --git a/README b/README
index aed2f7fd2040eb6c8c55316c1852206236616b38..1bb96e117f12f3ea64c50012efe0803cc1c6ae15 100644 (file)
--- a/README
+++ b/README
@@ -51,6 +51,14 @@ BIND 9
        For up-to-date release notes and errata, see
        http://www.isc.org/software/bind9/releasenotes
 
+BIND 9.11.0
+
+       BIND 9.11.0 includes a number of changes from BIND 9.10 and earlier
+       releases.  New features include:
+
+       - Dig now supports sending of arbitary EDNS options by specifying
+         them on the command line.
+
 BIND 9.10.0
 
        BIND 9.10.0 includes a number of changes from BIND 9.9 and earlier
index 007bcdd76788921c1449c2a34405740935512528..e9a537b5a2c1aa729794c66b3b7096d06c69c968 100644 (file)
@@ -29,8 +29,8 @@
 #include <isc/parseint.h>
 #include <isc/print.h>
 #include <isc/string.h>
-#include <isc/util.h>
 #include <isc/task.h>
+#include <isc/util.h>
 
 #include <dns/byaddr.h>
 #include <dns/fixedname.h>
@@ -755,7 +755,7 @@ plus_option(char *option, isc_boolean_t is_batchfile,
 {
        isc_result_t result;
        char option_store[256];
-       char *cmd, *value, *ptr;
+       char *cmd, *value, *ptr, *code;
        isc_uint32_t num;
        isc_boolean_t state = ISC_TRUE;
 #ifdef DIG_SIGCHASE
@@ -922,19 +922,54 @@ plus_option(char *option, isc_boolean_t is_batchfile,
        case 'e':
                switch (cmd[1]) {
                case 'd':
-                       FULLCHECK("edns");
-                       if (!state) {
-                               lookup->edns = -1;
-                               break;
-                       }
-                       if (value == NULL) {
-                               lookup->edns = 0;
+                       switch(cmd[2]) {
+                       case 'n':
+                               switch (cmd[3]) {
+                               case 's':
+                                       switch (cmd[4]) {
+                                       case 0:
+                                               FULLCHECK("edns");
+                                               if (!state) {
+                                                       lookup->edns = -1;
+                                                       break;
+                                               }
+                                               if (value == NULL) {
+                                                       lookup->edns = 0;
+                                                       break;
+                                               }
+                                               result = parse_uint(&num,
+                                                                   value,
+                                                                   255,
+                                                                   "edns");
+                                               if (result != ISC_R_SUCCESS)
+                                                       fatal("Couldn't parse "
+                                                             "edns");
+                                               lookup->edns = num;
+                                               break;
+                                       case 'o':
+                                               FULLCHECK("ednsopt");
+                                               if (!state) {
+                                                       lookup->ednsoptscnt = 0;
+                                                       break;
+                                               }
+                                               if (value == NULL)
+                                                       fatal("ednsopt no "
+                                                             "code point "
+                                                             "specified");
+                                               code = next_token(&value, ":");
+                                               save_opt(lookup, code, value);
+                                               break;
+                                       default:
+                                               goto invalid_option;
+                                       }
+                                       break;
+                               default:
+                                       goto invalid_option;
+                               }
                                break;
+                       default:
+                               goto invalid_option;
                        }
-                       result = parse_uint(&num, value, 255, "edns");
-                       if (result != ISC_R_SUCCESS)
-                               fatal("Couldn't parse edns");
-                       lookup->edns = num;
                        break;
                case 'x':
                        FULLCHECK("expire");
index 999a5609a47c21a697602a4e55f341e99d9aa7f5..7a4afed6661d5d9296dc6a749271ffdd698c6282 100644 (file)
          <term><option>+edns=#</option></term>
          <listitem>
            <para>
-              Specify the EDNS version to query with.  Valid values
-              are 0 to 255.  Setting the EDNS version will cause
-              a EDNS query to be sent.  <option>+noedns</option>
-              clears the remembered EDNS version.  EDNS is set to
-              0 by default.
+             Specify the EDNS version to query with.  Valid values
+             are 0 to 255.  Setting the EDNS version will cause
+             a EDNS query to be sent.  <option>+noedns</option>
+             clears the remembered EDNS version.  EDNS is set to
+             0 by default.
+           </para>
+         </listitem>
+       </varlistentry>
+
+       <varlistentry>
+         <term><option>+[no]ednsopt[=code[:value]]</option></term>
+         <listitem>
+           <para>
+             Specify EDNS option with code point <option>code</code>
+             and optionally payload of <option>value</value> as a
+             hexadecimal string.  <option>+noednsopt</option>
+             clears the EDNS options to to be sent.
            </para>
          </listitem>
        </varlistentry>
index 3bc81aff45d26769b10029d56303506f78f6a680..cfc796164421a94aa7b4998b64483de9fa355a7c 100644 (file)
@@ -811,6 +811,8 @@ make_empty_lookup(void) {
 #ifdef ISC_PLATFORM_USESIT
        looknew->sitvalue = NULL;
 #endif
+       looknew->ednsopts = NULL;
+       looknew->ednsoptscnt = 0;
        dns_fixedname_init(&looknew->fdomain);
        ISC_LINK_INIT(looknew, link);
        ISC_LIST_INIT(looknew->q);
@@ -863,6 +865,8 @@ clone_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
        looknew->sit = lookold->sit;
        looknew->sitvalue = lookold->sitvalue;
 #endif
+       looknew->ednsopts = lookold->ednsopts;
+       looknew->ednsoptscnt = lookold->ednsoptscnt;
 #ifdef DIG_SIGCHASE
        looknew->sigchase = lookold->sigchase;
 #if DIG_SIGCHASE_TD
@@ -1463,6 +1467,45 @@ setup_libs(void) {
        dns_result_register();
 }
 
+#define EDNSOPTS 100U
+static dns_ednsopt_t ednsopts[EDNSOPTS];
+static unsigned char ednsoptscnt = 0;
+
+void
+save_opt(dig_lookup_t *lookup, char *code, char *value) {
+        isc_uint32_t num;
+        isc_buffer_t b;
+        isc_result_t result;
+
+        if (ednsoptscnt == EDNSOPTS)
+                fatal("too many ednsopts");
+
+        result = parse_uint(&num, code, 65535, "ednsopt");
+       if (result != ISC_R_SUCCESS)
+               fatal("bad edns code point: %s", code);
+
+        ednsopts[ednsoptscnt].code = num;
+        ednsopts[ednsoptscnt].length = 0;
+        ednsopts[ednsoptscnt].value = NULL;
+
+        if (value != NULL) {
+                char *buf;
+                buf = isc_mem_allocate(mctx, strlen(value)/2 + 1);
+                if (buf == NULL)
+                        fatal("out of memory");
+                isc_buffer_init(&b, buf, strlen(value)/2 + 1);
+                result = isc_hex_decodestring(value, &b);
+                check_result(result, "isc_hex_decodestring");
+                ednsopts[ednsoptscnt].value = isc_buffer_base(&b);
+                ednsopts[ednsoptscnt].length = isc_buffer_usedlength(&b);
+        }
+
+        if (lookup->ednsoptscnt == 0)
+                lookup->ednsopts = &ednsopts[ednsoptscnt];
+        lookup->ednsoptscnt++;
+        ednsoptscnt++;
+}
+
 /*%
  * Add EDNS0 option record to a message.  Currently, the only supported
  * options are UDP buffer size, the DO bit, and EDNS options
@@ -2354,7 +2397,7 @@ setup_lookup(dig_lookup_t *lookup) {
        if (lookup->udpsize > 0 || lookup->dnssec ||
            lookup->edns > -1 || lookup->ecs_addr != NULL)
        {
-               dns_ednsopt_t opts[DNS_EDNSOPTIONS];
+               dns_ednsopt_t opts[EDNSOPTS + DNS_EDNSOPTIONS];
                int i = 0;
 
                if (lookup->udpsize == 0)
@@ -2441,6 +2484,12 @@ setup_lookup(dig_lookup_t *lookup) {
                        i++;
                }
 
+               if (lookup->ednsoptscnt != 0) {
+                       memmove(&opts[i], lookup->ednsopts,
+                               sizeof(dns_ednsopt_t) * lookup->ednsoptscnt);
+                       i += lookup->ednsoptscnt;
+               }
+
                add_opt(lookup->sendmsg, lookup->udpsize,
                        lookup->edns, lookup->dnssec, opts, i);
        }
@@ -4143,6 +4192,12 @@ destroy_libs(void) {
        debug("Removing log context");
        isc_log_destroy(&lctx);
 
+       while (ednsoptscnt > 0U) {
+               ednsoptscnt--;
+               if (ednsopts[ednsoptscnt].value != NULL)
+                       isc_mem_free(mctx, ednsopts[ednsoptscnt].value);
+       }
+
        debug("Destroy memory");
        if (memdebugging != 0)
                isc_mem_stats(mctx, stderr);
index 205e6cd2aeb0f6acdef1344192792ce985facab8..e5effffe56ef78c5571ba78686216c0c863f672c 100644 (file)
@@ -192,6 +192,8 @@ isc_boolean_t       sigchase;
 #ifdef ISC_PLATFORM_USESIT
        char *sitvalue;
 #endif
+       dns_ednsopt_t *ednsopts;
+       unsigned int ednsoptscnt;
 };
 
 /*% The dig_query structure */
@@ -427,6 +429,8 @@ void
 chase_sig(dns_message_t *msg);
 #endif
 
+void save_opt(dig_lookup_t *lookup, char *code, char *value);
+
 ISC_LANG_ENDDECLS
 
 #endif