]>
Commit | Line | Data |
---|---|---|
bbc27441 | 1 | /* |
ef57eb7b | 2 | * Copyright (C) 1996-2016 The Squid Software Foundation and contributors |
bbc27441 AJ |
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 | ||
f7f3304a | 9 | #include "squid.h" |
38e16f92 | 10 | #include "AccessLogEntry.h" |
582c2af2 | 11 | #include "client_side.h" |
38e16f92 AJ |
12 | #include "comm/Connection.h" |
13 | #include "err_detail_type.h" | |
14 | #include "errorpage.h" | |
f4698e0b | 15 | #include "fde.h" |
38e16f92 AJ |
16 | #include "format/Format.h" |
17 | #include "format/Quoting.h" | |
31971e6a | 18 | #include "format/Token.h" |
95e6d864 | 19 | #include "fqdncache.h" |
38e16f92 AJ |
20 | #include "HttpRequest.h" |
21 | #include "MemBuf.h" | |
22 | #include "rfc1738.h" | |
4b307ad4 | 23 | #include "security/NegotiationHistory.h" |
38e16f92 AJ |
24 | #include "SquidTime.h" |
25 | #include "Store.h" | |
95d78f10 | 26 | #include "tools.h" |
b1bd952a | 27 | #include "URL.h" |
cb4f4424 | 28 | #if USE_OPENSSL |
2f3e52b5 | 29 | #include "ssl/ErrorDetail.h" |
cedca6e7 | 30 | #include "ssl/ServerBump.h" |
2f3e52b5 CT |
31 | #endif |
32 | ||
bd85ea1f AJ |
33 | /// Convert a string to NULL pointer if it is "" |
34 | #define strOrNull(s) ((s)==NULL||(s)[0]=='\0'?NULL:(s)) | |
38e16f92 AJ |
35 | |
36 | Format::Format::Format(const char *n) : | |
f53969cc SM |
37 | format(NULL), |
38 | next(NULL) | |
38e16f92 AJ |
39 | { |
40 | name = xstrdup(n); | |
41 | } | |
42 | ||
43 | Format::Format::~Format() | |
44 | { | |
45 | // erase the list without consuming stack space | |
46 | while (next) { | |
47 | // unlink the next entry for deletion | |
48 | Format *temp = next; | |
49 | next = temp->next; | |
50 | temp->next = NULL; | |
51 | delete temp; | |
52 | } | |
53 | ||
54 | // remove locals | |
55 | xfree(name); | |
56 | delete format; | |
57 | } | |
58 | ||
59 | bool | |
f4698e0b | 60 | Format::Format::parse(const char *def) |
38e16f92 | 61 | { |
f4698e0b | 62 | const char *cur, *eos; |
38e16f92 AJ |
63 | Token *new_lt, *last_lt; |
64 | enum Quoting quote = LOG_QUOTE_NONE; | |
65 | ||
66 | debugs(46, 2, HERE << "got definition '" << def << "'"); | |
67 | ||
68 | if (format) { | |
69 | debugs(46, DBG_IMPORTANT, "WARNING: existing format for '" << name << " " << def << "'"); | |
70 | return false; | |
71 | } | |
72 | ||
73 | /* very inefficent parser, but who cares, this needs to be simple */ | |
74 | /* First off, let's tokenize, we'll optimize in a second pass. | |
75 | * A token can either be a %-prefixed sequence (usually a dynamic | |
76 | * token but it can be an escaped sequence), or a string. */ | |
77 | cur = def; | |
78 | eos = def + strlen(def); | |
79 | format = new_lt = last_lt = new Token; | |
80 | cur += new_lt->parse(cur, "e); | |
81 | ||
82 | while (cur < eos) { | |
83 | new_lt = new Token; | |
84 | last_lt->next = new_lt; | |
85 | last_lt = new_lt; | |
86 | cur += new_lt->parse(cur, "e); | |
87 | } | |
88 | ||
89 | return true; | |
90 | } | |
91 | ||
92 | void | |
4e56d7f6 | 93 | Format::Format::dump(StoreEntry * entry, const char *directiveName, bool eol) const |
38e16f92 AJ |
94 | { |
95 | debugs(46, 4, HERE); | |
96 | ||
97 | // loop rather than recursing to conserve stack space. | |
4e56d7f6 | 98 | for (const Format *fmt = this; fmt; fmt = fmt->next) { |
5f621cd0 | 99 | debugs(46, 3, HERE << "Dumping format definition for " << fmt->name); |
4e56d7f6 AJ |
100 | if (directiveName) |
101 | storeAppendPrintf(entry, "%s %s ", directiveName, fmt->name); | |
38e16f92 | 102 | |
5f621cd0 | 103 | for (Token *t = fmt->format; t; t = t->next) { |
38e16f92 AJ |
104 | if (t->type == LFT_STRING) |
105 | storeAppendPrintf(entry, "%s", t->data.string); | |
106 | else { | |
107 | char argbuf[256]; | |
108 | char *arg = NULL; | |
109 | ByteCode_t type = t->type; | |
110 | ||
111 | switch (type) { | |
f53969cc | 112 | /* special cases */ |
38e16f92 AJ |
113 | |
114 | case LFT_STRING: | |
115 | break; | |
116 | #if USE_ADAPTATION | |
117 | case LFT_ADAPTATION_LAST_HEADER_ELEM: | |
118 | #endif | |
119 | #if ICAP_CLIENT | |
120 | case LFT_ICAP_REQ_HEADER_ELEM: | |
121 | case LFT_ICAP_REP_HEADER_ELEM: | |
122 | #endif | |
123 | case LFT_REQUEST_HEADER_ELEM: | |
124 | case LFT_ADAPTED_REQUEST_HEADER_ELEM: | |
125 | case LFT_REPLY_HEADER_ELEM: | |
126 | ||
127 | if (t->data.header.separator != ',') | |
128 | snprintf(argbuf, sizeof(argbuf), "%s:%c%s", t->data.header.header, t->data.header.separator, t->data.header.element); | |
129 | else | |
130 | snprintf(argbuf, sizeof(argbuf), "%s:%s", t->data.header.header, t->data.header.element); | |
131 | ||
132 | arg = argbuf; | |
133 | ||
134 | switch (type) { | |
135 | case LFT_REQUEST_HEADER_ELEM: | |
136 | type = LFT_REQUEST_HEADER_ELEM; // XXX: remove _ELEM? | |
137 | break; | |
138 | case LFT_ADAPTED_REQUEST_HEADER_ELEM: | |
139 | type = LFT_ADAPTED_REQUEST_HEADER_ELEM; // XXX: remove _ELEM? | |
140 | break; | |
141 | case LFT_REPLY_HEADER_ELEM: | |
142 | type = LFT_REPLY_HEADER_ELEM; // XXX: remove _ELEM? | |
143 | break; | |
144 | #if USE_ADAPTATION | |
145 | case LFT_ADAPTATION_LAST_HEADER_ELEM: | |
146 | type = LFT_ADAPTATION_LAST_HEADER; | |
147 | break; | |
148 | #endif | |
149 | #if ICAP_CLIENT | |
150 | case LFT_ICAP_REQ_HEADER_ELEM: | |
151 | type = LFT_ICAP_REQ_HEADER; | |
152 | break; | |
153 | case LFT_ICAP_REP_HEADER_ELEM: | |
154 | type = LFT_ICAP_REP_HEADER; | |
155 | break; | |
156 | #endif | |
157 | default: | |
158 | break; | |
159 | } | |
160 | ||
161 | break; | |
162 | ||
163 | case LFT_REQUEST_ALL_HEADERS: | |
164 | case LFT_ADAPTED_REQUEST_ALL_HEADERS: | |
165 | case LFT_REPLY_ALL_HEADERS: | |
166 | ||
167 | #if USE_ADAPTATION | |
168 | case LFT_ADAPTATION_LAST_ALL_HEADERS: | |
169 | #endif | |
170 | #if ICAP_CLIENT | |
171 | case LFT_ICAP_REQ_ALL_HEADERS: | |
172 | case LFT_ICAP_REP_ALL_HEADERS: | |
173 | #endif | |
174 | ||
175 | switch (type) { | |
176 | case LFT_REQUEST_ALL_HEADERS: | |
177 | type = LFT_REQUEST_HEADER; | |
178 | break; | |
179 | case LFT_ADAPTED_REQUEST_ALL_HEADERS: | |
180 | type = LFT_ADAPTED_REQUEST_HEADER; | |
181 | break; | |
182 | case LFT_REPLY_ALL_HEADERS: | |
183 | type = LFT_REPLY_HEADER; | |
184 | break; | |
185 | #if USE_ADAPTATION | |
186 | case LFT_ADAPTATION_LAST_ALL_HEADERS: | |
187 | type = LFT_ADAPTATION_LAST_HEADER; | |
188 | break; | |
189 | #endif | |
190 | #if ICAP_CLIENT | |
191 | case LFT_ICAP_REQ_ALL_HEADERS: | |
192 | type = LFT_ICAP_REQ_HEADER; | |
193 | break; | |
194 | case LFT_ICAP_REP_ALL_HEADERS: | |
195 | type = LFT_ICAP_REP_HEADER; | |
196 | break; | |
197 | #endif | |
198 | default: | |
199 | break; | |
200 | } | |
201 | ||
202 | break; | |
203 | ||
204 | default: | |
205 | if (t->data.string) | |
206 | arg = t->data.string; | |
207 | ||
208 | break; | |
209 | } | |
210 | ||
211 | entry->append("%", 1); | |
212 | ||
213 | switch (t->quote) { | |
214 | ||
215 | case LOG_QUOTE_QUOTES: | |
216 | entry->append("\"", 1); | |
217 | break; | |
218 | ||
219 | case LOG_QUOTE_MIMEBLOB: | |
220 | entry->append("[", 1); | |
221 | break; | |
222 | ||
223 | case LOG_QUOTE_URL: | |
224 | entry->append("#", 1); | |
225 | break; | |
226 | ||
227 | case LOG_QUOTE_RAW: | |
228 | entry->append("'", 1); | |
229 | break; | |
230 | ||
95d78f10 AJ |
231 | case LOG_QUOTE_SHELL: |
232 | entry->append("/", 1); | |
233 | break; | |
234 | ||
38e16f92 AJ |
235 | case LOG_QUOTE_NONE: |
236 | break; | |
237 | } | |
238 | ||
239 | if (t->left) | |
240 | entry->append("-", 1); | |
241 | ||
242 | if (t->zero) | |
243 | entry->append("0", 1); | |
244 | ||
8846a2b4 CT |
245 | if (t->widthMin >= 0) |
246 | storeAppendPrintf(entry, "%d", t->widthMin); | |
38e16f92 | 247 | |
8846a2b4 CT |
248 | if (t->widthMax >= 0) |
249 | storeAppendPrintf(entry, ".%d", t->widthMax); | |
38e16f92 AJ |
250 | |
251 | if (arg) | |
252 | storeAppendPrintf(entry, "{%s}", arg); | |
253 | ||
aa99e35e | 254 | storeAppendPrintf(entry, "%s", t->label); |
38e16f92 AJ |
255 | |
256 | if (t->space) | |
257 | entry->append(" ", 1); | |
258 | } | |
259 | } | |
260 | ||
4e56d7f6 AJ |
261 | if (eol) |
262 | entry->append("\n", 1); | |
38e16f92 AJ |
263 | } |
264 | ||
265 | } | |
266 | ||
267 | static void | |
268 | log_quoted_string(const char *str, char *out) | |
269 | { | |
270 | char *p = out; | |
271 | ||
272 | while (*str) { | |
273 | int l = strcspn(str, "\"\\\r\n\t"); | |
274 | memcpy(p, str, l); | |
275 | str += l; | |
276 | p += l; | |
277 | ||
278 | switch (*str) { | |
279 | ||
280 | case '\0': | |
281 | break; | |
282 | ||
283 | case '\r': | |
a38ec4b1 FC |
284 | *p = '\\'; |
285 | ++p; | |
286 | *p = 'r'; | |
287 | ++p; | |
cb4185f1 | 288 | ++str; |
38e16f92 AJ |
289 | break; |
290 | ||
291 | case '\n': | |
a38ec4b1 FC |
292 | *p = '\\'; |
293 | ++p; | |
294 | *p = 'n'; | |
295 | ++p; | |
cb4185f1 | 296 | ++str; |
38e16f92 AJ |
297 | break; |
298 | ||
299 | case '\t': | |
a38ec4b1 FC |
300 | *p = '\\'; |
301 | ++p; | |
302 | *p = 't'; | |
303 | ++p; | |
cb4185f1 | 304 | ++str; |
38e16f92 AJ |
305 | break; |
306 | ||
307 | default: | |
a38ec4b1 FC |
308 | *p = '\\'; |
309 | ++p; | |
310 | *p = *str; | |
311 | ++p; | |
cb4185f1 | 312 | ++str; |
38e16f92 AJ |
313 | break; |
314 | } | |
315 | } | |
316 | ||
cb4185f1 | 317 | *p = '\0'; |
38e16f92 AJ |
318 | } |
319 | ||
7598eb63 CT |
320 | #if USE_OPENSSL |
321 | static char * | |
322 | sslErrorName(Ssl::ssl_error_t err, char *buf, size_t size) | |
323 | { | |
324 | snprintf(buf, size, "SSL_ERR=%d", err); | |
325 | return buf; | |
326 | } | |
327 | #endif | |
328 | ||
38e16f92 | 329 | void |
f4698e0b | 330 | Format::Format::assemble(MemBuf &mb, const AccessLogEntry::Pointer &al, int logSequenceNumber) const |
38e16f92 AJ |
331 | { |
332 | char tmp[1024]; | |
333 | String sb; | |
334 | ||
f53969cc | 335 | for (Token *fmt = format; fmt != NULL; fmt = fmt->next) { /* for each token */ |
38e16f92 AJ |
336 | const char *out = NULL; |
337 | int quote = 0; | |
338 | long int outint = 0; | |
339 | int doint = 0; | |
340 | int dofree = 0; | |
341 | int64_t outoff = 0; | |
342 | int dooff = 0; | |
01bd87d8 CT |
343 | struct timeval outtv = {0, 0}; |
344 | int doMsec = 0; | |
345 | int doSec = 0; | |
38e16f92 AJ |
346 | |
347 | switch (fmt->type) { | |
348 | ||
349 | case LFT_NONE: | |
350 | out = ""; | |
351 | break; | |
352 | ||
353 | case LFT_STRING: | |
354 | out = fmt->data.string; | |
355 | break; | |
356 | ||
357 | case LFT_CLIENT_IP_ADDRESS: | |
d4204018 AJ |
358 | al->getLogClientIp(tmp, sizeof(tmp)); |
359 | out = tmp; | |
38e16f92 AJ |
360 | break; |
361 | ||
362 | case LFT_CLIENT_FQDN: | |
4dd643d5 | 363 | if (al->cache.caddr.isAnyAddr()) // e.g., ICAP OPTIONS lack client |
38e16f92 AJ |
364 | out = "-"; |
365 | else | |
366 | out = fqdncache_gethostbyaddr(al->cache.caddr, FQDN_LOOKUP_IF_MISS); | |
367 | if (!out) { | |
4dd643d5 | 368 | out = al->cache.caddr.toStr(tmp,1024); |
38e16f92 AJ |
369 | } |
370 | ||
371 | break; | |
372 | ||
373 | case LFT_CLIENT_PORT: | |
374 | if (al->request) { | |
4dd643d5 | 375 | outint = al->request->client_addr.port(); |
38e16f92 AJ |
376 | doint = 1; |
377 | } | |
378 | break; | |
379 | ||
38e16f92 | 380 | case LFT_CLIENT_EUI: |
8652f8e7 | 381 | #if USE_SQUID_EUI |
38e16f92 AJ |
382 | // TODO make the ACL checklist have a direct link to any TCP details. |
383 | if (al->request && al->request->clientConnectionManager.valid() && al->request->clientConnectionManager->clientConnection != NULL) { | |
4dd643d5 | 384 | if (al->request->clientConnectionManager->clientConnection->remote.isIPv4()) |
38e16f92 AJ |
385 | al->request->clientConnectionManager->clientConnection->remoteEui48.encode(tmp, 1024); |
386 | else | |
387 | al->request->clientConnectionManager->clientConnection->remoteEui64.encode(tmp, 1024); | |
388 | out = tmp; | |
389 | } | |
38e16f92 | 390 | #endif |
8652f8e7 | 391 | break; |
38e16f92 | 392 | |
4e56d7f6 | 393 | case LFT_EXT_ACL_CLIENT_EUI48: |
38d7fa02 | 394 | #if USE_SQUID_EUI |
4e56d7f6 AJ |
395 | if (al->request && al->request->clientConnectionManager.valid() && |
396 | al->request->clientConnectionManager->clientConnection != NULL && | |
397 | al->request->clientConnectionManager->clientConnection->remote.isIPv4()) { | |
398 | al->request->clientConnectionManager->clientConnection->remoteEui48.encode(tmp, 1024); | |
399 | out = tmp; | |
400 | } | |
38d7fa02 | 401 | #endif |
4e56d7f6 AJ |
402 | break; |
403 | ||
404 | case LFT_EXT_ACL_CLIENT_EUI64: | |
38d7fa02 | 405 | #if USE_SQUID_EUI |
4e56d7f6 AJ |
406 | if (al->request && al->request->clientConnectionManager.valid() && |
407 | al->request->clientConnectionManager->clientConnection != NULL && | |
408 | !al->request->clientConnectionManager->clientConnection->remote.isIPv4()) { | |
409 | al->request->clientConnectionManager->clientConnection->remoteEui64.encode(tmp, 1024); | |
410 | out = tmp; | |
411 | } | |
4e56d7f6 | 412 | #endif |
38d7fa02 | 413 | break; |
4e56d7f6 | 414 | |
8652f8e7 AJ |
415 | case LFT_SERVER_IP_ADDRESS: |
416 | if (al->hier.tcpServer != NULL) { | |
4dd643d5 | 417 | out = al->hier.tcpServer->remote.toStr(tmp,sizeof(tmp)); |
8652f8e7 AJ |
418 | } |
419 | break; | |
38e16f92 | 420 | |
8652f8e7 | 421 | case LFT_SERVER_FQDN_OR_PEER_NAME: |
38e16f92 | 422 | out = al->hier.host; |
38e16f92 AJ |
423 | break; |
424 | ||
8652f8e7 AJ |
425 | case LFT_SERVER_PORT: |
426 | if (al->hier.tcpServer != NULL) { | |
4dd643d5 | 427 | outint = al->hier.tcpServer->remote.port(); |
8652f8e7 AJ |
428 | doint = 1; |
429 | } | |
430 | break; | |
38e16f92 | 431 | |
28417506 CT |
432 | case LFT_LOCAL_LISTENING_IP: { |
433 | // avoid logging a dash if we have reliable info | |
47176c0b | 434 | const bool interceptedAtKnownPort = al->request ? |
0d901ef4 | 435 | (al->request->flags.interceptTproxy || |
fa720bfb | 436 | al->request->flags.intercepted) && al->cache.port != NULL : |
47176c0b | 437 | false; |
28417506 | 438 | if (interceptedAtKnownPort) { |
4dd643d5 | 439 | const bool portAddressConfigured = !al->cache.port->s.isAnyAddr(); |
28417506 | 440 | if (portAddressConfigured) |
4dd643d5 | 441 | out = al->cache.port->s.toStr(tmp, sizeof(tmp)); |
28417506 | 442 | } else if (al->tcpClient != NULL) |
4dd643d5 | 443 | out = al->tcpClient->local.toStr(tmp, sizeof(tmp)); |
28417506 CT |
444 | } |
445 | break; | |
446 | ||
8652f8e7 | 447 | case LFT_CLIENT_LOCAL_IP: |
a14f38d0 | 448 | if (al->tcpClient != NULL) { |
4dd643d5 | 449 | out = al->tcpClient->local.toStr(tmp,sizeof(tmp)); |
38e16f92 | 450 | } |
38e16f92 AJ |
451 | break; |
452 | ||
f123f5e9 CT |
453 | case LFT_CLIENT_LOCAL_TOS: |
454 | if (al->tcpClient != NULL) { | |
455 | snprintf(tmp, sizeof(tmp), "0x%x", (uint32_t)al->tcpClient->tos); | |
456 | out = tmp; | |
457 | } | |
458 | break; | |
459 | ||
460 | case LFT_CLIENT_LOCAL_NFMARK: | |
461 | if (al->tcpClient != NULL) { | |
462 | snprintf(tmp, sizeof(tmp), "0x%x", al->tcpClient->nfmark); | |
463 | out = tmp; | |
464 | } | |
465 | break; | |
466 | ||
28417506 | 467 | case LFT_LOCAL_LISTENING_PORT: |
fa720bfb | 468 | if (al->cache.port != NULL) { |
4dd643d5 | 469 | outint = al->cache.port->s.port(); |
28417506 | 470 | doint = 1; |
fbbea662 AJ |
471 | } else if (al->request) { |
472 | outint = al->request->my_addr.port(); | |
473 | doint = 1; | |
28417506 CT |
474 | } |
475 | break; | |
476 | ||
8652f8e7 | 477 | case LFT_CLIENT_LOCAL_PORT: |
a14f38d0 | 478 | if (al->tcpClient != NULL) { |
4dd643d5 | 479 | outint = al->tcpClient->local.port(); |
38e16f92 AJ |
480 | doint = 1; |
481 | } | |
38e16f92 AJ |
482 | break; |
483 | ||
8652f8e7 AJ |
484 | case LFT_SERVER_LOCAL_IP_OLD_27: |
485 | case LFT_SERVER_LOCAL_IP: | |
a14f38d0 | 486 | if (al->hier.tcpServer != NULL) { |
4dd643d5 | 487 | out = al->hier.tcpServer->local.toStr(tmp,sizeof(tmp)); |
38e16f92 AJ |
488 | } |
489 | break; | |
490 | ||
8652f8e7 | 491 | case LFT_SERVER_LOCAL_PORT: |
a14f38d0 | 492 | if (al->hier.tcpServer != NULL) { |
4dd643d5 | 493 | outint = al->hier.tcpServer->local.port(); |
38e16f92 AJ |
494 | doint = 1; |
495 | } | |
496 | ||
497 | break; | |
498 | ||
f123f5e9 CT |
499 | case LFT_SERVER_LOCAL_TOS: |
500 | if (al->hier.tcpServer != NULL) { | |
501 | snprintf(tmp, sizeof(tmp), "0x%x", (uint32_t)al->hier.tcpServer->tos); | |
502 | out = tmp; | |
503 | } | |
504 | break; | |
505 | ||
506 | case LFT_SERVER_LOCAL_NFMARK: | |
507 | if (al->hier.tcpServer != NULL) { | |
508 | snprintf(tmp, sizeof(tmp), "0x%x", al->hier.tcpServer->nfmark); | |
509 | out = tmp; | |
510 | } | |
511 | break; | |
512 | ||
38e16f92 AJ |
513 | case LFT_TIME_SECONDS_SINCE_EPOCH: |
514 | // some platforms store time in 32-bit, some 64-bit... | |
515 | outoff = static_cast<int64_t>(current_time.tv_sec); | |
516 | dooff = 1; | |
517 | break; | |
518 | ||
519 | case LFT_TIME_SUBSECOND: | |
520 | outint = current_time.tv_usec / fmt->divisor; | |
521 | doint = 1; | |
522 | break; | |
523 | ||
38e16f92 AJ |
524 | case LFT_TIME_LOCALTIME: |
525 | ||
526 | case LFT_TIME_GMT: { | |
527 | const char *spec; | |
528 | ||
529 | struct tm *t; | |
b22c1ad3 | 530 | spec = fmt->data.string; |
38e16f92 AJ |
531 | |
532 | if (fmt->type == LFT_TIME_LOCALTIME) { | |
533 | if (!spec) | |
534 | spec = "%d/%b/%Y:%H:%M:%S %z"; | |
535 | t = localtime(&squid_curtime); | |
536 | } else { | |
537 | if (!spec) | |
538 | spec = "%d/%b/%Y:%H:%M:%S"; | |
539 | ||
540 | t = gmtime(&squid_curtime); | |
541 | } | |
542 | ||
543 | strftime(tmp, sizeof(tmp), spec, t); | |
544 | ||
545 | out = tmp; | |
546 | } | |
547 | ||
548 | break; | |
549 | ||
01bd87d8 CT |
550 | case LFT_TIME_START: |
551 | outtv = al->cache.start_time; | |
552 | doSec = 1; | |
f53969cc | 553 | break; |
af0ded40 | 554 | |
38e16f92 | 555 | case LFT_TIME_TO_HANDLE_REQUEST: |
01bd87d8 CT |
556 | outtv = al->cache.trTime; |
557 | doMsec = 1; | |
38e16f92 AJ |
558 | break; |
559 | ||
560 | case LFT_PEER_RESPONSE_TIME: | |
01bd87d8 | 561 | if (al->hier.peer_response_time.tv_sec == -1) { |
38e16f92 AJ |
562 | out = "-"; |
563 | } else { | |
01bd87d8 CT |
564 | outtv = al->hier.peer_response_time; |
565 | doMsec = 1; | |
38e16f92 AJ |
566 | } |
567 | break; | |
568 | ||
16b70e2a | 569 | case LFT_TOTAL_SERVER_SIDE_RESPONSE_TIME: { |
01bd87d8 CT |
570 | timeval total_response_time; |
571 | al->hier.totalResponseTime(total_response_time); | |
572 | if (total_response_time.tv_sec == -1) { | |
38e16f92 AJ |
573 | out = "-"; |
574 | } else { | |
01bd87d8 CT |
575 | outtv = total_response_time; |
576 | doMsec = 1; | |
38e16f92 | 577 | } |
16b70e2a CT |
578 | } |
579 | break; | |
38e16f92 AJ |
580 | |
581 | case LFT_DNS_WAIT_TIME: | |
582 | if (al->request && al->request->dnsWait >= 0) { | |
01bd87d8 CT |
583 | // TODO: microsecond precision for dns wait time. |
584 | // Convert miliseconds to timeval struct: | |
585 | outtv.tv_sec = al->request->dnsWait / 1000; | |
586 | outtv.tv_usec = (al->request->dnsWait % 1000) * 1000; | |
587 | doMsec = 1; | |
38e16f92 AJ |
588 | } |
589 | break; | |
590 | ||
591 | case LFT_REQUEST_HEADER: | |
592 | ||
593 | if (al->request) | |
594 | sb = al->request->header.getByName(fmt->data.header.header); | |
595 | ||
596 | out = sb.termedBuf(); | |
597 | ||
598 | quote = 1; | |
599 | ||
600 | break; | |
601 | ||
602 | case LFT_ADAPTED_REQUEST_HEADER: | |
603 | ||
38d92afa | 604 | if (al->adapted_request) |
38e16f92 AJ |
605 | sb = al->adapted_request->header.getByName(fmt->data.header.header); |
606 | ||
607 | out = sb.termedBuf(); | |
608 | ||
609 | quote = 1; | |
610 | ||
611 | break; | |
612 | ||
613 | case LFT_REPLY_HEADER: | |
614 | if (al->reply) | |
615 | sb = al->reply->header.getByName(fmt->data.header.header); | |
616 | ||
617 | out = sb.termedBuf(); | |
618 | ||
619 | quote = 1; | |
620 | ||
621 | break; | |
622 | ||
623 | #if USE_ADAPTATION | |
31971e6a | 624 | case LFT_ADAPTATION_SUM_XACT_TIMES: |
38e16f92 AJ |
625 | if (al->request) { |
626 | Adaptation::History::Pointer ah = al->request->adaptHistory(); | |
627 | if (ah != NULL) | |
628 | ah->sumLogString(fmt->data.string, sb); | |
629 | out = sb.termedBuf(); | |
630 | } | |
631 | break; | |
632 | ||
31971e6a | 633 | case LFT_ADAPTATION_ALL_XACT_TIMES: |
38e16f92 AJ |
634 | if (al->request) { |
635 | Adaptation::History::Pointer ah = al->request->adaptHistory(); | |
636 | if (ah != NULL) | |
637 | ah->allLogString(fmt->data.string, sb); | |
638 | out = sb.termedBuf(); | |
639 | } | |
640 | break; | |
641 | ||
642 | case LFT_ADAPTATION_LAST_HEADER: | |
643 | if (al->request) { | |
644 | const Adaptation::History::Pointer ah = al->request->adaptHistory(); | |
645 | if (ah != NULL) // XXX: add adapt::<all_h but use lastMeta here | |
646 | sb = ah->allMeta.getByName(fmt->data.header.header); | |
647 | } | |
648 | ||
649 | // XXX: here and elsewhere: move such code inside the if guard | |
650 | out = sb.termedBuf(); | |
651 | ||
652 | quote = 1; | |
653 | ||
654 | break; | |
655 | ||
656 | case LFT_ADAPTATION_LAST_HEADER_ELEM: | |
657 | if (al->request) { | |
658 | const Adaptation::History::Pointer ah = al->request->adaptHistory(); | |
659 | if (ah != NULL) // XXX: add adapt::<all_h but use lastMeta here | |
660 | sb = ah->allMeta.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator); | |
661 | } | |
662 | ||
663 | out = sb.termedBuf(); | |
664 | ||
665 | quote = 1; | |
666 | ||
667 | break; | |
668 | ||
669 | case LFT_ADAPTATION_LAST_ALL_HEADERS: | |
670 | out = al->adapt.last_meta; | |
671 | ||
672 | quote = 1; | |
673 | ||
674 | break; | |
675 | #endif | |
676 | ||
677 | #if ICAP_CLIENT | |
678 | case LFT_ICAP_ADDR: | |
679 | if (!out) | |
4dd643d5 | 680 | out = al->icap.hostAddr.toStr(tmp,1024); |
38e16f92 AJ |
681 | break; |
682 | ||
683 | case LFT_ICAP_SERV_NAME: | |
684 | out = al->icap.serviceName.termedBuf(); | |
685 | break; | |
686 | ||
687 | case LFT_ICAP_REQUEST_URI: | |
688 | out = al->icap.reqUri.termedBuf(); | |
689 | break; | |
690 | ||
691 | case LFT_ICAP_REQUEST_METHOD: | |
692 | out = Adaptation::Icap::ICAP::methodStr(al->icap.reqMethod); | |
693 | break; | |
694 | ||
695 | case LFT_ICAP_BYTES_SENT: | |
696 | outoff = al->icap.bytesSent; | |
697 | dooff = 1; | |
698 | break; | |
699 | ||
700 | case LFT_ICAP_BYTES_READ: | |
701 | outoff = al->icap.bytesRead; | |
702 | dooff = 1; | |
703 | break; | |
704 | ||
705 | case LFT_ICAP_BODY_BYTES_READ: | |
706 | if (al->icap.bodyBytesRead >= 0) { | |
707 | outoff = al->icap.bodyBytesRead; | |
708 | dooff = 1; | |
709 | } | |
710 | // else if icap.bodyBytesRead < 0, we do not have any http data, | |
711 | // so just print a "-" (204 responses etc) | |
712 | break; | |
713 | ||
714 | case LFT_ICAP_REQ_HEADER: | |
715 | if (NULL != al->icap.request) { | |
716 | sb = al->icap.request->header.getByName(fmt->data.header.header); | |
717 | out = sb.termedBuf(); | |
718 | quote = 1; | |
719 | } | |
720 | break; | |
721 | ||
722 | case LFT_ICAP_REQ_HEADER_ELEM: | |
7f0ceafc | 723 | if (al->icap.request) |
38e16f92 AJ |
724 | sb = al->icap.request->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator); |
725 | ||
726 | out = sb.termedBuf(); | |
727 | ||
728 | quote = 1; | |
729 | ||
730 | break; | |
731 | ||
732 | case LFT_ICAP_REQ_ALL_HEADERS: | |
733 | if (al->icap.request) { | |
734 | HttpHeaderPos pos = HttpHeaderInitPos; | |
735 | while (const HttpHeaderEntry *e = al->icap.request->header.getEntry(&pos)) { | |
736 | sb.append(e->name); | |
737 | sb.append(": "); | |
738 | sb.append(e->value); | |
739 | sb.append("\r\n"); | |
740 | } | |
741 | out = sb.termedBuf(); | |
742 | quote = 1; | |
743 | } | |
744 | break; | |
745 | ||
746 | case LFT_ICAP_REP_HEADER: | |
747 | if (NULL != al->icap.reply) { | |
748 | sb = al->icap.reply->header.getByName(fmt->data.header.header); | |
749 | out = sb.termedBuf(); | |
750 | quote = 1; | |
751 | } | |
752 | break; | |
753 | ||
754 | case LFT_ICAP_REP_HEADER_ELEM: | |
755 | if (NULL != al->icap.reply) | |
756 | sb = al->icap.reply->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator); | |
757 | ||
758 | out = sb.termedBuf(); | |
759 | ||
760 | quote = 1; | |
761 | ||
762 | break; | |
763 | ||
764 | case LFT_ICAP_REP_ALL_HEADERS: | |
765 | if (al->icap.reply) { | |
766 | HttpHeaderPos pos = HttpHeaderInitPos; | |
767 | while (const HttpHeaderEntry *e = al->icap.reply->header.getEntry(&pos)) { | |
768 | sb.append(e->name); | |
769 | sb.append(": "); | |
770 | sb.append(e->value); | |
771 | sb.append("\r\n"); | |
772 | } | |
773 | out = sb.termedBuf(); | |
774 | quote = 1; | |
775 | } | |
776 | break; | |
777 | ||
778 | case LFT_ICAP_TR_RESPONSE_TIME: | |
01bd87d8 CT |
779 | outtv = al->icap.trTime; |
780 | doMsec = 1; | |
38e16f92 AJ |
781 | break; |
782 | ||
783 | case LFT_ICAP_IO_TIME: | |
01bd87d8 CT |
784 | outtv = al->icap.ioTime; |
785 | doMsec = 1; | |
38e16f92 AJ |
786 | break; |
787 | ||
788 | case LFT_ICAP_STATUS_CODE: | |
789 | outint = al->icap.resStatus; | |
790 | doint = 1; | |
791 | break; | |
792 | ||
793 | case LFT_ICAP_OUTCOME: | |
794 | out = al->icap.outcome; | |
795 | break; | |
796 | ||
797 | case LFT_ICAP_TOTAL_TIME: | |
01bd87d8 CT |
798 | outtv = al->icap.processingTime; |
799 | doMsec = 1; | |
38e16f92 AJ |
800 | break; |
801 | #endif | |
802 | case LFT_REQUEST_HEADER_ELEM: | |
803 | if (al->request) | |
804 | sb = al->request->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator); | |
805 | ||
806 | out = sb.termedBuf(); | |
807 | ||
808 | quote = 1; | |
809 | ||
810 | break; | |
811 | ||
812 | case LFT_ADAPTED_REQUEST_HEADER_ELEM: | |
813 | if (al->adapted_request) | |
814 | sb = al->adapted_request->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator); | |
815 | ||
816 | out = sb.termedBuf(); | |
817 | ||
818 | quote = 1; | |
819 | ||
820 | break; | |
821 | ||
822 | case LFT_REPLY_HEADER_ELEM: | |
823 | if (al->reply) | |
824 | sb = al->reply->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator); | |
825 | ||
826 | out = sb.termedBuf(); | |
827 | ||
828 | quote = 1; | |
829 | ||
830 | break; | |
831 | ||
832 | case LFT_REQUEST_ALL_HEADERS: | |
833 | out = al->headers.request; | |
834 | ||
835 | quote = 1; | |
836 | ||
837 | break; | |
838 | ||
839 | case LFT_ADAPTED_REQUEST_ALL_HEADERS: | |
840 | out = al->headers.adapted_request; | |
841 | ||
842 | quote = 1; | |
843 | ||
844 | break; | |
845 | ||
846 | case LFT_REPLY_ALL_HEADERS: | |
847 | out = al->headers.reply; | |
848 | ||
849 | quote = 1; | |
850 | ||
851 | break; | |
852 | ||
853 | case LFT_USER_NAME: | |
c0e8c76f AJ |
854 | #if USE_AUTH |
855 | if (al->request && al->request->auth_user_request != NULL) | |
856 | out = strOrNull(al->request->auth_user_request->username()); | |
857 | #endif | |
38e16f92 | 858 | if (!out) |
bd85ea1f | 859 | out = strOrNull(al->cache.extuser); |
cb4f4424 | 860 | #if USE_OPENSSL |
38e16f92 | 861 | if (!out) |
bd85ea1f | 862 | out = strOrNull(al->cache.ssluser); |
38e16f92 | 863 | #endif |
38e16f92 | 864 | if (!out) |
bd85ea1f | 865 | out = strOrNull(al->cache.rfc931); |
38e16f92 AJ |
866 | break; |
867 | ||
868 | case LFT_USER_LOGIN: | |
c0e8c76f AJ |
869 | #if USE_AUTH |
870 | if (al->request && al->request->auth_user_request != NULL) | |
871 | out = strOrNull(al->request->auth_user_request->username()); | |
872 | #endif | |
38e16f92 AJ |
873 | break; |
874 | ||
875 | case LFT_USER_IDENT: | |
bd85ea1f | 876 | out = strOrNull(al->cache.rfc931); |
38e16f92 AJ |
877 | break; |
878 | ||
879 | case LFT_USER_EXTERNAL: | |
4e56d7f6 AJ |
880 | if (al->request && al->request->extacl_user.size()) |
881 | out = al->request->extacl_user.termedBuf(); | |
882 | ||
883 | if (!out) | |
884 | out = strOrNull(al->cache.extuser); | |
38e16f92 AJ |
885 | break; |
886 | ||
f53969cc SM |
887 | /* case LFT_USER_REALM: */ |
888 | /* case LFT_USER_SCHEME: */ | |
38e16f92 | 889 | |
f53969cc SM |
890 | // the fmt->type can not be LFT_HTTP_SENT_STATUS_CODE_OLD_30 |
891 | // but compiler complains if ommited | |
38e16f92 AJ |
892 | case LFT_HTTP_SENT_STATUS_CODE_OLD_30: |
893 | case LFT_HTTP_SENT_STATUS_CODE: | |
894 | outint = al->http.code; | |
895 | ||
896 | doint = 1; | |
897 | ||
898 | break; | |
899 | ||
900 | case LFT_HTTP_RECEIVED_STATUS_CODE: | |
955394ce | 901 | if (al->hier.peer_reply_status == Http::scNone) { |
38e16f92 AJ |
902 | out = "-"; |
903 | } else { | |
904 | outint = al->hier.peer_reply_status; | |
905 | doint = 1; | |
906 | } | |
907 | break; | |
f53969cc SM |
908 | /* case LFT_HTTP_STATUS: |
909 | * out = statusline->text; | |
910 | * quote = 1; | |
911 | * break; | |
912 | */ | |
38e16f92 AJ |
913 | case LFT_HTTP_BODY_BYTES_READ: |
914 | if (al->hier.bodyBytesRead >= 0) { | |
915 | outoff = al->hier.bodyBytesRead; | |
916 | dooff = 1; | |
917 | } | |
918 | // else if hier.bodyBytesRead < 0 we did not have any data exchange with | |
919 | // a peer server so just print a "-" (eg requests served from cache, | |
920 | // or internal error messages). | |
921 | break; | |
922 | ||
923 | case LFT_SQUID_STATUS: | |
a981b360 | 924 | out = al->cache.code.c_str(); |
38e16f92 AJ |
925 | break; |
926 | ||
927 | case LFT_SQUID_ERROR: | |
928 | if (al->request && al->request->errType != ERR_NONE) | |
929 | out = errorPageName(al->request->errType); | |
930 | break; | |
931 | ||
932 | case LFT_SQUID_ERROR_DETAIL: | |
cb4f4424 | 933 | #if USE_OPENSSL |
2f3e52b5 | 934 | if (al->request && al->request->errType == ERR_SECURE_CONNECT_FAIL) { |
7598eb63 CT |
935 | if (! (out = Ssl::GetErrorName(al->request->errDetail))) |
936 | out = sslErrorName(al->request->errDetail, tmp, sizeof(tmp)); | |
e83cdc25 | 937 | } else |
2f3e52b5 | 938 | #endif |
e83cdc25 | 939 | if (al->request && al->request->errDetail != ERR_DETAIL_NONE) { |
4e56d7f6 | 940 | if (al->request->errDetail > ERR_DETAIL_START && al->request->errDetail < ERR_DETAIL_MAX) |
e83cdc25 A |
941 | out = errorDetailName(al->request->errDetail); |
942 | else { | |
943 | if (al->request->errDetail >= ERR_DETAIL_EXCEPTION_START) | |
944 | snprintf(tmp, sizeof(tmp), "%s=0x%X", | |
945 | errorDetailName(al->request->errDetail), (uint32_t) al->request->errDetail); | |
946 | else | |
947 | snprintf(tmp, sizeof(tmp), "%s=%d", | |
948 | errorDetailName(al->request->errDetail), al->request->errDetail); | |
949 | out = tmp; | |
950 | } | |
38e16f92 | 951 | } |
38e16f92 AJ |
952 | break; |
953 | ||
954 | case LFT_SQUID_HIERARCHY: | |
955 | if (al->hier.ping.timedout) | |
956 | mb.append("TIMEOUT_", 8); | |
957 | ||
958 | out = hier_code_str[al->hier.code]; | |
959 | ||
960 | break; | |
961 | ||
962 | case LFT_MIME_TYPE: | |
963 | out = al->http.content_type; | |
964 | ||
965 | break; | |
966 | ||
967 | case LFT_CLIENT_REQ_METHOD: | |
968 | if (al->request) { | |
7f06a3d8 AJ |
969 | const SBuf &s = al->request->method.image(); |
970 | sb.append(s.rawContent(), s.length()); | |
971 | out = sb.termedBuf(); | |
38e16f92 AJ |
972 | quote = 1; |
973 | } | |
974 | break; | |
975 | ||
976 | case LFT_CLIENT_REQ_URI: | |
977 | // original client URI | |
978 | if (al->request) { | |
851feda6 AJ |
979 | const SBuf &s = al->request->effectiveRequestUri(); |
980 | sb.append(s.rawContent(), s.length()); | |
981 | out = sb.termedBuf(); | |
38e16f92 AJ |
982 | quote = 1; |
983 | } | |
984 | break; | |
985 | ||
5aca9cf2 AJ |
986 | case LFT_CLIENT_REQ_URLSCHEME: |
987 | if (al->request) { | |
988 | out = al->request->url.getScheme().c_str(); | |
989 | quote = 1; | |
990 | } | |
991 | break; | |
992 | ||
fa450988 AJ |
993 | case LFT_CLIENT_REQ_URLDOMAIN: |
994 | if (al->request) { | |
5c51bffb | 995 | out = al->request->url.host(); |
fa450988 AJ |
996 | quote = 1; |
997 | } | |
998 | break; | |
999 | ||
5aca9cf2 AJ |
1000 | case LFT_CLIENT_REQ_URLPORT: |
1001 | if (al->request) { | |
5c51bffb | 1002 | outint = al->request->url.port(); |
5aca9cf2 AJ |
1003 | doint = 1; |
1004 | } | |
1005 | break; | |
1006 | ||
38e16f92 AJ |
1007 | case LFT_REQUEST_URLPATH_OLD_31: |
1008 | case LFT_CLIENT_REQ_URLPATH: | |
1009 | if (al->request) { | |
51b5dcf5 AJ |
1010 | SBuf s = al->request->url.path(); |
1011 | out = s.c_str(); | |
38e16f92 AJ |
1012 | quote = 1; |
1013 | } | |
1014 | break; | |
1015 | ||
1016 | case LFT_CLIENT_REQ_VERSION: | |
1017 | if (al->request) { | |
1018 | snprintf(tmp, sizeof(tmp), "%d.%d", (int) al->request->http_ver.major, (int) al->request->http_ver.minor); | |
1019 | out = tmp; | |
1020 | } | |
1021 | break; | |
1022 | ||
1023 | case LFT_REQUEST_METHOD: | |
3736fdd6 SM |
1024 | { |
1025 | const SBuf s(al->getLogMethod()); | |
1026 | sb.append(s.rawContent(), s.length()); | |
1027 | out = sb.termedBuf(); | |
1028 | quote = 1; | |
1029 | } | |
1030 | break; | |
38e16f92 AJ |
1031 | |
1032 | case LFT_REQUEST_URI: | |
1033 | out = al->url; | |
1034 | break; | |
1035 | ||
1036 | case LFT_REQUEST_VERSION_OLD_2X: | |
1037 | case LFT_REQUEST_VERSION: | |
1038 | snprintf(tmp, sizeof(tmp), "%d.%d", (int) al->http.version.major, (int) al->http.version.minor); | |
1039 | out = tmp; | |
1040 | break; | |
1041 | ||
1042 | case LFT_SERVER_REQ_METHOD: | |
1043 | if (al->adapted_request) { | |
7f06a3d8 AJ |
1044 | const SBuf &s = al->adapted_request->method.image(); |
1045 | sb.append(s.rawContent(), s.length()); | |
1046 | out = sb.termedBuf(); | |
38e16f92 AJ |
1047 | quote = 1; |
1048 | } | |
1049 | break; | |
1050 | ||
1051 | case LFT_SERVER_REQ_URI: | |
1052 | // adapted request URI sent to server/peer | |
1053 | if (al->adapted_request) { | |
851feda6 AJ |
1054 | const SBuf &s = al->adapted_request->effectiveRequestUri(); |
1055 | sb.append(s.rawContent(), s.length()); | |
1056 | out = sb.termedBuf(); | |
38e16f92 AJ |
1057 | quote = 1; |
1058 | } | |
1059 | break; | |
1060 | ||
5aca9cf2 AJ |
1061 | case LFT_SERVER_REQ_URLSCHEME: |
1062 | if (al->adapted_request) { | |
1063 | out = al->adapted_request->url.getScheme().c_str(); | |
1064 | quote = 1; | |
1065 | } | |
1066 | break; | |
1067 | ||
1068 | case LFT_SERVER_REQ_URLDOMAIN: | |
1069 | if (al->adapted_request) { | |
5c51bffb | 1070 | out = al->adapted_request->url.host(); |
5aca9cf2 AJ |
1071 | quote = 1; |
1072 | } | |
1073 | break; | |
1074 | ||
1075 | case LFT_SERVER_REQ_URLPORT: | |
1076 | if (al->adapted_request) { | |
5c51bffb | 1077 | outint = al->adapted_request->url.port(); |
5aca9cf2 AJ |
1078 | doint = 1; |
1079 | } | |
1080 | break; | |
1081 | ||
38e16f92 AJ |
1082 | case LFT_SERVER_REQ_URLPATH: |
1083 | if (al->adapted_request) { | |
51b5dcf5 AJ |
1084 | SBuf s = al->adapted_request->url.path(); |
1085 | out = s.c_str(); | |
38e16f92 AJ |
1086 | quote = 1; |
1087 | } | |
1088 | break; | |
1089 | ||
1090 | case LFT_SERVER_REQ_VERSION: | |
1091 | if (al->adapted_request) { | |
1092 | snprintf(tmp, sizeof(tmp), "%d.%d", | |
1093 | (int) al->adapted_request->http_ver.major, | |
1094 | (int) al->adapted_request->http_ver.minor); | |
1095 | out = tmp; | |
1096 | } | |
1097 | break; | |
1098 | ||
d6df21d2 | 1099 | case LFT_CLIENT_REQUEST_SIZE_TOTAL: |
cc0ca3b9 | 1100 | outoff = al->http.clientRequestSz.messageTotal(); |
38e16f92 AJ |
1101 | dooff = 1; |
1102 | break; | |
1103 | ||
d6df21d2 | 1104 | case LFT_CLIENT_REQUEST_SIZE_HEADERS: |
cc0ca3b9 | 1105 | outoff = al->http.clientRequestSz.header; |
38e16f92 AJ |
1106 | dooff =1; |
1107 | break; | |
d6df21d2 | 1108 | |
f53969cc SM |
1109 | /*case LFT_REQUEST_SIZE_BODY: */ |
1110 | /*case LFT_REQUEST_SIZE_BODY_NO_TE: */ | |
38e16f92 | 1111 | |
d6df21d2 | 1112 | case LFT_ADAPTED_REPLY_SIZE_TOTAL: |
cc0ca3b9 | 1113 | outoff = al->http.clientReplySz.messageTotal(); |
38e16f92 AJ |
1114 | dooff = 1; |
1115 | break; | |
1116 | ||
1117 | case LFT_REPLY_HIGHOFFSET: | |
1118 | outoff = al->cache.highOffset; | |
1119 | ||
1120 | dooff = 1; | |
1121 | ||
1122 | break; | |
1123 | ||
1124 | case LFT_REPLY_OBJECTSIZE: | |
1125 | outoff = al->cache.objectSize; | |
1126 | ||
1127 | dooff = 1; | |
1128 | ||
1129 | break; | |
1130 | ||
d6df21d2 | 1131 | case LFT_ADAPTED_REPLY_SIZE_HEADERS: |
cc0ca3b9 | 1132 | outint = al->http.clientReplySz.header; |
38e16f92 AJ |
1133 | doint = 1; |
1134 | break; | |
d6df21d2 | 1135 | |
f53969cc SM |
1136 | /*case LFT_REPLY_SIZE_BODY: */ |
1137 | /*case LFT_REPLY_SIZE_BODY_NO_TE: */ | |
38e16f92 | 1138 | |
d6df21d2 | 1139 | case LFT_CLIENT_IO_SIZE_TOTAL: |
cc0ca3b9 | 1140 | outint = al->http.clientRequestSz.messageTotal() + al->http.clientReplySz.messageTotal(); |
d6df21d2 AJ |
1141 | doint = 1; |
1142 | break; | |
f53969cc | 1143 | /*case LFT_SERVER_IO_SIZE_TOTAL: */ |
d6df21d2 | 1144 | |
38e16f92 AJ |
1145 | case LFT_TAG: |
1146 | if (al->request) | |
1147 | out = al->request->tag.termedBuf(); | |
1148 | ||
1149 | quote = 1; | |
1150 | ||
1151 | break; | |
1152 | ||
38e16f92 AJ |
1153 | case LFT_EXT_LOG: |
1154 | if (al->request) | |
1155 | out = al->request->extacl_log.termedBuf(); | |
1156 | ||
1157 | quote = 1; | |
1158 | ||
1159 | break; | |
1160 | ||
1161 | case LFT_SEQUENCE_NUMBER: | |
1162 | outoff = logSequenceNumber; | |
1163 | dooff = 1; | |
1164 | break; | |
1165 | ||
cb4f4424 | 1166 | #if USE_OPENSSL |
08097970 AR |
1167 | case LFT_SSL_BUMP_MODE: { |
1168 | const Ssl::BumpMode mode = static_cast<Ssl::BumpMode>(al->ssl.bumpMode); | |
1169 | // for Ssl::bumpEnd, Ssl::bumpMode() returns NULL and we log '-' | |
1170 | out = Ssl::bumpMode(mode); | |
08097970 | 1171 | } |
3736fdd6 | 1172 | break; |
4e56d7f6 AJ |
1173 | |
1174 | case LFT_EXT_ACL_USER_CERT_RAW: | |
1175 | if (al->request) { | |
1176 | ConnStateData *conn = al->request->clientConnectionManager.get(); | |
1177 | if (conn != NULL && Comm::IsConnOpen(conn->clientConnection)) { | |
1178 | if (SSL *ssl = fd_table[conn->clientConnection->fd].ssl) | |
1179 | out = sslGetUserCertificatePEM(ssl); | |
1180 | } | |
1181 | } | |
1182 | break; | |
1183 | ||
1184 | case LFT_EXT_ACL_USER_CERTCHAIN_RAW: | |
1185 | if (al->request) { | |
1186 | ConnStateData *conn = al->request->clientConnectionManager.get(); | |
1187 | if (conn != NULL && Comm::IsConnOpen(conn->clientConnection)) { | |
1188 | if (SSL *ssl = fd_table[conn->clientConnection->fd].ssl) | |
1189 | out = sslGetUserCertificatePEM(ssl); | |
1190 | } | |
1191 | } | |
1192 | break; | |
1193 | ||
1194 | case LFT_EXT_ACL_USER_CERT: | |
1195 | if (al->request) { | |
1196 | ConnStateData *conn = al->request->clientConnectionManager.get(); | |
1197 | if (conn != NULL && Comm::IsConnOpen(conn->clientConnection)) { | |
1198 | if (SSL *ssl = fd_table[conn->clientConnection->fd].ssl) | |
1199 | out = sslGetUserAttribute(ssl, format->data.header.header); | |
1200 | } | |
1201 | } | |
1202 | break; | |
1203 | ||
1204 | case LFT_EXT_ACL_USER_CA_CERT: | |
1205 | if (al->request) { | |
1206 | ConnStateData *conn = al->request->clientConnectionManager.get(); | |
1207 | if (conn != NULL && Comm::IsConnOpen(conn->clientConnection)) { | |
1208 | if (SSL *ssl = fd_table[conn->clientConnection->fd].ssl) | |
3736fdd6 | 1209 | out = sslGetCAAttribute(ssl, format->data.header.header); |
4e56d7f6 AJ |
1210 | } |
1211 | } | |
1212 | break; | |
71cae389 | 1213 | |
f4698e0b CT |
1214 | case LFT_SSL_USER_CERT_SUBJECT: |
1215 | if (X509 *cert = al->cache.sslClientCert.get()) { | |
1216 | if (X509_NAME *subject = X509_get_subject_name(cert)) { | |
1217 | X509_NAME_oneline(subject, tmp, sizeof(tmp)); | |
1218 | out = tmp; | |
1219 | } | |
1220 | } | |
1221 | break; | |
1222 | ||
1223 | case LFT_SSL_USER_CERT_ISSUER: | |
1224 | if (X509 *cert = al->cache.sslClientCert.get()) { | |
1225 | if (X509_NAME *issuer = X509_get_issuer_name(cert)) { | |
1226 | X509_NAME_oneline(issuer, tmp, sizeof(tmp)); | |
1227 | out = tmp; | |
1228 | } | |
1229 | } | |
1230 | break; | |
4e56d7f6 | 1231 | |
cedca6e7 CT |
1232 | case LFT_SSL_CLIENT_SNI: |
1233 | if (al->request && al->request->clientConnectionManager.valid()) { | |
1234 | if (Ssl::ServerBump * srvBump = al->request->clientConnectionManager->serverBump()) { | |
1235 | if (!srvBump->clientSni.isEmpty()) | |
1236 | out = srvBump->clientSni.c_str(); | |
1237 | } | |
1238 | } | |
1239 | break; | |
789dda8d | 1240 | |
7598eb63 CT |
1241 | case LFT_SSL_SERVER_CERT_ERRORS: |
1242 | if (al->request && al->request->clientConnectionManager.valid()) { | |
1243 | if (Ssl::ServerBump * srvBump = al->request->clientConnectionManager->serverBump()) { | |
1244 | const char *separator = fmt->data.string ? fmt->data.string : ":"; | |
1245 | for (Ssl::CertErrors *sslError = srvBump->sslErrors; sslError != NULL; sslError = sslError->next) { | |
1246 | if (sb.size()) | |
1247 | sb.append(separator); | |
1248 | if (const char *errorName = Ssl::GetErrorName(sslError->element.code)) | |
1249 | sb.append(errorName); | |
1250 | else | |
1251 | sb.append(sslErrorName(sslError->element.code, tmp, sizeof(tmp))); | |
b4e6a8d4 CT |
1252 | if (sslError->element.depth >= 0) { |
1253 | snprintf(tmp, sizeof(tmp), "@depth=%d", sslError->element.depth); | |
1254 | sb.append(tmp); | |
1255 | } | |
7598eb63 CT |
1256 | } |
1257 | if (sb.size()) | |
1258 | out = sb.termedBuf(); | |
1259 | } | |
1260 | } | |
cedca6e7 | 1261 | break; |
789dda8d CT |
1262 | |
1263 | case LFT_SSL_SERVER_CERT_ISSUER: | |
1264 | case LFT_SSL_SERVER_CERT_SUBJECT: | |
1265 | // Not implemented | |
1266 | break; | |
2bcab852 CT |
1267 | |
1268 | case LFT_TLS_CLIENT_NEGOTIATED_VERSION: | |
1269 | if (al->tcpClient != nullptr && al->tcpClient->hasTlsNegotiations()) | |
1270 | out = al->tcpClient->hasTlsNegotiations()->negotiatedVersion(); | |
1271 | break; | |
1272 | ||
1273 | case LFT_TLS_SERVER_NEGOTIATED_VERSION: | |
1274 | if (al->hier.tcpServer != nullptr && al->hier.tcpServer->hasTlsNegotiations()) | |
1275 | out = al->hier.tcpServer->hasTlsNegotiations()->negotiatedVersion(); | |
1276 | break; | |
1277 | ||
1278 | case LFT_TLS_CLIENT_RECEIVED_HELLO_VERSION: | |
1279 | if (al->tcpClient != nullptr && al->tcpClient->hasTlsNegotiations()) | |
1280 | out = al->tcpClient->hasTlsNegotiations()->helloVersion(); | |
1281 | break; | |
1282 | ||
1283 | case LFT_TLS_SERVER_RECEIVED_HELLO_VERSION: | |
1284 | if (al->hier.tcpServer != nullptr && al->hier.tcpServer->hasTlsNegotiations()) | |
1285 | out = al->hier.tcpServer->hasTlsNegotiations()->helloVersion(); | |
1286 | break; | |
1287 | ||
1288 | case LFT_TLS_CLIENT_SUPPORTED_VERSION: | |
1289 | if (al->tcpClient != nullptr && al->tcpClient->hasTlsNegotiations()) | |
1290 | out = al->tcpClient->hasTlsNegotiations()->supportedVersion(); | |
1291 | break; | |
1292 | ||
1293 | case LFT_TLS_SERVER_SUPPORTED_VERSION: | |
1294 | if (al->hier.tcpServer != nullptr && al->hier.tcpServer->hasTlsNegotiations()) | |
1295 | out = al->hier.tcpServer->hasTlsNegotiations()->supportedVersion(); | |
1296 | break; | |
1297 | ||
1298 | case LFT_TLS_CLIENT_NEGOTIATED_CIPHER: | |
1299 | if (al->tcpClient != nullptr && al->tcpClient->hasTlsNegotiations()) | |
1300 | out = al->tcpClient->hasTlsNegotiations()->cipherName(); | |
1301 | break; | |
1302 | ||
1303 | case LFT_TLS_SERVER_NEGOTIATED_CIPHER: | |
1304 | if (al->hier.tcpServer != nullptr && al->hier.tcpServer->hasTlsNegotiations()) | |
1305 | out = al->hier.tcpServer->hasTlsNegotiations()->cipherName(); | |
1306 | break; | |
08097970 | 1307 | #endif |
f123f5e9 | 1308 | |
d074f918 TT |
1309 | case LFT_REQUEST_URLGROUP_OLD_2X: |
1310 | assert(LFT_REQUEST_URLGROUP_OLD_2X == 0); // should never happen. | |
1311 | ||
d7f4a0b7 | 1312 | case LFT_NOTE: |
c7bcf010 CT |
1313 | tmp[0] = fmt->data.header.separator; |
1314 | tmp[1] = '\0'; | |
1315 | if (fmt->data.header.header && *fmt->data.header.header) { | |
1316 | const char *separator = tmp; | |
cf9f0261 | 1317 | #if USE_ADAPTATION |
7f0ceafc | 1318 | Adaptation::History::Pointer ah = al->request ? al->request->adaptHistory() : Adaptation::History::Pointer(); |
cf9f0261 | 1319 | if (ah != NULL && ah->metaHeaders != NULL) { |
c7bcf010 | 1320 | if (const char *meta = ah->metaHeaders->find(fmt->data.header.header, separator)) |
cf9f0261 CT |
1321 | sb.append(meta); |
1322 | } | |
1323 | #endif | |
f4f55a21 | 1324 | if (al->notes != NULL) { |
c7bcf010 | 1325 | if (const char *note = al->notes->find(fmt->data.header.header, separator)) { |
cf9f0261 | 1326 | if (sb.size()) |
c7bcf010 | 1327 | sb.append(separator); |
cf9f0261 CT |
1328 | sb.append(note); |
1329 | } | |
1330 | } | |
d7f4a0b7 CT |
1331 | out = sb.termedBuf(); |
1332 | quote = 1; | |
1333 | } else { | |
c7bcf010 CT |
1334 | // if no argument given use default "\r\n" as notes separator |
1335 | const char *separator = fmt->data.string ? tmp : "\r\n"; | |
cf9f0261 | 1336 | #if USE_ADAPTATION |
7f0ceafc | 1337 | Adaptation::History::Pointer ah = al->request ? al->request->adaptHistory() : Adaptation::History::Pointer(); |
cf9f0261 | 1338 | if (ah != NULL && ah->metaHeaders != NULL && !ah->metaHeaders->empty()) |
c7bcf010 | 1339 | sb.append(ah->metaHeaders->toString(separator)); |
cf9f0261 | 1340 | #endif |
f4f55a21 | 1341 | if (al->notes != NULL && !al->notes->empty()) |
c7bcf010 | 1342 | sb.append(al->notes->toString(separator)); |
f4f55a21 | 1343 | |
d7f4a0b7 CT |
1344 | out = sb.termedBuf(); |
1345 | quote = 1; | |
1346 | } | |
1347 | break; | |
08097970 | 1348 | |
d4806c91 CT |
1349 | case LFT_CREDENTIALS: |
1350 | #if USE_AUTH | |
1351 | if (al->request && al->request->auth_user_request != NULL) | |
1352 | out = strOrNull(al->request->auth_user_request->credentialsStr()); | |
1353 | #endif | |
1354 | ||
1355 | break; | |
1356 | ||
38e16f92 AJ |
1357 | case LFT_PERCENT: |
1358 | out = "%"; | |
5aca9cf2 | 1359 | break; |
38e16f92 | 1360 | |
5aca9cf2 | 1361 | case LFT_EXT_ACL_NAME: |
4ff6370b | 1362 | out = al->lastAclName; |
4e56d7f6 AJ |
1363 | break; |
1364 | ||
5aca9cf2 | 1365 | case LFT_EXT_ACL_DATA: |
4ff6370b | 1366 | out = al->lastAclData; |
38e16f92 AJ |
1367 | break; |
1368 | } | |
1369 | ||
1370 | if (dooff) { | |
8846a2b4 | 1371 | snprintf(tmp, sizeof(tmp), "%0*" PRId64, fmt->zero && fmt->widthMin >= 0 ? fmt->widthMin : 0, outoff); |
38e16f92 AJ |
1372 | out = tmp; |
1373 | ||
1374 | } else if (doint) { | |
8846a2b4 | 1375 | snprintf(tmp, sizeof(tmp), "%0*ld", fmt->zero && fmt->widthMin >= 0 ? fmt->widthMin : 0, outint); |
38e16f92 | 1376 | out = tmp; |
01bd87d8 CT |
1377 | } else if (doMsec) { |
1378 | if (fmt->widthMax < 0) { | |
1379 | snprintf(tmp, sizeof(tmp), "%0*ld", fmt->widthMin , tvToMsec(outtv)); | |
1380 | } else { | |
1381 | int precision = fmt->widthMax; | |
1382 | snprintf(tmp, sizeof(tmp), "%0*" PRId64 ".%0*" PRId64 "", fmt->zero && (fmt->widthMin - precision - 1 >= 0) ? fmt->widthMin - precision - 1 : 0, static_cast<int64_t>(outtv.tv_sec * 1000 + outtv.tv_usec / 1000), precision, static_cast<int64_t>((outtv.tv_usec % 1000 )* (1000 / fmt->divisor))); | |
1383 | } | |
1384 | out = tmp; | |
1385 | } else if (doSec) { | |
1386 | int precision = fmt->widthMax >=0 ? fmt->widthMax :3; | |
1387 | snprintf(tmp, sizeof(tmp), "%0*" PRId64 ".%0*d", fmt->zero && (fmt->widthMin - precision - 1 >= 0) ? fmt->widthMin - precision - 1 : 0, static_cast<int64_t>(outtv.tv_sec), precision, (int)(outtv.tv_usec / fmt->divisor)); | |
1388 | out = tmp; | |
38e16f92 AJ |
1389 | } |
1390 | ||
1391 | if (out && *out) { | |
1392 | if (quote || fmt->quote != LOG_QUOTE_NONE) { | |
1393 | char *newout = NULL; | |
1394 | int newfree = 0; | |
1395 | ||
1396 | switch (fmt->quote) { | |
1397 | ||
1398 | case LOG_QUOTE_NONE: | |
1399 | newout = rfc1738_escape_unescaped(out); | |
1400 | break; | |
1401 | ||
1402 | case LOG_QUOTE_QUOTES: { | |
1403 | size_t out_len = static_cast<size_t>(strlen(out)) * 2 + 1; | |
1404 | if (out_len >= sizeof(tmp)) { | |
1405 | newout = (char *)xmalloc(out_len); | |
1406 | newfree = 1; | |
1407 | } else | |
1408 | newout = tmp; | |
1409 | log_quoted_string(out, newout); | |
1410 | } | |
1411 | break; | |
1412 | ||
1413 | case LOG_QUOTE_MIMEBLOB: | |
1414 | newout = QuoteMimeBlob(out); | |
1415 | newfree = 1; | |
1416 | break; | |
1417 | ||
1418 | case LOG_QUOTE_URL: | |
1419 | newout = rfc1738_escape(out); | |
1420 | break; | |
1421 | ||
95d78f10 AJ |
1422 | case LOG_QUOTE_SHELL: { |
1423 | MemBuf mbq; | |
1424 | mbq.init(); | |
1425 | strwordquote(&mbq, out); | |
1426 | newout = mbq.content(); | |
1427 | mbq.stolen = 1; | |
1428 | newfree = 1; | |
3736fdd6 SM |
1429 | } |
1430 | break; | |
95d78f10 | 1431 | |
38e16f92 AJ |
1432 | case LOG_QUOTE_RAW: |
1433 | break; | |
1434 | } | |
1435 | ||
1436 | if (newout) { | |
1437 | if (dofree) | |
1438 | safe_free(out); | |
1439 | ||
1440 | out = newout; | |
1441 | ||
1442 | dofree = newfree; | |
1443 | } | |
1444 | } | |
1445 | ||
c32c6db7 | 1446 | // enforce width limits if configured |
01bd87d8 | 1447 | const bool haveMaxWidth = fmt->widthMax >=0 && !doint && !dooff && !doMsec && !doSec; |
8846a2b4 CT |
1448 | if (haveMaxWidth || fmt->widthMin) { |
1449 | const int minWidth = fmt->widthMin >= 0 ? | |
b8ad91f5 | 1450 | fmt->widthMin :0; |
c32c6db7 | 1451 | const int maxWidth = haveMaxWidth ? |
8846a2b4 | 1452 | fmt->widthMax : strlen(out); |
c32c6db7 | 1453 | |
38e16f92 | 1454 | if (fmt->left) |
4391cd15 | 1455 | mb.appendf("%-*.*s", minWidth, maxWidth, out); |
38e16f92 | 1456 | else |
4391cd15 | 1457 | mb.appendf("%*.*s", minWidth, maxWidth, out); |
38e16f92 AJ |
1458 | } else |
1459 | mb.append(out, strlen(out)); | |
1460 | } else { | |
1461 | mb.append("-", 1); | |
1462 | } | |
1463 | ||
1464 | if (fmt->space) | |
1465 | mb.append(" ", 1); | |
1466 | ||
1467 | sb.clean(); | |
1468 | ||
1469 | if (dofree) | |
1470 | safe_free(out); | |
1471 | } | |
1472 | } | |
f53969cc | 1473 |