From: Aurelien DARRAGON Date: Wed, 22 Jan 2025 13:15:47 +0000 (+0100) Subject: CLEANUP: tree-wide: define and use acl_match_cond() helper X-Git-Tag: v3.2-dev5~94 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e768a531b753ce4b49f8a05eed26b4a5d2a30e63;p=thirdparty%2Fhaproxy.git 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. --- diff --git a/include/haproxy/acl.h b/include/haproxy/acl.h index b63b4fe84..af48dba38 100644 --- a/include/haproxy/acl.h +++ b/include/haproxy/acl.h @@ -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); + +/* 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 + * 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 * 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). diff --git a/src/fcgi-app.c b/src/fcgi-app.c index 98077b959..ab5284c50 100644 --- a/src/fcgi-app.c +++ b/src/fcgi-app.c @@ -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 htx *htx; struct http_hdr_ctx ctx; - int ret; htx = htxbuf(&msg->chn->buf); @@ -368,16 +367,8 @@ static int fcgi_flt_http_headers(struct stream *s, struct filter *filter, struct goto end; list_for_each_entry(rule, &fcgi_conf->param_rules, list) { - if (rule->cond) { - ret = acl_exec_cond(rule->cond, s->be, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL); - ret = acl_pass(ret); - if (rule->cond->pol == ACL_COND_UNLESS) - ret = !ret; - - /* the rule does not match */ - if (!ret) - continue; - } + if (!acl_match_cond(rule->cond, s->be, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL)) + continue; param_rule = NULL; 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) { - if (rule->cond) { - ret = acl_exec_cond(rule->cond, s->be, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL); - ret = acl_pass(ret); - if (rule->cond->pol == ACL_COND_UNLESS) - ret = !ret; - - /* the rule does not match */ - if (!ret) - continue; - } + if (!acl_match_cond(rule->cond, s->be, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL)) + continue; hdr_rule = NULL; node = ebis_lookup_len(&hdr_rules, rule->name.ptr, rule->name.len); diff --git a/src/flt_spoe.c b/src/flt_spoe.c index 49ff89665..60c820c79 100644 --- a/src/flt_spoe.c +++ b/src/flt_spoe.c @@ -592,16 +592,8 @@ static int spoe_encode_message(struct stream *s, struct spoe_context *ctx, struct spoe_arg *arg; int ret; - if (msg->cond) { - ret = acl_exec_cond(msg->cond, s->be, s->sess, s, dir|SMP_OPT_FINAL); - ret = acl_pass(ret); - if (msg->cond->pol == ACL_COND_UNLESS) - ret = !ret; - - /* the rule does not match */ - if (!ret) - goto next; - } + if (!acl_match_cond(msg->cond, s->be, s->sess, s, dir|SMP_OPT_FINAL)) + goto next; /* Check if there is enough space for the message name and the * number of arguments. It implies id_len> is encoded on 2 diff --git a/src/http_ana.c b/src/http_ana.c index 144bb073e..41c5effd6 100644 --- a/src/http_ana.c +++ b/src/http_ana.c @@ -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 */ 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); - - ret = acl_pass(ret); - if (cond->pol == ACL_COND_UNLESS) - ret = !ret; - - if (ret) { - /* 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; - } + if (!acl_match_cond(cond, sess->fe, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL)) + continue; + + /* 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 */ @@ -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 */ list_for_each_entry(rule, &px->redirect_rules, list) { - if (rule->cond) { - int ret; - - 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 (!acl_match_cond(rule->cond, px, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL)) + continue; if (!http_apply_redirect_rule(rule, s, txn)) { 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) { /* check optional condition */ - if (rule->cond) { - int ret; - - 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; - } + if (!acl_match_cond(rule->cond, px, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL)) + continue; act_opts |= ACT_OPT_FIRST; 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) { /* check optional condition */ - if (rule->cond) { - int ret; - - 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; - } + if (!acl_match_cond(rule->cond, px, sess, s, SMP_OPT_DIR_RES|SMP_OPT_FINAL)) + continue; act_opts |= ACT_OPT_FIRST; 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 */ list_for_each_entry(stats_admin_rule, &uri_auth->admin_rules, list) { - int ret = 1; - - if (stats_admin_rule->cond) { - ret = acl_exec_cond(stats_admin_rule->cond, s->be, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL); - ret = acl_pass(ret); - if (stats_admin_rule->cond->pol == ACL_COND_UNLESS) - ret = !ret; - } + if (!acl_match_cond(stats_admin_rule->cond, s->be, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL)) + continue; - if (ret) { - /* no rule, or the rule matches */ - ctx->flags |= STAT_F_ADMIN; - break; - } + /* no rule, or the rule matches */ + ctx->flags |= STAT_F_ADMIN; + break; } if (txn->meth == HTTP_METH_GET || txn->meth == HTTP_METH_HEAD) diff --git a/src/quic_rules.c b/src/quic_rules.c index 4a9ad3d27..050548a8e 100644 --- a/src/quic_rules.c +++ b/src/quic_rules.c @@ -18,7 +18,6 @@ int quic_init_exec_rules(struct listener *li, struct quic_dgram *dgram) { static THREAD_LOCAL struct session rule_sess; struct act_rule *rule; - enum acl_test_res ret; struct proxy *px; 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; list_for_each_entry(rule, &px->quic_init_rules, list) { - ret = ACL_TEST_PASS; - - if (rule->cond) { - ret = acl_exec_cond(rule->cond, px, &rule_sess, NULL, SMP_OPT_DIR_REQ|SMP_OPT_FINAL); - ret = acl_pass(ret); - if (rule->cond->pol == ACL_COND_UNLESS) - ret = !ret; - } - - 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) { + if (!acl_match_cond(rule->cond, px, &rule_sess, NULL, SMP_OPT_DIR_REQ|SMP_OPT_FINAL)) + continue; + + 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; - } - else if (rule->action == ACT_ACTION_DENY) { + 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; + } + else if (rule->action == ACT_ACTION_DENY) { + result = 0; + goto end; + } } end: diff --git a/src/stream.c b/src/stream.c index 9ffdf07d9..41a2ffcb9 100644 --- a/src/stream.c +++ b/src/stream.c @@ -1072,45 +1072,38 @@ static int process_switching_rules(struct stream *s, struct channel *req, int an struct switching_rule *rule; list_for_each_entry(rule, &fe->switching_rules, list) { - int ret = 1; + struct proxy *backend = NULL; - if (rule->cond) { - ret = acl_exec_cond(rule->cond, fe, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL); - 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 we can't resolve the name, or if any error occurs, break - * the loop and fallback to the default backend. - */ - struct proxy *backend = NULL; + if (!acl_match_cond(rule->cond, fe, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL)) + continue; - if (rule->dynamic) { - struct buffer *tmp; + /* If the backend name is dynamic, try to resolve the name. + * If we can't resolve the name, or if any error occurs, break + * the loop and fallback to the default backend. + */ - tmp = alloc_trash_chunk(); - if (!tmp) - goto sw_failed; + if (rule->dynamic) { + struct buffer *tmp; - if (build_logline(s, tmp->area, tmp->size, &rule->be.expr)) - backend = proxy_be_by_name(tmp->area); + tmp = alloc_trash_chunk(); + if (!tmp) + goto sw_failed; - free_trash_chunk(tmp); - tmp = NULL; + if (build_logline(s, tmp->area, tmp->size, &rule->be.expr)) + backend = proxy_be_by_name(tmp->area); - if (!backend) - break; - } - else - backend = rule->be.backend; + free_trash_chunk(tmp); + tmp = NULL; - if (!stream_set_backend(s, backend)) - goto sw_failed; - break; + 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 @@ -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. */ list_for_each_entry(prst_rule, &s->be->persist_rules, list) { - int ret = 1; - - if (prst_rule->cond) { - ret = acl_exec_cond(prst_rule->cond, s->be, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL); - ret = acl_pass(ret); - if (prst_rule->cond->pol == ACL_COND_UNLESS) - ret = !ret; - } + if (!acl_match_cond(prst_rule->cond, s->be, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL)) + continue; - 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; + /* 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; } 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)) { list_for_each_entry(rule, &px->server_rules, list) { - int ret; - - ret = acl_exec_cond(rule->cond, s->be, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL); - ret = acl_pass(ret); - if (rule->cond->pol == ACL_COND_UNLESS) - ret = !ret; - - if (ret) { - struct server *srv; + struct server *srv; - if (rule->dynamic) { - struct buffer *tmp = get_trash_chunk(); + if (!acl_match_cond(rule->cond, s->be, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL)) + continue; - if (!build_logline(s, tmp->area, tmp->size, &rule->expr)) - break; + if (rule->dynamic) { + struct buffer *tmp = get_trash_chunk(); - srv = findserver(s->be, tmp->area); - if (!srv) - break; - } - else - srv = rule->srv.ptr; + if (!build_logline(s, tmp->area, tmp->size, &rule->expr)) + break; - 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; + srv = findserver(s->be, tmp->area); + if (!srv) 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); list_for_each_entry(rule, &px->sticking_rules, list) { - int ret = 1 ; + struct stktable_key *key; int i; /* 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; } - if (rule->cond) { - 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 (!acl_match_cond(rule->cond, px, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL)) + continue; - if (ret) { - 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; - 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; - if (rule->flags & STK_IS_MATCH) { + 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 (s->store_count < (sizeof(s->store) / sizeof(s->store[0]))) { 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 (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; - } + 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); 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 * 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) continue; - if (rule->cond) { - 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 (!acl_match_cond(rule->cond, px, sess, s, SMP_OPT_DIR_RES|SMP_OPT_FINAL)) + continue; - if (ret) { - struct stktable_key *key; + key = stktable_fetch_key(rule->table.t, px, sess, s, SMP_OPT_DIR_RES|SMP_OPT_FINAL, rule->expr, NULL); + if (!key) + continue; - key = stktable_fetch_key(rule->table.t, px, sess, s, SMP_OPT_DIR_RES|SMP_OPT_FINAL, rule->expr, NULL); - if (!key) - continue; + if (s->store_count < (sizeof(s->store) / sizeof(s->store[0]))) { + struct stksess *ts; - 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; - } + 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; } } } diff --git a/src/tcp_rules.c b/src/tcp_rules.c index fcc47b3d1..9d450cfa9 100644 --- a/src/tcp_rules.c +++ b/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); if (rule->cond->pol == ACL_COND_UNLESS) ret = !ret; + + if (!ret) + continue; } - if (ret) { - act_opts |= ACT_OPT_FIRST; + act_opts |= ACT_OPT_FIRST; resume_execution: - /* Always call the action function if defined */ - if (rule->action_ptr) { - switch (rule->action_ptr(rule, s->be, s->sess, s, act_opts)) { - case ACT_RET_CONT: - break; - case ACT_RET_STOP: - case ACT_RET_DONE: - s->last_entity.type = STRM_ENTITY_RULE; - s->last_entity.ptr = rule; - goto end; - case ACT_RET_YIELD: - s->current_rule = rule; - if (act_opts & ACT_OPT_FINAL) { - send_log(s->be, LOG_WARNING, - "Internal error: yield not allowed if the inspect-delay expired " - "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: + /* Always call the action function if defined */ + if (rule->action_ptr) { + switch (rule->action_ptr(rule, s->be, s->sess, s, act_opts)) { + case ACT_RET_CONT: + break; + case ACT_RET_STOP: + case ACT_RET_DONE: + s->last_entity.type = STRM_ENTITY_RULE; + s->last_entity.ptr = rule; + goto end; + case ACT_RET_YIELD: + s->current_rule = rule; + if (act_opts & ACT_OPT_FINAL) { + send_log(s->be, LOG_WARNING, + "Internal error: yield not allowed if the inspect-delay expired " + "for the tcp-request content actions."); 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 */ + } + 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.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 (rule->action == ACT_ACTION_ALLOW) { - s->last_entity.type = STRM_ENTITY_RULE; - s->last_entity.ptr = rule; - goto end; - } - else if (rule->action == ACT_ACTION_DENY) { - s->last_entity.type = STRM_ENTITY_RULE; - s->last_entity.ptr = rule; - goto deny; - } + /* If not action function defined, check for known actions */ + if (rule->action == ACT_ACTION_ALLOW) { + s->last_entity.type = STRM_ENTITY_RULE; + s->last_entity.ptr = rule; + goto end; + } + else if (rule->action == ACT_ACTION_DENY) { + s->last_entity.type = STRM_ENTITY_RULE; + s->last_entity.ptr = rule; + goto deny; } } @@ -348,76 +349,76 @@ int tcp_inspect_response(struct stream *s, struct channel *rep, int an_bit) ret = acl_pass(ret); if (rule->cond->pol == ACL_COND_UNLESS) ret = !ret; + if (!ret) + continue; } - if (ret) { - act_opts |= ACT_OPT_FIRST; + act_opts |= ACT_OPT_FIRST; resume_execution: - /* Always call the action function if defined */ - if (rule->action_ptr) { - switch (rule->action_ptr(rule, s->be, s->sess, s, act_opts)) { - case ACT_RET_CONT: - break; - case ACT_RET_STOP: - case ACT_RET_DONE: - s->last_entity.type = STRM_ENTITY_RULE; - s->last_entity.ptr = rule; - goto end; - case ACT_RET_YIELD: - s->current_rule = rule; - if (act_opts & ACT_OPT_FINAL) { - send_log(s->be, LOG_WARNING, - "Internal error: yield not allowed if the inspect-delay expired " - "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: + /* Always call the action function if defined */ + if (rule->action_ptr) { + switch (rule->action_ptr(rule, s->be, s->sess, s, act_opts)) { + case ACT_RET_CONT: + break; + case ACT_RET_STOP: + case ACT_RET_DONE: + s->last_entity.type = STRM_ENTITY_RULE; + s->last_entity.ptr = rule; + goto end; + case ACT_RET_YIELD: + s->current_rule = rule; + if (act_opts & ACT_OPT_FINAL) { + send_log(s->be, LOG_WARNING, + "Internal error: yield not allowed if the inspect-delay expired " + "for the tcp-response content actions."); 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 */ + } + 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.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 (rule->action == ACT_ACTION_ALLOW) { - s->last_entity.type = STRM_ENTITY_RULE; - s->last_entity.ptr = rule; - goto end; - } - else if (rule->action == ACT_ACTION_DENY) { - s->last_entity.type = STRM_ENTITY_RULE; - s->last_entity.ptr = rule; - goto deny; - } - else if (rule->action == ACT_TCP_CLOSE) { - s->scb->flags |= SC_FL_NOLINGER | SC_FL_NOHALF; - sc_must_kill_conn(s->scb); - sc_abort(s->scb); - sc_shutdown(s->scb); - s->last_entity.type = STRM_ENTITY_RULE; - s->last_entity.ptr = rule; - goto end; - } + /* If not action function defined, check for known actions */ + if (rule->action == ACT_ACTION_ALLOW) { + s->last_entity.type = STRM_ENTITY_RULE; + s->last_entity.ptr = rule; + goto end; + } + else if (rule->action == ACT_ACTION_DENY) { + s->last_entity.type = STRM_ENTITY_RULE; + s->last_entity.ptr = rule; + goto deny; + } + else if (rule->action == ACT_TCP_CLOSE) { + s->scb->flags |= SC_FL_NOLINGER | SC_FL_NOHALF; + sc_must_kill_conn(s->scb); + sc_abort(s->scb); + sc_shutdown(s->scb); + s->last_entity.type = STRM_ENTITY_RULE; + s->last_entity.ptr = rule; + goto end; } } @@ -498,7 +499,6 @@ int tcp_exec_l4_rules(struct session *sess) struct act_rule *rule; struct connection *conn = objt_conn(sess->origin); int result = 1; - enum acl_test_res ret; if (!conn) return result; @@ -508,71 +508,64 @@ int tcp_exec_l4_rules(struct session *sess) restart: list_for_each_entry(rule, &px->tcp_req.l4_rules, list) { - ret = ACL_TEST_PASS; - if (rule->cond) { - ret = acl_exec_cond(rule->cond, sess->fe, sess, NULL, SMP_OPT_DIR_REQ|SMP_OPT_FINAL); - ret = acl_pass(ret); - if (rule->cond->pol == ACL_COND_UNLESS) - ret = !ret; - } - - if (ret) { - /* Always call the action function if defined */ - 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 (!acl_match_cond(rule->cond, sess->fe, sess, NULL, SMP_OPT_DIR_REQ|SMP_OPT_FINAL)) + continue; + + /* Always call the action function if defined */ + 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 not action function defined, check for known actions */ - if (rule->action == ACT_ACTION_ALLOW) { - goto end; - } - 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); + /* If not action function defined, check for known actions */ + if (rule->action == ACT_ACTION_ALLOW) { + goto end; + } + 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; - 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; - } + result = 0; + 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_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 act_rule *rule; int result = 1; - enum acl_test_res ret; if (sess->fe->defpx && (sess->fe->mode == PR_MODE_TCP || sess->fe->mode == PR_MODE_HTTP)) px = sess->fe->defpx; restart: list_for_each_entry(rule, &px->tcp_req.l5_rules, list) { - ret = ACL_TEST_PASS; - - if (rule->cond) { - ret = acl_exec_cond(rule->cond, sess->fe, sess, NULL, SMP_OPT_DIR_REQ|SMP_OPT_FINAL); - ret = acl_pass(ret); - if (rule->cond->pol == ACL_COND_UNLESS) - ret = !ret; - } - - if (ret) { - /* Always call the action function if defined */ - 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 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 (!acl_match_cond(rule->cond, sess->fe, sess, NULL, SMP_OPT_DIR_REQ|SMP_OPT_FINAL)) + continue; + + /* Always call the action function if defined */ + 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 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 */ - if (rule->action == ACT_ACTION_ALLOW) { - 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); + /* If not action function defined, check for known actions */ + if (rule->action == ACT_ACTION_ALLOW) { + 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; - } + result = 0; + goto end; } }