
phk at varnish-cache
Aug 6, 2013, 10:26 AM
Post #1 of 1
(14 views)
Permalink
|
|
[master] 7e4f3b3 Further mucking about with IP data type, this should make it work.
|
|
commit 7e4f3b30825c939c2de5355f457f19e8609ba3e1 Author: Poul-Henning Kamp <phk [at] FreeBSD> 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); + } +} _______________________________________________ varnish-commit mailing list varnish-commit [at] varnish-cache https://www.varnish-cache.org/lists/mailman/listinfo/varnish-commit
|