]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
4420. [func] nslookup now looks for AAAA as well as A by default.
authorMark Andrews <marka@isc.org>
Thu, 21 Jul 2016 17:27:49 +0000 (03:27 +1000)
committerMark Andrews <marka@isc.org>
Thu, 21 Jul 2016 17:27:49 +0000 (03:27 +1000)
                        [RT #40420]

CHANGES
bin/dig/nslookup.c
bin/tests/system/nslookup/ns1/named.conf
bin/tests/system/nslookup/tests.sh

diff --git a/CHANGES b/CHANGES
index 3bca3eed4a0a47221d9d4c23709830088497430a..401c08601bbd488c3d9f118057b73700679d7cfc 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+4420.  [func]          nslookup now looks for AAAA as well as A by default.
+                       [RT #40420]
+
 4419.  [bug]           Don't cause undefined result if the label of an
                        entry in catalog zone is changed. [RT #42708]
 
index 6a9955edd878002218494e2ba55c0fba338f4677..f00ab4558ee4b4bfb6fc378db729c1a59f6611c2 100644 (file)
@@ -46,7 +46,8 @@ static isc_boolean_t short_form = ISC_TRUE,
        comments = ISC_TRUE, section_question = ISC_TRUE,
        section_answer = ISC_TRUE, section_authority = ISC_TRUE,
        section_additional = ISC_TRUE, recurse = ISC_TRUE,
-       aaonly = ISC_FALSE, nofail = ISC_TRUE;
+       aaonly = ISC_FALSE, nofail = ISC_TRUE,
+       default_lookups = ISC_TRUE, a_noanswer = ISC_FALSE;
 
 static isc_boolean_t interactive;
 
@@ -182,9 +183,9 @@ printsoa(dns_rdata_t *rdata) {
 }
 
 static void
-printa(dns_rdata_t *rdata) {
+printaddr(dns_rdata_t *rdata) {
        isc_result_t result;
-       char text[sizeof("255.255.255.255")];
+       char text[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
        isc_buffer_t b;
 
        isc_buffer_init(&b, text, sizeof(text));
@@ -193,6 +194,7 @@ printa(dns_rdata_t *rdata) {
        printf("Address: %.*s\n", (int)isc_buffer_usedlength(&b),
               (char *)isc_buffer_base(&b));
 }
+
 #ifdef DIG_SIGCHASE
 /* Just for compatibility : not use in host program */
 isc_result_t
@@ -264,12 +266,13 @@ printsection(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers,
                                dns_rdataset_current(rdataset, &rdata);
                                switch (rdata.type) {
                                case dns_rdatatype_a:
+                               case dns_rdatatype_aaaa:
                                        if (section != DNS_SECTION_ANSWER)
                                                goto def_short_section;
                                        dns_name_format(name, namebuf,
                                                        sizeof(namebuf));
                                        printf("Name:\t%s\n", namebuf);
-                                       printa(&rdata);
+                                       printaddr(&rdata);
                                        break;
                                case dns_rdatatype_soa:
                                        dns_name_format(name, namebuf,
@@ -400,6 +403,31 @@ trying(char *frm, dig_lookup_t *lookup) {
 
 }
 
+static void
+chase_cnamechain(dns_message_t *msg, dns_name_t *qname) {
+       isc_result_t result;
+       dns_rdataset_t *rdataset;
+       dns_rdata_cname_t cname;
+       dns_rdata_t rdata = DNS_RDATA_INIT;
+       unsigned int i = msg->counts[DNS_SECTION_ANSWER];
+
+       while (i-- > 0) {
+               rdataset = NULL;
+               result = dns_message_findname(msg, DNS_SECTION_ANSWER, qname,
+                               dns_rdatatype_cname, 0, NULL, &rdataset);
+               if (result != ISC_R_SUCCESS)
+                       return;
+               result = dns_rdataset_first(rdataset);
+               check_result(result, "dns_rdataset_first");
+               dns_rdata_reset(&rdata);
+               dns_rdataset_current(rdataset, &rdata);
+               result = dns_rdata_tostruct(&rdata, &cname, NULL);
+               check_result(result, "dns_rdata_tostruct");
+               dns_name_copy(&cname.cname, qname, NULL);
+               dns_rdata_freestruct(&cname);
+       }
+}
+
 isc_result_t
 printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) {
        char servtext[ISC_SOCKADDR_FORMATSIZE];
@@ -409,11 +437,13 @@ printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) {
 
        debug("printmessage()");
 
-       isc_sockaddr_format(&query->sockaddr, servtext, sizeof(servtext));
-       printf("Server:\t\t%s\n", query->userarg);
-       printf("Address:\t%s\n", servtext);
+       if(!default_lookups || query->lookup->rdtype == dns_rdatatype_a) {
+               isc_sockaddr_format(&query->sockaddr, servtext, sizeof(servtext));
+               printf("Server:\t\t%s\n", query->userarg);
+               printf("Address:\t%s\n", servtext);
 
-       puts("");
+               puts("");
+       }
 
        if (!short_form) {
                puts("------------");
@@ -438,16 +468,50 @@ printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) {
                return (ISC_R_SUCCESS);
        }
 
-       if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0)
+       if ( default_lookups && query->lookup->rdtype == dns_rdatatype_a) {
+               char namestr[DNS_NAME_FORMATSIZE];
+               dig_lookup_t *lookup;
+               dns_fixedname_t fixed;
+               dns_name_t *name;
+
+               /* Add AAAA lookup. */
+               dns_fixedname_init(&fixed);
+               name = dns_fixedname_name(&fixed);
+               dns_name_copy(query->lookup->name, name, NULL);
+               chase_cnamechain(msg, name);
+               dns_name_format(name, namestr, sizeof(namestr));
+               lookup = clone_lookup(query->lookup, ISC_FALSE);
+               if (lookup != NULL) {
+                       strncpy(lookup->textname, namestr,
+                               sizeof(lookup->textname));
+                       lookup->textname[sizeof(lookup->textname)-1] = 0;
+                       lookup->rdtype = dns_rdatatype_aaaa;
+                       lookup->rdtypeset = ISC_TRUE;
+                       lookup->origin = NULL;
+                       lookup->retries = tries;
+                       ISC_LIST_APPEND(lookup_list, lookup, link);
+               }
+       }
+
+       if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0 &&
+           ( !default_lookups || query->lookup->rdtype == dns_rdatatype_a) )
                puts("Non-authoritative answer:");
        if (!ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER]))
                printsection(query, msg, headers, DNS_SECTION_ANSWER);
-       else
-               printf("*** Can't find %s: No answer\n",
-                      query->lookup->textname);
+       else {
+               if (default_lookups && query->lookup->rdtype == dns_rdatatype_a)
+                       a_noanswer = ISC_TRUE;
+
+               else if (!default_lookups ||
+                        (query->lookup->rdtype == dns_rdatatype_aaaa &&
+                        a_noanswer ) )
+                       printf("*** Can't find %s: No answer\n",
+                               query->lookup->textname);
+       }
 
        if (((msg->flags & DNS_MESSAGEFLAG_AA) == 0) &&
-           (query->lookup->rdtype != dns_rdatatype_a)) {
+           (query->lookup->rdtype != dns_rdatatype_a) &&
+           (query->lookup->rdtype != dns_rdatatype_aaaa) ) {
                puts("\nAuthoritative answers can be found from:");
                printsection(query, msg, headers,
                             DNS_SECTION_AUTHORITY);
@@ -585,23 +649,35 @@ setoption(char *opt) {
                if (testclass(&opt[3]))
                        strlcpy(defclass, &opt[3], sizeof(defclass));
        } else if (strncasecmp(opt, "type=", 5) == 0) {
-               if (testtype(&opt[5]))
+               if (testtype(&opt[5])) {
                        strlcpy(deftype, &opt[5], sizeof(deftype));
+                       default_lookups = ISC_FALSE;
+               }
        } else if (strncasecmp(opt, "ty=", 3) == 0) {
-               if (testtype(&opt[3]))
+               if (testtype(&opt[3])) {
                        strlcpy(deftype, &opt[3], sizeof(deftype));
+                       default_lookups = ISC_FALSE;
+               }
        } else if (strncasecmp(opt, "querytype=", 10) == 0) {
-               if (testtype(&opt[10]))
+               if (testtype(&opt[10])) {
                        strlcpy(deftype, &opt[10], sizeof(deftype));
+                       default_lookups = ISC_FALSE;
+               }
        } else if (strncasecmp(opt, "query=", 6) == 0) {
-               if (testtype(&opt[6]))
+               if (testtype(&opt[6])) {
                        strlcpy(deftype, &opt[6], sizeof(deftype));
+                       default_lookups = ISC_FALSE;
+               }
        } else if (strncasecmp(opt, "qu=", 3) == 0) {
-               if (testtype(&opt[3]))
+               if (testtype(&opt[3])) {
                        strlcpy(deftype, &opt[3], sizeof(deftype));
+                       default_lookups = ISC_FALSE;
+               }
        } else if (strncasecmp(opt, "q=", 2) == 0) {
-               if (testtype(&opt[2]))
+               if (testtype(&opt[2])) {
                        strlcpy(deftype, &opt[2], sizeof(deftype));
+                       default_lookups = ISC_FALSE;
+               }
        } else if (strncasecmp(opt, "domain=", 7) == 0) {
                strlcpy(domainopt, &opt[7], sizeof(domainopt));
                set_search_domain(domainopt);
@@ -671,6 +747,9 @@ addlookup(char *opt) {
        char store[MXNAME];
 
        debug("addlookup()");
+
+       a_noanswer = ISC_FALSE;
+
        tr.base = deftype;
        tr.length = strlen(deftype);
        result = dns_rdatatype_fromtext(&rdtype, &tr);
index aa02c89a448ba8157f545bfd56273aea4330d483..ddf4dabedcbc6505144f742e600230851b44cca0 100644 (file)
@@ -23,3 +23,8 @@ zone "example" {
        type master;
        file "example.db";
 };
+
+zone "example.net" {
+       type master;
+       file "example.net.db";
+};
index 1b612ff357cfb8955b469153f4dacd7497e47517..f088dd8db2e3beabe1df7c099e1c9e74035f501a 100644 (file)
@@ -23,5 +23,85 @@ grep "origin = ns1.example" nslookup.out${n} > /dev/null || ret=1
 if [ $ret != 0 ]; then echo "I:failed"; fi
 status=`expr $status + $ret`
 
+n=`expr $n + 1`
+echo "Check A only lookup"
+ret=0
+$NSLOOKUP -port=5300 a-only.example.net 10.53.0.1 > nslookup.out${n} || ret=1
+lines=`grep "Server:" nslookup.out${n} | wc -l`
+test $lines = 1 || ret=1
+lines=`grep a-only.example.net nslookup.out${n} | wc -l`
+test $lines = 1 || ret=1
+grep "1.2.3.4" nslookup.out${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "Check AAAA only lookup"
+ret=0
+$NSLOOKUP -port=5300 aaaa-only.example.net 10.53.0.1 > nslookup.out${n} || ret=1
+lines=`grep "Server:" nslookup.out${n} | wc -l`
+test $lines = 1 || ret=1
+lines=`grep aaaa-only.example.net nslookup.out${n} | wc -l`
+test $lines = 1 || ret=1
+grep "2001::ffff" nslookup.out${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "Check dual A + AAAA lookup"
+ret=0
+$NSLOOKUP -port=5300 dual.example.net 10.53.0.1 > nslookup.out${n} || ret=1
+lines=`grep "Server:" nslookup.out${n} | wc -l`
+test $lines = 1 || ret=1
+lines=`grep dual.example.net nslookup.out${n} | wc -l`
+test $lines = 2 || ret=1
+grep "1.2.3.4" nslookup.out${n} > /dev/null || ret=1
+grep "2001::ffff" nslookup.out${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "Check CNAME to A only lookup"
+ret=0
+$NSLOOKUP -port=5300 cname-a-only.example.net 10.53.0.1 > nslookup.out${n} || ret=1
+lines=`grep "Server:" nslookup.out${n} | wc -l`
+test $lines = 1 || ret=1
+lines=`grep "canonical name" nslookup.out${n} | wc -l`
+test $lines = 1 || ret=1
+lines=`grep a-only.example.net nslookup.out${n} | grep -v "canonical name" | wc -l`
+test $lines = 1 || ret=1
+grep "1.2.3.4" nslookup.out${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "Check CNAME to AAAA only lookup"
+ret=0
+$NSLOOKUP -port=5300 cname-aaaa-only.example.net 10.53.0.1 > nslookup.out${n} || ret=1
+lines=`grep "Server:" nslookup.out${n} | wc -l`
+test $lines = 1 || ret=1
+lines=`grep "canonical name" nslookup.out${n} | wc -l`
+test $lines = 1 || ret=1
+lines=`grep aaaa-only.example.net nslookup.out${n} | grep -v "canonical name" |wc -l`
+test $lines = 1 || ret=1
+grep "2001::ffff" nslookup.out${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "Check CNAME to dual A + AAAA lookup"
+ret=0
+$NSLOOKUP -port=5300 cname-dual.example.net 10.53.0.1 > nslookup.out${n} || ret=1
+lines=`grep "Server:" nslookup.out${n} | wc -l`
+test $lines = 1 || ret=1
+lines=`grep "canonical name" nslookup.out${n} | wc -l`
+test $lines = 1 || ret=1
+lines=`grep dual.example.net nslookup.out${n} | grep -v "canonical name" | wc -l`
+test $lines = 2 || ret=1
+grep "1.2.3.4" nslookup.out${n} > /dev/null || ret=1
+grep "2001::ffff" nslookup.out${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
 echo "I:exit status: $status"
 [ $status -eq 0 ] || exit 1