<sect1>Changes to existing tags<label id="modifiedtags">
<p>
<descrip>
+ <tag>access_log</tag>
+ <p>TCP accept(2) errors logged with URI <em>error:accept-client-connection</em>.
+ <p>Unused connections received in <em>http_port</em> or <em>https_port</em>
+ or transactions terminated before reading[parsing] request headers
+ logged with URI <em>error:transaction-end-before-headers</em>.
+
<tag>acl</tag>
<p>New <em>-m</em> flag for <em>note</em> ACL to match substrings.
tests_testCacheManager_LDFLAGS = $(LIBADD_DL)
tests_testDiskIO_SOURCES = \
+ AccessLogEntry.cc \
+ AccessLogEntry.h \
CacheDigest.h \
tests/stub_CacheDigest.cc \
cbdata.cc \
tests/stub_libeui.cc \
tests/stub_libformat.cc \
tests/stub_libicmp.cc \
+ tests/stub_liblog.cc \
tests/stub_MemStore.cc \
mime.h \
tests/stub_mime.cc \
fs/libfs.la \
ipc/libipc.la \
$(REPL_OBJS) \
+ $(ADAPTATION_LIBS) \
DiskIO/libdiskio.la \
acl/libapi.la \
anyp/libanyp.la \
$(REPL_OBJS)
tests_testUfs_SOURCES = \
+ AccessLogEntry.cc \
+ AccessLogEntry.h \
tests/testUfs.cc \
tests/testUfs.h \
tests/stub_cache_manager.cc \
tests/stub_ipcache.cc \
tests/stub_libeui.cc \
tests/stub_libicmp.cc \
+ tests/stub_liblog.cc \
tests/stub_MemStore.cc \
tests/stub_neighbors.cc \
tests/stub_pconn.cc \
ip/libip.la \
mem/libmem.la \
store/libstore.la \
+ $(ADAPTATION_LIBS) \
sbuf/libsbuf.la \
$(top_builddir)/lib/libmisccontainers.la \
$(top_builddir)/lib/libmiscencoding.la \
$(XTRA_LIBS)
tests_testRock_SOURCES = \
+ AccessLogEntry.cc \
+ AccessLogEntry.h \
cbdata.cc \
CacheDigest.h \
CollapsedForwarding.h \
tests/stub_libeui.cc \
tests/stub_libformat.cc \
tests/stub_libicmp.cc \
+ tests/stub_liblog.cc \
tests/stub_libmgr.cc \
tests/stub_libsecurity.cc \
tests/stub_MemStore.cc \
base/libbase.la \
mem/libmem.la \
store/libstore.la \
+ $(ADAPTATION_LIBS) \
sbuf/libsbuf.la \
$(top_builddir)/lib/libmisccontainers.la \
$(top_builddir)/lib/libmiscencoding.la \
return requests.front();
}
+Http::StreamPointer
+Pipeline::back() const
+{
+ if (requests.empty()) {
+ debugs(33, 3, "Pipeline " << (void*)this << " empty");
+ return Http::StreamPointer();
+ }
+
+ debugs(33, 3, "Pipeline " << (void*)this << " back " << requests.back());
+ return requests.back();
+}
+
void
Pipeline::terminateAll(int xerrno)
{
/// get the first request context in the pipeline
Http::StreamPointer front() const;
+ /// get the last request context in the pipeline
+ Http::StreamPointer back() const;
+
/// how many requests are currently pipelined
size_t count() const {return requests.size();}
ConnStateData::swanSong()
{
debugs(33, 2, HERE << clientConnection);
+ checkLogging();
+
flags.readMore = false;
DeregisterRunner(this);
clientdbEstablished(clientConnection->remote, -1); /* decrement */
* connection has gone away */
}
+void
+ConnStateData::checkLogging()
+{
+ // if we are parsing request body, its request is responsible for logging
+ if (bodyPipe)
+ return;
+
+ // a request currently using this connection is responsible for logging
+ if (!pipeline.empty() && pipeline.back()->mayUseConnection())
+ return;
+
+ /* Either we are waiting for the very first transaction, or
+ * we are done with the Nth transaction and are waiting for N+1st.
+ * XXX: We assume that if anything was added to inBuf, then it could
+ * only be consumed by actions already covered by the above checks.
+ */
+
+ // do not log connections that closed after a transaction (it is normal)
+ // TODO: access_log needs ACLs to match received-no-bytes connections
+ // XXX: TLS may return here even though we got no transactions yet
+ // XXX: PROXY protocol may return here even though we got no
+ // transactions yet
+ if (receivedFirstByte_ && inBuf.isEmpty())
+ return;
+
+ /* Create a temporary ClientHttpRequest object. Its destructor will log. */
+ ClientHttpRequest http(this);
+ http.req_sz = inBuf.length();
+ char const *uri = "error:transaction-end-before-headers";
+ http.uri = xstrdup(uri);
+ setLogUri(&http, uri);
+}
private:
/* ::Server API */
virtual bool connFinishedWithConn(int size);
+ virtual void checkLogging();
void clientAfterReadingRequests();
bool concurrentRequestQueueFilled() const;
/* DEBUG: section 05 Listener Socket Handler */
#include "squid.h"
+#include "acl/FilledChecklist.h"
#include "anyp/PortCfg.h"
#include "base/TextException.h"
#include "client_db.h"
#include "globals.h"
#include "ip/Intercept.h"
#include "ip/QosConfig.h"
+#include "log/access_log.h"
#include "MasterXaction.h"
#include "profiler/Profiler.h"
#include "SquidConfig.h"
return false;
}
+static void
+logAcceptError(const Comm::ConnectionPointer &conn)
+{
+ AccessLogEntry::Pointer al = new AccessLogEntry;
+ al->tcpClient = conn;
+ al->url = "error:accept-client-connection";
+ ACLFilledChecklist ch(nullptr, nullptr, nullptr);
+ ch.src_addr = conn->remote;
+ ch.my_addr = conn->local;
+ accessLogLog(al, &ch);
+}
+
void
Comm::TcpAcceptor::acceptOne()
{
// A non-recoverable error; notify the caller */
debugs(5, 5, HERE << "non-recoverable error:" << status() << " handler Subscription: " << theCallSub);
+ if (intendedForUserConnections())
+ logAcceptError(newConnDetails);
notify(flag, newConnDetails);
mustStop("Listener socket closed");
return;
Comm::Flag oldAccept(Comm::ConnectionPointer &details);
void setListen();
void handleClosure(const CommCloseCbParams &io);
+ /// whether we are listening on one of the squid.conf *ports
+ bool intendedForUserConnections() const { return bool(listenPort_); }
};
} // namespace Comm
// case Comm::COMM_ERROR:
default: // no other flags should ever occur
debugs(33, 2, io.conn << ": got flag " << rd.flag << "; " << xstrerr(rd.xerrno));
+ checkLogging();
pipeline.terminateAll(rd.xerrno);
io.conn->close();
return;
void doClientRead(const CommIoCbParams &io);
void clientWriteDone(const CommIoCbParams &io);
+ /// Log the current [attempt at] transaction if nobody else will.
+ virtual void checkLogging() = 0;
+
AsyncCall::Pointer reader; ///< set when we are reading
AsyncCall::Pointer writer; ///< set when we are writing
};
#include "squid.h"
#include "comm/Connection.h"
#include "ICP.h"
-#include "icp_opcode.h"
#define STUB_API "icp_*.cc"
#include "tests/STUB.h"
int icpSetCacheKey(const cache_key * key) STUB_RETVAL(0)
const cache_key *icpGetCacheKey(const char *url, int reqnum) STUB_RETVAL(NULL)
+#include "icp_opcode.h"
+// dynamically generated
+#include "icp_opcode.cc"
+
#define STUB_API "log/liblog.la"
#include "tests/STUB.h"
+// XXX: these should be moved to a log/ *.h file
+#include "AccessLogEntry.h"
+/*
+AccessLogEntry::~AccessLogEntry() {STUB}
+void AccessLogEntry::getLogClientIp(char *, size_t) const STUB
+SBuf AccessLogEntry::getLogMethod() const STUB_RETVAL(SBuf())
+#if USE_OPENSSL
+AccessLogEntry::SslDetails::SslDetails() {STUB}
+#endif
+*/
+void accessLogLogTo(CustomLog *, AccessLogEntry::Pointer &, ACLChecklist *) STUB
+void accessLogLog(AccessLogEntry::Pointer &, ACLChecklist *) STUB
+void accessLogRotate(void) STUB
+void accessLogClose(void) STUB
+void accessLogInit(void) STUB
+const char *accessLogTime(time_t) STUB_RETVAL(nullptr)
+
#include "log/access_log.h"
void fvdbCountVia(const char *) STUB
void fvdbCountForw(const char *) STUB