Take three
Differences from take two is that
* the test for IPv6 over IPv4 have been corrected, was triggering
a bit too much, blocking IPv6 access if tcp_outgoing_address not
set
* Set errno to ENETUNREACH when destination blocked by family, to
match what Linux returns if trying to connect over the socket.
I also tried to let connect() deal with the socket incompatibility, but
this failed in the way that incompatible addresses then got marked as
bad due to connect() returning ENETUNREACH and not EAFNOSUPPORT like we
expected which makes this case indistinguishable from the actual network
unreachable error case which should mark addresses as bad.
This patch backs out part of the patch for Bug #2222 and replaces it by
crudely cycling over the available addresses, trying to skip over
addresses not compatible with the current socket.
This solves issues seen when using tproxy or tcp_outgoing_address and
DNS of the requested host returns AAAA records in addition to A records.
This change is interim, waiting for the larger connection setup
overhaul. But seems to do the trick at least for me in tproxy & ipv4
setups. Unfortunately I do not have an IPv6 connection at the moment to
test IPv6 on, but I don't see how it could break IPv6.
One effect of this change is that there will be no fallback to the other
IP generation if the socket is configured to a specific outgoing
address. Priory the code threw away the outgoing address and tried
again when encountering an incompatibility.
Regards
Henrik
# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: [email protected]\
# 3t96ayov9whpmx1h
# target_branch: http://squid-cache.org/bzr/squid3/branches/SQUID_3_1/
# testament_sha1: 82fbabc83ff0884fa2cad3d399ebbd32e4f27488
# timestamp: 2010-05-14 03:38:40 +0200
# base_revision_id: [email protected]\
# 85q5fquskamzv6pu
#
# Begin patch
=== modified file 'src/comm.cc'
--- src/comm.cc 2010-04-23 01:17:20 +0000
+++ src/comm.cc 2010-05-14 01:38:27 +0000
@@ -968,9 +968,6 @@
int
ConnectStateData::commResetFD()
{
- struct addrinfo *AI = NULL;
- IpAddress nul;
- int new_family = AF_UNSPEC;
// XXX: do we have to check this?
//
@@ -979,21 +976,19 @@
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;
+ fde *F = &fd_table[fd];
+ struct addrinfo *AI = NULL;
+ F->local_addr.GetAddrInfo(AI);
int fd2 = socket(AI->ai_family, AI->ai_socktype, AI->ai_protocol);
- nul.FreeAddrInfo(AI);
-
if (fd2 < 0) {
debugs(5, DBG_CRITICAL, HERE << "WARNING: FD " << fd2 << " socket failed to allocate: " << xstrerror());
if (ENFILE == errno || EMFILE == errno)
fdAdjustReserved();
+ F->local_addr.FreeAddrInfo(AI);
return 0;
}
@@ -1013,17 +1008,15 @@
close(fd2);
+ F->local_addr.FreeAddrInfo(AI);
return 0;
}
commResetSelect(fd);
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;
+
+ F->flags.called_connect = 0;
+
/*
* yuck, this has assumptions about comm_open() arguments for
* the original socket
@@ -1034,9 +1027,6 @@
comm_set_transparent(fd);
}
- AI = NULL;
- F->local_addr.GetAddrInfo(AI);
-
if (commBind(fd, *AI) != COMM_OK) {
debugs(5, DBG_CRITICAL, "WARNING: Reset of FD " << fd << " for " << F->local_addr << " failed to bind: " << xstrerror());
F->local_addr.FreeAddrInfo(AI);
@@ -1104,8 +1094,7 @@
void
ConnectStateData::connect()
{
- if (S.IsAnyAddr())
- defaults();
+ defaults();
debugs(5,5, HERE << "to " << S);
@@ -1122,15 +1111,22 @@
callCallback(COMM_OK, 0);
break;
-#if USE_IPV6
case COMM_ERR_PROTOCOL:
+ debugs(5, 5, HERE "FD " << fd << ": COMM_ERR_PROTOCOL - try again");
/* problem using the desired protocol over this socket.
- * count the connection attempt, reset the socket, and immediately try again */
+ * skip to the next address and hope it's more compatible
+ * but do not mark the current address as bad
+ */
tries++;
- commResetFD();
- connect();
+ if (commRetryConnect()) {
+ /* Force an addr cycle to move forward to the next possible address */
+ ipcacheCycleAddr(host, NULL);
+ 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;
-#endif
default:
debugs(5, 5, HERE "FD " << fd << ": * - try again");
@@ -1232,18 +1228,27 @@
debugs(5, 9, "comm_connect_addr: connecting socket " << sock << " to " << address << " (want family: " << F->sock_family << ")");
- /* 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.
+ /* Handle IPv6 over IPv4-only socket case.
* 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
+ * 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
+ 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);
@@ -1337,23 +1342,10 @@
status = COMM_OK;
else if (ignoreErrno(errno))
status = COMM_INPROGRESS;
+ else if (errno == EAFNOSUPPORT || errno == EINVAL)
+ return COMM_ERR_PROTOCOL;
else
-#if USE_IPV6
- if ( address.IsIPv4() && F->sock_family == AF_INET6 ) {
-
- /* failover to trying IPv4-only link if an IPv6 one fails */
- /* to catch the edge case of apps listening on IPv4-localhost */
- F->sock_family = AF_INET;
- int res = comm_connect_addr(sock, address);
-
- /* if that fails too, undo our temporary socktype hack so the repeat works properly. */
- if (res == COMM_ERROR)
- F->sock_family = AF_INET6;
-
- return res;
- } else
-#endif
- return COMM_ERROR;
+ return COMM_ERROR;
address.NtoA(F->ipaddr, MAX_IPSTRLEN);
# Begin bundle
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