aboutsummaryrefslogtreecommitdiff
path: root/sbin
diff options
context:
space:
mode:
Diffstat (limited to 'sbin')
-rw-r--r--sbin/pfctl/parse.y119
-rw-r--r--sbin/pfctl/pf_print_state.c16
-rw-r--r--sbin/pfctl/pfctl.c39
-rw-r--r--sbin/pfctl/pfctl_parser.c58
-rw-r--r--sbin/pfctl/pfctl_parser.h3
5 files changed, 197 insertions, 38 deletions
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
index 6f9494828d53..e5629f9fcd5f 100644
--- a/sbin/pfctl/parse.y
+++ b/sbin/pfctl/parse.y
@@ -225,13 +225,21 @@ struct node_qassign {
static 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_AFTO 0x0080 /* not yet implemmented */
+#define FOM_SETTOS 0x0100
+#define FOM_SCRUB_TCP 0x0200
#define FOM_SETPRIO 0x0400
+#define FOM_ONCE 0x1000 /* not yet implemmented */
#define FOM_PRIO 0x2000
+#define FOM_SETDELAY 0x4000
+#define FOM_FRAGCACHE 0x8000 /* does not exist in OpenBSD */
struct node_uid *uid;
struct node_gid *gid;
struct {
@@ -266,6 +274,12 @@ static struct filter_opts {
struct node_host *addr;
u_int16_t port;
} divert;
+ /* new-style scrub opts */
+ int nodf;
+ int minttl;
+ int settos;
+ int randomid;
+ int max_mss;
} filter_opts;
static struct antispoof_opts {
@@ -277,10 +291,6 @@ static struct antispoof_opts {
static 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;
@@ -511,7 +521,7 @@ 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 syncookie_val
%type <v.i> sourcetrack flush unaryop statelock
@@ -631,7 +641,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;
@@ -1408,7 +1427,7 @@ scrubrule : scrubaction dir logquick interface af proto fromto scrub_opts
r.min_ttl = $8.minttl;
if ($8.maxmss)
r.max_mss = $8.maxmss;
- if ($8.marker & SOM_SETTOS) {
+ if ($8.marker & FOM_SETTOS) {
r.rule_flag |= PFRULE_SET_TOS;
r.set_tos = $8.settos;
}
@@ -1443,7 +1462,7 @@ scrub_opts : {
}
;
-scrub_opts_l : scrub_opts_l scrub_opt
+scrub_opts_l : scrub_opts_l comma scrub_opt
| scrub_opt
;
@@ -1455,7 +1474,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;
}
@@ -1463,11 +1482,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;
}
@@ -1475,23 +1494,23 @@ 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) {
+ if (scrub_opts.marker & FOM_FRAGCACHE) {
yyerror("fragcache cannot be respecified");
YYERROR;
}
- scrub_opts.marker |= SOM_FRAGCACHE;
+ scrub_opts.marker |= FOM_FRAGCACHE;
scrub_opts.fragcache = $1;
}
| REASSEMBLE STRING {
@@ -2351,6 +2370,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;
+
if ($9.marker & FOM_PRIO) {
if ($9.prio == 0)
r.prio = PF_PRIO_ZERO;
@@ -2933,6 +2967,24 @@ filter_opt : USER uids {
filter_opts.divert.port = 1; /* some random value */
#endif
}
+ | SCRUB '(' scrub_opts ')' {
+ filter_opts.nodf = $3.nodf;
+ filter_opts.minttl = $3.minttl;
+ if ($3.marker & FOM_SETTOS) {
+ /* Old style rules are "scrub set-tos 0x42"
+ * New style are "set tos 0x42 scrub (...)"
+ * What is in "scrub(...)"" is unfortunately the
+ * original scrub syntax so it would overwrite
+ * "set tos" of a pass/match rule.
+ */
+ 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;
+ }
| filter_sets
;
@@ -2953,6 +3005,14 @@ filter_set : prio {
filter_opts.set_prio[0] = $1.b1;
filter_opts.set_prio[1] = $1.b2;
}
+ | TOS tos {
+ if (filter_opts.marker & FOM_SETTOS) {
+ yyerror("tos cannot be respecified");
+ YYERROR;
+ }
+ filter_opts.marker |= FOM_SETTOS;
+ filter_opts.settos = $2;
+ }
prio : PRIO NUMBER {
if ($2 < 0 || $2 > PF_PRIO_MAX) {
yyerror("prio must be 0 - %u", PF_PRIO_MAX);
@@ -5170,6 +5230,7 @@ rule_consistent(struct pfctl_rule *r, int anchor_call)
switch (r->action) {
case PF_PASS:
+ case PF_MATCH:
case PF_DROP:
case PF_SCRUB:
case PF_NOSCRUB:
@@ -5240,8 +5301,8 @@ filter_consistent(struct pfctl_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 &&
@@ -5251,6 +5312,18 @@ filter_consistent(struct pfctl_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);
}
diff --git a/sbin/pfctl/pf_print_state.c b/sbin/pfctl/pf_print_state.c
index b66a296d6080..d23a0154b70d 100644
--- a/sbin/pfctl/pf_print_state.c
+++ b/sbin/pfctl/pf_print_state.c
@@ -339,8 +339,24 @@ print_state(struct pfctl_state *s, int opts)
printf(", anchor %u", s->anchor);
if (s->rule != -1)
printf(", rule %u", s->rule);
+ if (s->state_flags & PFSTATE_ALLOWOPTS)
+ printf(", allow-opts");
if (s->state_flags & PFSTATE_SLOPPY)
printf(", sloppy");
+ if (s->state_flags & PFSTATE_NOSYNC)
+ printf(", no-sync");
+ if (s->state_flags & PFSTATE_ACK)
+ printf(", psync-ack");
+ if (s->state_flags & PFSTATE_NODF)
+ printf(", no-df");
+ if (s->state_flags & PFSTATE_SETTOS)
+ printf(", set-tos");
+ if (s->state_flags & PFSTATE_RANDOMID)
+ printf(", random-id");
+ if (s->state_flags & PFSTATE_SCRUB_TCP)
+ printf(", scrub-tcp");
+ if (s->state_flags & PFSTATE_SETPRIO)
+ printf(", set-prio");
if (s->sync_flags & PFSYNC_FLAG_SRCNODE)
printf(", source-track");
if (s->sync_flags & PFSYNC_FLAG_NATSRCNODE)
diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
index f60e3f67e082..b5ef07064fb9 100644
--- a/sbin/pfctl/pfctl.c
+++ b/sbin/pfctl/pfctl.c
@@ -94,6 +94,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 *, u_int32_t);
+int pfctl_load_reassembly(struct pfctl *, u_int32_t);
int pfctl_load_syncookies(struct pfctl *, u_int8_t);
int pfctl_get_pool(int, struct pfctl_pool *, u_int32_t, u_int32_t, int,
char *);
@@ -2258,6 +2259,7 @@ pfctl_init_options(struct pfctl *pf)
pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT;
pf->debug = PF_DEBUG_URGENT;
+ pf->reassemble = 0;
pf->syncookies = false;
pf->syncookieswat[0] = PF_SYNCOOKIES_LOWATPCT;
@@ -2318,6 +2320,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;
+
/* load keepcounters */
if (pfctl_set_keepcounters(pf->dev, pf->keep_counters))
error = 1;
@@ -2415,6 +2422,28 @@ 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;
+ } else {
+ pf->reassemble = 0;
+ }
+
+ 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;
@@ -2513,6 +2542,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_load_syncookies(struct pfctl *pf, u_int8_t val)
{
struct pfctl_syncookies cookies;
diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c
index fca1a7aa7b8f..15ed8c29abd0 100644
--- a/sbin/pfctl/pfctl_parser.c
+++ b/sbin/pfctl/pfctl_parser.c
@@ -429,6 +429,7 @@ print_pool(struct pfctl_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 {
@@ -624,6 +625,10 @@ print_status(struct pfctl_status *s, struct pfctl_syncookies *cookies, int opts)
PFCTL_SYNCOOKIES_MODE_NAMES[cookies->mode]);
printf(" %-25s %s\n", "active",
s->syncookies_active ? "active" : "inactive");
+ printf("Reassemble %24s %s\n",
+ s->reass & PF_REASS_ENABLED ? "yes" : "no",
+ s->reass & PF_REASS_NODF ? "no-df" : ""
+ );
}
}
@@ -685,6 +690,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;
@@ -810,7 +816,8 @@ void
print_rule(struct pfctl_rule *r, const char *anchor_call, int verbose, int numeric)
{
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" };
@@ -946,7 +953,7 @@ print_rule(struct pfctl_rule *r, const char *anchor_call, int verbose, int numer
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)
@@ -988,6 +995,10 @@ print_rule(struct pfctl_rule *r, const char *anchor_call, int verbose, int numer
r->set_prio[1]);
comma = ",";
}
+ if (r->scrub_flags & PFSTATE_SETTOS) {
+ printf("%s tos 0x%2.2x", comma, r->set_tos);
+ comma = ",";
+ }
printf(" )");
}
if (!r->keep_state && r->action == PF_PASS && !anchor_call[0])
@@ -1113,26 +1124,43 @@ print_rule(struct pfctl_rule *r, const char *anchor_call, int verbose, int numer
}
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->rule_flag & PFRULE_FRAGMENT)
+ printf(" fragment");
if (r->action == PF_SCRUB) {
+ /* Scrub flags for old-style scrub. */
+ 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->rule_flag & PFRULE_REASSEMBLE_TCP)
printf(" reassemble tcp");
-
+ /* The PFRULE_FRAGMENT_NOREASS is set on all rules by default! */
printf(" fragment %sreassemble",
r->rule_flag & PFRULE_FRAGMENT_NOREASS ? "no " : "");
+ } else if (r->scrub_flags & PFSTATE_SCRUBMASK || r->min_ttl || r->max_mss) {
+ /* Scrub actions on normal rules. */
+ 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(")");
}
i = 0;
while (r->label[i][0])
diff --git a/sbin/pfctl/pfctl_parser.h b/sbin/pfctl/pfctl_parser.h
index 13151cc33829..c5da3408fb93 100644
--- a/sbin/pfctl/pfctl_parser.h
+++ b/sbin/pfctl/pfctl_parser.h
@@ -101,6 +101,7 @@ struct pfctl {
u_int32_t limit[PF_LIMIT_MAX];
u_int32_t debug;
u_int32_t hostid;
+ u_int32_t reassemble;
char *ifname;
bool keep_counters;
u_int8_t syncookies;
@@ -112,6 +113,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 {
@@ -285,6 +287,7 @@ void pfctl_move_pool(struct pfctl_pool *, struct pfctl_pool *);
void pfctl_clear_pool(struct pfctl_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 *);