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