]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
1961. [bug] Check the port and address of responses forwarded
authorMark Andrews <marka@isc.org>
Thu, 5 Jan 2006 03:26:01 +0000 (03:26 +0000)
committerMark Andrews <marka@isc.org>
Thu, 5 Jan 2006 03:26:01 +0000 (03:26 +0000)
                        to dispatch. [RT #15474]

CHANGES
lib/dns/dispatch.c

diff --git a/CHANGES b/CHANGES
index 563958e06d22f3d183edd099c7920cc351b5c76b..020bbbc75c25f721aee49c15b5859fcb3b6f1b0c 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+1961.  [bug]           Check the port and address of responses forwarded
+                       to dispatch. [RT #15474]
+
 1960.  [bug]           Update code should set NSEC ttls from SOA MINIMUM.
                        [RT #15465]
 
index 72bf1058a208220b07cb902ea4d70bef02a4cf3d..e7da8f1bd1a4b22d4593fdbbad7b2bb78d9bb87f 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: dispatch.c,v 1.124 2005/07/12 01:00:14 marka Exp $ */
+/* $Id: dispatch.c,v 1.125 2006/01/05 03:26:01 marka Exp $ */
 
 /*! \file */
 
@@ -643,6 +643,50 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in) {
                free_buffer(disp, ev->region.base, ev->region.length);
                goto unlock;
        } 
+
+       /*
+        * Now that we have the original dispatch the query was sent
+        * from check that the address and port the response was
+        * sent to make sense.
+        */
+       if (disp != resp->disp) {
+               isc_sockaddr_t a1;
+               isc_sockaddr_t a2;
+               
+               /*
+                * Check that the socket types and ports match.
+                */
+               if (disp->socktype != resp->disp->socktype ||
+                   isc_sockaddr_getport(&disp->local) !=
+                   isc_sockaddr_getport(&resp->disp->local)) {
+                       free_buffer(disp, ev->region.base, ev->region.length);
+                       goto unlock;
+               }
+
+               /*
+                * If both dispatches are bound to an address then fail as
+                * the addresses can't be equal (enforced by the IP stack).  
+                *
+                * Note under Linux a packet can be sent out via IPv4 socket
+                * and the response be received via a IPv6 socket.
+                * 
+                * Requests sent out via IPv6 should always come back in
+                * via IPv6.
+                */
+               if (isc_sockaddr_pf(&resp->disp->local) == PF_INET6 &&
+                   isc_sockaddr_pf(&disp->local) != PF_INET6) {
+                       free_buffer(disp, ev->region.base, ev->region.length);
+                       goto unlock;
+               }
+               isc_sockaddr_anyofpf(&a1, isc_sockaddr_pf(&resp->disp->local));
+               isc_sockaddr_anyofpf(&a2, isc_sockaddr_pf(&disp->local));
+               if (!isc_sockaddr_eqaddr(&a1, &resp->disp->local) &&
+                   !isc_sockaddr_eqaddr(&a2, &disp->local)) {
+                       free_buffer(disp, ev->region.base, ev->region.length);
+                       goto unlock;
+               }
+       }
+
        queue_response = resp->item_out;
        rev = allocate_event(resp->disp);
        if (rev == NULL) {