MEDIUM: sample: let the cast functions set their output type

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.
This commit is contained in:
Thierry FOURNIER 2013-11-26 20:47:54 +01:00 committed by Willy Tarreau
parent 803685fa12
commit b805f71d1b
3 changed files with 59 additions and 14 deletions

View 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 */

View 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 int c_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;
}

View 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 },