]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: http-rules: Make set/del-map and add/del-acl custom actions
authorChristopher Faulet <cfaulet@haproxy.com>
Tue, 17 Dec 2019 14:45:23 +0000 (15:45 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Mon, 20 Jan 2020 14:18:45 +0000 (15:18 +0100)
Now, these actions use their own dedicated function and are no longer handled
"in place" during the HTTP rules evaluation. Thus the action names
ACT_HTTP_*_ACL and ACT_HTTP_*_MAP are removed. The action type is now mapped as
following: 0 = add-acl, 1 = set-map, 2 = del-acl and 3 = del-map.

include/types/action.h
src/http_act.c
src/http_ana.c

index 16d669d3b1593da191f7b3309650a157cceb106a..6d77f9cd2e818ddb8acbf00a6482da92566a55f9 100644 (file)
@@ -84,10 +84,6 @@ enum act_name {
        ACT_HTTP_SET_LOGL,
        ACT_HTTP_SET_TOS,
        ACT_HTTP_SET_MARK,
-       ACT_HTTP_ADD_ACL,
-       ACT_HTTP_DEL_ACL,
-       ACT_HTTP_DEL_MAP,
-       ACT_HTTP_SET_MAP,
        ACT_HTTP_EARLY_HINT,
 
        /* http request actions. */
index aa8dfff495e4f2927beb023fb62fd15afaca8059..537b1d04a5a093f1b6c814984433da32ac14497f 100644 (file)
@@ -37,6 +37,7 @@
 #include <proto/http_htx.h>
 #include <proto/log.h>
 #include <proto/http_ana.h>
+#include <proto/pattern.h>
 #include <proto/stream_interface.h>
 
 
@@ -1212,25 +1213,118 @@ static enum act_parse_ret parse_http_redirect(const char **args, int *orig_arg,
        return ACT_RET_PRS_OK;
 }
 
+/* This function executes a add-acl, del-acl, set-map or del-map actions. On
+ * success, it returns ACT_RET_CONT. Otherwsize ACT_RET_ERR is returned.
+ */
+static enum act_return http_action_set_map(struct act_rule *rule, struct proxy *px,
+                                          struct session *sess, struct stream *s, int flags)
+{
+       struct pat_ref *ref;
+       struct buffer *key = NULL, *value = NULL;
+       enum act_return ret = ACT_RET_CONT;
+
+       /* collect reference */
+       ref = pat_ref_lookup(rule->arg.map.ref);
+       if (!ref)
+               goto leave;
+
+       /* allocate key */
+       key = alloc_trash_chunk();
+       if (!key)
+               goto fail_alloc;
+
+       /* collect key */
+       key->data = build_logline(s, key->area, key->size, &rule->arg.map.key);
+       key->area[key->data] = '\0';
+
+       switch (rule->action) {
+       case 0: // add-acl
+               /* add entry only if it does not already exist */
+               HA_SPIN_LOCK(PATREF_LOCK, &ref->lock);
+               if (pat_ref_find_elt(ref, key->area) == NULL)
+                       pat_ref_add(ref, key->area, NULL, NULL);
+               HA_SPIN_UNLOCK(PATREF_LOCK, &ref->lock);
+               break;
+
+       case 1: // set-map
+               /* allocate value */
+               value = alloc_trash_chunk();
+               if (!value)
+                       goto fail_alloc;
+
+               /* collect value */
+               value->data = build_logline(s, value->area, value->size, &rule->arg.map.value);
+               value->area[value->data] = '\0';
+
+               HA_SPIN_LOCK(PATREF_LOCK, &ref->lock);
+               if (pat_ref_find_elt(ref, key->area) != NULL) {
+                       /* update entry if it exists */
+                       pat_ref_set(ref, key->area, value->area, NULL);
+               }
+               else {
+                       /* insert a new entry */
+                       pat_ref_add(ref, key->area, value->area, NULL);
+               }
+               HA_SPIN_UNLOCK(PATREF_LOCK, &ref->lock);
+               break;
+
+       case 2: // del-acl
+       case 3: // del-map
+               /* returned code: 1=ok, 0=ko */
+               HA_SPIN_LOCK(PATREF_LOCK, &ref->lock);
+               pat_ref_delete(ref, key->area);
+               HA_SPIN_UNLOCK(PATREF_LOCK, &ref->lock);
+               break;
+
+       default:
+               ret = ACT_RET_ERR;
+       }
+
+
+  leave:
+       free_trash_chunk(key);
+       free_trash_chunk(value);
+       return ret;
+
+  fail_alloc:
+       if (!(s->flags & SF_ERR_MASK))
+               s->flags |= SF_ERR_RESOURCE;
+       ret = ACT_RET_ERR;
+       goto leave;
+}
+
 /* Parse a "add-acl", "del-acl", "set-map" or "del-map" actions. It takes one or
- * two log-format string as argument depending on the action. It returns
- * ACT_RET_PRS_OK on success, ACT_RET_PRS_ERR on error.
+ * two log-format string as argument depending on the action. The action is
+ * stored in <.action> as an int (0=add-acl, 1=set-map, 2=del-acl,
+ * 3=del-map). It returns ACT_RET_PRS_OK on success, ACT_RET_PRS_ERR on error.
  */
 static enum act_parse_ret parse_http_set_map(const char **args, int *orig_arg, struct proxy *px,
                                             struct act_rule *rule, char **err)
 {
        int cap, cur_arg;
 
-       rule->action = (args[*orig_arg-1][0] == 'a' ? ACT_HTTP_ADD_ACL :
-                       (args[*orig_arg-1][0] == 's' ? ACT_HTTP_SET_MAP :
-                        (args[*orig_arg-1][4] == 'a' ? ACT_HTTP_DEL_ACL : ACT_HTTP_DEL_MAP)));
+       if (args[*orig_arg-1][0] == 'a') // add-acl
+               rule->action = 0;
+       else if (args[*orig_arg-1][0] == 's') // set-map
+               rule->action = 1;
+       else if (args[*orig_arg-1][4] == 'a') // del-acl
+               rule->action = 2;
+       else if (args[*orig_arg-1][4] == 'm') // del-map
+               rule->action = 3;
+       else {
+               memprintf(err, "internal error: unhandled action '%s'", args[0]);
+               return ACT_RET_PRS_ERR;
+       }
+       rule->action_ptr = http_action_set_map;
 
        cur_arg = *orig_arg;
-       if (rule->action == ACT_HTTP_SET_MAP && (!*args[cur_arg] || !*args[cur_arg+1])) {
+       if (rule->action == 1 && (!*args[cur_arg] || !*args[cur_arg+1])) {
+               /* 2 args for set-map */
                memprintf(err, "expects exactly 2 arguments");
                return ACT_RET_PRS_ERR;
        }
        else if (!*args[cur_arg]) {
+               /* only one arg for other actions */
                memprintf(err, "expects exactly 1 arguments");
                return ACT_RET_PRS_ERR;
        }
@@ -1255,7 +1349,7 @@ static enum act_parse_ret parse_http_set_map(const char **args, int *orig_arg, s
        if (!parse_logformat_string(args[cur_arg], px, &rule->arg.map.key, LOG_OPT_HTTP, cap, err))
                return ACT_RET_PRS_ERR;
 
-       if (rule->action == ACT_HTTP_SET_MAP) {
+       if (rule->action == 1) {
                /* value pattern for set-map only */
                cur_arg++;
                LIST_INIT(&rule->arg.map.value);
index dc9f06e69c74af52d63abd434b7fc1ffecb0ccd7..1002dab4a7739501befcf0c0d4a05a0ec2e960dc 100644 (file)
@@ -26,7 +26,6 @@
 #include <proto/filters.h>
 #include <proto/http_htx.h>
 #include <proto/log.h>
-#include <proto/pattern.h>
 #include <proto/http_ana.h>
 #include <proto/proxy.h>
 #include <proto/server.h>
@@ -3038,122 +3037,6 @@ static enum rule_result http_req_get_intercept_rule(struct proxy *px, struct lis
                                        http_remove_header(htx, &ctx);
                                break;
 
-                       case ACT_HTTP_DEL_ACL:
-                       case ACT_HTTP_DEL_MAP: {
-                               struct pat_ref *ref;
-                               struct buffer *key;
-
-                               /* collect reference */
-                               ref = pat_ref_lookup(rule->arg.map.ref);
-                               if (!ref)
-                                       continue;
-
-                               /* allocate key */
-                               key = alloc_trash_chunk();
-                               if (!key) {
-                                       if (!(s->flags & SF_ERR_MASK))
-                                               s->flags |= SF_ERR_RESOURCE;
-                                       rule_ret = HTTP_RULE_RES_ERROR;
-                                       goto end;
-                               }
-
-                               /* collect key */
-                               key->data = build_logline(s, key->area, key->size, &rule->arg.map.key);
-                               key->area[key->data] = '\0';
-
-                               /* perform update */
-                               /* returned code: 1=ok, 0=ko */
-                               HA_SPIN_LOCK(PATREF_LOCK, &ref->lock);
-                               pat_ref_delete(ref, key->area);
-                               HA_SPIN_UNLOCK(PATREF_LOCK, &ref->lock);
-
-                               free_trash_chunk(key);
-                               break;
-                       }
-
-                       case ACT_HTTP_ADD_ACL: {
-                               struct pat_ref *ref;
-                               struct buffer *key;
-
-                               /* collect reference */
-                               ref = pat_ref_lookup(rule->arg.map.ref);
-                               if (!ref)
-                                       continue;
-
-                               /* allocate key */
-                               key = alloc_trash_chunk();
-                               if (!key) {
-                                       if (!(s->flags & SF_ERR_MASK))
-                                               s->flags |= SF_ERR_RESOURCE;
-                                       rule_ret = HTTP_RULE_RES_ERROR;
-                                       goto end;
-                               }
-
-                               /* collect key */
-                               key->data = build_logline(s, key->area, key->size, &rule->arg.map.key);
-                               key->area[key->data] = '\0';
-
-                               /* perform update */
-                               /* add entry only if it does not already exist */
-                               HA_SPIN_LOCK(PATREF_LOCK, &ref->lock);
-                               if (pat_ref_find_elt(ref, key->area) == NULL)
-                                       pat_ref_add(ref, key->area, NULL, NULL);
-                               HA_SPIN_UNLOCK(PATREF_LOCK, &ref->lock);
-
-                               free_trash_chunk(key);
-                               break;
-                       }
-
-                       case ACT_HTTP_SET_MAP: {
-                               struct pat_ref *ref;
-                               struct buffer *key, *value;
-
-                               /* collect reference */
-                               ref = pat_ref_lookup(rule->arg.map.ref);
-                               if (!ref)
-                                       continue;
-
-                               /* allocate key */
-                               key = alloc_trash_chunk();
-                               if (!key) {
-                                       if (!(s->flags & SF_ERR_MASK))
-                                               s->flags |= SF_ERR_RESOURCE;
-                                       rule_ret = HTTP_RULE_RES_ERROR;
-                                       goto end;
-                               }
-
-                               /* allocate value */
-                               value = alloc_trash_chunk();
-                               if (!value) {
-                                       free_trash_chunk(key);
-                                       if (!(s->flags & SF_ERR_MASK))
-                                               s->flags |= SF_ERR_RESOURCE;
-                                       rule_ret = HTTP_RULE_RES_ERROR;
-                                       goto end;
-                               }
-
-                               /* collect key */
-                               key->data = build_logline(s, key->area, key->size, &rule->arg.map.key);
-                               key->area[key->data] = '\0';
-
-                               /* collect value */
-                               value->data = build_logline(s, value->area, value->size, &rule->arg.map.value);
-                               value->area[value->data] = '\0';
-
-                               /* perform update */
-                               HA_SPIN_LOCK(PATREF_LOCK, &ref->lock);
-                               if (pat_ref_find_elt(ref, key->area) != NULL)
-                                       /* update entry if it exists */
-                                       pat_ref_set(ref, key->area, value->area, NULL);
-                               else
-                                       /* insert a new entry */
-                                       pat_ref_add(ref, key->area, value->area, NULL);
-                               HA_SPIN_UNLOCK(PATREF_LOCK, &ref->lock);
-                               free_trash_chunk(key);
-                               free_trash_chunk(value);
-                               break;
-                       }
-
                        case ACT_HTTP_EARLY_HINT:
                                if (!(txn->req.flags & HTTP_MSGF_VER_11))
                                        break;
@@ -3354,121 +3237,6 @@ resume_execution:
                                        http_remove_header(htx, &ctx);
                                break;
 
-                       case ACT_HTTP_DEL_ACL:
-                       case ACT_HTTP_DEL_MAP: {
-                               struct pat_ref *ref;
-                               struct buffer *key;
-
-                               /* collect reference */
-                               ref = pat_ref_lookup(rule->arg.map.ref);
-                               if (!ref)
-                                       continue;
-
-                       /* allocate key */
-                               key = alloc_trash_chunk();
-                               if (!key) {
-                                       if (!(s->flags & SF_ERR_MASK))
-                                               s->flags |= SF_ERR_RESOURCE;
-                                       rule_ret = HTTP_RULE_RES_ERROR;
-                                       goto end;
-                               }
-
-                               /* collect key */
-                               key->data = build_logline(s, key->area, key->size, &rule->arg.map.key);
-                               key->area[key->data] = '\0';
-
-                               /* perform update */
-                               /* returned code: 1=ok, 0=ko */
-                               HA_SPIN_LOCK(PATREF_LOCK, &ref->lock);
-                               pat_ref_delete(ref, key->area);
-                               HA_SPIN_UNLOCK(PATREF_LOCK, &ref->lock);
-
-                               free_trash_chunk(key);
-                               break;
-                       }
-
-                       case ACT_HTTP_ADD_ACL: {
-                               struct pat_ref *ref;
-                               struct buffer *key;
-
-                               /* collect reference */
-                               ref = pat_ref_lookup(rule->arg.map.ref);
-                               if (!ref)
-                                       continue;
-
-                               /* allocate key */
-                               key = alloc_trash_chunk();
-                               if (!key) {
-                                       if (!(s->flags & SF_ERR_MASK))
-                                               s->flags |= SF_ERR_RESOURCE;
-                                       rule_ret = HTTP_RULE_RES_ERROR;
-                                       goto end;
-                               }
-
-                               /* collect key */
-                               key->data = build_logline(s, key->area, key->size, &rule->arg.map.key);
-                               key->area[key->data] = '\0';
-
-                               /* perform update */
-                               /* check if the entry already exists */
-                               HA_SPIN_LOCK(PATREF_LOCK, &ref->lock);
-                               if (pat_ref_find_elt(ref, key->area) == NULL)
-                                       pat_ref_add(ref, key->area, NULL, NULL);
-                               HA_SPIN_UNLOCK(PATREF_LOCK, &ref->lock);
-                               free_trash_chunk(key);
-                               break;
-                       }
-
-                       case ACT_HTTP_SET_MAP: {
-                               struct pat_ref *ref;
-                               struct buffer *key, *value;
-
-                               /* collect reference */
-                               ref = pat_ref_lookup(rule->arg.map.ref);
-                               if (!ref)
-                                       continue;
-
-                               /* allocate key */
-                               key = alloc_trash_chunk();
-                               if (!key) {
-                                       if (!(s->flags & SF_ERR_MASK))
-                                               s->flags |= SF_ERR_RESOURCE;
-                                       rule_ret = HTTP_RULE_RES_ERROR;
-                                       goto end;
-                               }
-
-                               /* allocate value */
-                               value = alloc_trash_chunk();
-                               if (!value) {
-                                       free_trash_chunk(key);
-                                       if (!(s->flags & SF_ERR_MASK))
-                                               s->flags |= SF_ERR_RESOURCE;
-                                       rule_ret = HTTP_RULE_RES_ERROR;
-                                       goto end;
-                               }
-
-                               /* collect key */
-                               key->data = build_logline(s, key->area, key->size, &rule->arg.map.key);
-                               key->area[key->data] = '\0';
-
-                               /* collect value */
-                               value->data = build_logline(s, value->area, value->size, &rule->arg.map.value);
-                               value->area[value->data] = '\0';
-
-                               /* perform update */
-                               HA_SPIN_LOCK(PATREF_LOCK, &ref->lock);
-                               if (pat_ref_find_elt(ref, key->area) != NULL)
-                                       /* update entry if it exists */
-                                       pat_ref_set(ref, key->area, value->area, NULL);
-                               else
-                                       /* insert a new entry */
-                                       pat_ref_add(ref, key->area, value->area, NULL);
-                               HA_SPIN_UNLOCK(PATREF_LOCK, &ref->lock);
-                               free_trash_chunk(key);
-                               free_trash_chunk(value);
-                               break;
-                       }
-
                        case ACT_HTTP_REDIR:
                                rule_ret = HTTP_RULE_RES_DONE;
                                if (!http_apply_redirect_rule(rule->arg.redir, s, txn))