#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>
{
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
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");
<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>
#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);
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
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
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)
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);
}
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);