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.
This commit is contained in:
Christopher Faulet 2019-12-19 17:27:03 +01:00
parent ac98d81f46
commit d73b96d48c
5 changed files with 72 additions and 49 deletions

View File

@ -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 */

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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;