blob: 6e8e256d0cd6ed4ead78f098b06263582ac6e236 [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
35#ifdef USE_THREAD
36HA_RWLOCK_T var_names_rwlock;
37#endif
38
Willy Tarreau72330982015-06-19 11:21:56 +020039/* This function adds or remove memory size from the accounting. The inner
40 * pointers may be null when setting the outer ones only.
41 */
Willy Tarreau6204cd92016-03-10 16:33:04 +010042static void var_accounting_diff(struct vars *vars, struct session *sess, struct stream *strm, int size)
Thierry FOURNIER4834bc72015-06-06 19:29:07 +020043{
44 switch (vars->scope) {
45 case SCOPE_REQ:
46 case SCOPE_RES:
Christopher Faulete95f2c32017-07-24 16:30:34 +020047 HA_ATOMIC_ADD(&strm->vars_reqres.size, size);
Willy Tarreau6204cd92016-03-10 16:33:04 +010048 /* fall through */
Thierry FOURNIER4834bc72015-06-06 19:29:07 +020049 case SCOPE_TXN:
Christopher Faulete95f2c32017-07-24 16:30:34 +020050 HA_ATOMIC_ADD(&strm->vars_txn.size, size);
Willy Tarreau6204cd92016-03-10 16:33:04 +010051 /* fall through */
Thierry FOURNIER4834bc72015-06-06 19:29:07 +020052 case SCOPE_SESS:
Christopher Faulete95f2c32017-07-24 16:30:34 +020053 HA_ATOMIC_ADD(&sess->vars.size, size);
Christopher Fauletff2613e2016-11-09 11:36:17 +010054 /* fall through */
55 case SCOPE_PROC:
Christopher Faulete95f2c32017-07-24 16:30:34 +020056 HA_ATOMIC_ADD(&global.vars.size, size);
57 HA_ATOMIC_ADD(&var_global_size, size);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +020058 }
59}
60
61/* This function returns 1 if the <size> is available in the var
62 * pool <vars>, otherwise returns 0. If the space is avalaible,
Willy Tarreau72330982015-06-19 11:21:56 +020063 * the size is reserved. The inner pointers may be null when setting
Willy Tarreau6204cd92016-03-10 16:33:04 +010064 * the outer ones only. The accounting uses either <sess> or <strm>
65 * depending on the scope. <strm> may be NULL when no stream is known
66 * and only the session exists (eg: tcp-request connection).
Thierry FOURNIER4834bc72015-06-06 19:29:07 +020067 */
Willy Tarreau6204cd92016-03-10 16:33:04 +010068static int var_accounting_add(struct vars *vars, struct session *sess, struct stream *strm, int size)
Thierry FOURNIER4834bc72015-06-06 19:29:07 +020069{
70 switch (vars->scope) {
71 case SCOPE_REQ:
72 case SCOPE_RES:
Willy Tarreau6204cd92016-03-10 16:33:04 +010073 if (var_reqres_limit && strm->vars_reqres.size + size > var_reqres_limit)
Thierry FOURNIER4834bc72015-06-06 19:29:07 +020074 return 0;
Willy Tarreau6204cd92016-03-10 16:33:04 +010075 /* fall through */
Thierry FOURNIER4834bc72015-06-06 19:29:07 +020076 case SCOPE_TXN:
Willy Tarreau6204cd92016-03-10 16:33:04 +010077 if (var_txn_limit && strm->vars_txn.size + size > var_txn_limit)
Thierry FOURNIER4834bc72015-06-06 19:29:07 +020078 return 0;
Willy Tarreau6204cd92016-03-10 16:33:04 +010079 /* fall through */
Thierry FOURNIER4834bc72015-06-06 19:29:07 +020080 case SCOPE_SESS:
Willy Tarreau6204cd92016-03-10 16:33:04 +010081 if (var_sess_limit && sess->vars.size + size > var_sess_limit)
Thierry FOURNIER4834bc72015-06-06 19:29:07 +020082 return 0;
Christopher Fauletff2613e2016-11-09 11:36:17 +010083 /* fall through */
84 case SCOPE_PROC:
85 if (var_proc_limit && global.vars.size + size > var_proc_limit)
86 return 0;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +020087 if (var_global_limit && var_global_size + size > var_global_limit)
88 return 0;
89 }
Willy Tarreau6204cd92016-03-10 16:33:04 +010090 var_accounting_diff(vars, sess, strm, size);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +020091 return 1;
92}
93
Christopher Faulet85d79c92016-11-09 16:54:56 +010094/* This fnuction remove a variable from the list and free memory it used */
95unsigned int var_clear(struct var *var)
96{
97 unsigned int size = 0;
98
99 if (var->data.type == SMP_T_STR || var->data.type == SMP_T_BIN) {
100 free(var->data.u.str.str);
101 size += var->data.u.str.len;
102 }
Christopher Fauletd02210c2017-07-24 16:24:39 +0200103 else if (var->data.type == SMP_T_METH && var->data.u.meth.meth == HTTP_METH_OTHER) {
Christopher Faulet85d79c92016-11-09 16:54:56 +0100104 free(var->data.u.meth.str.str);
105 size += var->data.u.meth.str.len;
106 }
107 LIST_DEL(&var->l);
108 pool_free2(var_pool, var);
109 size += sizeof(struct var);
110 return size;
111}
112
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200113/* This function free all the memory used by all the varaibles
114 * in the list.
115 */
Willy Tarreau6204cd92016-03-10 16:33:04 +0100116void vars_prune(struct vars *vars, struct session *sess, struct stream *strm)
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200117{
118 struct var *var, *tmp;
Willy Tarreau72330982015-06-19 11:21:56 +0200119 unsigned int size = 0;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200120
Christopher Faulete95f2c32017-07-24 16:30:34 +0200121 RWLOCK_WRLOCK(VARS_LOCK, &vars->rwlock);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200122 list_for_each_entry_safe(var, tmp, &vars->head, l) {
Christopher Faulet85d79c92016-11-09 16:54:56 +0100123 size += var_clear(var);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200124 }
Christopher Faulete95f2c32017-07-24 16:30:34 +0200125 RWLOCK_WRUNLOCK(VARS_LOCK, &vars->rwlock);
Willy Tarreau6204cd92016-03-10 16:33:04 +0100126 var_accounting_diff(vars, sess, strm, -size);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200127}
128
Willy Tarreauebcd4842015-06-19 11:59:02 +0200129/* This function frees all the memory used by all the session variables in the
130 * list starting at <vars>.
131 */
132void vars_prune_per_sess(struct vars *vars)
133{
134 struct var *var, *tmp;
135 unsigned int size = 0;
136
Christopher Faulete95f2c32017-07-24 16:30:34 +0200137 RWLOCK_WRLOCK(VARS_LOCK, &vars->rwlock);
Willy Tarreauebcd4842015-06-19 11:59:02 +0200138 list_for_each_entry_safe(var, tmp, &vars->head, l) {
Christopher Faulet85d79c92016-11-09 16:54:56 +0100139 size += var_clear(var);
Willy Tarreauebcd4842015-06-19 11:59:02 +0200140 }
Christopher Faulete95f2c32017-07-24 16:30:34 +0200141 RWLOCK_WRUNLOCK(VARS_LOCK, &vars->rwlock);
142
143 HA_ATOMIC_SUB(&vars->size, size);
144 HA_ATOMIC_SUB(&global.vars.size, size);
145 HA_ATOMIC_SUB(&var_global_size, size);
Willy Tarreauebcd4842015-06-19 11:59:02 +0200146}
147
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200148/* This function init a list of variabes. */
149void vars_init(struct vars *vars, enum vars_scope scope)
150{
151 LIST_INIT(&vars->head);
152 vars->scope = scope;
153 vars->size = 0;
Christopher Faulete95f2c32017-07-24 16:30:34 +0200154 RWLOCK_INIT(&vars->rwlock);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200155}
156
157/* This function declares a new variable name. It returns a pointer
158 * on the string identifying the name. This function assures that
159 * the same name exists only once.
160 *
161 * This function check if the variable name is acceptable.
162 *
163 * The function returns NULL if an error occurs, and <err> is filled.
164 * In this case, the HAProxy must be stopped because the structs are
165 * left inconsistent. Otherwise, it returns the pointer on the global
166 * name.
167 */
Christopher Faulet09c9df22016-10-31 11:05:37 +0100168static char *register_name(const char *name, int len, enum vars_scope *scope,
169 int alloc, char **err)
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200170{
171 int i;
Hubert Verstraete831962e2016-06-28 22:44:26 +0200172 char **var_names2;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200173 const char *tmp;
Christopher Faulete95f2c32017-07-24 16:30:34 +0200174 char *res = NULL;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200175
176 /* Check length. */
177 if (len == 0) {
178 memprintf(err, "Empty variable name cannot be accepted");
Christopher Faulete95f2c32017-07-24 16:30:34 +0200179 res = NULL;
180 goto end;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200181 }
182
183 /* Check scope. */
Christopher Fauletff2613e2016-11-09 11:36:17 +0100184 if (len > 5 && strncmp(name, "proc.", 5) == 0) {
185 name += 5;
186 len -= 5;
187 *scope = SCOPE_PROC;
188 }
189 else if (len > 5 && strncmp(name, "sess.", 5) == 0) {
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200190 name += 5;
191 len -= 5;
192 *scope = SCOPE_SESS;
193 }
194 else if (len > 4 && strncmp(name, "txn.", 4) == 0) {
195 name += 4;
196 len -= 4;
197 *scope = SCOPE_TXN;
198 }
199 else if (len > 4 && strncmp(name, "req.", 4) == 0) {
200 name += 4;
201 len -= 4;
202 *scope = SCOPE_REQ;
203 }
204 else if (len > 4 && strncmp(name, "res.", 4) == 0) {
205 name += 4;
206 len -= 4;
207 *scope = SCOPE_RES;
208 }
209 else {
210 memprintf(err, "invalid variable name '%s'. A variable name must be start by its scope. "
Christopher Fauletff2613e2016-11-09 11:36:17 +0100211 "The scope can be 'proc', 'sess', 'txn', 'req' or 'res'", name);
Christopher Faulete95f2c32017-07-24 16:30:34 +0200212 res = NULL;
213 goto end;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200214 }
215
Christopher Faulete95f2c32017-07-24 16:30:34 +0200216 if (alloc)
217 RWLOCK_WRLOCK(VARS_LOCK, &var_names_rwlock);
218 else
219 RWLOCK_RDLOCK(VARS_LOCK, &var_names_rwlock);
220
221
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200222 /* Look for existing variable name. */
223 for (i = 0; i < var_names_nb; i++)
Christopher Faulete95f2c32017-07-24 16:30:34 +0200224 if (strncmp(var_names[i], name, len) == 0 && var_names[i][len] == '\0') {
225 res = var_names[i];
226 goto end;
227 }
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200228
Christopher Faulete95f2c32017-07-24 16:30:34 +0200229 if (!alloc) {
230 res = NULL;
231 goto end;
232 }
Christopher Faulet09c9df22016-10-31 11:05:37 +0100233
Hubert Verstraete831962e2016-06-28 22:44:26 +0200234 /* Store variable name. If realloc fails, var_names remains valid */
235 var_names2 = realloc(var_names, (var_names_nb + 1) * sizeof(*var_names));
236 if (!var_names2) {
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200237 memprintf(err, "out of memory error");
Christopher Faulete95f2c32017-07-24 16:30:34 +0200238 res = NULL;
239 goto end;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200240 }
Hubert Verstraete831962e2016-06-28 22:44:26 +0200241 var_names_nb++;
242 var_names = var_names2;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200243 var_names[var_names_nb - 1] = malloc(len + 1);
244 if (!var_names[var_names_nb - 1]) {
245 memprintf(err, "out of memory error");
Christopher Faulete95f2c32017-07-24 16:30:34 +0200246 res = NULL;
247 goto end;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200248 }
249 memcpy(var_names[var_names_nb - 1], name, len);
250 var_names[var_names_nb - 1][len] = '\0';
251
252 /* Check variable name syntax. */
253 tmp = var_names[var_names_nb - 1];
254 while (*tmp) {
Christopher Fauletb71557a2016-10-31 10:49:03 +0100255 if (!isalnum((int)(unsigned char)*tmp) && *tmp != '_' && *tmp != '.') {
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200256 memprintf(err, "invalid syntax at char '%s'", tmp);
Christopher Faulete95f2c32017-07-24 16:30:34 +0200257 res = NULL;
258 goto end;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200259 }
260 tmp++;
261 }
Christopher Faulete95f2c32017-07-24 16:30:34 +0200262 res = var_names[var_names_nb - 1];
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200263
Christopher Faulete95f2c32017-07-24 16:30:34 +0200264 end:
265 if (alloc)
266 RWLOCK_WRUNLOCK(VARS_LOCK, &var_names_rwlock);
267 else
268 RWLOCK_RDUNLOCK(VARS_LOCK, &var_names_rwlock);
269
270 return res;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200271}
272
273/* This function returns an existing variable or returns NULL. */
274static inline struct var *var_get(struct vars *vars, const char *name)
275{
276 struct var *var;
277
278 list_for_each_entry(var, &vars->head, l)
279 if (var->name == name)
280 return var;
281 return NULL;
282}
283
284/* Returns 0 if fails, else returns 1. */
285static int smp_fetch_var(const struct arg *args, struct sample *smp, const char *kw, void *private)
286{
287 const struct var_desc *var_desc = &args[0].data.var;
288 struct var *var;
289 struct vars *vars;
290
291 /* Check the availibity of the variable. */
292 switch (var_desc->scope) {
Christopher Fauletff2613e2016-11-09 11:36:17 +0100293 case SCOPE_PROC:
294 vars = &global.vars;
295 break;
Willy Tarreau7513d002016-10-21 17:14:35 +0200296 case SCOPE_SESS:
297 vars = &smp->sess->vars;
298 break;
299 case SCOPE_TXN:
300 if (!smp->strm)
301 return 0;
302 vars = &smp->strm->vars_txn;
303 break;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200304 case SCOPE_REQ:
Thierry FOURNIER0b243fd2015-06-16 23:52:47 +0200305 case SCOPE_RES:
Willy Tarreau7513d002016-10-21 17:14:35 +0200306 default:
307 if (!smp->strm)
308 return 0;
309 vars = &smp->strm->vars_reqres;
310 break;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200311 }
312 if (vars->scope != var_desc->scope)
313 return 0;
Christopher Faulete95f2c32017-07-24 16:30:34 +0200314
315 RWLOCK_RDLOCK(VARS_LOCK, &vars->rwlock);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200316 var = var_get(vars, var_desc->name);
317
318 /* check for the variable avalaibility */
Christopher Faulete95f2c32017-07-24 16:30:34 +0200319 if (!var) {
320 RWLOCK_RDUNLOCK(VARS_LOCK, &vars->rwlock);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200321 return 0;
Christopher Faulete95f2c32017-07-24 16:30:34 +0200322 }
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200323
Christopher Faulete95f2c32017-07-24 16:30:34 +0200324 /* Duplicate the sample data because it could modified by another
325 * thread */
Thierry FOURNIER5cc18d42015-08-19 09:02:36 +0200326 smp->data = var->data;
Christopher Faulete95f2c32017-07-24 16:30:34 +0200327 smp_dup(smp);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200328 smp->flags |= SMP_F_CONST;
Christopher Faulete95f2c32017-07-24 16:30:34 +0200329
330 RWLOCK_RDUNLOCK(VARS_LOCK, &vars->rwlock);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200331 return 1;
332}
333
334/* This function search in the <head> a variable with the same
335 * pointer value that the <name>. If the variable doesn't exists,
336 * create it. The function stores a copy of smp> if the variable.
337 * It returns 0 if fails, else returns 1.
338 */
Willy Tarreau6204cd92016-03-10 16:33:04 +0100339static int sample_store(struct vars *vars, const char *name, struct sample *smp)
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200340{
341 struct var *var;
342
343 /* Look for existing variable name. */
344 var = var_get(vars, name);
345
346 if (var) {
347 /* free its used memory. */
348 if (var->data.type == SMP_T_STR ||
349 var->data.type == SMP_T_BIN) {
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200350 free(var->data.u.str.str);
Willy Tarreau6204cd92016-03-10 16:33:04 +0100351 var_accounting_diff(vars, smp->sess, smp->strm, -var->data.u.str.len);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200352 }
Christopher Fauletd02210c2017-07-24 16:24:39 +0200353 else if (var->data.type == SMP_T_METH && var->data.u.meth.meth == HTTP_METH_OTHER) {
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200354 free(var->data.u.meth.str.str);
Willy Tarreau6204cd92016-03-10 16:33:04 +0100355 var_accounting_diff(vars, smp->sess, smp->strm, -var->data.u.meth.str.len);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200356 }
357 } else {
358
359 /* Check memory avalaible. */
Willy Tarreau6204cd92016-03-10 16:33:04 +0100360 if (!var_accounting_add(vars, smp->sess, smp->strm, sizeof(struct var)))
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200361 return 0;
362
363 /* Create new entry. */
364 var = pool_alloc2(var_pool);
365 if (!var)
366 return 0;
367 LIST_ADDQ(&vars->head, &var->l);
368 var->name = name;
369 }
370
371 /* Set type. */
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +0200372 var->data.type = smp->data.type;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200373
374 /* Copy data. If the data needs memory, the function can fail. */
375 switch (var->data.type) {
376 case SMP_T_BOOL:
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200377 case SMP_T_SINT:
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200378 var->data.u.sint = smp->data.u.sint;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200379 break;
380 case SMP_T_IPV4:
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200381 var->data.u.ipv4 = smp->data.u.ipv4;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200382 break;
383 case SMP_T_IPV6:
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200384 var->data.u.ipv6 = smp->data.u.ipv6;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200385 break;
386 case SMP_T_STR:
387 case SMP_T_BIN:
Willy Tarreau6204cd92016-03-10 16:33:04 +0100388 if (!var_accounting_add(vars, smp->sess, smp->strm, smp->data.u.str.len)) {
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200389 var->data.type = SMP_T_BOOL; /* This type doesn't use additional memory. */
390 return 0;
391 }
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200392 var->data.u.str.str = malloc(smp->data.u.str.len);
393 if (!var->data.u.str.str) {
Willy Tarreau6204cd92016-03-10 16:33:04 +0100394 var_accounting_diff(vars, smp->sess, smp->strm, -smp->data.u.str.len);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200395 var->data.type = SMP_T_BOOL; /* This type doesn't use additional memory. */
396 return 0;
397 }
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200398 var->data.u.str.len = smp->data.u.str.len;
399 memcpy(var->data.u.str.str, smp->data.u.str.str, var->data.u.str.len);
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 Tarreau6204cd92016-03-10 16:33:04 +0100406 if (!var_accounting_add(vars, smp->sess, smp->strm, smp->data.u.meth.str.len)) {
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 }
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200410 var->data.u.meth.str.str = malloc(smp->data.u.meth.str.len);
411 if (!var->data.u.meth.str.str) {
Willy Tarreau6204cd92016-03-10 16:33:04 +0100412 var_accounting_diff(vars, smp->sess, smp->strm, -smp->data.u.meth.str.len);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200413 var->data.type = SMP_T_BOOL; /* This type doesn't use additional memory. */
414 return 0;
415 }
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200416 var->data.u.meth.str.len = smp->data.u.meth.str.len;
417 var->data.u.meth.str.size = smp->data.u.meth.str.len;
418 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 +0200419 break;
420 }
421 return 1;
422}
423
Willy Tarreau620408f2016-10-21 16:37:51 +0200424/* Returns 0 if fails, else returns 1. Note that stream may be null for SCOPE_SESS. */
Willy Tarreau6204cd92016-03-10 16:33:04 +0100425static inline int sample_store_stream(const char *name, enum vars_scope scope, struct sample *smp)
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200426{
427 struct vars *vars;
Christopher Faulete95f2c32017-07-24 16:30:34 +0200428 int ret;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200429
430 switch (scope) {
Christopher Fauletff2613e2016-11-09 11:36:17 +0100431 case SCOPE_PROC: vars = &global.vars; break;
Willy Tarreau6204cd92016-03-10 16:33:04 +0100432 case SCOPE_SESS: vars = &smp->sess->vars; break;
433 case SCOPE_TXN: vars = &smp->strm->vars_txn; break;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200434 case SCOPE_REQ:
Thierry FOURNIER0b243fd2015-06-16 23:52:47 +0200435 case SCOPE_RES:
Willy Tarreau6204cd92016-03-10 16:33:04 +0100436 default: vars = &smp->strm->vars_reqres; break;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200437 }
438 if (vars->scope != scope)
439 return 0;
Christopher Faulete95f2c32017-07-24 16:30:34 +0200440
441 RWLOCK_WRLOCK(VARS_LOCK, &vars->rwlock);
442 ret = sample_store(vars, name, smp);
443 RWLOCK_WRUNLOCK(VARS_LOCK, &vars->rwlock);
444 return ret;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200445}
446
Christopher Faulet85d79c92016-11-09 16:54:56 +0100447/* Returns 0 if fails, else returns 1. Note that stream may be null for SCOPE_SESS. */
448static inline int sample_clear_stream(const char *name, enum vars_scope scope, struct sample *smp)
449{
450 struct vars *vars;
451 struct var *var;
452 unsigned int size = 0;
453
454 switch (scope) {
455 case SCOPE_PROC: vars = &global.vars; break;
456 case SCOPE_SESS: vars = &smp->sess->vars; break;
457 case SCOPE_TXN: vars = &smp->strm->vars_txn; break;
458 case SCOPE_REQ:
459 case SCOPE_RES:
460 default: vars = &smp->strm->vars_reqres; break;
461 }
462 if (vars->scope != scope)
463 return 0;
464
465 /* Look for existing variable name. */
Christopher Faulete95f2c32017-07-24 16:30:34 +0200466 RWLOCK_WRLOCK(VARS_LOCK, &vars->rwlock);
Christopher Faulet85d79c92016-11-09 16:54:56 +0100467 var = var_get(vars, name);
468 if (var) {
469 size = var_clear(var);
470 var_accounting_diff(vars, smp->sess, smp->strm, -size);
471 }
Christopher Faulete95f2c32017-07-24 16:30:34 +0200472 RWLOCK_WRUNLOCK(VARS_LOCK, &vars->rwlock);
Christopher Faulet85d79c92016-11-09 16:54:56 +0100473 return 1;
474}
475
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200476/* Returns 0 if fails, else returns 1. */
477static int smp_conv_store(const struct arg *args, struct sample *smp, void *private)
478{
Christopher Faulet0099a8c2016-11-09 16:15:32 +0100479 return sample_store_stream(args[0].data.var.name, args[0].data.var.scope, smp);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200480}
481
Christopher Faulet85d79c92016-11-09 16:54:56 +0100482/* Returns 0 if fails, else returns 1. */
483static int smp_conv_clear(const struct arg *args, struct sample *smp, void *private)
484{
485 return sample_clear_stream(args[0].data.var.name, args[0].data.var.scope, smp);
486}
487
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200488/* This fucntions check an argument entry and fill it with a variable
489 * type. The argumen must be a string. If the variable lookup fails,
490 * the function retuns 0 and fill <err>, otherwise it returns 1.
491 */
492int vars_check_arg(struct arg *arg, char **err)
493{
494 char *name;
495 enum vars_scope scope;
496
497 /* Check arg type. */
498 if (arg->type != ARGT_STR) {
499 memprintf(err, "unexpected argument type");
500 return 0;
501 }
502
503 /* Register new variable name. */
Christopher Faulet09c9df22016-10-31 11:05:37 +0100504 name = register_name(arg->data.str.str, arg->data.str.len, &scope, 1, err);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200505 if (!name)
506 return 0;
507
508 /* Use the global variable name pointer. */
509 arg->type = ARGT_VAR;
510 arg->data.var.name = name;
511 arg->data.var.scope = scope;
512 return 1;
513}
514
Christopher Faulet09c9df22016-10-31 11:05:37 +0100515/* This function store a sample in a variable if it was already defined.
516 * In error case, it fails silently.
517 */
518void vars_set_by_name_ifexist(const char *name, size_t len, struct sample *smp)
519{
520 enum vars_scope scope;
521
522 /* Resolve name and scope. */
523 name = register_name(name, len, &scope, 0, NULL);
524 if (!name)
525 return;
526
527 sample_store_stream(name, scope, smp);
528}
529
530
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200531/* This function store a sample in a variable.
532 * In error case, it fails silently.
533 */
Willy Tarreau6204cd92016-03-10 16:33:04 +0100534void vars_set_by_name(const char *name, size_t len, struct sample *smp)
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200535{
536 enum vars_scope scope;
537
538 /* Resolve name and scope. */
Christopher Faulet09c9df22016-10-31 11:05:37 +0100539 name = register_name(name, len, &scope, 1, NULL);
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200540 if (!name)
541 return;
542
Willy Tarreau6204cd92016-03-10 16:33:04 +0100543 sample_store_stream(name, scope, smp);
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200544}
545
Christopher Faulet85d79c92016-11-09 16:54:56 +0100546/* This function unset a variable if it was already defined.
547 * In error case, it fails silently.
548 */
549void vars_unset_by_name_ifexist(const char *name, size_t len, struct sample *smp)
550{
551 enum vars_scope scope;
552
553 /* Resolve name and scope. */
554 name = register_name(name, len, &scope, 0, NULL);
555 if (!name)
556 return;
557
558 sample_clear_stream(name, scope, smp);
559}
560
561
562/* This function unset a variable.
563 * In error case, it fails silently.
564 */
565void vars_unset_by_name(const char *name, size_t len, struct sample *smp)
566{
567 enum vars_scope scope;
568
569 /* Resolve name and scope. */
570 name = register_name(name, len, &scope, 1, NULL);
571 if (!name)
572 return;
573
574 sample_clear_stream(name, scope, smp);
575}
576
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200577/* this function fills a sample with the
578 * variable content. Returns 1 if the sample
579 * is filled, otherwise it returns 0.
580 */
Willy Tarreau6204cd92016-03-10 16:33:04 +0100581int vars_get_by_name(const char *name, size_t len, struct sample *smp)
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200582{
583 struct vars *vars;
584 struct var *var;
585 enum vars_scope scope;
586
587 /* Resolve name and scope. */
Christopher Faulet09c9df22016-10-31 11:05:37 +0100588 name = register_name(name, len, &scope, 1, NULL);
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200589 if (!name)
590 return 0;
591
592 /* Select "vars" pool according with the scope. */
593 switch (scope) {
Christopher Fauletff2613e2016-11-09 11:36:17 +0100594 case SCOPE_PROC: vars = &global.vars; break;
Willy Tarreau6204cd92016-03-10 16:33:04 +0100595 case SCOPE_SESS: vars = &smp->sess->vars; break;
596 case SCOPE_TXN: vars = &smp->strm->vars_txn; break;
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200597 case SCOPE_REQ:
Thierry FOURNIER0b243fd2015-06-16 23:52:47 +0200598 case SCOPE_RES:
Willy Tarreau6204cd92016-03-10 16:33:04 +0100599 default: vars = &smp->strm->vars_reqres; break;
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200600 }
601
602 /* Check if the scope is avalaible a this point of processing. */
603 if (vars->scope != scope)
604 return 0;
605
606 /* Get the variable entry. */
607 var = var_get(vars, name);
608 if (!var)
609 return 0;
610
611 /* Copy sample. */
Thierry FOURNIER5cc18d42015-08-19 09:02:36 +0200612 smp->data = var->data;
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200613 smp->flags = SMP_F_CONST;
Thierry FOURNIERc365d992015-06-09 12:27:17 +0200614 return 1;
615}
616
Thierry FOURNIERfd77e052015-07-07 21:20:42 +0200617/* this function fills a sample with the
618 * content of the varaible described by <var_desc>. Returns 1
619 * if the sample is filled, otherwise it returns 0.
620 */
Willy Tarreau6204cd92016-03-10 16:33:04 +0100621int vars_get_by_desc(const struct var_desc *var_desc, struct sample *smp)
Thierry FOURNIERfd77e052015-07-07 21:20:42 +0200622{
623 struct vars *vars;
624 struct var *var;
625
626 /* Select "vars" pool according with the scope. */
627 switch (var_desc->scope) {
Christopher Fauletff2613e2016-11-09 11:36:17 +0100628 case SCOPE_PROC: vars = &global.vars; break;
Willy Tarreau6204cd92016-03-10 16:33:04 +0100629 case SCOPE_SESS: vars = &smp->sess->vars; break;
630 case SCOPE_TXN: vars = &smp->strm->vars_txn; break;
Thierry FOURNIERfd77e052015-07-07 21:20:42 +0200631 case SCOPE_REQ:
632 case SCOPE_RES:
Willy Tarreau6204cd92016-03-10 16:33:04 +0100633 default: vars = &smp->strm->vars_reqres; break;
Thierry FOURNIERfd77e052015-07-07 21:20:42 +0200634 }
635
636 /* Check if the scope is avalaible a this point of processing. */
637 if (vars->scope != var_desc->scope)
638 return 0;
639
640 /* Get the variable entry. */
641 var = var_get(vars, var_desc->name);
642 if (!var)
643 return 0;
644
645 /* Copy sample. */
Thierry FOURNIER5cc18d42015-08-19 09:02:36 +0200646 smp->data = var->data;
Thierry FOURNIERfd77e052015-07-07 21:20:42 +0200647 smp->flags = SMP_F_CONST;
Thierry FOURNIERfd77e052015-07-07 21:20:42 +0200648 return 1;
649}
650
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200651/* Always returns ACT_RET_CONT even if an error occurs. */
652static enum act_return action_store(struct act_rule *rule, struct proxy *px,
Willy Tarreau658b85b2015-09-27 10:00:49 +0200653 struct session *sess, struct stream *s, int flags)
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200654{
655 struct sample smp;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200656 int dir;
657
658 switch (rule->from) {
Willy Tarreau620408f2016-10-21 16:37:51 +0200659 case ACT_F_TCP_REQ_SES: dir = SMP_OPT_DIR_REQ; break;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200660 case ACT_F_TCP_REQ_CNT: dir = SMP_OPT_DIR_REQ; break;
661 case ACT_F_TCP_RES_CNT: dir = SMP_OPT_DIR_RES; break;
662 case ACT_F_HTTP_REQ: dir = SMP_OPT_DIR_REQ; break;
663 case ACT_F_HTTP_RES: dir = SMP_OPT_DIR_RES; break;
664 default:
665 send_log(px, LOG_ERR, "Vars: internal error while execute action store.");
666 if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))
667 Alert("Vars: internal error while execute action store.\n");
668 return ACT_RET_CONT;
669 }
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200670
671 /* Process the expression. */
672 memset(&smp, 0, sizeof(smp));
Willy Tarreau108a8fd2016-10-21 17:13:24 +0200673 if (!sample_process(px, sess, s, dir|SMP_OPT_FINAL,
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200674 rule->arg.vars.expr, &smp))
Thierry FOURNIER24ff6c62015-08-06 08:52:53 +0200675 return ACT_RET_CONT;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200676
677 /* Store the sample, and ignore errors. */
Willy Tarreau6204cd92016-03-10 16:33:04 +0100678 sample_store_stream(rule->arg.vars.name, rule->arg.vars.scope, &smp);
Thierry FOURNIER24ff6c62015-08-06 08:52:53 +0200679 return ACT_RET_CONT;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200680}
681
Christopher Faulet85d79c92016-11-09 16:54:56 +0100682/* Always returns ACT_RET_CONT even if an error occurs. */
683static enum act_return action_clear(struct act_rule *rule, struct proxy *px,
684 struct session *sess, struct stream *s, int flags)
685{
686 struct sample smp;
687
688 memset(&smp, 0, sizeof(smp));
689 smp_set_owner(&smp, px, sess, s, SMP_OPT_FINAL);
690
691 /* Clear the variable using the sample context, and ignore errors. */
692 sample_clear_stream(rule->arg.vars.name, rule->arg.vars.scope, &smp);
693 return ACT_RET_CONT;
694}
695
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200696/* This two function checks the variable name and replace the
697 * configuration string name by the global string name. its
698 * the same string, but the global pointer can be easy to
699 * compare.
700 *
701 * The first function checks a sample-fetch and the second
702 * checks a converter.
703 */
704static int smp_check_var(struct arg *args, char **err)
705{
706 return vars_check_arg(&args[0], err);
707}
708
709static int conv_check_var(struct arg *args, struct sample_conv *conv,
710 const char *file, int line, char **err_msg)
711{
712 return vars_check_arg(&args[0], err_msg);
713}
714
715/* This function is a common parser for using variables. It understands
716 * the format:
717 *
718 * set-var(<variable-name>) <expression>
719 *
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200720 * It returns ACT_RET_PRS_ERR if fails and <err> is filled with an error
721 * message. Otherwise, it returns ACT_RET_PRS_OK and the variable <expr>
722 * is filled with the pointer to the expression to execute.
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200723 */
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200724static enum act_parse_ret parse_store(const char **args, int *arg, struct proxy *px,
725 struct act_rule *rule, char **err)
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200726{
727 const char *var_name = args[*arg-1];
728 int var_len;
Thierry FOURNIER48a9cd12015-07-28 19:00:28 +0200729 const char *kw_name;
Willy Tarreaue3658152016-11-24 21:23:28 +0100730 int flags, set_var = 0;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200731
Christopher Faulet85d79c92016-11-09 16:54:56 +0100732 if (!strncmp(var_name, "set-var", 7)) {
733 var_name += 7;
734 set_var = 1;
735 }
736 if (!strncmp(var_name, "unset-var", 9)) {
737 var_name += 9;
738 set_var = 0;
739 }
740
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200741 if (*var_name != '(') {
Christopher Faulet85d79c92016-11-09 16:54:56 +0100742 memprintf(err, "invalid variable '%s'. Expects 'set-var(<var-name>)' or 'unset-var(<var-name>)'",
743 args[*arg-1]);
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200744 return ACT_RET_PRS_ERR;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200745 }
746 var_name++; /* jump the '(' */
747 var_len = strlen(var_name);
748 var_len--; /* remove the ')' */
749 if (var_name[var_len] != ')') {
Christopher Faulet85d79c92016-11-09 16:54:56 +0100750 memprintf(err, "invalid variable '%s'. Expects 'set-var(<var-name>)' or 'unset-var(<var-name>)'",
751 args[*arg-1]);
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200752 return ACT_RET_PRS_ERR;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200753 }
754
Christopher Faulet09c9df22016-10-31 11:05:37 +0100755 rule->arg.vars.name = register_name(var_name, var_len, &rule->arg.vars.scope, 1, err);
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200756 if (!rule->arg.vars.name)
757 return ACT_RET_PRS_ERR;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200758
Christopher Faulet85d79c92016-11-09 16:54:56 +0100759 /* There is no fetch method when variable is unset. Just set the right
760 * action and return. */
761 if (!set_var) {
762 if (*args[*arg]) {
763 memprintf(err, "fetch method not supported");
764 return ACT_RET_PRS_ERR;
765 }
766 rule->action = ACT_CUSTOM;
767 rule->action_ptr = action_clear;
768 return ACT_RET_PRS_OK;
769 }
770
Thierry FOURNIER48a9cd12015-07-28 19:00:28 +0200771 kw_name = args[*arg-1];
772
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200773 rule->arg.vars.expr = sample_parse_expr((char **)args, arg, px->conf.args.file,
774 px->conf.args.line, err, &px->conf.args);
775 if (!rule->arg.vars.expr)
Thierry FOURNIERafa80492015-08-19 09:04:15 +0200776 return ACT_RET_PRS_ERR;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200777
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200778 switch (rule->from) {
Willy Tarreau620408f2016-10-21 16:37:51 +0200779 case ACT_F_TCP_REQ_SES: flags = SMP_VAL_FE_SES_ACC; break;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200780 case ACT_F_TCP_REQ_CNT: flags = SMP_VAL_FE_REQ_CNT; break;
781 case ACT_F_TCP_RES_CNT: flags = SMP_VAL_BE_RES_CNT; break;
782 case ACT_F_HTTP_REQ: flags = SMP_VAL_FE_HRQ_HDR; break;
783 case ACT_F_HTTP_RES: flags = SMP_VAL_BE_HRS_HDR; break;
784 default:
785 memprintf(err,
786 "internal error, unexpected rule->from=%d, please report this bug!",
787 rule->from);
Thierry FOURNIERafa80492015-08-19 09:04:15 +0200788 return ACT_RET_PRS_ERR;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200789 }
790 if (!(rule->arg.vars.expr->fetch->val & flags)) {
791 memprintf(err,
792 "fetch method '%s' extracts information from '%s', none of which is available here",
793 kw_name, sample_src_names(rule->arg.vars.expr->fetch->use));
794 free(rule->arg.vars.expr);
Thierry FOURNIERafa80492015-08-19 09:04:15 +0200795 return ACT_RET_PRS_ERR;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200796 }
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200797
Thierry FOURNIER42148732015-09-02 17:17:33 +0200798 rule->action = ACT_CUSTOM;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +0200799 rule->action_ptr = action_store;
Thierry FOURNIERafa80492015-08-19 09:04:15 +0200800 return ACT_RET_PRS_OK;
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200801}
802
803static int vars_max_size(char **args, int section_type, struct proxy *curpx,
804 struct proxy *defpx, const char *file, int line,
805 char **err, unsigned int *limit)
806{
807 char *error;
808
809 *limit = strtol(args[1], &error, 10);
810 if (*error != 0) {
811 memprintf(err, "%s: '%s' is an invalid size", args[0], args[1]);
812 return -1;
813 }
814 return 0;
815}
816
817static int vars_max_size_global(char **args, int section_type, struct proxy *curpx,
818 struct proxy *defpx, const char *file, int line,
819 char **err)
820{
821 return vars_max_size(args, section_type, curpx, defpx, file, line, err, &var_global_limit);
822}
823
Christopher Fauletff2613e2016-11-09 11:36:17 +0100824static int vars_max_size_proc(char **args, int section_type, struct proxy *curpx,
825 struct proxy *defpx, const char *file, int line,
826 char **err)
827{
828 return vars_max_size(args, section_type, curpx, defpx, file, line, err, &var_proc_limit);
829}
830
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200831static int vars_max_size_sess(char **args, int section_type, struct proxy *curpx,
832 struct proxy *defpx, const char *file, int line,
833 char **err)
834{
835 return vars_max_size(args, section_type, curpx, defpx, file, line, err, &var_sess_limit);
836}
837
838static int vars_max_size_txn(char **args, int section_type, struct proxy *curpx,
839 struct proxy *defpx, const char *file, int line,
840 char **err)
841{
842 return vars_max_size(args, section_type, curpx, defpx, file, line, err, &var_txn_limit);
843}
844
845static int vars_max_size_reqres(char **args, int section_type, struct proxy *curpx,
846 struct proxy *defpx, const char *file, int line,
847 char **err)
848{
849 return vars_max_size(args, section_type, curpx, defpx, file, line, err, &var_reqres_limit);
850}
851
852static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
853
Christopher Fauletff2613e2016-11-09 11:36:17 +0100854 { "var", smp_fetch_var, ARG1(1,STR), smp_check_var, SMP_T_STR, SMP_USE_L4CLI },
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200855 { /* END */ },
856}};
857
858static struct sample_conv_kw_list sample_conv_kws = {ILH, {
Christopher Faulet85d79c92016-11-09 16:54:56 +0100859 { "set-var", smp_conv_store, ARG1(1,STR), conv_check_var, SMP_T_ANY, SMP_T_ANY },
860 { "unset-var", smp_conv_clear, ARG1(1,STR), conv_check_var, SMP_T_ANY, SMP_T_ANY },
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200861 { /* END */ },
862}};
863
Willy Tarreau620408f2016-10-21 16:37:51 +0200864static struct action_kw_list tcp_req_sess_kws = { { }, {
Christopher Faulet85d79c92016-11-09 16:54:56 +0100865 { "set-var", parse_store, 1 },
866 { "unset-var", parse_store, 1 },
Willy Tarreau620408f2016-10-21 16:37:51 +0200867 { /* END */ }
868}};
869
870static struct action_kw_list tcp_req_cont_kws = { { }, {
Christopher Faulet85d79c92016-11-09 16:54:56 +0100871 { "set-var", parse_store, 1 },
872 { "unset-var", parse_store, 1 },
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200873 { /* END */ }
874}};
875
Thierry FOURNIER36481b82015-08-19 09:01:53 +0200876static struct action_kw_list tcp_res_kws = { { }, {
Christopher Faulet85d79c92016-11-09 16:54:56 +0100877 { "set-var", parse_store, 1 },
878 { "unset-var", parse_store, 1 },
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200879 { /* END */ }
880}};
881
Thierry FOURNIER36481b82015-08-19 09:01:53 +0200882static struct action_kw_list http_req_kws = { { }, {
Christopher Faulet85d79c92016-11-09 16:54:56 +0100883 { "set-var", parse_store, 1 },
884 { "unset-var", parse_store, 1 },
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200885 { /* END */ }
886}};
887
Thierry FOURNIER36481b82015-08-19 09:01:53 +0200888static struct action_kw_list http_res_kws = { { }, {
Christopher Faulet85d79c92016-11-09 16:54:56 +0100889 { "set-var", parse_store, 1 },
890 { "unset-var", parse_store, 1 },
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200891 { /* END */ }
892}};
893
894static struct cfg_kw_list cfg_kws = {{ },{
895 { CFG_GLOBAL, "tune.vars.global-max-size", vars_max_size_global },
Christopher Fauletff2613e2016-11-09 11:36:17 +0100896 { CFG_GLOBAL, "tune.vars.proc-max-size", vars_max_size_proc },
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200897 { CFG_GLOBAL, "tune.vars.sess-max-size", vars_max_size_sess },
898 { CFG_GLOBAL, "tune.vars.txn-max-size", vars_max_size_txn },
899 { CFG_GLOBAL, "tune.vars.reqres-max-size", vars_max_size_reqres },
900 { /* END */ }
901}};
902
903__attribute__((constructor))
Christopher Faulete95f2c32017-07-24 16:30:34 +0200904static void __vars_init(void)
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200905{
906 var_pool = create_pool("vars", sizeof(struct var), MEM_F_SHARED);
907
908 sample_register_fetches(&sample_fetch_keywords);
909 sample_register_convs(&sample_conv_kws);
Willy Tarreau620408f2016-10-21 16:37:51 +0200910 tcp_req_sess_keywords_register(&tcp_req_sess_kws);
911 tcp_req_cont_keywords_register(&tcp_req_cont_kws);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200912 tcp_res_cont_keywords_register(&tcp_res_kws);
913 http_req_keywords_register(&http_req_kws);
914 http_res_keywords_register(&http_res_kws);
915 cfg_register_keywords(&cfg_kws);
Christopher Faulete95f2c32017-07-24 16:30:34 +0200916
917 RWLOCK_INIT(&var_names_rwlock);
Thierry FOURNIER4834bc72015-06-06 19:29:07 +0200918}