summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sbin/pfctl/parse.y39
-rw-r--r--sbin/pfctl/pfctl.c9
-rw-r--r--sbin/pfctl/pfctl_parser.c4
-rw-r--r--share/man/man5/pf.conf.59
-rw-r--r--sys/net/pf.c38
-rw-r--r--sys/net/pfvar.h5
6 files changed, 78 insertions, 26 deletions
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
index 5a9eb9619b5..c2bd501998a 100644
--- a/sbin/pfctl/parse.y
+++ b/sbin/pfctl/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.74 2002/06/07 19:33:03 henning Exp $ */
+/* $OpenBSD: parse.y,v 1.75 2002/06/07 21:25:35 dhartmei Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
@@ -170,6 +170,12 @@ typedef struct {
struct node_host *address;
struct range rport;
} *redirection;
+ struct {
+ int action;
+ struct {
+ u_int32_t max_states;
+ } options;
+ } keep_state;
} v;
int lineno;
} YYSTYPE;
@@ -180,13 +186,13 @@ 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 USER GROUP MAXMSS
+%token NOROUTE FRAGMENT USER GROUP MAXMSS MAXIMUM
%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 gid maxmss
-%type <v.i> no dir log quick af keep nodf allowopts fragment
+%type <v.i> no dir log quick af nodf allowopts fragment
%type <v.b> action flag flags blockspec
%type <v.range> dport rport
%type <v.proto> proto proto_list proto_item
@@ -200,6 +206,7 @@ typedef struct {
%type <v.route> route
%type <v.redirection> redirection
%type <v.string> label
+%type <v.keep_state> keep keep_opts
%%
ruleset : /* empty */
@@ -249,7 +256,8 @@ pfrule : action dir log quick interface route af proto fromto
r.flags = $12.b1;
r.flagset = $12.b2;
- r.keep_state = $14;
+ r.keep_state = $14.action;
+ r.max_states = $14.options.max_states;
if ($15)
r.rule_flag |= PFRULE_FRAGMENT;
@@ -958,9 +966,25 @@ icmp6type : STRING {
}
;
-keep : /* empty */ { $$ = 0; }
- | KEEP STATE { $$ = PF_STATE_NORMAL; }
- | MODULATE STATE { $$ = PF_STATE_MODULATE; }
+keep : /* empty */ { $$.action = 0; }
+ | KEEP STATE keep_opts {
+ $$.action = PF_STATE_NORMAL;
+ $$.options = $3.options;
+ }
+ | MODULATE STATE keep_opts {
+ $$.action = PF_STATE_MODULATE;
+ $$.options = $3.options;
+ }
+ ;
+
+keep_opts : /* empty */ { $$.options.max_states = 0; }
+ | '(' MAXIMUM NUMBER ')' {
+ if ($3 <= 0) {
+ yyerror("illegal keep states max value %d", $3);
+ YYERROR;
+ }
+ $$.options.max_states = $3;
+ }
;
fragment : /* empty */ { $$ = 0; }
@@ -1840,6 +1864,7 @@ lookup(char *s)
{ "label", LABEL},
{ "log", LOG},
{ "log-all", LOGALL},
+ { "max", MAXIMUM},
{ "max-mss", MAXMSS},
{ "min-ttl", MINTTL},
{ "modulate", MODULATE},
diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
index 81dd612d407..b08b13261c2 100644
--- a/sbin/pfctl/pfctl.c
+++ b/sbin/pfctl/pfctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl.c,v 1.68 2002/06/06 22:22:44 mickey Exp $ */
+/* $OpenBSD: pfctl.c,v 1.69 2002/06/07 21:25:35 dhartmei Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -410,9 +410,10 @@ pfctl_show_rules(int dev, int opts, int format)
default:
print_rule(&pr.rule);
if (opts & PF_OPT_VERBOSE)
- printf("[ Evaluations: %-10llu Packets: %-10llu "
- "Bytes: %-10llu ]\n\n", pr.rule.evaluations,
- pr.rule.packets, pr.rule.bytes);
+ printf("[ Evaluations: %-8llu Packets: %-8llu "
+ "Bytes: %-10llu States: %-6u]\n\n",
+ pr.rule.evaluations, pr.rule.packets,
+ pr.rule.bytes, pr.rule.states);
}
}
return (0);
diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c
index 51c8652821a..e843b6adba2 100644
--- a/sbin/pfctl/pfctl_parser.c
+++ b/sbin/pfctl/pfctl_parser.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl_parser.c,v 1.77 2002/06/07 19:30:40 henning Exp $ */
+/* $OpenBSD: pfctl_parser.c,v 1.78 2002/06/07 21:25:35 dhartmei Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -682,6 +682,8 @@ print_rule(struct pf_rule *r)
printf("keep state ");
else if (r->keep_state == PF_STATE_MODULATE)
printf("modulate state ");
+ if (r->max_states)
+ printf("(max %u) ", r->max_states);
if (r->rule_flag & PFRULE_FRAGMENT)
printf("fragment ");
if (r->rule_flag & PFRULE_NODF)
diff --git a/share/man/man5/pf.conf.5 b/share/man/man5/pf.conf.5
index 53bb1bb36a7..6fe407392bf 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.48 2002/06/07 19:41:23 henning Exp $
+.\" $OpenBSD: pf.conf.5,v 1.49 2002/06/07 21:25:36 dhartmei Exp $
.\"
.\" Copyright (c) 2001, Daniel Hartmeier
.\" All rights reserved.
@@ -53,7 +53,7 @@ rule = action ( "in" | "out" )
hosts
[ user ] [ group ] [ flags ]
[ icmp-type | ipv6-icmp-type ]
- [ "keep state" ] [ "modulate state" ]
+ [ ( "keep" | "modulate" ) "state" [ "(" "max" number ")" ] ]
[ "fragment" ] [ "no-df" ] [ "min-ttl" number ]
[ "max-mss" number ] [ "allow-opts" ]
[ "label" string ] .
@@ -461,6 +461,11 @@ see
.Xr nat.conf 5
.Pc
implicitly create state for connections.
+.Pp
+The "(max <number>)" option can be used to limit the number of concurrent
+states a rule can create to the specified maximum.
+When this limit is reached, further packets matching the rule that would
+create state are dropped, until existing states time out.
.Sh STATE MODULATION
Much of the security derived from TCP is attributable to how well the
initial sequence numbers (ISNs) are chosen.
diff --git a/sys/net/pf.c b/sys/net/pf.c
index 676a54dfebc..a47e9f737fb 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.216 2002/06/07 21:14:02 frantzen Exp $ */
+/* $OpenBSD: pf.c,v 1.217 2002/06/07 21:25:35 dhartmei Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -628,12 +628,12 @@ pf_purge_expired_states(void)
KASSERT(peer->state == cur->state);
RB_REMOVE(pf_state_tree, &tree_lan_ext, peer);
-
/* release NAT resources */
if (STATE_TRANSLATE(cur->state))
pf_put_sport(cur->state->proto,
htons(cur->state->gwy.port));
-
+ if (cur->state->rule.ptr != NULL)
+ cur->state->rule.ptr->states--;
pool_put(&pf_state_pl, cur->state);
pool_put(&pf_tree_pl, cur);
pool_put(&pf_tree_pl, peer);
@@ -3168,16 +3168,20 @@ pf_test_tcp(struct pf_rule **rm, int direction, struct ifnet *ifp,
binat != NULL || rdr != NULL) {
/* create new state */
u_int16_t len;
- struct pf_state *s;
+ struct pf_state *s = NULL;
len = pd->tot_len - off - (th->th_off << 2);
- s = pool_get(&pf_state_pl, PR_NOWAIT);
+ if (*rm == NULL || !(*rm)->max_states ||
+ (*rm)->states < (*rm)->max_states)
+ s = pool_get(&pf_state_pl, PR_NOWAIT);
if (s == NULL) {
if (nport && nat != NULL)
pf_put_sport(IPPROTO_TCP, nport);
REASON_SET(&reason, PFRES_MEMORY);
return (PF_DROP);
}
+ if (*rm != NULL)
+ (*rm)->states++;
s->rule.ptr = *rm;
s->allow_opts = *rm && (*rm)->allow_opts;
@@ -3417,14 +3421,18 @@ pf_test_udp(struct pf_rule **rm, int direction, struct ifnet *ifp,
if ((*rm != NULL && (*rm)->keep_state) || nat != NULL ||
binat != NULL || rdr != NULL) {
/* create new state */
- struct pf_state *s;
+ struct pf_state *s = NULL;
- s = pool_get(&pf_state_pl, PR_NOWAIT);
+ if (*rm == NULL || !(*rm)->max_states ||
+ (*rm)->states < (*rm)->max_states)
+ s = pool_get(&pf_state_pl, PR_NOWAIT);
if (s == NULL) {
if (nport && nat != NULL)
pf_put_sport(IPPROTO_UDP, nport);
return (PF_DROP);
}
+ if (*rm != NULL)
+ (*rm)->states++;
s->rule.ptr = *rm;
s->allow_opts = *rm && (*rm)->allow_opts;
@@ -3682,11 +3690,15 @@ pf_test_icmp(struct pf_rule **rm, int direction, struct ifnet *ifp,
if (!state_icmp && ((*rm != NULL && (*rm)->keep_state) ||
nat != NULL || rdr != NULL || binat != NULL)) {
/* create new state */
- struct pf_state *s;
+ struct pf_state *s = NULL;
- s = pool_get(&pf_state_pl, PR_NOWAIT);
+ if (*rm == NULL || !(*rm)->max_states ||
+ (*rm)->states < (*rm)->max_states)
+ s = pool_get(&pf_state_pl, PR_NOWAIT);
if (s == NULL)
return (PF_DROP);
+ if (*rm != NULL)
+ (*rm)->states++;
s->rule.ptr = *rm;
s->allow_opts = *rm && (*rm)->allow_opts;
@@ -3886,11 +3898,15 @@ pf_test_other(struct pf_rule **rm, int direction, struct ifnet *ifp,
if ((*rm != NULL && (*rm)->keep_state) || nat != NULL ||
rdr != NULL || binat != NULL) {
/* create new state */
- struct pf_state *s;
+ struct pf_state *s = NULL;
- s = pool_get(&pf_state_pl, PR_NOWAIT);
+ if (*rm == NULL || !(*rm)->max_states ||
+ (*rm)->states < (*rm)->max_states)
+ s = pool_get(&pf_state_pl, PR_NOWAIT);
if (s == NULL)
return (PF_DROP);
+ if (*rm != NULL)
+ (*rm)->states++;
s->rule.ptr = *rm;
s->allow_opts = *rm && (*rm)->allow_opts;
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index 5f500e768e9..9222f40c498 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfvar.h,v 1.74 2002/06/07 21:14:02 frantzen Exp $ */
+/* $OpenBSD: pfvar.h,v 1.75 2002/06/07 21:25:35 dhartmei Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -244,6 +244,9 @@ struct pf_rule {
struct ifnet *ifp;
struct ifnet *rt_ifp;
+ u_int32_t states;
+ u_int32_t max_states;
+
u_int16_t nr;
u_int16_t return_icmp;
u_int16_t max_mss;