summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sbin/pfctl/parse.y35
-rw-r--r--sbin/pfctl/pfctl_parser.c4
-rw-r--r--share/man/man5/pf.conf.57
-rw-r--r--sys/net/pf_norm.c53
-rw-r--r--sys/net/pfvar.h3
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;