blob: d5a4d93e4938876e58d04d624bd3414ac54c8ca9 [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
Willy Tarreau0108d902018-11-25 19:14:37 +010015#include <common/hathreads.h>
16#include <common/initcall.h>
Christopher Faulete6c3b692015-09-02 17:15:16 +020017#include <common/standard.h>
18#include <common/time.h>
19#include <common/tools.h>
20
21#include <types/channel.h>
22#include <types/filters.h>
23#include <types/global.h>
24#include <types/proxy.h>
25#include <types/stream.h>
26
27#include <proto/filters.h>
Christopher Faulet1339d742016-05-11 16:48:33 +020028#include <proto/hdr_idx.h>
Christopher Faulete6c3b692015-09-02 17:15:16 +020029#include <proto/log.h>
30#include <proto/stream.h>
31
32struct flt_ops trace_ops;
33
34struct trace_config {
35 struct proxy *proxy;
36 char *name;
37 int rand_parsing;
38 int rand_forwarding;
Christopher Fauletfcd99f82016-10-31 11:27:21 +010039 int hexdump;
Christopher Faulete6c3b692015-09-02 17:15:16 +020040};
41
42#define TRACE(conf, fmt, ...) \
43 fprintf(stderr, "%d.%06d [%-20s] " fmt "\n", \
44 (int)now.tv_sec, (int)now.tv_usec, (conf)->name, \
45 ##__VA_ARGS__)
46
Christopher Fauletfcd99f82016-10-31 11:27:21 +010047#define STRM_TRACE(conf, strm, fmt, ...) \
48 fprintf(stderr, "%d.%06d [%-20s] [strm %p(%x) 0x%08x 0x%08x] " fmt "\n", \
49 (int)now.tv_sec, (int)now.tv_usec, (conf)->name, \
50 strm, (strm ? ((struct stream *)strm)->uniq_id : ~0U), \
51 (strm ? strm->req.analysers : 0), (strm ? strm->res.analysers : 0), \
Christopher Faulete6c3b692015-09-02 17:15:16 +020052 ##__VA_ARGS__)
53
54
55static const char *
56channel_label(const struct channel *chn)
57{
58 return (chn->flags & CF_ISRESP) ? "RESPONSE" : "REQUEST";
59}
60
61static const char *
62proxy_mode(const struct stream *s)
63{
64 struct proxy *px = (s->flags & SF_BE_ASSIGNED ? s->be : strm_fe(s));
65
66 return (px->mode == PR_MODE_HTTP) ? "HTTP" : "TCP";
67}
68
69static const char *
70stream_pos(const struct stream *s)
71{
72 return (s->flags & SF_BE_ASSIGNED) ? "backend" : "frontend";
73}
74
Christopher Faulet31ed32d2016-06-21 11:42:37 +020075static const char *
76filter_type(const struct filter *f)
77{
78 return (f->flags & FLT_FL_IS_BACKEND_FILTER) ? "backend" : "frontend";
79}
80
Christopher Fauletfcd99f82016-10-31 11:27:21 +010081static void
Willy Tarreauf1589372018-06-19 07:22:43 +020082trace_hexdump(struct buffer *buf, int len, int out)
Christopher Fauletfcd99f82016-10-31 11:27:21 +010083{
84 unsigned char p[len];
85 int block1, block2, i, j, padding;
86
87 block1 = len;
Willy Tarreauf1589372018-06-19 07:22:43 +020088 if (block1 > b_contig_data(buf, out))
89 block1 = b_contig_data(buf, out);
Willy Tarreau7194d3c2018-06-06 16:55:45 +020090 block2 = len - block1;
Christopher Fauletfcd99f82016-10-31 11:27:21 +010091
Willy Tarreauf1589372018-06-19 07:22:43 +020092 memcpy(p, b_head(buf), block1);
93 memcpy(p+block1, b_orig(buf), block2);
Christopher Fauletfcd99f82016-10-31 11:27:21 +010094
95 padding = ((len % 16) ? (16 - len % 16) : 0);
96 for (i = 0; i < len + padding; i++) {
97 if (!(i % 16))
98 fprintf(stderr, "\t0x%06x: ", i);
99 else if (!(i % 8))
100 fprintf(stderr, " ");
101
102 if (i < len)
103 fprintf(stderr, "%02x ", p[i]);
104 else
105 fprintf(stderr, " ");
106
107 /* print ASCII dump */
108 if (i % 16 == 15) {
109 fprintf(stderr, " |");
110 for(j = i - 15; j <= i && j < len; j++)
111 fprintf(stderr, "%c", (isprint(p[j]) ? p[j] : '.'));
112 fprintf(stderr, "|\n");
113 }
114 }
115}
116
Christopher Faulete6c3b692015-09-02 17:15:16 +0200117/***************************************************************************
118 * Hooks that manage the filter lifecycle (init/check/deinit)
119 **************************************************************************/
120/* Initialize the filter. Returns -1 on error, else 0. */
121static int
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100122trace_init(struct proxy *px, struct flt_conf *fconf)
Christopher Faulete6c3b692015-09-02 17:15:16 +0200123{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100124 struct trace_config *conf = fconf->conf;
Christopher Faulete6c3b692015-09-02 17:15:16 +0200125
126 if (conf->name)
127 memprintf(&conf->name, "%s/%s", conf->name, px->id);
128 else
129 memprintf(&conf->name, "TRACE/%s", px->id);
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100130 fconf->conf = conf;
Christopher Fauletfcd99f82016-10-31 11:27:21 +0100131 TRACE(conf, "filter initialized [read random=%s - fwd random=%s - hexdump=%s]",
Christopher Faulete6c3b692015-09-02 17:15:16 +0200132 (conf->rand_parsing ? "true" : "false"),
Christopher Fauletfcd99f82016-10-31 11:27:21 +0100133 (conf->rand_forwarding ? "true" : "false"),
134 (conf->hexdump ? "true" : "false"));
Christopher Faulete6c3b692015-09-02 17:15:16 +0200135 return 0;
136}
137
138/* Free ressources allocated by the trace filter. */
139static void
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100140trace_deinit(struct proxy *px, struct flt_conf *fconf)
Christopher Faulete6c3b692015-09-02 17:15:16 +0200141{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100142 struct trace_config *conf = fconf->conf;
Christopher Faulete6c3b692015-09-02 17:15:16 +0200143
144 if (conf) {
145 TRACE(conf, "filter deinitialized");
146 free(conf->name);
147 free(conf);
148 }
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100149 fconf->conf = NULL;
Christopher Faulete6c3b692015-09-02 17:15:16 +0200150}
151
152/* Check configuration of a trace filter for a specified proxy.
153 * Return 1 on error, else 0. */
154static int
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100155trace_check(struct proxy *px, struct flt_conf *fconf)
Christopher Faulete6c3b692015-09-02 17:15:16 +0200156{
157 return 0;
158}
159
Christopher Fauletf2273722017-07-27 16:58:42 +0200160/* Initialize the filter for each thread. Return -1 on error, else 0. */
161static int
162trace_init_per_thread(struct proxy *px, struct flt_conf *fconf)
163{
164 struct trace_config *conf = fconf->conf;
165
166 TRACE(conf, "filter initialized for thread tid %u", tid);
167 return 0;
168}
169
170/* Free ressources allocate by the trace filter for each thread. */
171static void
172trace_deinit_per_thread(struct proxy *px, struct flt_conf *fconf)
173{
174 struct trace_config *conf = fconf->conf;
175
176 if (conf)
177 TRACE(conf, "filter deinitialized for thread tid %u", tid);
178}
179
Christopher Faulete6c3b692015-09-02 17:15:16 +0200180/**************************************************************************
181 * Hooks to handle start/stop of streams
182 *************************************************************************/
Christopher Faulet31ed32d2016-06-21 11:42:37 +0200183/* Called when a filter instance is created and attach to a stream */
184static int
185trace_attach(struct stream *s, struct filter *filter)
186{
187 struct trace_config *conf = FLT_CONF(filter);
188
189 STRM_TRACE(conf, s, "%-25s: filter-type=%s",
190 __FUNCTION__, filter_type(filter));
191 return 1;
192}
193
194/* Called when a filter instance is detach from a stream, just before its
195 * destruction */
196static void
197trace_detach(struct stream *s, struct filter *filter)
198{
199 struct trace_config *conf = FLT_CONF(filter);
200
201 STRM_TRACE(conf, s, "%-25s: filter-type=%s",
202 __FUNCTION__, filter_type(filter));
203}
204
Christopher Faulete6c3b692015-09-02 17:15:16 +0200205/* Called when a stream is created */
206static int
207trace_stream_start(struct stream *s, struct filter *filter)
208{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100209 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200210
211 STRM_TRACE(conf, s, "%-25s",
212 __FUNCTION__);
213 return 0;
214}
215
Christopher Faulet31ed32d2016-06-21 11:42:37 +0200216
217/* Called when a backend is set for a stream */
218static int
219trace_stream_set_backend(struct stream *s, struct filter *filter,
220 struct proxy *be)
221{
222 struct trace_config *conf = FLT_CONF(filter);
223
224 STRM_TRACE(conf, s, "%-25s: backend=%s",
225 __FUNCTION__, be->id);
226 return 0;
227}
228
Christopher Faulete6c3b692015-09-02 17:15:16 +0200229/* Called when a stream is destroyed */
230static void
231trace_stream_stop(struct stream *s, struct filter *filter)
232{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100233 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200234
235 STRM_TRACE(conf, s, "%-25s",
236 __FUNCTION__);
237}
238
Christopher Fauleta00d8172016-11-10 14:58:05 +0100239/* Called when the stream is woken up because of an expired timer */
240static void
241trace_check_timeouts(struct stream *s, struct filter *filter)
242{
243 struct trace_config *conf = FLT_CONF(filter);
244
245 STRM_TRACE(conf, s, "%-25s",
246 __FUNCTION__);
247}
248
Christopher Faulete6c3b692015-09-02 17:15:16 +0200249/**************************************************************************
250 * Hooks to handle channels activity
251 *************************************************************************/
252/* Called when analyze starts for a given channel */
253static int
254trace_chn_start_analyze(struct stream *s, struct filter *filter,
255 struct channel *chn)
256{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100257 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200258
259 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s)",
260 __FUNCTION__,
261 channel_label(chn), proxy_mode(s), stream_pos(s));
Christopher Faulet3a394fa2016-05-11 17:13:39 +0200262 filter->pre_analyzers |= (AN_REQ_ALL | AN_RES_ALL);
263 filter->post_analyzers |= (AN_REQ_ALL | AN_RES_ALL);
Christopher Fauletfcd99f82016-10-31 11:27:21 +0100264 register_data_filter(s, chn, filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200265 return 1;
266}
267
268/* Called before a processing happens on a given channel */
269static int
270trace_chn_analyze(struct stream *s, struct filter *filter,
271 struct channel *chn, unsigned an_bit)
272{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100273 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200274 char *ana;
275
276 switch (an_bit) {
277 case AN_REQ_INSPECT_FE:
278 ana = "AN_REQ_INSPECT_FE";
279 break;
280 case AN_REQ_WAIT_HTTP:
281 ana = "AN_REQ_WAIT_HTTP";
282 break;
283 case AN_REQ_HTTP_BODY:
284 ana = "AN_REQ_HTTP_BODY";
285 break;
286 case AN_REQ_HTTP_PROCESS_FE:
287 ana = "AN_REQ_HTTP_PROCESS_FE";
288 break;
289 case AN_REQ_SWITCHING_RULES:
290 ana = "AN_REQ_SWITCHING_RULES";
291 break;
292 case AN_REQ_INSPECT_BE:
293 ana = "AN_REQ_INSPECT_BE";
294 break;
295 case AN_REQ_HTTP_PROCESS_BE:
296 ana = "AN_REQ_HTTP_PROCESS_BE";
297 break;
298 case AN_REQ_SRV_RULES:
299 ana = "AN_REQ_SRV_RULES";
300 break;
301 case AN_REQ_HTTP_INNER:
302 ana = "AN_REQ_HTTP_INNER";
303 break;
304 case AN_REQ_HTTP_TARPIT:
305 ana = "AN_REQ_HTTP_TARPIT";
306 break;
307 case AN_REQ_STICKING_RULES:
308 ana = "AN_REQ_STICKING_RULES";
309 break;
310 case AN_REQ_PRST_RDP_COOKIE:
311 ana = "AN_REQ_PRST_RDP_COOKIE";
312 break;
313 case AN_REQ_HTTP_XFER_BODY:
314 ana = "AN_REQ_HTTP_XFER_BODY";
315 break;
Christopher Faulete6c3b692015-09-02 17:15:16 +0200316 case AN_RES_INSPECT:
317 ana = "AN_RES_INSPECT";
318 break;
319 case AN_RES_WAIT_HTTP:
320 ana = "AN_RES_WAIT_HTTP";
321 break;
322 case AN_RES_HTTP_PROCESS_FE: // AN_RES_HTTP_PROCESS_BE
323 ana = "AN_RES_HTTP_PROCESS_FE/BE";
324 break;
325 case AN_RES_STORE_RULES:
326 ana = "AN_RES_STORE_RULES";
327 break;
Christopher Faulete6c3b692015-09-02 17:15:16 +0200328 case AN_RES_HTTP_XFER_BODY:
329 ana = "AN_RES_HTTP_XFER_BODY";
330 break;
Christopher Faulete6c3b692015-09-02 17:15:16 +0200331 default:
332 ana = "unknown";
333 }
334
Christopher Faulet3a394fa2016-05-11 17:13:39 +0200335 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s) - "
336 "analyzer=%s - step=%s",
Christopher Faulete6c3b692015-09-02 17:15:16 +0200337 __FUNCTION__,
338 channel_label(chn), proxy_mode(s), stream_pos(s),
Christopher Faulet3a394fa2016-05-11 17:13:39 +0200339 ana, ((chn->analysers & an_bit) ? "PRE" : "POST"));
Christopher Faulete6c3b692015-09-02 17:15:16 +0200340 return 1;
341}
342
343/* Called when analyze ends for a given channel */
344static int
345trace_chn_end_analyze(struct stream *s, struct filter *filter,
346 struct channel *chn)
347{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100348 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200349
350 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s)",
351 __FUNCTION__,
352 channel_label(chn), proxy_mode(s), stream_pos(s));
353 return 1;
354}
355
356/**************************************************************************
357 * Hooks to filter HTTP messages
358 *************************************************************************/
359static int
Christopher Faulet1339d742016-05-11 16:48:33 +0200360trace_http_headers(struct stream *s, struct filter *filter,
361 struct http_msg *msg)
362{
363 struct trace_config *conf = FLT_CONF(filter);
364 struct hdr_idx *hdr_idx;
365 char *cur_hdr;
366 int cur_idx;
367
368 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s)",
369 __FUNCTION__,
370 channel_label(msg->chn), proxy_mode(s), stream_pos(s));
371
Willy Tarreauf1589372018-06-19 07:22:43 +0200372 STRM_TRACE(conf, s, "\t%.*s", MIN(msg->sl.rq.l, 74), ci_head(msg->chn));
Christopher Faulet1339d742016-05-11 16:48:33 +0200373 hdr_idx = &s->txn->hdr_idx;
374 cur_idx = hdr_idx_first_idx(hdr_idx);
Willy Tarreauf1589372018-06-19 07:22:43 +0200375 cur_hdr = ci_head(msg->chn) + hdr_idx_first_pos(hdr_idx);
Christopher Faulet1339d742016-05-11 16:48:33 +0200376 while (cur_idx) {
377 STRM_TRACE(conf, s, "\t%.*s",
378 MIN(hdr_idx->v[cur_idx].len, 74), cur_hdr);
379 cur_hdr += hdr_idx->v[cur_idx].len + hdr_idx->v[cur_idx].cr + 1;
380 cur_idx = hdr_idx->v[cur_idx].next;
381 }
Christopher Faulet1339d742016-05-11 16:48:33 +0200382 return 1;
383}
384
385static int
Christopher Faulete6c3b692015-09-02 17:15:16 +0200386trace_http_data(struct stream *s, struct filter *filter,
387 struct http_msg *msg)
388{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100389 struct trace_config *conf = FLT_CONF(filter);
Willy Tarreauf1589372018-06-19 07:22:43 +0200390 int avail = MIN(msg->chunk_len + msg->next, ci_data(msg->chn)) - FLT_NXT(filter, msg->chn);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200391 int ret = avail;
392
393 if (ret && conf->rand_parsing)
394 ret = random() % (ret+1);
395
396 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s) - "
397 "chunk_len=%llu - next=%u - fwd=%u - avail=%d - consume=%d",
398 __FUNCTION__,
399 channel_label(msg->chn), proxy_mode(s), stream_pos(s),
400 msg->chunk_len, FLT_NXT(filter, msg->chn),
401 FLT_FWD(filter, msg->chn), avail, ret);
402 if (ret != avail)
403 task_wakeup(s->task, TASK_WOKEN_MSG);
404 return ret;
405}
406
407static int
408trace_http_chunk_trailers(struct stream *s, struct filter *filter,
409 struct http_msg *msg)
410{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100411 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200412
413 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s)",
414 __FUNCTION__,
415 channel_label(msg->chn), proxy_mode(s), stream_pos(s));
416 return 1;
417}
418
419static int
420trace_http_end(struct stream *s, struct filter *filter,
421 struct http_msg *msg)
422{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100423 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200424
425 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s)",
426 __FUNCTION__,
427 channel_label(msg->chn), proxy_mode(s), stream_pos(s));
428 return 1;
429}
430
431static void
432trace_http_reset(struct stream *s, struct filter *filter,
433 struct http_msg *msg)
434{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100435 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200436
437 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s)",
438 __FUNCTION__,
439 channel_label(msg->chn), proxy_mode(s), stream_pos(s));
440}
441
442static void
443trace_http_reply(struct stream *s, struct filter *filter, short status,
Willy Tarreau83061a82018-07-13 11:56:34 +0200444 const struct buffer *msg)
Christopher Faulete6c3b692015-09-02 17:15:16 +0200445{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100446 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200447
448 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s)",
449 __FUNCTION__, "-", proxy_mode(s), stream_pos(s));
450}
451
452static int
453trace_http_forward_data(struct stream *s, struct filter *filter,
454 struct http_msg *msg, unsigned int len)
455{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100456 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200457 int ret = len;
458
459 if (ret && conf->rand_forwarding)
460 ret = random() % (ret+1);
461
462 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s) - "
463 "len=%u - nxt=%u - fwd=%u - forward=%d",
464 __FUNCTION__,
465 channel_label(msg->chn), proxy_mode(s), stream_pos(s), len,
466 FLT_NXT(filter, msg->chn), FLT_FWD(filter, msg->chn), ret);
467
Christopher Fauletfcd99f82016-10-31 11:27:21 +0100468 if (conf->hexdump) {
Willy Tarreaubcbd3932018-06-06 07:13:22 +0200469 c_adv(msg->chn, FLT_FWD(filter, msg->chn));
Willy Tarreauc9fa0482018-07-10 17:43:27 +0200470 trace_hexdump(&msg->chn->buf, ret, co_data(msg->chn));
Willy Tarreaubcbd3932018-06-06 07:13:22 +0200471 c_rew(msg->chn, FLT_FWD(filter, msg->chn));
Christopher Fauletfcd99f82016-10-31 11:27:21 +0100472 }
473
Christopher Faulete6c3b692015-09-02 17:15:16 +0200474 if ((ret != len) ||
475 (FLT_NXT(filter, msg->chn) != FLT_FWD(filter, msg->chn) + ret))
476 task_wakeup(s->task, TASK_WOKEN_MSG);
477 return ret;
478}
479
480/**************************************************************************
481 * Hooks to filter TCP data
482 *************************************************************************/
483static int
484trace_tcp_data(struct stream *s, struct filter *filter, struct channel *chn)
485{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100486 struct trace_config *conf = FLT_CONF(filter);
Willy Tarreauf1589372018-06-19 07:22:43 +0200487 int avail = ci_data(chn) - FLT_NXT(filter, chn);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200488 int ret = avail;
489
490 if (ret && conf->rand_parsing)
491 ret = random() % (ret+1);
492
493 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s) - next=%u - avail=%u - consume=%d",
494 __FUNCTION__,
495 channel_label(chn), proxy_mode(s), stream_pos(s),
496 FLT_NXT(filter, chn), avail, ret);
497
498 if (ret != avail)
499 task_wakeup(s->task, TASK_WOKEN_MSG);
500 return ret;
501}
502
503static int
504trace_tcp_forward_data(struct stream *s, struct filter *filter, struct channel *chn,
505 unsigned int len)
506{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100507 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200508 int ret = len;
509
510 if (ret && conf->rand_forwarding)
511 ret = random() % (ret+1);
512
513 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s) - len=%u - fwd=%u - forward=%d",
514 __FUNCTION__,
515 channel_label(chn), proxy_mode(s), stream_pos(s), len,
516 FLT_FWD(filter, chn), ret);
517
Christopher Fauletfcd99f82016-10-31 11:27:21 +0100518 if (conf->hexdump) {
Willy Tarreaubcbd3932018-06-06 07:13:22 +0200519 c_adv(chn, FLT_FWD(filter, chn));
Willy Tarreauc9fa0482018-07-10 17:43:27 +0200520 trace_hexdump(&chn->buf, ret, co_data(chn));
Willy Tarreaubcbd3932018-06-06 07:13:22 +0200521 c_rew(chn, FLT_FWD(filter, chn));
Christopher Fauletfcd99f82016-10-31 11:27:21 +0100522 }
523
Christopher Faulete6c3b692015-09-02 17:15:16 +0200524 if (ret != len)
525 task_wakeup(s->task, TASK_WOKEN_MSG);
526 return ret;
527}
528
529/********************************************************************
530 * Functions that manage the filter initialization
531 ********************************************************************/
532struct flt_ops trace_ops = {
533 /* Manage trace filter, called for each filter declaration */
Christopher Fauletf2273722017-07-27 16:58:42 +0200534 .init = trace_init,
535 .deinit = trace_deinit,
536 .check = trace_check,
537 .init_per_thread = trace_init_per_thread,
538 .deinit_per_thread = trace_deinit_per_thread,
Christopher Faulete6c3b692015-09-02 17:15:16 +0200539
540 /* Handle start/stop of streams */
Christopher Faulet31ed32d2016-06-21 11:42:37 +0200541 .attach = trace_attach,
542 .detach = trace_detach,
543 .stream_start = trace_stream_start,
544 .stream_set_backend = trace_stream_set_backend,
545 .stream_stop = trace_stream_stop,
Christopher Fauleta00d8172016-11-10 14:58:05 +0100546 .check_timeouts = trace_check_timeouts,
Christopher Faulete6c3b692015-09-02 17:15:16 +0200547
548 /* Handle channels activity */
549 .channel_start_analyze = trace_chn_start_analyze,
Christopher Faulet3a394fa2016-05-11 17:13:39 +0200550 .channel_pre_analyze = trace_chn_analyze,
551 .channel_post_analyze = trace_chn_analyze,
Christopher Faulete6c3b692015-09-02 17:15:16 +0200552 .channel_end_analyze = trace_chn_end_analyze,
553
554 /* Filter HTTP requests and responses */
Christopher Faulet1339d742016-05-11 16:48:33 +0200555 .http_headers = trace_http_headers,
Christopher Faulete6c3b692015-09-02 17:15:16 +0200556 .http_data = trace_http_data,
557 .http_chunk_trailers = trace_http_chunk_trailers,
558 .http_end = trace_http_end,
559
560 .http_reset = trace_http_reset,
561 .http_reply = trace_http_reply,
562 .http_forward_data = trace_http_forward_data,
563
564 /* Filter TCP data */
565 .tcp_data = trace_tcp_data,
566 .tcp_forward_data = trace_tcp_forward_data,
567};
568
569/* Return -1 on error, else 0 */
570static int
571parse_trace_flt(char **args, int *cur_arg, struct proxy *px,
Thierry Fournier3610c392016-04-13 18:27:51 +0200572 struct flt_conf *fconf, char **err, void *private)
Christopher Faulete6c3b692015-09-02 17:15:16 +0200573{
574 struct trace_config *conf;
575 int pos = *cur_arg;
576
577 conf = calloc(1, sizeof(*conf));
578 if (!conf) {
579 memprintf(err, "%s: out of memory", args[*cur_arg]);
580 return -1;
581 }
582 conf->proxy = px;
583
584 if (!strcmp(args[pos], "trace")) {
585 pos++;
586
587 while (*args[pos]) {
588 if (!strcmp(args[pos], "name")) {
589 if (!*args[pos + 1]) {
590 memprintf(err, "'%s' : '%s' option without value",
591 args[*cur_arg], args[pos]);
592 goto error;
593 }
594 conf->name = strdup(args[pos + 1]);
595 if (!conf->name) {
596 memprintf(err, "%s: out of memory", args[*cur_arg]);
597 goto error;
598 }
599 pos++;
600 }
601 else if (!strcmp(args[pos], "random-parsing"))
602 conf->rand_parsing = 1;
603 else if (!strcmp(args[pos], "random-forwarding"))
604 conf->rand_forwarding = 1;
Christopher Fauletfcd99f82016-10-31 11:27:21 +0100605 else if (!strcmp(args[pos], "hexdump"))
606 conf->hexdump = 1;
Christopher Faulete6c3b692015-09-02 17:15:16 +0200607 else
608 break;
609 pos++;
610 }
611 *cur_arg = pos;
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100612 fconf->ops = &trace_ops;
Christopher Faulete6c3b692015-09-02 17:15:16 +0200613 }
614
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100615 fconf->conf = conf;
Christopher Faulete6c3b692015-09-02 17:15:16 +0200616 return 0;
617
618 error:
619 if (conf->name)
620 free(conf->name);
621 free(conf);
622 return -1;
623}
624
625/* Declare the filter parser for "trace" keyword */
626static struct flt_kw_list flt_kws = { "TRACE", { }, {
Thierry Fournier3610c392016-04-13 18:27:51 +0200627 { "trace", parse_trace_flt, NULL },
628 { NULL, NULL, NULL },
Christopher Faulete6c3b692015-09-02 17:15:16 +0200629 }
630};
631
Willy Tarreau0108d902018-11-25 19:14:37 +0100632INITCALL1(STG_REGISTER, flt_register_keywords, &flt_kws);