blob: 76081b2d56c6ac2481033e4ecb195d14ce00e90b [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
217/**************************************************************************
218 * Hooks to handle channels activity
219 *************************************************************************/
220/* Called when analyze starts for a given channel */
221static int
222trace_chn_start_analyze(struct stream *s, struct filter *filter,
223 struct channel *chn)
224{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100225 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200226
227 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s)",
228 __FUNCTION__,
229 channel_label(chn), proxy_mode(s), stream_pos(s));
Christopher Faulet3a394fa2016-05-11 17:13:39 +0200230 filter->pre_analyzers |= (AN_REQ_ALL | AN_RES_ALL);
231 filter->post_analyzers |= (AN_REQ_ALL | AN_RES_ALL);
Christopher Fauletfcd99f82016-10-31 11:27:21 +0100232 register_data_filter(s, chn, filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200233 return 1;
234}
235
236/* Called before a processing happens on a given channel */
237static int
238trace_chn_analyze(struct stream *s, struct filter *filter,
239 struct channel *chn, unsigned an_bit)
240{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100241 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200242 char *ana;
243
244 switch (an_bit) {
245 case AN_REQ_INSPECT_FE:
246 ana = "AN_REQ_INSPECT_FE";
247 break;
248 case AN_REQ_WAIT_HTTP:
249 ana = "AN_REQ_WAIT_HTTP";
250 break;
251 case AN_REQ_HTTP_BODY:
252 ana = "AN_REQ_HTTP_BODY";
253 break;
254 case AN_REQ_HTTP_PROCESS_FE:
255 ana = "AN_REQ_HTTP_PROCESS_FE";
256 break;
257 case AN_REQ_SWITCHING_RULES:
258 ana = "AN_REQ_SWITCHING_RULES";
259 break;
260 case AN_REQ_INSPECT_BE:
261 ana = "AN_REQ_INSPECT_BE";
262 break;
263 case AN_REQ_HTTP_PROCESS_BE:
264 ana = "AN_REQ_HTTP_PROCESS_BE";
265 break;
266 case AN_REQ_SRV_RULES:
267 ana = "AN_REQ_SRV_RULES";
268 break;
269 case AN_REQ_HTTP_INNER:
270 ana = "AN_REQ_HTTP_INNER";
271 break;
272 case AN_REQ_HTTP_TARPIT:
273 ana = "AN_REQ_HTTP_TARPIT";
274 break;
275 case AN_REQ_STICKING_RULES:
276 ana = "AN_REQ_STICKING_RULES";
277 break;
278 case AN_REQ_PRST_RDP_COOKIE:
279 ana = "AN_REQ_PRST_RDP_COOKIE";
280 break;
281 case AN_REQ_HTTP_XFER_BODY:
282 ana = "AN_REQ_HTTP_XFER_BODY";
283 break;
Christopher Faulete6c3b692015-09-02 17:15:16 +0200284 case AN_RES_INSPECT:
285 ana = "AN_RES_INSPECT";
286 break;
287 case AN_RES_WAIT_HTTP:
288 ana = "AN_RES_WAIT_HTTP";
289 break;
290 case AN_RES_HTTP_PROCESS_FE: // AN_RES_HTTP_PROCESS_BE
291 ana = "AN_RES_HTTP_PROCESS_FE/BE";
292 break;
293 case AN_RES_STORE_RULES:
294 ana = "AN_RES_STORE_RULES";
295 break;
Christopher Faulete6c3b692015-09-02 17:15:16 +0200296 case AN_RES_HTTP_XFER_BODY:
297 ana = "AN_RES_HTTP_XFER_BODY";
298 break;
Christopher Faulete6c3b692015-09-02 17:15:16 +0200299 default:
300 ana = "unknown";
301 }
302
Christopher Faulet3a394fa2016-05-11 17:13:39 +0200303 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s) - "
304 "analyzer=%s - step=%s",
Christopher Faulete6c3b692015-09-02 17:15:16 +0200305 __FUNCTION__,
306 channel_label(chn), proxy_mode(s), stream_pos(s),
Christopher Faulet3a394fa2016-05-11 17:13:39 +0200307 ana, ((chn->analysers & an_bit) ? "PRE" : "POST"));
Christopher Faulete6c3b692015-09-02 17:15:16 +0200308 return 1;
309}
310
311/* Called when analyze ends for a given channel */
312static int
313trace_chn_end_analyze(struct stream *s, struct filter *filter,
314 struct channel *chn)
315{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100316 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200317
318 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s)",
319 __FUNCTION__,
320 channel_label(chn), proxy_mode(s), stream_pos(s));
321 return 1;
322}
323
324/**************************************************************************
325 * Hooks to filter HTTP messages
326 *************************************************************************/
327static int
Christopher Faulet1339d742016-05-11 16:48:33 +0200328trace_http_headers(struct stream *s, struct filter *filter,
329 struct http_msg *msg)
330{
331 struct trace_config *conf = FLT_CONF(filter);
332 struct hdr_idx *hdr_idx;
333 char *cur_hdr;
334 int cur_idx;
335
336 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s)",
337 __FUNCTION__,
338 channel_label(msg->chn), proxy_mode(s), stream_pos(s));
339
340 STRM_TRACE(conf, s, "\t%.*s", MIN(msg->sl.rq.l, 74), msg->chn->buf->p);
341 hdr_idx = &s->txn->hdr_idx;
342 cur_idx = hdr_idx_first_idx(hdr_idx);
343 cur_hdr = msg->chn->buf->p + hdr_idx_first_pos(hdr_idx);
344 while (cur_idx) {
345 STRM_TRACE(conf, s, "\t%.*s",
346 MIN(hdr_idx->v[cur_idx].len, 74), cur_hdr);
347 cur_hdr += hdr_idx->v[cur_idx].len + hdr_idx->v[cur_idx].cr + 1;
348 cur_idx = hdr_idx->v[cur_idx].next;
349 }
Christopher Faulet1339d742016-05-11 16:48:33 +0200350 return 1;
351}
352
353static int
Christopher Faulete6c3b692015-09-02 17:15:16 +0200354trace_http_data(struct stream *s, struct filter *filter,
355 struct http_msg *msg)
356{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100357 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200358 int avail = MIN(msg->chunk_len + msg->next, msg->chn->buf->i) - FLT_NXT(filter, msg->chn);
359 int ret = avail;
360
361 if (ret && conf->rand_parsing)
362 ret = random() % (ret+1);
363
364 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s) - "
365 "chunk_len=%llu - next=%u - fwd=%u - avail=%d - consume=%d",
366 __FUNCTION__,
367 channel_label(msg->chn), proxy_mode(s), stream_pos(s),
368 msg->chunk_len, FLT_NXT(filter, msg->chn),
369 FLT_FWD(filter, msg->chn), avail, ret);
370 if (ret != avail)
371 task_wakeup(s->task, TASK_WOKEN_MSG);
372 return ret;
373}
374
375static int
376trace_http_chunk_trailers(struct stream *s, struct filter *filter,
377 struct http_msg *msg)
378{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100379 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200380
381 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s)",
382 __FUNCTION__,
383 channel_label(msg->chn), proxy_mode(s), stream_pos(s));
384 return 1;
385}
386
387static int
388trace_http_end(struct stream *s, struct filter *filter,
389 struct http_msg *msg)
390{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100391 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200392
393 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s)",
394 __FUNCTION__,
395 channel_label(msg->chn), proxy_mode(s), stream_pos(s));
396 return 1;
397}
398
399static void
400trace_http_reset(struct stream *s, struct filter *filter,
401 struct http_msg *msg)
402{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100403 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200404
405 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s)",
406 __FUNCTION__,
407 channel_label(msg->chn), proxy_mode(s), stream_pos(s));
408}
409
410static void
411trace_http_reply(struct stream *s, struct filter *filter, short status,
412 const struct chunk *msg)
413{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100414 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200415
416 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s)",
417 __FUNCTION__, "-", proxy_mode(s), stream_pos(s));
418}
419
420static int
421trace_http_forward_data(struct stream *s, struct filter *filter,
422 struct http_msg *msg, unsigned int len)
423{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100424 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200425 int ret = len;
426
427 if (ret && conf->rand_forwarding)
428 ret = random() % (ret+1);
429
430 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s) - "
431 "len=%u - nxt=%u - fwd=%u - forward=%d",
432 __FUNCTION__,
433 channel_label(msg->chn), proxy_mode(s), stream_pos(s), len,
434 FLT_NXT(filter, msg->chn), FLT_FWD(filter, msg->chn), ret);
435
Christopher Fauletfcd99f82016-10-31 11:27:21 +0100436 if (conf->hexdump) {
437 b_adv(msg->chn->buf, FLT_FWD(filter, msg->chn));
438 trace_hexdump(msg->chn->buf, ret);
439 b_rew(msg->chn->buf, FLT_FWD(filter, msg->chn));
440 }
441
Christopher Faulete6c3b692015-09-02 17:15:16 +0200442 if ((ret != len) ||
443 (FLT_NXT(filter, msg->chn) != FLT_FWD(filter, msg->chn) + ret))
444 task_wakeup(s->task, TASK_WOKEN_MSG);
445 return ret;
446}
447
448/**************************************************************************
449 * Hooks to filter TCP data
450 *************************************************************************/
451static int
452trace_tcp_data(struct stream *s, struct filter *filter, struct channel *chn)
453{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100454 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200455 int avail = chn->buf->i - FLT_NXT(filter, chn);
456 int ret = avail;
457
458 if (ret && conf->rand_parsing)
459 ret = random() % (ret+1);
460
461 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s) - next=%u - avail=%u - consume=%d",
462 __FUNCTION__,
463 channel_label(chn), proxy_mode(s), stream_pos(s),
464 FLT_NXT(filter, chn), avail, ret);
465
466 if (ret != avail)
467 task_wakeup(s->task, TASK_WOKEN_MSG);
468 return ret;
469}
470
471static int
472trace_tcp_forward_data(struct stream *s, struct filter *filter, struct channel *chn,
473 unsigned int len)
474{
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100475 struct trace_config *conf = FLT_CONF(filter);
Christopher Faulete6c3b692015-09-02 17:15:16 +0200476 int ret = len;
477
478 if (ret && conf->rand_forwarding)
479 ret = random() % (ret+1);
480
481 STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s) - len=%u - fwd=%u - forward=%d",
482 __FUNCTION__,
483 channel_label(chn), proxy_mode(s), stream_pos(s), len,
484 FLT_FWD(filter, chn), ret);
485
Christopher Fauletfcd99f82016-10-31 11:27:21 +0100486 if (conf->hexdump) {
487 b_adv(chn->buf, FLT_FWD(filter, chn));
488 trace_hexdump(chn->buf, ret);
489 b_rew(chn->buf, FLT_FWD(filter, chn));
490 }
491
Christopher Faulete6c3b692015-09-02 17:15:16 +0200492 if (ret != len)
493 task_wakeup(s->task, TASK_WOKEN_MSG);
494 return ret;
495}
496
497/********************************************************************
498 * Functions that manage the filter initialization
499 ********************************************************************/
500struct flt_ops trace_ops = {
501 /* Manage trace filter, called for each filter declaration */
502 .init = trace_init,
503 .deinit = trace_deinit,
504 .check = trace_check,
505
506 /* Handle start/stop of streams */
Christopher Faulet31ed32d2016-06-21 11:42:37 +0200507 .attach = trace_attach,
508 .detach = trace_detach,
509 .stream_start = trace_stream_start,
510 .stream_set_backend = trace_stream_set_backend,
511 .stream_stop = trace_stream_stop,
Christopher Faulete6c3b692015-09-02 17:15:16 +0200512
513 /* Handle channels activity */
514 .channel_start_analyze = trace_chn_start_analyze,
Christopher Faulet3a394fa2016-05-11 17:13:39 +0200515 .channel_pre_analyze = trace_chn_analyze,
516 .channel_post_analyze = trace_chn_analyze,
Christopher Faulete6c3b692015-09-02 17:15:16 +0200517 .channel_end_analyze = trace_chn_end_analyze,
518
519 /* Filter HTTP requests and responses */
Christopher Faulet1339d742016-05-11 16:48:33 +0200520 .http_headers = trace_http_headers,
Christopher Faulete6c3b692015-09-02 17:15:16 +0200521 .http_data = trace_http_data,
522 .http_chunk_trailers = trace_http_chunk_trailers,
523 .http_end = trace_http_end,
524
525 .http_reset = trace_http_reset,
526 .http_reply = trace_http_reply,
527 .http_forward_data = trace_http_forward_data,
528
529 /* Filter TCP data */
530 .tcp_data = trace_tcp_data,
531 .tcp_forward_data = trace_tcp_forward_data,
532};
533
534/* Return -1 on error, else 0 */
535static int
536parse_trace_flt(char **args, int *cur_arg, struct proxy *px,
Thierry Fournier3610c392016-04-13 18:27:51 +0200537 struct flt_conf *fconf, char **err, void *private)
Christopher Faulete6c3b692015-09-02 17:15:16 +0200538{
539 struct trace_config *conf;
540 int pos = *cur_arg;
541
542 conf = calloc(1, sizeof(*conf));
543 if (!conf) {
544 memprintf(err, "%s: out of memory", args[*cur_arg]);
545 return -1;
546 }
547 conf->proxy = px;
548
549 if (!strcmp(args[pos], "trace")) {
550 pos++;
551
552 while (*args[pos]) {
553 if (!strcmp(args[pos], "name")) {
554 if (!*args[pos + 1]) {
555 memprintf(err, "'%s' : '%s' option without value",
556 args[*cur_arg], args[pos]);
557 goto error;
558 }
559 conf->name = strdup(args[pos + 1]);
560 if (!conf->name) {
561 memprintf(err, "%s: out of memory", args[*cur_arg]);
562 goto error;
563 }
564 pos++;
565 }
566 else if (!strcmp(args[pos], "random-parsing"))
567 conf->rand_parsing = 1;
568 else if (!strcmp(args[pos], "random-forwarding"))
569 conf->rand_forwarding = 1;
Christopher Fauletfcd99f82016-10-31 11:27:21 +0100570 else if (!strcmp(args[pos], "hexdump"))
571 conf->hexdump = 1;
Christopher Faulete6c3b692015-09-02 17:15:16 +0200572 else
573 break;
574 pos++;
575 }
576 *cur_arg = pos;
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100577 fconf->ops = &trace_ops;
Christopher Faulete6c3b692015-09-02 17:15:16 +0200578 }
579
Christopher Faulet443ea1a2016-02-04 13:40:26 +0100580 fconf->conf = conf;
Christopher Faulete6c3b692015-09-02 17:15:16 +0200581 return 0;
582
583 error:
584 if (conf->name)
585 free(conf->name);
586 free(conf);
587 return -1;
588}
589
590/* Declare the filter parser for "trace" keyword */
591static struct flt_kw_list flt_kws = { "TRACE", { }, {
Thierry Fournier3610c392016-04-13 18:27:51 +0200592 { "trace", parse_trace_flt, NULL },
593 { NULL, NULL, NULL },
Christopher Faulete6c3b692015-09-02 17:15:16 +0200594 }
595};
596
597__attribute__((constructor))
598static void
599__flt_trace_init(void)
600{
601 flt_register_keywords(&flt_kws);
602}