mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-06 23:27:04 +02:00
CLEANUP: tree-wide: define and use acl_match_cond() helper
acl_match_cond() combines acl_exec_cond() + acl_pass() and a check on the condition->pol (to check if the cond is inverted) in order to return either 0 if the cond doesn't match or 1 if it matches (or NULL). Thanks to this we can actually simplify some redundant constructs that iterate over rules and evaluate if the condition matches or not. Conditions for tcp-request inspect-content and tcp-response inspect-content couldn't be simplified because they perform an extra check for missing data, and thus still need to leverage acl_exec_cond() It's best to display the patch using "-w", like "git show xxxx -w", because some blocks had to be re-indented after the cleanup, which makes the patch hard to review by default.
This commit is contained in:
parent
94d3b7375a
commit
e768a531b7
@ -104,6 +104,26 @@ struct acl_cond *build_acl_cond(const char *file, int line, struct list *known_a
|
|||||||
*/
|
*/
|
||||||
enum acl_test_res acl_exec_cond(struct acl_cond *cond, struct proxy *px, struct session *sess, struct stream *strm, unsigned int opt);
|
enum acl_test_res acl_exec_cond(struct acl_cond *cond, struct proxy *px, struct session *sess, struct stream *strm, unsigned int opt);
|
||||||
|
|
||||||
|
|
||||||
|
/* helper that combines acl_exec_cond() and acl_pass(), and also takes into
|
||||||
|
* account cond->pol in order to return either 1 if the cond should pass and
|
||||||
|
* 0 otherwise
|
||||||
|
* <cond> may be NULL, in which case 1 is returned as the cond cannot fail
|
||||||
|
*/
|
||||||
|
static inline int acl_match_cond(struct acl_cond *cond, struct proxy *px, struct session *sess, struct stream *strm, unsigned int opt)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!cond)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
ret = acl_pass(acl_exec_cond(cond, px, sess, strm, opt));
|
||||||
|
if (cond->pol == ACL_COND_UNLESS)
|
||||||
|
ret = !ret;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Returns a pointer to the first ACL conflicting with usage at place <where>
|
/* Returns a pointer to the first ACL conflicting with usage at place <where>
|
||||||
* which is one of the SMP_VAL_* bits indicating a check place, or NULL if
|
* which is one of the SMP_VAL_* bits indicating a check place, or NULL if
|
||||||
* no conflict is found. Only full conflicts are detected (ACL is not usable).
|
* no conflict is found. Only full conflicts are detected (ACL is not usable).
|
||||||
|
@ -311,7 +311,6 @@ static int fcgi_flt_http_headers(struct stream *s, struct filter *filter, struct
|
|||||||
struct eb_root hdr_rules = EB_ROOT;
|
struct eb_root hdr_rules = EB_ROOT;
|
||||||
struct htx *htx;
|
struct htx *htx;
|
||||||
struct http_hdr_ctx ctx;
|
struct http_hdr_ctx ctx;
|
||||||
int ret;
|
|
||||||
|
|
||||||
htx = htxbuf(&msg->chn->buf);
|
htx = htxbuf(&msg->chn->buf);
|
||||||
|
|
||||||
@ -368,16 +367,8 @@ static int fcgi_flt_http_headers(struct stream *s, struct filter *filter, struct
|
|||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
list_for_each_entry(rule, &fcgi_conf->param_rules, list) {
|
list_for_each_entry(rule, &fcgi_conf->param_rules, list) {
|
||||||
if (rule->cond) {
|
if (!acl_match_cond(rule->cond, s->be, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL))
|
||||||
ret = acl_exec_cond(rule->cond, s->be, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
|
continue;
|
||||||
ret = acl_pass(ret);
|
|
||||||
if (rule->cond->pol == ACL_COND_UNLESS)
|
|
||||||
ret = !ret;
|
|
||||||
|
|
||||||
/* the rule does not match */
|
|
||||||
if (!ret)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
param_rule = NULL;
|
param_rule = NULL;
|
||||||
node = ebis_lookup_len(¶m_rules, rule->name.ptr, rule->name.len);
|
node = ebis_lookup_len(¶m_rules, rule->name.ptr, rule->name.len);
|
||||||
@ -398,16 +389,8 @@ static int fcgi_flt_http_headers(struct stream *s, struct filter *filter, struct
|
|||||||
}
|
}
|
||||||
|
|
||||||
list_for_each_entry(rule, &fcgi_conf->hdr_rules, list) {
|
list_for_each_entry(rule, &fcgi_conf->hdr_rules, list) {
|
||||||
if (rule->cond) {
|
if (!acl_match_cond(rule->cond, s->be, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL))
|
||||||
ret = acl_exec_cond(rule->cond, s->be, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
|
continue;
|
||||||
ret = acl_pass(ret);
|
|
||||||
if (rule->cond->pol == ACL_COND_UNLESS)
|
|
||||||
ret = !ret;
|
|
||||||
|
|
||||||
/* the rule does not match */
|
|
||||||
if (!ret)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
hdr_rule = NULL;
|
hdr_rule = NULL;
|
||||||
node = ebis_lookup_len(&hdr_rules, rule->name.ptr, rule->name.len);
|
node = ebis_lookup_len(&hdr_rules, rule->name.ptr, rule->name.len);
|
||||||
|
@ -592,16 +592,8 @@ static int spoe_encode_message(struct stream *s, struct spoe_context *ctx,
|
|||||||
struct spoe_arg *arg;
|
struct spoe_arg *arg;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (msg->cond) {
|
if (!acl_match_cond(msg->cond, s->be, s->sess, s, dir|SMP_OPT_FINAL))
|
||||||
ret = acl_exec_cond(msg->cond, s->be, s->sess, s, dir|SMP_OPT_FINAL);
|
goto next;
|
||||||
ret = acl_pass(ret);
|
|
||||||
if (msg->cond->pol == ACL_COND_UNLESS)
|
|
||||||
ret = !ret;
|
|
||||||
|
|
||||||
/* the rule does not match */
|
|
||||||
if (!ret)
|
|
||||||
goto next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if there is enough space for the message name and the
|
/* Check if there is enough space for the message name and the
|
||||||
* number of arguments. It implies <msg->id_len> is encoded on 2
|
* number of arguments. It implies <msg->id_len> is encoded on 2
|
||||||
|
@ -237,19 +237,14 @@ int http_wait_for_request(struct stream *s, struct channel *req, int an_bit)
|
|||||||
|
|
||||||
/* Check if we want to fail this monitor request or not */
|
/* Check if we want to fail this monitor request or not */
|
||||||
list_for_each_entry(cond, &sess->fe->mon_fail_cond, list) {
|
list_for_each_entry(cond, &sess->fe->mon_fail_cond, list) {
|
||||||
int ret = acl_exec_cond(cond, sess->fe, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
|
if (!acl_match_cond(cond, sess->fe, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL))
|
||||||
|
continue;
|
||||||
|
|
||||||
ret = acl_pass(ret);
|
/* we fail this request, let's return 503 service unavail */
|
||||||
if (cond->pol == ACL_COND_UNLESS)
|
txn->status = 503;
|
||||||
ret = !ret;
|
if (!(s->flags & SF_ERR_MASK))
|
||||||
|
s->flags |= SF_ERR_LOCAL; /* we don't want a real error here */
|
||||||
if (ret) {
|
goto return_prx_cond;
|
||||||
/* we fail this request, let's return 503 service unavail */
|
|
||||||
txn->status = 503;
|
|
||||||
if (!(s->flags & SF_ERR_MASK))
|
|
||||||
s->flags |= SF_ERR_LOCAL; /* we don't want a real error here */
|
|
||||||
goto return_prx_cond;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* nothing to fail, let's reply normally */
|
/* nothing to fail, let's reply normally */
|
||||||
@ -505,16 +500,8 @@ int http_process_req_common(struct stream *s, struct channel *req, int an_bit, s
|
|||||||
|
|
||||||
/* check whether we have some ACLs set to redirect this request */
|
/* check whether we have some ACLs set to redirect this request */
|
||||||
list_for_each_entry(rule, &px->redirect_rules, list) {
|
list_for_each_entry(rule, &px->redirect_rules, list) {
|
||||||
if (rule->cond) {
|
if (!acl_match_cond(rule->cond, px, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL))
|
||||||
int ret;
|
continue;
|
||||||
|
|
||||||
ret = acl_exec_cond(rule->cond, px, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
|
|
||||||
ret = acl_pass(ret);
|
|
||||||
if (rule->cond->pol == ACL_COND_UNLESS)
|
|
||||||
ret = !ret;
|
|
||||||
if (!ret)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!http_apply_redirect_rule(rule, s, txn)) {
|
if (!http_apply_redirect_rule(rule, s, txn)) {
|
||||||
goto return_int_err;
|
goto return_int_err;
|
||||||
}
|
}
|
||||||
@ -2757,18 +2744,8 @@ static enum rule_result http_req_get_intercept_rule(struct proxy *px, struct lis
|
|||||||
|
|
||||||
list_for_each_entry(rule, s->current_rule_list, list) {
|
list_for_each_entry(rule, s->current_rule_list, list) {
|
||||||
/* check optional condition */
|
/* check optional condition */
|
||||||
if (rule->cond) {
|
if (!acl_match_cond(rule->cond, px, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL))
|
||||||
int ret;
|
continue;
|
||||||
|
|
||||||
ret = acl_exec_cond(rule->cond, px, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
|
|
||||||
ret = acl_pass(ret);
|
|
||||||
|
|
||||||
if (rule->cond->pol == ACL_COND_UNLESS)
|
|
||||||
ret = !ret;
|
|
||||||
|
|
||||||
if (!ret) /* condition not matched */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
act_opts |= ACT_OPT_FIRST;
|
act_opts |= ACT_OPT_FIRST;
|
||||||
resume_execution:
|
resume_execution:
|
||||||
@ -2938,18 +2915,8 @@ static enum rule_result http_res_get_intercept_rule(struct proxy *px, struct lis
|
|||||||
|
|
||||||
list_for_each_entry(rule, s->current_rule_list, list) {
|
list_for_each_entry(rule, s->current_rule_list, list) {
|
||||||
/* check optional condition */
|
/* check optional condition */
|
||||||
if (rule->cond) {
|
if (!acl_match_cond(rule->cond, px, sess, s, SMP_OPT_DIR_RES|SMP_OPT_FINAL))
|
||||||
int ret;
|
continue;
|
||||||
|
|
||||||
ret = acl_exec_cond(rule->cond, px, sess, s, SMP_OPT_DIR_RES|SMP_OPT_FINAL);
|
|
||||||
ret = acl_pass(ret);
|
|
||||||
|
|
||||||
if (rule->cond->pol == ACL_COND_UNLESS)
|
|
||||||
ret = !ret;
|
|
||||||
|
|
||||||
if (!ret) /* condition not matched */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
act_opts |= ACT_OPT_FIRST;
|
act_opts |= ACT_OPT_FIRST;
|
||||||
resume_execution:
|
resume_execution:
|
||||||
@ -4122,20 +4089,12 @@ static int http_handle_stats(struct stream *s, struct channel *req, struct proxy
|
|||||||
|
|
||||||
/* now check whether we have some admin rules for this request */
|
/* now check whether we have some admin rules for this request */
|
||||||
list_for_each_entry(stats_admin_rule, &uri_auth->admin_rules, list) {
|
list_for_each_entry(stats_admin_rule, &uri_auth->admin_rules, list) {
|
||||||
int ret = 1;
|
if (!acl_match_cond(stats_admin_rule->cond, s->be, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (stats_admin_rule->cond) {
|
/* no rule, or the rule matches */
|
||||||
ret = acl_exec_cond(stats_admin_rule->cond, s->be, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
|
ctx->flags |= STAT_F_ADMIN;
|
||||||
ret = acl_pass(ret);
|
break;
|
||||||
if (stats_admin_rule->cond->pol == ACL_COND_UNLESS)
|
|
||||||
ret = !ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret) {
|
|
||||||
/* no rule, or the rule matches */
|
|
||||||
ctx->flags |= STAT_F_ADMIN;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (txn->meth == HTTP_METH_GET || txn->meth == HTTP_METH_HEAD)
|
if (txn->meth == HTTP_METH_GET || txn->meth == HTTP_METH_HEAD)
|
||||||
|
@ -18,7 +18,6 @@ int quic_init_exec_rules(struct listener *li, struct quic_dgram *dgram)
|
|||||||
{
|
{
|
||||||
static THREAD_LOCAL struct session rule_sess;
|
static THREAD_LOCAL struct session rule_sess;
|
||||||
struct act_rule *rule;
|
struct act_rule *rule;
|
||||||
enum acl_test_res ret;
|
|
||||||
struct proxy *px;
|
struct proxy *px;
|
||||||
int result = 1;
|
int result = 1;
|
||||||
|
|
||||||
@ -34,41 +33,33 @@ int quic_init_exec_rules(struct listener *li, struct quic_dgram *dgram)
|
|||||||
rule_sess.origin = &dgram->obj_type;
|
rule_sess.origin = &dgram->obj_type;
|
||||||
|
|
||||||
list_for_each_entry(rule, &px->quic_init_rules, list) {
|
list_for_each_entry(rule, &px->quic_init_rules, list) {
|
||||||
ret = ACL_TEST_PASS;
|
if (!acl_match_cond(rule->cond, px, &rule_sess, NULL, SMP_OPT_DIR_REQ|SMP_OPT_FINAL))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (rule->cond) {
|
if (rule->action_ptr) {
|
||||||
ret = acl_exec_cond(rule->cond, px, &rule_sess, NULL, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
|
switch (rule->action_ptr(rule, px, &rule_sess, NULL, 0)) {
|
||||||
ret = acl_pass(ret);
|
case ACT_RET_CONT:
|
||||||
if (rule->cond->pol == ACL_COND_UNLESS)
|
break;
|
||||||
ret = !ret;
|
case ACT_RET_DONE:
|
||||||
}
|
case ACT_RET_STOP:
|
||||||
|
|
||||||
if (ret) {
|
|
||||||
if (rule->action_ptr) {
|
|
||||||
switch (rule->action_ptr(rule, px, &rule_sess, NULL, 0)) {
|
|
||||||
case ACT_RET_CONT:
|
|
||||||
break;
|
|
||||||
case ACT_RET_DONE:
|
|
||||||
case ACT_RET_STOP:
|
|
||||||
goto end;
|
|
||||||
case ACT_RET_ABRT:
|
|
||||||
case ACT_RET_DENY:
|
|
||||||
case ACT_RET_ERR:
|
|
||||||
case ACT_RET_INV:
|
|
||||||
result = 0;
|
|
||||||
goto end;
|
|
||||||
default:
|
|
||||||
ABORT_NOW("not implemented");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (rule->action == ACT_ACTION_ALLOW) {
|
|
||||||
goto end;
|
goto end;
|
||||||
}
|
case ACT_RET_ABRT:
|
||||||
else if (rule->action == ACT_ACTION_DENY) {
|
case ACT_RET_DENY:
|
||||||
|
case ACT_RET_ERR:
|
||||||
|
case ACT_RET_INV:
|
||||||
result = 0;
|
result = 0;
|
||||||
goto end;
|
goto end;
|
||||||
|
default:
|
||||||
|
ABORT_NOW("not implemented");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (rule->action == ACT_ACTION_ALLOW) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
else if (rule->action == ACT_ACTION_DENY) {
|
||||||
|
result = 0;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
|
219
src/stream.c
219
src/stream.c
@ -1072,45 +1072,38 @@ static int process_switching_rules(struct stream *s, struct channel *req, int an
|
|||||||
struct switching_rule *rule;
|
struct switching_rule *rule;
|
||||||
|
|
||||||
list_for_each_entry(rule, &fe->switching_rules, list) {
|
list_for_each_entry(rule, &fe->switching_rules, list) {
|
||||||
int ret = 1;
|
struct proxy *backend = NULL;
|
||||||
|
|
||||||
if (rule->cond) {
|
if (!acl_match_cond(rule->cond, fe, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL))
|
||||||
ret = acl_exec_cond(rule->cond, fe, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
|
continue;
|
||||||
ret = acl_pass(ret);
|
|
||||||
if (rule->cond->pol == ACL_COND_UNLESS)
|
|
||||||
ret = !ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret) {
|
/* If the backend name is dynamic, try to resolve the name.
|
||||||
/* If the backend name is dynamic, try to resolve the name.
|
* If we can't resolve the name, or if any error occurs, break
|
||||||
* If we can't resolve the name, or if any error occurs, break
|
* the loop and fallback to the default backend.
|
||||||
* the loop and fallback to the default backend.
|
*/
|
||||||
*/
|
|
||||||
struct proxy *backend = NULL;
|
|
||||||
|
|
||||||
if (rule->dynamic) {
|
if (rule->dynamic) {
|
||||||
struct buffer *tmp;
|
struct buffer *tmp;
|
||||||
|
|
||||||
tmp = alloc_trash_chunk();
|
tmp = alloc_trash_chunk();
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
goto sw_failed;
|
|
||||||
|
|
||||||
if (build_logline(s, tmp->area, tmp->size, &rule->be.expr))
|
|
||||||
backend = proxy_be_by_name(tmp->area);
|
|
||||||
|
|
||||||
free_trash_chunk(tmp);
|
|
||||||
tmp = NULL;
|
|
||||||
|
|
||||||
if (!backend)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
backend = rule->be.backend;
|
|
||||||
|
|
||||||
if (!stream_set_backend(s, backend))
|
|
||||||
goto sw_failed;
|
goto sw_failed;
|
||||||
break;
|
|
||||||
|
if (build_logline(s, tmp->area, tmp->size, &rule->be.expr))
|
||||||
|
backend = proxy_be_by_name(tmp->area);
|
||||||
|
|
||||||
|
free_trash_chunk(tmp);
|
||||||
|
tmp = NULL;
|
||||||
|
|
||||||
|
if (!backend)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
backend = rule->be.backend;
|
||||||
|
|
||||||
|
if (!stream_set_backend(s, backend))
|
||||||
|
goto sw_failed;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* To ensure correct connection accounting on the backend, we
|
/* To ensure correct connection accounting on the backend, we
|
||||||
@ -1147,24 +1140,16 @@ static int process_switching_rules(struct stream *s, struct channel *req, int an
|
|||||||
* persistence rule, and report that in the stream.
|
* persistence rule, and report that in the stream.
|
||||||
*/
|
*/
|
||||||
list_for_each_entry(prst_rule, &s->be->persist_rules, list) {
|
list_for_each_entry(prst_rule, &s->be->persist_rules, list) {
|
||||||
int ret = 1;
|
if (!acl_match_cond(prst_rule->cond, s->be, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (prst_rule->cond) {
|
/* no rule, or the rule matches */
|
||||||
ret = acl_exec_cond(prst_rule->cond, s->be, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
|
if (prst_rule->type == PERSIST_TYPE_FORCE) {
|
||||||
ret = acl_pass(ret);
|
s->flags |= SF_FORCE_PRST;
|
||||||
if (prst_rule->cond->pol == ACL_COND_UNLESS)
|
} else {
|
||||||
ret = !ret;
|
s->flags |= SF_IGNORE_PRST;
|
||||||
}
|
|
||||||
|
|
||||||
if (ret) {
|
|
||||||
/* no rule, or the rule matches */
|
|
||||||
if (prst_rule->type == PERSIST_TYPE_FORCE) {
|
|
||||||
s->flags |= SF_FORCE_PRST;
|
|
||||||
} else {
|
|
||||||
s->flags |= SF_IGNORE_PRST;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
DBG_TRACE_LEAVE(STRM_EV_STRM_ANA, s);
|
DBG_TRACE_LEAVE(STRM_EV_STRM_ANA, s);
|
||||||
@ -1201,40 +1186,34 @@ static int process_server_rules(struct stream *s, struct channel *req, int an_bi
|
|||||||
|
|
||||||
if (!(s->flags & SF_ASSIGNED)) {
|
if (!(s->flags & SF_ASSIGNED)) {
|
||||||
list_for_each_entry(rule, &px->server_rules, list) {
|
list_for_each_entry(rule, &px->server_rules, list) {
|
||||||
int ret;
|
struct server *srv;
|
||||||
|
|
||||||
ret = acl_exec_cond(rule->cond, s->be, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
|
if (!acl_match_cond(rule->cond, s->be, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL))
|
||||||
ret = acl_pass(ret);
|
continue;
|
||||||
if (rule->cond->pol == ACL_COND_UNLESS)
|
|
||||||
ret = !ret;
|
|
||||||
|
|
||||||
if (ret) {
|
if (rule->dynamic) {
|
||||||
struct server *srv;
|
struct buffer *tmp = get_trash_chunk();
|
||||||
|
|
||||||
if (rule->dynamic) {
|
if (!build_logline(s, tmp->area, tmp->size, &rule->expr))
|
||||||
struct buffer *tmp = get_trash_chunk();
|
break;
|
||||||
|
|
||||||
if (!build_logline(s, tmp->area, tmp->size, &rule->expr))
|
srv = findserver(s->be, tmp->area);
|
||||||
break;
|
if (!srv)
|
||||||
|
|
||||||
srv = findserver(s->be, tmp->area);
|
|
||||||
if (!srv)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
srv = rule->srv.ptr;
|
|
||||||
|
|
||||||
if ((srv->cur_state != SRV_ST_STOPPED) ||
|
|
||||||
(px->options & PR_O_PERSIST) ||
|
|
||||||
(s->flags & SF_FORCE_PRST)) {
|
|
||||||
s->flags |= SF_DIRECT | SF_ASSIGNED;
|
|
||||||
s->target = &srv->obj_type;
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
/* if the server is not UP, let's go on with next rules
|
|
||||||
* just in case another one is suited.
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
srv = rule->srv.ptr;
|
||||||
|
|
||||||
|
if ((srv->cur_state != SRV_ST_STOPPED) ||
|
||||||
|
(px->options & PR_O_PERSIST) ||
|
||||||
|
(s->flags & SF_FORCE_PRST)) {
|
||||||
|
s->flags |= SF_DIRECT | SF_ASSIGNED;
|
||||||
|
s->target = &srv->obj_type;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* if the server is not UP, let's go on with next rules
|
||||||
|
* just in case another one is suited.
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1310,7 +1289,7 @@ static int process_sticking_rules(struct stream *s, struct channel *req, int an_
|
|||||||
DBG_TRACE_ENTER(STRM_EV_STRM_ANA, s);
|
DBG_TRACE_ENTER(STRM_EV_STRM_ANA, s);
|
||||||
|
|
||||||
list_for_each_entry(rule, &px->sticking_rules, list) {
|
list_for_each_entry(rule, &px->sticking_rules, list) {
|
||||||
int ret = 1 ;
|
struct stktable_key *key;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Only the first stick store-request of each table is applied
|
/* Only the first stick store-request of each table is applied
|
||||||
@ -1330,38 +1309,30 @@ static int process_sticking_rules(struct stream *s, struct channel *req, int an_
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rule->cond) {
|
if (!acl_match_cond(rule->cond, px, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL))
|
||||||
ret = acl_exec_cond(rule->cond, px, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
|
continue;
|
||||||
ret = acl_pass(ret);
|
|
||||||
if (rule->cond->pol == ACL_COND_UNLESS)
|
key = stktable_fetch_key(rule->table.t, px, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL, rule->expr, NULL);
|
||||||
ret = !ret;
|
if (!key)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (rule->flags & STK_IS_MATCH) {
|
||||||
|
struct stksess *ts;
|
||||||
|
|
||||||
|
if ((ts = stktable_lookup_key(rule->table.t, key)) != NULL) {
|
||||||
|
if (!(s->flags & SF_ASSIGNED))
|
||||||
|
sticking_rule_find_target(s, rule->table.t, ts);
|
||||||
|
stktable_touch_local(rule->table.t, ts, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (rule->flags & STK_IS_STORE) {
|
||||||
if (ret) {
|
if (s->store_count < (sizeof(s->store) / sizeof(s->store[0]))) {
|
||||||
struct stktable_key *key;
|
|
||||||
|
|
||||||
key = stktable_fetch_key(rule->table.t, px, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL, rule->expr, NULL);
|
|
||||||
if (!key)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (rule->flags & STK_IS_MATCH) {
|
|
||||||
struct stksess *ts;
|
struct stksess *ts;
|
||||||
|
|
||||||
if ((ts = stktable_lookup_key(rule->table.t, key)) != NULL) {
|
ts = stksess_new(rule->table.t, key);
|
||||||
if (!(s->flags & SF_ASSIGNED))
|
if (ts) {
|
||||||
sticking_rule_find_target(s, rule->table.t, ts);
|
s->store[s->store_count].table = rule->table.t;
|
||||||
stktable_touch_local(rule->table.t, ts, 1);
|
s->store[s->store_count++].ts = ts;
|
||||||
}
|
|
||||||
}
|
|
||||||
if (rule->flags & STK_IS_STORE) {
|
|
||||||
if (s->store_count < (sizeof(s->store) / sizeof(s->store[0]))) {
|
|
||||||
struct stksess *ts;
|
|
||||||
|
|
||||||
ts = stksess_new(rule->table.t, key);
|
|
||||||
if (ts) {
|
|
||||||
s->store[s->store_count].table = rule->table.t;
|
|
||||||
s->store[s->store_count++].ts = ts;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1388,7 +1359,7 @@ static int process_store_rules(struct stream *s, struct channel *rep, int an_bit
|
|||||||
DBG_TRACE_ENTER(STRM_EV_STRM_ANA, s);
|
DBG_TRACE_ENTER(STRM_EV_STRM_ANA, s);
|
||||||
|
|
||||||
list_for_each_entry(rule, &px->storersp_rules, list) {
|
list_for_each_entry(rule, &px->storersp_rules, list) {
|
||||||
int ret = 1 ;
|
struct stktable_key *key;
|
||||||
|
|
||||||
/* Only the first stick store-response of each table is applied
|
/* Only the first stick store-response of each table is applied
|
||||||
* and other ones are ignored. The purpose is to allow complex
|
* and other ones are ignored. The purpose is to allow complex
|
||||||
@ -1411,28 +1382,20 @@ static int process_store_rules(struct stream *s, struct channel *rep, int an_bit
|
|||||||
if (i < s->store_count)
|
if (i < s->store_count)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (rule->cond) {
|
if (!acl_match_cond(rule->cond, px, sess, s, SMP_OPT_DIR_RES|SMP_OPT_FINAL))
|
||||||
ret = acl_exec_cond(rule->cond, px, sess, s, SMP_OPT_DIR_RES|SMP_OPT_FINAL);
|
continue;
|
||||||
ret = acl_pass(ret);
|
|
||||||
if (rule->cond->pol == ACL_COND_UNLESS)
|
|
||||||
ret = !ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret) {
|
key = stktable_fetch_key(rule->table.t, px, sess, s, SMP_OPT_DIR_RES|SMP_OPT_FINAL, rule->expr, NULL);
|
||||||
struct stktable_key *key;
|
if (!key)
|
||||||
|
continue;
|
||||||
|
|
||||||
key = stktable_fetch_key(rule->table.t, px, sess, s, SMP_OPT_DIR_RES|SMP_OPT_FINAL, rule->expr, NULL);
|
if (s->store_count < (sizeof(s->store) / sizeof(s->store[0]))) {
|
||||||
if (!key)
|
struct stksess *ts;
|
||||||
continue;
|
|
||||||
|
|
||||||
if (s->store_count < (sizeof(s->store) / sizeof(s->store[0]))) {
|
ts = stksess_new(rule->table.t, key);
|
||||||
struct stksess *ts;
|
if (ts) {
|
||||||
|
s->store[s->store_count].table = rule->table.t;
|
||||||
ts = stksess_new(rule->table.t, key);
|
s->store[s->store_count++].ts = ts;
|
||||||
if (ts) {
|
|
||||||
s->store[s->store_count].table = rule->table.t;
|
|
||||||
s->store[s->store_count++].ts = ts;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
412
src/tcp_rules.c
412
src/tcp_rules.c
@ -158,65 +158,66 @@ int tcp_inspect_request(struct stream *s, struct channel *req, int an_bit)
|
|||||||
ret = acl_pass(ret);
|
ret = acl_pass(ret);
|
||||||
if (rule->cond->pol == ACL_COND_UNLESS)
|
if (rule->cond->pol == ACL_COND_UNLESS)
|
||||||
ret = !ret;
|
ret = !ret;
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret) {
|
act_opts |= ACT_OPT_FIRST;
|
||||||
act_opts |= ACT_OPT_FIRST;
|
|
||||||
resume_execution:
|
resume_execution:
|
||||||
/* Always call the action function if defined */
|
/* Always call the action function if defined */
|
||||||
if (rule->action_ptr) {
|
if (rule->action_ptr) {
|
||||||
switch (rule->action_ptr(rule, s->be, s->sess, s, act_opts)) {
|
switch (rule->action_ptr(rule, s->be, s->sess, s, act_opts)) {
|
||||||
case ACT_RET_CONT:
|
case ACT_RET_CONT:
|
||||||
break;
|
break;
|
||||||
case ACT_RET_STOP:
|
case ACT_RET_STOP:
|
||||||
case ACT_RET_DONE:
|
case ACT_RET_DONE:
|
||||||
s->last_entity.type = STRM_ENTITY_RULE;
|
s->last_entity.type = STRM_ENTITY_RULE;
|
||||||
s->last_entity.ptr = rule;
|
s->last_entity.ptr = rule;
|
||||||
goto end;
|
goto end;
|
||||||
case ACT_RET_YIELD:
|
case ACT_RET_YIELD:
|
||||||
s->current_rule = rule;
|
s->current_rule = rule;
|
||||||
if (act_opts & ACT_OPT_FINAL) {
|
if (act_opts & ACT_OPT_FINAL) {
|
||||||
send_log(s->be, LOG_WARNING,
|
send_log(s->be, LOG_WARNING,
|
||||||
"Internal error: yield not allowed if the inspect-delay expired "
|
"Internal error: yield not allowed if the inspect-delay expired "
|
||||||
"for the tcp-request content actions.");
|
"for the tcp-request content actions.");
|
||||||
s->last_entity.type = STRM_ENTITY_RULE;
|
|
||||||
s->last_entity.ptr = rule;
|
|
||||||
goto internal;
|
|
||||||
}
|
|
||||||
s->waiting_entity.type = STRM_ENTITY_RULE;
|
|
||||||
s->waiting_entity.ptr = rule;
|
|
||||||
goto missing_data;
|
|
||||||
case ACT_RET_DENY:
|
|
||||||
s->last_entity.type = STRM_ENTITY_RULE;
|
|
||||||
s->last_entity.ptr = rule;
|
|
||||||
goto deny;
|
|
||||||
case ACT_RET_ABRT:
|
|
||||||
s->last_entity.type = STRM_ENTITY_RULE;
|
|
||||||
s->last_entity.ptr = rule;
|
|
||||||
goto abort;
|
|
||||||
case ACT_RET_ERR:
|
|
||||||
s->last_entity.type = STRM_ENTITY_RULE;
|
s->last_entity.type = STRM_ENTITY_RULE;
|
||||||
s->last_entity.ptr = rule;
|
s->last_entity.ptr = rule;
|
||||||
goto internal;
|
goto internal;
|
||||||
case ACT_RET_INV:
|
}
|
||||||
s->last_entity.type = STRM_ENTITY_RULE;
|
s->waiting_entity.type = STRM_ENTITY_RULE;
|
||||||
s->last_entity.ptr = rule;
|
s->waiting_entity.ptr = rule;
|
||||||
goto invalid;
|
goto missing_data;
|
||||||
}
|
case ACT_RET_DENY:
|
||||||
continue; /* eval the next rule */
|
s->last_entity.type = STRM_ENTITY_RULE;
|
||||||
|
s->last_entity.ptr = rule;
|
||||||
|
goto deny;
|
||||||
|
case ACT_RET_ABRT:
|
||||||
|
s->last_entity.type = STRM_ENTITY_RULE;
|
||||||
|
s->last_entity.ptr = rule;
|
||||||
|
goto abort;
|
||||||
|
case ACT_RET_ERR:
|
||||||
|
s->last_entity.type = STRM_ENTITY_RULE;
|
||||||
|
s->last_entity.ptr = rule;
|
||||||
|
goto internal;
|
||||||
|
case ACT_RET_INV:
|
||||||
|
s->last_entity.type = STRM_ENTITY_RULE;
|
||||||
|
s->last_entity.ptr = rule;
|
||||||
|
goto invalid;
|
||||||
}
|
}
|
||||||
|
continue; /* eval the next rule */
|
||||||
|
}
|
||||||
|
|
||||||
/* If not action function defined, check for known actions */
|
/* If not action function defined, check for known actions */
|
||||||
if (rule->action == ACT_ACTION_ALLOW) {
|
if (rule->action == ACT_ACTION_ALLOW) {
|
||||||
s->last_entity.type = STRM_ENTITY_RULE;
|
s->last_entity.type = STRM_ENTITY_RULE;
|
||||||
s->last_entity.ptr = rule;
|
s->last_entity.ptr = rule;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
else if (rule->action == ACT_ACTION_DENY) {
|
else if (rule->action == ACT_ACTION_DENY) {
|
||||||
s->last_entity.type = STRM_ENTITY_RULE;
|
s->last_entity.type = STRM_ENTITY_RULE;
|
||||||
s->last_entity.ptr = rule;
|
s->last_entity.ptr = rule;
|
||||||
goto deny;
|
goto deny;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,76 +349,76 @@ int tcp_inspect_response(struct stream *s, struct channel *rep, int an_bit)
|
|||||||
ret = acl_pass(ret);
|
ret = acl_pass(ret);
|
||||||
if (rule->cond->pol == ACL_COND_UNLESS)
|
if (rule->cond->pol == ACL_COND_UNLESS)
|
||||||
ret = !ret;
|
ret = !ret;
|
||||||
|
if (!ret)
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret) {
|
act_opts |= ACT_OPT_FIRST;
|
||||||
act_opts |= ACT_OPT_FIRST;
|
|
||||||
resume_execution:
|
resume_execution:
|
||||||
|
|
||||||
/* Always call the action function if defined */
|
/* Always call the action function if defined */
|
||||||
if (rule->action_ptr) {
|
if (rule->action_ptr) {
|
||||||
switch (rule->action_ptr(rule, s->be, s->sess, s, act_opts)) {
|
switch (rule->action_ptr(rule, s->be, s->sess, s, act_opts)) {
|
||||||
case ACT_RET_CONT:
|
case ACT_RET_CONT:
|
||||||
break;
|
break;
|
||||||
case ACT_RET_STOP:
|
case ACT_RET_STOP:
|
||||||
case ACT_RET_DONE:
|
case ACT_RET_DONE:
|
||||||
s->last_entity.type = STRM_ENTITY_RULE;
|
s->last_entity.type = STRM_ENTITY_RULE;
|
||||||
s->last_entity.ptr = rule;
|
s->last_entity.ptr = rule;
|
||||||
goto end;
|
goto end;
|
||||||
case ACT_RET_YIELD:
|
case ACT_RET_YIELD:
|
||||||
s->current_rule = rule;
|
s->current_rule = rule;
|
||||||
if (act_opts & ACT_OPT_FINAL) {
|
if (act_opts & ACT_OPT_FINAL) {
|
||||||
send_log(s->be, LOG_WARNING,
|
send_log(s->be, LOG_WARNING,
|
||||||
"Internal error: yield not allowed if the inspect-delay expired "
|
"Internal error: yield not allowed if the inspect-delay expired "
|
||||||
"for the tcp-response content actions.");
|
"for the tcp-response content actions.");
|
||||||
s->last_entity.type = STRM_ENTITY_RULE;
|
|
||||||
s->last_entity.ptr = rule;
|
|
||||||
goto internal;
|
|
||||||
}
|
|
||||||
s->waiting_entity.type = STRM_ENTITY_RULE;
|
|
||||||
s->waiting_entity.ptr = rule;
|
|
||||||
channel_dont_close(rep);
|
|
||||||
goto missing_data;
|
|
||||||
case ACT_RET_DENY:
|
|
||||||
s->last_entity.type = STRM_ENTITY_RULE;
|
|
||||||
s->last_entity.ptr = rule;
|
|
||||||
goto deny;
|
|
||||||
case ACT_RET_ABRT:
|
|
||||||
s->last_entity.type = STRM_ENTITY_RULE;
|
|
||||||
s->last_entity.ptr = rule;
|
|
||||||
goto abort;
|
|
||||||
case ACT_RET_ERR:
|
|
||||||
s->last_entity.type = STRM_ENTITY_RULE;
|
s->last_entity.type = STRM_ENTITY_RULE;
|
||||||
s->last_entity.ptr = rule;
|
s->last_entity.ptr = rule;
|
||||||
goto internal;
|
goto internal;
|
||||||
case ACT_RET_INV:
|
}
|
||||||
s->last_entity.type = STRM_ENTITY_RULE;
|
s->waiting_entity.type = STRM_ENTITY_RULE;
|
||||||
s->last_entity.ptr = rule;
|
s->waiting_entity.ptr = rule;
|
||||||
goto invalid;
|
channel_dont_close(rep);
|
||||||
}
|
goto missing_data;
|
||||||
continue; /* eval the next rule */
|
case ACT_RET_DENY:
|
||||||
|
s->last_entity.type = STRM_ENTITY_RULE;
|
||||||
|
s->last_entity.ptr = rule;
|
||||||
|
goto deny;
|
||||||
|
case ACT_RET_ABRT:
|
||||||
|
s->last_entity.type = STRM_ENTITY_RULE;
|
||||||
|
s->last_entity.ptr = rule;
|
||||||
|
goto abort;
|
||||||
|
case ACT_RET_ERR:
|
||||||
|
s->last_entity.type = STRM_ENTITY_RULE;
|
||||||
|
s->last_entity.ptr = rule;
|
||||||
|
goto internal;
|
||||||
|
case ACT_RET_INV:
|
||||||
|
s->last_entity.type = STRM_ENTITY_RULE;
|
||||||
|
s->last_entity.ptr = rule;
|
||||||
|
goto invalid;
|
||||||
}
|
}
|
||||||
|
continue; /* eval the next rule */
|
||||||
|
}
|
||||||
|
|
||||||
/* If not action function defined, check for known actions */
|
/* If not action function defined, check for known actions */
|
||||||
if (rule->action == ACT_ACTION_ALLOW) {
|
if (rule->action == ACT_ACTION_ALLOW) {
|
||||||
s->last_entity.type = STRM_ENTITY_RULE;
|
s->last_entity.type = STRM_ENTITY_RULE;
|
||||||
s->last_entity.ptr = rule;
|
s->last_entity.ptr = rule;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
else if (rule->action == ACT_ACTION_DENY) {
|
else if (rule->action == ACT_ACTION_DENY) {
|
||||||
s->last_entity.type = STRM_ENTITY_RULE;
|
s->last_entity.type = STRM_ENTITY_RULE;
|
||||||
s->last_entity.ptr = rule;
|
s->last_entity.ptr = rule;
|
||||||
goto deny;
|
goto deny;
|
||||||
}
|
}
|
||||||
else if (rule->action == ACT_TCP_CLOSE) {
|
else if (rule->action == ACT_TCP_CLOSE) {
|
||||||
s->scb->flags |= SC_FL_NOLINGER | SC_FL_NOHALF;
|
s->scb->flags |= SC_FL_NOLINGER | SC_FL_NOHALF;
|
||||||
sc_must_kill_conn(s->scb);
|
sc_must_kill_conn(s->scb);
|
||||||
sc_abort(s->scb);
|
sc_abort(s->scb);
|
||||||
sc_shutdown(s->scb);
|
sc_shutdown(s->scb);
|
||||||
s->last_entity.type = STRM_ENTITY_RULE;
|
s->last_entity.type = STRM_ENTITY_RULE;
|
||||||
s->last_entity.ptr = rule;
|
s->last_entity.ptr = rule;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -498,7 +499,6 @@ int tcp_exec_l4_rules(struct session *sess)
|
|||||||
struct act_rule *rule;
|
struct act_rule *rule;
|
||||||
struct connection *conn = objt_conn(sess->origin);
|
struct connection *conn = objt_conn(sess->origin);
|
||||||
int result = 1;
|
int result = 1;
|
||||||
enum acl_test_res ret;
|
|
||||||
|
|
||||||
if (!conn)
|
if (!conn)
|
||||||
return result;
|
return result;
|
||||||
@ -508,71 +508,64 @@ int tcp_exec_l4_rules(struct session *sess)
|
|||||||
|
|
||||||
restart:
|
restart:
|
||||||
list_for_each_entry(rule, &px->tcp_req.l4_rules, list) {
|
list_for_each_entry(rule, &px->tcp_req.l4_rules, list) {
|
||||||
ret = ACL_TEST_PASS;
|
|
||||||
|
|
||||||
if (rule->cond) {
|
if (!acl_match_cond(rule->cond, sess->fe, sess, NULL, SMP_OPT_DIR_REQ|SMP_OPT_FINAL))
|
||||||
ret = acl_exec_cond(rule->cond, sess->fe, sess, NULL, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
|
continue;
|
||||||
ret = acl_pass(ret);
|
|
||||||
if (rule->cond->pol == ACL_COND_UNLESS)
|
/* Always call the action function if defined */
|
||||||
ret = !ret;
|
if (rule->action_ptr) {
|
||||||
|
switch (rule->action_ptr(rule, sess->fe, sess, NULL, ACT_OPT_FINAL | ACT_OPT_FIRST)) {
|
||||||
|
case ACT_RET_YIELD:
|
||||||
|
/* yield is not allowed at this point. If this return code is
|
||||||
|
* used it is a bug, so I prefer to abort the process.
|
||||||
|
*/
|
||||||
|
send_log(sess->fe, LOG_WARNING,
|
||||||
|
"Internal error: yield not allowed with tcp-request connection actions.");
|
||||||
|
/* fall through */
|
||||||
|
case ACT_RET_STOP:
|
||||||
|
case ACT_RET_DONE:
|
||||||
|
goto end;
|
||||||
|
case ACT_RET_CONT:
|
||||||
|
break;
|
||||||
|
case ACT_RET_DENY:
|
||||||
|
case ACT_RET_ABRT:
|
||||||
|
case ACT_RET_ERR:
|
||||||
|
case ACT_RET_INV:
|
||||||
|
result = 0;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
continue; /* eval the next rule */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret) {
|
/* If not action function defined, check for known actions */
|
||||||
/* Always call the action function if defined */
|
if (rule->action == ACT_ACTION_ALLOW) {
|
||||||
if (rule->action_ptr) {
|
goto end;
|
||||||
switch (rule->action_ptr(rule, sess->fe, sess, NULL, ACT_OPT_FINAL | ACT_OPT_FIRST)) {
|
}
|
||||||
case ACT_RET_YIELD:
|
else if (rule->action == ACT_ACTION_DENY) {
|
||||||
/* yield is not allowed at this point. If this return code is
|
_HA_ATOMIC_INC(&sess->fe->fe_counters.denied_conn);
|
||||||
* used it is a bug, so I prefer to abort the process.
|
if (sess->listener && sess->listener->counters)
|
||||||
*/
|
_HA_ATOMIC_INC(&sess->listener->counters->denied_conn);
|
||||||
send_log(sess->fe, LOG_WARNING,
|
|
||||||
"Internal error: yield not allowed with tcp-request connection actions.");
|
result = 0;
|
||||||
/* fall through */
|
goto end;
|
||||||
case ACT_RET_STOP:
|
}
|
||||||
case ACT_RET_DONE:
|
else if (rule->action == ACT_TCP_EXPECT_PX) {
|
||||||
goto end;
|
if (!(conn->flags & CO_FL_HANDSHAKE)) {
|
||||||
case ACT_RET_CONT:
|
if (xprt_add_hs(conn) < 0) {
|
||||||
break;
|
result = 0;
|
||||||
case ACT_RET_DENY:
|
goto end;
|
||||||
case ACT_RET_ABRT:
|
|
||||||
case ACT_RET_ERR:
|
|
||||||
case ACT_RET_INV:
|
|
||||||
result = 0;
|
|
||||||
goto end;
|
|
||||||
}
|
}
|
||||||
continue; /* eval the next rule */
|
|
||||||
}
|
}
|
||||||
|
conn->flags |= CO_FL_ACCEPT_PROXY;
|
||||||
/* If not action function defined, check for known actions */
|
}
|
||||||
if (rule->action == ACT_ACTION_ALLOW) {
|
else if (rule->action == ACT_TCP_EXPECT_CIP) {
|
||||||
goto end;
|
if (!(conn->flags & CO_FL_HANDSHAKE)) {
|
||||||
}
|
if (xprt_add_hs(conn) < 0) {
|
||||||
else if (rule->action == ACT_ACTION_DENY) {
|
|
||||||
_HA_ATOMIC_INC(&sess->fe->fe_counters.denied_conn);
|
|
||||||
if (sess->listener && sess->listener->counters)
|
|
||||||
_HA_ATOMIC_INC(&sess->listener->counters->denied_conn);
|
|
||||||
|
|
||||||
result = 0;
|
result = 0;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
|
||||||
else if (rule->action == ACT_TCP_EXPECT_PX) {
|
|
||||||
if (!(conn->flags & CO_FL_HANDSHAKE)) {
|
|
||||||
if (xprt_add_hs(conn) < 0) {
|
|
||||||
result = 0;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
conn->flags |= CO_FL_ACCEPT_PROXY;
|
|
||||||
}
|
|
||||||
else if (rule->action == ACT_TCP_EXPECT_CIP) {
|
|
||||||
if (!(conn->flags & CO_FL_HANDSHAKE)) {
|
|
||||||
if (xprt_add_hs(conn) < 0) {
|
|
||||||
result = 0;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
conn->flags |= CO_FL_ACCEPT_CIP;
|
|
||||||
}
|
}
|
||||||
|
conn->flags |= CO_FL_ACCEPT_CIP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -596,60 +589,51 @@ int tcp_exec_l5_rules(struct session *sess)
|
|||||||
struct proxy *px = sess->fe;
|
struct proxy *px = sess->fe;
|
||||||
struct act_rule *rule;
|
struct act_rule *rule;
|
||||||
int result = 1;
|
int result = 1;
|
||||||
enum acl_test_res ret;
|
|
||||||
|
|
||||||
if (sess->fe->defpx && (sess->fe->mode == PR_MODE_TCP || sess->fe->mode == PR_MODE_HTTP))
|
if (sess->fe->defpx && (sess->fe->mode == PR_MODE_TCP || sess->fe->mode == PR_MODE_HTTP))
|
||||||
px = sess->fe->defpx;
|
px = sess->fe->defpx;
|
||||||
|
|
||||||
restart:
|
restart:
|
||||||
list_for_each_entry(rule, &px->tcp_req.l5_rules, list) {
|
list_for_each_entry(rule, &px->tcp_req.l5_rules, list) {
|
||||||
ret = ACL_TEST_PASS;
|
if (!acl_match_cond(rule->cond, sess->fe, sess, NULL, SMP_OPT_DIR_REQ|SMP_OPT_FINAL))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (rule->cond) {
|
/* Always call the action function if defined */
|
||||||
ret = acl_exec_cond(rule->cond, sess->fe, sess, NULL, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
|
if (rule->action_ptr) {
|
||||||
ret = acl_pass(ret);
|
switch (rule->action_ptr(rule, sess->fe, sess, NULL, ACT_OPT_FINAL | ACT_OPT_FIRST)) {
|
||||||
if (rule->cond->pol == ACL_COND_UNLESS)
|
case ACT_RET_YIELD:
|
||||||
ret = !ret;
|
/* yield is not allowed at this point. If this return code is
|
||||||
|
* used it is a bug, so I prefer to abort the process.
|
||||||
|
*/
|
||||||
|
send_log(sess->fe, LOG_WARNING,
|
||||||
|
"Internal error: yield not allowed with tcp-request session actions.");
|
||||||
|
/* fall through */
|
||||||
|
case ACT_RET_STOP:
|
||||||
|
case ACT_RET_DONE:
|
||||||
|
goto end;
|
||||||
|
case ACT_RET_CONT:
|
||||||
|
break;
|
||||||
|
case ACT_RET_DENY:
|
||||||
|
case ACT_RET_ABRT:
|
||||||
|
case ACT_RET_ERR:
|
||||||
|
case ACT_RET_INV:
|
||||||
|
result = 0;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
continue; /* eval the next rule */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret) {
|
/* If not action function defined, check for known actions */
|
||||||
/* Always call the action function if defined */
|
if (rule->action == ACT_ACTION_ALLOW) {
|
||||||
if (rule->action_ptr) {
|
goto end;
|
||||||
switch (rule->action_ptr(rule, sess->fe, sess, NULL, ACT_OPT_FINAL | ACT_OPT_FIRST)) {
|
}
|
||||||
case ACT_RET_YIELD:
|
else if (rule->action == ACT_ACTION_DENY) {
|
||||||
/* yield is not allowed at this point. If this return code is
|
_HA_ATOMIC_INC(&sess->fe->fe_counters.denied_sess);
|
||||||
* used it is a bug, so I prefer to abort the process.
|
if (sess->listener && sess->listener->counters)
|
||||||
*/
|
_HA_ATOMIC_INC(&sess->listener->counters->denied_sess);
|
||||||
send_log(sess->fe, LOG_WARNING,
|
|
||||||
"Internal error: yield not allowed with tcp-request session actions.");
|
|
||||||
/* fall through */
|
|
||||||
case ACT_RET_STOP:
|
|
||||||
case ACT_RET_DONE:
|
|
||||||
goto end;
|
|
||||||
case ACT_RET_CONT:
|
|
||||||
break;
|
|
||||||
case ACT_RET_DENY:
|
|
||||||
case ACT_RET_ABRT:
|
|
||||||
case ACT_RET_ERR:
|
|
||||||
case ACT_RET_INV:
|
|
||||||
result = 0;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
continue; /* eval the next rule */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If not action function defined, check for known actions */
|
result = 0;
|
||||||
if (rule->action == ACT_ACTION_ALLOW) {
|
goto end;
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
else if (rule->action == ACT_ACTION_DENY) {
|
|
||||||
_HA_ATOMIC_INC(&sess->fe->fe_counters.denied_sess);
|
|
||||||
if (sess->listener && sess->listener->counters)
|
|
||||||
_HA_ATOMIC_INC(&sess->listener->counters->denied_sess);
|
|
||||||
|
|
||||||
result = 0;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user