Log TOS and Netfilter marks set by Squid This patch add new logformat codes to log TOS/DSCP values and netfilter marks for client and server connections. If multiple outgoing connections were used, the last used connection value logged. The values printed in hexadecimal form. The logformat codes are: %>qos Client connection TOS/DSCP value set by Squid %nfmark Client connection netfilter mark set by Squid %pop(serverDestinations[0], host, checkRetriable()); const bool openedPconn = Comm::IsConnOpen(temp); pconnRace = openedPconn ? racePossible : raceImpossible; // if we found an open persistent connection to use. use it. if (openedPconn) { serverConn = temp; flags.connected_okay = true; debugs(17, 3, HERE << "reusing pconn " << serverConnection()); ++n_tries; comm_add_close_handler(serverConnection()->fd, fwdServerClosedWrapper, this); /* Update server side TOS and Netfilter mark on the connection. */ if (Ip::Qos::TheConfig.isAclTosActive()) { - temp->tos = GetTosToServer(request); - Ip::Qos::setSockTos(temp, temp->tos); + const tos_t tos = GetTosToServer(request); + Ip::Qos::setSockTos(temp, tos); } #if SO_MARK if (Ip::Qos::TheConfig.isAclNfmarkActive()) { - temp->nfmark = GetNfmarkToServer(request); - Ip::Qos::setSockNfmark(temp, temp->nfmark); + const nfmark_t nfmark = GetNfmarkToServer(request); + Ip::Qos::setSockNfmark(temp, nfmark); } #endif dispatch(); return; } // We will try to open a new connection, possibly to the same destination. // We reset serverDestinations[0] in case we are using it again because // ConnOpener modifies its destination argument. serverDestinations[0]->local.port(0); serverConn = NULL; #if URL_CHECKSUM_DEBUG entry->mem_obj->checkUrlChecksum(); #endif /* Get the server side TOS and Netfilter mark to be set on the connection. */ if (Ip::Qos::TheConfig.isAclTosActive()) { serverDestinations[0]->tos = GetTosToServer(request); === modified file 'src/cf.data.pre' --- src/cf.data.pre 2013-06-18 06:22:13 +0000 +++ src/cf.data.pre 2013-07-15 07:18:27 +0000 @@ -3670,40 +3670,44 @@ adaptation_meta configuration parameter. If no argument given all meta headers logged. Connection related format codes: >a Client source IP address >A Client FQDN >p Client source port >eui Client source EUI (MAC address, EUI-48 or EUI-64 identifier) >la Local IP address the client connected to >lp Local port number the client connected to la Local listening IP address the client connection was connected to. lp Local listening port number the client connection was connected to. qos Client connection TOS/DSCP value set by Squid + nfmark Client connection netfilter mark set by Squid + = 0) { debugs(5, 4, "BUG #3329: Orphan Comm::Connection: " << *this); debugs(5, 4, "NOTE: " << ++lost_conn << " Orphans since last started."); close(); } cbdataReferenceDone(peer_); } Comm::ConnectionPointer Comm::Connection::copyDetails() const { ConnectionPointer c = new Comm::Connection; c->local = local; c->remote = remote; c->peerType = peerType; c->tos = tos; + c->nfmark = nfmark; c->flags = flags; // ensure FD is not open in the new copy. c->fd = -1; // ensure we have a cbdata reference to peer_ not a straight ptr copy. c->peer_ = cbdataReference(getPeer()); return c; } void Comm::Connection::close() { if (isOpen()) { comm_close(fd); fd = -1; if (CachePeer *p=getPeer()) -- p->stats.conn_open; } === modified file 'src/format/ByteCode.h' --- src/format/ByteCode.h 2013-02-11 23:11:12 +0000 +++ src/format/ByteCode.h 2013-07-15 07:26:42 +0000 @@ -180,35 +180,39 @@ LFT_ICAP_REQ_HEADER_ELEM, LFT_ICAP_REQ_ALL_HEADERS, LFT_ICAP_REP_HEADER, LFT_ICAP_REP_HEADER_ELEM, LFT_ICAP_REP_ALL_HEADERS, LFT_ICAP_TR_RESPONSE_TIME, LFT_ICAP_IO_TIME, LFT_ICAP_OUTCOME, LFT_ICAP_STATUS_CODE, #endif #if USE_SSL LFT_SSL_BUMP_MODE, LFT_SSL_USER_CERT_SUBJECT, LFT_SSL_USER_CERT_ISSUER, #endif LFT_NOTE, + LFT_CLIENT_LOCAL_TOS, + LFT_SERVER_LOCAL_TOS, + LFT_CLIENT_LOCAL_NFMARK, + LFT_SERVER_LOCAL_NFMARK, LFT_PERCENT /* special string cases for escaped chars */ } ByteCode_t; /// Quoting style for a format output. enum Quoting { LOG_QUOTE_NONE = 0, LOG_QUOTE_QUOTES, LOG_QUOTE_MIMEBLOB, LOG_QUOTE_URL, LOG_QUOTE_RAW }; } // namespace Format #endif /* _SQUID_FMT_BYTECODE_H */ === modified file 'src/format/Format.cc' --- src/format/Format.cc 2013-06-11 09:25:07 +0000 +++ src/format/Format.cc 2013-07-15 07:28:57 +0000 @@ -1029,40 +1029,69 @@ } case LFT_SSL_USER_CERT_SUBJECT: if (X509 *cert = al->cache.sslClientCert.get()) { if (X509_NAME *subject = X509_get_subject_name(cert)) { X509_NAME_oneline(subject, tmp, sizeof(tmp)); out = tmp; } } break; case LFT_SSL_USER_CERT_ISSUER: if (X509 *cert = al->cache.sslClientCert.get()) { if (X509_NAME *issuer = X509_get_issuer_name(cert)) { X509_NAME_oneline(issuer, tmp, sizeof(tmp)); out = tmp; } } break; #endif + + case LFT_CLIENT_LOCAL_TOS: + if (al->tcpClient != NULL) { + snprintf(tmp, sizeof(tmp), "0x%x", (uint32_t)al->tcpClient->tos); + out = tmp; + } + break; + + case LFT_SERVER_LOCAL_TOS: + if (al->hier.tcpServer != NULL) { + snprintf(tmp, sizeof(tmp), "0x%x", (uint32_t)al->hier.tcpServer->tos); + out = tmp; + } + break; + + case LFT_CLIENT_LOCAL_NFMARK: + if (al->tcpClient != NULL) { + snprintf(tmp, sizeof(tmp), "0x%x", al->tcpClient->nfmark); + out = tmp; + } + break; + + case LFT_SERVER_LOCAL_NFMARK: + if (al->hier.tcpServer != NULL) { + snprintf(tmp, sizeof(tmp), "0x%x", al->hier.tcpServer->nfmark); + out = tmp; + } + break; + case LFT_NOTE: if (fmt->data.string) { #if USE_ADAPTATION Adaptation::History::Pointer ah = al->request ? al->request->adaptHistory() : Adaptation::History::Pointer(); if (ah != NULL && ah->metaHeaders != NULL) { if (const char *meta = ah->metaHeaders->find(fmt->data.string)) sb.append(meta); } #endif if (al->notes != NULL) { if (const char *note = al->notes->find(fmt->data.string)) { if (sb.size()) sb.append(", "); sb.append(note); } } out = sb.termedBuf(); quote = 1; } else { #if USE_ADAPTATION === modified file 'src/format/Token.cc' --- src/format/Token.cc 2013-05-22 01:04:34 +0000 +++ src/format/Token.cc 2013-07-15 07:28:12 +0000 @@ -29,41 +29,40 @@ {">v", LFT_REQUEST_VERSION_OLD_2X}, {"%", LFT_PERCENT}, {NULL, LFT_NONE} /* this must be last */ }; /// 2-char tokens static TokenTableEntry TokenTable2C[] = { {">la", LFT_CLIENT_LOCAL_IP}, {"la", LFT_LOCAL_LISTENING_IP}, {">lp", LFT_CLIENT_LOCAL_PORT}, {"lp", LFT_LOCAL_LISTENING_PORT}, /*{ "lA", LFT_LOCAL_NAME }, */ {"ha", LFT_ADAPTED_REQUEST_HEADER}, {">ha", LFT_ADAPTED_REQUEST_ALL_HEADERS}, {"un", LFT_USER_NAME}, {"ul", LFT_USER_LOGIN}, /*{ "ur", LFT_USER_REALM }, */ /*{ "us", LFT_USER_SCHEME }, */ {"ui", LFT_USER_IDENT}, {"ue", LFT_USER_EXTERNAL}, @@ -105,40 +104,44 @@ {"2 byte tokens static TokenTableEntry TokenTableMisc[] = { {">eui", LFT_CLIENT_EUI}, + {">qos", LFT_CLIENT_LOCAL_TOS}, + {"nfmark", LFT_CLIENT_LOCAL_NFMARK}, + {"fd, IPPROTO_IP, IP_TOS, &bTos, sizeof(bTos)); if (x < 0) debugs(50, 2, "Ip::Qos::setSockTos: setsockopt(IP_TOS) on " << conn << ": " << xstrerror()); + else + conn->tos = tos; return x; #else debugs(50, DBG_IMPORTANT, "WARNING: setsockopt(IP_TOS) not supported on this platform"); return -1; #endif } int Ip::Qos::setSockNfmark(const Comm::ConnectionPointer &conn, nfmark_t mark) { #if SO_MARK && USE_LIBCAP int x = setsockopt(conn->fd, SOL_SOCKET, SO_MARK, &mark, sizeof(nfmark_t)); if (x < 0) debugs(50, 2, "setSockNfmark: setsockopt(SO_MARK) on " << conn << ": " << xstrerror()); + else + conn->nfmark = mark; return x; #elif USE_LIBCAP debugs(50, DBG_IMPORTANT, "WARNING: setsockopt(SO_MARK) not supported on this platform"); return -1; #else debugs(50, DBG_IMPORTANT, "WARNING: Netfilter marking disabled (netfilter marking requires build with LIBCAP)"); return -1; #endif } bool Ip::Qos::Config::isHitTosActive() const { return (tosLocalHit || tosSiblingHit || tosParentHit || tosMiss || preserveMissTos); } bool Ip::Qos::Config::isHitNfmarkActive() const { return (markLocalHit || markSiblingHit || markParentHit || markMiss || preserveMissMark);