[MEDIUM] IPv6 support for stick-tables

Since IPv6 is a different type than IPv4, the pattern fetch functions
src6 and dst6 were added. IPv6 stick-tables can also fetch IPv4 addresses
with src and dst. In this case, the IPv4 addresses are mapped to their
IPv6 counterpart, according to RFC 4291.
This commit is contained in:
David du Colombier 2011-03-24 11:09:31 +01:00 committed by Willy Tarreau
parent be2e1d3ef4
commit 4f92d32004
10 changed files with 246 additions and 64 deletions

View File

@ -549,4 +549,18 @@ static inline int set_host_port(struct sockaddr_storage *addr, int port)
return 0;
}
/* Return true if IPv4 address is part of the network */
extern int in_net_ipv4(struct in_addr *addr, struct in_addr *mask, struct in_addr *net);
/* Return true if IPv6 address is part of the network */
extern int in_net_ipv6(struct in6_addr *addr, struct in6_addr *mask, struct in6_addr *net);
/* Map IPv4 adress on IPv6 address, as specified in RFC 3513. */
extern void v4tov6(struct in6_addr *sin6_addr, struct in_addr *sin_addr);
/* Map IPv6 adress on IPv4 address, as specified in RFC 3513.
* Return true if conversion is possible and false otherwise.
*/
extern int v6tov4(struct in_addr *sin_addr, struct in6_addr *sin6_addr);
#endif /* _COMMON_STANDARD_H */

View File

@ -36,18 +36,19 @@ int tcp_inspect_response(struct session *s, struct buffer *rep, int an_bit);
int tcp_persist_rdp_cookie(struct session *s, struct buffer *req, int an_bit);
int tcp_exec_req_rules(struct session *s);
/* Converts the TCPv4 source address to a stick_table key usable for table
/* Converts the TCP 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).
*/
static inline struct stktable_key *tcpv4_src_to_stktable_key(struct session *s)
static inline struct stktable_key *tcp_src_to_stktable_key(struct session *s)
{
/* right now we only support IPv4 */
if (s->si[0].addr.c.from.ss_family != AF_INET)
return NULL;
static_table_key.key = (void *)&((struct sockaddr_in *)&s->si[0].addr.c.from)->sin_addr;
switch (s->si[0].addr.c.from.ss_family) {
case AF_INET:
static_table_key.key = (void *)&((struct sockaddr_in *)&s->si[0].addr.c.from)->sin_addr;
case AF_INET6:
static_table_key.key = (void *)&((struct sockaddr_in6 *)&s->si[0].addr.c.from)->sin6_addr;
}
return &static_table_key;
}

View File

@ -29,6 +29,7 @@
/* pattern in and out types */
enum {
PATTERN_TYPE_IP = 0, /* ipv4 type */
PATTERN_TYPE_IPV6, /* ipv6 type */
PATTERN_TYPE_INTEGER, /* unsigned 32bits integer type */
PATTERN_TYPE_STRING, /* char string type */
PATTERN_TYPE_DATA, /* buffer type */
@ -41,6 +42,7 @@ enum {
/* pattern arg types */
enum {
PATTERN_ARG_TYPE_IP = 0, /* ipv4 type */
PATTERN_ARG_TYPE_IPV6, /* ipv6 type */
PATTERN_ARG_TYPE_INTEGER, /* unsigned 32bits integer type */
PATTERN_ARG_TYPE_SINTEGER, /* signed 32bits integer type */
PATTERN_ARG_TYPE_STRING /* string type */
@ -53,6 +55,7 @@ enum {
union pattern_arg_data {
struct in_addr ip; /* used for ipv4 type */
struct in6_addr ipv6; /* used for ipv6 type */
uint32_t integer; /* used for unsigned 32bits integer type */
int sinteger; /* used for signed 32bits integer type */
struct chunk str;
@ -66,6 +69,7 @@ struct pattern_arg {
/* pattern result data */
union pattern_data {
struct in_addr ip; /* used for ipv4 type */
struct in6_addr ipv6; /* used for ipv6 type */
uint32_t integer; /* used for unsigned 32bits integer type */
struct chunk str; /* used for char string type or buffers*/
};

View File

@ -35,6 +35,7 @@
/* stick table key types */
enum {
STKTABLE_TYPE_IP = 0, /* table key is ipv4 */
STKTABLE_TYPE_IPV6, /* table key is ipv6 */
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 */
@ -172,7 +173,8 @@ extern struct stktable_data_type stktable_data_types[STKTABLE_DATA_TYPES];
/* stick table key data */
union stktable_key_data {
struct in_addr ip; /* used to store an ip key */
struct in_addr ip; /* used to store an ipv4 key */
struct in6_addr ipv6; /* used to store an ipv6 key */
uint32_t integer; /* used to store an integer key */
char buf[BUFSIZE]; /* used to store a null terminated string key or a buffer of data */
};

View File

@ -3312,12 +3312,19 @@ int stats_dump_table_to_buffer(struct stream_interface *si)
chunk_printf(&msg, "%p:", si->applet.ctx.table.entry);
if (si->applet.ctx.table.proxy->table.type == STKTABLE_TYPE_IP) {
char addr[16];
char addr[INET_ADDRSTRLEN];
inet_ntop(AF_INET,
(const void *)&si->applet.ctx.table.entry->key.key,
addr, sizeof(addr));
chunk_printf(&msg, " key=%s", addr);
}
else if (si->applet.ctx.table.proxy->table.type == STKTABLE_TYPE_IPV6) {
char addr[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6,
(const void *)&si->applet.ctx.table.entry->key.key,
addr, sizeof(addr));
chunk_printf(&msg, " key=%s", addr);
}
else if (si->applet.ctx.table.proxy->table.type == STKTABLE_TYPE_INTEGER) {
chunk_printf(&msg, " key=%u", *(unsigned int *)si->applet.ctx.table.entry->key.key);
}

View File

@ -146,6 +146,32 @@ static int c_ip2str(union pattern_data *data)
return 1;
}
static int c_ip2ipv6(union pattern_data *data)
{
v4tov6(&data->ipv6, &data->ip);
return 1;
}
static int c_ipv62str(union pattern_data *data)
{
struct chunk *trash = get_trash_chunk();
if (!inet_ntop(AF_INET6, (void *)&data->ipv6, trash->str, trash->size))
return 0;
trash->len = strlen(trash->str);
pattern_data_setstring(data, trash);
return 1;
}
/*
static int c_ipv62ip(union pattern_data *data)
{
return v6tov4(&data->ip, &data->ipv6);
}
*/
static int c_int2ip(union pattern_data *data)
{
data->ip.s_addr = htonl(data->integer);
@ -159,6 +185,11 @@ static int c_str2ip(union pattern_data *data)
return 1;
}
static int c_str2ipv6(union pattern_data *data)
{
return inet_pton(AF_INET6, data->str.str, &data->ipv6);
}
static int c_int2str(union pattern_data *data)
{
struct chunk *trash = get_trash_chunk();
@ -222,13 +253,14 @@ 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] = {
/* 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 },
/* to: IP IPV6 INTEGER STRING DATA CONSTSTRING CONSTDATA */
/* from: IP */ { c_donothing, c_ip2ipv6, c_ip2int, c_ip2str, NULL, c_ip2str, NULL },
/* IPV6 */ { NULL, c_donothing, NULL, c_ipv62str, NULL, c_ipv62str, NULL },
/* INTEGER */ { c_int2ip, NULL, c_donothing, c_int2str, NULL, c_int2str, NULL },
/* STRING */ { c_str2ip, c_str2ipv6, c_str2int, c_donothing, c_donothing, c_donothing, c_donothing },
/* DATA */ { NULL, NULL, NULL, NULL, c_donothing, NULL, c_donothing },
/* CONSTSTRING */ { c_str2ip, c_str2ipv6, c_str2int, c_datadup, c_datadup, c_donothing, c_donothing },
/* CONSTDATA */ { NULL, NULL, NULL, NULL, c_datadup, NULL, c_donothing },
};

View File

@ -745,7 +745,7 @@ int tcp_inspect_request(struct session *s, struct buffer *req, int an_bit)
* to consider rule->act_prm->trk_ctr.type.
*/
t = rule->act_prm.trk_ctr.table.t;
ts = stktable_get_entry(t, tcpv4_src_to_stktable_key(s));
ts = stktable_get_entry(t, tcp_src_to_stktable_key(s));
if (ts) {
session_track_stkctr1(s, t, ts);
if (s->fe != s->be)
@ -761,7 +761,7 @@ int tcp_inspect_request(struct session *s, struct buffer *req, int an_bit)
* to consider rule->act_prm->trk_ctr.type.
*/
t = rule->act_prm.trk_ctr.table.t;
ts = stktable_get_entry(t, tcpv4_src_to_stktable_key(s));
ts = stktable_get_entry(t, tcp_src_to_stktable_key(s));
if (ts) {
session_track_stkctr2(s, t, ts);
if (s->fe != s->be)
@ -915,7 +915,7 @@ int tcp_exec_req_rules(struct session *s)
* to consider rule->act_prm->trk_ctr.type.
*/
t = rule->act_prm.trk_ctr.table.t;
ts = stktable_get_entry(t, tcpv4_src_to_stktable_key(s));
ts = stktable_get_entry(t, tcp_src_to_stktable_key(s));
if (ts)
session_track_stkctr1(s, t, ts);
}
@ -928,7 +928,7 @@ int tcp_exec_req_rules(struct session *s)
* to consider rule->act_prm->trk_ctr.type.
*/
t = rule->act_prm.trk_ctr.table.t;
ts = stktable_get_entry(t, tcpv4_src_to_stktable_key(s));
ts = stktable_get_entry(t, tcp_src_to_stktable_key(s));
if (ts)
session_track_stkctr2(s, t, ts);
}
@ -1275,7 +1275,7 @@ acl_fetch_src(struct proxy *px, struct session *l4, void *l7, int dir,
return 1;
}
/* extract the connection's source address */
/* extract the connection's source ipv4 address */
static int
pattern_fetch_src(struct proxy *px, struct session *l4, void *l7, int dir,
const struct pattern_arg *arg_p, int arg_i, union pattern_data *data)
@ -1287,6 +1287,17 @@ pattern_fetch_src(struct proxy *px, struct session *l4, void *l7, int dir,
return 1;
}
/* extract the connection's source ipv6 address */
static int
pattern_fetch_src6(struct proxy *px, struct session *l4, void *l7, int dir,
const struct pattern_arg *arg_p, int arg_i, union pattern_data *data)
{
if (l4->si[0].addr.c.from.ss_family != AF_INET6)
return 0;
memcpy(data->ipv6.s6_addr, ((struct sockaddr_in6 *)&l4->si[0].addr.c.from)->sin6_addr.s6_addr, sizeof(data->ipv6.s6_addr));
return 1;
}
/* set test->i to the connection's source port */
static int
@ -1326,7 +1337,7 @@ acl_fetch_dst(struct proxy *px, struct session *l4, void *l7, int dir,
}
/* extract the connection's destination address */
/* extract the connection's destination ipv4 address */
static int
pattern_fetch_dst(struct proxy *px, struct session *l4, void *l7, int dir,
const struct pattern_arg *arg_p, int arg_i, union pattern_data *data)
@ -1341,6 +1352,21 @@ pattern_fetch_dst(struct proxy *px, struct session *l4, void *l7, int dir,
return 1;
}
/* extract the connection's destination ipv6 address */
static int
pattern_fetch_dst6(struct proxy *px, struct session *l4, void *l7, int dir,
const struct pattern_arg *arg_p, int arg_i, union pattern_data *data)
{
if (!(l4->flags & SN_FRT_ADDR_SET))
get_frt_addr(l4);
if (l4->si[0].addr.c.to.ss_family != AF_INET6)
return 0;
memcpy(data->ipv6.s6_addr, ((struct sockaddr_in6 *)&l4->si[0].addr.c.to)->sin6_addr.s6_addr, sizeof(data->ipv6.s6_addr));
return 1;
}
/* set test->i to the frontend connexion's destination port */
static int
acl_fetch_dport(struct proxy *px, struct session *l4, void *l7, int dir,
@ -1367,10 +1393,13 @@ pattern_fetch_dport(struct proxy *px, struct session *l4, void *l7, int dir,
if (!(l4->flags & SN_FRT_ADDR_SET))
get_frt_addr(l4);
if (l4->si[0].addr.c.to.ss_family != AF_INET)
if (l4->si[0].addr.c.to.ss_family == AF_INET)
data->integer = ntohs(((struct sockaddr_in *)&l4->si[0].addr.c.to)->sin_port);
else if (l4->si[0].addr.c.to.ss_family == AF_INET6)
data->integer = ntohs(((struct sockaddr_in6 *)&l4->si[0].addr.c.to)->sin6_port);
else
return 0;
data->integer = ntohs(((struct sockaddr_in *)&l4->si[0].addr.c.to)->sin_port);
return 1;
}
@ -1566,7 +1595,9 @@ 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, NULL, PATTERN_TYPE_IP, PATTERN_FETCH_REQ },
{ "src6", pattern_fetch_src6, NULL, PATTERN_TYPE_IPV6, PATTERN_FETCH_REQ },
{ "dst", pattern_fetch_dst, NULL, PATTERN_TYPE_IP, PATTERN_FETCH_REQ },
{ "dst6", pattern_fetch_dst6, NULL, PATTERN_TYPE_IPV6, PATTERN_FETCH_REQ },
{ "dst_port", pattern_fetch_dport, NULL, PATTERN_TYPE_INTEGER, PATTERN_FETCH_REQ },
{ "payload", pattern_fetch_payload, pattern_arg_fetch_payload, PATTERN_TYPE_CONSTDATA, PATTERN_FETCH_REQ|PATTERN_FETCH_RTR },
{ "payload_lv", pattern_fetch_payloadlv, pattern_arg_fetch_payloadlv, PATTERN_TYPE_CONSTDATA, PATTERN_FETCH_REQ|PATTERN_FETCH_RTR },

View File

@ -2244,9 +2244,9 @@ acl_fetch_src_get_gpc0(struct proxy *px, struct session *l4, void *l7, int dir,
{
struct stktable_key *key;
key = tcpv4_src_to_stktable_key(l4);
key = tcp_src_to_stktable_key(l4);
if (!key)
return 0; /* only TCPv4 is supported right now */
return 0;
if (expr->arg_len)
px = find_stktable(expr->arg.str);
@ -2307,9 +2307,9 @@ acl_fetch_src_inc_gpc0(struct proxy *px, struct session *l4, void *l7, int dir,
{
struct stktable_key *key;
key = tcpv4_src_to_stktable_key(l4);
key = tcp_src_to_stktable_key(l4);
if (!key)
return 0; /* only TCPv4 is supported right now */
return 0;
if (expr->arg_len)
px = find_stktable(expr->arg.str);
@ -2366,9 +2366,9 @@ acl_fetch_src_conn_cnt(struct proxy *px, struct session *l4, void *l7, int dir,
{
struct stktable_key *key;
key = tcpv4_src_to_stktable_key(l4);
key = tcp_src_to_stktable_key(l4);
if (!key)
return 0; /* only TCPv4 is supported right now */
return 0;
if (expr->arg_len)
px = find_stktable(expr->arg.str);
@ -2430,9 +2430,9 @@ acl_fetch_src_conn_rate(struct proxy *px, struct session *l4, void *l7, int dir,
{
struct stktable_key *key;
key = tcpv4_src_to_stktable_key(l4);
key = tcp_src_to_stktable_key(l4);
if (!key)
return 0; /* only TCPv4 is supported right now */
return 0;
if (expr->arg_len)
px = find_stktable(expr->arg.str);
@ -2454,9 +2454,9 @@ acl_fetch_src_updt_conn_cnt(struct proxy *px, struct session *l4, void *l7, int
struct stktable_key *key;
void *ptr;
key = tcpv4_src_to_stktable_key(l4);
key = tcp_src_to_stktable_key(l4);
if (!key)
return 0; /* only TCPv4 is supported right now */
return 0;
if (expr->arg_len)
px = find_stktable(expr->arg.str);
@ -2524,9 +2524,9 @@ acl_fetch_src_conn_cur(struct proxy *px, struct session *l4, void *l7, int dir,
{
struct stktable_key *key;
key = tcpv4_src_to_stktable_key(l4);
key = tcp_src_to_stktable_key(l4);
if (!key)
return 0; /* only TCPv4 is supported right now */
return 0;
if (expr->arg_len)
px = find_stktable(expr->arg.str);
@ -2583,9 +2583,9 @@ acl_fetch_src_sess_cnt(struct proxy *px, struct session *l4, void *l7, int dir,
{
struct stktable_key *key;
key = tcpv4_src_to_stktable_key(l4);
key = tcp_src_to_stktable_key(l4);
if (!key)
return 0; /* only TCPv4 is supported right now */
return 0;
if (expr->arg_len)
px = find_stktable(expr->arg.str);
@ -2647,9 +2647,9 @@ acl_fetch_src_sess_rate(struct proxy *px, struct session *l4, void *l7, int dir,
{
struct stktable_key *key;
key = tcpv4_src_to_stktable_key(l4);
key = tcp_src_to_stktable_key(l4);
if (!key)
return 0; /* only TCPv4 is supported right now */
return 0;
if (expr->arg_len)
px = find_stktable(expr->arg.str);
@ -2706,9 +2706,9 @@ acl_fetch_src_http_req_cnt(struct proxy *px, struct session *l4, void *l7, int d
{
struct stktable_key *key;
key = tcpv4_src_to_stktable_key(l4);
key = tcp_src_to_stktable_key(l4);
if (!key)
return 0; /* only TCPv4 is supported right now */
return 0;
if (expr->arg_len)
px = find_stktable(expr->arg.str);
@ -2770,9 +2770,9 @@ acl_fetch_src_http_req_rate(struct proxy *px, struct session *l4, void *l7, int
{
struct stktable_key *key;
key = tcpv4_src_to_stktable_key(l4);
key = tcp_src_to_stktable_key(l4);
if (!key)
return 0; /* only TCPv4 is supported right now */
return 0;
if (expr->arg_len)
px = find_stktable(expr->arg.str);
@ -2829,9 +2829,9 @@ acl_fetch_src_http_err_cnt(struct proxy *px, struct session *l4, void *l7, int d
{
struct stktable_key *key;
key = tcpv4_src_to_stktable_key(l4);
key = tcp_src_to_stktable_key(l4);
if (!key)
return 0; /* only TCPv4 is supported right now */
return 0;
if (expr->arg_len)
px = find_stktable(expr->arg.str);
@ -2893,9 +2893,9 @@ acl_fetch_src_http_err_rate(struct proxy *px, struct session *l4, void *l7, int
{
struct stktable_key *key;
key = tcpv4_src_to_stktable_key(l4);
key = tcp_src_to_stktable_key(l4);
if (!key)
return 0; /* only TCPv4 is supported right now */
return 0;
if (expr->arg_len)
px = find_stktable(expr->arg.str);
@ -2957,9 +2957,9 @@ acl_fetch_src_kbytes_in(struct proxy *px, struct session *l4, void *l7, int dir,
{
struct stktable_key *key;
key = tcpv4_src_to_stktable_key(l4);
key = tcp_src_to_stktable_key(l4);
if (!key)
return 0; /* only TCPv4 is supported right now */
return 0;
if (expr->arg_len)
px = find_stktable(expr->arg.str);
@ -3023,9 +3023,9 @@ acl_fetch_src_bytes_in_rate(struct proxy *px, struct session *l4, void *l7, int
{
struct stktable_key *key;
key = tcpv4_src_to_stktable_key(l4);
key = tcp_src_to_stktable_key(l4);
if (!key)
return 0; /* only TCPv4 is supported right now */
return 0;
if (expr->arg_len)
px = find_stktable(expr->arg.str);
@ -3087,9 +3087,9 @@ acl_fetch_src_kbytes_out(struct proxy *px, struct session *l4, void *l7, int dir
{
struct stktable_key *key;
key = tcpv4_src_to_stktable_key(l4);
key = tcp_src_to_stktable_key(l4);
if (!key)
return 0; /* only TCPv4 is supported right now */
return 0;
if (expr->arg_len)
px = find_stktable(expr->arg.str);
@ -3153,9 +3153,9 @@ acl_fetch_src_bytes_out_rate(struct proxy *px, struct session *l4, void *l7, int
{
struct stktable_key *key;
key = tcpv4_src_to_stktable_key(l4);
key = tcp_src_to_stktable_key(l4);
if (!key)
return 0; /* only TCPv4 is supported right now */
return 0;
if (expr->arg_len)
px = find_stktable(expr->arg.str);

View File

@ -1199,6 +1199,54 @@ unsigned int full_hash(unsigned int a)
return __full_hash(a);
}
/* Return non-zero if IPv4 address is part of the network,
* otherwise zero.
*/
int in_net_ipv4(struct in_addr *addr, struct in_addr *mask, struct in_addr *net)
{
return((addr->s_addr & mask->s_addr) == (net->s_addr & mask->s_addr));
}
/* Return non-zero if IPv6 address is part of the network,
* otherwise zero.
*/
int in_net_ipv6(struct in6_addr *addr, struct in6_addr *mask, struct in6_addr *net)
{
int i;
for (i = 0; i < sizeof(struct in6_addr) / sizeof(int); i++)
if (((((int *)addr)[i] & ((int *)mask)[i])) !=
(((int *)net)[i] & ((int *)mask)[i]))
return 0;
return 1;
}
/* RFC 4291 prefix */
const char rfc4291_pfx[] = { 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFF, 0xFF };
/* Map IPv4 adress on IPv6 address, as specified in RFC 3513. */
void v4tov6(struct in6_addr *sin6_addr, struct in_addr *sin_addr)
{
memcpy(sin6_addr->s6_addr, rfc4291_pfx, sizeof(rfc4291_pfx));
memcpy(sin6_addr->s6_addr+12, &sin_addr->s_addr, 4);
}
/* Map IPv6 adress on IPv4 address, as specified in RFC 3513.
* Return true if conversion is possible and false otherwise.
*/
int v6tov4(struct in_addr *sin_addr, struct in6_addr *sin6_addr)
{
if (memcmp(sin6_addr->s6_addr, rfc4291_pfx, sizeof(rfc4291_pfx)) == 0) {
memcpy(&(sin_addr->s_addr), &(sin6_addr->s6_addr[12]),
sizeof(struct in_addr));
return 1;
}
return 0;
}
/*
* Local variables:
* c-indent-level: 8

View File

@ -406,9 +406,10 @@ int stktable_init(struct stktable *t)
* Configuration keywords of known table types
*/
struct stktable_type stktable_types[STKTABLE_TYPES] = {{ "ip", 0, 4 },
{ "ipv6", 0, 16 },
{ "integer", 0, 4 },
{ "string", STK_F_CUSTOM_KEYSIZE, 32 },
{ "binary", STK_F_CUSTOM_KEYSIZE, 32 } };
{ "binary", STK_F_CUSTOM_KEYSIZE, 32 } };
/*
@ -457,6 +458,25 @@ static void *k_ip2ip(union pattern_data *pdata, union stktable_key_data *kdata,
return (void *)&pdata->ip.s_addr;
}
static void *k_ip2ipv6(union pattern_data *pdata, union stktable_key_data *kdata, size_t *len)
{
v4tov6(&pdata->ipv6, &pdata->ip);
return (void *)&pdata->ipv6.s6_addr;
}
static void *k_ipv62ipv6(union pattern_data *pdata, union stktable_key_data *kdata, size_t *len)
{
return (void *)&pdata->ipv6.s6_addr;
}
/*
static void *k_ipv62ip(union pattern_data *pdata, union stktable_key_data *kdata, size_t *len)
{
v6tov4(&pdata->ip, &pdata->ipv6);
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);
@ -484,6 +504,15 @@ static void *k_ip2str(union pattern_data *pdata, union stktable_key_data *kdata,
return (void *)kdata->buf;
}
static void *k_ipv62str(union pattern_data *pdata, union stktable_key_data *kdata, size_t *len)
{
if (!inet_ntop(AF_INET6, &pdata->ipv6, 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;
@ -504,6 +533,13 @@ static void *k_str2ip(union pattern_data *pdata, union stktable_key_data *kdata,
return (void *)&kdata->ip.s_addr;
}
static void *k_str2ipv6(union pattern_data *pdata, union stktable_key_data *kdata, size_t *len)
{
if (!inet_pton(AF_INET6, pdata->str.str, &kdata->ipv6))
return NULL;
return (void *)&kdata->ipv6.s6_addr;
}
static void *k_str2int(union pattern_data *pdata, union stktable_key_data *kdata, size_t *len)
{
@ -527,15 +563,22 @@ static void *k_str2int(union pattern_data *pdata, union stktable_key_data *kdata
/* NULL pointer used for impossible pattern casts */
/*****************************************************************/
/*
* Conversions from IPv6 to IPv4 are available, but we haven't
* added them to the table since they doesn't seem sufficely
* relevant and could cause confusion in configuration.
*/
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] = {
/* 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 },
/* table type: IP IPV6 INTEGER STRING BINARY */
/* pattern type: IP */ { k_ip2ip, k_ip2ipv6, k_ip2int, k_ip2str, NULL },
/* IPV6 */ { NULL, k_ipv62ipv6, NULL, k_ipv62str, NULL },
/* INTEGER */ { k_int2ip, NULL, k_int2int, k_int2str, NULL },
/* STRING */ { k_str2ip, k_str2ipv6, k_str2int, k_str2str, k_str2str },
/* DATA */ { NULL, NULL, NULL, NULL, k_str2str },
/* CONSTSTRING */ { k_str2ip, k_str2ipv6, k_str2int, k_str2str, k_str2str },
};