From d73b96d48cb8ed45e4f32c735d28f5f7a2818900 Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Thu, 19 Dec 2019 17:27:03 +0100 Subject: [PATCH] MINOR: tcp-rules: Make tcp-request capture a custom action Now, this action is use its own dedicated function and is no longer handled "in place" during the TCP rules evaluation. Thus the action name ACT_TCP_CAPTURE is removed. The action type is set to ACT_CUSTOM and a check function is used to know if the rule depends on request contents while there is no inspect-delay. --- include/proto/action.h | 8 +++++ include/types/action.h | 1 - src/action.c | 20 ++++++++++++ src/cfgparse.c | 20 ------------ src/tcp_rules.c | 72 ++++++++++++++++++++++++++---------------- 5 files changed, 72 insertions(+), 49 deletions(-) diff --git a/include/proto/action.h b/include/proto/action.h index b7339f4e8..eb660dd5d 100644 --- a/include/proto/action.h +++ b/include/proto/action.h @@ -80,4 +80,12 @@ static inline void action_build_list(struct list *keywords, */ int check_trk_action(struct act_rule *rule, struct proxy *px, char **err); +/* check a capture rule. This function should be called during the configuration + * validity check. + * + * The function returns 1 in success case, otherwise, it returns 0 and err is + * filled. + */ +int check_capture(struct act_rule *rule, struct proxy *px, char **err); + #endif /* _PROTO_ACTION_H */ diff --git a/include/types/action.h b/include/types/action.h index 1077ec967..63dcfcf94 100644 --- a/include/types/action.h +++ b/include/types/action.h @@ -93,7 +93,6 @@ enum act_name { ACT_TCP_EXPECT_PX, ACT_TCP_EXPECT_CIP, ACT_TCP_CLOSE, /* close at the sender's */ - ACT_TCP_CAPTURE, /* capture a fetched sample */ }; /* NOTE: if <.action_ptr> is defined, the referenced function will always be diff --git a/src/action.c b/src/action.c index 544d3e468..dad747213 100644 --- a/src/action.c +++ b/src/action.c @@ -81,6 +81,26 @@ int check_trk_action(struct act_rule *rule, struct proxy *px, char **err) return 1; } +/* check a capture rule. This function should be called during the configuration + * validity check. + * + * The function returns 1 in success case, otherwise, it returns 0 and err is + * filled. + */ +int check_capture(struct act_rule *rule, struct proxy *px, char **err) +{ + if (rule->from == ACT_F_TCP_REQ_CNT && (px->cap & PR_CAP_FE) && !px->tcp_req.inspect_delay && + !(rule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC)) { + ha_warning("config : %s '%s' : a 'tcp-request capture' rule explicitly depending on request" + " contents without any 'tcp-request inspect-delay' setting." + " This means that this rule will randomly find its contents. This can be fixed by" + " setting the tcp-request inspect-delay.\n", + proxy_type_str(px), px->id); + } + + return 1; +} + int act_resolution_cb(struct dns_requester *requester, struct dns_nameserver *nameserver) { struct stream *stream; diff --git a/src/cfgparse.c b/src/cfgparse.c index 3ff8a8d35..3d72af9ad 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -3481,26 +3481,6 @@ out_uri_auth_compat: newsrv = newsrv->next; } - /* check if we have a frontend with "tcp-request content" looking at L7 - * with no inspect-delay - */ - if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) { - list_for_each_entry(arule, &curproxy->tcp_req.inspect_rules, list) { - if (arule->action == ACT_TCP_CAPTURE && - !(arule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC)) - break; - } - - if (&arule->list != &curproxy->tcp_req.inspect_rules) { - ha_warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request" - " contents were found in a frontend without any 'tcp-request inspect-delay' setting." - " This means that these rules will randomly find their contents. This can be fixed by" - " setting the tcp-request inspect-delay.\n", - proxy_type_str(curproxy), curproxy->id); - err_code |= ERR_WARN; - } - } - /* Check filter configuration, if any */ cfgerr += flt_check(curproxy); diff --git a/src/tcp_rules.c b/src/tcp_rules.c index fbd876857..4f90ced04 100644 --- a/src/tcp_rules.c +++ b/src/tcp_rules.c @@ -185,33 +185,6 @@ resume_execution: else if (rule->action == ACT_ACTION_DENY) { goto deny; } - else if (rule->action == ACT_TCP_CAPTURE) { - struct sample *key; - struct cap_hdr *h = rule->arg.cap.hdr; - char **cap = s->req_cap; - int len; - - key = sample_fetch_as_type(s->be, sess, s, SMP_OPT_DIR_REQ | partial, rule->arg.cap.expr, SMP_T_STR); - if (!key) - continue; - - if (key->flags & SMP_F_MAY_CHANGE) - goto missing_data; - - if (cap[h->index] == NULL) - cap[h->index] = pool_alloc(h->pool); - - if (cap[h->index] == NULL) /* no more capture memory */ - continue; - - len = key->data.u.str.data; - if (len > h->len) - len = h->len; - - memcpy(cap[h->index], key->data.u.str.area, - len); - cap[h->index][len] = 0; - } } } @@ -688,6 +661,47 @@ static enum act_return tcp_action_track_sc(struct act_rule *rule, struct proxy * return ACT_RET_CONT; } +/* This function executes a capture actions. It executes a fetch expression, + * turns the result into a string and puts it in a capture slot. On success, it + * returns ACT_RET_CONT. If it must yield, it return ACT_RET_YIELD. Otherwsize + * ACT_RET_ERR is returned. + */ +static enum act_return tcp_action_capture(struct act_rule *rule, struct proxy *px, + struct session *sess, struct stream *s, int flags) +{ + struct sample *key; + struct cap_hdr *h = rule->arg.cap.hdr; + char **cap = s->req_cap; + int len, opt; + + opt = ((rule->from == ACT_F_TCP_REQ_CNT) ? SMP_OPT_DIR_REQ : SMP_OPT_DIR_RES); + if (flags & ACT_FLAG_FINAL) + opt |= SMP_OPT_FINAL; + + key = sample_fetch_as_type(s->be, sess, s, opt, rule->arg.cap.expr, SMP_T_STR); + if (!key) + goto end; + + if ((key->flags & SMP_F_MAY_CHANGE) && !(flags & ACT_FLAG_FINAL)) + return ACT_RET_YIELD; /* key might appear later */ + + if (cap[h->index] == NULL) { + cap[h->index] = pool_alloc(h->pool); + if (cap[h->index] == NULL) /* no more capture memory, ignore error */ + goto end; + } + + len = key->data.u.str.data; + if (len > h->len) + len = h->len; + + memcpy(cap[h->index], key->data.u.str.area, len); + cap[h->index][len] = 0; + + end: + return ACT_RET_CONT; +} + /* Parse a tcp-request rule. Return a negative value in case of failure */ static int tcp_parse_request_rule(char **args, int arg, int section_type, struct proxy *curpx, struct proxy *defpx, @@ -794,7 +808,9 @@ static int tcp_parse_request_rule(char **args, int arg, int section_type, rule->arg.cap.expr = expr; rule->arg.cap.hdr = hdr; - rule->action = ACT_TCP_CAPTURE; + rule->action = ACT_CUSTOM; + rule->action_ptr = tcp_action_capture; + rule->check_ptr = check_capture; } else if (strncmp(args[arg], "track-sc", 8) == 0) { struct sample_expr *expr;