[MEDIUM] Create new protected pattern types CONSTSTRING and CONSTDATA to force memcpy if data from protected areas need to be manipulated.

Enhance pattern convs and fetch argument parsing, now fetchs and convs callbacks used typed args.
Add more details on error messages on parsing pattern expression function.
Update existing pattern convs and fetchs to new proto.
Create stick table key type "binary".
Manage Truncation and padding if pattern's fetch-converted result don't match table key size.
This commit is contained in:
Emeric Brun 2010-09-23 18:02:19 +02:00 committed by Willy Tarreau
parent 392d1d8b89
commit 485479d8e9
10 changed files with 291 additions and 87 deletions

View File

@ -25,11 +25,13 @@
#include <types/pattern.h>
#include <types/stick_table.h>
struct pattern_expr *pattern_parse_expr(char **str, int *idx);
struct pattern_expr *pattern_parse_expr(char **str, int *idx, char *err, int err_size);
struct pattern *pattern_process(struct proxy *px, struct session *l4,
void *l7, int dir, struct pattern_expr *expr,
struct pattern *p);
void pattern_register_fetches(struct pattern_fetch_kw_list *psl);
void pattern_register_convs(struct pattern_conv_kw_list *psl);
int pattern_arg_ipmask(const char *arg_str, struct pattern_arg **arg_p, int *arg_i);
int pattern_arg_str(const char *arg_str, struct pattern_arg **arg_p, int *arg_i);
#endif

View File

@ -46,9 +46,9 @@ struct stksess *stktable_touch(struct stktable *t, struct stksess *ts);
struct stksess *stktable_lookup(struct stktable *t, struct stksess *ts);
struct stksess *stktable_lookup_key(struct stktable *t, struct stktable_key *key);
struct stksess *stktable_update_key(struct stktable *table, struct stktable_key *key);
struct stktable_key *stktable_fetch_key(struct proxy *px, struct session *l4,
void *l7, int dir, struct pattern_expr *expr,
unsigned long table_type);
struct stktable_key *stktable_fetch_key(struct stktable *t, struct proxy *px,
struct session *l4, void *l7, int dir,
struct pattern_expr *expr);
int stktable_compatible_pattern(struct pattern_expr *expr, unsigned long table_type);
int stktable_get_data_type(char *name);
struct proxy *find_stktable(const char *name);

View File

@ -31,18 +31,43 @@ enum {
PATTERN_TYPE_IP = 0, /* ipv4 type */
PATTERN_TYPE_INTEGER, /* unsigned 32bits integer type */
PATTERN_TYPE_STRING, /* char string type */
PATTERN_TYPE_DATA, /* buffer type */
PATTERN_TYPE_CONSTSTRING, /* constant char string type, data need dup before conversion */
PATTERN_TYPE_CONSTDATA, /* constant buffer type, data need dup before conversion */
PATTERN_TYPES /* number of types, must always be last */
};
/* pattern arg types */
enum {
PATTERN_ARG_TYPE_IP = 0, /* ipv4 type */
PATTERN_ARG_TYPE_INTEGER, /* unsigned 32bits integer type */
PATTERN_ARG_TYPE_SINTEGER, /* signed 32bits integer type */
PATTERN_ARG_TYPE_STRING /* string type */
};
/* pattern fetch direction */
#define PATTERN_FETCH_REQ 1
#define PATTERN_FETCH_RTR 2
union pattern_arg_data {
struct in_addr ip; /* used for ipv4 type */
uint32_t integer; /* used for unsigned 32bits integer type */
int32_t sinteger; /* used for signed 32bits integer type */
struct chunk str;
};
struct pattern_arg {
int type; /* type of arg */
union pattern_arg_data data; /* data */
};
/* pattern result data */
union pattern_data {
struct in_addr ip; /* used for ipv4 type */
uint32_t integer; /* used for unsigned 32bits integer type */
struct chunk str; /* used for char string type */
struct chunk str; /* used for char string type or buffers*/
};
/* pattern result */
@ -54,22 +79,22 @@ struct pattern {
/* pattern conversion */
struct pattern_conv {
const char *kw; /* configuration keyword */
int (*process)(const void *arg_p,
int (*process)(const struct pattern_arg *arg_p,
int arg_i,
union pattern_data *data); /* process function */
int (*parse_args)(const char *arg_str,
struct pattern_arg **arg_p,
int *arg_i); /* argument parser. Can be NULL. */
unsigned int in_type; /* input needed pattern type */
unsigned int out_type; /* output pattern type */
int (*parse_args)(const char *arg_str,
void **arg_p,
int *arg_i); /* argument parser. Can be NULL. */
};
/* pattern conversion expression */
struct pattern_conv_expr {
struct list list; /* member of a pattern expression */
struct pattern_conv *conv; /* pattern conversion */
void *arg_p; /* pointer arg, most often a string argument */
int arg_i; /* int arg, most often the argument's length */
struct pattern_arg *arg_p; /* pointer on args */
int arg_i; /* number of args */
};
/* pattern fetch */
@ -78,9 +103,12 @@ struct pattern_fetch {
int (*process)(struct proxy *px,
struct session *l4,
void *l7,
int dir, const char *arg,
int arg_len,
int dir, const struct pattern_arg *arg_p,
int arg_i,
union pattern_data *data); /* fetch processing function */
int (*parse_args)(const char *arg_str,
struct pattern_arg **arg_p,
int *arg_i); /* argument parser. Can be NULL. */
unsigned long out_type; /* output pattern type */
int dir; /* usable directions */
};
@ -89,8 +117,8 @@ struct pattern_fetch {
struct pattern_expr {
struct list list; /* member of list of pattern, currently not used */
struct pattern_fetch *fetch; /* pattern fetch */
char *arg; /* configured keyword argument */
int arg_len; /* configured keyword argument length */
struct pattern_arg *arg_p; /* pointer on args */
int arg_i; /* number of args */
struct list conv_exprs; /* list of conversion expression to apply */
};

View File

@ -37,6 +37,7 @@ enum {
STKTABLE_TYPE_IP = 0, /* table key is ipv4 */
STKTABLE_TYPE_INTEGER, /* table key is unsigned 32bit integer */
STKTABLE_TYPE_STRING, /* table key is a null terminated string */
STKTABLE_TYPE_BINARY, /* table key is a buffer of data */
STKTABLE_TYPES /* Number of types, must always be last */
};
@ -118,6 +119,8 @@ struct stktable_type {
size_t default_size; /* default key size */
};
extern struct stktable_type stktable_types[];
/* Sticky session.
* Any additional data related to the stuck session is installed *before*
* stksess (with negative offsets). This allows us to run variable-sized
@ -159,7 +162,7 @@ extern struct stktable_data_type stktable_data_types[STKTABLE_DATA_TYPES];
union stktable_key_data {
struct in_addr ip; /* used to store an ip key */
uint32_t integer; /* used to store an integer key */
char buf[BUFSIZE]; /* used to store a null terminated string key */
char buf[BUFSIZE]; /* used to store a null terminated string key or a buffer of data */
};
/* stick table key */

View File

@ -2728,9 +2728,9 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
goto out;
}
expr = pattern_parse_expr(args, &myidx);
expr = pattern_parse_expr(args, &myidx, trash, sizeof(trash));
if (!expr) {
Alert("parsing [%s:%d] : '%s': unknown fetch method '%s'.\n", file, linenum, args[0], args[myidx]);
Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}

View File

@ -14,6 +14,7 @@
#include <arpa/inet.h>
#include <proto/pattern.h>
#include <proto/buffers.h>
#include <common/standard.h>
/* static structure used on pattern_process if <p> is NULL*/
@ -109,9 +110,7 @@ static struct chunk *get_trash_chunk(void)
else
pattern_trash_buf = pattern_trash_buf1;
trash_chunk.str = pattern_trash_buf;
trash_chunk.len = 0;
trash_chunk.size = BUFSIZE;
chunk_init(&trash_chunk, pattern_trash_buf, BUFSIZE);
return &trash_chunk;
}
@ -121,9 +120,7 @@ static struct chunk *get_trash_chunk(void)
*/
static void pattern_data_setstring(union pattern_data *data, struct chunk *c)
{
data->str.str = c->str;
data->str.len = c->len;
data->str.size = c->size;
chunk_initlen(&data->str, c->str, c->size, c->len);
}
/******************************************************************/
@ -172,6 +169,7 @@ static int c_int2str(union pattern_data *data)
if (!pos)
return 0;
trash->size = trash->size - (pos - trash->str);
trash->str = pos;
trash->len = strlen(pos);
@ -180,6 +178,19 @@ static int c_int2str(union pattern_data *data)
return 1;
}
static int c_datadup(union pattern_data *data)
{
struct chunk *trash = get_trash_chunk();
trash->len = data->str.len < trash->size ? data->str.len : trash->size;
memcpy(trash->str, data->str.str, trash->len);
pattern_data_setstring(data, trash);
return 1;
}
static int c_donothing(union pattern_data *data)
{
return 1;
@ -211,9 +222,13 @@ static int c_str2int(union pattern_data *data)
typedef int (*pattern_cast_fct)(union pattern_data *data);
static pattern_cast_fct pattern_casts[PATTERN_TYPES][PATTERN_TYPES] = {
{ c_donothing, c_ip2int, c_ip2str },
{ c_int2ip, c_donothing, c_int2str },
{ c_str2ip, c_str2int, c_donothing },
/* to: IP INTEGER STRING DATA CONSTSTRING CONSTDATA */
/* from: IP */ { c_donothing, c_ip2int, c_ip2str, NULL, c_ip2str, NULL },
/* INTEGER */ { c_int2ip, c_donothing, c_int2str, NULL, c_int2str, NULL },
/* STRING */ { c_str2ip, c_str2int, c_donothing, c_donothing, c_donothing, c_donothing },
/* DATA */ { NULL, NULL, NULL, c_donothing, NULL, c_donothing },
/* CONSTSTRING */ { c_str2ip, c_str2int, c_datadup, c_datadup, c_donothing, c_donothing },
/* CONSTDATA */ { NULL, NULL, NULL, c_datadup, NULL, NULL },
};
@ -222,7 +237,7 @@ static pattern_cast_fct pattern_casts[PATTERN_TYPES][PATTERN_TYPES] = {
* fetch keyword followed by format conversion keywords.
* Returns a pointer on allocated pattern expression structure.
*/
struct pattern_expr *pattern_parse_expr(char **str, int *idx)
struct pattern_expr *pattern_parse_expr(char **str, int *idx, char *err, int err_size)
{
const char *endw;
const char *end;
@ -230,34 +245,88 @@ struct pattern_expr *pattern_parse_expr(char **str, int *idx)
struct pattern_fetch *fetch;
struct pattern_conv *conv;
unsigned long prev_type;
char *p;
if (!str[*idx])
snprintf(err, err_size, "memory error.");
if (!str[*idx]) {
snprintf(err, err_size, "missing fetch method.");
goto out_error;
}
end = str[*idx] + strlen(str[*idx]);
endw = strchr(str[*idx], '(');
if (!endw)
endw = end;
else if ((end-1)[0] != ')')
else if ((end-1)[0] != ')') {
p = my_strndup(str[*idx], endw - str[*idx]);
if (p) {
snprintf(err, err_size, "syntax error: missing ')' after keyword '%s'.", p);
free(p);
}
goto out_error;
}
fetch = find_pattern_fetch(str[*idx], endw - str[*idx]);
if (!fetch)
if (!fetch) {
p = my_strndup(str[*idx], endw - str[*idx]);
if (p) {
snprintf(err, err_size, "unknown fetch method '%s'.", p);
free(p);
}
goto out_error;
}
if (fetch->out_type >= PATTERN_TYPES) {
if (fetch->out_type >= PATTERN_TYPES)
p = my_strndup(str[*idx], endw - str[*idx]);
if (p) {
snprintf(err, err_size, "returns type of fetch method '%s' is unknown.", p);
free(p);
}
goto out_error;
}
prev_type = fetch->out_type;
expr = calloc(1, sizeof(struct pattern_expr));
if (!expr)
goto out_error;
LIST_INIT(&(expr->conv_exprs));
expr->fetch = fetch;
if (end != endw) {
expr->arg_len = end - endw - 2;
expr->arg = my_strndup(endw + 1, expr->arg_len);
int i = end - endw - 2;
if (!fetch->parse_args) {
p = my_strndup(str[*idx], endw - str[*idx]);
if (p) {
snprintf(err, err_size, "fetch method '%s' does not support any args.", p);
free(p);
}
goto out_error;
}
p = my_strndup(endw + 1, i);
if (!p)
goto out_error;
i = fetch->parse_args(p, &expr->arg_p, &expr->arg_i);
free(p);
if (!i) {
p = my_strndup(str[*idx], endw - str[*idx]);
if (p) {
snprintf(err, err_size, "invalid args in fetch method '%s'.", p);
free(p);
}
goto out_error;
}
}
else if (fetch->parse_args) {
p = my_strndup(str[*idx], endw - str[*idx]);
if (p) {
snprintf(err, err_size, "missing args for fetch method '%s'.", p);
free(p);
}
goto out_error;
}
for (*idx += 1; *(str[*idx]); (*idx)++) {
@ -268,42 +337,85 @@ struct pattern_expr *pattern_parse_expr(char **str, int *idx)
if (!endw)
endw = end;
else if ((end-1)[0] != ')')
else if ((end-1)[0] != ')') {
p = my_strndup(str[*idx], endw - str[*idx]);
if (p) {
snprintf(err, err_size, "syntax error, missing ')' after keyword '%s'.", p);
free(p);
}
goto out_error;
}
conv = find_pattern_conv(str[*idx], endw - str[*idx]);
if (!conv)
break;
if (conv->in_type >= PATTERN_TYPES ||
conv->out_type >= PATTERN_TYPES)
conv->out_type >= PATTERN_TYPES) {
p = my_strndup(str[*idx], endw - str[*idx]);
if (p) {
snprintf(err, err_size, "returns type of conv method '%s' is unknown.", p);
free(p);
}
goto out_error;
}
/* If impossible type conversion */
if (!pattern_casts[prev_type][conv->in_type])
if (!pattern_casts[prev_type][conv->in_type]) {
p = my_strndup(str[*idx], endw - str[*idx]);
if (p) {
snprintf(err, err_size, "conv method '%s' cannot be applied.", p);
free(p);
}
goto out_error;
}
prev_type = conv->out_type;
conv_expr = calloc(1, sizeof(struct pattern_conv_expr));
if (!conv_expr)
goto out_error;
LIST_ADDQ(&(expr->conv_exprs), &(conv_expr->list));
conv_expr->conv = conv;
if (end != endw) {
int i = end - endw - 2;
char *p = my_strndup(endw + 1, i);
if (conv->parse_args) {
i = conv->parse_args(p, &conv_expr->arg_p, &conv_expr->arg_i);
free(p);
if (!i)
goto out_error;
} else {
conv_expr->arg_i = i;
conv_expr->arg_p = p;
if (!conv->parse_args) {
p = my_strndup(str[*idx], endw - str[*idx]);
if (p) {
snprintf(err, err_size, "conv method '%s' does not support any args.", p);
free(p);
}
goto out_error;
}
p = my_strndup(endw + 1, i);
if (!p)
goto out_error;
i = conv->parse_args(p, &conv_expr->arg_p, &conv_expr->arg_i);
free(p);
if (!i) {
p = my_strndup(str[*idx], endw - str[*idx]);
if (p) {
snprintf(err, err_size, "invalid args in conv method '%s'.", p);
free(p);
}
goto out_error;
}
}
else if (conv->parse_args) {
p = my_strndup(str[*idx], endw - str[*idx]);
if (p) {
snprintf(err, err_size, "missing args for conv method '%s'.", p);
free(p);
}
goto out_error;
}
}
return expr;
out_error:
@ -327,7 +439,7 @@ struct pattern *pattern_process(struct proxy *px, struct session *l4, void *l7,
if (p == NULL)
p = &spattern;
if (!expr->fetch->process(px, l4, l7, dir, expr->arg, expr->arg_len, &p->data))
if (!expr->fetch->process(px, l4, l7, dir, expr->arg_p, expr->arg_i, &p->data))
return NULL;
p->type = expr->fetch->out_type;
@ -345,28 +457,49 @@ struct pattern *pattern_process(struct proxy *px, struct session *l4, void *l7,
return p;
}
/* Converts an argument string to an IPv4 mask stored in network byte order in
* arg_i. Returns non-zero in case of success, 0 on error.
/* Converts an argument string mask to a pattern_arg type IP.
* Returns non-zero in case of success, 0 on error.
*/
static int pattern_conv_arg_to_ipmask(const char *arg_str, void **arg_p, int *arg_i)
int pattern_arg_ipmask(const char *arg_str, struct pattern_arg **arg_p, int *arg_i)
{
struct in_addr mask;
*arg_i = 1;
*arg_p = calloc(1, *arg_i*sizeof(struct pattern_arg));
(*arg_p)->type = PATTERN_ARG_TYPE_IP;
if (!str2mask(arg_str, &mask))
if (!str2mask(arg_str, &(*arg_p)->data.ip))
return 0;
*arg_i = mask.s_addr;
return 1;
}
/* Converts an argument string to a pattern_arg type STRING.
* Returns non-zero in case of success, 0 on error.
*/
int pattern_arg_str(const char *arg_str, struct pattern_arg **arg_p, int *arg_i)
{
*arg_i = 1;
*arg_p = calloc(1, *arg_i*sizeof(struct pattern_arg));
(*arg_p)->type = PATTERN_ARG_TYPE_STRING;
(*arg_p)->data.str.str = strdup(arg_str);
(*arg_p)->data.str.len = strlen(arg_str);
return 1;
}
/*****************************************************************/
/* Pattern format convert functions */
/*****************************************************************/
static int pattern_conv_str2lower(const void *arg_p, int arg_i, union pattern_data *data)
static int pattern_conv_str2lower(const struct pattern_arg *arg_p, int arg_i, union pattern_data *data)
{
int i;
if (!data->str.size)
return 0;
for (i = 0; i < data->str.len; i++) {
if ((data->str.str[i] >= 'A') && (data->str.str[i] <= 'Z'))
data->str.str[i] += 'a' - 'A';
@ -374,10 +507,13 @@ static int pattern_conv_str2lower(const void *arg_p, int arg_i, union pattern_da
return 1;
}
static int pattern_conv_str2upper(const void *arg_p, int arg_i, union pattern_data *data)
static int pattern_conv_str2upper(const struct pattern_arg *arg_p, int arg_i, union pattern_data *data)
{
int i;
if (!data->str.size)
return 0;
for (i = 0; i < data->str.len; i++) {
if ((data->str.str[i] >= 'a') && (data->str.str[i] <= 'z'))
data->str.str[i] += 'A' - 'a';
@ -386,7 +522,7 @@ static int pattern_conv_str2upper(const void *arg_p, int arg_i, union pattern_da
}
/* takes the netmask in arg_i */
static int pattern_conv_ipmask(const void *arg_p, int arg_i, union pattern_data *data)
static int pattern_conv_ipmask(const struct pattern_arg *arg_p, int arg_i, union pattern_data *data)
{
data->ip.s_addr &= arg_i;
return 1;
@ -394,10 +530,10 @@ static int pattern_conv_ipmask(const void *arg_p, int arg_i, union pattern_data
/* Note: must not be declared <const> as its list will be overwritten */
static struct pattern_conv_kw_list pattern_conv_kws = {{ },{
{ "upper", pattern_conv_str2upper, PATTERN_TYPE_STRING, PATTERN_TYPE_STRING },
{ "lower", pattern_conv_str2lower, PATTERN_TYPE_STRING, PATTERN_TYPE_STRING },
{ "ipmask", pattern_conv_ipmask, PATTERN_TYPE_IP, PATTERN_TYPE_IP, pattern_conv_arg_to_ipmask },
{ NULL, NULL, 0, 0 },
{ "upper", pattern_conv_str2upper, NULL, PATTERN_TYPE_STRING, PATTERN_TYPE_STRING },
{ "lower", pattern_conv_str2lower, NULL, PATTERN_TYPE_STRING, PATTERN_TYPE_STRING },
{ "ipmask", pattern_conv_ipmask, pattern_arg_ipmask, PATTERN_TYPE_IP, PATTERN_TYPE_IP },
{ NULL, NULL, NULL, 0, 0 },
}};
__attribute__((constructor))

View File

@ -8105,21 +8105,23 @@ static struct acl_kw_list acl_kws = {{ },{
*/
static int
pattern_fetch_hdr_ip(struct proxy *px, struct session *l4, void *l7, int dir,
const char *arg, int arg_len, union pattern_data *data)
const struct pattern_arg *arg_p, int arg_i, union pattern_data *data)
{
struct http_txn *txn = l7;
data->ip.s_addr = htonl(get_ip_from_hdr2(&txn->req, arg, arg_len, &txn->hdr_idx, -1));
data->ip.s_addr = htonl(get_ip_from_hdr2(&txn->req, arg_p->data.str.str, arg_p->data.str.len, &txn->hdr_idx, -1));
return data->ip.s_addr != 0;
}
/************************************************************************/
/* All supported keywords must be declared here. */
/************************************************************************/
/* Note: must not be declared <const> as its list will be overwritten */
static struct pattern_fetch_kw_list pattern_fetch_keywords = {{ },{
{ "hdr", pattern_fetch_hdr_ip, PATTERN_TYPE_IP, PATTERN_FETCH_REQ },
{ NULL, NULL, 0, 0 },
{ "hdr", pattern_fetch_hdr_ip, pattern_arg_str, PATTERN_TYPE_IP, PATTERN_FETCH_REQ },
{ NULL, NULL, NULL, 0, 0 },
}};

View File

@ -1244,7 +1244,7 @@ acl_fetch_src(struct proxy *px, struct session *l4, void *l7, int dir,
/* extract the connection's source address */
static int
pattern_fetch_src(struct proxy *px, struct session *l4, void *l7, int dir,
const char *arg, int arg_len, union pattern_data *data)
const struct pattern_arg *arg_p, int arg_i, union pattern_data *data)
{
if (l4->cli_addr.ss_family != AF_INET )
return 0;
@ -1295,7 +1295,7 @@ acl_fetch_dst(struct proxy *px, struct session *l4, void *l7, int dir,
/* extract the connection's destination address */
static int
pattern_fetch_dst(struct proxy *px, struct session *l4, void *l7, int dir,
const char *arg, int arg_len, union pattern_data *data)
const struct pattern_arg *arg_p, int arg_i, union pattern_data *data)
{
if (!(l4->flags & SN_FRT_ADDR_SET))
get_frt_addr(l4);
@ -1328,8 +1328,7 @@ acl_fetch_dport(struct proxy *px, struct session *l4, void *l7, int dir,
static int
pattern_fetch_dport(struct proxy *px, struct session *l4, void *l7, int dir,
const char *arg, int arg_len, union pattern_data *data)
const struct pattern_arg *arg, int i, union pattern_data *data)
{
if (!(l4->flags & SN_FRT_ADDR_SET))
get_frt_addr(l4);
@ -1358,10 +1357,10 @@ static struct acl_kw_list acl_kws = {{ },{
/* Note: must not be declared <const> as its list will be overwritten */
static struct pattern_fetch_kw_list pattern_fetch_keywords = {{ },{
{ "src", pattern_fetch_src, PATTERN_TYPE_IP, PATTERN_FETCH_REQ },
{ "dst", pattern_fetch_dst, PATTERN_TYPE_IP, PATTERN_FETCH_REQ },
{ "dst_port", pattern_fetch_dport, PATTERN_TYPE_INTEGER, PATTERN_FETCH_REQ },
{ NULL, NULL, 0, 0 },
{ "src", pattern_fetch_src, NULL, PATTERN_TYPE_IP, PATTERN_FETCH_REQ },
{ "dst", pattern_fetch_dst, NULL, PATTERN_TYPE_IP, PATTERN_FETCH_REQ },
{ "dst_port", pattern_fetch_dport, NULL, PATTERN_TYPE_INTEGER, PATTERN_FETCH_REQ },
{ NULL, NULL, NULL, 0, 0 },
}};
__attribute__((constructor))

View File

@ -1050,7 +1050,7 @@ int process_sticking_rules(struct session *s, struct buffer *req, int an_bit)
if (ret) {
struct stktable_key *key;
key = stktable_fetch_key(px, s, &s->txn, PATTERN_FETCH_REQ, rule->expr, rule->table.t->type);
key = stktable_fetch_key(rule->table.t, px, s, &s->txn, PATTERN_FETCH_REQ, rule->expr);
if (!key)
continue;
@ -1143,7 +1143,7 @@ int process_store_rules(struct session *s, struct buffer *rep, int an_bit)
if (ret) {
struct stktable_key *key;
key = stktable_fetch_key(px, s, &s->txn, PATTERN_FETCH_RTR, rule->expr, rule->table.t->type);
key = stktable_fetch_key(rule->table.t, px, s, &s->txn, PATTERN_FETCH_RTR, rule->expr);
if (!key)
continue;

View File

@ -181,7 +181,7 @@ struct stksess *stktable_lookup_key(struct stktable *t, struct stktable_key *key
struct ebmb_node *eb;
if (t->type == STKTABLE_TYPE_STRING)
eb = ebst_lookup_len(&t->keys, key->key, key->key_len);
eb = ebst_lookup_len(&t->keys, key->key, key->key_len+1 < t->key_size ? key->key_len : t->key_size-1);
else
eb = ebmb_lookup(&t->keys, key->key, t->key_size);
@ -383,9 +383,10 @@ int stktable_init(struct stktable *t)
/*
* Configuration keywords of known table types
*/
struct stktable_type stktable_types[STKTABLE_TYPES] = { { "ip", 0, 4 } ,
struct stktable_type stktable_types[STKTABLE_TYPES] = {{ "ip", 0, 4 },
{ "integer", 0, 4 },
{ "string", STK_F_CUSTOM_KEYSIZE, 32 } };
{ "string", STK_F_CUSTOM_KEYSIZE, 32 },
{ "binary", STK_F_CUSTOM_KEYSIZE, 32 } };
/*
@ -406,10 +407,12 @@ int stktable_parse_type(char **args, int *myidx, unsigned long *type, size_t *ke
if (strcmp("len", args[*myidx]) == 0) {
(*myidx)++;
*key_size = atol(args[*myidx]);
if ( !*key_size )
if (!*key_size)
break;
/* null terminated string needs +1 for '\0'. */
(*key_size)++;
if (*type == STKTABLE_TYPE_STRING) {
/* null terminated string needs +1 for '\0'. */
(*key_size)++;
}
(*myidx)++;
}
}
@ -504,9 +507,13 @@ static void *k_str2int(union pattern_data *pdata, union stktable_key_data *kdata
typedef void *(*pattern_to_key_fct)(union pattern_data *pdata, union stktable_key_data *kdata, size_t *len);
static pattern_to_key_fct pattern_to_key[PATTERN_TYPES][STKTABLE_TYPES] = {
{ k_ip2ip, k_ip2int, k_ip2str },
{ k_int2ip, k_int2int, k_int2str },
{ k_str2ip, k_str2int, k_str2str },
/* table type: IP INTEGER STRING BINARY */
/* pattern type: IP */ { k_ip2ip, k_ip2int, k_ip2str, NULL },
/* INTEGER */ { k_int2ip, k_int2int, k_int2str, NULL },
/* STRING */ { k_str2ip, k_str2int, k_str2str, k_str2str },
/* DATA */ { NULL, NULL, NULL, k_str2str },
/* CONSTSTRING */ { k_str2ip, k_str2int, k_str2str, k_str2str },
/* CONSTDATA */ { NULL, NULL, NULL, k_str2str },
};
@ -516,8 +523,8 @@ static pattern_to_key_fct pattern_to_key[PATTERN_TYPES][STKTABLE_TYPES] = {
* no key could be extracted, or a pointer to the converted result stored in
* static_table_key in format <table_type>.
*/
struct stktable_key *stktable_fetch_key(struct proxy *px, struct session *l4, void *l7, int dir,
struct pattern_expr *expr, unsigned long table_type)
struct stktable_key *stktable_fetch_key(struct stktable *t, struct proxy *px, struct session *l4, void *l7, int dir,
struct pattern_expr *expr)
{
struct pattern *ptrn;
@ -525,12 +532,39 @@ struct stktable_key *stktable_fetch_key(struct proxy *px, struct session *l4, vo
if (!ptrn)
return NULL;
static_table_key.key_len = (size_t)-1;
static_table_key.key = pattern_to_key[ptrn->type][table_type](&ptrn->data, &static_table_key.data, &static_table_key.key_len);
static_table_key.key_len = t->key_size;
static_table_key.key = pattern_to_key[ptrn->type][t->type](&ptrn->data, &static_table_key.data, &static_table_key.key_len);
if (!static_table_key.key)
return NULL;
if ((static_table_key.key_len < t->key_size) && (t->type != STKTABLE_TYPE_STRING)) {
/* need padding with null */
/* assume static_table_key.key_len is less than sizeof(static_table_key.data.buf)
cause t->key_size is necessary less than sizeof(static_table_key.data) */
if ((char *)static_table_key.key > (char *)&static_table_key.data &&
(char *)static_table_key.key < (char *)&static_table_key.data + sizeof(static_table_key.data)) {
/* key buffer is part of the static_table_key private data buffer, but is not aligned */
if (sizeof(static_table_key.data) - ((char *)static_table_key.key - (char *)&static_table_key.data) < t->key_size) {
/* if not remain enougth place for padding , process a realign */
memmove(static_table_key.data.buf, static_table_key.key, static_table_key.key_len);
static_table_key.key = static_table_key.data.buf;
}
}
else if (static_table_key.key != static_table_key.data.buf) {
/* key definitly not part of the static_table_key private data buffer */
memcpy(static_table_key.data.buf, static_table_key.key, static_table_key.key_len);
static_table_key.key = static_table_key.data.buf;
}
memset(static_table_key.key + static_table_key.key_len, 0, t->key_size - static_table_key.key_len);
}
return &static_table_key;
}