[master] 7e4f3b3 Further mucking about with IP data type, this should make it work.
Poul-Henning Kamp
phk at varnish-cache.org
Tue Aug 6 19:26:23 CEST 2013
commit 7e4f3b30825c939c2de5355f457f19e8609ba3e1
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date: Tue Aug 6 17:26:01 2013 +0000
Further mucking about with IP data type, this should make it work.
diff --git a/bin/varnishd/cache/cache_vrt_var.c b/bin/varnishd/cache/cache_vrt_var.c
index d3b212f..763e6ff 100644
--- a/bin/varnishd/cache/cache_vrt_var.c
+++ b/bin/varnishd/cache/cache_vrt_var.c
@@ -258,7 +258,7 @@ VRT_r_beresp_backend_name(const struct vrt_ctx *ctx)
return(ctx->bo->vbc->backend->vcl_name);
}
-struct sockaddr_storage *
+const void *
VRT_r_beresp_backend_ip(const struct vrt_ctx *ctx)
{
@@ -546,7 +546,7 @@ REQ_BOOL(hash_always_miss)
/*--------------------------------------------------------------------*/
-struct sockaddr_storage *
+const void *
VRT_r_client_ip(const struct vrt_ctx *ctx)
{
@@ -555,7 +555,7 @@ VRT_r_client_ip(const struct vrt_ctx *ctx)
return (&ctx->req->sp->sockaddr);
}
-struct sockaddr_storage *
+const void *
VRT_r_server_ip(const struct vrt_ctx *ctx)
{
int i;
diff --git a/include/vrt.h b/include/vrt.h
index 8b6e8a8..701e131 100644
--- a/include/vrt.h
+++ b/include/vrt.h
@@ -55,7 +55,7 @@ typedef double VCL_DURATION;
typedef const char * VCL_ENUM;
typedef const char * VCL_HEADER;
typedef long VCL_INT;
-typedef struct sockaddr_storage * VCL_IP;
+typedef const void * VCL_IP;
typedef double VCL_REAL;
typedef const char * VCL_STRING;
typedef double VCL_TIME;
@@ -125,7 +125,7 @@ struct vrt_backend {
const char *port;
const void *ipv4_sockaddr;
- const void *ipv6_sockaddr;
+ const void *ipv6_sockaddr;
const char *hosthdr;
diff --git a/lib/libvcl/vcc_backend.c b/lib/libvcl/vcc_backend.c
index 1c69ae8..a8773d0 100644
--- a/lib/libvcl/vcc_backend.c
+++ b/lib/libvcl/vcc_backend.c
@@ -50,11 +50,7 @@
#include "config.h"
-#include <sys/types.h>
-#include <sys/socket.h>
-
#include <limits.h>
-#include <netdb.h>
#include <stdlib.h>
#include <string.h>
@@ -75,34 +71,14 @@ struct host {
* 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;
-};
-
static 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 error, retval;
- char hbuf[NI_MAXHOST];
+ const char *ipv4, *ipv4a, *ipv6, *ipv6a, *pa;
char *hop, *pop;
- const char *sa;
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;
- hint.ai_socktype = SOCK_STREAM;
-
if (VSS_parse(t_host->dec, &hop, &pop)) {
VSB_printf(tl->sb,
"Backend host '%.*s': wrong syntax (unbalanced [...] ?)\n",
@@ -110,88 +86,20 @@ Emit_Sockaddr(struct vcc *tl, const struct token *t_host, const char *port)
vcc_ErrWhere(tl, t_host);
return;
}
- error = getaddrinfo(
+ Resolve_Sockaddr(tl,
hop != NULL ? hop : t_host->dec,
pop != NULL ? pop : port,
- &hint, &res0);
- free(hop);
- free(pop);
- if (error) {
- VSB_printf(tl->sb,
- "Backend host '%.*s'"
- " could not be resolved to an IP address:\n", PF(t_host));
- VSB_printf(tl->sb,
- "\t%s\n"
- "(Sorry if that error message is gibberish.)\n",
- gai_strerror(error));
- vcc_ErrWhere(tl, t_host);
- return;
- }
-
- for (res = res0; res; res = res->ai_next) {
- 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 (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), pp->name);
- for (res1 = res0; res1 != NULL; res1 = res1->ai_next) {
- error = getnameinfo(res1->ai_addr,
- res1->ai_addrlen, hbuf, sizeof hbuf,
- NULL, 0, NI_NUMERICHOST);
- AZ(error);
- VSB_printf(tl->sb, "\t%s\n", hbuf);
- }
- freeaddrinfo(res0);
- vcc_ErrWhere(tl, t_host);
- return;
- }
-
- pp->l = res->ai_addrlen;
- memcpy(&pp->sa, res->ai_addr, pp->l);
-
- sa = vcc_sockaddr(tl, res->ai_addr, res->ai_addrlen);
- Fb(tl, 0, "\t.%s_sockaddr = %s,\n", pp->name, sa);
- 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", pp->name, hbuf);
- retval++;
- }
- if (res0 != NULL) {
- error = getnameinfo(res0->ai_addr,
- res0->ai_addrlen, NULL, 0, hbuf, sizeof hbuf,
- NI_NUMERICSERV);
- AZ(error);
- Fb(tl, 0, "\t.port = \"%s\",\n", hbuf);
+ &ipv4, &ipv4a, &ipv6, &ipv6a, &pa, 2, t_host, "Backend host");
+ ERRCHK(tl);
+ if (ipv4 != NULL) {
+ Fb(tl, 0, "\t.ipv4_sockaddr = %s,\n", ipv4);
+ Fb(tl, 0, "\t.ipv4_addr = \"%s\",\n", ipv4a);
}
- freeaddrinfo(res0);
- if (retval == 0) {
- VSB_printf(tl->sb,
- "Backend host '%.*s': resolves to "
- "neither IPv4 nor IPv6 addresses.\n",
- PF(t_host) );
- vcc_ErrWhere(tl, t_host);
+ if (ipv6 != NULL) {
+ Fb(tl, 0, "\t.ipv6_sockaddr = %s,\n", ipv6);
+ Fb(tl, 0, "\t.ipv6_addr = \"%s\",\n", ipv6a);
}
+ Fb(tl, 0, "\t.port = \"%s\",\n", pa);
}
/*--------------------------------------------------------------------
diff --git a/lib/libvcl/vcc_compile.h b/lib/libvcl/vcc_compile.h
index 11bd782..1b6da33 100644
--- a/lib/libvcl/vcc_compile.h
+++ b/lib/libvcl/vcc_compile.h
@@ -50,6 +50,7 @@
struct vsb;
struct token;
+struct sockaddr_storage;
#define isident1(c) (isalpha(c))
#define isident(c) (isalpha(c) || isdigit(c) || (c) == '_' || (c) == '-')
@@ -285,9 +286,12 @@ void vcc_Parse(struct vcc *tl);
/* vcc_storage.c */
sym_wildcard_t vcc_Stv_Wildcard;
-/* vcc_string.c */
+/* vcc_utils.c */
const char *vcc_regexp(struct vcc *tl);
-const char *vcc_sockaddr(struct vcc *tl, const void *sa, unsigned sal);
+void Resolve_Sockaddr(struct vcc *tl, const char *host, const char *port, \
+ const char **ipv4, const char **ipv4_ascii, const char **ipv6, \
+ const char **ipv6_ascii, const char **p_ascii, int maxips,
+ const struct token *t_err, const char *errid);
/* vcc_symb.c */
struct symbol *VCC_AddSymbolStr(struct vcc *tl, const char *name, enum symkind);
diff --git a/lib/libvcl/vcc_expr.c b/lib/libvcl/vcc_expr.c
index 95eceba..164a8d6 100644
--- a/lib/libvcl/vcc_expr.c
+++ b/lib/libvcl/vcc_expr.c
@@ -652,6 +652,7 @@ static void
vcc_expr4(struct vcc *tl, struct expr **e, enum var_type fmt)
{
struct expr *e1, *e2;
+ const char *ip;
const struct symbol *sym;
double d;
@@ -698,13 +699,22 @@ vcc_expr4(struct vcc *tl, struct expr **e, enum var_type fmt)
return;
case CSTR:
assert(fmt != VOID);
- e1 = vcc_new_expr();
- EncToken(e1->vsb, tl->t);
- e1->fmt = STRING;
+ if (fmt == IP) {
+ Resolve_Sockaddr(tl, tl->t->dec, "80",
+ &ip, NULL, &ip, NULL, NULL, 1,
+ tl->t, "IP constant");
+ ERRCHK(tl);
+ e1 = vcc_mk_expr(IP, "%s", ip);
+ ERRCHK(tl);
+ } else {
+ e1 = vcc_new_expr();
+ EncToken(e1->vsb, tl->t);
+ e1->fmt = STRING;
+ AZ(VSB_finish(e1->vsb));
+ }
e1->t1 = tl->t;
e1->constant = EXPR_CONST;
vcc_NextToken(tl);
- AZ(VSB_finish(e1->vsb));
*e = e1;
break;
case CNUM:
diff --git a/lib/libvcl/vcc_utils.c b/lib/libvcl/vcc_utils.c
index bfb3c05..e75cf25 100644
--- a/lib/libvcl/vcc_utils.c
+++ b/lib/libvcl/vcc_utils.c
@@ -31,7 +31,9 @@
#include <stdio.h>
#include <string.h>
+#include <sys/types.h>
#include <sys/socket.h>
+#include <netdb.h>
#include "vcc_compile.h"
@@ -87,7 +89,7 @@ vcc_regexp(struct vcc *tl)
* will ensure good enough alignment.
*/
-const char *
+static const char *
vcc_sockaddr(struct vcc *tl, const void *sa, unsigned sal)
{
unsigned n = (sal + 7) / 8, len;
@@ -97,13 +99,13 @@ vcc_sockaddr(struct vcc *tl, const void *sa, unsigned sal)
assert(VSA_Sane(sa));
AN(sa);
AN(sal);
- assert(sal < 256);
+ assert(sal < sizeof(struct sockaddr_storage));
assert(sizeof(unsigned long long) == 8);
p = TlAlloc(tl, 20);
sprintf(p, "sockaddr_%u", tl->unique++);
- Fh(tl, 0, "\nstatic const unsigned long long");
+ Fh(tl, 0, "static const unsigned long long");
Fh(tl, 0, " %s[%d] = {\n", p, n);
memcpy(b, sa, sal);
for (len = 0; len <n; len++) {
@@ -114,3 +116,140 @@ vcc_sockaddr(struct vcc *tl, const void *sa, unsigned sal)
Fh(tl, 0, "\n};\n");
return (p);
}
+
+/*--------------------------------------------------------------------
+ * This routine is a monster, but at least we only have one such monster.
+ * Look up a IP number, and return IPv4/IPv6 address as VGC produced names
+ * and optionally ascii strings.
+ *
+ * For IP compile time constants we only want one IP#, but it can be
+ * IPv4 or IPv6.
+ *
+ * For backends, we accept up to one IPv4 and one IPv6.
+ */
+
+struct foo_proto {
+ const char *name;
+ int family;
+ struct sockaddr_storage sa;
+ socklen_t l;
+ const char **dst;
+ const char **dst_ascii;
+};
+
+void
+Resolve_Sockaddr(struct vcc *tl,
+ const char *host,
+ const char *port,
+ const char **ipv4,
+ const char **ipv4_ascii,
+ const char **ipv6,
+ const char **ipv6_ascii,
+ const char **p_ascii,
+ int maxips,
+ const struct token *t_err,
+ const char *errid)
+{
+ struct foo_proto protos[3], *pp;
+ struct addrinfo *res, *res0, *res1, hint;
+ int error, retval;
+ char hbuf[NI_MAXHOST];
+
+ memset(protos, 0, sizeof protos);
+ protos[0].name = "ipv4";
+ protos[0].family = PF_INET;
+ protos[0].dst = ipv4;
+ protos[0].dst_ascii = ipv4_ascii;
+ *ipv4 = NULL;
+
+ protos[1].name = "ipv6";
+ protos[1].family = PF_INET6;
+ protos[1].dst = ipv6;
+ protos[1].dst_ascii = ipv6_ascii;
+ *ipv6 = NULL;
+
+ retval = 0;
+ memset(&hint, 0, sizeof hint);
+ hint.ai_family = PF_UNSPEC;
+ hint.ai_socktype = SOCK_STREAM;
+
+ error = getaddrinfo(host, port, &hint, &res0);
+ if (error) {
+ VSB_printf(tl->sb,
+ "%s '%.*s' could not be resolved to an IP address:\n",
+ errid, PF(t_err));
+ VSB_printf(tl->sb,
+ "\t%s\n"
+ "(Sorry if that error message is gibberish.)\n",
+ gai_strerror(error));
+ vcc_ErrWhere(tl, t_err);
+ return;
+ }
+
+ for (res = res0; res; res = res->ai_next) {
+ 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 (pp->l != 0 || retval == maxips) {
+ VSB_printf(tl->sb,
+ "%s %.*s: resolves to too many addresses.\n"
+ "Only one IPv4 %s IPv6 are allowed.\n"
+ "Please specify which exact address "
+ "you want to use, we found all of these:\n",
+ errid, PF(t_err),
+ maxips > 1 ? "and one" : "or");
+ for (res1 = res0; res1 != NULL; res1 = res1->ai_next) {
+ error = getnameinfo(res1->ai_addr,
+ res1->ai_addrlen, hbuf, sizeof hbuf,
+ NULL, 0, NI_NUMERICHOST);
+ AZ(error);
+ VSB_printf(tl->sb, "\t%s\n", hbuf);
+ }
+ freeaddrinfo(res0);
+ vcc_ErrWhere(tl, t_err);
+ return;
+ }
+
+ pp->l = res->ai_addrlen;
+ assert(pp->l < sizeof(struct sockaddr_storage));
+ memcpy(&pp->sa, res->ai_addr, pp->l);
+
+ error = getnameinfo(res->ai_addr, res->ai_addrlen,
+ hbuf, sizeof hbuf, NULL, 0, NI_NUMERICHOST);
+ AZ(error);
+
+ Fh(tl, 0, "\n/* \"%s\" -> %s */\n", host, hbuf);
+ *(pp->dst) = vcc_sockaddr(tl, &pp->sa, pp->l);
+ if (pp->dst_ascii != NULL) {
+ *pp->dst_ascii = TlDup(tl, hbuf);
+ }
+ retval++;
+ }
+ if (p_ascii != NULL) {
+ error = getnameinfo(res0->ai_addr,
+ res0->ai_addrlen, NULL, 0, hbuf, sizeof hbuf,
+ NI_NUMERICSERV);
+ AZ(error);
+ *p_ascii = TlDup(tl, hbuf);
+ }
+ if (retval == 0) {
+ VSB_printf(tl->sb,
+ "%s '%.*s': resolves to "
+ "neither IPv4 nor IPv6 addresses.\n",
+ errid, PF(t_err) );
+ vcc_ErrWhere(tl, t_err);
+ }
+}
More information about the varnish-commit
mailing list