diff options
Diffstat (limited to 'sbin')
| -rw-r--r-- | sbin/pfctl/parse.y | 119 | ||||
| -rw-r--r-- | sbin/pfctl/pf_print_state.c | 16 | ||||
| -rw-r--r-- | sbin/pfctl/pfctl.c | 39 | ||||
| -rw-r--r-- | sbin/pfctl/pfctl_parser.c | 58 | ||||
| -rw-r--r-- | sbin/pfctl/pfctl_parser.h | 3 |
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 *); |
