[master] f2b398f0c varnishtest: Add tlv capabilities to client -proxy

Nils Goroll nils.goroll at uplex.de
Fri Feb 21 12:19:11 UTC 2025


commit f2b398f0ce0a3575bb3d3546f49cb40792ca8854
Author: Nils Goroll <nils.goroll at uplex.de>
Date:   Fri Feb 21 13:12:07 2025 +0100

    varnishtest: Add tlv capabilities to client -proxy

diff --git a/bin/varnishtest/vtc.h b/bin/varnishtest/vtc.h
index e7513092e..2e5d4161a 100644
--- a/bin/varnishtest/vtc.h
+++ b/bin/varnishtest/vtc.h
@@ -124,8 +124,9 @@ void vtc_dump(struct vtclog *vl, int lvl, const char *pfx,
     const char *str, int len);
 void vtc_hexdump(struct vtclog *, int , const char *, const void *, unsigned);
 
+void vtc_proxy_tlv(struct vtclog *vl, struct vsb *vsb, const char *kva);
 int vtc_send_proxy(int fd, int version, const struct suckaddr *sac,
-    const struct suckaddr *sas);
+    const struct suckaddr *sas, struct vsb *tlb);
 
 int exec_file(const char *fn, const char *script, const char *tmpdir,
     char *logbuf, unsigned loglen);
diff --git a/bin/varnishtest/vtc_client.c b/bin/varnishtest/vtc_client.c
index 1e52f6cdb..1281cc5a9 100644
--- a/bin/varnishtest/vtc_client.c
+++ b/bin/varnishtest/vtc_client.c
@@ -78,6 +78,7 @@ client_proxy(struct vtclog *vl, int fd, int version, const char *speca)
 {
 	const struct suckaddr *sac, *sas;
 	char *spec, *save, *p;
+	struct vsb *tlv;
 
 	spec = strdup(speca);
 	AN(spec);
@@ -95,9 +96,14 @@ client_proxy(struct vtclog *vl, int fd, int version, const char *speca)
 	if (sas == NULL)
 		vtc_fatal(vl, "Could not resolve client address");
 
+	tlv = VSB_new_auto();
+	while ((p = strtok_r(NULL, " ", &save)) != NULL)
+		vtc_proxy_tlv(vl, tlv, p);
+
 	free(spec);
 
-	if (vtc_send_proxy(fd, version, sac, sas))
+	AZ(VSB_finish(tlv));
+	if (vtc_send_proxy(fd, version, sac, sas, tlv))
 		vtc_fatal(vl, "Write failed: %s", strerror(errno));
 	VSA_free(&sac);
 	VSA_free(&sas);
diff --git a/bin/varnishtest/vtc_http.c b/bin/varnishtest/vtc_http.c
index 5ad7d9723..0f57aada6 100644
--- a/bin/varnishtest/vtc_http.c
+++ b/bin/varnishtest/vtc_http.c
@@ -128,7 +128,14 @@ extern const struct cmds http_cmds[];
  *
  * \-proxy2 STRING (client only)
  *        Use the PROXY protocol version 2 for this connection. STRING
- *        is of the form "CLIENTIP:PORT SERVERIP:PORT".
+ *        is of the form "CLIENTIP:PORT SERVERIP:PORT [TLV [TLV ... ]]".
+ *
+ *        TLV is in the form name=val
+ *
+ *        name: 0xID or alpn, authority, crc32c, noop, unique_id, netns
+ *        val: 0x... or string
+ *
+ *        ssl is currently not implemented (can be sent as hex)
  *
  * SECTION: client-server.spec Specification
  *
diff --git a/bin/varnishtest/vtc_proxy.c b/bin/varnishtest/vtc_proxy.c
index ab7167ee8..32983df8c 100644
--- a/bin/varnishtest/vtc_proxy.c
+++ b/bin/varnishtest/vtc_proxy.c
@@ -30,6 +30,8 @@
 
 #include "config.h"
 
+#include <stdlib.h>
+#include <string.h>
 #include <sys/socket.h>
 
 #include <netinet/in.h>
@@ -48,6 +50,101 @@ static const char vpx2_sig[] = {
 	'Q', 'U', 'I', 'T', '\n',
 };
 
+#define PP2_TYPE_ALPN           0x01
+#define PP2_TYPE_AUTHORITY      0x02
+#define PP2_TYPE_CRC32C         0x03
+#define PP2_TYPE_NOOP           0x04
+#define PP2_TYPE_UNIQUE_ID      0x05
+#define PP2_TYPE_SSL            0x20
+#define PP2_SUBTYPE_SSL_VERSION 0x21
+#define PP2_SUBTYPE_SSL_CN      0x22
+#define PP2_SUBTYPE_SSL_CIPHER  0x23
+#define PP2_SUBTYPE_SSL_SIG_ALG 0x24
+#define PP2_SUBTYPE_SSL_KEY_ALG 0x25
+#define PP2_SUBTYPE_SSL_MAX     0x25
+#define PP2_TYPE_NETNS          0x30
+
+struct pp2_type {
+	const char * name;
+	uint8_t type;
+};
+
+/* sorted ! */
+static const struct pp2_type pp2_types[] = {
+	{"alpn",	PP2_TYPE_ALPN},
+	{"authority",	PP2_TYPE_AUTHORITY},
+	{"crc32c",	PP2_TYPE_CRC32C},
+	{"netns",	PP2_TYPE_NETNS},
+	{"noop",	PP2_TYPE_NOOP},
+	{"unique_id",	PP2_TYPE_UNIQUE_ID}
+};
+
+static int
+pp2cmp(const void *va, const void *vb)
+{
+	const struct pp2_type *a = va;
+	const struct pp2_type *b = vb;
+	return (strcmp(a->name, b->name));
+}
+
+void
+vtc_proxy_tlv(struct vtclog *vl, struct vsb *vsb, const char *kva)
+{
+	struct pp2_type *pp2, needle;
+	char *save = NULL, *kv;
+	struct vsb *vsb2;
+	const char *p;
+	uint16_t le;
+	ssize_t sz;
+
+	kv = strdup(kva);
+	AN(kv);
+	save = NULL;
+
+	p = strtok_r(kv, "=", &save);
+	AN(p);
+	if (p[0] == '0' && p[1] == 'x') {
+		p += 2;
+		vsb2 = vtc_hex_to_bin(vl, p);
+		AN(vsb2);
+		if (VSB_len(vsb2) != 1)
+			vtc_fatal(vl, "tlv hex type has wrong length");
+		VSB_bcat(vsb, VSB_data(vsb2), 1);
+		VSB_destroy(&vsb2);
+	}
+	else {
+		needle = (typeof(needle)){p, 0};
+		pp2 = bsearch(&needle, pp2_types, sizeof pp2_types / sizeof pp2_types[0],
+		    sizeof pp2_types[0], pp2cmp);
+		if (pp2 == NULL)
+			vtc_fatal(vl, "tlv type %s not found", p);
+		VSB_putc(vsb, pp2->type);
+	}
+
+	p = strtok_r(NULL, "", &save);
+	if (p == NULL)
+		vtc_fatal(vl, "tlv value missing");
+	if (p[0] == '0' && p[1] == 'x')
+		vsb2 = vtc_hex_to_bin(vl, p + 2);
+	else {
+		vsb2 = VSB_new_auto();
+		AN(vsb2);
+		VSB_cat(vsb2, p);
+		VSB_finish(vsb2);
+	}
+	AN(vsb2);
+
+	sz = VSB_len(vsb2);
+	assert(sz >= 0);
+	assert(sz <= UINT16_MAX);
+
+	vbe16enc(&le, (uint16_t)sz);
+	assert(sizeof(le) == 2);
+	VSB_bcat(vsb, &le, 2);
+	VSB_bcat(vsb, VSB_data(vsb2), sz);
+	VSB_destroy(&vsb2);
+}
+
 static void
 vpx_enc_addr(struct vsb *vsb, int proto, const struct suckaddr *s)
 {
@@ -79,13 +176,14 @@ vpx_enc_port(struct vsb *vsb, const struct suckaddr *s)
 
 int
 vtc_send_proxy(int fd, int version, const struct suckaddr *sac,
-    const struct suckaddr *sas)
+    const struct suckaddr *sas, struct vsb *tlv)
 {
 	struct vsb *vsb;
 	char hc[VTCP_ADDRBUFSIZE];
 	char pc[VTCP_PORTBUFSIZE];
 	char hs[VTCP_ADDRBUFSIZE];
 	char ps[VTCP_PORTBUFSIZE];
+	uint16_t le, l;
 	int i;
 	int proto;
 
@@ -99,6 +197,11 @@ vtc_send_proxy(int fd, int version, const struct suckaddr *sac,
 	proto = VSA_Get_Proto(sas);
 	assert(proto == PF_INET6 || proto == PF_INET);
 
+	if (tlv == NULL)
+		l = 0;
+	else
+		l = VSB_len(tlv);
+
 	if (version == 1) {
 		VSB_bcat(vsb, vpx1_sig, sizeof(vpx1_sig));
 		if (proto == PF_INET6)
@@ -113,13 +216,16 @@ vtc_send_proxy(int fd, int version, const struct suckaddr *sac,
 		VSB_putc(vsb, 0x21);
 		if (proto == PF_INET6) {
 			VSB_putc(vsb, 0x21);
-			VSB_putc(vsb, 0x00);
-			VSB_putc(vsb, 0x24);
+			l += 0x24;
 		} else if (proto == PF_INET) {
 			VSB_putc(vsb, 0x11);
-			VSB_putc(vsb, 0x00);
-			VSB_putc(vsb, 0x0c);
-		}
+			l += 0x0c;
+		} else
+			WRONG("proto");
+
+		vbe16enc(&le, l);
+		assert(sizeof(le) == 2);
+		VSB_bcat(vsb, &le, 2);
 		vpx_enc_addr(vsb, proto, sac);
 		vpx_enc_addr(vsb, proto, sas);
 		vpx_enc_port(vsb, sac);
@@ -130,5 +236,12 @@ vtc_send_proxy(int fd, int version, const struct suckaddr *sac,
 	AZ(VSB_finish(vsb));
 	i = VSB_tofile(vsb, fd);
 	VSB_destroy(&vsb);
+	if (i != 0 && tlv != NULL)
+		VSB_destroy(&tlv);
+	if (i != 0 || tlv == NULL)
+		return (i);
+
+	i = VSB_tofile(tlv, fd);
+	VSB_destroy(&tlv);
 	return (i);
 }


More information about the varnish-commit mailing list