diff options
author | Daniel Hartmeier <dhartmei@cvs.openbsd.org> | 2002-06-08 07:58:08 +0000 |
---|---|---|
committer | Daniel Hartmeier <dhartmei@cvs.openbsd.org> | 2002-06-08 07:58:08 +0000 |
commit | 489f3c0c0c1e04a6675abfd96e5c5e086d82892a (patch) | |
tree | f3af1639feff5eba9694027797ca3b879e414449 /sbin | |
parent | 4e342561d3ae3af75526df8d00ea562ad4088488 (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')
-rw-r--r-- | sbin/pfctl/parse.y | 110 | ||||
-rw-r--r-- | sbin/pfctl/pfctl.c | 7 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_parser.c | 26 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_parser.h | 9 |
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_ */ |