blob: 96ce2ac58e51bc9bdc5001d9956051c9b4478da7 [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>
18
19#include <types/channel.h>
20#include <types/filters.h>
21#include <types/global.h>
22#include <types/proxy.h>
23#include <types/stream.h>
24
25#include <proto/filters.h>
Christopher Faulet1339d742016-05-11 16:48:33 +020026#include <proto/hdr_idx.h>
Christopher Faulete6c3b692015-09-02 17:15:16 +020027#include <proto/log.h>
28#include <proto/stream.h>
29
30struct flt_ops trace_ops;
31
32struct trace_config {
33 struct proxy *proxy;
34 char *name;
35 int rand_parsing;
36 int rand_forwarding;
Christopher Fauletfcd99f82016-10-31 11:27:21 +010037 int hexdump;
Christopher Faulete6c3b692015-09-02 17:15:16 +020038};
39
40#define TRACE(conf, fmt, ...) \
41 fprintf(stderr, "%d.%06d [%-20s] " fmt "\n", \
42 (int)now.tv_sec, (int)now.tv_usec, (conf)->name, \
43 ##__VA_ARGS__)
44
Christopher Fauletfcd99f82016-10-31 11:27:21 +010045#define STRM_TRACE(conf, strm, fmt, ...) \
46 fprintf(stderr, "%d.%06d [%-20s] [strm %p(%x) 0x%08x 0x%08x] " fmt "\n", \
47 (int)now.tv_sec, (int)now.tv_usec, (conf)->name, \
48 strm, (strm ? ((struct stream *)strm)->uniq_id : ~0U), \
49 (strm ? strm->req.analysers : 0), (strm ? strm->res.analysers : 0), \
Christopher Faulete6c3b692015-09-02 17:15:16 +020050 ##__VA_ARGS__)
51
52
53static const char *
54channel_label(const struct channel *chn)
55{
56 return (chn->flags & CF_ISRESP) ? "RESPONSE" : "REQUEST";
57}
58
59static const char *
60proxy_mode(const struct stream *s)
61{
62 struct proxy *px = (s->flags & SF_BE_ASSIGNED ? s->be : strm_fe(s));
63
64 return (px->mode == PR_MODE_HTTP) ? "HTTP" : "TCP";
65}
66
67static const char *
68stream_pos(const struct stream *s)
69{
70 return (s->flags & SF_BE_ASSIGNED) ? "backend" : "frontend";
71}
72
Christopher Faulet31ed32d2016-06-21 11:42:37 +020073static const char *
74filter_type(const struct filter *f)
75{
76 return (f->flags & FLT_FL_IS_BACKEND_FILTER) ? "backend" : "frontend";
77}
78
Christopher Fauletfcd99f82016-10-31 11:27:21 +010079static void
80trace_hexdump(struct buffer *buf, int len)
81{
82 unsigned char p[len];
83 int block1, block2, i, j, padding;
84
85 block1 = len;
86 if (block1 > bi_contig_data(buf))
87 block1 = bi_contig_data(buf);
88 block2 = len - block1;
89
90 memcpy(p, buf->p, block1);
91 memcpy(p+block1, buf->data, block2);
92
93 padding = ((len % 16) ? (16 - len % 16) : 0);
94 for (i = 0; i < len + padding; i++) {
95 if (!(i % 16))
96 fprintf(stderr, "\t0x%06x: ", i);
97 else if (!(i % 8))
98 fprintf(stderr, " ");
99
100 if (i < len)
101 fprintf(stderr, "%02x ", p[i]);
102 else
103 fprintf(stderr, " ");
104
105 /* print ASCII dump */
106 if (i % 16 == 15) {
107 fprintf(stderr, " |");
108 for(j = i - 15; j <= i && j < len; j++)
109 fprintf(stderr, "%c", (isprint(p[j]) ? p[j] : '.'));
110 fprintf(stderr, "|\n");
111 }
112 }
113}
114
Christopher Faulete6c3b692015-09-02 17:15:16 +0200115/***************************************************************************
116 * Hooks that manage the filter lifecycle (init/check/deinit)
117 **************************************************************************/
118/* Initialize the filter. Returns -1 on error, else 0. */
119static int
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100120trace_init(struct proxy *px, struct flt_conf *fconf)
Christopher Faulete6c3b692015-09-02 17:15:16 +0200121{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100122 struct trace_config *conf = fconf->conf;
Christopher Faulete6c3b692015-09-02 17:15:16 +0200123
124 if (conf->name)
125 memprintf(&conf->name, "%s/%s", conf->name, px->id);
126 else
127 memprintf(&conf->name, "TRACE/%s", px->id);
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100128 fconf->conf = conf;
Christopher Fauletfcd99f82016-10-31 11:27:21 +0100129 TRACE(conf, "filter initialized [read random=%s - fwd random=%s - hexdump=%s]",
Christopher Faulete6c3b692015-09-02 17:15:16 +0200130 (conf->rand_parsing ? "true" : "false"),
Christopher Fauletfcd99f82016-10-31 11:27:21 +0100131 (conf->rand_forwarding ? "true" : "false"),
132 (conf->hexdump ? "true" : "false"));
Christopher Faulete6c3b692015-09-02 17:15:16 +0200133 return 0;
134}
135
136/* Free ressources allocated by the trace filter. */
137static void
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100138trace_deinit(struct proxy *px, struct flt_conf *fconf)
Christopher Faulete6c3b692015-09-02 17:15:16 +0200139{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100140 struct trace_config *conf = fconf->conf;
Christopher Faulete6c3b692015-09-02 17:15:16 +0200141
142 if (conf) {
143 TRACE(conf, "filter deinitialized");
144 free(conf->name);
145 free(conf);
146 }
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100147 fconf->conf = NULL;
Christopher Faulete6c3b692015-09-02 17:15:16 +0200148}
149
150/* Check configuration of a trace filter for a specified proxy.
151 * Return 1 on error, else 0. */
152static int
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100153trace_check(struct proxy *px, struct flt_conf *fconf)
Christopher Faulete6c3b692015-09-02 17:15:16 +0200154{
155 return 0;
156}
157
158/**************************************************************************
159 * Hooks to handle start/stop of streams
160 *************************************************************************/
Christopher Faulet31ed32d2016-06-21 11:42:37 +0200161/* Called when a filter instance is created and attach to a stream */
162static int
163trace_attach(struct stream *s, struct filter *filter)
164{
165 struct trace_config *conf = FLT_CONF(filter);
166
167 STRM_TRACE(conf, s, "%-25s: filter-type=%s",
168 __FUNCTION__, filter_type(filter));
169 return 1;
170}
171
172/* Called when a filter instance is detach from a stream, just before its
173 * destruction */
174static void
175trace_detach(struct stream *s, struct filter *filter)
176{
177 struct trace_config *conf = FLT_CONF(filter);
178
179 STRM_TRACE(conf, s, "%-25s: filter-type=%s",
180 __FUNCTION__, filter_type(filter));
181}
182
Christopher Faulete6c3b692015-09-02 17:15:16 +0200183/* Called when a stream is created */
184static int
185trace_stream_start(struct stream *s, struct filter *filter)
186{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100187 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200188
189 STRM_TRACE(conf, s, "%-25s",
190 __FUNCTION__);
191 return 0;
192}
193
Christopher Faulet31ed32d2016-06-21 11:42:37 +0200194
195/* Called when a backend is set for a stream */
196static int
197trace_stream_set_backend(struct stream *s, struct filter *filter,
198 struct proxy *be)
199{
200 struct trace_config *conf = FLT_CONF(filter);
201
202 STRM_TRACE(conf, s, "%-25s: backend=%s",
203 __FUNCTION__, be->id);
204 return 0;
205}
206
Christopher Faulete6c3b692015-09-02 17:15:16 +0200207/* Called when a stream is destroyed */
208static void
209trace_stream_stop(struct stream *s, struct filter *filter)
210{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100211 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200212
213 STRM_TRACE(conf, s, "%-25s",
214 __FUNCTION__);
215}
216
Christopher Fauleta00d8172016-11-10 14:58:05 +0100217/* Called when the stream is woken up because of an expired timer */
218static void
219trace_check_timeouts(struct stream *s, struct filter *filter)
220{
221 struct trace_config *conf = FLT_CONF(filter);
222
223 STRM_TRACE(conf, s, "%-25s",
224 __FUNCTION__);
225}
226
Christopher Faulete6c3b692015-09-02 17:15:16 +0200227/**************************************************************************
228 * Hooks to handle channels activity
229 *************************************************************************/
230/* Called when analyze starts for a given channel */
231static int
232trace_chn_start_analyze(struct stream *s, struct filter *filter,
233 struct channel *chn)
234{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100235 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200236
237 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s)",
238 __FUNCTION__,
239 channel_label(chn), proxy_mode(s), stream_pos(s));
Christopher Faulet3a394fa2016-05-11 17:13:39 +0200240 filter->pre_analyzers |= (AN_REQ_ALL | AN_RES_ALL);
241 filter->post_analyzers |= (AN_REQ_ALL | AN_RES_ALL);
Christopher Fauletfcd99f82016-10-31 11:27:21 +0100242 register_data_filter(s, chn, filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200243 return 1;
244}
245
246/* Called before a processing happens on a given channel */
247static int
248trace_chn_analyze(struct stream *s, struct filter *filter,
249 struct channel *chn, unsigned an_bit)
250{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100251 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200252 char *ana;
253
254 switch (an_bit) {
255 case AN_REQ_INSPECT_FE:
256 ana = "AN_REQ_INSPECT_FE";
257 break;
258 case AN_REQ_WAIT_HTTP:
259 ana = "AN_REQ_WAIT_HTTP";
260 break;
261 case AN_REQ_HTTP_BODY:
262 ana = "AN_REQ_HTTP_BODY";
263 break;
264 case AN_REQ_HTTP_PROCESS_FE:
265 ana = "AN_REQ_HTTP_PROCESS_FE";
266 break;
267 case AN_REQ_SWITCHING_RULES:
268 ana = "AN_REQ_SWITCHING_RULES";
269 break;
270 case AN_REQ_INSPECT_BE:
271 ana = "AN_REQ_INSPECT_BE";
272 break;
273 case AN_REQ_HTTP_PROCESS_BE:
274 ana = "AN_REQ_HTTP_PROCESS_BE";
275 break;
276 case AN_REQ_SRV_RULES:
277 ana = "AN_REQ_SRV_RULES";
278 break;
279 case AN_REQ_HTTP_INNER:
280 ana = "AN_REQ_HTTP_INNER";
281 break;
282 case AN_REQ_HTTP_TARPIT:
283 ana = "AN_REQ_HTTP_TARPIT";
284 break;
285 case AN_REQ_STICKING_RULES:
286 ana = "AN_REQ_STICKING_RULES";
287 break;
288 case AN_REQ_PRST_RDP_COOKIE:
289 ana = "AN_REQ_PRST_RDP_COOKIE";
290 break;
291 case AN_REQ_HTTP_XFER_BODY:
292 ana = "AN_REQ_HTTP_XFER_BODY";
293 break;
Christopher Faulete6c3b692015-09-02 17:15:16 +0200294 case AN_RES_INSPECT:
295 ana = "AN_RES_INSPECT";
296 break;
297 case AN_RES_WAIT_HTTP:
298 ana = "AN_RES_WAIT_HTTP";
299 break;
300 case AN_RES_HTTP_PROCESS_FE: // AN_RES_HTTP_PROCESS_BE
301 ana = "AN_RES_HTTP_PROCESS_FE/BE";
302 break;
303 case AN_RES_STORE_RULES:
304 ana = "AN_RES_STORE_RULES";
305 break;
Christopher Faulete6c3b692015-09-02 17:15:16 +0200306 case AN_RES_HTTP_XFER_BODY:
307 ana = "AN_RES_HTTP_XFER_BODY";
308 break;
Christopher Faulete6c3b692015-09-02 17:15:16 +0200309 default:
310 ana = "unknown";
311 }
312
Christopher Faulet3a394fa2016-05-11 17:13:39 +0200313 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s) - "
314 "analyzer=%s - step=%s",
Christopher Faulete6c3b692015-09-02 17:15:16 +0200315 __FUNCTION__,
316 channel_label(chn), proxy_mode(s), stream_pos(s),
Christopher Faulet3a394fa2016-05-11 17:13:39 +0200317 ana, ((chn->analysers & an_bit) ? "PRE" : "POST"));
Christopher Faulete6c3b692015-09-02 17:15:16 +0200318 return 1;
319}
320
321/* Called when analyze ends for a given channel */
322static int
323trace_chn_end_analyze(struct stream *s, struct filter *filter,
324 struct channel *chn)
325{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100326 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200327
328 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s)",
329 __FUNCTION__,
330 channel_label(chn), proxy_mode(s), stream_pos(s));
331 return 1;
332}
333
334/**************************************************************************
335 * Hooks to filter HTTP messages
336 *************************************************************************/
337static int
Christopher Faulet1339d742016-05-11 16:48:33 +0200338trace_http_headers(struct stream *s, struct filter *filter,
339 struct http_msg *msg)
340{
341 struct trace_config *conf = FLT_CONF(filter);
342 struct hdr_idx *hdr_idx;
343 char *cur_hdr;
344 int cur_idx;
345
346 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s)",
347 __FUNCTION__,
348 channel_label(msg->chn), proxy_mode(s), stream_pos(s));
349
350 STRM_TRACE(conf, s, "\t%.*s", MIN(msg->sl.rq.l, 74), msg->chn->buf->p);
351 hdr_idx = &s->txn->hdr_idx;
352 cur_idx = hdr_idx_first_idx(hdr_idx);
353 cur_hdr = msg->chn->buf->p + hdr_idx_first_pos(hdr_idx);
354 while (cur_idx) {
355 STRM_TRACE(conf, s, "\t%.*s",
356 MIN(hdr_idx->v[cur_idx].len, 74), cur_hdr);
357 cur_hdr += hdr_idx->v[cur_idx].len + hdr_idx->v[cur_idx].cr + 1;
358 cur_idx = hdr_idx->v[cur_idx].next;
359 }
Christopher Faulet1339d742016-05-11 16:48:33 +0200360 return 1;
361}
362
363static int
Christopher Faulete6c3b692015-09-02 17:15:16 +0200364trace_http_data(struct stream *s, struct filter *filter,
365 struct http_msg *msg)
366{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100367 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200368 int avail = MIN(msg->chunk_len + msg->next, msg->chn->buf->i) - FLT_NXT(filter, msg->chn);
369 int ret = avail;
370
371 if (ret && conf->rand_parsing)
372 ret = random() % (ret+1);
373
374 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s) - "
375 "chunk_len=%llu - next=%u - fwd=%u - avail=%d - consume=%d",
376 __FUNCTION__,
377 channel_label(msg->chn), proxy_mode(s), stream_pos(s),
378 msg->chunk_len, FLT_NXT(filter, msg->chn),
379 FLT_FWD(filter, msg->chn), avail, ret);
380 if (ret != avail)
381 task_wakeup(s->task, TASK_WOKEN_MSG);
382 return ret;
383}
384
385static int
386trace_http_chunk_trailers(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);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200390
391 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s)",
392 __FUNCTION__,
393 channel_label(msg->chn), proxy_mode(s), stream_pos(s));
394 return 1;
395}
396
397static int
398trace_http_end(struct stream *s, struct filter *filter,
399 struct http_msg *msg)
400{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100401 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200402
403 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s)",
404 __FUNCTION__,
405 channel_label(msg->chn), proxy_mode(s), stream_pos(s));
406 return 1;
407}
408
409static void
410trace_http_reset(struct stream *s, struct filter *filter,
411 struct http_msg *msg)
412{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100413 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200414
415 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s)",
416 __FUNCTION__,
417 channel_label(msg->chn), proxy_mode(s), stream_pos(s));
418}
419
420static void
421trace_http_reply(struct stream *s, struct filter *filter, short status,
422 const struct chunk *msg)
423{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100424 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200425
426 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s)",
427 __FUNCTION__, "-", proxy_mode(s), stream_pos(s));
428}
429
430static int
431trace_http_forward_data(struct stream *s, struct filter *filter,
432 struct http_msg *msg, unsigned int len)
433{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100434 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200435 int ret = len;
436
437 if (ret && conf->rand_forwarding)
438 ret = random() % (ret+1);
439
440 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s) - "
441 "len=%u - nxt=%u - fwd=%u - forward=%d",
442 __FUNCTION__,
443 channel_label(msg->chn), proxy_mode(s), stream_pos(s), len,
444 FLT_NXT(filter, msg->chn), FLT_FWD(filter, msg->chn), ret);
445
Christopher Fauletfcd99f82016-10-31 11:27:21 +0100446 if (conf->hexdump) {
447 b_adv(msg->chn->buf, FLT_FWD(filter, msg->chn));
448 trace_hexdump(msg->chn->buf, ret);
449 b_rew(msg->chn->buf, FLT_FWD(filter, msg->chn));
450 }
451
Christopher Faulete6c3b692015-09-02 17:15:16 +0200452 if ((ret != len) ||
453 (FLT_NXT(filter, msg->chn) != FLT_FWD(filter, msg->chn) + ret))
454 task_wakeup(s->task, TASK_WOKEN_MSG);
455 return ret;
456}
457
458/**************************************************************************
459 * Hooks to filter TCP data
460 *************************************************************************/
461static int
462trace_tcp_data(struct stream *s, struct filter *filter, struct channel *chn)
463{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100464 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200465 int avail = chn->buf->i - FLT_NXT(filter, chn);
466 int ret = avail;
467
468 if (ret && conf->rand_parsing)
469 ret = random() % (ret+1);
470
471 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s) - next=%u - avail=%u - consume=%d",
472 __FUNCTION__,
473 channel_label(chn), proxy_mode(s), stream_pos(s),
474 FLT_NXT(filter, chn), avail, ret);
475
476 if (ret != avail)
477 task_wakeup(s->task, TASK_WOKEN_MSG);
478 return ret;
479}
480
481static int
482trace_tcp_forward_data(struct stream *s, struct filter *filter, struct channel *chn,
483 unsigned int len)
484{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100485 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200486 int ret = len;
487
488 if (ret && conf->rand_forwarding)
489 ret = random() % (ret+1);
490
491 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s) - len=%u - fwd=%u - forward=%d",
492 __FUNCTION__,
493 channel_label(chn), proxy_mode(s), stream_pos(s), len,
494 FLT_FWD(filter, chn), ret);
495
Christopher Fauletfcd99f82016-10-31 11:27:21 +0100496 if (conf->hexdump) {
497 b_adv(chn->buf, FLT_FWD(filter, chn));
498 trace_hexdump(chn->buf, ret);
499 b_rew(chn->buf, FLT_FWD(filter, chn));
500 }
501
Christopher Faulete6c3b692015-09-02 17:15:16 +0200502 if (ret != len)
503 task_wakeup(s->task, TASK_WOKEN_MSG);
504 return ret;
505}
506
507/********************************************************************
508 * Functions that manage the filter initialization
509 ********************************************************************/
510struct flt_ops trace_ops = {
511 /* Manage trace filter, called for each filter declaration */
512 .init = trace_init,
513 .deinit = trace_deinit,
514 .check = trace_check,
515
516 /* Handle start/stop of streams */
Christopher Faulet31ed32d2016-06-21 11:42:37 +0200517 .attach = trace_attach,
518 .detach = trace_detach,
519 .stream_start = trace_stream_start,
520 .stream_set_backend = trace_stream_set_backend,
521 .stream_stop = trace_stream_stop,
Christopher Fauleta00d8172016-11-10 14:58:05 +0100522 .check_timeouts = trace_check_timeouts,
Christopher Faulete6c3b692015-09-02 17:15:16 +0200523
524 /* Handle channels activity */
525 .channel_start_analyze = trace_chn_start_analyze,
Christopher Faulet3a394fa2016-05-11 17:13:39 +0200526 .channel_pre_analyze = trace_chn_analyze,
527 .channel_post_analyze = trace_chn_analyze,
Christopher Faulete6c3b692015-09-02 17:15:16 +0200528 .channel_end_analyze = trace_chn_end_analyze,
529
530 /* Filter HTTP requests and responses */
Christopher Faulet1339d742016-05-11 16:48:33 +0200531 .http_headers = trace_http_headers,
Christopher Faulete6c3b692015-09-02 17:15:16 +0200532 .http_data = trace_http_data,
533 .http_chunk_trailers = trace_http_chunk_trailers,
534 .http_end = trace_http_end,
535
536 .http_reset = trace_http_reset,
537 .http_reply = trace_http_reply,
538 .http_forward_data = trace_http_forward_data,
539
540 /* Filter TCP data */
541 .tcp_data = trace_tcp_data,
542 .tcp_forward_data = trace_tcp_forward_data,
543};
544
545/* Return -1 on error, else 0 */
546static int
547parse_trace_flt(char **args, int *cur_arg, struct proxy *px,
Thierry Fournier3610c392016-04-13 18:27:51 +0200548 struct flt_conf *fconf, char **err, void *private)
Christopher Faulete6c3b692015-09-02 17:15:16 +0200549{
550 struct trace_config *conf;
551 int pos = *cur_arg;
552
553 conf = calloc(1, sizeof(*conf));
554 if (!conf) {
555 memprintf(err, "%s: out of memory", args[*cur_arg]);
556 return -1;
557 }
558 conf->proxy = px;
559
560 if (!strcmp(args[pos], "trace")) {
561 pos++;
562
563 while (*args[pos]) {
564 if (!strcmp(args[pos], "name")) {
565 if (!*args[pos + 1]) {
566 memprintf(err, "'%s' : '%s' option without value",
567 args[*cur_arg], args[pos]);
568 goto error;
569 }
570 conf->name = strdup(args[pos + 1]);
571 if (!conf->name) {
572 memprintf(err, "%s: out of memory", args[*cur_arg]);
573 goto error;
574 }
575 pos++;
576 }
577 else if (!strcmp(args[pos], "random-parsing"))
578 conf->rand_parsing = 1;
579 else if (!strcmp(args[pos], "random-forwarding"))
580 conf->rand_forwarding = 1;
Christopher Fauletfcd99f82016-10-31 11:27:21 +0100581 else if (!strcmp(args[pos], "hexdump"))
582 conf->hexdump = 1;
Christopher Faulete6c3b692015-09-02 17:15:16 +0200583 else
584 break;
585 pos++;
586 }
587 *cur_arg = pos;
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100588 fconf->ops = &trace_ops;
Christopher Faulete6c3b692015-09-02 17:15:16 +0200589 }
590
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100591 fconf->conf = conf;
Christopher Faulete6c3b692015-09-02 17:15:16 +0200592 return 0;
593
594 error:
595 if (conf->name)
596 free(conf->name);
597 free(conf);
598 return -1;
599}
600
601/* Declare the filter parser for "trace" keyword */
602static struct flt_kw_list flt_kws = { "TRACE", { }, {
Thierry Fournier3610c392016-04-13 18:27:51 +0200603 { "trace", parse_trace_flt, NULL },
604 { NULL, NULL, NULL },
Christopher Faulete6c3b692015-09-02 17:15:16 +0200605 }
606};
607
608__attribute__((constructor))
609static void
610__flt_trace_init(void)
611{
612 flt_register_keywords(&flt_kws);
613}