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