mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-11 17:46:57 +02:00
MINOR: server: Extract the code which finalizes server initializations after 'server' lines parsing.
This patch moves the code which is responsible of finalizing server initializations after having fully parsed a 'server' line (health-check, agent check and SNI expression initializations) from parse_server() to new functions.
This commit is contained in:
parent
58b207cdd5
commit
759ea98db2
341
src/server.c
341
src/server.c
@ -1529,20 +1529,26 @@ const char *server_parse_maxconn_change_request(struct server *sv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
|
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
|
||||||
static int server_parse_sni_expr(struct server *newsrv, struct proxy *px, char **err)
|
static struct sample_expr *srv_sni_sample_parse_expr(struct server *srv, struct proxy *px,
|
||||||
|
const char *file, int linenum, char **err)
|
||||||
{
|
{
|
||||||
int idx;
|
int idx;
|
||||||
struct sample_expr *expr;
|
|
||||||
const char *args[] = {
|
const char *args[] = {
|
||||||
newsrv->sni_expr,
|
srv->sni_expr,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
idx = 0;
|
idx = 0;
|
||||||
px->conf.args.ctx = ARGC_SRV;
|
px->conf.args.ctx = ARGC_SRV;
|
||||||
|
|
||||||
expr = sample_parse_expr((char **)args, &idx, px->conf.file, px->conf.line,
|
return sample_parse_expr((char **)args, &idx, file, linenum, err, &px->conf.args);
|
||||||
err, &px->conf.args);
|
}
|
||||||
|
|
||||||
|
static int server_parse_sni_expr(struct server *newsrv, struct proxy *px, char **err)
|
||||||
|
{
|
||||||
|
struct sample_expr *expr;
|
||||||
|
|
||||||
|
expr = srv_sni_sample_parse_expr(newsrv, px, px->conf.file, px->conf.line, err);
|
||||||
if (!expr) {
|
if (!expr) {
|
||||||
memprintf(err, "error detected while parsing sni expression : %s", *err);
|
memprintf(err, "error detected while parsing sni expression : %s", *err);
|
||||||
return ERR_ALERT | ERR_FATAL;
|
return ERR_ALERT | ERR_FATAL;
|
||||||
@ -1552,7 +1558,7 @@ static int server_parse_sni_expr(struct server *newsrv, struct proxy *px, char *
|
|||||||
memprintf(err, "error detected while parsing sni expression : "
|
memprintf(err, "error detected while parsing sni expression : "
|
||||||
" fetch method '%s' extracts information from '%s', "
|
" fetch method '%s' extracts information from '%s', "
|
||||||
"none of which is available here.\n",
|
"none of which is available here.\n",
|
||||||
args[0], sample_src_names(expr->fetch->use));
|
newsrv->sni_expr, sample_src_names(expr->fetch->use));
|
||||||
return ERR_ALERT | ERR_FATAL;
|
return ERR_ALERT | ERR_FATAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1762,6 +1768,207 @@ static struct server *new_server(struct proxy *proxy)
|
|||||||
return srv;
|
return srv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Validate <srv> server health-check settings.
|
||||||
|
* Returns 0 if everything is OK, -1 if not.
|
||||||
|
*/
|
||||||
|
static int server_healthcheck_validate(const char *file, int linenum, struct server *srv)
|
||||||
|
{
|
||||||
|
struct tcpcheck_rule *r = NULL;
|
||||||
|
struct list *l;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need at least a service port, a check port or the first tcp-check rule must
|
||||||
|
* be a 'connect' one when checking an IPv4/IPv6 server.
|
||||||
|
*/
|
||||||
|
if ((srv_check_healthcheck_port(&srv->check) != 0) ||
|
||||||
|
(!is_inet_addr(&srv->check.addr) && (is_addr(&srv->check.addr) || !is_inet_addr(&srv->addr))))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
r = (struct tcpcheck_rule *)srv->proxy->tcpcheck_rules.n;
|
||||||
|
if (!r) {
|
||||||
|
Alert("parsing [%s:%d] : server %s has neither service port nor check port. "
|
||||||
|
"Check has been disabled.\n",
|
||||||
|
file, linenum, srv->id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* search the first action (connect / send / expect) in the list */
|
||||||
|
l = &srv->proxy->tcpcheck_rules;
|
||||||
|
list_for_each_entry(r, l, list) {
|
||||||
|
if (r->action != TCPCHK_ACT_COMMENT)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((r->action != TCPCHK_ACT_CONNECT) || !r->port) {
|
||||||
|
Alert("parsing [%s:%d] : server %s has neither service port nor check port "
|
||||||
|
"nor tcp_check rule 'connect' with port information. Check has been disabled.\n",
|
||||||
|
file, linenum, srv->id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* scan the tcp-check ruleset to ensure a port has been configured */
|
||||||
|
l = &srv->proxy->tcpcheck_rules;
|
||||||
|
list_for_each_entry(r, l, list) {
|
||||||
|
if ((r->action == TCPCHK_ACT_CONNECT) && (!r->port)) {
|
||||||
|
Alert("parsing [%s:%d] : server %s has neither service port nor check port, "
|
||||||
|
"and a tcp_check rule 'connect' with no port information. Check has been disabled.\n",
|
||||||
|
file, linenum, srv->id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize <srv> health-check structure.
|
||||||
|
* Returns the error string in case of memory allocation failure, NULL if not.
|
||||||
|
*/
|
||||||
|
static const char *do_health_check_init(struct server *srv, int check_type, int state)
|
||||||
|
{
|
||||||
|
const char *ret;
|
||||||
|
|
||||||
|
if (!srv->do_check)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ret = init_check(&srv->check, check_type);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (srv->resolution)
|
||||||
|
srv->resolution->opts = &srv->dns_opts;
|
||||||
|
|
||||||
|
srv->check.state |= state;
|
||||||
|
global.maxsock++;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int server_health_check_init(const char *file, int linenum,
|
||||||
|
struct server *srv, struct proxy *curproxy)
|
||||||
|
{
|
||||||
|
const char *ret;
|
||||||
|
|
||||||
|
if (!srv->do_check)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (srv->trackit) {
|
||||||
|
Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
|
||||||
|
file, linenum);
|
||||||
|
return ERR_ALERT | ERR_FATAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (server_healthcheck_validate(file, linenum, srv) < 0)
|
||||||
|
return ERR_ALERT | ERR_ABORT;
|
||||||
|
|
||||||
|
/* note: check type will be set during the config review phase */
|
||||||
|
ret = do_health_check_init(srv, 0, CHK_ST_CONFIGURED | CHK_ST_ENABLED);
|
||||||
|
if (ret) {
|
||||||
|
Alert("parsing [%s:%d] : %s.\n", file, linenum, ret);
|
||||||
|
return ERR_ALERT | ERR_ABORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize <srv> agent check structure.
|
||||||
|
* Returns the error string in case of memory allocation failure, NULL if not.
|
||||||
|
*/
|
||||||
|
static const char *do_server_agent_check_init(struct server *srv, int state)
|
||||||
|
{
|
||||||
|
const char *ret;
|
||||||
|
|
||||||
|
if (!srv->do_agent)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ret = init_check(&srv->agent, PR_O2_LB_AGENT_CHK);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (!srv->agent.inter)
|
||||||
|
srv->agent.inter = srv->check.inter;
|
||||||
|
|
||||||
|
srv->agent.state |= state;
|
||||||
|
global.maxsock++;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int server_agent_check_init(const char *file, int linenum,
|
||||||
|
struct server *srv, struct proxy *curproxy)
|
||||||
|
{
|
||||||
|
const char *ret;
|
||||||
|
|
||||||
|
if (!srv->do_agent)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!srv->agent.port) {
|
||||||
|
Alert("parsing [%s:%d] : server %s does not have agent port. Agent check has been disabled.\n",
|
||||||
|
file, linenum, srv->id);
|
||||||
|
return ERR_ALERT | ERR_FATAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = do_server_agent_check_init(srv, CHK_ST_CONFIGURED | CHK_ST_ENABLED | CHK_ST_AGENT);
|
||||||
|
if (ret) {
|
||||||
|
Alert("parsing [%s:%d] : %s.\n", file, linenum, ret);
|
||||||
|
return ERR_ALERT | ERR_ABORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
|
||||||
|
static int server_sni_expr_init(const char *file, int linenum, char **args, int cur_arg,
|
||||||
|
struct server *srv, struct proxy *proxy)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
char *err = NULL;
|
||||||
|
|
||||||
|
if (!srv->sni_expr)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ret = server_parse_sni_expr(srv, proxy, &err);
|
||||||
|
if (!ret)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
display_parser_err(file, linenum, args, cur_arg, &err);
|
||||||
|
free(err);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Server initializations finalization.
|
||||||
|
* Initialize health check, agent check and SNI expression if enabled.
|
||||||
|
* Must not be called for a default server instance.
|
||||||
|
*/
|
||||||
|
static int server_finalize_init(const char *file, int linenum, char **args, int cur_arg,
|
||||||
|
struct server *srv, struct proxy *px)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if ((ret = server_health_check_init(file, linenum, srv, px)) != 0 ||
|
||||||
|
(ret = server_agent_check_init(file, linenum, srv, px)) != 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
|
||||||
|
if ((ret = server_sni_expr_init(file, linenum, args, cur_arg, srv, px)) != 0)
|
||||||
|
return ret;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (srv->flags & SRV_F_BACKUP)
|
||||||
|
px->srv_bck++;
|
||||||
|
else
|
||||||
|
px->srv_act++;
|
||||||
|
srv_lb_commit_status(srv);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int parse_server(const char *file, int linenum, char **args, struct proxy *curproxy, struct proxy *defproxy)
|
int parse_server(const char *file, int linenum, char **args, struct proxy *curproxy, struct proxy *defproxy)
|
||||||
{
|
{
|
||||||
struct server *newsrv = NULL;
|
struct server *newsrv = NULL;
|
||||||
@ -2323,124 +2530,10 @@ int parse_server(const char *file, int linenum, char **args, struct proxy *curpr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This check is done only for 'server' instances. */
|
if (!defsrv)
|
||||||
if (!defsrv && newsrv->do_check) {
|
err_code |= server_finalize_init(file, linenum, args, cur_arg, newsrv, curproxy);
|
||||||
const char *ret;
|
if (err_code & ERR_FATAL)
|
||||||
|
goto out;
|
||||||
if (newsrv->trackit) {
|
|
||||||
Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
|
|
||||||
file, linenum);
|
|
||||||
err_code |= ERR_ALERT | ERR_FATAL;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We need at least a service port, a check port or the first tcp-check rule must
|
|
||||||
* be a 'connect' one when checking an IPv4/IPv6 server.
|
|
||||||
*/
|
|
||||||
if ((srv_check_healthcheck_port(&newsrv->check) == 0) &&
|
|
||||||
(is_inet_addr(&newsrv->check.addr) ||
|
|
||||||
(!is_addr(&newsrv->check.addr) && is_inet_addr(&newsrv->addr)))) {
|
|
||||||
struct tcpcheck_rule *r = NULL;
|
|
||||||
struct list *l;
|
|
||||||
|
|
||||||
r = (struct tcpcheck_rule *)newsrv->proxy->tcpcheck_rules.n;
|
|
||||||
if (!r) {
|
|
||||||
Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
|
|
||||||
file, linenum, newsrv->id);
|
|
||||||
err_code |= ERR_ALERT | ERR_FATAL;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
/* search the first action (connect / send / expect) in the list */
|
|
||||||
l = &newsrv->proxy->tcpcheck_rules;
|
|
||||||
list_for_each_entry(r, l, list) {
|
|
||||||
if (r->action != TCPCHK_ACT_COMMENT)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ((r->action != TCPCHK_ACT_CONNECT) || !r->port) {
|
|
||||||
Alert("parsing [%s:%d] : server %s has neither service port nor check port nor tcp_check rule 'connect' with port information. Check has been disabled.\n",
|
|
||||||
file, linenum, newsrv->id);
|
|
||||||
err_code |= ERR_ALERT | ERR_FATAL;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* scan the tcp-check ruleset to ensure a port has been configured */
|
|
||||||
l = &newsrv->proxy->tcpcheck_rules;
|
|
||||||
list_for_each_entry(r, l, list) {
|
|
||||||
if ((r->action == TCPCHK_ACT_CONNECT) && (!r->port)) {
|
|
||||||
Alert("parsing [%s:%d] : server %s has neither service port nor check port, and a tcp_check rule 'connect' with no port information. Check has been disabled.\n",
|
|
||||||
file, linenum, newsrv->id);
|
|
||||||
err_code |= ERR_ALERT | ERR_FATAL;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* note: check type will be set during the config review phase */
|
|
||||||
ret = init_check(&newsrv->check, 0);
|
|
||||||
if (ret) {
|
|
||||||
Alert("parsing [%s:%d] : %s.\n", file, linenum, ret);
|
|
||||||
err_code |= ERR_ALERT | ERR_ABORT;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newsrv->resolution)
|
|
||||||
newsrv->resolution->opts = &newsrv->dns_opts;
|
|
||||||
|
|
||||||
newsrv->check.state |= CHK_ST_CONFIGURED | CHK_ST_ENABLED;
|
|
||||||
global.maxsock++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!defsrv && newsrv->do_agent) {
|
|
||||||
const char *ret;
|
|
||||||
|
|
||||||
if (!newsrv->agent.port) {
|
|
||||||
Alert("parsing [%s:%d] : server %s does not have agent port. Agent check has been disabled.\n",
|
|
||||||
file, linenum, newsrv->id);
|
|
||||||
err_code |= ERR_ALERT | ERR_FATAL;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!newsrv->agent.inter)
|
|
||||||
newsrv->agent.inter = newsrv->check.inter;
|
|
||||||
|
|
||||||
ret = init_check(&newsrv->agent, PR_O2_LB_AGENT_CHK);
|
|
||||||
if (ret) {
|
|
||||||
Alert("parsing [%s:%d] : %s.\n", file, linenum, ret);
|
|
||||||
err_code |= ERR_ALERT | ERR_ABORT;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
newsrv->agent.state |= CHK_ST_CONFIGURED | CHK_ST_ENABLED | CHK_ST_AGENT;
|
|
||||||
global.maxsock++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!defsrv) {
|
|
||||||
if (newsrv->flags & SRV_F_BACKUP)
|
|
||||||
curproxy->srv_bck++;
|
|
||||||
else
|
|
||||||
curproxy->srv_act++;
|
|
||||||
|
|
||||||
srv_lb_commit_status(newsrv);
|
|
||||||
}
|
|
||||||
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
|
|
||||||
if (!defsrv && newsrv->sni_expr) {
|
|
||||||
int code;
|
|
||||||
char *err;
|
|
||||||
|
|
||||||
err = NULL;
|
|
||||||
|
|
||||||
code = server_parse_sni_expr(newsrv, curproxy, &err);
|
|
||||||
err_code |= code;
|
|
||||||
if (code) {
|
|
||||||
display_parser_err(file, linenum, args, cur_arg, &err);
|
|
||||||
free(err);
|
|
||||||
if (code & ERR_FATAL)
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
free(fqdn);
|
free(fqdn);
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user