Commit 87ffa18d authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Change the acl syntax slightly: the ( ... ) should enclose all of

the rule (ie: also !  and /mask if present).

Implement matching for IPv4.

Acl tests are shmlogged as follows (doc candidate):

	shmlog tag:	VCL_actl

	"NO_MATCH $acl"
		client did not match access list $acl
	"FAIL $acl $rule"
		getaddrinfo(3) failed on $rule which had a '!'
	"MATCH $acl $rule"
		client matched $rule
	"NEG_MATCH $acl $rule"
		client matched negated (!) $rule




git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@558 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent 5f67fbdb
......@@ -19,14 +19,85 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
static unsigned ipv4mask[] = {
[0] = 0xffffffff,
#define M(n) [n] = (0xffffffff << (32 - n))
M( 1), M( 2), M( 3), M( 4), M( 5), M( 6), M( 7), M( 8), M( 9), M(10),
M(11), M(12), M(13), M(14), M(15), M(16), M(17), M(18), M(19), M(20),
M(21), M(22), M(23), M(24), M(25), M(26), M(27), M(28), M(29), M(30),
M(31), M(32)
};
static int
vrt_acl_vsl(struct sess *sp, const char *acl, struct vrt_acl *ap, int r)
{
assert(ap != NULL);
if (ap->name == NULL) {
assert(r == 0);
VSL(SLT_VCL_acl, sp->fd, "NO_MATCH %s", acl);
return (r);
}
if (ap->priv == NULL) {
assert(r == 0);
VSL(SLT_VCL_acl, sp->fd, "FAIL %s %s", acl, ap->desc);
return (r);
}
VSL(SLT_VCL_acl, sp->fd, "%s %s %s",
r ? "MATCH" : "NEG_MATCH", acl, ap->desc);
return (r);
}
int
VRT_acl_match(struct sess *sp, struct vrt_acl *ap)
VRT_acl_match(struct sess *sp, const char *acl, struct vrt_acl *ap)
{
(void)sp;
(void)ap;
return (0);
struct addrinfo *a1;
struct sockaddr_in *sin1, *sin2;
if (sp->sockaddr->sa_family == AF_INET) {
assert(sp->sockaddrlen >= sizeof *sin1);
sin1 = (void*)sp->sockaddr;
} else {
sin1 = NULL;
}
for ( ; ap->name != NULL; ap++) {
if (ap->priv == NULL && ap->paren)
continue;
if (ap->priv == NULL && ap->not) {
return (vrt_acl_vsl(sp, acl, ap, 0));
}
if (ap->priv == NULL)
continue;
for (a1 = ap->priv; a1 != NULL; a1 = a1->ai_next) {
/* only match the right family */
if (a1->ai_family != sp->sockaddr->sa_family)
continue;
if (a1->ai_family == AF_INET) {
assert(sin1 != NULL);
assert(a1->ai_addrlen >= sizeof (*sin2));
sin2 = (void*)a1->ai_addr;
if (0 == ((
htonl(sin1->sin_addr.s_addr) ^
htonl(sin2->sin_addr.s_addr)) &
ipv4mask[ap->mask > 32 ? 32 : ap->mask]))
return (
vrt_acl_vsl(sp, acl, ap, !ap->not));
continue;
}
/* Not rules for unknown protos match */
if (ap->not)
return (vrt_acl_vsl(sp, acl, ap, 0));
}
}
return (vrt_acl_vsl(sp, acl, ap, 0));
}
void
......
......@@ -33,6 +33,7 @@ SLTM(RxHeader)
SLTM(TxHeader)
SLTM(LostHeader)
SLTM(TTL)
SLTM(VCL_acl)
SLTM(VCL_call)
SLTM(VCL_trace)
SLTM(VCL_return)
......
/*
* $Id: vcc_gen_fixed_token.tcl 553 2006-07-21 21:57:43Z phk $
* $Id: vcc_gen_fixed_token.tcl 556 2006-07-22 09:38:09Z phk $
*
* NB: This file is machine generated, DO NOT EDIT!
*
......
......@@ -20,14 +20,15 @@ struct vrt_ref {
struct vrt_acl {
unsigned char not;
unsigned char paren;
unsigned char mask;
unsigned char paren;
const char *name;
const char *desc;
void *priv;
};
/* ACL related */
int VRT_acl_match(struct sess *, struct vrt_acl *);
int VRT_acl_match(struct sess *, const char *, struct vrt_acl *);
void VRT_acl_init(struct vrt_acl *);
void VRT_acl_fini(struct vrt_acl *);
......
......@@ -33,7 +33,7 @@ vcc_Cond_Ip(struct var *vp, struct tokenlist *tl)
vcc_NextToken(tl);
ExpectErr(tl, ID);
AddRef(tl, tl->t, R_ACL);
Fc(tl, 1, "VRT_acl_match(sp, acl_%T)\n", tl->t);
Fc(tl, 1, "VRT_acl_match(sp, \"%T\", acl_%T)\n", tl->t, tl->t);
vcc_NextToken(tl);
break;
default:
......@@ -51,6 +51,7 @@ vcc_Acl(struct tokenlist *tl)
{
unsigned mask, para, not;
struct token *t, *an;
char *p;
vcc_NextToken(tl);
......@@ -71,13 +72,13 @@ vcc_Acl(struct tokenlist *tl)
not = para = mask = 0;
if (tl->t->tok == '!') {
not = 1;
if (tl->t->tok == '(') {
para = 1;
vcc_NextToken(tl);
}
if (tl->t->tok == '(') {
para = 1;
if (tl->t->tok == '!') {
not = 1;
vcc_NextToken(tl);
}
......@@ -90,7 +91,19 @@ vcc_Acl(struct tokenlist *tl)
ExpectErr(tl, CNUM);
mask = UintVal(tl);
}
Fc(tl, 1, "{ %u, %u, %u, %T },\n", not, mask, para, t);
Fc(tl, 1, "{ %u, %u, %u, %T, \"", not, mask, para, t);
if (para)
Fc(tl, 0, "(");
if (not)
Fc(tl, 0, "!");
p = EncString(t);
Fc(tl, 0, "%s", p);
free(p);
if (mask)
Fc(tl, 0, "/%u", mask);
if (para)
Fc(tl, 0, ")");
Fc(tl, 0, "\" },\n");
if (para) {
ExpectErr(tl, ')');
......@@ -99,7 +112,7 @@ vcc_Acl(struct tokenlist *tl)
ExpectErr(tl, ';');
vcc_NextToken(tl);
}
Fc(tl, 1, "{ 0, 0, 0, (void*)0}\n", 0, 0);
Fc(tl, 1, "{ 0, 0, 0, (void*)0, ""}\n", 0, 0);
tl->indent -= INDENT;
Fc(tl, 1, "};\n\n");
......
......@@ -486,14 +486,15 @@ vcl_output_lang_h(FILE *f)
fputs("\n", f);
fputs("struct vrt_acl {\n", f);
fputs(" unsigned char not;\n", f);
fputs(" unsigned char paren;\n", f);
fputs(" unsigned char mask;\n", f);
fputs(" unsigned char paren;\n", f);
fputs(" const char *name;\n", f);
fputs(" const char *desc;\n", f);
fputs(" void *priv;\n", f);
fputs("};\n", f);
fputs("\n", f);
fputs("/* ACL related */\n", f);
fputs("int VRT_acl_match(struct sess *, struct vrt_acl *);\n", f);
fputs("int VRT_acl_match(struct sess *, const char *, struct vrt_acl *);\n", f);
fputs("void VRT_acl_init(struct vrt_acl *);\n", f);
fputs("void VRT_acl_fini(struct vrt_acl *);\n", f);
fputs("\n", f);
......
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