[master] 40863ac Allow a backend to resolve to multiple identical IP addresses.
Poul-Henning Kamp
phk at varnish-cache.org
Wed Nov 21 11:22:15 CET 2012
commit 40863ac3d0a79e5969563361cf69a33abf3ff086
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date: Wed Nov 21 10:21:40 2012 +0000
Allow a backend to resolve to multiple identical IP addresses.
(This can happen with /etc/hosts)
Inspired by patch from: Tollef
diff --git a/bin/varnishtest/tests/v00002.vtc b/bin/varnishtest/tests/v00002.vtc
index 93f2f31..c17dc0b 100644
--- a/bin/varnishtest/tests/v00002.vtc
+++ b/bin/varnishtest/tests/v00002.vtc
@@ -110,7 +110,7 @@ varnish v1 -errvcl {Unknown director policy: 'anarchy' at} {
director r1 anarchy { .host = "127.0.0.1"; }
}
-varnish v1 -errvcl {Backend host "v00002.freebsd.dk": resolves to multiple IPv4 addresses.} {
+varnish v1 -errvcl {Backend host "v00002.freebsd.dk": resolves to multiple ipv4 addresses.} {
/* too many IP numbers */
backend b1 { .host = "v00002.freebsd.dk"; }
}
diff --git a/lib/libvcl/vcc_backend.c b/lib/libvcl/vcc_backend.c
index 78cb0b2..a480edd 100644
--- a/lib/libvcl/vcc_backend.c
+++ b/lib/libvcl/vcc_backend.c
@@ -77,7 +77,7 @@ emit_sockaddr(struct vcc *tl, void *sa, unsigned sal)
AN(sa);
AN(sal);
assert(sal < 256);
- Fh(tl, 0, "\nstatic const unsigned char sockaddr%u[%d] = {\n",
+ Fh(tl, 0, "\nstatic const unsigned char sockaddr_%u[%d] = {\n",
tl->unique, sal + 1);
Fh(tl, 0, " %3u, /* Length */\n", sal);
u = sa;
@@ -100,16 +100,28 @@ emit_sockaddr(struct vcc *tl, void *sa, unsigned sal)
* and put it in an official sockaddr when we load the VCL.
*/
+struct foo_proto {
+ const char *name;
+ int family;
+ struct sockaddr_storage sa;
+ socklen_t l;
+};
+
void
Emit_Sockaddr(struct vcc *tl, const struct token *t_host, const char *port)
{
+ struct foo_proto protos[3], *pp;
struct addrinfo *res, *res0, *res1, hint;
- int n4, n6, error, retval, x;
- const char *emit, *multiple;
+ int error, retval, x;
char hbuf[NI_MAXHOST];
char *hop, *pop;
AN(t_host->dec);
+
+ memset(protos, 0, sizeof protos);
+ protos[0].name = "ipv4"; protos[0].family = PF_INET;
+ protos[1].name = "ipv6"; protos[1].family = PF_INET6;
+
retval = 0;
memset(&hint, 0, sizeof hint);
hint.ai_family = PF_UNSPEC;
@@ -139,33 +151,32 @@ Emit_Sockaddr(struct vcc *tl, const struct token *t_host, const char *port)
vcc_ErrWhere(tl, t_host);
return;
}
- AZ(error);
- n4 = n6 = 0;
- multiple = NULL;
for (res = res0; res; res = res->ai_next) {
- emit = NULL;
- if (res->ai_family == PF_INET) {
- if (n4++ == 0)
- emit = "ipv4";
- else
- multiple = "IPv4";
- } else if (res->ai_family == PF_INET6) {
- if (n6++ == 0)
- emit = "ipv6";
- else
- multiple = "IPv6";
- } else
+ for (pp = protos; pp->name != NULL; pp++)
+ if (res->ai_family == pp->family)
+ break;
+ if (pp->name == NULL) {
+ /* Unknown proto, ignore */
continue;
+ }
+ if (pp->l == res->ai_addrlen &&
+ !memcmp(&pp->sa, res->ai_addr, pp->l)) {
+ /*
+ * Same address we already emitted.
+ * This can happen using /etc/hosts
+ */
+ continue;
+ }
- if (multiple != NULL) {
+ if (pp->l > 0) {
VSB_printf(tl->sb,
"Backend host %.*s: resolves to "
"multiple %s addresses.\n"
"Only one address is allowed.\n"
"Please specify which exact address "
"you want to use, we found these:\n",
- PF(t_host), multiple);
+ PF(t_host), pp->name);
for (res1 = res0; res1 != NULL; res1 = res1->ai_next) {
error = getnameinfo(res1->ai_addr,
res1->ai_addrlen, hbuf, sizeof hbuf,
@@ -173,17 +184,21 @@ Emit_Sockaddr(struct vcc *tl, const struct token *t_host, const char *port)
AZ(error);
VSB_printf(tl->sb, "\t%s\n", hbuf);
}
+ freeaddrinfo(res0);
vcc_ErrWhere(tl, t_host);
return;
}
- AN(emit);
+
+ pp->l = res->ai_addrlen;
+ memcpy(&pp->sa, res->ai_addr, pp->l);
+
x = emit_sockaddr(tl, res->ai_addr, res->ai_addrlen);
- Fb(tl, 0, "\t.%s_sockaddr = sockaddr%u,\n", emit, x);
+ Fb(tl, 0, "\t.%s_sockaddr = sockaddr_%u,\n", pp->name, x);
error = getnameinfo(res->ai_addr,
res->ai_addrlen, hbuf, sizeof hbuf,
NULL, 0, NI_NUMERICHOST);
AZ(error);
- Fb(tl, 0, "\t.%s_addr = \"%s\",\n", emit, hbuf);
+ Fb(tl, 0, "\t.%s_addr = \"%s\",\n", pp->name, hbuf);
retval++;
}
if (res0 != NULL) {
More information about the varnish-commit
mailing list