[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