blob: 6b65fe9389ef7b5009466d4a5439b71cb2732f63 [file] [log] [blame]
Christopher Faulete6c3b692015-09-02 17:15:16 +02001/*
2 * Stream filters related variables and functions.
3 *
4 * Copyright (C) 2015 Qualys Inc., Christopher Faulet <cfaulet@qualys.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Christopher Fauletfcd99f82016-10-31 11:27:21 +010013#include <ctype.h>
14
Christopher Faulete6c3b692015-09-02 17:15:16 +020015#include <common/standard.h>
16#include <common/time.h>
17#include <common/tools.h>
Christopher Fauletf2273722017-07-27 16:58:42 +020018#include <common/hathreads.h>
Christopher Faulete6c3b692015-09-02 17:15:16 +020019
20#include <types/channel.h>
21#include <types/filters.h>
22#include <types/global.h>
23#include <types/proxy.h>
24#include <types/stream.h>
25
26#include <proto/filters.h>
Christopher Faulet1339d742016-05-11 16:48:33 +020027#include <proto/hdr_idx.h>
Christopher Faulete6c3b692015-09-02 17:15:16 +020028#include <proto/log.h>
29#include <proto/stream.h>
30
31struct flt_ops trace_ops;
32
33struct trace_config {
34 struct proxy *proxy;
35 char *name;
36 int rand_parsing;
37 int rand_forwarding;
Christopher Fauletfcd99f82016-10-31 11:27:21 +010038 int hexdump;
Christopher Faulete6c3b692015-09-02 17:15:16 +020039};
40
41#define TRACE(conf, fmt, ...) \
42 fprintf(stderr, "%d.%06d [%-20s] " fmt "\n", \
43 (int)now.tv_sec, (int)now.tv_usec, (conf)->name, \
44 ##__VA_ARGS__)
45
Christopher Fauletfcd99f82016-10-31 11:27:21 +010046#define STRM_TRACE(conf, strm, fmt, ...) \
47 fprintf(stderr, "%d.%06d [%-20s] [strm %p(%x) 0x%08x 0x%08x] " fmt "\n", \
48 (int)now.tv_sec, (int)now.tv_usec, (conf)->name, \
49 strm, (strm ? ((struct stream *)strm)->uniq_id : ~0U), \
50 (strm ? strm->req.analysers : 0), (strm ? strm->res.analysers : 0), \
Christopher Faulete6c3b692015-09-02 17:15:16 +020051 ##__VA_ARGS__)
52
53
54static const char *
55channel_label(const struct channel *chn)
56{
57 return (chn->flags & CF_ISRESP) ? "RESPONSE" : "REQUEST";
58}
59
60static const char *
61proxy_mode(const struct stream *s)
62{
63 struct proxy *px = (s->flags & SF_BE_ASSIGNED ? s->be : strm_fe(s));
64
65 return (px->mode == PR_MODE_HTTP) ? "HTTP" : "TCP";
66}
67
68static const char *
69stream_pos(const struct stream *s)
70{
71 return (s->flags & SF_BE_ASSIGNED) ? "backend" : "frontend";
72}
73
Christopher Faulet31ed32d2016-06-21 11:42:37 +020074static const char *
75filter_type(const struct filter *f)
76{
77 return (f->flags & FLT_FL_IS_BACKEND_FILTER) ? "backend" : "frontend";
78}
79
Christopher Fauletfcd99f82016-10-31 11:27:21 +010080static void
Willy Tarreauf1589372018-06-19 07:22:43 +020081trace_hexdump(struct buffer *buf, int len, int out)
Christopher Fauletfcd99f82016-10-31 11:27:21 +010082{
83 unsigned char p[len];
84 int block1, block2, i, j, padding;
85
86 block1 = len;
Willy Tarreauf1589372018-06-19 07:22:43 +020087 if (block1 > b_contig_data(buf, out))
88 block1 = b_contig_data(buf, out);
Willy Tarreau7194d3c2018-06-06 16:55:45 +020089 block2 = len - block1;
Christopher Fauletfcd99f82016-10-31 11:27:21 +010090
Willy Tarreauf1589372018-06-19 07:22:43 +020091 memcpy(p, b_head(buf), block1);
92 memcpy(p+block1, b_orig(buf), block2);
Christopher Fauletfcd99f82016-10-31 11:27:21 +010093
94 padding = ((len % 16) ? (16 - len % 16) : 0);
95 for (i = 0; i < len + padding; i++) {
96 if (!(i % 16))
97 fprintf(stderr, "\t0x%06x: ", i);
98 else if (!(i % 8))
99 fprintf(stderr, " ");
100
101 if (i < len)
102 fprintf(stderr, "%02x ", p[i]);
103 else
104 fprintf(stderr, " ");
105
106 /* print ASCII dump */
107 if (i % 16 == 15) {
108 fprintf(stderr, " |");
109 for(j = i - 15; j <= i && j < len; j++)
110 fprintf(stderr, "%c", (isprint(p[j]) ? p[j] : '.'));
111 fprintf(stderr, "|\n");
112 }
113 }
114}
115
Christopher Faulete6c3b692015-09-02 17:15:16 +0200116/***************************************************************************
117 * Hooks that manage the filter lifecycle (init/check/deinit)
118 **************************************************************************/
119/* Initialize the filter. Returns -1 on error, else 0. */
120static int
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100121trace_init(struct proxy *px, struct flt_conf *fconf)
Christopher Faulete6c3b692015-09-02 17:15:16 +0200122{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100123 struct trace_config *conf = fconf->conf;
Christopher Faulete6c3b692015-09-02 17:15:16 +0200124
125 if (conf->name)
126 memprintf(&conf->name, "%s/%s", conf->name, px->id);
127 else
128 memprintf(&conf->name, "TRACE/%s", px->id);
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100129 fconf->conf = conf;
Christopher Fauletfcd99f82016-10-31 11:27:21 +0100130 TRACE(conf, "filter initialized [read random=%s - fwd random=%s - hexdump=%s]",
Christopher Faulete6c3b692015-09-02 17:15:16 +0200131 (conf->rand_parsing ? "true" : "false"),
Christopher Fauletfcd99f82016-10-31 11:27:21 +0100132 (conf->rand_forwarding ? "true" : "false"),
133 (conf->hexdump ? "true" : "false"));
Christopher Faulete6c3b692015-09-02 17:15:16 +0200134 return 0;
135}
136
137/* Free ressources allocated by the trace filter. */
138static void
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100139trace_deinit(struct proxy *px, struct flt_conf *fconf)
Christopher Faulete6c3b692015-09-02 17:15:16 +0200140{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100141 struct trace_config *conf = fconf->conf;
Christopher Faulete6c3b692015-09-02 17:15:16 +0200142
143 if (conf) {
144 TRACE(conf, "filter deinitialized");
145 free(conf->name);
146 free(conf);
147 }
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100148 fconf->conf = NULL;
Christopher Faulete6c3b692015-09-02 17:15:16 +0200149}
150
151/* Check configuration of a trace filter for a specified proxy.
152 * Return 1 on error, else 0. */
153static int
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100154trace_check(struct proxy *px, struct flt_conf *fconf)
Christopher Faulete6c3b692015-09-02 17:15:16 +0200155{
156 return 0;
157}
158
Christopher Fauletf2273722017-07-27 16:58:42 +0200159/* Initialize the filter for each thread. Return -1 on error, else 0. */
160static int
161trace_init_per_thread(struct proxy *px, struct flt_conf *fconf)
162{
163 struct trace_config *conf = fconf->conf;
164
165 TRACE(conf, "filter initialized for thread tid %u", tid);
166 return 0;
167}
168
169/* Free ressources allocate by the trace filter for each thread. */
170static void
171trace_deinit_per_thread(struct proxy *px, struct flt_conf *fconf)
172{
173 struct trace_config *conf = fconf->conf;
174
175 if (conf)
176 TRACE(conf, "filter deinitialized for thread tid %u", tid);
177}
178
Christopher Faulete6c3b692015-09-02 17:15:16 +0200179/**************************************************************************
180 * Hooks to handle start/stop of streams
181 *************************************************************************/
Christopher Faulet31ed32d2016-06-21 11:42:37 +0200182/* Called when a filter instance is created and attach to a stream */
183static int
184trace_attach(struct stream *s, struct filter *filter)
185{
186 struct trace_config *conf = FLT_CONF(filter);
187
188 STRM_TRACE(conf, s, "%-25s: filter-type=%s",
189 __FUNCTION__, filter_type(filter));
190 return 1;
191}
192
193/* Called when a filter instance is detach from a stream, just before its
194 * destruction */
195static void
196trace_detach(struct stream *s, struct filter *filter)
197{
198 struct trace_config *conf = FLT_CONF(filter);
199
200 STRM_TRACE(conf, s, "%-25s: filter-type=%s",
201 __FUNCTION__, filter_type(filter));
202}
203
Christopher Faulete6c3b692015-09-02 17:15:16 +0200204/* Called when a stream is created */
205static int
206trace_stream_start(struct stream *s, struct filter *filter)
207{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100208 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200209
210 STRM_TRACE(conf, s, "%-25s",
211 __FUNCTION__);
212 return 0;
213}
214
Christopher Faulet31ed32d2016-06-21 11:42:37 +0200215
216/* Called when a backend is set for a stream */
217static int
218trace_stream_set_backend(struct stream *s, struct filter *filter,
219 struct proxy *be)
220{
221 struct trace_config *conf = FLT_CONF(filter);
222
223 STRM_TRACE(conf, s, "%-25s: backend=%s",
224 __FUNCTION__, be->id);
225 return 0;
226}
227
Christopher Faulete6c3b692015-09-02 17:15:16 +0200228/* Called when a stream is destroyed */
229static void
230trace_stream_stop(struct stream *s, struct filter *filter)
231{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100232 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200233
234 STRM_TRACE(conf, s, "%-25s",
235 __FUNCTION__);
236}
237
Christopher Fauleta00d8172016-11-10 14:58:05 +0100238/* Called when the stream is woken up because of an expired timer */
239static void
240trace_check_timeouts(struct stream *s, struct filter *filter)
241{
242 struct trace_config *conf = FLT_CONF(filter);
243
244 STRM_TRACE(conf, s, "%-25s",
245 __FUNCTION__);
246}
247
Christopher Faulete6c3b692015-09-02 17:15:16 +0200248/**************************************************************************
249 * Hooks to handle channels activity
250 *************************************************************************/
251/* Called when analyze starts for a given channel */
252static int
253trace_chn_start_analyze(struct stream *s, struct filter *filter,
254 struct channel *chn)
255{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100256 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200257
258 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s)",
259 __FUNCTION__,
260 channel_label(chn), proxy_mode(s), stream_pos(s));
Christopher Faulet3a394fa2016-05-11 17:13:39 +0200261 filter->pre_analyzers |= (AN_REQ_ALL | AN_RES_ALL);
262 filter->post_analyzers |= (AN_REQ_ALL | AN_RES_ALL);
Christopher Fauletfcd99f82016-10-31 11:27:21 +0100263 register_data_filter(s, chn, filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200264 return 1;
265}
266
267/* Called before a processing happens on a given channel */
268static int
269trace_chn_analyze(struct stream *s, struct filter *filter,
270 struct channel *chn, unsigned an_bit)
271{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100272 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200273 char *ana;
274
275 switch (an_bit) {
276 case AN_REQ_INSPECT_FE:
277 ana = "AN_REQ_INSPECT_FE";
278 break;
279 case AN_REQ_WAIT_HTTP:
280 ana = "AN_REQ_WAIT_HTTP";
281 break;
282 case AN_REQ_HTTP_BODY:
283 ana = "AN_REQ_HTTP_BODY";
284 break;
285 case AN_REQ_HTTP_PROCESS_FE:
286 ana = "AN_REQ_HTTP_PROCESS_FE";
287 break;
288 case AN_REQ_SWITCHING_RULES:
289 ana = "AN_REQ_SWITCHING_RULES";
290 break;
291 case AN_REQ_INSPECT_BE:
292 ana = "AN_REQ_INSPECT_BE";
293 break;
294 case AN_REQ_HTTP_PROCESS_BE:
295 ana = "AN_REQ_HTTP_PROCESS_BE";
296 break;
297 case AN_REQ_SRV_RULES:
298 ana = "AN_REQ_SRV_RULES";
299 break;
300 case AN_REQ_HTTP_INNER:
301 ana = "AN_REQ_HTTP_INNER";
302 break;
303 case AN_REQ_HTTP_TARPIT:
304 ana = "AN_REQ_HTTP_TARPIT";
305 break;
306 case AN_REQ_STICKING_RULES:
307 ana = "AN_REQ_STICKING_RULES";
308 break;
309 case AN_REQ_PRST_RDP_COOKIE:
310 ana = "AN_REQ_PRST_RDP_COOKIE";
311 break;
312 case AN_REQ_HTTP_XFER_BODY:
313 ana = "AN_REQ_HTTP_XFER_BODY";
314 break;
Christopher Faulete6c3b692015-09-02 17:15:16 +0200315 case AN_RES_INSPECT:
316 ana = "AN_RES_INSPECT";
317 break;
318 case AN_RES_WAIT_HTTP:
319 ana = "AN_RES_WAIT_HTTP";
320 break;
321 case AN_RES_HTTP_PROCESS_FE: // AN_RES_HTTP_PROCESS_BE
322 ana = "AN_RES_HTTP_PROCESS_FE/BE";
323 break;
324 case AN_RES_STORE_RULES:
325 ana = "AN_RES_STORE_RULES";
326 break;
Christopher Faulete6c3b692015-09-02 17:15:16 +0200327 case AN_RES_HTTP_XFER_BODY:
328 ana = "AN_RES_HTTP_XFER_BODY";
329 break;
Christopher Faulete6c3b692015-09-02 17:15:16 +0200330 default:
331 ana = "unknown";
332 }
333
Christopher Faulet3a394fa2016-05-11 17:13:39 +0200334 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s) - "
335 "analyzer=%s - step=%s",
Christopher Faulete6c3b692015-09-02 17:15:16 +0200336 __FUNCTION__,
337 channel_label(chn), proxy_mode(s), stream_pos(s),
Christopher Faulet3a394fa2016-05-11 17:13:39 +0200338 ana, ((chn->analysers & an_bit) ? "PRE" : "POST"));
Christopher Faulete6c3b692015-09-02 17:15:16 +0200339 return 1;
340}
341
342/* Called when analyze ends for a given channel */
343static int
344trace_chn_end_analyze(struct stream *s, struct filter *filter,
345 struct channel *chn)
346{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100347 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200348
349 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s)",
350 __FUNCTION__,
351 channel_label(chn), proxy_mode(s), stream_pos(s));
352 return 1;
353}
354
355/**************************************************************************
356 * Hooks to filter HTTP messages
357 *************************************************************************/
358static int
Christopher Faulet1339d742016-05-11 16:48:33 +0200359trace_http_headers(struct stream *s, struct filter *filter,
360 struct http_msg *msg)
361{
362 struct trace_config *conf = FLT_CONF(filter);
363 struct hdr_idx *hdr_idx;
364 char *cur_hdr;
365 int cur_idx;
366
367 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s)",
368 __FUNCTION__,
369 channel_label(msg->chn), proxy_mode(s), stream_pos(s));
370
Willy Tarreauf1589372018-06-19 07:22:43 +0200371 STRM_TRACE(conf, s, "\t%.*s", MIN(msg->sl.rq.l, 74), ci_head(msg->chn));
Christopher Faulet1339d742016-05-11 16:48:33 +0200372 hdr_idx = &s->txn->hdr_idx;
373 cur_idx = hdr_idx_first_idx(hdr_idx);
Willy Tarreauf1589372018-06-19 07:22:43 +0200374 cur_hdr = ci_head(msg->chn) + hdr_idx_first_pos(hdr_idx);
Christopher Faulet1339d742016-05-11 16:48:33 +0200375 while (cur_idx) {
376 STRM_TRACE(conf, s, "\t%.*s",
377 MIN(hdr_idx->v[cur_idx].len, 74), cur_hdr);
378 cur_hdr += hdr_idx->v[cur_idx].len + hdr_idx->v[cur_idx].cr + 1;
379 cur_idx = hdr_idx->v[cur_idx].next;
380 }
Christopher Faulet1339d742016-05-11 16:48:33 +0200381 return 1;
382}
383
384static int
Christopher Faulete6c3b692015-09-02 17:15:16 +0200385trace_http_data(struct stream *s, struct filter *filter,
386 struct http_msg *msg)
387{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100388 struct trace_config *conf = FLT_CONF(filter);
Willy Tarreauf1589372018-06-19 07:22:43 +0200389 int avail = MIN(msg->chunk_len + msg->next, ci_data(msg->chn)) - FLT_NXT(filter, msg->chn);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200390 int ret = avail;
391
392 if (ret && conf->rand_parsing)
393 ret = random() % (ret+1);
394
395 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s) - "
396 "chunk_len=%llu - next=%u - fwd=%u - avail=%d - consume=%d",
397 __FUNCTION__,
398 channel_label(msg->chn), proxy_mode(s), stream_pos(s),
399 msg->chunk_len, FLT_NXT(filter, msg->chn),
400 FLT_FWD(filter, msg->chn), avail, ret);
401 if (ret != avail)
402 task_wakeup(s->task, TASK_WOKEN_MSG);
403 return ret;
404}
405
406static int
407trace_http_chunk_trailers(struct stream *s, struct filter *filter,
408 struct http_msg *msg)
409{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100410 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200411
412 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s)",
413 __FUNCTION__,
414 channel_label(msg->chn), proxy_mode(s), stream_pos(s));
415 return 1;
416}
417
418static int
419trace_http_end(struct stream *s, struct filter *filter,
420 struct http_msg *msg)
421{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100422 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200423
424 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s)",
425 __FUNCTION__,
426 channel_label(msg->chn), proxy_mode(s), stream_pos(s));
427 return 1;
428}
429
430static void
431trace_http_reset(struct stream *s, struct filter *filter,
432 struct http_msg *msg)
433{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100434 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200435
436 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s)",
437 __FUNCTION__,
438 channel_label(msg->chn), proxy_mode(s), stream_pos(s));
439}
440
441static void
442trace_http_reply(struct stream *s, struct filter *filter, short status,
Willy Tarreau83061a82018-07-13 11:56:34 +0200443 const struct buffer *msg)
Christopher Faulete6c3b692015-09-02 17:15:16 +0200444{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100445 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200446
447 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s)",
448 __FUNCTION__, "-", proxy_mode(s), stream_pos(s));
449}
450
451static int
452trace_http_forward_data(struct stream *s, struct filter *filter,
453 struct http_msg *msg, unsigned int len)
454{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100455 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200456 int ret = len;
457
458 if (ret && conf->rand_forwarding)
459 ret = random() % (ret+1);
460
461 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s) - "
462 "len=%u - nxt=%u - fwd=%u - forward=%d",
463 __FUNCTION__,
464 channel_label(msg->chn), proxy_mode(s), stream_pos(s), len,
465 FLT_NXT(filter, msg->chn), FLT_FWD(filter, msg->chn), ret);
466
Christopher Fauletfcd99f82016-10-31 11:27:21 +0100467 if (conf->hexdump) {
Willy Tarreaubcbd3932018-06-06 07:13:22 +0200468 c_adv(msg->chn, FLT_FWD(filter, msg->chn));
Willy Tarreauc9fa0482018-07-10 17:43:27 +0200469 trace_hexdump(&msg->chn->buf, ret, co_data(msg->chn));
Willy Tarreaubcbd3932018-06-06 07:13:22 +0200470 c_rew(msg->chn, FLT_FWD(filter, msg->chn));
Christopher Fauletfcd99f82016-10-31 11:27:21 +0100471 }
472
Christopher Faulete6c3b692015-09-02 17:15:16 +0200473 if ((ret != len) ||
474 (FLT_NXT(filter, msg->chn) != FLT_FWD(filter, msg->chn) + ret))
475 task_wakeup(s->task, TASK_WOKEN_MSG);
476 return ret;
477}
478
479/**************************************************************************
480 * Hooks to filter TCP data
481 *************************************************************************/
482static int
483trace_tcp_data(struct stream *s, struct filter *filter, struct channel *chn)
484{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100485 struct trace_config *conf = FLT_CONF(filter);
Willy Tarreauf1589372018-06-19 07:22:43 +0200486 int avail = ci_data(chn) - FLT_NXT(filter, chn);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200487 int ret = avail;
488
489 if (ret && conf->rand_parsing)
490 ret = random() % (ret+1);
491
492 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s) - next=%u - avail=%u - consume=%d",
493 __FUNCTION__,
494 channel_label(chn), proxy_mode(s), stream_pos(s),
495 FLT_NXT(filter, chn), avail, ret);
496
497 if (ret != avail)
498 task_wakeup(s->task, TASK_WOKEN_MSG);
499 return ret;
500}
501
502static int
503trace_tcp_forward_data(struct stream *s, struct filter *filter, struct channel *chn,
504 unsigned int len)
505{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100506 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200507 int ret = len;
508
509 if (ret && conf->rand_forwarding)
510 ret = random() % (ret+1);
511
512 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s) - len=%u - fwd=%u - forward=%d",
513 __FUNCTION__,
514 channel_label(chn), proxy_mode(s), stream_pos(s), len,
515 FLT_FWD(filter, chn), ret);
516
Christopher Fauletfcd99f82016-10-31 11:27:21 +0100517 if (conf->hexdump) {
Willy Tarreaubcbd3932018-06-06 07:13:22 +0200518 c_adv(chn, FLT_FWD(filter, chn));
Willy Tarreauc9fa0482018-07-10 17:43:27 +0200519 trace_hexdump(&chn->buf, ret, co_data(chn));
Willy Tarreaubcbd3932018-06-06 07:13:22 +0200520 c_rew(chn, FLT_FWD(filter, chn));
Christopher Fauletfcd99f82016-10-31 11:27:21 +0100521 }
522
Christopher Faulete6c3b692015-09-02 17:15:16 +0200523 if (ret != len)
524 task_wakeup(s->task, TASK_WOKEN_MSG);
525 return ret;
526}
527
528/********************************************************************
529 * Functions that manage the filter initialization
530 ********************************************************************/
531struct flt_ops trace_ops = {
532 /* Manage trace filter, called for each filter declaration */
Christopher Fauletf2273722017-07-27 16:58:42 +0200533 .init = trace_init,
534 .deinit = trace_deinit,
535 .check = trace_check,
536 .init_per_thread = trace_init_per_thread,
537 .deinit_per_thread = trace_deinit_per_thread,
Christopher Faulete6c3b692015-09-02 17:15:16 +0200538
539 /* Handle start/stop of streams */
Christopher Faulet31ed32d2016-06-21 11:42:37 +0200540 .attach = trace_attach,
541 .detach = trace_detach,
542 .stream_start = trace_stream_start,
543 .stream_set_backend = trace_stream_set_backend,
544 .stream_stop = trace_stream_stop,
Christopher Fauleta00d8172016-11-10 14:58:05 +0100545 .check_timeouts = trace_check_timeouts,
Christopher Faulete6c3b692015-09-02 17:15:16 +0200546
547 /* Handle channels activity */
548 .channel_start_analyze = trace_chn_start_analyze,
Christopher Faulet3a394fa2016-05-11 17:13:39 +0200549 .channel_pre_analyze = trace_chn_analyze,
550 .channel_post_analyze = trace_chn_analyze,
Christopher Faulete6c3b692015-09-02 17:15:16 +0200551 .channel_end_analyze = trace_chn_end_analyze,
552
553 /* Filter HTTP requests and responses */
Christopher Faulet1339d742016-05-11 16:48:33 +0200554 .http_headers = trace_http_headers,
Christopher Faulete6c3b692015-09-02 17:15:16 +0200555 .http_data = trace_http_data,
556 .http_chunk_trailers = trace_http_chunk_trailers,
557 .http_end = trace_http_end,
558
559 .http_reset = trace_http_reset,
560 .http_reply = trace_http_reply,
561 .http_forward_data = trace_http_forward_data,
562
563 /* Filter TCP data */
564 .tcp_data = trace_tcp_data,
565 .tcp_forward_data = trace_tcp_forward_data,
566};
567
568/* Return -1 on error, else 0 */
569static int
570parse_trace_flt(char **args, int *cur_arg, struct proxy *px,
Thierry Fournier3610c392016-04-13 18:27:51 +0200571 struct flt_conf *fconf, char **err, void *private)
Christopher Faulete6c3b692015-09-02 17:15:16 +0200572{
573 struct trace_config *conf;
574 int pos = *cur_arg;
575
576 conf = calloc(1, sizeof(*conf));
577 if (!conf) {
578 memprintf(err, "%s: out of memory", args[*cur_arg]);
579 return -1;
580 }
581 conf->proxy = px;
582
583 if (!strcmp(args[pos], "trace")) {
584 pos++;
585
586 while (*args[pos]) {
587 if (!strcmp(args[pos], "name")) {
588 if (!*args[pos + 1]) {
589 memprintf(err, "'%s' : '%s' option without value",
590 args[*cur_arg], args[pos]);
591 goto error;
592 }
593 conf->name = strdup(args[pos + 1]);
594 if (!conf->name) {
595 memprintf(err, "%s: out of memory", args[*cur_arg]);
596 goto error;
597 }
598 pos++;
599 }
600 else if (!strcmp(args[pos], "random-parsing"))
601 conf->rand_parsing = 1;
602 else if (!strcmp(args[pos], "random-forwarding"))
603 conf->rand_forwarding = 1;
Christopher Fauletfcd99f82016-10-31 11:27:21 +0100604 else if (!strcmp(args[pos], "hexdump"))
605 conf->hexdump = 1;
Christopher Faulete6c3b692015-09-02 17:15:16 +0200606 else
607 break;
608 pos++;
609 }
610 *cur_arg = pos;
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100611 fconf->ops = &trace_ops;
Christopher Faulete6c3b692015-09-02 17:15:16 +0200612 }
613
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100614 fconf->conf = conf;
Christopher Faulete6c3b692015-09-02 17:15:16 +0200615 return 0;
616
617 error:
618 if (conf->name)
619 free(conf->name);
620 free(conf);
621 return -1;
622}
623
624/* Declare the filter parser for "trace" keyword */
625static struct flt_kw_list flt_kws = { "TRACE", { }, {
Thierry Fournier3610c392016-04-13 18:27:51 +0200626 { "trace", parse_trace_flt, NULL },
627 { NULL, NULL, NULL },
Christopher Faulete6c3b692015-09-02 17:15:16 +0200628 }
629};
630
631__attribute__((constructor))
632static void
633__flt_trace_init(void)
634{
635 flt_register_keywords(&flt_kws);
636}