From 2c8ad11b7302d846f1cb201965cd2e5903858cc9 Mon Sep 17 00:00:00 2001 From: Amaury Denoyelle Date: Tue, 3 Feb 2026 11:09:42 +0100 Subject: [PATCH] MINOR: cfgparse: validate defaults proxies separately Default proxies validation occurs during post-parsing. The objective is to report any tcp/http-rules which could not behave as expected. Previously, this was performed while looping over standard proxies list, when such proxy is referencing a default instance. This was enough as only named referenced proxies were kept after parsing. However, this is not the case anymore in the context of dynamic backends creation at runtime. As such, this patch now performs validation on every named defaults outside of the standard proxies list loop. This should not cause any behavior difference, as defaults are validated without using the proxy which relies on it. Along with this change, PR_FL_READY proxy flag is now removed. Its usage was only really needed for defaults, to avoid validating a same instance multiple times. With the validation of defaults in their own loop, it is now redundant. --- include/haproxy/proxy-t.h | 2 +- src/cfgparse.c | 58 ++++++++++++++++----------------------- 2 files changed, 25 insertions(+), 35 deletions(-) diff --git a/include/haproxy/proxy-t.h b/include/haproxy/proxy-t.h index 02359079f..4f4b6c45d 100644 --- a/include/haproxy/proxy-t.h +++ b/include/haproxy/proxy-t.h @@ -242,7 +242,7 @@ enum PR_SRV_STATE_FILE { /* Proxy flags */ #define PR_FL_DISABLED 0x01 /* The proxy was disabled in the configuration (not at runtime) */ #define PR_FL_STOPPED 0x02 /* The proxy was stopped */ -#define PR_FL_READY 0x04 /* The proxy is ready to be used (initialized and configured) */ +/* 0x04 unused */ #define PR_FL_EXPLICIT_REF 0x08 /* The default proxy is explicitly referenced by another proxy */ #define PR_FL_IMPLICIT_REF 0x10 /* The default proxy is implicitly referenced by another proxy */ #define PR_FL_PAUSED 0x20 /* The proxy was paused at run time (reversible) */ diff --git a/src/cfgparse.c b/src/cfgparse.c index 52a4cb8fe..ea2eb32d9 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -2270,7 +2270,7 @@ err: int check_config_validity() { int cfgerr = 0; - struct proxy *init_proxies_list = NULL; + struct proxy *init_proxies_list = NULL, *defpx; struct stktable *t; struct server *newsrv = NULL; struct mt_list back; @@ -2358,6 +2358,29 @@ int check_config_validity() goto out; } + list_for_each_entry(defpx, &defaults_list, el) { + /* check validity for 'tcp-request' layer 4/5/6/7 rules */ + cfgerr += check_action_rules(&defpx->tcp_req.l4_rules, defpx, &err_code); + cfgerr += check_action_rules(&defpx->tcp_req.l5_rules, defpx, &err_code); + cfgerr += check_action_rules(&defpx->tcp_req.inspect_rules, defpx, &err_code); + cfgerr += check_action_rules(&defpx->tcp_rep.inspect_rules, defpx, &err_code); + cfgerr += check_action_rules(&defpx->http_req_rules, defpx, &err_code); + cfgerr += check_action_rules(&defpx->http_res_rules, defpx, &err_code); + cfgerr += check_action_rules(&defpx->http_after_res_rules, defpx, &err_code); + + err = NULL; + i = smp_resolve_args(defpx, &err); + cfgerr += i; + if (i) { + indent_msg(&err, 8); + ha_alert("%s%s\n", i > 1 ? "multiple argument resolution errors:" : "", err); + ha_free(&err); + } + else { + cfgerr += acl_find_targets(defpx); + } + } + /* starting to initialize the main proxies list */ init_proxies_list = proxies_list; @@ -2403,37 +2426,6 @@ init_proxies_list_stage1: continue; } - /* The current proxy is referencing a default proxy. We must - * finalize its config, but only once. If the default proxy is - * ready (PR_FL_READY) it means it was already fully configured. - */ - if (curproxy->defpx) { - if (!(curproxy->defpx->flags & PR_FL_READY)) { - /* check validity for 'tcp-request' layer 4/5/6/7 rules */ - cfgerr += check_action_rules(&curproxy->defpx->tcp_req.l4_rules, curproxy->defpx, &err_code); - cfgerr += check_action_rules(&curproxy->defpx->tcp_req.l5_rules, curproxy->defpx, &err_code); - cfgerr += check_action_rules(&curproxy->defpx->tcp_req.inspect_rules, curproxy->defpx, &err_code); - cfgerr += check_action_rules(&curproxy->defpx->tcp_rep.inspect_rules, curproxy->defpx, &err_code); - cfgerr += check_action_rules(&curproxy->defpx->http_req_rules, curproxy->defpx, &err_code); - cfgerr += check_action_rules(&curproxy->defpx->http_res_rules, curproxy->defpx, &err_code); - cfgerr += check_action_rules(&curproxy->defpx->http_after_res_rules, curproxy->defpx, &err_code); - - err = NULL; - i = smp_resolve_args(curproxy->defpx, &err); - cfgerr += i; - if (i) { - indent_msg(&err, 8); - ha_alert("%s%s\n", i > 1 ? "multiple argument resolution errors:" : "", err); - ha_free(&err); - } - else - cfgerr += acl_find_targets(curproxy->defpx); - - /* default proxy is now ready. Set the right FE/BE capabilities */ - curproxy->defpx->flags |= PR_FL_READY; - } - } - /* check and reduce the bind-proc of each listener */ list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) { int mode = conn_pr_mode_to_proto_mode(curproxy->mode); @@ -3860,7 +3852,6 @@ init_proxies_list_stage2: if (curproxy->task) { curproxy->task->context = curproxy; curproxy->task->process = manage_proxy; - curproxy->flags |= PR_FL_READY; } else { ha_alert("Proxy '%s': no more memory when trying to allocate the management task\n", @@ -3937,7 +3928,6 @@ init_proxies_list_stage2: * Note that ->srv is used by the local peer of a new process to connect to the local peer * of an old process. */ - curpeers->peers_fe->flags |= PR_FL_READY; p = curpeers->remote; while (p) { struct peer *other_peer; -- 2.47.3