]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: sample: let the cast functions set their output type
authorThierry FOURNIER <tfournier@exceliance.fr>
Tue, 26 Nov 2013 19:47:54 +0000 (20:47 +0100)
committerWilly Tarreau <w@1wt.eu>
Mon, 2 Dec 2013 22:31:33 +0000 (23:31 +0100)
This patch allows each sample cast function to specify the sample
output type. The goal is to be able to emit an output type IPv4 or
IPv6 depending on what is found in the input if the next converter
is able to process them both.

The patch also adds a new pseudo type called "ADDR". This type is an
alias for IPV4 and IPV6 which is only used as an input type by converters
who want to express their compatibility with both address formats. It may
not be emitted.

The goal is to unify as much as possible the processing of IPv4 and IPv6
in order not to add extra keywords for the maps which act as converters,
but will match samples like ACLs do with their patterns.

include/types/sample.h
src/sample.c
src/stick_table.c

index 4c1a244826a6850fea4349388e8fccbfff3f4483..a2d2296c8ba87be6982ebeb35cf6e6360a05ee6c 100644 (file)
@@ -35,6 +35,7 @@ enum {
        SMP_T_BOOL = 0,  /* boolean */
        SMP_T_UINT,      /* unsigned 32bits integer type */
        SMP_T_SINT,      /* signed 32bits integer type */
+       SMP_T_ADDR,      /* ipv4 or ipv6, only used for input type compatibility */
        SMP_T_IPV4,      /* ipv4 type */
        SMP_T_IPV6,      /* ipv6 type */
        SMP_T_STR,       /* char string type */
index 162c9495371470013e391bd12fc20b4477084e5a..a4a2773b0a423e100764cb5f28d4bb96f728e2a3 100644 (file)
@@ -397,6 +397,7 @@ struct sample_conv *find_sample_conv(const char *kw, int len)
 static int c_ip2int(struct sample *smp)
 {
        smp->data.uint = ntohl(smp->data.ipv4.s_addr);
+       smp->type = SMP_T_UINT;
        return 1;
 }
 
@@ -409,6 +410,7 @@ static int c_ip2str(struct sample *smp)
 
        trash->len = strlen(trash->str);
        smp->data.str = *trash;
+       smp->type = SMP_T_STR;
 
        return 1;
 }
@@ -416,6 +418,7 @@ static int c_ip2str(struct sample *smp)
 static int c_ip2ipv6(struct sample *smp)
 {
        v4tov6(&smp->data.ipv6, &smp->data.ipv4);
+       smp->type = SMP_T_IPV6;
        return 1;
 }
 
@@ -428,6 +431,7 @@ static int c_ipv62str(struct sample *smp)
 
        trash->len = strlen(trash->str);
        smp->data.str = *trash;
+       smp->type = SMP_T_STR;
        return 1;
 }
 
@@ -441,6 +445,21 @@ static int c_ipv62ip(struct sample *smp)
 static int c_int2ip(struct sample *smp)
 {
        smp->data.ipv4.s_addr = htonl(smp->data.uint);
+       smp->type = SMP_T_IPV4;
+       return 1;
+}
+
+static int c_str2addr(struct sample *smp)
+{
+       int ret;
+
+       if (!buf2ip(smp->data.str.str, smp->data.str.len, &smp->data.ipv4)) {
+               ret = inet_pton(AF_INET6, smp->data.str.str, &smp->data.ipv6);
+               if (ret)
+                       smp->type = SMP_T_IPV6;
+               return ret;
+       }
+       smp->type = SMP_T_IPV4;
        return 1;
 }
 
@@ -448,12 +467,18 @@ static int c_str2ip(struct sample *smp)
 {
        if (!buf2ip(smp->data.str.str, smp->data.str.len, &smp->data.ipv4))
                return 0;
+       smp->type = SMP_T_IPV4;
        return 1;
 }
 
 static int c_str2ipv6(struct sample *smp)
 {
-       return inet_pton(AF_INET6, smp->data.str.str, &smp->data.ipv6);
+       int ret;
+
+       ret = inet_pton(AF_INET6, smp->data.str.str, &smp->data.ipv6);
+       if (ret)
+               smp->type = SMP_T_IPV6;
+       return ret;
 }
 
 static int c_bin2str(struct sample *smp)
@@ -469,6 +494,7 @@ static int c_bin2str(struct sample *smp)
                trash->str[trash->len++] = hextab[c & 0xF];
        }
        smp->data.str = *trash;
+       smp->type = SMP_T_STR;
        return 1;
 }
 
@@ -486,16 +512,33 @@ static int c_int2str(struct sample *smp)
        trash->str = pos;
        trash->len = strlen(pos);
        smp->data.str = *trash;
+       smp->type = SMP_T_STR;
        return 1;
 }
 
-static inc_datadup(struct sample *smp)
+static inline void _c_datadup(struct sample *smp)
 {
        struct chunk *trash = get_trash_chunk();
 
        trash->len = smp->data.str.len < trash->size ? smp->data.str.len : trash->size;
        memcpy(trash->str, smp->data.str.str, trash->len);
        smp->data.str = *trash;
+}
+
+static int c_datadup(struct sample *smp)
+{
+       _c_datadup(smp);
+       if (smp->type == SMP_T_CSTR)
+               smp->type = SMP_T_STR;
+       else
+               smp->type = SMP_T_BIN;
+       return 1;
+}
+
+static int c_bindup(struct sample *smp)
+{
+       _c_datadup(smp);
+       smp->type = SMP_T_BIN;
        return 1;
 }
 
@@ -520,6 +563,7 @@ static int c_str2int(struct sample *smp)
        }
 
        smp->data.uint = ret;
+       smp->type = SMP_T_UINT;
        return 1;
 }
 
@@ -530,16 +574,17 @@ static int c_str2int(struct sample *smp)
 /*****************************************************************/
 
 sample_cast_fct sample_casts[SMP_TYPES][SMP_TYPES] = {
-/*            to:  BOOL       UINT       SINT       IPV4      IPV6        STR         BIN        CSTR        CBIN   */
-/* from: BOOL */ { c_none,    c_none,    c_none,    NULL,     NULL,       c_int2str,  NULL,      c_int2str,  NULL   },
-/*       UINT */ { c_none,    c_none,    c_none,    c_int2ip, NULL,       c_int2str,  NULL,      c_int2str,  NULL   },
-/*       SINT */ { c_none,    c_none,    c_none,    c_int2ip, NULL,       c_int2str,  NULL,      c_int2str,  NULL   },
-/*       IPV4 */ { NULL,      c_ip2int,  c_ip2int,  c_none,   c_ip2ipv6,  c_ip2str,   NULL,      c_ip2str,   NULL   },
-/*       IPV6 */ { NULL,      NULL,      NULL,      NULL,     c_none,     c_ipv62str, NULL,      c_ipv62str, NULL   },
-/*        STR */ { c_str2int, c_str2int, c_str2int, c_str2ip, c_str2ipv6, c_none,     c_none,    c_none,     c_none },
-/*        BIN */ { NULL,      NULL,      NULL,      NULL,     NULL,       c_bin2str,  c_none,    c_bin2str,  c_none },
-/*       CSTR */ { c_str2int, c_str2int, c_str2int, c_str2ip, c_str2ipv6, c_datadup,  c_datadup, c_none,     c_none },
-/*       CBIN */ { NULL,      NULL,      NULL,      NULL,     NULL,       c_bin2str,  c_datadup, c_bin2str,  c_none },
+/*            to:  BOOL       UINT       SINT       ADDR        IPV4      IPV6        STR         BIN        CSTR        CBIN    */
+/* from: BOOL */ { c_none,    c_none,    c_none,    NULL,       NULL,     NULL,       c_int2str,  NULL,      c_int2str,  NULL,   },
+/*       UINT */ { c_none,    c_none,    c_none,    c_int2ip,   c_int2ip, NULL,       c_int2str,  NULL,      c_int2str,  NULL,   },
+/*       SINT */ { c_none,    c_none,    c_none,    c_int2ip,   c_int2ip, NULL,       c_int2str,  NULL,      c_int2str,  NULL,   },
+/*       ADDR */ { NULL,      NULL,      NULL,      NULL,       NULL,     NULL,       NULL,       NULL,      NULL,       NULL,   },
+/*       IPV4 */ { NULL,      c_ip2int,  c_ip2int,  c_none,     c_none,   c_ip2ipv6,  c_ip2str,   NULL,      c_ip2str,   NULL,   },
+/*       IPV6 */ { NULL,      NULL,      NULL,      c_none,     NULL,     c_none,     c_ipv62str, NULL,      c_ipv62str, NULL,   },
+/*        STR */ { c_str2int, c_str2int, c_str2int, c_str2addr, c_str2ip, c_str2ipv6, c_none,     c_none,    c_none,     c_none, },
+/*        BIN */ { NULL,      NULL,      NULL,      NULL,       NULL,     NULL,       c_bin2str,  c_none,    c_bin2str,  c_none, },
+/*       CSTR */ { c_str2int, c_str2int, c_str2int, c_str2addr, c_str2ip, c_str2ipv6, c_datadup,  c_bindup,  c_none,     c_none, },
+/*       CBIN */ { NULL,      NULL,      NULL,      NULL,       NULL,     NULL,       c_bin2str,  c_datadup, c_bin2str,  c_none, },
 };
 
 /*
@@ -813,8 +858,6 @@ struct sample *sample_process(struct proxy *px, struct session *l4, void *l7,
 
                /* OK cast succeeded */
 
-               /* force the output type after a cast */
-               p->type = conv_expr->conv->in_type;
                if (!conv_expr->conv->process(conv_expr->arg_p, p))
                        return NULL;
        }
index 16b93ad06d335e6ee39ef4b174a5ba27e02c79fc..45e6118fec3dccafe07eecd7b94b1389e338cf47 100644 (file)
@@ -589,6 +589,7 @@ static sample_to_key_fct sample_to_key[SMP_TYPES][STKTABLE_TYPES] = {
 /* patt. type: BOOL */ { NULL,     NULL,        k_int2int, k_int2str,  NULL      },
 /*             UINT */ { k_int2ip, NULL,        k_int2int, k_int2str,  NULL      },
 /*             SINT */ { k_int2ip, NULL,        k_int2int, k_int2str,  NULL      },
+/*             ADDR */ { k_ip2ip,  k_ip2ipv6,   k_ip2int,  k_ip2str,   NULL      },
 /*             IPV4 */ { k_ip2ip,  k_ip2ipv6,   k_ip2int,  k_ip2str,   NULL      },
 /*             IPV6 */ { k_ip2ip,  k_ip2ipv6,   k_ip2int,  k_ip2str,   NULL      },
 /*              STR */ { k_str2ip, k_str2ipv6,  k_str2int, k_str2str,  k_str2str },