Hi,
Can you test the attached patch? It fixes the problrem for me. Without
this patch, I need to set tcp_outgoing_address to force IPv4 for some
sites.
diff -uNrp squid3-3.1.18.orig/src/comm.cc squid3-3.1.18/src/comm.cc
--- squid3-3.1.18.orig/src/comm.cc 2011-12-03 06:18:46.000000000 +0000
+++ squid3-3.1.18/src/comm.cc 2012-01-18 10:03:30.422424903 +0000
@@ -984,8 +984,8 @@ ConnectStateData::commResetFD()
fde *F = &fd_table[fd];
struct addrinfo *AI = NULL;
- F->local_addr.GetAddrInfo(AI);
- int new_family = AI->ai_family;
+ const int new_family = F->sock_family;
+ F->local_addr.GetAddrInfo(AI, new_family);
int fd2 = socket(new_family, AI->ai_socktype, AI->ai_protocol);
@@ -1126,22 +1126,31 @@ ConnectStateData::connect()
callCallback(COMM_OK, 0);
break;
- case COMM_ERR_PROTOCOL:
+ case COMM_ERR_PROTOCOL: {
debugs(5, 5, HERE "FD " << fd << ": COMM_ERR_PROTOCOL - try again");
- /* problem using the desired protocol over this socket.
- * skip to the next address and hope it's more compatible
- * but do not mark the current address as bad
+ /* A remote address is incompatible with this socket. If local
+ * address is not wildcard address, skip to the next address
+ * but do not mark the current address as bad.
*/
- tries++;
- if (commRetryConnect()) {
+ fde *F = &fd_table[fd];
+ if (F->local_addr.IsAnyAddr()) {
+ struct addrinfo *AI = NULL;
+ S.GetAddrInfo(AI);
+ F->sock_family = AI->ai_family;
+ S.FreeAddrInfo(AI);
+ } else {
+ tries++;
/* Force an addr cycle to move forward to the next possible
address */
ipcacheCycleAddr(host, NULL);
+ }
+ if (commRetryConnect()) {
eventAdd("commReconnect", commReconnect, this, this->addrcount ==
1 ? 0.05 : 0.0, 0);
} else {
debugs(5, 5, HERE << "FD " << fd << ": COMM_ERR_PROTOCOL - ERR
tried too many times already.");
callCallback(COMM_ERR_CONNECT, errno);
}
break;
+ }
default:
debugs(5, 5, HERE "FD " << fd << ": * - try again");
@@ -1243,29 +1252,7 @@ comm_connect_addr(int sock, const IpAddr
debugs(5, 9, "comm_connect_addr: connecting socket " << sock << " to " <<
address << " (want family: " << F->sock_family << ")");
- /* Handle IPv6 over IPv4-only socket case.
- * this case must presently be handled here since the GetAddrInfo asserts
on bad mappings.
- * NP: because commResetFD is private to ConnStateData we have to return
an error and
- * trust its handled properly.
- */
- if (F->sock_family == AF_INET && !address.IsIPv4()) {
- errno = ENETUNREACH;
- return COMM_ERR_PROTOCOL;
- }
-
- /* Handle IPv4 over IPv6-only socket case.
- * This case is presently handled here as it's both a known case and it's
- * uncertain what error will be returned by the IPv6 stack in such case.
It's
- * possible this will also be handled by the errno checks below after
connect()
- * but needs carefull cross-platform verification, and verifying the
address
- * condition here is simple.
- */
- if (!F->local_addr.IsIPv4() && address.IsIPv4()) {
- errno = ENETUNREACH;
- return COMM_ERR_PROTOCOL;
- }
-
- address.GetAddrInfo(AI, F->sock_family);
+ address.GetAddrInfo(AI);
/* Establish connection. */
errno = 0;