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;