blob: 5787cf6edda223d3987874aaacb2c0f20d33a236 [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) {
Willy Tarreau843b7cb2018-07-13 10:54:26 +020098 free(var->data.u.str.area);
99 size += var->data.u.str.data;
Christopher Faulet85d79c92016-11-09 16:54:56 +0100100 }
Christopher Fauletd02210c2017-07-24 16:24:39 +0200101 else if (var->data.type == SMP_T_METH && var->data.u.meth.meth == HTTP_METH_OTHER) {
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200102 free(var->data.u.meth.str.area);
103 size += var->data.u.meth.str.data;
Christopher Faulet85d79c92016-11-09 16:54:56 +0100104 }
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 Fauleteb3e2762017-12-08 09:17:39 +0100177 return res;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200178 }
179
180 /* Check scope. */
Christopher Fauletff2613e2016-11-09 11:36:17 +0100181 if (len > 5 && strncmp(name, "proc.", 5) == 0) {
182 name += 5;
183 len -= 5;
184 *scope = SCOPE_PROC;
185 }
186 else if (len > 5 && strncmp(name, "sess.", 5) == 0) {
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200187 name += 5;
188 len -= 5;
189 *scope = SCOPE_SESS;
190 }
191 else if (len > 4 && strncmp(name, "txn.", 4) == 0) {
192 name += 4;
193 len -= 4;
194 *scope = SCOPE_TXN;
195 }
196 else if (len > 4 && strncmp(name, "req.", 4) == 0) {
197 name += 4;
198 len -= 4;
199 *scope = SCOPE_REQ;
200 }
201 else if (len > 4 && strncmp(name, "res.", 4) == 0) {
202 name += 4;
203 len -= 4;
204 *scope = SCOPE_RES;
205 }
206 else {
207 memprintf(err, "invalid variable name '%s'. A variable name must be start by its scope. "
Christopher Fauletff2613e2016-11-09 11:36:17 +0100208 "The scope can be 'proc', 'sess', 'txn', 'req' or 'res'", name);
Christopher Fauleteb3e2762017-12-08 09:17:39 +0100209 return res;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200210 }
211
Christopher Faulete95f2c32017-07-24 16:30:34 +0200212 if (alloc)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100213 HA_RWLOCK_WRLOCK(VARS_LOCK, &var_names_rwlock);
Christopher Faulete95f2c32017-07-24 16:30:34 +0200214 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100215 HA_RWLOCK_RDLOCK(VARS_LOCK, &var_names_rwlock);
Christopher Faulete95f2c32017-07-24 16:30:34 +0200216
217
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200218 /* Look for existing variable name. */
219 for (i = 0; i < var_names_nb; i++)
Christopher Faulete95f2c32017-07-24 16:30:34 +0200220 if (strncmp(var_names[i], name, len) == 0 && var_names[i][len] == '\0') {
221 res = var_names[i];
222 goto end;
223 }
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200224
Christopher Faulete95f2c32017-07-24 16:30:34 +0200225 if (!alloc) {
226 res = NULL;
227 goto end;
228 }
Christopher Faulet09c9df22016-10-31 11:05:37 +0100229
Hubert Verstraete831962e2016-06-28 22:44:26 +0200230 /* Store variable name. If realloc fails, var_names remains valid */
231 var_names2 = realloc(var_names, (var_names_nb + 1) * sizeof(*var_names));
232 if (!var_names2) {
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200233 memprintf(err, "out of memory error");
Christopher Faulete95f2c32017-07-24 16:30:34 +0200234 res = NULL;
235 goto end;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200236 }
Hubert Verstraete831962e2016-06-28 22:44:26 +0200237 var_names_nb++;
238 var_names = var_names2;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200239 var_names[var_names_nb - 1] = malloc(len + 1);
240 if (!var_names[var_names_nb - 1]) {
241 memprintf(err, "out of memory error");
Christopher Faulete95f2c32017-07-24 16:30:34 +0200242 res = NULL;
243 goto end;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200244 }
245 memcpy(var_names[var_names_nb - 1], name, len);
246 var_names[var_names_nb - 1][len] = '\0';
247
248 /* Check variable name syntax. */
249 tmp = var_names[var_names_nb - 1];
250 while (*tmp) {
Christopher Fauletb71557a2016-10-31 10:49:03 +0100251 if (!isalnum((int)(unsigned char)*tmp) && *tmp != '_' && *tmp != '.') {
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200252 memprintf(err, "invalid syntax at char '%s'", tmp);
Christopher Faulete95f2c32017-07-24 16:30:34 +0200253 res = NULL;
254 goto end;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200255 }
256 tmp++;
257 }
Christopher Faulete95f2c32017-07-24 16:30:34 +0200258 res = var_names[var_names_nb - 1];
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200259
Christopher Faulete95f2c32017-07-24 16:30:34 +0200260 end:
261 if (alloc)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100262 HA_RWLOCK_WRUNLOCK(VARS_LOCK, &var_names_rwlock);
Christopher Faulete95f2c32017-07-24 16:30:34 +0200263 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100264 HA_RWLOCK_RDUNLOCK(VARS_LOCK, &var_names_rwlock);
Christopher Faulete95f2c32017-07-24 16:30:34 +0200265
266 return res;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200267}
268
269/* This function returns an existing variable or returns NULL. */
270static inline struct var *var_get(struct vars *vars, const char *name)
271{
272 struct var *var;
273
274 list_for_each_entry(var, &vars->head, l)
275 if (var->name == name)
276 return var;
277 return NULL;
278}
279
280/* Returns 0 if fails, else returns 1. */
281static int smp_fetch_var(const struct arg *args, struct sample *smp, const char *kw, void *private)
282{
283 const struct var_desc *var_desc = &args[0].data.var;
284 struct var *var;
285 struct vars *vars;
286
287 /* Check the availibity of the variable. */
288 switch (var_desc->scope) {
Christopher Fauletff2613e2016-11-09 11:36:17 +0100289 case SCOPE_PROC:
290 vars = &global.vars;
291 break;
Willy Tarreau7513d002016-10-21 17:14:35 +0200292 case SCOPE_SESS:
293 vars = &smp->sess->vars;
294 break;
295 case SCOPE_TXN:
296 if (!smp->strm)
297 return 0;
298 vars = &smp->strm->vars_txn;
299 break;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200300 case SCOPE_REQ:
Thierry FOURNIER0b243fd2015-06-16 23:52:47 +0200301 case SCOPE_RES:
Willy Tarreau7513d002016-10-21 17:14:35 +0200302 default:
303 if (!smp->strm)
304 return 0;
305 vars = &smp->strm->vars_reqres;
306 break;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200307 }
308 if (vars->scope != var_desc->scope)
309 return 0;
Christopher Faulete95f2c32017-07-24 16:30:34 +0200310
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100311 HA_RWLOCK_RDLOCK(VARS_LOCK, &vars->rwlock);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200312 var = var_get(vars, var_desc->name);
313
314 /* check for the variable avalaibility */
Christopher Faulete95f2c32017-07-24 16:30:34 +0200315 if (!var) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100316 HA_RWLOCK_RDUNLOCK(VARS_LOCK, &vars->rwlock);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200317 return 0;
Christopher Faulete95f2c32017-07-24 16:30:34 +0200318 }
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200319
Christopher Faulete95f2c32017-07-24 16:30:34 +0200320 /* Duplicate the sample data because it could modified by another
321 * thread */
Thierry FOURNIER5cc18d42015-08-19 09:02:36 +0200322 smp->data = var->data;
Christopher Faulete95f2c32017-07-24 16:30:34 +0200323 smp_dup(smp);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200324 smp->flags |= SMP_F_CONST;
Christopher Faulete95f2c32017-07-24 16:30:34 +0200325
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100326 HA_RWLOCK_RDUNLOCK(VARS_LOCK, &vars->rwlock);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200327 return 1;
328}
329
330/* This function search in the <head> a variable with the same
331 * pointer value that the <name>. If the variable doesn't exists,
332 * create it. The function stores a copy of smp> if the variable.
333 * It returns 0 if fails, else returns 1.
334 */
Willy Tarreau6204cd92016-03-10 16:33:04 +0100335static int sample_store(struct vars *vars, const char *name, struct sample *smp)
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200336{
337 struct var *var;
338
339 /* Look for existing variable name. */
340 var = var_get(vars, name);
341
342 if (var) {
343 /* free its used memory. */
344 if (var->data.type == SMP_T_STR ||
345 var->data.type == SMP_T_BIN) {
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200346 free(var->data.u.str.area);
347 var_accounting_diff(vars, smp->sess, smp->strm,
348 -var->data.u.str.data);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200349 }
Christopher Fauletd02210c2017-07-24 16:24:39 +0200350 else if (var->data.type == SMP_T_METH && var->data.u.meth.meth == HTTP_METH_OTHER) {
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200351 free(var->data.u.meth.str.area);
352 var_accounting_diff(vars, smp->sess, smp->strm,
353 -var->data.u.meth.str.data);
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 Tarreau843b7cb2018-07-13 10:54:26 +0200386 if (!var_accounting_add(vars, smp->sess, smp->strm, smp->data.u.str.data)) {
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 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200390 var->data.u.str.area = malloc(smp->data.u.str.data);
391 if (!var->data.u.str.area) {
392 var_accounting_diff(vars, smp->sess, smp->strm,
393 -smp->data.u.str.data);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200394 var->data.type = SMP_T_BOOL; /* This type doesn't use additional memory. */
395 return 0;
396 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200397 var->data.u.str.data = smp->data.u.str.data;
398 memcpy(var->data.u.str.area, smp->data.u.str.area,
399 var->data.u.str.data);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200400 break;
401 case SMP_T_METH:
Christopher Fauletd02210c2017-07-24 16:24:39 +0200402 var->data.u.meth.meth = smp->data.u.meth.meth;
403 if (smp->data.u.meth.meth != HTTP_METH_OTHER)
404 break;
405
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200406 if (!var_accounting_add(vars, smp->sess, smp->strm, smp->data.u.meth.str.data)) {
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200407 var->data.type = SMP_T_BOOL; /* This type doesn't use additional memory. */
408 return 0;
409 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200410 var->data.u.meth.str.area = malloc(smp->data.u.meth.str.data);
411 if (!var->data.u.meth.str.area) {
412 var_accounting_diff(vars, smp->sess, smp->strm,
413 -smp->data.u.meth.str.data);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200414 var->data.type = SMP_T_BOOL; /* This type doesn't use additional memory. */
415 return 0;
416 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200417 var->data.u.meth.str.data = smp->data.u.meth.str.data;
418 var->data.u.meth.str.size = smp->data.u.meth.str.data;
419 memcpy(var->data.u.meth.str.area, smp->data.u.meth.str.area,
420 var->data.u.meth.str.data);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200421 break;
422 }
423 return 1;
424}
425
Willy Tarreau620408f2016-10-21 16:37:51 +0200426/* Returns 0 if fails, else returns 1. Note that stream may be null for SCOPE_SESS. */
Willy Tarreau6204cd92016-03-10 16:33:04 +0100427static inline int sample_store_stream(const char *name, enum vars_scope scope, struct sample *smp)
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200428{
429 struct vars *vars;
Christopher Faulete95f2c32017-07-24 16:30:34 +0200430 int ret;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200431
432 switch (scope) {
Christopher Fauletff2613e2016-11-09 11:36:17 +0100433 case SCOPE_PROC: vars = &global.vars; break;
Willy Tarreau6204cd92016-03-10 16:33:04 +0100434 case SCOPE_SESS: vars = &smp->sess->vars; break;
435 case SCOPE_TXN: vars = &smp->strm->vars_txn; break;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200436 case SCOPE_REQ:
Thierry FOURNIER0b243fd2015-06-16 23:52:47 +0200437 case SCOPE_RES:
Willy Tarreau6204cd92016-03-10 16:33:04 +0100438 default: vars = &smp->strm->vars_reqres; break;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200439 }
440 if (vars->scope != scope)
441 return 0;
Christopher Faulete95f2c32017-07-24 16:30:34 +0200442
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100443 HA_RWLOCK_WRLOCK(VARS_LOCK, &vars->rwlock);
Christopher Faulete95f2c32017-07-24 16:30:34 +0200444 ret = sample_store(vars, name, smp);
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100445 HA_RWLOCK_WRUNLOCK(VARS_LOCK, &vars->rwlock);
Christopher Faulete95f2c32017-07-24 16:30:34 +0200446 return ret;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200447}
448
Christopher Faulet85d79c92016-11-09 16:54:56 +0100449/* Returns 0 if fails, else returns 1. Note that stream may be null for SCOPE_SESS. */
450static inline int sample_clear_stream(const char *name, enum vars_scope scope, struct sample *smp)
451{
452 struct vars *vars;
453 struct var *var;
454 unsigned int size = 0;
455
456 switch (scope) {
457 case SCOPE_PROC: vars = &global.vars; break;
458 case SCOPE_SESS: vars = &smp->sess->vars; break;
459 case SCOPE_TXN: vars = &smp->strm->vars_txn; break;
460 case SCOPE_REQ:
461 case SCOPE_RES:
462 default: vars = &smp->strm->vars_reqres; break;
463 }
464 if (vars->scope != scope)
465 return 0;
466
467 /* Look for existing variable name. */
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100468 HA_RWLOCK_WRLOCK(VARS_LOCK, &vars->rwlock);
Christopher Faulet85d79c92016-11-09 16:54:56 +0100469 var = var_get(vars, name);
470 if (var) {
471 size = var_clear(var);
472 var_accounting_diff(vars, smp->sess, smp->strm, -size);
473 }
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100474 HA_RWLOCK_WRUNLOCK(VARS_LOCK, &vars->rwlock);
Christopher Faulet85d79c92016-11-09 16:54:56 +0100475 return 1;
476}
477
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200478/* Returns 0 if fails, else returns 1. */
479static int smp_conv_store(const struct arg *args, struct sample *smp, void *private)
480{
Christopher Faulet0099a8c2016-11-09 16:15:32 +0100481 return sample_store_stream(args[0].data.var.name, args[0].data.var.scope, smp);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200482}
483
Christopher Faulet85d79c92016-11-09 16:54:56 +0100484/* Returns 0 if fails, else returns 1. */
485static int smp_conv_clear(const struct arg *args, struct sample *smp, void *private)
486{
487 return sample_clear_stream(args[0].data.var.name, args[0].data.var.scope, smp);
488}
489
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200490/* This fucntions check an argument entry and fill it with a variable
491 * type. The argumen must be a string. If the variable lookup fails,
492 * the function retuns 0 and fill <err>, otherwise it returns 1.
493 */
494int vars_check_arg(struct arg *arg, char **err)
495{
496 char *name;
497 enum vars_scope scope;
498
499 /* Check arg type. */
500 if (arg->type != ARGT_STR) {
501 memprintf(err, "unexpected argument type");
502 return 0;
503 }
504
505 /* Register new variable name. */
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200506 name = register_name(arg->data.str.area, arg->data.str.data, &scope,
507 1,
508 err);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200509 if (!name)
510 return 0;
511
512 /* Use the global variable name pointer. */
513 arg->type = ARGT_VAR;
514 arg->data.var.name = name;
515 arg->data.var.scope = scope;
516 return 1;
517}
518
Christopher Faulet09c9df22016-10-31 11:05:37 +0100519/* This function store a sample in a variable if it was already defined.
520 * In error case, it fails silently.
521 */
522void vars_set_by_name_ifexist(const char *name, size_t len, struct sample *smp)
523{
524 enum vars_scope scope;
525
526 /* Resolve name and scope. */
527 name = register_name(name, len, &scope, 0, NULL);
528 if (!name)
529 return;
530
531 sample_store_stream(name, scope, smp);
532}
533
534
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200535/* This function store a sample in a variable.
536 * In error case, it fails silently.
537 */
Willy Tarreau6204cd92016-03-10 16:33:04 +0100538void vars_set_by_name(const char *name, size_t len, struct sample *smp)
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200539{
540 enum vars_scope scope;
541
542 /* Resolve name and scope. */
Christopher Faulet09c9df22016-10-31 11:05:37 +0100543 name = register_name(name, len, &scope, 1, NULL);
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200544 if (!name)
545 return;
546
Willy Tarreau6204cd92016-03-10 16:33:04 +0100547 sample_store_stream(name, scope, smp);
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200548}
549
Christopher Faulet85d79c92016-11-09 16:54:56 +0100550/* This function unset a variable if it was already defined.
551 * In error case, it fails silently.
552 */
553void vars_unset_by_name_ifexist(const char *name, size_t len, struct sample *smp)
554{
555 enum vars_scope scope;
556
557 /* Resolve name and scope. */
558 name = register_name(name, len, &scope, 0, NULL);
559 if (!name)
560 return;
561
562 sample_clear_stream(name, scope, smp);
563}
564
565
566/* This function unset a variable.
567 * In error case, it fails silently.
568 */
569void vars_unset_by_name(const char *name, size_t len, struct sample *smp)
570{
571 enum vars_scope scope;
572
573 /* Resolve name and scope. */
574 name = register_name(name, len, &scope, 1, NULL);
575 if (!name)
576 return;
577
578 sample_clear_stream(name, scope, smp);
579}
580
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200581/* this function fills a sample with the
582 * variable content. Returns 1 if the sample
583 * is filled, otherwise it returns 0.
584 */
Willy Tarreau6204cd92016-03-10 16:33:04 +0100585int vars_get_by_name(const char *name, size_t len, struct sample *smp)
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200586{
587 struct vars *vars;
588 struct var *var;
589 enum vars_scope scope;
590
591 /* Resolve name and scope. */
Christopher Faulet09c9df22016-10-31 11:05:37 +0100592 name = register_name(name, len, &scope, 1, NULL);
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200593 if (!name)
594 return 0;
595
596 /* Select "vars" pool according with the scope. */
597 switch (scope) {
Christopher Fauletff2613e2016-11-09 11:36:17 +0100598 case SCOPE_PROC: vars = &global.vars; break;
Willy Tarreau6204cd92016-03-10 16:33:04 +0100599 case SCOPE_SESS: vars = &smp->sess->vars; break;
600 case SCOPE_TXN: vars = &smp->strm->vars_txn; break;
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200601 case SCOPE_REQ:
Thierry FOURNIER0b243fd2015-06-16 23:52:47 +0200602 case SCOPE_RES:
Willy Tarreau6204cd92016-03-10 16:33:04 +0100603 default: vars = &smp->strm->vars_reqres; break;
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200604 }
605
606 /* Check if the scope is avalaible a this point of processing. */
607 if (vars->scope != scope)
608 return 0;
609
610 /* Get the variable entry. */
611 var = var_get(vars, name);
612 if (!var)
613 return 0;
614
615 /* Copy sample. */
Thierry FOURNIER5cc18d42015-08-19 09:02:36 +0200616 smp->data = var->data;
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200617 smp->flags = SMP_F_CONST;
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200618 return 1;
619}
620
Thierry FOURNIERfd77e052015-07-07 21:20:42 +0200621/* this function fills a sample with the
622 * content of the varaible described by <var_desc>. Returns 1
623 * if the sample is filled, otherwise it returns 0.
624 */
Willy Tarreau6204cd92016-03-10 16:33:04 +0100625int vars_get_by_desc(const struct var_desc *var_desc, struct sample *smp)
Thierry FOURNIERfd77e052015-07-07 21:20:42 +0200626{
627 struct vars *vars;
628 struct var *var;
629
630 /* Select "vars" pool according with the scope. */
631 switch (var_desc->scope) {
Christopher Fauletff2613e2016-11-09 11:36:17 +0100632 case SCOPE_PROC: vars = &global.vars; break;
Willy Tarreau6204cd92016-03-10 16:33:04 +0100633 case SCOPE_SESS: vars = &smp->sess->vars; break;
634 case SCOPE_TXN: vars = &smp->strm->vars_txn; break;
Thierry FOURNIERfd77e052015-07-07 21:20:42 +0200635 case SCOPE_REQ:
636 case SCOPE_RES:
Willy Tarreau6204cd92016-03-10 16:33:04 +0100637 default: vars = &smp->strm->vars_reqres; break;
Thierry FOURNIERfd77e052015-07-07 21:20:42 +0200638 }
639
640 /* Check if the scope is avalaible a this point of processing. */
641 if (vars->scope != var_desc->scope)
642 return 0;
643
644 /* Get the variable entry. */
645 var = var_get(vars, var_desc->name);
646 if (!var)
647 return 0;
648
649 /* Copy sample. */
Thierry FOURNIER5cc18d42015-08-19 09:02:36 +0200650 smp->data = var->data;
Thierry FOURNIERfd77e052015-07-07 21:20:42 +0200651 smp->flags = SMP_F_CONST;
Thierry FOURNIERfd77e052015-07-07 21:20:42 +0200652 return 1;
653}
654
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200655/* Always returns ACT_RET_CONT even if an error occurs. */
656static enum act_return action_store(struct act_rule *rule, struct proxy *px,
Willy Tarreau658b85b2015-09-27 10:00:49 +0200657 struct session *sess, struct stream *s, int flags)
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200658{
659 struct sample smp;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200660 int dir;
661
662 switch (rule->from) {
Willy Tarreau620408f2016-10-21 16:37:51 +0200663 case ACT_F_TCP_REQ_SES: dir = SMP_OPT_DIR_REQ; break;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200664 case ACT_F_TCP_REQ_CNT: dir = SMP_OPT_DIR_REQ; break;
665 case ACT_F_TCP_RES_CNT: dir = SMP_OPT_DIR_RES; break;
666 case ACT_F_HTTP_REQ: dir = SMP_OPT_DIR_REQ; break;
667 case ACT_F_HTTP_RES: dir = SMP_OPT_DIR_RES; break;
668 default:
669 send_log(px, LOG_ERR, "Vars: internal error while execute action store.");
670 if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))
Christopher Faulet767a84b2017-11-24 16:50:31 +0100671 ha_alert("Vars: internal error while execute action store.\n");
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200672 return ACT_RET_CONT;
673 }
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200674
675 /* Process the expression. */
676 memset(&smp, 0, sizeof(smp));
Willy Tarreau108a8fd2016-10-21 17:13:24 +0200677 if (!sample_process(px, sess, s, dir|SMP_OPT_FINAL,
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200678 rule->arg.vars.expr, &smp))
Thierry FOURNIER24ff6c62015-08-06 08:52:53 +0200679 return ACT_RET_CONT;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200680
681 /* Store the sample, and ignore errors. */
Willy Tarreau6204cd92016-03-10 16:33:04 +0100682 sample_store_stream(rule->arg.vars.name, rule->arg.vars.scope, &smp);
Thierry FOURNIER24ff6c62015-08-06 08:52:53 +0200683 return ACT_RET_CONT;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200684}
685
Christopher Faulet85d79c92016-11-09 16:54:56 +0100686/* Always returns ACT_RET_CONT even if an error occurs. */
687static enum act_return action_clear(struct act_rule *rule, struct proxy *px,
688 struct session *sess, struct stream *s, int flags)
689{
690 struct sample smp;
691
692 memset(&smp, 0, sizeof(smp));
693 smp_set_owner(&smp, px, sess, s, SMP_OPT_FINAL);
694
695 /* Clear the variable using the sample context, and ignore errors. */
696 sample_clear_stream(rule->arg.vars.name, rule->arg.vars.scope, &smp);
697 return ACT_RET_CONT;
698}
699
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200700/* This two function checks the variable name and replace the
701 * configuration string name by the global string name. its
702 * the same string, but the global pointer can be easy to
703 * compare.
704 *
705 * The first function checks a sample-fetch and the second
706 * checks a converter.
707 */
708static int smp_check_var(struct arg *args, char **err)
709{
710 return vars_check_arg(&args[0], err);
711}
712
713static int conv_check_var(struct arg *args, struct sample_conv *conv,
714 const char *file, int line, char **err_msg)
715{
716 return vars_check_arg(&args[0], err_msg);
717}
718
719/* This function is a common parser for using variables. It understands
720 * the format:
721 *
722 * set-var(<variable-name>) <expression>
723 *
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200724 * It returns ACT_RET_PRS_ERR if fails and <err> is filled with an error
725 * message. Otherwise, it returns ACT_RET_PRS_OK and the variable <expr>
726 * is filled with the pointer to the expression to execute.
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200727 */
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200728static enum act_parse_ret parse_store(const char **args, int *arg, struct proxy *px,
729 struct act_rule *rule, char **err)
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200730{
731 const char *var_name = args[*arg-1];
732 int var_len;
Thierry FOURNIER48a9cd12015-07-28 19:00:28 +0200733 const char *kw_name;
Willy Tarreaue3658152016-11-24 21:23:28 +0100734 int flags, set_var = 0;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200735
Christopher Faulet85d79c92016-11-09 16:54:56 +0100736 if (!strncmp(var_name, "set-var", 7)) {
737 var_name += 7;
738 set_var = 1;
739 }
740 if (!strncmp(var_name, "unset-var", 9)) {
741 var_name += 9;
742 set_var = 0;
743 }
744
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200745 if (*var_name != '(') {
Christopher Faulet85d79c92016-11-09 16:54:56 +0100746 memprintf(err, "invalid variable '%s'. Expects 'set-var(<var-name>)' or 'unset-var(<var-name>)'",
747 args[*arg-1]);
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200748 return ACT_RET_PRS_ERR;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200749 }
750 var_name++; /* jump the '(' */
751 var_len = strlen(var_name);
752 var_len--; /* remove the ')' */
753 if (var_name[var_len] != ')') {
Christopher Faulet85d79c92016-11-09 16:54:56 +0100754 memprintf(err, "invalid variable '%s'. Expects 'set-var(<var-name>)' or 'unset-var(<var-name>)'",
755 args[*arg-1]);
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200756 return ACT_RET_PRS_ERR;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200757 }
758
Christopher Faulet09c9df22016-10-31 11:05:37 +0100759 rule->arg.vars.name = register_name(var_name, var_len, &rule->arg.vars.scope, 1, err);
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200760 if (!rule->arg.vars.name)
761 return ACT_RET_PRS_ERR;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200762
Christopher Faulet85d79c92016-11-09 16:54:56 +0100763 /* There is no fetch method when variable is unset. Just set the right
764 * action and return. */
765 if (!set_var) {
766 if (*args[*arg]) {
767 memprintf(err, "fetch method not supported");
768 return ACT_RET_PRS_ERR;
769 }
770 rule->action = ACT_CUSTOM;
771 rule->action_ptr = action_clear;
772 return ACT_RET_PRS_OK;
773 }
774
Thierry FOURNIER48a9cd12015-07-28 19:00:28 +0200775 kw_name = args[*arg-1];
776
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200777 rule->arg.vars.expr = sample_parse_expr((char **)args, arg, px->conf.args.file,
778 px->conf.args.line, err, &px->conf.args);
779 if (!rule->arg.vars.expr)
Thierry FOURNIERafa80492015-08-19 09:04:15 +0200780 return ACT_RET_PRS_ERR;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200781
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200782 switch (rule->from) {
Willy Tarreau620408f2016-10-21 16:37:51 +0200783 case ACT_F_TCP_REQ_SES: flags = SMP_VAL_FE_SES_ACC; break;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200784 case ACT_F_TCP_REQ_CNT: flags = SMP_VAL_FE_REQ_CNT; break;
785 case ACT_F_TCP_RES_CNT: flags = SMP_VAL_BE_RES_CNT; break;
786 case ACT_F_HTTP_REQ: flags = SMP_VAL_FE_HRQ_HDR; break;
787 case ACT_F_HTTP_RES: flags = SMP_VAL_BE_HRS_HDR; break;
788 default:
789 memprintf(err,
790 "internal error, unexpected rule->from=%d, please report this bug!",
791 rule->from);
Thierry FOURNIERafa80492015-08-19 09:04:15 +0200792 return ACT_RET_PRS_ERR;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200793 }
794 if (!(rule->arg.vars.expr->fetch->val & flags)) {
795 memprintf(err,
796 "fetch method '%s' extracts information from '%s', none of which is available here",
797 kw_name, sample_src_names(rule->arg.vars.expr->fetch->use));
798 free(rule->arg.vars.expr);
Thierry FOURNIERafa80492015-08-19 09:04:15 +0200799 return ACT_RET_PRS_ERR;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200800 }
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200801
Thierry FOURNIER42148732015-09-02 17:17:33 +0200802 rule->action = ACT_CUSTOM;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200803 rule->action_ptr = action_store;
Thierry FOURNIERafa80492015-08-19 09:04:15 +0200804 return ACT_RET_PRS_OK;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200805}
806
807static int vars_max_size(char **args, int section_type, struct proxy *curpx,
808 struct proxy *defpx, const char *file, int line,
809 char **err, unsigned int *limit)
810{
811 char *error;
812
813 *limit = strtol(args[1], &error, 10);
814 if (*error != 0) {
815 memprintf(err, "%s: '%s' is an invalid size", args[0], args[1]);
816 return -1;
817 }
818 return 0;
819}
820
821static int vars_max_size_global(char **args, int section_type, struct proxy *curpx,
822 struct proxy *defpx, const char *file, int line,
823 char **err)
824{
825 return vars_max_size(args, section_type, curpx, defpx, file, line, err, &var_global_limit);
826}
827
Christopher Fauletff2613e2016-11-09 11:36:17 +0100828static int vars_max_size_proc(char **args, int section_type, struct proxy *curpx,
829 struct proxy *defpx, const char *file, int line,
830 char **err)
831{
832 return vars_max_size(args, section_type, curpx, defpx, file, line, err, &var_proc_limit);
833}
834
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200835static int vars_max_size_sess(char **args, int section_type, struct proxy *curpx,
836 struct proxy *defpx, const char *file, int line,
837 char **err)
838{
839 return vars_max_size(args, section_type, curpx, defpx, file, line, err, &var_sess_limit);
840}
841
842static int vars_max_size_txn(char **args, int section_type, struct proxy *curpx,
843 struct proxy *defpx, const char *file, int line,
844 char **err)
845{
846 return vars_max_size(args, section_type, curpx, defpx, file, line, err, &var_txn_limit);
847}
848
849static int vars_max_size_reqres(char **args, int section_type, struct proxy *curpx,
850 struct proxy *defpx, const char *file, int line,
851 char **err)
852{
853 return vars_max_size(args, section_type, curpx, defpx, file, line, err, &var_reqres_limit);
854}
855
856static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
857
Christopher Fauletff2613e2016-11-09 11:36:17 +0100858 { "var", smp_fetch_var, ARG1(1,STR), smp_check_var, SMP_T_STR, SMP_USE_L4CLI },
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200859 { /* END */ },
860}};
861
862static struct sample_conv_kw_list sample_conv_kws = {ILH, {
Christopher Faulet85d79c92016-11-09 16:54:56 +0100863 { "set-var", smp_conv_store, ARG1(1,STR), conv_check_var, SMP_T_ANY, SMP_T_ANY },
864 { "unset-var", smp_conv_clear, ARG1(1,STR), conv_check_var, SMP_T_ANY, SMP_T_ANY },
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200865 { /* END */ },
866}};
867
Willy Tarreau620408f2016-10-21 16:37:51 +0200868static struct action_kw_list tcp_req_sess_kws = { { }, {
Christopher Faulet85d79c92016-11-09 16:54:56 +0100869 { "set-var", parse_store, 1 },
870 { "unset-var", parse_store, 1 },
Willy Tarreau620408f2016-10-21 16:37:51 +0200871 { /* END */ }
872}};
873
874static struct action_kw_list tcp_req_cont_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 tcp_res_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_req_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
Thierry FOURNIER36481b82015-08-19 09:01:53 +0200892static struct action_kw_list http_res_kws = { { }, {
Christopher Faulet85d79c92016-11-09 16:54:56 +0100893 { "set-var", parse_store, 1 },
894 { "unset-var", parse_store, 1 },
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200895 { /* END */ }
896}};
897
898static struct cfg_kw_list cfg_kws = {{ },{
899 { CFG_GLOBAL, "tune.vars.global-max-size", vars_max_size_global },
Christopher Fauletff2613e2016-11-09 11:36:17 +0100900 { CFG_GLOBAL, "tune.vars.proc-max-size", vars_max_size_proc },
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200901 { CFG_GLOBAL, "tune.vars.sess-max-size", vars_max_size_sess },
902 { CFG_GLOBAL, "tune.vars.txn-max-size", vars_max_size_txn },
903 { CFG_GLOBAL, "tune.vars.reqres-max-size", vars_max_size_reqres },
904 { /* END */ }
905}};
906
907__attribute__((constructor))
Christopher Faulete95f2c32017-07-24 16:30:34 +0200908static void __vars_init(void)
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200909{
910 var_pool = create_pool("vars", sizeof(struct var), MEM_F_SHARED);
911
912 sample_register_fetches(&sample_fetch_keywords);
913 sample_register_convs(&sample_conv_kws);
Willy Tarreau620408f2016-10-21 16:37:51 +0200914 tcp_req_sess_keywords_register(&tcp_req_sess_kws);
915 tcp_req_cont_keywords_register(&tcp_req_cont_kws);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200916 tcp_res_cont_keywords_register(&tcp_res_kws);
917 http_req_keywords_register(&http_req_kws);
918 http_res_keywords_register(&http_res_kws);
919 cfg_register_keywords(&cfg_kws);
Christopher Faulete95f2c32017-07-24 16:30:34 +0200920
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100921 HA_RWLOCK_INIT(&var_names_rwlock);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200922}