diff --git a/CHANGES b/CHANGES index f0c8702fac..a104487997 100644 --- a/CHANGES +++ b/CHANGES @@ -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 --- diff --git a/README b/README index 81f205ce43..7a695d6e6d 100644 --- a/README +++ b/README @@ -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 diff --git a/bin/dig/dig.c b/bin/dig/dig.c index 070eba7d39..460571e516 100644 --- a/bin/dig/dig.c +++ b/bin/dig/dig.c @@ -29,8 +29,8 @@ #include #include #include -#include #include +#include #include #include @@ -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"); diff --git a/bin/dig/dig.docbook b/bin/dig/dig.docbook index 049dd7adfb..9e0e7879cc 100644 --- a/bin/dig/dig.docbook +++ b/bin/dig/dig.docbook @@ -646,6 +646,18 @@ + + + + + Specify EDNS option with code point + clears the EDNS options to to be sent. + + + + diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index eb91532362..27b01a84d8 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -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); diff --git a/bin/dig/include/dig/dig.h b/bin/dig/include/dig/dig.h index ccd15e5fed..237eb915b6 100644 --- a/bin/dig/include/dig/dig.h +++ b/bin/dig/include/dig/dig.h @@ -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