MINOR: checks/vars: Add a check scope for variables

Add a dedicated vars scope for checks. This scope is considered as part of the
session scope for accounting purposes.

The scope can be addressed by a valid session, even embryonic. The stream is not
necessary.

The scope is initialized after the check session is created. All variables are
then pruned before the session is destroyed.
diff --git a/src/vars.c b/src/vars.c
index 403cb69..0b7b990 100644
--- a/src/vars.c
+++ b/src/vars.c
@@ -14,6 +14,7 @@
 #include <proto/stream.h>
 #include <proto/tcp_rules.h>
 #include <proto/vars.h>
+#include <proto/checks.h>
 
 /* This contains a pool of struct vars */
 DECLARE_STATIC_POOL(var_pool, "vars", sizeof(struct var));
@@ -33,6 +34,7 @@
 static unsigned int var_sess_limit = 0;
 static unsigned int var_txn_limit = 0;
 static unsigned int var_reqres_limit = 0;
+static unsigned int var_check_limit = 0;
 
 __decl_rwlock(var_names_rwlock);
 
@@ -46,6 +48,11 @@
 		return &global.vars;
 	case SCOPE_SESS:
 		return &sess->vars;
+	case SCOPE_CHECK: {
+			struct server *srv = objt_server(sess->origin);
+
+			return srv ? &srv->check.vars : NULL;
+		}
 	case SCOPE_TXN:
 		return strm ? &strm->vars_txn : NULL;
 	case SCOPE_REQ:
@@ -69,7 +76,15 @@
 	case SCOPE_TXN:
 		if (strm)
 			_HA_ATOMIC_ADD(&strm->vars_txn.size, size);
+		goto scope_sess;
+	case SCOPE_CHECK: {
+			struct server *srv = objt_server(sess->origin);
+
+			if (srv != NULL)
+				_HA_ATOMIC_ADD(&srv->check.vars.size, size);
+		}
 		/* fall through */
+scope_sess:
 	case SCOPE_SESS:
 		_HA_ATOMIC_ADD(&sess->vars.size, size);
 		/* fall through */
@@ -97,7 +112,16 @@
 	case SCOPE_TXN:
 		if (var_txn_limit && strm && strm->vars_txn.size + size > var_txn_limit)
 			return 0;
+		goto scope_sess;
+	case SCOPE_CHECK: {
+			struct server *srv = objt_server(sess->origin);
+
+			if (var_check_limit && srv &&
+			    srv->check.vars.size + size > var_check_limit)
+				return 0;
+		}
 		/* fall through */
+scope_sess:
 	case SCOPE_SESS:
 		if (var_sess_limit && sess->vars.size + size > var_sess_limit)
 			return 0;
@@ -226,9 +250,14 @@
 		len -= 4;
 		*scope = SCOPE_RES;
 	}
+	else if (len > 6 && strncmp(name, "check.", 6) == 0) {
+		name += 6;
+		len -= 6;
+		*scope = SCOPE_CHECK;
+	}
 	else {
 		memprintf(err, "invalid variable name '%s'. A variable name must be start by its scope. "
-		               "The scope can be 'proc', 'sess', 'txn', 'req' or 'res'", name);
+		               "The scope can be 'proc', 'sess', 'txn', 'req', 'res' or 'check'", name);
 		return res;
 	}
 
@@ -827,6 +856,13 @@
 	return vars_max_size(args, section_type, curpx, defpx, file, line, err, &var_reqres_limit);
 }
 
+static int vars_max_size_check(char **args, int section_type, struct proxy *curpx,
+                                struct proxy *defpx, const char *file, int line,
+                                char **err)
+{
+	return vars_max_size(args, section_type, curpx, defpx, file, line, err, &var_check_limit);
+}
+
 static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
 
 	{ "var", smp_fetch_var, ARG1(1,STR), smp_check_var, SMP_T_STR, SMP_USE_L4CLI },
@@ -897,6 +933,7 @@
 	{ CFG_GLOBAL, "tune.vars.sess-max-size",   vars_max_size_sess   },
 	{ CFG_GLOBAL, "tune.vars.txn-max-size",    vars_max_size_txn    },
 	{ CFG_GLOBAL, "tune.vars.reqres-max-size", vars_max_size_reqres },
+	{ CFG_GLOBAL, "tune.vars.check-max-size",  vars_max_size_check  },
 	{ /* END */ }
 }};