]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: acl: add types to ACL patterns
authorWilly Tarreau <w@1wt.eu>
Fri, 27 Apr 2012 20:10:57 +0000 (22:10 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 8 May 2012 18:57:21 +0000 (20:57 +0200)
We cannot currently match IPv6 addresses in ACL simply because we don't
support types on the patterns. Let's introduce this notion. For now, we
rely on the SMP_TYPES though it doesn't seem like it will last forever
given that some types are not present there (eg: regex, meth). Still it
should be enough to support mixed matchings for most types.

We use the special impossible value SMP_TYPES for types that don't exist
in the SMP_T_* space.

include/types/acl.h
src/acl.c

index ed8582b7c62028f2f43b01adf3a0bea559844a0b..492e9639f21627a3e984c75a40df4996b3b20c9b 100644 (file)
@@ -181,9 +181,16 @@ struct acl_time {
        int h2:5, m2:6;         /* 0..24:0..60. Use 24:0 for all day. */
 };
 
-/* The acl will be linked to from the proxy where it is declared */
+/* This describes one ACL pattern, which might be a single value or a tree of
+ * values. All patterns for a single ACL expression are linked together. Some
+ * of them might have a type (eg: IP). Right now, the types are shared with
+ * the samples, though it is possible that in the future this will change to
+ * accommodate for other types (eg: meth, regex). Unsigned and constant types
+ * are preferred when there is a doubt.
+ */
 struct acl_pattern {
        struct list list;                       /* chaining */
+       int type;                               /* type of the ACL pattern (SMP_T_*) */
        union {
                int i;                          /* integer value */
                struct {
@@ -209,14 +216,13 @@ struct acl_pattern {
        int flags;                      /* expr or pattern flags. */
 };
 
-/*
- * ACL keyword: Associates keywords with parsers, methods to retrieve the value and testers.
- */
-
 /* some dummy declarations to silent the compiler */
 struct proxy;
 struct session;
 
+/*
+ * ACL keyword: Associates keywords with parsers, methods to retrieve the value and testers.
+ */
 /*
  * NOTE:
  * The 'parse' function is called to parse words in the configuration. It must
@@ -268,6 +274,7 @@ struct acl_expr {
        struct eb_root pattern_tree;  /* may be used for lookup in large datasets */
 };
 
+/* The acl will be linked to from the proxy where it is declared */
 struct acl {
        struct list list;           /* chaining */
        char *name;                 /* acl name */
index a1346b8c804c2d908dda3613dc6ed963a33c1e75..013820364abd489320d56b727ae69fe9c3c4a3ee 100644 (file)
--- a/src/acl.c
+++ b/src/acl.c
@@ -709,7 +709,7 @@ int acl_match_ip(struct sample *smp, struct acl_pattern *pattern)
 {
        struct in_addr *s;
 
-       if (smp->type != SMP_T_IPV4)
+       if (smp->type != SMP_T_IPV4 || pattern->type != SMP_T_IPV4)
                return ACL_PAT_FAIL;
 
        s = &smp->data.ipv4;
@@ -738,6 +738,7 @@ int acl_parse_str(const char **text, struct acl_pattern *pattern, int *opaque, c
        int len;
 
        len  = strlen(*text);
+       pattern->type = SMP_T_CSTR;
 
        if (pattern->flags & ACL_PAT_F_TREE_OK) {
                /* we're allowed to put the data in a tree whose root is pointed
@@ -779,6 +780,7 @@ acl_parse_strcat(const char **text, struct acl_pattern *pattern, int *opaque, ch
        for (i = 0; *text[i]; i++)
                len += strlen(text[i])+1;
 
+       pattern->type = SMP_T_CSTR;
        pattern->ptr.str = s = calloc(1, len);
        if (!pattern->ptr.str) {
                if (err)
@@ -847,7 +849,7 @@ int acl_parse_int(const char **text, struct acl_pattern *pattern, int *opaque, c
        unsigned int j, last, skip = 0;
        const char *ptr = *text;
 
-
+       pattern->type = SMP_T_UINT;
        while (!isdigit((unsigned char)*ptr)) {
                switch (get_std_op(ptr)) {
                case STD_OP_EQ: *opaque = 0; break;
@@ -1023,7 +1025,7 @@ int acl_parse_dotted_ver(const char **text, struct acl_pattern *pattern, int *op
 /* 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.
+ * otherwise 0. NOTE: IP address patterns are typed (IPV4/IPV6).
  */
 int acl_parse_ip(const char **text, struct acl_pattern *pattern, int *opaque, char **err)
 {
@@ -1031,6 +1033,7 @@ int acl_parse_ip(const char **text, struct acl_pattern *pattern, int *opaque, ch
        if (pattern->flags & ACL_PAT_F_TREE_OK)
                tree = pattern->val.tree;
 
+       pattern->type = SMP_T_IPV4;
        if (str2net(*text, &pattern->val.ipv4.addr, &pattern->val.ipv4.mask)) {
                unsigned int mask = ntohl(pattern->val.ipv4.mask.s_addr);
                struct ebmb_node *node;
@@ -1248,6 +1251,7 @@ static int acl_read_patterns_from_file(   struct acl_keyword *aclkw,
                        pattern->val.tree = &expr->pattern_tree;
                }
 
+               pattern->type = SMP_TYPES; /* unspecified type by default */
                if (!aclkw->parse(args, pattern, &opaque, err))
                        goto out_free_pattern;
 
@@ -1416,6 +1420,7 @@ struct acl_expr *parse_acl_expr(const char **args, char **err)
                }
                pattern->flags = patflags;
 
+               pattern->type = SMP_TYPES; /* unspecified type */
                ret = aclkw->parse(args, pattern, &opaque, err);
                if (!ret)
                        goto out_free_pattern;