[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