Commit ccc1feed authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

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: http://www.varnish-cache.org/svn/trunk/varnish-cache@1389 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent 17a59db6
......@@ -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 @@ 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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment