[master] f66b84e Add a new VTLA: VSA.

Poul-Henning Kamp phk at varnish-cache.org
Mon Aug 5 11:13:01 CEST 2013


commit f66b84e3374778aef8db4bcb579e0c27f6efea31
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Mon Aug 5 09:10:45 2013 +0000

    Add a new VTLA:  VSA.
    
    This does absolutely not stand for "suckaddr", and but it tries to
    sanitize the sockaddr_* mess enough that we can simply pass around
    struct sockaddr_storage without also tracking its length.
    
    The cost is that we do know something about address families (IPv4, IPv6),
    which strictly speaking should not be necessary, had the sockaddr
    not been messed up by the IPv6 people.

diff --git a/bin/varnishadm/Makefile.am b/bin/varnishadm/Makefile.am
index 22825cd..8fb28d7 100644
--- a/bin/varnishadm/Makefile.am
+++ b/bin/varnishadm/Makefile.am
@@ -9,6 +9,7 @@ dist_man_MANS = varnishadm.1
 varnishadm_SOURCES = \
 	varnishadm.c \
 	$(top_builddir)/lib/libvarnish/vas.c \
+	$(top_builddir)/lib/libvarnish/vsa.c \
 	$(top_builddir)/lib/libvarnish/vtcp.c \
 	$(top_builddir)/lib/libvarnish/vss.c
 
diff --git a/bin/varnishd/cache/cache_backend.c b/bin/varnishd/cache/cache_backend.c
index f3ae536..e802446 100644
--- a/bin/varnishd/cache/cache_backend.c
+++ b/bin/varnishd/cache/cache_backend.c
@@ -109,8 +109,7 @@ VBE_ReleaseConn(struct vbc *vc)
 
 static int
 vbe_TryConnect(const struct busyobj *bo, int pf,
-    const struct sockaddr_storage *sa, socklen_t salen,
-    const struct vdi_simple *vs)
+    const struct sockaddr_storage *sa, const struct vdi_simple *vs)
 {
 	int s, i, tmo;
 	double tmod;
@@ -126,7 +125,7 @@ vbe_TryConnect(const struct busyobj *bo, int pf,
 
 	tmo = (int)(tmod * 1000.0);
 
-	i = VTCP_connect(s, sa, salen, tmo);
+	i = VTCP_connect(s, sa, tmo);
 
 	if (i != 0) {
 		AZ(close(s));
@@ -160,19 +159,16 @@ bes_conn_try(struct busyobj *bo, struct vbc *vc, const struct vdi_simple *vs)
 	/* release lock during stuff that can take a long time */
 
 	if (cache_param->prefer_ipv6 && bp->ipv6 != NULL) {
-		s = vbe_TryConnect(bo, PF_INET6, bp->ipv6, bp->ipv6len, vs);
+		s = vbe_TryConnect(bo, PF_INET6, bp->ipv6, vs);
 		vc->addr = bp->ipv6;
-		vc->addrlen = bp->ipv6len;
 	}
 	if (s == -1 && bp->ipv4 != NULL) {
-		s = vbe_TryConnect(bo, PF_INET, bp->ipv4, bp->ipv4len, vs);
+		s = vbe_TryConnect(bo, PF_INET, bp->ipv4, vs);
 		vc->addr = bp->ipv4;
-		vc->addrlen = bp->ipv4len;
 	}
 	if (s == -1 && !cache_param->prefer_ipv6 && bp->ipv6 != NULL) {
-		s = vbe_TryConnect(bo, PF_INET6, bp->ipv6, bp->ipv6len, vs);
+		s = vbe_TryConnect(bo, PF_INET6, bp->ipv6, vs);
 		vc->addr = bp->ipv6;
-		vc->addrlen = bp->ipv6len;
 	}
 
 	vc->fd = s;
@@ -182,7 +178,6 @@ bes_conn_try(struct busyobj *bo, struct vbc *vc, const struct vdi_simple *vs)
 		bp->refcount--;		/* Only keep ref on success */
 		Lck_Unlock(&bp->mtx);
 		vc->addr = NULL;
-		vc->addrlen = 0;
 	} else {
 		VTCP_myname(s, abuf1, sizeof abuf1, pbuf1, sizeof pbuf1);
 		VSLb(bo->vsl, SLT_BackendOpen, "%d %s %s %s ",
diff --git a/bin/varnishd/cache/cache_backend.h b/bin/varnishd/cache/cache_backend.h
index 97f7898..8103af5 100644
--- a/bin/varnishd/cache/cache_backend.h
+++ b/bin/varnishd/cache/cache_backend.h
@@ -128,9 +128,7 @@ struct backend {
 	char			*port;
 
 	struct sockaddr_storage	*ipv4;
-	socklen_t		ipv4len;
 	struct sockaddr_storage	*ipv6;
-	socklen_t		ipv6len;
 
 	unsigned		n_conn;
 	VTAILQ_HEAD(, vbc)	connlist;
@@ -158,7 +156,6 @@ struct vbc {
 	int			fd;
 
 	struct sockaddr_storage	*addr;
-	socklen_t		addrlen;
 
 	uint8_t			recycled;
 
diff --git a/bin/varnishd/cache/cache_backend_cfg.c b/bin/varnishd/cache/cache_backend_cfg.c
index 5b68bfb..b07252e 100644
--- a/bin/varnishd/cache/cache_backend_cfg.c
+++ b/bin/varnishd/cache/cache_backend_cfg.c
@@ -41,6 +41,7 @@
 #include "cache_backend.h"
 #include "vcli.h"
 #include "vcli_priv.h"
+#include "vsa.h"
 #include "vrt.h"
 
 /*
@@ -149,15 +150,14 @@ VBE_DropRefConn(struct backend *b)
  */
 
 static void
-copy_sockaddr(struct sockaddr_storage **sa, socklen_t *len,
-    const unsigned char *src)
+copy_sockaddr(struct sockaddr_storage **sa, const unsigned char *src)
 {
 
 	assert(*src > 0);
 	*sa = calloc(sizeof **sa, 1);
 	XXXAN(*sa);
 	memcpy(*sa, src + 1, *src);
-	*len = *src;
+	assert(VSA_Sane(*sa));
 }
 
 /*--------------------------------------------------------------------
@@ -182,13 +182,11 @@ VBE_AddBackend(struct cli *cli, const struct vrt_backend *vb)
 		CHECK_OBJ_NOTNULL(b, BACKEND_MAGIC);
 		if (strcmp(b->vcl_name, vb->vcl_name))
 			continue;
-		if (vb->ipv4_sockaddr != NULL && (
-		    b->ipv4len != vb->ipv4_sockaddr[0] ||
-		    memcmp(b->ipv4, vb->ipv4_sockaddr + 1, b->ipv4len)))
+		if (vb->ipv4_sockaddr != NULL &&
+		    VSA_Compare(b->ipv4, vb->ipv4_sockaddr + 1))
 			continue;
-		if (vb->ipv6_sockaddr != NULL && (
-		    b->ipv6len != vb->ipv6_sockaddr[0] ||
-		    memcmp(b->ipv6, vb->ipv6_sockaddr + 1, b->ipv6len)))
+		if (vb->ipv6_sockaddr != NULL &&
+		    VSA_Compare(b->ipv6, vb->ipv6_sockaddr + 1))
 			continue;
 		b->refcount++;
 		b->vsc->vcls++;
@@ -227,9 +225,9 @@ VBE_AddBackend(struct cli *cli, const struct vrt_backend *vb)
 	 * Copy over the sockaddrs
 	 */
 	if (vb->ipv4_sockaddr != NULL)
-		copy_sockaddr(&b->ipv4, &b->ipv4len, vb->ipv4_sockaddr);
+		copy_sockaddr(&b->ipv4, vb->ipv4_sockaddr);
 	if (vb->ipv6_sockaddr != NULL)
-		copy_sockaddr(&b->ipv6, &b->ipv6len, vb->ipv6_sockaddr);
+		copy_sockaddr(&b->ipv6, vb->ipv6_sockaddr);
 
 	assert(b->ipv4 != NULL || b->ipv6 != NULL);
 
diff --git a/bin/varnishd/cache/cache_backend_poll.c b/bin/varnishd/cache/cache_backend_poll.c
index cd9a215..f93fe2f 100644
--- a/bin/varnishd/cache/cache_backend_poll.c
+++ b/bin/varnishd/cache/cache_backend_poll.c
@@ -105,7 +105,7 @@ static struct lock			vbp_mtx;
  */
 
 static int
-vbp_connect(int pf, const struct sockaddr_storage *sa, socklen_t salen, int tmo)
+vbp_connect(int pf, const struct sockaddr_storage *sa, int tmo)
 {
 	int s, i;
 
@@ -113,7 +113,7 @@ vbp_connect(int pf, const struct sockaddr_storage *sa, socklen_t salen, int tmo)
 	if (s < 0)
 		return (s);
 
-	i = VTCP_connect(s, sa, salen, tmo);
+	i = VTCP_connect(s, sa, tmo);
 	if (i == 0)
 		return (s);
 	VTCP_close(&s);
@@ -139,21 +139,21 @@ vbp_poke(struct vbp_target *vt)
 
 	s = -1;
 	if (cache_param->prefer_ipv6 && bp->ipv6 != NULL) {
-		s = vbp_connect(PF_INET6, bp->ipv6, bp->ipv6len, tmo);
+		s = vbp_connect(PF_INET6, bp->ipv6, tmo);
 		t_now = VTIM_real();
 		tmo = (int)round((t_end - t_now) * 1e3);
 		if (s >= 0)
 			vt->good_ipv6 |= 1;
 	}
 	if (tmo > 0 && s < 0 && bp->ipv4 != NULL) {
-		s = vbp_connect(PF_INET, bp->ipv4, bp->ipv4len, tmo);
+		s = vbp_connect(PF_INET, bp->ipv4, tmo);
 		t_now = VTIM_real();
 		tmo = (int)round((t_end - t_now) * 1e3);
 		if (s >= 0)
 			vt->good_ipv4 |= 1;
 	}
 	if (tmo > 0 && s < 0 && bp->ipv6 != NULL) {
-		s = vbp_connect(PF_INET6, bp->ipv6, bp->ipv6len, tmo);
+		s = vbp_connect(PF_INET6, bp->ipv6, tmo);
 		t_now = VTIM_real();
 		tmo = (int)round((t_end - t_now) * 1e3);
 		if (s >= 0)
diff --git a/bin/varnishd/cache/cache_vrt_var.c b/bin/varnishd/cache/cache_vrt_var.c
index 1429602..d3b212f 100644
--- a/bin/varnishd/cache/cache_vrt_var.c
+++ b/bin/varnishd/cache/cache_vrt_var.c
@@ -39,6 +39,7 @@
 #include "cache_backend.h"
 #include "vrt.h"
 #include "vrt_obj.h"
+#include "vsa.h"
 #include "vtcp.h"
 #include "vtim.h"
 
@@ -274,7 +275,7 @@ VRT_r_beresp_backend_port(const struct vrt_ctx *ctx)
 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
 	CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
 	CHECK_OBJ_NOTNULL(ctx->bo->vbc, VBC_MAGIC);
-	return (VTCP_port(ctx->bo->vbc->addr));
+	return (VSA_Port(ctx->bo->vbc->addr));
 }
 
 const char *
@@ -609,7 +610,7 @@ VRT_r_server_port(const struct vrt_ctx *ctx)
 		    &ctx->req->sp->mysockaddrlen);
 		assert(VTCP_Check(i));
 	}
-	return (VTCP_port(&ctx->req->sp->mysockaddr));
+	return (VSA_Port(&ctx->req->sp->mysockaddr));
 }
 
 /*--------------------------------------------------------------------*/
diff --git a/include/Makefile.am b/include/Makefile.am
index 92cc1bd..605a71e 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -80,6 +80,7 @@ nobase_pkgdatainclude_HEADERS = \
 	vdef.h \
 	vrt.h \
 	vrt_obj.h \
+	vsa.h \
 	vsb.h \
 	vsha256.h
 
diff --git a/include/vsa.h b/include/vsa.h
new file mode 100644
index 0000000..c9d521a
--- /dev/null
+++ b/include/vsa.h
@@ -0,0 +1,38 @@
+/*-
+ * Copyright (c) 2013 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.
+ *
+ */
+
+#ifndef VSA_H_INCLUDED
+#define VSA_H_INCLUDED
+
+int VSA_Sane(const struct sockaddr_storage *ss);
+socklen_t VSA_Len(const struct sockaddr_storage *ss);
+unsigned VSA_Port(const struct sockaddr_storage *ss);
+int VSA_Compare(const struct sockaddr_storage *ss1, const void *ss2);
+
+#endif
diff --git a/include/vtcp.h b/include/vtcp.h
index 1594a4d..205d9e1 100644
--- a/include/vtcp.h
+++ b/include/vtcp.h
@@ -65,11 +65,9 @@ int VTCP_linger(int sock, int linger);
 int VTCP_check_hup(int sock);
 
 #ifdef SOL_SOCKET
-int VTCP_port(const struct sockaddr_storage *addr);
 void VTCP_name(const struct sockaddr_storage *addr, unsigned l, char *abuf,
     unsigned alen, char *pbuf, unsigned plen);
-int VTCP_connect(int s, const struct sockaddr_storage *name, socklen_t namelen,
-    int msec);
+int VTCP_connect(int s, const struct sockaddr_storage *name, int msec);
 void VTCP_close(int *s);
 void VTCP_set_read_timeout(int s, double seconds);
 #endif
diff --git a/lib/libvarnish/Makefile.am b/lib/libvarnish/Makefile.am
index 60f6a25..c471c9c 100644
--- a/lib/libvarnish/Makefile.am
+++ b/lib/libvarnish/Makefile.am
@@ -27,6 +27,7 @@ libvarnish_la_SOURCES = \
 	vmb.c \
 	vpf.c \
 	vre.c \
+	vsa.c \
 	vsb.c \
 	vsha256.c \
 	vss.c
diff --git a/lib/libvarnish/vsa.c b/lib/libvarnish/vsa.c
new file mode 100644
index 0000000..51f214a
--- /dev/null
+++ b/lib/libvarnish/vsa.c
@@ -0,0 +1,98 @@
+/*-
+ * Copyright (c) 2013 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.
+ *
+ * Struct sockaddr_* is not even close to a convenient API.
+ *
+ * These functions try to mitigate the madness, at the cost of actually
+ * knowing something about address families.
+ */
+
+#include "config.h"
+
+#include <errno.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include "vas.h"
+#include "vsa.h"
+
+int
+VSA_Sane(const struct sockaddr_storage *ss)
+{
+	switch(ss->ss_family) {
+		case PF_INET:
+		case PF_INET6:
+			return (1);
+		default:
+			return (0);
+	}
+}
+
+socklen_t
+VSA_Len(const struct sockaddr_storage *ss)
+{
+	switch(ss->ss_family) {
+		case PF_INET:
+			return (sizeof(struct sockaddr_in));
+		case PF_INET6:
+			return (sizeof(struct sockaddr_in6));
+		default:
+			WRONG("Illegal socket family");
+	}
+}
+
+int
+VSA_Compare(const struct sockaddr_storage *ss1, const void *ss2)
+{
+	switch(ss1->ss_family) {
+		case PF_INET:
+		case PF_INET6:
+			return (memcmp(ss1, ss2, VSA_Len(ss1)));
+		default:
+			return (-1);
+	}
+}
+
+unsigned
+VSA_Port(const struct sockaddr_storage *ss)
+{
+	switch(ss->ss_family) {
+		case PF_INET:
+			{
+			const struct sockaddr_in *ain = (const void *)ss;
+			return (ntohs((ain->sin_port)));
+			}
+		case PF_INET6:
+			{
+			const struct sockaddr_in6 *ain = (const void *)ss;
+			return (ntohs((ain->sin6_port)));
+			}
+		default:
+			WRONG("Illegal socket family");
+	}
+}
diff --git a/lib/libvarnish/vtcp.c b/lib/libvarnish/vtcp.c
index 7227fb3..6b9df11 100644
--- a/lib/libvarnish/vtcp.c
+++ b/lib/libvarnish/vtcp.c
@@ -51,28 +51,11 @@
 #include <unistd.h>
 
 #include "vas.h"
+#include "vsa.h"
 #include "vtcp.h"
 
 /*--------------------------------------------------------------------*/
 
-int
-VTCP_port(const struct sockaddr_storage *addr)
-{
-
-	if (addr->ss_family == AF_INET) {
-		const struct sockaddr_in *ain = (const void *)addr;
-		return (ntohs((ain->sin_port)));
-	}
-	if (addr->ss_family == AF_INET6) {
-		const struct sockaddr_in6 *ain = (const void *)addr;
-		return (ntohs((ain->sin6_port)));
-	}
-	return (-1);
-}
-
-
-/*--------------------------------------------------------------------*/
-
 void
 VTCP_name(const struct sockaddr_storage *addr, unsigned l,
     char *abuf, unsigned alen, char *pbuf, unsigned plen)
@@ -212,8 +195,7 @@ VTCP_nonblocking(int sock)
  */
 
 int
-VTCP_connect(int s, const struct sockaddr_storage *name, socklen_t namelen,
-    int msec)
+VTCP_connect(int s, const struct sockaddr_storage *name, int msec)
 {
 	int i, k;
 	socklen_t l;
@@ -226,7 +208,8 @@ VTCP_connect(int s, const struct sockaddr_storage *name, socklen_t namelen,
 		(void)VTCP_nonblocking(s);
 
 	/* Attempt the connect */
-	i = connect(s, (const void *)name, namelen);
+	assert(VSA_Sane(name));
+	i = connect(s, (const void *)name, VSA_Len(name));
 	if (i == 0 || errno != EINPROGRESS)
 		return (i);
 



More information about the varnish-commit mailing list