diff --git a/CHANGES b/CHANGES index 79790b05a9..1bfdce4f41 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,8 @@ +5447. [bug] IPv6 addresses ending in "::" could break YAML + parsing. A "0" is now appended to such addresses + in YAML output from dig, mdig, delv, and dnstap-read. + [GL #1952] + 5446. [bug] The validator could fail to accept a properly signed RRset if an unsupported algorithm appeared earlier in the DNSKEY RRset than a supported algorithm. It could diff --git a/bin/tests/system/digdelv/ns2/example.db.in b/bin/tests/system/digdelv/ns2/example.db.in index 3d4e460ea9..d69a7cb4b2 100644 --- a/bin/tests/system/digdelv/ns2/example.db.in +++ b/bin/tests/system/digdelv/ns2/example.db.in @@ -28,6 +28,8 @@ b A 10.0.0.2 b AAAA fd92:7065:b8e:ffff::2 c A 10.0.0.3 c AAAA fd92:7065:b8e:ffff::3 +d A 10.0.0.0 +d AAAA fd92:7065:b8e:ffff:: xn--caf-dma A 10.1.2.3 diff --git a/bin/tests/system/digdelv/tests.sh b/bin/tests/system/digdelv/tests.sh index 66223bdefc..6930a1c8cc 100644 --- a/bin/tests/system/digdelv/tests.sh +++ b/bin/tests/system/digdelv/tests.sh @@ -907,6 +907,16 @@ if [ -x "$DIG" ] ; then [ "$value" = "ns2.example. IN ANY" ] || ret=1 if [ $ret -ne 0 ]; then echo_i "failed"; fi status=$((status+ret)) + + n=$((n+1)) + echo_i "check dig +yaml output of an IPv6 address ending in zeroes ($n)" + ret=0 + dig_with_opts +qr +yaml @10.53.0.3 aaaa d.example > dig.out.test$n 2>&1 || ret=1 + $PYTHON yamlget.py dig.out.test$n 1 message response_message_data ANSWER_SECTION 0 > yamlget.out.test$n 2>&1 || ret=1 + read -r value < yamlget.out.test$n + [ "$value" = "d.example. 300 IN AAAA fd92:7065:b8e:ffff::0" ] || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status+ret)) fi n=$((n+1)) diff --git a/lib/dns/rdata.c b/lib/dns/rdata.c index 7199ca5891..c8453aae5c 100644 --- a/lib/dns/rdata.c +++ b/lib/dns/rdata.c @@ -151,7 +151,7 @@ static isc_result_t str_totext(const char *source, isc_buffer_t *target); static isc_result_t -inet_totext(int af, isc_region_t *src, isc_buffer_t *target); +inet_totext(int af, uint32_t flags, isc_region_t *src, isc_buffer_t *target); static bool buffer_empty(isc_buffer_t *source); @@ -1754,7 +1754,7 @@ str_totext(const char *source, isc_buffer_t *target) { } static isc_result_t -inet_totext(int af, isc_region_t *src, isc_buffer_t *target) { +inet_totext(int af, uint32_t flags, isc_region_t *src, isc_buffer_t *target) { char tmpbuf[64]; /* Note - inet_ntop doesn't do size checking on its input. */ @@ -1765,6 +1765,22 @@ inet_totext(int af, isc_region_t *src, isc_buffer_t *target) { return (ISC_R_NOSPACE); } isc_buffer_putstr(target, tmpbuf); + + /* + * An IPv6 address ending in "::" breaks YAML + * parsing, so append 0 in that case. + */ + if (af == AF_INET6 && (flags & DNS_STYLEFLAG_YAML) != 0) { + isc_textregion_t tr; + isc_buffer_usedregion(target, (isc_region_t *)&tr); + if (tr.base[tr.length - 1] == ':') { + if (isc_buffer_availablelength(target) == 0) { + return (ISC_R_NOSPACE); + } + isc_buffer_putmem(target, "0", 1); + } + } + return (ISC_R_SUCCESS); } diff --git a/lib/dns/rdata/generic/amtrelay_260.c b/lib/dns/rdata/generic/amtrelay_260.c index e14215d5f7..e65717cb5a 100644 --- a/lib/dns/rdata/generic/amtrelay_260.c +++ b/lib/dns/rdata/generic/amtrelay_260.c @@ -165,10 +165,10 @@ totext_amtrelay(ARGS_TOTEXT) { case 0: break; case 1: - return (inet_totext(AF_INET, ®ion, target)); + return (inet_totext(AF_INET, tctx->flags, ®ion, target)); case 2: - return (inet_totext(AF_INET6, ®ion, target)); + return (inet_totext(AF_INET6, tctx->flags, ®ion, target)); case 3: dns_name_init(&name, NULL); diff --git a/lib/dns/rdata/generic/ipseckey_45.c b/lib/dns/rdata/generic/ipseckey_45.c index dfbec4b716..48cf39b6e8 100644 --- a/lib/dns/rdata/generic/ipseckey_45.c +++ b/lib/dns/rdata/generic/ipseckey_45.c @@ -174,12 +174,12 @@ totext_ipseckey(ARGS_TOTEXT) { break; case 1: - RETERR(inet_totext(AF_INET, ®ion, target)); + RETERR(inet_totext(AF_INET, tctx->flags, ®ion, target)); isc_region_consume(®ion, 4); break; case 2: - RETERR(inet_totext(AF_INET6, ®ion, target)); + RETERR(inet_totext(AF_INET6, tctx->flags, ®ion, target)); isc_region_consume(®ion, 16); break; diff --git a/lib/dns/rdata/generic/l32_105.c b/lib/dns/rdata/generic/l32_105.c index 2cb5007c27..0c15e4c999 100644 --- a/lib/dns/rdata/generic/l32_105.c +++ b/lib/dns/rdata/generic/l32_105.c @@ -73,7 +73,7 @@ totext_l32(ARGS_TOTEXT) { RETERR(str_totext(" ", target)); - return (inet_totext(AF_INET, ®ion, target)); + return (inet_totext(AF_INET, tctx->flags, ®ion, target)); } static inline isc_result_t diff --git a/lib/dns/rdata/hs_4/a_1.c b/lib/dns/rdata/hs_4/a_1.c index 82403a30e3..6a2b76a70e 100644 --- a/lib/dns/rdata/hs_4/a_1.c +++ b/lib/dns/rdata/hs_4/a_1.c @@ -57,7 +57,7 @@ totext_hs_a(ARGS_TOTEXT) { UNUSED(tctx); dns_rdata_toregion(rdata, ®ion); - return (inet_totext(AF_INET, ®ion, target)); + return (inet_totext(AF_INET, tctx->flags, ®ion, target)); } static inline isc_result_t diff --git a/lib/dns/rdata/in_1/a6_38.c b/lib/dns/rdata/in_1/a6_38.c index 5e3b80adba..ac721aad4c 100644 --- a/lib/dns/rdata/in_1/a6_38.c +++ b/lib/dns/rdata/in_1/a6_38.c @@ -126,7 +126,7 @@ totext_in_a6(ARGS_TOTEXT) { addr[octets] &= mask; ar.base = addr; ar.length = sizeof(addr); - RETERR(inet_totext(AF_INET6, &ar, target)); + RETERR(inet_totext(AF_INET6, tctx->flags, &ar, target)); isc_region_consume(&sr, 16 - octets); } diff --git a/lib/dns/rdata/in_1/a_1.c b/lib/dns/rdata/in_1/a_1.c index bc34aeeba9..276e03c237 100644 --- a/lib/dns/rdata/in_1/a_1.c +++ b/lib/dns/rdata/in_1/a_1.c @@ -59,7 +59,7 @@ totext_in_a(ARGS_TOTEXT) { UNUSED(tctx); dns_rdata_toregion(rdata, ®ion); - return (inet_totext(AF_INET, ®ion, target)); + return (inet_totext(AF_INET, tctx->flags, ®ion, target)); } static inline isc_result_t diff --git a/lib/dns/rdata/in_1/aaaa_28.c b/lib/dns/rdata/in_1/aaaa_28.c index 9ac9c40e05..7b33dd0807 100644 --- a/lib/dns/rdata/in_1/aaaa_28.c +++ b/lib/dns/rdata/in_1/aaaa_28.c @@ -75,7 +75,7 @@ totext_in_aaaa(ARGS_TOTEXT) { return (str_totext(buf, target)); } dns_rdata_toregion(rdata, ®ion); - return (inet_totext(AF_INET6, ®ion, target)); + return (inet_totext(AF_INET6, tctx->flags, ®ion, target)); } static inline isc_result_t diff --git a/lib/dns/rdata/in_1/apl_42.c b/lib/dns/rdata/in_1/apl_42.c index 0b0c48620e..dde742ca07 100644 --- a/lib/dns/rdata/in_1/apl_42.c +++ b/lib/dns/rdata/in_1/apl_42.c @@ -154,7 +154,7 @@ totext_in_apl(ARGS_TOTEXT) { INSIST(prefix <= 32); memset(buf, 0, sizeof(buf)); memmove(buf, sr.base, len); - RETERR(inet_totext(AF_INET, &ir, target)); + RETERR(inet_totext(AF_INET, tctx->flags, &ir, target)); break; case 2: @@ -162,7 +162,7 @@ totext_in_apl(ARGS_TOTEXT) { INSIST(prefix <= 128); memset(buf, 0, sizeof(buf)); memmove(buf, sr.base, len); - RETERR(inet_totext(AF_INET6, &ir, target)); + RETERR(inet_totext(AF_INET6, tctx->flags, &ir, target)); break; default: diff --git a/lib/dns/rdata/in_1/wks_11.c b/lib/dns/rdata/in_1/wks_11.c index 942290362d..26eda5d7f6 100644 --- a/lib/dns/rdata/in_1/wks_11.c +++ b/lib/dns/rdata/in_1/wks_11.c @@ -218,7 +218,7 @@ totext_in_wks(ARGS_TOTEXT) { REQUIRE(rdata->length >= 5); dns_rdata_toregion(rdata, &sr); - RETERR(inet_totext(AF_INET, &sr, target)); + RETERR(inet_totext(AF_INET, tctx->flags, &sr, target)); isc_region_consume(&sr, 4); proto = uint8_fromregion(&sr);