Willy,
In this one I added a blank line after declaration that you missed during
review.
Best regards
Tim Düsterhus
Apply with `git am --scissors` to automatically cut the commit message.
-- >8 --
This patch reads a proxy protocol v2 provided unique ID and makes it
available using the `fc_pp_unique_id` fetch.
---
doc/configuration.txt | 4 +++
include/proto/connection.h | 5 +++
include/types/connection.h | 1 +
reg-tests/stream/unique-id-from-proxy.vtc | 38 ++++++++++++++++++++
src/connection.c | 42 +++++++++++++++++++++++
5 files changed, 90 insertions(+)
create mode 100644 reg-tests/stream/unique-id-from-proxy.vtc
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 33425a6c6..57f777a78 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -15131,6 +15131,10 @@ fc_pp_authority : string
Returns the authority TLV sent by the client in the PROXY protocol header,
if any.
+fc_pp_unique_id : string
+ Returns the unique ID TLV sent by the client in the PROXY protocol header,
+ if any.
+
fc_rcvd_proxy : boolean
Returns true if the client initiated the connection with a PROXY protocol
header.
diff --git a/include/proto/connection.h b/include/proto/connection.h
index fb264d2b5..9b8eb8ad3 100644
--- a/include/proto/connection.h
+++ b/include/proto/connection.h
@@ -325,6 +325,7 @@ static inline void conn_init(struct connection *conn)
conn->src = NULL;
conn->dst = NULL;
conn->proxy_authority = NULL;
+ conn->proxy_unique_id = IST_NULL;
}
/* sets <owner> as the connection's owner */
@@ -458,6 +459,10 @@ static inline void conn_free(struct connection *conn)
pool_free(pool_head_authority, conn->proxy_authority);
conn->proxy_authority = NULL;
}
+ if (isttest(conn->proxy_unique_id)) {
+ pool_free(pool_head_uniqueid, conn->proxy_unique_id.ptr);
+ conn->proxy_unique_id = IST_NULL;
+ }
/* By convention we always place a NULL where the ctx points to if the
* mux is null. It may have been used to store the connection as a
diff --git a/include/types/connection.h b/include/types/connection.h
index 0c2d960b9..30cb895ff 100644
--- a/include/types/connection.h
+++ b/include/types/connection.h
@@ -469,6 +469,7 @@ struct connection {
char *proxy_authority; /* Value of authority TLV received via
PROXYv2 */
unsigned int idle_time; /* Time the connection was
added to the idle list, or 0 if not in the idle list */
uint8_t proxy_authority_len; /* Length of authority TLV received via
PROXYv2 */
+ struct ist proxy_unique_id; /* Value of the unique ID TLV received via
PROXYv2 */
};
/* PROTO token registration */
diff --git a/reg-tests/stream/unique-id-from-proxy.vtc
b/reg-tests/stream/unique-id-from-proxy.vtc
new file mode 100644
index 000000000..81ee3dea9
--- /dev/null
+++ b/reg-tests/stream/unique-id-from-proxy.vtc
@@ -0,0 +1,38 @@
+varnishtest "Check that we are able to read a unique-id from PROXYv2"
+
+#REQUIRE_VERSION=2.2
+
+feature ignore_unknown_macro
+
+haproxy h1 -conf {
+ defaults
+ mode http
+ timeout connect 1s
+ timeout client 1s
+ timeout server 1s
+
+ frontend echo
+ bind "fd@${fe1}" accept-proxy
+ http-after-response set-header echo %[fc_pp_unique_id,hex]
+ http-request return status 200
+} -start
+
+client c1 -connect ${h1_fe1_sock} {
+ # PROXY v2 signature
+ sendhex "0d 0a 0d 0a 00 0d 0a 51 55 49 54 0a"
+ # version + PROXY
+ sendhex "21"
+ # TCP4
+ sendhex "11"
+ # length of the address (12) + length of the TLV (8)
+ sendhex "00 14"
+ # 127.0.0.1 42 127.0.0.1 1337
+ sendhex "7F 00 00 01 7F 00 00 01 00 2A 05 39"
+ # PP2_TYPE_UNIQUE_ID + length of the value + "12345"
+ sendhex "05 00 05 31 32 33 34 35"
+
+ txreq -url "/"
+ rxresp
+ expect resp.status == 200
+ expect resp.http.echo == "3132333435"
+} -run
diff --git a/src/connection.c b/src/connection.c
index 4e3a92f0c..728c0ec39 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -755,6 +755,22 @@ int conn_recv_proxy(struct connection *conn, int flag)
conn->proxy_authority_len = tlv_len;
break;
}
+ case PP2_TYPE_UNIQUE_ID: {
+ const struct ist tlv = ist2((const char
*)tlv_packet->value, tlv_len);
+
+ if (tlv.len > UNIQUEID_LEN)
+ goto bad_header;
+ conn->proxy_unique_id.ptr =
pool_alloc(pool_head_uniqueid);
+ if (!isttest(conn->proxy_unique_id))
+ goto fail;
+ if (istcpy(&conn->proxy_unique_id, tlv,
UNIQUEID_LEN) < 0) {
+ /* This is technically unreachable,
because we verified above
+ * that the TLV value fits.
+ */
+ goto fail;
+ }
+ break;
+ }
default:
break;
}
@@ -1586,6 +1602,31 @@ int smp_fetch_fc_pp_authority(const struct arg *args,
struct sample *smp, const
return 1;
}
+/* fetch the unique ID TLV from a PROXY protocol header */
+int smp_fetch_fc_pp_unique_id(const struct arg *args, struct sample *smp,
const char *kw, void *private)
+{
+ struct connection *conn;
+
+ conn = objt_conn(smp->sess->origin);
+ if (!conn)
+ return 0;
+
+ if (conn->flags & CO_FL_WAIT_XPRT) {
+ smp->flags |= SMP_F_MAY_CHANGE;
+ return 0;
+ }
+
+ if (!isttest(conn->proxy_unique_id))
+ return 0;
+
+ smp->flags = 0;
+ smp->data.type = SMP_T_STR;
+ smp->data.u.str.area = conn->proxy_unique_id.ptr;
+ smp->data.u.str.data = conn->proxy_unique_id.len;
+
+ return 1;
+}
+
/* Note: must not be declared <const> as its list will be overwritten.
* Note: fetches that may return multiple types must be declared as the lowest
* common denominator, the type that can be casted into all other ones. For
@@ -1596,6 +1637,7 @@ static struct sample_fetch_kw_list sample_fetch_keywords
= {ILH, {
{ "bc_http_major", smp_fetch_fc_http_major, 0, NULL, SMP_T_SINT,
SMP_USE_L4SRV },
{ "fc_rcvd_proxy", smp_fetch_fc_rcvd_proxy, 0, NULL, SMP_T_BOOL,
SMP_USE_L4CLI },
{ "fc_pp_authority", smp_fetch_fc_pp_authority, 0, NULL, SMP_T_STR,
SMP_USE_L4CLI },
+ { "fc_pp_unique_id", smp_fetch_fc_pp_unique_id, 0, NULL, SMP_T_STR,
SMP_USE_L4CLI },
{ /* END */ },
}};
--
2.25.1