Format.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
3  *
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.
7  */
8 
9 #include "squid.h"
10 #include "AccessLogEntry.h"
11 #include "base64.h"
12 #include "client_side.h"
13 #include "comm/Connection.h"
14 #include "error/Detail.h"
15 #include "errorpage.h"
16 #include "fde.h"
17 #include "format/Format.h"
18 #include "format/Quoting.h"
19 #include "format/Token.h"
20 #include "http/Stream.h"
21 #include "HttpRequest.h"
22 #include "MemBuf.h"
23 #include "proxyp/Header.h"
24 #include "rfc1738.h"
25 #include "sbuf/Stream.h"
26 #include "sbuf/StringConvert.h"
27 #include "security/CertError.h"
28 #include "security/Certificate.h"
30 #include "Store.h"
31 #include "tools.h"
32 #if USE_OPENSSL
33 #include "ssl/ErrorDetail.h"
34 #include "ssl/ServerBump.h"
35 #endif
36 
38 #define strOrNull(s) ((s)==NULL||(s)[0]=='\0'?NULL:(s))
39 
40 const SBuf Format::Dash("-");
41 
42 Format::Format::Format(const char *n) :
43  format(nullptr),
44  next(nullptr)
45 {
46  name = xstrdup(n);
47 }
48 
50 {
51  // erase the list without consuming stack space
52  while (next) {
53  // unlink the next entry for deletion
54  Format *temp = next;
55  next = temp->next;
56  temp->next = nullptr;
57  delete temp;
58  }
59 
60  // remove locals
61  xfree(name);
62  delete format;
63 }
64 
65 bool
66 Format::Format::parse(const char *def)
67 {
68  const char *cur, *eos;
69  Token *new_lt, *last_lt;
70  enum Quoting quote = LOG_QUOTE_NONE;
71 
72  debugs(46, 2, "got definition '" << def << "'");
73 
74  if (format) {
75  debugs(46, DBG_IMPORTANT, "WARNING: existing format for '" << name << " " << def << "'");
76  return false;
77  }
78 
79  /* very inefficient parser, but who cares, this needs to be simple */
80  /* First off, let's tokenize, we'll optimize in a second pass.
81  * A token can either be a %-prefixed sequence (usually a dynamic
82  * token but it can be an escaped sequence), or a string. */
83  cur = def;
84  eos = def + strlen(def);
85  format = new_lt = last_lt = new Token;
86  cur += new_lt->parse(cur, &quote);
87 
88  while (cur < eos) {
89  new_lt = new Token;
90  last_lt->next = new_lt;
91  last_lt = new_lt;
92  cur += new_lt->parse(cur, &quote);
93  }
94 
95  return true;
96 }
97 
98 size_t
99 Format::AssembleOne(const char *token, MemBuf &mb, const AccessLogEntryPointer &ale)
100 {
101  Token tkn;
102  enum Quoting quote = LOG_QUOTE_NONE;
103  const auto tokenSize = tkn.parse(token, &quote);
104  assert(tokenSize > 0);
105  if (ale != nullptr) {
106  Format fmt("SimpleToken");
107  fmt.format = &tkn;
108  fmt.assemble(mb, ale, 0);
109  fmt.format = nullptr;
110  } else {
111  mb.append("-", 1);
112  }
113  return static_cast<size_t>(tokenSize);
114 }
115 
116 void
117 Format::Format::dump(StoreEntry * entry, const char *directiveName, bool eol) const
118 {
119  debugs(46, 4, MYNAME);
120 
121  // loop rather than recursing to conserve stack space.
122  for (const Format *fmt = this; fmt; fmt = fmt->next) {
123  debugs(46, 3, "Dumping format definition for " << fmt->name);
124  if (directiveName)
125  storeAppendPrintf(entry, "%s %s ", directiveName, fmt->name);
126 
127  for (Token *t = fmt->format; t; t = t->next) {
128  if (t->type == LFT_STRING)
129  storeAppendPrintf(entry, "%s", t->data.string);
130  else {
131  char argbuf[256];
132  char *arg = nullptr;
133  ByteCode_t type = t->type;
134 
135  switch (type) {
136  /* special cases */
137 
138  case LFT_STRING:
139  break;
140 #if USE_ADAPTATION
142 #endif
143 #if ICAP_CLIENT
146 #endif
150 
151  if (t->data.header.separator != ',')
152  snprintf(argbuf, sizeof(argbuf), "%s:%c%s", t->data.header.header, t->data.header.separator, t->data.header.element);
153  else
154  snprintf(argbuf, sizeof(argbuf), "%s:%s", t->data.header.header, t->data.header.element);
155 
156  arg = argbuf;
157 
158  switch (type) {
160  type = LFT_REQUEST_HEADER_ELEM; // XXX: remove _ELEM?
161  break;
163  type = LFT_ADAPTED_REQUEST_HEADER_ELEM; // XXX: remove _ELEM?
164  break;
166  type = LFT_REPLY_HEADER_ELEM; // XXX: remove _ELEM?
167  break;
168 #if USE_ADAPTATION
171  break;
172 #endif
173 #if ICAP_CLIENT
175  type = LFT_ICAP_REQ_HEADER;
176  break;
178  type = LFT_ICAP_REP_HEADER;
179  break;
180 #endif
181  default:
182  break;
183  }
184 
185  break;
186 
190 
191 #if USE_ADAPTATION
193 #endif
194 #if ICAP_CLIENT
197 #endif
198 
199  switch (type) {
201  type = LFT_REQUEST_HEADER;
202  break;
205  break;
207  type = LFT_REPLY_HEADER;
208  break;
209 #if USE_ADAPTATION
212  break;
213 #endif
214 #if ICAP_CLIENT
216  type = LFT_ICAP_REQ_HEADER;
217  break;
219  type = LFT_ICAP_REP_HEADER;
220  break;
221 #endif
222  default:
223  break;
224  }
225 
226  break;
227 
228  default:
229  if (t->data.string)
230  arg = t->data.string;
231 
232  break;
233  }
234 
235  entry->append("%", 1);
236 
237  switch (t->quote) {
238 
239  case LOG_QUOTE_QUOTES:
240  entry->append("\"", 1);
241  break;
242 
243  case LOG_QUOTE_MIMEBLOB:
244  entry->append("[", 1);
245  break;
246 
247  case LOG_QUOTE_URL:
248  entry->append("#", 1);
249  break;
250 
251  case LOG_QUOTE_RAW:
252  entry->append("'", 1);
253  break;
254 
255  case LOG_QUOTE_SHELL:
256  entry->append("/", 1);
257  break;
258 
259  case LOG_QUOTE_NONE:
260  break;
261  }
262 
263  if (t->left)
264  entry->append("-", 1);
265 
266  if (t->zero)
267  entry->append("0", 1);
268 
269  if (t->widthMin >= 0)
270  storeAppendPrintf(entry, "%d", t->widthMin);
271 
272  if (t->widthMax >= 0)
273  storeAppendPrintf(entry, ".%d", t->widthMax);
274 
275  if (arg)
276  storeAppendPrintf(entry, "{%s}", arg);
277 
278  storeAppendPrintf(entry, "%s", t->label);
279 
280  if (t->space)
281  entry->append(" ", 1);
282  }
283  }
284 
285  if (eol)
286  entry->append("\n", 1);
287  }
288 
289 }
290 
291 static void
292 log_quoted_string(const char *str, char *out)
293 {
294  char *p = out;
295 
296  while (*str) {
297  int l = strcspn(str, "\"\\\r\n\t");
298  memcpy(p, str, l);
299  str += l;
300  p += l;
301 
302  switch (*str) {
303 
304  case '\0':
305  break;
306 
307  case '\r':
308  *p = '\\';
309  ++p;
310  *p = 'r';
311  ++p;
312  ++str;
313  break;
314 
315  case '\n':
316  *p = '\\';
317  ++p;
318  *p = 'n';
319  ++p;
320  ++str;
321  break;
322 
323  case '\t':
324  *p = '\\';
325  ++p;
326  *p = 't';
327  ++p;
328  ++str;
329  break;
330 
331  default:
332  *p = '\\';
333  ++p;
334  *p = *str;
335  ++p;
336  ++str;
337  break;
338  }
339  }
340 
341  *p = '\0';
342 }
343 
349 static const Http::Message *
351 {
352  const Http::Message *msg = al->reply.getRaw();
353 #if ICAP_CLIENT
354  // al->icap.reqMethod is methodNone in access.log context
355  if (!msg && al->icap.reqMethod == Adaptation::methodReqmod)
356  msg = al->adapted_request;
357 #endif
358  return msg;
359 }
360 
363 static const Http::Message *
365 {
366 #if ICAP_CLIENT
367  // al->icap.reqMethod is methodNone in access.log context
368  if (al->icap.reqMethod == Adaptation::methodRespmod) {
369  // XXX: for now AccessLogEntry lacks virgin response headers
370  return nullptr;
371  }
372 #endif
373  return al->request;
374 }
375 
376 void
377 Format::Format::assemble(MemBuf &mb, const AccessLogEntry::Pointer &al, int logSequenceNumber) const
378 {
379  static char tmp[1024];
380  SBuf sb;
381 
382  for (Token *fmt = format; fmt; fmt = fmt->next) { /* for each token */
383  const char *out = nullptr;
384  int quote = 0;
385  long int outint = 0;
386  int doint = 0;
387  int dofree = 0;
388  int64_t outoff = 0;
389  int dooff = 0;
390  struct timeval outtv = {};
391  int doMsec = 0;
392  int doSec = 0;
393  bool doUint64 = false;
394  uint64_t outUint64 = 0;
395 
396  switch (fmt->type) {
397 
398  case LFT_NONE:
399  out = "";
400  break;
401 
402  case LFT_BYTE:
403  tmp[0] = static_cast<char>(fmt->data.byteValue);
404  tmp[1] = '\0';
405  out = tmp;
406  break;
407 
408  case LFT_STRING:
409  out = fmt->data.string;
410  break;
411 
413  al->getLogClientIp(tmp, sizeof(tmp));
414  out = tmp;
415  break;
416 
417  case LFT_CLIENT_FQDN:
418  out = al->getLogClientFqdn(tmp, sizeof(tmp));
419  break;
420 
421  case LFT_CLIENT_PORT:
422  if (al->request) {
423  outint = al->request->client_addr.port();
424  doint = 1;
425  } else if (al->tcpClient) {
426  outint = al->tcpClient->remote.port();
427  doint = 1;
428  }
429  break;
430 
431  case LFT_CLIENT_EUI:
432 #if USE_SQUID_EUI
433  // TODO make the ACL checklist have a direct link to any TCP details.
434  if (al->request && al->request->clientConnectionManager.valid() &&
436  const auto &conn = al->request->clientConnectionManager->clientConnection;
437  if (conn->remote.isIPv4())
438  conn->remoteEui48.encode(tmp, sizeof(tmp));
439  else
440  conn->remoteEui64.encode(tmp, sizeof(tmp));
441  out = tmp;
442  }
443 #endif
444  break;
445 
447 #if USE_SQUID_EUI
448  if (al->request && al->request->clientConnectionManager.valid() &&
452  out = tmp;
453  }
454 #endif
455  break;
456 
458 #if USE_SQUID_EUI
459  if (al->request && al->request->clientConnectionManager.valid() &&
463  out = tmp;
464  }
465 #endif
466  break;
467 
469  if (al->hier.tcpServer)
470  out = al->hier.tcpServer->remote.toStr(tmp, sizeof(tmp));
471  break;
472 
474  out = al->hier.host;
475  break;
476 
477  case LFT_SERVER_PORT:
478  if (al->hier.tcpServer) {
479  outint = al->hier.tcpServer->remote.port();
480  doint = 1;
481  }
482  break;
483 
485  if (const auto addr = FindListeningPortAddress(nullptr, al.getRaw()))
486  out = addr->toStr(tmp, sizeof(tmp));
487  break;
488 
489  case LFT_CLIENT_LOCAL_IP:
490  if (al->tcpClient)
491  out = al->tcpClient->local.toStr(tmp, sizeof(tmp));
492  break;
493 
495  if (al->tcpClient) {
496  sb.appendf("0x%x", static_cast<uint32_t>(al->tcpClient->tos));
497  out = sb.c_str();
498  }
499  break;
500 
502  if (al->tcpClient) {
503  outUint64 = al->tcpClient->id.value;
504  doUint64 = true;
505  }
506  break;
507 
509  if (al->tcpClient) {
510  sb.appendf("0x%x", al->tcpClient->nfmark);
511  out = sb.c_str();
512  }
513  break;
514 
516  if (const auto port = FindListeningPortNumber(nullptr, al.getRaw())) {
517  outint = *port;
518  doint = 1;
519  }
520  break;
521 
523  if (al->tcpClient) {
524  outint = al->tcpClient->local.port();
525  doint = 1;
526  }
527  break;
528 
530  case LFT_SERVER_LOCAL_IP:
531  if (al->hier.tcpServer)
532  out = al->hier.tcpServer->local.toStr(tmp, sizeof(tmp));
533  break;
534 
536  if (al->hier.tcpServer) {
537  outint = al->hier.tcpServer->local.port();
538  doint = 1;
539  }
540  break;
541 
543  if (al->hier.tcpServer) {
544  sb.appendf("0x%x", static_cast<uint32_t>(al->hier.tcpServer->tos));
545  out = sb.c_str();
546  }
547  break;
548 
550  if (al->hier.tcpServer) {
551  sb.appendf("0x%x", al->hier.tcpServer->nfmark);
552  out = sb.c_str();
553  }
554  break;
555 
557  if (al->request && al->request->clientConnectionManager.valid()) {
558  const auto &handshake = al->request->clientConnectionManager->preservedClientData;
559  if (const auto rawLength = handshake.length()) {
560  // add 1 byte to optimize the c_str() conversion below
561  char *buf = sb.rawAppendStart(base64_encode_len(rawLength) + 1);
562 
563  struct base64_encode_ctx ctx;
564  base64_encode_init(&ctx);
565  auto encLength = base64_encode_update(&ctx, buf, rawLength, reinterpret_cast<const uint8_t*>(handshake.rawContent()));
566  encLength += base64_encode_final(&ctx, buf + encLength);
567 
568  sb.rawAppendFinish(buf, encLength);
569  out = sb.c_str();
570  }
571  }
572  break;
573 
575  // some platforms store time in 32-bit, some 64-bit...
576  outoff = static_cast<int64_t>(current_time.tv_sec);
577  dooff = 1;
578  break;
579 
580  case LFT_TIME_SUBSECOND:
581  outint = current_time.tv_usec / fmt->divisor;
582  doint = 1;
583  break;
584 
585  case LFT_TIME_LOCALTIME:
586  case LFT_TIME_GMT: {
587  const char *spec;
588  struct tm *t;
589  spec = fmt->data.string;
590 
591  if (fmt->type == LFT_TIME_LOCALTIME) {
592  if (!spec)
593  spec = "%d/%b/%Y:%H:%M:%S %z";
594  t = localtime(&squid_curtime);
595  } else {
596  if (!spec)
597  spec = "%d/%b/%Y:%H:%M:%S";
598 
599  t = gmtime(&squid_curtime);
600  }
601 
602  strftime(tmp, sizeof(tmp), spec, t);
603  out = tmp;
604  }
605  break;
606 
607  case LFT_TIME_START:
608  outtv = al->cache.start_time;
609  doSec = 1;
610  break;
611 
612  case LFT_BUSY_TIME: {
613  const auto &stopwatch = al->busyTime;
614  if (stopwatch.ran()) {
615  // make sure total() returns nanoseconds compatible with outoff
616  using nanos = std::chrono::duration<decltype(outoff), std::nano>;
617  const nanos n = stopwatch.total();
618  outoff = n.count();
619  dooff = true;
620  }
621  }
622  break;
623 
625  outtv = al->cache.trTime;
626  doMsec = 1;
627  break;
628 
630  struct timeval peerResponseTime;
631  if (al->hier.peerResponseTime(peerResponseTime)) {
632  outtv = peerResponseTime;
633  doMsec = 1;
634  }
635  break;
636 
638  // XXX: al->hier.totalPeeringTime is not updated until prepareLogWithRequestDetails().
639  // TODO: Avoid the need for updates by keeping totalPeeringTime (or even ALE::hier) in one place.
640  const auto &timer = (!al->hier.totalPeeringTime.ran() && al->request) ?
642  if (timer.ran()) {
643  using namespace std::chrono_literals;
644  const auto duration = timer.total();
645  outtv.tv_sec = std::chrono::duration_cast<std::chrono::seconds>(duration).count();
646  const auto totalUsec = std::chrono::duration_cast<std::chrono::microseconds>(duration);
647  outtv.tv_usec = (totalUsec % std::chrono::microseconds(1s)).count();
648  doMsec = 1;
649  }
650  }
651  break;
652 
653  case LFT_DNS_WAIT_TIME:
654  if (al->request && al->request->dnsWait >= 0) {
655  // TODO: microsecond precision for dns wait time.
656  // Convert milliseconds to timeval struct:
657  outtv.tv_sec = al->request->dnsWait / 1000;
658  outtv.tv_usec = (al->request->dnsWait % 1000) * 1000;
659  doMsec = 1;
660  }
661  break;
662 
663  case LFT_REQUEST_HEADER:
664  if (const Http::Message *msg = actualRequestHeader(al)) {
665  sb = StringToSBuf(msg->header.getByName(fmt->data.header.header));
666  out = sb.c_str();
667  quote = 1;
668  }
669  break;
670 
672  if (al->adapted_request) {
673  sb = StringToSBuf(al->adapted_request->header.getByName(fmt->data.header.header));
674  out = sb.c_str();
675  quote = 1;
676  }
677  break;
678 
679  case LFT_REPLY_HEADER:
680  if (const Http::Message *msg = actualReplyHeader(al)) {
681  sb = StringToSBuf(msg->header.getByName(fmt->data.header.header));
682  out = sb.c_str();
683  quote = 1;
684  }
685  break;
686 
687 #if USE_ADAPTATION
689  if (al->request) {
691  if (ah) {
692  ah->sumLogString(fmt->data.string, sb);
693  out = sb.c_str();
694  }
695  }
696  break;
697 
699  if (al->request) {
701  if (ah) {
702  ah->allLogString(fmt->data.string, sb);
703  out = sb.c_str();
704  }
705  }
706  break;
707 
709  if (al->request) {
711  if (ah) { // XXX: add adapt::<all_h but use lastMeta here
712  sb = StringToSBuf(ah->allMeta.getByName(fmt->data.header.header));
713  out = sb.c_str();
714  quote = 1;
715  }
716  }
717  break;
718 
720  if (al->request) {
722  if (ah) { // XXX: add adapt::<all_h but use lastMeta here
723  sb = ah->allMeta.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
724  out = sb.c_str();
725  quote = 1;
726  }
727  }
728  break;
729 
731  out = al->adapt.last_meta;
732  quote = 1;
733  break;
734 #endif
735 
736 #if ICAP_CLIENT
737  case LFT_ICAP_ADDR:
738  out = al->icap.hostAddr.toStr(tmp, sizeof(tmp));
739  break;
740 
741  case LFT_ICAP_SERV_NAME:
742  out = al->icap.serviceName.termedBuf();
743  break;
744 
746  out = al->icap.reqUri.termedBuf();
747  break;
748 
751  break;
752 
753  case LFT_ICAP_BYTES_SENT:
754  outoff = al->icap.bytesSent;
755  dooff = 1;
756  break;
757 
758  case LFT_ICAP_BYTES_READ:
759  outoff = al->icap.bytesRead;
760  dooff = 1;
761  break;
762 
764  if (al->icap.bodyBytesRead >= 0) {
765  outoff = al->icap.bodyBytesRead;
766  dooff = 1;
767  }
768  // else if icap.bodyBytesRead < 0, we do not have any http data,
769  // so just print a "-" (204 responses etc)
770  break;
771 
772  case LFT_ICAP_REQ_HEADER:
773  if (al->icap.request) {
774  sb = StringToSBuf(al->icap.request->header.getByName(fmt->data.header.header));
775  out = sb.c_str();
776  quote = 1;
777  }
778  break;
779 
781  if (al->icap.request) {
782  sb = al->icap.request->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
783  out = sb.c_str();
784  quote = 1;
785  }
786  break;
787 
789  if (al->icap.request) {
791  while (const HttpHeaderEntry *e = al->icap.request->header.getEntry(&pos)) {
792  sb.append(e->name);
793  sb.append(": ");
794  sb.append(StringToSBuf(e->value));
795  sb.append("\r\n");
796  }
797  out = sb.c_str();
798  quote = 1;
799  }
800  break;
801 
802  case LFT_ICAP_REP_HEADER:
803  if (al->icap.reply) {
804  sb = StringToSBuf(al->icap.reply->header.getByName(fmt->data.header.header));
805  out = sb.c_str();
806  quote = 1;
807  }
808  break;
809 
811  if (al->icap.reply) {
812  sb = al->icap.reply->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
813  out = sb.c_str();
814  quote = 1;
815  }
816  break;
817 
819  if (al->icap.reply) {
821  while (const HttpHeaderEntry *e = al->icap.reply->header.getEntry(&pos)) {
822  sb.append(e->name);
823  sb.append(": ");
824  sb.append(StringToSBuf(e->value));
825  sb.append("\r\n");
826  }
827  out = sb.c_str();
828  quote = 1;
829  }
830  break;
831 
833  outtv = al->icap.trTime;
834  doMsec = 1;
835  break;
836 
837  case LFT_ICAP_IO_TIME:
838  outtv = al->icap.ioTime;
839  doMsec = 1;
840  break;
841 
843  outint = al->icap.resStatus;
844  doint = 1;
845  break;
846 
847  case LFT_ICAP_OUTCOME:
848  out = al->icap.outcome;
849  break;
850 
851  case LFT_ICAP_TOTAL_TIME:
852  outtv = al->icap.processingTime;
853  doMsec = 1;
854  break;
855 #endif
857  if (const Http::Message *msg = actualRequestHeader(al)) {
858  sb = msg->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
859  out = sb.c_str();
860  quote = 1;
861  }
862  break;
863 
865  if (al->proxyProtocolHeader) {
866  sb = al->proxyProtocolHeader->getValues(fmt->data.headerId, fmt->data.header.separator);
867  out = sb.c_str();
868  quote = 1;
869  }
870  break;
871 
873  if (al->proxyProtocolHeader) {
874  sb = al->proxyProtocolHeader->toMime();
875  out = sb.c_str();
876  quote = 1;
877  }
878  break;
879 
881  if (al->proxyProtocolHeader) {
882  sb = al->proxyProtocolHeader->getElem(fmt->data.headerId, fmt->data.header.element, fmt->data.header.separator);
883  out = sb.c_str();
884  quote = 1;
885  }
886  break;
887 
889  if (al->adapted_request) {
890  sb = al->adapted_request->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
891  out = sb.c_str();
892  quote = 1;
893  }
894  break;
895 
897  if (const Http::Message *msg = actualReplyHeader(al)) {
898  sb = msg->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
899  out = sb.c_str();
900  quote = 1;
901  }
902  break;
903 
905 #if ICAP_CLIENT
907  // XXX: since AccessLogEntry::Headers lacks virgin response
908  // headers, do nothing for now
909  out = nullptr;
910  } else
911 #endif
912  {
913  // just headers without start-line and CRLF
914  // XXX: reconcile with '<h'
915  out = al->headers.request;
916  quote = 1;
917  }
918  break;
919 
921  // just headers without start-line and CRLF
922  // XXX: reconcile with '<h'
923  out = al->headers.adapted_request;
924  quote = 1;
925  break;
926 
927  case LFT_REPLY_ALL_HEADERS: {
928  MemBuf allHeaders;
929  allHeaders.init();
930  // status-line + headers + CRLF
931  // XXX: reconcile with '>h' and '>ha'
932  al->packReplyHeaders(allHeaders);
933  sb.assign(allHeaders.content(), allHeaders.contentSize());
934  out = sb.c_str();
935 #if ICAP_CLIENT
936  if (!out && al->icap.reqMethod == Adaptation::methodReqmod)
937  out = al->headers.adapted_request;
938 #endif
939  quote = 1;
940  }
941  break;
942 
943  case LFT_USER_NAME:
944 #if USE_AUTH
945  if (al->request && al->request->auth_user_request)
947 #endif
948  if (!out && al->request && al->request->extacl_user.size()) {
949  if (const char *t = al->request->extacl_user.termedBuf())
950  out = t;
951  }
952  if (!out)
953  out = strOrNull(al->getExtUser());
954 #if USE_OPENSSL
955  if (!out)
956  out = strOrNull(al->cache.ssluser);
957 #endif
958  break;
959 
960  case LFT_USER_LOGIN:
961 #if USE_AUTH
962  if (al->request && al->request->auth_user_request)
964 #endif
965  break;
966 
967  case LFT_USER_EXTERNAL:
968  out = strOrNull(al->getExtUser());
969  break;
970 
971  /* case LFT_USER_REALM: */
972  /* case LFT_USER_SCHEME: */
973 
974  // the fmt->type can not be LFT_HTTP_SENT_STATUS_CODE_OLD_30
975  // but compiler complains if omitted
978  outint = al->http.code;
979  doint = 1;
980  break;
981 
983  if (al->hier.peer_reply_status != Http::scNone) {
984  outint = al->hier.peer_reply_status;
985  doint = 1;
986  }
987  break;
988  /* case LFT_HTTP_STATUS:
989  * out = statusline->text;
990  * quote = 1;
991  * break;
992  */
994  if (al->hier.bodyBytesRead >= 0) {
995  outoff = al->hier.bodyBytesRead;
996  dooff = 1;
997  }
998  // else if hier.bodyBytesRead < 0 we did not have any data exchange with
999  // a peer server so just print a "-" (eg requests served from cache,
1000  // or internal error messages).
1001  break;
1002 
1003  case LFT_SQUID_STATUS:
1004  out = al->cache.code.c_str();
1005  break;
1006 
1007  case LFT_SQUID_ERROR:
1008  if (const auto error = al->error())
1009  out = errorPageName(error->category);
1010  break;
1011 
1013  if (const auto error = al->error()) {
1014  if (!error->details.empty()) {
1015  sb = ToSBuf(error->details);
1016  out = sb.c_str();
1017  }
1018  }
1019  break;
1020 
1021  case LFT_SQUID_HIERARCHY:
1022  if (al->hier.ping.timedout)
1023  mb.append("TIMEOUT_", 8);
1024  out = hier_code_str[al->hier.code];
1025  break;
1026 
1028  outint = al->requestAttempts;
1029  doint = 1;
1030  break;
1031 
1032  case LFT_MIME_TYPE:
1033  out = al->http.content_type;
1034  break;
1035 
1036  case LFT_CLIENT_REQ_METHOD:
1037  if (al->request) {
1038  sb = al->request->method.image();
1039  out = sb.c_str();
1040  quote = 1;
1041  }
1042  break;
1043 
1044  case LFT_CLIENT_REQ_URI:
1045  if (const auto uri = al->effectiveVirginUrl()) {
1046  sb = *uri;
1047  out = sb.c_str();
1048  quote = 1;
1049  }
1050  break;
1051 
1053  if (al->request) {
1054  sb = al->request->url.getScheme().image();
1055  out = sb.c_str();
1056  quote = 1;
1057  }
1058  break;
1059 
1061  if (al->request) {
1062  out = al->request->url.host();
1063  quote = 1;
1064  }
1065  break;
1066 
1068  if (al->request && al->request->url.port()) {
1069  outint = *al->request->url.port();
1070  doint = 1;
1071  }
1072  break;
1073 
1076  if (al->request) {
1077  sb = al->request->url.path();
1078  out = sb.c_str();
1079  quote = 1;
1080  }
1081  break;
1082 
1084  if (al->request) {
1085  sb.appendf("%u.%u", al->request->http_ver.major, al->request->http_ver.minor);
1086  out = sb.c_str();
1087  }
1088  break;
1089 
1090  case LFT_REQUEST_METHOD:
1091  if (al->hasLogMethod()) {
1092  sb = al->getLogMethod();
1093  out = sb.c_str();
1094  quote = 1;
1095  }
1096  break;
1097 
1098  case LFT_REQUEST_URI:
1099  if (!al->url.isEmpty()) {
1100  sb = al->url;
1101  out = sb.c_str();
1102  }
1103  break;
1104 
1106  case LFT_REQUEST_VERSION:
1107  sb.appendf("%u.%u", al->http.version.major, al->http.version.minor);
1108  out = sb.c_str();
1109  break;
1110 
1111  case LFT_SERVER_REQ_METHOD:
1112  if (al->adapted_request) {
1113  sb = al->adapted_request->method.image();
1114  out = sb.c_str();
1115  quote = 1;
1116  }
1117  break;
1118 
1119  case LFT_SERVER_REQ_URI:
1120  // adapted request URI sent to server/peer
1121  if (al->adapted_request) {
1123  out = sb.c_str();
1124  quote = 1;
1125  }
1126  break;
1127 
1129  if (al->adapted_request) {
1130  sb = al->adapted_request->url.getScheme().image();
1131  out = sb.c_str();
1132  quote = 1;
1133  }
1134  break;
1135 
1137  if (al->adapted_request) {
1138  out = al->adapted_request->url.host();
1139  quote = 1;
1140  }
1141  break;
1142 
1144  if (al->adapted_request && al->adapted_request->url.port()) {
1145  outint = *al->adapted_request->url.port();
1146  doint = 1;
1147  }
1148  break;
1149 
1151  if (al->adapted_request) {
1152  sb = al->adapted_request->url.path();
1153  out = sb.c_str();
1154  quote = 1;
1155  }
1156  break;
1157 
1159  if (al->adapted_request) {
1160  sb.appendf("%u.%u",
1163  out = tmp;
1164  }
1165  break;
1166 
1168  outoff = al->http.clientRequestSz.messageTotal();
1169  dooff = 1;
1170  break;
1171 
1173  outoff = al->http.clientRequestSz.header;
1174  dooff =1;
1175  break;
1176 
1177  /*case LFT_REQUEST_SIZE_BODY: */
1178  /*case LFT_REQUEST_SIZE_BODY_NO_TE: */
1179 
1181  outoff = al->http.clientReplySz.messageTotal();
1182  dooff = 1;
1183  break;
1184 
1185  case LFT_REPLY_HIGHOFFSET:
1186  outoff = al->cache.highOffset;
1187  dooff = 1;
1188  break;
1189 
1190  case LFT_REPLY_OBJECTSIZE:
1191  outoff = al->cache.objectSize;
1192  dooff = 1;
1193  break;
1194 
1196  outint = al->http.clientReplySz.header;
1197  doint = 1;
1198  break;
1199 
1200  /*case LFT_REPLY_SIZE_BODY: */
1201  /*case LFT_REPLY_SIZE_BODY_NO_TE: */
1202 
1205  doint = 1;
1206  break;
1207  /*case LFT_SERVER_IO_SIZE_TOTAL: */
1208 
1209  case LFT_TAG:
1210  if (al->request) {
1211  out = al->request->tag.termedBuf();
1212  quote = 1;
1213  }
1214  break;
1215 
1216  case LFT_EXT_LOG:
1217  if (al->request) {
1218  out = al->request->extacl_log.termedBuf();
1219  quote = 1;
1220  }
1221  break;
1222 
1223  case LFT_SEQUENCE_NUMBER:
1224  outoff = logSequenceNumber;
1225  dooff = 1;
1226  break;
1227 
1228 #if USE_OPENSSL
1229  case LFT_SSL_BUMP_MODE: {
1230  const Ssl::BumpMode mode = static_cast<Ssl::BumpMode>(al->ssl.bumpMode);
1231  // for Ssl::bumpEnd, Ssl::bumpMode() returns NULL and we log '-'
1232  out = Ssl::bumpMode(mode);
1233  }
1234  break;
1235 
1237  if (al->request) {
1239  if (conn && Comm::IsConnOpen(conn->clientConnection)) {
1240  if (const auto ssl = fd_table[conn->clientConnection->fd].ssl.get()) {
1241  sb = sslGetUserCertificatePEM(ssl);
1242  out = sb.c_str();
1243  }
1244  }
1245  }
1246  break;
1247 
1249  if (al->request) {
1251  if (conn && Comm::IsConnOpen(conn->clientConnection)) {
1252  if (const auto ssl = fd_table[conn->clientConnection->fd].ssl.get()) {
1253  sb = sslGetUserCertificatePEM(ssl);
1254  out = sb.c_str();
1255  }
1256  }
1257  }
1258  break;
1259 
1260  case LFT_EXT_ACL_USER_CERT:
1261  if (al->request) {
1263  if (conn && Comm::IsConnOpen(conn->clientConnection)) {
1264  if (auto ssl = fd_table[conn->clientConnection->fd].ssl.get())
1265  out = sslGetUserAttribute(ssl, fmt->data.header.header);
1266  }
1267  }
1268  break;
1269 
1271  if (al->request) {
1273  if (conn && Comm::IsConnOpen(conn->clientConnection)) {
1274  if (auto ssl = fd_table[conn->clientConnection->fd].ssl.get())
1275  out = sslGetCAAttribute(ssl, fmt->data.header.header);
1276  }
1277  }
1278  break;
1279 
1281  if (const auto &cert = al->cache.sslClientCert) {
1282  sb = Security::SubjectName(*cert);
1283  out = sb.c_str();
1284  }
1285  break;
1286 
1288  if (const auto &cert = al->cache.sslClientCert) {
1289  sb = Security::IssuerName(*cert);
1290  out = sb.c_str();
1291  }
1292  break;
1293 
1294  case LFT_SSL_CLIENT_SNI:
1295  if (al->request && al->request->clientConnectionManager.valid()) {
1296  if (const ConnStateData *conn = al->request->clientConnectionManager.get()) {
1297  if (!conn->tlsClientSni().isEmpty()) {
1298  sb = conn->tlsClientSni();
1299  out = sb.c_str();
1300  }
1301  }
1302  }
1303  break;
1304 
1306  if (al->request && al->request->clientConnectionManager.valid()) {
1307  if (Ssl::ServerBump * srvBump = al->request->clientConnectionManager->serverBump()) {
1308  const char *separator = fmt->data.string ? fmt->data.string : ":";
1309  for (const Security::CertErrors *sslError = srvBump->sslErrors(); sslError; sslError = sslError->next) {
1310  if (!sb.isEmpty())
1311  sb.append(separator);
1312  sb.append(Ssl::GetErrorName(sslError->element.code, true));
1313  if (sslError->element.depth >= 0)
1314  sb.appendf("@depth=%d", sslError->element.depth);
1315  }
1316  if (!sb.isEmpty())
1317  out = sb.c_str();
1318  }
1319  }
1320  break;
1321 
1325  if (al->request && al->request->clientConnectionManager.valid()) {
1326  if (Ssl::ServerBump * srvBump = al->request->clientConnectionManager->serverBump()) {
1327  if (X509 *serverCert = srvBump->serverCert.get()) {
1328  if (fmt->type == LFT_SSL_SERVER_CERT_SUBJECT)
1329  out = Ssl::GetX509UserAttribute(serverCert, "DN");
1330  else if (fmt->type == LFT_SSL_SERVER_CERT_ISSUER)
1331  out = Ssl::GetX509CAAttribute(serverCert, "DN");
1332  else {
1333  assert(fmt->type == LFT_SSL_SERVER_CERT_WHOLE);
1334  sb = Ssl::GetX509PEM(serverCert);
1335  out = sb.c_str();
1336  quote = 1;
1337  }
1338  }
1339  }
1340  }
1341  break;
1342 
1344  if (al->tcpClient && al->tcpClient->hasTlsNegotiations())
1346  break;
1347 
1349  if (al->hier.tcpServer && al->hier.tcpServer->hasTlsNegotiations())
1351  break;
1352 
1354  if (al->tcpClient && al->tcpClient->hasTlsNegotiations())
1355  out = al->tcpClient->hasTlsNegotiations()->helloVersion();
1356  break;
1357 
1359  if (al->hier.tcpServer && al->hier.tcpServer->hasTlsNegotiations())
1361  break;
1362 
1364  if (al->tcpClient && al->tcpClient->hasTlsNegotiations())
1366  break;
1367 
1369  if (al->hier.tcpServer && al->hier.tcpServer->hasTlsNegotiations())
1371  break;
1372 
1374  if (al->tcpClient && al->tcpClient->hasTlsNegotiations())
1375  out = al->tcpClient->hasTlsNegotiations()->cipherName();
1376  break;
1377 
1379  if (al->hier.tcpServer && al->hier.tcpServer->hasTlsNegotiations())
1380  out = al->hier.tcpServer->hasTlsNegotiations()->cipherName();
1381  break;
1382 #endif
1383 
1385  assert(LFT_REQUEST_URLGROUP_OLD_2X == 0); // should never happen.
1386  break;
1387 
1388  case LFT_NOTE:
1389  tmp[0] = fmt->data.header.separator;
1390  tmp[1] = '\0';
1391  if (fmt->data.header.header && *fmt->data.header.header) {
1392  const char *separator = tmp;
1393  static SBuf note;
1394 #if USE_ADAPTATION
1396  if (ah && ah->metaHeaders) {
1397  if (ah->metaHeaders->find(note, fmt->data.header.header, separator))
1398  sb.append(note);
1399  }
1400 #endif
1401  if (al->notes) {
1402  if (al->notes->find(note, fmt->data.header.header, separator)) {
1403  if (!sb.isEmpty())
1404  sb.append(separator);
1405  sb.append(note);
1406  }
1407  }
1408  out = sb.c_str();
1409  quote = 1;
1410  } else {
1411  // No specific annotation requested. Report all annotations.
1412 
1413  // if no argument given use default "\r\n" as notes separator
1414  const char *separator = fmt->data.string ? tmp : "\r\n";
1415  SBufStream os;
1416 #if USE_ADAPTATION
1418  if (ah && ah->metaHeaders)
1419  ah->metaHeaders->print(os, ": ", separator);
1420 #endif
1421  if (al->notes)
1422  al->notes->print(os, ": ", separator);
1423 
1424  sb = os.buf();
1425  out = sb.c_str();
1426  quote = 1;
1427  }
1428  break;
1429 
1430  case LFT_CREDENTIALS:
1431 #if USE_AUTH
1432  if (al->request && al->request->auth_user_request)
1434 #endif
1435  break;
1436 
1437  case LFT_PERCENT:
1438  out = "%";
1439  break;
1440 
1441  case LFT_EXT_ACL_NAME:
1442  if (!al->lastAclName.isEmpty())
1443  out = al->lastAclName.c_str();
1444  break;
1445 
1446  case LFT_EXT_ACL_DATA:
1447  if (!al->lastAclData.isEmpty())
1448  out = al->lastAclData.c_str();
1449  break;
1450 
1451  case LFT_MASTER_XACTION:
1452  if (al->request) {
1453  doUint64 = true;
1454  outUint64 = static_cast<uint64_t>(al->request->masterXaction->id.value);
1455  break;
1456  }
1457  }
1458 
1459  if (dooff) {
1460  sb.appendf("%0*" PRId64, fmt->zero && fmt->widthMin >= 0 ? fmt->widthMin : 0, outoff);
1461  out = sb.c_str();
1462 
1463  } else if (doint) {
1464  sb.appendf("%0*ld", fmt->zero && fmt->widthMin >= 0 ? fmt->widthMin : 0, outint);
1465  out = sb.c_str();
1466  } else if (doUint64) {
1467  sb.appendf("%0*" PRIu64, fmt->zero && fmt->widthMin >= 0 ? fmt->widthMin : 0, outUint64);
1468  out = sb.c_str();
1469  } else if (doMsec) {
1470  if (fmt->widthMax < 0) {
1471  sb.appendf("%0*ld", fmt->zero && fmt->widthMin >= 0 ? fmt->widthMin : 0, tvToMsec(outtv));
1472  } else {
1473  int precision = fmt->widthMax;
1474  sb.appendf("%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)));
1475  }
1476  out = sb.c_str();
1477  } else if (doSec) {
1478  int precision = fmt->widthMax >=0 ? fmt->widthMax :3;
1479  sb.appendf("%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));
1480  out = sb.c_str();
1481  }
1482 
1483  if (out && *out) {
1484  if (quote || fmt->quote != LOG_QUOTE_NONE) {
1485  // Do not write to the tmp buffer because it may contain the to-be-quoted value.
1486  static char quotedOut[2 * sizeof(tmp)];
1487  static_assert(sizeof(quotedOut) > 0, "quotedOut has zero length");
1488  quotedOut[0] = '\0';
1489 
1490  char *newout = nullptr;
1491  int newfree = 0;
1492 
1493  switch (fmt->quote) {
1494 
1495  case LOG_QUOTE_NONE:
1496  newout = rfc1738_escape_unescaped(out);
1497  break;
1498 
1499  case LOG_QUOTE_QUOTES: {
1500  size_t out_len = static_cast<size_t>(strlen(out)) * 2 + 1;
1501  if (out_len >= sizeof(tmp)) {
1502  newout = (char *)xmalloc(out_len);
1503  newfree = 1;
1504  } else
1505  newout = quotedOut;
1506  log_quoted_string(out, newout);
1507  }
1508  break;
1509 
1510  case LOG_QUOTE_MIMEBLOB:
1511  newout = QuoteMimeBlob(out);
1512  newfree = 1;
1513  break;
1514 
1515  case LOG_QUOTE_URL:
1516  newout = rfc1738_escape(out);
1517  break;
1518 
1519  case LOG_QUOTE_SHELL: {
1520  MemBuf mbq;
1521  mbq.init();
1522  strwordquote(&mbq, out);
1523  newout = mbq.content();
1524  mbq.stolen = 1;
1525  newfree = 1;
1526  }
1527  break;
1528 
1529  case LOG_QUOTE_RAW:
1530  break;
1531  }
1532 
1533  if (newout) {
1534  if (dofree)
1535  safe_free(out);
1536 
1537  out = newout;
1538 
1539  dofree = newfree;
1540  }
1541  }
1542 
1543  // enforce width limits if configured
1544  const bool haveMaxWidth = fmt->widthMax >=0 && !doint && !dooff && !doMsec && !doSec && !doUint64;
1545  if (haveMaxWidth || fmt->widthMin) {
1546  const int minWidth = fmt->widthMin >= 0 ?
1547  fmt->widthMin :0;
1548  const int maxWidth = haveMaxWidth ?
1549  fmt->widthMax : strlen(out);
1550 
1551  if (fmt->left)
1552  mb.appendf("%-*.*s", minWidth, maxWidth, out);
1553  else
1554  mb.appendf("%*.*s", minWidth, maxWidth, out);
1555  } else
1556  mb.append(out, strlen(out));
1557  } else {
1558  mb.append("-", 1);
1559  }
1560 
1561  if (fmt->space)
1562  mb.append(" ", 1);
1563 
1564  sb.clear();
1565 
1566  if (dofree)
1567  safe_free(out);
1568  }
1569 }
1570 
const char * sslGetCAAttribute(SSL *ssl, const char *attribute_name)
Definition: support.cc:962
@ LFT_ICAP_TR_RESPONSE_TIME
Definition: ByteCode.h:213
@ LFT_LOCAL_LISTENING_IP
Definition: ByteCode.h:56
@ LFT_TRANSPORT_CLIENT_CONNECTION_ID
Definition: ByteCode.h:51
@ LFT_TLS_CLIENT_NEGOTIATED_VERSION
Definition: ByteCode.h:229
@ LFT_EXT_ACL_USER_CERT_RAW
Definition: ByteCode.h:245
Value value
instance identifier
Definition: InstanceId.h:70
Cbc * get() const
a temporary valid raw Cbc pointer or NULL
Definition: CbcPointer.h:159
@ LFT_SQUID_ERROR_DETAIL
Definition: ByteCode.h:175
@ LFT_CLIENT_LOCAL_PORT
Definition: ByteCode.h:46
Token * next
Definition: Token.h:73
AnyP::Port FindListeningPortNumber(const HttpRequest *callerRequest, const AccessLogEntry *ale)
Definition: HttpRequest.cc:872
@ LFT_ICAP_REQUEST_METHOD
Definition: ByteCode.h:200
unsigned int major
major version number
const char * helloVersion() const
String representation of the received TLS hello message version.
@ LFT_ICAP_SERV_NAME
Definition: ByteCode.h:198
int64_t bytesRead
number of bytes read from ICAP server so far
AnyP::ProtocolVersion http_ver
Definition: Message.h:72
#define base64_encode_len(length)
Definition: base64.h:169
void appendf(const char *fmt,...) PRINTF_FORMAT_ARG2
Append operation with printf-style arguments.
Definition: Packable.h:61
@ LFT_ICAP_BODY_BYTES_READ
Definition: ByteCode.h:203
@ LFT_CLIENT_REQ_URLSCHEME
Definition: ByteCode.h:75
@ LFT_SSL_SERVER_CERT_ERRORS
Definition: ByteCode.h:227
@ LFT_USER_NAME
Definition: ByteCode.h:151
SBuf & assign(const SBuf &S)
Definition: SBuf.cc:83
AnyP::Uri url
the request URI
Definition: HttpRequest.h:115
common parts of HttpRequest and HttpReply
Definition: Message.h:25
@ LFT_ADAPTATION_LAST_ALL_HEADERS
Definition: ByteCode.h:190
#define xmalloc
@ LOG_QUOTE_URL
Definition: ByteCode.h:266
@ LFT_ICAP_IO_TIME
Definition: ByteCode.h:214
HttpHeader allMeta
All REQMOD and RESPMOD meta headers merged. Last field wins conflicts.
Definition: History.h:63
@ LFT_ADAPTATION_LAST_HEADER
Definition: ByteCode.h:188
@ LFT_TAG
Definition: ByteCode.h:180
@ LFT_TOTAL_SERVER_SIDE_RESPONSE_TIME
Definition: ByteCode.h:168
virtual ~Format()
Definition: Format.cc:49
@ LFT_ICAP_REQ_HEADER_ELEM
Definition: ByteCode.h:206
const char * getLogClientFqdn(char *buf, size_t bufSize) const
virtual const char * credentialsStr()=0
@ scNone
Definition: StatusCode.h:21
const Error * error() const
HttpHeader header
Definition: Message.h:74
@ LFT_CLIENT_LOCAL_IP
Definition: ByteCode.h:45
Http::StatusCode peer_reply_status
last HTTP status code received
@ LFT_PROXY_PROTOCOL_RECEIVED_HEADER
Definition: ByteCode.h:256
bool isEmpty() const
Definition: SBuf.h:435
@ LFT_CLIENT_EUI
Definition: ByteCode.h:42
@ LFT_SSL_USER_CERT_SUBJECT
Definition: ByteCode.h:222
ssize_t HttpHeaderPos
Definition: HttpHeader.h:45
@ LFT_REQUEST_VERSION
Definition: ByteCode.h:88
Eui::Eui64 remoteEui64
Definition: Connection.h:178
@ LFT_SERVER_LOCAL_IP_OLD_27
Definition: ByteCode.h:67
@ LFT_USER_LOGIN
Definition: ByteCode.h:152
@ LFT_TLS_CLIENT_SUPPORTED_VERSION
Definition: ByteCode.h:235
@ LFT_SERVER_REQ_URLDOMAIN
Definition: ByteCode.h:105
void append(char const *, int) override
Appends a c-string to existing packed data.
Definition: store.cc:803
String reqUri
ICAP Request-URI.
size_t base64_encode_final(struct base64_encode_ctx *ctx, char *dst)
Definition: base64.c:308
InstanceId< Connection, uint64_t > id
Definition: Connection.h:181
const char * GetErrorName(const Security::ErrorCode code, const bool prefixRawCode=false)
Definition: ErrorDetail.h:38
bool encode(char *buf, const int len) const
Definition: Eui48.cc:144
@ LFT_SSL_SERVER_CERT_ISSUER
Definition: ByteCode.h:226
#define HttpHeaderInitPos
Definition: HttpHeader.h:48
void storeAppendPrintf(StoreEntry *e, const char *fmt,...)
Definition: store.cc:855
void print(std::ostream &os, const char *nameValueSeparator, const char *entryTerminator) const
Definition: Notes.cc:295
void error(char *format,...)
char * QuoteMimeBlob(const char *header)
Definition: Quoting.cc:43
unsigned int minor
minor version number
HttpRequest * request
ICAP request.
void init(mb_size_t szInit, mb_size_t szMax)
Definition: MemBuf.cc:93
@ LOG_QUOTE_RAW
Definition: ByteCode.h:268
int parse(const char *def, enum Quoting *quote)
Definition: Token.cc:353
@ LFT_EXT_LOG
Definition: ByteCode.h:181
Definition: SBuf.h:93
BumpMode
Definition: support.h:132
CbDataList * next
Definition: CbDataList.h:31
@ LFT_REQUEST_METHOD
Definition: ByteCode.h:83
const SBuf * effectiveVirginUrl() const
@ LFT_SQUID_REQUEST_ATTEMPTS
Definition: ByteCode.h:177
GETX509PEM GetX509PEM
Definition: support.h:121
@ LFT_SQUID_ERROR
Definition: ByteCode.h:174
#define xstrdup
ByteCode_t
Definition: ByteCode.h:30
@ LFT_CLIENT_REQ_URI
Definition: ByteCode.h:74
const char * errorPageName(int pageId)
error ID to string
Definition: errorpage.cc:669
class AccessLogEntry::SslDetails ssl
#define PRIu64
Definition: types.h:114
void rawAppendFinish(const char *start, size_type actualSize)
Definition: SBuf.cc:144
GETX509ATTRIBUTE GetX509CAAttribute
Definition: support.h:118
@ LFT_SERVER_LOCAL_IP
Definition: ByteCode.h:66
Auth::UserRequest::Pointer auth_user_request
Definition: HttpRequest.h:127
@ LFT_MIME_TYPE
Definition: ByteCode.h:179
HierarchyLogEntry hier
const char * negotiatedVersion() const
String representation of TLS negotiated version.
C * getRaw() const
Definition: RefCount.h:89
@ LFT_USER_EXTERNAL
Definition: ByteCode.h:155
struct timeval start_time
The time the master transaction started.
const SBuf & image() const
int dnsWait
sum of DNS lookup delays in milliseconds, for dt
Definition: HttpRequest.h:159
bool IsConnOpen(const Comm::ConnectionPointer &conn)
Definition: Connection.cc:27
@ LFT_REQUEST_URLGROUP_OLD_2X
Definition: ByteCode.h:89
#define strOrNull(s)
Convert a string to NULL pointer if it is "".
Definition: Format.cc:38
struct timeval trTime
The response time.
@ LFT_SQUID_STATUS
Definition: ByteCode.h:173
@ LFT_REQUEST_HEADER
Definition: ByteCode.h:92
@ LFT_SERVER_REQ_URLSCHEME
Definition: ByteCode.h:104
#define rfc1738_escape(x)
Definition: rfc1738.h:52
AnyP::ProtocolVersion version
NotePairs::Pointer notes
bool isIPv4() const
Definition: Address.cc:178
@ LFT_TIME_LOCALTIME
Definition: ByteCode.h:161
Token * format
Definition: Format.h:60
@ LFT_ADAPTED_REQUEST_HEADER
Definition: ByteCode.h:97
@ LFT_SERVER_IP_ADDRESS
Definition: ByteCode.h:61
bool ran() const
whether we ever measured time (i.e. resume() has been called)
Definition: Stopwatch.h:43
@ LFT_TIME_START
Definition: ByteCode.h:163
@ LFT_ICAP_TOTAL_TIME
Definition: ByteCode.h:195
bool parse(const char *def)
Definition: Format.cc:66
String extacl_user
Definition: HttpRequest.h:178
SBuf SubjectName(Certificate &)
The SubjectName field of the given certificate (if found) or an empty SBuf.
Definition: Certificate.cc:68
SBuf lastAclData
string for external_acl_type DATA format code
static int port
Definition: ldap_backend.cc:70
@ LOG_QUOTE_NONE
Definition: ByteCode.h:263
@ LFT_TLS_SERVER_NEGOTIATED_CIPHER
Definition: ByteCode.h:232
@ LFT_REPLY_HIGHOFFSET
Definition: ByteCode.h:142
void clear()
Definition: SBuf.cc:175
@ LFT_CLIENT_FQDN
Definition: ByteCode.h:40
size_t AssembleOne(const char *start, MemBuf &buf, const AccessLogEntryPointer &ale)
Definition: Format.cc:99
char * toStr(char *buf, const unsigned int blen, int force=AF_UNSPEC) const
Definition: Address.cc:812
@ LFT_SERVER_LOCAL_PORT
Definition: ByteCode.h:68
class AccessLogEntry::HttpDetails http
const char * c_str() const
compute the status access.log field
Definition: LogTags.cc:75
@ LFT_SSL_USER_CERT_ISSUER
Definition: ByteCode.h:223
@ LFT_ADAPTATION_LAST_HEADER_ELEM
Definition: ByteCode.h:189
char * rawAppendStart(size_type anticipatedSize)
Definition: SBuf.cc:136
@ LFT_ICAP_STATUS_CODE
Definition: ByteCode.h:216
@ LFT_PEER_RESPONSE_TIME
Definition: ByteCode.h:167
@ LFT_SERVER_REQ_VERSION
Definition: ByteCode.h:109
@ LFT_REQUEST_URLPATH_OLD_31
Definition: ByteCode.h:85
Format * next
Definition: Format.h:61
@ LFT_TIME_GMT
Definition: ByteCode.h:162
class AccessLogEntry::IcapLogEntry icap
@ LFT_TLS_CLIENT_RECEIVED_HELLO_VERSION
Definition: ByteCode.h:233
HttpRequest * request
bool encode(char *buf, const int len) const
Definition: Eui64.cc:34
@ LFT_SERVER_LOCAL_NFMARK
Definition: ByteCode.h:70
@ LOG_QUOTE_SHELL
Definition: ByteCode.h:267
@ LFT_MASTER_XACTION
Definition: ByteCode.h:241
@ LFT_CLIENT_REQUEST_SIZE_TOTAL
Definition: ByteCode.h:112
mb_size_t contentSize() const
available data size
Definition: MemBuf.h:47
struct timeval current_time
the current UNIX time in timeval {seconds, microseconds} format
Definition: gadgets.cc:18
@ LFT_TLS_SERVER_NEGOTIATED_VERSION
Definition: ByteCode.h:230
void append(const char *c, int sz) override
Definition: MemBuf.cc:209
@ LFT_BUSY_TIME
Definition: ByteCode.h:170
char * last_meta
image of the last ICAP response header or eCAP meta received
@ LFT_ICAP_BYTES_READ
Definition: ByteCode.h:202
@ LFT_ADAPTATION_ALL_XACT_TIMES
Definition: ByteCode.h:187
@ LFT_ICAP_REP_HEADER
Definition: ByteCode.h:209
@ LFT_TLS_CLIENT_NEGOTIATED_CIPHER
Definition: ByteCode.h:231
@ LFT_HTTP_SENT_STATUS_CODE_OLD_30
Definition: ByteCode.h:124
@ LFT_REQUEST_URI
Definition: ByteCode.h:84
@ LFT_SERVER_REQ_URLPATH
Definition: ByteCode.h:107
const Security::NegotiationHistory * hasTlsNegotiations() const
Definition: Connection.h:138
@ LFT_HTTP_BODY_BYTES_READ
Definition: ByteCode.h:128
const char * username() const
Definition: UserRequest.cc:32
uint64_t header
Definition: MessageSizes.h:21
unsigned short port() const
Definition: Address.cc:798
Definition: MemBuf.h:23
SBuf StringToSBuf(const String &s)
create a new SBuf from a String by copying contents
Definition: StringConvert.h:17
@ LFT_TLS_SERVER_SUPPORTED_VERSION
Definition: ByteCode.h:236
Adaptation::Icap::XactOutcome outcome
final transaction status
Ip::Address local
Definition: Connection.h:146
@ LFT_DNS_WAIT_TIME
Definition: ByteCode.h:169
Format(const char *name)
Definition: Format.cc:42
@ LFT_STRING
Definition: ByteCode.h:34
@ LFT_ICAP_OUTCOME
Definition: ByteCode.h:215
@ LFT_CLIENT_REQUEST_SIZE_HEADERS
Definition: ByteCode.h:113
unsigned stolen
Definition: MemBuf.h:151
@ LFT_EXT_ACL_CLIENT_EUI64
Definition: ByteCode.h:251
Comm::ConnectionPointer tcpClient
TCP/IP level details about the client connection.
@ LFT_EXT_ACL_USER_CERTCHAIN_RAW
Definition: ByteCode.h:246
int64_t bytesSent
number of bytes sent to ICAP server so far
@ LFT_CLIENT_REQ_METHOD
Definition: ByteCode.h:73
bool peerResponseTime(struct timeval &responseTime)
Definition: access_log.cc:239
struct timeval ioTime
Transaction I/O time. The timer starts when the first ICAP request byte is scheduled for sending and ...
bool find(SBuf &resultNote, const char *noteKey, const char *sep=",") const
Definition: Notes.cc:281
#define safe_free(x)
Definition: xalloc.h:73
@ LFT_CLIENT_REQ_URLPATH
Definition: ByteCode.h:78
@ LFT_REQUEST_ALL_HEADERS
Definition: ByteCode.h:94
@ LFT_REPLY_HEADER
Definition: ByteCode.h:131
Ip::Address remote
Definition: Connection.h:149
MasterXaction::Pointer masterXaction
the master transaction this request belongs to. Never nil.
Definition: HttpRequest.h:238
#define assert(EX)
Definition: assert.h:17
@ LFT_SERVER_LOCAL_TOS
Definition: ByteCode.h:69
@ LFT_EXT_ACL_USER_CA_CERT
Definition: ByteCode.h:248
@ LFT_EXT_ACL_DATA
Definition: ByteCode.h:253
SBuf image() const
Definition: UriScheme.h:57
class AccessLogEntry::CacheDetails cache
HierarchyLogEntry hier
Definition: HttpRequest.h:157
SBuf IssuerName(Certificate &)
The Issuer field of the given certificate (if found) or an empty SBuf.
Definition: Certificate.cc:28
@ LFT_ICAP_REP_ALL_HEADERS
Definition: ByteCode.h:211
MessageSizes clientRequestSz
counters for the original request received from client
SBuf buf()
bytes written so far
Definition: Stream.h:41
NotePairs::Pointer metaHeaders
Definition: History.h:66
HttpReply * reply
ICAP reply.
const AnyP::UriScheme & getScheme() const
Definition: Uri.h:58
Eui::Eui48 remoteEui48
Definition: Connection.h:177
@ LFT_TIME_TO_HANDLE_REQUEST
Definition: ByteCode.h:166
@ LFT_ICAP_REQ_ALL_HEADERS
Definition: ByteCode.h:207
@ LFT_ICAP_REQ_HEADER
Definition: ByteCode.h:205
@ LFT_ICAP_REP_HEADER_ELEM
Definition: ByteCode.h:210
void port(const Port p)
reset authority port subcomponent
Definition: Uri.h:90
class AccessLogEntry::Headers headers
const char * c_str()
Definition: SBuf.cc:516
void base64_encode_init(struct base64_encode_ctx *ctx)
Definition: base64.c:232
@ LFT_CLIENT_IP_ADDRESS
Definition: ByteCode.h:39
String serviceName
ICAP service name.
const char * methodStr(Method)
Definition: Elements.cc:15
String extacl_log
Definition: HttpRequest.h:182
time_t squid_curtime
Definition: stub_libtime.cc:20
void allLogString(const char *serviceId, SBuf &)
dump individual xaction times to a string
Definition: History.cc:67
@ LFT_REPLY_OBJECTSIZE
Definition: ByteCode.h:143
int cur
Definition: ModDevPoll.cc:68
Comm::ConnectionPointer clientConnection
Definition: Server.h:100
const char * sslGetUserAttribute(SSL *ssl, const char *attribute_name)
Definition: support.cc:949
class AccessLogEntry::AdaptationDetails adapt
SBuf & append(const SBuf &S)
Definition: SBuf.cc:185
#define xfree
@ LFT_ADAPTED_REPLY_SIZE_TOTAL
Definition: ByteCode.h:141
@ LFT_ADAPTATION_SUM_XACT_TIMES
Definition: ByteCode.h:186
@ LFT_CLIENT_PORT
Definition: ByteCode.h:41
@ LFT_SERVER_REQ_URLPORT
Definition: ByteCode.h:106
@ LFT_EXT_ACL_NAME
Definition: ByteCode.h:252
RefCount< Adaptation::History > Pointer
Definition: History.h:27
@ LFT_ADAPTED_REPLY_SIZE_HEADERS
Definition: ByteCode.h:144
struct timeval trTime
Transaction response time. The timer starts when the ICAP transaction is created and stops when the r...
void strwordquote(MemBuf *mb, const char *str)
Definition: tools.cc:1080
@ LFT_EXT_ACL_USER_CERT
Definition: ByteCode.h:247
Adaptation::History::Pointer adaptHistory(bool createIfNone=false) const
Returns possibly nil history, creating it if requested.
Definition: HttpRequest.cc:404
SBuf preservedClientData
Definition: client_side.h:349
Security::CertPointer sslClientCert
cert received from the client
const Ip::Address * FindListeningPortAddress(const HttpRequest *callerRequest, const AccessLogEntry *ale)
Definition: HttpRequest.cc:863
@ LFT_TLS_SERVER_RECEIVED_HELLO_VERSION
Definition: ByteCode.h:234
@ LFT_PROXY_PROTOCOL_RECEIVED_ALL_HEADERS
Definition: ByteCode.h:258
void sumLogString(const char *serviceId, SBuf &)
dump xaction times, merging retried and retry times together
Definition: History.cc:83
#define fd_table
Definition: fde.h:189
#define rfc1738_escape_unescaped(x)
Definition: rfc1738.h:59
uint64_t messageTotal() const
total message size
Definition: MessageSizes.h:27
int64_t bodyBytesRead
number of body bytes received from the next hop or -1
Comm::ConnectionPointer tcpServer
TCP/IP level details of the last peer/server connection.
@ LFT_SEQUENCE_NUMBER
Definition: ByteCode.h:183
String getByName(const SBuf &name) const
Definition: HttpHeader.cc:848
ProxyProtocol::HeaderPointer proxyProtocolHeader
see ConnStateData::proxyProtocolHeader_
@ LFT_REPLY_ALL_HEADERS
Definition: ByteCode.h:133
HttpRequestMethod method
Definition: HttpRequest.h:114
void path(const char *p)
Definition: Uri.h:96
const char * hier_code_str[]
@ LFT_ADAPTED_REQUEST_HEADER_ELEM
Definition: ByteCode.h:98
@ LFT_SERVER_PORT
Definition: ByteCode.h:63
const char * termedBuf() const
Definition: SquidString.h:92
HttpRequest * adapted_request
@ methodRespmod
Definition: Elements.h:17
struct timeval processingTime
total ICAP processing time
@ LOG_QUOTE_QUOTES
Definition: ByteCode.h:264
Http::StatusCode resStatus
ICAP response status code.
SBuf getByNameListMember(const char *name, const char *member, const char separator) const
Definition: HttpHeader.cc:917
@ LFT_ADAPTED_REQUEST_ALL_HEADERS
Definition: ByteCode.h:99
char * content()
start of the added data
Definition: MemBuf.h:41
MessageSizes clientReplySz
counters for the response sent to client
@ LFT_CLIENT_REQ_VERSION
Definition: ByteCode.h:80
size_type size() const
Definition: SquidString.h:73
@ LOG_QUOTE_MIMEBLOB
Definition: ByteCode.h:265
GETX509ATTRIBUTE GetX509UserAttribute
Definition: support.h:115
void getLogClientIp(char *buf, size_t bufsz) const
@ LFT_PROXY_PROTOCOL_RECEIVED_HEADER_ELEM
Definition: ByteCode.h:257
@ LFT_CLIENT_REQ_URLDOMAIN
Definition: ByteCode.h:76
Stopwatch busyTime
time spent in this context (see also: busy_time)
Definition: CodeContext.h:76
SBuf ToSBuf(Args &&... args)
slowly stream-prints all arguments into a freshly allocated SBuf
Definition: Stream.h:63
@ LFT_CLIENT_LOCAL_NFMARK
Definition: ByteCode.h:49
static void log_quoted_string(const char *str, char *out)
Definition: Format.cc:292
@ LFT_HTTP_SENT_STATUS_CODE
Definition: ByteCode.h:125
#define DBG_IMPORTANT
Definition: Stream.h:38
Ssl::ServerBump * serverBump()
Definition: client_side.h:285
size_t base64_encode_update(struct base64_encode_ctx *ctx, char *dst, size_t length, const uint8_t *src)
Definition: base64.c:265
void packReplyHeaders(MemBuf &mb) const
dump all reply headers (for sending or risky logging)
@ LFT_TIME_SECONDS_SINCE_EPOCH
Definition: ByteCode.h:159
#define MYNAME
Definition: Stream.h:219
@ LFT_REQUEST_HEADER_ELEM
Definition: ByteCode.h:93
@ LFT_SSL_SERVER_CERT_WHOLE
Definition: ByteCode.h:228
SBuf lastAclName
string for external_acl_type ACL format code
bool hasLogMethod() const
whether we know what the request method is
void assemble(MemBuf &mb, const AccessLogEntryPointer &al, int logSequenceNumber) const
assemble the state information into a formatted line.
Definition: Format.cc:377
@ LFT_REQUEST_VERSION_OLD_2X
Definition: ByteCode.h:87
#define PRId64
Definition: types.h:104
@ methodReqmod
Definition: Elements.h:17
@ LFT_SERVER_REQ_METHOD
Definition: ByteCode.h:102
@ LFT_CLIENT_IO_SIZE_TOTAL
Definition: ByteCode.h:148
static const Http::Message * actualReplyHeader(const AccessLogEntry::Pointer &al)
Definition: Format.cc:350
char host[SQUIDHOSTNAMELEN]
@ LFT_SSL_BUMP_MODE
Definition: ByteCode.h:221
@ LFT_PERCENT
Definition: ByteCode.h:240
@ LFT_BYTE
Definition: ByteCode.h:36
@ LFT_CLIENT_REQ_URLPORT
Definition: ByteCode.h:77
long int tvToMsec(struct timeval &t)
Definition: gadgets.h:93
@ LFT_REPLY_HEADER_ELEM
Definition: ByteCode.h:132
@ LFT_HTTP_RECEIVED_STATUS_CODE
Definition: ByteCode.h:126
@ LFT_NONE
Definition: ByteCode.h:31
static const Http::Message * actualRequestHeader(const AccessLogEntry::Pointer &al)
Definition: Format.cc:364
Clock::duration total() const
Definition: Stopwatch.cc:22
Stopwatch totalPeeringTime
cumulative time spent (so far) communicating with all peers (see %<tt)
@ LFT_SSL_CLIENT_SNI
Definition: ByteCode.h:224
int bumpMode
whether and how the request was SslBumped
@ LFT_CLIENT_HANDSHAKE
Definition: ByteCode.h:53
@ LFT_NOTE
Definition: ByteCode.h:239
@ LFT_CREDENTIALS
Definition: ByteCode.h:218
InstanceId< MasterXaction, uint64_t > id
transaction ID.
Definition: MasterXaction.h:60
SBuf & appendf(const char *fmt,...) PRINTF_FORMAT_ARG2
Definition: SBuf.cc:229
HttpHeaderEntry * getEntry(HttpHeaderPos *pos) const
Definition: HttpHeader.cc:583
Ip::Address hostAddr
ICAP server IP address.
@ LFT_SERVER_REQ_URI
Definition: ByteCode.h:103
const SBuf & effectiveRequestUri() const
RFC 7230 section 5.5 - Effective Request URI.
Definition: HttpRequest.cc:744
@ LFT_ICAP_REQUEST_URI
Definition: ByteCode.h:199
Ip::Address client_addr
Definition: HttpRequest.h:149
@ LFT_TIME_SUBSECOND
Definition: ByteCode.h:160
@ LFT_SSL_SERVER_CERT_SUBJECT
Definition: ByteCode.h:225
void host(const char *src)
Definition: Uri.cc:123
void dump(StoreEntry *entry, const char *directiveName, bool eol=true) const
dump this whole list of formats into the provided StoreEntry
Definition: Format.cc:117
@ LFT_ICAP_ADDR
Definition: ByteCode.h:197
Adaptation::Icap::ICAP::Method reqMethod
ICAP request method.
const char * getExtUser() const
Fetch the external ACL provided 'user=' string, or nil if none is available.
const char * supportedVersion() const
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:192
String tag
Definition: HttpRequest.h:176
const char * bumpMode(int bm)
Definition: support.h:144
@ LFT_CLIENT_LOCAL_TOS
Definition: ByteCode.h:48
const SBuf Dash
@ LFT_SERVER_FQDN_OR_PEER_NAME
Definition: ByteCode.h:62
SBuf getLogMethod() const
Fetch the transaction method string (ICP opcode, HTCP opcode or HTTP method)
nfmark_t nfmark
Definition: Connection.h:163
@ LFT_LOCAL_LISTENING_PORT
Definition: ByteCode.h:57
SBuf sslGetUserCertificatePEM(SSL *ssl)
Definition: support.cc:982
@ LFT_EXT_ACL_CLIENT_EUI48
Definition: ByteCode.h:250
@ LFT_ICAP_BYTES_SENT
Definition: ByteCode.h:201
CbcPointer< ConnStateData > clientConnectionManager
Definition: HttpRequest.h:232
Quoting
Quoting style for a format output.
Definition: ByteCode.h:262
int timedout
Definition: PingData.h:42
@ LFT_SQUID_HIERARCHY
Definition: ByteCode.h:176

 

Introduction

Documentation

Support

Miscellaneous