From: Willy Tarreau Date: Thu, 19 Apr 2012 15:16:54 +0000 (+0200) Subject: MAJOR: acl: make use of the new argument parsing framework X-Git-Tag: v1.5-dev9~64 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=34db108;p=thirdparty%2Fhaproxy.git MAJOR: acl: make use of the new argument parsing framework 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. --- diff --git a/include/types/acl.h b/include/types/acl.h index 35a22a0d44..14e4f844f7 100644 --- a/include/types/acl.h +++ b/include/types/acl.h @@ -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 #include +#include #include #include #include @@ -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 */ }; diff --git a/src/acl.c b/src/acl.c index 507516f31e..84de6acef4 100644 --- a/src/acl.c +++ b/src/acl.c @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -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; diff --git a/src/backend.c b/src/backend.c index b4fa21d810..74bee83953 100644 --- a/src/backend.c +++ b/src/backend.c @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -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; diff --git a/src/frontend.c b/src/frontend.c index c18cc66c57..ac6027c6c0 100644 --- a/src/frontend.c +++ b/src/frontend.c @@ -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) diff --git a/src/proto_http.c b/src/proto_http.c index b8b0af6f17..7f65be47b6 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -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 is non-null, then + * match the name in expr->arg and expr->args->data.str.len. If 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))) { diff --git a/src/proto_tcp.c b/src/proto_tcp.c index 17144161bc..d53cd52d88 100644 --- a/src/proto_tcp.c +++ b/src/proto_tcp.c @@ -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) diff --git a/src/session.c b/src/session.c index e930dafd1a..16b50c994c 100644 --- a/src/session.c +++ b/src/session.c @@ -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 */