--- src/protos.h.orig 2006-11-07 13:24:18.000000000 +0800 +++ src/protos.h 2006-11-07 13:44:07.000000000 +0800 @@ -154,6 +154,7 @@ extern void comm_lingering_close(int fd); #endif extern void commConnectStart(int fd, const char *, u_short, CNCB *, void *); +extern void commConnectStart2(int fd, const char *, u_short, CNCB *, void *, struct in_addr *addr); extern int comm_connect_addr(int sock, const struct sockaddr_in *); extern void comm_init(void); extern int comm_listen(int sock); --- src/structs.h.orig 2006-11-08 14:58:40.000000000 +0800 +++ src/structs.h 2006-11-08 14:58:42.000000000 +0800 @@ -886,6 +886,7 @@ unsigned int nodelay:1; unsigned int close_on_exec:1; unsigned int backoff:1; /* keep track of whether the fd is backed off */ + unsigned int dnsfailed:1; /* did the dns lookup fail */ } flags; comm_pending read_pending; comm_pending write_pending; --- src/forward.c.orig 2006-11-07 13:24:51.000000000 +0800 +++ src/forward.c 2006-11-08 15:08:45.000000000 +0800 @@ -338,8 +338,11 @@ * Only set the dont_retry flag if the DNS lookup fails on * a direct connection. If DNS lookup fails when trying * a neighbor cache, we may want to retry another option. + * + * If this is a transparent connection, we will retry using the client's + * DNS lookup */ - if (NULL == fs->peer) + if ((NULL == fs->peer) && !fwdState->request->flags.transparent) fwdState->flags.dont_retry = 1; debug(17, 4) ("fwdConnectDone: Unknown host: %s\n", request->host); @@ -522,6 +525,9 @@ if (fd == -1) fd = pconnPop(name, port, domain, NULL, 0); if (fd != -1) { + /* Don't cache if the returned fd does not have valid DNS */ + if (fd_table[fd].flags.dnsfailed) + storeRelease(fwdState->entry); if (fwdCheckRetriable(fwdState)) { debug(17, 3) ("fwdConnectStart: reusing pconn FD %d\n", fd); fwdState->server_fd = fd; @@ -618,7 +624,18 @@ #endif hierarchyNote(&fwdState->request->hier, fs->code, fwdState->request->host); } - commConnectStart(fd, host, port, fwdConnectDone, fwdState); + + /* + * If we are retrying a transparent connection that is not being sent to a + * peer, then don't cache, and use the IP that the client's DNS lookup + * returned + */ + if(fwdState->request->flags.transparent && fwdState->n_tries && (NULL == fs->peer)) { + storeRelease(fwdState->entry); + commConnectStart2(fd, host, port, fwdConnectDone, fwdState, &fwdState->request->my_addr); + } else { + commConnectStart(fd, host, port, fwdConnectDone, fwdState); + } } static void --- src/comm.c.orig 2006-11-07 13:14:20.000000000 +0800 +++ src/comm.c 2006-11-08 15:08:36.000000000 +0800 @@ -270,14 +270,26 @@ void commConnectStart(int fd, const char *host, u_short port, CNCB * callback, void *data) { - ConnectStateData *cs; debug(5, 3) ("commConnectStart: FD %d, %s:%d\n", fd, host, (int) port); + commConnectStart2(fd, host, port, callback, data, NULL); +} + +void +commConnectStart2(int fd, const char *host, u_short port, CNCB * callback, void * data, struct in_addr *addr) +{ + ConnectStateData *cs; cs = cbdataAlloc(ConnectStateData); cs->fd = fd; cs->host = xstrdup(host); cs->port = port; cs->callback = callback; cs->data = data; + if(addr != NULL) { + cs->in_addr = *addr; + cs->addrcount = 1; + } else { + cs->addrcount = 0; + } cbdataLock(cs->data); comm_add_close_handler(fd, commConnectFree, cs); ipcache_nbgethostbyname(host, commConnectDnsHandle, cs); @@ -288,13 +300,20 @@ { ConnectStateData *cs = data; if (ia == NULL) { - debug(5, 3) ("commConnectDnsHandle: Unknown host: %s\n", cs->host); - if (!dns_error_message) { - dns_error_message = "Unknown DNS error"; - debug(5, 1) ("commConnectDnsHandle: Bad dns_error_message\n"); + /* If we've been given a default IP, use it */ + if(cs->addrcount > 0) { + fd_table[cs->fd].flags.dnsfailed=1; + cs->connstart = squid_curtime; + commConnectHandle(cs->fd, cs); + } else { + debug(5, 3) ("commConnectDnsHandle: Unknown host: %s\n", cs->host); + if (!dns_error_message) { + dns_error_message = "Unknown DNS error"; + debug(5, 1) ("commConnectDnsHandle: Bad dns_error_message\n"); + } + assert(dns_error_message != NULL); + commConnectCallback(cs, COMM_ERR_DNS); } - assert(dns_error_message != NULL); - commConnectCallback(cs, COMM_ERR_DNS); return; } assert(ia->cur < ia->count);