diff --git a/doc/configuration.txt b/doc/configuration.txt index 7e9a65036..a65db0dd5 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -8909,6 +8909,7 @@ The following ACL flags are currently supported : -i : ignore case during matching of all subsequent patterns. -f : load patterns from a file. -m : use a specific pattern matching method + -u : force the unique id of the ACL -- : force end of flags. Useful when a string looks like one of the flags. The "-f" flag is followed by the name of a file from which all lines will be @@ -8921,6 +8922,10 @@ a comment. Depending on the data type and match method, haproxy may load the lines into a binary tree, allowing very fast lookups. This is true for IPv4 and exact string matching. In this case, duplicates will automatically be removed. +The "-u" flag forces the unique id of the ACL. This unique id is used with the +socket interface to identify ACL and dynamically change its values. Note that a +file is always identified by its name even if an id is set. + Also, note that the "-i" flag applies to subsequent entries and not to entries loaded from files preceding it. For instance : diff --git a/src/acl.c b/src/acl.c index 4e3321357..49691552d 100644 --- a/src/acl.c +++ b/src/acl.c @@ -155,6 +155,10 @@ struct acl_expr *parse_acl_expr(const char **args, char **err, struct arg_list * /* The following buffer contain two numbers, a ':' separator and the final \0. */ char buffer[NB_LLMAX_STR + 1 + NB_LLMAX_STR + 1]; int is_loaded; + int unique_id; + char *error; + struct pat_ref *ref; + struct pattern_expr *pattern_expr; /* First, we look for an ACL keyword. And if we don't find one, then * we look for a sample fetch expression starting with a sample fetch @@ -416,13 +420,30 @@ struct acl_expr *parse_acl_expr(const char **args, char **err, struct arg_list * * -i : ignore case for all patterns by default * -f : read patterns from those files * -m : force matching method (must be used before -f) + * -u : force the unique id of the acl * -- : everything after this is not an option */ patflags = 0; is_loaded = 0; + unique_id = -1; while (**args == '-') { if ((*args)[1] == 'i') patflags |= PAT_F_IGNORE_CASE; + else if ((*args)[1] == 'u') { + unique_id = strtol(args[1], &error, 10); + if (*error != '\0') { + memprintf(err, "the argument of -u must be an integer"); + goto out_free_expr; + } + + /* Check if this id is really unique. */ + if (pat_ref_lookupid(unique_id)) { + memprintf(err, "the id is already used"); + goto out_free_expr; + } + + args++; + } else if ((*args)[1] == 'f') { if (!expr->pat.parse) { memprintf(err, "matching method must be specified first (using '-m') when using a sample fetch of this type ('%s')", expr->kw); @@ -476,6 +497,18 @@ struct acl_expr *parse_acl_expr(const char **args, char **err, struct arg_list * goto out_free_expr; } + /* Create new patern reference. */ + ref = pat_ref_newid(unique_id, PAT_REF_ACL); + if (!ref) { + memprintf(err, "memory error"); + goto out_free_expr; + } + + /* Create new pattern expression associated to this reference. */ + pattern_expr = pattern_new_expr(&expr->pat, ref, err); + if (!pattern_expr) + goto out_free_expr; + /* now parse all patterns */ while (**args) { arg = *args; @@ -598,7 +631,10 @@ struct acl_expr *parse_acl_expr(const char **args, char **err, struct arg_list * } } - if (!pattern_register(&expr->pat, -1, PAT_REF_ACL, arg, NULL, patflags, err)) + /* Add sample to the reference, and try to compile it fior each pattern + * using this value. + */ + if (!pat_ref_add(ref, arg, NULL, err)) goto out_free_expr; args++; }