[master] 66d14ff Add -proxy1 and -proxy2 support to varnishtest

Federico G. Schwindt fgsch at lodoss.net
Sun Jun 19 15:09:05 CEST 2016


commit 66d14ff3230122687f7277eb75ea5010cfc9082b
Author: Federico G. Schwindt <fgsch at lodoss.net>
Date:   Sun Jun 19 14:04:47 2016 +0100

    Add -proxy1 and -proxy2 support to varnishtest
    
    Fixes #1989.

diff --git a/bin/varnishtest/Makefile.am b/bin/varnishtest/Makefile.am
index 9d8c0b5..d6dbc10 100644
--- a/bin/varnishtest/Makefile.am
+++ b/bin/varnishtest/Makefile.am
@@ -23,19 +23,20 @@ AM_CPPFLAGS = \
 bin_PROGRAMS =	varnishtest
 
 varnishtest_SOURCES = \
+		programs.h \
+		vmods.h \
 		vtc.c \
 		vtc.h \
-		vmods.h \
-		programs.h \
 		vtc_barrier.c \
 		vtc_client.c \
 		vtc_http.c \
-		vtc_main.c \
 		vtc_log.c \
-		vtc_server.c \
-		vtc_varnish.c \
 		vtc_logexp.c \
-		vtc_process.c
+		vtc_main.c \
+		vtc_process.c \
+		vtc_proxy.c \
+		vtc_server.c \
+		vtc_varnish.c
 
 varnishtest_LDADD = \
 		$(top_builddir)/lib/libvarnish/libvarnish.la \
diff --git a/bin/varnishtest/tests/o00000.vtc b/bin/varnishtest/tests/o00000.vtc
index 1bf1e1d..5bd0a12 100644
--- a/bin/varnishtest/tests/o00000.vtc
+++ b/bin/varnishtest/tests/o00000.vtc
@@ -140,8 +140,7 @@ logexpect l1 -v v1 {
 } -start
 
 # Finally try something which works...
-client c1 {
-	send "PROXY TCP4 1.2.3.4 5.6.7.8 1234 5678\r\n"
+client c1 -proxy1 "1.2.3.4:1234 5.6.7.8:5678" {
 	txreq -url /1
 	rxresp
 	expect resp.http.url == "/1"
@@ -156,8 +155,7 @@ client c1 {
 } -run
 delay .1
 
-client c1 {
-	send "PROXY TCP6 1:f::2 5:a::8 1234 5678\r\n"
+client c1 -proxy1 "[1:f::2]:1234 [5:a::8]:5678" {
 	txreq -url /2
 	rxresp
 	expect resp.http.url == "/2"
@@ -175,14 +173,14 @@ delay .1
 logexpect l1 -wait
 
 # Try with appended request (See also: #1728)
-client c1 {
+client c2 {
 	send "PROXY TCP6 1:f::3 5:a::8 1234 5678\r\nGET /3 HTTP/1.1\r\nHdr1: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\r\n\r\n"
 	rxresp
 	expect resp.http.url == "/3"
 } -run
 
 # Malformed (missing \r)
-client c1 {
+client c2 {
 	send "PROXY TCP4 1.2.3.4 5.6.7.8 1234 5678\n"
 	expect_close
 } -run
@@ -190,7 +188,7 @@ delay .1
 
 # Malformed, too long (106)
 # NB: Should check VSL for proper disposal
-client c1 {
+client c2 {
 	send "PROXY TCP4 1.2.3.4 5.6.7.8 1234 5678                                                                     \r\n"
 	expect_close
 } -run
@@ -198,7 +196,7 @@ delay .1
 
 # Malformed, too long (107)
 # NB: Should check VSL for proper disposal
-client c1 {
+client c2 {
 	send "PROXY TCP4 1.2.3.4 5.6.7.8 1234 5678                                                                      \r\n"
 	expect_close
 } -run
@@ -206,7 +204,7 @@ delay .1
 
 # Malformed, too long (108)
 # NB: Should check VSL for proper disposal
-client c1 {
+client c2 {
 	send "PROXY TCP4 1.2.3.4 5.6.7.8 1234 5678                                                                       \r\n"
 	expect_close
 } -run
diff --git a/bin/varnishtest/tests/o00001.vtc b/bin/varnishtest/tests/o00001.vtc
index c906963..02ff279 100644
--- a/bin/varnishtest/tests/o00001.vtc
+++ b/bin/varnishtest/tests/o00001.vtc
@@ -120,14 +120,8 @@ client c1 {
 } -run
 delay .1
 
-client c1 {
-	# good IPv4
-	sendhex "0d 0a 0d 0a 00 0d 0a 51 55 49 54 0a"
-	sendhex "21 11 00 0c"
-	sendhex "01 02 03 04"
-	sendhex "05 06 07 08"
-	sendhex "09 0a"
-	sendhex "0b 0c"
+# good IPv4
+client c1 -proxy2 "1.2.3.4:2314 5.6.7.8:2828" {
 	txreq
 	rxresp
 	expect resp.status == 200
@@ -144,14 +138,9 @@ client c1 {
 } -run
 delay .1
 
-client c1 {
-	# good IPv6
-	sendhex "0d 0a 0d 0a 00 0d 0a 51 55 49 54 0a"
-	sendhex "21 21 00 24"
-	sendhex "01 02 03 04  05 06 00 00  00 00 00 00  0d 0e 0f 10"
-	sendhex "81 82 83 84  85 86 00 00  00 00 00 00  8d 8e 8f 80"
-	sendhex "09 0a"
-	sendhex "0b 0c"
+# good IPv6
+client c1 \
+    -proxy2 "[102:304:506::d0e:f10]:2314 [8182:8384:8586::8d8e:8f80]:2828" {
 	txreq
 	rxresp
 	expect resp.status == 200
diff --git a/bin/varnishtest/tests/o00002.vtc b/bin/varnishtest/tests/o00002.vtc
index 5c6fee0..13fba7d 100644
--- a/bin/varnishtest/tests/o00002.vtc
+++ b/bin/varnishtest/tests/o00002.vtc
@@ -70,32 +70,28 @@ varnish v2 -proto PROXY -vcl {
 	}
 } -start
 
-client c1 -connect ${v2_sock} {
-	send "PROXY TCP4 1.2.3.4 5.6.7.8 1111 5678\r\n"
+client c1 -connect ${v2_sock} -proxy1 "1.2.3.4:1111 5.6.7.8:5678" {
 	txreq -url /1
 	rxresp
 	expect resp.body == "proxy1"
 } -run
 delay .2
 
-client c1 -connect ${v2_sock} {
-	send "PROXY TCP4 1.2.3.4 5.6.7.8 2222 5678\r\n"
+client c1 -connect ${v2_sock} -proxy1 "1.2.3.4:2222 5.6.7.8:5678" {
 	txreq -url /2
 	rxresp
 	expect resp.body == "proxy2"
 } -run
 delay .2
 
-client c1 -connect ${v2_sock} {
-	send "PROXY TCP6 1:f::2 5:a::8 3333 5678\r\n"
+client c1 -connect ${v2_sock} -proxy1 "[1:f::2]:3333 [5:a::8]:5678" {
 	txreq -url /3
 	rxresp
 	expect resp.body == "proxy3"
 } -run
 delay .2
 
-client c1 -connect ${v2_sock} {
-	send "PROXY TCP6 1:f::2 5:a::8 4444 5678\r\n"
+client c1 -connect ${v2_sock} -proxy1 "[1:f::2]:4444 [5:a::8]:5678" {
 	txreq -url /4
 	rxresp
 	expect resp.body == "proxy4"
diff --git a/bin/varnishtest/tests/o00003.vtc b/bin/varnishtest/tests/o00003.vtc
index d821ce7..c883131 100644
--- a/bin/varnishtest/tests/o00003.vtc
+++ b/bin/varnishtest/tests/o00003.vtc
@@ -14,8 +14,7 @@ varnish v1 -proto PROXY -vcl+backend {
 	}
 } -start
 
-client c1 {
-	send "PROXY TCP4 1.2.3.4 5.6.7.8 1111 5678\r\n"
+client c1 -proxy1 "1.2.3.4:1111 5.6.7.8:5678" {
 	txreq
 	rxresp
 	expect resp.http.li == ${v1_addr}
diff --git a/bin/varnishtest/vtc.h b/bin/varnishtest/vtc.h
index 23095d4..b2b730a 100644
--- a/bin/varnishtest/vtc.h
+++ b/bin/varnishtest/vtc.h
@@ -43,6 +43,7 @@
 
 struct vtclog;
 struct cmds;
+struct suckaddr;
 
 #define CMD_ARGS \
     char * const *av, void *priv, const struct cmds *cmd, struct vtclog *vl
@@ -90,6 +91,9 @@ void vtc_dump(struct vtclog *vl, int lvl, const char *pfx,
 void vtc_hexdump(struct vtclog *vl, int lvl, const char *pfx,
     const unsigned char *str, int len);
 
+int vtc_send_proxy(int fd, int version, const struct suckaddr *sac,
+    const struct suckaddr *sas);
+
 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 74bc8e7..67c86d1 100644
--- a/bin/varnishtest/vtc_client.c
+++ b/bin/varnishtest/vtc_client.c
@@ -31,12 +31,14 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
 #include "vtc.h"
 
+#include "vsa.h"
 #include "vss.h"
 #include "vtcp.h"
 
@@ -51,6 +53,9 @@ struct client {
 
 	char			connect[256];
 
+	char			*proxy_spec;
+	int			proxy_version;
+
 	unsigned		repeat;
 
 	unsigned		running;
@@ -61,6 +66,47 @@ static VTAILQ_HEAD(, client)	clients =
     VTAILQ_HEAD_INITIALIZER(clients);
 
 /**********************************************************************
+ * Send the proxy header
+ */
+
+static int __match_proto__(vss_resolved_f)
+proxy_cb(void *priv, const struct suckaddr *sa)
+{
+	struct suckaddr **addr = priv;
+	*addr = VSA_Clone(sa);
+	return (1);
+}
+
+static void
+client_proxy(struct vtclog *vl, int fd, int version, char *spec)
+{
+	struct suckaddr *sac, *sas;
+	const char *err;
+	char *p, *p2;
+	int error;
+
+	p = strdup(spec);
+	AN(p);
+	p2 = strchr(p, ' ');
+	AN(p2);
+	*p2++ = '\0';
+
+	error = VSS_resolver(p, NULL, proxy_cb, &sac, &err);
+	if (err != NULL)
+		vtc_log(vl, 0, "Could not resolve client address: %s", err);
+	assert(error == 1);
+	error = VSS_resolver(p2, NULL, proxy_cb, &sas, &err);
+	if (err != NULL)
+		vtc_log(vl, 0, "Could not resolve server address: %s", err);
+	assert(error == 1);
+	if (vtc_send_proxy(fd, version, sac, sas))
+		vtc_log(vl, 0, "Write failed: %s", strerror(errno));
+	free(p);
+	free(sac);
+	free(sas);
+}
+
+/**********************************************************************
  * Client thread
  */
 
@@ -101,6 +147,8 @@ client_thread(void *priv)
 		VTCP_myname(fd, mabuf, sizeof mabuf, mpbuf, sizeof mpbuf);
 		vtc_log(vl, 3, "connected fd %d from %s %s to %s",
 		    fd, mabuf, mpbuf, VSB_data(vsb));
+		if (c->proxy_spec != NULL)
+			client_proxy(vl, fd, c->proxy_version, c->proxy_spec);
 		fd = http_process(vl, c->spec, fd, NULL);
 		vtc_log(vl, 3, "closing fd %d", fd);
 		VTCP_close(&fd);
@@ -146,6 +194,7 @@ client_delete(struct client *c)
 	vtc_logclose(c->vl);
 	free(c->spec);
 	free(c->name);
+	free(c->proxy_spec);
 	/* XXX: MEMLEAK (?)*/
 	FREE_OBJ(c);
 }
@@ -247,6 +296,18 @@ cmd_client(CMD_ARGS)
 			av++;
 			continue;
 		}
+		if (!strcmp(*av, "-proxy1")) {
+			REPLACE(c->proxy_spec, av[1]);
+			c->proxy_version = 1;
+			av++;
+			continue;
+		}
+		if (!strcmp(*av, "-proxy2")) {
+			REPLACE(c->proxy_spec, av[1]);
+			c->proxy_version = 2;
+			av++;
+			continue;
+		}
 		if (!strcmp(*av, "-repeat")) {
 			c->repeat = atoi(av[1]);
 			av++;
diff --git a/bin/varnishtest/vtc_http.c b/bin/varnishtest/vtc_http.c
index 184384c..753ac8a 100644
--- a/bin/varnishtest/vtc_http.c
+++ b/bin/varnishtest/vtc_http.c
@@ -101,15 +101,23 @@
  *        "IP PORT".
  *
  * \-connect STRING (client only)
- *         Indicate the server to connect to. STRING is also of the form
- *         "IP PORT".
+ *        Indicate the server to connect to. STRING is also of the form
+ *        "IP PORT".
  *
  * \-dispatch (server only, s0 only)
- *         Normally, to keep things simple, server threads only handle one
- *         connection at a time, but the -dispatch switch allows to accept
- *         any number of connection and handle them following the given spec.
+ *        Normally, to keep things simple, server threads only handle one
+ *        connection at a time, but the -dispatch switch allows to accept
+ *        any number of connection and handle them following the given spec.
+ *
+ *        However, -dispatch is only allowed for the server name "s0".
+ *
+ * \-proxy1 STRING (client only)
+ *        Use the PROXY protocol version 1 for this connection. STRING
+ *        is of the form "CLIENT:PORT SERVER:PORT".
  *
- *         However, -dispatch is only allowed for the server name "s0".
+ * \-proxy2 STRING (client only)
+ *        Use the PROXY protocol version 2 for this connection. STRING
+ *        is of the form "CLIENT:PORT SERVER:PORT".
  *
  * SECTION: client-server.spec Specification
  */
diff --git a/bin/varnishtest/vtc_proxy.c b/bin/varnishtest/vtc_proxy.c
new file mode 100644
index 0000000..e61658c
--- /dev/null
+++ b/bin/varnishtest/vtc_proxy.c
@@ -0,0 +1,132 @@
+/*-
+ * Copyright (c) 2015 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+
+#include <unistd.h>
+
+#include "vtc.h"
+
+#include "vend.h"
+#include "vsa.h"
+#include "vtcp.h"
+
+static const char vpx1_sig[] = {'P', 'R', 'O', 'X', 'Y'};
+static const char vpx2_sig[] = {
+	'\r', '\n', '\r', '\n', '\0', '\r', '\n',
+	'Q', 'U', 'I', 'T', '\n',
+};
+
+static void
+vpx_enc_addr(struct vsb *vsb, int proto, const struct suckaddr *s)
+{
+	const struct sockaddr_in *sin4;
+	const struct sockaddr_in6 *sin6;
+	socklen_t sl;
+
+	if (proto == PF_INET6) {
+		sin6 = VSA_Get_Sockaddr(s, &sl);	//lint !e826
+		AN(sin6);
+		assert(sl >= sizeof(*sin6));
+		VSB_bcat(vsb, &sin6->sin6_addr, sizeof(sin6->sin6_addr));
+	} else {
+		sin4 = VSA_Get_Sockaddr(s, &sl);	//lint !e826
+		AN(sin4);
+		assert(sl >= sizeof(*sin4));
+		VSB_bcat(vsb, &sin4->sin_addr, sizeof(sin4->sin_addr));
+	}
+}
+
+static void
+vpx_enc_port(struct vsb *vsb, const struct suckaddr *s)
+{
+	uint8_t b[2];
+
+	vbe16enc(b, (uint16_t)VSA_Port(s));
+	VSB_bcat(vsb, b, sizeof(b));
+}
+
+int
+vtc_send_proxy(int fd, int version, const struct suckaddr *sac,
+    const struct suckaddr *sas)
+{
+	struct vsb *vsb;
+	char hc[VTCP_ADDRBUFSIZE];
+	char pc[VTCP_PORTBUFSIZE];
+	char hs[VTCP_ADDRBUFSIZE];
+	char ps[VTCP_PORTBUFSIZE];
+	int i, len;
+	int proto;
+
+	AN(sac);
+	AN(sas);
+
+	assert(version == 1 || version == 2);
+	vsb = VSB_new_auto();
+	AN(vsb);
+
+	proto = VSA_Get_Proto(sas);
+	assert(proto == PF_INET6 || proto == PF_INET);
+
+	if (version == 1) {
+		VSB_bcat(vsb, vpx1_sig, sizeof(vpx1_sig));
+		if (proto == PF_INET6)
+			VSB_printf(vsb, " TCP6 ");
+		else if (proto == PF_INET)
+			VSB_printf(vsb, " TCP4 ");
+		VTCP_name(sac, hc, sizeof(hc), pc, sizeof(pc));
+		VTCP_name(sas, hs, sizeof(hs), ps, sizeof(ps));
+		VSB_printf(vsb, "%s %s %s %s\r\n", hc, hs, pc, ps);
+	} else if (version == 2) {
+		VSB_bcat(vsb, vpx2_sig, sizeof(vpx2_sig));
+		VSB_putc(vsb, 0x21);
+		if (proto == PF_INET6) {
+			VSB_putc(vsb, 0x21);
+			VSB_putc(vsb, 0x00);
+			VSB_putc(vsb, 0x24);
+		} else if (proto == PF_INET) {
+			VSB_putc(vsb, 0x11);
+			VSB_putc(vsb, 0x00);
+			VSB_putc(vsb, 0x0c);
+		}
+		vpx_enc_addr(vsb, proto, sac);
+		vpx_enc_addr(vsb, proto, sas);
+		vpx_enc_port(vsb, sac);
+		vpx_enc_port(vsb, sas);
+	} else
+		WRONG("Wrong proxy version");
+
+	AZ(VSB_finish(vsb));
+	len = VSB_len(vsb);
+	i = write(fd, VSB_data(vsb), len);
+	VSB_delete(vsb);
+	return (i != len);
+}



More information about the varnish-commit mailing list