summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sbin/pfctl/parse.y205
-rw-r--r--sbin/pfctl/pfctl.c83
-rw-r--r--sbin/pfctl/pfctl_parser.c52
-rw-r--r--sbin/pfctl/pfctl_parser.h5
-rw-r--r--share/man/man5/pf.conf.515
-rw-r--r--sys/net/pf.c279
-rw-r--r--sys/net/pf_ioctl.c17
-rw-r--r--sys/net/pf_norm.c573
-rw-r--r--sys/net/pf_ruleset.c7
-rw-r--r--sys/net/pfvar.h77
10 files changed, 473 insertions, 840 deletions
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
index 9c627390fce..3c3b9a67c85 100644
--- a/sbin/pfctl/parse.y
+++ b/sbin/pfctl/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.555 2009/02/19 17:08:42 deraadt Exp $ */
+/* $OpenBSD: parse.y,v 1.556 2009/04/06 12:05:55 henning Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
@@ -108,7 +108,6 @@ int atoul(char *, u_long *);
enum {
PFCTL_STATE_NONE,
PFCTL_STATE_OPTION,
- PFCTL_STATE_SCRUB,
PFCTL_STATE_QUEUE,
PFCTL_STATE_NAT,
PFCTL_STATE_FILTER
@@ -205,11 +204,15 @@ struct node_qassign {
struct filter_opts {
int marker;
-#define FOM_FLAGS 0x01
-#define FOM_ICMP 0x02
-#define FOM_TOS 0x04
-#define FOM_KEEP 0x08
-#define FOM_SRCTRACK 0x10
+#define FOM_FLAGS 0x0001
+#define FOM_ICMP 0x0002
+#define FOM_TOS 0x0004
+#define FOM_KEEP 0x0008
+#define FOM_SRCTRACK 0x0010
+#define FOM_MINTTL 0x0020
+#define FOM_MAXMSS 0x0040
+#define FOM_SETTOS 0x0100
+#define FOM_SCRUB_TCP 0x0200
struct node_uid *uid;
struct node_gid *gid;
struct {
@@ -237,6 +240,13 @@ struct filter_opts {
struct node_host *addr;
u_int16_t port;
} divert;
+
+ /* scrub opts */
+ int nodf;
+ int minttl;
+ int settos;
+ int randomid;
+ int max_mss;
} filter_opts;
struct antispoof_opts {
@@ -246,20 +256,12 @@ struct antispoof_opts {
struct scrub_opts {
int marker;
-#define SOM_MINTTL 0x01
-#define SOM_MAXMSS 0x02
-#define SOM_FRAGCACHE 0x04
-#define SOM_SETTOS 0x08
int nodf;
int minttl;
int maxmss;
int settos;
- int fragcache;
int randomid;
int reassemble_tcp;
- char *match_tag;
- u_int8_t match_tag_not;
- u_int rtableid;
} scrub_opts;
struct queue_opts {
@@ -430,7 +432,7 @@ int parseport(char *, struct range *r, int);
%}
-%token PASS BLOCK SCRUB RETURN IN OS OUT LOG QUICK ON FROM TO FLAGS
+%token PASS BLOCK MATCH SCRUB RETURN IN OS OUT LOG QUICK ON FROM TO FLAGS
%token RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE
%token ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF
%token MINTTL ERROR ALLOWOPTS FASTROUTE FILENAME ROUTETO DUPTO REPLYTO NO LABEL
@@ -452,11 +454,11 @@ int parseport(char *, struct range *r, int);
%token <v.i> PORTBINARY
%type <v.interface> interface if_list if_item_not if_item
%type <v.number> number icmptype icmp6type uid gid
-%type <v.number> tos not yesno
+%type <v.number> tos not yesno optnodf
%type <v.probability> probability
-%type <v.i> no dir af fragcache optimizer
+%type <v.i> no dir af optimizer
%type <v.i> sourcetrack flush unaryop statelock
-%type <v.b> action nataction natpasslog scrubaction
+%type <v.b> action nataction natpasslog
%type <v.b> flags flag blockspec
%type <v.range> portplain portstar portrange
%type <v.hashkey> hashkey
@@ -504,7 +506,6 @@ ruleset : /* empty */
| ruleset include '\n'
| ruleset '\n'
| ruleset option '\n'
- | ruleset scrubrule '\n'
| ruleset natrule '\n'
| ruleset binatrule '\n'
| ruleset pfrule '\n'
@@ -560,7 +561,16 @@ optimizer : string {
}
;
-option : SET OPTIMIZATION STRING {
+optnodf : /* empty */ { $$ = 0; }
+ | NODF { $$ = 1; }
+ ;
+
+option : SET REASSEMBLE yesno optnodf {
+ if (check_rulestate(PFCTL_STATE_OPTION))
+ YYERROR;
+ pfctl_set_reassembly(pf, $3, $4);
+ }
+ | SET OPTIMIZATION STRING {
if (check_rulestate(PFCTL_STATE_OPTION)) {
free($3);
YYERROR;
@@ -1018,87 +1028,18 @@ loadrule : LOAD ANCHOR string FROM string {
free($5);
};
-scrubaction : no SCRUB {
- $$.b2 = $$.w = 0;
- if ($1)
- $$.b1 = PF_NOSCRUB;
- else
- $$.b1 = PF_SCRUB;
- }
- ;
-
-scrubrule : scrubaction dir logquick interface af proto fromto scrub_opts
- {
- struct pf_rule r;
-
- if (check_rulestate(PFCTL_STATE_SCRUB))
- YYERROR;
-
- memset(&r, 0, sizeof(r));
-
- r.action = $1.b1;
- r.direction = $2;
-
- r.log = $3.log;
- r.logif = $3.logif;
- if ($3.quick) {
- yyerror("scrub rules do not support 'quick'");
- YYERROR;
- }
-
- r.af = $5;
- if ($8.nodf)
- r.rule_flag |= PFRULE_NODF;
- if ($8.randomid)
- r.rule_flag |= PFRULE_RANDOMID;
- if ($8.reassemble_tcp) {
- if (r.direction != PF_INOUT) {
- yyerror("reassemble tcp rules can not "
- "specify direction");
- YYERROR;
- }
- r.rule_flag |= PFRULE_REASSEMBLE_TCP;
- }
- if ($8.minttl)
- r.min_ttl = $8.minttl;
- if ($8.maxmss)
- r.max_mss = $8.maxmss;
- if ($8.marker & SOM_SETTOS) {
- r.rule_flag |= PFRULE_SET_TOS;
- r.set_tos = $8.settos;
- }
- if ($8.fragcache)
- r.rule_flag |= $8.fragcache;
- if ($8.match_tag)
- if (strlcpy(r.match_tagname, $8.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.rtableid = $8.rtableid;
-
- expand_rule(&r, $4, NULL, $6, $7.src_os,
- $7.src.host, $7.src.port, $7.dst.host, $7.dst.port,
- NULL, NULL, NULL, "");
- }
- ;
-
scrub_opts : {
bzero(&scrub_opts, sizeof scrub_opts);
- scrub_opts.rtableid = -1;
}
scrub_opts_l
{ $$ = scrub_opts; }
| /* empty */ {
bzero(&scrub_opts, sizeof scrub_opts);
- scrub_opts.rtableid = -1;
$$ = scrub_opts;
}
;
-scrub_opts_l : scrub_opts_l scrub_opt
+scrub_opts_l : scrub_opts_l comma scrub_opt
| scrub_opt
;
@@ -1110,7 +1051,7 @@ scrub_opt : NODF {
scrub_opts.nodf = 1;
}
| MINTTL NUMBER {
- if (scrub_opts.marker & SOM_MINTTL) {
+ if (scrub_opts.marker & FOM_MINTTL) {
yyerror("min-ttl cannot be respecified");
YYERROR;
}
@@ -1118,11 +1059,11 @@ scrub_opt : NODF {
yyerror("illegal min-ttl value %d", $2);
YYERROR;
}
- scrub_opts.marker |= SOM_MINTTL;
+ scrub_opts.marker |= FOM_MINTTL;
scrub_opts.minttl = $2;
}
| MAXMSS NUMBER {
- if (scrub_opts.marker & SOM_MAXMSS) {
+ if (scrub_opts.marker & FOM_MAXMSS) {
yyerror("max-mss cannot be respecified");
YYERROR;
}
@@ -1130,25 +1071,17 @@ scrub_opt : NODF {
yyerror("illegal max-mss value %d", $2);
YYERROR;
}
- scrub_opts.marker |= SOM_MAXMSS;
+ scrub_opts.marker |= FOM_MAXMSS;
scrub_opts.maxmss = $2;
}
| SETTOS tos {
- if (scrub_opts.marker & SOM_SETTOS) {
+ if (scrub_opts.marker & FOM_SETTOS) {
yyerror("set-tos cannot be respecified");
YYERROR;
}
- scrub_opts.marker |= SOM_SETTOS;
+ scrub_opts.marker |= FOM_SETTOS;
scrub_opts.settos = $2;
}
- | fragcache {
- if (scrub_opts.marker & SOM_FRAGCACHE) {
- yyerror("fragcache cannot be respecified");
- YYERROR;
- }
- scrub_opts.marker |= SOM_FRAGCACHE;
- scrub_opts.fragcache = $1;
- }
| REASSEMBLE STRING {
if (strcasecmp($2, "tcp") != 0) {
yyerror("scrub reassemble supports only tcp, "
@@ -1170,22 +1103,6 @@ scrub_opt : NODF {
}
scrub_opts.randomid = 1;
}
- | RTABLE NUMBER {
- if ($2 < 0 || $2 > RT_TABLEID_MAX) {
- yyerror("invalid rtable id");
- YYERROR;
- }
- scrub_opts.rtableid = $2;
- }
- | not TAGGED string {
- scrub_opts.match_tag = $3;
- scrub_opts.match_tag_not = $1;
- }
- ;
-
-fragcache : FRAGMENT REASSEMBLE { $$ = 0; /* default */ }
- | FRAGMENT FRAGCROP { $$ = PFRULE_FRAGCROP; }
- | FRAGMENT FRAGDROP { $$ = PFRULE_FRAGDROP; }
;
antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts {
@@ -1872,6 +1789,21 @@ pfrule : action dir logquick interface route af proto fromto
r.prob = $9.prob;
r.rtableid = $9.rtableid;
+ if ($9.nodf)
+ r.scrub_flags |= PFSTATE_NODF;
+ if ($9.randomid)
+ r.scrub_flags |= PFSTATE_RANDOMID;
+ if ($9.minttl)
+ r.min_ttl = $9.minttl;
+ if ($9.max_mss)
+ r.max_mss = $9.max_mss;
+ if ($9.marker & FOM_SETTOS) {
+ r.scrub_flags |= PFSTATE_SETTOS;
+ r.set_tos = $9.settos;
+ }
+ if ($9.marker & FOM_SCRUB_TCP)
+ r.scrub_flags |= PFSTATE_SCRUB_TCP;
+
r.af = $6;
if ($9.tag)
if (strlcpy(r.tagname, $9.tag,
@@ -2377,6 +2309,16 @@ filter_opt : USER uids {
| DIVERTREPLY {
filter_opts.divert.port = 1; /* some random value */
}
+ | SCRUB '(' scrub_opts ')' {
+ filter_opts.nodf = $3.nodf;
+ filter_opts.minttl = $3.minttl;
+ filter_opts.settos = $3.settos;
+ filter_opts.randomid = $3.randomid;
+ filter_opts.max_mss = $3.maxmss;
+ if ($3.reassemble_tcp)
+ filter_opts.marker |= FOM_SCRUB_TCP;
+ filter_opts.marker |= $3.marker;
+ }
;
probability : STRING {
@@ -2402,6 +2344,7 @@ probability : STRING {
action : PASS { $$.b1 = PF_PASS; $$.b2 = $$.w = 0; }
+ | MATCH { $$.b1 = PF_MATCH; $$.b2 = $$.w = 0; }
| BLOCK blockspec { $$ = $2; $$.b1 = PF_DROP; }
;
@@ -4364,9 +4307,8 @@ rule_consistent(struct pf_rule *r, int anchor_call)
switch (r->action) {
case PF_PASS:
+ case PF_MATCH:
case PF_DROP:
- case PF_SCRUB:
- case PF_NOSCRUB:
problems = filter_consistent(r, anchor_call);
break;
case PF_NAT:
@@ -4434,8 +4376,8 @@ filter_consistent(struct pf_rule *r, int anchor_call)
yyerror("max-src-nodes requires 'source-track rule'");
problems++;
}
- if (r->action == PF_DROP && r->keep_state) {
- yyerror("keep state on block rules doesn't make sense");
+ if (r->action != PF_PASS && r->keep_state) {
+ yyerror("keep state is great, but only for pass rules");
problems++;
}
if (r->rule_flag & PFRULE_STATESLOPPY &&
@@ -4445,6 +4387,18 @@ filter_consistent(struct pf_rule *r, int anchor_call)
"synproxy state or modulate state");
problems++;
}
+ /* match rules rules */
+ if (r->action == PF_MATCH) {
+ if (r->divert.port) {
+ yyerror("divert is not supported on match rules");
+ problems++;
+ }
+ if (r->rt) {
+ yyerror("route-to, reply-to, dup-to and fastroute "
+ "must not be used on match rules");
+ problems++;
+ }
+ }
return (-problems);
}
@@ -5267,6 +5221,7 @@ lookup(char *s)
{ "load", LOAD},
{ "log", LOG},
{ "loginterface", LOGINTERFACE},
+ { "match", MATCH},
{ "max", MAXIMUM},
{ "max-mss", MAXMSS},
{ "max-src-conn", MAXSRCCONN},
diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
index 12f59517c7f..ff03a04d02d 100644
--- a/sbin/pfctl/pfctl.c
+++ b/sbin/pfctl/pfctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl.c,v 1.280 2009/02/23 06:58:30 deraadt Exp $ */
+/* $OpenBSD: pfctl.c,v 1.281 2009/04/06 12:05:55 henning Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -78,6 +78,7 @@ int pfctl_load_timeout(struct pfctl *, unsigned int, unsigned int);
int pfctl_load_debug(struct pfctl *, unsigned int);
int pfctl_load_logif(struct pfctl *, char *);
int pfctl_load_hostid(struct pfctl *, unsigned int);
+int pfctl_load_reassembly(struct pfctl *, u_int32_t);
int pfctl_get_pool(int, struct pf_pool *, u_int32_t, u_int32_t, int,
char *);
void pfctl_print_rule_counters(struct pf_rule *, int);
@@ -310,8 +311,7 @@ pfctl_clear_rules(int dev, int opts, char *anchorname)
memset(&t, 0, sizeof(t));
t.pfrb_type = PFRB_TRANS;
- if (pfctl_add_trans(&t, PF_RULESET_SCRUB, anchorname) ||
- pfctl_add_trans(&t, PF_RULESET_FILTER, anchorname) ||
+ if (pfctl_add_trans(&t, PF_RULESET_FILTER, anchorname) ||
pfctl_trans(dev, &t, DIOCXBEGIN, 0) ||
pfctl_trans(dev, &t, DIOCXCOMMIT, 0))
err(1, "pfctl_clear_rules");
@@ -835,47 +835,15 @@ pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format,
}
header++;
}
- pr.rule.action = PF_SCRUB;
- if (ioctl(dev, DIOCGETRULES, &pr)) {
- warn("DIOCGETRULES");
- goto error;
- }
if (opts & PF_OPT_SHOWALL) {
if (format == PFCTL_SHOW_RULES && (pr.nr > 0 || header))
pfctl_print_title("FILTER RULES:");
else if (format == PFCTL_SHOW_LABELS && labels)
pfctl_print_title("LABEL COUNTERS:");
}
- mnr = pr.nr;
if (opts & PF_OPT_CLRRULECTRS)
pr.action = PF_GET_CLR_CNTR;
- for (nr = 0; nr < mnr; ++nr) {
- pr.nr = nr;
- if (ioctl(dev, DIOCGETRULE, &pr)) {
- warn("DIOCGETRULE");
- goto error;
- }
-
- if (pfctl_get_pool(dev, &pr.rule.rpool,
- nr, pr.ticket, PF_SCRUB, path) != 0)
- goto error;
-
- switch (format) {
- case PFCTL_SHOW_LABELS:
- break;
- case PFCTL_SHOW_RULES:
- if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL))
- labels = 1;
- print_rule(&pr.rule, pr.anchor_call, rule_numbers);
- printf("\n");
- pfctl_print_rule_counters(&pr.rule, opts);
- break;
- case PFCTL_SHOW_NOTHING:
- break;
- }
- pfctl_clear_pool(&pr.rule.rpool);
- }
pr.rule.action = PF_PASS;
if (ioctl(dev, DIOCGETRULES, &pr)) {
warn("DIOCGETRULES");
@@ -1180,7 +1148,8 @@ pfctl_add_rule(struct pfctl *pf, struct pf_rule *r, const char *anchor_call)
struct pf_ruleset *rs;
char *p;
- rs_num = pf_get_ruleset_number(r->action);
+ rs_num = pf_get_ruleset_number(r->action == PF_MATCH ? PF_PASS :
+ r->action);
if (rs_num == PF_RULESET_MAX)
errx(1, "Invalid rule type %d", r->action);
@@ -1236,8 +1205,7 @@ pfctl_ruleset_trans(struct pfctl *pf, char *path, struct pf_anchor *a)
return (2);
}
if ((pf->loadopt & PFCTL_FLAG_FILTER) != 0) {
- if (pfctl_add_trans(pf->trans, PF_RULESET_SCRUB, path) ||
- pfctl_add_trans(pf->trans, PF_RULESET_FILTER, path))
+ if (pfctl_add_trans(pf->trans, PF_RULESET_FILTER, path))
return (3);
}
if (pf->loadopt & PFCTL_FLAG_TABLE)
@@ -1470,9 +1438,7 @@ pfctl_rules(int dev, char *filename, int opts, int optimize,
goto _error;
}
- if ((pf.loadopt & PFCTL_FLAG_FILTER &&
- (pfctl_load_ruleset(&pf, path, rs, PF_RULESET_SCRUB, 0))) ||
- (pf.loadopt & PFCTL_FLAG_NAT &&
+ if ((pf.loadopt & PFCTL_FLAG_NAT &&
(pfctl_load_ruleset(&pf, path, rs, PF_RULESET_NAT, 0) ||
pfctl_load_ruleset(&pf, path, rs, PF_RULESET_RDR, 0) ||
pfctl_load_ruleset(&pf, path, rs, PF_RULESET_BINAT, 0))) ||
@@ -1636,6 +1602,11 @@ pfctl_load_options(struct pfctl *pf)
if (pfctl_load_hostid(pf, pf->hostid))
error = 1;
+ /* load reassembly settings */
+ if (!(pf->opts & PF_OPT_MERGE) || pf->reass_set)
+ if (pfctl_load_reassembly(pf, pf->reassemble))
+ error = 1;
+
return (error);
}
@@ -1725,6 +1696,26 @@ pfctl_load_timeout(struct pfctl *pf, unsigned int timeout, unsigned int seconds)
}
int
+pfctl_set_reassembly(struct pfctl *pf, int on, int nodf)
+{
+ if ((loadopt & PFCTL_FLAG_OPTION) == 0)
+ return (0);
+
+ pf->reass_set = 1;
+ if (on) {
+ pf->reassemble = PF_REASS_ENABLED;
+ if (nodf)
+ pf->reassemble &= PF_REASS_NODF;
+ }
+
+ if (pf->opts & PF_OPT_VERBOSE)
+ printf("set reassemble %s %s\n", on ? "yes" : "no",
+ nodf ? "no-df" : "");
+
+ return (0);
+}
+
+int
pfctl_set_optimization(struct pfctl *pf, const char *opt)
{
const struct pf_hint *hint;
@@ -1823,6 +1814,16 @@ pfctl_load_hostid(struct pfctl *pf, u_int32_t hostid)
}
int
+pfctl_load_reassembly(struct pfctl *pf, u_int32_t reassembly)
+{
+ if (ioctl(dev, DIOCSETREASS, &reassembly)) {
+ warnx("DIOCSETREASS");
+ return (1);
+ }
+ return (0);
+}
+
+int
pfctl_set_debug(struct pfctl *pf, char *d)
{
u_int32_t level;
diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c
index 86c5f90ffeb..e31f83e92d1 100644
--- a/sbin/pfctl/pfctl_parser.c
+++ b/sbin/pfctl/pfctl_parser.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl_parser.c,v 1.241 2008/09/09 13:56:38 henning Exp $ */
+/* $OpenBSD: pfctl_parser.c,v 1.242 2009/04/06 12:05:55 henning Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -413,6 +413,7 @@ print_pool(struct pf_pool *pool, u_int16_t p1, u_int16_t p2,
print_addr(&pooladdr->addr, af, 0);
break;
case PF_PASS:
+ case PF_MATCH:
if (PF_AZERO(&pooladdr->addr.v.a.addr, af))
printf("%s", pooladdr->ifname);
else {
@@ -651,6 +652,7 @@ print_src_node(struct pf_src_node *sn, int opts)
printf(", rdr rule %u", sn->rule.nr);
break;
case PF_PASS:
+ case PF_MATCH:
if (sn->rule.nr != -1)
printf(", filter rule %u", sn->rule.nr);
break;
@@ -663,7 +665,8 @@ void
print_rule(struct pf_rule *r, const char *anchor_call, int verbose)
{
static const char *actiontypes[] = { "pass", "block", "scrub",
- "no scrub", "nat", "no nat", "binat", "no binat", "rdr", "no rdr" };
+ "no scrub", "nat", "no nat", "binat", "no binat", "rdr", "no rdr",
+ "", "", "match"};
static const char *anchortypes[] = { "anchor", "anchor", "anchor",
"anchor", "nat-anchor", "nat-anchor", "binat-anchor",
"binat-anchor", "rdr-anchor", "rdr-anchor" };
@@ -671,7 +674,7 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose)
if (verbose)
printf("@%d ", r->nr);
- if (r->action > PF_NORDR)
+ if (r->action > PF_MATCH)
printf("action(%d)", r->action);
else if (anchor_call[0]) {
if (anchor_call[0] == '_') {
@@ -799,7 +802,7 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose)
print_flags(r->flags);
printf("/");
print_flags(r->flagset);
- } else if (r->action == PF_PASS &&
+ } else if ((r->action == PF_PASS || r->action == PF_MATCH) &&
(!r->proto || r->proto == IPPROTO_TCP) &&
!(r->rule_flag & PFRULE_FRAGMENT) &&
!anchor_call[0] && r->keep_state)
@@ -957,31 +960,26 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose)
}
printf(")");
}
- if (r->rule_flag & PFRULE_FRAGMENT)
- printf(" fragment");
- if (r->rule_flag & PFRULE_NODF)
- printf(" no-df");
- if (r->rule_flag & PFRULE_RANDOMID)
- printf(" random-id");
- if (r->min_ttl)
- printf(" min-ttl %d", r->min_ttl);
- if (r->max_mss)
- printf(" max-mss %d", r->max_mss);
- if (r->rule_flag & PFRULE_SET_TOS)
- printf(" set-tos 0x%2.2x", r->set_tos);
- if (r->allow_opts)
- printf(" allow-opts");
- if (r->action == PF_SCRUB) {
- if (r->rule_flag & PFRULE_REASSEMBLE_TCP)
- printf(" reassemble tcp");
- if (r->rule_flag & PFRULE_FRAGDROP)
- printf(" fragment drop-ovl");
- else if (r->rule_flag & PFRULE_FRAGCROP)
- printf(" fragment crop");
- else
- printf(" fragment reassemble");
+ if (r->scrub_flags & PFSTATE_NODF || r->min_ttl || r->max_mss) {
+ printf(" scrub(");
+ if (r->scrub_flags & PFSTATE_NODF)
+ printf(" no-df");
+ if (r->scrub_flags & PFSTATE_RANDOMID)
+ printf(" random-id");
+ if (r->min_ttl)
+ printf(" min-ttl %d", r->min_ttl);
+ if (r->scrub_flags & PFSTATE_SETTOS)
+ printf(" set-tos 0x%2.2x", r->set_tos);
+ if (r->scrub_flags & PFSTATE_SCRUB_TCP)
+ printf(" reassemble tcp");
+ if (r->max_mss)
+ printf(" max-mss %d", r->max_mss);
+ printf(")");
}
+
+ if (r->allow_opts)
+ printf(" allow-opts");
if (r->label[0])
printf(" label \"%s\"", r->label);
if (r->qname[0] && r->pqname[0])
diff --git a/sbin/pfctl/pfctl_parser.h b/sbin/pfctl/pfctl_parser.h
index 97b0325ddc7..758c576b4c4 100644
--- a/sbin/pfctl/pfctl_parser.h
+++ b/sbin/pfctl/pfctl_parser.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl_parser.h,v 1.87 2007/10/13 16:35:18 deraadt Exp $ */
+/* $OpenBSD: pfctl_parser.h,v 1.88 2009/04/06 12:05:55 henning Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -91,6 +91,7 @@ struct pfctl {
u_int32_t limit[PF_LIMIT_MAX];
u_int32_t debug;
u_int32_t hostid;
+ u_int32_t reassemble;
char *ifname;
u_int8_t timeout_set[PFTM_MAX];
@@ -98,6 +99,7 @@ struct pfctl {
u_int8_t debug_set;
u_int8_t hostid_set;
u_int8_t ifname_set;
+ u_int8_t reass_set;
};
struct node_if {
@@ -197,6 +199,7 @@ void pfctl_move_pool(struct pf_pool *, struct pf_pool *);
void pfctl_clear_pool(struct pf_pool *);
int pfctl_set_timeout(struct pfctl *, const char *, int, int);
+int pfctl_set_reassembly(struct pfctl *, int, int);
int pfctl_set_optimization(struct pfctl *, const char *);
int pfctl_set_limit(struct pfctl *, const char *, unsigned int);
int pfctl_set_logif(struct pfctl *, char *);
diff --git a/share/man/man5/pf.conf.5 b/share/man/man5/pf.conf.5
index 2514ecc166a..330dc609314 100644
--- a/share/man/man5/pf.conf.5
+++ b/share/man/man5/pf.conf.5
@@ -1,4 +1,4 @@
-.\" $OpenBSD: pf.conf.5,v 1.406 2009/01/31 19:37:12 sobrado Exp $
+.\" $OpenBSD: pf.conf.5,v 1.407 2009/04/06 12:05:55 henning Exp $
.\"
.\" Copyright (c) 2002, Daniel Hartmeier
.\" All rights reserved.
@@ -27,7 +27,7 @@
.\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd $Mdocdate: January 31 2009 $
+.Dd $Mdocdate: April 6 2009 $
.Dt PF.CONF 5
.Os
.Sh NAME
@@ -1291,6 +1291,15 @@ The packet is passed;
state is created unless the
.Ar no state
option is specified.
+.It Ar match
+Action is unaltered, the previously matched rule's action still matters.
+Match rules apply queue and rtable assignments for every matched packet,
+subsequent matching pass or match rules can overwrite the assignment,
+if they don't specify a queue or an rtable, respectively, the previously
+set value remains.
+Additionally, match rules can contain log statements; the is logging done
+for each and every matching match rule, so it is possible to log a single
+packet multiple times.
.El
.Pp
By default
@@ -2913,7 +2922,7 @@ queueopts = [ "bandwidth" bandwidth-spec ] |
schedulers = ( cbq-def | priq-def | hfsc-def )
bandwidth-spec = "number" ( "b" | "Kb" | "Mb" | "Gb" | "%" )
-action = "pass" | "block" [ return ] | [ "no" ] "scrub"
+action = "pass" | "match" | "block" [ return ] | [ "no" ] "scrub"
return = "drop" | "return" | "return-rst" [ "( ttl" number ")" ] |
"return-icmp" [ "(" icmpcode [ [ "," ] icmp6code ] ")" ] |
"return-icmp6" [ "(" icmp6code ")" ]
diff --git a/sys/net/pf.c b/sys/net/pf.c
index 67e0445ef95..81c3ca3eab1 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.639 2009/03/15 19:40:41 miod Exp $ */
+/* $OpenBSD: pf.c,v 1.640 2009/04/06 12:05:55 henning Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -127,7 +127,7 @@ struct pf_anchor_stackframe {
struct pool pf_src_tree_pl, pf_rule_pl, pf_pooladdr_pl;
struct pool pf_state_pl, pf_state_key_pl, pf_state_item_pl;
-struct pool pf_altq_pl;
+struct pool pf_altq_pl, pf_rule_item_pl;
void pf_init_threshold(struct pf_threshold *, u_int32_t,
u_int32_t);
@@ -153,12 +153,15 @@ void pf_send_tcp(const struct pf_rule *, sa_family_t,
const struct pf_addr *, const struct pf_addr *,
u_int16_t, u_int16_t, u_int32_t, u_int32_t,
u_int8_t, u_int16_t, u_int16_t, u_int8_t, int,
- u_int16_t, struct ether_header *, struct ifnet *);
+ u_int16_t, struct ether_header *, struct ifnet *,
+ u_int);
void pf_send_icmp(struct mbuf *, u_int8_t, u_int8_t,
- sa_family_t, struct pf_rule *);
+ sa_family_t, struct pf_rule *, u_int);
void pf_detach_state(struct pf_state *);
void pf_state_key_detach(struct pf_state *, int);
u_int32_t pf_tcp_iss(struct pf_pdesc *);
+void pf_rule_to_actions(struct pf_rule *,
+ struct pf_rule_actions *);
int pf_test_rule(struct pf_rule **, struct pf_state **,
int, struct pfi_kif *, struct mbuf *, int,
void *, struct pf_pdesc *, struct pf_rule **,
@@ -170,7 +173,8 @@ static __inline int pf_create_state(struct pf_rule *, struct pf_rule *,
struct pf_state_key *, struct mbuf *, int,
u_int16_t, u_int16_t, int *, struct pfi_kif *,
struct pf_state **, int, u_int16_t, u_int16_t,
- int);
+ int, struct pf_rule_slist *,
+ struct pf_rule_actions *);
int pf_test_fragment(struct pf_rule **, int,
struct pfi_kif *, struct mbuf *, void *,
struct pf_pdesc *, struct pf_rule **,
@@ -258,27 +262,35 @@ enum { PF_ICMP_MULTI_NONE, PF_ICMP_MULTI_SOLICITED, PF_ICMP_MULTI_LINK };
#define BOUND_IFACE(r, k) \
((r)->rule_flag & PFRULE_IFBOUND) ? (k) : pfi_all
-#define STATE_INC_COUNTERS(s) \
- do { \
- s->rule.ptr->states_cur++; \
- s->rule.ptr->states_tot++; \
- if (s->anchor.ptr != NULL) { \
- s->anchor.ptr->states_cur++; \
- s->anchor.ptr->states_tot++; \
- } \
- if (s->nat_rule.ptr != NULL) { \
- s->nat_rule.ptr->states_cur++; \
- s->nat_rule.ptr->states_tot++; \
- } \
+#define STATE_INC_COUNTERS(s) \
+ do { \
+ struct pf_rule_item *mrm; \
+ s->rule.ptr->states_cur++; \
+ s->rule.ptr->states_tot++; \
+ if (s->anchor.ptr != NULL) { \
+ s->anchor.ptr->states_cur++; \
+ s->anchor.ptr->states_tot++; \
+ } \
+ if (s->nat_rule.ptr != NULL) { \
+ s->nat_rule.ptr->states_cur++; \
+ s->nat_rule.ptr->states_tot++; \
+ } \
+ SLIST_FOREACH(mrm, &s->match_rules, entry) { \
+ mrm->r->states_cur++; \
+ mrm->r->states_tot++; \
+ } \
} while (0)
-#define STATE_DEC_COUNTERS(s) \
- do { \
- if (s->nat_rule.ptr != NULL) \
- s->nat_rule.ptr->states_cur--; \
- if (s->anchor.ptr != NULL) \
- s->anchor.ptr->states_cur--; \
- s->rule.ptr->states_cur--; \
+#define STATE_DEC_COUNTERS(s) \
+ do { \
+ struct pf_rule_item *mrm; \
+ if (s->nat_rule.ptr != NULL) \
+ s->nat_rule.ptr->states_cur--; \
+ if (s->anchor.ptr != NULL) \
+ s->anchor.ptr->states_cur--; \
+ s->rule.ptr->states_cur--; \
+ SLIST_FOREACH(mrm, &s->match_rules, entry) \
+ mrm->r->states_cur--; \
} while (0)
static __inline int pf_src_compare(struct pf_src_node *, struct pf_src_node *);
@@ -1091,7 +1103,8 @@ pf_unlink_state(struct pf_state *cur)
cur->key[PF_SK_WIRE]->port[1],
cur->key[PF_SK_WIRE]->port[0],
cur->src.seqhi, cur->src.seqlo + 1,
- TH_RST|TH_ACK, 0, 0, 0, 1, cur->tag, NULL, NULL);
+ TH_RST|TH_ACK, 0, 0, 0, 1, cur->tag, NULL, NULL,
+ cur->rtableid);
}
RB_REMOVE(pf_state_tree_id, &tree_id, cur);
#if NPFLOW > 0
@@ -1111,6 +1124,8 @@ pf_unlink_state(struct pf_state *cur)
void
pf_free_state(struct pf_state *cur)
{
+ struct pf_rule_item *ri;
+
splsoftassert(IPL_SOFTNET);
#if NPFSYNC > 0
@@ -1128,6 +1143,13 @@ pf_free_state(struct pf_state *cur)
if (cur->anchor.ptr != NULL)
if (--cur->anchor.ptr->states_cur <= 0)
pf_rm_rule(NULL, cur->anchor.ptr);
+ while ((ri = SLIST_FIRST(&cur->match_rules))) {
+ SLIST_REMOVE_HEAD(&cur->match_rules, entry);
+ if (--ri->r->states_cur <= 0 &&
+ ri->r->src_nodes <= 0)
+ pf_rm_rule(NULL, ri->r);
+ pool_put(&pf_rule_item_pl, ri);
+ }
pf_normalize_tcp_cleanup(cur);
pfi_kif_unref(cur->kif, PFI_KIF_REF_STATE);
TAILQ_REMOVE(&state_list, cur, entry_list);
@@ -1856,7 +1878,7 @@ pf_send_tcp(const struct pf_rule *r, sa_family_t af,
const struct pf_addr *saddr, const struct pf_addr *daddr,
u_int16_t sport, u_int16_t dport, u_int32_t seq, u_int32_t ack,
u_int8_t flags, u_int16_t win, u_int16_t mss, u_int8_t ttl, int tag,
- u_int16_t rtag, struct ether_header *eh, struct ifnet *ifp)
+ u_int16_t rtag, struct ether_header *eh, struct ifnet *ifp, u_int rtableid)
{
struct mbuf *m;
int len, tlen;
@@ -1895,8 +1917,8 @@ pf_send_tcp(const struct pf_rule *r, sa_family_t af,
m->m_pkthdr.pf.flags |= PF_TAG_GENERATED;
m->m_pkthdr.pf.tag = rtag;
- if (r != NULL && r->rtableid >= 0)
- m->m_pkthdr.pf.rtableid = r->rtableid;
+ if (rtableid >= 0)
+ m->m_pkthdr.pf.rtableid = rtableid;
#ifdef ALTQ
if (r != NULL && r->qid) {
@@ -2010,7 +2032,7 @@ pf_send_tcp(const struct pf_rule *r, sa_family_t af,
void
pf_send_icmp(struct mbuf *m, u_int8_t type, u_int8_t code, sa_family_t af,
- struct pf_rule *r)
+ struct pf_rule *r, u_int rtableid)
{
struct mbuf *m0;
@@ -2019,8 +2041,8 @@ pf_send_icmp(struct mbuf *m, u_int8_t type, u_int8_t code, sa_family_t af,
m0->m_pkthdr.pf.flags |= PF_TAG_GENERATED;
- if (r->rtableid >= 0)
- m0->m_pkthdr.pf.rtableid = r->rtableid;
+ if (rtableid >= 0)
+ m0->m_pkthdr.pf.rtableid = rtableid;
#ifdef ALTQ
if (r->qid) {
@@ -2595,24 +2617,47 @@ pf_tcp_iss(struct pf_pdesc *pd)
return (digest[0] + tcp_iss + pf_tcp_iss_off);
}
+void
+pf_rule_to_actions(struct pf_rule *r, struct pf_rule_actions *a)
+{
+ if (r->qid)
+ a->qid = r->qid;
+ if (r->pqid)
+ a->pqid = r->pqid;
+ if (r->rtableid >= 0)
+ a->rtableid = r->rtableid;
+ a->log |= r->log;
+ if (r->scrub_flags & PFSTATE_SETTOS)
+ a->set_tos = r->set_tos;
+ if (r->min_ttl)
+ a->min_ttl = r->min_ttl;
+ if (r->max_mss)
+ a->max_mss = r->max_mss;
+ a->flags |= (r->scrub_flags & (PFSTATE_NODF|PFSTATE_RANDOMID|
+ PFSTATE_SETTOS|PFSTATE_SCRUB_TCP));
+}
+
int
pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
struct pfi_kif *kif, struct mbuf *m, int off, void *h,
struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm,
struct ifqueue *ifq)
{
- struct pf_rule *nr = NULL;
+ struct pf_rule *nr = NULL, *lastr = NULL;
struct pf_addr *saddr = pd->src, *daddr = pd->dst;
sa_family_t af = pd->af;
struct pf_rule *r, *a = NULL;
struct pf_ruleset *ruleset = NULL;
+ struct pf_rule_slist rules;
+ struct pf_rule_item *ri;
struct pf_src_node *nsn = NULL;
struct tcphdr *th = pd->hdr.tcp;
struct pf_state_key *skw = NULL, *sks = NULL;
struct pf_state_key *sk = NULL, *nk = NULL;
+ struct pf_rule_actions act;
u_short reason;
int rewrite = 0, hdrlen = 0;
- int tag = -1, rtableid = -1;
+ int tag = -1;
int asd = 0;
int match = 0;
int state_icmp = 0, icmp_dir, multi;
@@ -2620,6 +2665,8 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
u_int16_t bproto_sum = 0, bip_sum;
u_int8_t icmptype = 0, icmpcode = 0;
+ bzero(&act, sizeof(act));
+ act.rtableid = -1;
if (direction == PF_IN && pf_check_congestion(ifq)) {
REASON_SET(&reason, PFRES_CONGEST);
@@ -2809,6 +2856,7 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
pd->nat_rule = nr;
}
+ SLIST_INIT(&rules);
while (r != NULL) {
r->evaluations++;
if (pfi_kif_match(r->kif, kif) == r->ifnot)
@@ -2869,15 +2917,24 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
r->os_fingerprint)))
r = TAILQ_NEXT(r, entries);
else {
+ lastr = r;
if (r->tag)
tag = r->tag;
- if (r->rtableid >= 0)
- rtableid = r->rtableid;
if (r->anchor == NULL) {
- match = 1;
- *rm = r;
- *am = a;
- *rsm = ruleset;
+ if (r->action == PF_MATCH) {
+ ri = pool_get(&pf_rule_item_pl,
+ PR_NOWAIT);
+ ri->r = r;
+ /* order is irrelevant */
+ SLIST_INSERT_HEAD(&rules, ri, entry);
+ pf_rule_to_actions(r, &act);
+ } else {
+ match = 1;
+ *rm = r;
+ *am = a;
+ *rsm = ruleset;
+ }
+
if ((*rm)->quick)
break;
r = TAILQ_NEXT(r, entries);
@@ -2893,13 +2950,24 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
a = *am;
ruleset = *rsm;
+ /* apply actions for last matching rule */
+ if (lastr && lastr->action != PF_MATCH)
+ pf_rule_to_actions(lastr, &act);
+
REASON_SET(&reason, PFRES_MATCH);
- if (r->log || (nr != NULL && nr->log)) {
+ if (act.log || (nr != NULL && nr->log)) {
+ struct pf_rule_item *mr;
+
if (rewrite)
m_copyback(m, off, hdrlen, pd->hdr.any);
- PFLOG_PACKET(kif, h, m, af, direction, reason, r->log ? r : nr,
- a, ruleset, pd);
+ if (r->log)
+ PFLOG_PACKET(kif, h, m, af, direction, reason,
+ r->log ? r : nr, a, ruleset, pd);
+ SLIST_FOREACH(mr, &rules, entry)
+ if (mr->r->log)
+ PFLOG_PACKET(kif, h, m, af, direction, reason,
+ mr->r, a, ruleset, pd);
}
if ((r->action == PF_DROP) &&
@@ -2950,32 +3018,32 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
pf_send_tcp(r, af, pd->dst,
pd->src, th->th_dport, th->th_sport,
ntohl(th->th_ack), ack, TH_RST|TH_ACK, 0, 0,
- r->return_ttl, 1, 0, pd->eh, kif->pfik_ifp);
+ r->return_ttl, 1, 0, pd->eh, kif->pfik_ifp,
+ act.rtableid);
}
} else if (pd->proto != IPPROTO_ICMP && af == AF_INET &&
r->return_icmp)
pf_send_icmp(m, r->return_icmp >> 8,
- r->return_icmp & 255, af, r);
+ r->return_icmp & 255, af, r, act.rtableid);
else if (pd->proto != IPPROTO_ICMPV6 && af == AF_INET6 &&
r->return_icmp6)
pf_send_icmp(m, r->return_icmp6 >> 8,
- r->return_icmp6 & 255, af, r);
+ r->return_icmp6 & 255, af, r, act.rtableid);
}
if (r->action == PF_DROP)
goto cleanup;
- if (pf_tag_packet(m, tag, rtableid)) {
+ if (pf_tag_packet(m, tag, act.rtableid)) {
REASON_SET(&reason, PFRES_MEMORY);
goto cleanup;
}
- if (!state_icmp && (r->keep_state || nr != NULL ||
- (pd->flags & PFDESC_TCP_NORM))) {
+ if (!state_icmp && (r->keep_state || nr != NULL)) {
int action;
action = pf_create_state(r, nr, a, pd, nsn, skw, sks, nk, sk, m,
off, sport, dport, &rewrite, kif, sm, tag, bproto_sum,
- bip_sum, hdrlen);
+ bip_sum, hdrlen, &rules, &act);
if (action != PF_PASS)
return (action);
} else {
@@ -3019,7 +3087,8 @@ pf_create_state(struct pf_rule *r, struct pf_rule *nr, struct pf_rule *a,
struct pf_state_key *sks, struct pf_state_key *nk, struct pf_state_key *sk,
struct mbuf *m, int off, u_int16_t sport, u_int16_t dport, int *rewrite,
struct pfi_kif *kif, struct pf_state **sm, int tag, u_int16_t bproto_sum,
- u_int16_t bip_sum, int hdrlen)
+ u_int16_t bip_sum, int hdrlen, struct pf_rule_slist *rules,
+ struct pf_rule_actions *act)
{
struct pf_state *s = NULL;
struct pf_src_node *sn = NULL;
@@ -3054,6 +3123,7 @@ pf_create_state(struct pf_rule *r, struct pf_rule *nr, struct pf_rule *a,
s->rule.ptr = r;
s->nat_rule.ptr = nr;
s->anchor.ptr = a;
+ bcopy(rules, &s->match_rules, sizeof(s->match_rules));
STATE_INC_COUNTERS(s);
if (r->allow_opts)
s->state_flags |= PFSTATE_ALLOWOPTS;
@@ -3061,7 +3131,14 @@ pf_create_state(struct pf_rule *r, struct pf_rule *nr, struct pf_rule *a,
s->state_flags |= PFSTATE_SLOPPY;
if (r->rule_flag & PFRULE_PFLOW)
s->state_flags |= PFSTATE_PFLOW;
- s->log = r->log & PF_LOG_ALL;
+ s->log = act->log & PF_LOG_ALL;
+ s->qid = act->qid;
+ s->pqid = act->pqid;
+ s->rtableid = act->rtableid;
+ s->min_ttl = act->min_ttl;
+ s->set_tos = act->set_tos;
+ s->max_mss = act->max_mss;
+ s->state_flags |= act->flags;
s->sync_state = PFSYNC_S_NONE;
if (nr != NULL)
s->log |= nr->log & PF_LOG_ALL;
@@ -3132,15 +3209,15 @@ pf_create_state(struct pf_rule *r, struct pf_rule *nr, struct pf_rule *a,
s->nat_src_node->states++;
}
if (pd->proto == IPPROTO_TCP) {
- if ((pd->flags & PFDESC_TCP_NORM) && pf_normalize_tcp_init(m,
- off, pd, th, &s->src, &s->dst)) {
+ if (s->state_flags & PFSTATE_SCRUB_TCP &&
+ pf_normalize_tcp_init(m, off, pd, th, &s->src, &s->dst)) {
REASON_SET(&reason, PFRES_MEMORY);
pf_src_tree_remove_state(s);
STATE_DEC_COUNTERS(s);
pool_put(&pf_state_pl, s);
return (PF_DROP);
}
- if ((pd->flags & PFDESC_TCP_NORM) && s->src.scrub &&
+ if (s->state_flags & PFSTATE_SCRUB_TCP && s->src.scrub &&
pf_normalize_tcp_stateful(m, off, pd, &reason, th, s,
&s->src, &s->dst, rewrite)) {
/* This really shouldn't happen!!! */
@@ -3203,7 +3280,8 @@ pf_create_state(struct pf_rule *r, struct pf_rule *nr, struct pf_rule *a,
s->src.mss = mss;
pf_send_tcp(r, pd->af, pd->dst, pd->src, th->th_dport,
th->th_sport, s->src.seqhi, ntohl(th->th_seq) + 1,
- TH_SYN|TH_ACK, 0, s->src.mss, 0, 1, 0, NULL, NULL);
+ TH_SYN|TH_ACK, 0, s->src.mss, 0, 1, 0, NULL, NULL,
+ act->rtableid);
REASON_SET(&reason, PFRES_SYNPROXY);
return (PF_SYNPROXY_DROP);
}
@@ -3345,7 +3423,7 @@ pf_tcp_track_full(struct pf_state_peer *src, struct pf_state_peer *dst,
if (src->seqlo == 0) {
/* First packet from this end. Set its state */
- if ((pd->flags & PFDESC_TCP_NORM || dst->scrub) &&
+ if (((*state)->state_flags & PFSTATE_SCRUB_TCP || dst->scrub) &&
src->scrub == NULL) {
if (pf_normalize_tcp_init(m, off, pd, th, src, dst)) {
REASON_SET(reason, PFRES_MEMORY);
@@ -3616,7 +3694,7 @@ pf_tcp_track_full(struct pf_state_peer *src, struct pf_state_peer *dst,
th->th_sport, ntohl(th->th_ack), 0,
TH_RST, 0, 0,
(*state)->rule.ptr->return_ttl, 1, 0,
- pd->eh, kif->pfik_ifp);
+ pd->eh, kif->pfik_ifp, (*state)->rtableid);
src->seqlo = 0;
src->seqhi = 1;
src->max_win = 1;
@@ -3768,7 +3846,7 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
pd->src, th->th_dport, th->th_sport,
(*state)->src.seqhi, ntohl(th->th_seq) + 1,
TH_SYN|TH_ACK, 0, (*state)->src.mss, 0, 1,
- 0, NULL, NULL);
+ 0, NULL, NULL, (*state)->rtableid);
REASON_SET(reason, PFRES_SYNPROXY);
return (PF_SYNPROXY_DROP);
} else if (!(th->th_flags & TH_ACK) ||
@@ -3798,7 +3876,8 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
&sk->addr[pd->sidx], &sk->addr[pd->didx],
sk->port[pd->sidx], sk->port[pd->didx],
(*state)->dst.seqhi, 0, TH_SYN, 0,
- (*state)->src.mss, 0, 0, (*state)->tag, NULL, NULL);
+ (*state)->src.mss, 0, 0, (*state)->tag, NULL, NULL,
+ (*state)->rtableid);
REASON_SET(reason, PFRES_SYNPROXY);
return (PF_SYNPROXY_DROP);
} else if (((th->th_flags & (TH_SYN|TH_ACK)) !=
@@ -3813,13 +3892,13 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
pd->src, th->th_dport, th->th_sport,
ntohl(th->th_ack), ntohl(th->th_seq) + 1,
TH_ACK, (*state)->src.max_win, 0, 0, 0,
- (*state)->tag, NULL, NULL);
+ (*state)->tag, NULL, NULL, (*state)->rtableid);
pf_send_tcp((*state)->rule.ptr, pd->af,
&sk->addr[pd->sidx], &sk->addr[pd->didx],
sk->port[pd->sidx], sk->port[pd->didx],
(*state)->src.seqhi + 1, (*state)->src.seqlo + 1,
TH_ACK, (*state)->dst.max_win, 0, 0, 1,
- 0, NULL, NULL);
+ 0, NULL, NULL, (*state)->rtableid);
(*state)->src.seqdiff = (*state)->dst.seqhi -
(*state)->src.seqlo;
(*state)->dst.seqdiff = (*state)->src.seqhi -
@@ -5328,15 +5407,17 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0,
if (m->m_pkthdr.len < (int)sizeof(*h)) {
action = PF_DROP;
REASON_SET(&reason, PFRES_SHORT);
- log = 1;
+ log = PF_LOG_FORCE;
goto done;
}
if (m->m_pkthdr.pf.flags & PF_TAG_GENERATED)
return (PF_PASS);
- /* We do IP header normalization and packet reassembly here */
- if (pf_normalize_ip(m0, dir, kif, &reason, &pd) != PF_PASS) {
+ /* packet reassembly here if 1) enabled 2) we deal with a fragment */
+ h = mtod(m, struct ip *);
+ if (pf_status.reass && (h->ip_off & htons(IP_MF | IP_OFFMASK)) &&
+ pf_normalize_ip(m0, dir, kif, &reason, &pd) != PF_PASS) {
action = PF_DROP;
goto done;
}
@@ -5347,7 +5428,7 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0,
if (off < (int)sizeof(*h)) {
action = PF_DROP;
REASON_SET(&reason, PFRES_SHORT);
- log = 1;
+ log = PF_LOG_FORCE;
goto done;
}
@@ -5380,7 +5461,8 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0,
pd.hdr.tcp = &th;
if (!pf_pull_hdr(m, off, &th, sizeof(th),
&action, &reason, AF_INET)) {
- log = action != PF_PASS;
+ if (action != PF_PASS)
+ log = PF_LOG_FORCE;
goto done;
}
pd.p_len = pd.tot_len - off - (th.th_off << 2);
@@ -5401,6 +5483,13 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0,
} else if (s == NULL)
action = pf_test_rule(&r, &s, dir, kif,
m, off, h, &pd, &a, &ruleset, &ipintrq);
+
+ if (s) {
+ if (s->max_mss)
+ pf_normalize_mss(m, off, &pd, s->max_mss);
+ } else if (r->max_mss)
+ pf_normalize_mss(m, off, &pd, r->max_mss);
+
break;
}
@@ -5410,7 +5499,8 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0,
pd.hdr.udp = &uh;
if (!pf_pull_hdr(m, off, &uh, sizeof(uh),
&action, &reason, AF_INET)) {
- log = action != PF_PASS;
+ if (action != PF_PASS)
+ log = PF_LOG_FORCE;
goto done;
}
if (uh.uh_dport == 0 ||
@@ -5440,7 +5530,8 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0,
pd.hdr.icmp = &ih;
if (!pf_pull_hdr(m, off, &ih, ICMP_MINLEN,
&action, &reason, AF_INET)) {
- log = action != PF_PASS;
+ if (action != PF_PASS)
+ log = PF_LOG_FORCE;
goto done;
}
action = pf_test_state_icmp(&s, dir, kif, m, off, h, &pd,
@@ -5478,23 +5569,28 @@ done:
!((s && s->state_flags & PFSTATE_ALLOWOPTS) || r->allow_opts)) {
action = PF_DROP;
REASON_SET(&reason, PFRES_IPOPTIONS);
- log = 1;
+ log = PF_LOG_FORCE;
DPFPRINTF(PF_DEBUG_MISC,
("pf: dropping packet with ip options\n"));
}
- if ((s && s->tag) || r->rtableid)
- pf_tag_packet(m, s ? s->tag : 0, r->rtableid);
+ if (s)
+ pf_scrub_ip(&m, s->state_flags, s->min_ttl, s->set_tos);
+ else
+ pf_scrub_ip(&m, r->scrub_flags, r->min_ttl, r->set_tos);
+
+ if (s && (s->tag || s->rtableid))
+ pf_tag_packet(m, s ? s->tag : 0, s->rtableid);
if (dir == PF_IN && s && s->key[PF_SK_STACK])
m->m_pkthdr.pf.statekey = s->key[PF_SK_STACK];
#ifdef ALTQ
- if (action == PF_PASS && r->qid) {
+ if (action == PF_PASS && s && s->qid) {
if (pqid || (pd.tos & IPTOS_LOWDELAY))
- m->m_pkthdr.pf.qid = r->pqid;
+ m->m_pkthdr.pf.qid = s->pqid;
else
- m->m_pkthdr.pf.qid = r->qid;
+ m->m_pkthdr.pf.qid = s->qid;
/* add hints for ecn */
m->m_pkthdr.pf.hdr = h;
}
@@ -5523,15 +5619,21 @@ done:
}
if (log) {
- struct pf_rule *lr;
+ struct pf_rule *lr;
+ struct pf_rule_item *ri;
if (s != NULL && s->nat_rule.ptr != NULL &&
s->nat_rule.ptr->log & PF_LOG_ALL)
lr = s->nat_rule.ptr;
else
lr = r;
- PFLOG_PACKET(kif, h, m, AF_INET, dir, reason, lr, a, ruleset,
- &pd);
+ if (log == PF_LOG_FORCE || lr->log & PF_LOG_ALL)
+ PFLOG_PACKET(kif, h, m, AF_INET, dir, reason, lr, a,
+ ruleset, &pd);
+ SLIST_FOREACH(ri, &s->match_rules, entry)
+ if (ri->r->log & PF_LOG_ALL)
+ PFLOG_PACKET(kif, h, m, AF_INET, dir, reason,
+ ri->r, a, ruleset, &pd);
}
kif->pfik_bytes[0][dir == PF_OUT][action != PF_PASS] += pd.tot_len;
@@ -5546,6 +5648,8 @@ done:
a->bytes[dirndx] += pd.tot_len;
}
if (s != NULL) {
+ struct pf_rule_item *ri;
+
if (s->nat_rule.ptr != NULL) {
s->nat_rule.ptr->packets[dirndx]++;
s->nat_rule.ptr->bytes[dirndx] += pd.tot_len;
@@ -5561,6 +5665,10 @@ done:
dirndx = (dir == s->direction) ? 0 : 1;
s->packets[dirndx]++;
s->bytes[dirndx] += pd.tot_len;
+ SLIST_FOREACH(ri, &s->match_rules, entry) {
+ ri->r->packets[dirndx]++;
+ ri->r->bytes[dirndx] += pd.tot_len;
+ }
}
tr = r;
nr = (s != NULL) ? s->nat_rule.ptr : pd.nat_rule;
@@ -5647,7 +5755,7 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0,
if (m->m_pkthdr.pf.flags & PF_TAG_GENERATED)
return (PF_PASS);
- /* We do IP header normalization and packet reassembly here */
+ /* packet reassembly */
if (pf_normalize_ip6(m0, dir, kif, &reason, &pd) != PF_PASS) {
action = PF_DROP;
goto done;
@@ -5889,18 +5997,23 @@ done:
("pf: dropping packet with dangerous v6 headers\n"));
}
- if ((s && s->tag) || r->rtableid)
- pf_tag_packet(m, s ? s->tag : 0, r->rtableid);
+ if (s)
+ pf_scrub_ip6(&m, s->min_ttl);
+ else
+ pf_scrub_ip6(&m, r->min_ttl);
+
+ if (s && (s->tag || s->rtableid))
+ pf_tag_packet(m, s ? s->tag : 0, s->rtableid);
if (dir == PF_IN && s && s->key[PF_SK_STACK])
m->m_pkthdr.pf.statekey = s->key[PF_SK_STACK];
#ifdef ALTQ
- if (action == PF_PASS && r->qid) {
+ if (action == PF_PASS && s && s->qid) {
if (pd.tos & IPTOS_LOWDELAY)
- m->m_pkthdr.pf.qid = r->pqid;
+ m->m_pkthdr.pf.qid = s->pqid;
else
- m->m_pkthdr.pf.qid = r->qid;
+ m->m_pkthdr.pf.qid = s->qid;
/* add hints for ecn */
m->m_pkthdr.pf.hdr = h;
}
diff --git a/sys/net/pf_ioctl.c b/sys/net/pf_ioctl.c
index d59cfe307fa..01eaaa79fa8 100644
--- a/sys/net/pf_ioctl.c
+++ b/sys/net/pf_ioctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_ioctl.c,v 1.215 2009/03/09 13:53:10 mcbride Exp $ */
+/* $OpenBSD: pf_ioctl.c,v 1.216 2009/04/06 12:05:55 henning Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -151,6 +151,8 @@ pfattach(int num)
"pfstatekeypl", NULL);
pool_init(&pf_state_item_pl, sizeof(struct pf_state_item), 0, 0, 0,
"pfstateitempl", NULL);
+ pool_init(&pf_rule_item_pl, sizeof(struct pf_rule_item), 0, 0, 0,
+ "pfruleitempl", NULL);
pool_init(&pf_altq_pl, sizeof(struct pf_altq), 0, 0, 0, "pfaltqpl",
&pool_allocator_nointr);
pool_init(&pf_pooladdr_pl, sizeof(struct pf_pooladdr), 0, 0, 0,
@@ -853,10 +855,6 @@ pf_setup_pfsync_matching(struct pf_ruleset *rs)
MD5Init(&ctx);
for (rs_cnt = 0; rs_cnt < PF_RULESET_MAX; rs_cnt++) {
- /* XXX PF_RULESET_SCRUB as well? */
- if (rs_cnt == PF_RULESET_SCRUB)
- continue;
-
if (rs->rules[rs_cnt].inactive.ptr_array)
free(rs->rules[rs_cnt].inactive.ptr_array, M_TEMP);
rs->rules[rs_cnt].inactive.ptr_array = NULL;
@@ -2839,6 +2837,15 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
+ case DIOCSETREASS: {
+ u_int32_t *reass = (u_int32_t *)addr;
+
+ pf_status.reass = *reass;
+ if (!(pf_status.reass & PF_REASS_ENABLED))
+ pf_status.reass = 0;
+ break;
+ }
+
default:
error = ENODEV;
break;
diff --git a/sys/net/pf_norm.c b/sys/net/pf_norm.c
index 8fa6081287e..9faef283832 100644
--- a/sys/net/pf_norm.c
+++ b/sys/net/pf_norm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_norm.c,v 1.115 2009/01/31 20:06:55 henning Exp $ */
+/* $OpenBSD: pf_norm.c,v 1.116 2009/04/06 12:05:55 henning Exp $ */
/*
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
@@ -112,15 +112,12 @@ void pf_free_fragment(struct pf_fragment *);
struct pf_fragment *pf_find_fragment(struct ip *, struct pf_frag_tree *);
struct mbuf *pf_reassemble(struct mbuf **, struct pf_fragment **,
struct pf_frent *, int);
-struct mbuf *pf_fragcache(struct mbuf **, struct ip*,
- struct pf_fragment **, int, int, int *);
-int pf_normalize_tcpopt(struct pf_rule *, struct mbuf *,
- struct tcphdr *, int, sa_family_t);
-void pf_scrub_ip(struct mbuf **, u_int32_t, u_int8_t,
+void pf_scrub_ip(struct mbuf **, u_int8_t, u_int8_t,
u_int8_t);
#ifdef INET6
void pf_scrub_ip6(struct mbuf **, u_int8_t);
#endif
+
#define DPFPRINTF(x) do { \
if (pf_status.debug >= PF_DEBUG_MISC) { \
printf("%s: ", __func__); \
@@ -520,308 +517,11 @@ pf_reassemble(struct mbuf **m0, struct pf_fragment **frag,
return (NULL);
}
-struct mbuf *
-pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff,
- int drop, int *nomem)
-{
- struct mbuf *m = *m0;
- struct pf_frcache *frp, *fra, *cur = NULL;
- int ip_len = ntohs(h->ip_len) - (h->ip_hl << 2);
- u_int16_t off = ntohs(h->ip_off) << 3;
- u_int16_t max = ip_len + off;
- int hosed = 0;
-
- KASSERT(*frag == NULL || !BUFFER_FRAGMENTS(*frag));
-
- /* Create a new range queue for this packet */
- if (*frag == NULL) {
- *frag = pool_get(&pf_cache_pl, PR_NOWAIT);
- if (*frag == NULL) {
- pf_flush_fragments();
- *frag = pool_get(&pf_cache_pl, PR_NOWAIT);
- if (*frag == NULL)
- goto no_mem;
- }
-
- /* Get an entry for the queue */
- cur = pool_get(&pf_cent_pl, PR_NOWAIT);
- if (cur == NULL) {
- pool_put(&pf_cache_pl, *frag);
- *frag = NULL;
- goto no_mem;
- }
- pf_ncache++;
-
- (*frag)->fr_flags = PFFRAG_NOBUFFER;
- (*frag)->fr_max = 0;
- (*frag)->fr_src = h->ip_src;
- (*frag)->fr_dst = h->ip_dst;
- (*frag)->fr_p = h->ip_p;
- (*frag)->fr_id = h->ip_id;
- (*frag)->fr_timeout = time_second;
-
- cur->fr_off = off;
- cur->fr_end = max;
- LIST_INIT(&(*frag)->fr_cache);
- LIST_INSERT_HEAD(&(*frag)->fr_cache, cur, fr_next);
-
- RB_INSERT(pf_frag_tree, &pf_cache_tree, *frag);
- TAILQ_INSERT_HEAD(&pf_cachequeue, *frag, frag_next);
-
- DPFPRINTF(("fragcache[%d]: new %d-%d\n", h->ip_id, off, max));
-
- goto pass;
- }
-
- /*
- * Find a fragment after the current one:
- * - off contains the real shifted offset.
- */
- frp = NULL;
- LIST_FOREACH(fra, &(*frag)->fr_cache, fr_next) {
- if (fra->fr_off > off)
- break;
- frp = fra;
- }
-
- KASSERT(frp != NULL || fra != NULL);
-
- if (frp != NULL) {
- int precut;
-
- precut = frp->fr_end - off;
- if (precut >= ip_len) {
- /* Fragment is entirely a duplicate */
- DPFPRINTF(("fragcache[%d]: dead (%d-%d) %d-%d\n",
- h->ip_id, frp->fr_off, frp->fr_end, off, max));
- goto drop_fragment;
- }
- if (precut == 0) {
- /* They are adjacent. Fixup cache entry */
- DPFPRINTF(("fragcache[%d]: adjacent (%d-%d) %d-%d\n",
- h->ip_id, frp->fr_off, frp->fr_end, off, max));
- frp->fr_end = max;
- } else if (precut > 0) {
- /* The first part of this payload overlaps with a
- * fragment that has already been passed.
- * Need to trim off the first part of the payload.
- * But to do so easily, we need to create another
- * mbuf to throw the original header into.
- */
-
- DPFPRINTF(("fragcache[%d]: chop %d (%d-%d) %d-%d\n",
- h->ip_id, precut, frp->fr_off, frp->fr_end, off,
- max));
-
- off += precut;
- max -= precut;
- /* Update the previous frag to encompass this one */
- frp->fr_end = max;
-
- if (!drop) {
- /* XXX Optimization opportunity
- * This is a very heavy way to trim the payload.
- * we could do it much faster by diddling mbuf
- * internals but that would be even less legible
- * than this mbuf magic. For my next trick,
- * I'll pull a rabbit out of my laptop.
- */
- *m0 = m_copym2(m, 0, h->ip_hl << 2, M_NOWAIT);
- if (*m0 == NULL)
- goto no_mem;
- KASSERT((*m0)->m_next == NULL);
- m_adj(m, precut + (h->ip_hl << 2));
- m_cat(*m0, m);
- m = *m0;
- if (m->m_flags & M_PKTHDR) {
- int plen = 0;
- struct mbuf *t;
- for (t = m; t; t = t->m_next)
- plen += t->m_len;
- m->m_pkthdr.len = plen;
- }
-
-
- h = mtod(m, struct ip *);
-
-
- KASSERT((int)m->m_len ==
- ntohs(h->ip_len) - precut);
- h->ip_off = htons(ntohs(h->ip_off) +
- (precut >> 3));
- h->ip_len = htons(ntohs(h->ip_len) - precut);
- } else {
- hosed++;
- }
- } else {
- /* There is a gap between fragments */
-
- DPFPRINTF(("fragcache[%d]: gap %d (%d-%d) %d-%d\n",
- h->ip_id, -precut, frp->fr_off, frp->fr_end, off,
- max));
-
- cur = pool_get(&pf_cent_pl, PR_NOWAIT);
- if (cur == NULL)
- goto no_mem;
- pf_ncache++;
-
- cur->fr_off = off;
- cur->fr_end = max;
- LIST_INSERT_AFTER(frp, cur, fr_next);
- }
- }
-
- if (fra != NULL) {
- int aftercut;
- int merge = 0;
-
- aftercut = max - fra->fr_off;
- if (aftercut == 0) {
- /* Adjacent fragments */
- DPFPRINTF(("fragcache[%d]: adjacent %d-%d (%d-%d)\n",
- h->ip_id, off, max, fra->fr_off, fra->fr_end));
- fra->fr_off = off;
- merge = 1;
- } else if (aftercut > 0) {
- /* Need to chop off the tail of this fragment */
- DPFPRINTF(("fragcache[%d]: chop %d %d-%d (%d-%d)\n",
- h->ip_id, aftercut, off, max, fra->fr_off,
- fra->fr_end));
- fra->fr_off = off;
- max -= aftercut;
-
- merge = 1;
-
- if (!drop) {
- m_adj(m, -aftercut);
- if (m->m_flags & M_PKTHDR) {
- int plen = 0;
- struct mbuf *t;
- for (t = m; t; t = t->m_next)
- plen += t->m_len;
- m->m_pkthdr.len = plen;
- }
- h = mtod(m, struct ip *);
- KASSERT((int)m->m_len ==
- ntohs(h->ip_len) - aftercut);
- h->ip_len = htons(ntohs(h->ip_len) - aftercut);
- } else {
- hosed++;
- }
- } else if (frp == NULL) {
- /* There is a gap between fragments */
- DPFPRINTF(("fragcache[%d]: gap %d %d-%d (%d-%d)\n",
- h->ip_id, -aftercut, off, max, fra->fr_off,
- fra->fr_end));
-
- cur = pool_get(&pf_cent_pl, PR_NOWAIT);
- if (cur == NULL)
- goto no_mem;
- pf_ncache++;
-
- cur->fr_off = off;
- cur->fr_end = max;
- LIST_INSERT_BEFORE(fra, cur, fr_next);
- }
-
-
- /* Need to glue together two separate fragment descriptors */
- if (merge) {
- if (cur && fra->fr_off <= cur->fr_end) {
- /* Need to merge in a previous 'cur' */
- DPFPRINTF(("fragcache[%d]: adjacent(merge "
- "%d-%d) %d-%d (%d-%d)\n",
- h->ip_id, cur->fr_off, cur->fr_end, off,
- max, fra->fr_off, fra->fr_end));
- fra->fr_off = cur->fr_off;
- LIST_REMOVE(cur, fr_next);
- pool_put(&pf_cent_pl, cur);
- pf_ncache--;
- cur = NULL;
-
- } else if (frp && fra->fr_off <= frp->fr_end) {
- /* Need to merge in a modified 'frp' */
- KASSERT(cur == NULL);
- DPFPRINTF(("fragcache[%d]: adjacent(merge "
- "%d-%d) %d-%d (%d-%d)\n",
- h->ip_id, frp->fr_off, frp->fr_end, off,
- max, fra->fr_off, fra->fr_end));
- fra->fr_off = frp->fr_off;
- LIST_REMOVE(frp, fr_next);
- pool_put(&pf_cent_pl, frp);
- pf_ncache--;
- frp = NULL;
-
- }
- }
- }
-
- if (hosed) {
- /*
- * We must keep tracking the overall fragment even when
- * we're going to drop it anyway so that we know when to
- * free the overall descriptor. Thus we drop the frag late.
- */
- goto drop_fragment;
- }
-
-
- pass:
- /* Update maximum data size */
- if ((*frag)->fr_max < max)
- (*frag)->fr_max = max;
-
- /* This is the last segment */
- if (!mff)
- (*frag)->fr_flags |= PFFRAG_SEENLAST;
-
- /* Check if we are completely reassembled */
- if (((*frag)->fr_flags & PFFRAG_SEENLAST) &&
- LIST_FIRST(&(*frag)->fr_cache)->fr_off == 0 &&
- LIST_FIRST(&(*frag)->fr_cache)->fr_end == (*frag)->fr_max) {
- /* Remove from fragment queue */
- DPFPRINTF(("fragcache[%d]: done 0-%d\n", h->ip_id,
- (*frag)->fr_max));
- pf_free_fragment(*frag);
- *frag = NULL;
- }
-
- return (m);
-
- no_mem:
- *nomem = 1;
-
- /* Still need to pay attention to !IP_MF */
- if (!mff && *frag != NULL)
- (*frag)->fr_flags |= PFFRAG_SEENLAST;
-
- m_freem(m);
- return (NULL);
-
- drop_fragment:
-
- /* Still need to pay attention to !IP_MF */
- if (!mff && *frag != NULL)
- (*frag)->fr_flags |= PFFRAG_SEENLAST;
-
- if (drop) {
- /* This fragment has been deemed bad. Don't reass */
- if (((*frag)->fr_flags & PFFRAG_DROP) == 0)
- DPFPRINTF(("fragcache[%d]: dropping overall fragment\n",
- h->ip_id));
- (*frag)->fr_flags |= PFFRAG_DROP;
- }
-
- m_freem(m);
- return (NULL);
-}
-
int
pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
struct pf_pdesc *pd)
{
struct mbuf *m = *m0;
- struct pf_rule *r;
struct pf_frent *frent;
struct pf_fragment *frag = NULL;
struct ip *h = mtod(m, struct ip *);
@@ -831,39 +531,6 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
u_int16_t max;
int ip_len;
int ip_off;
- int tag = -1;
-
- r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_SCRUB].active.ptr);
- while (r != NULL) {
- r->evaluations++;
- if (pfi_kif_match(r->kif, kif) == r->ifnot)
- r = r->skip[PF_SKIP_IFP].ptr;
- else if (r->direction && r->direction != dir)
- r = r->skip[PF_SKIP_DIR].ptr;
- else if (r->af && r->af != AF_INET)
- r = r->skip[PF_SKIP_AF].ptr;
- else if (r->proto && r->proto != h->ip_p)
- r = r->skip[PF_SKIP_PROTO].ptr;
- else if (PF_MISMATCHAW(&r->src.addr,
- (struct pf_addr *)&h->ip_src.s_addr, AF_INET,
- r->src.neg, kif))
- r = r->skip[PF_SKIP_SRC_ADDR].ptr;
- else if (PF_MISMATCHAW(&r->dst.addr,
- (struct pf_addr *)&h->ip_dst.s_addr, AF_INET,
- r->dst.neg, NULL))
- r = r->skip[PF_SKIP_DST_ADDR].ptr;
- else if (r->match_tag && !pf_match_tag(m, r, &tag))
- r = TAILQ_NEXT(r, entries);
- else
- break;
- }
-
- if (r == NULL || r->action == PF_NOSCRUB)
- return (PF_PASS);
- else {
- r->packets[dir == PF_OUT]++;
- r->bytes[dir == PF_OUT] += pd->tot_len;
- }
/* Check for illegal packets */
if (hlen < (int)sizeof(struct ip))
@@ -872,8 +539,8 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
if (hlen > ntohs(h->ip_len))
goto drop;
- /* Clear IP_DF if the rule uses the no-df option */
- if (r->rule_flag & PFRULE_NODF && h->ip_off & htons(IP_DF)) {
+ /* Clear IP_DF if we're in no-df mode */
+ if (!(pf_status.reass & PF_REASS_NODF) && h->ip_off & htons(IP_DF)) {
u_int16_t ip_off = h->ip_off;
h->ip_off &= htons(~IP_DF);
@@ -909,75 +576,35 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
}
max = fragoff + ip_len;
- if ((r->rule_flag & (PFRULE_FRAGCROP|PFRULE_FRAGDROP)) == 0) {
- /* Fully buffer all of the fragments */
-
- frag = pf_find_fragment(h, &pf_frag_tree);
-
- /* Check if we saw the last fragment already */
- if (frag != NULL && (frag->fr_flags & PFFRAG_SEENLAST) &&
- max > frag->fr_max)
- goto bad;
-
- /* Get an entry for the fragment queue */
- frent = pool_get(&pf_frent_pl, PR_NOWAIT);
- if (frent == NULL) {
- REASON_SET(reason, PFRES_MEMORY);
- return (PF_DROP);
- }
- pf_nfrents++;
- frent->fr_ip = h;
- frent->fr_m = m;
-
- /* Might return a completely reassembled mbuf, or NULL */
- DPFPRINTF(("reass frag %d @ %d-%d\n", h->ip_id, fragoff, max));
- *m0 = m = pf_reassemble(m0, &frag, frent, mff);
-
- if (m == NULL)
- return (PF_DROP);
-
- if (frag != NULL && (frag->fr_flags & PFFRAG_DROP))
- goto drop;
+ /* Fully buffer all of the fragments */
+ frag = pf_find_fragment(h, &pf_frag_tree);
- h = mtod(m, struct ip *);
- } else {
- /* non-buffering fragment cache (drops or masks overlaps) */
- int nomem = 0;
-
- if (dir == PF_OUT && m->m_pkthdr.pf.flags & PF_TAG_FRAGCACHE) {
- /*
- * Already passed the fragment cache in the
- * input direction. If we continued, it would
- * appear to be a dup and would be dropped.
- */
- goto fragment_pass;
- }
+ /* Check if we saw the last fragment already */
+ if (frag != NULL && (frag->fr_flags & PFFRAG_SEENLAST) &&
+ max > frag->fr_max)
+ goto bad;
- frag = pf_find_fragment(h, &pf_cache_tree);
+ /* Get an entry for the fragment queue */
+ frent = pool_get(&pf_frent_pl, PR_NOWAIT);
+ if (frent == NULL) {
+ REASON_SET(reason, PFRES_MEMORY);
+ return (PF_DROP);
+ }
+ pf_nfrents++;
+ frent->fr_ip = h;
+ frent->fr_m = m;
- /* Check if we saw the last fragment already */
- if (frag != NULL && (frag->fr_flags & PFFRAG_SEENLAST) &&
- max > frag->fr_max) {
- if (r->rule_flag & PFRULE_FRAGDROP)
- frag->fr_flags |= PFFRAG_DROP;
- goto bad;
- }
+ /* Might return a completely reassembled mbuf, or NULL */
+ DPFPRINTF(("reass frag %d @ %d-%d\n", h->ip_id, fragoff, max));
+ *m0 = m = pf_reassemble(m0, &frag, frent, mff);
- *m0 = m = pf_fragcache(m0, h, &frag, mff,
- (r->rule_flag & PFRULE_FRAGDROP) ? 1 : 0, &nomem);
- if (m == NULL) {
- if (nomem)
- goto no_mem;
- goto drop;
- }
+ if (m == NULL)
+ return (PF_DROP);
- if (dir == PF_IN)
- m->m_pkthdr.pf.flags |= PF_TAG_FRAGCACHE;
+ if (frag != NULL && (frag->fr_flags & PFFRAG_DROP))
+ goto drop;
- if (frag != NULL && (frag->fr_flags & PFFRAG_DROP))
- goto drop;
- goto fragment_pass;
- }
+ h = mtod(m, struct ip *);
no_fragment:
/* At this point, only IP_DF is allowed in ip_off */
@@ -988,25 +615,11 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
h->ip_sum = pf_cksum_fixup(h->ip_sum, ip_off, h->ip_off, 0);
}
- /* not missing a return here */
-
- fragment_pass:
- pf_scrub_ip(&m, r->rule_flag, r->min_ttl, r->set_tos);
-
- if ((r->rule_flag & (PFRULE_FRAGCROP|PFRULE_FRAGDROP)) == 0)
- pd->flags |= PFDESC_IP_REAS;
+ pd->flags |= PFDESC_IP_REAS;
return (PF_PASS);
- no_mem:
- REASON_SET(reason, PFRES_MEMORY);
- if (r != NULL && r->log)
- PFLOG_PACKET(kif, h, m, AF_INET, dir, *reason, r, NULL, NULL, pd);
- return (PF_DROP);
-
drop:
REASON_SET(reason, PFRES_NORM);
- if (r != NULL && r->log)
- PFLOG_PACKET(kif, h, m, AF_INET, dir, *reason, r, NULL, NULL, pd);
return (PF_DROP);
bad:
@@ -1017,8 +630,6 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
pf_free_fragment(frag);
REASON_SET(reason, PFRES_FRAG);
- if (r != NULL && r->log)
- PFLOG_PACKET(kif, h, m, AF_INET, dir, *reason, r, NULL, NULL, pd);
return (PF_DROP);
}
@@ -1029,7 +640,6 @@ pf_normalize_ip6(struct mbuf **m0, int dir, struct pfi_kif *kif,
u_short *reason, struct pf_pdesc *pd)
{
struct mbuf *m = *m0;
- struct pf_rule *r;
struct ip6_hdr *h = mtod(m, struct ip6_hdr *);
int off;
struct ip6_ext ext;
@@ -1043,38 +653,6 @@ pf_normalize_ip6(struct mbuf **m0, int dir, struct pfi_kif *kif,
u_int8_t proto;
int terminal;
- r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_SCRUB].active.ptr);
- while (r != NULL) {
- r->evaluations++;
- if (pfi_kif_match(r->kif, kif) == r->ifnot)
- r = r->skip[PF_SKIP_IFP].ptr;
- else if (r->direction && r->direction != dir)
- r = r->skip[PF_SKIP_DIR].ptr;
- else if (r->af && r->af != AF_INET6)
- r = r->skip[PF_SKIP_AF].ptr;
-#if 0 /* header chain! */
- else if (r->proto && r->proto != h->ip6_nxt)
- r = r->skip[PF_SKIP_PROTO].ptr;
-#endif
- else if (PF_MISMATCHAW(&r->src.addr,
- (struct pf_addr *)&h->ip6_src, AF_INET6,
- r->src.neg, kif))
- r = r->skip[PF_SKIP_SRC_ADDR].ptr;
- else if (PF_MISMATCHAW(&r->dst.addr,
- (struct pf_addr *)&h->ip6_dst, AF_INET6,
- r->dst.neg, NULL))
- r = r->skip[PF_SKIP_DST_ADDR].ptr;
- else
- break;
- }
-
- if (r == NULL || r->action == PF_NOSCRUB)
- return (PF_PASS);
- else {
- r->packets[dir == PF_OUT]++;
- r->bytes[dir == PF_OUT] += pd->tot_len;
- }
-
/* Check for illegal packets */
if (sizeof(struct ip6_hdr) + IPV6_MAXPACKET < m->m_pkthdr.len)
goto drop;
@@ -1161,8 +739,6 @@ pf_normalize_ip6(struct mbuf **m0, int dir, struct pfi_kif *kif,
if (sizeof(struct ip6_hdr) + plen > m->m_pkthdr.len)
goto shortpkt;
- pf_scrub_ip6(&m, r->min_ttl);
-
return (PF_PASS);
fragment:
@@ -1182,20 +758,14 @@ pf_normalize_ip6(struct mbuf **m0, int dir, struct pfi_kif *kif,
shortpkt:
REASON_SET(reason, PFRES_SHORT);
- if (r != NULL && r->log)
- PFLOG_PACKET(kif, h, m, AF_INET6, dir, *reason, r, NULL, NULL, pd);
return (PF_DROP);
drop:
REASON_SET(reason, PFRES_NORM);
- if (r != NULL && r->log)
- PFLOG_PACKET(kif, h, m, AF_INET6, dir, *reason, r, NULL, NULL, pd);
return (PF_DROP);
badfrag:
REASON_SET(reason, PFRES_FRAG);
- if (r != NULL && r->log)
- PFLOG_PACKET(kif, h, m, AF_INET6, dir, *reason, r, NULL, NULL, pd);
return (PF_DROP);
}
#endif /* INET6 */
@@ -1204,55 +774,10 @@ int
pf_normalize_tcp(int dir, struct pfi_kif *kif, struct mbuf *m, int ipoff,
int off, void *h, struct pf_pdesc *pd)
{
- struct pf_rule *r, *rm = NULL;
struct tcphdr *th = pd->hdr.tcp;
- int rewrite = 0;
u_short reason;
u_int8_t flags;
- sa_family_t af = pd->af;
-
- r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_SCRUB].active.ptr);
- while (r != NULL) {
- r->evaluations++;
- if (pfi_kif_match(r->kif, kif) == r->ifnot)
- r = r->skip[PF_SKIP_IFP].ptr;
- else if (r->direction && r->direction != dir)
- r = r->skip[PF_SKIP_DIR].ptr;
- else if (r->af && r->af != af)
- r = r->skip[PF_SKIP_AF].ptr;
- else if (r->proto && r->proto != pd->proto)
- r = r->skip[PF_SKIP_PROTO].ptr;
- else if (PF_MISMATCHAW(&r->src.addr, pd->src, af,
- r->src.neg, kif))
- r = r->skip[PF_SKIP_SRC_ADDR].ptr;
- else if (r->src.port_op && !pf_match_port(r->src.port_op,
- r->src.port[0], r->src.port[1], th->th_sport))
- r = r->skip[PF_SKIP_SRC_PORT].ptr;
- else if (PF_MISMATCHAW(&r->dst.addr, pd->dst, af,
- r->dst.neg, NULL))
- r = r->skip[PF_SKIP_DST_ADDR].ptr;
- else if (r->dst.port_op && !pf_match_port(r->dst.port_op,
- r->dst.port[0], r->dst.port[1], th->th_dport))
- r = r->skip[PF_SKIP_DST_PORT].ptr;
- else if (r->os_fingerprint != PF_OSFP_ANY && !pf_osfp_match(
- pf_osfp_fingerprint(pd, m, off, th),
- r->os_fingerprint))
- r = TAILQ_NEXT(r, entries);
- else {
- rm = r;
- break;
- }
- }
-
- if (rm == NULL || rm->action == PF_NOSCRUB)
- return (PF_PASS);
- else {
- r->packets[dir == PF_OUT]++;
- r->bytes[dir == PF_OUT] += pd->tot_len;
- }
-
- if (rm->rule_flag & PFRULE_REASSEMBLE_TCP)
- pd->flags |= PFDESC_TCP_NORM;
+ u_int rewrite = 0;
flags = th->th_flags;
if (flags & TH_SYN) {
@@ -1298,10 +823,6 @@ pf_normalize_tcp(int dir, struct pfi_kif *kif, struct mbuf *m, int ipoff,
rewrite = 1;
}
- /* Process options */
- if (r->max_mss && pf_normalize_tcpopt(r, m, th, off, pd->af))
- rewrite = 1;
-
/* copy back packet headers if we sanitized */
if (rewrite)
m_copyback(m, off, sizeof(*th), th);
@@ -1310,8 +831,6 @@ pf_normalize_tcp(int dir, struct pfi_kif *kif, struct mbuf *m, int ipoff,
tcp_drop:
REASON_SET(&reason, PFRES_NORM);
- if (rm != NULL && r->log)
- PFLOG_PACKET(kif, h, m, AF_INET, dir, reason, r, NULL, NULL, pd);
return (PF_DROP);
}
@@ -1801,13 +1320,12 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
}
int
-pf_normalize_tcpopt(struct pf_rule *r, struct mbuf *m, struct tcphdr *th,
- int off, sa_family_t af)
+pf_normalize_mss(struct mbuf *m, int off, struct pf_pdesc *pd, u_int16_t maxmss)
{
+ struct tcphdr *th = pd->hdr.tcp;
u_int16_t *mss;
int thoff;
int opt, cnt, optlen = 0;
- int rewrite = 0;
u_char opts[MAX_TCPOPTLEN];
u_char *optp = opts;
@@ -1815,8 +1333,8 @@ pf_normalize_tcpopt(struct pf_rule *r, struct mbuf *m, struct tcphdr *th,
cnt = thoff - sizeof(struct tcphdr);
if (cnt > 0 && !pf_pull_hdr(m, off + sizeof(*th), opts, cnt,
- NULL, NULL, af))
- return (rewrite);
+ NULL, NULL, pd->af))
+ return (0);
for (; cnt > 0; cnt -= optlen, optp += optlen) {
opt = optp[0];
@@ -1834,11 +1352,13 @@ pf_normalize_tcpopt(struct pf_rule *r, struct mbuf *m, struct tcphdr *th,
switch (opt) {
case TCPOPT_MAXSEG:
mss = (u_int16_t *)(optp + 2);
- if ((ntohs(*mss)) > r->max_mss) {
+ if ((ntohs(*mss)) > maxmss) {
th->th_sum = pf_cksum_fixup(th->th_sum,
- *mss, htons(r->max_mss), 0);
- *mss = htons(r->max_mss);
- rewrite = 1;
+ *mss, htons(maxmss), 0);
+ *mss = htons(maxmss);
+ m_copyback(m, off + sizeof(*th),
+ thoff - sizeof(*th), opts);
+ m_copyback(m, off, sizeof(*th), th);
}
break;
default:
@@ -1846,20 +1366,19 @@ pf_normalize_tcpopt(struct pf_rule *r, struct mbuf *m, struct tcphdr *th,
}
}
- if (rewrite)
- m_copyback(m, off + sizeof(*th), thoff - sizeof(*th), opts);
- return (rewrite);
+
+ return (0);
}
void
-pf_scrub_ip(struct mbuf **m0, u_int32_t flags, u_int8_t min_ttl, u_int8_t tos)
+pf_scrub_ip(struct mbuf **m0, u_int8_t flags, u_int8_t min_ttl, u_int8_t tos)
{
struct mbuf *m = *m0;
struct ip *h = mtod(m, struct ip *);
/* Clear IP_DF if no-df was requested */
- if (flags & PFRULE_NODF && h->ip_off & htons(IP_DF)) {
+ if (flags & PFSTATE_NODF && h->ip_off & htons(IP_DF)) {
u_int16_t ip_off = h->ip_off;
h->ip_off &= htons(~IP_DF);
@@ -1875,7 +1394,7 @@ pf_scrub_ip(struct mbuf **m0, u_int32_t flags, u_int8_t min_ttl, u_int8_t tos)
}
/* Enforce tos */
- if (flags & PFRULE_SET_TOS) {
+ if (flags & PFSTATE_SETTOS) {
u_int16_t ov, nv;
ov = *(u_int16_t *)h;
@@ -1886,7 +1405,7 @@ pf_scrub_ip(struct mbuf **m0, u_int32_t flags, u_int8_t min_ttl, u_int8_t tos)
}
/* random-id, but not for fragments */
- if (flags & PFRULE_RANDOMID && !(h->ip_off & ~htons(IP_DF))) {
+ if (flags & PFSTATE_RANDOMID && !(h->ip_off & ~htons(IP_DF))) {
u_int16_t ip_id = h->ip_id;
h->ip_id = ip_randomid();
diff --git a/sys/net/pf_ruleset.c b/sys/net/pf_ruleset.c
index b04ab88cc61..2cc57e52394 100644
--- a/sys/net/pf_ruleset.c
+++ b/sys/net/pf_ruleset.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_ruleset.c,v 1.3 2009/01/06 21:57:51 thib Exp $ */
+/* $OpenBSD: pf_ruleset.c,v 1.4 2009/04/06 12:05:55 henning Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -102,11 +102,8 @@ int
pf_get_ruleset_number(u_int8_t action)
{
switch (action) {
- case PF_SCRUB:
- case PF_NOSCRUB:
- return (PF_RULESET_SCRUB);
- break;
case PF_PASS:
+ case PF_MATCH:
case PF_DROP:
return (PF_RULESET_FILTER);
break;
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index 8dd2f87c0fc..9952de3cf69 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfvar.h,v 1.284 2009/03/09 13:53:10 mcbride Exp $ */
+/* $OpenBSD: pfvar.h,v 1.285 2009/04/06 12:05:55 henning Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -59,9 +59,10 @@ struct ip6_hdr;
enum { PF_INOUT, PF_IN, PF_OUT };
enum { PF_PASS, PF_DROP, PF_SCRUB, PF_NOSCRUB, PF_NAT, PF_NONAT,
- PF_BINAT, PF_NOBINAT, PF_RDR, PF_NORDR, PF_SYNPROXY_DROP, PF_DEFER };
-enum { PF_RULESET_SCRUB, PF_RULESET_FILTER, PF_RULESET_NAT,
- PF_RULESET_BINAT, PF_RULESET_RDR, PF_RULESET_MAX };
+ PF_BINAT, PF_NOBINAT, PF_RDR, PF_NORDR, PF_SYNPROXY_DROP, PF_DEFER,
+ PF_MATCH };
+enum { PF_RULESET_FILTER, PF_RULESET_NAT, PF_RULESET_BINAT,
+ PF_RULESET_RDR, PF_RULESET_MAX };
enum { PF_OP_NONE, PF_OP_IRG, PF_OP_EQ, PF_OP_NE, PF_OP_LT,
PF_OP_LE, PF_OP_GT, PF_OP_GE, PF_OP_XRG, PF_OP_RRG };
enum { PF_DEBUG_NONE, PF_DEBUG_URGENT, PF_DEBUG_MISC, PF_DEBUG_NOISY };
@@ -122,6 +123,7 @@ enum { PF_ADDR_ADDRMASK, PF_ADDR_NOROUTE, PF_ADDR_DYNIFTL,
#define PF_LOG 0x01
#define PF_LOG_ALL 0x02
#define PF_LOG_SOCKET_LOOKUP 0x04
+#define PF_LOG_FORCE 0x08
struct pf_addr {
union {
@@ -491,6 +493,17 @@ struct pf_osfp_ioctl {
int fp_getnum; /* DIOCOSFPGET number */
};
+struct pf_rule_actions {
+ int rtableid;
+ u_int16_t qid;
+ u_int16_t pqid;
+ u_int16_t max_mss;
+ u_int8_t log;
+ u_int8_t set_tos;
+ u_int8_t min_ttl;
+ u_int8_t flags;
+ u_int8_t pad[2];
+};
union pf_rule_ptr {
struct pf_rule *ptr;
@@ -599,6 +612,8 @@ struct pf_rule {
#define PF_FLUSH 0x01
#define PF_FLUSH_GLOBAL 0x02
u_int8_t flush;
+ u_int8_t scrub_flags;
+ u_int8_t pad2[3];
struct {
struct pf_addr addr;
@@ -616,14 +631,6 @@ struct pf_rule {
#define PFRULE_SRCTRACK 0x0020 /* track source states */
#define PFRULE_RULESRCTRACK 0x0040 /* per rule */
-/* scrub flags */
-#define PFRULE_NODF 0x0100
-#define PFRULE_FRAGCROP 0x0200 /* non-buffering frag cache */
-#define PFRULE_FRAGDROP 0x0400 /* drop funny fragments */
-#define PFRULE_RANDOMID 0x0800
-#define PFRULE_REASSEMBLE_TCP 0x1000
-#define PFRULE_SET_TOS 0x2000
-
/* rule flags again */
#define PFRULE_IFBOUND 0x00010000 /* if-bound */
#define PFRULE_STATESLOPPY 0x00020000 /* sloppy state tracking */
@@ -643,6 +650,13 @@ struct pf_threshold {
u_int32_t last;
};
+struct pf_rule_item {
+ SLIST_ENTRY(pf_rule_item) entry;
+ struct pf_rule *r;
+};
+
+SLIST_HEAD(pf_rule_slist, pf_rule_item);
+
struct pf_src_node {
RB_ENTRY(pf_src_node) entry;
struct pf_addr addr;
@@ -747,6 +761,7 @@ struct pf_state {
RB_ENTRY(pf_state) entry_id;
struct pf_state_peer src;
struct pf_state_peer dst;
+ struct pf_rule_slist match_rules;
union pf_rule_ptr rule;
union pf_rule_ptr anchor;
union pf_rule_ptr nat_rule;
@@ -761,20 +776,30 @@ struct pf_state {
u_int32_t creation;
u_int32_t expire;
u_int32_t pfsync_time;
+ u_int16_t qid;
+ u_int16_t pqid;
u_int16_t tag;
+ u_int16_t state_flags;
+#define PFSTATE_ALLOWOPTS 0x0001
+#define PFSTATE_SLOPPY 0x0002
+#define PFSTATE_PFLOW 0x0004
+#define PFSTATE_NOSYNC 0x0008
+#define PFSTATE_ACK 0x0010
+#define PFSTATE_NODF 0x0020
+#define PFSTATE_SETTOS 0x0040
+#define PFSTATE_RANDOMID 0x0080
+#define PFSTATE_SCRUB_TCP 0x0100
u_int8_t log;
- u_int8_t state_flags;
-#define PFSTATE_ALLOWOPTS 0x01
-#define PFSTATE_SLOPPY 0x02
-#define PFSTATE_PFLOW 0x04
-#define PFSTATE_NOSYNC 0x08
-#define PFSTATE_ACK 0x10
u_int8_t timeout;
u_int8_t sync_state; /* PFSYNC_S_x */
/* XXX */
u_int8_t sync_updates;
- u_int8_t _tail[3];
+
+ int16_t rtableid;
+ u_int8_t min_ttl;
+ u_int8_t set_tos;
+ u_int16_t max_mss;
};
/*
@@ -1110,9 +1135,7 @@ struct pf_pdesc {
u_int16_t *ip_sum;
u_int16_t *proto_sum;
- u_int16_t flags; /* Let SCRUB trigger behavior in
- * state code. Easier than tags */
-#define PFDESC_TCP_NORM 0x0001 /* TCP shall be statefully scrubbed */
+ u_int16_t flags;
#define PFDESC_IP_REAS 0x0002 /* IP frags would've been reassembled */
sa_family_t af;
u_int8_t proto;
@@ -1250,10 +1273,14 @@ struct pf_status {
u_int32_t since;
u_int32_t debug;
u_int32_t hostid;
+ u_int32_t reass; /* reassembly */
char ifname[IFNAMSIZ];
u_int8_t pf_chksum[PF_MD5_DIGEST_LENGTH];
};
+#define PF_REASS_ENABLED 0x01
+#define PF_REASS_NODF 0x02
+
struct cbq_opts {
u_int minburst;
u_int maxburst;
@@ -1579,6 +1606,7 @@ struct pfioc_iface {
#define DIOCSETIFFLAG _IOWR('D', 89, struct pfioc_iface)
#define DIOCCLRIFFLAG _IOWR('D', 90, struct pfioc_iface)
#define DIOCKILLSRCNODES _IOWR('D', 91, struct pfioc_src_node_kill)
+#define DIOCSETREASS _IOWR('D', 92, u_int32_t)
#ifdef _KERNEL
RB_HEAD(pf_src_tree, pf_src_node);
@@ -1612,7 +1640,7 @@ extern void pf_tbladdr_copyout(struct pf_addr_wrap *);
extern void pf_calc_skip_steps(struct pf_rulequeue *);
extern struct pool pf_src_tree_pl, pf_rule_pl;
extern struct pool pf_state_pl, pf_state_key_pl, pf_state_item_pl,
- pf_altq_pl, pf_pooladdr_pl;
+ pf_altq_pl, pf_pooladdr_pl, pf_rule_item_pl;
extern struct pool pf_state_scrub_pl;
extern void pf_purge_thread(void *);
extern void pf_purge_expired_src_nodes(int);
@@ -1683,6 +1711,9 @@ int pf_normalize_tcp_init(struct mbuf *, int, struct pf_pdesc *,
int pf_normalize_tcp_stateful(struct mbuf *, int, struct pf_pdesc *,
u_short *, struct tcphdr *, struct pf_state *,
struct pf_state_peer *, struct pf_state_peer *, int *);
+int pf_normalize_mss(struct mbuf *, int, struct pf_pdesc *, u_int16_t);
+void pf_scrub_ip(struct mbuf **, u_int8_t, u_int8_t, u_int8_t);
+void pf_scrub_ip6(struct mbuf **, u_int8_t);
u_int32_t
pf_state_expires(const struct pf_state *);
void pf_purge_expired_fragments(void);