]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: tcpcheck: Refactor how tcp-check rulesets are stored
authorChristopher Faulet <cfaulet@haproxy.com>
Thu, 26 Mar 2026 07:56:29 +0000 (08:56 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Wed, 1 Apr 2026 14:34:37 +0000 (16:34 +0200)
The tcpcheck_rules structure is replaced by the tcpcheck structure. The main
difference is that the ruleset is now referenced in the tcpcheck structure,
instead of the rules list. The flags about the ruleset type are moved into
the ruleset structure and flags to track unused rules remains on the
tcpcheck structure. So it should be easier to track unused rulesets. But it
should be possible to configure a set of tcpcheck rules outside of the proxy
scope.

The main idea of these changes is to prepare the parsing of a new
healthcheck section. So this patch is quite huge, but it is mainly about
renaming some fields.

include/haproxy/check-t.h
include/haproxy/proxy-t.h
include/haproxy/tcpcheck-t.h
include/haproxy/tcpcheck.h
src/cfgdiag.c
src/check.c
src/connection.c
src/proxy.c
src/server.c
src/tcpcheck.c

index 2be5ad2a0d3f8875ac24d706d41e75c1dfcb8b11..720d2ff02951b131c8c5fd1d3e3c1412d875d861 100644 (file)
@@ -155,7 +155,7 @@ enum {
 };
 
 struct tcpcheck_rule;
-struct tcpcheck_rules;
+struct tcpcheck;
 
 struct check {
        enum obj_type obj_type;                 /* object type == OBJ_TYPE_CHECK */
@@ -174,7 +174,7 @@ struct check {
        signed char use_ssl;                    /* use SSL for health checks (1: on, 0: server mode, -1: off) */
        int send_proxy;                         /* send a PROXY protocol header with checks */
        int reuse_pool;                         /* try to reuse idle connections */
-       struct tcpcheck_rules *tcpcheck_rules;  /* tcp-check send / expect rules */
+       struct tcpcheck *tcpcheck;               /* tcp-check to use to perform a health-check */
        struct tcpcheck_rule *current_step;     /* current step when using tcpcheck */
        int inter, fastinter, downinter;        /* checks: time in milliseconds */
        enum chk_result result;                 /* health-check result : CHK_RES_* */
index e4422b2e799c1851e89ba8c85788928187e48817..0960de70b6c4387e9fc2d77d422bbc42c28b1672 100644 (file)
@@ -445,7 +445,7 @@ struct proxy {
        struct stktable *table;                 /* table for storing sticking streams */
 
        struct task *task;                      /* the associated task, mandatory to manage rate limiting, stopping and resource shortage, NULL if disabled */
-       struct tcpcheck_rules tcpcheck_rules;   /* tcp-check send / expect rules */
+       struct tcpcheck tcpcheck;               /* tcp-check to use to perform a health-check */
        char *check_command;                    /* Command to use for external agent checks */
        char *check_path;                       /* PATH environment to use for external agent checks */
        struct http_reply *replies[HTTP_ERR_SIZE]; /* HTTP replies for known errors */
index 3f48527ed72fd2439176b1419e0f34a7277267d2..b35d60c7fbecff210508e9fc665c327f06223e54 100644 (file)
@@ -104,10 +104,10 @@ enum tcpcheck_rule_type {
        TCPCHK_ACT_ACTION_KW, /* custom registered action_kw rule. */
 };
 
-#define TCPCHK_RULES_NONE           0x00000000
-#define TCPCHK_RULES_UNUSED_TCP_RS  0x00000001 /* An unused tcp-check ruleset exists */
-#define TCPCHK_RULES_UNUSED_HTTP_RS 0x00000002 /* An unused http-check ruleset exists */
-#define TCPCHK_RULES_UNUSED_RS      0x00000003 /* Mask for unused ruleset */
+#define TCPCHK_FL_NONE           0x00000000
+#define TCPCHK_FL_UNUSED_TCP_RS  0x00000001 /* An unused tcp-check ruleset exists for the current proxy */
+#define TCPCHK_FL_UNUSED_HTTP_RS 0x00000002 /* An unused http-check ruleset exists for the current proxy  */
+#define TCPCHK_FL_UNUSED_RS      0x00000003 /* Mask for unused ruleset */
 
 #define TCPCHK_RULES_PGSQL_CHK   0x00000010
 #define TCPCHK_RULES_REDIS_CHK   0x00000020
@@ -228,18 +228,17 @@ struct tcpcheck_var {
        struct list list;        /* element to chain tcp-check vars */
 };
 
-/* a list of tcp-check rules */
-struct tcpcheck_rules {
-       unsigned int flags;       /* flags applied to the rules */
-       struct list *list;        /* the list of tcpcheck_rules */
-       struct list  preset_vars; /* The list of variable to preset before executing the ruleset */
-};
-
 /* A list of tcp-check rules with a name */
 struct tcpcheck_ruleset {
        struct list rules;     /* the list of tcpcheck_rule */
+       unsigned int flags;    /* flags applied to the rules */
        struct ebpt_node node; /* node in the shared tree */
 };
 
+struct tcpcheck {
+       struct tcpcheck_ruleset *rs; /* The tcp-check ruleset to use */
+       struct list preset_vars;     /* The list of variable to preset before executing the ruleset */
+       unsigned int flags;          /* TCPCHECK_FL_* */
+};
 
 #endif /* _HAPROXY_CHECKS_T_H */
index 95244a521203c2be167f772c66f7a8a0240ffc82..23059868c4a7bc7dbac8dee9b9691622b5455bdd 100644 (file)
@@ -36,7 +36,7 @@ extern struct action_kw_list tcp_check_keywords;
 extern struct pool_head *pool_head_tcpcheck_rule;
 
 int tcpcheck_get_step_id(const struct check *check, const struct tcpcheck_rule *rule);
-struct tcpcheck_rule *get_first_tcpcheck_rule(const struct tcpcheck_rules *rules);
+struct tcpcheck_rule *get_first_tcpcheck_rule(const struct tcpcheck_ruleset *rs);
 
 struct tcpcheck_ruleset *create_tcpcheck_ruleset(const char *name);
 struct tcpcheck_ruleset *find_tcpcheck_ruleset(const char *name);
@@ -50,9 +50,9 @@ void free_tcpcheck_var(struct tcpcheck_var *var);
 int dup_tcpcheck_vars(struct list *dst, const struct list *src);
 void free_tcpcheck_vars(struct list *vars);
 
-int add_tcpcheck_expect_str(struct tcpcheck_rules *rules, const char *str);
-int add_tcpcheck_send_strs(struct tcpcheck_rules *rules, const char * const *strs);
-int tcpcheck_add_http_rule(struct tcpcheck_rule *chk, struct tcpcheck_rules *rules, char **errmsg);
+int add_tcpcheck_expect_str(struct tcpcheck_ruleset *rs, const char *str);
+int add_tcpcheck_send_strs(struct tcpcheck_ruleset *rs, const char * const *strs);
+int tcpcheck_add_http_rule(struct tcpcheck_rule *chk, struct tcpcheck_ruleset *rs, char **errmsg);
 
 void free_tcpcheck_http_hdr(struct tcpcheck_http_hdr *hdr);
 
index 0d4e580d3f58dfe65af704d7e27d750f569778ef..f7ce45ac04316c2e266394b4d33b178d83265391 100644 (file)
@@ -71,7 +71,7 @@ static void srv_diag_cookies(int *ret, struct server *srv, struct eb_root *cooki
 static void srv_diag_check_reuse(int *ret, struct server *srv, struct proxy *px)
 {
        if (srv->do_check && srv->check.reuse_pool) {
-               if ((px->tcpcheck_rules.flags & TCPCHK_RULES_PROTO_CHK) != TCPCHK_RULES_HTTP_CHK) {
+               if (px->tcpcheck.rs && (px->tcpcheck.rs->flags & TCPCHK_RULES_PROTO_CHK) != TCPCHK_RULES_HTTP_CHK) {
                        diag_warning(ret, "parsing [%s:%d] : 'server %s': check-reuse-pool is ineffective for non http-check rulesets.\n",
                                     srv->conf.file, srv->conf.line, srv->id);
                }
index 051d4ca40a9a54877075c7412fec7b9bb4f0ff74..5b33e85c43dd527c3440e721c3885277e19727f5 100644 (file)
@@ -235,7 +235,7 @@ static void check_trace(enum trace_level level, uint64_t mask,
        if (mask & CHK_EV_TCPCHK) {
                const char *type;
 
-               switch (check->tcpcheck_rules->flags & TCPCHK_RULES_PROTO_CHK) {
+               switch (check->tcpcheck->rs->flags & TCPCHK_RULES_PROTO_CHK) {
                        case TCPCHK_RULES_PGSQL_CHK: type = "PGSQL"; break;
                        case TCPCHK_RULES_REDIS_CHK: type = "REDIS"; break;
                        case TCPCHK_RULES_SMTP_CHK:  type = "SMTP";  break;
@@ -271,7 +271,7 @@ static void check_trace(enum trace_level level, uint64_t mask,
                        buf = (b_is_null(&check->bo) ? NULL : &check->bo);
 
                if (buf) {
-                       if ((check->tcpcheck_rules->flags & TCPCHK_RULES_PROTO_CHK) == TCPCHK_RULES_HTTP_CHK) {
+                       if ((check->tcpcheck->rs->flags & TCPCHK_RULES_PROTO_CHK) == TCPCHK_RULES_HTTP_CHK) {
                                int full = (src->verbosity == CHK_VERB_COMPLETE);
 
                                chunk_memcat(&trace_buf, "\n\t", 2);
@@ -832,7 +832,7 @@ void chk_report_conn_err(struct check *check, int errno_bck, int expired)
        chk = get_trash_chunk();
 
        if (check->type == PR_O2_TCPCHK_CHK &&
-           (check->tcpcheck_rules->flags & TCPCHK_RULES_PROTO_CHK) == TCPCHK_RULES_TCP_CHK) {
+           (check->tcpcheck->rs->flags & TCPCHK_RULES_PROTO_CHK) == TCPCHK_RULES_TCP_CHK) {
                step = tcpcheck_get_step_id(check, NULL);
                if (!step) {
                        TRACE_DEVEL("initial connection failure", CHK_EV_HCHK_END|CHK_EV_HCHK_ERR, check);
@@ -1565,8 +1565,8 @@ void free_check(struct check *check)
         * in this case.
         */
        if (check->state & CHK_ST_AGENT) {
-               free_tcpcheck_vars(&check->tcpcheck_rules->preset_vars);
-               ha_free(&check->tcpcheck_rules);
+               free_tcpcheck_vars(&check->tcpcheck->preset_vars);
+               ha_free(&check->tcpcheck);
        }
 
        ha_free(&check->pool_conn_name);
@@ -1686,7 +1686,7 @@ static int start_checks()
        for (px = proxies_list; px; px = px->next) {
                for (s = px->srv; s; s = s->next) {
                        if ((px->options2 & PR_O2_USE_SBUF_CHECK) &&
-                           (s->check.tcpcheck_rules->flags & TCPCHK_RULES_MAY_USE_SBUF))
+                           (s->check.tcpcheck->rs->flags & TCPCHK_RULES_MAY_USE_SBUF))
                                s->check.state |= CHK_ST_USE_SMALL_BUFF;
 
                        if (s->check.state & CHK_ST_CONFIGURED) {
@@ -1803,7 +1803,7 @@ int init_srv_check(struct server *srv)
        if (!srv->do_check || !(srv->proxy->cap & PR_CAP_BE))
                goto out;
 
-       check_type = srv->check.tcpcheck_rules->flags & TCPCHK_RULES_PROTO_CHK;
+       check_type = srv->check.tcpcheck->rs->flags & TCPCHK_RULES_PROTO_CHK;
 
        if (!(srv->flags & SRV_F_DYNAMIC)) {
                /* If neither a port nor an addr was specified and no check
@@ -1897,7 +1897,7 @@ int init_srv_check(struct server *srv)
            (!is_inet_addr(&srv->check.addr) && (is_addr(&srv->check.addr) || !is_inet_addr(&srv->addr))))
                goto init;
 
-       if (!srv->proxy->tcpcheck_rules.list || LIST_ISEMPTY(srv->proxy->tcpcheck_rules.list)) {
+       if (LIST_ISEMPTY(&srv->check.tcpcheck->rs->rules)) {
                ha_alert("config: %s '%s': server '%s' has neither service port nor check port.\n",
                         proxy_type_str(srv->proxy), srv->proxy->id, srv->id);
                ret |= ERR_ALERT | ERR_ABORT;
@@ -1905,7 +1905,7 @@ int init_srv_check(struct server *srv)
        }
 
        /* search the first action (connect / send / expect) in the list */
-       r = get_first_tcpcheck_rule(&srv->proxy->tcpcheck_rules);
+       r = get_first_tcpcheck_rule(srv->check.tcpcheck->rs);
        if (!r || (r->action != TCPCHK_ACT_CONNECT) || (!r->connect.port && !get_host_port(&r->connect.addr))) {
                ha_alert("config: %s '%s': server '%s' has neither service port nor check port "
                         "nor tcp_check rule 'connect' with port information.\n",
@@ -1915,7 +1915,7 @@ int init_srv_check(struct server *srv)
        }
 
        /* scan the tcp-check ruleset to ensure a port has been configured */
-       list_for_each_entry(r, srv->proxy->tcpcheck_rules.list, list) {
+       list_for_each_entry(r, &srv->check.tcpcheck->rs->rules, list) {
                if ((r->action == TCPCHK_ACT_CONNECT) && (!r->connect.port && !get_host_port(&r->connect.addr))) {
                        ha_alert("config: %s '%s': server '%s' has neither service port nor check port, "
                                 "and a tcp_check rule 'connect' with no port information.\n",
@@ -1962,7 +1962,7 @@ int init_srv_agent_check(struct server *srv)
        /* If there is no connect rule preceding all send / expect rules, an
         * implicit one is inserted before all others.
         */
-       chk = get_first_tcpcheck_rule(srv->agent.tcpcheck_rules);
+       chk = get_first_tcpcheck_rule(srv->agent.tcpcheck->rs);
        if (!chk || chk->action != TCPCHK_ACT_CONNECT) {
                chk = calloc(1, sizeof(*chk));
                if (!chk) {
@@ -1974,14 +1974,14 @@ int init_srv_agent_check(struct server *srv)
                }
                chk->action = TCPCHK_ACT_CONNECT;
                chk->connect.options = (TCPCHK_OPT_DEFAULT_CONNECT|TCPCHK_OPT_IMPLICIT);
-               LIST_INSERT(srv->agent.tcpcheck_rules->list, &chk->list);
+               LIST_INSERT(&srv->agent.tcpcheck->rs->rules, &chk->list);
        }
 
        /* <chk> is always defined here and it is a CONNECT action. If there is
         * a preset variable, it means there is an agent string defined and data
         * will be sent after the connect.
         */
-       if (!LIST_ISEMPTY(&srv->agent.tcpcheck_rules->preset_vars))
+       if (!LIST_ISEMPTY(&srv->agent.tcpcheck->preset_vars))
                chk->connect.options |= TCPCHK_OPT_HAS_DATA;
 
 
@@ -2137,7 +2137,7 @@ static int srv_parse_agent_check(char **args, int *cur_arg, struct proxy *curpx,
                                 char **errmsg)
 {
        struct tcpcheck_ruleset *rs = NULL;
-       struct tcpcheck_rules *rules = srv->agent.tcpcheck_rules;
+       struct tcpcheck *tc = srv->agent.tcpcheck;
        struct tcpcheck_rule *chk;
        int err_code = 0;
 
@@ -2150,17 +2150,15 @@ static int srv_parse_agent_check(char **args, int *cur_arg, struct proxy *curpx,
                return ERR_WARN;
        }
 
-       if (!rules) {
-               rules = calloc(1, sizeof(*rules));
-               if (!rules) {
+       if (!tc) {
+               tc = calloc(1, sizeof(*tc));
+               if (!tc) {
                        memprintf(errmsg, "out of memory.");
                        goto error;
                }
-               LIST_INIT(&rules->preset_vars);
-               srv->agent.tcpcheck_rules = rules;
+               LIST_INIT(&tc->preset_vars);
+               srv->agent.tcpcheck = tc;
        }
-       rules->list  = NULL;
-       rules->flags = 0;
 
        rs = find_tcpcheck_ruleset("*agent-check");
        if (rs)
@@ -2193,9 +2191,9 @@ static int srv_parse_agent_check(char **args, int *cur_arg, struct proxy *curpx,
        LIST_APPEND(&rs->rules, &chk->list);
 
   ruleset_found:
-       rules->list = &rs->rules;
-       rules->flags &= ~(TCPCHK_RULES_PROTO_CHK|TCPCHK_RULES_UNUSED_RS);
-       rules->flags |= TCPCHK_RULES_AGENT_CHK;
+       tc->rs = rs;
+       tc->flags &= ~TCPCHK_FL_UNUSED_RS;
+       rs->flags |= TCPCHK_RULES_AGENT_CHK;
        srv->do_agent = 1;
 
   out:
@@ -2288,7 +2286,7 @@ static int srv_parse_agent_port(char **args, int *cur_arg, struct proxy *curpx,
 
 int set_srv_agent_send(struct server *srv, const char *send)
 {
-       struct tcpcheck_rules *rules = srv->agent.tcpcheck_rules;
+       struct tcpcheck *tc = srv->agent.tcpcheck;
        struct tcpcheck_var *var = NULL;
        char *str;
 
@@ -2297,13 +2295,13 @@ int set_srv_agent_send(struct server *srv, const char *send)
        if (str == NULL || var == NULL)
                goto error;
 
-       free_tcpcheck_vars(&rules->preset_vars);
+       free_tcpcheck_vars(&tc->preset_vars);
 
        var->data.type = SMP_T_STR;
        var->data.u.str.area = str;
        var->data.u.str.data = strlen(str);
        LIST_INIT(&var->list);
-       LIST_APPEND(&rules->preset_vars, &var->list);
+       LIST_APPEND(&tc->preset_vars, &var->list);
 
        return 1;
 
@@ -2317,7 +2315,7 @@ int set_srv_agent_send(struct server *srv, const char *send)
 static int srv_parse_agent_send(char **args, int *cur_arg, struct proxy *curpx, struct server *srv,
                                char **errmsg)
 {
-       struct tcpcheck_rules *rules = srv->agent.tcpcheck_rules;
+       struct tcpcheck *tc = srv->agent.tcpcheck;
        int err_code = 0;
 
        if (!*(args[*cur_arg+1])) {
@@ -2325,14 +2323,14 @@ static int srv_parse_agent_send(char **args, int *cur_arg, struct proxy *curpx,
                goto error;
        }
 
-       if (!rules) {
-               rules = calloc(1, sizeof(*rules));
-               if (!rules) {
+       if (!tc) {
+               tc = calloc(1, sizeof(*tc));
+               if (!tc) {
                        memprintf(errmsg, "out of memory.");
                        goto error;
                }
-               LIST_INIT(&rules->preset_vars);
-               srv->agent.tcpcheck_rules = rules;
+               LIST_INIT(&tc->preset_vars);
+               srv->agent.tcpcheck = tc;
        }
 
        if (!set_srv_agent_send(srv, args[*cur_arg+1])) {
index 227d25599a08e5101456661e77237b6beff8c5e6..19ee3be57c1a898f65a9fa9994a328ea4534a4d3 100644 (file)
@@ -412,7 +412,7 @@ int conn_install_mux_chk(struct connection *conn, void *ctx, struct session *ses
                struct ist mux_proto;
                const char *alpn_str = NULL;
                int alpn_len = 0;
-               int mode = tcpchk_rules_type_to_proto_mode(check->tcpcheck_rules->flags);
+               int mode = tcpchk_rules_type_to_proto_mode(check->tcpcheck->flags);
 
                conn_get_alpn(conn, &alpn_str, &alpn_len);
                mux_proto = ist2(alpn_str, alpn_len);
index 515b291f3ce168b4354cd4d660218fd62e9c895a..e9f9021a9898199af756a5eda0e7f0b8d954403e 100644 (file)
@@ -1577,7 +1577,7 @@ void init_new_proxy(struct proxy *p)
        LIST_INIT(&p->conf.args.list);
        LIST_INIT(&p->conf.lf_checks);
        LIST_INIT(&p->filter_configs);
-       LIST_INIT(&p->tcpcheck_rules.preset_vars);
+       LIST_INIT(&p->tcpcheck.preset_vars);
 
        MT_LIST_INIT(&p->lbprm.lb_free_list);
 
@@ -1876,14 +1876,14 @@ int proxy_finalize(struct proxy *px, int *err_code)
        else if (px->options & PR_O_TRANSP)
                px->options &= ~PR_O_DISPATCH;
 
-       if ((px->tcpcheck_rules.flags & TCPCHK_RULES_UNUSED_HTTP_RS)) {
+       if ((px->tcpcheck.flags & TCPCHK_FL_UNUSED_HTTP_RS)) {
                ha_warning("%s '%s' uses http-check rules without 'option httpchk', so the rules are ignored.\n",
                           proxy_type_str(px), px->id);
                *err_code |= ERR_WARN;
        }
 
        if ((px->options2 & PR_O2_CHK_ANY) == PR_O2_TCPCHK_CHK &&
-           (px->tcpcheck_rules.flags & TCPCHK_RULES_PROTO_CHK) != TCPCHK_RULES_HTTP_CHK) {
+           px->tcpcheck.rs && (px->tcpcheck.rs->flags & TCPCHK_RULES_PROTO_CHK) != TCPCHK_RULES_HTTP_CHK) {
                if (px->options & PR_O_DISABLE404) {
                        ha_warning("'%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
                                   "disable-on-404", proxy_type_str(px), px->id);
@@ -2443,7 +2443,7 @@ int proxy_finalize(struct proxy *px, int *err_code)
        if ((px->cap & PR_CAP_BE) && !px->timeout.queue)
                px->timeout.queue = px->timeout.connect;
 
-       if ((px->tcpcheck_rules.flags & TCPCHK_RULES_UNUSED_TCP_RS)) {
+       if (px->tcpcheck.flags & TCPCHK_FL_UNUSED_TCP_RS) {
                ha_warning("%s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
                           proxy_type_str(px), px->id);
                *err_code |= ERR_WARN;
@@ -2924,7 +2924,6 @@ int proxy_finalize(struct proxy *px, int *err_code)
        if (px->cap & PR_CAP_BE) {
                if (!(px->options2 & PR_O2_CHK_ANY)) {
                        struct tcpcheck_ruleset *rs = NULL;
-                       struct tcpcheck_rules *rules = &px->tcpcheck_rules;
 
                        px->options2 |= PR_O2_TCPCHK_CHK;
 
@@ -2937,10 +2936,8 @@ int proxy_finalize(struct proxy *px, int *err_code)
                                        cfgerr++;
                                }
                        }
-
-                       free_tcpcheck_vars(&rules->preset_vars);
-                       rules->list = &rs->rules;
-                       rules->flags = 0;
+                       px->tcpcheck.rs = rs;
+                       free_tcpcheck_vars(&px->tcpcheck.preset_vars);
                }
        }
 
@@ -3173,7 +3170,7 @@ int proxy_ref_defaults(struct proxy *px, struct proxy *defpx, char **errmsg)
                defaults_px_ref(defpx, px);
        }
 
-       if ((defpx->tcpcheck_rules.flags & TCPCHK_RULES_PROTO_CHK) &&
+       if (defpx->tcpcheck.rs && (defpx->tcpcheck.rs->flags & TCPCHK_RULES_PROTO_CHK) &&
            (px->cap & PR_CAP_LISTEN) == PR_CAP_BE) {
                /* If the current default proxy defines tcpcheck rules, the
                 * current proxy will keep a reference on it. but only if the
@@ -3411,14 +3408,12 @@ static int proxy_defproxy_cpy(struct proxy *curproxy, const struct proxy *defpro
                curproxy->redispatch_after = defproxy->redispatch_after;
                curproxy->max_ka_queue = defproxy->max_ka_queue;
 
-               curproxy->tcpcheck_rules.flags = (defproxy->tcpcheck_rules.flags & ~TCPCHK_RULES_UNUSED_RS);
-               curproxy->tcpcheck_rules.list  = defproxy->tcpcheck_rules.list;
-               if (!LIST_ISEMPTY(&defproxy->tcpcheck_rules.preset_vars)) {
-                       if (!dup_tcpcheck_vars(&curproxy->tcpcheck_rules.preset_vars,
-                                              &defproxy->tcpcheck_rules.preset_vars)) {
-                               memprintf(errmsg, "proxy '%s': failed to duplicate tcpcheck preset-vars", curproxy->id);
-                               return 1;
-                       }
+               curproxy->tcpcheck.flags = (defproxy->tcpcheck.flags & ~TCPCHK_FL_UNUSED_RS);
+               curproxy->tcpcheck.rs  = defproxy->tcpcheck.rs;
+               if (!dup_tcpcheck_vars(&curproxy->tcpcheck.preset_vars,
+                                      &defproxy->tcpcheck.preset_vars)) {
+                       memprintf(errmsg, "proxy '%s': failed to duplicate tcpcheck preset-vars", curproxy->id);
+                       return 1;
                }
 
                curproxy->ck_opts = defproxy->ck_opts;
index 58ccb50368a040181b5561144521d3999a878f43..aaa04abfe4fa663ebaeda7475ba6224ad24c6110 100644 (file)
@@ -2969,14 +2969,14 @@ void srv_settings_cpy(struct server *srv, const struct server *src, int srv_tmpl
        srv->agent.use_ssl            = src->agent.use_ssl;
        srv->agent.port               = src->agent.port;
 
-       if (src->agent.tcpcheck_rules) {
-               srv->agent.tcpcheck_rules = calloc(1, sizeof(*srv->agent.tcpcheck_rules));
-               if (srv->agent.tcpcheck_rules) {
-                       srv->agent.tcpcheck_rules->flags = src->agent.tcpcheck_rules->flags;
-                       srv->agent.tcpcheck_rules->list  = src->agent.tcpcheck_rules->list;
-                       LIST_INIT(&srv->agent.tcpcheck_rules->preset_vars);
-                       dup_tcpcheck_vars(&srv->agent.tcpcheck_rules->preset_vars,
-                                         &src->agent.tcpcheck_rules->preset_vars);
+       if (src->agent.tcpcheck) {
+               srv->agent.tcpcheck = calloc(1, sizeof(*srv->agent.tcpcheck));
+               if (srv->agent.tcpcheck) {
+                       srv->agent.tcpcheck->flags = (src->agent.tcpcheck->flags & ~TCPCHK_FL_UNUSED_RS);
+                       srv->agent.tcpcheck->rs = src->agent.tcpcheck->rs;
+                       LIST_INIT(&srv->agent.tcpcheck->preset_vars);
+                       dup_tcpcheck_vars(&srv->agent.tcpcheck->preset_vars,
+                                         &src->agent.tcpcheck->preset_vars);
                }
        }
 
@@ -3123,7 +3123,7 @@ struct server *new_server(struct proxy *proxy)
        srv->check.status = HCHK_STATUS_INI;
        srv->check.server = srv;
        srv->check.proxy = proxy;
-       srv->check.tcpcheck_rules = &proxy->tcpcheck_rules;
+       srv->check.tcpcheck = &proxy->tcpcheck;
 
        srv->agent.obj_type = OBJ_TYPE_CHECK;
        srv->agent.status = HCHK_STATUS_INI;
index bf42de0559b3fae6fcdfc191f679033aae77cdcc..5844860486b3a14828ce2d5a6ccad69e1b412e44 100644 (file)
@@ -312,7 +312,7 @@ struct tcpcheck_ruleset *create_tcpcheck_ruleset(const char *name)
                free(rs);
                return NULL;
        }
-
+       rs->flags = 0;
        LIST_INIT(&rs->rules);
        ebis_insert(&shared_tcpchecks, &rs->node);
        return rs;
@@ -361,11 +361,11 @@ int tcpcheck_get_step_id(const struct check *check, const struct tcpcheck_rule *
 /* Returns the first non COMMENT/ACTION_KW tcp-check rule from list <list> or
  * NULL if none was found.
  */
-struct tcpcheck_rule *get_first_tcpcheck_rule(const struct tcpcheck_rules *rules)
+struct tcpcheck_rule *get_first_tcpcheck_rule(const struct tcpcheck_ruleset *rs)
 {
        struct tcpcheck_rule *r;
 
-       list_for_each_entry(r, rules->list, list) {
+       list_for_each_entry(r, &rs->rules, list) {
                if (r->action != TCPCHK_ACT_COMMENT && r->action != TCPCHK_ACT_ACTION_KW)
                        return r;
        }
@@ -375,11 +375,11 @@ struct tcpcheck_rule *get_first_tcpcheck_rule(const struct tcpcheck_rules *rules
 /* Returns the last non COMMENT/ACTION_KW tcp-check rule from list <list> or
  * NULL if none was found.
  */
-static struct tcpcheck_rule *get_last_tcpcheck_rule(struct tcpcheck_rules *rules)
+static struct tcpcheck_rule *get_last_tcpcheck_rule(struct tcpcheck_ruleset *rs)
 {
        struct tcpcheck_rule *r;
 
-       list_for_each_entry_rev(r, rules->list, list) {
+       list_for_each_entry_rev(r, &rs->rules, list) {
                if (r->action != TCPCHK_ACT_COMMENT && r->action != TCPCHK_ACT_ACTION_KW)
                        return r;
        }
@@ -390,15 +390,15 @@ static struct tcpcheck_rule *get_last_tcpcheck_rule(struct tcpcheck_rules *rules
  * <start> or NULL if non was found. If <start> is NULL, it relies on
  * get_first_tcpcheck_rule().
  */
-static struct tcpcheck_rule *get_next_tcpcheck_rule(struct tcpcheck_rules *rules, struct tcpcheck_rule *start)
+static struct tcpcheck_rule *get_next_tcpcheck_rule(struct tcpcheck_ruleset *rs, struct tcpcheck_rule *start)
 {
        struct tcpcheck_rule *r;
 
        if (!start)
-               return get_first_tcpcheck_rule(rules);
+               return get_first_tcpcheck_rule(rs);
 
        r = LIST_NEXT(&start->list, typeof(r), list);
-       list_for_each_entry_from(r, rules->list, list) {
+       list_for_each_entry_from(r, &rs->rules, list) {
                if (r->action != TCPCHK_ACT_COMMENT && r->action != TCPCHK_ACT_ACTION_KW)
                        return r;
        }
@@ -438,7 +438,7 @@ static void tcpcheck_expect_onerror_message(struct buffer *msg, struct check *ch
        }
 
        if (check->type == PR_O2_TCPCHK_CHK &&
-           (check->tcpcheck_rules->flags & TCPCHK_RULES_PROTO_CHK) != TCPCHK_RULES_TCP_CHK) {
+           (check->tcpcheck->rs->flags & TCPCHK_RULES_PROTO_CHK) != TCPCHK_RULES_TCP_CHK) {
                goto comment;
        }
 
@@ -523,7 +523,7 @@ static void tcpcheck_expect_onsuccess_message(struct buffer *msg, struct check *
                msg->data += sess_build_logline(check->sess, NULL, b_tail(msg), b_room(msg),
                                                &rule->expect.onsuccess_fmt);
        else if (check->type == PR_O2_TCPCHK_CHK &&
-                (check->tcpcheck_rules->flags & TCPCHK_RULES_PROTO_CHK) == TCPCHK_RULES_TCP_CHK)
+                (check->tcpcheck->rs->flags & TCPCHK_RULES_PROTO_CHK) == TCPCHK_RULES_TCP_CHK)
                chunk_strcat(msg, "(tcp-check)");
 
        /* Finally, the check status code is set if the expect rule defines a
@@ -589,7 +589,7 @@ static enum tcpcheck_eval_ret tcpcheck_mysql_expect_packet(struct check *check,
                goto error;
        }
 
-       if (get_next_tcpcheck_rule(check->tcpcheck_rules, rule) != NULL) {
+       if (get_next_tcpcheck_rule(check->tcpcheck->rs, rule) != NULL) {
                /* Not the last rule, continue */
                goto out;
        }
@@ -1287,9 +1287,9 @@ enum tcpcheck_eval_ret tcpcheck_eval_connect(struct check *check, struct tcpchec
 
        TRACE_ENTER(CHK_EV_TCPCHK_CONN, check);
 
-       check_type = check->tcpcheck_rules->flags & TCPCHK_RULES_PROTO_CHK;
+       check_type = check->tcpcheck->rs->flags & TCPCHK_RULES_PROTO_CHK;
 
-       next = get_next_tcpcheck_rule(check->tcpcheck_rules, rule);
+       next = get_next_tcpcheck_rule(check->tcpcheck->rs, rule);
 
        /* current connection already created, check if it is established or not */
        if (conn) {
@@ -1567,7 +1567,7 @@ enum tcpcheck_eval_ret tcpcheck_eval_connect(struct check *check, struct tcpchec
                else if ((connect->options & TCPCHK_OPT_DEFAULT_CONNECT) && check->mux_proto)
                        mux_ops = check->mux_proto->mux;
                else {
-                       int mode = tcpchk_rules_type_to_proto_mode(check->tcpcheck_rules->flags);
+                       int mode = tcpchk_rules_type_to_proto_mode(check->tcpcheck->rs->flags);
 
                        mux_ops = conn_get_best_mux(conn, IST_NULL, PROTO_SIDE_BE, mode);
                }
@@ -2505,10 +2505,10 @@ int tcpcheck_main(struct check *check)
                        goto out_end_tcpcheck;
                }
                vars_init_head(&check->vars, SCOPE_CHECK);
-               rule = LIST_NEXT(check->tcpcheck_rules->list, typeof(rule), list);
+               rule = LIST_NEXT(&check->tcpcheck->rs->rules, typeof(rule), list);
 
                /* Preset tcp-check variables */
-               list_for_each_entry(var, &check->tcpcheck_rules->preset_vars, list) {
+               list_for_each_entry(var, &check->tcpcheck->preset_vars, list) {
                        struct sample smp;
 
                        memset(&smp, 0, sizeof(smp));
@@ -2521,7 +2521,7 @@ int tcpcheck_main(struct check *check)
 
        /* Now evaluate the tcp-check rules */
 
-       list_for_each_entry_from(rule, check->tcpcheck_rules->list, list) {
+       list_for_each_entry_from(rule, &check->tcpcheck->rs->rules, list) {
                check->code = 0;
                switch (rule->action) {
                case TCPCHK_ACT_CONNECT:
@@ -2567,7 +2567,7 @@ int tcpcheck_main(struct check *check)
                                must_read = 0;
                        }
 
-                       eval_ret = ((check->tcpcheck_rules->flags & TCPCHK_RULES_PROTO_CHK) == TCPCHK_RULES_HTTP_CHK
+                       eval_ret = ((check->tcpcheck->rs->flags & TCPCHK_RULES_PROTO_CHK) == TCPCHK_RULES_HTTP_CHK
                                    ? tcpcheck_eval_expect_http(check, rule, last_read)
                                    : tcpcheck_eval_expect(check, rule, last_read));
 
@@ -3903,7 +3903,7 @@ void tcpcheck_overwrite_send_http_rule(struct tcpcheck_rule *old, struct tcpchec
  * returns 1 on success and 0 on error and <errmsg> is filled with the error
  * message.
  */
-int tcpcheck_add_http_rule(struct tcpcheck_rule *chk, struct tcpcheck_rules *rules, char **errmsg)
+int tcpcheck_add_http_rule(struct tcpcheck_rule *chk, struct tcpcheck_ruleset *rs, char **errmsg)
 {
        struct tcpcheck_rule *r;
 
@@ -3929,15 +3929,15 @@ int tcpcheck_add_http_rule(struct tcpcheck_rule *chk, struct tcpcheck_rules *rul
                 *     both, overwriting the old send rule (the explicit one) with info of the
                 *     new send rule (the implicit one).
                 */
-               r = get_first_tcpcheck_rule(rules);
+               r = get_first_tcpcheck_rule(rs);
                if (r && r->action == TCPCHK_ACT_CONNECT)
-                       r = get_next_tcpcheck_rule(rules, r);
+                       r = get_next_tcpcheck_rule(rs, r);
                if (!r || r->action != TCPCHK_ACT_SEND)
-                       LIST_INSERT(rules->list, &chk->list);
+                       LIST_INSERT(&rs->rules, &chk->list);
                else if (r->send.http.flags & TCPCHK_SND_HTTP_FROM_OPT) {
                        LIST_DELETE(&r->list);
                        free_tcpcheck(r, 0);
-                       LIST_INSERT(rules->list, &chk->list);
+                       LIST_INSERT(&rs->rules, &chk->list);
                }
                else {
                        tcpcheck_overwrite_send_http_rule(r, chk);
@@ -3951,7 +3951,7 @@ int tcpcheck_add_http_rule(struct tcpcheck_rule *chk, struct tcpcheck_rules *rul
                 * the rule is appended to the list.
                 */
 
-               r = get_last_tcpcheck_rule(rules);
+               r = get_last_tcpcheck_rule(rs);
                if (!r || (r->action == TCPCHK_ACT_SEND && (r->send.http.flags & TCPCHK_SND_HTTP_FROM_OPT)))
                        /* no error */;
                else if (r->action != TCPCHK_ACT_CONNECT && chk->action == TCPCHK_ACT_SEND) {
@@ -3971,7 +3971,7 @@ int tcpcheck_add_http_rule(struct tcpcheck_rule *chk, struct tcpcheck_rules *rul
                }
 
                if (chk->action == TCPCHK_ACT_SEND) {
-                       r = get_first_tcpcheck_rule(rules);
+                       r = get_first_tcpcheck_rule(rs);
                        if (r && r->action == TCPCHK_ACT_SEND && (r->send.http.flags & TCPCHK_SND_HTTP_FROM_OPT)) {
                                tcpcheck_overwrite_send_http_rule(r, chk);
                                free_tcpcheck(chk, 0);
@@ -3980,7 +3980,7 @@ int tcpcheck_add_http_rule(struct tcpcheck_rule *chk, struct tcpcheck_rules *rul
                                chk = r;
                        }
                }
-               LIST_APPEND(rules->list, &chk->list);
+               LIST_APPEND(&rs->rules, &chk->list);
        }
        return 1;
 }
@@ -4001,23 +4001,23 @@ static int check_proxy_tcpcheck(struct proxy *px)
        ha_free(&px->check_command);
        ha_free(&px->check_path);
 
-       if (!px->tcpcheck_rules.list) {
+       if (!px->tcpcheck.rs) {
                ha_alert("proxy '%s' : tcp-check configured but no ruleset defined.\n", px->id);
                ret |= ERR_ALERT | ERR_FATAL;
                goto out;
        }
 
        /* HTTP ruleset only :  */
-       if ((px->tcpcheck_rules.flags & TCPCHK_RULES_PROTO_CHK) == TCPCHK_RULES_HTTP_CHK) {
+       if ((px->tcpcheck.rs->flags & TCPCHK_RULES_PROTO_CHK) == TCPCHK_RULES_HTTP_CHK) {
                struct tcpcheck_rule *next;
 
                /* move remaining implicit send rule from "option httpchk" line to the right place.
                 * If such rule exists, it must be the first one. In this case, the rule is moved
                 * after the first connect rule, if any. Otherwise, nothing is done.
                 */
-               chk = get_first_tcpcheck_rule(&px->tcpcheck_rules);
+               chk = get_first_tcpcheck_rule(px->tcpcheck.rs);
                if (chk && chk->action == TCPCHK_ACT_SEND && (chk->send.http.flags & TCPCHK_SND_HTTP_FROM_OPT)) {
-                       next = get_next_tcpcheck_rule(&px->tcpcheck_rules, chk);
+                       next = get_next_tcpcheck_rule(px->tcpcheck.rs, chk);
                        if (next && next->action == TCPCHK_ACT_CONNECT) {
                                LIST_DELETE(&chk->list);
                                LIST_INSERT(&next->list, &chk->list);
@@ -4029,10 +4029,10 @@ static int check_proxy_tcpcheck(struct proxy *px)
                 * versions where the http expect rule was optional. Now it is possible to chained
                 * send/expect rules but the last expect may still be implicit.
                 */
-               chk = get_last_tcpcheck_rule(&px->tcpcheck_rules);
+               chk = get_last_tcpcheck_rule(px->tcpcheck.rs);
                if (chk && chk->action == TCPCHK_ACT_SEND) {
                        next = parse_tcpcheck_expect((char *[]){"http-check", "expect", "status", "200-399", ""},
-                                                    1, px, px->tcpcheck_rules.list, TCPCHK_RULES_HTTP_CHK,
+                                                    1, px, &px->tcpcheck.rs->rules, TCPCHK_RULES_HTTP_CHK,
                                                     px->conf.file, px->conf.line, &errmsg);
                        if (!next) {
                                ha_alert("proxy '%s': unable to add implicit http-check expect rule "
@@ -4041,7 +4041,7 @@ static int check_proxy_tcpcheck(struct proxy *px)
                                ret |= ERR_ALERT | ERR_FATAL;
                                goto out;
                        }
-                       LIST_APPEND(px->tcpcheck_rules.list, &next->list);
+                       LIST_APPEND(&px->tcpcheck.rs->rules, &next->list);
                        next->index = chk->index + 1;
                }
        }
@@ -4051,7 +4051,7 @@ static int check_proxy_tcpcheck(struct proxy *px)
        /* If there is no connect rule preceding all send / expect rules, an
         * implicit one is inserted before all others.
         */
-       chk = get_first_tcpcheck_rule(&px->tcpcheck_rules);
+       chk = get_first_tcpcheck_rule(px->tcpcheck.rs);
        if (!chk || chk->action != TCPCHK_ACT_CONNECT) {
                chk = calloc(1, sizeof(*chk));
                if (!chk) {
@@ -4062,17 +4062,17 @@ static int check_proxy_tcpcheck(struct proxy *px)
                }
                chk->action = TCPCHK_ACT_CONNECT;
                chk->connect.options = (TCPCHK_OPT_DEFAULT_CONNECT|TCPCHK_OPT_IMPLICIT);
-               LIST_INSERT(px->tcpcheck_rules.list, &chk->list);
+               LIST_INSERT(&px->tcpcheck.rs->rules, &chk->list);
        }
 
        /* Now, back again on HTTP ruleset. Try to resolve the sni log-format
         * string if necessary, but onlu for implicit connect rules, by getting
         * it from the following send rule.
         */
-       if ((px->tcpcheck_rules.flags & TCPCHK_RULES_PROTO_CHK) == TCPCHK_RULES_HTTP_CHK) {
+       if ((px->tcpcheck.rs->flags & TCPCHK_RULES_PROTO_CHK) == TCPCHK_RULES_HTTP_CHK) {
                struct tcpcheck_connect *connect = NULL;
 
-               list_for_each_entry(chk, px->tcpcheck_rules.list, list) {
+               list_for_each_entry(chk, &px->tcpcheck.rs->rules, list) {
                        if (chk->action == TCPCHK_ACT_CONNECT && !chk->connect.sni &&
                            (chk->connect.options & TCPCHK_OPT_IMPLICIT)) {
                                /* Only eval connect rule with no explici SNI */
@@ -4091,12 +4091,12 @@ static int check_proxy_tcpcheck(struct proxy *px)
        }
 
        /* Allow small buffer use by default. All send rules must be compatible */
-       px->tcpcheck_rules.flags |= (global.tune.bufsize_small ? TCPCHK_RULES_MAY_USE_SBUF : 0);
+       px->tcpcheck.rs->flags |= (global.tune.bufsize_small ? TCPCHK_RULES_MAY_USE_SBUF : 0);
 
        /* Remove all comment rules. To do so, when a such rule is found, the
         * comment is assigned to the following rule(s).
         */
-       list_for_each_entry_safe(chk, back, px->tcpcheck_rules.list, list) {
+       list_for_each_entry_safe(chk, back, &px->tcpcheck.rs->rules, list) {
                struct tcpcheck_rule *next;
 
                if (chk->action != prev_action && prev_action != TCPCHK_ACT_COMMENT)
@@ -4113,7 +4113,7 @@ static int check_proxy_tcpcheck(struct proxy *px)
                case TCPCHK_ACT_CONNECT:
                        if (!chk->comment && comment)
                                chk->comment = strdup(comment);
-                       next = get_next_tcpcheck_rule(&px->tcpcheck_rules, chk);
+                       next = get_next_tcpcheck_rule(px->tcpcheck.rs, chk);
                        if (next && next->action == TCPCHK_ACT_SEND)
                                chk->connect.options |= TCPCHK_OPT_HAS_DATA;
                        __fallthrough;
@@ -4126,16 +4126,16 @@ static int check_proxy_tcpcheck(struct proxy *px)
                        case TCPCHK_SEND_STRING:
                        case TCPCHK_SEND_BINARY:
                                if (istlen(chk->send.data) >= global.tune.bufsize_small)
-                                       px->tcpcheck_rules.flags &= ~TCPCHK_RULES_MAY_USE_SBUF;
+                                       px->tcpcheck.rs->flags &= ~TCPCHK_RULES_MAY_USE_SBUF;
                                break;
                        case TCPCHK_SEND_STRING_LF:
                        case TCPCHK_SEND_BINARY_LF:
-                               px->tcpcheck_rules.flags &= ~TCPCHK_RULES_MAY_USE_SBUF;
+                               px->tcpcheck.rs->flags &= ~TCPCHK_RULES_MAY_USE_SBUF;
                                break;
                        case TCPCHK_SEND_HTTP:
                                if ((chk->send.http.flags & TCPCHK_SND_HTTP_FL_BODY_FMT) ||
                                    (istlen(chk->send.http.body) >= global.tune.bufsize_small))
-                                       px->tcpcheck_rules.flags &= ~TCPCHK_RULES_MAY_USE_SBUF;
+                                       px->tcpcheck.rs->flags &= ~TCPCHK_RULES_MAY_USE_SBUF;
                        default:
                                break;
                        }
@@ -4154,9 +4154,9 @@ static int check_proxy_tcpcheck(struct proxy *px)
 
 void deinit_proxy_tcpcheck(struct proxy *px)
 {
-       free_tcpcheck_vars(&px->tcpcheck_rules.preset_vars);
-       px->tcpcheck_rules.flags = 0;
-       px->tcpcheck_rules.list  = NULL;
+       free_tcpcheck_vars(&px->tcpcheck.preset_vars);
+       px->tcpcheck.flags = 0;
+       px->tcpcheck.rs = NULL;
 }
 
 static void deinit_tcpchecks()
@@ -4180,7 +4180,7 @@ static void deinit_tcpchecks()
        }
 }
 
-int add_tcpcheck_expect_str(struct tcpcheck_rules *rules, const char *str)
+int add_tcpcheck_expect_str(struct tcpcheck_ruleset *rs, const char *str)
 {
        struct tcpcheck_rule *tcpcheck, *prev_check;
        struct tcpcheck_expect *expect;
@@ -4206,7 +4206,7 @@ int add_tcpcheck_expect_str(struct tcpcheck_rules *rules, const char *str)
         * in a chain of one or more expect rule, potentially itself.
         */
        tcpcheck->expect.head = tcpcheck;
-       list_for_each_entry_rev(prev_check, rules->list, list) {
+       list_for_each_entry_rev(prev_check, &rs->rules, list) {
                if (prev_check->action == TCPCHK_ACT_EXPECT) {
                        if (prev_check->expect.flags & TCPCHK_EXPT_FL_INV)
                                tcpcheck->expect.head = prev_check;
@@ -4215,11 +4215,11 @@ int add_tcpcheck_expect_str(struct tcpcheck_rules *rules, const char *str)
                if (prev_check->action != TCPCHK_ACT_COMMENT && prev_check->action != TCPCHK_ACT_ACTION_KW)
                        break;
        }
-       LIST_APPEND(rules->list, &tcpcheck->list);
+       LIST_APPEND(&rs->rules, &tcpcheck->list);
        return 1;
 }
 
-int add_tcpcheck_send_strs(struct tcpcheck_rules *rules, const char * const *strs)
+int add_tcpcheck_send_strs(struct tcpcheck_ruleset *rs, const char * const *strs)
 {
        struct tcpcheck_rule *tcpcheck;
        struct tcpcheck_send *send;
@@ -4248,7 +4248,7 @@ int add_tcpcheck_send_strs(struct tcpcheck_rules *rules, const char * const *str
                for (in = strs[i]; (*dst = *in++); dst++);
        *dst = 0;
 
-       LIST_APPEND(rules->list, &tcpcheck->list);
+       LIST_APPEND(&rs->rules, &tcpcheck->list);
        return 1;
 }
 
@@ -4276,6 +4276,7 @@ int proxy_parse_tcpcheck(char **args, int section, struct proxy *curpx,
                        memprintf(errmsg, "out of memory.\n");
                        goto error;
                }
+               rs->flags |= TCPCHK_RULES_TCP_CHK;
        }
 
        index = 0;
@@ -4319,14 +4320,14 @@ int proxy_parse_tcpcheck(char **args, int section, struct proxy *curpx,
        LIST_APPEND(&rs->rules, &chk->list);
 
        if ((curpx->options2 & PR_O2_CHK_ANY) == PR_O2_TCPCHK_CHK &&
-           (curpx->tcpcheck_rules.flags & TCPCHK_RULES_PROTO_CHK) == TCPCHK_RULES_TCP_CHK) {
+           (curpx->tcpcheck.rs->flags & TCPCHK_RULES_PROTO_CHK) == TCPCHK_RULES_TCP_CHK) {
                /* Use this ruleset if the proxy already has tcp-check enabled */
-               curpx->tcpcheck_rules.list = &rs->rules;
-               curpx->tcpcheck_rules.flags &= ~TCPCHK_RULES_UNUSED_TCP_RS;
+               curpx->tcpcheck.rs = rs;
+               curpx->tcpcheck.flags &= ~TCPCHK_FL_UNUSED_TCP_RS;
        }
        else {
                /* mark this ruleset as unused for now */
-               curpx->tcpcheck_rules.flags |= TCPCHK_RULES_UNUSED_TCP_RS;
+               curpx->tcpcheck.flags |= TCPCHK_FL_UNUSED_TCP_RS;
        }
 
        return ret;
@@ -4377,6 +4378,7 @@ static int proxy_parse_httpcheck(char **args, int section, struct proxy *curpx,
                        memprintf(errmsg, "out of memory.\n");
                        goto error;
                }
+               rs->flags |= TCPCHK_RULES_HTTP_CHK;
        }
 
        index = 0;
@@ -4417,19 +4419,19 @@ static int proxy_parse_httpcheck(char **args, int section, struct proxy *curpx,
 
        chk->index = index;
        if ((curpx->options2 & PR_O2_CHK_ANY) == PR_O2_TCPCHK_CHK &&
-           (curpx->tcpcheck_rules.flags & TCPCHK_RULES_PROTO_CHK) == TCPCHK_RULES_HTTP_CHK) {
+           (curpx->tcpcheck.rs->flags & TCPCHK_RULES_PROTO_CHK) == TCPCHK_RULES_HTTP_CHK) {
                /* Use this ruleset if the proxy already has http-check enabled */
-               curpx->tcpcheck_rules.list = &rs->rules;
-               curpx->tcpcheck_rules.flags &= ~TCPCHK_RULES_UNUSED_HTTP_RS;
-               if (!tcpcheck_add_http_rule(chk, &curpx->tcpcheck_rules, errmsg)) {
+               curpx->tcpcheck.rs = rs;
+               curpx->tcpcheck.flags &= ~TCPCHK_FL_UNUSED_HTTP_RS;
+               if (!tcpcheck_add_http_rule(chk, curpx->tcpcheck.rs, errmsg)) {
                        memprintf(errmsg, "'%s %s' : %s.", args[0], args[1], *errmsg);
-                       curpx->tcpcheck_rules.list = NULL;
+                       curpx->tcpcheck.rs = NULL;
                        goto error;
                }
        }
        else {
                /* mark this ruleset as unused for now */
-               curpx->tcpcheck_rules.flags |= TCPCHK_RULES_UNUSED_HTTP_RS;
+               curpx->tcpcheck.flags |= TCPCHK_FL_UNUSED_HTTP_RS;
                LIST_APPEND(&rs->rules, &chk->list);
        }
 
@@ -4450,7 +4452,7 @@ int proxy_parse_redis_check_opt(char **args, int cur_arg, struct proxy *curpx, c
        static char *redis_res = "+PONG\r\n";
 
        struct tcpcheck_ruleset *rs = NULL;
-       struct tcpcheck_rules *rules = &curpx->tcpcheck_rules;
+       struct tcpcheck *tc = &curpx->tcpcheck;
        struct tcpcheck_rule *chk;
        char *errmsg = NULL;
        int err_code = 0;
@@ -4464,9 +4466,8 @@ int proxy_parse_redis_check_opt(char **args, int cur_arg, struct proxy *curpx, c
        curpx->options2 &= ~PR_O2_CHK_ANY;
        curpx->options2 |= PR_O2_TCPCHK_CHK;
 
-       free_tcpcheck_vars(&rules->preset_vars);
-       rules->list  = NULL;
-       rules->flags = 0;
+       free_tcpcheck_vars(&tc->preset_vars);
+       tc->rs = NULL;
 
        rs = find_tcpcheck_ruleset("*redis-check");
        if (rs)
@@ -4477,6 +4478,7 @@ int proxy_parse_redis_check_opt(char **args, int cur_arg, struct proxy *curpx, c
                ha_alert("parsing [%s:%d] : out of memory.\n", file, line);
                goto error;
        }
+       rs->flags |= TCPCHK_RULES_REDIS_CHK;
 
        chk = parse_tcpcheck_send((char *[]){"tcp-check", "send", redis_req, ""},
                                  1, curpx, &rs->rules, file, line, &errmsg);
@@ -4501,9 +4503,7 @@ int proxy_parse_redis_check_opt(char **args, int cur_arg, struct proxy *curpx, c
        LIST_APPEND(&rs->rules, &chk->list);
 
   ruleset_found:
-       rules->list = &rs->rules;
-       rules->flags &= ~(TCPCHK_RULES_PROTO_CHK|TCPCHK_RULES_UNUSED_RS);
-       rules->flags |= TCPCHK_RULES_REDIS_CHK;
+       tc->rs = rs;
 
   out:
        free(errmsg);
@@ -4551,7 +4551,7 @@ int proxy_parse_ssl_hello_chk_opt(char **args, int cur_arg, struct proxy *curpx,
        };
 
        struct tcpcheck_ruleset *rs = NULL;
-       struct tcpcheck_rules *rules = &curpx->tcpcheck_rules;
+       struct tcpcheck *tc = &curpx->tcpcheck;
        struct tcpcheck_rule *chk;
        char *errmsg = NULL;
        int err_code = 0;
@@ -4565,9 +4565,8 @@ int proxy_parse_ssl_hello_chk_opt(char **args, int cur_arg, struct proxy *curpx,
        curpx->options2 &= ~PR_O2_CHK_ANY;
        curpx->options2 |= PR_O2_TCPCHK_CHK;
 
-       free_tcpcheck_vars(&rules->preset_vars);
-       rules->list  = NULL;
-       rules->flags = 0;
+       free_tcpcheck_vars(&tc->preset_vars);
+       tc->rs = NULL;
 
        rs = find_tcpcheck_ruleset("*ssl-hello-check");
        if (rs)
@@ -4578,6 +4577,7 @@ int proxy_parse_ssl_hello_chk_opt(char **args, int cur_arg, struct proxy *curpx,
                ha_alert("parsing [%s:%d] : out of memory.\n", file, line);
                goto error;
        }
+       rs->flags |= TCPCHK_RULES_SSL3_CHK;
 
        chk = parse_tcpcheck_send((char *[]){"tcp-check", "send-binary-lf", sslv3_client_hello, ""},
                                  1, curpx, &rs->rules, file, line, &errmsg);
@@ -4601,9 +4601,7 @@ int proxy_parse_ssl_hello_chk_opt(char **args, int cur_arg, struct proxy *curpx,
        LIST_APPEND(&rs->rules, &chk->list);
 
   ruleset_found:
-       rules->list = &rs->rules;
-       rules->flags &= ~(TCPCHK_RULES_PROTO_CHK|TCPCHK_RULES_UNUSED_RS);
-       rules->flags |= TCPCHK_RULES_SSL3_CHK;
+       tc->rs = rs;
 
   out:
        free(errmsg);
@@ -4622,7 +4620,7 @@ int proxy_parse_smtpchk_opt(char **args, int cur_arg, struct proxy *curpx, const
        static char *smtp_req = "%[var(check.smtp_cmd)]\r\n";
 
        struct tcpcheck_ruleset *rs = NULL;
-       struct tcpcheck_rules *rules = &curpx->tcpcheck_rules;
+       struct tcpcheck *tc = &curpx->tcpcheck;
        struct tcpcheck_rule *chk;
        struct tcpcheck_var *var = NULL;
        char *cmd = NULL, *errmsg = NULL;
@@ -4637,9 +4635,8 @@ int proxy_parse_smtpchk_opt(char **args, int cur_arg, struct proxy *curpx, const
        curpx->options2 &= ~PR_O2_CHK_ANY;
        curpx->options2 |= PR_O2_TCPCHK_CHK;
 
-       free_tcpcheck_vars(&rules->preset_vars);
-       rules->list  = NULL;
-       rules->flags = 0;
+       free_tcpcheck_vars(&tc->preset_vars);
+       tc->rs  = NULL;
 
        cur_arg += 2;
        if (*args[cur_arg] && *args[cur_arg+1] &&
@@ -4665,7 +4662,7 @@ int proxy_parse_smtpchk_opt(char **args, int cur_arg, struct proxy *curpx, const
        var->data.u.str.area = cmd;
        var->data.u.str.data = strlen(cmd);
        LIST_INIT(&var->list);
-       LIST_APPEND(&rules->preset_vars, &var->list);
+       LIST_APPEND(&tc->preset_vars, &var->list);
        cmd = NULL;
        var = NULL;
 
@@ -4678,6 +4675,7 @@ int proxy_parse_smtpchk_opt(char **args, int cur_arg, struct proxy *curpx, const
                ha_alert("parsing [%s:%d] : out of memory.\n", file, line);
                goto error;
        }
+       rs->flags |= TCPCHK_RULES_SMTP_CHK;
 
        chk = parse_tcpcheck_connect((char *[]){"tcp-check", "connect", "default", "linger", ""},
                                     1, curpx, &rs->rules, file, line, &errmsg);
@@ -4765,9 +4763,7 @@ int proxy_parse_smtpchk_opt(char **args, int cur_arg, struct proxy *curpx, const
         LIST_APPEND(&rs->rules, &chk->list);
 
   ruleset_found:
-       rules->list = &rs->rules;
-       rules->flags &= ~(TCPCHK_RULES_PROTO_CHK|TCPCHK_RULES_UNUSED_RS);
-       rules->flags |= TCPCHK_RULES_SMTP_CHK;
+       tc->rs = rs;
 
   out:
        free(errmsg);
@@ -4776,7 +4772,7 @@ int proxy_parse_smtpchk_opt(char **args, int cur_arg, struct proxy *curpx, const
   error:
        free(cmd);
        free(var);
-       free_tcpcheck_vars(&rules->preset_vars);
+       free_tcpcheck_vars(&tc->preset_vars);
        free_tcpcheck_ruleset(rs);
        err_code |= ERR_ALERT | ERR_FATAL;
        goto out;
@@ -4795,7 +4791,7 @@ int proxy_parse_pgsql_check_opt(char **args, int cur_arg, struct proxy *curpx, c
        };
 
        struct tcpcheck_ruleset *rs = NULL;
-       struct tcpcheck_rules *rules = &curpx->tcpcheck_rules;
+       struct tcpcheck *tc = &curpx->tcpcheck;
        struct tcpcheck_rule *chk;
        struct tcpcheck_var *var = NULL;
        char *user = NULL, *errmsg = NULL;
@@ -4811,9 +4807,8 @@ int proxy_parse_pgsql_check_opt(char **args, int cur_arg, struct proxy *curpx, c
        curpx->options2 &= ~PR_O2_CHK_ANY;
        curpx->options2 |= PR_O2_TCPCHK_CHK;
 
-       free_tcpcheck_vars(&rules->preset_vars);
-       rules->list  = NULL;
-       rules->flags = 0;
+       free_tcpcheck_vars(&tc->preset_vars);
+       tc->rs  = NULL;
 
        cur_arg += 2;
        if (!*args[cur_arg] || !*args[cur_arg+1]) {
@@ -4834,7 +4829,7 @@ int proxy_parse_pgsql_check_opt(char **args, int cur_arg, struct proxy *curpx, c
                var->data.u.str.area = user;
                var->data.u.str.data = strlen(user);
                LIST_INIT(&var->list);
-               LIST_APPEND(&rules->preset_vars, &var->list);
+               LIST_APPEND(&tc->preset_vars, &var->list);
                user = NULL;
                var = NULL;
 
@@ -4846,7 +4841,7 @@ int proxy_parse_pgsql_check_opt(char **args, int cur_arg, struct proxy *curpx, c
                var->data.type = SMP_T_SINT;
                var->data.u.sint = packetlen;
                LIST_INIT(&var->list);
-               LIST_APPEND(&rules->preset_vars, &var->list);
+               LIST_APPEND(&tc->preset_vars, &var->list);
                var = NULL;
        }
        else {
@@ -4864,6 +4859,7 @@ int proxy_parse_pgsql_check_opt(char **args, int cur_arg, struct proxy *curpx, c
                ha_alert("parsing [%s:%d] : out of memory.\n", file, line);
                goto error;
        }
+       rs->flags |= TCPCHK_RULES_PGSQL_CHK;
 
        chk = parse_tcpcheck_connect((char *[]){"tcp-check", "connect", "default", "linger", ""},
                                     1, curpx, &rs->rules, file, line, &errmsg);
@@ -4911,9 +4907,7 @@ int proxy_parse_pgsql_check_opt(char **args, int cur_arg, struct proxy *curpx, c
        LIST_APPEND(&rs->rules, &chk->list);
 
   ruleset_found:
-       rules->list = &rs->rules;
-       rules->flags &= ~(TCPCHK_RULES_PROTO_CHK|TCPCHK_RULES_UNUSED_RS);
-       rules->flags |= TCPCHK_RULES_PGSQL_CHK;
+       tc->rs = rs;
 
   out:
        free(errmsg);
@@ -4922,7 +4916,7 @@ int proxy_parse_pgsql_check_opt(char **args, int cur_arg, struct proxy *curpx, c
   error:
        free(user);
        free(var);
-       free_tcpcheck_vars(&rules->preset_vars);
+       free_tcpcheck_vars(&tc->preset_vars);
        free_tcpcheck_ruleset(rs);
        err_code |= ERR_ALERT | ERR_FATAL;
        goto out;
@@ -5018,7 +5012,7 @@ int proxy_parse_mysql_check_opt(char **args, int cur_arg, struct proxy *curpx, c
        };
 
        struct tcpcheck_ruleset *rs = NULL;
-       struct tcpcheck_rules *rules = &curpx->tcpcheck_rules;
+       struct tcpcheck *tc = &curpx->tcpcheck;
        struct tcpcheck_rule *chk;
        struct tcpcheck_var *var = NULL;
        char *mysql_rsname = "*mysql-check";
@@ -5034,9 +5028,8 @@ int proxy_parse_mysql_check_opt(char **args, int cur_arg, struct proxy *curpx, c
        curpx->options2 &= ~PR_O2_CHK_ANY;
        curpx->options2 |= PR_O2_TCPCHK_CHK;
 
-       free_tcpcheck_vars(&rules->preset_vars);
-       rules->list  = NULL;
-       rules->flags = 0;
+       free_tcpcheck_vars(&tc->preset_vars);
+       tc->rs  = NULL;
 
        cur_arg += 2;
        if (*args[cur_arg]) {
@@ -5099,7 +5092,7 @@ int proxy_parse_mysql_check_opt(char **args, int cur_arg, struct proxy *curpx, c
                var->data.u.str.area = hdr;
                var->data.u.str.data = 4;
                LIST_INIT(&var->list);
-               LIST_APPEND(&rules->preset_vars, &var->list);
+               LIST_APPEND(&tc->preset_vars, &var->list);
                hdr = NULL;
                var = NULL;
 
@@ -5112,7 +5105,7 @@ int proxy_parse_mysql_check_opt(char **args, int cur_arg, struct proxy *curpx, c
                var->data.u.str.area = user;
                var->data.u.str.data = strlen(user);
                LIST_INIT(&var->list);
-               LIST_APPEND(&rules->preset_vars, &var->list);
+               LIST_APPEND(&tc->preset_vars, &var->list);
                user = NULL;
                var = NULL;
        }
@@ -5126,6 +5119,7 @@ int proxy_parse_mysql_check_opt(char **args, int cur_arg, struct proxy *curpx, c
                ha_alert("parsing [%s:%d] : out of memory.\n", file, line);
                goto error;
        }
+       rs->flags |= TCPCHK_RULES_MYSQL_CHK;
 
        chk = parse_tcpcheck_connect((char *[]){"tcp-check", "connect", "default", "linger", ""},
                                     1, curpx, &rs->rules, file, line, &errmsg);
@@ -5170,9 +5164,7 @@ int proxy_parse_mysql_check_opt(char **args, int cur_arg, struct proxy *curpx, c
        }
 
   ruleset_found:
-       rules->list = &rs->rules;
-       rules->flags &= ~(TCPCHK_RULES_PROTO_CHK|TCPCHK_RULES_UNUSED_RS);
-       rules->flags |= TCPCHK_RULES_MYSQL_CHK;
+       tc->rs = rs;
 
   out:
        free(errmsg);
@@ -5182,7 +5174,7 @@ int proxy_parse_mysql_check_opt(char **args, int cur_arg, struct proxy *curpx, c
        free(hdr);
        free(user);
        free(var);
-       free_tcpcheck_vars(&rules->preset_vars);
+       free_tcpcheck_vars(&tc->preset_vars);
        free_tcpcheck_ruleset(rs);
        err_code |= ERR_ALERT | ERR_FATAL;
        goto out;
@@ -5194,7 +5186,7 @@ int proxy_parse_ldap_check_opt(char **args, int cur_arg, struct proxy *curpx, co
        static char *ldap_req = "300C020101600702010304008000";
 
        struct tcpcheck_ruleset *rs = NULL;
-       struct tcpcheck_rules *rules = &curpx->tcpcheck_rules;
+       struct tcpcheck *tc = &curpx->tcpcheck;
        struct tcpcheck_rule *chk;
        char *errmsg = NULL;
        int err_code = 0;
@@ -5208,9 +5200,8 @@ int proxy_parse_ldap_check_opt(char **args, int cur_arg, struct proxy *curpx, co
        curpx->options2 &= ~PR_O2_CHK_ANY;
        curpx->options2 |= PR_O2_TCPCHK_CHK;
 
-       free_tcpcheck_vars(&rules->preset_vars);
-       rules->list  = NULL;
-       rules->flags = 0;
+       free_tcpcheck_vars(&tc->preset_vars);
+       tc->rs  = NULL;
 
        rs = find_tcpcheck_ruleset("*ldap-check");
        if (rs)
@@ -5221,6 +5212,7 @@ int proxy_parse_ldap_check_opt(char **args, int cur_arg, struct proxy *curpx, co
                ha_alert("parsing [%s:%d] : out of memory.\n", file, line);
                goto error;
        }
+       rs->flags |= TCPCHK_RULES_LDAP_CHK;
 
        chk = parse_tcpcheck_send((char *[]){"tcp-check", "send-binary", ldap_req, ""},
                                  1, curpx, &rs->rules, file, line, &errmsg);
@@ -5254,9 +5246,7 @@ int proxy_parse_ldap_check_opt(char **args, int cur_arg, struct proxy *curpx, co
        LIST_APPEND(&rs->rules, &chk->list);
 
   ruleset_found:
-       rules->list = &rs->rules;
-       rules->flags &= ~(TCPCHK_RULES_PROTO_CHK|TCPCHK_RULES_UNUSED_RS);
-       rules->flags |= TCPCHK_RULES_LDAP_CHK;
+       tc->rs = rs;
 
   out:
        free(errmsg);
@@ -5279,7 +5269,7 @@ int proxy_parse_spop_check_opt(char **args, int cur_arg, struct proxy *curpx, co
                "62696c697469657308000b6865616c7468636865636b11";
 
        struct tcpcheck_ruleset *rs = NULL;
-       struct tcpcheck_rules *rules = &curpx->tcpcheck_rules;
+       struct tcpcheck *tc = &curpx->tcpcheck;
        struct tcpcheck_rule *chk;
        char *errmsg = NULL;
        int err_code = 0;
@@ -5293,9 +5283,8 @@ int proxy_parse_spop_check_opt(char **args, int cur_arg, struct proxy *curpx, co
        curpx->options2 &= ~PR_O2_CHK_ANY;
        curpx->options2 |= PR_O2_TCPCHK_CHK;
 
-       free_tcpcheck_vars(&rules->preset_vars);
-       rules->list  = NULL;
-       rules->flags = 0;
+       free_tcpcheck_vars(&tc->preset_vars);
+       tc->rs  = NULL;
 
        rs = find_tcpcheck_ruleset("*spop-check");
        if (rs)
@@ -5306,6 +5295,7 @@ int proxy_parse_spop_check_opt(char **args, int cur_arg, struct proxy *curpx, co
                ha_alert("parsing [%s:%d] : out of memory.\n", file, line);
                goto error;
        }
+       rs->flags |= TCPCHK_RULES_SPOP_CHK;
 
        chk = parse_tcpcheck_connect((char *[]){"tcp-check", "connect", "default", "proto", "none", ""},
                                     1, curpx, &rs->rules, file, line, &errmsg);
@@ -5336,9 +5326,7 @@ int proxy_parse_spop_check_opt(char **args, int cur_arg, struct proxy *curpx, co
        LIST_APPEND(&rs->rules, &chk->list);
 
   ruleset_found:
-       rules->list = &rs->rules;
-       rules->flags &= ~(TCPCHK_RULES_PROTO_CHK|TCPCHK_RULES_UNUSED_RS);
-       rules->flags |= TCPCHK_RULES_SPOP_CHK;
+       tc->rs = rs;
 
   out:
        return err_code;
@@ -5445,7 +5433,7 @@ int proxy_parse_httpchk_opt(char **args, int cur_arg, struct proxy *curpx, const
                            const char *file, int line)
 {
        struct tcpcheck_ruleset *rs = NULL;
-       struct tcpcheck_rules *rules = &curpx->tcpcheck_rules;
+       struct tcpcheck *tc = &curpx->tcpcheck;
        struct tcpcheck_rule *chk;
        char *errmsg = NULL;
        int err_code = 0;
@@ -5467,12 +5455,11 @@ int proxy_parse_httpchk_opt(char **args, int cur_arg, struct proxy *curpx, const
                ha_free(&errmsg);
        }
 
-  no_request:
        curpx->options2 &= ~PR_O2_CHK_ANY;
        curpx->options2 |= PR_O2_TCPCHK_CHK;
 
-       free_tcpcheck_vars(&rules->preset_vars);
-       rules->list = NULL;
+       free_tcpcheck_vars(&tc->preset_vars);
+       tc->rs = NULL;
 
        /* Deduce the ruleset name from the proxy info */
        chunk_printf(&trash, "*http-check-%s_%s-%d",
@@ -5486,14 +5473,14 @@ int proxy_parse_httpchk_opt(char **args, int cur_arg, struct proxy *curpx, const
                        ha_alert("parsing [%s:%d] : out of memory.\n", file, line);
                        goto error;
                }
+               rs->flags |= TCPCHK_RULES_HTTP_CHK;
        }
 
-       rules->list = &rs->rules;
-       rules->flags &= ~(TCPCHK_RULES_PROTO_CHK|TCPCHK_RULES_UNUSED_RS);
-       rules->flags |= TCPCHK_RULES_HTTP_CHK;
-       if (!tcpcheck_add_http_rule(chk, rules, &errmsg)) {
+       tc->rs = rs;
+       tc->flags &= ~TCPCHK_FL_UNUSED_HTTP_RS;
+       if (!tcpcheck_add_http_rule(chk, rs, &errmsg)) {
                ha_alert("parsing [%s:%d] : '%s %s' : %s.\n", file, line, args[0], args[1], errmsg);
-               rules->list = NULL;
+               tc->rs = NULL;
                goto error;
        }
 
@@ -5513,7 +5500,7 @@ int proxy_parse_tcp_check_opt(char **args, int cur_arg, struct proxy *curpx, con
                              const char *file, int line)
 {
        struct tcpcheck_ruleset *rs = NULL;
-       struct tcpcheck_rules *rules = &curpx->tcpcheck_rules;
+       struct tcpcheck *tc = &curpx->tcpcheck;
        int err_code = 0;
 
        if (warnifnotcap(curpx, PR_CAP_BE, file, line, args[cur_arg+1], NULL))
@@ -5525,25 +5512,9 @@ int proxy_parse_tcp_check_opt(char **args, int cur_arg, struct proxy *curpx, con
        curpx->options2 &= ~PR_O2_CHK_ANY;
        curpx->options2 |= PR_O2_TCPCHK_CHK;
 
-       if ((rules->flags & TCPCHK_RULES_PROTO_CHK) == TCPCHK_RULES_TCP_CHK) {
-               /* If a tcp-check rulesset is already set, do nothing */
-               if (rules->list)
-                       goto out;
-
-               /* If a tcp-check ruleset is waiting to be used for the current proxy,
-                * get it.
-                */
-               if (rules->flags & TCPCHK_RULES_UNUSED_TCP_RS)
-                       goto curpx_ruleset;
-
-               /* Otherwise, try to get the tcp-check ruleset of the default proxy */
-               chunk_printf(&trash, "*tcp-check-defaults_%s-%d", defpx->conf.file, defpx->conf.line);
-               rs = find_tcpcheck_ruleset(b_orig(&trash));
-               if (rs)
-                       goto ruleset_found;
-       }
+       free_tcpcheck_vars(&tc->preset_vars);
+       tc->rs = NULL;
 
-  curpx_ruleset:
        /* Deduce the ruleset name from the proxy info */
        chunk_printf(&trash, "*tcp-check-%s_%s-%d",
                     ((curpx == defpx) ? "defaults" : curpx->id),
@@ -5556,13 +5527,11 @@ int proxy_parse_tcp_check_opt(char **args, int cur_arg, struct proxy *curpx, con
                        ha_alert("parsing [%s:%d] : out of memory.\n", file, line);
                        goto error;
                }
+               rs->flags |= TCPCHK_RULES_TCP_CHK;
        }
 
-  ruleset_found:
-       free_tcpcheck_vars(&rules->preset_vars);
-       rules->list = &rs->rules;
-       rules->flags &= ~(TCPCHK_RULES_PROTO_CHK|TCPCHK_RULES_UNUSED_RS);
-       rules->flags |= TCPCHK_RULES_TCP_CHK;
+       tc->rs = rs;
+       tc->flags &= ~TCPCHK_FL_UNUSED_TCP_RS;
 
   out:
        return err_code;