Commit 6ba31f50 authored by Tollef Fog Heen's avatar Tollef Fog Heen

Merge r3409: Clean up the ACL generation code a bit.



git-svn-id: http://www.varnish-cache.org/svn/branches/2.0@3617 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent d0743524
...@@ -60,59 +60,87 @@ struct acl_e { ...@@ -60,59 +60,87 @@ struct acl_e {
/* Compare two acl rules for ordering */ /* Compare two acl rules for ordering */
#define CMP(a, b) \
do { \
if ((a) < (b)) \
return (-1); \
else if ((b) < (a)) \
return (1); \
} while (0)
static int static int
vcl_acl_cmp(struct tokenlist *tl, struct acl_e *ae1, struct acl_e *ae2) vcl_acl_cmp(struct acl_e *ae1, struct acl_e *ae2)
{ {
unsigned char *p1, *p2; unsigned char *p1, *p2;
unsigned m; unsigned m;
(void)tl;
p1 = ae1->data; p1 = ae1->data;
p2 = ae2->data; p2 = ae2->data;
m = ae1->mask; m = ae1->mask;
if (ae2->mask < m) if (ae2->mask < m)
m = ae2->mask; m = ae2->mask;
for (; m >= 8; m -= 8) { for (; m >= 8; m -= 8) {
if (*p1 < *p2) CMP(*p1, *p2);
return (-1);
if (*p1 > *p2)
return (1);
p1++; p1++;
p2++; p2++;
} }
if (m) { if (m) {
m = 0xff00 >> m; m = 0xff00 >> m;
m &= 0xff; m &= 0xff;
if ((*p1 & m) < (*p2 & m)) CMP(*p1 & m, *p2 & m);
return (-1);
if ((*p1 & m) > (*p2 & m))
return (1);
} }
if (ae1->mask > ae2->mask) /* Long mask is less than short mask */
return (-1); CMP(ae2->mask, ae1->mask);
if (ae1->mask < ae2->mask)
return (1);
return (0); return (0);
} }
static void static void
vcl_acl_add_entry(struct tokenlist *tl, struct acl_e *ae) vcc_acl_add_entry(struct tokenlist *tl, const struct acl_e *ae, int l,
const unsigned char *u, int fam)
{ {
struct acl_e *ae2; struct acl_e *ae2, *aen;
int i; int i;
if (fam == PF_INET && ae->mask > 32) {
vsb_printf(tl->sb,
"Too wide mask (%u) for IPv4 address", ae->mask);
vcc_ErrWhere(tl, ae->t_mask);
return;
}
if (fam == PF_INET6 && ae->mask > 128) {
vsb_printf(tl->sb,
"Too wide mask (%u) for IPv6 address", ae->mask);
vcc_ErrWhere(tl, ae->t_mask);
return;
}
/* Make a copy from the template */
aen = TlAlloc(tl, sizeof *ae2);
AN(aen);
*aen = *ae;
/* We treat family as part of address, it saves code */
assert(fam <= 0xff);
aen->data[0] = fam & 0xff;
aen->mask += 8;
memcpy(aen->data + 1, u, l);
VTAILQ_FOREACH(ae2, &tl->acl, list) { VTAILQ_FOREACH(ae2, &tl->acl, list) {
i = vcl_acl_cmp(tl, ae, ae2); i = vcl_acl_cmp(aen, ae2);
if (i == 0) { if (i == 0) {
/* If the two rules agree, silently ignore it */ /*
if (ae->not == ae2->not) * If the two rules agree, silently ignore it
* XXX: is that counter intuitive ?
*/
if (aen->not == ae2->not)
return; return;
vsb_printf(tl->sb, "Conflicting ACL entries:\n"); vsb_printf(tl->sb, "Conflicting ACL entries:\n");
vcc_ErrWhere(tl, ae2->t_addr); vcc_ErrWhere(tl, ae2->t_addr);
vsb_printf(tl->sb, "vs:\n"); vsb_printf(tl->sb, "vs:\n");
vcc_ErrWhere(tl, ae->t_addr); vcc_ErrWhere(tl, aen->t_addr);
return; return;
} }
/* /*
...@@ -126,43 +154,11 @@ vcl_acl_add_entry(struct tokenlist *tl, struct acl_e *ae) ...@@ -126,43 +154,11 @@ vcl_acl_add_entry(struct tokenlist *tl, struct acl_e *ae)
* be used to gather statistics. * be used to gather statistics.
*/ */
if (i < 0) { if (i < 0) {
VTAILQ_INSERT_BEFORE(ae2, ae, list); VTAILQ_INSERT_BEFORE(ae2, aen, list);
return; return;
} }
} }
VTAILQ_INSERT_TAIL(&tl->acl, ae, list); VTAILQ_INSERT_TAIL(&tl->acl, aen, list);
}
static void
vcc_acl_emit_entry(struct tokenlist *tl, const struct acl_e *ae, int l,
const unsigned char *u, int fam)
{
struct acl_e *ae2;
if (fam == PF_INET && ae->mask > 32) {
vsb_printf(tl->sb,
"Too wide mask (%u) for IPv4 address", ae->mask);
vcc_ErrWhere(tl, ae->t_mask);
return;
}
if (fam == PF_INET6 && ae->mask > 128) {
vsb_printf(tl->sb,
"Too wide mask (%u) for IPv6 address", ae->mask);
vcc_ErrWhere(tl, ae->t_mask);
return;
}
ae2 = TlAlloc(tl, sizeof *ae2);
AN(ae2);
*ae2 = *ae;
ae2->data[0] = fam & 0xff;
ae2->mask += 8; /* family matching */
memcpy(ae2->data + 1, u, l);
vcl_acl_add_entry(tl, ae2);
} }
static void static void
...@@ -211,7 +207,7 @@ vcc_acl_try_getaddrinfo(struct tokenlist *tl, struct acl_e *ae) ...@@ -211,7 +207,7 @@ vcc_acl_try_getaddrinfo(struct tokenlist *tl, struct acl_e *ae)
if (ae->t_mask == NULL) if (ae->t_mask == NULL)
ae->mask = 32; ae->mask = 32;
i4++; i4++;
vcc_acl_emit_entry(tl, ae, 4, u, res->ai_family); vcc_acl_add_entry(tl, ae, 4, u, res->ai_family);
break; break;
case PF_INET6: case PF_INET6:
assert(PF_INET6 < 256); assert(PF_INET6 < 256);
...@@ -221,7 +217,7 @@ vcc_acl_try_getaddrinfo(struct tokenlist *tl, struct acl_e *ae) ...@@ -221,7 +217,7 @@ vcc_acl_try_getaddrinfo(struct tokenlist *tl, struct acl_e *ae)
if (ae->t_mask == NULL) if (ae->t_mask == NULL)
ae->mask = 128; ae->mask = 128;
i6++; i6++;
vcc_acl_emit_entry(tl, ae, 16, u, res->ai_family); vcc_acl_add_entry(tl, ae, 16, u, res->ai_family);
break; break;
default: default:
vsb_printf(tl->sb, vsb_printf(tl->sb,
...@@ -270,7 +266,7 @@ vcc_acl_try_netnotation(struct tokenlist *tl, struct acl_e *ae) ...@@ -270,7 +266,7 @@ vcc_acl_try_netnotation(struct tokenlist *tl, struct acl_e *ae)
} }
if (ae->t_mask == NULL) if (ae->t_mask == NULL)
ae->mask = 8 + 8 * i; ae->mask = 8 + 8 * i;
vcc_acl_emit_entry(tl, ae, 4, b, AF_INET); vcc_acl_add_entry(tl, ae, 4, b, AF_INET);
return (1); return (1);
} }
...@@ -321,9 +317,12 @@ vcc_acl_entry(struct tokenlist *tl) ...@@ -321,9 +317,12 @@ vcc_acl_entry(struct tokenlist *tl)
ERRCHK(tl); ERRCHK(tl);
} }
/*********************************************************************
* Emit a function to match the ACL we have collected
*/
static void static void
vcc_acl_bot(const struct tokenlist *tl, const char *acln, int silent, vcc_acl_emit(const struct tokenlist *tl, const char *acln, int anon)
const char *pfx)
{ {
struct acl_e *ae; struct acl_e *ae;
int depth, l, m, i; int depth, l, m, i;
...@@ -333,7 +332,7 @@ vcc_acl_bot(const struct tokenlist *tl, const char *acln, int silent, ...@@ -333,7 +332,7 @@ vcc_acl_bot(const struct tokenlist *tl, const char *acln, int silent,
Fh(tl, 0, "\nstatic int\n"); Fh(tl, 0, "\nstatic int\n");
Fh(tl, 0, "match_acl_%s_%s(const struct sess *sp, const void *p)\n", Fh(tl, 0, "match_acl_%s_%s(const struct sess *sp, const void *p)\n",
pfx, acln); anon ? "anon" : "named", acln);
Fh(tl, 0, "{\n"); Fh(tl, 0, "{\n");
Fh(tl, 0, "\tconst unsigned char *a;\n"); Fh(tl, 0, "\tconst unsigned char *a;\n");
assert(sizeof (unsigned char) == 1); assert(sizeof (unsigned char) == 1);
...@@ -375,30 +374,31 @@ vcc_acl_bot(const struct tokenlist *tl, const char *acln, int silent, ...@@ -375,30 +374,31 @@ vcc_acl_bot(const struct tokenlist *tl, const char *acln, int silent,
/* Back down, if necessary */ /* Back down, if necessary */
oc = ""; oc = "";
while (l <= depth) { while (l <= depth) {
Fh(tl, 0, "\t%*s}\n", Fh(tl, 0, "\t%*s}\n", -depth, "");
-depth, "");
depth--; depth--;
oc = "else "; oc = "else ";
} }
m = ae->mask; m = ae->mask;
m -= l * 8; m -= l * 8;
/* Do whole byte compares */
for (i = l; m >= 8; m -= 8, i++) { for (i = l; m >= 8; m -= 8, i++) {
if (i == 0) { if (i == 0)
Fh(tl, 0, "\t%*s%sif (fam == %d) {\n", Fh(tl, 0, "\t%*s%sif (fam == %d) {\n",
-i, "", oc, ae->data[i]); -i, "", oc, ae->data[i]);
} else { else
Fh(tl, 0, "\t%*s%sif (a[%d] == %d) {\n", Fh(tl, 0, "\t%*s%sif (a[%d] == %d) {\n",
-i, "", oc, i - 1, ae->data[i]); -i, "", oc, i - 1, ae->data[i]);
}
at[i] = ae->data[i]; at[i] = ae->data[i];
depth = i; depth = i;
oc = ""; oc = "";
} }
if (m > 0) { if (m > 0) {
/* Do fractional byte compares */
Fh(tl, 0, "\t%*s%sif ((a[%d] & 0x%x) == %d) {\n", Fh(tl, 0, "\t%*s%sif ((a[%d] & 0x%x) == %d) {\n",
-i, "", -i, "", oc, i - 1, (0xff00 >> m) & 0xff,
oc,
i - 1, (0xff00 >> m) & 0xff,
ae->data[i] & ((0xff00 >> m) & 0xff)); ae->data[i] & ((0xff00 >> m) & 0xff));
at[i] = 256; at[i] = 256;
depth = i; depth = i;
...@@ -407,11 +407,9 @@ vcc_acl_bot(const struct tokenlist *tl, const char *acln, int silent, ...@@ -407,11 +407,9 @@ vcc_acl_bot(const struct tokenlist *tl, const char *acln, int silent,
i = (ae->mask + 7) / 8; i = (ae->mask + 7) / 8;
if (!silent) { if (!anon) {
Fh(tl, 0, "\t%*sVRT_acl_log(sp, \"%sMATCH %s \" ", Fh(tl, 0, "\t%*sVRT_acl_log(sp, \"%sMATCH %s \" ",
-i, "", -i, "", ae->not ? "NEG_" : "", acln,
ae->not ? "NEG_" : "",
acln,
PF(ae->t_addr)); PF(ae->t_addr));
EncToken(tl->fh, ae->t_addr); EncToken(tl->fh, ae->t_addr);
if (ae->t_mask != NULL) if (ae->t_mask != NULL)
...@@ -422,9 +420,12 @@ vcc_acl_bot(const struct tokenlist *tl, const char *acln, int silent, ...@@ -422,9 +420,12 @@ vcc_acl_bot(const struct tokenlist *tl, const char *acln, int silent,
Fh(tl, 0, "\t%*sreturn (%d);\n", -i, "", ae->not ? 0 : 1); Fh(tl, 0, "\t%*sreturn (%d);\n", -i, "", ae->not ? 0 : 1);
} }
/* Unwind */
for (; 0 <= depth; depth--) for (; 0 <= depth; depth--)
Fh(tl, 0, "\t%*.*s}\n", depth, depth, ""); Fh(tl, 0, "\t%*.*s}\n", depth, depth, "");
if (!silent)
/* Deny by default */
if (!anon)
Fh(tl, 0, "\tVRT_acl_log(sp, \"NO_MATCH %s\");\n", acln); Fh(tl, 0, "\tVRT_acl_log(sp, \"NO_MATCH %s\");\n", acln);
Fh(tl, 0, "\treturn (0);\n}\n"); Fh(tl, 0, "\treturn (0);\n}\n");
} }
...@@ -453,7 +454,7 @@ vcc_Cond_Ip(const struct var *vp, struct tokenlist *tl) ...@@ -453,7 +454,7 @@ vcc_Cond_Ip(const struct var *vp, struct tokenlist *tl)
asprintf(&acln, "%u", tl->cnt); asprintf(&acln, "%u", tl->cnt);
assert(acln != NULL); assert(acln != NULL);
vcc_acl_entry(tl); vcc_acl_entry(tl);
vcc_acl_bot(tl, acln, 1, "anon"); vcc_acl_emit(tl, acln, 1);
Fb(tl, 1, "%smatch_acl_anon_%s(sp, %s)\n", Fb(tl, 1, "%smatch_acl_anon_%s(sp, %s)\n",
(tcond == T_NEQ ? "!" : ""), acln, vp->rname); (tcond == T_NEQ ? "!" : ""), acln, vp->rname);
free(acln); free(acln);
...@@ -497,7 +498,7 @@ vcc_Acl(struct tokenlist *tl) ...@@ -497,7 +498,7 @@ vcc_Acl(struct tokenlist *tl)
ExpectErr(tl, '}'); ExpectErr(tl, '}');
vcc_NextToken(tl); vcc_NextToken(tl);
vcc_acl_bot(tl, acln, 0, "named"); vcc_acl_emit(tl, acln, 0);
free(acln); free(acln);
} }
...@@ -223,8 +223,8 @@ vcl_output_lang_h(struct vsb *sb) ...@@ -223,8 +223,8 @@ vcl_output_lang_h(struct vsb *sb)
vsb_cat(sb, " * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWI"); vsb_cat(sb, " * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWI");
vsb_cat(sb, "SE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFT"); vsb_cat(sb, "SE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFT");
vsb_cat(sb, "WARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n"); vsb_cat(sb, "WARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n");
vsb_cat(sb, " * SUCH DAMAGE.\n *\n * $Id: vrt.h 3609 2009-02-05 11:"); vsb_cat(sb, " * SUCH DAMAGE.\n *\n * $Id: vrt.h 3616 2009-02-05 11:");
vsb_cat(sb, "14:28Z tfheen $\n *\n * Runtime support for compiled V"); vsb_cat(sb, "43:20Z tfheen $\n *\n * Runtime support for compiled V");
vsb_cat(sb, "CL programs.\n *\n * XXX: When this file is changed, l"); vsb_cat(sb, "CL programs.\n *\n * XXX: When this file is changed, l");
vsb_cat(sb, "ib/libvcl/vcc_gen_fixed_token.tcl\n"); vsb_cat(sb, "ib/libvcl/vcc_gen_fixed_token.tcl\n");
vsb_cat(sb, " * XXX: *MUST* be rerun.\n */\n"); vsb_cat(sb, " * XXX: *MUST* be rerun.\n */\n");
...@@ -311,7 +311,7 @@ vcl_output_lang_h(struct vsb *sb) ...@@ -311,7 +311,7 @@ vcl_output_lang_h(struct vsb *sb)
/* ../../include/vrt_obj.h */ /* ../../include/vrt_obj.h */
vsb_cat(sb, "/*\n * $Id: vrt_obj.h 3169 2008-09-08 09:49:01Z tfheen"); vsb_cat(sb, "/*\n * $Id: vrt_obj.h 3616 2009-02-05 11:43:20Z tfheen");
vsb_cat(sb, " $\n *\n * NB: This file is machine generated, DO NOT"); vsb_cat(sb, " $\n *\n * NB: This file is machine generated, DO NOT");
vsb_cat(sb, " EDIT!\n *\n * Edit vcc_gen_obj.tcl instead\n"); vsb_cat(sb, " EDIT!\n *\n * Edit vcc_gen_obj.tcl instead\n");
vsb_cat(sb, " */\n\nstruct sockaddr * VRT_r_client_ip(const struct "); vsb_cat(sb, " */\n\nstruct sockaddr * VRT_r_client_ip(const struct ");
......
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