summaryrefslogtreecommitdiff
path: root/sbin/pfctl
diff options
context:
space:
mode:
authorDaniel Hartmeier <dhartmei@cvs.openbsd.org>2002-06-08 07:58:08 +0000
committerDaniel Hartmeier <dhartmei@cvs.openbsd.org>2002-06-08 07:58:08 +0000
commit489f3c0c0c1e04a6675abfd96e5c5e086d82892a (patch)
treef3af1639feff5eba9694027797ca3b879e414449 /sbin/pfctl
parent4e342561d3ae3af75526df8d00ea562ad4088488 (diff)
Make state timeouts configurable per rule, like
pass in from any to any port www keep state (tcp.established 60) ok frantzen@
Diffstat (limited to 'sbin/pfctl')
-rw-r--r--sbin/pfctl/parse.y110
-rw-r--r--sbin/pfctl/pfctl.c7
-rw-r--r--sbin/pfctl/pfctl_parser.c26
-rw-r--r--sbin/pfctl/pfctl_parser.h9
4 files changed, 128 insertions, 24 deletions
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
index 4bf9bc08cdd..e6f88352269 100644
--- a/sbin/pfctl/parse.y
+++ b/sbin/pfctl/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.80 2002/06/08 01:00:23 henning Exp $ */
+/* $OpenBSD: parse.y,v 1.81 2002/06/08 07:58:07 dhartmei Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
@@ -103,6 +103,19 @@ struct node_icmp {
struct node_icmp *next;
};
+struct node_state_opt {
+ enum { PF_STATE_OPT_MAX=0, PF_STATE_OPT_TIMEOUT=1 };
+ int type;
+ union {
+ u_int32_t max_states;
+ struct {
+ int number;
+ u_int32_t seconds;
+ } timeout;
+ } data;
+ struct node_state_opt *next;
+};
+
struct peer {
struct node_host *host;
struct node_port *port;
@@ -158,6 +171,7 @@ typedef struct {
struct node_port *port;
struct node_uid *uid;
struct node_gid *gid;
+ struct node_state_opt *state_opt;
struct peer peer;
struct {
struct peer src, dst;
@@ -173,10 +187,8 @@ typedef struct {
struct range rport;
} *redirection;
struct {
- int action;
- struct {
- u_int32_t max_states;
- } options;
+ int action;
+ struct node_state_opt *options;
} keep_state;
} v;
int lineno;
@@ -208,7 +220,8 @@ typedef struct {
%type <v.route> route
%type <v.redirection> redirection
%type <v.string> label
-%type <v.keep_state> keep keep_opts
+%type <v.keep_state> keep
+%type <v.state_opt> state_opt_spec state_opt_list state_opt_item
%%
ruleset : /* empty */
@@ -237,6 +250,7 @@ pfrule : action dir log quick interface route af proto fromto
maxmss allowopts label
{
struct pf_rule r;
+ struct node_state_opt *o;
if (natmode) {
yyerror("filter rule not permitted in nat mode");
@@ -260,7 +274,33 @@ pfrule : action dir log quick interface route af proto fromto
r.flagset = $12.b2;
r.keep_state = $14.action;
- r.max_states = $14.options.max_states;
+ o = $14.options;
+ while (o) {
+ struct node_state_opt *p = o;
+
+ switch (o->type) {
+ case PF_STATE_OPT_MAX:
+ if (r.max_states) {
+ yyerror("state option 'max' "
+ "multiple definitions");
+ YYERROR;
+ }
+ r.max_states = o->data.max_states;
+ break;
+ case PF_STATE_OPT_TIMEOUT:
+ if (r.timeout[o->data.timeout.number]) {
+ yyerror("state timeout %s "
+ "multiple definitions",
+ pf_timeouts[o->data.
+ timeout.number].name);
+ YYERROR;
+ }
+ r.timeout[o->data.timeout.number] =
+ o->data.timeout.seconds;
+ }
+ o = o->next;
+ free(p);
+ }
if ($15)
r.rule_flag |= PFRULE_FRAGMENT;
@@ -974,23 +1014,61 @@ icmp6type : STRING {
;
keep : /* empty */ { $$.action = 0; }
- | KEEP STATE keep_opts {
+ | KEEP STATE state_opt_spec {
$$.action = PF_STATE_NORMAL;
- $$.options = $3.options;
+ $$.options = $3;
}
- | MODULATE STATE keep_opts {
+ | MODULATE STATE state_opt_spec {
$$.action = PF_STATE_MODULATE;
- $$.options = $3.options;
+ $$.options = $3;
+ }
+ ;
+
+state_opt_spec : /* empty */ { $$ = NULL; }
+ | '(' state_opt_list ')' { $$ = $2; }
+ ;
+
+state_opt_list : state_opt_item { $$ = $1; }
+ | state_opt_list ',' state_opt_item {
+ $$ = $1;
+ while ($1->next)
+ $1 = $1->next;
+ $1->next = $3;
}
;
-keep_opts : /* empty */ { $$.options.max_states = 0; }
- | '(' MAXIMUM NUMBER ')' {
- if ($3 <= 0) {
- yyerror("illegal keep states max value %d", $3);
+state_opt_item : MAXIMUM NUMBER {
+ if ($2 <= 0) {
+ yyerror("illegal states max value %d", $2);
+ YYERROR;
+ }
+ $$ = calloc(1, sizeof(struct node_state_opt));
+ if ($$ == NULL)
+ err(1, "state_opt_item: calloc");
+ $$->type = PF_STATE_OPT_MAX;
+ $$->data.max_states = $2;
+ $$->next = NULL;
+ }
+ | STRING NUMBER {
+ int i;
+
+ for (i = 0; pf_timeouts[i].name &&
+ strcmp(pf_timeouts[i].name, $1); ++i);
+ if (!pf_timeouts[i].name) {
+ yyerror("illegal timeout name %s", $1);
YYERROR;
}
- $$.options.max_states = $3;
+ if ($2 < 0) {
+ yyerror("illegal timeout value %d", $2);
+ YYERROR;
+ }
+ $$ = calloc(1, sizeof(struct node_state_opt));
+ if ($$ == NULL)
+ err(1, "state_opt_item: calloc");
+ $$->type = PF_STATE_OPT_TIMEOUT;
+ $$->data.timeout.number = pf_timeouts[i].timeout;
+ $$->data.timeout.seconds = $2;
+ $$->next = NULL;
}
;
diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
index b08b13261c2..9a31c58dea2 100644
--- a/sbin/pfctl/pfctl.c
+++ b/sbin/pfctl/pfctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl.c,v 1.69 2002/06/07 21:25:35 dhartmei Exp $ */
+/* $OpenBSD: pfctl.c,v 1.70 2002/06/08 07:58:07 dhartmei Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -92,10 +92,7 @@ char *state_kill[2];
char *infile;
-static const struct {
- const char *name;
- int timeout;
-} pf_timeouts[] = {
+const struct pf_timeout pf_timeouts[] = {
{ "tcp.first", PFTM_TCP_FIRST_PACKET },
{ "tcp.opening", PFTM_TCP_OPENING },
{ "tcp.established", PFTM_TCP_ESTABLISHED },
diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c
index fab149fb866..a11f13a42f8 100644
--- a/sbin/pfctl/pfctl_parser.c
+++ b/sbin/pfctl/pfctl_parser.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl_parser.c,v 1.79 2002/06/07 22:53:45 pb Exp $ */
+/* $OpenBSD: pfctl_parser.c,v 1.80 2002/06/08 07:58:07 dhartmei Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -530,6 +530,8 @@ print_status(struct pf_status *s)
void
print_rule(struct pf_rule *r)
{
+ int i, opts;
+
printf("@%d ", r->nr);
if (r->action == PF_PASS)
printf("pass ");
@@ -685,8 +687,28 @@ print_rule(struct pf_rule *r)
printf("keep state ");
else if (r->keep_state == PF_STATE_MODULATE)
printf("modulate state ");
+ opts = 0;
if (r->max_states)
- printf("(max %u) ", r->max_states);
+ opts = 1;
+ for (i = 0; !opts && i < PFTM_MAX; ++i)
+ if (r->timeout[i])
+ opts = 1;
+ if (opts) {
+ printf("(");
+ if (r->max_states) {
+ printf("max %u", r->max_states);
+ opts = 0;
+ }
+ for (i = 0; i < PFTM_MAX; ++i)
+ if (r->timeout[i]) {
+ if (!opts)
+ printf(", ");
+ opts = 0;
+ printf("%s %u", pf_timeouts[i].name,
+ r->timeout[i]);
+ }
+ printf(") ");
+ }
if (r->rule_flag & PFRULE_FRAGMENT)
printf("fragment ");
if (r->rule_flag & PFRULE_NODF)
diff --git a/sbin/pfctl/pfctl_parser.h b/sbin/pfctl/pfctl_parser.h
index e3773439cd8..807b0a18764 100644
--- a/sbin/pfctl/pfctl_parser.h
+++ b/sbin/pfctl/pfctl_parser.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl_parser.h,v 1.18 2002/06/07 19:33:03 henning Exp $ */
+/* $OpenBSD: pfctl_parser.h,v 1.19 2002/06/08 07:58:07 dhartmei Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -86,4 +86,11 @@ struct icmptypeent *geticmptypebyname(char *, u_int8_t);
struct icmpcodeent *geticmpcodebynumber(u_int8_t, u_int8_t, u_int8_t);
struct icmpcodeent *geticmpcodebyname(u_long, char *, u_int8_t);
+struct pf_timeout {
+ const char *name;
+ int timeout;
+};
+
+extern const struct pf_timeout pf_timeouts[];
+
#endif /* _PFCTL_PARSER_H_ */