From 08f01297320b7ad55d0abff0aca9a577196079e2 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Mon, 29 Jun 2015 18:33:18 +0530 Subject: [PATCH] Fix a bug printing zone names with '/' character in XML and JSON stats (#39873) --- CHANGES | 3 ++ bin/named/statschannel.c | 15 +++---- bin/tests/system/conf.sh.in | 6 +++ bin/tests/system/statistics/clean.sh | 1 + bin/tests/system/statistics/ns1/named.conf | 9 ++++ bin/tests/system/statistics/ns1/zone.db | 17 ++++++++ bin/tests/system/statistics/tests.sh | 14 +++++++ configure | 48 ++++++++++++++++++++++ configure.in | 7 ++++ lib/dns/include/dns/zone.h | 10 +++++ lib/dns/win32/libdns.def.in | 1 + lib/dns/zone.c | 7 ++++ 12 files changed, 128 insertions(+), 10 deletions(-) create mode 100644 bin/tests/system/statistics/ns1/zone.db diff --git a/CHANGES b/CHANGES index 46d8df4d30..0ab5a34137 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +4148. [bug] Fix a bug when printing zone names with '/' character + in XML and JSON statistics output. [RT #39873] + 4147. [bug] Filter-aaaa / filter-aaaa-on-v4 / filter-aaaa-on-v6 was returning referrals rather than nodata responses when the AAAA records were filtered. [RT #39843] diff --git a/bin/named/statschannel.c b/bin/named/statschannel.c index 68ae98bbd0..ccbc1b1d12 100644 --- a/bin/named/statschannel.c +++ b/bin/named/statschannel.c @@ -915,7 +915,6 @@ static isc_result_t zone_xmlrender(dns_zone_t *zone, void *arg) { isc_result_t result; char buf[1024 + 32]; /* sufficiently large for zone name and class */ - char *zone_name_only = NULL; dns_rdataclass_t rdclass; isc_uint32_t serial; xmlTextWriterPtr writer = arg; @@ -934,13 +933,11 @@ zone_xmlrender(dns_zone_t *zone, void *arg) { dumparg.arg = writer; TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "zone")); - dns_zone_name(zone, buf, sizeof(buf)); - zone_name_only = strtok(buf, "/"); - if(zone_name_only == NULL) - zone_name_only = buf; + dns_zone_nameonly(zone, buf, sizeof(buf)); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "name", - ISC_XMLCHAR zone_name_only)); + ISC_XMLCHAR buf)); + rdclass = dns_zone_getclass(zone); dns_rdataclass_format(rdclass, buf, sizeof(buf)); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "rdataclass", @@ -1475,10 +1472,8 @@ zone_jsonrender(dns_zone_t *zone, void *arg) { if (statlevel == dns_zonestat_none) return (ISC_R_SUCCESS); - dns_zone_name(zone, buf, sizeof(buf)); - zone_name_only = strtok(buf, "/"); - if(zone_name_only == NULL) - zone_name_only = buf; + dns_zone_nameonly(zone, buf, sizeof(buf)); + zone_name_only = buf; rdclass = dns_zone_getclass(zone); dns_rdataclass_format(rdclass, class, sizeof(class)); diff --git a/bin/tests/system/conf.sh.in b/bin/tests/system/conf.sh.in index 98116b59e7..cf07d0cb3e 100644 --- a/bin/tests/system/conf.sh.in +++ b/bin/tests/system/conf.sh.in @@ -81,6 +81,12 @@ SUBDIRS="acl additional allow_query addzone autosign builtin # Use the CONFIG_SHELL detected by configure for tests SHELL=@SHELL@ +# CURL will be empty if no program was found by configure +CURL=@CURL@ + +# XMLLINT will be empty if no program was found by configure +XMLLINT=@XMLLINT@ + # PERL will be an empty string if no perl interpreter was found. PERL=@PERL@ if test -n "$PERL" diff --git a/bin/tests/system/statistics/clean.sh b/bin/tests/system/statistics/clean.sh index 87a329cee6..4d68e09f75 100644 --- a/bin/tests/system/statistics/clean.sh +++ b/bin/tests/system/statistics/clean.sh @@ -26,4 +26,5 @@ rm -f */named.memstats rm -f */named.run rm -f */named.stats rm -f dig.out* +rm -f curl.out.* rm -f ns*/named.lock diff --git a/bin/tests/system/statistics/ns1/named.conf b/bin/tests/system/statistics/ns1/named.conf index f95ff98b1b..be9629446d 100644 --- a/bin/tests/system/statistics/ns1/named.conf +++ b/bin/tests/system/statistics/ns1/named.conf @@ -30,6 +30,10 @@ options { notify yes; }; +statistics-channels { + inet 10.53.0.1 port 8053 allow { any; }; +}; + zone "." { type master; file "root.db"; @@ -39,3 +43,8 @@ zone "example.info." { type master; file "example-info.db"; }; + +zone "32/1.0.0.127-in-addr.example." { + type master; + file "zone.db"; +}; diff --git a/bin/tests/system/statistics/ns1/zone.db b/bin/tests/system/statistics/ns1/zone.db new file mode 100644 index 0000000000..0dbc615f8f --- /dev/null +++ b/bin/tests/system/statistics/ns1/zone.db @@ -0,0 +1,17 @@ +; Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC") +; +; Permission to use, copy, modify, and/or distribute this software for any +; purpose with or without fee is hereby granted, provided that the above +; copyright notice and this permission notice appear in all copies. +; +; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +; AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +; PERFORMANCE OF THIS SOFTWARE. + +@ 3600 IN SOA ns.example. hostmaster.example. 1 3600 1200 604800 3600 +@ 3600 IN NS ns.example. +ns.example. 3600 IN A 10.53.0.1 diff --git a/bin/tests/system/statistics/tests.sh b/bin/tests/system/statistics/tests.sh index 2a2642b40b..c783cb5727 100644 --- a/bin/tests/system/statistics/tests.sh +++ b/bin/tests/system/statistics/tests.sh @@ -24,6 +24,8 @@ DIGCMD="$DIG $DIGOPTS -p 5300" RNDCCMD="$RNDC -p 9953 -c ../common/rndc.conf" status=0 +t=0 + ret=0 echo "I:fetching a.example from ns2's initial configuration" $DIGCMD +noauth a.example. @10.53.0.2 any > dig.out.ns2.1 || ret=1 @@ -102,5 +104,17 @@ grep "bucket size" ns3/named.stats > /dev/null || ret=1 if [ $ret != 0 ]; then echo "I: failed"; fi status=`expr $status + $ret` +ret=0 +t=`expr $t + 1` +echo "I:checking that zones with slash are properly shown in XML output (${t})" +if [ -x ${CURL} -a -x ${XMLLINT} ] ; then + ${CURL} http://10.53.0.1:8053/xml/v3/zones > curl.out.${t} 2>/dev/null || ret=1 + ${XMLLINT} --xpath '//statistics/views/view/zones/zone[@name="32/1.0.0.127-in-addr.example"]' curl.out.${t} > /dev/null 2>&1 || ret=1 +else + echo "I:skipping test as curl and/or xmllint were not found" +fi +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + echo "I:exit status: $status" exit $status diff --git a/configure b/configure index 75cf58444d..2e43a91b6c 100755 --- a/configure +++ b/configure @@ -696,6 +696,7 @@ XSLT_DOCBOOK_CHUNK_HTML XSLT_DOCBOOK_STYLE_MAN XSLT_DOCBOOK_STYLE_XHTML XSLT_DOCBOOK_STYLE_HTML +CURL DOXYGEN XMLLINT XSLTPROC @@ -20193,6 +20194,53 @@ fi +# +# Look for curl +# + +# Extract the first word of "curl", so it can be a program name with args. +set dummy curl; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_CURL+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $CURL in + [\\/]* | ?:[\\/]*) + ac_cv_path_CURL="$CURL" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_CURL="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_CURL" && ac_cv_path_CURL="curl" + ;; +esac +fi +CURL=$ac_cv_path_CURL +if test -n "$CURL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CURL" >&5 +$as_echo "$CURL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + # # Subroutine for searching for an ordinary file (e.g., a stylesheet) # in a number of directories: diff --git a/configure.in b/configure.in index f6393ab39e..afe0708b54 100644 --- a/configure.in +++ b/configure.in @@ -3980,6 +3980,13 @@ AC_SUBST(XMLLINT) AC_PATH_PROG(DOXYGEN, doxygen, doxygen) AC_SUBST(DOXYGEN) +# +# Look for curl +# + +AC_PATH_PROG(CURL, curl, curl) +AC_SUBST(CURL) + # # Subroutine for searching for an ordinary file (e.g., a stylesheet) # in a number of directories: diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h index 6eec0f9a1b..a5f3cde275 100644 --- a/lib/dns/include/dns/zone.h +++ b/lib/dns/include/dns/zone.h @@ -1981,6 +1981,16 @@ dns_zone_name(dns_zone_t *zone, char *buf, size_t len); *\li 'buf' to be non NULL. */ +void +dns_zone_nameonly(dns_zone_t *zone, char *buf, size_t len); +/*%< + * Return the name of the zone only. + * + * Requires: + *\li 'zone' to be valid. + *\li 'buf' to be non NULL. + */ + isc_result_t dns_zone_checknames(dns_zone_t *zone, dns_name_t *name, dns_rdata_t *rdata); /*%< diff --git a/lib/dns/win32/libdns.def.in b/lib/dns/win32/libdns.def.in index 596c5d4d27..f110e54f0d 100644 --- a/lib/dns/win32/libdns.def.in +++ b/lib/dns/win32/libdns.def.in @@ -1155,6 +1155,7 @@ dns_zone_mkey_hour dns_zone_mkey_day dns_zone_mkey_month dns_zone_name +dns_zone_nameonly dns_zone_next dns_zone_notify dns_zone_notifyreceive diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 7cb3cfcb7a..0a2d5a2774 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -13141,6 +13141,13 @@ dns_zone_name(dns_zone_t *zone, char *buf, size_t length) { zone_namerd_tostr(zone, buf, length); } +void +dns_zone_nameonly(dns_zone_t *zone, char *buf, size_t length) { + REQUIRE(DNS_ZONE_VALID(zone)); + REQUIRE(buf != NULL); + zone_name_tostr(zone, buf, length); +} + static void notify_log(dns_zone_t *zone, int level, const char *fmt, ...) { va_list ap;