[master] d866395 Use the new VSS_resolver() function to handle IP's in VCC
Poul-Henning Kamp
phk at FreeBSD.org
Wed Mar 11 23:05:52 CET 2015
commit d86639568e660bbf272492659f85e271145903c6
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date: Wed Mar 11 22:04:01 2015 +0000
Use the new VSS_resolver() function to handle IP's in VCC
diff --git a/lib/libvcc/vcc_backend.c b/lib/libvcc/vcc_backend.c
index 29444a6..2f167bf 100644
--- a/lib/libvcc/vcc_backend.c
+++ b/lib/libvcc/vcc_backend.c
@@ -35,8 +35,6 @@
#include "vcc_compile.h"
-#include "vss.h"
-
/*--------------------------------------------------------------------
* Struct sockaddr is not really designed to be a compile time
* initialized data structure, so we encode it as a byte-string
@@ -44,27 +42,19 @@
*/
static void
-Emit_Sockaddr(struct vcc *tl, const struct token *t_host, const char *port)
+Emit_Sockaddr(struct vcc *tl, const struct token *t_host,
+ const struct token *t_port)
{
const char *ipv4, *ipv4a, *ipv6, *ipv6a, *pa;
- const char *err;
- char *p;
- char *hop, *pop;
+ char buf[256];
AN(t_host->dec);
- p = TlDup(tl, t_host->dec);
- AN(p);
- err = VSS_parse(p, &hop, &pop);
- if (err != NULL) {
- VSB_printf(tl->sb,
- "Backend host '%.*s': %s\n", PF(t_host), err);
- vcc_ErrWhere(tl, t_host);
- return;
- }
- Resolve_Sockaddr(tl,
- hop != NULL ? hop : t_host->dec,
- pop != NULL ? pop : port,
+ if (t_port != NULL)
+ bprintf(buf, "%s %s", t_host->dec, t_port->dec);
+ else
+ bprintf(buf, "%s", t_host->dec);
+ Resolve_Sockaddr(tl, buf, "http",
&ipv4, &ipv4a, &ipv6, &ipv6a, &pa, 2, t_host, "Backend host");
ERRCHK(tl);
if (ipv4 != NULL) {
@@ -398,10 +388,7 @@ vcc_ParseHostDef(struct vcc *tl, const struct token *t_be)
/* Check that the hostname makes sense */
assert(t_host != NULL);
- if (t_port != NULL)
- Emit_Sockaddr(tl, t_host, t_port->dec);
- else
- Emit_Sockaddr(tl, t_host, "80");
+ Emit_Sockaddr(tl, t_host, t_port);
ERRCHK(tl);
ExpectErr(tl, '}');
diff --git a/lib/libvcc/vcc_compile.h b/lib/libvcc/vcc_compile.h
index 42f8c5c..a4697a5 100644
--- a/lib/libvcc/vcc_compile.h
+++ b/lib/libvcc/vcc_compile.h
@@ -293,8 +293,8 @@ sym_wildcard_t vcc_Stv_Wildcard;
/* vcc_utils.c */
const char *vcc_regexp(struct vcc *tl);
-void Resolve_Sockaddr(struct vcc *tl, const char *host, const char *port, \
- const char **ipv4, const char **ipv4_ascii, const char **ipv6, \
+void Resolve_Sockaddr(struct vcc *tl, const char *host, const char *defport,
+ 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);
diff --git a/lib/libvcc/vcc_utils.c b/lib/libvcc/vcc_utils.c
index f5908ad..fcbcb07 100644
--- a/lib/libvcc/vcc_utils.c
+++ b/lib/libvcc/vcc_utils.c
@@ -34,13 +34,14 @@
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
-#include <netdb.h>
#include "vcc_compile.h"
#include "vre.h"
#include "vrt.h"
#include "vsa.h"
+#include "vss.h"
+#include "vtcp.h"
/*--------------------------------------------------------------------*/
@@ -94,37 +95,38 @@ vcc_regexp(struct vcc *tl)
* alignment.
*/
-static const char *
-vcc_sockaddr(struct vcc *tl, const void *sa, unsigned sal)
+static void
+vcc_suckaddr(struct vcc *tl, const char *host, const struct suckaddr *vsa,
+ const char **ip, const char **ip_ascii, const char **p_ascii)
{
+ char a[VTCP_ADDRBUFSIZE];
+ char p[VTCP_PORTBUFSIZE];
const int sz = sizeof(unsigned long long);
const unsigned n = (vsa_suckaddr_len + sz - 1) / sz;
- unsigned len;
unsigned long long b[n];
- struct suckaddr *sua;
- char *p;
+ int len;
+ char *q;
- AN(sa);
- AN(sal);
-
- sua = VSA_Malloc(sa, sal);
- AN(sua);
+ VTCP_name(vsa, a, sizeof a, p, sizeof p);
+ Fh(tl, 0, "\n/* \"%s\" -> %s */\n", host, a);
+ if (ip_ascii != NULL)
+ *ip_ascii = TlDup(tl, a);
+ if (p_ascii != NULL && *p_ascii == NULL)
+ *p_ascii = TlDup(tl, p);
Fh(tl, 0, "static const unsigned long long");
Fh(tl, 0, " suckaddr_%u[%d] = {\n", tl->unique, n);
- memcpy(b, sua, vsa_suckaddr_len);
- free(sua);
+ memcpy(b, vsa, vsa_suckaddr_len);
for (len = 0; len < n; len++)
Fh(tl, 0, "%s 0x%0*llxLL",
len ? ",\n" : "", sz * 2, b[len]);
Fh(tl, 0, "\n};\n");
- p = TlAlloc(tl, 40);
- AN(p);
- sprintf(p, "(const void*)suckaddr_%u", tl->unique);
-
+ q = TlAlloc(tl, 40);
+ AN(q);
+ sprintf(q, "(const void*)suckaddr_%u", tl->unique);
+ *ip = q;
tl->unique++;
- return (p);
}
/*--------------------------------------------------------------------
@@ -138,19 +140,57 @@ vcc_sockaddr(struct vcc *tl, const void *sa, unsigned sal)
* 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;
+struct rss {
+ unsigned magic;
+#define RSS_MAGIC 0x11e966ab
+
+ struct suckaddr *vsa4;
+ struct suckaddr *vsa6;
};
+static int __match_proto__(resolved_f)
+rs_callback(void *priv, const struct suckaddr *vsa)
+{
+ struct rss *rss;
+ int v;
+
+ CAST_OBJ_NOTNULL(rss, priv, RSS_MAGIC);
+ assert(VSA_Sane(vsa));
+
+ v = VSA_Get_Proto(vsa);
+ if (v == AF_INET) {
+ if (rss->vsa4 == NULL)
+ rss->vsa4 = VSA_Clone(vsa);
+ else if (VSA_Compare(vsa, rss->vsa4))
+ return (-2);
+ } else if (v == AF_INET6) {
+ if (rss->vsa6 == NULL)
+ rss->vsa6 = VSA_Clone(vsa);
+ else if (VSA_Compare(vsa, rss->vsa6))
+ return (-2);
+ } else {
+ WRONG("Wrong protocol");
+ }
+ return (0);
+}
+
+static int __match_proto__(resolved_f)
+rs_callback2(void *priv, const struct suckaddr *vsa)
+{
+ struct vcc *tl;
+ char a[VTCP_ADDRBUFSIZE];
+ char p[VTCP_PORTBUFSIZE];
+
+ CAST_OBJ_NOTNULL(tl, priv, VCC_MAGIC);
+ VTCP_name(vsa, a, sizeof a, p, sizeof p);
+ VSB_printf(tl->sb, "\t%s:%s\n", a, p);
+ return (0);
+}
+
void
Resolve_Sockaddr(struct vcc *tl,
const char *host,
- const char *port,
+ const char *def_port,
const char **ipv4,
const char **ipv4_ascii,
const char **ipv6,
@@ -160,100 +200,63 @@ Resolve_Sockaddr(struct vcc *tl,
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];
+ int error, retval = 0;
+ struct rss *rss;
+ const char *err;
- 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;
+ if (p_ascii != NULL)
+ *p_ascii = NULL;
- retval = 0;
- memset(&hint, 0, sizeof hint);
- hint.ai_family = PF_UNSPEC;
- hint.ai_socktype = SOCK_STREAM;
+ ALLOC_OBJ(rss, RSS_MAGIC);
+ AN(rss);
- 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));
+ error = VSS_resolver(host, def_port, rs_callback, rss, &err);
+ if (err != NULL) {
VSB_printf(tl->sb,
+ "%s '%.*s' could not be resolved to an IP address:\n"
"\t%s\n"
"(Sorry if that error message is gibberish.)\n",
- gai_strerror(error));
+ errid, PF(t_err), err);
vcc_ErrWhere(tl, t_err);
+ free(rss->vsa4);
+ free(rss->vsa6);
+ FREE_OBJ(rss);
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);
+ if (rss->vsa4 != NULL) {
+ vcc_suckaddr(tl, host, rss->vsa4, ipv4, ipv4_ascii, p_ascii);
+ free(rss->vsa4);
+ retval++;
+ }
+ if (rss->vsa6 != NULL) {
+ vcc_suckaddr(tl, host, rss->vsa6, ipv6, ipv6_ascii, p_ascii);
+ free(rss->vsa6);
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);
+ FREE_OBJ(rss);
+ if (error == -2 || 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");
+ (void)VSS_resolver(host, def_port, rs_callback2, tl, &err);
+ if (err != NULL) {
+ VSB_printf(tl->sb,
+ "%s '%.*s' could not be resolved to an"
+ " IP address:\n"
+ "\t%s\n"
+ "(Sorry if that error message is gibberish.)\n",
+ errid, PF(t_err), err);
+ }
+ vcc_ErrWhere(tl, t_err);
+ return;
}
+ AZ(error);
if (retval == 0) {
VSB_printf(tl->sb,
"%s '%.*s': resolves to "
More information about the varnish-commit
mailing list