MINOR: checks: Add support to set-var and unset-var rules in tcp-checks

Evaluate the registered action_ptr associated with each CHK_ACTION_KW rules from
a ruleset. Currently only the 'set-var' and 'unset-var' are parsed by the
tcp-check parser. Thus it is now possible to set or unset variables. It is
possible to use such rules before the first connect of the ruleset.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 09f4b66..40585b8 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -2759,6 +2759,8 @@
 tcp-check expect                          -          -         X         X
 tcp-check send                            -          -         X         X
 tcp-check send-binary                     -          -         X         X
+tcp-check set-var                         -          -         X         X
+tcp-check unset-var                       -          -         X         X
 tcp-request connection                    -          X         X         -
 tcp-request content                       -          X         X         X
 tcp-request inspect-delay                 -          X         X         X
@@ -7986,6 +7988,10 @@
     in debug mode. It is useful to make user-friendly error reporting.
     The "comment" is of course optional.
 
+    During the execution of a health check, a variable scope is made available
+    to store data samples, using the "tcp-check set-var" operation. Freeing
+    those variable is possible using "tcp-check unset-var".
+
 
   Examples :
          # perform a POP check (analyze only server's banner)
@@ -9805,6 +9811,9 @@
   the ruleset with a 'connect' rule. Purpose is to ensure admin know what they
   do.
 
+  When a connect must start the ruleset, if may still be preceded by set-var,
+  unset-var or comment rules.
+
   Parameters :
     They are optional and can be used to describe how HAProxy should open and
     use the TCP connection.
@@ -9991,6 +10000,50 @@
              "tcp-check send", tune.chksize
 
 
+tcp-check set-var(<var-name>) <expr>
+
+  This operation sets the content of a variable. The variable is declared inline.
+
+  May be used in sections:   defaults | frontend | listen | backend
+                               no     |    no    |   yes  |   yes
+
+  Arguments:
+    <var-name>  The name of the variable starts with an indication about its
+                scope. The scopes allowed for tcp-check are:
+                  "proc" : the variable is shared with the whole process.
+                  "sess" : the variable is shared with the tcp-check session.
+                  "check": the variable is declared for the lifetime of the tcp-check.
+                This prefix is followed by a name. The separator is a '.'.
+                The name may only contain characters 'a-z', 'A-Z', '0-9', '.',
+                and '-'.
+
+    <expr>      Is a sample-fetch expression potentially followed by converters.
+
+  Example:
+    tcp-check set-var(check.port) int(1234)
+
+
+tcp-check unset-var(<var-name>)
+
+  Free a reference to a variable within its scope.
+
+  May be used in sections:   defaults | frontend | listen | backend
+                               no     |    no    |   yes  |   yes
+
+  Arguments:
+    <var-name>  The name of the variable starts with an indication about its
+                scope. The scopes allowed for tcp-check are:
+                  "proc" : the variable is shared with the whole process.
+                  "sess" : the variable is shared with the tcp-check session.
+                  "check": the variable is declared for the lifetime of the tcp-check.
+                This prefix is followed by a name. The separator is a '.'.
+                The name may only contain characters 'a-z', 'A-Z', '0-9', '.',
+                and '-'.
+
+  Example:
+    tcp-check unset-var(check.port)
+
+
 tcp-request connection <action> [{if | unless} <condition>]
   Perform an action on an incoming connection depending on a layer 4 condition
   May be used in sections :   defaults | frontend | listen | backend
diff --git a/src/checks.c b/src/checks.c
index 5e147b8..b9fb4d5 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -3042,8 +3042,7 @@
 }
 
 /* Evaluate a TCPCHK_ACT_EXPECT rule. It returns 1 to evaluate the next rule, 0
- * to wait and -1 to stop the check. <rule> is updated to point on the last
- * evaluated TCPCHK_ACT_EXPECT rule.
+ * to wait and -1 to stop the check.
  */
 static enum tcpcheck_eval_ret tcpcheck_eval_expect(struct check *check, struct tcpcheck_rule *rule, int last_read)
 {
@@ -3167,6 +3166,27 @@
 	return ret;
 }
 
+/* Evaluate a TCPCHK_ACT_ACTION_KW rule. It returns 1 to evaluate the next rule, 0
+ * to wait and -1 to stop the check.
+ */
+static enum tcpcheck_eval_ret tcpcheck_eval_action_kw(struct check *check, struct tcpcheck_rule *rule)
+{
+	enum tcpcheck_eval_ret ret = TCPCHK_EVAL_CONTINUE;
+	struct act_rule *act_rule;
+	enum act_return act_ret;
+
+	act_rule =rule->action_kw.rule;
+	act_ret = act_rule->action_ptr(act_rule, check->proxy, check->sess, NULL, 0);
+	if (act_ret != ACT_RET_CONT) {
+		chunk_printf(&trash, "TCPCHK ACTION unexpected result at step %d\n",
+			     tcpcheck_get_step_id(check, rule));
+		set_server_check_status(check, HCHK_STATUS_L7RSP, trash.area);
+		ret = TCPCHK_EVAL_STOP;
+	}
+
+	return ret;
+}
+
 /* proceed with next steps for the TCP checks <check>. Note that this is called
  * both from the connection's wake() callback and from the check scheduling task.
  * It returns 0 on normal cases, or <0 if a close() has happened on an existing
@@ -3308,12 +3328,17 @@
 				}
 				must_read = 0;
 			}
+
 			eval_ret = tcpcheck_eval_expect(check, rule, last_read);
 			if (eval_ret == TCPCHK_EVAL_WAIT) {
 				check->current_step = rule->expect.head;
 				conn->mux->subscribe(cs, SUB_RETRY_RECV, &check->wait_list);
 			}
 			break;
+		case TCPCHK_ACT_ACTION_KW:
+			/* Don't update the current step */
+			eval_ret = tcpcheck_eval_action_kw(check, rule);
+			break;
 		default:
 			/* Otherwise, just go to the next one and don't update
 			 * the current step
@@ -3588,7 +3613,7 @@
 				tcpcheck->expect.head = prev_check;
 			continue;
 		}
-		if (prev_check->action != TCPCHK_ACT_COMMENT)
+		if (prev_check->action != TCPCHK_ACT_COMMENT && prev_check->action != TCPCHK_ACT_ACTION_KW)
 			break;
 	}
 	LIST_ADDQ(list, &tcpcheck->list);
@@ -4368,7 +4393,7 @@
 				chk->expect.head = prev_check;
 			continue;
 		}
-		if (prev_check->action != TCPCHK_ACT_COMMENT)
+		if (prev_check->action != TCPCHK_ACT_COMMENT && prev_check->action != TCPCHK_ACT_ACTION_KW)
 			break;
 	}
 	return chk;
diff --git a/src/vars.c b/src/vars.c
index 7f3d2d0..0fa3397 100644
--- a/src/vars.c
+++ b/src/vars.c
@@ -671,6 +671,7 @@
 	case ACT_F_TCP_RES_CNT: dir = SMP_OPT_DIR_RES; break;
 	case ACT_F_HTTP_REQ:    dir = SMP_OPT_DIR_REQ; break;
 	case ACT_F_HTTP_RES:    dir = SMP_OPT_DIR_RES; break;
+	case ACT_F_TCP_CHK:     dir = SMP_OPT_DIR_REQ; break;
 	default:
 		send_log(px, LOG_ERR, "Vars: internal error while execute action store.");
 		if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))