]> err.no Git - varnish/commitdiff
Implement '==' and '!=' for IP number variables (presently only client.ip)
authorphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Wed, 9 May 2007 08:06:00 +0000 (08:06 +0000)
committerphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Wed, 9 May 2007 08:06:00 +0000 (08:06 +0000)
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

varnish-cache/lib/libvcl/vcc_acl.c

index eebfa84bb15ccd7493371b693b74e492c0749004..db0063b71df1e68199bdd5e488739739e14909f7 100644 (file)
  */
 
 #include <stdio.h>
+#include <assert.h>
+#include <stdlib.h>
 
 #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);
 }