blob: c8aa5ac897a9e42816f5ac27c7746c44969c2ece [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>
Thierry FOURNIER4834bc72015-06-06 19:29:07 +020010#include <proto/sample.h>
11#include <proto/stream.h>
Willy Tarreau39713102016-11-25 15:49:32 +010012#include <proto/tcp_rules.h>
Willy Tarreauebcd4842015-06-19 11:59:02 +020013#include <proto/vars.h>
Thierry FOURNIER4834bc72015-06-06 19:29:07 +020014
15/* This contains a pool of struct vars */
16static struct pool_head *var_pool = NULL;
17
18/* This array contain all the names of all the HAProxy vars.
19 * This permits to identify two variables name with
20 * only one pointer. It permits to not using strdup() for
21 * each variable name used during the runtime.
22 */
23static char **var_names = NULL;
24static int var_names_nb = 0;
25
26/* This array of int contains the system limits per context. */
27static unsigned int var_global_limit = 0;
28static unsigned int var_global_size = 0;
Christopher Fauletff2613e2016-11-09 11:36:17 +010029static unsigned int var_proc_limit = 0;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +020030static unsigned int var_sess_limit = 0;
31static unsigned int var_txn_limit = 0;
32static unsigned int var_reqres_limit = 0;
33
Christopher Faulete95f2c32017-07-24 16:30:34 +020034
Christopher Faulet9dcf9b62017-11-13 10:34:01 +010035__decl_hathreads(HA_RWLOCK_T var_names_rwlock);
Christopher Faulete95f2c32017-07-24 16:30:34 +020036
Willy Tarreau72330982015-06-19 11:21:56 +020037/* This function adds or remove memory size from the accounting. The inner
38 * pointers may be null when setting the outer ones only.
39 */
Willy Tarreau6204cd92016-03-10 16:33:04 +010040static void var_accounting_diff(struct vars *vars, struct session *sess, struct stream *strm, int size)
Thierry FOURNIER4834bc72015-06-06 19:29:07 +020041{
42 switch (vars->scope) {
43 case SCOPE_REQ:
44 case SCOPE_RES:
Christopher Faulete95f2c32017-07-24 16:30:34 +020045 HA_ATOMIC_ADD(&strm->vars_reqres.size, size);
Willy Tarreau6204cd92016-03-10 16:33:04 +010046 /* fall through */
Thierry FOURNIER4834bc72015-06-06 19:29:07 +020047 case SCOPE_TXN:
Christopher Faulete95f2c32017-07-24 16:30:34 +020048 HA_ATOMIC_ADD(&strm->vars_txn.size, size);
Willy Tarreau6204cd92016-03-10 16:33:04 +010049 /* fall through */
Thierry FOURNIER4834bc72015-06-06 19:29:07 +020050 case SCOPE_SESS:
Christopher Faulete95f2c32017-07-24 16:30:34 +020051 HA_ATOMIC_ADD(&sess->vars.size, size);
Christopher Fauletff2613e2016-11-09 11:36:17 +010052 /* fall through */
53 case SCOPE_PROC:
Christopher Faulete95f2c32017-07-24 16:30:34 +020054 HA_ATOMIC_ADD(&global.vars.size, size);
55 HA_ATOMIC_ADD(&var_global_size, size);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +020056 }
57}
58
59/* This function returns 1 if the <size> is available in the var
60 * pool <vars>, otherwise returns 0. If the space is avalaible,
Willy Tarreau72330982015-06-19 11:21:56 +020061 * the size is reserved. The inner pointers may be null when setting
Willy Tarreau6204cd92016-03-10 16:33:04 +010062 * the outer ones only. The accounting uses either <sess> or <strm>
63 * depending on the scope. <strm> may be NULL when no stream is known
64 * and only the session exists (eg: tcp-request connection).
Thierry FOURNIER4834bc72015-06-06 19:29:07 +020065 */
Willy Tarreau6204cd92016-03-10 16:33:04 +010066static int var_accounting_add(struct vars *vars, struct session *sess, struct stream *strm, int size)
Thierry FOURNIER4834bc72015-06-06 19:29:07 +020067{
68 switch (vars->scope) {
69 case SCOPE_REQ:
70 case SCOPE_RES:
Willy Tarreau6204cd92016-03-10 16:33:04 +010071 if (var_reqres_limit && strm->vars_reqres.size + size > var_reqres_limit)
Thierry FOURNIER4834bc72015-06-06 19:29:07 +020072 return 0;
Willy Tarreau6204cd92016-03-10 16:33:04 +010073 /* fall through */
Thierry FOURNIER4834bc72015-06-06 19:29:07 +020074 case SCOPE_TXN:
Willy Tarreau6204cd92016-03-10 16:33:04 +010075 if (var_txn_limit && strm->vars_txn.size + size > var_txn_limit)
Thierry FOURNIER4834bc72015-06-06 19:29:07 +020076 return 0;
Willy Tarreau6204cd92016-03-10 16:33:04 +010077 /* fall through */
Thierry FOURNIER4834bc72015-06-06 19:29:07 +020078 case SCOPE_SESS:
Willy Tarreau6204cd92016-03-10 16:33:04 +010079 if (var_sess_limit && sess->vars.size + size > var_sess_limit)
Thierry FOURNIER4834bc72015-06-06 19:29:07 +020080 return 0;
Christopher Fauletff2613e2016-11-09 11:36:17 +010081 /* fall through */
82 case SCOPE_PROC:
83 if (var_proc_limit && global.vars.size + size > var_proc_limit)
84 return 0;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +020085 if (var_global_limit && var_global_size + size > var_global_limit)
86 return 0;
87 }
Willy Tarreau6204cd92016-03-10 16:33:04 +010088 var_accounting_diff(vars, sess, strm, size);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +020089 return 1;
90}
91
Christopher Faulet85d79c92016-11-09 16:54:56 +010092/* This fnuction remove a variable from the list and free memory it used */
93unsigned int var_clear(struct var *var)
94{
95 unsigned int size = 0;
96
97 if (var->data.type == SMP_T_STR || var->data.type == SMP_T_BIN) {
98 free(var->data.u.str.str);
99 size += var->data.u.str.len;
100 }
Christopher Fauletd02210c2017-07-24 16:24:39 +0200101 else if (var->data.type == SMP_T_METH && var->data.u.meth.meth == HTTP_METH_OTHER) {
Christopher Faulet85d79c92016-11-09 16:54:56 +0100102 free(var->data.u.meth.str.str);
103 size += var->data.u.meth.str.len;
104 }
105 LIST_DEL(&var->l);
Willy Tarreaubafbe012017-11-24 17:34:44 +0100106 pool_free(var_pool, var);
Christopher Faulet85d79c92016-11-09 16:54:56 +0100107 size += sizeof(struct var);
108 return size;
109}
110
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200111/* This function free all the memory used by all the varaibles
112 * in the list.
113 */
Willy Tarreau6204cd92016-03-10 16:33:04 +0100114void vars_prune(struct vars *vars, struct session *sess, struct stream *strm)
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200115{
116 struct var *var, *tmp;
Willy Tarreau72330982015-06-19 11:21:56 +0200117 unsigned int size = 0;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200118
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100119 HA_RWLOCK_WRLOCK(VARS_LOCK, &vars->rwlock);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200120 list_for_each_entry_safe(var, tmp, &vars->head, l) {
Christopher Faulet85d79c92016-11-09 16:54:56 +0100121 size += var_clear(var);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200122 }
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100123 HA_RWLOCK_WRUNLOCK(VARS_LOCK, &vars->rwlock);
Willy Tarreau6204cd92016-03-10 16:33:04 +0100124 var_accounting_diff(vars, sess, strm, -size);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200125}
126
Willy Tarreauebcd4842015-06-19 11:59:02 +0200127/* This function frees all the memory used by all the session variables in the
128 * list starting at <vars>.
129 */
130void vars_prune_per_sess(struct vars *vars)
131{
132 struct var *var, *tmp;
133 unsigned int size = 0;
134
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100135 HA_RWLOCK_WRLOCK(VARS_LOCK, &vars->rwlock);
Willy Tarreauebcd4842015-06-19 11:59:02 +0200136 list_for_each_entry_safe(var, tmp, &vars->head, l) {
Christopher Faulet85d79c92016-11-09 16:54:56 +0100137 size += var_clear(var);
Willy Tarreauebcd4842015-06-19 11:59:02 +0200138 }
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100139 HA_RWLOCK_WRUNLOCK(VARS_LOCK, &vars->rwlock);
Christopher Faulete95f2c32017-07-24 16:30:34 +0200140
141 HA_ATOMIC_SUB(&vars->size, size);
142 HA_ATOMIC_SUB(&global.vars.size, size);
143 HA_ATOMIC_SUB(&var_global_size, size);
Willy Tarreauebcd4842015-06-19 11:59:02 +0200144}
145
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200146/* This function init a list of variabes. */
147void vars_init(struct vars *vars, enum vars_scope scope)
148{
149 LIST_INIT(&vars->head);
150 vars->scope = scope;
151 vars->size = 0;
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100152 HA_RWLOCK_INIT(&vars->rwlock);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200153}
154
155/* This function declares a new variable name. It returns a pointer
156 * on the string identifying the name. This function assures that
157 * the same name exists only once.
158 *
159 * This function check if the variable name is acceptable.
160 *
161 * The function returns NULL if an error occurs, and <err> is filled.
162 * In this case, the HAProxy must be stopped because the structs are
163 * left inconsistent. Otherwise, it returns the pointer on the global
164 * name.
165 */
Christopher Faulet09c9df22016-10-31 11:05:37 +0100166static char *register_name(const char *name, int len, enum vars_scope *scope,
167 int alloc, char **err)
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200168{
169 int i;
Hubert Verstraete831962e2016-06-28 22:44:26 +0200170 char **var_names2;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200171 const char *tmp;
Christopher Faulete95f2c32017-07-24 16:30:34 +0200172 char *res = NULL;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200173
174 /* Check length. */
175 if (len == 0) {
176 memprintf(err, "Empty variable name cannot be accepted");
Christopher Faulete95f2c32017-07-24 16:30:34 +0200177 res = NULL;
178 goto end;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200179 }
180
181 /* Check scope. */
Christopher Fauletff2613e2016-11-09 11:36:17 +0100182 if (len > 5 && strncmp(name, "proc.", 5) == 0) {
183 name += 5;
184 len -= 5;
185 *scope = SCOPE_PROC;
186 }
187 else if (len > 5 && strncmp(name, "sess.", 5) == 0) {
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200188 name += 5;
189 len -= 5;
190 *scope = SCOPE_SESS;
191 }
192 else if (len > 4 && strncmp(name, "txn.", 4) == 0) {
193 name += 4;
194 len -= 4;
195 *scope = SCOPE_TXN;
196 }
197 else if (len > 4 && strncmp(name, "req.", 4) == 0) {
198 name += 4;
199 len -= 4;
200 *scope = SCOPE_REQ;
201 }
202 else if (len > 4 && strncmp(name, "res.", 4) == 0) {
203 name += 4;
204 len -= 4;
205 *scope = SCOPE_RES;
206 }
207 else {
208 memprintf(err, "invalid variable name '%s'. A variable name must be start by its scope. "
Christopher Fauletff2613e2016-11-09 11:36:17 +0100209 "The scope can be 'proc', 'sess', 'txn', 'req' or 'res'", name);
Christopher Faulete95f2c32017-07-24 16:30:34 +0200210 res = NULL;
211 goto end;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200212 }
213
Christopher Faulete95f2c32017-07-24 16:30:34 +0200214 if (alloc)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100215 HA_RWLOCK_WRLOCK(VARS_LOCK, &var_names_rwlock);
Christopher Faulete95f2c32017-07-24 16:30:34 +0200216 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100217 HA_RWLOCK_RDLOCK(VARS_LOCK, &var_names_rwlock);
Christopher Faulete95f2c32017-07-24 16:30:34 +0200218
219
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200220 /* Look for existing variable name. */
221 for (i = 0; i < var_names_nb; i++)
Christopher Faulete95f2c32017-07-24 16:30:34 +0200222 if (strncmp(var_names[i], name, len) == 0 && var_names[i][len] == '\0') {
223 res = var_names[i];
224 goto end;
225 }
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200226
Christopher Faulete95f2c32017-07-24 16:30:34 +0200227 if (!alloc) {
228 res = NULL;
229 goto end;
230 }
Christopher Faulet09c9df22016-10-31 11:05:37 +0100231
Hubert Verstraete831962e2016-06-28 22:44:26 +0200232 /* Store variable name. If realloc fails, var_names remains valid */
233 var_names2 = realloc(var_names, (var_names_nb + 1) * sizeof(*var_names));
234 if (!var_names2) {
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200235 memprintf(err, "out of memory error");
Christopher Faulete95f2c32017-07-24 16:30:34 +0200236 res = NULL;
237 goto end;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200238 }
Hubert Verstraete831962e2016-06-28 22:44:26 +0200239 var_names_nb++;
240 var_names = var_names2;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200241 var_names[var_names_nb - 1] = malloc(len + 1);
242 if (!var_names[var_names_nb - 1]) {
243 memprintf(err, "out of memory error");
Christopher Faulete95f2c32017-07-24 16:30:34 +0200244 res = NULL;
245 goto end;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200246 }
247 memcpy(var_names[var_names_nb - 1], name, len);
248 var_names[var_names_nb - 1][len] = '\0';
249
250 /* Check variable name syntax. */
251 tmp = var_names[var_names_nb - 1];
252 while (*tmp) {
Christopher Fauletb71557a2016-10-31 10:49:03 +0100253 if (!isalnum((int)(unsigned char)*tmp) && *tmp != '_' && *tmp != '.') {
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200254 memprintf(err, "invalid syntax at char '%s'", tmp);
Christopher Faulete95f2c32017-07-24 16:30:34 +0200255 res = NULL;
256 goto end;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200257 }
258 tmp++;
259 }
Christopher Faulete95f2c32017-07-24 16:30:34 +0200260 res = var_names[var_names_nb - 1];
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200261
Christopher Faulete95f2c32017-07-24 16:30:34 +0200262 end:
263 if (alloc)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100264 HA_RWLOCK_WRUNLOCK(VARS_LOCK, &var_names_rwlock);
Christopher Faulete95f2c32017-07-24 16:30:34 +0200265 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100266 HA_RWLOCK_RDUNLOCK(VARS_LOCK, &var_names_rwlock);
Christopher Faulete95f2c32017-07-24 16:30:34 +0200267
268 return res;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200269}
270
271/* This function returns an existing variable or returns NULL. */
272static inline struct var *var_get(struct vars *vars, const char *name)
273{
274 struct var *var;
275
276 list_for_each_entry(var, &vars->head, l)
277 if (var->name == name)
278 return var;
279 return NULL;
280}
281
282/* Returns 0 if fails, else returns 1. */
283static int smp_fetch_var(const struct arg *args, struct sample *smp, const char *kw, void *private)
284{
285 const struct var_desc *var_desc = &args[0].data.var;
286 struct var *var;
287 struct vars *vars;
288
289 /* Check the availibity of the variable. */
290 switch (var_desc->scope) {
Christopher Fauletff2613e2016-11-09 11:36:17 +0100291 case SCOPE_PROC:
292 vars = &global.vars;
293 break;
Willy Tarreau7513d002016-10-21 17:14:35 +0200294 case SCOPE_SESS:
295 vars = &smp->sess->vars;
296 break;
297 case SCOPE_TXN:
298 if (!smp->strm)
299 return 0;
300 vars = &smp->strm->vars_txn;
301 break;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200302 case SCOPE_REQ:
Thierry FOURNIER0b243fd2015-06-16 23:52:47 +0200303 case SCOPE_RES:
Willy Tarreau7513d002016-10-21 17:14:35 +0200304 default:
305 if (!smp->strm)
306 return 0;
307 vars = &smp->strm->vars_reqres;
308 break;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200309 }
310 if (vars->scope != var_desc->scope)
311 return 0;
Christopher Faulete95f2c32017-07-24 16:30:34 +0200312
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100313 HA_RWLOCK_RDLOCK(VARS_LOCK, &vars->rwlock);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200314 var = var_get(vars, var_desc->name);
315
316 /* check for the variable avalaibility */
Christopher Faulete95f2c32017-07-24 16:30:34 +0200317 if (!var) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100318 HA_RWLOCK_RDUNLOCK(VARS_LOCK, &vars->rwlock);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200319 return 0;
Christopher Faulete95f2c32017-07-24 16:30:34 +0200320 }
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200321
Christopher Faulete95f2c32017-07-24 16:30:34 +0200322 /* Duplicate the sample data because it could modified by another
323 * thread */
Thierry FOURNIER5cc18d42015-08-19 09:02:36 +0200324 smp->data = var->data;
Christopher Faulete95f2c32017-07-24 16:30:34 +0200325 smp_dup(smp);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200326 smp->flags |= SMP_F_CONST;
Christopher Faulete95f2c32017-07-24 16:30:34 +0200327
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100328 HA_RWLOCK_RDUNLOCK(VARS_LOCK, &vars->rwlock);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200329 return 1;
330}
331
332/* This function search in the <head> a variable with the same
333 * pointer value that the <name>. If the variable doesn't exists,
334 * create it. The function stores a copy of smp> if the variable.
335 * It returns 0 if fails, else returns 1.
336 */
Willy Tarreau6204cd92016-03-10 16:33:04 +0100337static int sample_store(struct vars *vars, const char *name, struct sample *smp)
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200338{
339 struct var *var;
340
341 /* Look for existing variable name. */
342 var = var_get(vars, name);
343
344 if (var) {
345 /* free its used memory. */
346 if (var->data.type == SMP_T_STR ||
347 var->data.type == SMP_T_BIN) {
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200348 free(var->data.u.str.str);
Willy Tarreau6204cd92016-03-10 16:33:04 +0100349 var_accounting_diff(vars, smp->sess, smp->strm, -var->data.u.str.len);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200350 }
Christopher Fauletd02210c2017-07-24 16:24:39 +0200351 else if (var->data.type == SMP_T_METH && var->data.u.meth.meth == HTTP_METH_OTHER) {
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200352 free(var->data.u.meth.str.str);
Willy Tarreau6204cd92016-03-10 16:33:04 +0100353 var_accounting_diff(vars, smp->sess, smp->strm, -var->data.u.meth.str.len);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200354 }
355 } else {
356
357 /* Check memory avalaible. */
Willy Tarreau6204cd92016-03-10 16:33:04 +0100358 if (!var_accounting_add(vars, smp->sess, smp->strm, sizeof(struct var)))
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200359 return 0;
360
361 /* Create new entry. */
Willy Tarreaubafbe012017-11-24 17:34:44 +0100362 var = pool_alloc(var_pool);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200363 if (!var)
364 return 0;
365 LIST_ADDQ(&vars->head, &var->l);
366 var->name = name;
367 }
368
369 /* Set type. */
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +0200370 var->data.type = smp->data.type;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200371
372 /* Copy data. If the data needs memory, the function can fail. */
373 switch (var->data.type) {
374 case SMP_T_BOOL:
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200375 case SMP_T_SINT:
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200376 var->data.u.sint = smp->data.u.sint;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200377 break;
378 case SMP_T_IPV4:
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200379 var->data.u.ipv4 = smp->data.u.ipv4;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200380 break;
381 case SMP_T_IPV6:
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200382 var->data.u.ipv6 = smp->data.u.ipv6;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200383 break;
384 case SMP_T_STR:
385 case SMP_T_BIN:
Willy Tarreau6204cd92016-03-10 16:33:04 +0100386 if (!var_accounting_add(vars, smp->sess, smp->strm, smp->data.u.str.len)) {
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200387 var->data.type = SMP_T_BOOL; /* This type doesn't use additional memory. */
388 return 0;
389 }
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200390 var->data.u.str.str = malloc(smp->data.u.str.len);
391 if (!var->data.u.str.str) {
Willy Tarreau6204cd92016-03-10 16:33:04 +0100392 var_accounting_diff(vars, smp->sess, smp->strm, -smp->data.u.str.len);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200393 var->data.type = SMP_T_BOOL; /* This type doesn't use additional memory. */
394 return 0;
395 }
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200396 var->data.u.str.len = smp->data.u.str.len;
397 memcpy(var->data.u.str.str, smp->data.u.str.str, var->data.u.str.len);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200398 break;
399 case SMP_T_METH:
Christopher Fauletd02210c2017-07-24 16:24:39 +0200400 var->data.u.meth.meth = smp->data.u.meth.meth;
401 if (smp->data.u.meth.meth != HTTP_METH_OTHER)
402 break;
403
Willy Tarreau6204cd92016-03-10 16:33:04 +0100404 if (!var_accounting_add(vars, smp->sess, smp->strm, smp->data.u.meth.str.len)) {
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200405 var->data.type = SMP_T_BOOL; /* This type doesn't use additional memory. */
406 return 0;
407 }
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200408 var->data.u.meth.str.str = malloc(smp->data.u.meth.str.len);
409 if (!var->data.u.meth.str.str) {
Willy Tarreau6204cd92016-03-10 16:33:04 +0100410 var_accounting_diff(vars, smp->sess, smp->strm, -smp->data.u.meth.str.len);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200411 var->data.type = SMP_T_BOOL; /* This type doesn't use additional memory. */
412 return 0;
413 }
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200414 var->data.u.meth.str.len = smp->data.u.meth.str.len;
415 var->data.u.meth.str.size = smp->data.u.meth.str.len;
416 memcpy(var->data.u.meth.str.str, smp->data.u.meth.str.str, var->data.u.meth.str.len);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200417 break;
418 }
419 return 1;
420}
421
Willy Tarreau620408f2016-10-21 16:37:51 +0200422/* Returns 0 if fails, else returns 1. Note that stream may be null for SCOPE_SESS. */
Willy Tarreau6204cd92016-03-10 16:33:04 +0100423static inline int sample_store_stream(const char *name, enum vars_scope scope, struct sample *smp)
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200424{
425 struct vars *vars;
Christopher Faulete95f2c32017-07-24 16:30:34 +0200426 int ret;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200427
428 switch (scope) {
Christopher Fauletff2613e2016-11-09 11:36:17 +0100429 case SCOPE_PROC: vars = &global.vars; break;
Willy Tarreau6204cd92016-03-10 16:33:04 +0100430 case SCOPE_SESS: vars = &smp->sess->vars; break;
431 case SCOPE_TXN: vars = &smp->strm->vars_txn; break;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200432 case SCOPE_REQ:
Thierry FOURNIER0b243fd2015-06-16 23:52:47 +0200433 case SCOPE_RES:
Willy Tarreau6204cd92016-03-10 16:33:04 +0100434 default: vars = &smp->strm->vars_reqres; break;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200435 }
436 if (vars->scope != scope)
437 return 0;
Christopher Faulete95f2c32017-07-24 16:30:34 +0200438
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100439 HA_RWLOCK_WRLOCK(VARS_LOCK, &vars->rwlock);
Christopher Faulete95f2c32017-07-24 16:30:34 +0200440 ret = sample_store(vars, name, smp);
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100441 HA_RWLOCK_WRUNLOCK(VARS_LOCK, &vars->rwlock);
Christopher Faulete95f2c32017-07-24 16:30:34 +0200442 return ret;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200443}
444
Christopher Faulet85d79c92016-11-09 16:54:56 +0100445/* Returns 0 if fails, else returns 1. Note that stream may be null for SCOPE_SESS. */
446static inline int sample_clear_stream(const char *name, enum vars_scope scope, struct sample *smp)
447{
448 struct vars *vars;
449 struct var *var;
450 unsigned int size = 0;
451
452 switch (scope) {
453 case SCOPE_PROC: vars = &global.vars; break;
454 case SCOPE_SESS: vars = &smp->sess->vars; break;
455 case SCOPE_TXN: vars = &smp->strm->vars_txn; break;
456 case SCOPE_REQ:
457 case SCOPE_RES:
458 default: vars = &smp->strm->vars_reqres; break;
459 }
460 if (vars->scope != scope)
461 return 0;
462
463 /* Look for existing variable name. */
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100464 HA_RWLOCK_WRLOCK(VARS_LOCK, &vars->rwlock);
Christopher Faulet85d79c92016-11-09 16:54:56 +0100465 var = var_get(vars, name);
466 if (var) {
467 size = var_clear(var);
468 var_accounting_diff(vars, smp->sess, smp->strm, -size);
469 }
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100470 HA_RWLOCK_WRUNLOCK(VARS_LOCK, &vars->rwlock);
Christopher Faulet85d79c92016-11-09 16:54:56 +0100471 return 1;
472}
473
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200474/* Returns 0 if fails, else returns 1. */
475static int smp_conv_store(const struct arg *args, struct sample *smp, void *private)
476{
Christopher Faulet0099a8c2016-11-09 16:15:32 +0100477 return sample_store_stream(args[0].data.var.name, args[0].data.var.scope, smp);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200478}
479
Christopher Faulet85d79c92016-11-09 16:54:56 +0100480/* Returns 0 if fails, else returns 1. */
481static int smp_conv_clear(const struct arg *args, struct sample *smp, void *private)
482{
483 return sample_clear_stream(args[0].data.var.name, args[0].data.var.scope, smp);
484}
485
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200486/* This fucntions check an argument entry and fill it with a variable
487 * type. The argumen must be a string. If the variable lookup fails,
488 * the function retuns 0 and fill <err>, otherwise it returns 1.
489 */
490int vars_check_arg(struct arg *arg, char **err)
491{
492 char *name;
493 enum vars_scope scope;
494
495 /* Check arg type. */
496 if (arg->type != ARGT_STR) {
497 memprintf(err, "unexpected argument type");
498 return 0;
499 }
500
501 /* Register new variable name. */
Christopher Faulet09c9df22016-10-31 11:05:37 +0100502 name = register_name(arg->data.str.str, arg->data.str.len, &scope, 1, err);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200503 if (!name)
504 return 0;
505
506 /* Use the global variable name pointer. */
507 arg->type = ARGT_VAR;
508 arg->data.var.name = name;
509 arg->data.var.scope = scope;
510 return 1;
511}
512
Christopher Faulet09c9df22016-10-31 11:05:37 +0100513/* This function store a sample in a variable if it was already defined.
514 * In error case, it fails silently.
515 */
516void vars_set_by_name_ifexist(const char *name, size_t len, struct sample *smp)
517{
518 enum vars_scope scope;
519
520 /* Resolve name and scope. */
521 name = register_name(name, len, &scope, 0, NULL);
522 if (!name)
523 return;
524
525 sample_store_stream(name, scope, smp);
526}
527
528
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200529/* This function store a sample in a variable.
530 * In error case, it fails silently.
531 */
Willy Tarreau6204cd92016-03-10 16:33:04 +0100532void vars_set_by_name(const char *name, size_t len, struct sample *smp)
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200533{
534 enum vars_scope scope;
535
536 /* Resolve name and scope. */
Christopher Faulet09c9df22016-10-31 11:05:37 +0100537 name = register_name(name, len, &scope, 1, NULL);
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200538 if (!name)
539 return;
540
Willy Tarreau6204cd92016-03-10 16:33:04 +0100541 sample_store_stream(name, scope, smp);
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200542}
543
Christopher Faulet85d79c92016-11-09 16:54:56 +0100544/* This function unset a variable if it was already defined.
545 * In error case, it fails silently.
546 */
547void vars_unset_by_name_ifexist(const char *name, size_t len, struct sample *smp)
548{
549 enum vars_scope scope;
550
551 /* Resolve name and scope. */
552 name = register_name(name, len, &scope, 0, NULL);
553 if (!name)
554 return;
555
556 sample_clear_stream(name, scope, smp);
557}
558
559
560/* This function unset a variable.
561 * In error case, it fails silently.
562 */
563void vars_unset_by_name(const char *name, size_t len, struct sample *smp)
564{
565 enum vars_scope scope;
566
567 /* Resolve name and scope. */
568 name = register_name(name, len, &scope, 1, NULL);
569 if (!name)
570 return;
571
572 sample_clear_stream(name, scope, smp);
573}
574
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200575/* this function fills a sample with the
576 * variable content. Returns 1 if the sample
577 * is filled, otherwise it returns 0.
578 */
Willy Tarreau6204cd92016-03-10 16:33:04 +0100579int vars_get_by_name(const char *name, size_t len, struct sample *smp)
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200580{
581 struct vars *vars;
582 struct var *var;
583 enum vars_scope scope;
584
585 /* Resolve name and scope. */
Christopher Faulet09c9df22016-10-31 11:05:37 +0100586 name = register_name(name, len, &scope, 1, NULL);
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200587 if (!name)
588 return 0;
589
590 /* Select "vars" pool according with the scope. */
591 switch (scope) {
Christopher Fauletff2613e2016-11-09 11:36:17 +0100592 case SCOPE_PROC: vars = &global.vars; break;
Willy Tarreau6204cd92016-03-10 16:33:04 +0100593 case SCOPE_SESS: vars = &smp->sess->vars; break;
594 case SCOPE_TXN: vars = &smp->strm->vars_txn; break;
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200595 case SCOPE_REQ:
Thierry FOURNIER0b243fd2015-06-16 23:52:47 +0200596 case SCOPE_RES:
Willy Tarreau6204cd92016-03-10 16:33:04 +0100597 default: vars = &smp->strm->vars_reqres; break;
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200598 }
599
600 /* Check if the scope is avalaible a this point of processing. */
601 if (vars->scope != scope)
602 return 0;
603
604 /* Get the variable entry. */
605 var = var_get(vars, name);
606 if (!var)
607 return 0;
608
609 /* Copy sample. */
Thierry FOURNIER5cc18d42015-08-19 09:02:36 +0200610 smp->data = var->data;
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200611 smp->flags = SMP_F_CONST;
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200612 return 1;
613}
614
Thierry FOURNIERfd77e052015-07-07 21:20:42 +0200615/* this function fills a sample with the
616 * content of the varaible described by <var_desc>. Returns 1
617 * if the sample is filled, otherwise it returns 0.
618 */
Willy Tarreau6204cd92016-03-10 16:33:04 +0100619int vars_get_by_desc(const struct var_desc *var_desc, struct sample *smp)
Thierry FOURNIERfd77e052015-07-07 21:20:42 +0200620{
621 struct vars *vars;
622 struct var *var;
623
624 /* Select "vars" pool according with the scope. */
625 switch (var_desc->scope) {
Christopher Fauletff2613e2016-11-09 11:36:17 +0100626 case SCOPE_PROC: vars = &global.vars; break;
Willy Tarreau6204cd92016-03-10 16:33:04 +0100627 case SCOPE_SESS: vars = &smp->sess->vars; break;
628 case SCOPE_TXN: vars = &smp->strm->vars_txn; break;
Thierry FOURNIERfd77e052015-07-07 21:20:42 +0200629 case SCOPE_REQ:
630 case SCOPE_RES:
Willy Tarreau6204cd92016-03-10 16:33:04 +0100631 default: vars = &smp->strm->vars_reqres; break;
Thierry FOURNIERfd77e052015-07-07 21:20:42 +0200632 }
633
634 /* Check if the scope is avalaible a this point of processing. */
635 if (vars->scope != var_desc->scope)
636 return 0;
637
638 /* Get the variable entry. */
639 var = var_get(vars, var_desc->name);
640 if (!var)
641 return 0;
642
643 /* Copy sample. */
Thierry FOURNIER5cc18d42015-08-19 09:02:36 +0200644 smp->data = var->data;
Thierry FOURNIERfd77e052015-07-07 21:20:42 +0200645 smp->flags = SMP_F_CONST;
Thierry FOURNIERfd77e052015-07-07 21:20:42 +0200646 return 1;
647}
648
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200649/* Always returns ACT_RET_CONT even if an error occurs. */
650static enum act_return action_store(struct act_rule *rule, struct proxy *px,
Willy Tarreau658b85b2015-09-27 10:00:49 +0200651 struct session *sess, struct stream *s, int flags)
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200652{
653 struct sample smp;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200654 int dir;
655
656 switch (rule->from) {
Willy Tarreau620408f2016-10-21 16:37:51 +0200657 case ACT_F_TCP_REQ_SES: dir = SMP_OPT_DIR_REQ; break;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200658 case ACT_F_TCP_REQ_CNT: dir = SMP_OPT_DIR_REQ; break;
659 case ACT_F_TCP_RES_CNT: dir = SMP_OPT_DIR_RES; break;
660 case ACT_F_HTTP_REQ: dir = SMP_OPT_DIR_REQ; break;
661 case ACT_F_HTTP_RES: dir = SMP_OPT_DIR_RES; break;
662 default:
663 send_log(px, LOG_ERR, "Vars: internal error while execute action store.");
664 if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))
Christopher Faulet767a84b2017-11-24 16:50:31 +0100665 ha_alert("Vars: internal error while execute action store.\n");
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200666 return ACT_RET_CONT;
667 }
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200668
669 /* Process the expression. */
670 memset(&smp, 0, sizeof(smp));
Willy Tarreau108a8fd2016-10-21 17:13:24 +0200671 if (!sample_process(px, sess, s, dir|SMP_OPT_FINAL,
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200672 rule->arg.vars.expr, &smp))
Thierry FOURNIER24ff6c62015-08-06 08:52:53 +0200673 return ACT_RET_CONT;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200674
675 /* Store the sample, and ignore errors. */
Willy Tarreau6204cd92016-03-10 16:33:04 +0100676 sample_store_stream(rule->arg.vars.name, rule->arg.vars.scope, &smp);
Thierry FOURNIER24ff6c62015-08-06 08:52:53 +0200677 return ACT_RET_CONT;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200678}
679
Christopher Faulet85d79c92016-11-09 16:54:56 +0100680/* Always returns ACT_RET_CONT even if an error occurs. */
681static enum act_return action_clear(struct act_rule *rule, struct proxy *px,
682 struct session *sess, struct stream *s, int flags)
683{
684 struct sample smp;
685
686 memset(&smp, 0, sizeof(smp));
687 smp_set_owner(&smp, px, sess, s, SMP_OPT_FINAL);
688
689 /* Clear the variable using the sample context, and ignore errors. */
690 sample_clear_stream(rule->arg.vars.name, rule->arg.vars.scope, &smp);
691 return ACT_RET_CONT;
692}
693
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200694/* This two function checks the variable name and replace the
695 * configuration string name by the global string name. its
696 * the same string, but the global pointer can be easy to
697 * compare.
698 *
699 * The first function checks a sample-fetch and the second
700 * checks a converter.
701 */
702static int smp_check_var(struct arg *args, char **err)
703{
704 return vars_check_arg(&args[0], err);
705}
706
707static int conv_check_var(struct arg *args, struct sample_conv *conv,
708 const char *file, int line, char **err_msg)
709{
710 return vars_check_arg(&args[0], err_msg);
711}
712
713/* This function is a common parser for using variables. It understands
714 * the format:
715 *
716 * set-var(<variable-name>) <expression>
717 *
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200718 * It returns ACT_RET_PRS_ERR if fails and <err> is filled with an error
719 * message. Otherwise, it returns ACT_RET_PRS_OK and the variable <expr>
720 * is filled with the pointer to the expression to execute.
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200721 */
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200722static enum act_parse_ret parse_store(const char **args, int *arg, struct proxy *px,
723 struct act_rule *rule, char **err)
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200724{
725 const char *var_name = args[*arg-1];
726 int var_len;
Thierry FOURNIER48a9cd12015-07-28 19:00:28 +0200727 const char *kw_name;
Willy Tarreaue3658152016-11-24 21:23:28 +0100728 int flags, set_var = 0;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200729
Christopher Faulet85d79c92016-11-09 16:54:56 +0100730 if (!strncmp(var_name, "set-var", 7)) {
731 var_name += 7;
732 set_var = 1;
733 }
734 if (!strncmp(var_name, "unset-var", 9)) {
735 var_name += 9;
736 set_var = 0;
737 }
738
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200739 if (*var_name != '(') {
Christopher Faulet85d79c92016-11-09 16:54:56 +0100740 memprintf(err, "invalid variable '%s'. Expects 'set-var(<var-name>)' or 'unset-var(<var-name>)'",
741 args[*arg-1]);
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200742 return ACT_RET_PRS_ERR;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200743 }
744 var_name++; /* jump the '(' */
745 var_len = strlen(var_name);
746 var_len--; /* remove the ')' */
747 if (var_name[var_len] != ')') {
Christopher Faulet85d79c92016-11-09 16:54:56 +0100748 memprintf(err, "invalid variable '%s'. Expects 'set-var(<var-name>)' or 'unset-var(<var-name>)'",
749 args[*arg-1]);
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200750 return ACT_RET_PRS_ERR;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200751 }
752
Christopher Faulet09c9df22016-10-31 11:05:37 +0100753 rule->arg.vars.name = register_name(var_name, var_len, &rule->arg.vars.scope, 1, err);
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200754 if (!rule->arg.vars.name)
755 return ACT_RET_PRS_ERR;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200756
Christopher Faulet85d79c92016-11-09 16:54:56 +0100757 /* There is no fetch method when variable is unset. Just set the right
758 * action and return. */
759 if (!set_var) {
760 if (*args[*arg]) {
761 memprintf(err, "fetch method not supported");
762 return ACT_RET_PRS_ERR;
763 }
764 rule->action = ACT_CUSTOM;
765 rule->action_ptr = action_clear;
766 return ACT_RET_PRS_OK;
767 }
768
Thierry FOURNIER48a9cd12015-07-28 19:00:28 +0200769 kw_name = args[*arg-1];
770
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200771 rule->arg.vars.expr = sample_parse_expr((char **)args, arg, px->conf.args.file,
772 px->conf.args.line, err, &px->conf.args);
773 if (!rule->arg.vars.expr)
Thierry FOURNIERafa80492015-08-19 09:04:15 +0200774 return ACT_RET_PRS_ERR;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200775
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200776 switch (rule->from) {
Willy Tarreau620408f2016-10-21 16:37:51 +0200777 case ACT_F_TCP_REQ_SES: flags = SMP_VAL_FE_SES_ACC; break;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200778 case ACT_F_TCP_REQ_CNT: flags = SMP_VAL_FE_REQ_CNT; break;
779 case ACT_F_TCP_RES_CNT: flags = SMP_VAL_BE_RES_CNT; break;
780 case ACT_F_HTTP_REQ: flags = SMP_VAL_FE_HRQ_HDR; break;
781 case ACT_F_HTTP_RES: flags = SMP_VAL_BE_HRS_HDR; break;
782 default:
783 memprintf(err,
784 "internal error, unexpected rule->from=%d, please report this bug!",
785 rule->from);
Thierry FOURNIERafa80492015-08-19 09:04:15 +0200786 return ACT_RET_PRS_ERR;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200787 }
788 if (!(rule->arg.vars.expr->fetch->val & flags)) {
789 memprintf(err,
790 "fetch method '%s' extracts information from '%s', none of which is available here",
791 kw_name, sample_src_names(rule->arg.vars.expr->fetch->use));
792 free(rule->arg.vars.expr);
Thierry FOURNIERafa80492015-08-19 09:04:15 +0200793 return ACT_RET_PRS_ERR;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200794 }
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200795
Thierry FOURNIER42148732015-09-02 17:17:33 +0200796 rule->action = ACT_CUSTOM;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200797 rule->action_ptr = action_store;
Thierry FOURNIERafa80492015-08-19 09:04:15 +0200798 return ACT_RET_PRS_OK;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200799}
800
801static int vars_max_size(char **args, int section_type, struct proxy *curpx,
802 struct proxy *defpx, const char *file, int line,
803 char **err, unsigned int *limit)
804{
805 char *error;
806
807 *limit = strtol(args[1], &error, 10);
808 if (*error != 0) {
809 memprintf(err, "%s: '%s' is an invalid size", args[0], args[1]);
810 return -1;
811 }
812 return 0;
813}
814
815static int vars_max_size_global(char **args, int section_type, struct proxy *curpx,
816 struct proxy *defpx, const char *file, int line,
817 char **err)
818{
819 return vars_max_size(args, section_type, curpx, defpx, file, line, err, &var_global_limit);
820}
821
Christopher Fauletff2613e2016-11-09 11:36:17 +0100822static int vars_max_size_proc(char **args, int section_type, struct proxy *curpx,
823 struct proxy *defpx, const char *file, int line,
824 char **err)
825{
826 return vars_max_size(args, section_type, curpx, defpx, file, line, err, &var_proc_limit);
827}
828
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200829static int vars_max_size_sess(char **args, int section_type, struct proxy *curpx,
830 struct proxy *defpx, const char *file, int line,
831 char **err)
832{
833 return vars_max_size(args, section_type, curpx, defpx, file, line, err, &var_sess_limit);
834}
835
836static int vars_max_size_txn(char **args, int section_type, struct proxy *curpx,
837 struct proxy *defpx, const char *file, int line,
838 char **err)
839{
840 return vars_max_size(args, section_type, curpx, defpx, file, line, err, &var_txn_limit);
841}
842
843static int vars_max_size_reqres(char **args, int section_type, struct proxy *curpx,
844 struct proxy *defpx, const char *file, int line,
845 char **err)
846{
847 return vars_max_size(args, section_type, curpx, defpx, file, line, err, &var_reqres_limit);
848}
849
850static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
851
Christopher Fauletff2613e2016-11-09 11:36:17 +0100852 { "var", smp_fetch_var, ARG1(1,STR), smp_check_var, SMP_T_STR, SMP_USE_L4CLI },
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200853 { /* END */ },
854}};
855
856static struct sample_conv_kw_list sample_conv_kws = {ILH, {
Christopher Faulet85d79c92016-11-09 16:54:56 +0100857 { "set-var", smp_conv_store, ARG1(1,STR), conv_check_var, SMP_T_ANY, SMP_T_ANY },
858 { "unset-var", smp_conv_clear, ARG1(1,STR), conv_check_var, SMP_T_ANY, SMP_T_ANY },
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200859 { /* END */ },
860}};
861
Willy Tarreau620408f2016-10-21 16:37:51 +0200862static struct action_kw_list tcp_req_sess_kws = { { }, {
Christopher Faulet85d79c92016-11-09 16:54:56 +0100863 { "set-var", parse_store, 1 },
864 { "unset-var", parse_store, 1 },
Willy Tarreau620408f2016-10-21 16:37:51 +0200865 { /* END */ }
866}};
867
868static struct action_kw_list tcp_req_cont_kws = { { }, {
Christopher Faulet85d79c92016-11-09 16:54:56 +0100869 { "set-var", parse_store, 1 },
870 { "unset-var", parse_store, 1 },
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200871 { /* END */ }
872}};
873
Thierry FOURNIER36481b82015-08-19 09:01:53 +0200874static struct action_kw_list tcp_res_kws = { { }, {
Christopher Faulet85d79c92016-11-09 16:54:56 +0100875 { "set-var", parse_store, 1 },
876 { "unset-var", parse_store, 1 },
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200877 { /* END */ }
878}};
879
Thierry FOURNIER36481b82015-08-19 09:01:53 +0200880static struct action_kw_list http_req_kws = { { }, {
Christopher Faulet85d79c92016-11-09 16:54:56 +0100881 { "set-var", parse_store, 1 },
882 { "unset-var", parse_store, 1 },
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200883 { /* END */ }
884}};
885
Thierry FOURNIER36481b82015-08-19 09:01:53 +0200886static struct action_kw_list http_res_kws = { { }, {
Christopher Faulet85d79c92016-11-09 16:54:56 +0100887 { "set-var", parse_store, 1 },
888 { "unset-var", parse_store, 1 },
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200889 { /* END */ }
890}};
891
892static struct cfg_kw_list cfg_kws = {{ },{
893 { CFG_GLOBAL, "tune.vars.global-max-size", vars_max_size_global },
Christopher Fauletff2613e2016-11-09 11:36:17 +0100894 { CFG_GLOBAL, "tune.vars.proc-max-size", vars_max_size_proc },
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200895 { CFG_GLOBAL, "tune.vars.sess-max-size", vars_max_size_sess },
896 { CFG_GLOBAL, "tune.vars.txn-max-size", vars_max_size_txn },
897 { CFG_GLOBAL, "tune.vars.reqres-max-size", vars_max_size_reqres },
898 { /* END */ }
899}};
900
901__attribute__((constructor))
Christopher Faulete95f2c32017-07-24 16:30:34 +0200902static void __vars_init(void)
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200903{
904 var_pool = create_pool("vars", sizeof(struct var), MEM_F_SHARED);
905
906 sample_register_fetches(&sample_fetch_keywords);
907 sample_register_convs(&sample_conv_kws);
Willy Tarreau620408f2016-10-21 16:37:51 +0200908 tcp_req_sess_keywords_register(&tcp_req_sess_kws);
909 tcp_req_cont_keywords_register(&tcp_req_cont_kws);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200910 tcp_res_cont_keywords_register(&tcp_res_kws);
911 http_req_keywords_register(&http_req_kws);
912 http_res_keywords_register(&http_res_kws);
913 cfg_register_keywords(&cfg_kws);
Christopher Faulete95f2c32017-07-24 16:30:34 +0200914
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100915 HA_RWLOCK_INIT(&var_names_rwlock);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200916}