From: Mark Andrews Date: Tue, 19 May 2015 02:46:06 +0000 (+1000) Subject: 4119. [func] Allow dig to set the message opcode. [RT #39550] X-Git-Tag: v9.11.0a1~811 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=c7463967dbcb31c2ec0dd513986a9dec05994a0a;p=thirdparty%2Fbind9.git 4119. [func] Allow dig to set the message opcode. [RT #39550] --- diff --git a/CHANGES b/CHANGES index e6d3c5cf6d2..6a6fc71713f 100644 --- 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. diff --git a/bin/dig/dig.c b/bin/dig/dig.c index fdb95874b2d..6144bfc8881 100644 --- a/bin/dig/dig.c +++ b/bin/dig/dig.c @@ -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]) { diff --git a/bin/dig/dig.docbook b/bin/dig/dig.docbook index b3ec8b490e6..66b21c199bb 100644 --- a/bin/dig/dig.docbook +++ b/bin/dig/dig.docbook @@ -822,6 +822,16 @@ + + + + + Set [restore] the DNS message opcode to the specified + value. The default value is QUERY (0). + + + + diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index c2bb8c4b282..701964dd948 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -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 diff --git a/bin/dig/include/dig/dig.h b/bin/dig/include/dig/dig.h index d08260e5c9d..c464d8fe7ae 100644 --- a/bin/dig/include/dig/dig.h +++ b/bin/dig/include/dig/dig.h @@ -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 */ diff --git a/bin/tests/system/resolver/tests.sh b/bin/tests/system/resolver/tests.sh index cd9f922d753..83987f56eb8 100755 --- a/bin/tests/system/resolver/tests.sh +++ b/bin/tests/system/resolver/tests.sh @@ -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