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, 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" 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..99be9ad03a 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); @@ -693,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: @@ -747,7 +750,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)); 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"),