]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: tcp-rules: Make tcp-request capture a custom action
authorChristopher Faulet <cfaulet@haproxy.com>
Thu, 19 Dec 2019 16:27:03 +0000 (17:27 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Mon, 20 Jan 2020 14:18:45 +0000 (15:18 +0100)
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
include/types/action.h
src/action.c
src/cfgparse.c
src/tcp_rules.c

index b7339f4e8b0100ebde3b1e7b6a97beed5500ac52..eb660dd5da478061f7ba4d8c0453d2fa340950ab 100644 (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 */
index 1077ec967c9db1383510725674f5ce0ae8860580..63dcfcf94dfb13a030c83fae614382ca066aaed3 100644 (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
index 544d3e46806e00ea10974e36b1f66031ec92494a..dad7472139d0e24033eb768b8ad975914c8ccdf1 100644 (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;
index 3ff8a8d3534a4a9d00ef3b5d87270a42fcf87478..3d72af9ad490abe14e66641c011f86a9978a7fac 100644 (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);
 
index fbd876857309c06713a70cf2b26ce1c6c0e0b503..4f90ced048a52d7b380c4b48242eecf3cbef1436 100644 (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;