]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Bug 2222 part 2: ipv4 client trying to view an ipv6 website crashes FreeBSD squid
authorAmos Jeffries <squid3@treenet.co.nz>
Thu, 8 May 2008 03:47:53 +0000 (15:47 +1200)
committerAmos Jeffries <squid3@treenet.co.nz>
Thu, 8 May 2008 03:47:53 +0000 (15:47 +1200)
This one:
 - omits the v6-specific socket options on new addrinfo
 - correctly counts the failed connection
 - Resets the socket when a protocol error is found
 - retries without any delay

lib/IPAddress.cc
src/comm.cc
src/comm.h

index 4dea87589b5f7dab3a939892e18ca9c7ed8372ce..1b5deaf721ced7a2e875247797ffd8ae9d1e5dac 100644 (file)
@@ -833,7 +833,21 @@ void IPAddress::GetAddrInfo(struct addrinfo *&dst, int force) const
         dst->ai_addrlen = sizeof(struct sockaddr_in6);
 
         dst->ai_family = ((struct sockaddr_in6*)dst->ai_addr)->sin6_family;
+
+#if 0
+        /**
+         * Enable only if you must and please report to squid-dev if you find a need for this.
+         *
+         * Vista may need this to cope with dual-stack (unsetting IP6_V6ONLY).
+         *         http://msdn.microsoft.com/en-us/library/ms738574(VS.85).aspx
+         * Linux appears to only do some things when its present.
+         *         (93) Bad Protocol
+         * FreeBSD dies horribly when using dual-stack with it set.
+         *         (43) Protocol not supported
+         */
         dst->ai_protocol = IPPROTO_IPV6;
+#endif
+
     } else
 #endif
         if( force == AF_INET || (force == AF_UNSPEC && IsIPv4()) )
index 87de2530ed265a248f25f5a081dc87b0c2337fbe..9d227a627037258d65a76bab939833c7c9dddf52 100644 (file)
@@ -927,6 +927,7 @@ ConnectStateData::commResetFD()
 {
     struct addrinfo *AI = NULL;
     IPAddress nul;
+    int new_family = AF_UNSPEC;
 
 // XXX: do we have to check this?
 //
@@ -936,7 +937,9 @@ ConnectStateData::commResetFD()
     statCounter.syscalls.sock.sockets++;
 
     /* setup a bare-bones addrinfo */
+    /* TODO INET6: for WinXP we may need to check the local_addr type and setup the family properly. */
     nul.GetAddrInfo(AI);
+    new_family = AI->ai_family;
 
     int fd2 = socket(AI->ai_family, AI->ai_socktype, AI->ai_protocol);
 
@@ -973,6 +976,10 @@ ConnectStateData::commResetFD()
 
     close(fd2);
     fde *F = &fd_table[fd];
+
+    /* INET6: copy the new sockets family type to the FDE table */
+    fd_table[fd].sock_family = new_family;
+
     fd_table[fd].flags.called_connect = 0;
     /*
      * yuck, this has assumptions about comm_open() arguments for
@@ -1067,6 +1074,16 @@ ConnectStateData::connect()
         callCallback(COMM_OK, 0);
         break;
 
+#if USE_IPV6
+    case COMM_ERR_PROTOCOL:
+        /* problem using the desired protocol over this socket.
+         * count the connection attempt, reset the socket, and immediately try again */
+        tries++;
+        commResetFD();
+        connect();
+        break;
+#endif
+
     default:
         debugs(5, 5, HERE "FD " << fd << ": * - try again");
         tries++;
@@ -1165,7 +1182,19 @@ comm_connect_addr(int sock, const IPAddress &address)
 
     debugs(5, 9, "comm_connect_addr: connecting socket " << sock << " to " << address << " (want family: " << F->sock_family << ")");
 
-    /* FIXME INET6 : Bug 2222: when sock is an IPv4-only socket IPv6 traffic will crash. */
+    /* BUG 2222 FIX: reset the FD when its found to be IPv4 in IPv6 mode */
+    /* inverse case of IPv4 failing to connect on IPv6 socket is handeld post-connect.
+     * this case must presently be handled here since the GetAddrInfo asserts on bad mappings.
+     * eventually we want it to throw a Must() that gets handled there instead of this if.
+     * NP: because commresetFD is private to ConnStateData we have to return an error and
+     *     trust its handled properly.
+     */
+#if USE_IPV6
+    if(F->sock_family == AF_INET && !address.IsIPv4()) {
+        return COMM_ERR_PROTOCOL;
+    }
+#endif
+
     address.GetAddrInfo(AI, F->sock_family);
 
     /* Establish connection. */
index b87df719b9d892fd4da450ef251e429d85016d52..d1c249efcca567e09dce45b7ade967ec74c504da 100644 (file)
@@ -22,6 +22,9 @@ typedef enum {
     COMM_ERR_CONNECT = -8,
     COMM_ERR_DNS = -9,
     COMM_ERR_CLOSING = -10,
+#if USE_IPV6
+    COMM_ERR_PROTOCOL = -11, /* IPv4 or IPv6 cannot be used on the fd socket */
+#endif
 } comm_err_t;
 
 typedef void CNCB(int fd, comm_err_t status, int xerrno, void *data);