MINOR: tcp_samples: Add samples to get src/dst info of the backend connection

This patch adds 4 new sample fetches to get the source and the destination
info (ip address and port) of the backend connection :

 * bc_dst      : Returns the destination address of the backend connection
 * bc_dst_port : Returns the destination port of the backend connection
 * bc_src      : Returns the source address of the backend connection
 * bc_src_port : Returns the source port of the backend connection

The configuration manual was updated accordingly.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 61c2a6d..4241f92 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -17247,11 +17247,31 @@
 tracked key will be looked up into this alternate table instead of the table
 currently being tracked.
 
+bc_dst : ip
+  This is the destination ip address of the connection on the server side,
+  which is the server address HAProxy connected to. It is of type IP and works
+  on both IPv4 and IPv6 tables.  On IPv6 tables, IPv4 address is mapped to its
+  IPv6 equivalent, according to RFC 4291.
+
+bc_dst_port : integer
+  Returns an integer value corresponding to the destination TCP port of the
+  connection on the server side, which is the port HAproxy connected to.
+
 bc_http_major : integer
   Returns the backend connection's HTTP major version encoding, which may be 1
   for HTTP/0.9 to HTTP/1.1 or 2 for HTTP/2. Note, this is based on the on-wire
   encoding and not the version present in the request header.
 
+bc_src : ip
+  This is the source ip address of the connection on the server side, which is
+  the server address haproxy connected from. It is of type IP and works on both
+  IPv4 and IPv6 tables. On IPv6 tables, IPv4 addresses are mapped to their IPv6
+  equivalent, according to RFC 4291.
+
+bc_src_port : integer
+  Returns an integer value corresponding to the TCP source port of the
+  connection on the server side, which is the port HAproxy connected from.
+
 be_id : integer
   Returns an integer containing the current backend's id. It can be used in
   frontends with responses to check which backend processed the request. It can
diff --git a/src/tcp_sample.c b/src/tcp_sample.c
index 06ad6c6..4fbd98c 100644
--- a/src/tcp_sample.c
+++ b/src/tcp_sample.c
@@ -41,27 +41,28 @@
 #include <haproxy/tools.h>
 
 
-/* Fetch the connection's source IPv4/IPv6 address. Note that this is also
- * directly called by stick_table.c and as such must remain publicly visible.
+/* Fetch the connection's source IPv4/IPv6 address. Depending on the keyword, it
+ * may be the frontend or the backend connection.
  */
 static int
 smp_fetch_src(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	struct connection *cli_conn = objt_conn(smp->sess->origin);
+	struct connection *conn = (kw[0] != 'b') ? objt_conn(smp->sess->origin) :
+		smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
 
-	if (!cli_conn)
+	if (!conn)
 		return 0;
 
-	if (!conn_get_src(cli_conn))
+	if (!conn_get_src(conn))
 		return 0;
 
-	switch (cli_conn->src->ss_family) {
+	switch (conn->src->ss_family) {
 	case AF_INET:
-		smp->data.u.ipv4 = ((struct sockaddr_in *)cli_conn->src)->sin_addr;
+		smp->data.u.ipv4 = ((struct sockaddr_in *)conn->src)->sin_addr;
 		smp->data.type = SMP_T_IPV4;
 		break;
 	case AF_INET6:
-		smp->data.u.ipv6 = ((struct sockaddr_in6 *)cli_conn->src)->sin6_addr;
+		smp->data.u.ipv6 = ((struct sockaddr_in6 *)conn->src)->sin6_addr;
 		smp->data.type = SMP_T_IPV6;
 		break;
 	default:
@@ -72,45 +73,51 @@
 	return 1;
 }
 
-/* set temp integer to the connection's source port */
+/* set temp integer to the connection's source port. Depending on the
+ * keyword, it may be the frontend or the backend connection.
+ */
 static int
-smp_fetch_sport(const struct arg *args, struct sample *smp, const char *k, void *private)
+smp_fetch_sport(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	struct connection *cli_conn = objt_conn(smp->sess->origin);
+	struct connection *conn = (kw[0] != 'b') ? objt_conn(smp->sess->origin) :
+		smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
 
-	if (!cli_conn)
+	if (!conn)
 		return 0;
 
-	if (!conn_get_src(cli_conn))
+	if (!conn_get_src(conn))
 		return 0;
 
 	smp->data.type = SMP_T_SINT;
-	if (!(smp->data.u.sint = get_host_port(cli_conn->src)))
+	if (!(smp->data.u.sint = get_host_port(conn->src)))
 		return 0;
 
 	smp->flags = 0;
 	return 1;
 }
 
-/* fetch the connection's destination IPv4/IPv6 address */
+/* fetch the connection's destination IPv4/IPv6 address. Depending on the
+ * keyword, it may be the frontend or the backend connection.
+ */
 static int
 smp_fetch_dst(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	struct connection *cli_conn = objt_conn(smp->sess->origin);
+	struct connection *conn = (kw[0] != 'b') ? objt_conn(smp->sess->origin) :
+		smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
 
-	if (!cli_conn)
+	if (!conn)
 		return 0;
 
-	if (!conn_get_dst(cli_conn))
+	if (!conn_get_dst(conn))
 		return 0;
 
-	switch (cli_conn->dst->ss_family) {
+	switch (conn->dst->ss_family) {
 	case AF_INET:
-		smp->data.u.ipv4 = ((struct sockaddr_in *)cli_conn->dst)->sin_addr;
+		smp->data.u.ipv4 = ((struct sockaddr_in *)conn->dst)->sin_addr;
 		smp->data.type = SMP_T_IPV4;
 		break;
 	case AF_INET6:
-		smp->data.u.ipv6 = ((struct sockaddr_in6 *)cli_conn->dst)->sin6_addr;
+		smp->data.u.ipv6 = ((struct sockaddr_in6 *)conn->dst)->sin6_addr;
 		smp->data.type = SMP_T_IPV6;
 		break;
 	default:
@@ -161,20 +168,23 @@
 	return smp->data.u.sint >= 0;
 }
 
-/* set temp integer to the frontend connexion's destination port */
+/* set temp integer to the connexion's destination port. Depending on the
+ * keyword, it may be the frontend or the backend connection.
+ */
 static int
 smp_fetch_dport(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	struct connection *cli_conn = objt_conn(smp->sess->origin);
+	struct connection *conn = (kw[0] != 'b') ? objt_conn(smp->sess->origin) :
+		smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
 
-	if (!cli_conn)
+	if (!conn)
 		return 0;
 
-	if (!conn_get_dst(cli_conn))
+	if (!conn_get_dst(conn))
 		return 0;
 
 	smp->data.type = SMP_T_SINT;
-	if (!(smp->data.u.sint = get_host_port(cli_conn->dst)))
+	if (!(smp->data.u.sint = get_host_port(conn->dst)))
 		return 0;
 
 	smp->flags = 0;
@@ -383,6 +393,11 @@
  * instance v4/v6 must be declared v4.
  */
 static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
+	{ "bc_dst",      smp_fetch_dst,   0, NULL, SMP_T_SINT, SMP_USE_L4SRV },
+	{ "bc_dst_port", smp_fetch_dport, 0, NULL, SMP_T_SINT, SMP_USE_L4SRV },
+	{ "bc_src",      smp_fetch_src,   0, NULL, SMP_T_SINT, SMP_USE_L4SRV },
+	{ "bc_src_port", smp_fetch_sport, 0, NULL, SMP_T_SINT, SMP_USE_L4SRV },
+
 	{ "dst",      smp_fetch_dst,   0, NULL, SMP_T_IPV4, SMP_USE_L4CLI },
 	{ "dst_is_local", smp_fetch_dst_is_local, 0, NULL, SMP_T_BOOL, SMP_USE_L4CLI },
 	{ "dst_port", smp_fetch_dport, 0, NULL, SMP_T_SINT, SMP_USE_L4CLI },