diff --git a/src/cfgparse-listen.c b/src/cfgparse-listen.c index d079ecf40..9dbf7ed98 100644 --- a/src/cfgparse-listen.c +++ b/src/cfgparse-listen.c @@ -333,6 +333,70 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) goto out; } + if (curr_defproxy && (!LIST_ISEMPTY(&curr_defproxy->http_req_rules) || + !LIST_ISEMPTY(&curr_defproxy->http_res_rules) || + !LIST_ISEMPTY(&curr_defproxy->http_after_res_rules) || + !LIST_ISEMPTY(&curr_defproxy->tcp_req.l4_rules) || + !LIST_ISEMPTY(&curr_defproxy->tcp_req.l5_rules) || + !LIST_ISEMPTY(&curr_defproxy->tcp_req.inspect_rules) || + !LIST_ISEMPTY(&curr_defproxy->tcp_rep.inspect_rules))) { + /* If the current default proxy defines TCP/HTTP rules, the + * current proxy will keep a reference on it. But some sanity + * checks are performed first: + * + * - It cannot be used to init a defaults section + * - It cannot be used to init a listen section + * - It cannot be used to init backend and frontend sections at + * same time. It can be used to init several sections of the + * same type only. + * - It cannot define L4/L5 TCP rules if it is used to init + * backend sections. + * - It cannot define 'tcp-response content' rules if it + * is used to init frontend sections. + * + * If no error is found, refcount of the default proxy is incremented. + */ + + /* Note: Add tcpcheck_rules too if unresolve args become allowed in defaults section */ + if (rc & PR_CAP_DEF) { + ha_alert("parsing [%s:%d]: a defaults section cannot inherit from a defaults section defining TCP/HTTP rules (defaults section at %s:%d).\n", + file, linenum, curr_defproxy->conf.file, curr_defproxy->conf.line); + err_code |= ERR_ALERT | ERR_ABORT; + } + else if ((rc & PR_CAP_LISTEN) == PR_CAP_LISTEN) { + ha_alert("parsing [%s:%d]: a listen section cannot inherit from a defaults section defining TCP/HTTP rules.\n", + file, linenum); + err_code |= ERR_ALERT | ERR_ABORT; + } + else { + char defcap = (curr_defproxy->cap & PR_CAP_LISTEN); + + if ((defcap == PR_CAP_BE || defcap == PR_CAP_FE) && (rc & PR_CAP_LISTEN) != defcap) { + ha_alert("parsing [%s:%d]: frontends and backends cannot inherit from the same defaults section" + " if it defines TCP/HTTP rules (defaults section at %s:%d).\n", + file, linenum, curr_defproxy->conf.file, curr_defproxy->conf.line); + err_code |= ERR_ALERT | ERR_ABORT; + } + else if (!(rc & PR_CAP_FE) && (!LIST_ISEMPTY(&curr_defproxy->tcp_req.l4_rules) || + !LIST_ISEMPTY(&curr_defproxy->tcp_req.l5_rules))) { + ha_alert("parsing [%s:%d]: a backend section cannot inherit from a defaults section defining" + " 'tcp-request connection' or 'tcp-request session' rules (defaults section at %s:%d).\n", + file, linenum, curr_defproxy->conf.file, curr_defproxy->conf.line); + err_code |= ERR_ALERT | ERR_ABORT; + } + else if (!(rc & PR_CAP_BE) && !LIST_ISEMPTY(&curr_defproxy->tcp_rep.inspect_rules)) { + ha_alert("parsing [%s:%d]: a frontend section cannot inherit from a defaults section defining" + " 'tcp-response content' rules (defaults section at %s:%d).\n", + file, linenum, curr_defproxy->conf.file, curr_defproxy->conf.line); + err_code |= ERR_ALERT | ERR_ABORT; + } + else { + curr_defproxy->cap = (curr_defproxy->cap & ~PR_CAP_LISTEN) | (rc & PR_CAP_LISTEN); + proxy_ref_defaults(curproxy, curr_defproxy); + } + } + } + if (curr_defproxy && (curr_defproxy->tcpcheck_rules.flags & TCPCHK_RULES_PROTO_CHK) && (curproxy->cap & PR_CAP_LISTEN) == PR_CAP_BE) { /* If the current default proxy defines tcpcheck rules, the @@ -641,8 +705,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) err_code |= ERR_WARN; } else if (strcmp(args[0], "acl") == 0) { /* add an ACL */ - if (curproxy->cap & PR_CAP_DEF) { - ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]); + if ((curproxy->cap & PR_CAP_DEF) && strlen(curproxy->id) == 0) { + ha_alert("parsing [%s:%d] : '%s' not allowed in anonymous 'defaults' section.\n", file, linenum, args[0]); err_code |= ERR_ALERT | ERR_FATAL; goto out; } @@ -1212,8 +1276,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) else if (strcmp(args[0], "http-request") == 0) { /* request access control: allow/deny/auth */ struct act_rule *rule; - if (curproxy->cap & PR_CAP_DEF) { - ha_alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]); + if ((curproxy->cap & PR_CAP_DEF) && strlen(curproxy->id) == 0) { + ha_alert("parsing [%s:%d] : '%s' not allowed in anonymous 'defaults' section.\n", file, linenum, args[0]); err_code |= ERR_ALERT | ERR_FATAL; goto out; } @@ -1243,8 +1307,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) else if (strcmp(args[0], "http-response") == 0) { /* response access control */ struct act_rule *rule; - if (curproxy->cap & PR_CAP_DEF) { - ha_alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]); + if ((curproxy->cap & PR_CAP_DEF) && strlen(curproxy->id) == 0) { + ha_alert("parsing [%s:%d] : '%s' not allowed in anonymous 'defaults' section.\n", file, linenum, args[0]); err_code |= ERR_ALERT | ERR_FATAL; goto out; } @@ -1273,8 +1337,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) else if (strcmp(args[0], "http-after-response") == 0) { struct act_rule *rule; - if (curproxy->cap & PR_CAP_DEF) { - ha_alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]); + if ((curproxy->cap & PR_CAP_DEF) && strlen(curproxy->id) == 0) { + ha_alert("parsing [%s:%d] : '%s' not allowed in anonymous 'defaults' section.\n", file, linenum, args[0]); err_code |= ERR_ALERT | ERR_FATAL; goto out; } diff --git a/src/cfgparse.c b/src/cfgparse.c index 02ddd959d..00faeac83 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -2520,6 +2520,15 @@ int check_config_validity() */ 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; @@ -3612,8 +3621,8 @@ out_uri_auth_compat: if (!curproxy->accept) curproxy->accept = frontend_accept; - if (curproxy->tcp_req.inspect_delay || - !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules)) + if (!LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules) || + (curproxy->defpx && !LIST_ISEMPTY(&curproxy->defpx->tcp_req.inspect_rules))) curproxy->fe_req_ana |= AN_REQ_INSPECT_FE; if (curproxy->mode == PR_MODE_HTTP) { @@ -3637,11 +3646,12 @@ out_uri_auth_compat: } if (curproxy->cap & PR_CAP_BE) { - if (curproxy->tcp_req.inspect_delay || - !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules)) + if (!LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules) || + (curproxy->defpx && !LIST_ISEMPTY(&curproxy->defpx->tcp_req.inspect_rules))) curproxy->be_req_ana |= AN_REQ_INSPECT_BE; - if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules)) + if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules) || + (curproxy->defpx && !LIST_ISEMPTY(&curproxy->defpx->tcp_rep.inspect_rules))) curproxy->be_rsp_ana |= AN_RES_INSPECT; if (curproxy->mode == PR_MODE_HTTP) { diff --git a/src/proxy.c b/src/proxy.c index c66aa8874..27a917dfd 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -1576,6 +1576,8 @@ static int proxy_defproxy_cpy(struct proxy *curproxy, const struct proxy *defpro curproxy->except_xff_net = defproxy->except_xff_net; curproxy->except_xot_net = defproxy->except_xot_net; curproxy->retry_type = defproxy->retry_type; + curproxy->tcp_req.inspect_delay = defproxy->tcp_req.inspect_delay; + curproxy->tcp_rep.inspect_delay = defproxy->tcp_rep.inspect_delay; if (defproxy->fwdfor_hdr_len) { curproxy->fwdfor_hdr_len = defproxy->fwdfor_hdr_len; diff --git a/src/tcp_rules.c b/src/tcp_rules.c index 375da6bef..5d97b25cb 100644 --- a/src/tcp_rules.c +++ b/src/tcp_rules.c @@ -574,8 +574,8 @@ static int tcp_parse_response_rule(char **args, int arg, int section_type, unsigned int where, const char *file, int line) { - if (curpx == defpx || !(curpx->cap & PR_CAP_BE)) { - memprintf(err, "%s %s is only allowed in 'backend' sections", + if ((curpx == defpx && strlen(defpx->id) == 0) || !(curpx->cap & PR_CAP_BE)) { + memprintf(err, "%s %s is only allowed in 'backend' sections or 'defaults' section with a name", args[0], args[1]); return -1; } @@ -742,9 +742,9 @@ static int tcp_parse_request_rule(char **args, int arg, int section_type, struct act_rule *rule, char **err, unsigned int where, const char *file, int line) { - if (curpx == defpx) { - memprintf(err, "%s %s is not allowed in 'defaults' sections", - args[0], args[1]); + if (curpx == defpx && strlen(defpx->id) == 0) { + memprintf(err, "%s %s is not allowed in anonymous 'defaults' sections", + args[0], args[1]); return -1; } @@ -1031,8 +1031,8 @@ static int tcp_parse_tcp_rep(char **args, int section_type, struct proxy *curpx, } if (strcmp(args[1], "inspect-delay") == 0) { - if (curpx == defpx || !(curpx->cap & PR_CAP_BE)) { - memprintf(err, "%s %s is only allowed in 'backend' sections", + if ((curpx == defpx && strlen(defpx->id) == 0) || !(curpx->cap & PR_CAP_BE)) { + memprintf(err, "%s %s is only allowed in 'backend' sections or 'defaults' section with a name", args[0], args[1]); return -1; } @@ -1148,9 +1148,9 @@ static int tcp_parse_tcp_req(char **args, int section_type, struct proxy *curpx, } if (strcmp(args[1], "inspect-delay") == 0) { - if (curpx == defpx) { - memprintf(err, "%s %s is not allowed in 'defaults' sections", - args[0], args[1]); + if (curpx == defpx && strlen(defpx->id) == 0) { + memprintf(err, "%s %s is not allowed in anonymous 'defaults' sections", + args[0], args[1]); return -1; }