4 * DEBUG: section 46 Access Log
5 * AUTHOR: Duane Wessels
7 * SQUID Web Proxy Cache http://www.squid-cache.org/
8 * ----------------------------------------------------------
10 * Squid is the result of efforts by numerous individuals from
11 * the Internet community; see the CONTRIBUTORS file for full
12 * details. Many organizations have provided support for Squid's
13 * development; see the SPONSORS file for full details. Squid is
14 * Copyrighted (C) 2001 by the Regents of the University of
15 * California; see the COPYRIGHT file for full details. Squid
16 * incorporates software developed and/or copyrighted by other
17 * sources; see the CREDITS file for full details.
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
37 #include "AccessLogEntry.h"
39 // Store.h Required by configuration directives parsing/dumping only
42 #include "acl/Checklist.h"
44 #include "hier_code.h"
45 #include "HttpReply.h"
46 #include "HttpRequest.h"
48 #include "SquidTime.h"
49 #include "CacheManager.h"
51 static void accessLogSquid(AccessLogEntry
* al
, Logfile
* logfile
);
52 static void accessLogCommon(AccessLogEntry
* al
, Logfile
* logfile
);
53 static void accessLogCustom(AccessLogEntry
* al
, customlog
* log
);
55 static Logfile
*headerslog
= NULL
;
58 #if MULTICAST_MISS_STREAM
59 static int mcast_miss_fd
= -1;
61 static struct sockaddr_in mcast_miss_to
;
62 static void mcast_encode(unsigned int *, size_t, const unsigned int *);
65 const char *log_tags
[] = {
69 "TCP_REFRESH_UNMODIFIED",
71 "TCP_REFRESH_MODIFIED",
72 "TCP_CLIENT_REFRESH_MISS",
98 static hash_table
*via_table
= NULL
;
99 static hash_table
*forw_table
= NULL
;
100 static void fvdbInit();
101 static void fvdbDumpTable(StoreEntry
* e
, hash_table
* hash
);
102 static void fvdbCount(hash_table
* hash
, const char *key
);
103 static OBJH fvdbDumpVia
;
104 static OBJH fvdbDumpForw
;
105 static FREE fvdbFreeEntry
;
106 static void fvdbClear(void);
107 static void fvdbRegisterWithCacheManager();
110 int LogfileStatus
= LOG_DISABLE
;
113 bool alLogformatHasAdaptToken
= false;
117 bool alLogformatHasIcapToken
= false;
120 #define LOG_BUF_SZ (MAX_URL<<2)
122 static const char c2x
[] =
123 "000102030405060708090a0b0c0d0e0f"
124 "101112131415161718191a1b1c1d1e1f"
125 "202122232425262728292a2b2c2d2e2f"
126 "303132333435363738393a3b3c3d3e3f"
127 "404142434445464748494a4b4c4d4e4f"
128 "505152535455565758595a5b5c5d5e5f"
129 "606162636465666768696a6b6c6d6e6f"
130 "707172737475767778797a7b7c7d7e7f"
131 "808182838485868788898a8b8c8d8e8f"
132 "909192939495969798999a9b9c9d9e9f"
133 "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
134 "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
135 "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
136 "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
137 "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
138 "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
140 /* log_quote -- URL-style encoding on MIME headers. */
143 log_quote(const char *header
)
150 if (header
== NULL
) {
151 buf
= static_cast<char *>(xcalloc(1, 1));
156 buf
= static_cast<char *>(xcalloc(1, (strlen(header
) * 3) + 1));
159 * We escape: \x00-\x1F"#%;<>?{}|\\\\^~`\[\]\x7F-\xFF
160 * which is the default escape list for the CPAN Perl5 URI module
161 * modulo the inclusion of space (x40) to make the raw logs a bit
165 while ((c
= *(const unsigned char *) header
++) != '\0') {
169 *buf_cursor
++ = '\\';
171 } else if (c
== '\n') {
172 *buf_cursor
++ = '\\';
198 *buf_cursor
++ = c2x
[i
];
199 *buf_cursor
++ = c2x
[i
+ 1];
202 } else if (c
== '\\') {
203 *buf_cursor
++ = '\\';
204 *buf_cursor
++ = '\\';
208 *buf_cursor
++ = (char) c
;
217 username_quote(const char *header
)
218 /* copy of log_quote. Bugs there will be found here */
225 if (header
== NULL
) {
226 buf
= static_cast<char *>(xcalloc(1, 1));
231 buf
= static_cast<char *>(xcalloc(1, (strlen(header
) * 3) + 1));
234 * We escape: space \x00-\x1F and space (0x40) and \x7F-\xFF
235 * to prevent garbage in the logs. CR and LF are also there just in case.
238 while ((c
= *(const unsigned char *) header
++) != '\0') {
240 *buf_cursor
++ = '\\';
242 } else if (c
== '\n') {
243 *buf_cursor
++ = '\\';
251 *buf_cursor
++ = c2x
[i
];
252 *buf_cursor
++ = c2x
[i
+ 1];
254 *buf_cursor
++ = (char) c
;
263 accessLogFormatName(const char *name
)
271 return username_quote(name
);
275 log_quoted_string(const char *str
)
277 char *out
= (char *)xmalloc(strlen(str
) * 2 + 1);
281 int l
= strcspn(str
, "\"\\\r\n\t");
322 * Bytecodes for the configureable logformat stuff
325 LFT_NONE
, /* dummy */
328 LFT_CLIENT_IP_ADDRESS
,
332 /*LFT_SERVER_IP_ADDRESS, */
333 LFT_SERVER_IP_OR_PEER_NAME
,
334 /*LFT_SERVER_PORT, */
340 LFT_TIME_SECONDS_SINCE_EPOCH
,
344 LFT_TIME_TO_HANDLE_REQUEST
,
346 LFT_PEER_RESPONSE_TIME
,
347 LFT_TOTAL_SERVER_SIDE_RESPONSE_TIME
,
351 LFT_REQUEST_HEADER_ELEM
,
352 LFT_REQUEST_ALL_HEADERS
,
355 LFT_REPLY_HEADER_ELEM
,
356 LFT_REPLY_ALL_HEADERS
,
362 /*LFT_USER_SCHEME, */
365 LFT_HTTP_SENT_STATUS_CODE_OLD_30
,
366 LFT_HTTP_SENT_STATUS_CODE
,
367 LFT_HTTP_RECEIVED_STATUS_CODE
,
368 /*LFT_HTTP_STATUS, */
371 /*LFT_SQUID_ERROR, */
379 /*LFT_REQUEST_QUERY, * // * this is not needed. see strip_query_terms */
382 LFT_REQUEST_SIZE_TOTAL
,
383 /*LFT_REQUEST_SIZE_LINE, */
384 LFT_REQUEST_SIZE_HEADERS
,
385 /*LFT_REQUEST_SIZE_BODY, */
386 /*LFT_REQUEST_SIZE_BODY_NO_TE, */
388 LFT_REPLY_SIZE_TOTAL
,
389 LFT_REPLY_HIGHOFFSET
,
390 LFT_REPLY_OBJECTSIZE
,
391 /*LFT_REPLY_SIZE_LINE, */
392 LFT_REPLY_SIZE_HEADERS
,
393 /*LFT_REPLY_SIZE_BODY, */
394 /*LFT_REPLY_SIZE_BODY_NO_TE, */
401 LTF_ADAPTATION_SUM_XACT_TIMES
,
402 LTF_ADAPTATION_ALL_XACT_TIMES
,
408 LFT_ICAP_LAST_MATCHED_HEADER
,
409 LFT_ICAP_LAST_MATCHED_HEADER_ELEM
,
410 LFT_ICAP_LAST_MATCHED_ALL_HEADERS
,
414 LFT_ICAP_REQUEST_URI
,
415 LFT_ICAP_REQUEST_METHOD
,
420 LFT_ICAP_REQ_HEADER_ELEM
,
421 LFT_ICAP_REQ_ALL_HEADERS
,
424 LFT_ICAP_REP_HEADER_ELEM
,
425 LFT_ICAP_REP_ALL_HEADERS
,
427 LFT_ICAP_TR_RESPONSE_TIME
,
430 LFT_ICAP_STATUS_CODE
,
433 LFT_PERCENT
/* special string cases for escaped chars */
444 /* FIXME: public class so we can pre-define its type. */
445 class logformat_token
448 logformat_bcode_t type
;
460 unsigned char precision
;
461 enum log_quote quote
;
463 unsigned int space
:1;
466 logformat_token
*next
; /* todo: move from linked list to array */
469 struct logformat_token_table_entry
{
471 logformat_bcode_t token_type
;
475 struct logformat_token_table_entry logformat_token_table
[] = {
477 {">a", LFT_CLIENT_IP_ADDRESS
},
479 { ">p", LFT_CLIENT_PORT
},
480 {">A", LFT_CLIENT_FQDN
},
482 /*{ "<a", LFT_SERVER_IP_ADDRESS }, */
483 /*{ "<p", LFT_SERVER_PORT }, */
484 {"<A", LFT_SERVER_IP_OR_PEER_NAME
},
486 /* {"oa", LFT_OUTGOING_IP}, */
487 /* {"ot", LFT_OUTGOING_TOS}, */
489 {"la", LFT_LOCAL_IP
},
490 {"lp", LFT_LOCAL_PORT
},
491 /*{ "lA", LFT_LOCAL_NAME }, */
493 {"ts", LFT_TIME_SECONDS_SINCE_EPOCH
},
494 {"tu", LFT_TIME_SUBSECOND
},
495 {"tl", LFT_TIME_LOCALTIME
},
496 {"tg", LFT_TIME_GMT
},
497 {"tr", LFT_TIME_TO_HANDLE_REQUEST
},
499 {"<pt", LFT_PEER_RESPONSE_TIME
},
500 {"<tt", LFT_TOTAL_SERVER_SIDE_RESPONSE_TIME
},
501 {"dt", LFT_DNS_WAIT_TIME
},
503 {">h", LFT_REQUEST_HEADER
},
504 {">h", LFT_REQUEST_ALL_HEADERS
},
505 {"<h", LFT_REPLY_HEADER
},
506 {"<h", LFT_REPLY_ALL_HEADERS
},
508 {"un", LFT_USER_NAME
},
509 {"ul", LFT_USER_LOGIN
},
510 /*{ "ur", LFT_USER_REALM }, */
511 /*{ "us", LFT_USER_SCHEME }, */
512 {"ui", LFT_USER_IDENT
},
513 {"ue", LFT_USER_EXTERNAL
},
515 {"Hs", LFT_HTTP_SENT_STATUS_CODE_OLD_30
},
516 {">Hs", LFT_HTTP_SENT_STATUS_CODE
},
517 {"<Hs", LFT_HTTP_RECEIVED_STATUS_CODE
},
518 /*{ "Ht", LFT_HTTP_STATUS }, */
520 {"Ss", LFT_SQUID_STATUS
},
521 /*{ "Se", LFT_SQUID_ERROR }, */
522 {"Sh", LFT_SQUID_HIERARCHY
},
524 {"mt", LFT_MIME_TYPE
},
526 {"rm", LFT_REQUEST_METHOD
},
527 {"ru", LFT_REQUEST_URI
}, /* doesn't include the query-string */
528 {"rp", LFT_REQUEST_URLPATH
}, /* doesn't include the host */
529 /* { "rq", LFT_REQUEST_QUERY }, * / / * the query-string, INCLUDING the leading ? */
530 {">v", LFT_REQUEST_VERSION
},
531 {"rv", LFT_REQUEST_VERSION
},
533 { ">st", LFT_REQUEST_SIZE_TOTAL
},
534 /*{ ">sl", LFT_REQUEST_SIZE_LINE }, * / / * the request line "GET ... " */
535 { ">sh", LFT_REQUEST_SIZE_HEADERS
},
536 /*{ ">sb", LFT_REQUEST_SIZE_BODY }, */
537 /*{ ">sB", LFT_REQUEST_SIZE_BODY_NO_TE }, */
539 {"<st", LFT_REPLY_SIZE_TOTAL
},
540 {"<sH", LFT_REPLY_HIGHOFFSET
},
541 {"<sS", LFT_REPLY_OBJECTSIZE
},
542 /*{ "<sl", LFT_REPLY_SIZE_LINE }, * / / * the reply line (protocol, code, text) */
543 { "<sh", LFT_REPLY_SIZE_HEADERS
},
544 /*{ "<sb", LFT_REPLY_SIZE_BODY }, */
545 /*{ "<sB", LFT_REPLY_SIZE_BODY_NO_TE }, */
548 {"st", LFT_IO_SIZE_TOTAL
},
554 {"adapt::all_trs", LTF_ADAPTATION_ALL_XACT_TIMES
},
555 {"adapt::sum_trs", LTF_ADAPTATION_SUM_XACT_TIMES
},
559 {"icap::tt", LFT_ICAP_TOTAL_TIME
},
560 {"icap::<last_h", LFT_ICAP_LAST_MATCHED_HEADER
},
562 {"icap::<A", LFT_ICAP_ADDR
},
563 {"icap::<service_name", LFT_ICAP_SERV_NAME
},
564 {"icap::ru", LFT_ICAP_REQUEST_URI
},
565 {"icap::rm", LFT_ICAP_REQUEST_METHOD
},
566 {"icap::>st", LFT_ICAP_BYTES_SENT
},
567 {"icap::<st", LFT_ICAP_BYTES_READ
},
569 {"icap::>h", LFT_ICAP_REQ_HEADER
},
570 {"icap::<h", LFT_ICAP_REP_HEADER
},
572 {"icap::tr", LFT_ICAP_TR_RESPONSE_TIME
},
573 {"icap::tio", LFT_ICAP_IO_TIME
},
574 {"icap::to", LFT_ICAP_OUTCOME
},
575 {"icap::Hs", LFT_ICAP_STATUS_CODE
},
578 {NULL
, LFT_NONE
} /* this must be last */
582 accessLogCustom(AccessLogEntry
* al
, customlog
* log
)
586 logformat_token
*fmt
;
594 logfile
= log
->logfile
;
596 for (fmt
= lf
->format
; fmt
!= NULL
; fmt
= fmt
->next
) { /* for each token */
597 const char *out
= NULL
;
612 out
= fmt
->data
.string
;
615 case LFT_CLIENT_IP_ADDRESS
:
616 if (al
->cache
.caddr
.IsNoAddr()) // e.g., ICAP OPTIONS lack client
619 out
= al
->cache
.caddr
.NtoA(tmp
,1024);
622 case LFT_CLIENT_FQDN
:
623 if (al
->cache
.caddr
.IsAnyAddr()) // e.g., ICAP OPTIONS lack client
626 out
= fqdncache_gethostbyaddr(al
->cache
.caddr
, FQDN_LOOKUP_IF_MISS
);
628 out
= al
->cache
.caddr
.NtoA(tmp
,1024);
633 case LFT_CLIENT_PORT
:
635 outint
= al
->request
->client_addr
.GetPort();
640 /* case LFT_SERVER_IP_ADDRESS: */
642 case LFT_SERVER_IP_OR_PEER_NAME
:
647 /* case LFT_SERVER_PORT: */
651 out
= al
->request
->my_addr
.NtoA(tmp
,1024);
658 outint
= al
->request
->my_addr
.GetPort();
664 case LFT_TIME_SECONDS_SINCE_EPOCH
:
665 // some platforms store time in 32-bit, some 64-bit...
666 outoff
= static_cast<int64_t>(current_time
.tv_sec
);
670 case LFT_TIME_SUBSECOND
:
671 outint
= current_time
.tv_usec
/ fmt
->divisor
;
676 case LFT_TIME_LOCALTIME
:
682 spec
= fmt
->data
.timespec
;
684 if (fmt
->type
== LFT_TIME_LOCALTIME
) {
686 spec
= "%d/%b/%Y:%H:%M:%S %z";
687 t
= localtime(&squid_curtime
);
690 spec
= "%d/%b/%Y:%H:%M:%S";
692 t
= gmtime(&squid_curtime
);
695 strftime(tmp
, sizeof(tmp
), spec
, t
);
702 case LFT_TIME_TO_HANDLE_REQUEST
:
703 outint
= al
->cache
.msec
;
707 case LFT_PEER_RESPONSE_TIME
:
708 if (al
->hier
.peer_response_time
< 0) {
711 outoff
= al
->hier
.peer_response_time
;
716 case LFT_TOTAL_SERVER_SIDE_RESPONSE_TIME
:
717 if (al
->hier
.total_response_time
< 0) {
720 outoff
= al
->hier
.total_response_time
;
725 case LFT_DNS_WAIT_TIME
:
726 if (al
->request
&& al
->request
->dnsWait
>= 0) {
727 outint
= al
->request
->dnsWait
;
732 case LFT_REQUEST_HEADER
:
735 sb
= al
->request
->header
.getByName(fmt
->data
.header
.header
);
737 out
= sb
.termedBuf();
743 case LFT_REPLY_HEADER
:
745 sb
= al
->reply
->header
.getByName(fmt
->data
.header
.header
);
747 out
= sb
.termedBuf();
754 case LTF_ADAPTATION_SUM_XACT_TIMES
:
756 Adaptation::History::Pointer ah
= al
->request
->adaptHistory();
758 ah
->sumLogString(fmt
->data
.string
, sb
);
759 out
= sb
.termedBuf();
763 case LTF_ADAPTATION_ALL_XACT_TIMES
:
765 Adaptation::History::Pointer ah
= al
->request
->adaptHistory();
767 ah
->allLogString(fmt
->data
.string
, sb
);
768 out
= sb
.termedBuf();
774 case LFT_ICAP_LAST_MATCHED_HEADER
:
776 Adaptation::Icap::History::Pointer ih
= al
->request
->icapHistory();
778 sb
= ih
->mergeOfIcapHeaders
.getByName(fmt
->data
.header
.header
);
781 out
= sb
.termedBuf();
787 case LFT_ICAP_LAST_MATCHED_HEADER_ELEM
:
789 Adaptation::Icap::History::Pointer ih
= al
->request
->icapHistory();
791 sb
= ih
->mergeOfIcapHeaders
.getByNameListMember(fmt
->data
.header
.header
, fmt
->data
.header
.element
, fmt
->data
.header
.separator
);
794 out
= sb
.termedBuf();
800 case LFT_ICAP_LAST_MATCHED_ALL_HEADERS
:
801 out
= al
->headers
.icap
;
809 out
= al
->icap
.hostAddr
.NtoA(tmp
,1024);
812 case LFT_ICAP_SERV_NAME
:
813 out
= al
->icap
.serviceName
.termedBuf();
816 case LFT_ICAP_REQUEST_URI
:
817 out
= al
->icap
.reqUri
.termedBuf();
820 case LFT_ICAP_REQUEST_METHOD
:
821 out
= Adaptation::Icap::ICAP::methodStr(al
->icap
.reqMethod
);
824 case LFT_ICAP_BYTES_SENT
:
825 outint
= al
->icap
.bytesSent
;
829 case LFT_ICAP_BYTES_READ
:
830 outint
= al
->icap
.bytesRead
;
834 case LFT_ICAP_REQ_HEADER
:
835 if (NULL
!= al
->icap
.request
) {
836 sb
= al
->icap
.request
->header
.getByName(fmt
->data
.header
.header
);
837 out
= sb
.termedBuf();
842 case LFT_ICAP_REQ_HEADER_ELEM
:
844 sb
= al
->icap
.request
->header
.getByNameListMember(fmt
->data
.header
.header
, fmt
->data
.header
.element
, fmt
->data
.header
.separator
);
846 out
= sb
.termedBuf();
852 case LFT_ICAP_REQ_ALL_HEADERS
:
853 if (al
->icap
.request
) {
854 HttpHeaderPos pos
= HttpHeaderInitPos
;
855 while (const HttpHeaderEntry
*e
= al
->icap
.request
->header
.getEntry(&pos
)) {
861 out
= sb
.termedBuf();
866 case LFT_ICAP_REP_HEADER
:
867 if (NULL
!= al
->icap
.reply
) {
868 sb
= al
->icap
.reply
->header
.getByName(fmt
->data
.header
.header
);
869 out
= sb
.termedBuf();
874 case LFT_ICAP_REP_HEADER_ELEM
:
875 if (NULL
!= al
->icap
.reply
)
876 sb
= al
->icap
.reply
->header
.getByNameListMember(fmt
->data
.header
.header
, fmt
->data
.header
.element
, fmt
->data
.header
.separator
);
878 out
= sb
.termedBuf();
884 case LFT_ICAP_REP_ALL_HEADERS
:
885 if (al
->icap
.reply
) {
886 HttpHeaderPos pos
= HttpHeaderInitPos
;
887 while (const HttpHeaderEntry
*e
= al
->icap
.reply
->header
.getEntry(&pos
)) {
893 out
= sb
.termedBuf();
898 case LFT_ICAP_TR_RESPONSE_TIME
:
899 outint
= al
->icap
.trTime
;
903 case LFT_ICAP_IO_TIME
:
904 outint
= al
->icap
.ioTime
;
908 case LFT_ICAP_STATUS_CODE
:
909 outint
= al
->icap
.resStatus
;
913 case LFT_ICAP_OUTCOME
:
914 out
= al
->icap
.outcome
;
917 case LFT_ICAP_TOTAL_TIME
:
918 outint
= al
->icap
.processingTime
;
922 case LFT_REQUEST_HEADER_ELEM
:
924 sb
= al
->request
->header
.getByNameListMember(fmt
->data
.header
.header
, fmt
->data
.header
.element
, fmt
->data
.header
.separator
);
926 out
= sb
.termedBuf();
932 case LFT_REPLY_HEADER_ELEM
:
934 sb
= al
->reply
->header
.getByNameListMember(fmt
->data
.header
.header
, fmt
->data
.header
.element
, fmt
->data
.header
.separator
);
936 out
= sb
.termedBuf();
942 case LFT_REQUEST_ALL_HEADERS
:
943 out
= al
->headers
.request
;
949 case LFT_REPLY_ALL_HEADERS
:
950 out
= al
->headers
.reply
;
957 out
= accessLogFormatName(al
->cache
.authuser
);
960 out
= accessLogFormatName(al
->cache
.extuser
);
965 out
= accessLogFormatName(al
->cache
.ssluser
);
970 out
= accessLogFormatName(al
->cache
.rfc931
);
977 out
= accessLogFormatName(al
->cache
.authuser
);
984 out
= accessLogFormatName(al
->cache
.rfc931
);
990 case LFT_USER_EXTERNAL
:
991 out
= accessLogFormatName(al
->cache
.extuser
);
997 /* case LFT_USER_REALM: */
998 /* case LFT_USER_SCHEME: */
1000 // the fmt->type can not be LFT_HTTP_SENT_STATUS_CODE_OLD_30
1001 // but compiler complains if ommited
1002 case LFT_HTTP_SENT_STATUS_CODE_OLD_30
:
1003 case LFT_HTTP_SENT_STATUS_CODE
:
1004 outint
= al
->http
.code
;
1010 case LFT_HTTP_RECEIVED_STATUS_CODE
:
1011 if (al
->hier
.peer_reply_status
== HTTP_STATUS_NONE
) {
1014 outint
= al
->hier
.peer_reply_status
;
1018 /* case LFT_HTTP_STATUS:
1019 * out = statusline->text;
1024 case LFT_SQUID_STATUS
:
1025 out
= log_tags
[al
->cache
.code
];
1029 /* case LFT_SQUID_ERROR: */
1031 case LFT_SQUID_HIERARCHY
:
1032 if (al
->hier
.ping
.timedout
)
1033 mb
.append("TIMEOUT_", 8);
1035 out
= hier_code_str
[al
->hier
.code
];
1040 out
= al
->http
.content_type
;
1044 case LFT_REQUEST_METHOD
:
1045 out
= al
->_private
.method_str
;
1049 case LFT_REQUEST_URI
:
1054 case LFT_REQUEST_URLPATH
:
1056 out
= al
->request
->urlpath
.termedBuf();
1061 case LFT_REQUEST_VERSION
:
1062 snprintf(tmp
, sizeof(tmp
), "%d.%d", (int) al
->http
.version
.major
, (int) al
->http
.version
.minor
);
1066 case LFT_REQUEST_SIZE_TOTAL
:
1067 outoff
= al
->cache
.requestSize
;
1071 /*case LFT_REQUEST_SIZE_LINE: */
1072 case LFT_REQUEST_SIZE_HEADERS
:
1073 outoff
= al
->cache
.requestHeadersSize
;
1076 /*case LFT_REQUEST_SIZE_BODY: */
1077 /*case LFT_REQUEST_SIZE_BODY_NO_TE: */
1079 case LFT_REPLY_SIZE_TOTAL
:
1080 outoff
= al
->cache
.replySize
;
1084 case LFT_REPLY_HIGHOFFSET
:
1085 outoff
= al
->cache
.highOffset
;
1091 case LFT_REPLY_OBJECTSIZE
:
1092 outoff
= al
->cache
.objectSize
;
1098 /*case LFT_REPLY_SIZE_LINE: */
1099 case LFT_REPLY_SIZE_HEADERS
:
1100 outint
= al
->cache
.replyHeadersSize
;
1102 /*case LFT_REPLY_SIZE_BODY: */
1103 /*case LFT_REPLY_SIZE_BODY_NO_TE: */
1107 out
= al
->request
->tag
.termedBuf();
1113 case LFT_IO_SIZE_TOTAL
:
1114 outint
= al
->cache
.requestSize
+ al
->cache
.replySize
;
1120 out
= al
->request
->extacl_log
.termedBuf();
1133 snprintf(tmp
, sizeof(tmp
), "%0*" PRId64
, fmt
->zero
? (int) fmt
->width
: 0, outoff
);
1137 snprintf(tmp
, sizeof(tmp
), "%0*ld", fmt
->zero
? (int) fmt
->width
: 0, outint
);
1142 if (quote
|| fmt
->quote
!= LOG_QUOTE_NONE
) {
1143 char *newout
= NULL
;
1146 switch (fmt
->quote
) {
1148 case LOG_QUOTE_NONE
:
1149 newout
= rfc1738_escape_unescaped(out
);
1152 case LOG_QUOTE_QUOTES
:
1153 newout
= log_quoted_string(out
);
1157 case LOG_QUOTE_BRAKETS
:
1158 newout
= log_quote(out
);
1163 newout
= rfc1738_escape(out
);
1182 mb
.Printf("%-*s", (int) fmt
->width
, out
);
1184 mb
.Printf("%*s", (int) fmt
->width
, out
);
1186 mb
.append(out
, strlen(out
));
1200 logfilePrintf(logfile
, "%s\n", mb
.buf
);
1203 /* parses a single token. Returns the token length in characters,
1204 * and fills in the lt item with the token information.
1205 * def is for sure null-terminated
1208 accessLogGetNewLogFormatToken(logformat_token
* lt
, char *def
, enum log_quote
*quote
)
1212 struct logformat_token_table_entry
*lte
;
1215 memset(lt
, 0, sizeof(*lt
));
1216 l
= strcspn(cur
, "%");
1220 /* it's a string for sure, until \0 or the next % */
1221 cp
= (char *)xmalloc(l
+ 1);
1222 xstrncpy(cp
, cur
, l
+ 1);
1223 lt
->type
= LFT_STRING
;
1224 lt
->data
.string
= cp
;
1231 if (*quote
== LOG_QUOTE_NONE
)
1232 *quote
= LOG_QUOTE_QUOTES
;
1233 else if (*quote
== LOG_QUOTE_QUOTES
)
1234 *quote
= LOG_QUOTE_NONE
;
1239 if (*quote
== LOG_QUOTE_NONE
)
1240 *quote
= LOG_QUOTE_BRAKETS
;
1245 if (*quote
== LOG_QUOTE_BRAKETS
)
1246 *quote
= LOG_QUOTE_NONE
;
1266 lt
->quote
= LOG_QUOTE_QUOTES
;
1271 lt
->quote
= LOG_QUOTE_RAW
;
1276 lt
->quote
= LOG_QUOTE_BRAKETS
;
1281 lt
->quote
= LOG_QUOTE_URL
;
1301 lt
->width
= strtol(cur
, &cur
, 10);
1304 lt
->precision
= strtol(cur
+ 1, &cur
, 10);
1309 l
= strcspn(cur
, "}");
1310 cp
= (char *)xmalloc(l
+ 1);
1311 xstrncpy(cp
, cur
, l
+ 1);
1312 lt
->data
.string
= cp
;
1319 // For upward compatibility, assume "http::" prefix as default prefix
1320 // for all log access formating codes, except those starting
1321 // from "icap::", "adapt::" and "%"
1322 if (strncmp(cur
,"http::", 6) == 0 &&
1323 strncmp(cur
+6, "icap::", 6) != 0 &&
1324 strncmp(cur
+6, "adapt::", 12) != 0 && *(cur
+6) != '%' ) {
1328 lt
->type
= LFT_NONE
;
1330 for (lte
= logformat_token_table
; lte
->config
!= NULL
; lte
++) {
1331 if (strncmp(lte
->config
, cur
, strlen(lte
->config
)) == 0) {
1332 lt
->type
= lte
->token_type
;
1333 cur
+= strlen(lte
->config
);
1338 if (lt
->type
== LFT_NONE
) {
1339 fatalf("Can't parse configuration token: '%s'\n",
1353 case LFT_ICAP_LAST_MATCHED_HEADER
:
1355 case LFT_ICAP_REQ_HEADER
:
1357 case LFT_ICAP_REP_HEADER
:
1360 case LFT_REQUEST_HEADER
:
1362 case LFT_REPLY_HEADER
:
1364 if (lt
->data
.string
) {
1365 char *header
= lt
->data
.string
;
1366 char *cp
= strchr(header
, ':');
1371 if (*cp
== ',' || *cp
== ';' || *cp
== ':')
1372 lt
->data
.header
.separator
= *cp
++;
1374 lt
->data
.header
.separator
= ',';
1376 lt
->data
.header
.element
= cp
;
1379 case LFT_REQUEST_HEADER
:
1380 lt
->type
= LFT_REQUEST_HEADER_ELEM
;
1382 case LFT_REPLY_HEADER
:
1383 lt
->type
= LFT_REPLY_HEADER_ELEM
;
1386 case LFT_ICAP_LAST_MATCHED_HEADER
:
1387 lt
->type
= LFT_ICAP_LAST_MATCHED_HEADER_ELEM
;
1389 case LFT_ICAP_REQ_HEADER
:
1390 lt
->type
= LFT_ICAP_REQ_HEADER_ELEM
;
1392 case LFT_ICAP_REP_HEADER
:
1393 lt
->type
= LFT_ICAP_REP_HEADER_ELEM
;
1401 lt
->data
.header
.header
= header
;
1404 case LFT_REQUEST_HEADER
:
1405 lt
->type
= LFT_REQUEST_ALL_HEADERS
;
1407 case LFT_REPLY_HEADER
:
1408 lt
->type
= LFT_REPLY_ALL_HEADERS
;
1411 case LFT_ICAP_LAST_MATCHED_HEADER
:
1412 lt
->type
= LFT_ICAP_LAST_MATCHED_ALL_HEADERS
;
1414 case LFT_ICAP_REQ_HEADER
:
1415 lt
->type
= LFT_ICAP_REQ_ALL_HEADERS
;
1417 case LFT_ICAP_REP_HEADER
:
1418 lt
->type
= LFT_ICAP_REP_ALL_HEADERS
;
1424 Config
.onoff
.log_mime_hdrs
= 1;
1429 case LFT_CLIENT_FQDN
:
1430 Config
.onoff
.log_fqdn
= 1;
1433 case LFT_TIME_SUBSECOND
:
1436 if (lt
->precision
) {
1438 lt
->divisor
= 1000000;
1440 for (i
= lt
->precision
; i
> 1; i
--)
1449 case LFT_HTTP_SENT_STATUS_CODE_OLD_30
:
1450 debugs(46, 0, "WARNING: the \"Hs\" formating code is deprecated use the \">Hs\" instead");
1451 lt
->type
= LFT_HTTP_SENT_STATUS_CODE
;
1461 accessLogParseLogFormat(logformat_token
** fmt
, char *def
)
1464 logformat_token
*new_lt
, *last_lt
;
1465 enum log_quote quote
= LOG_QUOTE_NONE
;
1467 debugs(46, 2, "accessLogParseLogFormat: got definition '" << def
<< "'");
1469 /* very inefficent parser, but who cares, this needs to be simple */
1470 /* First off, let's tokenize, we'll optimize in a second pass.
1471 * A token can either be a %-prefixed sequence (usually a dynamic
1472 * token but it can be an escaped sequence), or a string. */
1474 eos
= def
+ strlen(def
);
1475 *fmt
= new_lt
= last_lt
= (logformat_token
*)xmalloc(sizeof(logformat_token
));
1476 cur
+= accessLogGetNewLogFormatToken(new_lt
, cur
, "e
);
1479 new_lt
= (logformat_token
*)xmalloc(sizeof(logformat_token
));
1480 last_lt
->next
= new_lt
;
1482 cur
+= accessLogGetNewLogFormatToken(new_lt
, cur
, "e
);
1489 accessLogDumpLogFormat(StoreEntry
* entry
, const char *name
, logformat
* definitions
)
1494 struct logformat_token_table_entry
*te
;
1495 debugs(46, 0, "accessLogDumpLogFormat called");
1497 for (format
= definitions
; format
; format
= format
->next
) {
1498 debugs(46, 0, "Dumping logformat definition for " << format
->name
);
1499 storeAppendPrintf(entry
, "logformat %s ", format
->name
);
1501 for (t
= format
->format
; t
; t
= t
->next
) {
1502 if (t
->type
== LFT_STRING
)
1503 storeAppendPrintf(entry
, "%s", t
->data
.string
);
1507 logformat_bcode_t type
= t
->type
;
1515 case LFT_ICAP_LAST_MATCHED_HEADER_ELEM
:
1516 case LFT_ICAP_REQ_HEADER_ELEM
:
1517 case LFT_ICAP_REP_HEADER_ELEM
:
1519 case LFT_REQUEST_HEADER_ELEM
:
1521 case LFT_REPLY_HEADER_ELEM
:
1523 if (t
->data
.header
.separator
!= ',')
1524 snprintf(argbuf
, sizeof(argbuf
), "%s:%c%s", t
->data
.header
.header
, t
->data
.header
.separator
, t
->data
.header
.element
);
1526 snprintf(argbuf
, sizeof(argbuf
), "%s:%s", t
->data
.header
.header
, t
->data
.header
.element
);
1531 case LFT_REQUEST_HEADER_ELEM
:
1532 type
= LFT_REQUEST_HEADER_ELEM
;
1534 case LFT_REPLY_HEADER_ELEM
:
1535 type
= LFT_REPLY_HEADER_ELEM
;
1538 case LFT_ICAP_LAST_MATCHED_HEADER_ELEM
:
1539 type
= LFT_ICAP_LAST_MATCHED_HEADER
;
1541 case LFT_ICAP_REQ_HEADER_ELEM
:
1542 type
= LFT_ICAP_REQ_HEADER
;
1544 case LFT_ICAP_REP_HEADER_ELEM
:
1545 type
= LFT_ICAP_REP_HEADER
;
1554 case LFT_REQUEST_ALL_HEADERS
:
1556 case LFT_REPLY_ALL_HEADERS
:
1559 case LFT_ICAP_LAST_MATCHED_ALL_HEADERS
:
1560 case LFT_ICAP_REQ_ALL_HEADERS
:
1561 case LFT_ICAP_REP_ALL_HEADERS
:
1565 case LFT_REQUEST_ALL_HEADERS
:
1566 type
= LFT_REQUEST_HEADER
;
1568 case LFT_REPLY_ALL_HEADERS
:
1569 type
= LFT_REPLY_HEADER
;
1572 case LFT_ICAP_LAST_MATCHED_ALL_HEADERS
:
1573 type
= LFT_ICAP_LAST_MATCHED_HEADER
;
1575 case LFT_ICAP_REQ_ALL_HEADERS
:
1576 type
= LFT_ICAP_REQ_HEADER
;
1578 case LFT_ICAP_REP_ALL_HEADERS
:
1579 type
= LFT_ICAP_REP_HEADER
;
1590 arg
= t
->data
.string
;
1595 entry
->append("%", 1);
1599 case LOG_QUOTE_QUOTES
:
1600 entry
->append("\"", 1);
1603 case LOG_QUOTE_BRAKETS
:
1604 entry
->append("[", 1);
1608 entry
->append("#", 1);
1612 entry
->append("'", 1);
1615 case LOG_QUOTE_NONE
:
1620 entry
->append("-", 1);
1623 entry
->append("0", 1);
1626 storeAppendPrintf(entry
, "%d", (int) t
->width
);
1629 storeAppendPrintf(entry
, ".%d", (int) t
->precision
);
1632 storeAppendPrintf(entry
, "{%s}", arg
);
1634 for (te
= logformat_token_table
; te
->config
!= NULL
; te
++) {
1635 if (te
->token_type
== type
) {
1636 storeAppendPrintf(entry
, "%s", te
->config
);
1642 entry
->append(" ", 1);
1644 assert(te
->config
!= NULL
);
1648 entry
->append("\n", 1);
1654 accessLogFreeLogFormat(logformat_token
** tokens
)
1657 logformat_token
*token
= *tokens
;
1658 *tokens
= token
->next
;
1659 safe_free(token
->data
.string
);
1665 accessLogSquid(AccessLogEntry
* al
, Logfile
* logfile
)
1667 const char *client
= NULL
;
1668 const char *user
= NULL
;
1669 char buf
[MAX_IPSTRLEN
];
1671 if (Config
.onoff
.log_fqdn
) {
1672 client
= fqdncache_gethostbyaddr(al
->cache
.caddr
, FQDN_LOOKUP_IF_MISS
);
1675 if (client
== NULL
) {
1676 client
= al
->cache
.caddr
.NtoA(buf
,MAX_IPSTRLEN
);
1679 user
= accessLogFormatName(al
->cache
.authuser
);
1682 user
= accessLogFormatName(al
->cache
.extuser
);
1687 user
= accessLogFormatName(al
->cache
.ssluser
);
1692 user
= accessLogFormatName(al
->cache
.rfc931
);
1697 if (!Config
.onoff
.log_mime_hdrs
) {
1698 logfilePrintf(logfile
, "%9ld.%03d %6d %s %s/%03d %"PRId64
" %s %s %s %s%s/%s %s\n",
1699 (long int) current_time
.tv_sec
,
1700 (int) current_time
.tv_usec
/ 1000,
1703 log_tags
[al
->cache
.code
],
1705 al
->cache
.replySize
,
1706 al
->_private
.method_str
,
1708 user
? user
: dash_str
,
1709 al
->hier
.ping
.timedout
? "TIMEOUT_" : "",
1710 hier_code_str
[al
->hier
.code
],
1712 al
->http
.content_type
);
1714 char *ereq
= log_quote(al
->headers
.request
);
1715 char *erep
= log_quote(al
->headers
.reply
);
1716 logfilePrintf(logfile
, "%9ld.%03d %6d %s %s/%03d %"PRId64
" %s %s %s %s%s/%s %s [%s] [%s]\n",
1717 (long int) current_time
.tv_sec
,
1718 (int) current_time
.tv_usec
/ 1000,
1721 log_tags
[al
->cache
.code
],
1723 al
->cache
.replySize
,
1724 al
->_private
.method_str
,
1726 user
? user
: dash_str
,
1727 al
->hier
.ping
.timedout
? "TIMEOUT_" : "",
1728 hier_code_str
[al
->hier
.code
],
1730 al
->http
.content_type
,
1740 accessLogCommon(AccessLogEntry
* al
, Logfile
* logfile
)
1742 const char *client
= NULL
;
1743 char *user1
= NULL
, *user2
= NULL
;
1744 char buf
[MAX_IPSTRLEN
];
1746 if (Config
.onoff
.log_fqdn
) {
1747 client
= fqdncache_gethostbyaddr(al
->cache
.caddr
, 0);
1750 if (client
== NULL
) {
1751 client
= al
->cache
.caddr
.NtoA(buf
,MAX_IPSTRLEN
);
1754 user1
= accessLogFormatName(al
->cache
.authuser
);
1756 user2
= accessLogFormatName(al
->cache
.rfc931
);
1758 logfilePrintf(logfile
, "%s %s %s [%s] \"%s %s HTTP/%d.%d\" %d %"PRId64
" %s:%s",
1760 user2
? user2
: dash_str
,
1761 user1
? user1
: dash_str
,
1762 mkhttpdlogtime(&squid_curtime
),
1763 al
->_private
.method_str
,
1765 al
->http
.version
.major
, al
->http
.version
.minor
,
1767 al
->cache
.replySize
,
1768 log_tags
[al
->cache
.code
],
1769 hier_code_str
[al
->hier
.code
]);
1775 if (Config
.onoff
.log_mime_hdrs
) {
1776 char *ereq
= log_quote(al
->headers
.request
);
1777 char *erep
= log_quote(al
->headers
.reply
);
1778 logfilePrintf(logfile
, " [%s] [%s]\n", ereq
, erep
);
1782 logfilePrintf(logfile
, "\n");
1789 accessLogICAPSquid(AccessLogEntry
* al
, Logfile
* logfile
)
1791 const char *client
= NULL
;
1792 const char *user
= NULL
;
1793 char tmp
[MAX_IPSTRLEN
], clientbuf
[MAX_IPSTRLEN
];
1795 if (al
->cache
.caddr
.IsAnyAddr()) { // ICAP OPTIONS xactions lack client
1798 if (Config
.onoff
.log_fqdn
)
1799 client
= fqdncache_gethostbyaddr(al
->cache
.caddr
, FQDN_LOOKUP_IF_MISS
);
1801 client
= al
->cache
.caddr
.NtoA(clientbuf
, MAX_IPSTRLEN
);
1804 user
= accessLogFormatName(al
->cache
.authuser
);
1807 user
= accessLogFormatName(al
->cache
.extuser
);
1812 user
= accessLogFormatName(al
->cache
.ssluser
);
1817 user
= accessLogFormatName(al
->cache
.rfc931
);
1822 logfilePrintf(logfile
, "%9ld.%03d %6d %s -/%03d %"PRId64
" %s %s %s -/%s -\n",
1823 (long int) current_time
.tv_sec
,
1824 (int) current_time
.tv_usec
/ 1000,
1831 Adaptation::Icap::ICAP::methodStr(al
->icap
.reqMethod
),
1832 al
->icap
.reqUri
.termedBuf(),
1833 user
? user
: dash_str
,
1834 al
->icap
.hostAddr
.NtoA(tmp
, MAX_IPSTRLEN
));
1840 accessLogLogTo(customlog
* log
, AccessLogEntry
* al
, ACLChecklist
* checklist
)
1843 if (al
->url
== NULL
)
1846 if (!al
->http
.content_type
|| *al
->http
.content_type
== '\0')
1847 al
->http
.content_type
= dash_str
;
1850 al
->_private
.method_str
= icp_opcode_str
[al
->icp
.opcode
];
1851 else if (al
->htcp
.opcode
)
1852 al
->_private
.method_str
= al
->htcp
.opcode
;
1854 al
->_private
.method_str
= RequestMethodStr(al
->http
.method
);
1856 if (al
->hier
.host
[0] == '\0')
1857 xstrncpy(al
->hier
.host
, dash_str
, SQUIDHOSTNAMELEN
);
1859 for (; log
; log
= log
->next
) {
1860 if (checklist
&& log
->aclList
&& !checklist
->matchAclListFast(log
->aclList
))
1863 switch (log
->type
) {
1867 if (Config
.onoff
.common_log
)
1868 accessLogCommon(al
, log
->logfile
);
1870 accessLogSquid(al
, log
->logfile
);
1875 accessLogSquid(al
, log
->logfile
);
1880 accessLogCommon(al
, log
->logfile
);
1885 accessLogCustom(al
, log
);
1890 case CLF_ICAP_SQUID
:
1891 accessLogICAPSquid(al
, log
->logfile
);
1900 fatalf("Unknown log format %d\n", log
->type
);
1905 logfileFlush(log
->logfile
);
1912 (void)0; /* NULL statement for label */
1916 accessLogLog(AccessLogEntry
* al
, ACLChecklist
* checklist
)
1918 if (LogfileStatus
!= LOG_ENABLE
)
1921 accessLogLogTo(Config
.Log
.accesslogs
, al
, checklist
);
1922 #if MULTICAST_MISS_STREAM
1924 if (al
->cache
.code
!= LOG_TCP_MISS
)
1926 else if (al
->http
.method
!= METHOD_GET
)
1928 else if (mcast_miss_fd
< 0)
1931 unsigned int ibuf
[365];
1933 xstrncpy((char *) ibuf
, al
->url
, 364 * sizeof(int));
1934 isize
= ((strlen(al
->url
) + 8) / 8) * 2;
1939 mcast_encode((unsigned int *) ibuf
, isize
,
1940 (const unsigned int *) Config
.mcast_miss
.encode_key
);
1942 comm_udp_sendto(mcast_miss_fd
,
1943 &mcast_miss_to
, sizeof(mcast_miss_to
),
1944 ibuf
, isize
* sizeof(int));
1951 accessLogRotate(void)
1959 for (log
= Config
.Log
.accesslogs
; log
; log
= log
->next
) {
1961 logfileRotate(log
->logfile
);
1967 logfileRotate(headerslog
);
1973 accessLogClose(void)
1977 for (log
= Config
.Log
.accesslogs
; log
; log
= log
->next
) {
1979 logfileClose(log
->logfile
);
1980 log
->logfile
= NULL
;
1986 logfileClose(headerslog
);
1993 HierarchyLogEntry::HierarchyLogEntry() :
1995 cd_lookup(LOOKUP_NONE
),
1998 peer_reply_status(HTTP_STATUS_NONE
),
1999 peer_response_time(-1),
2000 total_response_time(-1)
2002 memset(host
, '\0', SQUIDHOSTNAMELEN
);
2003 memset(cd_host
, '\0', SQUIDHOSTNAMELEN
);
2005 peer_select_start
.tv_sec
=0;
2006 peer_select_start
.tv_usec
=0;
2008 store_complete_stop
.tv_sec
=0;
2009 store_complete_stop
.tv_usec
=0;
2011 peer_http_request_sent
.tv_sec
= 0;
2012 peer_http_request_sent
.tv_usec
= 0;
2014 first_conn_start
.tv_sec
= 0;
2015 first_conn_start
.tv_usec
= 0;
2019 hierarchyNote(HierarchyLogEntry
* hl
,
2021 const char *cache_peer
)
2025 xstrncpy(hl
->host
, cache_peer
, SQUIDHOSTNAMELEN
);
2029 accessLogRegisterWithCacheManager(void)
2032 fvdbRegisterWithCacheManager();
2041 accessLogRegisterWithCacheManager();
2043 assert(sizeof(log_tags
) == (LOG_TYPE_MAX
+ 1) * sizeof(char *));
2045 for (log
= Config
.Log
.accesslogs
; log
; log
= log
->next
) {
2046 if (log
->type
== CLF_NONE
)
2049 log
->logfile
= logfileOpen(log
->filename
, MAX_URL
<< 1, 1);
2051 LogfileStatus
= LOG_ENABLE
;
2053 #if USE_ADAPTATION || ICAP_CLIENT
2054 alLogformatHasAdaptToken
= false;
2055 alLogformatHasIcapToken
= false;
2056 for (logformat_token
* curr_token
= (log
->logFormat
?log
->logFormat
->format
:NULL
); curr_token
; curr_token
= curr_token
->next
) {
2058 if (curr_token
->type
== LTF_ADAPTATION_SUM_XACT_TIMES
||
2059 curr_token
->type
== LTF_ADAPTATION_ALL_XACT_TIMES
) {
2060 alLogformatHasAdaptToken
= true;
2064 if (curr_token
->type
== LFT_ICAP_LAST_MATCHED_HEADER
||
2065 curr_token
->type
== LFT_ICAP_LAST_MATCHED_HEADER_ELEM
||
2066 curr_token
->type
== LFT_ICAP_LAST_MATCHED_ALL_HEADERS
) {
2067 alLogformatHasIcapToken
= true;
2076 headerslog
= logfileOpen("/usr/local/squid/logs/headers.log", 512);
2078 assert(NULL
!= headerslog
);
2081 #if MULTICAST_MISS_STREAM
2083 if (Config
.mcast_miss
.addr
.s_addr
!= no_addr
.s_addr
) {
2084 memset(&mcast_miss_to
, '\0', sizeof(mcast_miss_to
));
2085 mcast_miss_to
.sin_family
= AF_INET
;
2086 mcast_miss_to
.sin_port
= htons(Config
.mcast_miss
.port
);
2087 mcast_miss_to
.sin_addr
.s_addr
= Config
.mcast_miss
.addr
.s_addr
;
2088 mcast_miss_fd
= comm_open(SOCK_DGRAM
,
2090 Config
.Addrs
.udp_incoming
,
2091 Config
.mcast_miss
.port
,
2093 "Multicast Miss Stream");
2095 if (mcast_miss_fd
< 0)
2096 fatal("Cannot open Multicast Miss Stream Socket");
2098 debugs(46, 1, "Multicast Miss Stream Socket opened on FD " << mcast_miss_fd
);
2100 mcastSetTtl(mcast_miss_fd
, Config
.mcast_miss
.ttl
);
2102 if (strlen(Config
.mcast_miss
.encode_key
) < 16)
2103 fatal("mcast_encode_key is too short, must be 16 characters");
2115 accessLogTime(time_t t
)
2119 static char buf
[128];
2120 static time_t last_t
= 0;
2124 strftime(buf
, 127, "%Y/%m/%d %H:%M:%S", tm
);
2137 via_table
= hash_create((HASHCMP
*) strcmp
, 977, hash4
);
2138 forw_table
= hash_create((HASHCMP
*) strcmp
, 977, hash4
);
2142 fvdbRegisterWithCacheManager(void)
2144 CacheManager
*manager
=CacheManager::GetInstance();
2145 manager
->registerAction("via_headers", "Via Request Headers", fvdbDumpVia
, 0, 1);
2146 manager
->registerAction("forw_headers", "X-Forwarded-For Request Headers",
2147 fvdbDumpForw
, 0, 1);
2151 fvdbCount(hash_table
* hash
, const char *key
)
2158 fv
= (fvdb_entry
*)hash_lookup(hash
, key
);
2161 fv
= static_cast <fvdb_entry
*>(xcalloc(1, sizeof(fvdb_entry
)));
2162 fv
->hash
.key
= xstrdup(key
);
2163 hash_join(hash
, &fv
->hash
);
2170 fvdbCountVia(const char *key
)
2172 fvdbCount(via_table
, key
);
2176 fvdbCountForw(const char *key
)
2178 fvdbCount(forw_table
, key
);
2182 fvdbDumpTable(StoreEntry
* e
, hash_table
* hash
)
2192 while ((h
= hash_next(hash
))) {
2193 fv
= (fvdb_entry
*) h
;
2194 storeAppendPrintf(e
, "%9d %s\n", fv
->n
, hashKeyStr(&fv
->hash
));
2199 fvdbDumpVia(StoreEntry
* e
)
2201 fvdbDumpTable(e
, via_table
);
2205 fvdbDumpForw(StoreEntry
* e
)
2207 fvdbDumpTable(e
, forw_table
);
2212 fvdbFreeEntry(void *data
)
2214 fvdb_entry
*fv
= static_cast <fvdb_entry
*>(data
);
2215 xfree(fv
->hash
.key
);
2222 hashFreeItems(via_table
, fvdbFreeEntry
);
2223 hashFreeMemory(via_table
);
2224 via_table
= hash_create((HASHCMP
*) strcmp
, 977, hash4
);
2225 hashFreeItems(forw_table
, fvdbFreeEntry
);
2226 hashFreeMemory(forw_table
);
2227 forw_table
= hash_create((HASHCMP
*) strcmp
, 977, hash4
);
2232 #if MULTICAST_MISS_STREAM
2234 * From http://www.io.com/~paulhart/game/algorithms/tea.html
2236 * size of 'ibuf' must be a multiple of 2.
2237 * size of 'key' must be 4.
2238 * 'ibuf' is modified in place, encrypted data is written in
2239 * network byte order.
2242 mcast_encode(unsigned int *ibuf
, size_t isize
, const unsigned int *key
)
2247 const unsigned int delta
= 0x9e3779b9;
2248 unsigned int n
= 32;
2249 const unsigned int k0
= htonl(key
[0]);
2250 const unsigned int k1
= htonl(key
[1]);
2251 const unsigned int k2
= htonl(key
[2]);
2252 const unsigned int k3
= htonl(key
[3]);
2255 for (i
= 0; i
< isize
; i
+= 2) {
2257 z
= htonl(ibuf
[i
+ 1]);
2260 for (n
= 32; n
; n
--) {
2262 y
+= (z
<< 4) + (k0
^ z
) + (sum
^ (z
>> 5)) + k1
;
2263 z
+= (y
<< 4) + (k2
^ y
) + (sum
^ (y
>> 5)) + k3
;
2267 ibuf
[i
+ 1] = htonl(z
);
2275 headersLog(int cs
, int pq
, const HttpRequestMethod
& method
, void *data
)
2279 unsigned short magic
= 0;
2280 unsigned char M
= (unsigned char) m
;
2290 hmask
= rep
->header
.mask
;
2292 if (rep
->cache_control
)
2293 ccmask
= rep
->cache_control
->mask
;
2299 hmask
= req
->header
.mask
;
2301 if (req
->cache_control
)
2302 ccmask
= req
->cache_control
->mask
;
2313 magic
= htons(magic
);
2314 ccmask
= htonl(ccmask
);
2317 S
= (unsigned short) rep
->sline
.status
;
2319 S
= (unsigned short) HTTP_STATUS_NONE
;
2321 logfileWrite(headerslog
, &magic
, sizeof(magic
));
2323 logfileWrite(headerslog
, &M
, sizeof(M
));
2325 logfileWrite(headerslog
, &S
, sizeof(S
));
2327 logfileWrite(headerslog
, hmask
, sizeof(HttpHeaderMask
));
2329 logfileWrite(headerslog
, &ccmask
, sizeof(int));
2331 logfileFlush(headerslog
);
2337 accessLogFreeMemory(AccessLogEntry
* aLogEntry
)
2339 safe_free(aLogEntry
->headers
.request
);
2342 safe_free(aLogEntry
->headers
.icap
);
2345 safe_free(aLogEntry
->headers
.reply
);
2346 safe_free(aLogEntry
->cache
.authuser
);
2348 HTTPMSGUNLOCK(aLogEntry
->reply
);
2349 HTTPMSGUNLOCK(aLogEntry
->request
);
2351 HTTPMSGUNLOCK(aLogEntry
->icap
.reply
);
2352 HTTPMSGUNLOCK(aLogEntry
->icap
.request
);
2357 logTypeIsATcpHit(log_type code
)
2359 /* this should be a bitmap for better optimization */
2361 if (code
== LOG_TCP_HIT
)
2364 if (code
== LOG_TCP_IMS_HIT
)
2367 if (code
== LOG_TCP_REFRESH_FAIL
)
2370 if (code
== LOG_TCP_REFRESH_UNMODIFIED
)
2373 if (code
== LOG_TCP_NEGATIVE_HIT
)
2376 if (code
== LOG_TCP_MEM_HIT
)
2379 if (code
== LOG_TCP_OFFLINE_HIT
)