r1389 - trunk/varnish-cache/lib/libvcl

phk at projects.linpro.no phk at projects.linpro.no
Wed May 9 10:06:00 CEST 2007


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);
 }




More information about the varnish-commit mailing list