]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: pattern: add indexation function.
authorThierry FOURNIER <tfournier@exceliance.fr>
Fri, 13 Dec 2013 14:12:32 +0000 (15:12 +0100)
committerWilly Tarreau <w@1wt.eu>
Mon, 17 Mar 2014 17:06:06 +0000 (18:06 +0100)
Before this patch, the indexation function check the declared patttern
matching function and index the data according with this function. This
is not useful to add some indexation mode.

This commit adds dedicated indexation function. Each struct pattern is
associated with one indexation function. This function permit to index
data according with the type of pattern and with the type of match.

include/proto/pattern.h
include/types/acl.h
include/types/pattern.h
src/acl.c
src/dumpstats.c
src/map.c
src/pattern.c
src/payload.c
src/proto_http.c
src/ssl_sock.c

index 163f36b7a89fb1907c2ed9ed6deb130209234f85..b9947b5dde91a70de7a6379202a144e51cbd35dd 100644 (file)
@@ -40,7 +40,7 @@
  * The function returns 1 if the processing is ok, return 0
  * if the parser fails, with <err> message filled.
  */
-int pattern_register(struct pattern_expr *expr, const char *arg, struct sample_storage *smp, struct pattern_list **pattern, int patflags, char **err);
+int pattern_register(struct pattern_expr *expr, const char *arg, struct sample_storage *smp, int patflags, char **err);
 
 /* return the PAT_MATCH_* index for match name "name", or < 0 if not found */
 static inline int pat_find_match_name(const char *name)
@@ -60,6 +60,18 @@ static inline int pat_find_match_name(const char *name)
  */
 enum pat_match_res pattern_exec_match(struct pattern_expr *expr, struct sample *smp, struct sample_storage **sample, struct pattern **pat, struct pat_idx_elt **elt);
 
+/*
+ *
+ * The following function gets "pattern", duplicate it and index it in "expr"
+ *
+ */
+int pat_idx_list_val(struct pattern_expr *expr, struct pattern *pat, char **err);
+int pat_idx_list_ptr(struct pattern_expr *expr, struct pattern *pat, char **err);
+int pat_idx_list_str(struct pattern_expr *expr, struct pattern *pat, char **err);
+int pat_idx_list_reg(struct pattern_expr *expr, struct pattern *pat, char **err);
+int pat_idx_tree_ip(struct pattern_expr *expr, struct pattern *pat, char **err);
+int pat_idx_tree_str(struct pattern_expr *expr, struct pattern *pat, char **err);
+
 /*
  *
  * The following functions are general purpose pattern matching functions.
index 74db67b556d3fbee744e770d26941b122c098433..0b6524b1a6c794b52d4c5907a8b72b13c06761bd 100644 (file)
@@ -93,6 +93,7 @@ struct acl_keyword {
        const char *kw;
        char *fetch_kw;
        int (*parse)(const char *text, struct pattern *pattern, enum pat_usage usage, char **err);
+       int (*index)(struct pattern_expr *expr, struct pattern *pattern, char **err);
        enum pat_match_res (*match)(struct sample *smp, struct pattern *pattern);
        /* must be after the config params */
        struct sample_fetch *smp; /* the sample fetch we depend on */
index 935dd1d14667e53563bd1ed7400d06f33fdb4c0f..c4f235ffd918d6ee29dc37c45eea48ca523e5197 100644 (file)
@@ -165,6 +165,7 @@ struct pattern_list {
  */
 struct pattern_expr {
        int (*parse)(const char *text, struct pattern *pattern, enum pat_usage usage, char **err);
+       int (*index)(struct pattern_expr *, struct pattern *, char **);
        enum pat_match_res (*match)(struct sample *smp, struct pattern *pattern);
        struct list patterns;         /* list of acl_patterns */
        struct eb_root pattern_tree;  /* may be used for lookup in large datasets */
@@ -172,6 +173,7 @@ struct pattern_expr {
 
 extern char *pat_match_names[PAT_MATCH_NUM];
 extern int (*pat_parse_fcts[PAT_MATCH_NUM])(const char *, struct pattern *, enum pat_usage, char **);
+extern int (*pat_index_fcts[PAT_MATCH_NUM])(struct pattern_expr *, struct pattern *, char **);
 extern enum pat_match_res (*pat_match_fcts[PAT_MATCH_NUM])(struct sample *, struct pattern *);
 extern int pat_match_types[PAT_MATCH_NUM];
 
index 26c58e7c05517431c1da0a5e4bf224911fde2781..78c3f307d5e0a893455e69585381ebbea7695c56 100644 (file)
--- a/src/acl.c
+++ b/src/acl.c
@@ -130,10 +130,9 @@ static struct acl_expr *prune_acl_expr(struct acl_expr *expr)
  */
 struct acl_expr *parse_acl_expr(const char **args, char **err, struct arg_list *al)
 {
-       __label__ out_return, out_free_expr, out_free_pattern;
+       __label__ out_return, out_free_expr;
        struct acl_expr *expr;
        struct acl_keyword *aclkw;
-       struct pattern_list *pattern;
        int patflags;
        const char *arg;
        struct sample_expr *smp = NULL;
@@ -350,6 +349,7 @@ struct acl_expr *parse_acl_expr(const char **args, char **err, struct arg_list *
 
        expr->kw = aclkw ? aclkw->kw : smp->fetch->kw;
        expr->pat.parse = aclkw ? aclkw->parse : NULL;
+       expr->pat.index = aclkw ? aclkw->index : NULL;
        expr->pat.match = aclkw ? aclkw->match : NULL;
        expr->smp = smp;
        smp = NULL;
@@ -360,16 +360,19 @@ struct acl_expr *parse_acl_expr(const char **args, char **err, struct arg_list *
                switch (expr->smp ? expr->smp->fetch->out_type : aclkw->smp->out_type) {
                case SMP_T_BOOL:
                        expr->pat.parse = pat_parse_fcts[PAT_MATCH_BOOL];
+                       expr->pat.index = pat_index_fcts[PAT_MATCH_BOOL];
                        expr->pat.match = pat_match_fcts[PAT_MATCH_BOOL];
                        break;
                case SMP_T_SINT:
                case SMP_T_UINT:
                        expr->pat.parse = pat_parse_fcts[PAT_MATCH_INT];
+                       expr->pat.index = pat_index_fcts[PAT_MATCH_INT];
                        expr->pat.match = pat_match_fcts[PAT_MATCH_INT];
                        break;
                case SMP_T_IPV4:
                case SMP_T_IPV6:
                        expr->pat.parse = pat_parse_fcts[PAT_MATCH_IP];
+                       expr->pat.index = pat_index_fcts[PAT_MATCH_IP];
                        expr->pat.match = pat_match_fcts[PAT_MATCH_IP];
                        break;
                }
@@ -429,6 +432,7 @@ struct acl_expr *parse_acl_expr(const char **args, char **err, struct arg_list *
                                goto out_free_expr;
                        }
                        expr->pat.parse = pat_parse_fcts[idx];
+                       expr->pat.index = pat_index_fcts[idx];
                        expr->pat.match = pat_match_fcts[idx];
                        args++;
                }
@@ -447,7 +451,6 @@ struct acl_expr *parse_acl_expr(const char **args, char **err, struct arg_list *
        }
 
        /* now parse all patterns */
-       pattern = NULL;
        while (**args) {
                arg = *args;
 
@@ -513,11 +516,11 @@ struct acl_expr *parse_acl_expr(const char **args, char **err, struct arg_list *
                                if (expr->pat.parse == pat_parse_dotted_ver && have_dot) {
                                        if (strl2llrc(dot+1, strlen(dot+1), &minor) != 0) {
                                                memprintf(err, "'%s' is neither a number nor a supported operator", arg);
-                                               goto out_free_pattern;
+                                               goto out_free_expr;
                                        }
                                        if (minor >= 65536) {
                                                memprintf(err, "'%s' contains too large a minor value", arg);
-                                               goto out_free_pattern;
+                                               goto out_free_expr;
                                        }
                                }
 
@@ -526,12 +529,12 @@ struct acl_expr *parse_acl_expr(const char **args, char **err, struct arg_list *
                                 */
                                if (strl2llrc(arg, dot - arg, &value) != 0) {
                                        memprintf(err, "'%s' is neither a number nor a supported operator", arg);
-                                       goto out_free_pattern;
+                                       goto out_free_expr;
                                }
                                if (expr->pat.parse == pat_parse_dotted_ver)  {
                                        if (value >= 65536) {
                                                memprintf(err, "'%s' contains too large a major value", arg);
-                                               goto out_free_pattern;
+                                               goto out_free_expr;
                                        }
                                        value = (value << 16) | (minor & 0xffff);
                                }
@@ -540,7 +543,7 @@ struct acl_expr *parse_acl_expr(const char **args, char **err, struct arg_list *
 
                                case STD_OP_EQ: /* this case is not possible. */
                                        memprintf(err, "internal error");
-                                       goto out_free_pattern;
+                                       goto out_free_expr;
 
                                case STD_OP_GT:
                                        value++; /* gt = ge + 1 */
@@ -569,15 +572,13 @@ struct acl_expr *parse_acl_expr(const char **args, char **err, struct arg_list *
                        }
                }
 
-               if (!pattern_register(&expr->pat, arg, NULL, &pattern, patflags, err))
-                       goto out_free_pattern;
+               if (!pattern_register(&expr->pat, arg, NULL, patflags, err))
+                       goto out_free_expr;
                args++;
        }
 
        return expr;
 
- out_free_pattern:
-       pattern_free(pattern);
  out_free_expr:
        prune_acl_expr(expr);
        free(expr);
index ba0a7a502d26067ef26e82e8b00ed4ea9976f8a2..0eb563970a8ea99ef103efb7c82b882d039d77e9 100644 (file)
@@ -1920,7 +1920,6 @@ static int stats_sock_parse_request(struct stream_interface *si, char *line)
        }
        else if (strcmp(args[0], "add") == 0) {
                if (strcmp(args[1], "map") == 0) {
-                       struct pattern_list *pat;
                        struct map_entry *ent;
                        struct sample_storage *smp;
 
@@ -1993,23 +1992,7 @@ static int stats_sock_parse_request(struct stream_interface *si, char *line)
                                        continue;
                                }
 
-                               /* If the value can be indexed, get the first pattern. If
-                                * the return entry is not the indexed entry, new 'pattern' is
-                                * created by the function pattern_register(). If the 'pattern'
-                                * is NULL, new entry is created. This is ugly because the
-                                * following code interfers with the own code of the function
-                                * pattern_register().
-                                */
-                               if (appctx->ctx.map.desc->pat->match == pat_match_str ||
-                                   appctx->ctx.map.desc->pat->match == pat_match_ip) {
-                                       pat = LIST_NEXT(&appctx->ctx.map.desc->pat->patterns, struct pattern_list *, list);
-                                       if (&pat->list == &appctx->ctx.map.desc->pat->patterns)
-                                               pat = NULL;
-                               }
-                               else
-                                       pat = NULL;
-
-                               if (!pattern_register(appctx->ctx.map.desc->pat, args[3], smp, &pat, 0, NULL)) {
+                               if (!pattern_register(appctx->ctx.map.desc->pat, args[3], smp, 0, NULL)) {
                                        free(smp);
                                        continue;
                                }
index 7e546c7b7e6af703452eea7ca0291297e0dd2ee7..52f077d8e91d8c87317dee0e8412afcaf1d77fd7 100644 (file)
--- a/src/map.c
+++ b/src/map.c
@@ -301,7 +301,6 @@ static int map_read_entries_from_file(const char *filename,
  * <patflags> must be PAT_F_*.
  */
 static int map_parse_and_index(struct map_descriptor *desc,
-                               struct pattern_list **pattern,
                                struct map_entry *ent,
                                int patflags,
                                char **err)
@@ -321,7 +320,7 @@ static int map_parse_and_index(struct map_descriptor *desc,
        }
 
        /* register key */
-       if (!pattern_register(desc->pat, ent->key, smp, pattern, patflags, err))
+       if (!pattern_register(desc->pat, ent->key, smp, patflags, err))
                return 0;
 
        return 1;
@@ -337,7 +336,6 @@ static int sample_load_map(struct arg *arg, struct sample_conv *conv, char **err
 {
        struct map_reference *ref;
        struct map_descriptor *desc;
-       struct pattern_list *pattern;
        struct map_entry *ent;
        struct pattern_expr *pat = NULL;
 
@@ -412,11 +410,11 @@ static int sample_load_map(struct arg *arg, struct sample_conv *conv, char **err
                /* set the match method */
                desc->pat->match = pat_match_fcts[conv->private];
                desc->pat->parse = pat_parse_fcts[conv->private];
+               desc->pat->index = pat_index_fcts[conv->private];
 
                /* parse each line of the file */
-               pattern = NULL;
                list_for_each_entry(ent, &ref->entries, list)
-                       if (!map_parse_and_index(desc, &pattern, ent, 0, err))
+                       if (!map_parse_and_index(desc, ent, 0, err))
                                return 0;
        }
 
index 6ff6e26ee3d61ab6b1a08ed513cfffb1076b1750..e65219044eefef7f202ba0b708039172e601930d 100644 (file)
@@ -56,6 +56,22 @@ int (*pat_parse_fcts[PAT_MATCH_NUM])(const char *, struct pattern *, enum pat_us
        [PAT_MATCH_REG]   = pat_parse_reg,
 };
 
+int (*pat_index_fcts[PAT_MATCH_NUM])(struct pattern_expr *, struct pattern *, char **) = {
+       [PAT_MATCH_FOUND] = pat_idx_list_val,
+       [PAT_MATCH_BOOL]  = pat_idx_list_val,
+       [PAT_MATCH_INT]   = pat_idx_list_val,
+       [PAT_MATCH_IP]    = pat_idx_tree_ip,
+       [PAT_MATCH_BIN]   = pat_idx_list_ptr,
+       [PAT_MATCH_LEN]   = pat_idx_list_val,
+       [PAT_MATCH_STR]   = pat_idx_tree_str,
+       [PAT_MATCH_BEG]   = pat_idx_list_str,
+       [PAT_MATCH_SUB]   = pat_idx_list_str,
+       [PAT_MATCH_DIR]   = pat_idx_list_str,
+       [PAT_MATCH_DOM]   = pat_idx_list_str,
+       [PAT_MATCH_END]   = pat_idx_list_str,
+       [PAT_MATCH_REG]   = pat_idx_list_reg,
+};
+
 enum pat_match_res (*pat_match_fcts[PAT_MATCH_NUM])(struct sample *, struct pattern *) = {
        [PAT_MATCH_FOUND] = NULL,
        [PAT_MATCH_BOOL]  = pat_match_nothing,
@@ -786,135 +802,233 @@ void pattern_init_expr(struct pattern_expr *expr)
        expr->pattern_tree = EB_ROOT_UNIQUE;
 }
 
-/* return 1 if the process is ok
- * return -1 if the parser fail. The err message is filled.
- * return -2 if out of memory
+/*
+ *
+ * The following functions are used for the pattern indexation
+ *
  */
-int pattern_register(struct pattern_expr *expr, const char *arg,
-                     struct sample_storage *smp,
-                     struct pattern_list **pattern,
-                     int patflags, char **err)
+
+int pat_idx_list_val(struct pattern_expr *expr, struct pattern *pat, char **err)
 {
-       unsigned int mask = 0;
-       struct pat_idx_elt *node;
-       int len;
-       int ret;
+       struct pattern_list *patl;
 
-       /* we keep the previous pattern along iterations as long as it's not used */
-       if (!*pattern)
-               *pattern = (struct pattern_list *)malloc(sizeof(**pattern));
-       if (!*pattern) {
-               memprintf(err, "out of memory while loading pattern");
+       /* allocate pattern */
+       patl = calloc(1, sizeof(*patl));
+       if (!patl) {
+               memprintf(err, "out of memory while indexing pattern");
                return 0;
        }
 
-       memset(*pattern, 0, sizeof(**pattern));
-       (*pattern)->pat.flags = patflags;
+       /* duplicate pattern */
+       memcpy(&patl->pat, pat, sizeof(*pat));
 
-       ret = expr->parse(arg, &(*pattern)->pat, PAT_U_COMPILE, err);
-       if (!ret)
+       /* chain pattern in the expression */
+       LIST_ADDQ(&expr->patterns, &patl->list);
+
+       /* that's ok */
+       return 1;
+}
+
+int pat_idx_list_ptr(struct pattern_expr *expr, struct pattern *pat, char **err)
+{
+       struct pattern_list *patl;
+
+       /* allocate pattern */
+       patl = calloc(1, sizeof(*patl));
+       if (!patl)
                return 0;
 
-       if (expr->match == pat_match_str) {
-               /* SMP_T_CSTR tree indexation.
-                * The match "pat_match_str()" can use trees.
-                */
-               if ((*pattern)->pat.flags & PAT_F_IGNORE_CASE) {
-                       /* If the flag PAT_F_IGNORE_CASE is set, we cannot use trees */
-                       goto just_chain_the_pattern;
-               }
+       /* duplicate pattern */
+       memcpy(&patl->pat, pat, sizeof(*pat));
+       patl->pat.ptr.ptr = malloc(patl->pat.len);
+       if (!patl->pat.ptr.ptr) {
+               free(patl);
+               memprintf(err, "out of memory while indexing pattern");
+               return 0;
+       }
+       memcpy(patl->pat.ptr.ptr, pat->ptr.ptr, pat->len);
 
-               /* Process the key len */
-               len = strlen((*pattern)->pat.ptr.str) + 1;
+       /* chain pattern in the expression */
+       LIST_ADDQ(&expr->patterns, &patl->list);
 
-               /* node memory allocation */
-               node = calloc(1, sizeof(*node) + len);
-               if (!node) {
-                       memprintf(err, "out of memory while loading pattern");
-                       return 0;
-               }
+       /* that's ok */
+       return 1;
+}
 
-               /* copy the pointer to sample associated to this node */
-               node->smp = smp;
+int pat_idx_list_str(struct pattern_expr *expr, struct pattern *pat, char **err)
+{
+       struct pattern_list *patl;
 
-               /* copy the string */
-               memcpy(node->node.key, (*pattern)->pat.ptr.str, len);
+       /* allocate pattern */
+       patl = calloc(1, sizeof(*patl));
+       if (!patl) {
+               memprintf(err, "out of memory while indexing pattern");
+               return 0;
+       }
 
-               /* the "map_parser_str()" function always duplicate string information */
-               free((*pattern)->pat.ptr.str);
-               (*pattern)->pat.ptr.str = NULL;
+       /* duplicate pattern */
+       memcpy(&patl->pat, pat, sizeof(*pat));
+       patl->pat.ptr.str = malloc(patl->pat.len + 1);
+       if (!patl->pat.ptr.str) {
+               free(patl);
+               memprintf(err, "out of memory while indexing pattern");
+               return 0;
+       }
+       memcpy(patl->pat.ptr.ptr, pat->ptr.ptr, pat->len);
+       patl->pat.ptr.str[patl->pat.len] = '\0';
 
-               /* we pre-set the data pointer to the tree's head so that functions
-                * which are able to insert in a tree know where to do that.
-                *
-                * because "val" is an "union", the previous data are crushed.
-                */
-               (*pattern)->pat.flags |= PAT_F_TREE;
-               (*pattern)->pat.val.tree = &expr->pattern_tree;
+       /* chain pattern in the expression */
+       LIST_ADDQ(&expr->patterns, &patl->list);
 
-               /* index the new node */
-               if (ebst_insert((*pattern)->pat.val.tree, &node->node) != &node->node)
-                       free(node); /* was a duplicate */
+       /* that's ok */
+       return 1;
+}
+
+int pat_idx_list_reg(struct pattern_expr *expr, struct pattern *pat, char **err)
+{
+       struct pattern_list *patl;
+
+       /* allocate pattern */
+       patl = calloc(1, sizeof(*patl));
+       if (!patl) {
+               memprintf(err, "out of memory while indexing pattern");
+               return 0;
+       }
+
+       /* duplicate pattern */
+       memcpy(&patl->pat, pat, sizeof(*pat));
+
+       /* allocate regex */
+       patl->pat.ptr.reg = calloc(1, sizeof(*patl->pat.ptr.reg));
+       if (!patl->pat.ptr.reg) {
+               free(patl);
+               memprintf(err, "out of memory while indexing pattern");
+               return 0;
+       }
+
+       /* compile regex */
+       if (!regex_comp(pat->ptr.reg->regstr, patl->pat.ptr.reg, !(patl->pat.flags & PAT_F_IGNORE_CASE), 0, err)) {
+               free(patl);
+               free(patl->pat.ptr.reg);
+               return 0;
        }
-       else if (expr->match == pat_match_ip) {
-               /* SMP_T_IPV4 tree indexation
-                * The match "pat_match_ip()" can use tree.
-                */
-               if ((*pattern)->pat.type != SMP_T_IPV4) {
-                       /* Only IPv4 can be indexed */
-                       goto just_chain_the_pattern;
-               }
 
+       /* free pattern method */
+       patl->pat.freeptrbuf = &pat_free_reg;
+
+       /* chain pattern in the expression */
+       LIST_ADDQ(&expr->patterns, &patl->list);
+
+       /* that's ok */
+       return 1;
+}
+
+int pat_idx_tree_ip(struct pattern_expr *expr, struct pattern *pat, char **err)
+{
+       unsigned int mask;
+       struct pat_idx_elt *node;
+
+       /* Only IPv4 can be indexed */
+       if (pat->type == SMP_T_IPV4) {
                /* in IPv4 case, check if the mask is contiguous so that we can
                 * insert the network into the tree. A continuous mask has only
                 * ones on the left. This means that this mask + its lower bit
                 * added once again is null.
                 */
-               mask = ntohl((*pattern)->pat.val.ipv4.mask.s_addr);
-               if (mask + (mask & -mask) != 0)
-                       goto just_chain_the_pattern;
-               mask = mask ? 33 - flsnz(mask & -mask) : 0; /* equals cidr value */
-
-               /* node memory allocation */
-               node = calloc(1, sizeof(*node) + 4);
-               if (!node) {
-                       memprintf(err, "out of memory while loading pattern");
-                       return 0;
-               }
+               mask = ntohl(pat->val.ipv4.mask.s_addr);
+               if (mask + (mask & -mask) == 0) {
+                       mask = mask ? 33 - flsnz(mask & -mask) : 0; /* equals cidr value */
 
-               /* copy the pointer to sample associated to this node */
-               node->smp = smp;
+                       /* node memory allocation */
+                       node = calloc(1, sizeof(*node) + 4);
+                       if (!node) {
+                               memprintf(err, "out of memory while loading pattern");
+                               return 0;
+                       }
 
-               /* FIXME: insert <addr>/<mask> into the tree here */
-               memcpy(node->node.key, &(*pattern)->pat.val.ipv4.addr, 4); /* network byte order */
+                       /* copy the pointer to sample associated to this node */
+                       node->smp = pat->smp;
 
-               /* we pre-set the data pointer to the tree's head so that functions
-                * which are able to insert in a tree know where to do that.
-                *
-                * because "val" is an "union", the previous data are crushed.
-                */
-               (*pattern)->pat.flags |= PAT_F_TREE;
-               (*pattern)->pat.val.tree = &expr->pattern_tree;
+                       /* FIXME: insert <addr>/<mask> into the tree here */
+                       memcpy(node->node.key, &pat->val.ipv4.addr, 4); /* network byte order */
+                       node->node.node.pfx = mask;
+                       if (ebmb_insert_prefix(&expr->pattern_tree, &node->node, 4) != &node->node)
+                               free(node); /* was a duplicate */
 
-               /* Index the new node
-                * FIXME: insert <addr>/<mask> into the tree here
-                */
-               node->node.node.pfx = mask;
-               if (ebmb_insert_prefix((*pattern)->pat.val.tree, &node->node, 4) != &node->node)
-                       free(node); /* was a duplicate */
+                       /* that's ok */
+                       return 1;
+               }
        }
-       else {
-just_chain_the_pattern:
-               /* if the parser did not feed the tree, let's chain the pattern to the list */
-               LIST_ADDQ(&expr->patterns, &(*pattern)->list);
 
-               /* copy the pointer to sample associated to this node */
-               (*pattern)->pat.smp = smp;
+       /* If the value cannot be indexed, just add it to the list */
+       return pat_idx_list_val(expr, pat, err);
+}
+
+int pat_idx_tree_str(struct pattern_expr *expr, struct pattern *pat, char **err)
+{
+       int len;
+       struct pat_idx_elt *node;
+
+       /* Only string can be indexed */
+       if (pat->type != SMP_T_CSTR && pat->type != SMP_T_STR) {
+               memprintf(err, "internal error: string expected, but the type is '%s'",
+                         smp_to_type[pat->type]);
+               return 0;
+       }
+
+       /* If the flag PAT_F_IGNORE_CASE is set, we cannot use trees */
+       if (pat->flags & PAT_F_IGNORE_CASE)
+               return pat_idx_list_str(expr, pat, err);
+
+       /* Process the key len */
+       len = strlen(pat->ptr.str) + 1;
 
-               /* get a new one */
-               *pattern = NULL;
+       /* node memory allocation */
+       node = calloc(1, sizeof(*node) + len);
+       if (!node) {
+               memprintf(err, "out of memory while loading pattern");
+               return 0;
        }
 
+       /* copy the pointer to sample associated to this node */
+       node->smp = pat->smp;
+
+       /* copy the string */
+       memcpy(node->node.key, pat->ptr.str, len);
+
+       /* index the new node */
+       if (ebst_insert(&expr->pattern_tree, &node->node) != &node->node)
+               free(node); /* was a duplicate */
+
+       /* that's ok */
+       return 1;
+}
+
+/* return 1 if the process is ok
+ * return -1 if the parser fail. The err message is filled.
+ * return -2 if out of memory
+ */
+int pattern_register(struct pattern_expr *expr, const char *arg,
+                     struct sample_storage *smp,
+                     int patflags, char **err)
+{
+       int ret;
+       struct pattern pattern;
+
+       /* initialise pattern */
+       memset(&pattern, 0, sizeof(pattern));
+       pattern.flags = patflags;
+       pattern.smp = smp;
+
+       /* parse pattern */
+       ret = expr->parse(arg, &pattern, PAT_U_LOOKUP, err);
+       if (!ret)
+               return 0;
+
+       /* index pattern */
+       if (!expr->index(expr, &pattern, err))
+               return 0;
+
        return 1;
 }
 
@@ -928,7 +1042,6 @@ int pattern_read_from_file(struct pattern_expr *expr,
        FILE *file;
        char *c;
        char *arg;
-       struct pattern_list *pattern;
        int ret = 0;
        int line = 0;
        int code;
@@ -943,7 +1056,6 @@ int pattern_read_from_file(struct pattern_expr *expr,
         * line. If the line contains spaces, they will be part of the pattern.
         * The pattern stops at the first CR, LF or EOF encountered.
         */
-       pattern = NULL;
        while (fgets(trash.str, trash.size, file) != NULL) {
                line++;
                c = trash.str;
@@ -966,21 +1078,19 @@ int pattern_read_from_file(struct pattern_expr *expr,
                if (c == arg)
                        continue;
 
-               code = pattern_register(expr, arg, NULL, &pattern, patflags, err);
+               code = pattern_register(expr, arg, NULL, patflags, err);
                if (code == -2) {
                        memprintf(err, "out of memory when loading patterns from file <%s>", filename);
                        goto out_close;
                }
                else if (code < 0) {
                        memprintf(err, "%s when loading patterns from file <%s>", *err, filename);
-                       goto out_free_pattern;
+                       goto out_close;
                }
        }
 
        ret = 1; /* success */
 
- out_free_pattern:
-       pattern_free(pattern);
  out_close:
        fclose(file);
        return ret;
index 1db1a7f7a7b08eca5cc7912112c9210c53ecdc9b..d9d66f92a34285793ec23316393cf81bf79c7f8f 100644 (file)
@@ -681,13 +681,13 @@ static struct sample_fetch_kw_list smp_kws = {ILH, {
  * Please take care of keeping this list alphabetically sorted.
  */
 static struct acl_kw_list acl_kws = {ILH, {
-       { "payload",            "req.payload",        pat_parse_bin,        pat_match_bin     },
-       { "payload_lv",         "req.payload_lv",     pat_parse_bin,        pat_match_bin     },
-       { "req_rdp_cookie",     "req.rdp_cookie",     pat_parse_str,        pat_match_str     },
-       { "req_rdp_cookie_cnt", "req.rdp_cookie_cnt", pat_parse_int,        pat_match_int     },
-       { "req_ssl_sni",        "req.ssl_sni",        pat_parse_str,        pat_match_str     },
-       { "req_ssl_ver",        "req.ssl_ver",        pat_parse_dotted_ver, pat_match_int     },
-       { "req.ssl_ver",        "req.ssl_ver",        pat_parse_dotted_ver, pat_match_int     },
+       { "payload",            "req.payload",        pat_parse_bin,        pat_idx_list_ptr, pat_match_bin },
+       { "payload_lv",         "req.payload_lv",     pat_parse_bin,        pat_idx_list_ptr, pat_match_bin },
+       { "req_rdp_cookie",     "req.rdp_cookie",     pat_parse_str,        pat_idx_tree_str, pat_match_str },
+       { "req_rdp_cookie_cnt", "req.rdp_cookie_cnt", pat_parse_int,        pat_idx_list_val, pat_match_int },
+       { "req_ssl_sni",        "req.ssl_sni",        pat_parse_str,        pat_idx_tree_str, pat_match_str },
+       { "req_ssl_ver",        "req.ssl_ver",        pat_parse_dotted_ver, pat_idx_list_val, pat_match_int },
+       { "req.ssl_ver",        "req.ssl_ver",        pat_parse_dotted_ver, pat_idx_list_val, pat_match_int },
        { /* END */ },
 }};
 
index fefcf641468618d2755a713b7d410a2a364b195d..8bd10b71bd77d32822a344f5edc261bd0c5eb044 100644 (file)
@@ -10346,84 +10346,84 @@ static int sample_conv_http_date(const struct arg *args, struct sample *smp)
  * Please take care of keeping this list alphabetically sorted.
  */
 static struct acl_kw_list acl_kws = {ILH, {
-       { "base",            "base",          pat_parse_str,     pat_match_str     },
-       { "base_beg",        "base",          pat_parse_str,     pat_match_beg     },
-       { "base_dir",        "base",          pat_parse_str,     pat_match_dir     },
-       { "base_dom",        "base",          pat_parse_str,     pat_match_dom     },
-       { "base_end",        "base",          pat_parse_str,     pat_match_end     },
-       { "base_len",        "base",          pat_parse_int,     pat_match_len     },
-       { "base_reg",        "base",          pat_parse_reg,     pat_match_reg     },
-       { "base_sub",        "base",          pat_parse_str,     pat_match_sub     },
-
-       { "cook",            "req.cook",      pat_parse_str,     pat_match_str     },
-       { "cook_beg",        "req.cook",      pat_parse_str,     pat_match_beg     },
-       { "cook_dir",        "req.cook",      pat_parse_str,     pat_match_dir     },
-       { "cook_dom",        "req.cook",      pat_parse_str,     pat_match_dom     },
-       { "cook_end",        "req.cook",      pat_parse_str,     pat_match_end     },
-       { "cook_len",        "req.cook",      pat_parse_int,     pat_match_len     },
-       { "cook_reg",        "req.cook",      pat_parse_reg,     pat_match_reg     },
-       { "cook_sub",        "req.cook",      pat_parse_str,     pat_match_sub     },
-
-       { "hdr",             "req.hdr",       pat_parse_str,     pat_match_str     },
-       { "hdr_beg",         "req.hdr",       pat_parse_str,     pat_match_beg     },
-       { "hdr_dir",         "req.hdr",       pat_parse_str,     pat_match_dir     },
-       { "hdr_dom",         "req.hdr",       pat_parse_str,     pat_match_dom     },
-       { "hdr_end",         "req.hdr",       pat_parse_str,     pat_match_end     },
-       { "hdr_len",         "req.hdr",       pat_parse_int,     pat_match_len     },
-       { "hdr_reg",         "req.hdr",       pat_parse_reg,     pat_match_reg     },
-       { "hdr_sub",         "req.hdr",       pat_parse_str,     pat_match_sub     },
-
-       { "http_auth_group", NULL,            pat_parse_str,     pat_match_auth    },
-
-       { "method",          NULL,            pat_parse_meth,    pat_match_meth    },
-
-       { "path",            "path",          pat_parse_str,     pat_match_str     },
-       { "path_beg",        "path",          pat_parse_str,     pat_match_beg     },
-       { "path_dir",        "path",          pat_parse_str,     pat_match_dir     },
-       { "path_dom",        "path",          pat_parse_str,     pat_match_dom     },
-       { "path_end",        "path",          pat_parse_str,     pat_match_end     },
-       { "path_len",        "path",          pat_parse_int,     pat_match_len     },
-       { "path_reg",        "path",          pat_parse_reg,     pat_match_reg     },
-       { "path_sub",        "path",          pat_parse_str,     pat_match_sub     },
-
-       { "req_ver",         "req.ver",       pat_parse_str,     pat_match_str     },
-       { "resp_ver",        "res.ver",       pat_parse_str,     pat_match_str     },
-
-       { "scook",           "res.cook",      pat_parse_str,     pat_match_str     },
-       { "scook_beg",       "res.cook",      pat_parse_str,     pat_match_beg     },
-       { "scook_dir",       "res.cook",      pat_parse_str,     pat_match_dir     },
-       { "scook_dom",       "res.cook",      pat_parse_str,     pat_match_dom     },
-       { "scook_end",       "res.cook",      pat_parse_str,     pat_match_end     },
-       { "scook_len",       "res.cook",      pat_parse_int,     pat_match_len     },
-       { "scook_reg",       "res.cook",      pat_parse_reg,     pat_match_reg     },
-       { "scook_sub",       "res.cook",      pat_parse_str,     pat_match_sub     },
-
-       { "shdr",            "res.hdr",       pat_parse_str,     pat_match_str     },
-       { "shdr_beg",        "res.hdr",       pat_parse_str,     pat_match_beg     },
-       { "shdr_dir",        "res.hdr",       pat_parse_str,     pat_match_dir     },
-       { "shdr_dom",        "res.hdr",       pat_parse_str,     pat_match_dom     },
-       { "shdr_end",        "res.hdr",       pat_parse_str,     pat_match_end     },
-       { "shdr_len",        "res.hdr",       pat_parse_int,     pat_match_len     },
-       { "shdr_reg",        "res.hdr",       pat_parse_reg,     pat_match_reg     },
-       { "shdr_sub",        "res.hdr",       pat_parse_str,     pat_match_sub     },
-
-       { "url",             "url",           pat_parse_str,     pat_match_str     },
-       { "url_beg",         "url",           pat_parse_str,     pat_match_beg     },
-       { "url_dir",         "url",           pat_parse_str,     pat_match_dir     },
-       { "url_dom",         "url",           pat_parse_str,     pat_match_dom     },
-       { "url_end",         "url",           pat_parse_str,     pat_match_end     },
-       { "url_len",         "url",           pat_parse_int,     pat_match_len     },
-       { "url_reg",         "url",           pat_parse_reg,     pat_match_reg     },
-       { "url_sub",         "url",           pat_parse_str,     pat_match_sub     },
-
-       { "urlp",            "urlp",          pat_parse_str,     pat_match_str     },
-       { "urlp_beg",        "urlp",          pat_parse_str,     pat_match_beg     },
-       { "urlp_dir",        "urlp",          pat_parse_str,     pat_match_dir     },
-       { "urlp_dom",        "urlp",          pat_parse_str,     pat_match_dom     },
-       { "urlp_end",        "urlp",          pat_parse_str,     pat_match_end     },
-       { "urlp_len",        "urlp",          pat_parse_int,     pat_match_len     },
-       { "urlp_reg",        "urlp",          pat_parse_reg,     pat_match_reg     },
-       { "urlp_sub",        "urlp",          pat_parse_str,     pat_match_sub     },
+       { "base",            "base",     pat_parse_str,  pat_idx_tree_str, pat_match_str  },
+       { "base_beg",        "base",     pat_parse_str,  pat_idx_list_str, pat_match_beg  },
+       { "base_dir",        "base",     pat_parse_str,  pat_idx_list_str, pat_match_dir  },
+       { "base_dom",        "base",     pat_parse_str,  pat_idx_list_str, pat_match_dom  },
+       { "base_end",        "base",     pat_parse_str,  pat_idx_list_str, pat_match_end  },
+       { "base_len",        "base",     pat_parse_int,  pat_idx_list_val, pat_match_len  },
+       { "base_reg",        "base",     pat_parse_reg,  pat_idx_list_reg, pat_match_reg  },
+       { "base_sub",        "base",     pat_parse_str,  pat_idx_list_str, pat_match_sub  },
+
+       { "cook",            "req.cook", pat_parse_str,  pat_idx_tree_str, pat_match_str  },
+       { "cook_beg",        "req.cook", pat_parse_str,  pat_idx_list_str, pat_match_beg  },
+       { "cook_dir",        "req.cook", pat_parse_str,  pat_idx_list_str, pat_match_dir  },
+       { "cook_dom",        "req.cook", pat_parse_str,  pat_idx_list_str, pat_match_dom  },
+       { "cook_end",        "req.cook", pat_parse_str,  pat_idx_list_str, pat_match_end  },
+       { "cook_len",        "req.cook", pat_parse_int,  pat_idx_list_val, pat_match_len  },
+       { "cook_reg",        "req.cook", pat_parse_reg,  pat_idx_list_reg, pat_match_reg  },
+       { "cook_sub",        "req.cook", pat_parse_str,  pat_idx_list_str, pat_match_sub  },
+
+       { "hdr",             "req.hdr",  pat_parse_str,  pat_idx_tree_str, pat_match_str  },
+       { "hdr_beg",         "req.hdr",  pat_parse_str,  pat_idx_list_str, pat_match_beg  },
+       { "hdr_dir",         "req.hdr",  pat_parse_str,  pat_idx_list_str, pat_match_dir  },
+       { "hdr_dom",         "req.hdr",  pat_parse_str,  pat_idx_list_str, pat_match_dom  },
+       { "hdr_end",         "req.hdr",  pat_parse_str,  pat_idx_list_str, pat_match_end  },
+       { "hdr_len",         "req.hdr",  pat_parse_int,  pat_idx_list_val, pat_match_len  },
+       { "hdr_reg",         "req.hdr",  pat_parse_reg,  pat_idx_list_reg, pat_match_reg  },
+       { "hdr_sub",         "req.hdr",  pat_parse_str,  pat_idx_list_str, pat_match_sub  },
+
+       { "http_auth_group", NULL,       pat_parse_str,  pat_idx_list_str, pat_match_auth },
+
+       { "method",          NULL,       pat_parse_meth, pat_idx_list_str, pat_match_meth },
+
+       { "path",            "path",     pat_parse_str,  pat_idx_tree_str, pat_match_str  },
+       { "path_beg",        "path",     pat_parse_str,  pat_idx_list_str, pat_match_beg  },
+       { "path_dir",        "path",     pat_parse_str,  pat_idx_list_str, pat_match_dir  },
+       { "path_dom",        "path",     pat_parse_str,  pat_idx_list_str, pat_match_dom  },
+       { "path_end",        "path",     pat_parse_str,  pat_idx_list_str, pat_match_end  },
+       { "path_len",        "path",     pat_parse_int,  pat_idx_list_val, pat_match_len  },
+       { "path_reg",        "path",     pat_parse_reg,  pat_idx_list_reg, pat_match_reg  },
+       { "path_sub",        "path",     pat_parse_str,  pat_idx_list_str, pat_match_sub  },
+
+       { "req_ver",         "req.ver",  pat_parse_str,  pat_idx_tree_str, pat_match_str  },
+       { "resp_ver",        "res.ver",  pat_parse_str,  pat_idx_tree_str, pat_match_str  },
+
+       { "scook",           "res.cook", pat_parse_str,  pat_idx_tree_str, pat_match_str  },
+       { "scook_beg",       "res.cook", pat_parse_str,  pat_idx_list_str, pat_match_beg  },
+       { "scook_dir",       "res.cook", pat_parse_str,  pat_idx_list_str, pat_match_dir  },
+       { "scook_dom",       "res.cook", pat_parse_str,  pat_idx_list_str, pat_match_dom  },
+       { "scook_end",       "res.cook", pat_parse_str,  pat_idx_list_str, pat_match_end  },
+       { "scook_len",       "res.cook", pat_parse_int,  pat_idx_list_val, pat_match_len  },
+       { "scook_reg",       "res.cook", pat_parse_reg,  pat_idx_list_reg, pat_match_reg  },
+       { "scook_sub",       "res.cook", pat_parse_str,  pat_idx_list_str, pat_match_sub  },
+
+       { "shdr",            "res.hdr",  pat_parse_str,  pat_idx_tree_str, pat_match_str  },
+       { "shdr_beg",        "res.hdr",  pat_parse_str,  pat_idx_list_str, pat_match_beg  },
+       { "shdr_dir",        "res.hdr",  pat_parse_str,  pat_idx_list_str, pat_match_dir  },
+       { "shdr_dom",        "res.hdr",  pat_parse_str,  pat_idx_list_str, pat_match_dom  },
+       { "shdr_end",        "res.hdr",  pat_parse_str,  pat_idx_list_str, pat_match_end  },
+       { "shdr_len",        "res.hdr",  pat_parse_int,  pat_idx_list_val, pat_match_len  },
+       { "shdr_reg",        "res.hdr",  pat_parse_reg,  pat_idx_list_reg, pat_match_reg  },
+       { "shdr_sub",        "res.hdr",  pat_parse_str,  pat_idx_list_str, pat_match_sub  },
+
+       { "url",             "url",      pat_parse_str,  pat_idx_tree_str, pat_match_str  },
+       { "url_beg",         "url",      pat_parse_str,  pat_idx_list_str, pat_match_beg  },
+       { "url_dir",         "url",      pat_parse_str,  pat_idx_list_str, pat_match_dir  },
+       { "url_dom",         "url",      pat_parse_str,  pat_idx_list_str, pat_match_dom  },
+       { "url_end",         "url",      pat_parse_str,  pat_idx_list_str, pat_match_end  },
+       { "url_len",         "url",      pat_parse_int,  pat_idx_list_val, pat_match_len  },
+       { "url_reg",         "url",      pat_parse_reg,  pat_idx_list_reg, pat_match_reg  },
+       { "url_sub",         "url",      pat_parse_str,  pat_idx_list_str, pat_match_sub  },
+
+       { "urlp",            "urlp",     pat_parse_str,  pat_idx_tree_str, pat_match_str  },
+       { "urlp_beg",        "urlp",     pat_parse_str,  pat_idx_list_str, pat_match_beg  },
+       { "urlp_dir",        "urlp",     pat_parse_str,  pat_idx_list_str, pat_match_dir  },
+       { "urlp_dom",        "urlp",     pat_parse_str,  pat_idx_list_str, pat_match_dom  },
+       { "urlp_end",        "urlp",     pat_parse_str,  pat_idx_list_str, pat_match_end  },
+       { "urlp_len",        "urlp",     pat_parse_int,  pat_idx_list_val, pat_match_len  },
+       { "urlp_reg",        "urlp",     pat_parse_reg,  pat_idx_list_reg, pat_match_reg  },
+       { "urlp_sub",        "urlp",     pat_parse_str,  pat_idx_list_str, pat_match_sub  },
 
        { /* END */ },
 }};
index b095f8c1a58cbdd5f9d31bbc0bb655614705820c..188c1e3275b66e50d0dd00195ed711e1d118536c 100644 (file)
@@ -3540,31 +3540,31 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
  * Please take care of keeping this list alphabetically sorted.
  */
 static struct acl_kw_list acl_kws = {ILH, {
-       { "ssl_c_i_dn",             NULL,         pat_parse_str,     pat_match_str     },
-       { "ssl_c_key_alg",          NULL,         pat_parse_str,     pat_match_str     },
-       { "ssl_c_notafter",         NULL,         pat_parse_str,     pat_match_str     },
-       { "ssl_c_notbefore",        NULL,         pat_parse_str,     pat_match_str     },
-       { "ssl_c_sig_alg",          NULL,         pat_parse_str,     pat_match_str     },
-       { "ssl_c_s_dn",             NULL,         pat_parse_str,     pat_match_str     },
-       { "ssl_c_serial",           NULL,         pat_parse_bin,     pat_match_bin     },
-       { "ssl_f_i_dn",             NULL,         pat_parse_str,     pat_match_str     },
-       { "ssl_f_key_alg",          NULL,         pat_parse_str,     pat_match_str     },
-       { "ssl_f_notafter",         NULL,         pat_parse_str,     pat_match_str     },
-       { "ssl_f_notbefore",        NULL,         pat_parse_str,     pat_match_str     },
-       { "ssl_f_sig_alg",          NULL,         pat_parse_str,     pat_match_str     },
-       { "ssl_f_s_dn",             NULL,         pat_parse_str,     pat_match_str     },
-       { "ssl_f_serial",           NULL,         pat_parse_bin,     pat_match_bin     },
-       { "ssl_fc_cipher",          NULL,         pat_parse_str,     pat_match_str     },
+       { "ssl_c_i_dn",             NULL,         pat_parse_str, pat_idx_tree_str, pat_match_str     },
+       { "ssl_c_key_alg",          NULL,         pat_parse_str, pat_idx_tree_str, pat_match_str     },
+       { "ssl_c_notafter",         NULL,         pat_parse_str, pat_idx_tree_str, pat_match_str     },
+       { "ssl_c_notbefore",        NULL,         pat_parse_str, pat_idx_tree_str, pat_match_str     },
+       { "ssl_c_sig_alg",          NULL,         pat_parse_str, pat_idx_tree_str, pat_match_str     },
+       { "ssl_c_s_dn",             NULL,         pat_parse_str, pat_idx_tree_str, pat_match_str     },
+       { "ssl_c_serial",           NULL,         pat_parse_bin, pat_idx_list_ptr, pat_match_bin     },
+       { "ssl_f_i_dn",             NULL,         pat_parse_str, pat_idx_tree_str, pat_match_str     },
+       { "ssl_f_key_alg",          NULL,         pat_parse_str, pat_idx_tree_str, pat_match_str     },
+       { "ssl_f_notafter",         NULL,         pat_parse_str, pat_idx_tree_str, pat_match_str     },
+       { "ssl_f_notbefore",        NULL,         pat_parse_str, pat_idx_tree_str, pat_match_str     },
+       { "ssl_f_sig_alg",          NULL,         pat_parse_str, pat_idx_tree_str, pat_match_str     },
+       { "ssl_f_s_dn",             NULL,         pat_parse_str, pat_idx_tree_str, pat_match_str     },
+       { "ssl_f_serial",           NULL,         pat_parse_bin, pat_idx_list_ptr, pat_match_bin     },
+       { "ssl_fc_cipher",          NULL,         pat_parse_str, pat_idx_tree_str, pat_match_str     },
 #ifdef OPENSSL_NPN_NEGOTIATED
-       { "ssl_fc_npn",             NULL,         pat_parse_str,     pat_match_str     },
+       { "ssl_fc_npn",             NULL,         pat_parse_str, pat_idx_tree_str, pat_match_str     },
 #endif
 #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
-       { "ssl_fc_alpn",            NULL,         pat_parse_str,     pat_match_str     },
+       { "ssl_fc_alpn",            NULL,         pat_parse_str, pat_idx_tree_str, pat_match_str     },
 #endif
-       { "ssl_fc_protocol",        NULL,         pat_parse_str,     pat_match_str     },
-       { "ssl_fc_sni",             "ssl_fc_sni", pat_parse_str,     pat_match_str     },
-       { "ssl_fc_sni_end",         "ssl_fc_sni", pat_parse_str,     pat_match_end     },
-       { "ssl_fc_sni_reg",         "ssl_fc_sni", pat_parse_reg,     pat_match_reg     },
+       { "ssl_fc_protocol",        NULL,         pat_parse_str, pat_idx_tree_str, pat_match_str     },
+       { "ssl_fc_sni",             "ssl_fc_sni", pat_parse_str, pat_idx_tree_str, pat_match_str     },
+       { "ssl_fc_sni_end",         "ssl_fc_sni", pat_parse_str, pat_idx_list_str, pat_match_end     },
+       { "ssl_fc_sni_reg",         "ssl_fc_sni", pat_parse_reg, pat_idx_list_reg, pat_match_reg     },
        { /* END */ },
 }};