2 * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
10 #include "AccessLogEntry.h"
11 #include "client_side.h"
12 #include "comm/Connection.h"
13 #include "err_detail_type.h"
14 #include "errorpage.h"
16 #include "format/Format.h"
17 #include "format/Quoting.h"
18 #include "format/Token.h"
19 #include "fqdncache.h"
20 #include "HttpRequest.h"
23 #include "SquidTime.h"
28 #include "ssl/ErrorDetail.h"
29 #include "ssl/ServerBump.h"
32 /// Convert a string to NULL pointer if it is ""
33 #define strOrNull(s) ((s)==NULL||(s)[0]=='\0'?NULL:(s))
35 Format::Format::Format(const char *n
) :
42 Format::Format::~Format()
44 // erase the list without consuming stack space
46 // unlink the next entry for deletion
59 Format::Format::parse(const char *def
)
61 const char *cur
, *eos
;
62 Token
*new_lt
, *last_lt
;
63 enum Quoting quote
= LOG_QUOTE_NONE
;
65 debugs(46, 2, HERE
<< "got definition '" << def
<< "'");
68 debugs(46, DBG_IMPORTANT
, "WARNING: existing format for '" << name
<< " " << def
<< "'");
72 /* very inefficent parser, but who cares, this needs to be simple */
73 /* First off, let's tokenize, we'll optimize in a second pass.
74 * A token can either be a %-prefixed sequence (usually a dynamic
75 * token but it can be an escaped sequence), or a string. */
77 eos
= def
+ strlen(def
);
78 format
= new_lt
= last_lt
= new Token
;
79 cur
+= new_lt
->parse(cur
, "e
);
83 last_lt
->next
= new_lt
;
85 cur
+= new_lt
->parse(cur
, "e
);
92 Format::Format::dump(StoreEntry
* entry
, const char *directiveName
, bool eol
) const
96 // loop rather than recursing to conserve stack space.
97 for (const Format
*fmt
= this; fmt
; fmt
= fmt
->next
) {
98 debugs(46, 3, HERE
<< "Dumping format definition for " << fmt
->name
);
100 storeAppendPrintf(entry
, "%s %s ", directiveName
, fmt
->name
);
102 for (Token
*t
= fmt
->format
; t
; t
= t
->next
) {
103 if (t
->type
== LFT_STRING
)
104 storeAppendPrintf(entry
, "%s", t
->data
.string
);
108 ByteCode_t type
= t
->type
;
116 case LFT_ADAPTATION_LAST_HEADER_ELEM
:
119 case LFT_ICAP_REQ_HEADER_ELEM
:
120 case LFT_ICAP_REP_HEADER_ELEM
:
122 case LFT_REQUEST_HEADER_ELEM
:
123 case LFT_ADAPTED_REQUEST_HEADER_ELEM
:
124 case LFT_REPLY_HEADER_ELEM
:
126 if (t
->data
.header
.separator
!= ',')
127 snprintf(argbuf
, sizeof(argbuf
), "%s:%c%s", t
->data
.header
.header
, t
->data
.header
.separator
, t
->data
.header
.element
);
129 snprintf(argbuf
, sizeof(argbuf
), "%s:%s", t
->data
.header
.header
, t
->data
.header
.element
);
134 case LFT_REQUEST_HEADER_ELEM
:
135 type
= LFT_REQUEST_HEADER_ELEM
; // XXX: remove _ELEM?
137 case LFT_ADAPTED_REQUEST_HEADER_ELEM
:
138 type
= LFT_ADAPTED_REQUEST_HEADER_ELEM
; // XXX: remove _ELEM?
140 case LFT_REPLY_HEADER_ELEM
:
141 type
= LFT_REPLY_HEADER_ELEM
; // XXX: remove _ELEM?
144 case LFT_ADAPTATION_LAST_HEADER_ELEM
:
145 type
= LFT_ADAPTATION_LAST_HEADER
;
149 case LFT_ICAP_REQ_HEADER_ELEM
:
150 type
= LFT_ICAP_REQ_HEADER
;
152 case LFT_ICAP_REP_HEADER_ELEM
:
153 type
= LFT_ICAP_REP_HEADER
;
162 case LFT_REQUEST_ALL_HEADERS
:
163 case LFT_ADAPTED_REQUEST_ALL_HEADERS
:
164 case LFT_REPLY_ALL_HEADERS
:
167 case LFT_ADAPTATION_LAST_ALL_HEADERS
:
170 case LFT_ICAP_REQ_ALL_HEADERS
:
171 case LFT_ICAP_REP_ALL_HEADERS
:
175 case LFT_REQUEST_ALL_HEADERS
:
176 type
= LFT_REQUEST_HEADER
;
178 case LFT_ADAPTED_REQUEST_ALL_HEADERS
:
179 type
= LFT_ADAPTED_REQUEST_HEADER
;
181 case LFT_REPLY_ALL_HEADERS
:
182 type
= LFT_REPLY_HEADER
;
185 case LFT_ADAPTATION_LAST_ALL_HEADERS
:
186 type
= LFT_ADAPTATION_LAST_HEADER
;
190 case LFT_ICAP_REQ_ALL_HEADERS
:
191 type
= LFT_ICAP_REQ_HEADER
;
193 case LFT_ICAP_REP_ALL_HEADERS
:
194 type
= LFT_ICAP_REP_HEADER
;
205 arg
= t
->data
.string
;
210 entry
->append("%", 1);
214 case LOG_QUOTE_QUOTES
:
215 entry
->append("\"", 1);
218 case LOG_QUOTE_MIMEBLOB
:
219 entry
->append("[", 1);
223 entry
->append("#", 1);
227 entry
->append("'", 1);
230 case LOG_QUOTE_SHELL
:
231 entry
->append("/", 1);
239 entry
->append("-", 1);
242 entry
->append("0", 1);
244 if (t
->widthMin
>= 0)
245 storeAppendPrintf(entry
, "%d", t
->widthMin
);
247 if (t
->widthMax
>= 0)
248 storeAppendPrintf(entry
, ".%d", t
->widthMax
);
251 storeAppendPrintf(entry
, "{%s}", arg
);
253 storeAppendPrintf(entry
, "%s", t
->label
);
256 entry
->append(" ", 1);
261 entry
->append("\n", 1);
267 log_quoted_string(const char *str
, char *out
)
272 int l
= strcspn(str
, "\"\\\r\n\t");
321 sslErrorName(Ssl::ssl_error_t err
, char *buf
, size_t size
)
323 snprintf(buf
, size
, "SSL_ERR=%d", err
);
329 Format::Format::assemble(MemBuf
&mb
, const AccessLogEntry::Pointer
&al
, int logSequenceNumber
) const
334 for (Token
*fmt
= format
; fmt
!= NULL
; fmt
= fmt
->next
) { /* for each token */
335 const char *out
= NULL
;
342 struct timeval outtv
= {0, 0};
353 out
= fmt
->data
.string
;
356 case LFT_CLIENT_IP_ADDRESS
:
357 al
->getLogClientIp(tmp
, sizeof(tmp
));
361 case LFT_CLIENT_FQDN
:
362 if (al
->cache
.caddr
.isAnyAddr()) // e.g., ICAP OPTIONS lack client
365 out
= fqdncache_gethostbyaddr(al
->cache
.caddr
, FQDN_LOOKUP_IF_MISS
);
367 out
= al
->cache
.caddr
.toStr(tmp
,1024);
372 case LFT_CLIENT_PORT
:
374 outint
= al
->request
->client_addr
.port();
381 // TODO make the ACL checklist have a direct link to any TCP details.
382 if (al
->request
&& al
->request
->clientConnectionManager
.valid() && al
->request
->clientConnectionManager
->clientConnection
!= NULL
) {
383 if (al
->request
->clientConnectionManager
->clientConnection
->remote
.isIPv4())
384 al
->request
->clientConnectionManager
->clientConnection
->remoteEui48
.encode(tmp
, 1024);
386 al
->request
->clientConnectionManager
->clientConnection
->remoteEui64
.encode(tmp
, 1024);
392 case LFT_EXT_ACL_CLIENT_EUI48
:
394 if (al
->request
&& al
->request
->clientConnectionManager
.valid() &&
395 al
->request
->clientConnectionManager
->clientConnection
!= NULL
&&
396 al
->request
->clientConnectionManager
->clientConnection
->remote
.isIPv4()) {
397 al
->request
->clientConnectionManager
->clientConnection
->remoteEui48
.encode(tmp
, 1024);
403 case LFT_EXT_ACL_CLIENT_EUI64
:
405 if (al
->request
&& al
->request
->clientConnectionManager
.valid() &&
406 al
->request
->clientConnectionManager
->clientConnection
!= NULL
&&
407 !al
->request
->clientConnectionManager
->clientConnection
->remote
.isIPv4()) {
408 al
->request
->clientConnectionManager
->clientConnection
->remoteEui64
.encode(tmp
, 1024);
414 case LFT_SERVER_IP_ADDRESS
:
415 if (al
->hier
.tcpServer
!= NULL
) {
416 out
= al
->hier
.tcpServer
->remote
.toStr(tmp
,sizeof(tmp
));
420 case LFT_SERVER_FQDN_OR_PEER_NAME
:
424 case LFT_SERVER_PORT
:
425 if (al
->hier
.tcpServer
!= NULL
) {
426 outint
= al
->hier
.tcpServer
->remote
.port();
431 case LFT_LOCAL_LISTENING_IP
: {
432 // avoid logging a dash if we have reliable info
433 const bool interceptedAtKnownPort
= al
->request
?
434 (al
->request
->flags
.interceptTproxy
||
435 al
->request
->flags
.intercepted
) && al
->cache
.port
!= NULL
:
437 if (interceptedAtKnownPort
) {
438 const bool portAddressConfigured
= !al
->cache
.port
->s
.isAnyAddr();
439 if (portAddressConfigured
)
440 out
= al
->cache
.port
->s
.toStr(tmp
, sizeof(tmp
));
441 } else if (al
->tcpClient
!= NULL
)
442 out
= al
->tcpClient
->local
.toStr(tmp
, sizeof(tmp
));
446 case LFT_CLIENT_LOCAL_IP
:
447 if (al
->tcpClient
!= NULL
) {
448 out
= al
->tcpClient
->local
.toStr(tmp
,sizeof(tmp
));
452 case LFT_CLIENT_LOCAL_TOS
:
453 if (al
->tcpClient
!= NULL
) {
454 snprintf(tmp
, sizeof(tmp
), "0x%x", (uint32_t)al
->tcpClient
->tos
);
459 case LFT_CLIENT_LOCAL_NFMARK
:
460 if (al
->tcpClient
!= NULL
) {
461 snprintf(tmp
, sizeof(tmp
), "0x%x", al
->tcpClient
->nfmark
);
466 case LFT_LOCAL_LISTENING_PORT
:
467 if (al
->cache
.port
!= NULL
) {
468 outint
= al
->cache
.port
->s
.port();
470 } else if (al
->request
) {
471 outint
= al
->request
->my_addr
.port();
476 case LFT_CLIENT_LOCAL_PORT
:
477 if (al
->tcpClient
!= NULL
) {
478 outint
= al
->tcpClient
->local
.port();
483 case LFT_SERVER_LOCAL_IP_OLD_27
:
484 case LFT_SERVER_LOCAL_IP
:
485 if (al
->hier
.tcpServer
!= NULL
) {
486 out
= al
->hier
.tcpServer
->local
.toStr(tmp
,sizeof(tmp
));
490 case LFT_SERVER_LOCAL_PORT
:
491 if (al
->hier
.tcpServer
!= NULL
) {
492 outint
= al
->hier
.tcpServer
->local
.port();
498 case LFT_SERVER_LOCAL_TOS
:
499 if (al
->hier
.tcpServer
!= NULL
) {
500 snprintf(tmp
, sizeof(tmp
), "0x%x", (uint32_t)al
->hier
.tcpServer
->tos
);
505 case LFT_SERVER_LOCAL_NFMARK
:
506 if (al
->hier
.tcpServer
!= NULL
) {
507 snprintf(tmp
, sizeof(tmp
), "0x%x", al
->hier
.tcpServer
->nfmark
);
512 case LFT_TIME_SECONDS_SINCE_EPOCH
:
513 // some platforms store time in 32-bit, some 64-bit...
514 outoff
= static_cast<int64_t>(current_time
.tv_sec
);
518 case LFT_TIME_SUBSECOND
:
519 outint
= current_time
.tv_usec
/ fmt
->divisor
;
523 case LFT_TIME_LOCALTIME
:
529 spec
= fmt
->data
.string
;
531 if (fmt
->type
== LFT_TIME_LOCALTIME
) {
533 spec
= "%d/%b/%Y:%H:%M:%S %z";
534 t
= localtime(&squid_curtime
);
537 spec
= "%d/%b/%Y:%H:%M:%S";
539 t
= gmtime(&squid_curtime
);
542 strftime(tmp
, sizeof(tmp
), spec
, t
);
550 outtv
= al
->cache
.start_time
;
554 case LFT_TIME_TO_HANDLE_REQUEST
:
555 outtv
= al
->cache
.trTime
;
559 case LFT_PEER_RESPONSE_TIME
:
560 if (al
->hier
.peer_response_time
.tv_sec
== -1) {
563 outtv
= al
->hier
.peer_response_time
;
568 case LFT_TOTAL_SERVER_SIDE_RESPONSE_TIME
: {
569 timeval total_response_time
;
570 al
->hier
.totalResponseTime(total_response_time
);
571 if (total_response_time
.tv_sec
== -1) {
574 outtv
= total_response_time
;
580 case LFT_DNS_WAIT_TIME
:
581 if (al
->request
&& al
->request
->dnsWait
>= 0) {
582 // TODO: microsecond precision for dns wait time.
583 // Convert miliseconds to timeval struct:
584 outtv
.tv_sec
= al
->request
->dnsWait
/ 1000;
585 outtv
.tv_usec
= (al
->request
->dnsWait
% 1000) * 1000;
590 case LFT_REQUEST_HEADER
:
593 sb
= al
->request
->header
.getByName(fmt
->data
.header
.header
);
595 out
= sb
.termedBuf();
601 case LFT_ADAPTED_REQUEST_HEADER
:
603 if (al
->adapted_request
)
604 sb
= al
->adapted_request
->header
.getByName(fmt
->data
.header
.header
);
606 out
= sb
.termedBuf();
612 case LFT_REPLY_HEADER
:
614 sb
= al
->reply
->header
.getByName(fmt
->data
.header
.header
);
616 out
= sb
.termedBuf();
623 case LFT_ADAPTATION_SUM_XACT_TIMES
:
625 Adaptation::History::Pointer ah
= al
->request
->adaptHistory();
627 ah
->sumLogString(fmt
->data
.string
, sb
);
628 out
= sb
.termedBuf();
632 case LFT_ADAPTATION_ALL_XACT_TIMES
:
634 Adaptation::History::Pointer ah
= al
->request
->adaptHistory();
636 ah
->allLogString(fmt
->data
.string
, sb
);
637 out
= sb
.termedBuf();
641 case LFT_ADAPTATION_LAST_HEADER
:
643 const Adaptation::History::Pointer ah
= al
->request
->adaptHistory();
644 if (ah
!= NULL
) // XXX: add adapt::<all_h but use lastMeta here
645 sb
= ah
->allMeta
.getByName(fmt
->data
.header
.header
);
648 // XXX: here and elsewhere: move such code inside the if guard
649 out
= sb
.termedBuf();
655 case LFT_ADAPTATION_LAST_HEADER_ELEM
:
657 const Adaptation::History::Pointer ah
= al
->request
->adaptHistory();
658 if (ah
!= NULL
) // XXX: add adapt::<all_h but use lastMeta here
659 sb
= ah
->allMeta
.getByNameListMember(fmt
->data
.header
.header
, fmt
->data
.header
.element
, fmt
->data
.header
.separator
);
662 out
= sb
.termedBuf();
668 case LFT_ADAPTATION_LAST_ALL_HEADERS
:
669 out
= al
->adapt
.last_meta
;
679 out
= al
->icap
.hostAddr
.toStr(tmp
,1024);
682 case LFT_ICAP_SERV_NAME
:
683 out
= al
->icap
.serviceName
.termedBuf();
686 case LFT_ICAP_REQUEST_URI
:
687 out
= al
->icap
.reqUri
.termedBuf();
690 case LFT_ICAP_REQUEST_METHOD
:
691 out
= Adaptation::Icap::ICAP::methodStr(al
->icap
.reqMethod
);
694 case LFT_ICAP_BYTES_SENT
:
695 outoff
= al
->icap
.bytesSent
;
699 case LFT_ICAP_BYTES_READ
:
700 outoff
= al
->icap
.bytesRead
;
704 case LFT_ICAP_BODY_BYTES_READ
:
705 if (al
->icap
.bodyBytesRead
>= 0) {
706 outoff
= al
->icap
.bodyBytesRead
;
709 // else if icap.bodyBytesRead < 0, we do not have any http data,
710 // so just print a "-" (204 responses etc)
713 case LFT_ICAP_REQ_HEADER
:
714 if (NULL
!= al
->icap
.request
) {
715 sb
= al
->icap
.request
->header
.getByName(fmt
->data
.header
.header
);
716 out
= sb
.termedBuf();
721 case LFT_ICAP_REQ_HEADER_ELEM
:
722 if (al
->icap
.request
)
723 sb
= al
->icap
.request
->header
.getByNameListMember(fmt
->data
.header
.header
, fmt
->data
.header
.element
, fmt
->data
.header
.separator
);
725 out
= sb
.termedBuf();
731 case LFT_ICAP_REQ_ALL_HEADERS
:
732 if (al
->icap
.request
) {
733 HttpHeaderPos pos
= HttpHeaderInitPos
;
734 while (const HttpHeaderEntry
*e
= al
->icap
.request
->header
.getEntry(&pos
)) {
740 out
= sb
.termedBuf();
745 case LFT_ICAP_REP_HEADER
:
746 if (NULL
!= al
->icap
.reply
) {
747 sb
= al
->icap
.reply
->header
.getByName(fmt
->data
.header
.header
);
748 out
= sb
.termedBuf();
753 case LFT_ICAP_REP_HEADER_ELEM
:
754 if (NULL
!= al
->icap
.reply
)
755 sb
= al
->icap
.reply
->header
.getByNameListMember(fmt
->data
.header
.header
, fmt
->data
.header
.element
, fmt
->data
.header
.separator
);
757 out
= sb
.termedBuf();
763 case LFT_ICAP_REP_ALL_HEADERS
:
764 if (al
->icap
.reply
) {
765 HttpHeaderPos pos
= HttpHeaderInitPos
;
766 while (const HttpHeaderEntry
*e
= al
->icap
.reply
->header
.getEntry(&pos
)) {
772 out
= sb
.termedBuf();
777 case LFT_ICAP_TR_RESPONSE_TIME
:
778 outtv
= al
->icap
.trTime
;
782 case LFT_ICAP_IO_TIME
:
783 outtv
= al
->icap
.ioTime
;
787 case LFT_ICAP_STATUS_CODE
:
788 outint
= al
->icap
.resStatus
;
792 case LFT_ICAP_OUTCOME
:
793 out
= al
->icap
.outcome
;
796 case LFT_ICAP_TOTAL_TIME
:
797 outtv
= al
->icap
.processingTime
;
801 case LFT_REQUEST_HEADER_ELEM
:
803 sb
= al
->request
->header
.getByNameListMember(fmt
->data
.header
.header
, fmt
->data
.header
.element
, fmt
->data
.header
.separator
);
805 out
= sb
.termedBuf();
811 case LFT_ADAPTED_REQUEST_HEADER_ELEM
:
812 if (al
->adapted_request
)
813 sb
= al
->adapted_request
->header
.getByNameListMember(fmt
->data
.header
.header
, fmt
->data
.header
.element
, fmt
->data
.header
.separator
);
815 out
= sb
.termedBuf();
821 case LFT_REPLY_HEADER_ELEM
:
823 sb
= al
->reply
->header
.getByNameListMember(fmt
->data
.header
.header
, fmt
->data
.header
.element
, fmt
->data
.header
.separator
);
825 out
= sb
.termedBuf();
831 case LFT_REQUEST_ALL_HEADERS
:
832 out
= al
->headers
.request
;
838 case LFT_ADAPTED_REQUEST_ALL_HEADERS
:
839 out
= al
->headers
.adapted_request
;
845 case LFT_REPLY_ALL_HEADERS
:
846 out
= al
->headers
.reply
;
854 if (al
->request
&& al
->request
->auth_user_request
!= NULL
)
855 out
= strOrNull(al
->request
->auth_user_request
->username());
858 out
= strOrNull(al
->cache
.extuser
);
861 out
= strOrNull(al
->cache
.ssluser
);
864 out
= strOrNull(al
->cache
.rfc931
);
869 if (al
->request
&& al
->request
->auth_user_request
!= NULL
)
870 out
= strOrNull(al
->request
->auth_user_request
->username());
875 out
= strOrNull(al
->cache
.rfc931
);
878 case LFT_USER_EXTERNAL
:
879 if (al
->request
&& al
->request
->extacl_user
.size())
880 out
= al
->request
->extacl_user
.termedBuf();
883 out
= strOrNull(al
->cache
.extuser
);
886 /* case LFT_USER_REALM: */
887 /* case LFT_USER_SCHEME: */
889 // the fmt->type can not be LFT_HTTP_SENT_STATUS_CODE_OLD_30
890 // but compiler complains if ommited
891 case LFT_HTTP_SENT_STATUS_CODE_OLD_30
:
892 case LFT_HTTP_SENT_STATUS_CODE
:
893 outint
= al
->http
.code
;
899 case LFT_HTTP_RECEIVED_STATUS_CODE
:
900 if (al
->hier
.peer_reply_status
== Http::scNone
) {
903 outint
= al
->hier
.peer_reply_status
;
907 /* case LFT_HTTP_STATUS:
908 * out = statusline->text;
912 case LFT_HTTP_BODY_BYTES_READ
:
913 if (al
->hier
.bodyBytesRead
>= 0) {
914 outoff
= al
->hier
.bodyBytesRead
;
917 // else if hier.bodyBytesRead < 0 we did not have any data exchange with
918 // a peer server so just print a "-" (eg requests served from cache,
919 // or internal error messages).
922 case LFT_SQUID_STATUS
:
923 out
= al
->cache
.code
.c_str();
926 case LFT_SQUID_ERROR
:
927 if (al
->request
&& al
->request
->errType
!= ERR_NONE
)
928 out
= errorPageName(al
->request
->errType
);
931 case LFT_SQUID_ERROR_DETAIL
:
933 if (al
->request
&& al
->request
->errType
== ERR_SECURE_CONNECT_FAIL
) {
934 if (! (out
= Ssl::GetErrorName(al
->request
->errDetail
)))
935 out
= sslErrorName(al
->request
->errDetail
, tmp
, sizeof(tmp
));
938 if (al
->request
&& al
->request
->errDetail
!= ERR_DETAIL_NONE
) {
939 if (al
->request
->errDetail
> ERR_DETAIL_START
&& al
->request
->errDetail
< ERR_DETAIL_MAX
)
940 out
= errorDetailName(al
->request
->errDetail
);
942 if (al
->request
->errDetail
>= ERR_DETAIL_EXCEPTION_START
)
943 snprintf(tmp
, sizeof(tmp
), "%s=0x%X",
944 errorDetailName(al
->request
->errDetail
), (uint32_t) al
->request
->errDetail
);
946 snprintf(tmp
, sizeof(tmp
), "%s=%d",
947 errorDetailName(al
->request
->errDetail
), al
->request
->errDetail
);
953 case LFT_SQUID_HIERARCHY
:
954 if (al
->hier
.ping
.timedout
)
955 mb
.append("TIMEOUT_", 8);
957 out
= hier_code_str
[al
->hier
.code
];
962 out
= al
->http
.content_type
;
966 case LFT_CLIENT_REQ_METHOD
:
968 const SBuf
&s
= al
->request
->method
.image();
969 sb
.append(s
.rawContent(), s
.length());
970 out
= sb
.termedBuf();
975 case LFT_CLIENT_REQ_URI
:
976 // original client URI
978 const SBuf
&s
= al
->request
->effectiveRequestUri();
979 sb
.append(s
.rawContent(), s
.length());
980 out
= sb
.termedBuf();
985 case LFT_CLIENT_REQ_URLSCHEME
:
987 out
= al
->request
->url
.getScheme().c_str();
992 case LFT_CLIENT_REQ_URLDOMAIN
:
994 out
= al
->request
->url
.host();
999 case LFT_CLIENT_REQ_URLPORT
:
1001 outint
= al
->request
->url
.port();
1006 case LFT_REQUEST_URLPATH_OLD_31
:
1007 case LFT_CLIENT_REQ_URLPATH
:
1009 SBuf s
= al
->request
->url
.path();
1015 case LFT_CLIENT_REQ_VERSION
:
1017 snprintf(tmp
, sizeof(tmp
), "%d.%d", (int) al
->request
->http_ver
.major
, (int) al
->request
->http_ver
.minor
);
1022 case LFT_REQUEST_METHOD
:
1023 if (al
->_private
.method_str
) // ICP, HTCP method code
1024 out
= al
->_private
.method_str
;
1026 const SBuf
&s
= al
->http
.method
.image();
1027 sb
.append(s
.rawContent(), s
.length());
1028 out
= sb
.termedBuf();
1033 case LFT_REQUEST_URI
:
1037 case LFT_REQUEST_VERSION_OLD_2X
:
1038 case LFT_REQUEST_VERSION
:
1039 snprintf(tmp
, sizeof(tmp
), "%d.%d", (int) al
->http
.version
.major
, (int) al
->http
.version
.minor
);
1043 case LFT_SERVER_REQ_METHOD
:
1044 if (al
->adapted_request
) {
1045 const SBuf
&s
= al
->adapted_request
->method
.image();
1046 sb
.append(s
.rawContent(), s
.length());
1047 out
= sb
.termedBuf();
1052 case LFT_SERVER_REQ_URI
:
1053 // adapted request URI sent to server/peer
1054 if (al
->adapted_request
) {
1055 const SBuf
&s
= al
->adapted_request
->effectiveRequestUri();
1056 sb
.append(s
.rawContent(), s
.length());
1057 out
= sb
.termedBuf();
1062 case LFT_SERVER_REQ_URLSCHEME
:
1063 if (al
->adapted_request
) {
1064 out
= al
->adapted_request
->url
.getScheme().c_str();
1069 case LFT_SERVER_REQ_URLDOMAIN
:
1070 if (al
->adapted_request
) {
1071 out
= al
->adapted_request
->url
.host();
1076 case LFT_SERVER_REQ_URLPORT
:
1077 if (al
->adapted_request
) {
1078 outint
= al
->adapted_request
->url
.port();
1083 case LFT_SERVER_REQ_URLPATH
:
1084 if (al
->adapted_request
) {
1085 SBuf s
= al
->adapted_request
->url
.path();
1091 case LFT_SERVER_REQ_VERSION
:
1092 if (al
->adapted_request
) {
1093 snprintf(tmp
, sizeof(tmp
), "%d.%d",
1094 (int) al
->adapted_request
->http_ver
.major
,
1095 (int) al
->adapted_request
->http_ver
.minor
);
1100 case LFT_CLIENT_REQUEST_SIZE_TOTAL
:
1101 outoff
= al
->http
.clientRequestSz
.messageTotal();
1105 case LFT_CLIENT_REQUEST_SIZE_HEADERS
:
1106 outoff
= al
->http
.clientRequestSz
.header
;
1110 /*case LFT_REQUEST_SIZE_BODY: */
1111 /*case LFT_REQUEST_SIZE_BODY_NO_TE: */
1113 case LFT_ADAPTED_REPLY_SIZE_TOTAL
:
1114 outoff
= al
->http
.clientReplySz
.messageTotal();
1118 case LFT_REPLY_HIGHOFFSET
:
1119 outoff
= al
->cache
.highOffset
;
1125 case LFT_REPLY_OBJECTSIZE
:
1126 outoff
= al
->cache
.objectSize
;
1132 case LFT_ADAPTED_REPLY_SIZE_HEADERS
:
1133 outint
= al
->http
.clientReplySz
.header
;
1137 /*case LFT_REPLY_SIZE_BODY: */
1138 /*case LFT_REPLY_SIZE_BODY_NO_TE: */
1140 case LFT_CLIENT_IO_SIZE_TOTAL
:
1141 outint
= al
->http
.clientRequestSz
.messageTotal() + al
->http
.clientReplySz
.messageTotal();
1144 /*case LFT_SERVER_IO_SIZE_TOTAL: */
1148 out
= al
->request
->tag
.termedBuf();
1156 out
= al
->request
->extacl_log
.termedBuf();
1162 case LFT_SEQUENCE_NUMBER
:
1163 outoff
= logSequenceNumber
;
1168 case LFT_SSL_BUMP_MODE
: {
1169 const Ssl::BumpMode mode
= static_cast<Ssl::BumpMode
>(al
->ssl
.bumpMode
);
1170 // for Ssl::bumpEnd, Ssl::bumpMode() returns NULL and we log '-'
1171 out
= Ssl::bumpMode(mode
);
1175 case LFT_EXT_ACL_USER_CERT_RAW
:
1177 ConnStateData
*conn
= al
->request
->clientConnectionManager
.get();
1178 if (conn
!= NULL
&& Comm::IsConnOpen(conn
->clientConnection
)) {
1179 if (SSL
*ssl
= fd_table
[conn
->clientConnection
->fd
].ssl
)
1180 out
= sslGetUserCertificatePEM(ssl
);
1185 case LFT_EXT_ACL_USER_CERTCHAIN_RAW
:
1187 ConnStateData
*conn
= al
->request
->clientConnectionManager
.get();
1188 if (conn
!= NULL
&& Comm::IsConnOpen(conn
->clientConnection
)) {
1189 if (SSL
*ssl
= fd_table
[conn
->clientConnection
->fd
].ssl
)
1190 out
= sslGetUserCertificatePEM(ssl
);
1195 case LFT_EXT_ACL_USER_CERT
:
1197 ConnStateData
*conn
= al
->request
->clientConnectionManager
.get();
1198 if (conn
!= NULL
&& Comm::IsConnOpen(conn
->clientConnection
)) {
1199 if (SSL
*ssl
= fd_table
[conn
->clientConnection
->fd
].ssl
)
1200 out
= sslGetUserAttribute(ssl
, format
->data
.header
.header
);
1205 case LFT_EXT_ACL_USER_CA_CERT
:
1207 ConnStateData
*conn
= al
->request
->clientConnectionManager
.get();
1208 if (conn
!= NULL
&& Comm::IsConnOpen(conn
->clientConnection
)) {
1209 if (SSL
*ssl
= fd_table
[conn
->clientConnection
->fd
].ssl
)
1210 out
= sslGetCAAttribute(ssl
, format
->data
.header
.header
);
1215 case LFT_SSL_USER_CERT_SUBJECT
:
1216 if (X509
*cert
= al
->cache
.sslClientCert
.get()) {
1217 if (X509_NAME
*subject
= X509_get_subject_name(cert
)) {
1218 X509_NAME_oneline(subject
, tmp
, sizeof(tmp
));
1224 case LFT_SSL_USER_CERT_ISSUER
:
1225 if (X509
*cert
= al
->cache
.sslClientCert
.get()) {
1226 if (X509_NAME
*issuer
= X509_get_issuer_name(cert
)) {
1227 X509_NAME_oneline(issuer
, tmp
, sizeof(tmp
));
1233 case LFT_SSL_CLIENT_SNI
:
1234 if (al
->request
&& al
->request
->clientConnectionManager
.valid()) {
1235 if (Ssl::ServerBump
* srvBump
= al
->request
->clientConnectionManager
->serverBump()) {
1236 if (!srvBump
->clientSni
.isEmpty())
1237 out
= srvBump
->clientSni
.c_str();
1242 case LFT_SSL_SERVER_CERT_ERRORS
:
1243 if (al
->request
&& al
->request
->clientConnectionManager
.valid()) {
1244 if (Ssl::ServerBump
* srvBump
= al
->request
->clientConnectionManager
->serverBump()) {
1245 const char *separator
= fmt
->data
.string
? fmt
->data
.string
: ":";
1246 for (Ssl::CertErrors
*sslError
= srvBump
->sslErrors
; sslError
!= NULL
; sslError
= sslError
->next
) {
1248 sb
.append(separator
);
1249 if (const char *errorName
= Ssl::GetErrorName(sslError
->element
.code
))
1250 sb
.append(errorName
);
1252 sb
.append(sslErrorName(sslError
->element
.code
, tmp
, sizeof(tmp
)));
1255 out
= sb
.termedBuf();
1260 case LFT_SSL_SERVER_CERT_ISSUER
:
1261 case LFT_SSL_SERVER_CERT_SUBJECT
:
1266 case LFT_REQUEST_URLGROUP_OLD_2X
:
1267 assert(LFT_REQUEST_URLGROUP_OLD_2X
== 0); // should never happen.
1270 tmp
[0] = fmt
->data
.header
.separator
;
1272 if (fmt
->data
.header
.header
&& *fmt
->data
.header
.header
) {
1273 const char *separator
= tmp
;
1275 Adaptation::History::Pointer ah
= al
->request
? al
->request
->adaptHistory() : Adaptation::History::Pointer();
1276 if (ah
!= NULL
&& ah
->metaHeaders
!= NULL
) {
1277 if (const char *meta
= ah
->metaHeaders
->find(fmt
->data
.header
.header
, separator
))
1281 if (al
->notes
!= NULL
) {
1282 if (const char *note
= al
->notes
->find(fmt
->data
.header
.header
, separator
)) {
1284 sb
.append(separator
);
1288 out
= sb
.termedBuf();
1291 // if no argument given use default "\r\n" as notes separator
1292 const char *separator
= fmt
->data
.string
? tmp
: "\r\n";
1294 Adaptation::History::Pointer ah
= al
->request
? al
->request
->adaptHistory() : Adaptation::History::Pointer();
1295 if (ah
!= NULL
&& ah
->metaHeaders
!= NULL
&& !ah
->metaHeaders
->empty())
1296 sb
.append(ah
->metaHeaders
->toString(separator
));
1298 if (al
->notes
!= NULL
&& !al
->notes
->empty())
1299 sb
.append(al
->notes
->toString(separator
));
1301 out
= sb
.termedBuf();
1306 case LFT_CREDENTIALS
:
1308 if (al
->request
&& al
->request
->auth_user_request
!= NULL
)
1309 out
= strOrNull(al
->request
->auth_user_request
->credentialsStr());
1318 case LFT_EXT_ACL_NAME
:
1319 out
= al
->lastAclName
;
1322 case LFT_EXT_ACL_DATA
:
1323 out
= al
->lastAclData
;
1328 snprintf(tmp
, sizeof(tmp
), "%0*" PRId64
, fmt
->zero
&& fmt
->widthMin
>= 0 ? fmt
->widthMin
: 0, outoff
);
1332 snprintf(tmp
, sizeof(tmp
), "%0*ld", fmt
->zero
&& fmt
->widthMin
>= 0 ? fmt
->widthMin
: 0, outint
);
1334 } else if (doMsec
) {
1335 if (fmt
->widthMax
< 0) {
1336 snprintf(tmp
, sizeof(tmp
), "%0*ld", fmt
->widthMin
, tvToMsec(outtv
));
1338 int precision
= fmt
->widthMax
;
1339 snprintf(tmp
, sizeof(tmp
), "%0*" PRId64
".%0*" PRId64
"", fmt
->zero
&& (fmt
->widthMin
- precision
- 1 >= 0) ? fmt
->widthMin
- precision
- 1 : 0, static_cast<int64_t>(outtv
.tv_sec
* 1000 + outtv
.tv_usec
/ 1000), precision
, static_cast<int64_t>((outtv
.tv_usec
% 1000 )* (1000 / fmt
->divisor
)));
1343 int precision
= fmt
->widthMax
>=0 ? fmt
->widthMax
:3;
1344 snprintf(tmp
, sizeof(tmp
), "%0*" PRId64
".%0*d", fmt
->zero
&& (fmt
->widthMin
- precision
- 1 >= 0) ? fmt
->widthMin
- precision
- 1 : 0, static_cast<int64_t>(outtv
.tv_sec
), precision
, (int)(outtv
.tv_usec
/ fmt
->divisor
));
1349 if (quote
|| fmt
->quote
!= LOG_QUOTE_NONE
) {
1350 char *newout
= NULL
;
1353 switch (fmt
->quote
) {
1355 case LOG_QUOTE_NONE
:
1356 newout
= rfc1738_escape_unescaped(out
);
1359 case LOG_QUOTE_QUOTES
: {
1360 size_t out_len
= static_cast<size_t>(strlen(out
)) * 2 + 1;
1361 if (out_len
>= sizeof(tmp
)) {
1362 newout
= (char *)xmalloc(out_len
);
1366 log_quoted_string(out
, newout
);
1370 case LOG_QUOTE_MIMEBLOB
:
1371 newout
= QuoteMimeBlob(out
);
1376 newout
= rfc1738_escape(out
);
1379 case LOG_QUOTE_SHELL
: {
1382 strwordquote(&mbq
, out
);
1383 newout
= mbq
.content();
1402 // enforce width limits if configured
1403 const bool haveMaxWidth
= fmt
->widthMax
>=0 && !doint
&& !dooff
&& !doMsec
&& !doSec
;
1404 if (haveMaxWidth
|| fmt
->widthMin
) {
1405 const int minWidth
= fmt
->widthMin
>= 0 ?
1407 const int maxWidth
= haveMaxWidth
?
1408 fmt
->widthMax
: strlen(out
);
1411 mb
.appendf("%-*.*s", minWidth
, maxWidth
, out
);
1413 mb
.appendf("%*.*s", minWidth
, maxWidth
, out
);
1415 mb
.append(out
, strlen(out
));