From b25262b1df9e7280114165888cd0c0b952186dd1 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Tue, 27 Aug 2019 13:49:15 +1000 Subject: [PATCH] Add support for displaying EDNS option LLQ. (cherry picked from commit d98f446d3fa7230f76966fb4876b14c7bee298c5) --- CHANGES | 2 + bin/dig/dighost.c | 1 + bin/tests/system/digdelv/tests.sh | 8 ++++ lib/dns/include/dns/message.h | 1 + lib/dns/message.c | 63 ++++++++++++++++++++++++++++++- lib/dns/rdata/generic/opt_41.c | 6 +++ 6 files changed, 79 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 305b41e8b7..716d63fa18 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,5 @@ +5280. [protocol] Add support for displaying EDNS option LLQ. [GL #1201] + 5279. [bug] When loading, reject zones containing CDS or CDNSKEY RRsets at the zone apex if they would cause DNSSEC validation failures if published in the parent zone diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index e3ae66e7b7..36ea046d93 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -1399,6 +1399,7 @@ typedef struct dig_ednsoptname { } dig_ednsoptname_t; dig_ednsoptname_t optnames[] = { + { 1, "LLQ" }, /* draft-sekar-dns-llq */ { 3, "NSID" }, /* RFC 5001 */ { 5, "DAU" }, /* RFC 6975 */ { 6, "DHU" }, /* RFC 6975 */ diff --git a/bin/tests/system/digdelv/tests.sh b/bin/tests/system/digdelv/tests.sh index 530c7fe4ba..6c9e7f7d74 100644 --- a/bin/tests/system/digdelv/tests.sh +++ b/bin/tests/system/digdelv/tests.sh @@ -514,6 +514,14 @@ if [ -x "$DIG" ] ; then if [ $ret -ne 0 ]; then echo_i "failed"; fi status=$((status+ret)) + n=$((n+1)) + echo_i "checking ednsopt LLQ prints as expected ($n)" + ret=0 + dig_with_opts @10.53.0.3 +ednsopt=llq:0001000200001234567812345678fefefefe +qr a.example > dig.out.test$n 2>&1 || ret=1 + grep 'LLQ: Version: 1, Opcode: 2, Error: 0, Identifier: 1311768465173141112, Lifetime: 4278124286$' dig.out.test$n > /dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status+ret)) + n=$((n+1)) echo_i "checking that dig warns about .local queries ($n)" ret=0 diff --git a/lib/dns/include/dns/message.h b/lib/dns/include/dns/message.h index 1f793b4809..3542f399ff 100644 --- a/lib/dns/include/dns/message.h +++ b/lib/dns/include/dns/message.h @@ -99,6 +99,7 @@ #define DNS_MESSAGEEXTFLAG_DO 0x8000U /*%< EDNS0 extended OPT codes */ +#define DNS_OPT_LLQ 1 /*%< LLQ opt code */ #define DNS_OPT_NSID 3 /*%< NSID opt code */ #define DNS_OPT_CLIENT_SUBNET 8 /*%< client subnet opt code */ #define DNS_OPT_EXPIRE 9 /*%< EXPIRE opt code */ diff --git a/lib/dns/message.c b/lib/dns/message.c index dd00e60f98..3d7a00cf30 100644 --- a/lib/dns/message.c +++ b/lib/dns/message.c @@ -3435,6 +3435,42 @@ render_ecs(isc_buffer_t *ecsbuf, isc_buffer_t *target) { return (result); } +static isc_result_t +render_llq(isc_buffer_t *optbuf, isc_buffer_t *target) { + char buf[sizeof("18446744073709551615")]; /* 2^64-1 */ + isc_result_t result = ISC_R_SUCCESS; + uint32_t u; + uint64_t q; + + u = isc_buffer_getuint16(optbuf); + ADD_STRING(target, " Version: "); + snprintf(buf, sizeof(buf), "%u", u); + ADD_STRING(target, buf); + + u = isc_buffer_getuint16(optbuf); + ADD_STRING(target, ", Opcode: "); + snprintf(buf, sizeof(buf), "%u", u); + ADD_STRING(target, buf); + + u = isc_buffer_getuint16(optbuf); + ADD_STRING(target, ", Error: "); + snprintf(buf, sizeof(buf), "%u", u); + ADD_STRING(target, buf); + + q = isc_buffer_getuint32(optbuf); + q <<= 32; + q |= isc_buffer_getuint32(optbuf); + ADD_STRING(target, ", Identifier: "); + snprintf(buf, sizeof(buf), "%" PRIu64, q); + ADD_STRING(target, buf); + + u = isc_buffer_getuint32(optbuf); + ADD_STRING(target, ", Lifetime: "); + snprintf(buf, sizeof(buf), "%u", u); + ADD_STRING(target, buf); + cleanup: + return (result); +} static isc_result_t dns_message_pseudosectiontoyaml(dns_message_t *msg, @@ -3521,7 +3557,19 @@ dns_message_pseudosectiontoyaml(dns_message_t *msg, optlen = isc_buffer_getuint16(&optbuf); INSIST(isc_buffer_remaininglength(&optbuf) >= optlen); - if (optcode == DNS_OPT_NSID) { + if (optcode == DNS_OPT_LLQ) { + INDENT(style); + if (optlen == 18U) { + ADD_STRING(target, "LLQ: "); + result = render_llq(&optbuf, target); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + ADD_STRING(target, "\n"); + continue; + } + ADD_STRING(target, "LLQ"); + } else if (optcode == DNS_OPT_NSID) { INDENT(style); ADD_STRING(target, "NSID"); } else if (optcode == DNS_OPT_COOKIE) { @@ -3803,7 +3851,18 @@ dns_message_pseudosectiontotext(dns_message_t *msg, INDENT(style); - if (optcode == DNS_OPT_NSID) { + if (optcode == DNS_OPT_LLQ) { + if (optlen == 18U) { + ADD_STRING(target, "; LLQ:"); + result = render_llq(&optbuf, target); + if (result != ISC_R_SUCCESS) { + return (result); + } + ADD_STRING(target, "\n"); + continue; + } + ADD_STRING(target, "; LLQ"); + } else if (optcode == DNS_OPT_NSID) { ADD_STRING(target, "; NSID"); } else if (optcode == DNS_OPT_COOKIE) { ADD_STRING(target, "; COOKIE"); diff --git a/lib/dns/rdata/generic/opt_41.c b/lib/dns/rdata/generic/opt_41.c index b8b7f53656..0fe7243f64 100644 --- a/lib/dns/rdata/generic/opt_41.c +++ b/lib/dns/rdata/generic/opt_41.c @@ -116,6 +116,12 @@ fromwire_opt(ARGS_FROMWIRE) { return (ISC_R_UNEXPECTEDEND); } switch (opt) { + case DNS_OPT_LLQ: + if (length != 18U) { + return (DNS_R_OPTERR); + } + isc_region_consume(&sregion, length); + break; case DNS_OPT_CLIENT_SUBNET: { uint16_t family; uint8_t addrlen;