diff --git a/include/types/proxy.h b/include/types/proxy.h index 9666909e5..36eb515cc 100644 --- a/include/types/proxy.h +++ b/include/types/proxy.h @@ -422,7 +422,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 list tcpcheck_rules; /* tcp-check send / expect rules */ + struct list *tcpcheck_rules; /* tcp-check send / expect rules */ int grace; /* grace time after stop request */ int check_len; /* Length of the HTTP or SSL3 request */ char *check_req; /* HTTP or SSL request to use for PR_O_HTTP_CHK|PR_O_SSL3_CHK */ diff --git a/src/cfgparse-listen.c b/src/cfgparse-listen.c index 06ed3e449..e922c09ba 100644 --- a/src/cfgparse-listen.c +++ b/src/cfgparse-listen.c @@ -352,6 +352,16 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) } curproxy->check_body_len = defproxy.check_body_len; + if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_TCPCHK_CHK) { + curproxy->tcpcheck_rules = calloc(1, sizeof(*curproxy->tcpcheck_rules)); + if (!curproxy->tcpcheck_rules) { + ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum); + err_code |= ERR_ALERT | ERR_FATAL; + goto out; + } + LIST_INIT(curproxy->tcpcheck_rules); + } + if (defproxy.expect_str) { curproxy->expect_str = strdup(defproxy.expect_str); if (defproxy.expect_regex) { @@ -2712,6 +2722,16 @@ stats_error_parsing: if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) err_code |= ERR_WARN; + if ((curproxy != &defproxy) && !curproxy->tcpcheck_rules) { + curproxy->tcpcheck_rules = calloc(1, sizeof(*curproxy->tcpcheck_rules)); + if (!curproxy->tcpcheck_rules) { + ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum); + err_code |= ERR_ALERT | ERR_FATAL; + goto out; + } + LIST_INIT(curproxy->tcpcheck_rules); + } + free(curproxy->check_req); curproxy->check_req = NULL; curproxy->options2 &= ~PR_O2_CHK_ANY; @@ -3075,6 +3095,16 @@ stats_error_parsing: goto out; } + if (curproxy->tcpcheck_rules == NULL) { + curproxy->tcpcheck_rules = calloc(1, sizeof(*curproxy->tcpcheck_rules)); + if (curproxy->tcpcheck_rules == NULL) { + ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum); + err_code |= ERR_ALERT | ERR_ABORT; + goto out; + } + LIST_INIT(curproxy->tcpcheck_rules); + } + if (strcmp(args[1], "comment") == 0) { int cur_arg; struct tcpcheck_rule *tcpcheck; @@ -3092,7 +3122,7 @@ stats_error_parsing: tcpcheck->comment = strdup(args[cur_arg + 1]); - LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list); + LIST_ADDQ(curproxy->tcpcheck_rules, &tcpcheck->list); if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code)) goto out; } @@ -3102,13 +3132,13 @@ stats_error_parsing: struct tcpcheck_rule *tcpcheck; /* check if first rule is also a 'connect' action */ - tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list); - while (&tcpcheck->list != &curproxy->tcpcheck_rules && + tcpcheck = LIST_NEXT(curproxy->tcpcheck_rules, struct tcpcheck_rule *, list); + while (&tcpcheck->list != curproxy->tcpcheck_rules && tcpcheck->action == TCPCHK_ACT_COMMENT) { tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list); } - if (&tcpcheck->list != &curproxy->tcpcheck_rules + if (&tcpcheck->list != curproxy->tcpcheck_rules && tcpcheck->action != TCPCHK_ACT_CONNECT) { ha_alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n", file, linenum); @@ -3174,7 +3204,7 @@ stats_error_parsing: } - LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list); + LIST_ADDQ(curproxy->tcpcheck_rules, &tcpcheck->list); } else if (strcmp(args[1], "send") == 0) { if (! *(args[2]) ) { @@ -3203,7 +3233,7 @@ stats_error_parsing: tcpcheck->comment = strdup(args[4]); } - LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list); + LIST_ADDQ(curproxy->tcpcheck_rules, &tcpcheck->list); } } else if (strcmp(args[1], "send-binary") == 0) { @@ -3238,7 +3268,7 @@ stats_error_parsing: tcpcheck->comment = strdup(args[4]); } - LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list); + LIST_ADDQ(curproxy->tcpcheck_rules, &tcpcheck->list); } } else if (strcmp(args[1], "expect") == 0) { @@ -3389,7 +3419,7 @@ stats_error_parsing: * in a chain of one or more expect rule, potentially itself. */ tcpcheck->expect.head = tcpcheck; - list_for_each_entry_rev(prev_check, &curproxy->tcpcheck_rules, list) { + list_for_each_entry_rev(prev_check, curproxy->tcpcheck_rules, list) { if (prev_check->action == TCPCHK_ACT_EXPECT) { if (prev_check->expect.inverse) tcpcheck->expect.head = prev_check; @@ -3398,7 +3428,7 @@ stats_error_parsing: if (prev_check->action != TCPCHK_ACT_COMMENT) break; } - LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list); + LIST_ADDQ(curproxy->tcpcheck_rules, &tcpcheck->list); } else { ha_alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]); diff --git a/src/cfgparse.c b/src/cfgparse.c index d049899b3..139103399 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -3133,7 +3133,7 @@ out_uri_auth_compat: memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len); } - if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) && + if (curproxy->tcpcheck_rules != NULL && (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) { ha_warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n", proxy_type_str(curproxy), curproxy->id); diff --git a/src/checks.c b/src/checks.c index b2fb34d0f..bb1a5041c 100644 --- a/src/checks.c +++ b/src/checks.c @@ -3804,7 +3804,7 @@ static 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 (!LIST_ISEMPTY(&srv->proxy->tcpcheck_rules)) { + if (!srv->proxy->tcpcheck_rules || LIST_ISEMPTY(srv->proxy->tcpcheck_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; @@ -3812,7 +3812,7 @@ static 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->proxy->tcpcheck_rules); if (!r || (r->action != TCPCHK_ACT_CONNECT) || !r->port) { ha_alert("config: %s '%s': server '%s' has neither service port nor check port " "nor tcp_check rule 'connect' with port information.\n", @@ -3822,7 +3822,7 @@ static 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_for_each_entry(r, srv->proxy->tcpcheck_rules, list) { if ((r->action == TCPCHK_ACT_CONNECT) && (!r->port)) { 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", diff --git a/src/proxy.c b/src/proxy.c index 046b1b555..d2d6a43d6 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -876,7 +876,6 @@ void init_new_proxy(struct proxy *p) LIST_INIT(&p->conf.listeners); LIST_INIT(&p->conf.errors); LIST_INIT(&p->conf.args.list); - LIST_INIT(&p->tcpcheck_rules); LIST_INIT(&p->filter_configs); /* Timeouts are defined as -1 */ diff --git a/src/server.c b/src/server.c index 8307ae2ca..e5652f26b 100644 --- a/src/server.c +++ b/src/server.c @@ -1867,7 +1867,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_rules = proxy->tcpcheck_rules; srv->agent.status = HCHK_STATUS_INI; srv->agent.server = srv;