From b07a2b3939ecefa321bb21d59cd8cbb04ce372bc Mon Sep 17 00:00:00 2001 From: phk Date: Sat, 22 Jul 2006 09:38:09 +0000 Subject: [PATCH] VCL compiler: add two sbufs for "init" and "fini" actions. VCL ACLs: Change syntax and implementation as follows. ACL Syntax now works the following way: acl $name { ! ( "myhost.com" ) ; "10.0.0.1" /8 ; } The '!' means not. If the address matches the rest of the rule the address does NOT match the acl and the search terminates here. Enclosing the string in paranthesis means that the rule will be ignored if the string cannot be converted to an address (with getaddrinfo). When a string can not be looked up, and is not enclosed in a paranthesis, a positive rule (ie: without !) will not match and a negative rule (with !) will match. A mask can always be supplied, no matter the style of the string given, so it is possible to do things like: { "fw.ourcompany.dom" / 24 } Which means "any host on the same /24 subnet as fw.ourcompany.dom". Unfortunately getaddrinfo() does not return a TTL for the results, in the future we may want to use some kind of timeout to refresh the lookups. git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@556 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- varnish-cache/bin/varnishd/Makefile.am | 1 + varnish-cache/bin/varnishd/cache_vrt.c | 13 +++ varnish-cache/bin/varnishd/cache_vrt_acl.c | 69 +++++++++++ varnish-cache/include/vcl.h | 2 + varnish-cache/include/vcl_returns.h | 2 +- varnish-cache/include/vrt.h | 21 ++-- varnish-cache/include/vrt_obj.h | 2 +- varnish-cache/lib/libvcl/vcc_acl.c | 108 +++++++----------- varnish-cache/lib/libvcl/vcc_compile.c | 69 ++++++++--- varnish-cache/lib/libvcl/vcc_compile.h | 7 +- varnish-cache/lib/libvcl/vcc_fixed_token.c | 23 ++-- .../lib/libvcl/vcc_gen_fixed_token.tcl | 2 + 12 files changed, 219 insertions(+), 100 deletions(-) create mode 100644 varnish-cache/bin/varnishd/cache_vrt_acl.c diff --git a/varnish-cache/bin/varnishd/Makefile.am b/varnish-cache/bin/varnishd/Makefile.am index 489e3fbd..1d53f946 100644 --- a/varnish-cache/bin/varnishd/Makefile.am +++ b/varnish-cache/bin/varnishd/Makefile.am @@ -30,6 +30,7 @@ varnishd_SOURCES = \ cache_session.c \ cache_vcl.c \ cache_vrt.c \ + cache_vrt_acl.c \ cli_event.c \ hash_simple_list.c \ hash_classic.c \ diff --git a/varnish-cache/bin/varnishd/cache_vrt.c b/varnish-cache/bin/varnishd/cache_vrt.c index 2e46f843..254c3286 100644 --- a/varnish-cache/bin/varnishd/cache_vrt.c +++ b/varnish-cache/bin/varnishd/cache_vrt.c @@ -86,6 +86,19 @@ VRT_alloc_backends(struct VCL_conf *cp) } } +void +VRT_free_backends(struct VCL_conf *cp) +{ + + (void)cp; +} + +void +VRT_fini_backend(struct backend *be) +{ + (void)be; +} + /*--------------------------------------------------------------------*/ #define VBACKEND(type,onm,field) \ diff --git a/varnish-cache/bin/varnishd/cache_vrt_acl.c b/varnish-cache/bin/varnishd/cache_vrt_acl.c new file mode 100644 index 00000000..3a461de6 --- /dev/null +++ b/varnish-cache/bin/varnishd/cache_vrt_acl.c @@ -0,0 +1,69 @@ +/* + * $Id$ + * + * Runtime support for compiled VCL programs, ACLs + * + * XXX: getaddrinfo() does not return a TTL. We might want to add + * XXX: a refresh facility. + */ + +#include +#include +#include + +#include "shmlog.h" +#include "vrt.h" +#include "vrt_obj.h" +#include "vcl.h" +#include "cache.h" +#include +#include +#include + + +int +VRT_acl_match(struct sess *sp, struct vrt_acl *ap) +{ + (void)sp; + (void)ap; + return (0); +} + +void +VRT_acl_init(struct vrt_acl *ap) +{ + struct addrinfo a0, *a1; + int i; + + memset(&a0, 0, sizeof a0); + a0.ai_socktype = SOCK_STREAM; + + for ( ; ap->name != NULL; ap++) { + a1 = NULL; + i = getaddrinfo(ap->name, NULL, &a0, &a1); + if (i != 0) { + fprintf(stderr, "getaddrinfo(%s) = %s\n", + ap->name, gai_strerror(i)); + if (a1 != NULL) + freeaddrinfo(a1); + a1 = NULL; + } + ap->priv = a1; + } +} + +void +VRT_acl_fini(struct vrt_acl *ap) +{ + struct addrinfo *a1; + + for ( ; ap->name != NULL; ap++) { + if (ap->priv == NULL) + continue; + a1 = ap->priv; + ap->priv = NULL; + freeaddrinfo(a1); + } +} + + diff --git a/varnish-cache/include/vcl.h b/varnish-cache/include/vcl.h index eb323224..a6c78957 100644 --- a/varnish-cache/include/vcl.h +++ b/varnish-cache/include/vcl.h @@ -9,6 +9,7 @@ struct sess; typedef void vcl_init_f(void); +typedef void vcl_fini_f(void); typedef int vcl_func_f(struct sess *sp); struct VCL_conf { @@ -22,6 +23,7 @@ struct VCL_conf { unsigned busy; vcl_init_f *init_func; + vcl_fini_f *fini_func; vcl_func_f *recv_func; vcl_func_f *miss_func; diff --git a/varnish-cache/include/vcl_returns.h b/varnish-cache/include/vcl_returns.h index 1fef265e..9fa9a14b 100644 --- a/varnish-cache/include/vcl_returns.h +++ b/varnish-cache/include/vcl_returns.h @@ -1,5 +1,5 @@ /* - * $Id: vcc_gen_fixed_token.tcl 545 2006-07-21 20:43:56Z phk $ + * $Id: vcc_gen_fixed_token.tcl 553 2006-07-21 21:57:43Z phk $ * * NB: This file is machine generated, DO NOT EDIT! * diff --git a/varnish-cache/include/vrt.h b/varnish-cache/include/vrt.h index 69cfe852..9598bb40 100644 --- a/varnish-cache/include/vrt.h +++ b/varnish-cache/include/vrt.h @@ -19,15 +19,19 @@ struct vrt_ref { }; struct vrt_acl { - unsigned ip; - unsigned mask; + unsigned char not; + unsigned char paren; + unsigned char mask; + const char *name; + void *priv; }; +/* ACL related */ +int VRT_acl_match(struct sess *, struct vrt_acl *); +void VRT_acl_init(struct vrt_acl *); +void VRT_acl_fini(struct vrt_acl *); + void VRT_count(struct sess *, unsigned); -#if 0 -int ip_match(unsigned, struct vcl_acl *); -int string_match(const char *, const char *); -#endif int VRT_rewrite(const char *, const char *); void VRT_error(struct sess *, unsigned, const char *); int VRT_switch_config(const char *); @@ -35,9 +39,12 @@ int VRT_switch_config(const char *); char *VRT_GetHdr(struct sess *, const char *); void VRT_handling(struct sess *sp, unsigned hand); +/* Backend related */ void VRT_set_backend_name(struct backend *, const char *); - void VRT_alloc_backends(struct VCL_conf *cp); +void VRT_free_backends(struct VCL_conf *cp); +void VRT_fini_backend(struct backend *be); + #define VRT_done(sp, hand) \ do { \ diff --git a/varnish-cache/include/vrt_obj.h b/varnish-cache/include/vrt_obj.h index 9ab2334c..8bb9da11 100644 --- a/varnish-cache/include/vrt_obj.h +++ b/varnish-cache/include/vrt_obj.h @@ -1,5 +1,5 @@ /* - * $Id: vcc_gen_obj.tcl 550 2006-07-21 21:13:43Z phk $ + * $Id: vcc_gen_obj.tcl 555 2006-07-22 08:02:47Z phk $ * * NB: This file is machine generated, DO NOT EDIT! * diff --git a/varnish-cache/lib/libvcl/vcc_acl.c b/varnish-cache/lib/libvcl/vcc_acl.c index 128260b4..50b0d548 100644 --- a/varnish-cache/lib/libvcl/vcc_acl.c +++ b/varnish-cache/lib/libvcl/vcc_acl.c @@ -22,65 +22,19 @@ #include "libvcl.h" -unsigned -vcc_IpVal(struct tokenlist *tl) -{ - unsigned u, v; - struct token *t; - - t = tl->t; - u = UintVal(tl); - if (u < 256) { - v = u << 24; - Expect(tl, '.'); - vcc_NextToken(tl); - t = tl->t; - u = UintVal(tl); - if (u < 256) { - v |= u << 16; - Expect(tl, '.'); - vcc_NextToken(tl); - t = tl->t; - u = UintVal(tl); - if (u < 256) { - v |= u << 8; - Expect(tl, '.'); - vcc_NextToken(tl); - t = tl->t; - u = UintVal(tl); - if (u < 256) { - v |= u; - return (v); - } - } - } - } - sbuf_printf(tl->sb, "Illegal octet in IP number\n"); - vcc_ErrWhere(tl, t); - return (0); -} - void vcc_Cond_Ip(struct var *vp, struct tokenlist *tl) { - unsigned u; + + (void)vp; /* only client.ip at this time */ switch (tl->t->tok) { case '~': vcc_NextToken(tl); ExpectErr(tl, ID); AddRef(tl, tl->t, R_ACL); - Fc(tl, 1, "ip_match(%s, acl_%T)\n", vp->rname, tl->t); - vcc_NextToken(tl); - break; - case T_EQ: - case T_NEQ: - Fc(tl, 1, "%s %T ", vp->rname, tl->t); + Fc(tl, 1, "VRT_acl_match(sp, acl_%T)\n", tl->t); vcc_NextToken(tl); - u = vcc_IpVal(tl); - Fc(tl, 0, "%uU /* %u.%u.%u.%u */\n", u, - (u >> 24) & 0xff, (u >> 16) & 0xff, - (u >> 8) & 0xff, (u) & 0xff); break; default: sbuf_printf(tl->sb, "Illegal condition "); @@ -95,41 +49,63 @@ vcc_Cond_Ip(struct var *vp, struct tokenlist *tl) void vcc_Acl(struct tokenlist *tl) { - unsigned u, m; + unsigned mask, para, not; + struct token *t, *an; vcc_NextToken(tl); ExpectErr(tl, ID); - AddDef(tl, tl->t, R_ACL); - Fh(tl, 0, "static struct vcl_acl acl_%T[];\n", tl->t); - Fc(tl, 1, "static struct vcl_acl acl_%T[] = {\n", tl->t); + an = tl->t; vcc_NextToken(tl); + AddDef(tl, an, R_ACL); + Fh(tl, 0, "static struct vrt_acl acl_%T[];\n", an); + Fc(tl, 1, "static struct vrt_acl acl_%T[] = {\n", an); + tl->indent += INDENT; ExpectErr(tl, '{'); vcc_NextToken(tl); - while (tl->t->tok == CNUM) { - u = vcc_IpVal(tl); + while (tl->t->tok != '}') { + + not = para = mask = 0; + + if (tl->t->tok == '!') { + not = 1; + vcc_NextToken(tl); + } + + if (tl->t->tok == '(') { + para = 1; + vcc_NextToken(tl); + } + + ExpectErr(tl, CSTR); + /* XXX: try to look it up, warn if failure */ + t = tl->t; + vcc_NextToken(tl); if (tl->t->tok == '/') { vcc_NextToken(tl); ExpectErr(tl, CNUM); - m = UintVal(tl); - } else - m = 32; + mask = UintVal(tl); + } + Fc(tl, 1, "{ %u, %u, %u, %T },\n", not, mask, para, t); + + if (para) { + ExpectErr(tl, ')'); + vcc_NextToken(tl); + } ExpectErr(tl, ';'); vcc_NextToken(tl); - Fc(tl, 1, "{ %11uU, %3uU }, /* %u.%u.%u.%u/%u */\n", - u, m, - (u >> 24) & 0xff, (u >> 16) & 0xff, - (u >> 8) & 0xff, (u) & 0xff, m); } - ExpectErr(tl, '}'); - Fc(tl, 1, "{ %11uU, %3uU }\n", 0, 0); - + Fc(tl, 1, "{ 0, 0, 0, (void*)0}\n", 0, 0); tl->indent -= INDENT; - Fc(tl, 1, "};\n\n"); + + ExpectErr(tl, '}'); vcc_NextToken(tl); + + Fi(tl, 1, "\tVRT_acl_init(acl_%T);\n", an); + Ff(tl, 1, "\tVRT_acl_fini(acl_%T);\n", an); } diff --git a/varnish-cache/lib/libvcl/vcc_compile.c b/varnish-cache/lib/libvcl/vcc_compile.c index 0f5b0262..7b3caf07 100644 --- a/varnish-cache/lib/libvcl/vcc_compile.c +++ b/varnish-cache/lib/libvcl/vcc_compile.c @@ -114,9 +114,33 @@ Fc(struct tokenlist *tl, int indent, const char *fmt, ...) va_end(ap); } +void +Fi(struct tokenlist *tl, int indent, const char *fmt, ...) +{ + va_list ap; + + if (indent) + sbuf_printf(tl->fi, "%*.*s", tl->indent, tl->indent, ""); + va_start(ap, fmt); + sbuf_vprintf(tl->fi, fmt, ap); + va_end(ap); +} + +void +Ff(struct tokenlist *tl, int indent, const char *fmt, ...) +{ + va_list ap; + + if (indent) + sbuf_printf(tl->ff, "%*.*s", tl->indent, tl->indent, ""); + va_start(ap, fmt); + sbuf_vprintf(tl->ff, fmt, ap); + va_end(ap); +} + /*--------------------------------------------------------------------*/ -static char * +char * EncString(struct token *t) { char *p, *q; @@ -871,11 +895,11 @@ Backend(struct tokenlist *tl) AddRef(tl, tl->t, R_BACKEND); Fh(tl, 1, "#define VGC_backend_%T (VCL_conf.backend[%d])\n", tl->t, tl->nbackend); + Fc(tl, 0, "\n"); Fc(tl, 0, "static void\n"); Fc(tl, 1, "VGC_init_backend_%T (void)\n", tl->t); Fc(tl, 1, "{\n"); Fc(tl, 1, "\tstruct backend *backend = VGC_backend_%T;\n", tl->t); - Fc(tl, 1, "\tconst char *p;\n"); Fc(tl, 1, "\n"); Fc(tl, 1, "\tVRT_set_backend_name(backend, \"%T\");\n", tl->t); vcc_NextToken(tl); @@ -941,6 +965,8 @@ Backend(struct tokenlist *tl) vcc_NextToken(tl); Fc(tl, 1, "}\n"); Fc(tl, 0, "\n"); + Fi(tl, 0, "\tVGC_init_backend_%T();\n", t_be); + Ff(tl, 0, "\tVRT_fini_backend(VGC_backend_%T);\n", t_be); tl->nbackend++; } @@ -1208,22 +1234,20 @@ LocTable(struct tokenlist *tl) static void EmitInitFunc(struct tokenlist *tl) { - struct ref *r; Fc(tl, 0, "\nstatic void\nVGC_Init(void)\n{\n\n"); - Fc(tl, 0, "\tVRT_alloc_backends(&VCL_conf);\n"); - - TAILQ_FOREACH(r, &tl->refs, list) { - switch(r->type) { - case R_FUNC: - break; - case R_ACL: - break; - case R_BACKEND: - Fc(tl, 0, "\tVGC_init_backend_%T();\n", r->name); - break; - } - } + sbuf_finish(tl->fi); + sbuf_cat(tl->fc, sbuf_data(tl->fi)); + Fc(tl, 0, "}\n"); +} + +static void +EmitFiniFunc(struct tokenlist *tl) +{ + + Fc(tl, 0, "\nstatic void\nVGC_Fini(void)\n{\n\n"); + sbuf_finish(tl->ff); + sbuf_cat(tl->fc, sbuf_data(tl->ff)); Fc(tl, 0, "}\n"); } @@ -1236,6 +1260,7 @@ EmitStruct(struct tokenlist *tl) Fc(tl, 0, "\nstruct VCL_conf VCL_conf = {\n"); Fc(tl, 0, "\t.magic = VCL_CONF_MAGIC,\n"); Fc(tl, 0, "\t.init_func = VGC_Init,\n"); + Fc(tl, 0, "\t.fini_func = VGC_Fini,\n"); Fc(tl, 0, "\t.nbackend = %d,\n", tl->nbackend); Fc(tl, 0, "\t.ref = VGC_ref,\n"); Fc(tl, 0, "\t.nref = VGC_NREFS,\n"); @@ -1279,8 +1304,16 @@ VCC_Compile(struct sbuf *sb, const char *b, const char *e) tokens.fh = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND); assert(tokens.fh != NULL); + tokens.fi = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND); + assert(tokens.fi != NULL); + + tokens.ff = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND); + assert(tokens.ff != NULL); + Fh(&tokens, 0, "extern struct VCL_conf VCL_conf;\n"); + Fi(&tokens, 0, "\tVRT_alloc_backends(&VCL_conf);\n"); + tokens.b = b; if (e == NULL) e = strchr(b, '\0'); @@ -1300,8 +1333,12 @@ VCC_Compile(struct sbuf *sb, const char *b, const char *e) goto done; LocTable(&tokens); + Ff(&tokens, 0, "\tVRT_free_backends(&VCL_conf);\n"); + EmitInitFunc(&tokens); + EmitFiniFunc(&tokens); + EmitStruct(&tokens); if (CheckRefs(&tokens)) diff --git a/varnish-cache/lib/libvcl/vcc_compile.h b/varnish-cache/lib/libvcl/vcc_compile.h index fd13be1e..0ddfa437 100644 --- a/varnish-cache/lib/libvcl/vcc_compile.h +++ b/varnish-cache/lib/libvcl/vcc_compile.h @@ -22,7 +22,7 @@ struct tokenlist { struct token *t; int indent; unsigned cnt; - struct sbuf *fc, *fh; + struct sbuf *fc, *fh, *fi, *ff; TAILQ_HEAD(, ref) refs; struct sbuf *sb; int err; @@ -97,16 +97,19 @@ struct proc { /* vcc_acl.c */ void vcc_Acl(struct tokenlist *tl); -unsigned vcc_IpVal(struct tokenlist *tl); void vcc_Cond_Ip(struct var *vp, struct tokenlist *tl); /* vcc_compile.c */ extern const char *vcc_default_vcl_b, *vcc_default_vcl_e; void Fh(struct tokenlist *tl, int indent, const char *fmt, ...); void Fc(struct tokenlist *tl, int indent, const char *fmt, ...); +void Fi(struct tokenlist *tl, int indent, const char *fmt, ...); +void Ff(struct tokenlist *tl, int indent, const char *fmt, ...); unsigned UintVal(struct tokenlist *tl); void AddDef(struct tokenlist *tl, struct token *t, enum ref_type type); void AddRef(struct tokenlist *tl, struct token *t, enum ref_type type); +char *EncString(struct token *t); + /* vcc_obj.c */ extern struct var vcc_be_vars[]; diff --git a/varnish-cache/lib/libvcl/vcc_fixed_token.c b/varnish-cache/lib/libvcl/vcc_fixed_token.c index c5db22e7..58bef42c 100644 --- a/varnish-cache/lib/libvcl/vcc_fixed_token.c +++ b/varnish-cache/lib/libvcl/vcc_fixed_token.c @@ -442,6 +442,7 @@ vcl_output_lang_h(FILE *f) fputs("struct sess;\n", f); fputs("\n", f); fputs("typedef void vcl_init_f(void);\n", f); + fputs("typedef void vcl_fini_f(void);\n", f); fputs("typedef int vcl_func_f(struct sess *sp);\n", f); fputs("\n", f); fputs("struct VCL_conf {\n", f); @@ -455,6 +456,7 @@ vcl_output_lang_h(FILE *f) fputs(" unsigned busy;\n", f); fputs("\n", f); fputs(" vcl_init_f *init_func;\n", f); + fputs(" vcl_fini_f *fini_func;\n", f); fputs("\n", f); fputs(" vcl_func_f *recv_func;\n", f); fputs(" vcl_func_f *miss_func;\n", f); @@ -483,15 +485,19 @@ vcl_output_lang_h(FILE *f) fputs("};\n", f); fputs("\n", f); fputs("struct vrt_acl {\n", f); - fputs(" unsigned ip;\n", f); - fputs(" unsigned mask;\n", f); + fputs(" unsigned char not;\n", f); + fputs(" unsigned char paren;\n", f); + fputs(" unsigned char mask;\n", f); + fputs(" const char *name;\n", f); + fputs(" void *priv;\n", f); fputs("};\n", f); fputs("\n", f); + fputs("/* ACL related */\n", f); + fputs("int VRT_acl_match(struct sess *, struct vrt_acl *);\n", f); + fputs("void VRT_acl_init(struct vrt_acl *);\n", f); + fputs("void VRT_acl_fini(struct vrt_acl *);\n", f); + fputs("\n", f); fputs("void VRT_count(struct sess *, unsigned);\n", f); - fputs("#if 0\n", f); - fputs("int ip_match(unsigned, struct vcl_acl *);\n", f); - fputs("int string_match(const char *, const char *);\n", f); - fputs("#endif\n", f); fputs("int VRT_rewrite(const char *, const char *);\n", f); fputs("void VRT_error(struct sess *, unsigned, const char *);\n", f); fputs("int VRT_switch_config(const char *);\n", f); @@ -499,9 +505,12 @@ vcl_output_lang_h(FILE *f) fputs("char *VRT_GetHdr(struct sess *, const char *);\n", f); fputs("void VRT_handling(struct sess *sp, unsigned hand);\n", f); fputs("\n", f); + fputs("/* Backend related */\n", f); fputs("void VRT_set_backend_name(struct backend *, const char *);\n", f); - fputs("\n", f); fputs("void VRT_alloc_backends(struct VCL_conf *cp);\n", f); + fputs("void VRT_free_backends(struct VCL_conf *cp);\n", f); + fputs("void VRT_fini_backend(struct backend *be);\n", f); + fputs("\n", f); fputs("\n", f); fputs("#define VRT_done(sp, hand) \\\n", f); fputs(" do { \\\n", f); diff --git a/varnish-cache/lib/libvcl/vcc_gen_fixed_token.tcl b/varnish-cache/lib/libvcl/vcc_gen_fixed_token.tcl index 1a087bad..ce827693 100755 --- a/varnish-cache/lib/libvcl/vcc_gen_fixed_token.tcl +++ b/varnish-cache/lib/libvcl/vcc_gen_fixed_token.tcl @@ -97,6 +97,7 @@ warns $fo puts $fo {struct sess; typedef void vcl_init_f(void); +typedef void vcl_fini_f(void); typedef int vcl_func_f(struct sess *sp); } puts $fo "struct VCL_conf {" @@ -110,6 +111,7 @@ puts $fo { unsigned magic; unsigned busy; vcl_init_f *init_func; + vcl_fini_f *fini_func; } foreach m $methods { puts $fo "\tvcl_func_f\t*[lindex $m 0]_func;" -- 2.39.5