From c6e369547860a1dd8e4fd1af53bab182270aa90a Mon Sep 17 00:00:00 2001 From: Aram Sargsyan Date: Mon, 10 Feb 2025 13:11:18 +0000 Subject: [PATCH 1/5] Use named Service Parameter Keys (SvcParamKeys) by default When converting SVCB records to text representation use named SvcParamKeys values unless backward-compatible mode is activated, in which case the values which were not defined initially in RFC9460 and were added later (see [1]) are converted to opaque "keyN" syntax, like, for example, "key7" instead of "dohpath". [1] https://www.iana.org/assignments/dns-svcb/dns-svcb.xhtml Co-authored-by: sdomi --- lib/dns/include/dns/rdata.h | 3 +++ lib/dns/rdata/in_1/svcb_64.c | 13 ++++++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/dns/include/dns/rdata.h b/lib/dns/include/dns/rdata.h index 2123bbc927..ac255b2028 100644 --- a/lib/dns/include/dns/rdata.h +++ b/lib/dns/include/dns/rdata.h @@ -173,6 +173,9 @@ struct dns_rdata { /*% Print AAAA record fully expanded */ #define DNS_STYLEFLAG_EXPANDAAAA 0x00000020ULL +/*% Print non-initial Service Parameter Keys in backward-compatible format */ +#define DNS_STYLEFLAG_SVCPARAMKEYCOMPAT 0x00000040ULL + #define DNS_RDATA_DOWNCASE DNS_NAME_DOWNCASE #define DNS_RDATA_CHECKNAMES DNS_NAME_CHECKNAMES #define DNS_RDATA_CHECKNAMESFAIL DNS_NAME_CHECKNAMESFAIL diff --git a/lib/dns/rdata/in_1/svcb_64.c b/lib/dns/rdata/in_1/svcb_64.c index 8764617688..b5c431c70b 100644 --- a/lib/dns/rdata/in_1/svcb_64.c +++ b/lib/dns/rdata/in_1/svcb_64.c @@ -377,12 +377,12 @@ svc_fromtext(isc_textregion_t *region, isc_buffer_t *target) { static const char * svcparamkey(unsigned short value, enum encoding *encoding, char *buf, - size_t len) { + size_t len, bool compat) { size_t i; int n; for (i = 0; i < ARRAY_SIZE(sbpr); i++) { - if (sbpr[i].value == value && sbpr[i].initial) { + if (sbpr[i].value == value && (sbpr[i].initial || !compat)) { *encoding = sbpr[i].encoding; return sbpr[i].name; } @@ -639,6 +639,7 @@ generic_totext_in_svcb(ARGS_TOTEXT) { char buf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")]; unsigned short num; int n; + bool compat = (tctx->flags & DNS_STYLEFLAG_SVCPARAMKEYCOMPAT) != 0; REQUIRE(rdata->length != 0); @@ -674,8 +675,9 @@ generic_totext_in_svcb(ARGS_TOTEXT) { INSIST(region.length >= 2); num = uint16_fromregion(®ion); isc_region_consume(®ion, 2); - RETERR(str_totext(svcparamkey(num, &encoding, buf, sizeof(buf)), - target)); + RETERR(str_totext( + svcparamkey(num, &encoding, buf, sizeof(buf), compat), + target)); INSIST(region.length >= 2); num = uint16_fromregion(®ion); @@ -747,7 +749,8 @@ generic_totext_in_svcb(ARGS_TOTEXT) { num = uint16_fromregion(&r); isc_region_consume(&r, 2); RETERR(str_totext(svcparamkey(num, &encoding, - buf, sizeof(buf)), + buf, sizeof(buf), + compat), target)); if (r.length != 0) { RETERR(str_totext(",", target)); From d5d63d62533c75553daaf533da369f0a2ec11163 Mon Sep 17 00:00:00 2001 From: Aram Sargsyan Date: Mon, 10 Feb 2025 13:15:12 +0000 Subject: [PATCH 2/5] Fix a bug in generic_totext_in_svcb() The 'sbpr_dohpath' case was missing from the switch-case. Add the 'sbpr_dohpath' case, which should work similarly as the 'sbpr_text' case. --- lib/dns/rdata/in_1/svcb_64.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/dns/rdata/in_1/svcb_64.c b/lib/dns/rdata/in_1/svcb_64.c index b5c431c70b..99be9ad03a 100644 --- a/lib/dns/rdata/in_1/svcb_64.c +++ b/lib/dns/rdata/in_1/svcb_64.c @@ -695,6 +695,7 @@ generic_totext_in_svcb(ARGS_TOTEXT) { } switch (encoding) { case sbpr_text: + case sbpr_dohpath: RETERR(multitxt_totext(&r, target)); break; case sbpr_port: From 583a838c2553b4ea52b26430d682b551d8a303c1 Mon Sep 17 00:00:00 2001 From: Aram Sargsyan Date: Mon, 10 Feb 2025 13:22:58 +0000 Subject: [PATCH 3/5] Implement dig +[no]svcparamkeycompat The new +[no]svcparamkeycompat option for dig enables the backward-compatible mode for the Service Parameter Keys' (SvcParamKeys) representation format. See the previous commit for more information. --- bin/dig/dig.c | 12 ++++++++++++ bin/dig/dig.rst | 8 ++++++++ bin/dig/dighost.c | 1 + bin/dig/dighost.h | 5 ++--- 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/bin/dig/dig.c b/bin/dig/dig.c index f6783deb48..67056ec490 100644 --- a/bin/dig/dig.c +++ b/bin/dig/dig.c @@ -303,6 +303,8 @@ help(void) { "statistics)\n" " +subnet=addr (Set edns-client-subnet " "option)\n" + " +[no]svcparamkeycompat (Display backward-" + "compatible SvcParamKey names (keyN) for non-initial entries)\n" " +[no]tcflag (Set TC flag in query " "(+[no]tcflag))\n" " +[no]tcp (TCP mode (+[no]vc))\n" @@ -502,6 +504,9 @@ say_message(dns_rdata_t *rdata, dig_query_t *query, isc_buffer_t *buf) { if (query->lookup->expandaaaa) { styleflags |= DNS_STYLEFLAG_EXPANDAAAA; } + if (query->lookup->svcparamkeycompat) { + styleflags |= DNS_STYLEFLAG_SVCPARAMKEYCOMPAT; + } result = dns_rdata_tofmttext(rdata, NULL, styleflags, 0, splitwidth, " ", buf); if (result == ISC_R_NOSPACE) { @@ -695,6 +700,9 @@ printmessage(dig_query_t *query, const isc_buffer_t *msgbuf, dns_message_t *msg, if (query->lookup->expandaaaa) { styleflags |= DNS_STYLEFLAG_EXPANDAAAA; } + if (query->lookup->svcparamkeycompat) { + styleflags |= DNS_STYLEFLAG_SVCPARAMKEYCOMPAT; + } if (query->lookup->multiline) { styleflags |= DNS_STYLEFLAG_OMIT_OWNER; styleflags |= DNS_STYLEFLAG_OMIT_CLASS; @@ -2394,6 +2402,10 @@ plus_option(char *option, bool is_batchfile, bool *need_clone, goto exit_or_usage; } break; + case 'v': /* svcparamkeycompat */ + FULLCHECK("svcparamkeycompat"); + lookup->svcparamkeycompat = state; + break; default: goto invalid_option; } diff --git a/bin/dig/dig.rst b/bin/dig/dig.rst index 90c4a8dc96..fa436fefac 100644 --- a/bin/dig/dig.rst +++ b/bin/dig/dig.rst @@ -642,6 +642,14 @@ abbreviation is unambiguous; for example, :option:`+cd` is equivalent to prefix-length of zero, which signals a resolver that the client's address information must *not* be used when resolving this query. +.. option:: +svcparamkeycompat, +nosvcparamkeycompat + + This option sets [or does not set] the backward-compatible representation of + the Service Parameter Keys (SvcParamKeys) for SVCB records, in which case + the keys, which were not defined initially in :rfc:`9460` are represented + in their opaque "keyN"-like format, where "N" is their numerical value. The + default is ``+nosvcparamkeycompat``. + .. option:: +tcflag, +notcflag This option sets [or does not set] the TC (TrunCation) bit in the query. The default is diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index b491ebb27a..8c25504782 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -758,6 +758,7 @@ clone_lookup(dig_lookup_t *lookold, bool servers) { looknew->nocrypto = lookold->nocrypto; looknew->ttlunits = lookold->ttlunits; looknew->expandaaaa = lookold->expandaaaa; + looknew->svcparamkeycompat = lookold->svcparamkeycompat; looknew->qr = lookold->qr; looknew->idnin = lookold->idnin; looknew->idnout = lookold->idnout; diff --git a/bin/dig/dighost.h b/bin/dig/dighost.h index 81ce6b609d..1c5c7ddf94 100644 --- a/bin/dig/dighost.h +++ b/bin/dig/dighost.h @@ -104,9 +104,8 @@ struct dig_lookup { isc_refcount_t references; bool aaonly, adflag, badcookie, besteffort, cdflag, cleared, comments, dns64prefix, dnssec, doing_xfr, done_as_is, ednsneg, expandaaaa, - expire, fuzzing, header_only, identify, /*%< Append an "on - server " message - */ + svcparamkeycompat, expire, fuzzing, header_only, + identify, /*%< Append an "on server " message */ identify_previous_line, /*% Prepend a "Nameserver :" message, with newline and tab */ idnin, idnout, ignore, multiline, need_search, new_search, From 3482d7e694a91f530f9a6b19e96e48568dd0e878 Mon Sep 17 00:00:00 2001 From: Aram Sargsyan Date: Mon, 10 Feb 2025 13:25:57 +0000 Subject: [PATCH 4/5] Test dig +svcparamkeycompat This check in the nsupdate system test expects the opaque representation of the "dohpath" Service Parameter Key. Use the +svcparamkeycompat dig option to enable it. --- bin/tests/system/nsupdate/tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/tests/system/nsupdate/tests.sh b/bin/tests/system/nsupdate/tests.sh index 2995bb5b69..c6752ed75c 100755 --- a/bin/tests/system/nsupdate/tests.sh +++ b/bin/tests/system/nsupdate/tests.sh @@ -2366,7 +2366,7 @@ check-svcb no update add _dns.ns.relaxed 0 in SVCB 1 ns.relaxed dohpath=/{?dns} send END -$DIG $DIGOPTS +tcp @10.53.0.3 _dns.ns.relaxed SVCB >dig.out.ns3.test$n || ret=1 +$DIG $DIGOPTS +tcp +svcparamkeycompat @10.53.0.3 _dns.ns.relaxed SVCB >dig.out.ns3.test$n || ret=1 grep '1 ns.relaxed. key7="/{?dns}"' dig.out.ns3.test$n >/dev/null || ret=1 [ $ret = 0 ] || { echo_i "failed" From 9d441c93d042a1d2e9ce9a0b8b47f8d578af111d Mon Sep 17 00:00:00 2001 From: Aram Sargsyan Date: Mon, 10 Feb 2025 13:27:44 +0000 Subject: [PATCH 5/5] Update the rdata unit test Update the rdata unit test to accommodate the change in the default represenation of the Service Parameter Keys (SvcParamKeys) for the SVCB records. --- tests/dns/rdata_test.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/tests/dns/rdata_test.c b/tests/dns/rdata_test.c index bed419a20e..85ed8056ed 100644 --- a/tests/dns/rdata_test.c +++ b/tests/dns/rdata_test.c @@ -2698,31 +2698,32 @@ ISC_RUN_TEST_IMPL(https_svcb) { "key123=abc)"), /* dohpath tests */ TEXT_VALID_LOOPCHG(1, "1 example.net. dohpath=/{dns}", - "1 example.net. key7=\"/{dns}\""), + "1 example.net. dohpath=\"/{dns}\""), TEXT_VALID_LOOPCHG(1, "1 example.net. dohpath=/{+dns}", - "1 example.net. key7=\"/{+dns}\""), + "1 example.net. dohpath=\"/{+dns}\""), TEXT_VALID_LOOPCHG(1, "1 example.net. dohpath=/{#dns}", - "1 example.net. key7=\"/{#dns}\""), + "1 example.net. dohpath=\"/{#dns}\""), TEXT_VALID_LOOPCHG(1, "1 example.net. dohpath=/{.dns}", - "1 example.net. key7=\"/{.dns}\""), - TEXT_VALID_LOOPCHG(1, "1 example.net. dohpath=\"/{;dns}\"", - "1 example.net. key7=\"/{;dns}\""), + "1 example.net. dohpath=\"/{.dns}\""), + TEXT_VALID_LOOP(1, "1 example.net. dohpath=\"/{;dns}\""), TEXT_VALID_LOOPCHG(1, "1 example.net. dohpath=/{?dns}", - "1 example.net. key7=\"/{?dns}\""), + "1 example.net. dohpath=\"/{?dns}\""), TEXT_VALID_LOOPCHG(1, "1 example.net. dohpath=/some/path{?dns}", - "1 example.net. key7=\"/some/path{?dns}\""), + "1 example.net. " + "dohpath=\"/some/path{?dns}\""), TEXT_VALID_LOOPCHG(1, "1 example.net. dohpath=/{dns:9999}", - "1 example.net. key7=\"/{dns:9999}\""), + "1 example.net. dohpath=\"/{dns:9999}\""), TEXT_VALID_LOOPCHG(1, "1 example.net. dohpath=/{dns*}", - "1 example.net. key7=\"/{dns*}\""), + "1 example.net. dohpath=\"/{dns*}\""), TEXT_VALID_LOOPCHG( 1, "1 example.net. dohpath=/some/path?key=value{&dns}", - "1 example.net. key7=\"/some/path?key=value{&dns}\""), + "1 example.net. " + "dohpath=\"/some/path?key=value{&dns}\""), TEXT_VALID_LOOPCHG(1, "1 example.net. " "dohpath=/some/path?key=value{&dns,x*}", "1 example.net. " - "key7=\"/some/path?key=value{&dns,x*}\""), + "dohpath=\"/some/path?key=value{&dns,x*}\""), TEXT_INVALID("1 example.com. dohpath=not-relative"), TEXT_INVALID("1 example.com. dohpath=/{?no_dns_variable}"), TEXT_INVALID("1 example.com. dohpath=/novariable"),