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. Priorly 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: hen...@henriknordstrom.net-20100511013541-\ # 1v1dnocxttvwqv82 # target_branch: http://squid-cache.org/bzr/squid3/branches/SQUID_3_1/ # testament_sha1: 261b470e0c4b4451cc5e5541e62463f5d59456dd # timestamp: 2010-05-11 03:35:58 +0200 # base_revision_id: squ...@treenet.co.nz-20100505074245-\ # qpjwdvcumn8f94bd # # Begin patch === modified file 'src/comm.cc' --- src/comm.cc 2010-04-23 01:17:20 +0000 +++ src/comm.cc 2010-05-11 01:35:41 +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); @@ -1125,10 +1114,18 @@ #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 */ + * 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 << ": * - ERR tried too many times already."); + callCallback(COMM_ERR_CONNECT, errno); + } break; #endif @@ -1232,7 +1229,6 @@ 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. * 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. # Begin bundle IyBCYXphYXIgcmV2aXNpb24gYnVuZGxlIHY0CiMKQlpoOTFBWSZTWX4OKCkAAmzfgEZQUff////n lgq////6UAU4q9N3VLgLrBXOQJIkNEGjTKaYBU/1Gkwp+ST9Q9NE0ZQPU2gmgSUCYTUybUT1T1PU fqRtQAA0ANAAAAlNIJoKbJTymzVDyJjUNHpNABoA0NNA9Q4yZNGIYmmAgYE0wRgmJppoAMIJJEwK YU/U1T9TUGjahoGgYmg0yAAAJDB28+jHXGxZ90YN00xKUliRRGB0T6N0UrrWoJrFvaNcIhqQWu5k TD8F/DZbNWRd6q8wzDTGDl4zk6fhZ3vzjjx8J8cEwJMbKcv3yfUbfOuu+UdEdKhi6Sm4ljN4Ga5n Ymkwbbks5M1F1wZn5t9nuq4NT25MJZ6Y8060OyjJHqeR11eGfFKzD/QzCgu7XkecpEIWxmm4r4wL Ki4pErvuPp51Ut2Ryx69sNXT0ENk7PwvZxXJbccJEcGQ8zNS2cyKMOo2Ouu1mJX9Pon5fMnKGZlL 3u3I7q4Bf4IC4dGJd4I351rpVshI0uRT+1XgZLkDYd2I1c1+3pRf7e0nSHY5GCptl100RDCGrYDc mRNsUXWNMKYoILsI3jYO4ruouOeA0kFiVlUIjXJ7hhRGTe9M61xyCcA17Tg0ftxY6yiLCh9iCpBt dXHAfDwp8SwfwWmBEWRUZGweIuVhlqWOBonJ/AXOYlN9FoVVwX0ZdneThFUrUo1icUueDxRTGFNk yoVNURwyuFJpOTyE05xcs9Ci31fhnR9KW2D+GdygC5Yt+lJZjEtuzM1j12OkoZYcWUg3jipXKO5W LxhfRbdg2+ZUhFEMyi3EVKFRsWFpwG7xrEmPvGyZSOg8sVNqxiYsYXhOQ2vdKqZcENwJpgmMqLMt ikkiWWK6oVlxKWG49WNzB0mxdXeQalMjwYc3t8JSrMdLuatLBHHvLaYRciz9SJI9iWkNvUsE4zLE wxxk+r9ePDHf3Uf56YbtPl5jVy+5M/9BoVp6nr60vOvoVcqbiiExyWy0ZV9pJbVpcNkOb5apiMA3 m0/Y75uF3iY7V0OnaBhKDAaAruL4tkaiwpe5O+Xw/NQoSMnn8PjQOUx5/Hv4jGUvVmCN2jakq8TF 0xnvPEs+a+e0Ki5+fgZa6xm6CcMVnFhzj3Oc+Qp/R8DLyU1Ymp11TUNs669MBwzEVImeicm5Owan MmTCfUqe0uOtyu3jrmQrUErAa+6qbJLCe2G/y3RIwqdNcjbo2985irE0parokge+Frc5aFt6ETwM iWzAPTqEoaMyZEbZdKmgZ4ligPUbJDfeXRMBKXFGfDqOXIYyo0KbMYvx9tekvnlzx99aHDe90Vns e9CozA6ePptNqb8Jbol/dhEQ2anvvVUjciEp8tBBJZFIrxr8wvzbsGaSOChkp+eo6gJt3RHb1q3V UxwUEuUIukyjasb4yWdmd+MkwZudP7NksuepMlrTosMSkoL1uhyMqChTkYbCaDQdiZMKUkkGCFoc iWQRIH1TYyDHtC30pTSWLCmyGV+oNhXbViCpyBYnFTvYCRIuoPa5laiXXa4YpA/fxvJZMC4MuTZw tXklV/OyfdgaaaKFzCSP6sJUnMZjouCOIW/o1aGiYmhwua6DUGm8oGedwohh18tbE7CU9ySlPea2 TBPMxmraaJOyWEEU/suDSKU4iTlM2MhFxKgD5aNyT8SFQbIKAZQOZ8NWfcny1xrir3wUBi1m0KNZ ItKzrNJaquRqv4hyawJhem94GNcg1UcRYp1FUTyzOhxo5MNi144ubF/iFIXKuWqhbJMAxFj/lXm8 ArkYinGWyl7/SoNI9u4Jbcy/A8Z/xdyRThQkH4OKCkA=