MEDIUM: tcpcheck: Refactor how tcp-check rulesets are stored

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.
This commit is contained in:
Christopher Faulet 2026-03-26 08:56:29 +01:00
parent 949aa36820
commit dc7c8bd2f8
10 changed files with 192 additions and 231 deletions

View 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_* */

View 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 */

View 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 */

View 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);

View 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);
}

View 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])) {

View 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);

View 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;

View 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;

View 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;
free_tcpcheck_vars(&tc->preset_vars);
tc->rs = NULL;
/* 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;
}
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;