]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
4119. [func] Allow dig to set the message opcode. [RT #39550]
authorMark Andrews <marka@isc.org>
Tue, 19 May 2015 02:46:06 +0000 (12:46 +1000)
committerMark Andrews <marka@isc.org>
Tue, 19 May 2015 02:46:06 +0000 (12:46 +1000)
CHANGES
bin/dig/dig.c
bin/dig/dig.docbook
bin/dig/dighost.c
bin/dig/include/dig/dig.h
bin/tests/system/resolver/tests.sh

diff --git a/CHANGES b/CHANGES
index e6d3c5cf6d220fc47421889872da3bb2f19c92fd..6a6fc71713fb733a6e080e68a6d05ae133159bc9 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,5 @@
+4119.  [func]          Allow dig to set the message opcode. [RT #39550]
+
 4118.  [bug]           Teach isc-config.sh about irs. [RT #39213]
 
 4117.  [protocol]      Add EMPTY.AS112.ARPA as per RFC 7534.
index fdb95874b2d00c7305004682acf1e329b3a1a0a4..6144bfc8881f805388e4bed0347cd8260c92d795 100644 (file)
@@ -248,6 +248,7 @@ help(void) {
 "                 +[no]onesoa         (AXFR prints only one soa record)\n"
 "                 +[no]keepopen       (Keep the TCP socket open between queries)\n"
 "                 +[no]dscp[=###]     (Set the DSCP value to ### [0..63])\n"
+"                 +[no]opcode[###]    (Set the opcode of the request)\n"
 "        global d-opts and servers (before host name) affect all queries.\n"
 "        local d-opts and servers (after host name) affect only that lookup.\n"
 "        -h                           (print help and exit)\n"
@@ -1099,8 +1100,37 @@ plus_option(char *option, isc_boolean_t is_batchfile,
                }
                break;
        case 'o':
-               FULLCHECK("onesoa");
-               onesoa = state;
+               switch (cmd[1]) {
+               case 'n':
+                       FULLCHECK("onesoa");
+                       onesoa = state;
+                       break;
+               case 'p':
+                       FULLCHECK("opcode");
+                       if (!state) {
+                               lookup->opcode = 0;     /* default - query */
+                               break;
+                       }
+                       if (value == NULL)
+                               goto need_value;
+                       for (num = 0;
+                            num < sizeof(opcodetext)/sizeof(opcodetext[0]);
+                            num++) {
+                               if (strcasecmp(opcodetext[num], value) == 0)
+                                       break;
+                       }
+                       if (num < 16) {
+                               lookup->opcode = (dns_opcode_t)num;
+                               break;
+                       }
+                       result = parse_uint(&num, value, 15, "opcode");
+                       if (result != ISC_R_SUCCESS)
+                               fatal("Couldn't parse opcode");
+                       lookup->opcode = (dns_opcode_t)num;
+                       break;
+               default:
+                       goto invalid_option;
+               }
                break;
        case 'q':
                switch (cmd[1]) {
index b3ec8b490e6222164e52a6c4c41292aad2eeee0e..66b21c199bbb0a1891ad26c751aca5ffcc937bb9 100644 (file)
          </listitem>
        </varlistentry>
 
+       <varlistentry>
+         <term><option>+[no]opcode=value</option></term>
+         <listitem>
+           <para>
+             Set [restore] the DNS message opcode to the specified
+             value.  The default value is QUERY (0).
+           </para>
+         </listitem>
+       </varlistentry>
+
        <varlistentry>
          <term><option>+[no]qr</option></term>
          <listitem>
index c2bb8c4b2825b24e1416e4edd803dced633b114b..701964dd9486428272e6e33b573ee8fce0565db4 100644 (file)
@@ -788,6 +788,7 @@ make_empty_lookup(void) {
        looknew->besteffort = ISC_TRUE;
        looknew->dnssec = ISC_FALSE;
        looknew->ednsflags = 0;
+       looknew->opcode = dns_opcode_query;
        looknew->expire = ISC_FALSE;
        looknew->nsid = ISC_FALSE;
        looknew->header_only = ISC_FALSE;
@@ -886,6 +887,7 @@ clone_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
        looknew->besteffort = lookold->besteffort;
        looknew->dnssec = lookold->dnssec;
        looknew->ednsflags = lookold->ednsflags;
+       looknew->opcode = lookold->opcode;
        looknew->expire = lookold->expire;
        looknew->nsid = lookold->nsid;
        looknew->header_only = lookold->header_only;
@@ -2387,7 +2389,7 @@ setup_lookup(dig_lookup_t *lookup) {
 
        isc_random_get(&id);
        lookup->sendmsg->id = (unsigned short)id & 0xFFFF;
-       lookup->sendmsg->opcode = dns_opcode_query;
+       lookup->sendmsg->opcode = lookup->opcode;
        lookup->msgcounter = 0;
        /*
         * If this is a trace request, completely disallow recursion, since
index d08260e5c9d43271f22d5f1a381ca5174a0b951a..c464d8fe7ae26332dd76b830a1891d757dc433db 100644 (file)
@@ -198,6 +198,7 @@ isc_boolean_t       sigchase;
        unsigned int ednsoptscnt;
        isc_dscp_t dscp;
        unsigned int ednsflags;
+       dns_opcode_t opcode;
 };
 
 /*% The dig_query structure */
index cd9f922d753531d4e784dd0e8e347d740655b0a8..83987f56eb8c80d92fde3f35570337001c19c775 100755 (executable)
@@ -536,5 +536,12 @@ grep "skipping nameserver 'cname.tld' because it is a CNAME, while resolving 'al
 if [ $ret != 0 ]; then echo "I:failed"; fi
 status=`expr $status + $ret`
 
+n=`expr $n + 1`
+echo "I:check that unexpected opcodes are handled correctly (${n})"
+ret=0
+$DIG soa all-cnames @10.53.0.5 -p 5300 +opcode=status > dig.out.ns5.test${n} || ret=1
+grep "status: NOTIMP" dig.out.ns5.test${n} > /dev/null || ret=1
+status=`expr $status + $ret`
+
 echo "I:exit status: $status"
 exit $status