blob: fe78c46a45a82a42ae93eaf2aa037b7a5997b031 [file] [log] [blame]
Thierry FOURNIER4834bc72015-06-06 19:29:07 +02001#include <ctype.h>
2
3#include <common/cfgparse.h>
4#include <common/mini-clist.h>
5
6#include <types/vars.h>
7
8#include <proto/arg.h>
9#include <proto/proto_http.h>
10#include <proto/proto_tcp.h>
11#include <proto/sample.h>
12#include <proto/stream.h>
13
14/* This contains a pool of struct vars */
15static struct pool_head *var_pool = NULL;
16
17/* This array contain all the names of all the HAProxy vars.
18 * This permits to identify two variables name with
19 * only one pointer. It permits to not using strdup() for
20 * each variable name used during the runtime.
21 */
22static char **var_names = NULL;
23static int var_names_nb = 0;
24
25/* This array of int contains the system limits per context. */
26static unsigned int var_global_limit = 0;
27static unsigned int var_global_size = 0;
28static unsigned int var_sess_limit = 0;
29static unsigned int var_txn_limit = 0;
30static unsigned int var_reqres_limit = 0;
31
32/* This function adds or remove memory size from the accounting. */
33static void var_accounting_diff(struct vars *vars, struct stream *strm, int size)
34{
35 switch (vars->scope) {
36 case SCOPE_REQ:
37 case SCOPE_RES:
38 strm->vars_reqres.size += size;
39 case SCOPE_TXN:
40 strm->vars_txn.size += size;
41 case SCOPE_SESS:
42 strm->vars_sess.size += size;
43 var_global_size += size;
44 }
45}
46
47/* This function returns 1 if the <size> is available in the var
48 * pool <vars>, otherwise returns 0. If the space is avalaible,
49 * the size is reserved.
50 */
51static int var_accounting_add(struct vars *vars, struct stream *strm, int size)
52{
53 switch (vars->scope) {
54 case SCOPE_REQ:
55 case SCOPE_RES:
56 if (var_reqres_limit && strm->vars_reqres.size + size > var_reqres_limit)
57 return 0;
58 case SCOPE_TXN:
59 if (var_txn_limit && strm->vars_txn.size + size > var_txn_limit)
60 return 0;
61 case SCOPE_SESS:
62 if (var_sess_limit && strm->vars_sess.size + size > var_sess_limit)
63 return 0;
64 if (var_global_limit && var_global_size + size > var_global_limit)
65 return 0;
66 }
67 var_accounting_diff(vars, strm, size);
68 return 1;
69}
70
71/* This function free all the memory used by all the varaibles
72 * in the list.
73 */
74void vars_prune(struct vars *vars, struct stream *strm)
75{
76 struct var *var, *tmp;
77
78 list_for_each_entry_safe(var, tmp, &vars->head, l) {
79 if (var->data.type == SMP_T_STR ||
80 var->data.type == SMP_T_BIN) {
81 free(var->data.data.str.str);
82 var_accounting_diff(vars, strm, -var->data.data.str.len);
83 }
84 else if (var->data.type == SMP_T_METH) {
85 free(var->data.data.meth.str.str);
86 var_accounting_diff(vars, strm, -var->data.data.meth.str.len);
87 }
88 LIST_DEL(&var->l);
89 pool_free2(var_pool, var);
90 var_accounting_diff(vars, strm, -(int)sizeof(struct var));
91 }
92}
93
94/* This function init a list of variabes. */
95void vars_init(struct vars *vars, enum vars_scope scope)
96{
97 LIST_INIT(&vars->head);
98 vars->scope = scope;
99 vars->size = 0;
100}
101
102/* This function declares a new variable name. It returns a pointer
103 * on the string identifying the name. This function assures that
104 * the same name exists only once.
105 *
106 * This function check if the variable name is acceptable.
107 *
108 * The function returns NULL if an error occurs, and <err> is filled.
109 * In this case, the HAProxy must be stopped because the structs are
110 * left inconsistent. Otherwise, it returns the pointer on the global
111 * name.
112 */
113static char *register_name(const char *name, int len, enum vars_scope *scope, char **err)
114{
115 int i;
116 const char *tmp;
117
118 /* Check length. */
119 if (len == 0) {
120 memprintf(err, "Empty variable name cannot be accepted");
121 return NULL;
122 }
123
124 /* Check scope. */
125 if (len > 5 && strncmp(name, "sess.", 5) == 0) {
126 name += 5;
127 len -= 5;
128 *scope = SCOPE_SESS;
129 }
130 else if (len > 4 && strncmp(name, "txn.", 4) == 0) {
131 name += 4;
132 len -= 4;
133 *scope = SCOPE_TXN;
134 }
135 else if (len > 4 && strncmp(name, "req.", 4) == 0) {
136 name += 4;
137 len -= 4;
138 *scope = SCOPE_REQ;
139 }
140 else if (len > 4 && strncmp(name, "res.", 4) == 0) {
141 name += 4;
142 len -= 4;
143 *scope = SCOPE_RES;
144 }
145 else {
146 memprintf(err, "invalid variable name '%s'. A variable name must be start by its scope. "
147 "The scope can be 'sess', 'txn', 'req' or 'res'", name);
148 return NULL;
149 }
150
151 /* Look for existing variable name. */
152 for (i = 0; i < var_names_nb; i++)
153 if (strncmp(var_names[i], name, len) == 0)
154 return var_names[i];
155
156 /* Store variable name. */
157 var_names_nb++;
158 var_names = realloc(var_names, var_names_nb * sizeof(*var_names));
159 if (!var_names) {
160 memprintf(err, "out of memory error");
161 return NULL;
162 }
163 var_names[var_names_nb - 1] = malloc(len + 1);
164 if (!var_names[var_names_nb - 1]) {
165 memprintf(err, "out of memory error");
166 return NULL;
167 }
168 memcpy(var_names[var_names_nb - 1], name, len);
169 var_names[var_names_nb - 1][len] = '\0';
170
171 /* Check variable name syntax. */
172 tmp = var_names[var_names_nb - 1];
173 while (*tmp) {
174 if (!isalnum((int)(unsigned char)*tmp) && *tmp != '_') {
175 memprintf(err, "invalid syntax at char '%s'", tmp);
176 return NULL;
177 }
178 tmp++;
179 }
180
181 /* Return the result. */
182 return var_names[var_names_nb - 1];
183}
184
185/* This function returns an existing variable or returns NULL. */
186static inline struct var *var_get(struct vars *vars, const char *name)
187{
188 struct var *var;
189
190 list_for_each_entry(var, &vars->head, l)
191 if (var->name == name)
192 return var;
193 return NULL;
194}
195
196/* Returns 0 if fails, else returns 1. */
197static int smp_fetch_var(const struct arg *args, struct sample *smp, const char *kw, void *private)
198{
199 const struct var_desc *var_desc = &args[0].data.var;
200 struct var *var;
201 struct vars *vars;
202
203 /* Check the availibity of the variable. */
204 switch (var_desc->scope) {
205 case SCOPE_SESS: vars = &smp->strm->vars_sess; break;
206 case SCOPE_TXN: vars = &smp->strm->vars_txn; break;
207 case SCOPE_REQ:
Thierry FOURNIER0b243fd2015-06-16 23:52:47 +0200208 case SCOPE_RES:
209 default: vars = &smp->strm->vars_reqres; break;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200210 }
211 if (vars->scope != var_desc->scope)
212 return 0;
213 var = var_get(vars, var_desc->name);
214
215 /* check for the variable avalaibility */
216 if (!var)
217 return 0;
218
219 /* Copy sample. */
220 smp->type = var->data.type;
221 smp->flags |= SMP_F_CONST;
222 memcpy(&smp->data, &var->data.data, sizeof(smp->data));
223 return 1;
224}
225
226/* This function search in the <head> a variable with the same
227 * pointer value that the <name>. If the variable doesn't exists,
228 * create it. The function stores a copy of smp> if the variable.
229 * It returns 0 if fails, else returns 1.
230 */
231static int sample_store(struct vars *vars, const char *name, struct stream *strm, struct sample *smp)
232{
233 struct var *var;
234
235 /* Look for existing variable name. */
236 var = var_get(vars, name);
237
238 if (var) {
239 /* free its used memory. */
240 if (var->data.type == SMP_T_STR ||
241 var->data.type == SMP_T_BIN) {
242 free(var->data.data.str.str);
243 var_accounting_diff(vars, strm, -var->data.data.str.len);
244 }
245 else if (var->data.type == SMP_T_METH) {
246 free(var->data.data.meth.str.str);
247 var_accounting_diff(vars, strm, -var->data.data.meth.str.len);
248 }
249 } else {
250
251 /* Check memory avalaible. */
252 if (!var_accounting_add(vars, strm, sizeof(struct var)))
253 return 0;
254
255 /* Create new entry. */
256 var = pool_alloc2(var_pool);
257 if (!var)
258 return 0;
259 LIST_ADDQ(&vars->head, &var->l);
260 var->name = name;
261 }
262
263 /* Set type. */
264 var->data.type = smp->type;
265
266 /* Copy data. If the data needs memory, the function can fail. */
267 switch (var->data.type) {
268 case SMP_T_BOOL:
269 case SMP_T_UINT:
270 case SMP_T_SINT:
271 var->data.data.sint = smp->data.sint;
272 break;
273 case SMP_T_IPV4:
274 var->data.data.ipv4 = smp->data.ipv4;
275 break;
276 case SMP_T_IPV6:
277 var->data.data.ipv6 = smp->data.ipv6;
278 break;
279 case SMP_T_STR:
280 case SMP_T_BIN:
281 if (!var_accounting_add(vars, strm, smp->data.str.len)) {
282 var->data.type = SMP_T_BOOL; /* This type doesn't use additional memory. */
283 return 0;
284 }
285 var->data.data.str.str = malloc(smp->data.str.len);
286 if (!var->data.data.str.str) {
287 var_accounting_diff(vars, strm, -smp->data.str.len);
288 var->data.type = SMP_T_BOOL; /* This type doesn't use additional memory. */
289 return 0;
290 }
291 var->data.data.str.len = smp->data.str.len;
292 memcpy(var->data.data.str.str, smp->data.str.str, var->data.data.str.len);
293 break;
294 case SMP_T_METH:
295 if (!var_accounting_add(vars, strm, smp->data.meth.str.len)) {
296 var->data.type = SMP_T_BOOL; /* This type doesn't use additional memory. */
297 return 0;
298 }
299 var->data.data.meth.str.str = malloc(smp->data.meth.str.len);
300 if (!var->data.data.meth.str.str) {
301 var_accounting_diff(vars, strm, -smp->data.meth.str.len);
302 var->data.type = SMP_T_BOOL; /* This type doesn't use additional memory. */
303 return 0;
304 }
305 var->data.data.meth.meth = smp->data.meth.meth;
306 var->data.data.meth.str.len = smp->data.meth.str.len;
307 var->data.data.meth.str.size = smp->data.meth.str.len;
308 memcpy(var->data.data.meth.str.str, smp->data.meth.str.str, var->data.data.meth.str.len);
309 break;
310 }
311 return 1;
312}
313
314/* Returns 0 if fails, else returns 1. */
315static inline int sample_store_stream(const char *name, enum vars_scope scope,
316 struct stream *strm, struct sample *smp)
317{
318 struct vars *vars;
319
320 switch (scope) {
321 case SCOPE_SESS: vars = &strm->vars_sess; break;
322 case SCOPE_TXN: vars = &strm->vars_txn; break;
323 case SCOPE_REQ:
Thierry FOURNIER0b243fd2015-06-16 23:52:47 +0200324 case SCOPE_RES:
325 default: vars = &strm->vars_reqres; break;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200326 }
327 if (vars->scope != scope)
328 return 0;
329 return sample_store(vars, name, strm, smp);
330}
331
332/* Returns 0 if fails, else returns 1. */
333static int smp_conv_store(const struct arg *args, struct sample *smp, void *private)
334{
335 return sample_store_stream(args[0].data.var.name, args[1].data.var.scope, smp->strm, smp);
336}
337
338/* This fucntions check an argument entry and fill it with a variable
339 * type. The argumen must be a string. If the variable lookup fails,
340 * the function retuns 0 and fill <err>, otherwise it returns 1.
341 */
342int vars_check_arg(struct arg *arg, char **err)
343{
344 char *name;
345 enum vars_scope scope;
346
347 /* Check arg type. */
348 if (arg->type != ARGT_STR) {
349 memprintf(err, "unexpected argument type");
350 return 0;
351 }
352
353 /* Register new variable name. */
354 name = register_name(arg->data.str.str, arg->data.str.len, &scope, err);
355 if (!name)
356 return 0;
357
358 /* Use the global variable name pointer. */
359 arg->type = ARGT_VAR;
360 arg->data.var.name = name;
361 arg->data.var.scope = scope;
362 return 1;
363}
364
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200365/* This function store a sample in a variable.
366 * In error case, it fails silently.
367 */
368void vars_set_by_name(const char *name, size_t len, struct stream *strm, struct sample *smp)
369{
370 enum vars_scope scope;
371
372 /* Resolve name and scope. */
373 name = register_name(name, len, &scope, NULL);
374 if (!name)
375 return;
376
377 sample_store_stream(name, scope, strm, smp);
378}
379
380/* this function fills a sample with the
381 * variable content. Returns 1 if the sample
382 * is filled, otherwise it returns 0.
383 */
384int vars_get_by_name(const char *name, size_t len, struct stream *strm, struct sample *smp)
385{
386 struct vars *vars;
387 struct var *var;
388 enum vars_scope scope;
389
390 /* Resolve name and scope. */
391 name = register_name(name, len, &scope, NULL);
392 if (!name)
393 return 0;
394
395 /* Select "vars" pool according with the scope. */
396 switch (scope) {
397 case SCOPE_SESS: vars = &strm->vars_sess; break;
398 case SCOPE_TXN: vars = &strm->vars_txn; break;
399 case SCOPE_REQ:
Thierry FOURNIER0b243fd2015-06-16 23:52:47 +0200400 case SCOPE_RES:
401 default: vars = &strm->vars_reqres; break;
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200402 }
403
404 /* Check if the scope is avalaible a this point of processing. */
405 if (vars->scope != scope)
406 return 0;
407
408 /* Get the variable entry. */
409 var = var_get(vars, name);
410 if (!var)
411 return 0;
412
413 /* Copy sample. */
414 smp->type = var->data.type;
415 smp->flags = SMP_F_CONST;
416 memcpy(&smp->data, &var->data.data, sizeof(smp->data));
417 return 1;
418}
419
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200420/* Returns 0 if miss data, else returns 1. */
421static inline int action_store(struct sample_expr *expr, const char *name,
422 enum vars_scope scope, struct proxy *px,
423 struct stream *s, int sens)
424{
425 struct sample smp;
426
427 /* Process the expression. */
428 memset(&smp, 0, sizeof(smp));
429 if (!sample_process(px, s->sess, s, sens|SMP_OPT_FINAL, expr, &smp))
430 return 0;
431
432 /* Store the sample, and ignore errors. */
433 sample_store_stream(name, scope, s, &smp);
434 return 1;
435}
436
437/* Returns 0 if miss data, else returns 1. */
438static int action_tcp_req_store(struct tcp_rule *rule, struct proxy *px, struct stream *s)
439{
440 struct sample_expr *expr = rule->act_prm.data[0];
441 const char *name = rule->act_prm.data[1];
442 int scope = (long)rule->act_prm.data[2];
443
444 return action_store(expr, name, scope, px, s, SMP_OPT_DIR_REQ);
445}
446
447/* Returns 0 if miss data, else returns 1. */
448static int action_tcp_res_store(struct tcp_rule *rule, struct proxy *px, struct stream *s)
449{
450 struct sample_expr *expr = rule->act_prm.data[0];
451 const char *name = rule->act_prm.data[1];
452 int scope = (long)rule->act_prm.data[2];
453
454 return action_store(expr, name, scope, px, s, SMP_OPT_DIR_RES);
455}
456
457/* Returns 0 if miss data, else returns 1. */
458static int action_http_req_store(struct http_req_rule *rule, struct proxy *px, struct stream *s)
459{
460 struct sample_expr *expr = rule->arg.act.p[0];
461 const char *name = rule->arg.act.p[1];
462 int scope = (long)rule->arg.act.p[2];
463
464 return action_store(expr, name, scope, px, s, SMP_OPT_DIR_REQ);
465}
466
467/* Returns 0 if miss data, else returns 1. */
468static int action_http_res_store(struct http_res_rule *rule, struct proxy *px, struct stream *s)
469{
470 struct sample_expr *expr = rule->arg.act.p[0];
471 const char *name = rule->arg.act.p[1];
472 int scope = (long)rule->arg.act.p[2];
473
474 return action_store(expr, name, scope, px, s, SMP_OPT_DIR_RES);
475}
476
477/* This two function checks the variable name and replace the
478 * configuration string name by the global string name. its
479 * the same string, but the global pointer can be easy to
480 * compare.
481 *
482 * The first function checks a sample-fetch and the second
483 * checks a converter.
484 */
485static int smp_check_var(struct arg *args, char **err)
486{
487 return vars_check_arg(&args[0], err);
488}
489
490static int conv_check_var(struct arg *args, struct sample_conv *conv,
491 const char *file, int line, char **err_msg)
492{
493 return vars_check_arg(&args[0], err_msg);
494}
495
496/* This function is a common parser for using variables. It understands
497 * the format:
498 *
499 * set-var(<variable-name>) <expression>
500 *
501 * It returns 0 if fails and <err> is filled with an error message. Otherwise,
502 * it returns 1 and the variable <expr> is filled with the pointer to the
503 * expression to execute.
504 */
505static int parse_vars(const char **args, int *arg, struct proxy *px,
506 struct sample_expr **expr, char **name,
507 enum vars_scope *scope, char **err)
508{
509 const char *var_name = args[*arg-1];
510 int var_len;
511
512 var_name += strlen("set-var");
513 if (*var_name != '(') {
514 memprintf(err, "invalid variable '%s'. Expects 'set-var(<var-name>)'", args[*arg-1]);
515 return 0;
516 }
517 var_name++; /* jump the '(' */
518 var_len = strlen(var_name);
519 var_len--; /* remove the ')' */
520 if (var_name[var_len] != ')') {
521 memprintf(err, "invalid variable '%s'. Expects 'set-var(<var-name>)'", args[*arg-1]);
522 return 0;
523 }
524
525 *name = register_name(var_name, var_len, scope, err);
526 if (!*name)
527 return 0;
528
529 *expr = sample_parse_expr((char **)args, arg, px->conf.args.file, px->conf.args.line,
530 err, &px->conf.args);
531 if (!*expr)
532 return 0;
533
534 return 1;
535}
536
537static int parse_tcp_req_store(const char **args, int *arg, struct proxy *px,
538 struct tcp_rule *rule, char **err)
539{
540 struct sample_expr *expr;
541 int cur_arg = *arg;
542 char *name;
543 enum vars_scope scope;
544
545 if (!parse_vars(args, arg, px, &expr, &name, &scope, err))
546 return 0;
547
548 if (!(expr->fetch->val & SMP_VAL_FE_REQ_CNT)) {
549 memprintf(err,
550 "fetch method '%s' extracts information from '%s', none of which is available here",
551 args[cur_arg-1], sample_src_names(expr->fetch->use));
552 free(expr);
553 return 0;
554 }
555
556 rule->action = TCP_ACT_CUSTOM_CONT;
557 rule->action_ptr = action_tcp_req_store;
558 rule->act_prm.data[0] = expr;
559 rule->act_prm.data[1] = name;
560 rule->act_prm.data[2] = (void *)(long)scope;
561
562 return 1;
563}
564
565static int parse_tcp_res_store(const char **args, int *arg, struct proxy *px,
566 struct tcp_rule *rule, char **err)
567{
568 struct sample_expr *expr;
569 int cur_arg = *arg;
570 char *name;
571 enum vars_scope scope;
572
573 if (!parse_vars(args, arg, px, &expr, &name, &scope, err))
574 return 0;
575
576 if (!(expr->fetch->val & SMP_VAL_BE_RES_CNT)) {
577 memprintf(err,
578 "fetch method '%s' extracts information from '%s', none of which is available here",
579 args[cur_arg-1], sample_src_names(expr->fetch->use));
580 free(expr);
581 return 0;
582 }
583
584 rule->action = TCP_ACT_CUSTOM_CONT;
585 rule->action_ptr = action_tcp_res_store;
586 rule->act_prm.data[0] = expr;
587 rule->act_prm.data[1] = name;
588 rule->act_prm.data[2] = (void *)(long)scope;
589
590 return 1;
591}
592
593static int parse_http_req_store(const char **args, int *arg, struct proxy *px,
594 struct http_req_rule *rule, char **err)
595{
596 struct sample_expr *expr;
597 int cur_arg = *arg;
598 char *name;
599 enum vars_scope scope;
600
601 if (!parse_vars(args, arg, px, &expr, &name, &scope, err))
602 return -1;
603
604 if (!(expr->fetch->val & SMP_VAL_FE_HRQ_HDR)) {
605 memprintf(err,
606 "fetch method '%s' extracts information from '%s', none of which is available here",
607 args[cur_arg-1], sample_src_names(expr->fetch->use));
608 free(expr);
609 return -1;
610 }
611
612 rule->action = HTTP_REQ_ACT_CUSTOM_CONT;
613 rule->action_ptr = action_http_req_store;
614 rule->arg.act.p[0] = expr;
615 rule->arg.act.p[1] = name;
616 rule->arg.act.p[2] = (void *)(long)scope;
617
618 return 0;
619}
620
621static int parse_http_res_store(const char **args, int *arg, struct proxy *px,
622 struct http_res_rule *rule, char **err)
623{
624 struct sample_expr *expr;
625 int cur_arg = *arg;
626 char *name;
627 enum vars_scope scope;
628
629 if (!parse_vars(args, arg, px, &expr, &name, &scope, err))
630 return -1;
631
632 if (!(expr->fetch->val & SMP_VAL_BE_HRS_HDR)) {
633 memprintf(err,
634 "fetch method '%s' extracts information from '%s', none of which is available here",
635 args[cur_arg-1], sample_src_names(expr->fetch->use));
636 free(expr);
637 return -1;
638 }
639
640 rule->action = HTTP_RES_ACT_CUSTOM_CONT;
641 rule->action_ptr = action_http_res_store;
642 rule->arg.act.p[0] = expr;
643 rule->arg.act.p[1] = name;
644 rule->arg.act.p[2] = (void *)(long)scope;
645
646 return 0;
647}
648
649static int vars_max_size(char **args, int section_type, struct proxy *curpx,
650 struct proxy *defpx, const char *file, int line,
651 char **err, unsigned int *limit)
652{
653 char *error;
654
655 *limit = strtol(args[1], &error, 10);
656 if (*error != 0) {
657 memprintf(err, "%s: '%s' is an invalid size", args[0], args[1]);
658 return -1;
659 }
660 return 0;
661}
662
663static int vars_max_size_global(char **args, int section_type, struct proxy *curpx,
664 struct proxy *defpx, const char *file, int line,
665 char **err)
666{
667 return vars_max_size(args, section_type, curpx, defpx, file, line, err, &var_global_limit);
668}
669
670static int vars_max_size_sess(char **args, int section_type, struct proxy *curpx,
671 struct proxy *defpx, const char *file, int line,
672 char **err)
673{
674 return vars_max_size(args, section_type, curpx, defpx, file, line, err, &var_sess_limit);
675}
676
677static int vars_max_size_txn(char **args, int section_type, struct proxy *curpx,
678 struct proxy *defpx, const char *file, int line,
679 char **err)
680{
681 return vars_max_size(args, section_type, curpx, defpx, file, line, err, &var_txn_limit);
682}
683
684static int vars_max_size_reqres(char **args, int section_type, struct proxy *curpx,
685 struct proxy *defpx, const char *file, int line,
686 char **err)
687{
688 return vars_max_size(args, section_type, curpx, defpx, file, line, err, &var_reqres_limit);
689}
690
691static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
692
693 { "var", smp_fetch_var, ARG1(1,STR), smp_check_var, SMP_T_STR, SMP_USE_HTTP_ANY },
694 { /* END */ },
695}};
696
697static struct sample_conv_kw_list sample_conv_kws = {ILH, {
698 { "set-var", smp_conv_store, ARG1(1,STR), conv_check_var, SMP_T_ANY, SMP_T_ANY },
699 { /* END */ },
700}};
701
702static struct tcp_action_kw_list tcp_req_kws = {"vars", { }, {
703 { "set-var", parse_tcp_req_store, 1 },
704 { /* END */ }
705}};
706
707static struct tcp_action_kw_list tcp_res_kws = {"vars", { }, {
708 { "set-var", parse_tcp_res_store, 1 },
709 { /* END */ }
710}};
711
712static struct http_req_action_kw_list http_req_kws = {"vars", { }, {
713 { "set-var", parse_http_req_store, 1 },
714 { /* END */ }
715}};
716
717static struct http_res_action_kw_list http_res_kws = {"vars", { }, {
718 { "set-var", parse_http_res_store, 1 },
719 { /* END */ }
720}};
721
722static struct cfg_kw_list cfg_kws = {{ },{
723 { CFG_GLOBAL, "tune.vars.global-max-size", vars_max_size_global },
724 { CFG_GLOBAL, "tune.vars.sess-max-size", vars_max_size_sess },
725 { CFG_GLOBAL, "tune.vars.txn-max-size", vars_max_size_txn },
726 { CFG_GLOBAL, "tune.vars.reqres-max-size", vars_max_size_reqres },
727 { /* END */ }
728}};
729
730__attribute__((constructor))
731static void __http_protocol_init(void)
732{
733 var_pool = create_pool("vars", sizeof(struct var), MEM_F_SHARED);
734
735 sample_register_fetches(&sample_fetch_keywords);
736 sample_register_convs(&sample_conv_kws);
737 tcp_req_cont_keywords_register(&tcp_req_kws);
738 tcp_res_cont_keywords_register(&tcp_res_kws);
739 http_req_keywords_register(&http_req_kws);
740 http_res_keywords_register(&http_res_kws);
741 cfg_register_keywords(&cfg_kws);
742}