From: Amos Jeffries Date: Tue, 29 Nov 2011 06:48:59 +0000 (-0700) Subject: Bug 3301: ERR_DNS_FAIL never shown X-Git-Tag: SQUID_3_2_0_14~24 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a782d23c578e3a17af3a3dcadf1980ed939f43a5;p=thirdparty%2Fsquid.git Bug 3301: ERR_DNS_FAIL never shown --- diff --git a/errors/templates/ERR_CANNOT_FORWARD b/errors/templates/ERR_CANNOT_FORWARD index 7e7a7a4518..63fc1fc2ef 100644 --- a/errors/templates/ERR_CANNOT_FORWARD +++ b/errors/templates/ERR_CANNOT_FORWARD @@ -23,7 +23,14 @@ body

Unable to forward this request at this time.

-

This request could not be forwarded to the origin server or to any parent caches. The most likely cause for this error is that the cache administrator does not allow this cache to make direct connections to origin servers, and all configured parent caches are currently unreachable.

+

This request could not be forwarded to the origin server or to any parent caches.

+ +

Some possible problems are:

+

Your cache administrator is %w.

diff --git a/src/PeerSelectState.h b/src/PeerSelectState.h index 7a323ac9c0..639f041a4f 100644 --- a/src/PeerSelectState.h +++ b/src/PeerSelectState.h @@ -43,8 +43,9 @@ class HttpRequest; class StoreEntry; +class ErrorState; -typedef void PSC(Comm::ConnectionList *, void *); +typedef void PSC(Comm::ConnectionList *, ErrorState *, void *); SQUIDCEXTERN void peerSelect(Comm::ConnectionList *, HttpRequest *, StoreEntry *, PSC *, void *data); SQUIDCEXTERN void peerSelectInit(void); @@ -79,6 +80,7 @@ public: int direct; // TODO: fold always_direct/never_direct/prefer_direct into this now that ACL can do a multi-state result. PSC *callback; void *callback_data; + ErrorState *lastError; Comm::ConnectionList *paths; ///< the callers paths array. to be filled with our final results. FwdServer *servers; ///< temporary linked list of peers we will pass back. diff --git a/src/forward.cc b/src/forward.cc index 56f3c65471..c721013790 100644 --- a/src/forward.cc +++ b/src/forward.cc @@ -410,9 +410,11 @@ FwdState::complete() /**** CALLBACK WRAPPERS ************************************************************/ static void -fwdPeerSelectionCompleteWrapper(Comm::ConnectionList * unused, void *data) +fwdPeerSelectionCompleteWrapper(Comm::ConnectionList * unused, ErrorState *err, void *data) { FwdState *fwd = (FwdState *) data; + if (err) + fwd->fail(err); fwd->startConnectionOrFail(); } diff --git a/src/peer_select.cc b/src/peer_select.cc index dc1a0ea57c..13f31d4b2c 100644 --- a/src/peer_select.cc +++ b/src/peer_select.cc @@ -34,6 +34,7 @@ #include "squid.h" #include "DnsLookupDetails.h" +#include "errorpage.h" #include "event.h" #include "PeerSelectState.h" #include "Store.h" @@ -104,6 +105,8 @@ peerSelectStateFree(ps_state * psstate) psstate->entry = NULL; } + delete psstate->lastError; + cbdataFree(psstate); } @@ -265,7 +268,8 @@ peerSelectDnsPaths(ps_state *psstate) void *cbdata; if (cbdataReferenceValidDone(psstate->callback_data, &cbdata)) { - callback(psstate->paths, cbdata); + callback(psstate->paths, psstate->lastError, cbdata); + psstate->lastError = NULL; // FwdState has taken control over the ErrorState object. } peerSelectStateFree(psstate); @@ -317,6 +321,13 @@ peerSelectDnsResults(const ipcache_addrs *ia, const DnsLookupDetails &details, v } } else { debugs(44, 3, HERE << "Unknown host: " << fs->_peer ? fs->_peer->host : psstate->request->GetHost()); + // discard any previous error. + delete psstate->lastError; + psstate->lastError = NULL; + if (fs->code == HIER_DIRECT) { + psstate->lastError = new ErrorState(ERR_DNS_FAIL, HTTP_SERVICE_UNAVAILABLE, psstate->request); + psstate->lastError->dnsError = details.error; + } } psstate->servers = fs->next; @@ -899,6 +910,7 @@ ps_state::ps_state() : request (NULL), direct(DIRECT_UNKNOWN), callback (NULL), callback_data (NULL), + lastError(NULL), servers (NULL), first_parent_miss(), closest_parent_miss(), diff --git a/src/tunnel.cc b/src/tunnel.cc index 3344f79926..8c3cc4b05c 100644 --- a/src/tunnel.cc +++ b/src/tunnel.cc @@ -697,20 +697,23 @@ tunnelRelayConnectRequest(const Comm::ConnectionPointer &srv, void *data) } static void -tunnelPeerSelectComplete(Comm::ConnectionList *peer_paths, void *data) +tunnelPeerSelectComplete(Comm::ConnectionList *peer_paths, ErrorState *err, void *data) { TunnelStateData *tunnelState = (TunnelStateData *)data; if (peer_paths == NULL || peer_paths->size() < 1) { debugs(26, 3, HERE << "No paths found. Aborting CONNECT"); - ErrorState *err; - err = errorCon(ERR_CANNOT_FORWARD, HTTP_SERVICE_UNAVAILABLE, tunnelState->request); - *tunnelState->status_ptr = HTTP_SERVICE_UNAVAILABLE; + if (!err) { + err = errorCon(ERR_CANNOT_FORWARD, HTTP_SERVICE_UNAVAILABLE, tunnelState->request); + } + *tunnelState->status_ptr = err->httpStatus; err->callback = tunnelErrorComplete; err->callback_data = tunnelState; errorSend(tunnelState->client.conn, err); return; } + delete err; + debugs(26, 3, HERE << "paths=" << peer_paths->size() << ", p[0]={" << (*peer_paths)[0] << "}, serverDest[0]={" << tunnelState->serverDestinations[0] << "}");