From: Christopher Faulet Date: Wed, 18 Dec 2019 13:58:12 +0000 (+0100) Subject: MINOR: actions: Add flags to configure the action behaviour X-Git-Tag: v2.2-dev1~44 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=245cf795c12af77f29f3c6420cbb4dadd3bbd9e2;p=thirdparty%2Fhaproxy.git MINOR: actions: Add flags to configure the action behaviour Some flags can now be set on an action when it is registered. The flags are defined in the act_flag enum. For now, only ACT_FLAG_FINAL may be set on an action to specify if it stops the rules evaluation. It is set on ACT_ACTION_ALLOW, ACT_ACTION_DENY, ACT_HTTP_REQ_TARPIT, ACT_HTTP_REQ_AUTH, ACT_HTTP_REDIR and ACT_TCP_CLOSE actions. But, when required, it may also be set on custom actions. Consequently, this flag is checked instead of the action type during the configuration parsing to trigger a warning when a rule inhibits all the following ones. --- diff --git a/include/types/action.h b/include/types/action.h index d13a54903f..1a7e9a641d 100644 --- a/include/types/action.h +++ b/include/types/action.h @@ -59,6 +59,12 @@ enum act_opt { ACT_OPT_FIRST = 0x00000002, /* first call for this action */ }; +/* Flags used to describe the action. */ +enum act_flag { + ACT_FLAG_FINAL = 1 << 0, /* the action stops the rules evaluation when executed */ +}; + + /* known actions to be used without any action function pointer. This enum is * typically used in a switch case, iff .action_ptr is undefined. So if an * action function is defined for one of following action types, the function @@ -110,6 +116,7 @@ struct act_rule { struct list list; struct acl_cond *cond; /* acl condition to meet */ enum act_name action; /* ACT_ACTION_* */ + unsigned int flags; /* ACT_FLAG_* */ enum act_from from; /* ACT_F_* */ enum act_return (*action_ptr)(struct act_rule *rule, struct proxy *px, /* ptr to custom action */ struct session *sess, struct stream *s, int opts); diff --git a/src/cfgparse-listen.c b/src/cfgparse-listen.c index 9975e46876..0151130cd7 100644 --- a/src/cfgparse-listen.c +++ b/src/cfgparse-listen.c @@ -1333,10 +1333,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) if (!LIST_ISEMPTY(&curproxy->http_req_rules) && !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond && - (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW || - LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY || - LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR || - LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) { + (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->flags & ACT_FLAG_FINAL)) { ha_warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n", file, linenum, args[0]); err_code |= ERR_WARN; @@ -1367,8 +1364,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) if (!LIST_ISEMPTY(&curproxy->http_res_rules) && !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond && - (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW || - LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) { + (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->flags & ACT_FLAG_FINAL)) { ha_warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n", file, linenum, args[0]); err_code |= ERR_WARN; diff --git a/src/http_act.c b/src/http_act.c index 994e3b47c0..564e5ba66e 100644 --- a/src/http_act.c +++ b/src/http_act.c @@ -748,6 +748,7 @@ static enum act_parse_ret parse_http_allow(const char **args, int *orig_arg, str struct act_rule *rule, char **err) { rule->action = ACT_ACTION_ALLOW; + rule->flags |= ACT_FLAG_FINAL; return ACT_RET_PRS_OK; } @@ -769,6 +770,7 @@ static enum act_parse_ret parse_http_req_deny(const char **args, int *orig_arg, rule->action = ACT_ACTION_DENY; rule->arg.http.i = HTTP_ERR_403; } + rule->flags |= ACT_FLAG_FINAL; if (strcmp(args[cur_arg], "deny_status") == 0) { cur_arg++; @@ -801,6 +803,7 @@ static enum act_parse_ret parse_http_res_deny(const char **args, int *orig_arg, struct act_rule *rule, char **err) { rule->action = ACT_ACTION_DENY; + rule->flags |= ACT_FLAG_FINAL; return ACT_RET_PRS_OK; } @@ -813,6 +816,7 @@ static enum act_parse_ret parse_http_auth(const char **args, int *orig_arg, stru int cur_arg; rule->action = ACT_HTTP_REQ_AUTH; + rule->flags |= ACT_FLAG_FINAL; cur_arg = *orig_arg; if (!strcmp(args[cur_arg], "realm")) { @@ -1071,6 +1075,7 @@ static enum act_parse_ret parse_http_redirect(const char **args, int *orig_arg, int dir, cur_arg; rule->action = ACT_HTTP_REDIR; + rule->flags |= ACT_FLAG_FINAL; cur_arg = *orig_arg; diff --git a/src/tcp_rules.c b/src/tcp_rules.c index ebf4e05c72..fae2e152bc 100644 --- a/src/tcp_rules.c +++ b/src/tcp_rules.c @@ -660,14 +660,17 @@ static int tcp_parse_response_rule(char **args, int arg, int section_type, if (strcmp(args[arg], "accept") == 0) { arg++; rule->action = ACT_ACTION_ALLOW; + rule->flags |= ACT_FLAG_FINAL; } else if (strcmp(args[arg], "reject") == 0) { arg++; rule->action = ACT_ACTION_DENY; + rule->flags |= ACT_FLAG_FINAL; } else if (strcmp(args[arg], "close") == 0) { arg++; rule->action = ACT_TCP_CLOSE; + rule->flags |= ACT_FLAG_FINAL; } else { struct action_kw *kw; @@ -721,10 +724,12 @@ static int tcp_parse_request_rule(char **args, int arg, int section_type, if (!strcmp(args[arg], "accept")) { arg++; rule->action = ACT_ACTION_ALLOW; + rule->flags |= ACT_FLAG_FINAL; } else if (!strcmp(args[arg], "reject")) { arg++; rule->action = ACT_ACTION_DENY; + rule->flags |= ACT_FLAG_FINAL; } else if (strcmp(args[arg], "capture") == 0) { struct sample_expr *expr;