BUG/MEDIUM: stick-table: fix IPv4-to-IPv6 conversion in src_* fetches

The function addr_to_stktable_key doesn't consider the expected
type of key. If the stick table key is based on IPv6 addresses
and the input is IPv4, the returned key is IPv4 adddress and his
length is 4 bytes, while is expected 16 bytes key.

This patch considers the expected key and try to convert IPv4 to
IPv6 and IPv6 to IPv4 according with the expected key.

This fixes the bug reported by Apollon Oikonomopoulos.

This bug was introduced somewhere in the 1.5-dev process.
This commit is contained in:
Thierry FOURNIER 2014-04-14 14:35:40 +02:00 committed by Willy Tarreau
parent b75d692ca6
commit 74c219dc04
2 changed files with 34 additions and 10 deletions

View File

@ -40,19 +40,43 @@ int tcp_inspect_response(struct session *s, struct channel *rep, int an_bit);
int tcp_exec_req_rules(struct session *s);
/* Converts the INET/INET6 source address to a stick_table key usable for table
* lookups. Returns either NULL if the source cannot be converted (eg: not
* IPv4) or a pointer to the converted result in static_table_key in the
* appropriate format (IP).
* lookups. <type> can be STKTABLE_TYPE_IP or STKTABLE_TYPE_IPV6. The function
* try to convert the incoming IP to the type expected by the sticktable.
* Returns either NULL if the source cannot be converted (eg: not IPv4) or a
* pointer to the converted result in static_table_key in the appropriate format
* (IP).
*/
static inline struct stktable_key *addr_to_stktable_key(struct sockaddr_storage *addr)
static inline struct stktable_key *addr_to_stktable_key(struct sockaddr_storage *addr, long type)
{
switch (addr->ss_family) {
case AF_INET:
static_table_key->key = (void *)&((struct sockaddr_in *)addr)->sin_addr;
break;
/* Convert IPv4 to IPv4 key. */
if (type == STKTABLE_TYPE_IP) {
static_table_key->key = (void *)&((struct sockaddr_in *)addr)->sin_addr;
break;
}
/* Convert IPv4 to IPv6 key. */
if (type == STKTABLE_TYPE_IPV6) {
v4tov6(&static_table_key->data.ipv6, &((struct sockaddr_in *)addr)->sin_addr);
static_table_key->key = &static_table_key->data.ipv6;
break;
}
return NULL;
case AF_INET6:
static_table_key->key = (void *)&((struct sockaddr_in6 *)addr)->sin6_addr;
break;
/* Convert IPv6 to IPv4 key. This conversion can be failed. */
if (type == STKTABLE_TYPE_IP) {
if (!v6tov4(&static_table_key->data.ip, &((struct sockaddr_in6 *)addr)->sin6_addr))
return NULL;
static_table_key->key = &static_table_key->data.ip;
break;
}
/* Convert IPv6 to IPv6 key. */
if (type == STKTABLE_TYPE_IPV6) {
static_table_key->key = (void *)&((struct sockaddr_in6 *)addr)->sin6_addr;
break;
}
return NULL;
default:
return NULL;
}

View File

@ -2656,7 +2656,7 @@ smp_fetch_sc_stkctr(struct session *l4, const struct arg *args, const char *kw)
if (!conn)
return NULL;
key = addr_to_stktable_key(&conn->addr.from);
key = addr_to_stktable_key(&conn->addr.from, args->data.prx->table.type);
if (!key)
return NULL;
@ -2880,7 +2880,7 @@ smp_fetch_src_updt_conn_cnt(struct proxy *px, struct session *l4, void *l7, unsi
if (!conn)
return 0;
key = addr_to_stktable_key(&conn->addr.from);
key = addr_to_stktable_key(&conn->addr.from, px->table.type);
if (!key)
return 0;