*/
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>
* 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).
struct eb_root hdr_rules = EB_ROOT;
struct htx *htx;
struct http_hdr_ctx ctx;
- int ret;
htx = htxbuf(&msg->chn->buf);
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);
}
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);
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 <msg->id_len> is encoded on 2
/* 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 */
/* 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;
}
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:
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:
/* 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)
{
static THREAD_LOCAL struct session rule_sess;
struct act_rule *rule;
- enum acl_test_res ret;
struct proxy *px;
int result = 1;
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:
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
* 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);
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.
+ */
}
}
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
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;
}
}
}
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
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;
}
}
}
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;
}
}
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;
}
}
struct act_rule *rule;
struct connection *conn = objt_conn(sess->origin);
int result = 1;
- enum acl_test_res ret;
if (!conn)
return result;
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;
}
}
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;
}
}