3812. [func] Dig now supports sending arbitary EDNS options from

the command line (+ednsopt=code[:value]). [RT #35584]

(cherry picked from commit e560fbdf77)
This commit is contained in:
Mark Andrews
2014-04-18 09:52:12 +10:00
parent 905d55107b
commit dd696539d3
6 changed files with 128 additions and 14 deletions

View File

@@ -165,6 +165,9 @@
conditions causing SERVFAILs when resolving.
[RT #35538]
3812. [func] Dig now supports sending arbitary EDNS options from
the command line (+ednsopt=code[:value]). [RT #35584]
--- 9.10.2 released ---
--- 9.10.2rc2 released ---

5
README
View File

@@ -51,6 +51,11 @@ BIND 9
For up-to-date release notes and errata, see
http://www.isc.org/software/bind9/releasenotes
BIND 9.10.3
- Dig now supports sending of arbitary EDNS options by specifying
them on the command line.
BIND 9.10.2
BIND 9.10.2 is a maintenance release and addresses bugs

View 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>
@@ -754,7 +754,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;
#if defined(DIG_SIGCHASE) || defined(ISC_PLATFORM_USESIT)
@@ -921,19 +921,54 @@ plus_option(char *option, isc_boolean_t is_batchfile,
case 'e':
switch (cmd[1]) {
case 'd':
FULLCHECK("edns");
if (!state) {
lookup->edns = -1;
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;
}
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 'x':
FULLCHECK("expire");

View File

@@ -646,6 +646,18 @@
</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>
<varlistentry>
<term><option>+[no]expire</option></term>
<listitem>

View File

@@ -834,6 +834,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);
@@ -887,6 +889,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
@@ -1494,6 +1498,45 @@ setup_libs(void) {
check_result(result, "isc_mutex_init");
}
#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
@@ -2398,7 +2441,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)
@@ -2482,6 +2525,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);
}
@@ -4213,6 +4262,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);

View File

@@ -191,6 +191,8 @@ isc_boolean_t sigchase;
#ifdef ISC_PLATFORM_USESIT
char *sitvalue;
#endif
dns_ednsopt_t *ednsopts;
unsigned int ednsoptscnt;
dns_opcode_t opcode;
};
@@ -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