[master] dcce66a Implement the vtc server and client commands for Unix domain sockets.

Geoff Simmons geoff at uplex.de
Fri Feb 16 11:02:02 UTC 2018


commit dcce66a62c99cfe9697f196bd24272d8c32db10b
Author: Geoff Simmons <geoff at uplex.de>
Date:   Thu Feb 15 20:02:30 2018 +0100

    Implement the vtc server and client commands for Unix domain sockets.
    
    This adds the VUS interface to libvarnish.
    
    UDS code corresponding to VTCP_open() and VTCP_listen_on() is
    implemented in the vtc code, since it will only ever be used
    there.

diff --git a/bin/varnishtest/tests/a00002.vtc b/bin/varnishtest/tests/a00002.vtc
index 2aa6f64..2d8c755 100644
--- a/bin/varnishtest/tests/a00002.vtc
+++ b/bin/varnishtest/tests/a00002.vtc
@@ -21,3 +21,24 @@ client c1 -connect ${s1_sock} {
 client c1 -run
 
 server s1 -wait
+
+# The same tests with unix domain sockets
+server s2 -listen "${tmpdir}/s2.sock" {
+	rxreq
+	expect req.method == PUT
+	expect req.proto == HTTP/1.0
+	expect req.url == "/foo"
+	txresp -proto HTTP/1.2 -status 201 -reason Foo
+} -start
+
+client c2 -connect ${s2_sock} {
+	txreq -req PUT -proto HTTP/1.0 -url /foo
+	rxresp
+	expect resp.proto == HTTP/1.2
+	expect resp.status == 201
+	expect resp.reason == Foo
+}
+
+client c2 -run
+
+server s2 -wait
diff --git a/bin/varnishtest/tests/a00003.vtc b/bin/varnishtest/tests/a00003.vtc
index 8855dba..7962eef 100644
--- a/bin/varnishtest/tests/a00003.vtc
+++ b/bin/varnishtest/tests/a00003.vtc
@@ -43,3 +43,48 @@ client c2 -wait
 
 server s1 -wait
 server s2 -wait
+
+# The same tests with Unix domain sockets
+server s3 -listen "${tmpdir}/s3.sock" {
+	rxreq
+	expect req.method == PUT
+	expect req.proto == HTTP/1.0
+	expect req.url == "/foo"
+	txresp -proto HTTP/1.2 -status 201 -reason Foo
+}
+
+server s4 -listen "${tmpdir}/s4.sock" {
+	rxreq
+	expect req.method == GET
+	expect req.proto == HTTP/1.1
+	expect req.url == "/"
+	txresp
+}
+
+server s3 -start
+server s4 -start
+
+client c3 -connect ${s3_sock} {
+	txreq -req PUT -proto HTTP/1.0 -url /foo
+	rxresp
+	expect resp.proto == HTTP/1.2
+	expect resp.status == 201
+	expect resp.reason == Foo
+}
+
+client c4 -connect ${s4_sock} {
+	txreq
+	rxresp
+	expect resp.proto == HTTP/1.1
+	expect resp.status == 200
+	expect resp.reason == OK
+}
+
+client c3 -start
+client c4 -start
+
+client c3 -wait
+client c4 -wait
+
+server s3 -wait
+server s4 -wait
diff --git a/bin/varnishtest/tests/a00004.vtc b/bin/varnishtest/tests/a00004.vtc
index be185a6..05474f6 100644
--- a/bin/varnishtest/tests/a00004.vtc
+++ b/bin/varnishtest/tests/a00004.vtc
@@ -33,3 +33,38 @@ client c1 -wait
 client c2 -wait
 
 server s1 -wait
+
+# The same tests with Unix domain sockets
+server s2 -repeat 2 -listen "${tmpdir}/s2.sock" {
+	rxreq
+	expect req.method == PUT
+	expect req.proto == HTTP/1.0
+	expect req.url == "/foo"
+	txresp -proto HTTP/1.2 -status 201 -reason Foo
+}
+
+server s2 -start
+
+client c3 -connect ${s2_sock} {
+	txreq -req PUT -proto HTTP/1.0 -url /foo
+	rxresp
+	expect resp.proto == HTTP/1.2
+	expect resp.status == 201
+	expect resp.reason == Foo
+}
+
+client c4 -connect ${s2_sock} {
+	txreq -req PUT -proto HTTP/1.0 -url /foo
+	rxresp
+	expect resp.proto == HTTP/1.2
+	expect resp.status == 201
+	expect resp.reason == Foo
+}
+
+client c3 -start
+client c4 -start
+
+client c3 -wait
+client c4 -wait
+
+server s2 -wait
diff --git a/bin/varnishtest/tests/a00005.vtc b/bin/varnishtest/tests/a00005.vtc
index 7de7675..fe4885f 100644
--- a/bin/varnishtest/tests/a00005.vtc
+++ b/bin/varnishtest/tests/a00005.vtc
@@ -41,3 +41,46 @@ client c1 -run
 
 server s1 -wait
 server s2 -wait
+
+# The same tests with unix domain sockets
+server s3 -listen "${tmpdir}/s3.sock" {
+	rxreq
+	expect req.method == PUT
+	expect req.proto == HTTP/1.0
+	expect req.url == "/foo"
+	txresp -proto HTTP/1.2 -status 201 -reason Foo
+}
+
+server s4 -listen "${tmpdir}/s4.sock" {
+	rxreq
+	expect req.method == GET
+	expect req.proto == HTTP/1.1
+	expect req.url == "/"
+	txresp
+}
+
+server s3 -start
+server s4 -start
+
+client c2 -connect ${s3_sock} {
+	txreq -req PUT -proto HTTP/1.0 -url /foo
+	rxresp
+	expect resp.proto == HTTP/1.2
+	expect resp.status == 201
+	expect resp.reason == Foo
+}
+
+client c2 -run
+
+client c2 -connect ${s4_sock} {
+	txreq
+	rxresp
+	expect resp.proto == HTTP/1.1
+	expect resp.status == 200
+	expect resp.reason == OK
+}
+
+client c2 -run
+
+server s3 -wait
+server s4 -wait
diff --git a/bin/varnishtest/tests/a00006.vtc b/bin/varnishtest/tests/a00006.vtc
index c01522d..2ca486b 100644
--- a/bin/varnishtest/tests/a00006.vtc
+++ b/bin/varnishtest/tests/a00006.vtc
@@ -23,3 +23,28 @@ client c1 -connect ${s1_sock} {
 client c1 -run
 
 server s1 -wait
+
+# The same tests with Unix domain sockets
+server s2 -listen "${tmpdir}/s2.sock" {
+	rxreq
+	expect req.method == PUT
+	expect req.proto == HTTP/1.0
+	expect req.url == "/foo"
+	txresp -proto HTTP/1.2 -status 201 -reason Foo \
+		-body "987654321\n"
+}
+
+server s2 -start
+
+client c2 -connect ${s2_sock} {
+	txreq -req PUT -proto HTTP/1.0 -url /foo \
+		-body "123456789\n"
+	rxresp
+	expect resp.proto == HTTP/1.2
+	expect resp.status == 201
+	expect resp.reason == Foo
+}
+
+client c2 -run
+
+server s2 -wait
diff --git a/bin/varnishtest/vtc.h b/bin/varnishtest/vtc.h
index 6e99403..b404552 100644
--- a/bin/varnishtest/vtc.h
+++ b/bin/varnishtest/vtc.h
@@ -93,7 +93,8 @@ extern int feature_dns;
 
 void init_server(void);
 
-int http_process(struct vtclog *vl, const char *spec, int sock, int *sfd);
+int http_process(struct vtclog *vl, const char *spec, int sock, int *sfd,
+		 const char *addr);
 
 char * synth_body(const char *len, int rnd);
 
diff --git a/bin/varnishtest/vtc_client.c b/bin/varnishtest/vtc_client.c
index 167d80c..754d4ec 100644
--- a/bin/varnishtest/vtc_client.c
+++ b/bin/varnishtest/vtc_client.c
@@ -29,17 +29,21 @@
 #include "config.h"
 
 #include <sys/socket.h>
+#include <sys/un.h>
 
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <poll.h>
+#include <unistd.h>
 
 #include "vtc.h"
 
 #include "vsa.h"
 #include "vss.h"
 #include "vtcp.h"
+#include "vus.h"
 
 struct client {
 	unsigned		magic;
@@ -106,6 +110,83 @@ client_proxy(struct vtclog *vl, int fd, int version, const char *spec)
 }
 
 /**********************************************************************
+ * Socket connect.
+ */
+
+static int
+client_tcp_connect(struct vtclog *vl, const char *addr, double tmo,
+		   const char **errp)
+{
+	int fd;
+	char mabuf[32], mpbuf[32];
+
+	fd = VTCP_open(addr, NULL, tmo, errp);
+	if (fd < 0)
+		return fd;
+	VTCP_myname(fd, mabuf, sizeof mabuf, mpbuf, sizeof mpbuf);
+	vtc_log(vl, 3, "connected fd %d from %s %s to %s", fd, mabuf, mpbuf,
+		addr);
+	return fd;
+}
+
+/* cf. VTCP_Open() */
+static int v_matchproto_(vus_resolved_f)
+uds_open(void *priv, const struct sockaddr_un *uds)
+{
+	double *p, tmo;
+	int s, i;
+	struct pollfd fds[1];
+	socklen_t sl = sizeof(*uds);
+
+	AN(priv);
+	AN(uds);
+	p = priv;
+	assert(*p > 0.);
+	tmo = *p * 1e3;
+
+	s = socket(uds->sun_family, SOCK_STREAM, 0);
+	if (s < 0)
+		return (s);
+
+	(void) VTCP_nonblocking(s);
+	i = connect(s, uds, sl);
+	if (i == 0)
+		return(s);
+	if (errno != EINPROGRESS) {
+		closefd(&s);
+		return (-1);
+	}
+
+	fds[0].fd = s;
+	fds[0].events = POLLWRNORM;
+	fds[0].revents = 0;
+	i = poll(fds, 1, tmo);
+
+	if (i == 0) {
+		closefd(&s);
+		errno = ETIMEDOUT;
+		return (-1);
+	}
+
+	return (VTCP_connected(s));
+}
+
+static int
+client_uds_connect(struct vtclog *vl, const char *path, double tmo,
+		   const char **errp)
+{
+	int fd;
+
+	assert(tmo >= 0);
+
+	fd = VUS_resolver(path, uds_open, &tmo, errp);
+	if (fd < 0)
+		return fd;
+	vtc_log(vl, 3, "connected fd %d to %s", fd, path);
+	return fd;
+}
+
+/**********************************************************************
  * Client thread
  */
 
@@ -117,7 +198,6 @@ client_thread(void *priv)
 	int fd;
 	unsigned u;
 	struct vsb *vsb;
-	char mabuf[32], mpbuf[32];
 	const char *err;
 
 	CAST_OBJ_NOTNULL(c, priv, CLIENT_MAGIC);
@@ -133,20 +213,21 @@ client_thread(void *priv)
 	if (c->repeat != 1)
 		vtc_log(vl, 2, "Started (%u iterations)", c->repeat);
 	for (u = 0; u < c->repeat; u++) {
-		vtc_log(vl, 3, "Connect to %s", VSB_data(vsb));
-		fd = VTCP_open(VSB_data(vsb), NULL, 10., &err);
+		char *addr = VSB_data(vsb);
+
+		vtc_log(vl, 3, "Connect to %s", addr);
+		if (*addr == '/')
+			fd = client_uds_connect(vl, addr, 10., &err);
+		else
+			fd = client_tcp_connect(vl, VSB_data(vsb), 10., &err);
 		if (fd < 0)
 			vtc_fatal(c->vl, "Failed to open %s: %s",
 			    VSB_data(vsb), err);
-		assert(fd >= 0);
 		/* VTCP_blocking does its own checks, trust it */
 		(void)VTCP_blocking(fd);
-		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);
+		fd = http_process(vl, c->spec, fd, NULL, addr);
 		vtc_log(vl, 3, "closing fd %d", fd);
 		VTCP_close(&fd);
 	}
diff --git a/bin/varnishtest/vtc_http.c b/bin/varnishtest/vtc_http.c
index c65139b..62df449 100644
--- a/bin/varnishtest/vtc_http.c
+++ b/bin/varnishtest/vtc_http.c
@@ -1840,7 +1840,8 @@ const struct cmds http_cmds[] = {
 };
 
 int
-http_process(struct vtclog *vl, const char *spec, int sock, int *sfd)
+http_process(struct vtclog *vl, const char *spec, int sock, int *sfd,
+	     const char *addr)
 {
 	struct http *hp;
 	int retval;
@@ -1870,8 +1871,13 @@ http_process(struct vtclog *vl, const char *spec, int sock, int *sfd)
 	hp->gziplevel = 0;
 	hp->gzipresidual = -1;
 
-	VTCP_hisname(sock,
-	    hp->rem_ip, VTCP_ADDRBUFSIZE, hp->rem_port, VTCP_PORTBUFSIZE);
+	if (*addr != '/')
+		VTCP_hisname(sock, hp->rem_ip, VTCP_ADDRBUFSIZE, hp->rem_port,
+			     VTCP_PORTBUFSIZE);
+	else {
+		strcpy(hp->rem_ip, "0.0.0.0");
+		strcpy(hp->rem_port, "0");
+	}
 	parse_string(spec, http_cmds, hp, vl);
 	if (hp->h2)
 		stop_h2(hp);
diff --git a/bin/varnishtest/vtc_server.c b/bin/varnishtest/vtc_server.c
index fb811df..a0e531a 100644
--- a/bin/varnishtest/vtc_server.c
+++ b/bin/varnishtest/vtc_server.c
@@ -29,15 +29,19 @@
 #include "config.h"
 
 #include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 
 #include "vtc.h"
 
 #include "vtcp.h"
+#include "vus.h"
 
 struct server {
 	unsigned		magic;
@@ -114,6 +118,81 @@ server_delete(struct server *s)
  * Server listen
  */
 
+struct helper {
+	int		depth;
+	const char	**errp;
+};
+
+/* cf. VTCP_listen_on() */
+static int v_matchproto_(vus_resolved_f)
+uds_listen(void *priv, const struct sockaddr_un *uds)
+{
+	int sock, e;
+	struct helper *hp = priv;
+
+	sock = VUS_bind(uds, hp->errp);
+	if (sock >= 0)   {
+		if (listen(sock, hp->depth) != 0) {
+			e = errno;
+			closefd(&sock);
+			errno = e;
+			if (hp->errp != NULL)
+				*hp->errp = "listen(2)";
+			return (-1);
+		}
+	}
+	if (sock > 0) {
+		*hp->errp = NULL;
+		return (sock);
+	}
+	AN(*hp->errp);
+	return (0);
+}
+
+static void
+server_listen_uds(struct server *s, const char **errp)
+{
+	mode_t m;
+	struct helper h;
+
+	h.depth = s->depth;
+	h.errp = errp;
+
+	errno = 0;
+	if (unlink(s->listen) != 0 && errno != ENOENT)
+		vtc_fatal(s->vl, "Could not unlink %s before bind: %s",
+			  s->listen, strerror(errno));
+	/*
+	 * Temporarily set the umask to 0 to avoid issues with
+	 * permissions.
+	 */
+	m = umask(0);
+	s->sock = VUS_resolver(s->listen, uds_listen, &h, errp);
+	umask(m);
+	if (*errp != NULL)
+		return;
+	assert(s->sock > 0);
+	macro_def(s->vl, s->name, "addr", "0.0.0.0");
+	macro_def(s->vl, s->name, "port", "0");
+	macro_def(s->vl, s->name, "sock", "%s", s->listen);
+}
+
+static void
+server_listen_tcp(struct server *s, const char **errp)
+{
+	s->sock = VTCP_listen_on(s->listen, "0", s->depth, errp);
+	if (*errp != NULL)
+		return;
+	assert(s->sock > 0);
+	VTCP_myname(s->sock, s->aaddr, sizeof s->aaddr,
+	    s->aport, sizeof s->aport);
+	macro_def(s->vl, s->name, "addr", "%s", s->aaddr);
+	macro_def(s->vl, s->name, "port", "%s", s->aport);
+	macro_def(s->vl, s->name, "sock", "%s %s", s->aaddr, s->aport);
+	/* Record the actual port, and reuse it on subsequent starts */
+	bprintf(s->listen, "%s %s", s->aaddr, s->aport);
+}
+
 static void
 server_listen(struct server *s)
 {
@@ -123,19 +202,14 @@ server_listen(struct server *s)
 
 	if (s->sock >= 0)
 		VTCP_close(&s->sock);
-	s->sock = VTCP_listen_on(s->listen, "0", s->depth, &err);
+	if (*s->listen != '/')
+		server_listen_tcp(s, &err);
+	else
+		server_listen_uds(s, &err);
 	if (err != NULL)
 		vtc_fatal(s->vl,
 		    "Server listen address (%s) cannot be resolved: %s",
 		    s->listen, err);
-	assert(s->sock > 0);
-	VTCP_myname(s->sock, s->aaddr, sizeof s->aaddr,
-	    s->aport, sizeof s->aport);
-	macro_def(s->vl, s->name, "addr", "%s", s->aaddr);
-	macro_def(s->vl, s->name, "port", "%s", s->aport);
-	macro_def(s->vl, s->name, "sock", "%s %s", s->aaddr, s->aport);
-	/* Record the actual port, and reuse it on subsequent starts */
-	bprintf(s->listen, "%s %s", s->aaddr, s->aport);
 }
 
 /**********************************************************************
@@ -170,7 +244,7 @@ server_thread(void *priv)
 			vtc_fatal(vl, "Accept failed: %s", strerror(errno));
 		VTCP_hisname(fd, abuf, sizeof abuf, pbuf, sizeof pbuf);
 		vtc_log(vl, 3, "accepted fd %d %s %s", fd, abuf, pbuf);
-		fd = http_process(vl, s->spec, fd, &s->sock);
+		fd = http_process(vl, s->spec, fd, &s->sock, s->listen);
 		vtc_log(vl, 3, "shutting fd %d", fd);
 		j = shutdown(fd, SHUT_WR);
 		if (!VTCP_Check(j))
@@ -215,7 +289,7 @@ server_dispatch_wrk(void *priv)
 	fd = s->fd;
 
 	vtc_log(vl, 3, "start with fd %d", fd);
-	fd = http_process(vl, s->spec, fd, &s->sock);
+	fd = http_process(vl, s->spec, fd, &s->sock, s->listen);
 	vtc_log(vl, 3, "shutting fd %d", fd);
 	j = shutdown(fd, SHUT_WR);
 	if (!VTCP_Check(j))
diff --git a/include/Makefile.am b/include/Makefile.am
index b98f8d0..afa8864 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -96,7 +96,8 @@ nobase_noinst_HEADERS = \
 	vsub.h \
 	vss.h \
 	vtcp.h \
-	vtree.h
+	vtree.h \
+	vus.h
 
 ## keep in sync with lib/libvcc/Makefile.am
 vmod_abi.h: \
diff --git a/include/vus.h b/include/vus.h
new file mode 100644
index 0000000..3747d92
--- /dev/null
+++ b/include/vus.h
@@ -0,0 +1,35 @@
+/*-
+ * Copyright (c) 2018 UPLEX - Nils Goroll Systemoptimierung
+ * All rights reserved.
+ *
+ * Author: Geoffrey Simmons <geoffrey.simmons at uplex.de>
+ *
+ * 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_un;
+
+typedef int vus_resolved_f(void *priv, const struct sockaddr_un *);
+int VUS_resolver(const char *path, vus_resolved_f *func, void *priv,
+		 const char **err);
+int VUS_bind(const struct sockaddr_un *uds, const char **errp);
diff --git a/lib/libvarnish/Makefile.am b/lib/libvarnish/Makefile.am
index 1616f0e..231827f 100644
--- a/lib/libvarnish/Makefile.am
+++ b/lib/libvarnish/Makefile.am
@@ -37,7 +37,8 @@ libvarnish_a_SOURCES = \
 	vss.c \
 	vsub.c \
 	vtcp.c \
-	vtim.c
+	vtim.c \
+	vus.c
 
 TESTS = vnum_c_test binheap
 
diff --git a/lib/libvarnish/vus.c b/lib/libvarnish/vus.c
new file mode 100644
index 0000000..ce0f0fd
--- /dev/null
+++ b/lib/libvarnish/vus.c
@@ -0,0 +1,96 @@
+/*-
+ * Copyright (c) 2018 UPLEX - Nils Goroll Systemoptimierung
+ * All rights reserved.
+ *
+ * Author: Geoffrey Simmons <geoffrey.simmons at uplex.de>
+ *
+ * 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/socket.h>
+#include <sys/un.h>
+
+#include <unistd.h>
+#include <errno.h>
+
+#include "vdef.h"
+#include "vas.h"
+#include "vus.h"
+
+int
+VUS_resolver(const char *path, vus_resolved_f *func, void *priv,
+	     const char **err)
+{
+	struct sockaddr_un uds;
+	int ret = 0;
+
+	AN(path);
+	assert(*path == '/');
+
+	AN(err);
+	*err = NULL;
+	if (strlen(path) + 1 > sizeof(uds.sun_path)) {
+		*err = "Path too long for a Unix domain socket";
+		return(-1);
+	}
+	strcpy(uds.sun_path, path);
+	uds.sun_family = PF_UNIX;
+	if (func != NULL)
+		ret = func(priv, &uds);
+	return(ret);
+}
+
+int
+VUS_bind(const struct sockaddr_un *uds, const char **errp)
+{
+	int sd, e;
+	socklen_t sl = sizeof(*uds);
+
+	if (errp != NULL)
+		*errp = NULL;
+
+	sd = socket(PF_UNIX, SOCK_STREAM, 0);
+	if (sd < 0) {
+		if (errp != NULL)
+			*errp = "socket(2)";
+		return (-1);
+	}
+
+	if (unlink(uds->sun_path) != 0 && errno != ENOENT) {
+		if (errp != NULL)
+			*errp = "unlink(2)";
+		e = errno;
+		closefd(&sd);
+		errno = e;
+		return (-1);
+	}
+
+	if (bind(sd, (const struct sockaddr *)uds, sl) != 0) {
+		if (errp != NULL)
+			*errp = "bind(2)";
+		e = errno;
+		closefd(&sd);
+		errno = e;
+		return (-1);
+	}
+	return (sd);
+}


More information about the varnish-commit mailing list