[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/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 },