Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 17 Feb 2011 22:05:00 +0000 (UTC)
From:      "Bjoern A. Zeeb" <bz@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   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
Message-ID:  <201102172205.p1HM50Ck033152@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201102172205.p1HM50Ck033152>