summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sbin/pfctl/parse.y31
-rw-r--r--sys/net/pf.c80
-rw-r--r--sys/net/pfvar.h3
3 files changed, 74 insertions, 40 deletions
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
index 11e329ae607..d7d2b4ae5b2 100644
--- a/sbin/pfctl/parse.y
+++ b/sbin/pfctl/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.505 2006/10/06 11:05:30 mcbride Exp $ */
+/* $OpenBSD: parse.y,v 1.506 2006/10/11 08:42:31 mcbride Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
@@ -445,7 +445,7 @@ typedef struct {
%type <v.string> label string tag
%type <v.keep_state> keep
%type <v.state_opt> state_opt_spec state_opt_list state_opt_item
-%type <v.logquick> logquick
+%type <v.logquick> logquick quick
%type <v.interface> antispoof_ifspc antispoof_iflst antispoof_if
%type <v.qassign> qname
%type <v.queue> qassign qassign_list qassign_item
@@ -608,7 +608,7 @@ varset : STRING '=' string {
}
;
-anchorrule : ANCHOR string dir interface af proto fromto filter_opts {
+anchorrule : ANCHOR string dir quick interface af proto fromto filter_opts {
struct pf_rule r;
if (check_rulestate(PFCTL_STATE_FILTER)) {
@@ -618,24 +618,25 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts {
memset(&r, 0, sizeof(r));
r.direction = $3;
- r.af = $5;
- r.prob = $8.prob;
- r.rtableid = $8.rtableid;
+ r.quick = $4.quick;
+ r.af = $6;
+ r.prob = $9.prob;
+ r.rtableid = $9.rtableid;
- if ($8.match_tag)
- if (strlcpy(r.match_tagname, $8.match_tag,
+ if ($9.match_tag)
+ if (strlcpy(r.match_tagname, $9.match_tag,
PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
yyerror("tag too long, max %u chars",
PF_TAG_NAME_SIZE - 1);
YYERROR;
}
- r.match_tag_not = $8.match_tag_not;
+ r.match_tag_not = $9.match_tag_not;
- decide_address_family($7.src.host, &r.af);
- decide_address_family($7.dst.host, &r.af);
+ decide_address_family($8.src.host, &r.af);
+ decide_address_family($8.dst.host, &r.af);
- expand_rule(&r, $4, NULL, $6, $7.src_os,
- $7.src.host, $7.src.port, $7.dst.host, $7.dst.port,
+ expand_rule(&r, $5, NULL, $7, $8.src_os,
+ $8.src.host, $8.src.port, $8.dst.host, $8.dst.port,
0, 0, 0, $2);
free($2);
}
@@ -2101,6 +2102,10 @@ dir : /* empty */ { $$ = 0; }
| OUT { $$ = PF_OUT; }
;
+quick : /* empty */ { $$.quick = 0; }
+ | QUICK { $$.quick = 1; }
+ ;
+
logquick : /* empty */ { $$.log = 0; $$.quick = 0; }
| log { $$.log = $1; $$.quick = 0; }
| QUICK { $$.log = 0; $$.quick = 1; }
diff --git a/sys/net/pf.c b/sys/net/pf.c
index 085e81458f5..5b4de807b95 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.515 2006/09/18 09:53:05 markus Exp $ */
+/* $OpenBSD: pf.c,v 1.516 2006/10/11 08:42:31 mcbride Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -186,6 +186,9 @@ int pf_test_state_other(struct pf_state **, int,
struct pfi_kif *, struct pf_pdesc *);
int pf_match_tag(struct mbuf *, struct pf_rule *,
struct pf_mtag *, int *);
+int pf_step_out_of_anchor(int *, struct pf_ruleset **,
+ int, struct pf_rule **, struct pf_rule **,
+ int *);
void pf_hash(struct pf_addr *, struct pf_addr *,
struct pf_poolhashkey *, sa_family_t);
int pf_map_addr(u_int8_t, struct pf_rule *,
@@ -1912,10 +1915,13 @@ pf_tag_packet(struct mbuf *m, struct pf_mtag *pf_mtag, int tag, int rtableid)
static void
pf_step_into_anchor(int *depth, struct pf_ruleset **rs, int n,
- struct pf_rule **r, struct pf_rule **a)
+ struct pf_rule **r, struct pf_rule **a, int *match)
{
struct pf_anchor_stackframe *f;
+ (*r)->anchor->match = 0;
+ if (match)
+ *match = 0;
if (*depth >= sizeof(pf_anchor_stack) /
sizeof(pf_anchor_stack[0])) {
printf("pf_step_into_anchor: stack overflow\n");
@@ -1942,17 +1948,23 @@ pf_step_into_anchor(int *depth, struct pf_ruleset **rs, int n,
*r = TAILQ_FIRST((*rs)->rules[n].active.ptr);
}
-static void
+int
pf_step_out_of_anchor(int *depth, struct pf_ruleset **rs, int n,
- struct pf_rule **r, struct pf_rule **a)
+ struct pf_rule **r, struct pf_rule **a, int *match)
{
struct pf_anchor_stackframe *f;
+ int quick = 0;
do {
if (*depth <= 0)
break;
f = pf_anchor_stack + *depth - 1;
if (f->parent != NULL && f->child != NULL) {
+ if (f->child->match ||
+ (match != NULL && *match)) {
+ f->r->anchor->match = 1;
+ *match = 0;
+ }
f->child = RB_NEXT(pf_anchor_node, f->parent, f->child);
if (f->child != NULL) {
*rs = &f->child->ruleset;
@@ -1967,8 +1979,12 @@ pf_step_out_of_anchor(int *depth, struct pf_ruleset **rs, int n,
if (*depth == 0 && a != NULL)
*a = NULL;
*rs = f->rs;
+ if (f->r->anchor->match || (match != NULL && *match))
+ quick = f->r->quick;
*r = TAILQ_NEXT(f->r, entries);
} while (*r == NULL);
+
+ return (quick);
}
#ifdef INET6
@@ -2423,10 +2439,12 @@ pf_match_translation(struct pf_pdesc *pd, struct mbuf *m, int off,
if (r->anchor == NULL) {
rm = r;
} else
- pf_step_into_anchor(&asd, &ruleset, rs_num, &r, NULL);
+ pf_step_into_anchor(&asd, &ruleset, rs_num,
+ &r, NULL, NULL);
}
if (r == NULL)
- pf_step_out_of_anchor(&asd, &ruleset, rs_num, &r, NULL);
+ pf_step_out_of_anchor(&asd, &ruleset, rs_num, &r,
+ NULL, NULL);
}
if (pf_tag_packet(m, pd->pf_mtag, tag, rtableid))
return (NULL);
@@ -2837,6 +2855,7 @@ pf_test_tcp(struct pf_rule **rm, struct pf_state **sm, int direction,
int tag = -1, rtableid = -1;
u_int16_t mss = tcp_mssdflt;
int asd = 0;
+ int match = 0;
if (pf_check_congestion(ifq)) {
REASON_SET(&reason, PFRES_CONGEST);
@@ -2926,6 +2945,7 @@ pf_test_tcp(struct pf_rule **rm, struct pf_state **sm, int direction,
if (r->rtableid >= 0)
rtableid = r->rtableid;
if (r->anchor == NULL) {
+ match = 1;
*rm = r;
*am = a;
*rsm = ruleset;
@@ -2934,11 +2954,11 @@ pf_test_tcp(struct pf_rule **rm, struct pf_state **sm, int direction,
r = TAILQ_NEXT(r, entries);
} else
pf_step_into_anchor(&asd, &ruleset,
- PF_RULESET_FILTER, &r, &a);
+ PF_RULESET_FILTER, &r, &a, &match);
}
- if (r == NULL)
- pf_step_out_of_anchor(&asd, &ruleset,
- PF_RULESET_FILTER, &r, &a);
+ if (r == NULL && pf_step_out_of_anchor(&asd, &ruleset,
+ PF_RULESET_FILTER, &r, &a, &match))
+ break;
}
r = *rm;
a = *am;
@@ -3215,6 +3235,7 @@ pf_test_udp(struct pf_rule **rm, struct pf_state **sm, int direction,
int rewrite = 0;
int tag = -1, rtableid = -1;
int asd = 0;
+ int match = 0;
if (pf_check_congestion(ifq)) {
REASON_SET(&reason, PFRES_CONGEST);
@@ -3301,6 +3322,7 @@ pf_test_udp(struct pf_rule **rm, struct pf_state **sm, int direction,
if (r->rtableid >= 0)
rtableid = r->rtableid;
if (r->anchor == NULL) {
+ match = 1;
*rm = r;
*am = a;
*rsm = ruleset;
@@ -3309,11 +3331,11 @@ pf_test_udp(struct pf_rule **rm, struct pf_state **sm, int direction,
r = TAILQ_NEXT(r, entries);
} else
pf_step_into_anchor(&asd, &ruleset,
- PF_RULESET_FILTER, &r, &a);
+ PF_RULESET_FILTER, &r, &a, &match);
}
- if (r == NULL)
- pf_step_out_of_anchor(&asd, &ruleset,
- PF_RULESET_FILTER, &r, &a);
+ if (r == NULL && pf_step_out_of_anchor(&asd, &ruleset,
+ PF_RULESET_FILTER, &r, &a, &match))
+ break;
}
r = *rm;
a = *am;
@@ -3498,6 +3520,7 @@ pf_test_icmp(struct pf_rule **rm, struct pf_state **sm, int direction,
int rewrite = 0;
#endif /* INET6 */
int asd = 0;
+ int match = 0;
if (pf_check_congestion(ifq)) {
REASON_SET(&reason, PFRES_CONGEST);
@@ -3630,6 +3653,7 @@ pf_test_icmp(struct pf_rule **rm, struct pf_state **sm, int direction,
if (r->rtableid >= 0)
rtableid = r->rtableid;
if (r->anchor == NULL) {
+ match = 1;
*rm = r;
*am = a;
*rsm = ruleset;
@@ -3638,11 +3662,11 @@ pf_test_icmp(struct pf_rule **rm, struct pf_state **sm, int direction,
r = TAILQ_NEXT(r, entries);
} else
pf_step_into_anchor(&asd, &ruleset,
- PF_RULESET_FILTER, &r, &a);
+ PF_RULESET_FILTER, &r, &a, &match);
}
- if (r == NULL)
- pf_step_out_of_anchor(&asd, &ruleset,
- PF_RULESET_FILTER, &r, &a);
+ if (r == NULL && pf_step_out_of_anchor(&asd, &ruleset,
+ PF_RULESET_FILTER, &r, &a, &match))
+ break;
}
r = *rm;
a = *am;
@@ -3801,6 +3825,7 @@ pf_test_other(struct pf_rule **rm, struct pf_state **sm, int direction,
u_short reason;
int tag = -1, rtableid = -1;
int asd = 0;
+ int match = 0;
if (pf_check_congestion(ifq)) {
REASON_SET(&reason, PFRES_CONGEST);
@@ -3887,6 +3912,7 @@ pf_test_other(struct pf_rule **rm, struct pf_state **sm, int direction,
if (r->rtableid >= 0)
rtableid = r->rtableid;
if (r->anchor == NULL) {
+ match = 1;
*rm = r;
*am = a;
*rsm = ruleset;
@@ -3895,11 +3921,11 @@ pf_test_other(struct pf_rule **rm, struct pf_state **sm, int direction,
r = TAILQ_NEXT(r, entries);
} else
pf_step_into_anchor(&asd, &ruleset,
- PF_RULESET_FILTER, &r, &a);
+ PF_RULESET_FILTER, &r, &a, &match);
}
- if (r == NULL)
- pf_step_out_of_anchor(&asd, &ruleset,
- PF_RULESET_FILTER, &r, &a);
+ if (r == NULL && pf_step_out_of_anchor(&asd, &ruleset,
+ PF_RULESET_FILTER, &r, &a, &match))
+ break;
}
r = *rm;
a = *am;
@@ -4068,6 +4094,7 @@ pf_test_fragment(struct pf_rule **rm, int direction, struct pfi_kif *kif,
u_short reason;
int tag = -1;
int asd = 0;
+ int match = 0;
r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr);
while (r != NULL) {
@@ -4098,6 +4125,7 @@ pf_test_fragment(struct pf_rule **rm, int direction, struct pfi_kif *kif,
r = TAILQ_NEXT(r, entries);
else {
if (r->anchor == NULL) {
+ match = 1;
*rm = r;
*am = a;
*rsm = ruleset;
@@ -4106,11 +4134,11 @@ pf_test_fragment(struct pf_rule **rm, int direction, struct pfi_kif *kif,
r = TAILQ_NEXT(r, entries);
} else
pf_step_into_anchor(&asd, &ruleset,
- PF_RULESET_FILTER, &r, &a);
+ PF_RULESET_FILTER, &r, &a, &match);
}
- if (r == NULL)
- pf_step_out_of_anchor(&asd, &ruleset,
- PF_RULESET_FILTER, &r, &a);
+ if (r == NULL && pf_step_out_of_anchor(&asd, &ruleset,
+ PF_RULESET_FILTER, &r, &a, &match))
+ break;
}
r = *rm;
a = *am;
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index 21eebdd3836..9ac1dfbbe25 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfvar.h,v 1.236 2006/07/06 13:25:40 henning Exp $ */
+/* $OpenBSD: pfvar.h,v 1.237 2006/10/11 08:42:31 mcbride Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -770,6 +770,7 @@ struct pf_anchor {
char path[MAXPATHLEN];
struct pf_ruleset ruleset;
int refcnt; /* anchor rules */
+ int match;
};
RB_PROTOTYPE(pf_anchor_global, pf_anchor, entry_global, pf_anchor_compare);
RB_PROTOTYPE(pf_anchor_node, pf_anchor, entry_node, pf_anchor_compare);