aboutsummaryrefslogtreecommitdiff
path: root/contrib/pf/pfctl
diff options
context:
space:
mode:
authorBjoern A. Zeeb <bz@FreeBSD.org>2011-06-28 11:57:25 +0000
committerBjoern A. Zeeb <bz@FreeBSD.org>2011-06-28 11:57:25 +0000
commite0bfbfce7922dd3c28eb072b599c6bb8f65f039e (patch)
tree6f90e30d66bc1d86e242d960993589e5a0ad8936 /contrib/pf/pfctl
parente6df989fe417530d0f5f3390b19eb8373289cfab (diff)
parent739de636d7c95255cef4fc68a2c80cd8af54e502 (diff)
Notes
Diffstat (limited to 'contrib/pf/pfctl')
-rw-r--r--contrib/pf/pfctl/parse.y1560
-rw-r--r--contrib/pf/pfctl/pf_print_state.c150
-rw-r--r--contrib/pf/pfctl/pfctl.8135
-rw-r--r--contrib/pf/pfctl/pfctl.c231
-rw-r--r--contrib/pf/pfctl/pfctl.h13
-rw-r--r--contrib/pf/pfctl/pfctl_altq.c25
-rw-r--r--contrib/pf/pfctl/pfctl_optimize.c15
-rw-r--r--contrib/pf/pfctl/pfctl_osfp.c2
-rw-r--r--contrib/pf/pfctl/pfctl_parser.c41
-rw-r--r--contrib/pf/pfctl/pfctl_parser.h12
-rw-r--r--contrib/pf/pfctl/pfctl_qstats.c14
-rw-r--r--contrib/pf/pfctl/pfctl_radix.c52
-rw-r--r--contrib/pf/pfctl/pfctl_table.c15
13 files changed, 1418 insertions, 847 deletions
diff --git a/contrib/pf/pfctl/parse.y b/contrib/pf/pfctl/parse.y
index c22a0b662e6f..440692e1ef3a 100644
--- a/contrib/pf/pfctl/parse.y
+++ b/contrib/pf/pfctl/parse.y
@@ -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_NOSYNC, PF_STATE_OPT_SRCTRACK,
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,26 +235,34 @@ 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 {
- int marker;
+ int marker;
#define SOM_MINTTL 0x01
#define SOM_MAXMSS 0x02
#define SOM_FRAGCACHE 0x04
- int nodf;
- int minttl;
- int maxmss;
- int fragcache;
- int randomid;
- int reassemble_tcp;
- int rtableid;
+#define SOM_SETTOS 0x08
+ int nodf;
+ int minttl;
+ int maxmss;
+ int settos;
+ int fragcache;
+ int randomid;
+ int reassemble_tcp;
+ 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 interface af proto fromto
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 interface af proto fromto
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 interface af proto fromto
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 interface af proto fromto scrub_opts
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_ifspc af antispoof_opts {
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_ifspc af antispoof_opts {
}
;
-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 route af proto fromto
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 route af proto fromto
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 route af proto fromto
}
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 route af proto fromto
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 route af proto fromto
}
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);
- free($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;
}
- filter_opts.prob = (u_int32_t)p;
- free($2);
+#endif
}
- | RTABLE number {
+ | DIVERTTO STRING PORT portplain {
#ifndef __FreeBSD__
- if ($2 > RT_TABLEID_MAX || $2 < 0) {
- yyerror("invalid rtable id");
+ if ((filter_opts.divert.addr = host($2)) == NULL) {
+ yyerror("could not parse divert address: %s",
+ $2);
+ free($2);
YYERROR;
}
+#else
+ if ($2)
+#endif
+ free($2);
+ 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;
+ e++;
+ }
+ if (*e) {
+ yyerror("invalid probability: %s", $1);
+ free($1);
+ YYERROR;
+ }
+ free($1);
+ $$ = p;
+ }
+ | NUMBER {
+ $$ = (double)$1;
+ }
+ ;
+
+
action : PASS { $$.b1 = PF_PASS; $$.b2 = $$.w = 0; }
| BLOCK blockspec { $$ = $2; $$.b1 = PF_DROP; }
;
@@ -2184,8 +2445,8 @@ blockspec : /* empty */ {
$$.w = 0;
$$.w2 = 0;
}
- | RETURNRST '(' TTL number ')' {
- if ($4 > 255) {
+ | RETURNRST '(' TTL NUMBER ')' {
+ if ($4 < 0 || $4 > 255) {
yyerror("illegal ttl value %d", $4);
YYERROR;
}
@@ -2203,34 +2464,20 @@ blockspec : /* empty */ {
$$.w = returnicmpdefault;
$$.w2 = returnicmp6default;
}
- | RETURNICMP '(' STRING ')' {
+ | RETURNICMP '(' reticmpspec ')' {
$$.b2 = PFRULE_RETURNICMP;
- if (!($$.w = parseicmpspec($3, AF_INET))) {
- free($3);
- YYERROR;
- }
- free($3);
- $$.w2 = returnicmp6default;
+ $$.w = $3;
+ $$.w2 = returnicmpdefault;
}
- | RETURNICMP6 '(' STRING ')' {
+ | RETURNICMP6 '(' reticmp6spec ')' {
$$.b2 = PFRULE_RETURNICMP;
$$.w = returnicmpdefault;
- if (!($$.w2 = parseicmpspec($3, AF_INET6))) {
- free($3);
- YYERROR;
- }
- free($3);
+ $$.w2 = $3;
}
- | RETURNICMP '(' STRING comma STRING ')' {
+ | RETURNICMP '(' reticmpspec comma reticmp6spec ')' {
$$.b2 = PFRULE_RETURNICMP;
- if (!($$.w = parseicmpspec($3, AF_INET)) ||
- !($$.w2 = parseicmpspec($5, AF_INET6))) {
- free($3);
- free($5);
- YYERROR;
- }
- free($3);
- free($5);
+ $$.w = $3;
+ $$.w2 = $5;
}
| RETURN {
$$.b2 = PFRULE_RETURN;
@@ -2239,7 +2486,45 @@ blockspec : /* empty */ {
}
;
-dir : /* empty */ { $$ = 0; }
+reticmpspec : STRING {
+ if (!($$ = parseicmpspec($1, AF_INET))) {
+ free($1);
+ YYERROR;
+ }
+ free($1);
+ }
+ | NUMBER {
+ u_int8_t icmptype;
+
+ if ($1 < 0 || $1 > 255) {
+ yyerror("invalid icmp code %lu", $1);
+ YYERROR;
+ }
+ icmptype = returnicmpdefault >> 8;
+ $$ = (icmptype << 8 | $1);
+ }
+ ;
+
+reticmp6spec : STRING {
+ if (!($$ = parseicmpspec($1, AF_INET6))) {
+ free($1);
+ YYERROR;
+ }
+ free($1);
+ }
+ | NUMBER {
+ u_int8_t icmptype;
+
+ if ($1 < 0 || $1 > 255) {
+ yyerror("invalid icmp code %lu", $1);
+ YYERROR;
+ }
+ icmptype = returnicmp6default >> 8;
+ $$ = (icmptype << 8 | $1);
+ }
+ ;
+
+dir : /* empty */ { $$ = PF_INOUT; }
| IN { $$ = PF_IN; }
| OUT { $$ = PF_OUT; }
;
@@ -2297,11 +2582,11 @@ logopt : ALL { $$.log = PF_LOG_ALL; $$.logif = 0; }
interface : /* empty */ { $$ = NULL; }
| ON if_item_not { $$ = $2; }
- | ON '{' if_list '}' { $$ = $3; }
+ | ON '{' optnl if_list '}' { $$ = $4; }
;
-if_list : if_item_not { $$ = $1; }
- | if_list comma if_item_not {
+if_list : if_item_not optnl { $$ = $1; }
+ | if_list comma if_item_not optnl {
$1->tail->next = $3;
$1->tail = $3;
$$ = $1;
@@ -2340,42 +2625,23 @@ af : /* empty */ { $$ = 0; }
| INET6 { $$ = AF_INET6; }
;
-proto : /* empty */ { $$ = NULL; }
- | PROTO proto_item { $$ = $2; }
- | PROTO '{' proto_list '}' { $$ = $3; }
+proto : /* empty */ { $$ = NULL; }
+ | PROTO proto_item { $$ = $2; }
+ | PROTO '{' optnl proto_list '}' { $$ = $4; }
;
-proto_list : proto_item { $$ = $1; }
- | proto_list comma proto_item {
+proto_list : proto_item optnl { $$ = $1; }
+ | proto_list comma proto_item optnl {
$1->tail->next = $3;
$1->tail = $3;
$$ = $1;
}
;
-proto_item : STRING {
+proto_item : protoval {
u_int8_t pr;
- u_long ulval;
- if (atoul($1, &ulval) == 0) {
- if (ulval > 255) {
- yyerror("protocol outside range");
- free($1);
- YYERROR;
- }
- pr = (u_int8_t)ulval;
- } else {
- struct protoent *p;
-
- p = getprotobyname($1);
- if (p == NULL) {
- yyerror("unknown protocol %s", $1);
- free($1);
- YYERROR;
- }
- pr = p->p_proto;
- }
- free($1);
+ pr = (u_int8_t)$1;
if (pr == 0) {
yyerror("proto 0 cannot be used");
YYERROR;
@@ -2389,6 +2655,26 @@ proto_item : STRING {
}
;
+protoval : STRING {
+ struct protoent *p;
+
+ p = getprotobyname($1);
+ if (p == NULL) {
+ yyerror("unknown protocol %s", $1);
+ free($1);
+ YYERROR;
+ }
+ $$ = p->p_proto;
+ free($1);
+ }
+ | NUMBER {
+ if ($1 < 0 || $1 > 255) {
+ yyerror("protocol outside range");
+ YYERROR;
+ }
+ }
+ ;
+
fromto : ALL {
$$.src.host = NULL;
$$.src.port = NULL;
@@ -2405,7 +2691,7 @@ fromto : ALL {
os : /* empty */ { $$ = NULL; }
| OS xos { $$ = $2; }
- | OS '{' os_list '}' { $$ = $3; }
+ | OS '{' optnl os_list '}' { $$ = $4; }
;
xos : STRING {
@@ -2417,8 +2703,8 @@ xos : STRING {
}
;
-os_list : xos { $$ = $1; }
- | os_list comma xos {
+os_list : xos optnl { $$ = $1; }
+ | os_list comma xos optnl {
$1->tail->next = $3;
$1->tail = $3;
$$ = $1;
@@ -2460,13 +2746,21 @@ ipportspec : ipspec {
}
;
+optnl : '\n' optnl
+ |
+ ;
+
ipspec : ANY { $$ = NULL; }
| xhost { $$ = $1; }
- | '{' host_list '}' { $$ = $2; }
+ | '{' optnl host_list '}' { $$ = $3; }
;
-host_list : ipspec { $$ = $1; }
- | host_list comma ipspec {
+toipspec : TO ipspec { $$ = $2; }
+ | /* empty */ { $$ = NULL; }
+ ;
+
+host_list : ipspec optnl { $$ = $1; }
+ | host_list comma ipspec optnl {
if ($3 == NULL)
$$ = $1;
else if ($1 == NULL)
@@ -2516,10 +2810,43 @@ host : STRING {
free($1);
}
- | STRING '/' number {
+ | STRING '-' STRING {
+ struct node_host *b, *e;
+
+ if ((b = host($1)) == NULL || (e = host($3)) == NULL) {
+ free($1);
+ free($3);
+ yyerror("could not parse host specification");
+ YYERROR;
+ }
+ if (b->af != e->af ||
+ b->addr.type != PF_ADDR_ADDRMASK ||
+ e->addr.type != PF_ADDR_ADDRMASK ||
+ unmask(&b->addr.v.a.mask, b->af) !=
+ (b->af == AF_INET ? 32 : 128) ||
+ unmask(&e->addr.v.a.mask, e->af) !=
+ (e->af == AF_INET ? 32 : 128) ||
+ b->next != NULL || b->not ||
+ e->next != NULL || e->not) {
+ free(b);
+ free(e);
+ free($1);
+ free($3);
+ yyerror("invalid address range");
+ YYERROR;
+ }
+ memcpy(&b->addr.v.a.mask, &e->addr.v.a.addr,
+ sizeof(b->addr.v.a.mask));
+ b->addr.type = PF_ADDR_RANGE;
+ $$ = b;
+ free(e);
+ free($1);
+ free($3);
+ }
+ | STRING '/' NUMBER {
char *buf;
- if (asprintf(&buf, "%s/%u", $1, $3) == -1)
+ if (asprintf(&buf, "%s/%lld", $1, (long long)$3) == -1)
err(1, "host: asprintf");
free($1);
if (($$ = host(buf)) == NULL) {
@@ -2530,10 +2857,32 @@ host : STRING {
}
free(buf);
}
+ | NUMBER '/' NUMBER {
+ char *buf;
+
+ /* ie. for 10/8 parsing */
+#ifdef __FreeBSD__
+ if (asprintf(&buf, "%lld/%lld", (long long)$1, (long long)$3) == -1)
+#else
+ if (asprintf(&buf, "%lld/%lld", $1, $3) == -1)
+#endif
+ err(1, "host: asprintf");
+ if (($$ = host(buf)) == NULL) {
+ /* error. "any" is handled elsewhere */
+ free(buf);
+ yyerror("could not parse host specification");
+ YYERROR;
+ }
+ free(buf);
+ }
| dynaddr
- | dynaddr '/' number {
+ | dynaddr '/' NUMBER {
struct node_host *n;
+ if ($3 < 0 || $3 > 128) {
+ yyerror("bit number too big");
+ YYERROR;
+ }
$$ = $1;
for (n = $1; n != NULL; n = n->next)
set_ipmask(n, $3);
@@ -2578,7 +2927,8 @@ host : STRING {
}
;
-number : STRING {
+number : NUMBER
+ | STRING {
u_long ulval;
if (atoul($1, &ulval) == -1) {
@@ -2646,18 +2996,18 @@ dynaddr : '(' STRING ')' {
;
portspec : port_item { $$ = $1; }
- | '{' port_list '}' { $$ = $2; }
+ | '{' optnl port_list '}' { $$ = $3; }
;
-port_list : port_item { $$ = $1; }
- | port_list comma port_item {
+port_list : port_item optnl { $$ = $1; }
+ | port_list comma port_item optnl {
$1->tail->next = $3;
$1->tail = $3;
$$ = $1;
}
;
-port_item : port {
+port_item : portrange {
$$ = calloc(1, sizeof(struct node_port));
if ($$ == NULL)
err(1, "port_item: calloc");
@@ -2670,7 +3020,7 @@ port_item : port {
$$->next = NULL;
$$->tail = $$;
}
- | unaryop port {
+ | unaryop portrange {
if ($2.t) {
yyerror("':' cannot be used with an other "
"port operator");
@@ -2685,7 +3035,7 @@ port_item : port {
$$->next = NULL;
$$->tail = $$;
}
- | port PORTBINARY port {
+ | portrange PORTBINARY portrange {
if ($1.t || $3.t) {
yyerror("':' cannot be used with an other "
"port operator");
@@ -2702,38 +3052,30 @@ port_item : port {
}
;
-port : STRING {
- char *p = strchr($1, ':');
-
- if (p == NULL) {
- if (($$.a = getservice($1)) == -1) {
- free($1);
- YYERROR;
- }
- $$.b = $$.t = 0;
- } else {
- int port[2];
+portplain : numberstring {
+ if (parseport($1, &$$, 0) == -1) {
+ free($1);
+ YYERROR;
+ }
+ free($1);
+ }
+ ;
- *p++ = 0;
- if ((port[0] = getservice($1)) == -1 ||
- (port[1] = getservice(p)) == -1) {
- free($1);
- YYERROR;
- }
- $$.a = port[0];
- $$.b = port[1];
- $$.t = PF_OP_RRG;
+portrange : numberstring {
+ if (parseport($1, &$$, PPORT_RANGE) == -1) {
+ free($1);
+ YYERROR;
}
free($1);
}
;
uids : uid_item { $$ = $1; }
- | '{' uid_list '}' { $$ = $2; }
+ | '{' optnl uid_list '}' { $$ = $3; }
;
-uid_list : uid_item { $$ = $1; }
- | uid_list comma uid_item {
+uid_list : uid_item optnl { $$ = $1; }
+ | uid_list comma uid_item optnl {
$1->tail->next = $3;
$1->tail = $3;
$$ = $1;
@@ -2783,39 +3125,35 @@ uid_item : uid {
;
uid : STRING {
- u_long ulval;
-
- if (atoul($1, &ulval) == -1) {
- if (!strcmp($1, "unknown"))
- $$ = UID_MAX;
- else {
- struct passwd *pw;
+ if (!strcmp($1, "unknown"))
+ $$ = UID_MAX;
+ else {
+ struct passwd *pw;
- if ((pw = getpwnam($1)) == NULL) {
- yyerror("unknown user %s", $1);
- free($1);
- YYERROR;
- }
- $$ = pw->pw_uid;
- }
- } else {
- if (ulval >= UID_MAX) {
+ if ((pw = getpwnam($1)) == NULL) {
+ yyerror("unknown user %s", $1);
free($1);
- yyerror("illegal uid value %lu", ulval);
YYERROR;
}
- $$ = ulval;
+ $$ = pw->pw_uid;
}
free($1);
}
+ | NUMBER {
+ if ($1 < 0 || $1 >= UID_MAX) {
+ yyerror("illegal uid value %lu", $1);
+ YYERROR;
+ }
+ $$ = $1;
+ }
;
gids : gid_item { $$ = $1; }
- | '{' gid_list '}' { $$ = $2; }
+ | '{' optnl gid_list '}' { $$ = $3; }
;
-gid_list : gid_item { $$ = $1; }
- | gid_list comma gid_item {
+gid_list : gid_item optnl { $$ = $1; }
+ | gid_list comma gid_item optnl {
$1->tail->next = $3;
$1->tail = $3;
$$ = $1;
@@ -2865,31 +3203,27 @@ gid_item : gid {
;
gid : STRING {
- u_long ulval;
-
- if (atoul($1, &ulval) == -1) {
- if (!strcmp($1, "unknown"))
- $$ = GID_MAX;
- else {
- struct group *grp;
+ if (!strcmp($1, "unknown"))
+ $$ = GID_MAX;
+ else {
+ struct group *grp;
- if ((grp = getgrnam($1)) == NULL) {
- yyerror("unknown group %s", $1);
- free($1);
- YYERROR;
- }
- $$ = grp->gr_gid;
- }
- } else {
- if (ulval >= GID_MAX) {
- yyerror("illegal gid value %lu", ulval);
+ if ((grp = getgrnam($1)) == NULL) {
+ yyerror("unknown group %s", $1);
free($1);
YYERROR;
}
- $$ = ulval;
+ $$ = grp->gr_gid;
}
free($1);
}
+ | NUMBER {
+ if ($1 < 0 || $1 >= GID_MAX) {
+ yyerror("illegal gid value %lu", $1);
+ YYERROR;
+ }
+ $$ = $1;
+ }
;
flag : STRING {
@@ -2910,22 +3244,22 @@ flags : FLAGS flag '/' flag { $$.b1 = $2.b1; $$.b2 = $4.b1; }
| FLAGS ANY { $$.b1 = 0; $$.b2 = 0; }
;
-icmpspec : ICMPTYPE icmp_item { $$ = $2; }
- | ICMPTYPE '{' icmp_list '}' { $$ = $3; }
- | ICMP6TYPE icmp6_item { $$ = $2; }
- | ICMP6TYPE '{' icmp6_list '}' { $$ = $3; }
+icmpspec : ICMPTYPE icmp_item { $$ = $2; }
+ | ICMPTYPE '{' optnl icmp_list '}' { $$ = $4; }
+ | ICMP6TYPE icmp6_item { $$ = $2; }
+ | ICMP6TYPE '{' optnl icmp6_list '}' { $$ = $4; }
;
-icmp_list : icmp_item { $$ = $1; }
- | icmp_list comma icmp_item {
+icmp_list : icmp_item optnl { $$ = $1; }
+ | icmp_list comma icmp_item optnl {
$1->tail->next = $3;
$1->tail = $3;
$$ = $1;
}
;
-icmp6_list : icmp6_item { $$ = $1; }
- | icmp6_list comma icmp6_item {
+icmp6_list : icmp6_item optnl { $$ = $1; }
+ | icmp6_list comma icmp6_item optnl {
$1->tail->next = $3;
$1->tail = $3;
$$ = $1;
@@ -2944,29 +3278,33 @@ icmp_item : icmptype {
}
| icmptype CODE STRING {
const struct icmpcodeent *p;
- u_long ulval;
- if (atoul($3, &ulval) == 0) {
- if (ulval > 255) {
- free($3);
- yyerror("illegal icmp-code %lu", ulval);
- YYERROR;
- }
- } else {
- if ((p = geticmpcodebyname($1-1, $3,
- AF_INET)) == NULL) {
- yyerror("unknown icmp-code %s", $3);
- free($3);
- YYERROR;
- }
- ulval = p->code;
+ if ((p = geticmpcodebyname($1-1, $3, AF_INET)) == NULL) {
+ yyerror("unknown icmp-code %s", $3);
+ free($3);
+ YYERROR;
}
+
free($3);
$$ = calloc(1, sizeof(struct node_icmp));
if ($$ == NULL)
err(1, "icmp_item: calloc");
$$->type = $1;
- $$->code = ulval + 1;
+ $$->code = p->code + 1;
+ $$->proto = IPPROTO_ICMP;
+ $$->next = NULL;
+ $$->tail = $$;
+ }
+ | icmptype CODE NUMBER {
+ if ($3 < 0 || $3 > 255) {
+ yyerror("illegal icmp-code %lu", $3);
+ YYERROR;
+ }
+ $$ = calloc(1, sizeof(struct node_icmp));
+ if ($$ == NULL)
+ err(1, "icmp_item: calloc");
+ $$->type = $1;
+ $$->code = $3 + 1;
$$->proto = IPPROTO_ICMP;
$$->next = NULL;
$$->tail = $$;
@@ -2985,30 +3323,33 @@ icmp6_item : icmp6type {
}
| icmp6type CODE STRING {
const struct icmpcodeent *p;
- u_long ulval;
- if (atoul($3, &ulval) == 0) {
- if (ulval > 255) {
- yyerror("illegal icmp6-code %lu",
- ulval);
- free($3);
- YYERROR;
- }
- } else {
- if ((p = geticmpcodebyname($1-1, $3,
- AF_INET6)) == NULL) {
- yyerror("unknown icmp6-code %s", $3);
- free($3);
- YYERROR;
- }
- ulval = p->code;
+ if ((p = geticmpcodebyname($1-1, $3, AF_INET6)) == NULL) {
+ yyerror("unknown icmp6-code %s", $3);
+ free($3);
+ YYERROR;
}
free($3);
+
$$ = calloc(1, sizeof(struct node_icmp));
if ($$ == NULL)
err(1, "icmp_item: calloc");
$$->type = $1;
- $$->code = ulval + 1;
+ $$->code = p->code + 1;
+ $$->proto = IPPROTO_ICMPV6;
+ $$->next = NULL;
+ $$->tail = $$;
+ }
+ | icmp6type CODE NUMBER {
+ if ($3 < 0 || $3 > 255) {
+ yyerror("illegal icmp-code %lu", $3);
+ YYERROR;
+ }
+ $$ = calloc(1, sizeof(struct node_icmp));
+ if ($$ == NULL)
+ err(1, "icmp_item: calloc");
+ $$->type = $1;
+ $$->code = $3 + 1;
$$->proto = IPPROTO_ICMPV6;
$$->next = NULL;
$$->tail = $$;
@@ -3017,70 +3358,69 @@ icmp6_item : icmp6type {
icmptype : STRING {
const struct icmptypeent *p;
- u_long ulval;
- if (atoul($1, &ulval) == 0) {
- if (ulval > 255) {
- yyerror("illegal icmp-type %lu", ulval);
- free($1);
- YYERROR;
- }
- $$ = ulval + 1;
- } else {
- if ((p = geticmptypebyname($1, AF_INET)) ==
- NULL) {
- yyerror("unknown icmp-type %s", $1);
- free($1);
- YYERROR;
- }
- $$ = p->type + 1;
+ if ((p = geticmptypebyname($1, AF_INET)) == NULL) {
+ yyerror("unknown icmp-type %s", $1);
+ free($1);
+ YYERROR;
}
+ $$ = p->type + 1;
free($1);
}
+ | NUMBER {
+ if ($1 < 0 || $1 > 255) {
+ yyerror("illegal icmp-type %lu", $1);
+ YYERROR;
+ }
+ $$ = $1 + 1;
+ }
;
icmp6type : STRING {
const struct icmptypeent *p;
- u_long ulval;
- if (atoul($1, &ulval) == 0) {
- if (ulval > 255) {
- yyerror("illegal icmp6-type %lu",
- ulval);
- free($1);
- YYERROR;
- }
- $$ = ulval + 1;
- } else {
- if ((p = geticmptypebyname($1, AF_INET6)) ==
- NULL) {
- yyerror("unknown icmp6-type %s", $1);
- free($1);
- YYERROR;
- }
- $$ = p->type + 1;
+ if ((p = geticmptypebyname($1, AF_INET6)) ==
+ NULL) {
+ yyerror("unknown icmp6-type %s", $1);
+ free($1);
+ YYERROR;
}
+ $$ = p->type + 1;
free($1);
}
+ | NUMBER {
+ if ($1 < 0 || $1 > 255) {
+ yyerror("illegal icmp6-type %lu", $1);
+ YYERROR;
+ }
+ $$ = $1 + 1;
+ }
;
-tos : TOS STRING {
- if (!strcmp($2, "lowdelay"))
+tos : STRING {
+ if (!strcmp($1, "lowdelay"))
$$ = IPTOS_LOWDELAY;
- else if (!strcmp($2, "throughput"))
+ else if (!strcmp($1, "throughput"))
$$ = IPTOS_THROUGHPUT;
- else if (!strcmp($2, "reliability"))
+ else if (!strcmp($1, "reliability"))
$$ = IPTOS_RELIABILITY;
- else if ($2[0] == '0' && $2[1] == 'x')
- $$ = strtoul($2, NULL, 16);
+ else if ($1[0] == '0' && $1[1] == 'x')
+ $$ = strtoul($1, NULL, 16);
else
- $$ = strtoul($2, NULL, 10);
+ $$ = 0; /* flag bad argument */
if (!$$ || $$ > 255) {
- yyerror("illegal tos value %s", $2);
- free($2);
+ yyerror("illegal tos value %s", $1);
+ free($1);
+ YYERROR;
+ }
+ free($1);
+ }
+ | NUMBER {
+ $$ = $1;
+ if (!$$ || $$ > 255) {
+ yyerror("illegal tos value %s", $1);
YYERROR;
}
- free($2);
}
;
@@ -3134,7 +3474,11 @@ state_opt_list : state_opt_item { $$ = $1; }
}
;
-state_opt_item : MAXIMUM number {
+state_opt_item : MAXIMUM NUMBER {
+ if ($2 < 0 || $2 > UINT_MAX) {
+ yyerror("only positive values permitted");
+ YYERROR;
+ }
$$ = calloc(1, sizeof(struct node_state_opt));
if ($$ == NULL)
err(1, "state_opt_item: calloc");
@@ -3151,7 +3495,11 @@ state_opt_item : MAXIMUM number {
$$->next = NULL;
$$->tail = $$;
}
- | MAXSRCSTATES number {
+ | MAXSRCSTATES NUMBER {
+ if ($2 < 0 || $2 > UINT_MAX) {
+ yyerror("only positive values permitted");
+ YYERROR;
+ }
$$ = calloc(1, sizeof(struct node_state_opt));
if ($$ == NULL)
err(1, "state_opt_item: calloc");
@@ -3160,7 +3508,11 @@ state_opt_item : MAXIMUM number {
$$->next = NULL;
$$->tail = $$;
}
- | MAXSRCCONN number {
+ | MAXSRCCONN NUMBER {
+ if ($2 < 0 || $2 > UINT_MAX) {
+ yyerror("only positive values permitted");
+ YYERROR;
+ }
$$ = calloc(1, sizeof(struct node_state_opt));
if ($$ == NULL)
err(1, "state_opt_item: calloc");
@@ -3169,7 +3521,12 @@ state_opt_item : MAXIMUM number {
$$->next = NULL;
$$->tail = $$;
}
- | MAXSRCCONNRATE number '/' number {
+ | MAXSRCCONNRATE NUMBER '/' NUMBER {
+ if ($2 < 0 || $2 > UINT_MAX ||
+ $4 < 0 || $4 > UINT_MAX) {
+ yyerror("only positive values permitted");
+ YYERROR;
+ }
$$ = calloc(1, sizeof(struct node_state_opt));
if ($$ == NULL)
err(1, "state_opt_item: calloc");
@@ -3197,7 +3554,11 @@ state_opt_item : MAXIMUM number {
$$->next = NULL;
$$->tail = $$;
}
- | MAXSRCNODES number {
+ | MAXSRCNODES NUMBER {
+ if ($2 < 0 || $2 > UINT_MAX) {
+ yyerror("only positive values permitted");
+ YYERROR;
+ }
$$ = calloc(1, sizeof(struct node_state_opt));
if ($$ == NULL)
err(1, "state_opt_item: calloc");
@@ -3232,9 +3593,21 @@ state_opt_item : MAXIMUM number {
$$->next = NULL;
$$->tail = $$;
}
- | STRING number {
+ | PFLOW {
+ $$ = calloc(1, sizeof(struct node_state_opt));
+ if ($$ == NULL)
+ err(1, "state_opt_item: calloc");
+ $$->type = PF_STATE_OPT_PFLOW;
+ $$->next = NULL;
+ $$->tail = $$;
+ }
+ | STRING NUMBER {
int i;
+ if ($2 < 0 || $2 > UINT_MAX) {
+ yyerror("only positive values permitted");
+ YYERROR;
+ }
for (i = 0; pf_timeouts[i].name &&
strcmp(pf_timeouts[i].name, $1); ++i)
; /* nothing */
@@ -3267,9 +3640,11 @@ label : LABEL STRING {
qname : QUEUE STRING {
$$.qname = $2;
+ $$.pqname = NULL;
}
| QUEUE '(' STRING ')' {
$$.qname = $3;
+ $$.pqname = NULL;
}
| QUEUE '(' STRING comma STRING ')' {
$$.qname = $3;
@@ -3281,44 +3656,21 @@ no : /* empty */ { $$ = 0; }
| NO { $$ = 1; }
;
-rport : STRING {
- char *p = strchr($1, ':');
-
- if (p == NULL) {
- if (($$.a = getservice($1)) == -1) {
- free($1);
- YYERROR;
- }
- $$.b = $$.t = 0;
- } else if (!strcmp(p+1, "*")) {
- *p = 0;
- if (($$.a = getservice($1)) == -1) {
- free($1);
- YYERROR;
- }
- $$.b = 0;
- $$.t = 1;
- } else {
- *p++ = 0;
- if (($$.a = getservice($1)) == -1 ||
- ($$.b = getservice(p)) == -1) {
- free($1);
- YYERROR;
- }
- if ($$.a == $$.b)
- $$.b = 0;
- $$.t = 0;
+portstar : numberstring {
+ if (parseport($1, &$$, PPORT_RANGE|PPORT_STAR) == -1) {
+ free($1);
+ YYERROR;
}
free($1);
}
;
redirspec : host { $$ = $1; }
- | '{' redir_host_list '}' { $$ = $2; }
+ | '{' optnl redir_host_list '}' { $$ = $3; }
;
-redir_host_list : host { $$ = $1; }
- | redir_host_list comma host {
+redir_host_list : host optnl { $$ = $1; }
+ | redir_host_list comma host optnl {
$1->tail->next = $3;
$1->tail = $3->tail;
$$ = $1;
@@ -3333,7 +3685,7 @@ redirpool : /* empty */ { $$ = NULL; }
$$->host = $2;
$$->rport.a = $$->rport.b = $$->rport.t = 0;
}
- | ARROW redirspec PORT rport {
+ | ARROW redirspec PORT portstar {
$$ = calloc(1, sizeof(struct redirection));
if ($$ == NULL)
err(1, "redirection: calloc");
@@ -3459,7 +3811,7 @@ redirection : /* empty */ { $$ = NULL; }
$$->host = $2;
$$->rport.a = $$->rport.b = $$->rport.t = 0;
}
- | ARROW host PORT rport {
+ | ARROW host PORT portstar {
$$ = calloc(1, sizeof(struct redirection));
if ($$ == NULL)
err(1, "redirection: calloc");
@@ -3468,17 +3820,13 @@ redirection : /* empty */ { $$ = NULL; }
}
;
-/* ifdef __FreeBSD__ */
-natpass : /* empty */ { $$.b1 = $$.b2 = 0; $$.w2 = 0; }
+natpasslog : /* empty */ { $$.b1 = $$.b2 = 0; $$.w2 = 0; }
| PASS { $$.b1 = 1; $$.b2 = 0; $$.w2 = 0; }
-/* else
-natpass : empty { $$.b1 = $$.b2 = 0; }
- | PASS { $$.b1 = 1; $$.b2 = 0; }
- * endif */
| PASS log { $$.b1 = 1; $$.b2 = $2.log; $$.w2 = $2.logif; }
+ | log { $$.b1 = 0; $$.b2 = $1.log; $$.w2 = $1.logif; }
;
-nataction : no NAT natpass {
+nataction : no NAT natpasslog {
if ($1 && $3.b1) {
yyerror("\"pass\" not valid with \"no\"");
YYERROR;
@@ -3491,7 +3839,7 @@ nataction : no NAT natpass {
$$.w = $3.b2;
$$.w2 = $3.w2;
}
- | no RDR natpass {
+ | no RDR natpasslog {
if ($1 && $3.b1) {
yyerror("\"pass\" not valid with \"no\"");
YYERROR;
@@ -3665,7 +4013,7 @@ natrule : nataction interface af proto fromto tag tagged rtable
}
;
-binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag
+binatrule : no BINAT natpasslog interface af proto FROM host toipspec tag
tagged rtable redirection
{
struct pf_rule binat;
@@ -3673,7 +4021,7 @@ binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag
if (check_rulestate(PFCTL_STATE_NAT))
YYERROR;
- if (disallow_urpf_failed($10, "\"urpf-failed\" is not "
+ if (disallow_urpf_failed($9, "\"urpf-failed\" is not "
"permitted as a binat destination"))
YYERROR;
@@ -3693,11 +4041,11 @@ binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag
binat.af = $5;
if (!binat.af && $8 != NULL && $8->af)
binat.af = $8->af;
- if (!binat.af && $10 != NULL && $10->af)
- binat.af = $10->af;
+ if (!binat.af && $9 != NULL && $9->af)
+ binat.af = $9->af;
- if (!binat.af && $14 != NULL && $14->host)
- binat.af = $14->host->af;
+ if (!binat.af && $13 != NULL && $13->host)
+ binat.af = $13->host->af;
if (!binat.af) {
yyerror("address family (inet/inet6) "
"undefined");
@@ -3711,22 +4059,22 @@ binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag
free($4);
}
- if ($11 != NULL)
- if (strlcpy(binat.tagname, $11,
+ if ($10 != NULL)
+ if (strlcpy(binat.tagname, $10,
PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
yyerror("tag too long, max %u chars",
PF_TAG_NAME_SIZE - 1);
YYERROR;
}
- if ($12.name)
- if (strlcpy(binat.match_tagname, $12.name,
+ if ($11.name)
+ if (strlcpy(binat.match_tagname, $11.name,
PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
yyerror("tag too long, max %u chars",
PF_TAG_NAME_SIZE - 1);
YYERROR;
}
- binat.match_tag_not = $12.neg;
- binat.rtableid = $13;
+ binat.match_tag_not = $11.neg;
+ binat.rtableid = $12;
if ($6 != NULL) {
binat.proto = $6->proto;
@@ -3740,12 +4088,12 @@ binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag
"interface (%s) as the source address of a binat "
"rule"))
YYERROR;
- if ($14 != NULL && $14->host != NULL && disallow_table(
- $14->host, "invalid use of table <%s> as the "
+ if ($13 != NULL && $13->host != NULL && disallow_table(
+ $13->host, "invalid use of table <%s> as the "
"redirect address of a binat rule"))
YYERROR;
- if ($14 != NULL && $14->host != NULL && disallow_alias(
- $14->host, "invalid use of interface (%s) as the "
+ if ($13 != NULL && $13->host != NULL && disallow_alias(
+ $13->host, "invalid use of interface (%s) as the "
"redirect address of a binat rule"))
YYERROR;
@@ -3766,51 +4114,51 @@ binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag
sizeof(binat.src.addr));
free($8);
}
- if ($10 != NULL) {
- if ($10->next) {
+ if ($9 != NULL) {
+ if ($9->next) {
yyerror("multiple binat ip addresses");
YYERROR;
}
- if ($10->af != binat.af && $10->af) {
+ if ($9->af != binat.af && $9->af) {
yyerror("binat ip versions must match");
YYERROR;
}
- if (check_netmask($10, binat.af))
+ if (check_netmask($9, binat.af))
YYERROR;
- memcpy(&binat.dst.addr, &$10->addr,
+ memcpy(&binat.dst.addr, &$9->addr,
sizeof(binat.dst.addr));
- binat.dst.neg = $10->not;
- free($10);
+ binat.dst.neg = $9->not;
+ free($9);
}
if (binat.action == PF_NOBINAT) {
- if ($14 != NULL) {
+ if ($13 != NULL) {
yyerror("'no binat' rule does not need"
" '->'");
YYERROR;
}
} else {
- if ($14 == NULL || $14->host == NULL) {
+ if ($13 == NULL || $13->host == NULL) {
yyerror("'binat' rule requires"
" '-> address'");
YYERROR;
}
- remove_invalid_hosts(&$14->host, &binat.af);
- if (invalid_redirect($14->host, binat.af))
+ remove_invalid_hosts(&$13->host, &binat.af);
+ if (invalid_redirect($13->host, binat.af))
YYERROR;
- if ($14->host->next != NULL) {
+ if ($13->host->next != NULL) {
yyerror("binat rule must redirect to "
"a single address");
YYERROR;
}
- if (check_netmask($14->host, binat.af))
+ if (check_netmask($13->host, binat.af))
YYERROR;
if (!PF_AZERO(&binat.src.addr.v.a.mask,
binat.af) &&
!PF_AEQ(&binat.src.addr.v.a.mask,
- &$14->host->addr.v.a.mask, binat.af)) {
+ &$13->host->addr.v.a.mask, binat.af)) {
yyerror("'binat' source mask and "
"redirect mask must be the same");
YYERROR;
@@ -3820,12 +4168,12 @@ binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag
pa = calloc(1, sizeof(struct pf_pooladdr));
if (pa == NULL)
err(1, "binat: calloc");
- pa->addr = $14->host->addr;
+ pa->addr = $13->host->addr;
pa->ifname[0] = 0;
TAILQ_INSERT_TAIL(&binat.rpool.list,
pa, entries);
- free($14);
+ free($13);
}
pfctl_add_rule(pf, &binat, "");
@@ -3841,17 +4189,12 @@ tagged : /* empty */ { $$.neg = 0; $$.name = NULL; }
;
rtable : /* empty */ { $$ = -1; }
- | RTABLE number {
-#ifdef __FreeBSD__
- yyerror("rtable id not supported in FreeBSD, yet");
- YYERROR;
-#else
- if ($2 > RT_TABLEID_MAX || $2 < 0) {
+ | RTABLE NUMBER {
+ if ($2 < 0 /* || $2 > RT_TABLEID_MAX */ ) {
yyerror("invalid rtable id");
YYERROR;
}
$$ = $2;
-#endif
}
;
@@ -3870,8 +4213,8 @@ route_host : STRING {
}
;
-route_host_list : route_host { $$ = $1; }
- | route_host_list comma route_host {
+route_host_list : route_host optnl { $$ = $1; }
+ | route_host_list comma route_host optnl {
if ($1->af == 0)
$1->af = $3->af;
if ($1->af != $3->af) {
@@ -3886,7 +4229,7 @@ route_host_list : route_host { $$ = $1; }
;
routespec : route_host { $$ = $1; }
- | '{' route_host_list '}' { $$ = $2; }
+ | '{' optnl route_host_list '}' { $$ = $3; }
;
route : /* empty */ {
@@ -3922,12 +4265,16 @@ route : /* empty */ {
}
;
-timeout_spec : STRING number
+timeout_spec : STRING NUMBER
{
if (check_rulestate(PFCTL_STATE_OPTION)) {
free($1);
YYERROR;
}
+ if ($2 < 0 || $2 > UINT_MAX) {
+ yyerror("only positive values permitted");
+ YYERROR;
+ }
if (pfctl_set_timeout(pf, $1, $2, 0) != 0) {
yyerror("unknown timeout %s", $1);
free($1);
@@ -3937,16 +4284,20 @@ timeout_spec : STRING number
}
;
-timeout_list : timeout_list comma timeout_spec
- | timeout_spec
+timeout_list : timeout_list comma timeout_spec optnl
+ | timeout_spec optnl
;
-limit_spec : STRING number
+limit_spec : STRING NUMBER
{
if (check_rulestate(PFCTL_STATE_OPTION)) {
free($1);
YYERROR;
}
+ if ($2 < 0 || $2 > UINT_MAX) {
+ yyerror("only positive values permitted");
+ YYERROR;
+ }
if (pfctl_set_limit(pf, $1, $2) != 0) {
yyerror("unable to set limit %s %u", $1, $2);
free($1);
@@ -3956,8 +4307,8 @@ limit_spec : STRING number
}
;
-limit_list : limit_list comma limit_spec
- | limit_spec
+limit_list : limit_list comma limit_spec optnl
+ | limit_spec optnl
;
comma : ','
@@ -3992,11 +4343,10 @@ int
yyerror(const char *fmt, ...)
{
va_list ap;
- extern char *infile;
- errors = 1;
+ file->errors++;
va_start(ap, fmt);
- fprintf(stderr, "%s:%d: ", infile, yylval.lineno);
+ fprintf(stderr, "%s:%d: ", file->name, yylval.lineno);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
@@ -4914,6 +5264,8 @@ lookup(char *s)
{ "code", CODE},
{ "crop", FRAGCROP},
{ "debug", DEBUG},
+ { "divert-reply", DIVERTREPLY},
+ { "divert-to", DIVERTTO},
{ "drop", DROP},
{ "drop-ovl", FRAGDROP},
{ "dup-to", DUPTO},
@@ -4934,6 +5286,7 @@ lookup(char *s)
{ "icmp6-type", ICMP6TYPE},
{ "if-bound", IFBOUND},
{ "in", IN},
+ { "include", INCLUDE},
{ "inet", INET},
{ "inet6", INET6},
{ "keep", KEEP},
@@ -4963,6 +5316,7 @@ lookup(char *s)
{ "out", OUT},
{ "overload", OVERLOAD},
{ "pass", PASS},
+ { "pflow", PFLOW},
{ "port", PORT},
{ "priority", PRIORITY},
{ "priq", PRIQ},
@@ -4991,11 +5345,13 @@ lookup(char *s)
{ "ruleset-optimization", RULESET_OPTIMIZATION},
{ "scrub", SCRUB},
{ "set", SET},
+ { "set-tos", SETTOS},
{ "skip", SKIP},
{ "sloppy", SLOPPY},
{ "source-hash", SOURCEHASH},
{ "source-track", SOURCETRACK},
{ "state", STATE},
+ { "state-defaults", STATEDEFAULTS},
{ "state-policy", STATEPOLICY},
{ "static-port", STATICPORT},
{ "sticky-address", STICKYADDRESS},
@@ -5036,9 +5392,9 @@ char pushback_buffer[MAXPUSHBACK];
int pushback_index = 0;
int
-lgetc(FILE *f)
+lgetc(int quotec)
{
- int c, next;
+ int c, next;
if (parsebuf) {
/* Read character from the parsebuffer instead of input. */
@@ -5054,24 +5410,31 @@ lgetc(FILE *f)
if (pushback_index)
return (pushback_buffer[--pushback_index]);
- while ((c = getc(f)) == '\\') {
- next = getc(f);
+ if (quotec) {
+ if ((c = getc(file->stream)) == EOF) {
+ yyerror("reached end of file while parsing quoted string");
+ if (popfile() == EOF)
+ return (EOF);
+ return (quotec);
+ }
+ return (c);
+ }
+
+ while ((c = getc(file->stream)) == '\\') {
+ next = getc(file->stream);
if (next != '\n') {
c = next;
break;
}
- yylval.lineno = lineno;
- lineno++;
- }
- if (c == '\t' || c == ' ') {
- /* Compress blanks to a single space. */
- do {
- c = getc(f);
- } while (c == '\t' || c == ' ');
- ungetc(c, f);
- c = ' ';
+ yylval.lineno = file->lineno;
+ file->lineno++;
}
+ while (c == EOF) {
+ if (popfile() == EOF)
+ return (EOF);
+ c = getc(file->stream);
+ }
return (c);
}
@@ -5097,13 +5460,15 @@ findeol(void)
int c;
parsebuf = NULL;
- pushback_index = 0;
/* skip to either EOF or the first real EOL */
while (1) {
- c = lgetc(fin);
+ if (pushback_index)
+ c = pushback_buffer[--pushback_index];
+ else
+ c = lgetc(0);
if (c == '\n') {
- lineno++;
+ file->lineno++;
break;
}
if (c == EOF)
@@ -5117,21 +5482,21 @@ yylex(void)
{
char buf[8096];
char *p, *val;
- int endc, c, next;
+ int quotec, next, c;
int token;
top:
p = buf;
- while ((c = lgetc(fin)) == ' ')
+ while ((c = lgetc(0)) == ' ' || c == '\t')
; /* nothing */
- yylval.lineno = lineno;
+ yylval.lineno = file->lineno;
if (c == '#')
- while ((c = lgetc(fin)) != '\n' && c != EOF)
+ while ((c = lgetc(0)) != '\n' && c != EOF)
; /* nothing */
if (c == '$' && parsebuf == NULL) {
while (1) {
- if ((c = lgetc(fin)) == EOF)
+ if ((c = lgetc(0)) == EOF)
return (0);
if (p + 1 >= buf + sizeof(buf) - 1) {
@@ -5159,17 +5524,25 @@ top:
switch (c) {
case '\'':
case '"':
- endc = c;
+ quotec = c;
while (1) {
- if ((c = lgetc(fin)) == EOF)
+ if ((c = lgetc(quotec)) == EOF)
return (0);
- if (c == endc) {
- *p = '\0';
- break;
- }
if (c == '\n') {
- lineno++;
+ file->lineno++;
continue;
+ } else if (c == '\\') {
+ if ((next = lgetc(quotec)) == EOF)
+ return (0);
+ if (next == quotec || c == ' ' || c == '\t')
+ c = next;
+ else if (next == '\n')
+ continue;
+ else
+ lungetc(next);
+ } else if (c == quotec) {
+ *p = '\0';
+ break;
}
if (p + 1 >= buf + sizeof(buf) - 1) {
yyerror("string too long");
@@ -5182,7 +5555,7 @@ top:
err(1, "yylex: strdup");
return (STRING);
case '<':
- next = lgetc(fin);
+ next = lgetc(0);
if (next == '>') {
yylval.v.i = PF_OP_XRG;
return (PORTBINARY);
@@ -5190,7 +5563,7 @@ top:
lungetc(next);
break;
case '>':
- next = lgetc(fin);
+ next = lgetc(0);
if (next == '<') {
yylval.v.i = PF_OP_IRG;
return (PORTBINARY);
@@ -5198,13 +5571,49 @@ top:
lungetc(next);
break;
case '-':
- next = lgetc(fin);
+ next = lgetc(0);
if (next == '>')
return (ARROW);
lungetc(next);
break;
}
+#define allowed_to_end_number(x) \
+ (isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
+
+ if (c == '-' || isdigit(c)) {
+ do {
+ *p++ = c;
+ if ((unsigned)(p-buf) >= sizeof(buf)) {
+ yyerror("string too long");
+ return (findeol());
+ }
+ } while ((c = lgetc(0)) != EOF && isdigit(c));
+ lungetc(c);
+ if (p == buf + 1 && buf[0] == '-')
+ goto nodigits;
+ if (c == EOF || allowed_to_end_number(c)) {
+ const char *errstr = NULL;
+
+ *p = '\0';
+ yylval.v.number = strtonum(buf, LLONG_MIN,
+ LLONG_MAX, &errstr);
+ if (errstr) {
+ yyerror("\"%s\" invalid number: %s",
+ buf, errstr);
+ return (findeol());
+ }
+ return (NUMBER);
+ } else {
+nodigits:
+ while (p > buf + 1)
+ lungetc(*--p);
+ c = *--p;
+ if (c == '-')
+ return (c);
+ }
+ }
+
#define allowed_in_string(x) \
(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
x != '{' && x != '}' && x != '<' && x != '>' && \
@@ -5218,7 +5627,7 @@ top:
yyerror("string too long");
return (findeol());
}
- } while ((c = lgetc(fin)) != EOF && (allowed_in_string(c)));
+ } while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
lungetc(c);
*p = '\0';
if ((token = lookup(buf)) == STRING)
@@ -5227,8 +5636,8 @@ top:
return (token);
}
if (c == '\n') {
- yylval.lineno = lineno;
- lineno++;
+ yylval.lineno = file->lineno;
+ file->lineno++;
}
if (c == EOF)
return (0);
@@ -5236,13 +5645,84 @@ top:
}
int
-parse_rules(FILE *input, struct pfctl *xpf)
+check_file_secrecy(int fd, const char *fname)
+{
+ struct stat st;
+
+ if (fstat(fd, &st)) {
+ warn("cannot stat %s", fname);
+ return (-1);
+ }
+ if (st.st_uid != 0 && st.st_uid != getuid()) {
+ warnx("%s: owner not root or current user", fname);
+ return (-1);
+ }
+ if (st.st_mode & (S_IRWXG | S_IRWXO)) {
+ warnx("%s: group/world readable/writeable", fname);
+ return (-1);
+ }
+ return (0);
+}
+
+struct file *
+pushfile(const char *name, int secret)
+{
+ struct file *nfile;
+
+ if ((nfile = calloc(1, sizeof(struct file))) == NULL ||
+ (nfile->name = strdup(name)) == NULL) {
+ warn("malloc");
+ return (NULL);
+ }
+ if (TAILQ_FIRST(&files) == NULL && strcmp(nfile->name, "-") == 0) {
+ nfile->stream = stdin;
+ free(nfile->name);
+ if ((nfile->name = strdup("stdin")) == NULL) {
+ warn("strdup");
+ free(nfile);
+ return (NULL);
+ }
+ } else if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
+ warn("%s", nfile->name);
+ free(nfile->name);
+ free(nfile);
+ return (NULL);
+ } else if (secret &&
+ check_file_secrecy(fileno(nfile->stream), nfile->name)) {
+ fclose(nfile->stream);
+ free(nfile->name);
+ free(nfile);
+ return (NULL);
+ }
+ nfile->lineno = 1;
+ TAILQ_INSERT_TAIL(&files, nfile, entry);
+ return (nfile);
+}
+
+int
+popfile(void)
{
- struct sym *sym, *next;
+ struct file *prev;
+
+ if ((prev = TAILQ_PREV(file, files, entry)) != NULL) {
+ prev->errors += file->errors;
+ TAILQ_REMOVE(&files, file, entry);
+ fclose(file->stream);
+ free(file->name);
+ free(file);
+ file = prev;
+ return (0);
+ }
+ return (EOF);
+}
+
+int
+parse_config(char *filename, struct pfctl *xpf)
+{
+ int errors = 0;
+ struct sym *sym;
- fin = input;
pf = xpf;
- lineno = 1;
errors = 0;
rulestate = PFCTL_STATE_NONE;
returnicmpdefault = (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT;
@@ -5251,34 +5731,36 @@ parse_rules(FILE *input, struct pfctl *xpf)
blockpolicy = PFRULE_DROP;
require_order = 1;
+ if ((file = pushfile(filename, 0)) == NULL) {
+ warn("cannot open the main config file!");
+ return (-1);
+ }
+
yyparse();
+ errors = file->errors;
+ popfile();
/* Free macros and check which have not been used. */
- for (sym = TAILQ_FIRST(&symhead); sym != NULL; sym = next) {
- next = TAILQ_NEXT(sym, entries);
+ while ((sym = TAILQ_FIRST(&symhead))) {
if ((pf->opts & PF_OPT_VERBOSE2) && !sym->used)
fprintf(stderr, "warning: macro '%s' not "
"used\n", sym->nam);
free(sym->nam);
free(sym->val);
- TAILQ_REMOVE(&symhead, sym, entries);
+ TAILQ_REMOVE(&symhead, sym, entry);
free(sym);
}
return (errors ? -1 : 0);
}
-/*
- * Over-designed efficiency is a French and German concept, so how about
- * we wait until they discover this ugliness and make it all fancy.
- */
int
symset(const char *nam, const char *val, int persist)
{
struct sym *sym;
for (sym = TAILQ_FIRST(&symhead); sym && strcmp(nam, sym->nam);
- sym = TAILQ_NEXT(sym, entries))
+ sym = TAILQ_NEXT(sym, entry))
; /* nothing */
if (sym != NULL) {
@@ -5287,7 +5769,7 @@ symset(const char *nam, const char *val, int persist)
else {
free(sym->nam);
free(sym->val);
- TAILQ_REMOVE(&symhead, sym, entries);
+ TAILQ_REMOVE(&symhead, sym, entry);
free(sym);
}
}
@@ -5307,7 +5789,7 @@ symset(const char *nam, const char *val, int persist)
}
sym->used = 0;
sym->persist = persist;
- TAILQ_INSERT_TAIL(&symhead, sym, entries);
+ TAILQ_INSERT_TAIL(&symhead, sym, entry);
return (0);
}
@@ -5336,7 +5818,7 @@ symget(const char *nam)
{
struct sym *sym;
- TAILQ_FOREACH(sym, &symhead, entries)
+ TAILQ_FOREACH(sym, &symhead, entry)
if (strcmp(nam, sym->nam) == 0) {
sym->used = 1;
return (sym->val);
@@ -5519,20 +6001,50 @@ parseicmpspec(char *w, sa_family_t af)
}
int
+parseport(char *port, struct range *r, int extensions)
+{
+ char *p = strchr(port, ':');
+
+ if (p == NULL) {
+ if ((r->a = getservice(port)) == -1)
+ return (-1);
+ r->b = 0;
+ r->t = PF_OP_NONE;
+ return (0);
+ }
+ if ((extensions & PPORT_STAR) && !strcmp(p+1, "*")) {
+ *p = 0;
+ if ((r->a = getservice(port)) == -1)
+ return (-1);
+ r->b = 0;
+ r->t = PF_OP_IRG;
+ return (0);
+ }
+ if ((extensions & PPORT_RANGE)) {
+ *p++ = 0;
+ if ((r->a = getservice(port)) == -1 ||
+ (r->b = getservice(p)) == -1)
+ return (-1);
+ if (r->a == r->b) {
+ r->b = 0;
+ r->t = PF_OP_NONE;
+ } else
+ r->t = PF_OP_RRG;
+ return (0);
+ }
+ return (-1);
+}
+
+int
pfctl_load_anchors(int dev, struct pfctl *pf, struct pfr_buffer *trans)
{
struct loadanchors *la;
- FILE *fin;
TAILQ_FOREACH(la, &loadanchorshead, entries) {
if (pf->opts & PF_OPT_VERBOSE)
fprintf(stderr, "\nLoading anchor %s from %s\n",
la->anchorname, la->filename);
- if ((fin = pfctl_fopen(la->filename, "r")) == NULL) {
- warn("%s", la->filename);
- continue;
- }
- if (pfctl_rules(dev, la->filename, fin, pf->opts, pf->optimize,
+ if (pfctl_rules(dev, la->filename, pf->opts, pf->optimize,
la->anchorname, trans) == -1)
return (-1);
}
diff --git a/contrib/pf/pfctl/pf_print_state.c b/contrib/pf/pfctl/pf_print_state.c
index 02a39b321567..069851646049 100644
--- a/contrib/pf/pfctl/pf_print_state.c
+++ b/contrib/pf/pfctl/pf_print_state.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_print_state.c,v 1.44 2007/03/01 17:20:53 deraadt Exp $ */
+/* $OpenBSD: pf_print_state.c,v 1.52 2008/08/12 16:40:18 david Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -35,7 +35,10 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/socket.h>
+#ifdef __FreeBSD__
#include <sys/endian.h>
+#define betoh64 be64toh
+#endif
#include <net/if.h>
#define TCPSTATES
#include <netinet/tcp_fsm.h>
@@ -83,6 +86,19 @@ print_addr(struct pf_addr_wrap *addr, sa_family_t af, int verbose)
else
printf("<%s>", addr->v.tblname);
return;
+ case PF_ADDR_RANGE: {
+ char buf[48];
+
+ if (inet_ntop(af, &addr->v.a.addr, buf, sizeof(buf)) == NULL)
+ printf("?");
+ else
+ printf("%s", buf);
+ if (inet_ntop(af, &addr->v.a.mask, buf, sizeof(buf)) == NULL)
+ printf(" - ?");
+ else
+ printf(" - %s", buf);
+ break;
+ }
case PF_ADDR_ADDRMASK:
if (PF_AZERO(&addr->v.a.addr, AF_INET6) &&
PF_AZERO(&addr->v.a.mask, AF_INET6))
@@ -112,7 +128,8 @@ print_addr(struct pf_addr_wrap *addr, sa_family_t af, int verbose)
}
/* mask if not _both_ address and mask are zero */
- if (!(PF_AZERO(&addr->v.a.addr, AF_INET6) &&
+ if (addr->type != PF_ADDR_RANGE &&
+ !(PF_AZERO(&addr->v.a.addr, AF_INET6) &&
PF_AZERO(&addr->v.a.mask, AF_INET6))) {
int bits = unmask(&addr->v.a.mask, af);
@@ -155,17 +172,15 @@ print_name(struct pf_addr *addr, sa_family_t af)
}
void
-print_host(struct pf_state_host *h, sa_family_t af, int opts)
+print_host(struct pf_addr *addr, u_int16_t port, sa_family_t af, int opts)
{
- u_int16_t p = ntohs(h->port);
-
if (opts & PF_OPT_USEDNS)
- print_name(&h->addr, af);
+ print_name(addr, af);
else {
struct pf_addr_wrap aw;
memset(&aw, 0, sizeof(aw));
- aw.v.a.addr = h->addr;
+ aw.v.a.addr = *addr;
if (af == AF_INET)
aw.v.a.mask.addr32[0] = 0xffffffff;
else {
@@ -175,57 +190,72 @@ print_host(struct pf_state_host *h, sa_family_t af, int opts)
print_addr(&aw, af, opts & PF_OPT_VERBOSE2);
}
- if (p) {
+ if (port) {
if (af == AF_INET)
- printf(":%u", p);
+ printf(":%u", ntohs(port));
else
- printf("[%u]", p);
+ printf("[%u]", ntohs(port));
}
}
void
-print_seq(struct pf_state_peer *p)
+print_seq(struct pfsync_state_peer *p)
{
if (p->seqdiff)
- printf("[%u + %u](+%u)", p->seqlo, p->seqhi - p->seqlo,
- p->seqdiff);
+ printf("[%u + %u](+%u)", ntohl(p->seqlo),
+ ntohl(p->seqhi) - ntohl(p->seqlo), ntohl(p->seqdiff));
else
- printf("[%u + %u]", p->seqlo, p->seqhi - p->seqlo);
+ printf("[%u + %u]", ntohl(p->seqlo),
+ ntohl(p->seqhi) - ntohl(p->seqlo));
}
void
-print_state(struct pf_state *s, int opts)
+print_state(struct pfsync_state *s, int opts)
{
- struct pf_state_peer *src, *dst;
+ struct pfsync_state_peer *src, *dst;
+ struct pfsync_state_key *sk, *nk;
struct protoent *p;
int min, sec;
if (s->direction == PF_OUT) {
src = &s->src;
dst = &s->dst;
+ sk = &s->key[PF_SK_STACK];
+ nk = &s->key[PF_SK_WIRE];
+ if (s->proto == IPPROTO_ICMP || s->proto == IPPROTO_ICMPV6)
+ sk->port[0] = nk->port[0];
} else {
src = &s->dst;
dst = &s->src;
+ sk = &s->key[PF_SK_WIRE];
+ nk = &s->key[PF_SK_STACK];
+ if (s->proto == IPPROTO_ICMP || s->proto == IPPROTO_ICMPV6)
+ sk->port[1] = nk->port[1];
}
- printf("%s ", s->u.ifname);
+ printf("%s ", s->ifname);
if ((p = getprotobynumber(s->proto)) != NULL)
printf("%s ", p->p_name);
else
printf("%u ", s->proto);
- if (PF_ANEQ(&s->lan.addr, &s->gwy.addr, s->af) ||
- (s->lan.port != s->gwy.port)) {
- print_host(&s->lan, s->af, opts);
- if (s->direction == PF_OUT)
- printf(" -> ");
- else
- printf(" <- ");
+
+ print_host(&nk->addr[1], nk->port[1], s->af, opts);
+ if (PF_ANEQ(&nk->addr[1], &sk->addr[1], s->af) ||
+ nk->port[1] != sk->port[1]) {
+ printf(" (");
+ print_host(&sk->addr[1], sk->port[1], s->af, opts);
+ printf(")");
}
- print_host(&s->gwy, s->af, opts);
if (s->direction == PF_OUT)
printf(" -> ");
else
printf(" <- ");
- print_host(&s->ext, s->af, opts);
+ print_host(&nk->addr[0], nk->port[0], s->af, opts);
+ if (PF_ANEQ(&nk->addr[0], &sk->addr[0], s->af) ||
+ nk->port[0] != sk->port[0]) {
+ printf(" (");
+ print_host(&sk->addr[0], sk->port[0], s->af, opts);
+ printf(")");
+ }
printf(" ");
if (s->proto == IPPROTO_TCP) {
@@ -271,45 +301,63 @@ print_state(struct pf_state *s, int opts)
}
if (opts & PF_OPT_VERBOSE) {
- sec = s->creation % 60;
- s->creation /= 60;
- min = s->creation % 60;
- s->creation /= 60;
- printf(" age %.2u:%.2u:%.2u", s->creation, min, sec);
- sec = s->expire % 60;
- s->expire /= 60;
- min = s->expire % 60;
- s->expire /= 60;
- printf(", expires in %.2u:%.2u:%.2u", s->expire, min, sec);
+ u_int64_t packets[2];
+ u_int64_t bytes[2];
+ u_int32_t creation = ntohl(s->creation);
+ u_int32_t expire = ntohl(s->expire);
+
+ sec = creation % 60;
+ creation /= 60;
+ min = creation % 60;
+ creation /= 60;
+ printf(" age %.2u:%.2u:%.2u", creation, min, sec);
+ sec = expire % 60;
+ expire /= 60;
+ min = expire % 60;
+ expire /= 60;
+ printf(", expires in %.2u:%.2u:%.2u", expire, min, sec);
+
+ bcopy(s->packets[0], &packets[0], sizeof(u_int64_t));
+ bcopy(s->packets[1], &packets[1], sizeof(u_int64_t));
+ bcopy(s->bytes[0], &bytes[0], sizeof(u_int64_t));
+ bcopy(s->bytes[1], &bytes[1], sizeof(u_int64_t));
printf(", %llu:%llu pkts, %llu:%llu bytes",
#ifdef __FreeBSD__
- (unsigned long long)s->packets[0],
- (unsigned long long)s->packets[1],
- (unsigned long long)s->bytes[0],
- (unsigned long long)s->bytes[1]);
+ (unsigned long long)betoh64(packets[0]),
+ (unsigned long long)betoh64(packets[1]),
+ (unsigned long long)betoh64(bytes[0]),
+ (unsigned long long)betoh64(bytes[1]));
#else
- s->packets[0], s->packets[1], s->bytes[0], s->bytes[1]);
+ betoh64(packets[0]),
+ betoh64(packets[1]),
+ betoh64(bytes[0]),
+ betoh64(bytes[1]));
#endif
- if (s->anchor.nr != -1)
- printf(", anchor %u", s->anchor.nr);
- if (s->rule.nr != -1)
- printf(", rule %u", s->rule.nr);
+ if (ntohl(s->anchor) != -1)
+ printf(", anchor %u", ntohl(s->anchor));
+ if (ntohl(s->rule) != -1)
+ printf(", rule %u", ntohl(s->rule));
if (s->state_flags & PFSTATE_SLOPPY)
printf(", sloppy");
- if (s->src_node != NULL)
+ if (s->state_flags & PFSTATE_PFLOW)
+ printf(", pflow");
+ if (s->sync_flags & PFSYNC_FLAG_SRCNODE)
printf(", source-track");
- if (s->nat_src_node != NULL)
+ if (s->sync_flags & PFSYNC_FLAG_NATSRCNODE)
printf(", sticky-address");
printf("\n");
}
if (opts & PF_OPT_VERBOSE2) {
- printf(" id: %016llx creatorid: %08x%s\n",
+ u_int64_t id;
+
+ bcopy(&s->id, &id, sizeof(u_int64_t));
+ printf(" id: %016llx creatorid: %08x",
#ifdef __FreeBSD__
- (unsigned long long)be64toh(s->id), ntohl(s->creatorid),
+ (unsigned long long)betoh64(id), ntohl(s->creatorid));
#else
- betoh64(s->id), ntohl(s->creatorid),
+ betoh64(id), ntohl(s->creatorid));
#endif
- ((s->sync_flags & PFSTATE_NOSYNC) ? " (no-sync)" : ""));
+ printf("\n");
}
}
diff --git a/contrib/pf/pfctl/pfctl.8 b/contrib/pf/pfctl/pfctl.8
index 917a859745c7..07304432d5d5 100644
--- a/contrib/pf/pfctl/pfctl.8
+++ b/contrib/pf/pfctl/pfctl.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: pfctl.8,v 1.128 2007/01/30 21:01:56 jmc Exp $
+.\" $OpenBSD: pfctl.8,v 1.138 2008/06/10 20:55:02 mcbride Exp $
.\"
.\" Copyright (c) 2001 Kjell Wooding. All rights reserved.
.\"
@@ -26,12 +26,12 @@
.\"
.\" $FreeBSD$
.\"
-.Dd June 13, 2011
+.Dd June 21, 2011
.Dt PFCTL 8
.Os
.Sh NAME
.Nm pfctl
-.Nd "control the packet filter (PF) and network address translation (NAT) device"
+.Nd control the packet filter (PF) device
.Sh SYNOPSIS
.Nm pfctl
.Bk -words
@@ -43,15 +43,18 @@
.Op Fl f Ar file
.Op Fl i Ar interface
.Op Fl K Ar host | network
-.Op Fl k Ar host | network
-.Op Fl o Op Ar level
+.Xo
+.Oo Fl k
+.Ar host | network | label | id
+.Oc Xc
+.Op Fl o Ar level
.Op Fl p Ar device
.Op Fl s Ar modifier
-.Oo
-.Fl t Ar table
+.Xo
+.Oo Fl t Ar table
.Fl T Ar command
-.Op Ar address ...
-.Oc
+.Op Ar address ... Oc
+.Xc
.Op Fl x Ar level
.Ek
.Sh DESCRIPTION
@@ -85,7 +88,7 @@ When the variable
is set to
.Dv YES
in
-.Xr rc.conf.local 5 ,
+.Xr rc.conf.local 8 ,
the rule file specified with the variable
.Va pf_rules
is loaded automatically by the
@@ -211,7 +214,7 @@ Flush the NAT rules.
Flush the queue rules.
.It Fl F Cm rules
Flush the filter rules.
-.It Fl F Cm state
+.It Fl F Cm states
Flush the state table (NAT and filter).
.It Fl F Cm Sources
Flush the source tracking table.
@@ -251,22 +254,28 @@ or
.Fl K Ar network
option may be specified, which will kill all the source tracking
entries from the first host/network to the second.
-.It Fl k Ar host | network
-Kill all of the state entries originating from the specified
-.Ar host
+.It Xo
+.Fl k
+.Ar host | network | label | id
+.Xc
+Kill all of the state entries matching the specified
+.Ar host ,
+.Ar network ,
+.Ar label ,
or
-.Ar network .
+.Ar id .
+.Pp
+For example, to kill all of the state entries originating from
+.Dq host :
+.Pp
+.Dl # pfctl -k host
+.Pp
A second
.Fl k Ar host
or
.Fl k Ar network
option may be specified, which will kill all the state entries
from the first host/network to the second.
-For example, to kill all of the state entries originating from
-.Dq host :
-.Pp
-.Dl # pfctl -k host
-.Pp
To kill all of the state entries from
.Dq host1
to
@@ -283,6 +292,32 @@ To kill all states with the target
.Dq host2 :
.Pp
.Dl # pfctl -k 0.0.0.0/0 -k host2
+.Pp
+It is also possible to kill states by rule label or state ID.
+In this mode the first
+.Fl k
+argument is used to specify the type
+of the second argument.
+The following command would kill all states that have been created
+from rules carrying the label
+.Dq foobar :
+.Pp
+.Dl # pfctl -k label -k foobar
+.Pp
+To kill one specific state by its unique state ID
+(as shown by pfctl -s state -vv),
+use the
+.Ar id
+modifier and as a second argument the state ID and optional creator ID.
+To kill a state with ID 4823e84500000003 use:
+.Pp
+.Dl # pfctl -k id -k 4823e84500000003
+.Pp
+To kill a state with ID 4823e84500000018 created from a backup
+firewall with hostid 00000002 use:
+.Pp
+.Dl # pfctl -k id -k 4823e84500000018/2
+.Pp
.It Fl m
Merge in explicitly given options without resetting those
which are omitted.
@@ -298,58 +333,20 @@ Do not actually load rules, just parse them.
.It Fl O
Load only the options present in the rule file.
Other rules and options are ignored.
-.It Fl o Op Ar level
-Control the ruleset optimizer.
-The ruleset optimizer attempts to improve rulesets by removing rule
-duplication and making better use of rule ordering.
+.It Fl o Ar level
+Control the ruleset optimizer, overriding any rule file settings.
.Pp
.Bl -tag -width xxxxxxxxxxxx -compact
.It Fl o Cm none
Disable the ruleset optimizer.
.It Fl o Cm basic
Enable basic ruleset optimizations.
+This is the default behaviour.
.It Fl o Cm profile
Enable basic ruleset optimizations with profiling.
.El
-.Pp
-.Cm basic
-optimization does does four things:
-.Pp
-.Bl -enum -compact
-.It
-remove duplicate rules
-.It
-remove rules that are a subset of another rule
-.It
-combine multiple rules into a table when advantageous
-.It
-re-order the rules to improve evaluation performance
-.El
-.Pp
-If
-.Cm profile
-is specified, the currently loaded ruleset will be examined as a feedback
-profile to tailor the optimization of the
-.Ar quick
-rules to the actual network behavior.
-.Pp
-It is important to note that the ruleset optimizer will modify the ruleset
-to improve performance.
-A side effect of the ruleset modification is that per-rule accounting
-statistics will have different meanings than before.
-If per-rule accounting is important for billing purposes or whatnot, either
-the ruleset optimizer should not be used or a
-.Ar label
-field should be added to all of the accounting rules to act as optimization
-barriers.
-.Pp
-To retain compatibility with previous behaviour, a single
-.Fl o
-without any options will enable
-.Cm basic
-optimizations, and a second
-.Fl o
-will enable profiling.
+For further information on the ruleset optimizer, see
+.Xr pf.conf 5 .
.It Fl P
Do not perform service name lookup for port specific rules,
instead display the ports numerically.
@@ -407,7 +404,7 @@ If
.Fl v
is specified, all anchors attached under the target anchor will be
displayed recursively.
-.It Fl s Cm state
+.It Fl s Cm states
Show the contents of the state table.
.It Fl s Cm Sources
Show the contents of the source tracking table.
@@ -418,7 +415,7 @@ When used together with
source tracking statistics are also shown.
.It Fl s Cm labels
Show per-rule statistics (label, evaluations, packets total, bytes total,
-packets in, bytes in, packets out, bytes out) of
+packets in, bytes in, packets out, bytes out, state creations) of
filter rules with labels, useful for accounting.
.It Fl s Cm timeouts
Show the current global timeouts.
@@ -529,7 +526,7 @@ attributes.
The address/network has been cleared (statistics).
.El
.Pp
-Each table maintains a set of counters that can be retrieved using the
+Each table can maintain a set of counters that can be retrieved using the
.Fl v
flag of
.Nm .
@@ -540,7 +537,7 @@ FTP server.
The following commands configure the firewall and send 10 pings to the FTP
server:
.Bd -literal -offset indent
-# printf "table <test> { ftp.openbsd.org }\en \e
+# printf "table <test> counters { ftp.openbsd.org }\en \e
pass out to <test>\en" | pfctl -f-
# ping -qc10 ftp.openbsd.org
.Ed
@@ -574,7 +571,7 @@ the number of rules which reference the table, and the global
packet statistics for the whole table:
.Bd -literal -offset indent
# pfctl -vvsTables
---a-r- test
+--a-r-C test
Addresses: 1
Cleared: Thu Feb 13 18:55:18 2003
References: [ Anchors: 0 Rules: 1 ]
@@ -634,6 +631,8 @@ For tables which are referenced (used) by rules.
.It h
This flag is set when a table in the main ruleset is hidden by one or more
tables of the same name from anchors attached below it.
+.It C
+This flag is set when per-address counters are enabled on the table.
.El
.It Fl t Ar table
Specify the name of the table.
diff --git a/contrib/pf/pfctl/pfctl.c b/contrib/pf/pfctl/pfctl.c
index e76261bdcbbf..8b07a2be3bc8 100644
--- a/contrib/pf/pfctl/pfctl.c
+++ b/contrib/pf/pfctl/pfctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl.c,v 1.262 2007/03/01 17:20:53 deraadt Exp $ */
+/* $OpenBSD: pfctl.c,v 1.278 2008/08/31 20:18:17 jmc Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -39,6 +39,10 @@ __FBSDID("$FreeBSD$");
#include <sys/socket.h>
#include <sys/stat.h>
+#ifdef __FreeBSD__
+#include <sys/endian.h>
+#endif
+
#include <net/if.h>
#include <netinet/in.h>
#include <net/pfvar.h>
@@ -59,10 +63,6 @@ __FBSDID("$FreeBSD$");
#include "pfctl_parser.h"
#include "pfctl.h"
-#ifdef __FreeBSD__
-#define HTONL(x) (x) = htonl((__uint32_t)(x))
-#endif
-
void usage(void);
int pfctl_enable(int, int);
int pfctl_disable(int, int);
@@ -75,7 +75,9 @@ int pfctl_clear_src_nodes(int, int);
int pfctl_clear_states(int, const char *, int);
void pfctl_addrprefix(char *, struct pf_addr *);
int pfctl_kill_src_nodes(int, const char *, int);
-int pfctl_kill_states(int, const char *, int);
+int pfctl_net_kill_states(int, const char *, int);
+int pfctl_label_kill_states(int, const char *, int);
+int pfctl_id_kill_states(int, const char *, int);
void pfctl_init_options(struct pfctl *);
int pfctl_load_options(struct pfctl *);
int pfctl_load_limit(struct pfctl *, unsigned int, unsigned int);
@@ -126,8 +128,6 @@ int dev = -1;
int first_title = 1;
int labels = 0;
-const char *infile;
-
#define INDENT(d, o) do { \
if (o) { \
int i; \
@@ -208,11 +208,11 @@ static const struct {
static const char *clearopt_list[] = {
"nat", "queue", "rules", "Sources",
- "state", "info", "Tables", "osfp", "all", NULL
+ "states", "info", "Tables", "osfp", "all", NULL
};
static const char *showopt_list[] = {
- "nat", "queue", "rules", "Anchors", "Sources", "state", "info",
+ "nat", "queue", "rules", "Anchors", "Sources", "states", "info",
"Interfaces", "labels", "timeouts", "memory", "Tables", "osfp",
"all", NULL
};
@@ -227,7 +227,7 @@ static const char *debugopt_list[] = {
};
static const char *optiopt_list[] = {
- "o", "none", "basic", "profile", NULL
+ "none", "basic", "profile", NULL
};
void
@@ -237,10 +237,11 @@ usage(void)
fprintf(stderr, "usage: %s [-AdeghmNnOPqRrvz] ", __progname);
fprintf(stderr, "[-a anchor] [-D macro=value] [-F modifier]\n");
- fprintf(stderr, "\t[-f file] [-i interface] [-K host | network] ");
- fprintf(stderr, "[-k host | network ]\n");
- fprintf(stderr, "\t[-o [level]] [-p device] [-s modifier ]\n");
- fprintf(stderr, "\t[-t table -T command [address ...]] [-x level]\n");
+ fprintf(stderr, "\t[-f file] [-i interface] [-K host | network]\n");
+ fprintf(stderr, "\t[-k host | network | label | id] ");
+ fprintf(stderr, "[-o level] [-p device]\n");
+ fprintf(stderr, "\t[-s modifier] ");
+ fprintf(stderr, "[-t table -T command [address ...]] [-x level]\n");
exit(1);
}
@@ -389,7 +390,7 @@ pfctl_clear_states(int dev, const char *iface, int opts)
if (ioctl(dev, DIOCCLRSTATES, &psk))
err(1, "DIOCCLRSTATES");
if ((opts & PF_OPT_QUIET) == 0)
- fprintf(stderr, "%d states cleared\n", psk.psk_af);
+ fprintf(stderr, "%d states cleared\n", psk.psk_killed);
return (0);
}
@@ -528,17 +529,13 @@ pfctl_kill_src_nodes(int dev, const char *iface, int opts)
if (ioctl(dev, DIOCKILLSRCNODES, &psnk))
err(1, "DIOCKILLSRCNODES");
- killed += psnk.psnk_af;
- /* fixup psnk.psnk_af */
- psnk.psnk_af = resp[1]->ai_family;
+ killed += psnk.psnk_killed;
}
freeaddrinfo(res[1]);
} else {
if (ioctl(dev, DIOCKILLSRCNODES, &psnk))
err(1, "DIOCKILLSRCNODES");
- killed += psnk.psnk_af;
- /* fixup psnk.psnk_af */
- psnk.psnk_af = res[0]->ai_family;
+ killed += psnk.psnk_killed;
}
}
@@ -551,7 +548,7 @@ pfctl_kill_src_nodes(int dev, const char *iface, int opts)
}
int
-pfctl_kill_states(int dev, const char *iface, int opts)
+pfctl_net_kill_states(int dev, const char *iface, int opts)
{
struct pfioc_state_kill psk;
struct addrinfo *res[2], *resp[2];
@@ -638,17 +635,13 @@ pfctl_kill_states(int dev, const char *iface, int opts)
if (ioctl(dev, DIOCKILLSTATES, &psk))
err(1, "DIOCKILLSTATES");
- killed += psk.psk_af;
- /* fixup psk.psk_af */
- psk.psk_af = resp[1]->ai_family;
+ killed += psk.psk_killed;
}
freeaddrinfo(res[1]);
} else {
if (ioctl(dev, DIOCKILLSTATES, &psk))
err(1, "DIOCKILLSTATES");
- killed += psk.psk_af;
- /* fixup psk.psk_af */
- psk.psk_af = res[0]->ai_family;
+ killed += psk.psk_killed;
}
}
@@ -661,6 +654,68 @@ pfctl_kill_states(int dev, const char *iface, int opts)
}
int
+pfctl_label_kill_states(int dev, const char *iface, int opts)
+{
+ struct pfioc_state_kill psk;
+
+ if (state_killers != 2 || (strlen(state_kill[1]) == 0)) {
+ warnx("no label specified");
+ usage();
+ }
+ memset(&psk, 0, sizeof(psk));
+ if (iface != NULL && strlcpy(psk.psk_ifname, iface,
+ sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname))
+ errx(1, "invalid interface: %s", iface);
+
+ if (strlcpy(psk.psk_label, state_kill[1], sizeof(psk.psk_label)) >=
+ sizeof(psk.psk_label))
+ errx(1, "label too long: %s", state_kill[1]);
+
+ if (ioctl(dev, DIOCKILLSTATES, &psk))
+ err(1, "DIOCKILLSTATES");
+
+ if ((opts & PF_OPT_QUIET) == 0)
+ fprintf(stderr, "killed %d states\n", psk.psk_killed);
+
+ return (0);
+}
+
+int
+pfctl_id_kill_states(int dev, const char *iface, int opts)
+{
+ struct pfioc_state_kill psk;
+
+ if (state_killers != 2 || (strlen(state_kill[1]) == 0)) {
+ warnx("no id specified");
+ usage();
+ }
+
+ memset(&psk, 0, sizeof(psk));
+ if ((sscanf(state_kill[1], "%jx/%x",
+ &psk.psk_pfcmp.id, &psk.psk_pfcmp.creatorid)) == 2)
+ HTONL(psk.psk_pfcmp.creatorid);
+ else if ((sscanf(state_kill[1], "%jx", &psk.psk_pfcmp.id)) == 1) {
+ psk.psk_pfcmp.creatorid = 0;
+ } else {
+ warnx("wrong id format specified");
+ usage();
+ }
+ if (psk.psk_pfcmp.id == 0) {
+ warnx("cannot kill id 0");
+ usage();
+ }
+
+ psk.psk_pfcmp.id = htobe64(psk.psk_pfcmp.id);
+ if (ioctl(dev, DIOCKILLSTATES, &psk))
+ err(1, "DIOCKILLSTATES");
+
+ if ((opts & PF_OPT_QUIET) == 0)
+ fprintf(stderr, "killed %d states\n", psk.psk_killed);
+
+ return (0);
+}
+
+int
pfctl_get_pool(int dev, struct pf_pool *pool, u_int32_t nr,
u_int32_t ticket, int r_action, char *anchorname)
{
@@ -747,10 +802,12 @@ pfctl_print_rule_counters(struct pf_rule *rule, int opts)
(unsigned long long)(rule->packets[0] +
rule->packets[1]),
(unsigned long long)(rule->bytes[0] +
- rule->bytes[1]), rule->states);
+ rule->bytes[1]), rule->states_cur);
if (!(opts & PF_OPT_DEBUG))
- printf(" [ Inserted: uid %u pid %u ]\n",
- (unsigned)rule->cuid, (unsigned)rule->cpid);
+ printf(" [ Inserted: uid %u pid %u "
+ "State Creations: %-6u]\n",
+ (unsigned)rule->cuid, (unsigned)rule->cpid,
+ rule->states_tot);
}
}
@@ -818,19 +875,6 @@ pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format,
switch (format) {
case PFCTL_SHOW_LABELS:
- if (pr.rule.label[0]) {
- printf("%s ", pr.rule.label);
- printf("%llu %llu %llu %llu %llu %llu %llu\n",
- (unsigned long long)pr.rule.evaluations,
- (unsigned long long)(pr.rule.packets[0] +
- pr.rule.packets[1]),
- (unsigned long long)(pr.rule.bytes[0] +
- pr.rule.bytes[1]),
- (unsigned long long)pr.rule.packets[0],
- (unsigned long long)pr.rule.bytes[0],
- (unsigned long long)pr.rule.packets[1],
- (unsigned long long)pr.rule.bytes[1]);
- }
break;
case PFCTL_SHOW_RULES:
if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL))
@@ -864,8 +908,9 @@ pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format,
switch (format) {
case PFCTL_SHOW_LABELS:
if (pr.rule.label[0]) {
- printf("%s ", pr.rule.label);
- printf("%llu %llu %llu %llu %llu %llu %llu\n",
+ printf("%s %llu %llu %llu %llu"
+ " %llu %llu %llu %llu\n",
+ pr.rule.label,
(unsigned long long)pr.rule.evaluations,
(unsigned long long)(pr.rule.packets[0] +
pr.rule.packets[1]),
@@ -874,7 +919,8 @@ pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format,
(unsigned long long)pr.rule.packets[0],
(unsigned long long)pr.rule.bytes[0],
(unsigned long long)pr.rule.packets[1],
- (unsigned long long)pr.rule.bytes[1]);
+ (unsigned long long)pr.rule.bytes[1],
+ (unsigned long long)pr.rule.states_tot);
}
break;
case PFCTL_SHOW_RULES:
@@ -967,7 +1013,7 @@ pfctl_show_src_nodes(int dev, int opts)
struct pfioc_src_nodes psn;
struct pf_src_node *p;
char *inbuf = NULL, *newinbuf = NULL;
- unsigned len = 0;
+ unsigned int len = 0;
int i;
memset(&psn, 0, sizeof(psn));
@@ -1010,9 +1056,9 @@ int
pfctl_show_states(int dev, const char *iface, int opts)
{
struct pfioc_states ps;
- struct pf_state *p;
+ struct pfsync_state *p;
char *inbuf = NULL, *newinbuf = NULL;
- unsigned len = 0;
+ unsigned int len = 0;
int i, dotitle = (opts & PF_OPT_SHOWALL);
memset(&ps, 0, sizeof(ps));
@@ -1041,7 +1087,7 @@ pfctl_show_states(int dev, const char *iface, int opts)
}
p = ps.ps_states;
for (i = 0; i < ps.ps_len; i += sizeof(*p), p++) {
- if (iface != NULL && strcmp(p->u.ifname, iface))
+ if (iface != NULL && strcmp(p->ifname, iface))
continue;
if (dotitle) {
pfctl_print_title("STATES:");
@@ -1163,7 +1209,7 @@ pfctl_add_rule(struct pfctl *pf, struct pf_rule *r, const char *anchor_call)
r->anchor->ruleset.anchor = r->anchor;
if (strlcpy(r->anchor->path, anchor_call,
sizeof(rule->anchor->path)) >= sizeof(rule->anchor->path))
- errx(1, "pfctl_add_rule: strlcpy");
+ errx(1, "pfctl_add_rule: strlcpy");
if ((p = strrchr(anchor_call, '/')) != NULL) {
if (!strlen(p))
err(1, "pfctl_add_rule: bad anchor name %s",
@@ -1172,7 +1218,7 @@ pfctl_add_rule(struct pfctl *pf, struct pf_rule *r, const char *anchor_call)
p = (char *)anchor_call;
if (strlcpy(r->anchor->name, p,
sizeof(rule->anchor->name)) >= sizeof(rule->anchor->name))
- errx(1, "pfctl_add_rule: strlcpy");
+ errx(1, "pfctl_add_rule: strlcpy");
}
if ((rule = calloc(1, sizeof(*rule))) == NULL)
@@ -1197,7 +1243,7 @@ pfctl_ruleset_trans(struct pfctl *pf, char *path, struct pf_anchor *a)
return (1);
}
if (a == pf->astack[0] && ((altqsupport &&
- (pf->loadopt & PFCTL_FLAG_ALTQ) != 0))) {
+ (pf->loadopt & PFCTL_FLAG_ALTQ) != 0))) {
if (pfctl_add_trans(pf->trans, PF_RULESET_ALTQ, path))
return (2);
}
@@ -1350,7 +1396,7 @@ pfctl_add_altq(struct pfctl *pf, struct pf_altq *a)
}
int
-pfctl_rules(int dev, char *filename, FILE *fin, int opts, int optimize,
+pfctl_rules(int dev, char *filename, int opts, int optimize,
char *anchorname, struct pfr_buffer *trans)
{
#define ERR(x) do { warn(x); goto _error; } while(0)
@@ -1386,7 +1432,6 @@ pfctl_rules(int dev, char *filename, FILE *fin, int opts, int optimize,
if (strlcpy(trs.pfrt_anchor, anchorname,
sizeof(trs.pfrt_anchor)) >= sizeof(trs.pfrt_anchor))
ERRX("pfctl_rules: strlcpy");
- infile = filename;
pf.dev = dev;
pf.opts = opts;
pf.optimize = optimize;
@@ -1430,7 +1475,7 @@ pfctl_rules(int dev, char *filename, FILE *fin, int opts, int optimize,
pfctl_get_ticket(t, PF_RULESET_TABLE, anchorname);
}
- if (parse_rules(fin, &pf) < 0) {
+ if (parse_config(filename, &pf) < 0) {
if ((opts & PF_OPT_NOACTION) == 0)
ERRX("Syntax error in config file: "
"pf rules not loaded");
@@ -1456,11 +1501,6 @@ pfctl_rules(int dev, char *filename, FILE *fin, int opts, int optimize,
if (check_commit_altq(dev, opts) != 0)
ERRX("errors in altq config");
- if (fin != stdin) {
- fclose(fin);
- fin = NULL;
- }
-
/* process "load anchor" directives */
if (!anchorname[0])
if (pfctl_load_anchors(dev, &pf, t) == -1)
@@ -1482,8 +1522,6 @@ _error:
err(1, "DIOCXROLLBACK");
exit(1);
} else { /* sub ruleset */
- if (fin != NULL && fin != stdin)
- fclose(fin);
return (-1);
}
@@ -1515,7 +1553,8 @@ pfctl_fopen(const char *name, const char *mode)
void
pfctl_init_options(struct pfctl *pf)
{
- int mib[2], mem;
+ int64_t mem;
+ int mib[2];
size_t size;
pf->timeout[PFTM_TCP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL;
@@ -1546,9 +1585,14 @@ pfctl_init_options(struct pfctl *pf)
pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT;
mib[0] = CTL_HW;
+#ifdef __FreeBSD__
mib[1] = HW_PHYSMEM;
+#else
+ mib[1] = HW_PHYSMEM64;
+#endif
size = sizeof(mem);
- (void) sysctl(mib, 2, &mem, &size, NULL, 0);
+ if (sysctl(mib, 2, &mem, &size, NULL, 0) == -1)
+ err(1, "sysctl");
if (mem <= 100*1024*1024)
pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT_SMALL;
@@ -1572,7 +1616,7 @@ pfctl_load_options(struct pfctl *pf)
}
/*
- * If we've set the limit, but havn't explicitly set adaptive
+ * If we've set the limit, but haven't explicitly set adaptive
* timeouts, do it now with a start of 60% and end of 120%.
*/
if (pf->limit_set[PF_LIMIT_STATES] &&
@@ -1897,9 +1941,6 @@ pfctl_debug(int dev, u_int32_t level, int opts)
int
pfctl_test_altqsupport(int dev, int opts)
{
-#if defined(__FreeBSD__) && !defined(ENABLE_ALTQ)
- return (0);
-#else
struct pfioc_altq pa;
if (ioctl(dev, DIOCGETALTQS, &pa)) {
@@ -1912,7 +1953,6 @@ pfctl_test_altqsupport(int dev, int opts)
err(1, "DIOCGETALTQS");
}
return (1);
-#endif
}
int
@@ -1971,16 +2011,15 @@ main(int argc, char *argv[])
int ch;
int mode = O_RDONLY;
int opts = 0;
- int optimize = 0;
+ int optimize = PF_OPTIMIZE_BASIC;
char anchorname[MAXPATHLEN];
char *path;
- FILE *fin = NULL;
if (argc < 2)
usage();
while ((ch = getopt(argc, argv,
- "a:AdD:eqf:F:ghi:k:K:mnNOo::Pp:rRs:t:T:vx:z")) != -1) {
+ "a:AdD:eqf:F:ghi:k:K:mnNOo:Pp:rRs:t:T:vx:z")) != -1) {
switch (ch) {
case 'a':
anchoropt = optarg;
@@ -2056,24 +2095,11 @@ main(int argc, char *argv[])
loadopt |= PFCTL_FLAG_FILTER;
break;
case 'o':
- if (optarg) {
- optiopt = pfctl_lookup_option(optarg,
- optiopt_list);
- if (optiopt == NULL) {
- warnx("Unknown optimization '%s'",
- optarg);
- usage();
- }
- }
- if (opts & PF_OPT_OPTIMIZE) {
- if (optiopt != NULL) {
- warnx("Cannot specify -o multiple times"
- "with optimizer level");
- usage();
- }
- optimize |= PF_OPTIMIZE_PROFILE;
+ optiopt = pfctl_lookup_option(optarg, optiopt_list);
+ if (optiopt == NULL) {
+ warnx("Unknown optimization '%s'", optarg);
+ usage();
}
- optimize |= PF_OPTIMIZE_BASIC;
opts |= PF_OPT_OPTIMIZE;
break;
case 'O':
@@ -2303,8 +2329,14 @@ main(int argc, char *argv[])
break;
}
}
- if (state_killers)
- pfctl_kill_states(dev, ifaceopt, opts);
+ if (state_killers) {
+ if (!strcmp(state_kill[0], "label"))
+ pfctl_label_kill_states(dev, ifaceopt, opts);
+ else if (!strcmp(state_kill[0], "id"))
+ pfctl_id_kill_states(dev, ifaceopt, opts);
+ else
+ pfctl_net_kill_states(dev, ifaceopt, opts);
+ }
if (src_node_killers)
pfctl_kill_src_nodes(dev, ifaceopt, opts);
@@ -2329,15 +2361,6 @@ main(int argc, char *argv[])
}
}
- if (rulesopt != NULL) {
- if (strcmp(rulesopt, "-") == 0) {
- fin = stdin;
- rulesopt = "stdin";
- } else {
- if ((fin = pfctl_fopen(rulesopt, "r")) == NULL)
- err(1, "%s", rulesopt);
- }
- }
if ((rulesopt != NULL) && (loadopt & PFCTL_FLAG_OPTION) &&
!anchorname[0])
if (pfctl_clear_interface_flags(dev, opts | PF_OPT_QUIET))
@@ -2352,7 +2375,7 @@ main(int argc, char *argv[])
if (anchorname[0] == '_' || strstr(anchorname, "/_") != NULL)
errx(1, "anchor names beginning with '_' cannot "
"be modified from the command line");
- if (pfctl_rules(dev, rulesopt, fin, opts, optimize,
+ if (pfctl_rules(dev, rulesopt, opts, optimize,
anchorname, NULL))
error = 1;
else if (!(opts & PF_OPT_NOACTION) &&
diff --git a/contrib/pf/pfctl/pfctl.h b/contrib/pf/pfctl/pfctl.h
index 98a1bef2a28b..2c69bc2068b0 100644
--- a/contrib/pf/pfctl/pfctl.h
+++ b/contrib/pf/pfctl/pfctl.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl.h,v 1.40 2007/02/09 11:25:27 henning Exp $ */
+/* $OpenBSD: pfctl.h,v 1.42 2007/12/05 12:01:47 chl Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -49,7 +49,6 @@ struct pfr_buffer {
(var) != NULL; \
(var) = pfr_buf_next((buf), (var)))
-void pfr_set_fd(int);
int pfr_get_fd(void);
int pfr_clr_tables(struct pfr_table *, int *, int);
int pfr_add_tables(struct pfr_table *, int, int *, int);
@@ -64,9 +63,7 @@ int pfr_set_addrs(struct pfr_table *, struct pfr_addr *, int, int *,
int *, int *, int *, int);
int pfr_get_addrs(struct pfr_table *, struct pfr_addr *, int *, int);
int pfr_get_astats(struct pfr_table *, struct pfr_astats *, int *, int);
-int pfr_clr_astats(struct pfr_table *, struct pfr_addr *, int, int *, int);
int pfr_tst_addrs(struct pfr_table *, struct pfr_addr *, int, int *, int);
-int pfr_set_tflags(struct pfr_table *, int, int, int, int *, int *, int);
int pfr_ina_define(struct pfr_table *, struct pfr_addr *, int, int *,
int *, int, int);
void pfr_buf_clear(struct pfr_buffer *);
@@ -91,6 +88,8 @@ FILE *pfctl_fopen(const char *, const char *);
#ifdef __FreeBSD__
extern int altqsupport;
+extern int dummynetsupport;
+#define HTONL(x) (x) = htonl((__uint32_t)(x))
#endif
#ifndef DEFAULT_PRIORITY
@@ -117,9 +116,9 @@ struct pf_altq *pfaltq_lookup(const char *);
char *rate2str(double);
void print_addr(struct pf_addr_wrap *, sa_family_t, int);
-void print_host(struct pf_state_host *, sa_family_t, int);
-void print_seq(struct pf_state_peer *);
-void print_state(struct pf_state *, int);
+void print_host(struct pf_addr *, u_int16_t p, sa_family_t, int);
+void print_seq(struct pfsync_state_peer *);
+void print_state(struct pfsync_state *, int);
int unmask(struct pf_addr *, sa_family_t);
int pfctl_cmdline_symset(char *);
diff --git a/contrib/pf/pfctl/pfctl_altq.c b/contrib/pf/pfctl/pfctl_altq.c
index b90e7c6b2742..40e11d5a9eb9 100644
--- a/contrib/pf/pfctl/pfctl_altq.c
+++ b/contrib/pf/pfctl/pfctl_altq.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl_altq.c,v 1.91 2006/11/28 00:08:50 henning Exp $ */
+/* $OpenBSD: pfctl_altq.c,v 1.93 2007/10/15 02:16:35 deraadt Exp $ */
/*
* Copyright (c) 2002
@@ -21,7 +21,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include <sys/param.h>
+#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
@@ -78,7 +78,7 @@ static int gsc_add_seg(struct gen_sc *, double, double, double,
static double sc_x2y(struct service_curve *, double);
#ifdef __FreeBSD__
-u_int32_t getifspeed(int, char *);
+u_int32_t getifspeed(int, char *);
#else
u_int32_t getifspeed(char *);
#endif
@@ -145,8 +145,8 @@ qname_to_qid(const char *qname)
}
void
-print_altq(const struct pf_altq *a, unsigned level, struct node_queue_bw *bw,
- struct node_queue_opt *qopts)
+print_altq(const struct pf_altq *a, unsigned int level,
+ struct node_queue_bw *bw, struct node_queue_opt *qopts)
{
if (a->qname[0] != 0) {
print_queue(a, level, bw, 1, qopts);
@@ -157,6 +157,7 @@ print_altq(const struct pf_altq *a, unsigned level, struct node_queue_bw *bw,
if (a->local_flags & PFALTQ_FLAG_IF_REMOVED)
printf("INACTIVE ");
#endif
+
printf("altq on %s ", a->ifname);
switch (a->scheduler) {
@@ -186,10 +187,11 @@ print_altq(const struct pf_altq *a, unsigned level, struct node_queue_bw *bw,
}
void
-print_queue(const struct pf_altq *a, unsigned level, struct node_queue_bw *bw,
- int print_interface, struct node_queue_opt *qopts)
+print_queue(const struct pf_altq *a, unsigned int level,
+ struct node_queue_bw *bw, int print_interface,
+ struct node_queue_opt *qopts)
{
- unsigned i;
+ unsigned int i;
#ifdef __FreeBSD__
if (a->local_flags & PFALTQ_FLAG_IF_REMOVED)
@@ -893,9 +895,6 @@ print_hfsc_opts(const struct pf_altq *a, const struct node_queue_opt *qopts)
/*
* admission control using generalized service curve
*/
-#ifndef INFINITY
-#define INFINITY HUGE_VAL /* positive infinity defined in <math.h> */
-#endif
/* add a new service curve to a generalized service curve */
static void
@@ -1132,8 +1131,6 @@ getifspeed(char *ifname)
ifr.ifr_data = (caddr_t)&ifrdat;
if (ioctl(s, SIOCGIFDATA, (caddr_t)&ifr) == -1)
err(1, "SIOCGIFDATA");
- if (shutdown(s, SHUT_RDWR) == -1)
- err(1, "shutdown");
if (close(s))
err(1, "close");
return ((u_int32_t)ifrdat.ifi_baudrate);
@@ -1158,8 +1155,6 @@ getifmtu(char *ifname)
#else
err(1, "SIOCGIFMTU");
#endif
- if (shutdown(s, SHUT_RDWR) == -1)
- err(1, "shutdown");
if (close(s))
err(1, "close");
if (ifr.ifr_mtu > 0)
diff --git a/contrib/pf/pfctl/pfctl_optimize.c b/contrib/pf/pfctl/pfctl_optimize.c
index 0514e8105bf2..9511720ed67d 100644
--- a/contrib/pf/pfctl/pfctl_optimize.c
+++ b/contrib/pf/pfctl/pfctl_optimize.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl_optimize.c,v 1.13 2006/10/31 14:17:45 mcbride Exp $ */
+/* $OpenBSD: pfctl_optimize.c,v 1.17 2008/05/06 03:45:21 mpf Exp $ */
/*
* Copyright (c) 2004 Mike Frantzen <frantzen@openbsd.org>
@@ -185,7 +185,8 @@ struct pf_rule_field {
PF_RULE_FIELD(packets, DC),
PF_RULE_FIELD(bytes, DC),
PF_RULE_FIELD(kif, DC),
- PF_RULE_FIELD(states, DC),
+ PF_RULE_FIELD(states_cur, DC),
+ PF_RULE_FIELD(states_tot, DC),
PF_RULE_FIELD(src_nodes, DC),
PF_RULE_FIELD(nr, DC),
PF_RULE_FIELD(entries, DC),
@@ -201,6 +202,7 @@ struct pf_rule_field {
PF_RULE_FIELD(natpass, NEVER),
PF_RULE_FIELD(max_mss, NEVER),
PF_RULE_FIELD(min_ttl, NEVER),
+ PF_RULE_FIELD(set_tos, NEVER),
};
@@ -398,7 +400,7 @@ optimize_superblock(struct pfctl *pf, struct superblock *block)
* out rules.
*/
- /* shortcut. there will be alot of 1-rule superblocks */
+ /* shortcut. there will be a lot of 1-rule superblocks */
if (!TAILQ_NEXT(TAILQ_FIRST(&block->sb_rules), por_entry))
return (0);
@@ -1320,8 +1322,9 @@ again:
if (pfctl_define_table(tbl->pt_name, PFR_TFLAG_CONST, 1,
- pf->anchor->name, tbl->pt_buf, pf->anchor->ruleset.tticket)) {
- warn("failed to create table %s", tbl->pt_name);
+ pf->astack[0]->name, tbl->pt_buf, pf->astack[0]->ruleset.tticket)) {
+ warn("failed to create table %s in %s",
+ tbl->pt_name, pf->astack[0]->name);
return (1);
}
return (0);
@@ -1424,7 +1427,7 @@ superblock_inclusive(struct superblock *block, struct pf_opt_rule *por)
return (0);
/*
- * Have to handle interface groups seperately. Consider the following
+ * Have to handle interface groups separately. Consider the following
* rules:
* block on EXTIFS to any port 22
* pass on em0 to any port 22
diff --git a/contrib/pf/pfctl/pfctl_osfp.c b/contrib/pf/pfctl/pfctl_osfp.c
index 7018d6cd3657..df789811ddb5 100644
--- a/contrib/pf/pfctl/pfctl_osfp.c
+++ b/contrib/pf/pfctl/pfctl_osfp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl_osfp.c,v 1.15 2006/12/13 05:10:15 itojun Exp $ */
+/* $OpenBSD: pfctl_osfp.c,v 1.14 2006/04/08 02:13:14 ray Exp $ */
/*
* Copyright (c) 2003 Mike Frantzen <frantzen@openbsd.org>
diff --git a/contrib/pf/pfctl/pfctl_parser.c b/contrib/pf/pfctl/pfctl_parser.c
index 7dc0c592f2e1..d45b9b78997d 100644
--- a/contrib/pf/pfctl/pfctl_parser.c
+++ b/contrib/pf/pfctl/pfctl_parser.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl_parser.c,v 1.234 2006/10/31 23:46:24 mcbride Exp $ */
+/* $OpenBSD: pfctl_parser.c,v 1.240 2008/06/10 20:55:02 mcbride Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -52,7 +52,6 @@ __FBSDID("$FreeBSD$");
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
-#include <limits.h>
#include <netdb.h>
#include <stdarg.h>
#include <errno.h>
@@ -500,7 +499,7 @@ print_status(struct pf_status *s, int opts)
running = s->running ? "Enabled" : "Disabled";
if (s->since) {
- unsigned sec, min, hrs, day = runtime;
+ unsigned int sec, min, hrs, day = runtime;
sec = day % 60;
day /= 60;
@@ -581,7 +580,11 @@ print_status(struct pf_status *s, int opts)
s->src_nodes, "");
for (i = 0; i < SCNT_MAX; i++) {
printf(" %-25s %14lld ", pf_scounters[i],
- (unsigned long long)s->scounters[i]);
+#ifdef __FreeBSD__
+ (long long)s->scounters[i]);
+#else
+ s->scounters[i]);
+#endif
if (runtime > 0)
printf("%14.1f/s\n",
(double)s->scounters[i] / (double)runtime);
@@ -952,6 +955,12 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose, int numeric)
printf("sloppy");
opts = 0;
}
+ if (r->rule_flag & PFRULE_PFLOW) {
+ if (!opts)
+ printf(", ");
+ printf("pflow");
+ opts = 0;
+ }
for (i = 0; i < PFTM_MAX; ++i)
if (r->timeout[i]) {
int j;
@@ -979,6 +988,8 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose, int numeric)
printf(" min-ttl %d", r->min_ttl);
if (r->max_mss)
printf(" max-mss %d", r->max_mss);
+ if (r->rule_flag & PFRULE_SET_TOS)
+ printf(" set-tos 0x%2.2x", r->set_tos);
if (r->allow_opts)
printf(" allow-opts");
if (r->action == PF_SCRUB) {
@@ -1007,6 +1018,26 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose, int numeric)
}
if (r->rtableid != -1)
printf(" rtable %u", r->rtableid);
+ if (r->divert.port) {
+#ifdef __FreeBSD__
+ printf(" divert-to %u", ntohs(r->divert.port));
+#else
+ if (PF_AZERO(&r->divert.addr, r->af)) {
+ printf(" divert-reply");
+ } else {
+ /* XXX cut&paste from print_addr */
+ char buf[48];
+
+ printf(" divert-to ");
+ if (inet_ntop(r->af, &r->divert.addr, buf,
+ sizeof(buf)) == NULL)
+ printf("?");
+ else
+ printf("%s", buf);
+ printf(" port %u", ntohs(r->divert.port));
+ }
+#endif
+ }
if (!anchor_call[0] && (r->action == PF_NAT ||
r->action == PF_BINAT || r->action == PF_RDR)) {
printf(" -> ");
@@ -1027,6 +1058,8 @@ print_tabledef(const char *name, int flags, int addrs,
printf(" const");
if (flags & PFR_TFLAG_PERSIST)
printf(" persist");
+ if (flags & PFR_TFLAG_COUNTERS)
+ printf(" counters");
SIMPLEQ_FOREACH(ti, nodes, entries) {
if (ti->file) {
printf(" file \"%s\"", ti->file);
diff --git a/contrib/pf/pfctl/pfctl_parser.h b/contrib/pf/pfctl/pfctl_parser.h
index ab9017e51a2f..4560d66bb0ed 100644
--- a/contrib/pf/pfctl/pfctl_parser.h
+++ b/contrib/pf/pfctl/pfctl_parser.h
@@ -172,10 +172,10 @@ struct node_queue_opt {
#define SIMPLEQ_END(head) NULL
#define SIMPLEQ_EMPTY STAILQ_EMPTY
#define SIMPLEQ_NEXT STAILQ_NEXT
-/*#define SIMPLEQ_FOREACH STAILQ_FOREACH*/
-#define SIMPLEQ_FOREACH(var, head, field) \
- for((var) = SIMPLEQ_FIRST(head); \
- (var) != SIMPLEQ_END(head); \
+/*#define SIMPLEQ_FOREACH STAILQ_FOREACH*/
+#define SIMPLEQ_FOREACH(var, head, field) \
+ for((var) = SIMPLEQ_FIRST(head); \
+ (var) != SIMPLEQ_END(head); \
(var) = SIMPLEQ_NEXT(var, field))
#define SIMPLEQ_INIT STAILQ_INIT
#define SIMPLEQ_INSERT_HEAD STAILQ_INSERT_HEAD
@@ -213,7 +213,7 @@ struct pf_opt_rule {
TAILQ_HEAD(pf_opt_queue, pf_opt_rule);
-int pfctl_rules(int, char *, FILE *, int, int, char *, struct pfr_buffer *);
+int pfctl_rules(int, char *, int, int, char *, struct pfr_buffer *);
int pfctl_optimize_ruleset(struct pfctl *, struct pf_ruleset *);
int pfctl_add_rule(struct pfctl *, struct pf_rule *, const char *);
@@ -230,7 +230,7 @@ int pfctl_set_hostid(struct pfctl *, u_int32_t);
int pfctl_set_debug(struct pfctl *, char *);
int pfctl_set_interface_flags(struct pfctl *, char *, int, int);
-int parse_rules(FILE *, struct pfctl *);
+int parse_config(char *, struct pfctl *);
int parse_flags(char *);
int pfctl_load_anchors(int, struct pfctl *, struct pfr_buffer *);
diff --git a/contrib/pf/pfctl/pfctl_qstats.c b/contrib/pf/pfctl/pfctl_qstats.c
index d4089d6fbc83..95371e47af44 100644
--- a/contrib/pf/pfctl/pfctl_qstats.c
+++ b/contrib/pf/pfctl/pfctl_qstats.c
@@ -73,7 +73,7 @@ void pfctl_insert_altq_node(struct pf_altq_node **,
struct pf_altq_node *pfctl_find_altq_node(struct pf_altq_node *,
const char *, const char *);
void pfctl_print_altq_node(int, const struct pf_altq_node *,
- unsigned, int);
+ unsigned, int);
void print_cbqstats(struct queue_stats);
void print_priqstats(struct queue_stats);
void print_hfscstats(struct queue_stats);
@@ -185,8 +185,8 @@ pfctl_update_qstats(int dev, struct pf_altq_node **root)
}
}
#ifdef __FreeBSD__
- else if (pa.altq.local_flags & PFALTQ_FLAG_IF_REMOVED) {
- memset(&qstats.data, 0, sizeof(qstats.data));
+ else if (pa.altq.local_flags & PFALTQ_FLAG_IF_REMOVED) {
+ memset(&qstats.data, 0, sizeof(qstats.data));
if ((node = pfctl_find_altq_node(*root, pa.altq.qname,
pa.altq.ifname)) != NULL) {
memcpy(&node->qstats.data, &qstats.data,
@@ -194,7 +194,7 @@ pfctl_update_qstats(int dev, struct pf_altq_node **root)
update_avg(node);
} else {
pfctl_insert_altq_node(root, pa.altq, qstats);
- }
+ }
}
#endif
}
@@ -262,8 +262,8 @@ pfctl_find_altq_node(struct pf_altq_node *root, const char *qname,
}
void
-pfctl_print_altq_node(int dev, const struct pf_altq_node *node, unsigned level,
- int opts)
+pfctl_print_altq_node(int dev, const struct pf_altq_node *node,
+ unsigned int level, int opts)
{
const struct pf_altq_node *child;
@@ -302,11 +302,11 @@ pfctl_print_altq_nodestat(int dev, const struct pf_altq_node *a)
{
if (a->altq.qid == 0)
return;
+
#ifdef __FreeBSD__
if (a->altq.local_flags & PFALTQ_FLAG_IF_REMOVED)
return;
#endif
-
switch (a->altq.scheduler) {
case ALTQT_CBQ:
print_cbqstats(a->qstats);
diff --git a/contrib/pf/pfctl/pfctl_radix.c b/contrib/pf/pfctl/pfctl_radix.c
index 01ad4758ff1a..38f16c4b72a9 100644
--- a/contrib/pf/pfctl/pfctl_radix.c
+++ b/contrib/pf/pfctl/pfctl_radix.c
@@ -30,6 +30,9 @@
*
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
@@ -300,29 +303,6 @@ pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size,
}
int
-pfr_clr_astats(struct pfr_table *tbl, struct pfr_addr *addr, int size,
- int *nzero, int flags)
-{
- struct pfioc_table io;
-
- if (tbl == NULL || size < 0 || (size && addr == NULL)) {
- errno = EINVAL;
- return (-1);
- }
- bzero(&io, sizeof io);
- io.pfrio_flags = flags;
- io.pfrio_table = *tbl;
- io.pfrio_buffer = addr;
- io.pfrio_esize = sizeof(*addr);
- io.pfrio_size = size;
- if (ioctl(dev, DIOCRCLRASTATS, &io))
- return (-1);
- if (nzero != NULL)
- *nzero = io.pfrio_nzero;
- return (0);
-}
-
-int
pfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags)
{
struct pfioc_table io;
@@ -344,32 +324,6 @@ pfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags)
}
int
-pfr_set_tflags(struct pfr_table *tbl, int size, int setflag, int clrflag,
- int *nchange, int *ndel, int flags)
-{
- struct pfioc_table io;
-
- if (size < 0 || (size && !tbl)) {
- errno = EINVAL;
- return (-1);
- }
- bzero(&io, sizeof io);
- io.pfrio_flags = flags;
- io.pfrio_buffer = tbl;
- io.pfrio_esize = sizeof(*tbl);
- io.pfrio_size = size;
- io.pfrio_setflag = setflag;
- io.pfrio_clrflag = clrflag;
- if (ioctl(dev, DIOCRSETTFLAGS, &io))
- return (-1);
- if (nchange)
- *nchange = io.pfrio_nchange;
- if (ndel)
- *ndel = io.pfrio_ndel;
- return (0);
-}
-
-int
pfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
int *nmatch, int flags)
{
diff --git a/contrib/pf/pfctl/pfctl_table.c b/contrib/pf/pfctl/pfctl_table.c
index 3d54466a4493..257c01485011 100644
--- a/contrib/pf/pfctl/pfctl_table.c
+++ b/contrib/pf/pfctl/pfctl_table.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl_table.c,v 1.66 2007/03/01 17:20:54 deraadt Exp $ */
+/* $OpenBSD: pfctl_table.c,v 1.67 2008/06/10 20:55:02 mcbride Exp $ */
/*
* Copyright (c) 2002 Cedric Berger
@@ -275,12 +275,14 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command,
if (b.pfrb_size <= b.pfrb_msize)
break;
}
- PFRB_FOREACH(p, &b)
+ PFRB_FOREACH(p, &b) {
+ ((struct pfr_astats *)p)->pfras_a.pfra_fback = 0;
if (time(NULL) - ((struct pfr_astats *)p)->pfras_tzero >
- lifetime)
+ lifetime)
if (pfr_buf_add(&b2,
&((struct pfr_astats *)p)->pfras_a))
err(1, "duplicate buffer");
+ }
if (opts & PF_OPT_VERBOSE)
flags |= PFR_FLAG_FEEDBACK;
@@ -367,13 +369,14 @@ print_table(struct pfr_table *ta, int verbose, int debug)
if (!debug && !(ta->pfrt_flags & PFR_TFLAG_ACTIVE))
return;
if (verbose) {
- printf("%c%c%c%c%c%c\t%s",
+ printf("%c%c%c%c%c%c%c\t%s",
(ta->pfrt_flags & PFR_TFLAG_CONST) ? 'c' : '-',
(ta->pfrt_flags & PFR_TFLAG_PERSIST) ? 'p' : '-',
(ta->pfrt_flags & PFR_TFLAG_ACTIVE) ? 'a' : '-',
(ta->pfrt_flags & PFR_TFLAG_INACTIVE) ? 'i' : '-',
(ta->pfrt_flags & PFR_TFLAG_REFERENCED) ? 'r' : '-',
(ta->pfrt_flags & PFR_TFLAG_REFDANCHOR) ? 'h' : '-',
+ (ta->pfrt_flags & PFR_TFLAG_COUNTERS) ? 'C' : '-',
ta->pfrt_name);
if (ta->pfrt_anchor[0])
printf("\t%s", ta->pfrt_anchor);
@@ -428,7 +431,7 @@ void
print_addrx(struct pfr_addr *ad, struct pfr_addr *rad, int dns)
{
char ch, buf[256] = "{error}";
- char fb[] = { ' ', 'M', 'A', 'D', 'C', 'Z', 'X', ' ', 'Y' };
+ char fb[] = { ' ', 'M', 'A', 'D', 'C', 'Z', 'X', ' ', 'Y', ' ' };
unsigned int fback, hostnet;
fback = (rad != NULL) ? rad->pfra_fback : ad->pfra_fback;
@@ -477,6 +480,8 @@ print_astats(struct pfr_astats *as, int dns)
print_addrx(&as->pfras_a, NULL, dns);
printf("\tCleared: %s", ctime(&time));
+ if (as->pfras_a.pfra_fback == PFR_FB_NOCOUNT)
+ return;
for (dir = 0; dir < PFR_DIR_MAX; dir++)
for (op = 0; op < PFR_OP_ADDR_MAX; op++)
printf("\t%-12s [ Packets: %-18llu Bytes: %-18llu ]\n",