]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MAJOR: acl: make use of the new argument parsing framework
authorWilly Tarreau <w@1wt.eu>
Thu, 19 Apr 2012 15:16:54 +0000 (17:16 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 8 May 2012 18:57:11 +0000 (20:57 +0200)
The ACL parser now uses the argument parser to build a typed argument list.
Right now arguments are all strings and only one argument is supported since
this is what ACLs currently support.

include/types/acl.h
src/acl.c
src/backend.c
src/frontend.c
src/proto_http.c
src/proto_tcp.c
src/session.c

index 35a22a0d443d51391d5a8c6888336413b374e8d2..14e4f844f73e0cce72e43dfe3319773bda3e0428 100644 (file)
@@ -2,7 +2,7 @@
  * include/types/acl.h
  * This file provides structures and types for ACLs.
  *
- * Copyright (C) 2000-2010 Willy Tarreau - w@1wt.eu
+ * Copyright (C) 2000-2012 Willy Tarreau - w@1wt.eu
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -26,6 +26,7 @@
 #include <common/config.h>
 #include <common/mini-clist.h>
 
+#include <types/arg.h>
 #include <types/auth.h>
 #include <types/proxy.h>
 #include <types/server.h>
@@ -302,12 +303,7 @@ struct acl_kw_list {
 struct acl_expr {
        struct list list;           /* chaining */
        struct acl_keyword *kw;     /* back-reference to the keyword */
-       union {                     /* optional argument of the subject (eg: header or cookie name) */
-               char *str;
-               struct userlist *ul;
-               struct server *srv; /* must be initialised by acl_find_targets */
-       } arg;
-       int arg_len;                /* optional argument length */
+       struct arg *args;           /* optional argument list (eg: header or cookie name) */
        struct list patterns;       /* list of acl_patterns */
        struct eb_root pattern_tree;  /* may be used for lookup in large datasets */
 };
index 507516f31e433490e2b5b06019d6c27297824b27..84de6acef455e030e133f9026e328b2bd6e81ed4 100644 (file)
--- a/src/acl.c
+++ b/src/acl.c
@@ -22,6 +22,7 @@
 #include <types/global.h>
 
 #include <proto/acl.h>
+#include <proto/arg.h>
 #include <proto/auth.h>
 #include <proto/buffers.h>
 #include <proto/log.h>
@@ -446,6 +447,8 @@ acl_fetch_ssl_hello_sni(struct proxy *px, struct session *l4, void *l7, int dir,
 
 /* Fetch the RDP cookie identified in the expression.
  * Note: this decoder only works with non-wrapping data.
+ * Accepts either 0 or 1 argument. Argument is a string (cookie name), other
+ * types will lead to undefined behaviour.
  */
 int
 acl_fetch_rdp_cookie(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -480,17 +483,17 @@ acl_fetch_rdp_cookie(struct proxy *px, struct session *l4, void *l7, int dir,
                bleft--;
        }
 
-       if (expr->arg_len) {
+       if (expr->args) {
 
-               if (bleft <= expr->arg_len)
+               if (bleft <= expr->args->data.str.len)
                        goto too_short;
 
-               if ((data[expr->arg_len] != '=') ||
-                   strncasecmp(expr->arg.str, (const char *)data, expr->arg_len) != 0)
+               if ((data[expr->args->data.str.len] != '=') ||
+                   strncasecmp(expr->args->data.str.str, (const char *)data, expr->args->data.str.len) != 0)
                        goto not_cookie;
 
-               data += expr->arg_len + 1;
-               bleft -= expr->arg_len + 1;
+               data += expr->args->data.str.len + 1;
+               bleft -= expr->args->data.str.len + 1;
        } else {
                while (bleft > 0 && *data != '=') {
                        if (*data == '\r' || *data == '\n')
@@ -1241,11 +1244,25 @@ static void free_pattern_tree(struct eb_root *root)
 
 static struct acl_expr *prune_acl_expr(struct acl_expr *expr)
 {
+       struct arg *arg;
+
        free_pattern_list(&expr->patterns);
        free_pattern_tree(&expr->pattern_tree);
        LIST_INIT(&expr->patterns);
-       if (expr->arg_len && expr->arg.str)
-               free(expr->arg.str);
+
+       for (arg = expr->args; arg; arg++) {
+               if (arg->type == ARGT_STOP)
+                       break;
+               if (arg->type == ARGT_FE || arg->type == ARGT_BE ||
+                   arg->type == ARGT_TAB || arg->type == ARGT_SRV ||
+                   arg->type == ARGT_USR || arg->type == ARGT_STR) {
+                       free(arg->data.str.str);
+                       arg->data.str.str = NULL;
+               }
+               arg++;
+       }
+
+       free(expr->args);
        expr->kw->use_cnt--;
        return expr;
 }
@@ -1355,22 +1372,26 @@ struct acl_expr *parse_acl_expr(const char **args)
        aclkw->use_cnt++;
        LIST_INIT(&expr->patterns);
        expr->pattern_tree = EB_ROOT_UNIQUE;
-       expr->arg.str = NULL;
-       expr->arg_len = 0;
 
        arg = strchr(args[0], '(');
        if (arg != NULL) {
-               char *end, *arg2;
-               /* there is an argument in the form "subject(arg)" */
+               char *end;
+               int nbargs;
+
+               /* there is an argument in the form "subject(arg[,arg]*)" */
                arg++;
                end = strchr(arg, ')');
                if (!end)
                        goto out_free_expr;
-               arg2 = my_strndup(arg, end - arg);
-               if (!arg2)
+
+               /* Parse the arguments. Note that currently we have no way to
+                * report parsing errors, hence the NULL in the error pointers.
+                * At the moment only one string arg is supported.
+                */
+               nbargs = make_arg_list(arg, end - arg, ARG1(STR), &expr->args,
+                                      NULL, NULL, NULL);
+               if (nbargs < 0)
                        goto out_free_expr;
-               expr->arg_len = end - arg;
-               expr->arg.str = arg2;
        }
 
        args++;
@@ -1935,14 +1956,17 @@ acl_find_targets(struct proxy *p)
                                struct server *srv;
                                char *pname, *sname;
 
-                               if (!expr->arg.str || !*expr->arg.str) {
+                               /* FIXME: at the moment we check argument types from the keyword,
+                                * but later we'll simlpy inspect argument types.
+                                */
+                               if (!expr->args || !expr->args->data.str.len) {
                                        Alert("proxy %s: acl %s %s(): missing server name.\n",
                                                p->id, acl->name, expr->kw->kw);
                                        cfgerr++;
                                        continue;
                                }
 
-                               pname = expr->arg.str;
+                               pname = expr->args->data.str.str;
                                sname = strrchr(pname, '/');
 
                                if (sname)
@@ -1971,15 +1995,17 @@ acl_find_targets(struct proxy *p)
                                        continue;
                                }
 
-                               free(expr->arg.str);
-                               expr->arg_len = 0;
-                               expr->arg.srv = srv;
+                               free(expr->args->data.str.str);
+                               expr->args->data.srv = srv;
                                continue;
                        }
 
                        if (strstr(expr->kw->kw, "http_auth") == expr->kw->kw) {
 
-                               if (!expr->arg.str || !*expr->arg.str) {
+                               /* FIXME: at the moment we check argument types from the keyword,
+                                * but later we'll simlpy inspect argument types.
+                                */
+                               if (!expr->args || !expr->args->data.str.len) {
                                        Alert("proxy %s: acl %s %s(): missing userlist name.\n",
                                                p->id, acl->name, expr->kw->kw);
                                        cfgerr++;
@@ -1987,20 +2013,20 @@ acl_find_targets(struct proxy *p)
                                }
 
                                if (p->uri_auth && p->uri_auth->userlist &&
-                                   !strcmp(p->uri_auth->userlist->name, expr->arg.str))
+                                   !strcmp(p->uri_auth->userlist->name, expr->args->data.str.str))
                                        ul = p->uri_auth->userlist;
                                else
-                                       ul = auth_find_userlist(expr->arg.str);
+                                       ul = auth_find_userlist(expr->args->data.str.str);
 
                                if (!ul) {
                                        Alert("proxy %s: acl %s %s(%s): unable to find userlist.\n",
-                                               p->id, acl->name, expr->kw->kw, expr->arg.str);
+                                               p->id, acl->name, expr->kw->kw, expr->args->data.str.str);
                                        cfgerr++;
                                        continue;
                                }
 
-                               expr->arg_len = 0;
-                               expr->arg.ul  = ul;
+                               free(expr->args->data.str.str);
+                               expr->args->data.usr = ul;
                        }
 
 
@@ -2014,7 +2040,7 @@ acl_find_targets(struct proxy *p)
                                }
 
                                list_for_each_entry(pattern, &expr->patterns, list) {
-                                       pattern->val.group_mask = auth_resolve_groups(expr->arg.ul, pattern->ptr.str);
+                                       pattern->val.group_mask = auth_resolve_groups(expr->args->data.usr, pattern->ptr.str);
 
                                        free(pattern->ptr.str);
                                        pattern->ptr.str = NULL;
index b4fa21d8105a4ba6ee6ce29ececba69dc07e3bee..74bee8395322ee1f569a7b365ff307506ff03aca 100644 (file)
@@ -28,6 +28,7 @@
 #include <types/global.h>
 
 #include <proto/acl.h>
+#include <proto/arg.h>
 #include <proto/backend.h>
 #include <proto/frontend.h>
 #include <proto/lb_chash.h>
@@ -393,6 +394,7 @@ struct server *get_server_hh(struct session *s)
                return map_get_server_hash(px, hash);
 }
 
+/* RDP Cookie HASH.  */
 struct server *get_server_rch(struct session *s)
 {
        unsigned long    hash = 0;
@@ -402,6 +404,7 @@ struct server *get_server_rch(struct session *s)
        int              ret;
        struct acl_expr  expr;
        struct acl_test  test;
+       struct arg       args[2];
 
        /* tot_weight appears to mean srv_count */
        if (px->lbprm.tot_weight == 0)
@@ -410,8 +413,12 @@ struct server *get_server_rch(struct session *s)
        memset(&expr, 0, sizeof(expr));
        memset(&test, 0, sizeof(test));
 
-       expr.arg.str = px->hh_name;
-       expr.arg_len = px->hh_len;
+       args[0].type = ARGT_STR;
+       args[0].data.str.str = px->hh_name;
+       args[0].data.str.len = px->hh_len;
+       args[1].type = ARGT_STOP;
+
+       expr.args = args;
 
        ret = acl_fetch_rdp_cookie(px, s, NULL, ACL_DIR_REQ, &expr, &test);
        len = temp_pattern.data.str.len;
@@ -1111,6 +1118,7 @@ int tcp_persist_rdp_cookie(struct session *s, struct buffer *req, int an_bit)
        struct server *srv = px->srv;
        struct sockaddr_in addr;
        char *p;
+       struct arg       args[2];
 
        DPRINTF(stderr,"[%u] %s: session=%p b=%p, exp(r,w)=%u,%u bf=%08x bh=%d analysers=%02x\n",
                now_ms, __FUNCTION__,
@@ -1127,8 +1135,12 @@ int tcp_persist_rdp_cookie(struct session *s, struct buffer *req, int an_bit)
        memset(&expr, 0, sizeof(expr));
        memset(&test, 0, sizeof(test));
 
-       expr.arg.str = s->be->rdp_cookie_name;
-       expr.arg_len = s->be->rdp_cookie_len;
+       args[0].type = ARGT_STR;
+       args[0].data.str.str = s->be->rdp_cookie_name;
+       args[0].data.str.len = s->be->rdp_cookie_len;
+       args[1].type = ARGT_STOP;
+
+       expr.args = args;
 
        ret = acl_fetch_rdp_cookie(px, s, NULL, ACL_DIR_REQ, &expr, &test);
        if (ret == 0 || (test.flags & ACL_TEST_F_MAY_CHANGE) || temp_pattern.data.str.len == 0)
@@ -1365,16 +1377,19 @@ int backend_parse_balance(const char **args, char *err, int errlen, struct proxy
 /*             All supported keywords must be declared here.            */
 /************************************************************************/
 
-/* set temp integer to the number of enabled servers on the proxy */
+/* set temp integer to the number of enabled servers on the proxy.
+ * Accepts either 0 or 1 argument. Argument is a string, other types will lead to
+ * undefined behaviour.
+ */
 static int
 acl_fetch_nbsrv(struct proxy *px, struct session *l4, void *l7, int dir,
                 struct acl_expr *expr, struct acl_test *test)
 {
        test->flags = ACL_TEST_F_VOL_TEST;
-       if (expr->arg_len) {
+       if (expr->args) {
                /* another proxy was designated, we must look for it */
                for (px = proxy; px; px = px->next)
-                       if ((px->cap & PR_CAP_BE) && !strcmp(px->id, expr->arg.str))
+                       if ((px->cap & PR_CAP_BE) && !strcmp(px->id, expr->args->data.str.str))
                                break;
        }
        if (!px)
@@ -1392,12 +1407,14 @@ acl_fetch_nbsrv(struct proxy *px, struct session *l4, void *l7, int dir,
 
 /* report in test->flags a success or failure depending on the designated
  * server's state. There is no match function involved since there's no pattern.
+ * Accepts exactly 1 argument. Argument is a server, other types will lead to
+ * undefined behaviour.
  */
 static int
 acl_fetch_srv_is_up(struct proxy *px, struct session *l4, void *l7, int dir,
                    struct acl_expr *expr, struct acl_test *test)
 {
-       struct server *srv = expr->arg.srv;
+       struct server *srv = expr->args->data.srv;
 
        test->flags = ACL_TEST_F_VOL_TEST;
        if (!(srv->state & SRV_MAINTAIN) &&
@@ -1408,17 +1425,20 @@ acl_fetch_srv_is_up(struct proxy *px, struct session *l4, void *l7, int dir,
        return 1;
 }
 
-/* set temp integer to the number of enabled servers on the proxy */
+/* set temp integer to the number of enabled servers on the proxy.
+ * Accepts either 0 or 1 argument. Argument is a string, other types will lead to
+ * undefined behaviour.
+ */
 static int
 acl_fetch_connslots(struct proxy *px, struct session *l4, void *l7, int dir,
                    struct acl_expr *expr, struct acl_test *test)
 {
        struct server *iterator;
        test->flags = ACL_TEST_F_VOL_TEST;
-       if (expr->arg_len) {
+       if (expr->args) {
                /* another proxy was designated, we must look for it */
                for (px = proxy; px; px = px->next)
-                       if ((px->cap & PR_CAP_BE) && !strcmp(px->id, expr->arg.str))
+                       if ((px->cap & PR_CAP_BE) && !strcmp(px->id, expr->args->data.str.str))
                                break;
        }
        if (!px)
@@ -1470,16 +1490,19 @@ acl_fetch_srv_id(struct proxy *px, struct session *l4, void *l7, int dir,
        return 1;
 }
 
-/* set temp integer to the number of connections per second reaching the backend */
+/* set temp integer to the number of connections per second reaching the backend.
+ * Accepts either 0 or 1 argument. Argument is a string, other types will lead to
+ * undefined behaviour.
+ */
 static int
 acl_fetch_be_sess_rate(struct proxy *px, struct session *l4, void *l7, int dir,
                        struct acl_expr *expr, struct acl_test *test)
 {
        test->flags = ACL_TEST_F_VOL_TEST;
-       if (expr->arg_len) {
+       if (expr->args) {
                /* another proxy was designated, we must look for it */
                for (px = proxy; px; px = px->next)
-                       if ((px->cap & PR_CAP_BE) && !strcmp(px->id, expr->arg.str))
+                       if ((px->cap & PR_CAP_BE) && !strcmp(px->id, expr->args->data.str.str))
                                break;
        }
        if (!px)
@@ -1489,16 +1512,19 @@ acl_fetch_be_sess_rate(struct proxy *px, struct session *l4, void *l7, int dir,
        return 1;
 }
 
-/* set temp integer to the number of concurrent connections on the backend */
+/* set temp integer to the number of concurrent connections on the backend.
+ * Accepts either 0 or 1 argument. Argument is a string, other types will lead to
+ * undefined behaviour.
+ */
 static int
 acl_fetch_be_conn(struct proxy *px, struct session *l4, void *l7, int dir,
                  struct acl_expr *expr, struct acl_test *test)
 {
        test->flags = ACL_TEST_F_VOL_TEST;
-       if (expr->arg_len) {
+       if (expr->args) {
                /* another proxy was designated, we must look for it */
                for (px = proxy; px; px = px->next)
-                       if ((px->cap & PR_CAP_BE) && !strcmp(px->id, expr->arg.str))
+                       if ((px->cap & PR_CAP_BE) && !strcmp(px->id, expr->args->data.str.str))
                                break;
        }
        if (!px)
@@ -1508,16 +1534,19 @@ acl_fetch_be_conn(struct proxy *px, struct session *l4, void *l7, int dir,
        return 1;
 }
 
-/* set temp integer to the total number of queued connections on the backend */
+/* set temp integer to the total number of queued connections on the backend.
+ * Accepts either 0 or 1 argument. Argument is a string, other types will lead to
+ * undefined behaviour.
+ */
 static int
 acl_fetch_queue_size(struct proxy *px, struct session *l4, void *l7, int dir,
                   struct acl_expr *expr, struct acl_test *test)
 {
        test->flags = ACL_TEST_F_VOL_TEST;
-       if (expr->arg_len) {
+       if (expr->args) {
                /* another proxy was designated, we must look for it */
                for (px = proxy; px; px = px->next)
-                       if ((px->cap & PR_CAP_BE) && !strcmp(px->id, expr->arg.str))
+                       if ((px->cap & PR_CAP_BE) && !strcmp(px->id, expr->args->data.str.str))
                                break;
        }
        if (!px)
@@ -1532,6 +1561,8 @@ acl_fetch_queue_size(struct proxy *px, struct session *l4, void *l7, int dir,
  * server, we return twice the total, just as if we had half a running server.
  * This is more or less correct anyway, since we expect the last server to come
  * back soon.
+ * Accepts either 0 or 1 argument. Argument is a string, other types will lead to
+ * undefined behaviour.
  */
 static int
 acl_fetch_avg_queue_size(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -1540,10 +1571,10 @@ acl_fetch_avg_queue_size(struct proxy *px, struct session *l4, void *l7, int dir
        int nbsrv;
 
        test->flags = ACL_TEST_F_VOL_TEST;
-       if (expr->arg_len) {
+       if (expr->args) {
                /* another proxy was designated, we must look for it */
                for (px = proxy; px; px = px->next)
-                       if ((px->cap & PR_CAP_BE) && !strcmp(px->id, expr->arg.str))
+                       if ((px->cap & PR_CAP_BE) && !strcmp(px->id, expr->args->data.str.str))
                                break;
        }
        if (!px)
@@ -1564,12 +1595,15 @@ acl_fetch_avg_queue_size(struct proxy *px, struct session *l4, void *l7, int dir
        return 1;
 }
 
-/* set temp integer to the number of concurrent connections on the server in the backend */
+/* set temp integer to the number of concurrent connections on the server in the backend.
+ * Accepts exactly 1 argument. Argument is a server, other types will lead to
+ * undefined behaviour.
+ */
 static int
 acl_fetch_srv_conn(struct proxy *px, struct session *l4, void *l7, int dir,
                  struct acl_expr *expr, struct acl_test *test)
 {
-       struct server *srv = expr->arg.srv;
+       struct server *srv = expr->args->data.srv;
 
        temp_pattern.data.integer = srv->cur_sess;
        return 1;
index c18cc66c5737145c3114ff403e5407c3429fd26e..ac6027c6c005c6dfd2946bf93da0e91166e82f53 100644 (file)
@@ -506,16 +506,19 @@ acl_fetch_fe_id(struct proxy *px, struct session *l4, void *l7, int dir,
        return 1;
 }
 
-/* set temp integer to the number of connections per second reaching the frontend */
+/* set temp integer to the number of connections per second reaching the frontend.
+ * Accepts either 0 or 1 argument. Argument is a string, other types will cause
+ * an undefined behaviour.
+ */
 static int
 acl_fetch_fe_sess_rate(struct proxy *px, struct session *l4, void *l7, int dir,
                        struct acl_expr *expr, struct acl_test *test)
 {
        test->flags = ACL_TEST_F_VOL_TEST;
-       if (expr->arg_len) {
+       if (expr->args) {
                /* another proxy was designated, we must look for it */
                for (px = proxy; px; px = px->next)
-                       if ((px->cap & PR_CAP_FE) && !strcmp(px->id, expr->arg.str))
+                       if ((px->cap & PR_CAP_FE) && !strcmp(px->id, expr->args->data.str.str))
                                break;
        }
        if (!px)
@@ -525,16 +528,19 @@ acl_fetch_fe_sess_rate(struct proxy *px, struct session *l4, void *l7, int dir,
        return 1;
 }
 
-/* set temp integer to the number of concurrent connections on the frontend */
+/* set temp integer to the number of concurrent connections on the frontend
+ * Accepts either 0 or 1 argument. Argument is a string, other types will cause
+ * an undefined behaviour.
+ */
 static int
 acl_fetch_fe_conn(struct proxy *px, struct session *l4, void *l7, int dir,
                  struct acl_expr *expr, struct acl_test *test)
 {
        test->flags = ACL_TEST_F_VOL_TEST;
-       if (expr->arg_len) {
+       if (expr->args) {
                /* another proxy was designated, we must look for it */
                for (px = proxy; px; px = px->next)
-                       if ((px->cap & PR_CAP_FE) && !strcmp(px->id, expr->arg.str))
+                       if ((px->cap & PR_CAP_FE) && !strcmp(px->id, expr->args->data.str.str))
                                break;
        }
        if (!px)
index b8b0af6f17c4e1491982c2e2d4b36396c9dd9f55..7f65be47b6886c5a50de17881d342a6faa12a8e2 100644 (file)
@@ -7836,6 +7836,7 @@ acl_fetch_url_port(struct proxy *px, struct session *l4, void *l7, int dir,
 }
 
 /* 5. Check on HTTP header. A pointer to the beginning of the value is returned.
+ * Accepts exactly 1 argument of type string.
  */
 static int
 acl_fetch_hdr(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -7846,13 +7847,16 @@ acl_fetch_hdr(struct proxy *px, struct session *l4, void *l7, int dir,
        struct hdr_ctx *ctx = (struct hdr_ctx *)test->ctx.a;
        const struct http_msg *msg = ((dir & ACL_DIR_MASK) == ACL_DIR_REQ) ? &txn->req : &txn->rsp;
 
+       if (!expr->args || expr->args->type != ARGT_STR)
+               return 0;
+
        CHECK_HTTP_MESSAGE_FIRST();
 
        if (!(test->flags & ACL_TEST_F_FETCH_MORE))
                /* search for header from the beginning */
                ctx->idx = 0;
 
-       if (http_find_header2(expr->arg.str, expr->arg_len, msg->buf->p + msg->sol, idx, ctx)) {
+       if (http_find_header2(expr->args->data.str.str, expr->args->data.str.len, msg->buf->p + msg->sol, idx, ctx)) {
                test->flags |= ACL_TEST_F_FETCH_MORE;
                test->flags |= ACL_TEST_F_VOL_HDR;
                temp_pattern.data.str.str = (char *)ctx->line + ctx->val;
@@ -7867,6 +7871,7 @@ acl_fetch_hdr(struct proxy *px, struct session *l4, void *l7, int dir,
 }
 
 /* 6. Check on HTTP header count. The number of occurrences is returned.
+ * Accepts exactly 1 argument of type string.
  */
 static int
 acl_fetch_hdr_cnt(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -7878,11 +7883,14 @@ acl_fetch_hdr_cnt(struct proxy *px, struct session *l4, void *l7, int dir,
        const struct http_msg *msg = ((dir & ACL_DIR_MASK) == ACL_DIR_REQ) ? &txn->req : &txn->rsp;
        int cnt;
 
+       if (!expr->args || expr->args->type != ARGT_STR)
+               return 0;
+
        CHECK_HTTP_MESSAGE_FIRST();
 
        ctx.idx = 0;
        cnt = 0;
-       while (http_find_header2(expr->arg.str, expr->arg_len, msg->buf->p + msg->sol, idx, &ctx))
+       while (http_find_header2(expr->args->data.str.str, expr->args->data.str.len, msg->buf->p + msg->sol, idx, &ctx))
                cnt++;
 
        temp_pattern.data.integer = cnt;
@@ -7982,17 +7990,21 @@ acl_fetch_http_first_req(struct proxy *px, struct session *s, void *l7, int dir,
        return 1;
 }
 
+/* Accepts exactly 1 argument of type userlist */
 static int
 acl_fetch_http_auth(struct proxy *px, struct session *l4, void *l7, int dir,
                    struct acl_expr *expr, struct acl_test *test)
 {
 
+       if (!expr->args || expr->args->type != ARGT_USR)
+               return 0;
+
        CHECK_HTTP_MESSAGE_FIRST();
 
        if (!get_http_auth(l4))
                return 0;
 
-       test->ctx.a[0] = expr->arg.ul;
+       test->ctx.a[0] = expr->args->data.usr;
        test->ctx.a[1] = l4->txn.auth.user;
        test->ctx.a[2] = l4->txn.auth.pass;
 
@@ -8100,7 +8112,8 @@ extract_cookie_value(char *hdr, const char *hdr_end,
  * test->ctx.a[0] for the in-header position, test->ctx.a[1] for the
  * end-of-header-value, and test->ctx.a[2] for the hdr_idx. Depending on
  * the direction, multiple cookies may be parsed on the same line or not.
- * The cookie name is in expr->arg and the name length in expr->arg_len.
+ * The cookie name is in expr->arg and the name length in expr->args->data.str.len.
+ * Accepts exactly 1 argument of type string.
  */
 static int
 acl_fetch_cookie_value(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -8114,6 +8127,9 @@ acl_fetch_cookie_value(struct proxy *px, struct session *l4, void *l7, int dir,
        int hdr_name_len;
        char *sol;
 
+       if (!expr->args || expr->args->type != ARGT_STR)
+               return 0;
+
        CHECK_HTTP_MESSAGE_FIRST();
 
        if ((dir & ACL_DIR_MASK) == ACL_DIR_REQ) {
@@ -8141,7 +8157,7 @@ acl_fetch_cookie_value(struct proxy *px, struct session *l4, void *l7, int dir,
                        if (!http_find_header2(hdr_name, hdr_name_len, sol, idx, ctx))
                                goto out;
 
-                       if (ctx->vlen < expr->arg_len + 1)
+                       if (ctx->vlen < expr->args->data.str.len + 1)
                                continue;
 
                        test->ctx.a[0] = ctx->line + ctx->val;
@@ -8149,7 +8165,7 @@ acl_fetch_cookie_value(struct proxy *px, struct session *l4, void *l7, int dir,
                }
 
                test->ctx.a[0] = extract_cookie_value(test->ctx.a[0], test->ctx.a[1],
-                                                     expr->arg.str, expr->arg_len,
+                                                     expr->args->data.str.str, expr->args->data.str.len,
                                                      (dir & ACL_DIR_MASK) == ACL_DIR_REQ,
                                                      &temp_pattern.data.str.str,
                                                      &temp_pattern.data.str.len);
@@ -8168,8 +8184,9 @@ acl_fetch_cookie_value(struct proxy *px, struct session *l4, void *l7, int dir,
 }
 
 /* Iterate over all cookies present in a request to count how many occurrences
- * match the name in expr->arg and expr->arg_len. If <multi> is non-null, then
+ * match the name in expr->arg and expr->args->data.str.len. If <multi> is non-null, then
  * multiple cookies may be parsed on the same line.
+ * Accepts exactly 1 argument of type string.
  */
 static int
 acl_fetch_cookie_cnt(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -8185,6 +8202,9 @@ acl_fetch_cookie_cnt(struct proxy *px, struct session *l4, void *l7, int dir,
        char *val_beg, *val_end;
        char *sol;
 
+       if (!expr->args || expr->args->type != ARGT_STR)
+               return 0;
+
        CHECK_HTTP_MESSAGE_FIRST();
 
        if ((dir & ACL_DIR_MASK) == ACL_DIR_REQ) {
@@ -8208,7 +8228,7 @@ acl_fetch_cookie_cnt(struct proxy *px, struct session *l4, void *l7, int dir,
                        if (!http_find_header2(hdr_name, hdr_name_len, sol, idx, &ctx))
                                break;
 
-                       if (ctx.vlen < expr->arg_len + 1)
+                       if (ctx.vlen < expr->args->data.str.len + 1)
                                continue;
 
                        val_beg = ctx.line + ctx.val;
@@ -8216,7 +8236,7 @@ acl_fetch_cookie_cnt(struct proxy *px, struct session *l4, void *l7, int dir,
                }
 
                while ((val_beg = extract_cookie_value(val_beg, val_end,
-                                                      expr->arg.str, expr->arg_len,
+                                                      expr->args->data.str.str, expr->args->data.str.len,
                                                       (dir & ACL_DIR_MASK) == ACL_DIR_REQ,
                                                       &temp_pattern.data.str.str,
                                                       &temp_pattern.data.str.len))) {
index 17144161bc7a361a61854996ffe2a5541277660c..d53cd52d880443cbe1c2ddcf6b396f4cac2562c5 100644 (file)
@@ -1569,6 +1569,7 @@ pattern_fetch_rdp_cookie(struct proxy *px, struct session *l4, void *l7, int dir
        int ret;
        struct acl_expr  expr;
        struct acl_test  test;
+       struct arg       args[2];
 
        if (!l4)
                return 0;
@@ -1576,8 +1577,12 @@ pattern_fetch_rdp_cookie(struct proxy *px, struct session *l4, void *l7, int dir
        memset(&expr, 0, sizeof(expr));
        memset(&test, 0, sizeof(test));
 
-       expr.arg.str = arg_p[0].data.str.str;
-       expr.arg_len = arg_p[0].data.str.len;
+       args[0].type = ARGT_STR;
+       args[0].data.str.str = arg_p[0].data.str.str;
+       args[0].data.str.len = arg_p[0].data.str.len;
+       args[1].type = ARGT_STOP;
+
+       expr.args = args;
 
        ret = acl_fetch_rdp_cookie(px, l4, NULL, ACL_DIR_REQ, &expr, &test);
        if (ret == 0 || (test.flags & ACL_TEST_F_MAY_CHANGE) || temp_pattern.data.str.len == 0)
index e930dafd1aa3a524a35d7219c8f59e2f4ae2b23f..16b50c994c69bf83ec10425ece8f1e4dcd476fba 100644 (file)
@@ -2346,6 +2346,7 @@ acl_fetch_sc2_get_gpc0(struct proxy *px, struct session *l4, void *l7, int dir,
 
 /* set temp integer to the General Purpose Counter 0 value from the session's source
  * address in the table pointed to by expr.
+ * Accepts 0 or 1 argument of type string.
  */
 static int
 acl_fetch_src_get_gpc0(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -2357,8 +2358,8 @@ acl_fetch_src_get_gpc0(struct proxy *px, struct session *l4, void *l7, int dir,
        if (!key)
                return 0;
 
-       if (expr->arg_len)
-               px = find_stktable(expr->arg.str);
+       if (expr->args)
+               px = find_stktable(expr->args->data.str.str);
 
        if (!px)
                return 0; /* table not found */
@@ -2409,6 +2410,7 @@ acl_fetch_sc2_inc_gpc0(struct proxy *px, struct session *l4, void *l7, int dir,
 
 /* Increment the General Purpose Counter 0 value from the session's source
  * address in the table pointed to by expr, and return it into temp integer.
+ * Accepts 0 or 1 argument of type string.
  */
 static int
 acl_fetch_src_inc_gpc0(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -2420,8 +2422,8 @@ acl_fetch_src_inc_gpc0(struct proxy *px, struct session *l4, void *l7, int dir,
        if (!key)
                return 0;
 
-       if (expr->arg_len)
-               px = find_stktable(expr->arg.str);
+       if (expr->args)
+               px = find_stktable(expr->args->data.str.str);
 
        if (!px)
                return 0; /* table not found */
@@ -2473,6 +2475,7 @@ acl_fetch_sc2_clr_gpc0(struct proxy *px, struct session *l4, void *l7, int dir,
 
 /* Clear the General Purpose Counter 0 value from the session's source address
  * in the table pointed to by expr, and return its previous value into temp integer.
+ * Accepts 0 or 1 argument of type string.
  */
 static int
 acl_fetch_src_clr_gpc0(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -2484,8 +2487,8 @@ acl_fetch_src_clr_gpc0(struct proxy *px, struct session *l4, void *l7, int dir,
        if (!key)
                return 0;
 
-       if (expr->arg_len)
-               px = find_stktable(expr->arg.str);
+       if (expr->args)
+               px = find_stktable(expr->args->data.str.str);
 
        if (!px)
                return 0; /* table not found */
@@ -2532,6 +2535,7 @@ acl_fetch_sc2_conn_cnt(struct proxy *px, struct session *l4, void *l7, int dir,
 
 /* set temp integer to the cumulated number of connections from the session's source
  * address in the table pointed to by expr.
+ * Accepts 0 or 1 argument of type string.
  */
 static int
 acl_fetch_src_conn_cnt(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -2543,8 +2547,8 @@ acl_fetch_src_conn_cnt(struct proxy *px, struct session *l4, void *l7, int dir,
        if (!key)
                return 0;
 
-       if (expr->arg_len)
-               px = find_stktable(expr->arg.str);
+       if (expr->args)
+               px = find_stktable(expr->args->data.str.str);
 
        if (!px)
                return 0; /* table not found */
@@ -2596,6 +2600,7 @@ acl_fetch_sc2_conn_rate(struct proxy *px, struct session *l4, void *l7, int dir,
 
 /* set temp integer to the connection rate from the session's source address in the
  * table pointed to by expr, over the configured period.
+ * Accepts 0 or 1 argument of type string.
  */
 static int
 acl_fetch_src_conn_rate(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -2607,8 +2612,8 @@ acl_fetch_src_conn_rate(struct proxy *px, struct session *l4, void *l7, int dir,
        if (!key)
                return 0;
 
-       if (expr->arg_len)
-               px = find_stktable(expr->arg.str);
+       if (expr->args)
+               px = find_stktable(expr->args->data.str.str);
 
        if (!px)
                return 0; /* table not found */
@@ -2618,6 +2623,7 @@ acl_fetch_src_conn_rate(struct proxy *px, struct session *l4, void *l7, int dir,
 
 /* set temp integer to the number of connections from the session's source address
  * in the table pointed to by expr, after updating it.
+ * Accepts 0 or 1 argument of type string.
  */
 static int
 acl_fetch_src_updt_conn_cnt(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -2631,8 +2637,8 @@ acl_fetch_src_updt_conn_cnt(struct proxy *px, struct session *l4, void *l7, int
        if (!key)
                return 0;
 
-       if (expr->arg_len)
-               px = find_stktable(expr->arg.str);
+       if (expr->args)
+               px = find_stktable(expr->args->data.str.str);
 
        if (!px)
                return 0; /* table not found */
@@ -2690,6 +2696,7 @@ acl_fetch_sc2_conn_cur(struct proxy *px, struct session *l4, void *l7, int dir,
 
 /* set temp integer to the number of concurrent connections from the session's source
  * address in the table pointed to by expr.
+ * Accepts 0 or 1 argument of type string.
  */
 static int
 acl_fetch_src_conn_cur(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -2701,8 +2708,8 @@ acl_fetch_src_conn_cur(struct proxy *px, struct session *l4, void *l7, int dir,
        if (!key)
                return 0;
 
-       if (expr->arg_len)
-               px = find_stktable(expr->arg.str);
+       if (expr->args)
+               px = find_stktable(expr->args->data.str.str);
 
        if (!px)
                return 0; /* table not found */
@@ -2749,6 +2756,7 @@ acl_fetch_sc2_sess_cnt(struct proxy *px, struct session *l4, void *l7, int dir,
 
 /* set temp integer to the cumulated number of session from the session's source
  * address in the table pointed to by expr.
+ * Accepts 0 or 1 argument of type string.
  */
 static int
 acl_fetch_src_sess_cnt(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -2760,8 +2768,8 @@ acl_fetch_src_sess_cnt(struct proxy *px, struct session *l4, void *l7, int dir,
        if (!key)
                return 0;
 
-       if (expr->arg_len)
-               px = find_stktable(expr->arg.str);
+       if (expr->args)
+               px = find_stktable(expr->args->data.str.str);
 
        if (!px)
                return 0; /* table not found */
@@ -2813,6 +2821,7 @@ acl_fetch_sc2_sess_rate(struct proxy *px, struct session *l4, void *l7, int dir,
 
 /* set temp integer to the session rate from the session's source address in the
  * table pointed to by expr, over the configured period.
+ * Accepts 0 or 1 argument of type string.
  */
 static int
 acl_fetch_src_sess_rate(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -2824,8 +2833,8 @@ acl_fetch_src_sess_rate(struct proxy *px, struct session *l4, void *l7, int dir,
        if (!key)
                return 0;
 
-       if (expr->arg_len)
-               px = find_stktable(expr->arg.str);
+       if (expr->args)
+               px = find_stktable(expr->args->data.str.str);
 
        if (!px)
                return 0; /* table not found */
@@ -2872,6 +2881,7 @@ acl_fetch_sc2_http_req_cnt(struct proxy *px, struct session *l4, void *l7, int d
 
 /* set temp integer to the cumulated number of session from the session's source
  * address in the table pointed to by expr.
+ * Accepts 0 or 1 argument of type string.
  */
 static int
 acl_fetch_src_http_req_cnt(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -2883,8 +2893,8 @@ acl_fetch_src_http_req_cnt(struct proxy *px, struct session *l4, void *l7, int d
        if (!key)
                return 0;
 
-       if (expr->arg_len)
-               px = find_stktable(expr->arg.str);
+       if (expr->args)
+               px = find_stktable(expr->args->data.str.str);
 
        if (!px)
                return 0; /* table not found */
@@ -2936,6 +2946,7 @@ acl_fetch_sc2_http_req_rate(struct proxy *px, struct session *l4, void *l7, int
 
 /* set temp integer to the session rate from the session's source address in the
  * table pointed to by expr, over the configured period.
+ * Accepts 0 or 1 argument of type string.
  */
 static int
 acl_fetch_src_http_req_rate(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -2947,8 +2958,8 @@ acl_fetch_src_http_req_rate(struct proxy *px, struct session *l4, void *l7, int
        if (!key)
                return 0;
 
-       if (expr->arg_len)
-               px = find_stktable(expr->arg.str);
+       if (expr->args)
+               px = find_stktable(expr->args->data.str.str);
 
        if (!px)
                return 0; /* table not found */
@@ -2995,6 +3006,7 @@ acl_fetch_sc2_http_err_cnt(struct proxy *px, struct session *l4, void *l7, int d
 
 /* set temp integer to the cumulated number of session from the session's source
  * address in the table pointed to by expr.
+ * Accepts 0 or 1 argument of type string.
  */
 static int
 acl_fetch_src_http_err_cnt(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -3006,8 +3018,8 @@ acl_fetch_src_http_err_cnt(struct proxy *px, struct session *l4, void *l7, int d
        if (!key)
                return 0;
 
-       if (expr->arg_len)
-               px = find_stktable(expr->arg.str);
+       if (expr->args)
+               px = find_stktable(expr->args->data.str.str);
 
        if (!px)
                return 0; /* table not found */
@@ -3059,6 +3071,7 @@ acl_fetch_sc2_http_err_rate(struct proxy *px, struct session *l4, void *l7, int
 
 /* set temp integer to the session rate from the session's source address in the
  * table pointed to by expr, over the configured period.
+ * Accepts 0 or 1 argument of type string.
  */
 static int
 acl_fetch_src_http_err_rate(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -3070,8 +3083,8 @@ acl_fetch_src_http_err_rate(struct proxy *px, struct session *l4, void *l7, int
        if (!key)
                return 0;
 
-       if (expr->arg_len)
-               px = find_stktable(expr->arg.str);
+       if (expr->args)
+               px = find_stktable(expr->args->data.str.str);
 
        if (!px)
                return 0; /* table not found */
@@ -3123,6 +3136,7 @@ acl_fetch_sc2_kbytes_in(struct proxy *px, struct session *l4, void *l7, int dir,
 
 /* set temp integer to the number of kbytes received from the session's source
  * address in the table pointed to by expr.
+ * Accepts 0 or 1 argument of type string.
  */
 static int
 acl_fetch_src_kbytes_in(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -3134,8 +3148,8 @@ acl_fetch_src_kbytes_in(struct proxy *px, struct session *l4, void *l7, int dir,
        if (!key)
                return 0;
 
-       if (expr->arg_len)
-               px = find_stktable(expr->arg.str);
+       if (expr->args)
+               px = find_stktable(expr->args->data.str.str);
 
        if (!px)
                return 0; /* table not found */
@@ -3189,6 +3203,7 @@ acl_fetch_sc2_bytes_in_rate(struct proxy *px, struct session *l4, void *l7, int
 
 /* set temp integer to the bytes rate from clients from the session's source address
  * in the table pointed to by expr, over the configured period.
+ * Accepts 0 or 1 argument of type string.
  */
 static int
 acl_fetch_src_bytes_in_rate(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -3200,8 +3215,8 @@ acl_fetch_src_bytes_in_rate(struct proxy *px, struct session *l4, void *l7, int
        if (!key)
                return 0;
 
-       if (expr->arg_len)
-               px = find_stktable(expr->arg.str);
+       if (expr->args)
+               px = find_stktable(expr->args->data.str.str);
 
        if (!px)
                return 0; /* table not found */
@@ -3253,6 +3268,7 @@ acl_fetch_sc2_kbytes_out(struct proxy *px, struct session *l4, void *l7, int dir
 
 /* set temp integer to the number of kbytes sent to the session's source address in
  * the table pointed to by expr.
+ * Accepts 0 or 1 argument of type string.
  */
 static int
 acl_fetch_src_kbytes_out(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -3264,8 +3280,8 @@ acl_fetch_src_kbytes_out(struct proxy *px, struct session *l4, void *l7, int dir
        if (!key)
                return 0;
 
-       if (expr->arg_len)
-               px = find_stktable(expr->arg.str);
+       if (expr->args)
+               px = find_stktable(expr->args->data.str.str);
 
        if (!px)
                return 0; /* table not found */
@@ -3319,6 +3335,7 @@ acl_fetch_sc2_bytes_out_rate(struct proxy *px, struct session *l4, void *l7, int
 
 /* set temp integer to the bytes rate to client from the session's source address in
  * the table pointed to by expr, over the configured period.
+ * Accepts 0 or 1 argument of type string.
  */
 static int
 acl_fetch_src_bytes_out_rate(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -3330,8 +3347,8 @@ acl_fetch_src_bytes_out_rate(struct proxy *px, struct session *l4, void *l7, int
        if (!key)
                return 0;
 
-       if (expr->arg_len)
-               px = find_stktable(expr->arg.str);
+       if (expr->args)
+               px = find_stktable(expr->args->data.str.str);
 
        if (!px)
                return 0; /* table not found */
@@ -3339,13 +3356,15 @@ acl_fetch_src_bytes_out_rate(struct proxy *px, struct session *l4, void *l7, int
        return acl_fetch_bytes_out_rate(&px->table, test, stktable_lookup_key(&px->table, key));
 }
 
-/* set temp integer to the number of used entries in the table pointed to by expr. */
+/* set temp integer to the number of used entries in the table pointed to by expr.
+ * Accepts 0 or 1 argument of type string.
+ */
 static int
 acl_fetch_table_cnt(struct proxy *px, struct session *l4, void *l7, int dir,
                        struct acl_expr *expr, struct acl_test *test)
 {
-       if (expr->arg_len)
-               px = find_stktable(expr->arg.str);
+       if (expr->args)
+               px = find_stktable(expr->args->data.str.str);
 
        if (!px)
                return 0; /* table not found */
@@ -3355,13 +3374,15 @@ acl_fetch_table_cnt(struct proxy *px, struct session *l4, void *l7, int dir,
        return 1;
 }
 
-/* set temp integer to the number of free entries in the table pointed to by expr. */
+/* set temp integer to the number of free entries in the table pointed to by expr.
+ * Accepts 0 or 1 argument of type string.
+ */
 static int
 acl_fetch_table_avl(struct proxy *px, struct session *l4, void *l7, int dir,
                             struct acl_expr *expr, struct acl_test *test)
 {
-       if (expr->arg_len)
-               px = find_stktable(expr->arg.str);
+       if (expr->args)
+               px = find_stktable(expr->args->data.str.str);
 
        if (!px)
                return 0; /* table not found */