blob: 566ead6ec1ad48cf701eed22193d07ed4e7a3250 [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 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) {
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200346 free(var->data.u.str.str);
Willy Tarreau6204cd92016-03-10 16:33:04 +0100347 var_accounting_diff(vars, smp->sess, smp->strm, -var->data.u.str.len);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200348 }
Christopher Fauletd02210c2017-07-24 16:24:39 +0200349 else if (var->data.type == SMP_T_METH && var->data.u.meth.meth == HTTP_METH_OTHER) {
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200350 free(var->data.u.meth.str.str);
Willy Tarreau6204cd92016-03-10 16:33:04 +0100351 var_accounting_diff(vars, smp->sess, smp->strm, -var->data.u.meth.str.len);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200352 }
353 } else {
354
355 /* Check memory avalaible. */
Willy Tarreau6204cd92016-03-10 16:33:04 +0100356 if (!var_accounting_add(vars, smp->sess, smp->strm, sizeof(struct var)))
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200357 return 0;
358
359 /* Create new entry. */
Willy Tarreaubafbe012017-11-24 17:34:44 +0100360 var = pool_alloc(var_pool);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200361 if (!var)
362 return 0;
363 LIST_ADDQ(&vars->head, &var->l);
364 var->name = name;
365 }
366
367 /* Set type. */
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +0200368 var->data.type = smp->data.type;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200369
370 /* Copy data. If the data needs memory, the function can fail. */
371 switch (var->data.type) {
372 case SMP_T_BOOL:
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200373 case SMP_T_SINT:
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200374 var->data.u.sint = smp->data.u.sint;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200375 break;
376 case SMP_T_IPV4:
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200377 var->data.u.ipv4 = smp->data.u.ipv4;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200378 break;
379 case SMP_T_IPV6:
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200380 var->data.u.ipv6 = smp->data.u.ipv6;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200381 break;
382 case SMP_T_STR:
383 case SMP_T_BIN:
Willy Tarreau6204cd92016-03-10 16:33:04 +0100384 if (!var_accounting_add(vars, smp->sess, smp->strm, smp->data.u.str.len)) {
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200385 var->data.type = SMP_T_BOOL; /* This type doesn't use additional memory. */
386 return 0;
387 }
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200388 var->data.u.str.str = malloc(smp->data.u.str.len);
389 if (!var->data.u.str.str) {
Willy Tarreau6204cd92016-03-10 16:33:04 +0100390 var_accounting_diff(vars, smp->sess, smp->strm, -smp->data.u.str.len);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200391 var->data.type = SMP_T_BOOL; /* This type doesn't use additional memory. */
392 return 0;
393 }
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200394 var->data.u.str.len = smp->data.u.str.len;
395 memcpy(var->data.u.str.str, smp->data.u.str.str, var->data.u.str.len);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200396 break;
397 case SMP_T_METH:
Christopher Fauletd02210c2017-07-24 16:24:39 +0200398 var->data.u.meth.meth = smp->data.u.meth.meth;
399 if (smp->data.u.meth.meth != HTTP_METH_OTHER)
400 break;
401
Willy Tarreau6204cd92016-03-10 16:33:04 +0100402 if (!var_accounting_add(vars, smp->sess, smp->strm, smp->data.u.meth.str.len)) {
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200403 var->data.type = SMP_T_BOOL; /* This type doesn't use additional memory. */
404 return 0;
405 }
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200406 var->data.u.meth.str.str = malloc(smp->data.u.meth.str.len);
407 if (!var->data.u.meth.str.str) {
Willy Tarreau6204cd92016-03-10 16:33:04 +0100408 var_accounting_diff(vars, smp->sess, smp->strm, -smp->data.u.meth.str.len);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200409 var->data.type = SMP_T_BOOL; /* This type doesn't use additional memory. */
410 return 0;
411 }
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200412 var->data.u.meth.str.len = smp->data.u.meth.str.len;
413 var->data.u.meth.str.size = smp->data.u.meth.str.len;
414 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 +0200415 break;
416 }
417 return 1;
418}
419
Willy Tarreau620408f2016-10-21 16:37:51 +0200420/* Returns 0 if fails, else returns 1. Note that stream may be null for SCOPE_SESS. */
Willy Tarreau6204cd92016-03-10 16:33:04 +0100421static inline int sample_store_stream(const char *name, enum vars_scope scope, struct sample *smp)
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200422{
423 struct vars *vars;
Christopher Faulete95f2c32017-07-24 16:30:34 +0200424 int ret;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200425
426 switch (scope) {
Christopher Fauletff2613e2016-11-09 11:36:17 +0100427 case SCOPE_PROC: vars = &global.vars; break;
Willy Tarreau6204cd92016-03-10 16:33:04 +0100428 case SCOPE_SESS: vars = &smp->sess->vars; break;
429 case SCOPE_TXN: vars = &smp->strm->vars_txn; break;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200430 case SCOPE_REQ:
Thierry FOURNIER0b243fd2015-06-16 23:52:47 +0200431 case SCOPE_RES:
Willy Tarreau6204cd92016-03-10 16:33:04 +0100432 default: vars = &smp->strm->vars_reqres; break;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200433 }
434 if (vars->scope != scope)
435 return 0;
Christopher Faulete95f2c32017-07-24 16:30:34 +0200436
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100437 HA_RWLOCK_WRLOCK(VARS_LOCK, &vars->rwlock);
Christopher Faulete95f2c32017-07-24 16:30:34 +0200438 ret = sample_store(vars, name, smp);
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100439 HA_RWLOCK_WRUNLOCK(VARS_LOCK, &vars->rwlock);
Christopher Faulete95f2c32017-07-24 16:30:34 +0200440 return ret;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200441}
442
Christopher Faulet85d79c92016-11-09 16:54:56 +0100443/* Returns 0 if fails, else returns 1. Note that stream may be null for SCOPE_SESS. */
444static inline int sample_clear_stream(const char *name, enum vars_scope scope, struct sample *smp)
445{
446 struct vars *vars;
447 struct var *var;
448 unsigned int size = 0;
449
450 switch (scope) {
451 case SCOPE_PROC: vars = &global.vars; break;
452 case SCOPE_SESS: vars = &smp->sess->vars; break;
453 case SCOPE_TXN: vars = &smp->strm->vars_txn; break;
454 case SCOPE_REQ:
455 case SCOPE_RES:
456 default: vars = &smp->strm->vars_reqres; break;
457 }
458 if (vars->scope != scope)
459 return 0;
460
461 /* Look for existing variable name. */
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100462 HA_RWLOCK_WRLOCK(VARS_LOCK, &vars->rwlock);
Christopher Faulet85d79c92016-11-09 16:54:56 +0100463 var = var_get(vars, name);
464 if (var) {
465 size = var_clear(var);
466 var_accounting_diff(vars, smp->sess, smp->strm, -size);
467 }
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100468 HA_RWLOCK_WRUNLOCK(VARS_LOCK, &vars->rwlock);
Christopher Faulet85d79c92016-11-09 16:54:56 +0100469 return 1;
470}
471
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200472/* Returns 0 if fails, else returns 1. */
473static int smp_conv_store(const struct arg *args, struct sample *smp, void *private)
474{
Christopher Faulet0099a8c2016-11-09 16:15:32 +0100475 return sample_store_stream(args[0].data.var.name, args[0].data.var.scope, smp);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200476}
477
Christopher Faulet85d79c92016-11-09 16:54:56 +0100478/* Returns 0 if fails, else returns 1. */
479static int smp_conv_clear(const struct arg *args, struct sample *smp, void *private)
480{
481 return sample_clear_stream(args[0].data.var.name, args[0].data.var.scope, smp);
482}
483
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200484/* This fucntions check an argument entry and fill it with a variable
485 * type. The argumen must be a string. If the variable lookup fails,
486 * the function retuns 0 and fill <err>, otherwise it returns 1.
487 */
488int vars_check_arg(struct arg *arg, char **err)
489{
490 char *name;
491 enum vars_scope scope;
492
493 /* Check arg type. */
494 if (arg->type != ARGT_STR) {
495 memprintf(err, "unexpected argument type");
496 return 0;
497 }
498
499 /* Register new variable name. */
Christopher Faulet09c9df22016-10-31 11:05:37 +0100500 name = register_name(arg->data.str.str, arg->data.str.len, &scope, 1, err);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200501 if (!name)
502 return 0;
503
504 /* Use the global variable name pointer. */
505 arg->type = ARGT_VAR;
506 arg->data.var.name = name;
507 arg->data.var.scope = scope;
508 return 1;
509}
510
Christopher Faulet09c9df22016-10-31 11:05:37 +0100511/* This function store a sample in a variable if it was already defined.
512 * In error case, it fails silently.
513 */
514void vars_set_by_name_ifexist(const char *name, size_t len, struct sample *smp)
515{
516 enum vars_scope scope;
517
518 /* Resolve name and scope. */
519 name = register_name(name, len, &scope, 0, NULL);
520 if (!name)
521 return;
522
523 sample_store_stream(name, scope, smp);
524}
525
526
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200527/* This function store a sample in a variable.
528 * In error case, it fails silently.
529 */
Willy Tarreau6204cd92016-03-10 16:33:04 +0100530void vars_set_by_name(const char *name, size_t len, struct sample *smp)
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200531{
532 enum vars_scope scope;
533
534 /* Resolve name and scope. */
Christopher Faulet09c9df22016-10-31 11:05:37 +0100535 name = register_name(name, len, &scope, 1, NULL);
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200536 if (!name)
537 return;
538
Willy Tarreau6204cd92016-03-10 16:33:04 +0100539 sample_store_stream(name, scope, smp);
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200540}
541
Christopher Faulet85d79c92016-11-09 16:54:56 +0100542/* This function unset a variable if it was already defined.
543 * In error case, it fails silently.
544 */
545void vars_unset_by_name_ifexist(const char *name, size_t len, struct sample *smp)
546{
547 enum vars_scope scope;
548
549 /* Resolve name and scope. */
550 name = register_name(name, len, &scope, 0, NULL);
551 if (!name)
552 return;
553
554 sample_clear_stream(name, scope, smp);
555}
556
557
558/* This function unset a variable.
559 * In error case, it fails silently.
560 */
561void vars_unset_by_name(const char *name, size_t len, struct sample *smp)
562{
563 enum vars_scope scope;
564
565 /* Resolve name and scope. */
566 name = register_name(name, len, &scope, 1, NULL);
567 if (!name)
568 return;
569
570 sample_clear_stream(name, scope, smp);
571}
572
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200573/* this function fills a sample with the
574 * variable content. Returns 1 if the sample
575 * is filled, otherwise it returns 0.
576 */
Willy Tarreau6204cd92016-03-10 16:33:04 +0100577int vars_get_by_name(const char *name, size_t len, struct sample *smp)
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200578{
579 struct vars *vars;
580 struct var *var;
581 enum vars_scope scope;
582
583 /* Resolve name and scope. */
Christopher Faulet09c9df22016-10-31 11:05:37 +0100584 name = register_name(name, len, &scope, 1, NULL);
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200585 if (!name)
586 return 0;
587
588 /* Select "vars" pool according with the scope. */
589 switch (scope) {
Christopher Fauletff2613e2016-11-09 11:36:17 +0100590 case SCOPE_PROC: vars = &global.vars; break;
Willy Tarreau6204cd92016-03-10 16:33:04 +0100591 case SCOPE_SESS: vars = &smp->sess->vars; break;
592 case SCOPE_TXN: vars = &smp->strm->vars_txn; break;
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200593 case SCOPE_REQ:
Thierry FOURNIER0b243fd2015-06-16 23:52:47 +0200594 case SCOPE_RES:
Willy Tarreau6204cd92016-03-10 16:33:04 +0100595 default: vars = &smp->strm->vars_reqres; break;
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200596 }
597
598 /* Check if the scope is avalaible a this point of processing. */
599 if (vars->scope != scope)
600 return 0;
601
602 /* Get the variable entry. */
603 var = var_get(vars, name);
604 if (!var)
605 return 0;
606
607 /* Copy sample. */
Thierry FOURNIER5cc18d42015-08-19 09:02:36 +0200608 smp->data = var->data;
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200609 smp->flags = SMP_F_CONST;
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200610 return 1;
611}
612
Thierry FOURNIERfd77e052015-07-07 21:20:42 +0200613/* this function fills a sample with the
614 * content of the varaible described by <var_desc>. Returns 1
615 * if the sample is filled, otherwise it returns 0.
616 */
Willy Tarreau6204cd92016-03-10 16:33:04 +0100617int vars_get_by_desc(const struct var_desc *var_desc, struct sample *smp)
Thierry FOURNIERfd77e052015-07-07 21:20:42 +0200618{
619 struct vars *vars;
620 struct var *var;
621
622 /* Select "vars" pool according with the scope. */
623 switch (var_desc->scope) {
Christopher Fauletff2613e2016-11-09 11:36:17 +0100624 case SCOPE_PROC: vars = &global.vars; break;
Willy Tarreau6204cd92016-03-10 16:33:04 +0100625 case SCOPE_SESS: vars = &smp->sess->vars; break;
626 case SCOPE_TXN: vars = &smp->strm->vars_txn; break;
Thierry FOURNIERfd77e052015-07-07 21:20:42 +0200627 case SCOPE_REQ:
628 case SCOPE_RES:
Willy Tarreau6204cd92016-03-10 16:33:04 +0100629 default: vars = &smp->strm->vars_reqres; break;
Thierry FOURNIERfd77e052015-07-07 21:20:42 +0200630 }
631
632 /* Check if the scope is avalaible a this point of processing. */
633 if (vars->scope != var_desc->scope)
634 return 0;
635
636 /* Get the variable entry. */
637 var = var_get(vars, var_desc->name);
638 if (!var)
639 return 0;
640
641 /* Copy sample. */
Thierry FOURNIER5cc18d42015-08-19 09:02:36 +0200642 smp->data = var->data;
Thierry FOURNIERfd77e052015-07-07 21:20:42 +0200643 smp->flags = SMP_F_CONST;
Thierry FOURNIERfd77e052015-07-07 21:20:42 +0200644 return 1;
645}
646
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200647/* Always returns ACT_RET_CONT even if an error occurs. */
648static enum act_return action_store(struct act_rule *rule, struct proxy *px,
Willy Tarreau658b85b2015-09-27 10:00:49 +0200649 struct session *sess, struct stream *s, int flags)
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200650{
651 struct sample smp;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200652 int dir;
653
654 switch (rule->from) {
Willy Tarreau620408f2016-10-21 16:37:51 +0200655 case ACT_F_TCP_REQ_SES: dir = SMP_OPT_DIR_REQ; break;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200656 case ACT_F_TCP_REQ_CNT: dir = SMP_OPT_DIR_REQ; break;
657 case ACT_F_TCP_RES_CNT: dir = SMP_OPT_DIR_RES; break;
658 case ACT_F_HTTP_REQ: dir = SMP_OPT_DIR_REQ; break;
659 case ACT_F_HTTP_RES: dir = SMP_OPT_DIR_RES; break;
660 default:
661 send_log(px, LOG_ERR, "Vars: internal error while execute action store.");
662 if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))
Christopher Faulet767a84b2017-11-24 16:50:31 +0100663 ha_alert("Vars: internal error while execute action store.\n");
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200664 return ACT_RET_CONT;
665 }
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200666
667 /* Process the expression. */
668 memset(&smp, 0, sizeof(smp));
Willy Tarreau108a8fd2016-10-21 17:13:24 +0200669 if (!sample_process(px, sess, s, dir|SMP_OPT_FINAL,
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200670 rule->arg.vars.expr, &smp))
Thierry FOURNIER24ff6c62015-08-06 08:52:53 +0200671 return ACT_RET_CONT;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200672
673 /* Store the sample, and ignore errors. */
Willy Tarreau6204cd92016-03-10 16:33:04 +0100674 sample_store_stream(rule->arg.vars.name, rule->arg.vars.scope, &smp);
Thierry FOURNIER24ff6c62015-08-06 08:52:53 +0200675 return ACT_RET_CONT;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200676}
677
Christopher Faulet85d79c92016-11-09 16:54:56 +0100678/* Always returns ACT_RET_CONT even if an error occurs. */
679static enum act_return action_clear(struct act_rule *rule, struct proxy *px,
680 struct session *sess, struct stream *s, int flags)
681{
682 struct sample smp;
683
684 memset(&smp, 0, sizeof(smp));
685 smp_set_owner(&smp, px, sess, s, SMP_OPT_FINAL);
686
687 /* Clear the variable using the sample context, and ignore errors. */
688 sample_clear_stream(rule->arg.vars.name, rule->arg.vars.scope, &smp);
689 return ACT_RET_CONT;
690}
691
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200692/* This two function checks the variable name and replace the
693 * configuration string name by the global string name. its
694 * the same string, but the global pointer can be easy to
695 * compare.
696 *
697 * The first function checks a sample-fetch and the second
698 * checks a converter.
699 */
700static int smp_check_var(struct arg *args, char **err)
701{
702 return vars_check_arg(&args[0], err);
703}
704
705static int conv_check_var(struct arg *args, struct sample_conv *conv,
706 const char *file, int line, char **err_msg)
707{
708 return vars_check_arg(&args[0], err_msg);
709}
710
711/* This function is a common parser for using variables. It understands
712 * the format:
713 *
714 * set-var(<variable-name>) <expression>
715 *
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200716 * It returns ACT_RET_PRS_ERR if fails and <err> is filled with an error
717 * message. Otherwise, it returns ACT_RET_PRS_OK and the variable <expr>
718 * is filled with the pointer to the expression to execute.
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200719 */
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200720static enum act_parse_ret parse_store(const char **args, int *arg, struct proxy *px,
721 struct act_rule *rule, char **err)
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200722{
723 const char *var_name = args[*arg-1];
724 int var_len;
Thierry FOURNIER48a9cd12015-07-28 19:00:28 +0200725 const char *kw_name;
Willy Tarreaue3658152016-11-24 21:23:28 +0100726 int flags, set_var = 0;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200727
Christopher Faulet85d79c92016-11-09 16:54:56 +0100728 if (!strncmp(var_name, "set-var", 7)) {
729 var_name += 7;
730 set_var = 1;
731 }
732 if (!strncmp(var_name, "unset-var", 9)) {
733 var_name += 9;
734 set_var = 0;
735 }
736
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200737 if (*var_name != '(') {
Christopher Faulet85d79c92016-11-09 16:54:56 +0100738 memprintf(err, "invalid variable '%s'. Expects 'set-var(<var-name>)' or 'unset-var(<var-name>)'",
739 args[*arg-1]);
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200740 return ACT_RET_PRS_ERR;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200741 }
742 var_name++; /* jump the '(' */
743 var_len = strlen(var_name);
744 var_len--; /* remove the ')' */
745 if (var_name[var_len] != ')') {
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
Christopher Faulet09c9df22016-10-31 11:05:37 +0100751 rule->arg.vars.name = register_name(var_name, var_len, &rule->arg.vars.scope, 1, err);
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200752 if (!rule->arg.vars.name)
753 return ACT_RET_PRS_ERR;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200754
Christopher Faulet85d79c92016-11-09 16:54:56 +0100755 /* There is no fetch method when variable is unset. Just set the right
756 * action and return. */
757 if (!set_var) {
758 if (*args[*arg]) {
759 memprintf(err, "fetch method not supported");
760 return ACT_RET_PRS_ERR;
761 }
762 rule->action = ACT_CUSTOM;
763 rule->action_ptr = action_clear;
764 return ACT_RET_PRS_OK;
765 }
766
Thierry FOURNIER48a9cd12015-07-28 19:00:28 +0200767 kw_name = args[*arg-1];
768
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200769 rule->arg.vars.expr = sample_parse_expr((char **)args, arg, px->conf.args.file,
770 px->conf.args.line, err, &px->conf.args);
771 if (!rule->arg.vars.expr)
Thierry FOURNIERafa80492015-08-19 09:04:15 +0200772 return ACT_RET_PRS_ERR;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200773
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200774 switch (rule->from) {
Willy Tarreau620408f2016-10-21 16:37:51 +0200775 case ACT_F_TCP_REQ_SES: flags = SMP_VAL_FE_SES_ACC; break;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200776 case ACT_F_TCP_REQ_CNT: flags = SMP_VAL_FE_REQ_CNT; break;
777 case ACT_F_TCP_RES_CNT: flags = SMP_VAL_BE_RES_CNT; break;
778 case ACT_F_HTTP_REQ: flags = SMP_VAL_FE_HRQ_HDR; break;
779 case ACT_F_HTTP_RES: flags = SMP_VAL_BE_HRS_HDR; break;
780 default:
781 memprintf(err,
782 "internal error, unexpected rule->from=%d, please report this bug!",
783 rule->from);
Thierry FOURNIERafa80492015-08-19 09:04:15 +0200784 return ACT_RET_PRS_ERR;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200785 }
786 if (!(rule->arg.vars.expr->fetch->val & flags)) {
787 memprintf(err,
788 "fetch method '%s' extracts information from '%s', none of which is available here",
789 kw_name, sample_src_names(rule->arg.vars.expr->fetch->use));
790 free(rule->arg.vars.expr);
Thierry FOURNIERafa80492015-08-19 09:04:15 +0200791 return ACT_RET_PRS_ERR;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200792 }
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200793
Thierry FOURNIER42148732015-09-02 17:17:33 +0200794 rule->action = ACT_CUSTOM;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200795 rule->action_ptr = action_store;
Thierry FOURNIERafa80492015-08-19 09:04:15 +0200796 return ACT_RET_PRS_OK;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200797}
798
799static int vars_max_size(char **args, int section_type, struct proxy *curpx,
800 struct proxy *defpx, const char *file, int line,
801 char **err, unsigned int *limit)
802{
803 char *error;
804
805 *limit = strtol(args[1], &error, 10);
806 if (*error != 0) {
807 memprintf(err, "%s: '%s' is an invalid size", args[0], args[1]);
808 return -1;
809 }
810 return 0;
811}
812
813static int vars_max_size_global(char **args, int section_type, struct proxy *curpx,
814 struct proxy *defpx, const char *file, int line,
815 char **err)
816{
817 return vars_max_size(args, section_type, curpx, defpx, file, line, err, &var_global_limit);
818}
819
Christopher Fauletff2613e2016-11-09 11:36:17 +0100820static int vars_max_size_proc(char **args, int section_type, struct proxy *curpx,
821 struct proxy *defpx, const char *file, int line,
822 char **err)
823{
824 return vars_max_size(args, section_type, curpx, defpx, file, line, err, &var_proc_limit);
825}
826
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200827static int vars_max_size_sess(char **args, int section_type, struct proxy *curpx,
828 struct proxy *defpx, const char *file, int line,
829 char **err)
830{
831 return vars_max_size(args, section_type, curpx, defpx, file, line, err, &var_sess_limit);
832}
833
834static int vars_max_size_txn(char **args, int section_type, struct proxy *curpx,
835 struct proxy *defpx, const char *file, int line,
836 char **err)
837{
838 return vars_max_size(args, section_type, curpx, defpx, file, line, err, &var_txn_limit);
839}
840
841static int vars_max_size_reqres(char **args, int section_type, struct proxy *curpx,
842 struct proxy *defpx, const char *file, int line,
843 char **err)
844{
845 return vars_max_size(args, section_type, curpx, defpx, file, line, err, &var_reqres_limit);
846}
847
848static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
849
Christopher Fauletff2613e2016-11-09 11:36:17 +0100850 { "var", smp_fetch_var, ARG1(1,STR), smp_check_var, SMP_T_STR, SMP_USE_L4CLI },
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200851 { /* END */ },
852}};
853
854static struct sample_conv_kw_list sample_conv_kws = {ILH, {
Christopher Faulet85d79c92016-11-09 16:54:56 +0100855 { "set-var", smp_conv_store, ARG1(1,STR), conv_check_var, SMP_T_ANY, SMP_T_ANY },
856 { "unset-var", smp_conv_clear, ARG1(1,STR), conv_check_var, SMP_T_ANY, SMP_T_ANY },
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200857 { /* END */ },
858}};
859
Willy Tarreau620408f2016-10-21 16:37:51 +0200860static struct action_kw_list tcp_req_sess_kws = { { }, {
Christopher Faulet85d79c92016-11-09 16:54:56 +0100861 { "set-var", parse_store, 1 },
862 { "unset-var", parse_store, 1 },
Willy Tarreau620408f2016-10-21 16:37:51 +0200863 { /* END */ }
864}};
865
866static struct action_kw_list tcp_req_cont_kws = { { }, {
Christopher Faulet85d79c92016-11-09 16:54:56 +0100867 { "set-var", parse_store, 1 },
868 { "unset-var", parse_store, 1 },
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200869 { /* END */ }
870}};
871
Thierry FOURNIER36481b82015-08-19 09:01:53 +0200872static struct action_kw_list tcp_res_kws = { { }, {
Christopher Faulet85d79c92016-11-09 16:54:56 +0100873 { "set-var", parse_store, 1 },
874 { "unset-var", parse_store, 1 },
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200875 { /* END */ }
876}};
877
Thierry FOURNIER36481b82015-08-19 09:01:53 +0200878static struct action_kw_list http_req_kws = { { }, {
Christopher Faulet85d79c92016-11-09 16:54:56 +0100879 { "set-var", parse_store, 1 },
880 { "unset-var", parse_store, 1 },
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200881 { /* END */ }
882}};
883
Thierry FOURNIER36481b82015-08-19 09:01:53 +0200884static struct action_kw_list http_res_kws = { { }, {
Christopher Faulet85d79c92016-11-09 16:54:56 +0100885 { "set-var", parse_store, 1 },
886 { "unset-var", parse_store, 1 },
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200887 { /* END */ }
888}};
889
890static struct cfg_kw_list cfg_kws = {{ },{
891 { CFG_GLOBAL, "tune.vars.global-max-size", vars_max_size_global },
Christopher Fauletff2613e2016-11-09 11:36:17 +0100892 { CFG_GLOBAL, "tune.vars.proc-max-size", vars_max_size_proc },
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200893 { CFG_GLOBAL, "tune.vars.sess-max-size", vars_max_size_sess },
894 { CFG_GLOBAL, "tune.vars.txn-max-size", vars_max_size_txn },
895 { CFG_GLOBAL, "tune.vars.reqres-max-size", vars_max_size_reqres },
896 { /* END */ }
897}};
898
899__attribute__((constructor))
Christopher Faulete95f2c32017-07-24 16:30:34 +0200900static void __vars_init(void)
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200901{
902 var_pool = create_pool("vars", sizeof(struct var), MEM_F_SHARED);
903
904 sample_register_fetches(&sample_fetch_keywords);
905 sample_register_convs(&sample_conv_kws);
Willy Tarreau620408f2016-10-21 16:37:51 +0200906 tcp_req_sess_keywords_register(&tcp_req_sess_kws);
907 tcp_req_cont_keywords_register(&tcp_req_cont_kws);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200908 tcp_res_cont_keywords_register(&tcp_res_kws);
909 http_req_keywords_register(&http_req_kws);
910 http_res_keywords_register(&http_res_kws);
911 cfg_register_keywords(&cfg_kws);
Christopher Faulete95f2c32017-07-24 16:30:34 +0200912
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100913 HA_RWLOCK_INIT(&var_names_rwlock);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200914}