diff options
-rw-r--r-- | sbin/pfctl/parse.y | 35 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_parser.c | 4 | ||||
-rw-r--r-- | share/man/man5/pf.conf.5 | 7 | ||||
-rw-r--r-- | sys/net/pf_norm.c | 53 | ||||
-rw-r--r-- | sys/net/pfvar.h | 3 |
5 files changed, 88 insertions, 14 deletions
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y index caaba9e4acb..9936423b602 100644 --- a/sbin/pfctl/parse.y +++ b/sbin/pfctl/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.62 2002/05/09 19:58:42 dhartmei Exp $ */ +/* $OpenBSD: parse.y,v 1.63 2002/05/09 21:58:12 jasoni Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -171,12 +171,12 @@ typedef struct { %token RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE %token ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF %token MINTTL IPV6ADDR ERROR ALLOWOPTS FASTROUTE ROUTETO DUPTO NO LABEL -%token NOROUTE FRAGMENT RUID EUID +%token NOROUTE FRAGMENT RUID EUID MAXMSS %token <v.string> STRING %token <v.number> NUMBER %token <v.i> PORTUNARY PORTBINARY %type <v.interface> interface if_list if_item_not if_item -%type <v.number> port icmptype icmp6type minttl uid +%type <v.number> port icmptype icmp6type minttl uid maxmss %type <v.i> no dir log quick af keep nodf allowopts fragment %type <v.b> action flag flags blockspec %type <v.range> dport rport @@ -213,7 +213,7 @@ varset : STRING PORTUNARY STRING } ; -pfrule : action dir log quick interface route af proto fromto ruid euid flags icmpspec keep fragment nodf minttl allowopts label +pfrule : action dir log quick interface route af proto fromto ruid euid flags icmpspec keep fragment nodf minttl maxmss allowopts label { struct pf_rule r; @@ -245,7 +245,9 @@ pfrule : action dir log quick interface route af proto fromto ruid euid flags i r.rule_flag |= PFRULE_NODF; if ($17) r.min_ttl = $17; - r.allow_opts = $18; + if ($18) + r.max_mss = $18; + r.allow_opts = $19; if ($6.rt) { r.rt = $6.rt; @@ -268,14 +270,14 @@ pfrule : action dir log quick interface route af proto fromto ruid euid flags i } } - if ($19) { - if (strlen($19) >= PF_RULE_LABEL_SIZE) { + if ($20) { + if (strlen($20) >= PF_RULE_LABEL_SIZE) { yyerror("rule label too long (max " "%d chars)", PF_RULE_LABEL_SIZE-1); YYERROR; } - strlcpy(r.label, $19, sizeof(r.label)); - free($19); + strlcpy(r.label, $20, sizeof(r.label)); + free($20); } expand_rule(&r, $5, $8, $9.src.host, $9.src.port, @@ -855,6 +857,16 @@ nodf : /* empty */ { $$ = 0; } | NODF { $$ = 1; } ; +maxmss : /* empty */ { $$ = 0; } + | MAXMSS NUMBER { + if ($2 < 0) { + yyerror("illegal max-mss value %d", $2); + YYERROR; + } + $$ = $2; + } + ; + allowopts : /* empty */ { $$ = 0; } | ALLOWOPTS { $$ = 1; } @@ -1332,6 +1344,10 @@ rule_consistent(struct pf_rule *r) yyerror("min-ttl only applies to scrub"); problems++; } + if (r->max_mss) { + yyerror("max-mss only applies to scrub"); + problems++; + } } if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP && (r->src.port_op || r->dst.port_op)) { @@ -1556,6 +1572,7 @@ lookup(char *s) { "label", LABEL}, { "log", LOG}, { "log-all", LOGALL}, + { "max-mss", MAXMSS}, { "min-ttl", MINTTL}, { "modulate", MODULATE}, { "nat", NAT}, diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c index 9d4739e0696..9d8cba5e749 100644 --- a/sbin/pfctl/pfctl_parser.c +++ b/sbin/pfctl/pfctl_parser.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_parser.c,v 1.68 2002/05/09 19:58:42 dhartmei Exp $ */ +/* $OpenBSD: pfctl_parser.c,v 1.69 2002/05/09 21:58:12 jasoni Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -848,6 +848,8 @@ print_rule(struct pf_rule *r) printf("no-df "); if (r->min_ttl) printf("min-ttl %d ", r->min_ttl); + if (r->max_mss) + printf("max-mss %d ", r->max_mss); if (r->allow_opts) printf("allow-opts "); if (r->label[0]) diff --git a/share/man/man5/pf.conf.5 b/share/man/man5/pf.conf.5 index 3d2589c2973..d05e4fb463d 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.43 2002/05/09 19:58:42 dhartmei Exp $ +.\" $OpenBSD: pf.conf.5,v 1.44 2002/05/09 21:58:12 jasoni Exp $ .\" .\" Copyright (c) 2001, Daniel Hartmeier .\" All rights reserved. @@ -55,7 +55,8 @@ rule = action ( "in" | "out" ) [ icmp-type | ipv6-icmp-type ] [ "keep state" ] [ "modulate state" ] [ "fragment" ] [ "no-df" ] [ "min-ttl" number ] - [ "allow-opts" ] [ "label" string ] . + [ "max-mss" number ] [ "allow-opts" ] + [ "label" string ] . action = "pass" | "block" [ return ] | "scrub" . return = "return-rst" | @@ -505,6 +506,8 @@ Clears the bit from a matching ip packet. .Ss min-ttl <number> Enforces a minimum ttl for matching ip packets. +.Ss max-mss <number> +Enforces a maximum mss for matching tcp packets. .Pp Normalization occurs before filtering, scrub rules and pass/block rules are evaluated independantly. diff --git a/sys/net/pf_norm.c b/sys/net/pf_norm.c index a525259d4fb..0ca14a4ffe2 100644 --- a/sys/net/pf_norm.c +++ b/sys/net/pf_norm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_norm.c,v 1.25 2002/05/06 15:49:54 jasoni Exp $ */ +/* $OpenBSD: pf_norm.c,v 1.26 2002/05/09 21:58:12 jasoni Exp $ */ /* * Copyright 2001 Niels Provos <provos@citi.umich.edu> @@ -89,6 +89,8 @@ struct mbuf *pf_reassemble(struct mbuf **, struct pf_fragment *, u_int16_t pf_cksum_fixup(u_int16_t, u_int16_t, u_int16_t); int pf_normalize_tcp(int, struct ifnet *, struct mbuf *, int, int, void *, struct pf_pdesc *); +int pf_normalize_tcpopt(struct pf_rule *, struct mbuf *, + struct tcphdr *, int); #define DPFPRINTF(x) if (pf_status.debug >= PF_DEBUG_MISC) printf x @@ -658,6 +660,10 @@ pf_normalize_tcp(int dir, struct ifnet *ifp, struct mbuf *m, int ipoff, rewrite = 1; } + /* Process options */ + if (r->max_mss && pf_normalize_tcpopt(r, m, th, off)) + rewrite = 1; + /* copy back packet headers if we sanitized */ if (rewrite) m_copyback(m, off, sizeof(*th), (caddr_t)th); @@ -670,3 +676,48 @@ pf_normalize_tcp(int dir, struct ifnet *ifp, struct mbuf *m, int ipoff, PFLOG_PACKET(ifp, h, m, AF_INET, dir, reason, rm); return (PF_DROP); } + +int +pf_normalize_tcpopt(struct pf_rule *r, struct mbuf *m, struct tcphdr *th, + int off) +{ + u_int16_t *mss; + int thoff; + int opt, cnt, optlen = 0; + int rewrite = 0; + u_char *optp; + + thoff = th->th_off << 2; + cnt = thoff - sizeof(struct tcphdr); + optp = mtod(m, caddr_t) + off + sizeof(struct tcphdr); + + for (; cnt > 0; cnt -= optlen, optp += optlen) { + opt = optp[0]; + if (opt == TCPOPT_EOL) + break; + if (opt == TCPOPT_NOP) + optlen = 1; + else { + if (cnt < 2) + break; + optlen = optp[1]; + if (optlen < 2 || optlen > cnt) + break; + } + switch (opt) { + case TCPOPT_MAXSEG: + mss = (u_int16_t *)(optp + 2); + if ((ntohs(*mss)) > r->max_mss) { + th->th_sum = pf_cksum_fixup(th->th_sum, + *mss, htons(r->max_mss)); + *mss = htons(r->max_mss); + rewrite = 1; + } + break; + default: + break; + } + } + + return (rewrite); +} diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index 5b3ddcf9c0b..d6a7726144f 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pfvar.h,v 1.70 2002/05/09 19:58:42 dhartmei Exp $ */ +/* $OpenBSD: pfvar.h,v 1.71 2002/05/09 21:58:12 jasoni Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -240,6 +240,7 @@ struct pf_rule { u_int16_t nr; u_int16_t return_icmp; + u_int16_t max_mss; struct pf_rule_uid ruid; struct pf_rule_uid euid; |