vtest: Untie vtest from 127.0.0.1 and support IPv6 only setups

to support IPv6 only hosts, we try to resolve "localhost" if resolving
"127.0.0.1" fails.

Whatever address we determine is stored in the ${localhost}
macro. Because of the different address:port vs. [address]:port
formats for IPv4 vs. IPv6, we store "${localhost}:0" /
"[${localhost}]:0" in the ${listen_addr} macro.

Likewise we unify the *_sock macros to ${Xaddr}:${Xport} (the colon
used to be missing) for IPv4 and [${Xaddr}]:${Xport} for IPv6.

We also save ${listen_addr} in default_listen_addr for use from within
the vtest code whenever we want to bind to or listen on an emphemeral
port.

Ref #3490
parent 2aa9a8b0
...@@ -76,5 +76,5 @@ client c1 -connect ${v3_sock} { ...@@ -76,5 +76,5 @@ client c1 -connect ${v3_sock} {
expect resp.http.a0_sock == "${tmpdir}/v1.sock" expect resp.http.a0_sock == "${tmpdir}/v1.sock"
expect resp.http.a1_addr != "0.0.0.0" expect resp.http.a1_addr != "0.0.0.0"
expect resp.http.a1_port != "0" expect resp.http.a1_port != "0"
expect resp.http.a1_sock ~ "[^ ]+ [^ ]+" expect resp.http.a1_sock ~ "[^ ]+:[^ ]+"
} -run } -run
...@@ -81,6 +81,7 @@ extern char *vmod_path; ...@@ -81,6 +81,7 @@ extern char *vmod_path;
extern struct vsb *params_vsb; extern struct vsb *params_vsb;
extern int leave_temp; extern int leave_temp;
extern int ign_unknown_macro; extern int ign_unknown_macro;
extern const char *default_listen_addr;
void init_server(void); void init_server(void);
void init_syslog(void); void init_syslog(void);
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include "vtc.h" #include "vtc.h"
#include "vtcp.h" #include "vtcp.h"
#include "vsa.h"
enum barrier_e { enum barrier_e {
BARRIER_NONE = 0, BARRIER_NONE = 0,
...@@ -128,7 +129,10 @@ barrier_sock_thread(void *priv) ...@@ -128,7 +129,10 @@ barrier_sock_thread(void *priv)
struct barrier *b; struct barrier *b;
struct vtclog *vl; struct vtclog *vl;
const char *err; const char *err;
char abuf[16], pbuf[6]; char buf[vsa_suckaddr_len];
struct suckaddr *sua;
char abuf[VTCP_ADDRBUFSIZE], pbuf[VTCP_PORTBUFSIZE];
int i, sock, *conns; int i, sock, *conns;
struct pollfd pfd[1]; struct pollfd pfd[1];
...@@ -140,7 +144,7 @@ barrier_sock_thread(void *priv) ...@@ -140,7 +144,7 @@ barrier_sock_thread(void *priv)
vl = vtc_logopen("%s", b->name); vl = vtc_logopen("%s", b->name);
pthread_cleanup_push(vtc_logclose, vl); pthread_cleanup_push(vtc_logclose, vl);
sock = VTCP_listen_on("127.0.0.1:0", NULL, b->expected, &err); sock = VTCP_listen_on(default_listen_addr, NULL, b->expected, &err);
if (sock < 0) { if (sock < 0) {
AZ(pthread_cond_signal(&b->cond)); AZ(pthread_cond_signal(&b->cond));
AZ(pthread_mutex_unlock(&b->mtx)); AZ(pthread_mutex_unlock(&b->mtx));
...@@ -149,11 +153,16 @@ barrier_sock_thread(void *priv) ...@@ -149,11 +153,16 @@ barrier_sock_thread(void *priv)
} }
assert(sock > 0); assert(sock > 0);
VTCP_nonblocking(sock); VTCP_nonblocking(sock);
VTCP_myname(sock, abuf, sizeof abuf, pbuf, sizeof pbuf); sua = VSA_getsockname(sock, buf, sizeof buf);
AN(sua);
VTCP_name(sua, abuf, sizeof abuf, pbuf, sizeof pbuf);
macro_def(vl, b->name, "addr", "%s", abuf); macro_def(vl, b->name, "addr", "%s", abuf);
macro_def(vl, b->name, "port", "%s", pbuf); macro_def(vl, b->name, "port", "%s", pbuf);
if (VSA_Get_Proto(sua) == AF_INET)
macro_def(vl, b->name, "sock", "%s:%s", abuf, pbuf); macro_def(vl, b->name, "sock", "%s:%s", abuf, pbuf);
else
macro_def(vl, b->name, "sock", "[%s]:%s", abuf, pbuf);
AZ(pthread_cond_signal(&b->cond)); AZ(pthread_cond_signal(&b->cond));
AZ(pthread_mutex_unlock(&b->mtx)); AZ(pthread_mutex_unlock(&b->mtx));
......
...@@ -106,7 +106,7 @@ client_tcp_connect(struct vtclog *vl, const char *addr, double tmo, ...@@ -106,7 +106,7 @@ client_tcp_connect(struct vtclog *vl, const char *addr, double tmo,
const char **errp) const char **errp)
{ {
int fd; int fd;
char mabuf[32], mpbuf[32]; char mabuf[VTCP_ADDRBUFSIZE], mpbuf[VTCP_PORTBUFSIZE];
AN(addr); AN(addr);
AN(errp); AN(errp);
......
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
#include "vpf.h" #include "vpf.h"
#include "vre.h" #include "vre.h"
#include "vtcp.h" #include "vtcp.h"
#include "vsa.h"
#include "vtim.h" #include "vtim.h"
#define HAPROXY_PROGRAM_ENV_VAR "HAPROXY_PROGRAM" #define HAPROXY_PROGRAM_ENV_VAR "HAPROXY_PROGRAM"
...@@ -173,7 +174,7 @@ haproxy_cli_tcp_connect(struct vtclog *vl, const char *addr, double tmo, ...@@ -173,7 +174,7 @@ haproxy_cli_tcp_connect(struct vtclog *vl, const char *addr, double tmo,
const char **errp) const char **errp)
{ {
int fd; int fd;
char mabuf[32], mpbuf[32]; char mabuf[VTCP_ADDRBUFSIZE], mpbuf[VTCP_PORTBUFSIZE];
AN(addr); AN(addr);
AN(errp); AN(errp);
...@@ -519,16 +520,23 @@ haproxy_create_mcli(struct haproxy *h) ...@@ -519,16 +520,23 @@ haproxy_create_mcli(struct haproxy *h)
int sock; int sock;
const char *err; const char *err;
char buf[128], addr[128], port[128]; char buf[128], addr[128], port[128];
char vsabuf[vsa_suckaddr_len];
struct suckaddr *sua;
sock = VTCP_listen_on("127.0.0.1:0", NULL, 100, &err); sock = VTCP_listen_on(default_listen_addr, NULL, 100, &err);
if (err != NULL) if (err != NULL)
vtc_fatal(h->vl, vtc_fatal(h->vl,
"Create listen socket failed: %s", err); "Create listen socket failed: %s", err);
assert(sock > 0); assert(sock > 0);
sua = VSA_getsockname(sock, vsabuf, sizeof vsabuf);
AN(sua);
VTCP_myname(sock, addr, sizeof addr, port, sizeof port); VTCP_name(sua, addr, sizeof addr, port, sizeof port);
bprintf(buf, "%s_mcli", h->name); bprintf(buf, "%s_mcli", h->name);
macro_def(h->vl, buf, "sock", "%s %s", addr, port); if (VSA_Get_Proto(sua) == AF_INET)
macro_def(h->vl, buf, "sock", "%s:%s", addr, port);
else
macro_def(h->vl, buf, "sock", "[%s]:%s", addr, port);
macro_def(h->vl, buf, "addr", "%s", addr); macro_def(h->vl, buf, "addr", "%s", addr);
macro_def(h->vl, buf, "port", "%s", port); macro_def(h->vl, buf, "port", "%s", port);
...@@ -558,6 +566,8 @@ haproxy_new(const char *name) ...@@ -558,6 +566,8 @@ haproxy_new(const char *name)
int closed_sock; int closed_sock;
char addr[128], port[128]; char addr[128], port[128];
const char *err; const char *err;
char vsabuf[vsa_suckaddr_len];
struct suckaddr *sua;
ALLOC_OBJ(h, HAPROXY_MAGIC); ALLOC_OBJ(h, HAPROXY_MAGIC);
AN(h); AN(h);
...@@ -597,8 +607,13 @@ haproxy_new(const char *name) ...@@ -597,8 +607,13 @@ haproxy_new(const char *name)
vtc_fatal(h->vl, vtc_fatal(h->vl,
"Create listen socket failed: %s", err); "Create listen socket failed: %s", err);
assert(closed_sock > 0); assert(closed_sock > 0);
VTCP_myname(closed_sock, addr, sizeof addr, port, sizeof port); sua = VSA_getsockname(closed_sock, vsabuf, sizeof vsabuf);
macro_def(h->vl, h->closed_sock, "sock", "%s %s", addr, port); AN(sua);
VTCP_name(sua, addr, sizeof addr, port, sizeof port);
if (VSA_Get_Proto(sua) == AF_INET)
macro_def(h->vl, h->closed_sock, "sock", "%s:%s", addr, port);
else
macro_def(h->vl, h->closed_sock, "sock", "[%s]:%s", addr, port);
macro_def(h->vl, h->closed_sock, "addr", "%s", addr); macro_def(h->vl, h->closed_sock, "addr", "%s", addr);
macro_def(h->vl, h->closed_sock, "port", "%s", port); macro_def(h->vl, h->closed_sock, "port", "%s", port);
VTCP_close(&closed_sock); VTCP_close(&closed_sock);
...@@ -836,6 +851,8 @@ haproxy_build_backends(struct haproxy *h, const char *vsb_data) ...@@ -836,6 +851,8 @@ haproxy_build_backends(struct haproxy *h, const char *vsb_data)
int sock; int sock;
char buf[128], addr[128], port[128]; char buf[128], addr[128], port[128];
const char *err; const char *err;
char vsabuf[vsa_suckaddr_len];
struct suckaddr *sua;
p = strstr(p, HAPROXY_BE_FD_STR); p = strstr(p, HAPROXY_BE_FD_STR);
if (!p) if (!p)
...@@ -853,10 +870,15 @@ haproxy_build_backends(struct haproxy *h, const char *vsb_data) ...@@ -853,10 +870,15 @@ haproxy_build_backends(struct haproxy *h, const char *vsb_data)
vtc_fatal(h->vl, vtc_fatal(h->vl,
"Create listen socket failed: %s", err); "Create listen socket failed: %s", err);
assert(sock > 0); assert(sock > 0);
sua = VSA_getsockname(sock, vsabuf, sizeof vsabuf);
AN(sua);
VTCP_myname(sock, addr, sizeof addr, port, sizeof port); VTCP_name(sua, addr, sizeof addr, port, sizeof port);
bprintf(buf, "%s_%s", h->name, p); bprintf(buf, "%s_%s", h->name, p);
macro_def(h->vl, buf, "sock", "%s %s", addr, port); if (VSA_Get_Proto(sua) == AF_INET)
macro_def(h->vl, buf, "sock", "%s:%s", addr, port);
else
macro_def(h->vl, buf, "sock", "[%s]:%s", addr, port);
macro_def(h->vl, buf, "addr", "%s", addr); macro_def(h->vl, buf, "addr", "%s", addr);
macro_def(h->vl, buf, "port", "%s", port); macro_def(h->vl, buf, "port", "%s", port);
......
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
#include "vnum.h" #include "vnum.h"
#include "vrnd.h" #include "vrnd.h"
#include "vss.h" #include "vss.h"
#include "vsa.h"
#include "vsub.h" #include "vsub.h"
#include "vtcp.h" #include "vtcp.h"
#include "vtim.h" #include "vtim.h"
...@@ -116,6 +117,7 @@ static int bad_backend_fd; ...@@ -116,6 +117,7 @@ static int bad_backend_fd;
static int cleaner_fd = -1; static int cleaner_fd = -1;
static pid_t cleaner_pid; static pid_t cleaner_pid;
const char *default_listen_addr;
static struct buf * static struct buf *
get_buf(void) get_buf(void)
...@@ -594,8 +596,13 @@ ip_magic(void) ...@@ -594,8 +596,13 @@ ip_magic(void)
sa = VSS_ResolveOne(NULL, "127.0.0.1", "0", 0, SOCK_STREAM, 0); sa = VSS_ResolveOne(NULL, "127.0.0.1", "0", 0, SOCK_STREAM, 0);
AN(sa); AN(sa);
bad_backend_fd = VTCP_bind(sa, NULL); bad_backend_fd = VTCP_bind(sa, NULL);
assert(bad_backend_fd >= 0); if (bad_backend_fd < 0) {
free(sa); free(sa);
sa = VSS_ResolveFirst(NULL, "localhost", "0", 0, SOCK_STREAM, 0);
AN(sa);
bad_backend_fd = VTCP_bind(sa, NULL);
}
assert(bad_backend_fd >= 0);
VTCP_myname(bad_backend_fd, abuf, sizeof abuf, pbuf, sizeof(pbuf)); VTCP_myname(bad_backend_fd, abuf, sizeof abuf, pbuf, sizeof(pbuf));
extmacro_def("localhost", "%s", abuf); extmacro_def("localhost", "%s", abuf);
...@@ -609,7 +616,21 @@ ip_magic(void) ...@@ -609,7 +616,21 @@ ip_magic(void)
#endif #endif
/* Expose a backend that is forever down. */ /* Expose a backend that is forever down. */
extmacro_def("bad_backend", "%s %s", abuf, pbuf); if (VSA_Get_Proto(sa) == AF_INET)
extmacro_def("bad_backend", "%s:%s", abuf, pbuf);
else
extmacro_def("bad_backend", "[%s]:%s", abuf, pbuf);
/* our default bind/listen address */
if (VSA_Get_Proto(sa) == AF_INET)
bprintf(abuf, "%s:0", macro_get("localhost", NULL));
else
bprintf(abuf, "[%s]:0", macro_get("localhost", NULL));
extmacro_def("listen_addr", "%s", abuf);
default_listen_addr = strdup(abuf);
AN(default_listen_addr);
free(sa);
/* /*
* We need an IP number which will not repond, ever, and that is a * We need an IP number which will not repond, ever, and that is a
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include "vsa.h"
#include "vtc.h" #include "vtc.h"
#include "vtcp.h" #include "vtcp.h"
...@@ -59,8 +60,8 @@ struct server { ...@@ -59,8 +60,8 @@ struct server {
int sock; int sock;
int fd; int fd;
char listen[256]; char listen[256];
char aaddr[32]; char aaddr[VTCP_ADDRBUFSIZE];
char aport[32]; char aport[VTCP_PORTBUFSIZE];
pthread_t tp; pthread_t tp;
}; };
...@@ -88,7 +89,7 @@ server_new(const char *name, struct vtclog *vl) ...@@ -88,7 +89,7 @@ server_new(const char *name, struct vtclog *vl)
s->vsp = Sess_New(s->vl, name); s->vsp = Sess_New(s->vl, name);
AN(s->vsp); AN(s->vsp);
bprintf(s->listen, "%s", "127.0.0.1 0"); bprintf(s->listen, "%s", default_listen_addr);
s->depth = 10; s->depth = 10;
s->sock = -1; s->sock = -1;
s->fd = -1; s->fd = -1;
...@@ -183,17 +184,27 @@ server_listen_uds(struct server *s, const char **errp) ...@@ -183,17 +184,27 @@ server_listen_uds(struct server *s, const char **errp)
static void static void
server_listen_tcp(struct server *s, const char **errp) server_listen_tcp(struct server *s, const char **errp)
{ {
char buf[vsa_suckaddr_len];
struct suckaddr *sua;
s->sock = VTCP_listen_on(s->listen, "0", s->depth, errp); s->sock = VTCP_listen_on(s->listen, "0", s->depth, errp);
if (*errp != NULL) if (*errp != NULL)
return; return;
assert(s->sock > 0); assert(s->sock > 0);
VTCP_myname(s->sock, s->aaddr, sizeof s->aaddr, sua = VSA_getsockname(s->sock, buf, sizeof buf);
AN(sua);
VTCP_name(sua, s->aaddr, sizeof s->aaddr,
s->aport, sizeof s->aport); s->aport, sizeof s->aport);
/* Record the actual port, and reuse it on subsequent starts */
if (VSA_Get_Proto(sua) == AF_INET)
bprintf(s->listen, "%s:%s", s->aaddr, s->aport);
else
bprintf(s->listen, "[%s]:%s", s->aaddr, s->aport);
macro_def(s->vl, s->name, "addr", "%s", s->aaddr); 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, "port", "%s", s->aport);
macro_def(s->vl, s->name, "sock", "%s %s", s->aaddr, s->aport); macro_def(s->vl, s->name, "sock", "%s", s->listen);
/* Record the actual port, and reuse it on subsequent starts */
bprintf(s->listen, "%s %s", s->aaddr, s->aport);
} }
static void static void
......
...@@ -265,7 +265,7 @@ syslog_new(const char *name, struct vtclog *vl) ...@@ -265,7 +265,7 @@ syslog_new(const char *name, struct vtclog *vl)
AN(s->vl); AN(s->vl);
vtc_log_set_cmd(s->vl, syslog_cmds); vtc_log_set_cmd(s->vl, syslog_cmds);
bprintf(s->bind, "%s", "127.0.0.1 0"); bprintf(s->bind, "%s", default_listen_addr);
s->repeat = 1; s->repeat = 1;
s->sock = -1; s->sock = -1;
s->lvl = -1; s->lvl = -1;
...@@ -358,6 +358,8 @@ syslog_bind(struct syslog_srv *s) ...@@ -358,6 +358,8 @@ syslog_bind(struct syslog_srv *s)
const char *err; const char *err;
char aaddr[VTCP_ADDRBUFSIZE]; char aaddr[VTCP_ADDRBUFSIZE];
char aport[VTCP_PORTBUFSIZE]; char aport[VTCP_PORTBUFSIZE];
char buf[vsa_suckaddr_len];
struct suckaddr *sua;
CHECK_OBJ_NOTNULL(s, SYSLOG_SRV_MAGIC); CHECK_OBJ_NOTNULL(s, SYSLOG_SRV_MAGIC);
...@@ -369,10 +371,15 @@ syslog_bind(struct syslog_srv *s) ...@@ -369,10 +371,15 @@ syslog_bind(struct syslog_srv *s)
"Syslog server bind address (%s) cannot be resolved: %s", "Syslog server bind address (%s) cannot be resolved: %s",
s->bind, err); s->bind, err);
assert(s->sock > 0); assert(s->sock > 0);
VTCP_myname(s->sock, aaddr, sizeof aaddr, aport, sizeof aport); sua = VSA_getsockname(s->sock, buf, sizeof buf);
AN(sua);
VTCP_name(sua, aaddr, sizeof aaddr, aport, sizeof aport);
macro_def(s->vl, s->name, "addr", "%s", aaddr); macro_def(s->vl, s->name, "addr", "%s", aaddr);
macro_def(s->vl, s->name, "port", "%s", aport); macro_def(s->vl, s->name, "port", "%s", aport);
macro_def(s->vl, s->name, "sock", "%s %s", aaddr, aport); if (VSA_Get_Proto(sua) == AF_INET)
macro_def(s->vl, s->name, "sock", "%s:%s", aaddr, aport);
else
macro_def(s->vl, s->name, "sock", "[%s]:%s", aaddr, aport);
/* Record the actual port, and reuse it on subsequent starts */ /* Record the actual port, and reuse it on subsequent starts */
bprintf(s->bind, "%s %s", aaddr, aport); bprintf(s->bind, "%s %s", aaddr, aport);
} }
......
...@@ -392,7 +392,7 @@ varnish_launch(struct varnish *v) ...@@ -392,7 +392,7 @@ varnish_launch(struct varnish *v)
char *r = NULL; char *r = NULL;
/* Create listener socket */ /* Create listener socket */
v->cli_fd = VTCP_listen_on("127.0.0.1:0", NULL, 1, &err); v->cli_fd = VTCP_listen_on(default_listen_addr, NULL, 1, &err);
if (err != NULL) if (err != NULL)
vtc_fatal(v->vl, "Create CLI listen socket failed: %s", err); vtc_fatal(v->vl, "Create CLI listen socket failed: %s", err);
assert(v->cli_fd > 0); assert(v->cli_fd > 0);
...@@ -420,7 +420,7 @@ varnish_launch(struct varnish *v) ...@@ -420,7 +420,7 @@ varnish_launch(struct varnish *v)
VSB_cat(vsb, " -p h2_initial_window_size=1m"); VSB_cat(vsb, " -p h2_initial_window_size=1m");
VSB_cat(vsb, " -p h2_rx_window_low_water=64k"); VSB_cat(vsb, " -p h2_rx_window_low_water=64k");
if (!v->has_a_arg) { if (!v->has_a_arg) {
VSB_printf(vsb, " -a '%s'", "127.0.0.1:0"); VSB_printf(vsb, " -a '%s'", default_listen_addr);
if (v->proto != NULL) if (v->proto != NULL)
VSB_printf(vsb, ",%s", v->proto); VSB_printf(vsb, ",%s", v->proto);
} }
...@@ -572,12 +572,14 @@ varnish_listen(const struct varnish *v, char *la) ...@@ -572,12 +572,14 @@ varnish_listen(const struct varnish *v, char *la)
AN(*a); AN(*a);
AN(*p); AN(*p);
if (*p != '-') { if (*p == '-') {
bprintf(s, "%s %s", a, p);
} else {
bprintf(s, "%s", a); bprintf(s, "%s", a);
a = "0.0.0.0"; a = "0.0.0.0";
p = "0"; p = "0";
} else if (strchr(a, ':')) {
bprintf(s, "[%s]:%s", a, p);
} else {
bprintf(s, "%s:%s", a, p);
} }
if (first) { if (first) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment