From f0b38bfc33288508e4205c20cde793eb77c98c7d Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Sun, 6 Jun 2010 13:22:23 +0200 Subject: [PATCH] [CLEANUP] stick_table: move pattern to key functions to stick_table.c pattern.c depended on stick_table while in fact it should be the opposite. So we move from pattern.c everything related to stick_tables and invert the dependency. That way the code becomes more logical and intuitive. --- include/common/standard.h | 5 + include/proto/pattern.h | 4 - include/proto/stick_table.h | 4 + src/cfgparse.c | 4 +- src/pattern.c | 201 ++---------------------------------- src/session.c | 5 +- src/standard.c | 52 ++++++++++ src/stick_table.c | 141 +++++++++++++++++++++++++ 8 files changed, 212 insertions(+), 204 deletions(-) diff --git a/include/common/standard.h b/include/common/standard.h index 762fab562..eff47e749 100644 --- a/include/common/standard.h +++ b/include/common/standard.h @@ -379,4 +379,9 @@ unsigned int get_next_id(struct eb_root *root, unsigned int key); */ int word_match(const char *sample, int slen, const char *word, int wlen); +/* Convert a fixed-length string to an IP address. Returns 0 in case of error, + * or the number of chars read in case of success. + */ +int buf2ip(const char *buf, size_t len, struct in_addr *dst); + #endif /* _COMMON_STANDARD_H */ diff --git a/include/proto/pattern.h b/include/proto/pattern.h index 41eda06e9..0bef7e6a2 100644 --- a/include/proto/pattern.h +++ b/include/proto/pattern.h @@ -29,10 +29,6 @@ struct pattern_expr *pattern_parse_expr(char **str, int *idx); struct pattern *pattern_process(struct proxy *px, struct session *l4, void *l7, int dir, struct pattern_expr *expr, struct pattern *p); -struct stktable_key *pattern_process_key(struct proxy *px, struct session *l4, - void *l7, int dir, struct pattern_expr *expr, - unsigned long table_type); -int pattern_notusable_key(struct pattern_expr *expr, unsigned long table_type); void pattern_register_fetches(struct pattern_fetch_kw_list *psl); void pattern_register_convs(struct pattern_conv_kw_list *psl); diff --git a/include/proto/stick_table.h b/include/proto/stick_table.h index ed44cc0c7..f26e002a9 100644 --- a/include/proto/stick_table.h +++ b/include/proto/stick_table.h @@ -32,6 +32,10 @@ int stktable_init(struct stktable *t); int stktable_parse_type(char **args, int *idx, unsigned long *type, size_t *key_size); int stktable_store(struct stktable *t, struct stksess *ts, int sid); struct stksess *stktable_lookup(struct stktable *t, 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); +int stktable_compatible_pattern(struct pattern_expr *expr, unsigned long table_type); #endif /* _PROTO_STICK_TABLE_H */ diff --git a/src/cfgparse.c b/src/cfgparse.c index 1abb1b713..d2f79f220 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -4873,7 +4873,7 @@ int check_config_validity() curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id); cfgerr++; } - else if (pattern_notusable_key(mrule->expr, target->table.type)) { + else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) { Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n", curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id); cfgerr++; @@ -4905,7 +4905,7 @@ int check_config_validity() curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id); cfgerr++; } - else if (pattern_notusable_key(mrule->expr, target->table.type)) { + else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) { Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n", curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id); cfgerr++; diff --git a/src/pattern.c b/src/pattern.c index 63bae2b8c..6a12442fc 100644 --- a/src/pattern.c +++ b/src/pattern.c @@ -12,7 +12,6 @@ #include #include -#include #include #include @@ -30,9 +29,6 @@ static char pattern_trash_buf2[BUFSIZE]; /* pattern_trash_buf point on used buffer*/ static char *pattern_trash_buf = pattern_trash_buf1; -/* static structure used to returns builded table key from a pattern*/ -static struct stktable_key stable_key; - /* list head of all known pattern fetch keywords */ static struct pattern_fetch_kw_list pattern_fetches = { .list = LIST_HEAD_INIT(pattern_fetches.list) @@ -159,56 +155,6 @@ static int c_int2ip(union pattern_data *data) return 1; } -/* Convert a fixed-length string to an IP address. Returns 0 in case of error, - * or the number of chars read in case of success. - */ -static int buf2ip(const char *buf, size_t len, struct in_addr *dst) -{ - const char *addr; - int saw_digit, octets, ch; - u_char tmp[4], *tp; - const char *cp = buf; - - saw_digit = 0; - octets = 0; - *(tp = tmp) = 0; - - for (addr = buf; addr - buf < len; addr++) { - unsigned char digit = (ch = *addr) - '0'; - - if (digit > 9 && ch != '.') - break; - - if (digit <= 9) { - u_int new = *tp * 10 + digit; - - if (new > 255) - return 0; - - *tp = new; - - if (!saw_digit) { - if (++octets > 4) - return 0; - saw_digit = 1; - } - } else if (ch == '.' && saw_digit) { - if (octets == 4) - return 0; - - *++tp = 0; - saw_digit = 0; - } else - return 0; - } - - if (octets < 4) - return 0; - - memcpy(&dst->s_addr, tmp, 4); - return addr - cp; -} - static int c_str2ip(union pattern_data *data) { if (!buf2ip(data->str.str, data->str.len, &data->ip)) @@ -263,100 +209,14 @@ static int c_str2int(union pattern_data *data) /* NULL pointer used for impossible pattern casts */ /*****************************************************************/ -typedef int (*pattern_cast)(union pattern_data *data); -static pattern_cast pattern_casts[PATTERN_TYPES][PATTERN_TYPES] = { { c_donothing, c_ip2int, c_ip2str }, - { c_int2ip, c_donothing, c_int2str }, - { c_str2ip, c_str2int, c_donothing } }; +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 }, +}; -/*****************************************************************/ -/* typed pattern to typed table key functions */ -/*****************************************************************/ - -static void *k_int2int(union pattern_data *pdata, union stktable_key_data *kdata, size_t *len) -{ - return (void *)&pdata->integer; -} - -static void *k_ip2ip(union pattern_data *pdata, union stktable_key_data *kdata, size_t *len) -{ - return (void *)&pdata->ip.s_addr; -} - -static void *k_ip2int(union pattern_data *pdata, union stktable_key_data *kdata, size_t *len) -{ - kdata->integer = ntohl(pdata->ip.s_addr); - return (void *)&kdata->integer; -} - -static void *k_int2ip(union pattern_data *pdata, union stktable_key_data *kdata, size_t *len) -{ - kdata->ip.s_addr = htonl(pdata->integer); - return (void *)&kdata->ip.s_addr; -} - -static void *k_str2str(union pattern_data *pdata, union stktable_key_data *kdata, size_t *len) -{ - *len = pdata->str.len; - return (void *)pdata->str.str; -} - -static void *k_ip2str(union pattern_data *pdata, union stktable_key_data *kdata, size_t *len) -{ - if (!inet_ntop(AF_INET, &pdata->ip, kdata->buf, sizeof(kdata->buf))) - return NULL; - - *len = strlen((const char *)kdata->buf); - return (void *)kdata->buf; -} - -static void *k_int2str(union pattern_data *pdata, union stktable_key_data *kdata, size_t *len) -{ - void *key; - - key = (void *)ultoa_r(pdata->integer, kdata->buf, sizeof(kdata->buf)); - if (!key) - return NULL; - - *len = strlen((const char *)key); - return key; -} - -static void *k_str2ip(union pattern_data *pdata, union stktable_key_data *kdata, size_t *len) -{ - if (!buf2ip(pdata->str.str, pdata->str.len, &kdata->ip)) - return NULL; - - return (void *)&kdata->ip.s_addr; -} - - -static void *k_str2int(union pattern_data *pdata, union stktable_key_data *kdata, size_t *len) -{ - int i; - - kdata->integer = 0; - for (i = 0; i < pdata->str.len; i++) { - uint32_t val = pdata->str.str[i] - '0'; - - if (val > 9) - break; - - kdata->integer = kdata->integer * 10 + val; - } - return (void *)&kdata->integer; -} - -/*****************************************************************/ -/* typed pattern to typed table key matrix: */ -/* pattern_keys[from pattern type][to table key type] */ -/* NULL pointer used for impossible pattern casts */ -/*****************************************************************/ - -typedef void *(*pattern_key)(union pattern_data *pdata, union stktable_key_data *kdata, size_t *len); -static pattern_key pattern_keys[PATTERN_TYPES][STKTABLE_TYPES] = { { k_ip2ip, k_ip2int, k_ip2str }, - { k_int2ip, k_int2int, k_int2str }, - { k_str2ip, k_str2int, k_str2str } }; /* * Parse a pattern expression configuration: * fetch keyword followed by format conversion keywords. @@ -485,55 +345,6 @@ struct pattern *pattern_process(struct proxy *px, struct session *l4, void *l7, return p; } -/* - * Process a fetch + format conversion of defined by the pattern expression - * on request or response considering the parameter. - * Returns a pointer on a static tablekey structure of type of - * the converted result. - */ -struct stktable_key *pattern_process_key(struct proxy *px, struct session *l4, void *l7, int dir, - struct pattern_expr *expr, unsigned long table_type) -{ - struct pattern *ptrn; - - ptrn = pattern_process(px, l4, l7, dir, expr, NULL); - if (!ptrn) - return NULL; - - stable_key.key_len = (size_t)-1; - stable_key.key = pattern_keys[ptrn->type][table_type](&ptrn->data, &stable_key.data, &stable_key.key_len); - - if (!stable_key.key) - return NULL; - - return &stable_key; -} - -/* - * Returns 1 if pattern expression result cannot be converted to table key of - * type . - * - * Used in configuration check - */ -int pattern_notusable_key(struct pattern_expr *expr, unsigned long table_type) -{ - - if (table_type >= STKTABLE_TYPES) - return 1; - - if (LIST_ISEMPTY(&expr->conv_exprs)) { - if (!pattern_keys[expr->fetch->out_type][table_type]) - return 1; - } else { - struct pattern_conv_expr *conv_expr; - conv_expr = LIST_PREV(&expr->conv_exprs, typeof(conv_expr), list); - - if (!pattern_keys[conv_expr->conv->out_type][table_type]) - return 1; - } - return 0; -} - /* 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. */ diff --git a/src/session.c b/src/session.c index 137bbd330..63184f389 100644 --- a/src/session.c +++ b/src/session.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -936,7 +935,7 @@ int process_sticking_rules(struct session *s, struct buffer *req, int an_bit) if (ret) { struct stktable_key *key; - key = pattern_process_key(px, s, &s->txn, PATTERN_FETCH_REQ, rule->expr, rule->table.t->type); + key = stktable_fetch_key(px, s, &s->txn, PATTERN_FETCH_REQ, rule->expr, rule->table.t->type); if (!key) continue; @@ -1027,7 +1026,7 @@ int process_store_rules(struct session *s, struct buffer *rep, int an_bit) if (ret) { struct stktable_key *key; - key = pattern_process_key(px, s, &s->txn, PATTERN_FETCH_RTR, rule->expr, rule->table.t->type); + key = stktable_fetch_key(px, s, &s->txn, PATTERN_FETCH_RTR, rule->expr, rule->table.t->type); if (!key) continue; diff --git a/src/standard.c b/src/standard.c index c8b0d51b3..3f3e6bd0e 100644 --- a/src/standard.c +++ b/src/standard.c @@ -1007,6 +1007,58 @@ unsigned int inetaddr_host_lim_ret(const char *text, char *stop, const char **re return ((dig100 * 10) + dig10) * 10 + dig1; } +/* Convert a fixed-length string to an IP address. Returns 0 in case of error, + * or the number of chars read in case of success. Maybe this could be replaced + * by one of the functions above. Also, apparently this function does not support + * hosts above 255 and requires exactly 4 octets. + */ +int buf2ip(const char *buf, size_t len, struct in_addr *dst) +{ + const char *addr; + int saw_digit, octets, ch; + u_char tmp[4], *tp; + const char *cp = buf; + + saw_digit = 0; + octets = 0; + *(tp = tmp) = 0; + + for (addr = buf; addr - buf < len; addr++) { + unsigned char digit = (ch = *addr) - '0'; + + if (digit > 9 && ch != '.') + break; + + if (digit <= 9) { + u_int new = *tp * 10 + digit; + + if (new > 255) + return 0; + + *tp = new; + + if (!saw_digit) { + if (++octets > 4) + return 0; + saw_digit = 1; + } + } else if (ch == '.' && saw_digit) { + if (octets == 4) + return 0; + + *++tp = 0; + saw_digit = 0; + } else + return 0; + } + + if (octets < 4) + return 0; + + memcpy(&dst->s_addr, tmp, 4); + return addr - cp; +} + /* * Local variables: * c-indent-level: 8 diff --git a/src/stick_table.c b/src/stick_table.c index 099f78301..fa4692555 100644 --- a/src/stick_table.c +++ b/src/stick_table.c @@ -23,11 +23,15 @@ #include +#include #include #include #include +/* static structure used to return a table key built from a pattern */ +static struct stktable_key static_table_key; + /* * Free an allocated sticky session , and decrease sticky sessions counter * in table . @@ -332,4 +336,141 @@ int stktable_parse_type(char **args, int *myidx, unsigned long *type, size_t *ke return 1; } +/*****************************************************************/ +/* typed pattern to typed table key functions */ +/*****************************************************************/ + +static void *k_int2int(union pattern_data *pdata, union stktable_key_data *kdata, size_t *len) +{ + return (void *)&pdata->integer; +} + +static void *k_ip2ip(union pattern_data *pdata, union stktable_key_data *kdata, size_t *len) +{ + return (void *)&pdata->ip.s_addr; +} + +static void *k_ip2int(union pattern_data *pdata, union stktable_key_data *kdata, size_t *len) +{ + kdata->integer = ntohl(pdata->ip.s_addr); + return (void *)&kdata->integer; +} + +static void *k_int2ip(union pattern_data *pdata, union stktable_key_data *kdata, size_t *len) +{ + kdata->ip.s_addr = htonl(pdata->integer); + return (void *)&kdata->ip.s_addr; +} + +static void *k_str2str(union pattern_data *pdata, union stktable_key_data *kdata, size_t *len) +{ + *len = pdata->str.len; + return (void *)pdata->str.str; +} + +static void *k_ip2str(union pattern_data *pdata, union stktable_key_data *kdata, size_t *len) +{ + if (!inet_ntop(AF_INET, &pdata->ip, kdata->buf, sizeof(kdata->buf))) + return NULL; + + *len = strlen((const char *)kdata->buf); + return (void *)kdata->buf; +} + +static void *k_int2str(union pattern_data *pdata, union stktable_key_data *kdata, size_t *len) +{ + void *key; + + key = (void *)ultoa_r(pdata->integer, kdata->buf, sizeof(kdata->buf)); + if (!key) + return NULL; + + *len = strlen((const char *)key); + return key; +} + +static void *k_str2ip(union pattern_data *pdata, union stktable_key_data *kdata, size_t *len) +{ + if (!buf2ip(pdata->str.str, pdata->str.len, &kdata->ip)) + return NULL; + + return (void *)&kdata->ip.s_addr; +} + + +static void *k_str2int(union pattern_data *pdata, union stktable_key_data *kdata, size_t *len) +{ + int i; + + kdata->integer = 0; + for (i = 0; i < pdata->str.len; i++) { + uint32_t val = pdata->str.str[i] - '0'; + + if (val > 9) + break; + + kdata->integer = kdata->integer * 10 + val; + } + return (void *)&kdata->integer; +} + +/*****************************************************************/ +/* typed pattern to typed table key matrix: */ +/* pattern_to_key[from pattern type][to table key type] */ +/* NULL pointer used for impossible pattern casts */ +/*****************************************************************/ + +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 }, +}; + + +/* + * Process a fetch + format conversion as defined by the pattern expression + * on request or response considering the parameter. Returns either NULL if + * no key could be extracted, or a pointer to the converted result stored in + * static_table_key in format . + */ +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 pattern *ptrn; + + ptrn = pattern_process(px, l4, l7, dir, expr, NULL); + 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); + + if (!static_table_key.key) + return NULL; + + return &static_table_key; +} + +/* + * Returns 1 if pattern expression result can be converted to table key of + * type , otherwise zero. Used in configuration check. + */ +int stktable_compatible_pattern(struct pattern_expr *expr, unsigned long table_type) +{ + if (table_type >= STKTABLE_TYPES) + return 0; + + if (LIST_ISEMPTY(&expr->conv_exprs)) { + if (!pattern_to_key[expr->fetch->out_type][table_type]) + return 0; + } else { + struct pattern_conv_expr *conv_expr; + conv_expr = LIST_PREV(&expr->conv_exprs, typeof(conv_expr), list); + + if (!pattern_to_key[conv_expr->conv->out_type][table_type]) + return 0; + } + return 1; +}