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.
This commit is contained in:
Amaury Denoyelle 2026-02-03 11:09:42 +01:00
parent 2a07dc9c24
commit 2c8ad11b73
2 changed files with 25 additions and 35 deletions

View file

@ -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) */

View file

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