--- ./contrib/pf/pfctl/parse.y.orig 2008-05-05 02:27:28.000000000 +0100 +++ ./contrib/pf/pfctl/parse.y 2008-05-05 04:46:41.000000000 +0100 @@ -412,7 +412,8 @@ %token PASS BLOCK 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 +%token MINTTL ERROR ALLOWOPTS ALLOWOPTSRA +%token FASTROUTE FILENAME ROUTETO DUPTO REPLYTO NO LABEL %token NOROUTE URPFFAILED FRAGMENT USER GROUP MAXMSS MAXIMUM TTL TOS DROP TABLE %token REASSEMBLE FRAGDROP FRAGCROP ANCHOR NATANCHOR RDRANCHOR BINATANCHOR %token SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY RANDOMID @@ -2107,7 +2108,10 @@ filter_opts.fragment = 1; } | ALLOWOPTS { - filter_opts.allowopts = 1; + filter_opts.allowopts = PF_ALLOWOPTS_ALL; + } + | ALLOWOPTSRA { + filter_opts.allowopts |= PF_ALLOWOPTS_RA; } | label { if (filter_opts.label) { @@ -4886,6 +4890,7 @@ static const struct keywords keywords[] = { { "all", ALL}, { "allow-opts", ALLOWOPTS}, + { "allow-ra-opt", ALLOWOPTSRA}, { "altq", ALTQ}, { "anchor", ANCHOR}, { "antispoof", ANTISPOOF}, --- ./contrib/pf/pfctl/pfctl_parser.c.orig 2008-05-05 02:27:35.000000000 +0100 +++ ./contrib/pf/pfctl/pfctl_parser.c 2008-05-05 04:45:23.000000000 +0100 @@ -966,8 +966,10 @@ printf(" min-ttl %d", r->min_ttl); if (r->max_mss) printf(" max-mss %d", r->max_mss); - if (r->allow_opts) + if (r->allow_opts & PF_ALLOWOPTS_ALL) printf(" allow-opts"); + else if (r->allow_opts & PF_ALLOWOPTS_RA) + printf(" allow-ra-opt"); if (r->action == PF_SCRUB) { if (r->rule_flag & PFRULE_REASSEMBLE_TCP) printf(" reassemble tcp"); --- ./sys/contrib/pf/net/pf.c.orig 2008-04-20 01:21:54.000000000 +0100 +++ ./sys/contrib/pf/net/pf.c 2008-05-05 04:49:00.000000000 +0100 @@ -6968,13 +6968,35 @@ } done: - if (action == PF_PASS && h->ip_hl > 5 && - !((s && s->allow_opts) || r->allow_opts)) { - action = PF_DROP; - REASON_SET(&reason, PFRES_IPOPTIONS); - log = 1; - DPFPRINTF(PF_DEBUG_MISC, - ("pf: dropping packet with ip options\n")); + if (action == PF_PASS && h->ip_hl > 5) { + do { + /* If allow-opts is set, allow any IP option. */ + if ((s && (s->allow_opts & PF_ALLOWOPTS_ALL)) || + (r->allow_opts & PF_ALLOWOPTS_ALL)) + break; + /* + * If allow-ra-opt is set, allow only the + * IP Router Alert option; it must be the first + * IP option, and its value is ignored. + */ + if ((s && (s->allow_opts & PF_ALLOWOPTS_RA)) || + (r->allow_opts & PF_ALLOWOPTS_RA)) { + uint8_t opt[4]; + if (pf_pull_hdr(m, sizeof(struct ip), + &opt[0], sizeof(opt), + &action, &reason, + AF_INET) != NULL) { + if (opt[0] == IPOPT_RA && + opt[1] == 4) + break; + } + } + action = PF_DROP; + REASON_SET(&reason, PFRES_IPOPTIONS); + log = 1; + DPFPRINTF(PF_DEBUG_MISC, + ("pf: dropping packet with ip options\n")); + } while (0); } if ((s && s->tag) || r->rtableid) --- ./sys/contrib/pf/net/pf_ioctl.c.orig 2008-03-29 00:24:36.000000000 +0000 +++ ./sys/contrib/pf/net/pf_ioctl.c 2008-05-05 04:49:00.000000000 +0100 @@ -352,6 +352,7 @@ /* default rule should never be garbage collected */ pf_default_rule.entries.tqe_prev = &pf_default_rule.entries.tqe_next; pf_default_rule.action = PF_PASS; + pf_default_rule.allow_opts = PF_ALLOWOPTS_RA; pf_default_rule.nr = -1; pf_default_rule.rtableid = -1; @@ -431,6 +432,7 @@ /* default rule should never be garbage collected */ pf_default_rule.entries.tqe_prev = &pf_default_rule.entries.tqe_next; pf_default_rule.action = PF_PASS; + pf_default_rule.allow_opts = PF_ALLOWOPTS_RA; pf_default_rule.nr = -1; pf_default_rule.rtableid = -1; --- ./sys/contrib/pf/net/pfvar.h.orig 2008-03-29 00:24:36.000000000 +0000 +++ ./sys/contrib/pf/net/pfvar.h 2008-05-05 04:49:00.000000000 +0100 @@ -670,6 +670,9 @@ u_int8_t flagset; u_int8_t min_ttl; u_int8_t allow_opts; +#define PF_ALLOWOPTS_ALL 0x1 +#define PF_ALLOWOPTS_RA 0x2 /* IP Router Alert */ +#define PF_ALLOWOPTS_MASK 0x3 u_int8_t rt; u_int8_t return_ttl; u_int8_t tos;