svn commit: r218783 - in projects/pf/pf45: contrib/pf/pfctl
sys/contrib/pf/net sys/modules/pf sys/modules/pfsync
sys/netinet sys/netinet/ipfw sys/netinet6 sys/netipsec sys/sys
Bjoern A. Zeeb
bz at FreeBSD.org
Thu Feb 17 22:05:00 UTC 2011
Author: bz
Date: Thu Feb 17 22:05:00 2011
New Revision: 218783
URL: http://svn.freebsd.org/changeset/base/218783
Log:
Import the latest pf45 patch (with minor whitespace adjustments already)
for cleanup and finalizing.
Submitted by: eri
Discussed with: eri
Obtained from: http://docs.FreeBSD.org/cgi/mid.cgi?AANLkTinXNRKSwjuOeQkDTANhSSbHYHZnf4SvaFHbEdrg
Added:
projects/pf/pf45/sys/contrib/pf/net/pf_lb.c (contents, props changed)
projects/pf/pf45/sys/modules/pfsync/
projects/pf/pf45/sys/modules/pfsync/Makefile (contents, props changed)
Modified:
projects/pf/pf45/contrib/pf/pfctl/parse.y
projects/pf/pf45/contrib/pf/pfctl/pf_print_state.c
projects/pf/pf45/contrib/pf/pfctl/pfctl.8
projects/pf/pf45/contrib/pf/pfctl/pfctl.c
projects/pf/pf45/contrib/pf/pfctl/pfctl.h
projects/pf/pf45/contrib/pf/pfctl/pfctl_altq.c
projects/pf/pf45/contrib/pf/pfctl/pfctl_optimize.c
projects/pf/pf45/contrib/pf/pfctl/pfctl_osfp.c
projects/pf/pf45/contrib/pf/pfctl/pfctl_parser.c
projects/pf/pf45/contrib/pf/pfctl/pfctl_parser.h
projects/pf/pf45/contrib/pf/pfctl/pfctl_qstats.c
projects/pf/pf45/contrib/pf/pfctl/pfctl_radix.c
projects/pf/pf45/contrib/pf/pfctl/pfctl_table.c
projects/pf/pf45/sys/contrib/pf/net/if_pflog.c
projects/pf/pf45/sys/contrib/pf/net/if_pflog.h
projects/pf/pf45/sys/contrib/pf/net/if_pfsync.c
projects/pf/pf45/sys/contrib/pf/net/if_pfsync.h
projects/pf/pf45/sys/contrib/pf/net/pf.c
projects/pf/pf45/sys/contrib/pf/net/pf_if.c
projects/pf/pf45/sys/contrib/pf/net/pf_ioctl.c
projects/pf/pf45/sys/contrib/pf/net/pf_mtag.h
projects/pf/pf45/sys/contrib/pf/net/pf_norm.c
projects/pf/pf45/sys/contrib/pf/net/pf_osfp.c
projects/pf/pf45/sys/contrib/pf/net/pf_ruleset.c
projects/pf/pf45/sys/contrib/pf/net/pf_table.c
projects/pf/pf45/sys/contrib/pf/net/pfvar.h
projects/pf/pf45/sys/modules/pf/Makefile
projects/pf/pf45/sys/netinet/in_gif.c
projects/pf/pf45/sys/netinet/ip_icmp.c
projects/pf/pf45/sys/netinet/ipfw/ip_fw2.c
projects/pf/pf45/sys/netinet/raw_ip.c
projects/pf/pf45/sys/netinet6/icmp6.c
projects/pf/pf45/sys/netinet6/in6_gif.c
projects/pf/pf45/sys/netipsec/ipsec_input.c
projects/pf/pf45/sys/netipsec/ipsec_output.c
projects/pf/pf45/sys/netipsec/xform_ipip.c
projects/pf/pf45/sys/sys/mbuf.h
Modified: projects/pf/pf45/contrib/pf/pfctl/parse.y
==============================================================================
--- projects/pf/pf45/contrib/pf/pfctl/parse.y Thu Feb 17 21:35:10 2011 (r218782)
+++ projects/pf/pf45/contrib/pf/pfctl/parse.y Thu Feb 17 22:05:00 2011 (r218783)
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.517 2007/02/03 23:26:40 dhartmei Exp $ */
+/* $OpenBSD: parse.y,v 1.554 2008/10/17 12:59:53 henning Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
@@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/stat.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
@@ -46,6 +47,7 @@ __FBSDID("$FreeBSD$");
#include <altq/altq_hfsc.h>
#include <stdio.h>
+#include <unistd.h>
#include <stdlib.h>
#include <netdb.h>
#include <stdarg.h>
@@ -62,15 +64,8 @@ __FBSDID("$FreeBSD$");
#include "pfctl_parser.h"
#include "pfctl.h"
-#ifdef __FreeBSD__
-#define HTONL(x) (x) = htonl((__uint32_t)(x))
-#endif
-
static struct pfctl *pf = NULL;
-static FILE *fin = NULL;
static int debug = 0;
-static int lineno = 1;
-static int errors = 0;
static int rulestate = 0;
static u_int16_t returnicmpdefault =
(ICMP_UNREACH << 8) | ICMP_UNREACH_PORT;
@@ -80,6 +75,39 @@ static int blockpolicy = PFRULE_DROP;
static int require_order = 1;
static int default_statelock;
+TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files);
+static struct file {
+ TAILQ_ENTRY(file) entry;
+ FILE *stream;
+ char *name;
+ int lineno;
+ int errors;
+} *file;
+struct file *pushfile(const char *, int);
+int popfile(void);
+int check_file_secrecy(int, const char *);
+int yyparse(void);
+int yylex(void);
+int yyerror(const char *, ...);
+int kw_cmp(const void *, const void *);
+int lookup(char *);
+int lgetc(int);
+int lungetc(int);
+int findeol(void);
+
+TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead);
+struct sym {
+ TAILQ_ENTRY(sym) entry;
+ int used;
+ int persist;
+ char *nam;
+ char *val;
+};
+int symset(const char *, const char *, int);
+char *symget(const char *);
+
+int atoul(char *, u_long *);
+
enum {
PFCTL_STATE_NONE,
PFCTL_STATE_OPTION,
@@ -128,7 +156,8 @@ enum { PF_STATE_OPT_MAX, PF_STATE_OPT_NO
PF_STATE_OPT_MAX_SRC_STATES, PF_STATE_OPT_MAX_SRC_CONN,
PF_STATE_OPT_MAX_SRC_CONN_RATE, PF_STATE_OPT_MAX_SRC_NODES,
PF_STATE_OPT_OVERLOAD, PF_STATE_OPT_STATELOCK,
- PF_STATE_OPT_TIMEOUT, PF_STATE_OPT_SLOPPY };
+ PF_STATE_OPT_TIMEOUT, PF_STATE_OPT_SLOPPY,
+ PF_STATE_OPT_PFLOW };
enum { PF_SRCTRACK_NONE, PF_SRCTRACK, PF_SRCTRACK_GLOBAL, PF_SRCTRACK_RULE };
@@ -206,12 +235,16 @@ struct filter_opts {
char *tag;
char *match_tag;
u_int8_t match_tag_not;
- int rtableid;
+ u_int rtableid;
+ struct {
+ struct node_host *addr;
+ u_int16_t port;
+ } divert;
} filter_opts;
struct antispoof_opts {
char *label;
- int rtableid;
+ u_int rtableid;
} antispoof_opts;
struct scrub_opts {
@@ -219,13 +252,17 @@ struct scrub_opts {
#define SOM_MINTTL 0x01
#define SOM_MAXMSS 0x02
#define SOM_FRAGCACHE 0x04
+#define SOM_SETTOS 0x08
int nodf;
int minttl;
int maxmss;
+ int settos;
int fragcache;
int randomid;
int reassemble_tcp;
- int rtableid;
+ char *match_tag;
+ u_int8_t match_tag_not;
+ u_int rtableid;
} scrub_opts;
struct queue_opts {
@@ -260,63 +297,45 @@ struct pool_opts {
} pool_opts;
-struct node_hfsc_opts hfsc_opts;
+struct node_hfsc_opts hfsc_opts;
+struct node_state_opt *keep_state_defaults = NULL;
-int yyerror(const char *, ...);
-int disallow_table(struct node_host *, const char *);
-int disallow_urpf_failed(struct node_host *, const char *);
-int disallow_alias(struct node_host *, const char *);
-int rule_consistent(struct pf_rule *, int);
-int filter_consistent(struct pf_rule *, int);
-int nat_consistent(struct pf_rule *);
-int rdr_consistent(struct pf_rule *);
-int process_tabledef(char *, struct table_opts *);
-int yyparse(void);
-void expand_label_str(char *, size_t, const char *, const char *);
-void expand_label_if(const char *, char *, size_t, const char *);
-void expand_label_addr(const char *, char *, size_t, u_int8_t,
- struct node_host *);
-void expand_label_port(const char *, char *, size_t, struct node_port *);
-void expand_label_proto(const char *, char *, size_t, u_int8_t);
-void expand_label_nr(const char *, char *, size_t);
-void expand_label(char *, size_t, const char *, u_int8_t, struct node_host *,
- struct node_port *, struct node_host *, struct node_port *,
- u_int8_t);
-void expand_rule(struct pf_rule *, struct node_if *, struct node_host *,
- struct node_proto *, struct node_os*, struct node_host *,
- struct node_port *, struct node_host *, struct node_port *,
- struct node_uid *, struct node_gid *, struct node_icmp *,
- const char *);
-int expand_altq(struct pf_altq *, struct node_if *, struct node_queue *,
- struct node_queue_bw bwspec, struct node_queue_opt *);
-int expand_queue(struct pf_altq *, struct node_if *, struct node_queue *,
- struct node_queue_bw, struct node_queue_opt *);
-int expand_skip_interface(struct node_if *);
+int disallow_table(struct node_host *, const char *);
+int disallow_urpf_failed(struct node_host *, const char *);
+int disallow_alias(struct node_host *, const char *);
+int rule_consistent(struct pf_rule *, int);
+int filter_consistent(struct pf_rule *, int);
+int nat_consistent(struct pf_rule *);
+int rdr_consistent(struct pf_rule *);
+int process_tabledef(char *, struct table_opts *);
+void expand_label_str(char *, size_t, const char *, const char *);
+void expand_label_if(const char *, char *, size_t, const char *);
+void expand_label_addr(const char *, char *, size_t, u_int8_t,
+ struct node_host *);
+void expand_label_port(const char *, char *, size_t,
+ struct node_port *);
+void expand_label_proto(const char *, char *, size_t, u_int8_t);
+void expand_label_nr(const char *, char *, size_t);
+void expand_label(char *, size_t, const char *, u_int8_t,
+ struct node_host *, struct node_port *, struct node_host *,
+ struct node_port *, u_int8_t);
+void expand_rule(struct pf_rule *, struct node_if *,
+ struct node_host *, struct node_proto *, struct node_os *,
+ struct node_host *, struct node_port *, struct node_host *,
+ struct node_port *, struct node_uid *, struct node_gid *,
+ struct node_icmp *, const char *);
+int expand_altq(struct pf_altq *, struct node_if *,
+ struct node_queue *, struct node_queue_bw bwspec,
+ struct node_queue_opt *);
+int expand_queue(struct pf_altq *, struct node_if *,
+ struct node_queue *, struct node_queue_bw,
+ struct node_queue_opt *);
+int expand_skip_interface(struct node_if *);
int check_rulestate(int);
-int kw_cmp(const void *, const void *);
-int lookup(char *);
-int lgetc(FILE *);
-int lungetc(int);
-int findeol(void);
-int yylex(void);
-int atoul(char *, u_long *);
int getservice(char *);
int rule_label(struct pf_rule *, char *);
-TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead);
-struct sym {
- TAILQ_ENTRY(sym) entries;
- int used;
- int persist;
- char *nam;
- char *val;
-};
-
-
-int symset(const char *, const char *, int);
-char *symget(const char *);
-
void mv_rules(struct pf_ruleset *, struct pf_ruleset *);
void decide_address_family(struct node_host *, sa_family_t *);
void remove_invalid_hosts(struct node_host **, sa_family_t *);
@@ -334,10 +353,11 @@ struct loadanchors {
typedef struct {
union {
- u_int32_t number;
+ int64_t number;
+ double probability;
int i;
char *string;
- int rtableid;
+ u_int rtableid;
struct {
u_int8_t b1;
u_int8_t b2;
@@ -403,6 +423,10 @@ typedef struct {
int lineno;
} YYSTYPE;
+#define PPORT_RANGE 1
+#define PPORT_STAR 2
+int parseport(char *, struct range *r, int);
+
#define DYNIF_MULTIADDR(addr) ((addr).type == PF_ADDR_DYNIFTL && \
(!((addr).iflags & PFI_AFLAG_NOALIAS) || \
!isdigit((addr).v.ifname[strlen((addr).v.ifname)-1])))
@@ -417,32 +441,37 @@ typedef struct {
%token REASSEMBLE FRAGDROP FRAGCROP ANCHOR NATANCHOR RDRANCHOR BINATANCHOR
%token SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY RANDOMID
%token REQUIREORDER SYNPROXY FINGERPRINTS NOSYNC DEBUG SKIP HOSTID
-%token ANTISPOOF FOR
+%token ANTISPOOF FOR INCLUDE
%token BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT PROBABILITY
%token ALTQ CBQ PRIQ HFSC BANDWIDTH TBRSIZE LINKSHARE REALTIME UPPERLIMIT
%token QUEUE PRIORITY QLIMIT RTABLE
%token LOAD RULESET_OPTIMIZATION
%token STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE
-%token MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH SLOPPY
-%token TAGGED TAG IFBOUND FLOATING STATEPOLICY ROUTE
+%token MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH SLOPPY PFLOW
+%token TAGGED TAG IFBOUND FLOATING STATEPOLICY STATEDEFAULTS ROUTE SETTOS
+%token DIVERTTO DIVERTREPLY
%token <v.string> STRING
+%token <v.number> NUMBER
%token <v.i> PORTBINARY
%type <v.interface> interface if_list if_item_not if_item
%type <v.number> number icmptype icmp6type uid gid
%type <v.number> tos not yesno
+%type <v.probability> probability
%type <v.i> no dir af fragcache optimizer
%type <v.i> sourcetrack flush unaryop statelock
-%type <v.b> action nataction natpass scrubaction
+%type <v.b> action nataction natpasslog scrubaction
%type <v.b> flags flag blockspec
-%type <v.range> port rport
+%type <v.range> portplain portstar portrange
%type <v.hashkey> hashkey
%type <v.proto> proto proto_list proto_item
+%type <v.number> protoval
%type <v.icmp> icmpspec
%type <v.icmp> icmp_list icmp_item
%type <v.icmp> icmp6_list icmp6_item
+%type <v.number> reticmpspec reticmp6spec
%type <v.fromto> fromto
%type <v.peer> ipportspec from to
-%type <v.host> ipspec xhost host dynaddr host_list
+%type <v.host> ipspec toipspec xhost host dynaddr host_list
%type <v.host> redir_host_list redirspec
%type <v.host> route_host route_host_list routespec
%type <v.os> os xos os_list
@@ -451,7 +480,8 @@ typedef struct {
%type <v.gid> gids gid_list gid_item
%type <v.route> route
%type <v.redirection> redirection redirpool
-%type <v.string> label string tag anchorname
+%type <v.string> label stringall tag anchorname
+%type <v.string> string varstring numberstring
%type <v.keep_state> keep
%type <v.state_opt> state_opt_spec state_opt_list state_opt_item
%type <v.logquick> logquick quick log logopts logopt
@@ -474,6 +504,7 @@ typedef struct {
%%
ruleset : /* empty */
+ | ruleset include '\n'
| ruleset '\n'
| ruleset option '\n'
| ruleset scrubrule '\n'
@@ -488,7 +519,22 @@ ruleset : /* empty */
| ruleset antispoof '\n'
| ruleset tabledef '\n'
| '{' fakeanchor '}' '\n';
- | ruleset error '\n' { errors++; }
+ | ruleset error '\n' { file->errors++; }
+ ;
+
+include : INCLUDE STRING {
+ struct file *nfile;
+
+ if ((nfile = pushfile($2, 0)) == NULL) {
+ yyerror("failed to include file %s", $2);
+ free($2);
+ YYERROR;
+ }
+ free($2);
+
+ file = nfile;
+ lungetc('\n');
+ }
;
/*
@@ -511,7 +557,7 @@ optimizer : string {
else if (!strcmp($1, "profile"))
$$ = PF_OPTIMIZE_BASIC | PF_OPTIMIZE_PROFILE;
else {
- yyerror("unknown ruleset-optimization %s", $$);
+ yyerror("unknown ruleset-optimization %s", $1);
YYERROR;
}
}
@@ -536,10 +582,10 @@ option : SET OPTIMIZATION STRING {
}
}
| SET TIMEOUT timeout_spec
- | SET TIMEOUT '{' timeout_list '}'
+ | SET TIMEOUT '{' optnl timeout_list '}'
| SET LIMIT limit_spec
- | SET LIMIT '{' limit_list '}'
- | SET LOGINTERFACE STRING {
+ | SET LIMIT '{' optnl limit_list '}'
+ | SET LOGINTERFACE stringall {
if (check_rulestate(PFCTL_STATE_OPTION)) {
free($3);
YYERROR;
@@ -552,7 +598,7 @@ option : SET OPTIMIZATION STRING {
free($3);
}
| SET HOSTID number {
- if ($3 == 0) {
+ if ($3 == 0 || $3 > UINT_MAX) {
yyerror("hostid must be non-zero");
YYERROR;
}
@@ -629,9 +675,24 @@ option : SET OPTIMIZATION STRING {
YYERROR;
}
}
+ | SET STATEDEFAULTS state_opt_list {
+ if (keep_state_defaults != NULL) {
+ yyerror("cannot redefine state-defaults");
+ YYERROR;
+ }
+ keep_state_defaults = $3;
+ }
;
-string : string STRING {
+stringall : STRING { $$ = $1; }
+ | ALL {
+ if (($$ = strdup("all")) == NULL) {
+ err(1, "stringall: strdup");
+ }
+ }
+ ;
+
+string : STRING string {
if (asprintf(&$$, "%s %s", $1, $2) == -1)
err(1, "string: asprintf");
free($1);
@@ -640,7 +701,27 @@ string : string STRING {
| STRING
;
-varset : STRING '=' string {
+varstring : numberstring varstring {
+ if (asprintf(&$$, "%s %s", $1, $2) == -1)
+ err(1, "string: asprintf");
+ free($1);
+ free($2);
+ }
+ | numberstring
+ ;
+
+numberstring : NUMBER {
+ char *s;
+ if (asprintf(&s, "%lld", (long long)$1) == -1) {
+ yyerror("string: asprintf");
+ YYERROR;
+ }
+ $$ = s;
+ }
+ | STRING
+ ;
+
+varset : STRING '=' varstring {
if (pf->opts & PF_OPT_VERBOSE)
printf("%s = \"%s\"\n", $1, $3);
if (symset($1, $3, 0) == -1)
@@ -654,14 +735,10 @@ anchorname : STRING { $$ = $1; }
| /* empty */ { $$ = NULL; }
;
-optnl : optnl '\n'
- |
- ;
-
-pfa_anchorlist : pfrule optnl
- | anchorrule optnl
- | pfa_anchorlist pfrule optnl
- | pfa_anchorlist anchorrule optnl
+pfa_anchorlist : /* empty */
+ | pfa_anchorlist '\n'
+ | pfa_anchorlist pfrule '\n'
+ | pfa_anchorlist anchorrule '\n'
;
pfa_anchor : '{'
@@ -694,6 +771,7 @@ anchorrule : ANCHOR anchorname dir quick
filter_opts pfa_anchor
{
struct pf_rule r;
+ struct node_proto *proto;
if (check_rulestate(PFCTL_STATE_FILTER)) {
if ($2)
@@ -744,6 +822,55 @@ anchorrule : ANCHOR anchorname dir quick
r.prob = $9.prob;
r.rtableid = $9.rtableid;
+ if ($9.tag)
+ if (strlcpy(r.tagname, $9.tag,
+ PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
+ yyerror("tag too long, max %u chars",
+ PF_TAG_NAME_SIZE - 1);
+ YYERROR;
+ }
+ if ($9.match_tag)
+ if (strlcpy(r.match_tagname, $9.match_tag,
+ PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
+ yyerror("tag too long, max %u chars",
+ PF_TAG_NAME_SIZE - 1);
+ YYERROR;
+ }
+ r.match_tag_not = $9.match_tag_not;
+ if (rule_label(&r, $9.label))
+ YYERROR;
+ free($9.label);
+ r.flags = $9.flags.b1;
+ r.flagset = $9.flags.b2;
+ if (($9.flags.b1 & $9.flags.b2) != $9.flags.b1) {
+ yyerror("flags always false");
+ YYERROR;
+ }
+ if ($9.flags.b1 || $9.flags.b2 || $8.src_os) {
+ for (proto = $7; proto != NULL &&
+ proto->proto != IPPROTO_TCP;
+ proto = proto->next)
+ ; /* nothing */
+ if (proto == NULL && $7 != NULL) {
+ if ($9.flags.b1 || $9.flags.b2)
+ yyerror(
+ "flags only apply to tcp");
+ if ($8.src_os)
+ yyerror(
+ "OS fingerprinting only "
+ "applies to tcp");
+ YYERROR;
+ }
+ }
+
+ r.tos = $9.tos;
+
+ if ($9.keep.action) {
+ yyerror("cannot specify state handling "
+ "on anchors");
+ YYERROR;
+ }
+
if ($9.match_tag)
if (strlcpy(r.match_tagname, $9.match_tag,
PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
@@ -758,8 +885,8 @@ anchorrule : ANCHOR anchorname dir quick
expand_rule(&r, $5, NULL, $7, $8.src_os,
$8.src.host, $8.src.port, $8.dst.host, $8.dst.port,
- 0, 0, 0, pf->astack[pf->asd + 1] ?
- pf->alast->name : $2);
+ $9.uid, $9.gid, $9.icmpspec,
+ pf->astack[pf->asd + 1] ? pf->alast->name : $2);
free($2);
pf->astack[pf->asd + 1] = NULL;
}
@@ -939,8 +1066,20 @@ scrubrule : scrubaction dir logquick int
r.min_ttl = $8.minttl;
if ($8.maxmss)
r.max_mss = $8.maxmss;
+ if ($8.marker & SOM_SETTOS) {
+ r.rule_flag |= PFRULE_SET_TOS;
+ r.set_tos = $8.settos;
+ }
if ($8.fragcache)
r.rule_flag |= $8.fragcache;
+ if ($8.match_tag)
+ if (strlcpy(r.match_tagname, $8.match_tag,
+ PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
+ yyerror("tag too long, max %u chars",
+ PF_TAG_NAME_SIZE - 1);
+ YYERROR;
+ }
+ r.match_tag_not = $8.match_tag_not;
r.rtableid = $8.rtableid;
expand_rule(&r, $4, NULL, $6, $7.src_os,
@@ -973,30 +1112,38 @@ scrub_opt : NODF {
}
scrub_opts.nodf = 1;
}
- | MINTTL number {
+ | MINTTL NUMBER {
if (scrub_opts.marker & SOM_MINTTL) {
yyerror("min-ttl cannot be respecified");
YYERROR;
}
- if ($2 > 255) {
+ if ($2 < 0 || $2 > 255) {
yyerror("illegal min-ttl value %d", $2);
YYERROR;
}
scrub_opts.marker |= SOM_MINTTL;
scrub_opts.minttl = $2;
}
- | MAXMSS number {
+ | MAXMSS NUMBER {
if (scrub_opts.marker & SOM_MAXMSS) {
yyerror("max-mss cannot be respecified");
YYERROR;
}
- if ($2 > 65535) {
+ if ($2 < 0 || $2 > 65535) {
yyerror("illegal max-mss value %d", $2);
YYERROR;
}
scrub_opts.marker |= SOM_MAXMSS;
scrub_opts.maxmss = $2;
}
+ | SETTOS tos {
+ if (scrub_opts.marker & SOM_SETTOS) {
+ yyerror("set-tos cannot be respecified");
+ YYERROR;
+ }
+ scrub_opts.marker |= SOM_SETTOS;
+ scrub_opts.settos = $2;
+ }
| fragcache {
if (scrub_opts.marker & SOM_FRAGCACHE) {
yyerror("fragcache cannot be respecified");
@@ -1026,15 +1173,17 @@ scrub_opt : NODF {
}
scrub_opts.randomid = 1;
}
- | RTABLE number {
-#ifndef __FreeBSD__
- if ($2 > RT_TABLEID_MAX || $2 < 0) {
+ | RTABLE NUMBER {
+ if ($2 < 0 /* || $2 > RT_TABLEID_MAX */) {
yyerror("invalid rtable id");
YYERROR;
}
-#endif
scrub_opts.rtableid = $2;
}
+ | not TAGGED string {
+ scrub_opts.match_tag = $3;
+ scrub_opts.match_tag_not = $1;
+ }
;
fragcache : FRAGMENT REASSEMBLE { $$ = 0; /* default */ }
@@ -1108,6 +1257,7 @@ antispoof : ANTISPOOF logquick antispoof
r.action = PF_DROP;
r.direction = PF_IN;
r.log = $2.log;
+ r.logif = $2.logif;
r.quick = $2.quick;
r.af = $4;
if (rule_label(&r, $5.label))
@@ -1128,20 +1278,20 @@ antispoof : ANTISPOOF logquick antispoof
}
;
-antispoof_ifspc : FOR antispoof_if { $$ = $2; }
- | FOR '{' antispoof_iflst '}' { $$ = $3; }
+antispoof_ifspc : FOR antispoof_if { $$ = $2; }
+ | FOR '{' optnl antispoof_iflst '}' { $$ = $4; }
;
-antispoof_iflst : antispoof_if { $$ = $1; }
- | antispoof_iflst comma antispoof_if {
+antispoof_iflst : antispoof_if optnl { $$ = $1; }
+ | antispoof_iflst comma antispoof_if optnl {
$1->tail->next = $3;
$1->tail = $3;
$$ = $1;
}
;
-antispoof_if : if_item { $$ = $1; }
- | '(' if_item ')' {
+antispoof_if : if_item { $$ = $1; }
+ | '(' if_item ')' {
$2->dynamic = 1;
$$ = $2;
}
@@ -1171,13 +1321,11 @@ antispoof_opt : label {
}
antispoof_opts.label = $1;
}
- | RTABLE number {
-#ifndef __FreeBSD__
- if ($2 > RT_TABLEID_MAX || $2 < 0) {
+ | RTABLE NUMBER {
+ if ($2 < 0 /* || $2 > RT_TABLEID_MAX */ ) {
yyerror("invalid rtable id");
YYERROR;
}
-#endif
antispoof_opts.rtableid = $2;
}
;
@@ -1239,6 +1387,8 @@ table_opt : STRING {
table_opts.flags |= PFR_TFLAG_CONST;
else if (!strcmp($1, "persist"))
table_opts.flags |= PFR_TFLAG_PERSIST;
+ else if (!strcmp($1, "counters"))
+ table_opts.flags |= PFR_TFLAG_COUNTERS;
else {
yyerror("invalid table option '%s'", $1);
free($1);
@@ -1246,15 +1396,19 @@ table_opt : STRING {
}
free($1);
}
- | '{' '}' { table_opts.init_addr = 1; }
- | '{' host_list '}' {
+ | '{' optnl '}' { table_opts.init_addr = 1; }
+ | '{' optnl host_list '}' {
struct node_host *n;
struct node_tinit *ti;
- for (n = $2; n != NULL; n = n->next) {
+ for (n = $3; n != NULL; n = n->next) {
switch (n->addr.type) {
case PF_ADDR_ADDRMASK:
continue; /* ok */
+ case PF_ADDR_RANGE:
+ yyerror("address ranges are not "
+ "permitted inside tables");
+ break;
case PF_ADDR_DYNIFTL:
yyerror("dynamic addresses are not "
"permitted inside tables");
@@ -1278,7 +1432,7 @@ table_opt : STRING {
}
if (!(ti = calloc(1, sizeof(*ti))))
err(1, "table_opt: calloc");
- ti->host = $2;
+ ti->host = $3;
SIMPLEQ_INSERT_TAIL(&table_opts.init_nodes, ti,
entries);
table_opts.init_addr = 1;
@@ -1387,24 +1541,24 @@ queue_opt : BANDWIDTH bandwidth {
queue_opts.marker |= QOM_BWSPEC;
queue_opts.queue_bwspec = $2;
}
- | PRIORITY number {
+ | PRIORITY NUMBER {
if (queue_opts.marker & QOM_PRIORITY) {
yyerror("priority cannot be respecified");
YYERROR;
}
- if ($2 > 255) {
+ if ($2 < 0 || $2 > 255) {
yyerror("priority out of range: max 255");
YYERROR;
}
queue_opts.marker |= QOM_PRIORITY;
queue_opts.priority = $2;
}
- | QLIMIT number {
+ | QLIMIT NUMBER {
if (queue_opts.marker & QOM_QLIMIT) {
yyerror("qlimit cannot be respecified");
YYERROR;
}
- if ($2 > 65535) {
+ if ($2 < 0 || $2 > 65535) {
yyerror("qlimit out of range: max 65535");
YYERROR;
}
@@ -1419,12 +1573,12 @@ queue_opt : BANDWIDTH bandwidth {
queue_opts.marker |= QOM_SCHEDULER;
queue_opts.scheduler = $1;
}
- | TBRSIZE number {
+ | TBRSIZE NUMBER {
if (queue_opts.marker & QOM_TBRSIZE) {
yyerror("tbrsize cannot be respecified");
YYERROR;
}
- if ($2 > 65535) {
+ if ($2 < 0 || $2 > 65535) {
yyerror("tbrsize too big: max 65535");
YYERROR;
}
@@ -1467,6 +1621,14 @@ bandwidth : STRING {
free($1);
$$.bw_absolute = (u_int32_t)bps;
}
+ | NUMBER {
+ if ($1 < 0 || $1 > UINT_MAX) {
+ yyerror("bandwidth number too big");
+ YYERROR;
+ }
+ $$.bw_percent = 0;
+ $$.bw_absolute = $1;
+ }
;
scheduler : CBQ {
@@ -1563,8 +1725,12 @@ hfscopts_item : LINKSHARE bandwidth {
hfsc_opts.linkshare.m2 = $2;
hfsc_opts.linkshare.used = 1;
}
- | LINKSHARE '(' bandwidth comma number comma bandwidth ')'
+ | LINKSHARE '(' bandwidth comma NUMBER comma bandwidth ')'
{
+ if ($5 < 0 || $5 > INT_MAX) {
+ yyerror("timing in curve out of range");
+ YYERROR;
+ }
if (hfsc_opts.linkshare.used) {
yyerror("linkshare already specified");
YYERROR;
@@ -1582,8 +1748,12 @@ hfscopts_item : LINKSHARE bandwidth {
hfsc_opts.realtime.m2 = $2;
hfsc_opts.realtime.used = 1;
}
- | REALTIME '(' bandwidth comma number comma bandwidth ')'
+ | REALTIME '(' bandwidth comma NUMBER comma bandwidth ')'
{
+ if ($5 < 0 || $5 > INT_MAX) {
+ yyerror("timing in curve out of range");
+ YYERROR;
+ }
if (hfsc_opts.realtime.used) {
yyerror("realtime already specified");
YYERROR;
@@ -1601,8 +1771,12 @@ hfscopts_item : LINKSHARE bandwidth {
hfsc_opts.upperlimit.m2 = $2;
hfsc_opts.upperlimit.used = 1;
}
- | UPPERLIMIT '(' bandwidth comma number comma bandwidth ')'
+ | UPPERLIMIT '(' bandwidth comma NUMBER comma bandwidth ')'
{
+ if ($5 < 0 || $5 > INT_MAX) {
+ yyerror("timing in curve out of range");
+ YYERROR;
+ }
if (hfsc_opts.upperlimit.used) {
yyerror("upperlimit already specified");
YYERROR;
@@ -1632,11 +1806,11 @@ hfscopts_item : LINKSHARE bandwidth {
qassign : /* empty */ { $$ = NULL; }
| qassign_item { $$ = $1; }
- | '{' qassign_list '}' { $$ = $2; }
+ | '{' optnl qassign_list '}' { $$ = $3; }
;
-qassign_list : qassign_item { $$ = $1; }
- | qassign_list comma qassign_item {
+qassign_list : qassign_item optnl { $$ = $1; }
+ | qassign_list comma qassign_item optnl {
$1->tail->next = $3;
$1->tail = $3;
$$ = $1;
@@ -1670,6 +1844,7 @@ pfrule : action dir logquick interface
int srctrack = 0;
int statelock = 0;
int adaptive = 0;
+ int defaults = 0;
if (check_rulestate(PFCTL_STATE_FILTER))
YYERROR;
@@ -1752,13 +1927,16 @@ pfrule : action dir logquick interface
r.tos = $9.tos;
r.keep_state = $9.keep.action;
+ o = $9.keep.options;
/* 'keep state' by default on pass rules. */
if (!r.keep_state && !r.action &&
- !($9.marker & FOM_KEEP))
+ !($9.marker & FOM_KEEP)) {
r.keep_state = PF_STATE_NORMAL;
+ o = keep_state_defaults;
+ defaults = 1;
+ }
- o = $9.keep.options;
while (o) {
struct node_state_opt *p = o;
@@ -1899,6 +2077,15 @@ pfrule : action dir logquick interface
}
r.rule_flag |= PFRULE_STATESLOPPY;
break;
+ case PF_STATE_OPT_PFLOW:
+ if (r.rule_flag & PFRULE_PFLOW) {
+ yyerror("state pflow "
+ "option: multiple "
+ "definitions");
+ YYERROR;
+ }
+ r.rule_flag |= PFRULE_PFLOW;
+ break;
case PF_STATE_OPT_TIMEOUT:
if (o->data.timeout.number ==
PFTM_ADAPTIVE_START ||
@@ -1916,7 +2103,8 @@ pfrule : action dir logquick interface
o->data.timeout.seconds;
}
o = o->next;
- free(p);
+ if (!defaults)
+ free(p);
}
/* 'flags S/SA' by default on stateful rules */
@@ -2035,6 +2223,34 @@ pfrule : action dir logquick interface
}
free($9.queues.pqname);
}
+#ifdef __FreeBSD__
+ r.divert.port = $9.divert.port;
+#else
+ if ((r.divert.port = $9.divert.port)) {
+ if (r.direction == PF_OUT) {
+ if ($9.divert.addr) {
+ yyerror("address specified "
+ "for outgoing divert");
+ YYERROR;
+ }
+ bzero(&r.divert.addr,
+ sizeof(r.divert.addr));
+ } else {
+ if (!$9.divert.addr) {
+ yyerror("no address specified "
+ "for incoming divert");
+ YYERROR;
+ }
+ if ($9.divert.addr->af != r.af) {
+ yyerror("address family "
+ "mismatch for divert");
+ YYERROR;
+ }
+ r.divert.addr =
+ $9.divert.addr->addr.v.a.addr;
+ }
+ }
+#endif
expand_rule(&r, $4, $5.host, $7, $8.src_os,
$8.src.host, $8.src.port, $8.dst.host, $8.dst.port,
@@ -2088,13 +2304,13 @@ filter_opt : USER uids {
filter_opts.marker |= FOM_ICMP;
filter_opts.icmpspec = $1;
}
- | tos {
+ | TOS tos {
if (filter_opts.marker & FOM_TOS) {
yyerror("tos cannot be redefined");
YYERROR;
}
filter_opts.marker |= FOM_TOS;
- filter_opts.tos = $1;
+ filter_opts.tos = $2;
}
| keep {
if (filter_opts.marker & FOM_KEEP) {
@@ -2132,39 +2348,84 @@ filter_opt : USER uids {
filter_opts.match_tag = $3;
filter_opts.match_tag_not = $1;
}
- | PROBABILITY STRING {
- char *e;
- double p = strtod($2, &e);
+ | PROBABILITY probability {
+ double p;
- if (*e == '%') {
- p *= 0.01;
- e++;
+ p = floor($2 * UINT_MAX + 0.5);
+ if (p < 0.0 || p > UINT_MAX) {
+ yyerror("invalid probability: %lf", p);
+ YYERROR;
}
- if (*e) {
- yyerror("invalid probability: %s", $2);
- free($2);
+ filter_opts.prob = (u_int32_t)p;
+ if (filter_opts.prob == 0)
+ filter_opts.prob = 1;
+ }
+ | RTABLE NUMBER {
+ if ($2 < 0 /* || $2 > RT_TABLEID_MAX */ ) {
+ yyerror("invalid rtable id");
YYERROR;
}
- p = floor(p * (UINT_MAX+1.0) + 0.5);
- if (p < 1.0 || p >= (UINT_MAX+1.0)) {
- yyerror("invalid probability: %s", $2);
+ filter_opts.rtableid = $2;
+ }
+ | DIVERTTO portplain {
+#ifdef __FreeBSD__
+ filter_opts.divert.port = $2.a;
+ if (!filter_opts.divert.port) {
+ yyerror("invalid divert port: %u", ntohs($2.a));
+ YYERROR;
+ }
+#endif
+ }
+ | DIVERTTO STRING PORT portplain {
+#ifndef __FreeBSD__
+ if ((filter_opts.divert.addr = host($2)) == NULL) {
+ yyerror("could not parse divert address: %s",
+ $2);
free($2);
YYERROR;
}
- filter_opts.prob = (u_int32_t)p;
+#else
+ if ($2)
+#endif
free($2);
- }
- | RTABLE number {
-#ifndef __FreeBSD__
- if ($2 > RT_TABLEID_MAX || $2 < 0) {
- yyerror("invalid rtable id");
+ filter_opts.divert.port = $4.a;
+ if (!filter_opts.divert.port) {
+ yyerror("invalid divert port: %u", ntohs($4.a));
YYERROR;
}
+ }
+ | DIVERTREPLY {
+#ifdef __FreeBSD__
+ yyerror("divert-reply has no meaning in FreeBSD pf(4)");
+ YYERROR;
+#else
+ filter_opts.divert.port = 1; /* some random value */
#endif
- filter_opts.rtableid = $2;
}
;
+probability : STRING {
+ char *e;
+ double p = strtod($1, &e);
+
+ if (*e == '%') {
+ p *= 0.01;
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-projects
mailing list