Mailing List Archive

r1389 - trunk/varnish-cache/lib/libvcl
Author: phk
Date: 2007-05-09 10:06:00 +0200 (Wed, 09 May 2007)
New Revision: 1389

Modified:
trunk/varnish-cache/lib/libvcl/vcc_acl.c
Log:
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) {



Modified: trunk/varnish-cache/lib/libvcl/vcc_acl.c
===================================================================
--- trunk/varnish-cache/lib/libvcl/vcc_acl.c 2007-05-09 07:59:22 UTC (rev 1388)
+++ trunk/varnish-cache/lib/libvcl/vcc_acl.c 2007-05-09 08:06:00 UTC (rev 1389)
@@ -30,15 +30,88 @@
*/

#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 @@
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 @@
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_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);
}