[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.
diff --git a/include/common/standard.h b/include/common/standard.h
index e20eb77..e7a1052 100644
--- a/include/common/standard.h
+++ b/include/common/standard.h
@@ -549,4 +549,18 @@
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 */
diff --git a/include/proto/proto_tcp.h b/include/proto/proto_tcp.h
index 26e06df..c7aef6a 100644
--- a/include/proto/proto_tcp.h
+++ b/include/proto/proto_tcp.h
@@ -36,18 +36,19 @@
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;
}
diff --git a/include/types/pattern.h b/include/types/pattern.h
index a3d5c36..9b4e340 100644
--- a/include/types/pattern.h
+++ b/include/types/pattern.h
@@ -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 @@
/* 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 @@
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 @@
/* 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*/
};
diff --git a/include/types/stick_table.h b/include/types/stick_table.h
index e519f49..cccf9fb 100644
--- a/include/types/stick_table.h
+++ b/include/types/stick_table.h
@@ -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 @@
/* 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 */
};
diff --git a/src/dumpstats.c b/src/dumpstats.c
index 8b8c3fc..75baadb 100644
--- a/src/dumpstats.c
+++ b/src/dumpstats.c
@@ -3312,12 +3312,19 @@
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);
}
diff --git a/src/pattern.c b/src/pattern.c
index ba8d5a0..e705f00 100644
--- a/src/pattern.c
+++ b/src/pattern.c
@@ -146,6 +146,32 @@
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 @@
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 @@
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 },
};
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index 3c8a04f..ca993a6 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -745,7 +745,7 @@
* 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 @@
* 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 @@
* 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 @@
* 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 @@
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 @@
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 @@
}
-/* 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 @@
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 @@
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 @@
/* 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 },
diff --git a/src/session.c b/src/session.c
index b7914d0..27f4fbd 100644
--- a/src/session.c
+++ b/src/session.c
@@ -2244,9 +2244,9 @@
{
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 @@
{
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 @@
{
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 @@
{
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 @@
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 @@
{
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 @@
{
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 @@
{
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 @@
{
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 @@
{
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 @@
{
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 @@
{
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 @@
{
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 @@
{
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 @@
{
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 @@
{
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);
diff --git a/src/standard.c b/src/standard.c
index 0e5c71e..d3b9ef7 100644
--- a/src/standard.c
+++ b/src/standard.c
@@ -1199,6 +1199,54 @@
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
diff --git a/src/stick_table.c b/src/stick_table.c
index 7c9ad8d..5e9aa35 100644
--- a/src/stick_table.c
+++ b/src/stick_table.c
@@ -406,9 +406,10 @@
* 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 @@
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 @@
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 @@
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 @@
/* 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 },
+
};