/* pattern management function arrays */
extern char *pat_match_names[PAT_MATCH_NUM];
-extern int (*pat_parse_fcts[PAT_MATCH_NUM])(const char *, struct pattern *, char **);
+extern int (*pat_parse_fcts[PAT_MATCH_NUM])(const char *, struct pattern *, int, char **);
extern int (*pat_index_fcts[PAT_MATCH_NUM])(struct pattern_expr *, struct pattern *, char **);
extern void (*pat_delete_fcts[PAT_MATCH_NUM])(struct pattern_expr *, struct pat_ref_elt *);
extern void (*pat_prune_fcts[PAT_MATCH_NUM])(struct pattern_expr *);
/* ignore the current line */
-int pat_parse_nothing(const char *text, struct pattern *pattern, char **err);
+int pat_parse_nothing(const char *text, struct pattern *pattern, int mflags, char **err);
/* Parse an integer. It is put both in min and max. */
-int pat_parse_int(const char *text, struct pattern *pattern, char **err);
+int pat_parse_int(const char *text, struct pattern *pattern, int mflags, char **err);
/* Parse an version. It is put both in min and max. */
-int pat_parse_dotted_ver(const char *text, struct pattern *pattern, char **err);
+int pat_parse_dotted_ver(const char *text, struct pattern *pattern, int mflags, char **err);
/* Parse a range of integers delimited by either ':' or '-'. If only one
* integer is read, it is set as both min and max.
*/
-int pat_parse_range(const char *text, struct pattern *pattern, char **err);
+int pat_parse_range(const char *text, struct pattern *pattern, int mflags, char **err);
/* Parse a string. It is allocated and duplicated. */
-int pat_parse_str(const char *text, struct pattern *pattern, char **err);
+int pat_parse_str(const char *text, struct pattern *pattern, int mflags, char **err);
/* Parse a hexa binary definition. It is allocated and duplicated. */
-int pat_parse_bin(const char *text, struct pattern *pattern, char **err);
+int pat_parse_bin(const char *text, struct pattern *pattern, int mflags, char **err);
/* Parse a regex. It is allocated. */
-int pat_parse_reg(const char *text, struct pattern *pattern, char **err);
+int pat_parse_reg(const char *text, struct pattern *pattern, int mflags, char **err);
/* Parse an IP address and an optional mask in the form addr[/mask].
* The addr may either be an IPv4 address or a hostname. The mask
* may either be a dotted mask or a number of bits. Returns 1 if OK,
* otherwise 0.
*/
-int pat_parse_ip(const char *text, struct pattern *pattern, char **err);
+int pat_parse_ip(const char *text, struct pattern *pattern, int mflags, char **err);
/* NB: For two strings to be identical, it is required that their lengths match */
struct pattern *pat_match_str(struct sample *smp, struct pattern_expr *expr, int fill);
struct pat_ref *pat_ref_newid(int unique_id, const char *display, unsigned int flags);
struct pat_ref_elt *pat_ref_find_elt(struct pat_ref *ref, const char *key);
int pat_ref_append(struct pat_ref *ref, char *pattern, char *sample, int line);
-int pat_ref_add(struct pat_ref *ref, const char *pattern, const char *sample, int patflags, char **err);
+int pat_ref_add(struct pat_ref *ref, const char *pattern, const char *sample, char **err);
int pat_ref_set(struct pat_ref *ref, const char *pattern, const char *sample, char **err);
int pat_ref_set_by_id(struct pat_ref *ref, struct pat_ref_elt *refelt, const char *value, char **err);
int pat_ref_delete(struct pat_ref *ref, const char *key);
const char *kw;
char *fetch_kw;
int match_type; /* Contain PAT_MATCH_* */
- int (*parse)(const char *text, struct pattern *pattern, char **err);
+ int (*parse)(const char *text, struct pattern *pattern, int flags, char **err);
int (*index)(struct pattern_expr *expr, struct pattern *pattern, char **err);
void (*delete)(struct pattern_expr *expr, struct pat_ref_elt *);
void (*prune)(struct pattern_expr *expr);
PAT_MATCH = 3, /* sample matched at least one pattern */
};
-/* possible flags for expressions or patterns */
+/* possible flags for patterns matching or parsing */
enum {
- PAT_F_IGNORE_CASE = 1 << 0, /* ignore case */
- PAT_F_TREE = 1 << 1, /* some patterns are arranged in a tree */
- PAT_F_NO_DNS = 1 << 2, /* dont perform any DNS requests */
+ PAT_MF_IGNORE_CASE = 1 << 0, /* ignore case */
+ PAT_MF_NO_DNS = 1 << 1, /* dont perform any DNS requests */
+};
+
+/* possible flags for patterns storage */
+enum {
+ PAT_SF_TREE = 1 << 0, /* some patterns are arranged in a tree */
};
/* ACL match methods */
struct my_regex *reg; /* a compiled regex */
} ptr; /* indirect values, allocated */
int len; /* data length when required */
- int flags; /* expr or pattern flags. */
+ int sflags; /* flags relative to the storage method. */
struct sample_storage *smp; /* used to store a pointer to sample value associated
with the match. It is used with maps */
struct pat_ref_elt *ref;
struct list patterns; /* list of acl_patterns */
struct eb_root pattern_tree; /* may be used for lookup in large datasets */
struct eb_root pattern_tree_2; /* may be used for different types */
+ int mflags; /* flags relative to the parsing or matching method. */
};
/* This is a list of expression. A struct pattern_expr can be used by
/* This struct contain a list of pattern expr */
struct pattern_head {
- int (*parse)(const char *text, struct pattern *pattern, char **err);
+ int (*parse)(const char *text, struct pattern *pattern, int flags, char **err);
int (*parse_smp)(const char *text, struct sample_storage *smp);
int (*index)(struct pattern_expr *, struct pattern *, char **);
void (*delete)(struct pattern_expr *, struct pat_ref_elt *);
unique_id = -1;
while (**args == '-') {
if ((*args)[1] == 'i')
- patflags |= PAT_F_IGNORE_CASE;
+ patflags |= PAT_MF_IGNORE_CASE;
else if ((*args)[1] == 'n')
- patflags |= PAT_F_NO_DNS;
+ patflags |= PAT_MF_NO_DNS;
else if ((*args)[1] == 'u') {
unique_id = strtol(args[1], &error, 10);
if (*error != '\0') {
if (!pattern_expr)
goto out_free_expr;
+ /* Copy the pattern matching and indexing flags. */
+ pattern_expr->mflags = patflags;
+
/* now parse all patterns */
while (**args) {
arg = *args;
/* Add sample to the reference, and try to compile it fior each pattern
* using this value.
*/
- if (!pat_ref_add(ref, arg, NULL, patflags, err))
+ if (!pat_ref_add(ref, arg, NULL, err))
goto out_free_expr;
args++;
}
/* Add value. */
err = NULL;
if (appctx->ctx.map.display_flags == PAT_REF_MAP)
- ret = pat_ref_add(appctx->ctx.map.ref, args[3], args[4], 0, &err);
+ ret = pat_ref_add(appctx->ctx.map.ref, args[3], args[4], &err);
else
- ret = pat_ref_add(appctx->ctx.map.ref, args[3], NULL, 0, &err);
+ ret = pat_ref_add(appctx->ctx.map.ref, args[3], NULL, &err);
if (!ret) {
if (err)
memprintf(&err, "%s.\n", err);
else
chunk_appendf(&trash, "type=%s", pat_match_names[match_method]);
+ /* case sensitive */
+ if (appctx->ctx.map.expr->mflags & PAT_MF_IGNORE_CASE)
+ chunk_appendf(&trash, ", case=insensitive");
+ else
+ chunk_appendf(&trash, ", case=sensitive");
+
/* Display no match, and set default value */
if (!pat) {
if (appctx->ctx.map.display_flags == PAT_REF_MAP)
chunk_appendf(&trash, ", match=yes");
/* display index mode */
- if (pat->flags & PAT_F_TREE)
+ if (pat->sflags & PAT_SF_TREE)
chunk_appendf(&trash, ", idx=tree");
else
chunk_appendf(&trash, ", idx=list");
- /* case sensitive */
- if (pat->flags & PAT_F_IGNORE_CASE)
- chunk_appendf(&trash, ", case=insensitive");
- else
- chunk_appendf(&trash, ", case=sensitive");
-
/* display pattern */
if (appctx->ctx.map.display_flags == PAT_REF_MAP) {
if (pat->ref && pat->ref->pattern)
}
/* Load map. */
- if (!pattern_read_from_file(&desc->pat, PAT_REF_MAP, arg[0].data.str.str, PAT_F_NO_DNS,
+ if (!pattern_read_from_file(&desc->pat, PAT_REF_MAP, arg[0].data.str.str, PAT_MF_NO_DNS,
1, err, file, line))
return 0;
[PAT_MATCH_REG] = "reg",
};
-int (*pat_parse_fcts[PAT_MATCH_NUM])(const char *, struct pattern *, char **) = {
+int (*pat_parse_fcts[PAT_MATCH_NUM])(const char *, struct pattern *, int, char **) = {
[PAT_MATCH_FOUND] = pat_parse_nothing,
[PAT_MATCH_BOOL] = pat_parse_nothing,
[PAT_MATCH_INT] = pat_parse_int,
*/
/* ignore the current line */
-int pat_parse_nothing(const char *text, struct pattern *pattern, char **err)
+int pat_parse_nothing(const char *text, struct pattern *pattern, int mflags, char **err)
{
return 1;
}
/* Parse a string. It is allocated and duplicated. */
-int pat_parse_str(const char *text, struct pattern *pattern, char **err)
+int pat_parse_str(const char *text, struct pattern *pattern, int mflags, char **err)
{
pattern->type = SMP_T_STR;
pattern->ptr.str = (char *)text;
}
/* Parse a binary written in hexa. It is allocated. */
-int pat_parse_bin(const char *text, struct pattern *pattern, char **err)
+int pat_parse_bin(const char *text, struct pattern *pattern, int mflags, char **err)
{
struct chunk *trash;
}
/* Parse a regex. It is allocated. */
-int pat_parse_reg(const char *text, struct pattern *pattern, char **err)
+int pat_parse_reg(const char *text, struct pattern *pattern, int mflags, char **err)
{
struct chunk *trash;
* non-zero on success.
*
*/
-int pat_parse_int(const char *text, struct pattern *pattern, char **err)
+int pat_parse_int(const char *text, struct pattern *pattern, int mflags, char **err)
{
const char *ptr = text;
* acl valid_ssl ssl_req_proto 3.0-3.1
*
*/
-int pat_parse_dotted_ver(const char *text, struct pattern *pattern, char **err)
+int pat_parse_dotted_ver(const char *text, struct pattern *pattern, int mflags, char **err)
{
const char *ptr = text;
* may either be a dotted mask or a number of bits. Returns 1 if OK,
* otherwise 0. NOTE: IP address patterns are typed (IPV4/IPV6).
*/
-int pat_parse_ip(const char *text, struct pattern *pattern, char **err)
+int pat_parse_ip(const char *text, struct pattern *pattern, int mflags, char **err)
{
- if (str2net(text, !(pattern->flags & PAT_F_NO_DNS) && (global.mode & MODE_STARTING),
+ if (str2net(text, !(mflags & PAT_MF_NO_DNS) && (global.mode & MODE_STARTING),
&pattern->val.ipv4.addr, &pattern->val.ipv4.mask)) {
pattern->type = SMP_T_IPV4;
return 1;
if (fill) {
static_pattern.smp = NULL;
static_pattern.ref = NULL;
- static_pattern.flags = 0;
static_pattern.type = 0;
static_pattern.ptr.str = NULL;
}
elt = ebmb_entry(node, struct pattern_tree, node);
static_pattern.smp = elt->smp;
static_pattern.ref = elt->ref;
- static_pattern.flags = PAT_F_TREE;
+ static_pattern.sflags = PAT_SF_TREE;
static_pattern.type = SMP_T_STR;
static_pattern.ptr.str = (char *)elt->node.key;
}
if (pattern->len != smp->data.str.len)
continue;
- icase = pattern->flags & PAT_F_IGNORE_CASE;
+ icase = expr->mflags & PAT_MF_IGNORE_CASE;
if ((icase && strncasecmp(pattern->ptr.str, smp->data.str.str, smp->data.str.len) == 0) ||
(!icase && strncmp(pattern->ptr.str, smp->data.str.str, smp->data.str.len) == 0))
return pattern;
if (pattern->len > smp->data.str.len)
continue;
- icase = pattern->flags & PAT_F_IGNORE_CASE;
+ icase = expr->mflags & PAT_MF_IGNORE_CASE;
if ((icase && strncasecmp(pattern->ptr.str, smp->data.str.str, pattern->len) != 0) ||
(!icase && strncmp(pattern->ptr.str, smp->data.str.str, pattern->len) != 0))
continue;
if (pattern->len > smp->data.str.len)
continue;
- icase = pattern->flags & PAT_F_IGNORE_CASE;
+ icase = expr->mflags & PAT_MF_IGNORE_CASE;
if ((icase && strncasecmp(pattern->ptr.str, smp->data.str.str + smp->data.str.len - pattern->len, pattern->len) != 0) ||
(!icase && strncmp(pattern->ptr.str, smp->data.str.str + smp->data.str.len - pattern->len, pattern->len) != 0))
continue;
continue;
end = smp->data.str.str + smp->data.str.len - pattern->len;
- icase = pattern->flags & PAT_F_IGNORE_CASE;
+ icase = expr->mflags & PAT_MF_IGNORE_CASE;
if (icase) {
for (c = smp->data.str.str; c <= end; c++) {
if (tolower(*c) != tolower(*pattern->ptr.str))
* provided as an unsigned int made by make_4delim() and match up to 4 different
* delimiters. Delimiters are stripped at the beginning and end of the pattern.
*/
-static int match_word(struct sample *smp, struct pattern *pattern, unsigned int delimiters)
+static int match_word(struct sample *smp, struct pattern *pattern, int mflags, unsigned int delimiters)
{
int may_match, icase;
char *c, *end;
return PAT_NOMATCH;
may_match = 1;
- icase = pattern->flags & PAT_F_IGNORE_CASE;
+ icase = mflags & PAT_MF_IGNORE_CASE;
end = smp->data.str.str + smp->data.str.len - pl;
for (c = smp->data.str.str; c <= end; c++) {
if (is_delimiter(*c, delimiters)) {
list_for_each_entry(lst, &expr->patterns, list) {
pattern = &lst->pat;
- if (match_word(smp, pattern, make_4delim('/', '?', '?', '?')))
+ if (match_word(smp, pattern, expr->mflags, make_4delim('/', '?', '?', '?')))
return pattern;
}
return NULL;
list_for_each_entry(lst, &expr->patterns, list) {
pattern = &lst->pat;
- if (match_word(smp, pattern, make_4delim('/', '?', '.', ':')))
+ if (match_word(smp, pattern, expr->mflags, make_4delim('/', '?', '.', ':')))
return pattern;
}
return NULL;
elt = ebmb_entry(node, struct pattern_tree, node);
static_pattern.smp = elt->smp;
static_pattern.ref = elt->ref;
- static_pattern.flags = PAT_F_TREE;
+ static_pattern.sflags = PAT_SF_TREE;
static_pattern.type = SMP_T_IPV4;
memcpy(&static_pattern.val.ipv4.addr.s_addr, elt->node.key, 4);
if (!cidr2dotted(elt->node.node.pfx, &static_pattern.val.ipv4.mask))
elt = ebmb_entry(node, struct pattern_tree, node);
static_pattern.smp = elt->smp;
static_pattern.ref = elt->ref;
- static_pattern.flags = PAT_F_TREE;
+ static_pattern.sflags = PAT_SF_TREE;
static_pattern.type = SMP_T_IPV6;
memcpy(&static_pattern.val.ipv6.addr, elt->node.key, 16);
static_pattern.val.ipv6.mask = elt->node.node.pfx;
elt = ebmb_entry(node, struct pattern_tree, node);
static_pattern.smp = elt->smp;
static_pattern.ref = elt->ref;
- static_pattern.flags = PAT_F_TREE;
+ static_pattern.sflags = PAT_SF_TREE;
static_pattern.type = SMP_T_IPV6;
memcpy(&static_pattern.val.ipv6.addr, elt->node.key, 16);
static_pattern.val.ipv6.mask = elt->node.node.pfx;
elt = ebmb_entry(node, struct pattern_tree, node);
static_pattern.smp = elt->smp;
static_pattern.ref = elt->ref;
- static_pattern.flags = PAT_F_TREE;
+ static_pattern.sflags = PAT_SF_TREE;
static_pattern.type = SMP_T_IPV4;
memcpy(&static_pattern.val.ipv4.addr.s_addr, elt->node.key, 4);
if (!cidr2dotted(elt->node.node.pfx, &static_pattern.val.ipv4.mask))
}
/* compile regex */
- if (!regex_comp(pat->ptr.str, patl->pat.ptr.reg, !(patl->pat.flags & PAT_F_IGNORE_CASE), 0, err)) {
+ if (!regex_comp(pat->ptr.str, patl->pat.ptr.reg, !(expr->mflags & PAT_MF_IGNORE_CASE), 0, err)) {
free(patl);
free(patl->pat.ptr.reg);
return 0;
}
/* If the flag PAT_F_IGNORE_CASE is set, we cannot use trees */
- if (pat->flags & PAT_F_IGNORE_CASE)
+ if (expr->mflags & PAT_MF_IGNORE_CASE)
return pat_idx_list_str(expr, pat, err);
/* Process the key len */
/* initialise pattern */
memset(&pattern, 0, sizeof(pattern));
- pattern.flags = patflags;
pattern.smp = smp;
pattern.ref = elt;
/* parse pattern */
- if (!expr->pat_head->parse(elt->pattern, &pattern, err)) {
+ if (!expr->pat_head->parse(elt->pattern, &pattern, expr->mflags, err)) {
free(smp);
return 0;
}
*/
int pat_ref_add(struct pat_ref *ref,
const char *pattern, const char *sample,
- int patflags, char **err)
+ char **err)
{
struct pat_ref_elt *elt;
struct pattern_expr *expr;
LIST_ADDQ(&ref->head, &elt->list);
list_for_each_entry(expr, &ref->pat, list) {
- if (!pat_ref_push(elt, expr, patflags, err)) {
+ if (!pat_ref_push(elt, expr, 0, err)) {
/* If the insertion fails, try to delete all the added entries. */
pat_ref_delete_by_id(ref, elt);
return 0;
* doesn't exists, create it.
*/
expr = pattern_lookup_expr(head, ref);
- if (!expr) {
+ if (!expr || (expr->mflags != patflags)) {
expr = pattern_new_expr(head, ref, err);
if (!expr)
return 0;
+ expr->mflags = patflags;
}
/* Load reference content in the pattern expression. */
if (fill) {
static_pattern.smp = NULL;
static_pattern.ref = NULL;
- static_pattern.flags = 0;
+ static_pattern.sflags = 0;
static_pattern.type = SMP_T_UINT;
static_pattern.val.i = 1;
}
/* perform update */
/* add entry only if it does not already exist */
if (pat_ref_find_elt(ref, key) == NULL)
- pat_ref_add(ref, key, NULL, 0, NULL);
+ pat_ref_add(ref, key, NULL, NULL);
break;
}
pat_ref_set(ref, key, value, NULL);
else
/* insert a new entry */
- pat_ref_add(ref, key, value, 0, NULL);
+ pat_ref_add(ref, key, value, NULL);
break;
}
/* perform update */
/* check if the entry already exists */
if (pat_ref_find_elt(ref, key) == NULL)
- pat_ref_add(ref, key, NULL, 0, NULL);
+ pat_ref_add(ref, key, NULL, NULL);
break;
}
pat_ref_set(ref, key, value, NULL);
else
/* insert a new entry */
- pat_ref_add(ref, key, value, 0, NULL);
+ pat_ref_add(ref, key, value, NULL);
break;
}
* We use the pre-parsed method if it is known, and store its number as an
* integer. If it is unknown, we use the pointer and the length.
*/
-static int pat_parse_meth(const char *text, struct pattern *pattern, char **err)
+static int pat_parse_meth(const char *text, struct pattern *pattern, int mflags, char **err)
{
int len, meth;
struct chunk *trash;
if (pattern->len != smp->data.meth.str.len)
continue;
- icase = pattern->flags & PAT_F_IGNORE_CASE;
+ icase = expr->mflags & PAT_MF_IGNORE_CASE;
if ((icase && strncasecmp(pattern->ptr.str, smp->data.meth.str.str, smp->data.meth.str.len) != 0) ||
(!icase && strncmp(pattern->ptr.str, smp->data.meth.str.str, smp->data.meth.str.len) != 0))
return pattern;