From: phk Date: Wed, 9 May 2007 08:06:00 +0000 (+0000) Subject: Implement '==' and '!=' for IP number variables (presently only client.ip) X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fb03a47d1a0b2c272cc0e07a034940c468d50fac;p=varnish Implement '==' and '!=' for IP number variables (presently only client.ip) It works by building a one-entry ACL of the subsequent tokens and matching this ACL just like '~' would have done. This means that it is possible to use the '!', '(...)', '/width' constructs and domain-names in these comparisons. Examples: if (client.ip == ( "www.freebsd.org" )) { if (client.ip == (! "localhost" )) { if (client.ip == (! "10.0.0.0"/8 )) { or even if (client.ip != "somehost" / 28) { git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@1389 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- diff --git a/varnish-cache/lib/libvcl/vcc_acl.c b/varnish-cache/lib/libvcl/vcc_acl.c index eebfa84b..db0063b7 100644 --- a/varnish-cache/lib/libvcl/vcc_acl.c +++ b/varnish-cache/lib/libvcl/vcc_acl.c @@ -30,15 +30,88 @@ */ #include +#include +#include #include "vsb.h" #include "vcc_priv.h" #include "vcc_compile.h" +static void +vcc_acl_top(struct tokenlist *tl, const char *acln) +{ + + Fh(tl, 1, "\nstatic struct vrt_acl acl_%s[] = {\n", acln); + tl->hindent += INDENT; + +} + +static void +vcc_acl_entry(struct tokenlist *tl) +{ + unsigned mask, para, not; + struct token *t; + + not = para = mask = 0; + + if (tl->t->tok == '(') { + para = 1; + vcc_NextToken(tl); + } + + if (tl->t->tok == '!') { + not = 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); + mask = vcc_UintVal(tl); + } + Fh(tl, 1, "{ %u, %u, %u, ", not, mask, para); + EncToken(tl->fh, t); + Fh(tl, 0, ", \""); + if (para) + Fh(tl, 0, "("); + if (not) + Fh(tl, 0, "!"); + Fh(tl, 0, "\\\"\" "); + EncToken(tl->fh, t); + Fh(tl, 0, " \"\\\""); + if (mask) + Fh(tl, 0, "/%u", mask); + if (para) + Fh(tl, 0, ")"); + Fh(tl, 0, "\" },\n"); + + if (para) { + ExpectErr(tl, ')'); + vcc_NextToken(tl); + } +} + +static void +vcc_acl_bot(struct tokenlist *tl, const char *acln) +{ + + Fh(tl, 1, "{ 0, 0, 0, (void*)0, ""}\n", 0, 0); + tl->hindent -= INDENT; + Fh(tl, 1, "};\n"); + Fi(tl, 1, "\tVRT_acl_init(acl_%s);\n", acln); + Ff(tl, 1, "\tVRT_acl_fini(acl_%s);\n", acln); +} + void vcc_Cond_Ip(struct var *vp, struct tokenlist *tl) { + unsigned tcond; + char *acln; (void)vp; /* only client.ip at this time */ @@ -51,6 +124,19 @@ vcc_Cond_Ip(struct var *vp, struct tokenlist *tl) PF(tl->t), PF(tl->t)); vcc_NextToken(tl); break; + case T_EQ: + case T_NEQ: + tcond = tl->t->tok; + vcc_NextToken(tl); + asprintf(&acln, "acl_%u", tl->cnt); + assert(acln != NULL); + vcc_acl_top(tl, acln); + vcc_acl_entry(tl); + vcc_acl_bot(tl, acln); + Fb(tl, 1, "%sVRT_acl_match(sp, \"%s\", acl_%s)\n", + (tcond == T_NEQ ? "!" : ""), acln, acln); + free(acln); + break; default: vsb_printf(tl->sb, "Illegal condition "); vcc_ErrToken(tl, tl->t); @@ -64,8 +150,8 @@ vcc_Cond_Ip(struct var *vp, struct tokenlist *tl) void vcc_Acl(struct tokenlist *tl) { - unsigned mask, para, not; - struct token *t, *an; + struct token *an; + char *acln; vcc_NextToken(tl); @@ -74,67 +160,24 @@ vcc_Acl(struct tokenlist *tl) vcc_NextToken(tl); vcc_AddDef(tl, an, R_ACL); - Fh(tl, 0, "static struct vrt_acl acl_%.*s[];\n", PF(an)); - Fc(tl, 1, "static struct vrt_acl acl_%.*s[] = {\n", PF(an)); + asprintf(&acln, "%.*s", PF(an)); + assert(acln != NULL); - tl->indent += INDENT; + vcc_acl_top(tl, acln); ExpectErr(tl, '{'); vcc_NextToken(tl); while (tl->t->tok != '}') { - - not = para = mask = 0; - - if (tl->t->tok == '(') { - para = 1; - vcc_NextToken(tl); - } - - if (tl->t->tok == '!') { - not = 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); - mask = vcc_UintVal(tl); - } - Fc(tl, 1, "{ %u, %u, %u, ", not, mask, para); - EncToken(tl->fc, t); - Fc(tl, 0, ", \""); - if (para) - Fc(tl, 0, "("); - if (not) - Fc(tl, 0, "!"); - Fc(tl, 0, "\\\"\" "); - EncToken(tl->fc, t); - Fc(tl, 0, " \"\\\""); - if (mask) - Fc(tl, 0, "/%u", mask); - if (para) - Fc(tl, 0, ")"); - Fc(tl, 0, "\" },\n"); - - if (para) { - ExpectErr(tl, ')'); - vcc_NextToken(tl); - } + vcc_acl_entry(tl); + ERRCHK(tl); ExpectErr(tl, ';'); vcc_NextToken(tl); } - 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_%.*s);\n", PF(an)); - Ff(tl, 1, "\tVRT_acl_fini(acl_%.*s);\n", PF(an)); + vcc_acl_bot(tl, acln); + + free(acln); }