]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
4282. [func] 'dig +[no]mapped' determine whether the use of mapped
authorMark Andrews <marka@isc.org>
Fri, 18 Dec 2015 22:47:11 +0000 (09:47 +1100)
committerMark Andrews <marka@isc.org>
Fri, 18 Dec 2015 22:47:11 +0000 (09:47 +1100)
                        IPv4 addresses over IPv6 is permitted or not.  The
                        default is +mapped.  [RT #41307]

CHANGES
bin/dig/dig.c
bin/dig/dig.docbook
bin/dig/dighost.c
bin/dig/include/dig/dig.h
bin/tests/system/digdelv/tests.sh

diff --git a/CHANGES b/CHANGES
index 57875233c868e6f9c9bbd2a9f0b0e82c0ea8da01..9d11028159e910449dd68783a6a7d1a93d680875 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,7 @@
+4282.  [func]          'dig +[no]mapped' determine whether the use of mapped
+                       IPv4 addresses over IPv6 is permitted or not.  The
+                       default is +mapped.  [RT #41307]
+
 4281.  [bug]           Teach dns_message_totext about BADCOOKIE. [RT #41257]
 
 4280.  [performance]   Use optimal message sizes to improve compression
index 0ae86b60228bb5f10f802f866639bd8118ece211..e09cff15133326c1f119920b3824a49ae0d37102 100644 (file)
@@ -195,6 +195,7 @@ help(void) {
 "                 +[no]identify       (ID responders in short answers)\n"
 "                 +[no]ignore         (Don't revert to TCP for TC responses.)\n"
 "                 +[no]keepopen       (Keep the TCP socket open between queries)\n"
+"                 +[no]mapped         (Allow mapped IPv4 over IPv6)\n"
 "                 +[no]multiline      (Print records in an expanded format)\n"
 "                 +ndots=###          (Set search NDOTS value)\n"
 "                 +[no]nsid           (Request Name Server ID)\n"
@@ -1061,8 +1062,18 @@ plus_option(const char *option, isc_boolean_t is_batchfile,
                keep_open = state;
                break;
        case 'm': /* multiline */
-               FULLCHECK("multiline");
-               multiline = state;
+               switch (cmd[1]) {
+               case 'a':
+                       FULLCHECK("mapped");
+                       lookup->mapped = state;
+                       break;
+               case 'u':
+                       FULLCHECK("multiline");
+                       multiline = state;
+                       break;
+               default:
+                       goto invalid_option;
+               }
                break;
        case 'n':
                switch (cmd[1]) {
@@ -1849,7 +1860,7 @@ parse_args(isc_boolean_t is_batchfile, isc_boolean_t config_only,
                        if (is_batchfile && !config_only) {
                                addresscount = getaddresses(lookup, &rv[0][1],
                                                             &result);
-                               if (result != ISC_R_SUCCESS) {
+                               if (addresscount == 0) {
                                        fprintf(stderr, "couldn't get address "
                                                "for '%s': %s: skipping "
                                                "lookup\n", &rv[0][1],
@@ -1860,9 +1871,13 @@ parse_args(isc_boolean_t is_batchfile, isc_boolean_t config_only,
                                        destroy_lookup(lookup);
                                        return;
                                }
-                       } else
+                       } else {
                                addresscount = getaddresses(lookup, &rv[0][1],
                                                            NULL);
+                               if (addresscount == 0)
+                                       fatal("no valid addresses for '%s'\n",
+                                             &rv[0][1]);
+                       }
                } else if (rv[0][0] == '+') {
                        plus_option(&rv[0][1], is_batchfile,
                                    lookup);
index 7230935947a83b239f1c0f90a755582f6a6c4981..33c02430b5aea1d926cafed28094c27d9cd96b65 100644 (file)
          </listitem>
        </varlistentry>
 
+       <varlistentry>
+         <term><option>+[no]mapped</option></term>
+         <listitem>
+           <para>
+             Allow mapped IPv4 over IPv6 addresses to be used.  The
+             default is <option>+mapped</option>.
+           </para>
+         </listitem>
+       </varlistentry>
+
        <varlistentry>
          <term><option>+[no]multiline</option></term>
          <listitem>
index 9785e900c1420ab00118b62fdc47c8ffe8e93020..d7586df42bfb1189df1c98524e51096a99e92de5 100644 (file)
@@ -830,6 +830,7 @@ make_empty_lookup(void) {
        looknew->ednsopts = NULL;
        looknew->ednsoptscnt = 0;
        looknew->ednsneg = ISC_TRUE;
+       looknew->mapped = ISC_TRUE;
        looknew->dscp = -1;
        dns_fixedname_init(&looknew->fdomain);
        ISC_LINK_INIT(looknew, link);
@@ -889,6 +890,7 @@ clone_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
        looknew->ednsopts = lookold->ednsopts;
        looknew->ednsoptscnt = lookold->ednsoptscnt;
        looknew->ednsneg = lookold->ednsneg;
+       looknew->mapped = lookold->mapped;
 #ifdef DIG_SIGCHASE
        looknew->sigchase = lookold->sigchase;
 #if DIG_SIGCHASE_TD
@@ -2840,6 +2842,28 @@ send_tcp_connect(dig_query_t *query) {
                return;
        }
 
+       if (!l->mapped && isc_sockaddr_pf(&query->sockaddr) == AF_INET6 &&
+           IN6_IS_ADDR_V4MAPPED(&query->sockaddr.type.sin6.sin6_addr)) {
+               isc_netaddr_t netaddr;
+               char buf[ISC_NETADDR_FORMATSIZE];
+
+               isc_netaddr_fromsockaddr(&netaddr, &query->sockaddr);
+               isc_netaddr_format(&netaddr, buf, sizeof(buf));
+               printf(";; Skipping mapped address '%s'\n", buf);
+
+               query->waiting_connect = ISC_FALSE;
+               next = ISC_LIST_NEXT(query, link);
+               l = query->lookup;
+               clear_query(query);
+               if (next == NULL) {
+                       printf(";; No acceptable nameservers\n");
+                       check_next_lookup(l);
+                       return;
+               }
+               send_tcp_connect(next);
+               return;
+       }
+
        if (specified_source &&
            (isc_sockaddr_pf(&query->sockaddr) !=
             isc_sockaddr_pf(&bind_address))) {
@@ -2876,6 +2900,7 @@ send_tcp_connect(dig_query_t *query) {
        debug("sockcount=%d", sockcount);
        if (query->lookup->dscp != -1)
                isc_socket_dscp(query->sock, query->lookup->dscp);
+       isc_socket_ipv6only(query->sock, ISC_TF(!query->lookup->mapped));
        if (specified_source)
                result = isc_socket_bind(query->sock, &bind_address,
                                         ISC_SOCKET_REUSEADDRESS);
@@ -2929,6 +2954,7 @@ send_udp(dig_query_t *query) {
        dig_lookup_t *l = NULL;
        isc_result_t result;
        isc_buffer_t *sendbuf;
+       dig_query_t *next;
 
        debug("send_udp(%p)", query);
 
@@ -2946,6 +2972,25 @@ send_udp(dig_query_t *query) {
                        return;
                }
 
+               if (!l->mapped &&
+                   isc_sockaddr_pf(&query->sockaddr) == AF_INET6 &&
+                   IN6_IS_ADDR_V4MAPPED(&query->sockaddr.type.sin6.sin6_addr)) {
+                       isc_netaddr_t netaddr;
+                       char buf[ISC_NETADDR_FORMATSIZE];
+
+                       isc_netaddr_fromsockaddr(&netaddr, &query->sockaddr);
+                       isc_netaddr_format(&netaddr, buf, sizeof(buf));
+                       printf(";; Skipping mapped address '%s'\n", buf);
+
+                       next = ISC_LIST_NEXT(query, link);
+                       l = query->lookup;
+                       clear_query(query);
+                       if (next == NULL)
+                               printf(";; No acceptable nameservers\n");
+                       check_next_lookup(l);
+                       return;
+               }
+
                result = isc_socket_create(socketmgr,
                                           isc_sockaddr_pf(&query->sockaddr),
                                           isc_sockettype_udp, &query->sock);
@@ -2954,6 +2999,8 @@ send_udp(dig_query_t *query) {
                debug("sockcount=%d", sockcount);
                if (query->lookup->dscp != -1)
                        isc_socket_dscp(query->sock, query->lookup->dscp);
+               isc_socket_ipv6only(query->sock,
+                                   ISC_TF(!query->lookup->mapped));
                if (specified_source) {
                        result = isc_socket_bind(query->sock, &bind_address,
                                                 ISC_SOCKET_REUSEADDRESS);
index 478f8377ce21e98a94557bb04c3a0760aa53185f..9e2094929ca620119725a2fe89e5dd24d8a215cc 100644 (file)
@@ -136,7 +136,8 @@ struct dig_lookup {
                badcookie,
                nsid,   /*% Name Server ID (RFC 5001) */
                header_only,
-               ednsneg;
+               ednsneg,
+               mapped;
 #ifdef DIG_SIGCHASE
 isc_boolean_t  sigchase;
 #if DIG_SIGCHASE_TD
index 7974df0b17142b6128b7bc1ff0fdaed1038e8bee..3e654a6ab18ce4f8949572c64e509fc33f15d642 100644 (file)
@@ -202,18 +202,46 @@ if [ -x ${DIG} ] ; then
   fi
   
   n=`expr $n + 1`
-  echo "I:checking dig @IPv4addr -6 A a.example ($n)"
+  echo "I:checking dig @IPv4addr -6 +mapped A a.example ($n)"
   if $TESTSOCK6 fd92:7065:b8e:ffff::2
   then
     ret=0
     ret=0
-    $DIG $DIGOPTS +tcp @10.53.0.2 -6 A a.example > dig.out.test$n 2>&1 || ret=1
+    $DIG $DIGOPTS +tcp @10.53.0.2 -6 +mapped A a.example > dig.out.test$n 2>&1 || ret=1
     grep "SERVER: ::ffff:10.53.0.2#5300" < dig.out.test$n > /dev/null || ret=1
     if [ $ret != 0 ]; then echo "I:failed"; fi
     status=`expr $status + $ret`
   else
     echo "I:IPv6 unavailable; skipping"
   fi
+
+  n=`expr $n + 1`
+  echo "I:checking dig +tcp @IPv4addr -6 +nomapped A a.example ($n)"
+  if $TESTSOCK6 fd92:7065:b8e:ffff::2
+  then
+    ret=0
+    ret=0
+    $DIG $DIGOPTS +tcp @10.53.0.2 -6 +nomapped A a.example > dig.out.test$n 2>&1 || ret=1
+    grep "SERVER: ::ffff:10.53.0.2#5300" < dig.out.test$n > /dev/null && ret=1
+    if [ $ret != 0 ]; then echo "I:failed"; fi
+    status=`expr $status + $ret`
+  else
+    echo "I:IPv6 unavailable; skipping"
+  fi
+  n=`expr $n + 1`
+
+  echo "I:checking dig +notcp @IPv4addr -6 +nomapped A a.example ($n)"
+  if $TESTSOCK6 fd92:7065:b8e:ffff::2
+  then
+    ret=0
+    ret=0
+    $DIG $DIGOPTS +notcp @10.53.0.2 -6 +nomapped A a.example > dig.out.test$n 2>&1 || ret=1
+    grep "SERVER: ::ffff:10.53.0.2#5300" < dig.out.test$n > /dev/null && ret=1
+    if [ $ret != 0 ]; then echo "I:failed"; fi
+    status=`expr $status + $ret`
+  else
+    echo "I:IPv6 unavailable; skipping"
+  fi
   
   n=`expr $n + 1`
   echo "I:checking dig +subnet ($n)"