summaryrefslogtreecommitdiffstats
path: root/contrib/pf/pfctl
diff options
context:
space:
mode:
authormlaier <mlaier@FreeBSD.org>2005-05-03 16:55:20 +0000
committermlaier <mlaier@FreeBSD.org>2005-05-03 16:55:20 +0000
commitb28479dfe2b344764dddb58a31df37c21423cfde (patch)
tree7a2c1661f3b801f814c99be7e4339e2b5cfdb86f /contrib/pf/pfctl
parentf9e60af5004dc157f222b733768010aa3d2e98d7 (diff)
downloadFreeBSD-src-b28479dfe2b344764dddb58a31df37c21423cfde.zip
FreeBSD-src-b28479dfe2b344764dddb58a31df37c21423cfde.tar.gz
Resolve conflicts created during the import of pf 3.7 Some features are
missing and will be implemented in a second step. This is functional as is. Tested by: freebsd-pf, pfsense.org Obtained from: OpenBSD
Diffstat (limited to 'contrib/pf/pfctl')
-rw-r--r--contrib/pf/pfctl/parse.y644
-rw-r--r--contrib/pf/pfctl/pf_print_state.c5
-rw-r--r--contrib/pf/pfctl/pfctl.c722
-rw-r--r--contrib/pf/pfctl/pfctl.h17
-rw-r--r--contrib/pf/pfctl/pfctl_altq.c63
-rw-r--r--contrib/pf/pfctl/pfctl_optimize.c7
-rw-r--r--contrib/pf/pfctl/pfctl_parser.c213
-rw-r--r--contrib/pf/pfctl/pfctl_parser.h61
-rw-r--r--contrib/pf/pfctl/pfctl_qstats.c8
-rw-r--r--contrib/pf/pfctl/pfctl_table.c36
10 files changed, 1127 insertions, 649 deletions
diff --git a/contrib/pf/pfctl/parse.y b/contrib/pf/pfctl/parse.y
index 2c82bcd..a06a5de 100644
--- a/contrib/pf/pfctl/parse.y
+++ b/contrib/pf/pfctl/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.449 2004/03/20 23:20:20 david Exp $ */
+/* $OpenBSD: parse.y,v 1.482 2005/03/07 13:20:03 henning Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
@@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$");
#include <errno.h>
#include <string.h>
#include <ctype.h>
+#include <math.h>
#include <err.h>
#include <limits.h>
#include <pwd.h>
@@ -124,8 +125,10 @@ struct node_icmp {
};
enum { PF_STATE_OPT_MAX, PF_STATE_OPT_NOSYNC, PF_STATE_OPT_SRCTRACK,
- PF_STATE_OPT_MAX_SRC_STATES, PF_STATE_OPT_MAX_SRC_NODES,
- PF_STATE_OPT_STATELOCK, PF_STATE_OPT_TIMEOUT };
+ 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 };
enum { PF_SRCTRACK_NONE, PF_SRCTRACK, PF_SRCTRACK_GLOBAL, PF_SRCTRACK_RULE };
@@ -134,6 +137,15 @@ struct node_state_opt {
union {
u_int32_t max_states;
u_int32_t max_src_states;
+ u_int32_t max_src_conn;
+ struct {
+ u_int32_t limit;
+ u_int32_t seconds;
+ } max_src_conn_rate;
+ struct {
+ u_int8_t flush;
+ char tblname[PF_TABLE_NAME_SIZE];
+ } overload;
u_int32_t max_src_nodes;
u_int8_t src_track;
u_int32_t statelock;
@@ -182,6 +194,7 @@ struct filter_opts {
} flags;
struct node_icmp *icmpspec;
u_int32_t tos;
+ u_int32_t prob;
struct {
int action;
struct node_state_opt *options;
@@ -268,11 +281,13 @@ void expand_label(char *, size_t, const char *, u_int8_t, struct node_host *,
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 *);
+ 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 *);
@@ -309,7 +324,6 @@ TAILQ_HEAD(loadanchorshead, loadanchors)
struct loadanchors {
TAILQ_ENTRY(loadanchors) entries;
char *anchorname;
- char *rulesetname;
char *filename;
};
@@ -362,6 +376,10 @@ typedef struct {
u_int8_t log;
u_int8_t quick;
} logquick;
+ struct {
+ int neg;
+ char *name;
+ } tagged;
struct pf_poolhashkey *hashkey;
struct node_queue *queue;
struct node_queue_opt queue_options;
@@ -378,18 +396,6 @@ typedef struct {
int lineno;
} YYSTYPE;
-#define PREPARE_ANCHOR_RULE(r, a) \
- do { \
- memset(&(r), 0, sizeof(r)); \
- if (strlcpy(r.anchorname, (a), \
- sizeof(r.anchorname)) >= \
- sizeof(r.anchorname)) { \
- yyerror("anchor name '%s' too long", \
- (a)); \
- YYERROR; \
- } \
- } while (0)
-
#define DYNIF_MULTIADDR(addr) ((addr).type == PF_ADDR_DYNIFTL && \
(!((addr).iflags & PFI_AFLAG_NOALIAS) || \
!isdigit((addr).v.ifname[strlen((addr).v.ifname)-1])))
@@ -403,22 +409,24 @@ typedef struct {
%token NOROUTE FRAGMENT USER GROUP MAXMSS MAXIMUM TTL TOS DROP TABLE
%token REASSEMBLE FRAGDROP FRAGCROP ANCHOR NATANCHOR RDRANCHOR BINATANCHOR
%token SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY RANDOMID
-%token REQUIREORDER SYNPROXY FINGERPRINTS NOSYNC DEBUG HOSTID
+%token REQUIREORDER SYNPROXY FINGERPRINTS NOSYNC DEBUG SKIP HOSTID
%token ANTISPOOF FOR
-%token BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT
+%token BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT PROBABILITY
%token ALTQ CBQ PRIQ HFSC BANDWIDTH TBRSIZE LINKSHARE REALTIME UPPERLIMIT
%token QUEUE PRIORITY QLIMIT
%token LOAD
%token STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE
-%token TAGGED TAG IFBOUND GRBOUND FLOATING STATEPOLICY
+%token MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH
+%token TAGGED TAG IFBOUND GRBOUND FLOATING STATEPOLICY ROUTE
%token <v.string> STRING
%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 natpass
-%type <v.i> no dir log af fragcache sourcetrack
+%type <v.i> no dir log af fragcache sourcetrack flush
%type <v.i> unaryop statelock
-%type <v.b> action nataction flags flag blockspec
+%type <v.b> action nataction scrubaction
+%type <v.b> flags flag blockspec
%type <v.range> port rport
%type <v.hashkey> hashkey
%type <v.proto> proto proto_list proto_item
@@ -440,7 +448,7 @@ typedef struct {
%type <v.keep_state> keep
%type <v.state_opt> state_opt_spec state_opt_list state_opt_item
%type <v.logquick> logquick
-%type <v.interface> antispoof_ifspc antispoof_iflst
+%type <v.interface> antispoof_ifspc antispoof_iflst antispoof_if
%type <v.qassign> qname
%type <v.queue> qassign qassign_list qassign_item
%type <v.queue_options> scheduler
@@ -454,6 +462,7 @@ typedef struct {
%type <v.scrub_opts> scrub_opts scrub_opt scrub_opts_l
%type <v.table_opts> table_opts table_opt table_opts_l
%type <v.pool_opts> pool_opts pool_opt pool_opts_l
+%type <v.tagged> tagged
%%
ruleset : /* empty */
@@ -494,11 +503,6 @@ option : SET OPTIMIZATION STRING {
free($3);
YYERROR;
}
- if ((ifa_exists($3, 0) == NULL) && strcmp($3, "none")) {
- yyerror("interface %s doesn't exist", $3);
- free($3);
- YYERROR;
- }
if (pfctl_set_logif(pf, $3) != 0) {
yyerror("error setting loginterface %s", $3);
free($3);
@@ -512,7 +516,7 @@ option : SET OPTIMIZATION STRING {
YYERROR;
}
if (pfctl_set_hostid(pf, $3) != 0) {
- yyerror("error setting loginterface %08x", $3);
+ yyerror("error setting hostid %08x", $3);
YYERROR;
}
}
@@ -538,15 +542,19 @@ option : SET OPTIMIZATION STRING {
}
| SET FINGERPRINTS STRING {
if (pf->opts & PF_OPT_VERBOSE)
- printf("fingerprints %s\n", $3);
+ printf("set fingerprints %s\n", $3);
if (check_rulestate(PFCTL_STATE_OPTION)) {
free($3);
YYERROR;
}
- if (pfctl_file_fingerprints(pf->dev, pf->opts, $3)) {
- yyerror("error loading fingerprints %s", $3);
- free($3);
- YYERROR;
+ if (!pf->anchor[0]) {
+ if (pfctl_file_fingerprints(pf->dev,
+ pf->opts, $3)) {
+ yyerror("error loading "
+ "fingerprints %s", $3);
+ free($3);
+ YYERROR;
+ }
}
free($3);
}
@@ -578,6 +586,12 @@ option : SET OPTIMIZATION STRING {
}
free($3);
}
+ | SET SKIP interface {
+ if (expand_skip_interface($3) != 0) {
+ yyerror("error setting skip interface(s)");
+ YYERROR;
+ }
+ }
;
string : string STRING {
@@ -607,9 +621,10 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts {
YYERROR;
}
- PREPARE_ANCHOR_RULE(r, $2);
+ memset(&r, 0, sizeof(r));
r.direction = $3;
r.af = $5;
+ r.prob = $8.prob;
if ($8.match_tag)
if (strlcpy(r.match_tagname, $8.match_tag,
@@ -625,7 +640,8 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts {
expand_rule(&r, $4, NULL, $6, $7.src_os,
$7.src.host, $7.src.port, $7.dst.host, $7.dst.port,
- 0, 0, 0);
+ 0, 0, 0, $2);
+ free($2);
}
| NATANCHOR string interface af proto fromto {
struct pf_rule r;
@@ -635,8 +651,7 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts {
YYERROR;
}
- PREPARE_ANCHOR_RULE(r, $2);
- free($2);
+ memset(&r, 0, sizeof(r));
r.action = PF_NAT;
r.af = $4;
@@ -645,7 +660,8 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts {
expand_rule(&r, $3, NULL, $5, $6.src_os,
$6.src.host, $6.src.port, $6.dst.host, $6.dst.port,
- 0, 0, 0);
+ 0, 0, 0, $2);
+ free($2);
}
| RDRANCHOR string interface af proto fromto {
struct pf_rule r;
@@ -655,8 +671,7 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts {
YYERROR;
}
- PREPARE_ANCHOR_RULE(r, $2);
- free($2);
+ memset(&r, 0, sizeof(r));
r.action = PF_RDR;
r.af = $4;
@@ -686,7 +701,8 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts {
expand_rule(&r, $3, NULL, $5, $6.src_os,
$6.src.host, $6.src.port, $6.dst.host, $6.dst.port,
- 0, 0, 0);
+ 0, 0, 0, $2);
+ free($2);
}
| BINATANCHOR string interface af proto fromto {
struct pf_rule r;
@@ -696,8 +712,7 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts {
YYERROR;
}
- PREPARE_ANCHOR_RULE(r, $2);
- free($2);
+ memset(&r, 0, sizeof(r));
r.action = PF_BINAT;
r.af = $4;
if ($5 != NULL) {
@@ -720,39 +735,24 @@ anchorrule : ANCHOR string dir interface af proto fromto filter_opts {
decide_address_family($6.src.host, &r.af);
decide_address_family($6.dst.host, &r.af);
- pfctl_add_rule(pf, &r);
+ pfctl_add_rule(pf, &r, $2);
+ free($2);
}
;
loadrule : LOAD ANCHOR string FROM string {
- char *t;
struct loadanchors *loadanchor;
- t = strsep(&$3, ":");
- if (*t == '\0' || $3 == NULL || *$3 == '\0') {
- yyerror("anchor '%s' invalid\n", $3);
- free(t);
- YYERROR;
- }
- if (strlen(t) >= PF_ANCHOR_NAME_SIZE) {
+ if (strlen($3) >= MAXPATHLEN) {
yyerror("anchorname %s too long, max %u\n",
- t, PF_ANCHOR_NAME_SIZE - 1);
- free(t);
- YYERROR;
- }
- if (strlen($3) >= PF_RULESET_NAME_SIZE) {
- yyerror("rulesetname %s too long, max %u\n",
- $3, PF_RULESET_NAME_SIZE - 1);
- free(t);
+ $3, MAXPATHLEN - 1);
+ free($3);
YYERROR;
}
-
loadanchor = calloc(1, sizeof(struct loadanchors));
if (loadanchor == NULL)
err(1, "loadrule: calloc");
- if ((loadanchor->anchorname = strdup(t)) == NULL)
- err(1, "loadrule: strdup");
- if ((loadanchor->rulesetname = strdup($3)) == NULL)
+ if ((loadanchor->anchorname = strdup($3)) == NULL)
err(1, "loadrule: strdup");
if ((loadanchor->filename = strdup($5)) == NULL)
err(1, "loadrule: strdup");
@@ -760,11 +760,20 @@ loadrule : LOAD ANCHOR string FROM string {
TAILQ_INSERT_TAIL(&loadanchorshead, loadanchor,
entries);
- free(t); /* not $3 */
+ free($3);
free($5);
};
-scrubrule : SCRUB dir logquick interface af proto fromto scrub_opts
+scrubaction : no SCRUB {
+ $$.b2 = $$.w = 0;
+ if ($1)
+ $$.b1 = PF_NOSCRUB;
+ else
+ $$.b1 = PF_SCRUB;
+ }
+ ;
+
+scrubrule : scrubaction dir logquick interface af proto fromto scrub_opts
{
struct pf_rule r;
@@ -773,7 +782,7 @@ scrubrule : SCRUB dir logquick interface af proto fromto scrub_opts
memset(&r, 0, sizeof(r));
- r.action = PF_SCRUB;
+ r.action = $1.b1;
r.direction = $2;
r.log = $3.log;
@@ -804,7 +813,7 @@ scrubrule : SCRUB dir logquick interface af proto fromto scrub_opts
expand_rule(&r, $4, NULL, $6, $7.src_os,
$7.src.host, $7.src.port, $7.dst.host, $7.dst.port,
- NULL, NULL, NULL);
+ NULL, NULL, NULL, "");
}
;
@@ -864,6 +873,8 @@ scrub_opt : NODF {
}
| REASSEMBLE STRING {
if (strcasecmp($2, "tcp") != 0) {
+ yyerror("scrub reassemble supports only tcp, "
+ "not '%s'", $2);
free($2);
YYERROR;
}
@@ -890,7 +901,7 @@ fragcache : FRAGMENT REASSEMBLE { $$ = 0; /* default */ }
antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts {
struct pf_rule r;
- struct node_host *h = NULL;
+ struct node_host *h = NULL, *hh;
struct node_if *i, *j;
if (check_rulestate(PFCTL_STATE_FILTER))
@@ -916,11 +927,35 @@ antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts {
YYERROR;
}
j->not = 1;
- h = ifa_lookup(j->ifname, PFI_AFLAG_NETWORK);
+ if (i->dynamic) {
+ h = calloc(1, sizeof(*h));
+ if (h == NULL)
+ err(1, "address: calloc");
+ h->addr.type = PF_ADDR_DYNIFTL;
+ set_ipmask(h, 128);
+ if (strlcpy(h->addr.v.ifname, i->ifname,
+ sizeof(h->addr.v.ifname)) >=
+ sizeof(h->addr.v.ifname)) {
+ free(h);
+ yyerror(
+ "interface name too long");
+ YYERROR;
+ }
+ hh = malloc(sizeof(*hh));
+ if (hh == NULL)
+ err(1, "address: malloc");
+ bcopy(h, hh, sizeof(*hh));
+ h->addr.iflags = PFI_AFLAG_NETWORK;
+ } else {
+ h = ifa_lookup(j->ifname,
+ PFI_AFLAG_NETWORK);
+ hh = NULL;
+ }
if (h != NULL)
expand_rule(&r, j, NULL, NULL, NULL, h,
- NULL, NULL, NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL, NULL, NULL,
+ NULL, "");
if ((i->ifa_flags & IFF_LOOPBACK) == 0) {
bzero(&r, sizeof(r));
@@ -932,29 +967,40 @@ antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts {
r.af = $4;
if (rule_label(&r, $5.label))
YYERROR;
- h = ifa_lookup(i->ifname, 0);
+ if (hh != NULL)
+ h = hh;
+ else
+ h = ifa_lookup(i->ifname, 0);
if (h != NULL)
expand_rule(&r, NULL, NULL,
NULL, NULL, h, NULL, NULL,
- NULL, NULL, NULL, NULL);
- }
+ NULL, NULL, NULL, NULL, "");
+ } else
+ free(hh);
}
free($5.label);
}
;
-antispoof_ifspc : FOR if_item { $$ = $2; }
+antispoof_ifspc : FOR antispoof_if { $$ = $2; }
| FOR '{' antispoof_iflst '}' { $$ = $3; }
;
-antispoof_iflst : if_item { $$ = $1; }
- | antispoof_iflst comma if_item {
+antispoof_iflst : antispoof_if { $$ = $1; }
+ | antispoof_iflst comma antispoof_if {
$1->tail->next = $3;
$1->tail = $3;
$$ = $1;
}
;
+antispoof_if : if_item { $$ = $1; }
+ | '(' if_item ')' {
+ $2->dynamic = 1;
+ $$ = $2;
+ }
+ ;
+
antispoof_opts : { bzero(&antispoof_opts, sizeof antispoof_opts); }
antispoof_opts_l
{ $$ = antispoof_opts; }
@@ -1035,6 +1081,7 @@ table_opt : STRING {
else if (!strcmp($1, "persist"))
table_opts.flags |= PFR_TFLAG_PERSIST;
else {
+ yyerror("invalid table option '%s'", $1);
free($1);
YYERROR;
}
@@ -1353,14 +1400,15 @@ hfscopts_item : LINKSHARE bandwidth {
hfsc_opts.linkshare.m2 = $2;
hfsc_opts.linkshare.used = 1;
}
- | LINKSHARE '(' bandwidth number bandwidth ')' {
+ | LINKSHARE '(' bandwidth comma number comma bandwidth ')'
+ {
if (hfsc_opts.linkshare.used) {
yyerror("linkshare already specified");
YYERROR;
}
hfsc_opts.linkshare.m1 = $3;
- hfsc_opts.linkshare.d = $4;
- hfsc_opts.linkshare.m2 = $5;
+ hfsc_opts.linkshare.d = $5;
+ hfsc_opts.linkshare.m2 = $7;
hfsc_opts.linkshare.used = 1;
}
| REALTIME bandwidth {
@@ -1371,14 +1419,15 @@ hfscopts_item : LINKSHARE bandwidth {
hfsc_opts.realtime.m2 = $2;
hfsc_opts.realtime.used = 1;
}
- | REALTIME '(' bandwidth number bandwidth ')' {
+ | REALTIME '(' bandwidth comma number comma bandwidth ')'
+ {
if (hfsc_opts.realtime.used) {
yyerror("realtime already specified");
YYERROR;
}
hfsc_opts.realtime.m1 = $3;
- hfsc_opts.realtime.d = $4;
- hfsc_opts.realtime.m2 = $5;
+ hfsc_opts.realtime.d = $5;
+ hfsc_opts.realtime.m2 = $7;
hfsc_opts.realtime.used = 1;
}
| UPPERLIMIT bandwidth {
@@ -1389,14 +1438,15 @@ hfscopts_item : LINKSHARE bandwidth {
hfsc_opts.upperlimit.m2 = $2;
hfsc_opts.upperlimit.used = 1;
}
- | UPPERLIMIT '(' bandwidth number bandwidth ')' {
+ | UPPERLIMIT '(' bandwidth comma number comma bandwidth ')'
+ {
if (hfsc_opts.upperlimit.used) {
yyerror("upperlimit already specified");
YYERROR;
}
hfsc_opts.upperlimit.m1 = $3;
- hfsc_opts.upperlimit.d = $4;
- hfsc_opts.upperlimit.m2 = $5;
+ hfsc_opts.upperlimit.d = $5;
+ hfsc_opts.upperlimit.m2 = $7;
hfsc_opts.upperlimit.used = 1;
}
| STRING {
@@ -1482,6 +1532,7 @@ pfrule : action dir logquick interface route af proto fromto
r.direction = $2;
r.log = $3.log;
r.quick = $3.quick;
+ r.prob = $9.prob;
r.af = $6;
if ($9.tag)
@@ -1560,6 +1611,7 @@ pfrule : action dir logquick interface route af proto fromto
YYERROR;
}
srctrack = o->data.src_track;
+ r.rule_flag |= PFRULE_SRCTRACK;
break;
case PF_STATE_OPT_MAX_SRC_STATES:
if (r.max_src_states) {
@@ -1568,7 +1620,7 @@ pfrule : action dir logquick interface route af proto fromto
"multiple definitions");
YYERROR;
}
- if (o->data.max_src_nodes == 0) {
+ if (o->data.max_src_states == 0) {
yyerror("'max-src-states' must "
"be > 0");
YYERROR;
@@ -1577,6 +1629,66 @@ pfrule : action dir logquick interface route af proto fromto
o->data.max_src_states;
r.rule_flag |= PFRULE_SRCTRACK;
break;
+ case PF_STATE_OPT_OVERLOAD:
+ if (r.overload_tblname[0]) {
+ yyerror("multiple 'overload' "
+ "table definitions");
+ YYERROR;
+ }
+ if (strlcpy(r.overload_tblname,
+ o->data.overload.tblname,
+ PF_TABLE_NAME_SIZE) >=
+ PF_TABLE_NAME_SIZE) {
+ yyerror("state option: "
+ "strlcpy");
+ YYERROR;
+ }
+ r.flush = o->data.overload.flush;
+ break;
+ case PF_STATE_OPT_MAX_SRC_CONN:
+ if (r.max_src_conn) {
+ yyerror("state option "
+ "'max-src-conn' "
+ "multiple definitions");
+ YYERROR;
+ }
+ if (o->data.max_src_conn == 0) {
+ yyerror("'max-src-conn' "
+ "must be > 0");
+ YYERROR;
+ }
+ r.max_src_conn =
+ o->data.max_src_conn;
+ r.rule_flag |= PFRULE_SRCTRACK |
+ PFRULE_RULESRCTRACK;
+ break;
+ case PF_STATE_OPT_MAX_SRC_CONN_RATE:
+ if (r.max_src_conn_rate.limit) {
+ yyerror("state option "
+ "'max-src-conn-rate' "
+ "multiple definitions");
+ YYERROR;
+ }
+ if (!o->data.max_src_conn_rate.limit ||
+ !o->data.max_src_conn_rate.seconds) {
+ yyerror("'max-src-conn-rate' "
+ "values must be > 0");
+ YYERROR;
+ }
+ if (o->data.max_src_conn_rate.limit >
+ PF_THRESHOLD_MAX) {
+ yyerror("'max-src-conn-rate' "
+ "maximum rate must be < %u",
+ PF_THRESHOLD_MAX);
+ YYERROR;
+ }
+ r.max_src_conn_rate.limit =
+ o->data.max_src_conn_rate.limit;
+ r.max_src_conn_rate.seconds =
+ o->data.max_src_conn_rate.seconds;
+ r.rule_flag |= PFRULE_SRCTRACK |
+ PFRULE_RULESRCTRACK;
+ break;
case PF_STATE_OPT_MAX_SRC_NODES:
if (r.max_src_nodes) {
yyerror("state option "
@@ -1617,7 +1729,7 @@ pfrule : action dir logquick interface route af proto fromto
o = o->next;
free(p);
}
- if (srctrack) {
+ if (r.rule_flag & PFRULE_SRCTRACK) {
if (srctrack == PF_SRCTRACK_GLOBAL &&
r.max_src_nodes) {
yyerror("'max-src-nodes' is "
@@ -1625,6 +1737,24 @@ pfrule : action dir logquick interface route af proto fromto
"'source-track global'");
YYERROR;
}
+ if (srctrack == PF_SRCTRACK_GLOBAL &&
+ r.max_src_conn) {
+ yyerror("'max-src-conn' is "
+ "incompatible with "
+ "'source-track global'");
+ YYERROR;
+ }
+ if (srctrack == PF_SRCTRACK_GLOBAL &&
+ r.max_src_conn_rate.seconds) {
+ yyerror("'max-src-conn-rate' is "
+ "incompatible with "
+ "'source-track global'");
+ YYERROR;
+ }
+ if (r.timeout[PFTM_SRC_NODE] <
+ r.max_src_conn_rate.seconds)
+ r.timeout[PFTM_SRC_NODE] =
+ r.max_src_conn_rate.seconds;
r.rule_flag |= PFRULE_SRCTRACK;
if (srctrack == PF_SRCTRACK_RULE)
r.rule_flag |= PFRULE_RULESRCTRACK;
@@ -1705,7 +1835,7 @@ pfrule : action dir logquick interface route af proto fromto
expand_rule(&r, $4, $5.host, $7, $8.src_os,
$8.src.host, $8.src.port, $8.dst.host, $8.dst.port,
- $9.uid, $9.gid, $9.icmpspec);
+ $9.uid, $9.gid, $9.icmpspec, "");
}
;
@@ -1795,6 +1925,28 @@ filter_opt : USER uids {
filter_opts.match_tag = $3;
filter_opts.match_tag_not = $1;
}
+ | PROBABILITY STRING {
+ char *e;
+ double p = strtod($2, &e);
+
+ if (*e == '%') {
+ p *= 0.01;
+ e++;
+ }
+ if (*e) {
+ yyerror("invalid probability: %s", $2);
+ free($2);
+ 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);
+ YYERROR;
+ }
+ filter_opts.prob = (u_int32_t)p;
+ free($2);
+ }
;
action : PASS { $$.b1 = PF_PASS; $$.b2 = $$.w = 0; }
@@ -1906,13 +2058,6 @@ if_item_not : not if_item { $$ = $2; $$->not = $1; }
if_item : STRING {
struct node_host *n;
- if ((n = ifa_exists($1, 1)) == NULL) {
-#ifndef __FreeBSD__
- yyerror("unknown interface %s", $1);
- free($1);
- YYERROR;
-#endif
- }
$$ = calloc(1, sizeof(struct node_if));
if ($$ == NULL)
err(1, "if_item: calloc");
@@ -1923,13 +2068,11 @@ if_item : STRING {
yyerror("interface name too long");
YYERROR;
}
+
+ if ((n = ifa_exists($1, 1)) != NULL)
+ $$->ifa_flags = n->ifa_flags;
+
free($1);
-#ifdef __FreeBSD__
- if (n == NULL)
- $$->ifa_flags = PF_IFA_FLAG_DYNAMIC;
- else /* XXX ugly */
-#endif
- $$->ifa_flags = n->ifa_flags;
$$->not = 0;
$$->next = NULL;
$$->tail = $$;
@@ -2144,6 +2287,26 @@ host : STRING {
$$->next = NULL;
$$->tail = $$;
}
+ | ROUTE STRING {
+ $$ = calloc(1, sizeof(struct node_host));
+ if ($$ == NULL) {
+ free($2);
+ err(1, "host: calloc");
+ }
+ $$->addr.type = PF_ADDR_RTLABEL;
+ if (strlcpy($$->addr.v.rtlabelname, $2,
+ sizeof($$->addr.v.rtlabelname)) >=
+ sizeof($$->addr.v.rtlabelname)) {
+ yyerror("route label too long, max %u chars",
+ sizeof($$->addr.v.rtlabelname) - 1);
+ free($2);
+ free($$);
+ YYERROR;
+ }
+ $$->next = NULL;
+ $$->tail = $$;
+ free($2);
+ }
;
number : STRING {
@@ -2164,6 +2327,11 @@ dynaddr : '(' STRING ')' {
char *p, *op;
op = $2;
+ if (!isalpha(op[0])) {
+ yyerror("invalid interface name '%s'", op);
+ free(op);
+ YYERROR;
+ }
while ((p = strrchr($2, ':')) != NULL) {
if (!strcmp(p+1, "network"))
flags |= PFI_AFLAG_NETWORK;
@@ -2187,13 +2355,6 @@ dynaddr : '(' STRING ')' {
"interface modifiers");
YYERROR;
}
- if (ifa_exists($2, 1) == NULL && strcmp($2, "self")) {
-#ifndef __FreeBSD__
- yyerror("interface %s does not exist", $2);
- free(op);
- YYERROR;
-#endif
- }
$$ = calloc(1, sizeof(struct node_host));
if ($$ == NULL)
err(1, "address: calloc");
@@ -2281,7 +2442,7 @@ port : STRING {
if (atoul($1, &ulval) == 0) {
if (ulval > 65535) {
free($1);
- yyerror("illegal port value %d",
+ yyerror("illegal port value %lu",
ulval);
YYERROR;
}
@@ -2536,7 +2697,7 @@ icmp_item : icmptype {
if (atoul($3, &ulval) == 0) {
if (ulval > 255) {
free($3);
- yyerror("illegal icmp-code %d", ulval);
+ yyerror("illegal icmp-code %lu", ulval);
YYERROR;
}
} else {
@@ -2576,7 +2737,7 @@ icmp6_item : icmp6type {
if (atoul($3, &ulval) == 0) {
if (ulval > 255) {
- yyerror("illegal icmp6-code %ld",
+ yyerror("illegal icmp6-code %lu",
ulval);
free($3);
YYERROR;
@@ -2608,7 +2769,7 @@ icmptype : STRING {
if (atoul($1, &ulval) == 0) {
if (ulval > 255) {
- yyerror("illegal icmp-type %d", ulval);
+ yyerror("illegal icmp-type %lu", ulval);
free($1);
YYERROR;
}
@@ -2632,7 +2793,7 @@ icmp6type : STRING {
if (atoul($1, &ulval) == 0) {
if (ulval > 255) {
- yyerror("illegal icmp6-type %d", ulval);
+ yyerror("illegal icmp6-type %lu", ulval);
free($1);
YYERROR;
}
@@ -2700,6 +2861,13 @@ keep : KEEP STATE state_opt_spec {
}
;
+flush : /* empty */ { $$ = 0; }
+ | FLUSH { $$ = PF_FLUSH; }
+ | FLUSH GLOBAL {
+ $$ = PF_FLUSH | PF_FLUSH_GLOBAL;
+ }
+ ;
+
state_opt_spec : '(' state_opt_list ')' { $$ = $2; }
| /* empty */ { $$ = NULL; }
;
@@ -2738,6 +2906,43 @@ state_opt_item : MAXIMUM number {
$$->next = NULL;
$$->tail = $$;
}
+ | MAXSRCCONN number {
+ $$ = calloc(1, sizeof(struct node_state_opt));
+ if ($$ == NULL)
+ err(1, "state_opt_item: calloc");
+ $$->type = PF_STATE_OPT_MAX_SRC_CONN;
+ $$->data.max_src_conn = $2;
+ $$->next = NULL;
+ $$->tail = $$;
+ }
+ | MAXSRCCONNRATE number '/' number {
+ $$ = calloc(1, sizeof(struct node_state_opt));
+ if ($$ == NULL)
+ err(1, "state_opt_item: calloc");
+ $$->type = PF_STATE_OPT_MAX_SRC_CONN_RATE;
+ $$->data.max_src_conn_rate.limit = $2;
+ $$->data.max_src_conn_rate.seconds = $4;
+ $$->next = NULL;
+ $$->tail = $$;
+ }
+ | OVERLOAD '<' STRING '>' flush {
+ if (strlen($3) >= PF_TABLE_NAME_SIZE) {
+ yyerror("table name '%s' too long", $3);
+ free($3);
+ YYERROR;
+ }
+ $$ = calloc(1, sizeof(struct node_state_opt));
+ if ($$ == NULL)
+ err(1, "state_opt_item: calloc");
+ if (strlcpy($$->data.overload.tblname, $3,
+ PF_TABLE_NAME_SIZE) >= PF_TABLE_NAME_SIZE)
+ errx(1, "state_opt_item: strlcpy");
+ free($3);
+ $$->type = PF_STATE_OPT_OVERLOAD;
+ $$->data.overload.flush = $5;
+ $$->next = NULL;
+ $$->tail = $$;
+ }
| MAXSRCNODES number {
$$ = calloc(1, sizeof(struct node_state_opt));
if ($$ == NULL)
@@ -3023,7 +3228,7 @@ nataction : no NAT natpass {
}
;
-natrule : nataction interface af proto fromto tag redirpool pool_opts
+natrule : nataction interface af proto fromto tag tagged redirpool pool_opts
{
struct pf_rule r;
@@ -3053,46 +3258,55 @@ natrule : nataction interface af proto fromto tag redirpool pool_opts
YYERROR;
}
+ if ($7.name)
+ if (strlcpy(r.match_tagname, $7.name,
+ 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 = $7.neg;
+
if (r.action == PF_NONAT || r.action == PF_NORDR) {
- if ($7 != NULL) {
+ if ($8 != NULL) {
yyerror("translation rule with 'no' "
"does not need '->'");
YYERROR;
}
} else {
- if ($7 == NULL || $7->host == NULL) {
+ if ($8 == NULL || $8->host == NULL) {
yyerror("translation rule requires '-> "
"address'");
YYERROR;
}
- if (!r.af && ! $7->host->ifindex)
- r.af = $7->host->af;
+ if (!r.af && ! $8->host->ifindex)
+ r.af = $8->host->af;
- remove_invalid_hosts(&$7->host, &r.af);
- if (invalid_redirect($7->host, r.af))
+ remove_invalid_hosts(&$8->host, &r.af);
+ if (invalid_redirect($8->host, r.af))
YYERROR;
- if (check_netmask($7->host, r.af))
+ if (check_netmask($8->host, r.af))
YYERROR;
- r.rpool.proxy_port[0] = ntohs($7->rport.a);
+ r.rpool.proxy_port[0] = ntohs($8->rport.a);
switch (r.action) {
case PF_RDR:
- if (!$7->rport.b && $7->rport.t &&
+ if (!$8->rport.b && $8->rport.t &&
$5.dst.port != NULL) {
r.rpool.proxy_port[1] =
- ntohs($7->rport.a) +
+ ntohs($8->rport.a) +
(ntohs(
$5.dst.port->port[1]) -
ntohs(
$5.dst.port->port[0]));
} else
r.rpool.proxy_port[1] =
- ntohs($7->rport.b);
+ ntohs($8->rport.b);
break;
case PF_NAT:
r.rpool.proxy_port[1] =
- ntohs($7->rport.b);
+ ntohs($8->rport.b);
if (!r.rpool.proxy_port[0] &&
!r.rpool.proxy_port[1]) {
r.rpool.proxy_port[0] =
@@ -3107,25 +3321,25 @@ natrule : nataction interface af proto fromto tag redirpool pool_opts
break;
}
- r.rpool.opts = $8.type;
+ r.rpool.opts = $9.type;
if ((r.rpool.opts & PF_POOL_TYPEMASK) ==
- PF_POOL_NONE && ($7->host->next != NULL ||
- $7->host->addr.type == PF_ADDR_TABLE ||
- DYNIF_MULTIADDR($7->host->addr)))
+ PF_POOL_NONE && ($8->host->next != NULL ||
+ $8->host->addr.type == PF_ADDR_TABLE ||
+ DYNIF_MULTIADDR($8->host->addr)))
r.rpool.opts = PF_POOL_ROUNDROBIN;
if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
PF_POOL_ROUNDROBIN &&
- disallow_table($7->host, "tables are only "
+ disallow_table($8->host, "tables are only "
"supported in round-robin redirection "
"pools"))
YYERROR;
if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
PF_POOL_ROUNDROBIN &&
- disallow_alias($7->host, "interface (%s) "
+ disallow_alias($8->host, "interface (%s) "
"is only supported in round-robin "
"redirection pools"))
YYERROR;
- if ($7->host->next != NULL) {
+ if ($8->host->next != NULL) {
if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
PF_POOL_ROUNDROBIN) {
yyerror("only round-robin "
@@ -3136,14 +3350,14 @@ natrule : nataction interface af proto fromto tag redirpool pool_opts
}
}
- if ($8.key != NULL)
- memcpy(&r.rpool.key, $8.key,
+ if ($9.key != NULL)
+ memcpy(&r.rpool.key, $9.key,
sizeof(struct pf_poolhashkey));
- if ($8.opts)
- r.rpool.opts |= $8.opts;
+ if ($9.opts)
+ r.rpool.opts |= $9.opts;
- if ($8.staticport) {
+ if ($9.staticport) {
if (r.action != PF_NAT) {
yyerror("the 'static-port' option is "
"only valid with nat rules");
@@ -3162,14 +3376,14 @@ natrule : nataction interface af proto fromto tag redirpool pool_opts
r.rpool.proxy_port[1] = 0;
}
- expand_rule(&r, $2, $7 == NULL ? NULL : $7->host, $4,
+ expand_rule(&r, $2, $8 == NULL ? NULL : $8->host, $4,
$5.src_os, $5.src.host, $5.src.port, $5.dst.host,
- $5.dst.port, 0, 0, 0);
- free($7);
+ $5.dst.port, 0, 0, 0, "");
+ free($8);
}
;
-binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag
+binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag tagged
redirection
{
struct pf_rule binat;
@@ -3190,8 +3404,9 @@ binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag
binat.af = $8->af;
if (!binat.af && $10 != NULL && $10->af)
binat.af = $10->af;
- if (!binat.af && $12 != NULL && $12->host)
- binat.af = $12->host->af;
+
+ if (!binat.af && $13 != NULL && $13->host)
+ binat.af = $13->host->af;
if (!binat.af) {
yyerror("address family (inet/inet6) "
"undefined");
@@ -3204,6 +3419,7 @@ binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag
binat.ifnot = $4->not;
free($4);
}
+
if ($11 != NULL)
if (strlcpy(binat.tagname, $11,
PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
@@ -3211,6 +3427,14 @@ binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag
PF_TAG_NAME_SIZE - 1);
YYERROR;
}
+ if ($12.name)
+ if (strlcpy(binat.match_tagname, $12.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;
if ($6 != NULL) {
binat.proto = $6->proto;
@@ -3224,12 +3448,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 ($12 != NULL && $12->host != NULL && disallow_table(
- $12->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 ($12 != NULL && $12->host != NULL && disallow_alias(
- $12->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;
@@ -3263,38 +3487,38 @@ binatrule : no BINAT natpass interface af proto FROM host TO ipspec tag
YYERROR;
memcpy(&binat.dst.addr, &$10->addr,
sizeof(binat.dst.addr));
- binat.dst.not = $10->not;
+ binat.dst.neg = $10->not;
free($10);
}
if (binat.action == PF_NOBINAT) {
- if ($12 != NULL) {
+ if ($13 != NULL) {
yyerror("'no binat' rule does not need"
" '->'");
YYERROR;
}
} else {
- if ($12 == NULL || $12->host == NULL) {
+ if ($13 == NULL || $13->host == NULL) {
yyerror("'binat' rule requires"
" '-> address'");
YYERROR;
}
- remove_invalid_hosts(&$12->host, &binat.af);
- if (invalid_redirect($12->host, binat.af))
+ remove_invalid_hosts(&$13->host, &binat.af);
+ if (invalid_redirect($13->host, binat.af))
YYERROR;
- if ($12->host->next != NULL) {
+ if ($13->host->next != NULL) {
yyerror("binat rule must redirect to "
"a single address");
YYERROR;
}
- if (check_netmask($12->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,
- &$12->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;
@@ -3304,15 +3528,15 @@ 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 = $12->host->addr;
+ pa->addr = $13->host->addr;
pa->ifname[0] = 0;
TAILQ_INSERT_TAIL(&binat.rpool.list,
pa, entries);
- free($12);
+ free($13);
}
- pfctl_add_rule(pf, &binat);
+ pfctl_add_rule(pf, &binat, "");
}
;
@@ -3320,18 +3544,15 @@ tag : /* empty */ { $$ = NULL; }
| TAG STRING { $$ = $2; }
;
+tagged : /* empty */ { $$.neg = 0; $$.name = NULL; }
+ | not TAGGED string { $$.neg = $1; $$.name = $3; }
+ ;
+
route_host : STRING {
$$ = calloc(1, sizeof(struct node_host));
if ($$ == NULL)
err(1, "route_host: calloc");
$$->ifname = $1;
- if (ifa_exists($$->ifname, 0) == NULL) {
- yyerror("routeto: unknown interface %s",
- $$->ifname);
- free($1);
- free($$);
- YYERROR;
- }
set_ipmask($$, 128);
$$->next = NULL;
$$->tail = $$;
@@ -3339,11 +3560,6 @@ route_host : STRING {
| '(' STRING host ')' {
$$ = $3;
$$->ifname = $2;
- if (ifa_exists($$->ifname, 0) == NULL) {
- yyerror("routeto: unknown interface %s",
- $$->ifname);
- YYERROR;
- }
}
;
@@ -3446,6 +3662,8 @@ yesno : NO { $$ = 0; }
if (!strcmp($1, "yes"))
$$ = 1;
else {
+ yyerror("invalid value '%s', expected 'yes' "
+ "or 'no'", $1);
free($1);
YYERROR;
}
@@ -3509,6 +3727,7 @@ rule_consistent(struct pf_rule *r)
case PF_PASS:
case PF_DROP:
case PF_SCRUB:
+ case PF_NOSCRUB:
problems = filter_consistent(r);
break;
case PF_NAT:
@@ -3546,6 +3765,12 @@ filter_consistent(struct pf_rule *r)
yyerror("must indicate address family with icmp-type/code");
problems++;
}
+ if (r->overload_tblname[0] &&
+ r->max_src_conn == 0 && r->max_src_conn_rate.seconds == 0) {
+ yyerror("'overload' requires 'max-src-conn' "
+ "or 'max-src-conn-rate'");
+ problems++;
+ }
if ((r->proto == IPPROTO_ICMP && r->af == AF_INET6) ||
(r->proto == IPPROTO_ICMPV6 && r->af == AF_INET)) {
yyerror("proto %s doesn't match address family %s",
@@ -3575,7 +3800,7 @@ filter_consistent(struct pf_rule *r)
problems++;
}
if ((r->tagname[0] || r->match_tagname[0]) && !r->keep_state &&
- r->action == PF_PASS && !r->anchorname[0]) {
+ r->action == PF_PASS) {
yyerror("tags cannot be used without keep state");
problems++;
}
@@ -3646,7 +3871,7 @@ process_tabledef(char *name, struct table_opts *opts)
&opts->init_nodes);
if (!(pf->opts & PF_OPT_NOACTION) &&
pfctl_define_table(name, opts->flags, opts->init_addr,
- pf->anchor, pf->ruleset, &ab, pf->tticket)) {
+ pf->anchor, &ab, pf->tticket)) {
yyerror("cannot define table %s: %s", name,
pfr_strerror(errno));
goto _error;
@@ -4112,7 +4337,8 @@ expand_rule(struct pf_rule *r,
struct node_proto *protos, struct node_os *src_oses,
struct node_host *src_hosts, struct node_port *src_ports,
struct node_host *dst_hosts, struct node_port *dst_ports,
- struct node_uid *uids, struct node_gid *gids, struct node_icmp *icmp_types)
+ struct node_uid *uids, struct node_gid *gids, struct node_icmp *icmp_types,
+ const char *anchor_call)
{
sa_family_t af = r->af;
int added = 0, error = 0;
@@ -4165,11 +4391,12 @@ expand_rule(struct pf_rule *r,
r->af = dst_host->af;
if (*interface->ifname)
- memcpy(r->ifname, interface->ifname, sizeof(r->ifname));
+ strlcpy(r->ifname, interface->ifname,
+ sizeof(r->ifname));
else if (if_indextoname(src_host->ifindex, ifname))
- memcpy(r->ifname, ifname, sizeof(r->ifname));
+ strlcpy(r->ifname, ifname, sizeof(r->ifname));
else if (if_indextoname(dst_host->ifindex, ifname))
- memcpy(r->ifname, ifname, sizeof(r->ifname));
+ strlcpy(r->ifname, ifname, sizeof(r->ifname));
else
memset(r->ifname, '\0', sizeof(r->ifname));
@@ -4196,12 +4423,12 @@ expand_rule(struct pf_rule *r,
r->ifnot = interface->not;
r->proto = proto->proto;
r->src.addr = src_host->addr;
- r->src.not = src_host->not;
+ r->src.neg = src_host->not;
r->src.port[0] = src_port->port[0];
r->src.port[1] = src_port->port[1];
r->src.port_op = src_port->op;
r->dst.addr = dst_host->addr;
- r->dst.not = dst_host->not;
+ r->dst.neg = dst_host->not;
r->dst.port[0] = dst_port->port[0];
r->dst.port[1] = dst_port->port[1];
r->dst.port_op = dst_port->op;
@@ -4264,7 +4491,7 @@ expand_rule(struct pf_rule *r,
yyerror("skipping rule due to errors");
else {
r->nr = pf->rule_nr++;
- pfctl_add_rule(pf, r);
+ pfctl_add_rule(pf, r, anchor_call);
added++;
}
@@ -4286,6 +4513,42 @@ expand_rule(struct pf_rule *r,
yyerror("rule expands to no valid combination");
}
+int
+expand_skip_interface(struct node_if *interfaces)
+{
+ int errs = 0;
+
+ if (!interfaces || (!interfaces->next && !interfaces->not &&
+ !strcmp(interfaces->ifname, "none"))) {
+ if (pf->opts & PF_OPT_VERBOSE)
+ printf("set skip on none\n");
+ errs = pfctl_set_interface_flags(pf, "", PFI_IFLAG_SKIP, 0);
+ return (errs);
+ }
+
+ if (pf->opts & PF_OPT_VERBOSE)
+ printf("set skip on {");
+ LOOP_THROUGH(struct node_if, interface, interfaces,
+ if (pf->opts & PF_OPT_VERBOSE)
+ printf(" %s", interface->ifname);
+ if (interface->not) {
+ yyerror("skip on ! <interface> is not supported");
+ errs++;
+ } else
+ errs += pfctl_set_interface_flags(pf,
+ interface->ifname, PFI_IFLAG_SKIP, 1);
+ );
+ if (pf->opts & PF_OPT_VERBOSE)
+ printf(" }\n");
+
+ FREE_LIST(struct node_if, interfaces);
+
+ if (errs)
+ return (1);
+ else
+ return (0);
+}
+
#undef FREE_LIST
#undef LOOP_THROUGH
@@ -4336,6 +4599,7 @@ lookup(char *s)
{ "fingerprints", FINGERPRINTS},
{ "flags", FLAGS},
{ "floating", FLOATING},
+ { "flush", FLUSH},
{ "for", FOR},
{ "fragment", FRAGMENT},
{ "from", FROM},
@@ -4360,6 +4624,8 @@ lookup(char *s)
{ "loginterface", LOGINTERFACE},
{ "max", MAXIMUM},
{ "max-mss", MAXMSS},
+ { "max-src-conn", MAXSRCCONN},
+ { "max-src-conn-rate", MAXSRCCONNRATE},
{ "max-src-nodes", MAXSRCNODES},
{ "max-src-states", MAXSRCSTATES},
{ "min-ttl", MINTTL},
@@ -4374,10 +4640,12 @@ lookup(char *s)
{ "optimization", OPTIMIZATION},
{ "os", OS},
{ "out", OUT},
+ { "overload", OVERLOAD},
{ "pass", PASS},
{ "port", PORT},
{ "priority", PRIORITY},
{ "priq", PRIQ},
+ { "probability", PROBABILITY},
{ "proto", PROTO},
{ "qlimit", QLIMIT},
{ "queue", QUEUE},
@@ -4395,10 +4663,12 @@ lookup(char *s)
{ "return-icmp6", RETURNICMP6},
{ "return-rst", RETURNRST},
{ "round-robin", ROUNDROBIN},
+ { "route", ROUTE},
{ "route-to", ROUTETO},
{ "rule", RULE},
{ "scrub", SCRUB},
{ "set", SET},
+ { "skip", SKIP},
{ "source-hash", SOURCEHASH},
{ "source-track", SOURCETRACK},
{ "state", STATE},
@@ -4850,7 +5120,7 @@ getservice(char *n)
if (atoul(n, &ulval) == 0) {
if (ulval > 65535) {
- yyerror("illegal port value %d", ulval);
+ yyerror("illegal port value %lu", ulval);
return (-1);
}
return (htons(ulval));
@@ -4900,7 +5170,7 @@ parseicmpspec(char *w, sa_family_t af)
ulval = p->code;
}
if (ulval > 255) {
- yyerror("invalid icmp code %ld", ulval);
+ yyerror("invalid icmp code %lu", ulval);
return (0);
}
return (icmptype << 8 | ulval);
@@ -4913,10 +5183,10 @@ pfctl_load_anchors(int dev, int opts, struct pfr_buffer *trans)
TAILQ_FOREACH(la, &loadanchorshead, entries) {
if (opts & PF_OPT_VERBOSE)
- fprintf(stderr, "\nLoading anchor %s:%s from %s\n",
- la->anchorname, la->rulesetname, la->filename);
+ fprintf(stderr, "\nLoading anchor %s from %s\n",
+ la->anchorname, la->filename);
if (pfctl_rules(dev, la->filename, opts, la->anchorname,
- la->rulesetname, trans) == -1)
+ trans) == -1)
return (-1);
}
diff --git a/contrib/pf/pfctl/pf_print_state.c b/contrib/pf/pfctl/pf_print_state.c
index 318bde7..1205547 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.39 2004/02/10 17:48:08 henning Exp $ */
+/* $OpenBSD: pf_print_state.c,v 1.40 2004/12/10 22:13:26 henning Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -100,6 +100,9 @@ print_addr(struct pf_addr_wrap *addr, sa_family_t af, int verbose)
case PF_ADDR_NOROUTE:
printf("no-route");
return;
+ case PF_ADDR_RTLABEL:
+ printf("route \"%s\"", addr->v.rtlabelname);
+ return;
default:
printf("?");
return;
diff --git a/contrib/pf/pfctl/pfctl.c b/contrib/pf/pfctl/pfctl.c
index 6abbbec..bc4c96e 100644
--- a/contrib/pf/pfctl/pfctl.c
+++ b/contrib/pf/pfctl/pfctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl.c,v 1.213 2004/03/20 09:31:42 david Exp $ */
+/* $OpenBSD: pfctl.c,v 1.234 2005/03/07 13:52:50 henning Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
+#include <sys/stat.h>
#include <net/if.h>
#include <netinet/in.h>
@@ -65,23 +66,31 @@ void usage(void);
int pfctl_enable(int, int);
int pfctl_disable(int, int);
int pfctl_clear_stats(int, int);
-int pfctl_clear_rules(int, int, char *, char *);
-int pfctl_clear_nat(int, int, char *, char *);
+int pfctl_clear_interface_flags(int, int);
+int pfctl_clear_rules(int, int, char *);
+int pfctl_clear_nat(int, int, char *);
int pfctl_clear_altq(int, int);
int pfctl_clear_src_nodes(int, int);
int pfctl_clear_states(int, const char *, int);
int pfctl_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);
+int pfctl_load_timeout(struct pfctl *, unsigned int, unsigned int);
+int pfctl_load_debug(struct pfctl *, unsigned int);
+int pfctl_load_logif(struct pfctl *, char *);
+int pfctl_load_hostid(struct pfctl *, unsigned int);
int pfctl_get_pool(int, struct pf_pool *, u_int32_t, u_int32_t, int,
- char *, char *);
+ char *);
void pfctl_print_rule_counters(struct pf_rule *, int);
-int pfctl_show_rules(int, int, int, char *, char *);
-int pfctl_show_nat(int, int, char *, char *);
+int pfctl_show_rules(int, int, int, char *);
+int pfctl_show_nat(int, int, char *);
int pfctl_show_src_nodes(int, int);
int pfctl_show_states(int, const char *, int);
int pfctl_show_status(int, int);
int pfctl_show_timeouts(int, int);
int pfctl_show_limits(int, int);
-int pfctl_debug(int, u_int32_t, int);
+void pfctl_debug(int, u_int32_t, int);
int pfctl_clear_rule_counters(int, int);
int pfctl_test_altqsupport(int, int);
int pfctl_show_anchors(int, int, char *);
@@ -128,6 +137,7 @@ static const struct pf_hint pf_hint_normal[] = {
{ "tcp.closing", 15 * 60 },
{ "tcp.finwait", 45 },
{ "tcp.closed", 90 },
+ { "tcp.tsdiff", 30 },
{ NULL, 0 }
};
static const struct pf_hint pf_hint_satellite[] = {
@@ -137,6 +147,7 @@ static const struct pf_hint pf_hint_satellite[] = {
{ "tcp.closing", 15 * 60 + 5 },
{ "tcp.finwait", 45 + 5 },
{ "tcp.closed", 90 + 5 },
+ { "tcp.tsdiff", 60 },
{ NULL, 0 }
};
static const struct pf_hint pf_hint_conservative[] = {
@@ -146,6 +157,7 @@ static const struct pf_hint pf_hint_conservative[] = {
{ "tcp.closing", 60 * 60 },
{ "tcp.finwait", 10 * 60 },
{ "tcp.closed", 3 * 60 },
+ { "tcp.tsdiff", 60 },
{ NULL, 0 }
};
static const struct pf_hint pf_hint_aggressive[] = {
@@ -155,6 +167,7 @@ static const struct pf_hint pf_hint_aggressive[] = {
{ "tcp.closing", 60 },
{ "tcp.finwait", 30 },
{ "tcp.closed", 30 },
+ { "tcp.tsdiff", 10 },
{ NULL, 0 }
};
@@ -196,14 +209,14 @@ usage(void)
{
extern char *__progname;
- fprintf(stderr, "usage: %s [-AdeghNnOqRrvz] ", __progname);
- fprintf(stderr, "[-a anchor[:ruleset]] [-D macro=value]\n");
+ fprintf(stderr, "usage: %s [-AdeghmNnOoqRrvz] ", __progname);
+ fprintf(stderr, "[-a anchor] [-D macro=value] [-F modifier]\n");
fprintf(stderr, " ");
- fprintf(stderr, "[-F modifier] [-f file] [-i interface] ");
- fprintf(stderr, "[-k host] [-p device]\n");
+ fprintf(stderr, "[-f file] [-i interface] [-k host] ");
+ fprintf(stderr, "[-p device] [-s modifier]\n");
fprintf(stderr, " ");
- fprintf(stderr, "[-s modifier] [-T command [address ...]] ");
- fprintf(stderr, "[-t table] [-x level]\n");
+ fprintf(stderr, "[-t table -T command [address ...]] ");
+ fprintf(stderr, "[-x level]\n");
exit(1);
}
@@ -260,42 +273,31 @@ pfctl_clear_stats(int dev, int opts)
}
int
-pfctl_clear_rules(int dev, int opts, char *anchorname, char *rulesetname)
+pfctl_clear_interface_flags(int dev, int opts)
{
- struct pfr_buffer t;
+ struct pfioc_iface pi;
- if (*anchorname && !*rulesetname) {
- struct pfioc_ruleset pr;
- int mnr, nr, r;
+ if ((opts & PF_OPT_NOACTION) == 0) {
+ bzero(&pi, sizeof(pi));
+ pi.pfiio_flags = PFI_IFLAG_SETABLE_MASK;
- memset(&pr, 0, sizeof(pr));
- memcpy(pr.anchor, anchorname, sizeof(pr.anchor));
- if (ioctl(dev, DIOCGETRULESETS, &pr)) {
- if (errno == EINVAL)
- fprintf(stderr, "No rulesets in anchor '%s'.\n",
- anchorname);
- else
- err(1, "DIOCGETRULESETS");
- return (-1);
- }
- mnr = pr.nr;
- for (nr = mnr - 1; nr >= 0; --nr) {
- pr.nr = nr;
- if (ioctl(dev, DIOCGETRULESET, &pr))
- err(1, "DIOCGETRULESET");
- r = pfctl_clear_rules(dev, opts | PF_OPT_QUIET,
- anchorname, pr.name);
- if (r)
- return (r);
- }
+ if (ioctl(dev, DIOCCLRIFFLAG, &pi))
+ err(1, "DIOCCLRIFFLAG");
if ((opts & PF_OPT_QUIET) == 0)
- fprintf(stderr, "rules cleared\n");
- return (0);
+ fprintf(stderr, "pf: interface flags reset\n");
}
+ return (0);
+}
+
+int
+pfctl_clear_rules(int dev, int opts, char *anchorname)
+{
+ struct pfr_buffer t;
+
memset(&t, 0, sizeof(t));
t.pfrb_type = PFRB_TRANS;
- if (pfctl_add_trans(&t, PF_RULESET_SCRUB, anchorname, rulesetname) ||
- pfctl_add_trans(&t, PF_RULESET_FILTER, anchorname, rulesetname) ||
+ if (pfctl_add_trans(&t, PF_RULESET_SCRUB, anchorname) ||
+ pfctl_add_trans(&t, PF_RULESET_FILTER, anchorname) ||
pfctl_trans(dev, &t, DIOCXBEGIN, 0) ||
pfctl_trans(dev, &t, DIOCXCOMMIT, 0))
err(1, "pfctl_clear_rules");
@@ -305,43 +307,15 @@ pfctl_clear_rules(int dev, int opts, char *anchorname, char *rulesetname)
}
int
-pfctl_clear_nat(int dev, int opts, char *anchorname, char *rulesetname)
+pfctl_clear_nat(int dev, int opts, char *anchorname)
{
struct pfr_buffer t;
- if (*anchorname && !*rulesetname) {
- struct pfioc_ruleset pr;
- int mnr, nr, r;
-
- memset(&pr, 0, sizeof(pr));
- memcpy(pr.anchor, anchorname, sizeof(pr.anchor));
- if (ioctl(dev, DIOCGETRULESETS, &pr)) {
- if (errno == EINVAL)
- fprintf(stderr, "No rulesets in anchor '%s'.\n",
- anchorname);
- else
- err(1, "DIOCGETRULESETS");
- return (-1);
- }
- mnr = pr.nr;
- for (nr = mnr - 1; nr >= 0; --nr) {
- pr.nr = nr;
- if (ioctl(dev, DIOCGETRULESET, &pr))
- err(1, "DIOCGETRULESET");
- r = pfctl_clear_nat(dev, opts | PF_OPT_QUIET,
- anchorname, pr.name);
- if (r)
- return (r);
- }
- if ((opts & PF_OPT_QUIET) == 0)
- fprintf(stderr, "nat cleared\n");
- return (0);
- }
memset(&t, 0, sizeof(t));
t.pfrb_type = PFRB_TRANS;
- if (pfctl_add_trans(&t, PF_RULESET_NAT, anchorname, rulesetname) ||
- pfctl_add_trans(&t, PF_RULESET_BINAT, anchorname, rulesetname) ||
- pfctl_add_trans(&t, PF_RULESET_RDR, anchorname, rulesetname) ||
+ if (pfctl_add_trans(&t, PF_RULESET_NAT, anchorname) ||
+ pfctl_add_trans(&t, PF_RULESET_BINAT, anchorname) ||
+ pfctl_add_trans(&t, PF_RULESET_RDR, anchorname) ||
pfctl_trans(dev, &t, DIOCXBEGIN, 0) ||
pfctl_trans(dev, &t, DIOCXCOMMIT, 0))
err(1, "pfctl_clear_nat");
@@ -359,7 +333,7 @@ pfctl_clear_altq(int dev, int opts)
return (-1);
memset(&t, 0, sizeof(t));
t.pfrb_type = PFRB_TRANS;
- if (pfctl_add_trans(&t, PF_RULESET_ALTQ, "", "") ||
+ if (pfctl_add_trans(&t, PF_RULESET_ALTQ, "") ||
pfctl_trans(dev, &t, DIOCXBEGIN, 0) ||
pfctl_trans(dev, &t, DIOCXCOMMIT, 0))
err(1, "pfctl_clear_altq");
@@ -503,7 +477,7 @@ pfctl_kill_states(int dev, const char *iface, int opts)
int
pfctl_get_pool(int dev, struct pf_pool *pool, u_int32_t nr,
- u_int32_t ticket, int r_action, char *anchorname, char *rulesetname)
+ u_int32_t ticket, int r_action, char *anchorname)
{
struct pfioc_pooladdr pp;
struct pf_pooladdr *pa;
@@ -511,7 +485,6 @@ pfctl_get_pool(int dev, struct pf_pool *pool, u_int32_t nr,
memset(&pp, 0, sizeof(pp));
memcpy(pp.anchor, anchorname, sizeof(pp.anchor));
- memcpy(pp.ruleset, rulesetname, sizeof(pp.ruleset));
pp.r_action = r_action;
pp.r_num = nr;
pp.ticket = ticket;
@@ -589,45 +562,14 @@ pfctl_print_title(char *title)
}
int
-pfctl_show_rules(int dev, int opts, int format, char *anchorname,
- char *rulesetname)
+pfctl_show_rules(int dev, int opts, int format, char *anchorname)
{
struct pfioc_rule pr;
u_int32_t nr, mnr, header = 0;
int rule_numbers = opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG);
- if (*anchorname && !*rulesetname) {
- struct pfioc_ruleset pr;
- int r;
-
- memset(&pr, 0, sizeof(pr));
- memcpy(pr.anchor, anchorname, sizeof(pr.anchor));
- if (ioctl(dev, DIOCGETRULESETS, &pr)) {
- if (errno == EINVAL)
- fprintf(stderr, "No rulesets in anchor '%s'.\n",
- anchorname);
- else
- err(1, "DIOCGETRULESETS");
- return (-1);
- }
- if (opts & PF_OPT_SHOWALL && pr.nr)
- pfctl_print_title("FILTER RULES:");
- mnr = pr.nr;
- for (nr = 0; nr < mnr; ++nr) {
- pr.nr = nr;
- if (ioctl(dev, DIOCGETRULESET, &pr))
- err(1, "DIOCGETRULESET");
- r = pfctl_show_rules(dev, opts, format, anchorname,
- pr.name);
- if (r)
- return (r);
- }
- return (0);
- }
-
memset(&pr, 0, sizeof(pr));
memcpy(pr.anchor, anchorname, sizeof(pr.anchor));
- memcpy(pr.ruleset, rulesetname, sizeof(pr.ruleset));
if (opts & PF_OPT_SHOWALL) {
pr.rule.action = PF_PASS;
if (ioctl(dev, DIOCGETRULES, &pr)) {
@@ -656,7 +598,7 @@ pfctl_show_rules(int dev, int opts, int format, char *anchorname,
}
if (pfctl_get_pool(dev, &pr.rule.rpool,
- nr, pr.ticket, PF_SCRUB, anchorname, rulesetname) != 0)
+ nr, pr.ticket, PF_SCRUB, anchorname) != 0)
return (-1);
switch (format) {
@@ -672,7 +614,7 @@ pfctl_show_rules(int dev, int opts, int format, char *anchorname,
default:
if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL))
labels = 1;
- print_rule(&pr.rule, rule_numbers);
+ print_rule(&pr.rule, pr.anchor_call, rule_numbers);
pfctl_print_rule_counters(&pr.rule, opts);
}
pfctl_clear_pool(&pr.rule.rpool);
@@ -691,7 +633,7 @@ pfctl_show_rules(int dev, int opts, int format, char *anchorname,
}
if (pfctl_get_pool(dev, &pr.rule.rpool,
- nr, pr.ticket, PF_PASS, anchorname, rulesetname) != 0)
+ nr, pr.ticket, PF_PASS, anchorname) != 0)
return (-1);
switch (format) {
@@ -707,7 +649,7 @@ pfctl_show_rules(int dev, int opts, int format, char *anchorname,
default:
if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL))
labels = 1;
- print_rule(&pr.rule, rule_numbers);
+ print_rule(&pr.rule, pr.anchor_call, rule_numbers);
pfctl_print_rule_counters(&pr.rule, opts);
}
pfctl_clear_pool(&pr.rule.rpool);
@@ -716,42 +658,15 @@ pfctl_show_rules(int dev, int opts, int format, char *anchorname,
}
int
-pfctl_show_nat(int dev, int opts, char *anchorname, char *rulesetname)
+pfctl_show_nat(int dev, int opts, char *anchorname)
{
struct pfioc_rule pr;
u_int32_t mnr, nr;
static int nattype[3] = { PF_NAT, PF_RDR, PF_BINAT };
int i, dotitle = opts & PF_OPT_SHOWALL;
- if (*anchorname && !*rulesetname) {
- struct pfioc_ruleset pr;
- int r;
-
- memset(&pr, 0, sizeof(pr));
- memcpy(pr.anchor, anchorname, sizeof(pr.anchor));
- if (ioctl(dev, DIOCGETRULESETS, &pr)) {
- if (errno == EINVAL)
- fprintf(stderr, "No rulesets in anchor '%s'.\n",
- anchorname);
- else
- err(1, "DIOCGETRULESETS");
- return (-1);
- }
- mnr = pr.nr;
- for (nr = 0; nr < mnr; ++nr) {
- pr.nr = nr;
- if (ioctl(dev, DIOCGETRULESET, &pr))
- err(1, "DIOCGETRULESET");
- r = pfctl_show_nat(dev, opts, anchorname, pr.name);
- if (r)
- return (r);
- }
- return (0);
- }
-
memset(&pr, 0, sizeof(pr));
memcpy(pr.anchor, anchorname, sizeof(pr.anchor));
- memcpy(pr.ruleset, rulesetname, sizeof(pr.ruleset));
for (i = 0; i < 3; i++) {
pr.rule.action = nattype[i];
if (ioctl(dev, DIOCGETRULES, &pr)) {
@@ -766,14 +681,14 @@ pfctl_show_nat(int dev, int opts, char *anchorname, char *rulesetname)
return (-1);
}
if (pfctl_get_pool(dev, &pr.rule.rpool, nr,
- pr.ticket, nattype[i], anchorname,
- rulesetname) != 0)
+ pr.ticket, nattype[i], anchorname) != 0)
return (-1);
if (dotitle) {
pfctl_print_title("TRANSLATION RULES:");
dotitle = 0;
}
- print_rule(&pr.rule, opts & PF_OPT_VERBOSE2);
+ print_rule(&pr.rule, pr.anchor_call,
+ opts & PF_OPT_VERBOSE2);
pfctl_print_rule_counters(&pr.rule, opts);
pfctl_clear_pool(&pr.rule.rpool);
}
@@ -897,7 +812,8 @@ pfctl_show_timeouts(int dev, int opts)
if (ioctl(dev, DIOCGETTIMEOUT, &pt))
err(1, "DIOCGETTIMEOUT");
printf("%-20s %10d", pf_timeouts[i].name, pt.seconds);
- if (i >= PFTM_ADAPTIVE_START && i <= PFTM_ADAPTIVE_END)
+ if (pf_timeouts[i].timeout >= PFTM_ADAPTIVE_START &&
+ pf_timeouts[i].timeout <= PFTM_ADAPTIVE_END)
printf(" states");
else
printf("s");
@@ -952,13 +868,14 @@ pfctl_add_pool(struct pfctl *pf, struct pf_pool *p, sa_family_t af)
}
int
-pfctl_add_rule(struct pfctl *pf, struct pf_rule *r)
+pfctl_add_rule(struct pfctl *pf, struct pf_rule *r, const char *anchor_call)
{
u_int8_t rs_num;
struct pfioc_rule pr;
switch (r->action) {
case PF_SCRUB:
+ case PF_NOSCRUB:
if ((loadopt & PFCTL_FLAG_FILTER) == 0)
return (0);
rs_num = PF_RULESET_SCRUB;
@@ -988,28 +905,59 @@ pfctl_add_rule(struct pfctl *pf, struct pf_rule *r)
rs_num = PF_RULESET_BINAT;
break;
default:
- errx(1, "Invalid rule type");
+ errx(1, "Invalid rule type %d", r->action);
break;
}
+
+ if ((pf->opts & PF_OPT_OPTIMIZE) && rs_num == PF_RULESET_FILTER) {
+ /*
+ * We'll do an optimization post-pass before finally adding the
+ * rules. Then we'll disable the optimization flag and feed
+ * the rules right back into this function.
+ */
+ struct pf_opt_rule *pfr;
+ struct pf_pooladdr *pa;
+
+ if ((pfr = calloc(1, sizeof(*pfr))) == NULL)
+ err(1, "calloc");
+ memcpy(&pfr->por_rule, r, sizeof(*r));
+ if (strlcpy(pfr->por_anchor, anchor_call,
+ sizeof(pfr->por_anchor)) >= sizeof(pfr->por_anchor))
+ errx(1, "pfctl_add_rule: strlcpy");
+ TAILQ_INSERT_TAIL(&pf->opt_queue, pfr, por_entry);
+
+ if (TAILQ_FIRST(&r->rpool.list) != NULL) {
+ TAILQ_INIT(&pfr->por_rule.rpool.list);
+ while ((pa = TAILQ_FIRST(&r->rpool.list)) != NULL) {
+ TAILQ_REMOVE(&r->rpool.list, pa, entries);
+ TAILQ_INSERT_TAIL(&pfr->por_rule.rpool.list, pa,
+ entries);
+ }
+ } else {
+ memset(&pfr->por_rule.rpool, 0,
+ sizeof(pfr->por_rule.rpool));
+
+ }
+ return (0);
+ }
+
if ((pf->opts & PF_OPT_NOACTION) == 0) {
bzero(&pr, sizeof(pr));
if (strlcpy(pr.anchor, pf->anchor, sizeof(pr.anchor)) >=
- sizeof(pr.anchor) ||
- strlcpy(pr.ruleset, pf->ruleset, sizeof(pr.ruleset)) >=
- sizeof(pr.ruleset))
+ sizeof(pr.anchor))
errx(1, "pfctl_add_rule: strlcpy");
if (pfctl_add_pool(pf, &r->rpool, r->af))
return (1);
- pr.ticket = pfctl_get_ticket(pf->trans, rs_num, pf->anchor,
- pf->ruleset);
+ pr.ticket = pfctl_get_ticket(pf->trans, rs_num, pf->anchor);
pr.pool_ticket = pf->paddr.ticket;
memcpy(&pr.rule, r, sizeof(pr.rule));
+ strlcpy(pr.anchor_call, anchor_call, sizeof(pr.anchor_call));
if (ioctl(pf->dev, DIOCADDRULE, &pr))
err(1, "DIOCADDRULE");
}
if (pf->opts & PF_OPT_VERBOSE)
- print_rule(r, pf->opts & PF_OPT_VERBOSE2);
+ print_rule(r, anchor_call, pf->opts & PF_OPT_VERBOSE2);
pfctl_clear_pool(&r->rpool);
return (0);
}
@@ -1038,7 +986,7 @@ pfctl_add_altq(struct pfctl *pf, struct pf_altq *a)
int
pfctl_rules(int dev, char *filename, int opts, char *anchorname,
- char *rulesetname, struct pfr_buffer *trans)
+ struct pfr_buffer *trans)
{
#define ERR(x) do { warn(x); goto _error; } while(0)
#define ERRX(x) do { warnx(x); goto _error; } while(0)
@@ -1064,15 +1012,13 @@ pfctl_rules(int dev, char *filename, int opts, char *anchorname,
memset(&pf, 0, sizeof(pf));
memset(&trs, 0, sizeof(trs));
if (strlcpy(trs.pfrt_anchor, anchorname,
- sizeof(trs.pfrt_anchor)) >= sizeof(trs.pfrt_anchor) ||
- strlcpy(trs.pfrt_ruleset, rulesetname,
- sizeof(trs.pfrt_ruleset)) >= sizeof(trs.pfrt_ruleset))
+ sizeof(trs.pfrt_anchor)) >= sizeof(trs.pfrt_anchor))
ERRX("pfctl_rules: strlcpy");
if (strcmp(filename, "-") == 0) {
fin = stdin;
infile = "stdin";
} else {
- if ((fin = fopen(filename, "r")) == NULL) {
+ if ((fin = pfctl_fopen(filename, "r")) == NULL) {
warn("%s", filename);
return (1);
}
@@ -1087,43 +1033,37 @@ pfctl_rules(int dev, char *filename, int opts, char *anchorname,
pf.trans = t;
pf.rule_nr = 0;
pf.anchor = anchorname;
- pf.ruleset = rulesetname;
+ TAILQ_INIT(&pf.opt_queue);
+ pfctl_init_options(&pf);
if ((opts & PF_OPT_NOACTION) == 0) {
if ((pf.loadopt & PFCTL_FLAG_NAT) != 0) {
- if (pfctl_add_trans(t, PF_RULESET_NAT, anchorname,
- rulesetname) ||
- pfctl_add_trans(t, PF_RULESET_BINAT, anchorname,
- rulesetname) ||
- pfctl_add_trans(t, PF_RULESET_RDR, anchorname,
- rulesetname))
+ if (pfctl_add_trans(t, PF_RULESET_NAT, anchorname) ||
+ pfctl_add_trans(t, PF_RULESET_BINAT, anchorname) ||
+ pfctl_add_trans(t, PF_RULESET_RDR, anchorname))
ERR("pfctl_rules");
}
if (((altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ) != 0))) {
- if (pfctl_add_trans(t, PF_RULESET_ALTQ, anchorname,
- rulesetname))
+ if (pfctl_add_trans(t, PF_RULESET_ALTQ, anchorname))
ERR("pfctl_rules");
}
if ((pf.loadopt & PFCTL_FLAG_FILTER) != 0) {
- if (pfctl_add_trans(t, PF_RULESET_SCRUB, anchorname,
- rulesetname) ||
- pfctl_add_trans(t, PF_RULESET_FILTER, anchorname,
- rulesetname))
+ if (pfctl_add_trans(t, PF_RULESET_SCRUB, anchorname) ||
+ pfctl_add_trans(t, PF_RULESET_FILTER, anchorname))
ERR("pfctl_rules");
}
if (pf.loadopt & PFCTL_FLAG_TABLE) {
- if (pfctl_add_trans(t, PF_RULESET_TABLE, anchorname,
- rulesetname))
+ if (pfctl_add_trans(t, PF_RULESET_TABLE, anchorname))
ERR("pfctl_rules");
}
if (pfctl_trans(dev, t, DIOCXBEGIN, osize))
ERR("DIOCXBEGIN");
if (altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ))
pa.ticket = pfctl_get_ticket(t, PF_RULESET_ALTQ,
- anchorname, rulesetname);
+ anchorname);
if (pf.loadopt & PFCTL_FLAG_TABLE)
pf.tticket = pfctl_get_ticket(t, PF_RULESET_TABLE,
- anchorname, rulesetname);
+ anchorname);
}
if (parse_rules(fin, &pf) < 0) {
if ((opts & PF_OPT_NOACTION) == 0)
@@ -1132,20 +1072,32 @@ pfctl_rules(int dev, char *filename, int opts, char *anchorname,
else
goto _error;
}
+ if (pf.opts & PF_OPT_OPTIMIZE) {
+ if (pfctl_optimize_rules(&pf))
+ ERRX("Failed to optimize ruleset: pf rules not loaded");
+ }
+
if ((altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ) != 0))
if (check_commit_altq(dev, opts) != 0)
ERRX("errors in altq config");
- if (fin != stdin)
+
+ if (fin != stdin) {
fclose(fin);
+ fin = NULL;
+ }
/* process "load anchor" directives */
- if (!anchorname[0] && !rulesetname[0])
+ if (!anchorname[0])
if (pfctl_load_anchors(dev, opts, t) == -1)
ERRX("load anchors");
- if (trans == NULL && (opts & PF_OPT_NOACTION) == 0)
+ if (trans == NULL && (opts & PF_OPT_NOACTION) == 0) {
+ if (!anchorname[0])
+ if (pfctl_load_options(&pf))
+ goto _error;
if (pfctl_trans(dev, t, DIOCXCOMMIT, 0))
ERR("DIOCXCOMMIT");
+ }
return (0);
_error:
@@ -1154,38 +1106,118 @@ _error:
if (pfctl_trans(dev, t, DIOCXROLLBACK, 0))
err(1, "DIOCXROLLBACK");
exit(1);
- } else /* sub ruleset */
+ } else { /* sub ruleset */
+ if (fin != NULL && fin != stdin)
+ fclose(fin);
return (-1);
+ }
#undef ERR
#undef ERRX
}
+FILE *
+pfctl_fopen(const char *name, const char *mode)
+{
+ struct stat st;
+ FILE *fp;
+
+ fp = fopen(name, mode);
+ if (fp == NULL)
+ return (NULL);
+ if (fstat(fileno(fp), &st)) {
+ fclose(fp);
+ return (NULL);
+ }
+ if (S_ISDIR(st.st_mode)) {
+ fclose(fp);
+ errno = EISDIR;
+ return (NULL);
+ }
+ return (fp);
+}
+
+void
+pfctl_init_options(struct pfctl *pf)
+{
+ pf->timeout[PFTM_TCP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL;
+ pf->timeout[PFTM_TCP_OPENING] = PFTM_TCP_OPENING_VAL;
+ pf->timeout[PFTM_TCP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL;
+ pf->timeout[PFTM_TCP_CLOSING] = PFTM_TCP_CLOSING_VAL;
+ pf->timeout[PFTM_TCP_FIN_WAIT] = PFTM_TCP_FIN_WAIT_VAL;
+ pf->timeout[PFTM_TCP_CLOSED] = PFTM_TCP_CLOSED_VAL;
+ pf->timeout[PFTM_UDP_FIRST_PACKET] = PFTM_UDP_FIRST_PACKET_VAL;
+ pf->timeout[PFTM_UDP_SINGLE] = PFTM_UDP_SINGLE_VAL;
+ pf->timeout[PFTM_UDP_MULTIPLE] = PFTM_UDP_MULTIPLE_VAL;
+ pf->timeout[PFTM_ICMP_FIRST_PACKET] = PFTM_ICMP_FIRST_PACKET_VAL;
+ pf->timeout[PFTM_ICMP_ERROR_REPLY] = PFTM_ICMP_ERROR_REPLY_VAL;
+ pf->timeout[PFTM_OTHER_FIRST_PACKET] = PFTM_OTHER_FIRST_PACKET_VAL;
+ pf->timeout[PFTM_OTHER_SINGLE] = PFTM_OTHER_SINGLE_VAL;
+ pf->timeout[PFTM_OTHER_MULTIPLE] = PFTM_OTHER_MULTIPLE_VAL;
+ pf->timeout[PFTM_FRAG] = PFTM_FRAG_VAL;
+ pf->timeout[PFTM_INTERVAL] = PFTM_INTERVAL_VAL;
+ pf->timeout[PFTM_SRC_NODE] = PFTM_SRC_NODE_VAL;
+ pf->timeout[PFTM_TS_DIFF] = PFTM_TS_DIFF_VAL;
+
+ pf->limit[PF_LIMIT_STATES] = PFSTATE_HIWAT;
+ pf->limit[PF_LIMIT_FRAGS] = PFFRAG_FRENT_HIWAT;
+ pf->limit[PF_LIMIT_SRC_NODES] = PFSNODE_HIWAT;
+
+ pf->debug = PF_DEBUG_URGENT;
+}
+
int
-pfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit)
+pfctl_load_options(struct pfctl *pf)
{
- struct pfioc_limit pl;
- int i;
+ int i, error = 0;
if ((loadopt & PFCTL_FLAG_OPTION) == 0)
return (0);
- memset(&pl, 0, sizeof(pl));
+ /* load limits */
+ for (i = 0; i < PF_LIMIT_MAX; i++) {
+ if ((pf->opts & PF_OPT_MERGE) && !pf->limit_set[i])
+ continue;
+ if (pfctl_load_limit(pf, i, pf->limit[i]))
+ error = 1;
+ }
+
+ /* load timeouts */
+ for (i = 0; i < PFTM_MAX; i++) {
+ if ((pf->opts & PF_OPT_MERGE) && !pf->timeout_set[i])
+ continue;
+ if (pfctl_load_timeout(pf, i, pf->timeout[i]))
+ error = 1;
+ }
+
+ /* load debug */
+ if (!(pf->opts & PF_OPT_MERGE) || pf->debug_set)
+ if (pfctl_load_debug(pf, pf->debug))
+ error = 1;
+
+ /* load logif */
+ if (!(pf->opts & PF_OPT_MERGE) || pf->ifname_set)
+ if (pfctl_load_logif(pf, pf->ifname))
+ error = 1;
+
+ /* load hostid */
+ if (!(pf->opts & PF_OPT_MERGE) || pf->hostid_set)
+ if (pfctl_load_hostid(pf, pf->hostid))
+ error = 1;
+
+ return (error);
+}
+
+int
+pfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit)
+{
+ int i;
+
+
for (i = 0; pf_limits[i].name; i++) {
if (strcasecmp(opt, pf_limits[i].name) == 0) {
- pl.index = pf_limits[i].index;
- pl.limit = limit;
- if ((pf->opts & PF_OPT_NOACTION) == 0) {
- if (ioctl(pf->dev, DIOCSETLIMIT, &pl)) {
- if (errno == EBUSY) {
- warnx("Current pool "
- "size exceeds requested "
- "hard limit");
- return (1);
- } else
- err(1, "DIOCSETLIMIT");
- }
- }
+ pf->limit[pf_limits[i].index] = limit;
+ pf->limit_set[pf_limits[i].index] = 1;
break;
}
}
@@ -1201,18 +1233,35 @@ pfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit)
}
int
+pfctl_load_limit(struct pfctl *pf, unsigned int index, unsigned int limit)
+{
+ struct pfioc_limit pl;
+
+ memset(&pl, 0, sizeof(pl));
+ pl.index = index;
+ pl.limit = limit;
+ if (ioctl(pf->dev, DIOCSETLIMIT, &pl)) {
+ if (errno == EBUSY)
+ warnx("Current pool size exceeds requested hard limit");
+ else
+ warnx("DIOCSETLIMIT");
+ return (1);
+ }
+ return (0);
+}
+
+int
pfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet)
{
- struct pfioc_tm pt;
int i;
if ((loadopt & PFCTL_FLAG_OPTION) == 0)
return (0);
- memset(&pt, 0, sizeof(pt));
for (i = 0; pf_timeouts[i].name; i++) {
if (strcasecmp(opt, pf_timeouts[i].name) == 0) {
- pt.timeout = pf_timeouts[i].timeout;
+ pf->timeout[pf_timeouts[i].timeout] = seconds;
+ pf->timeout_set[pf_timeouts[i].timeout] = 1;
break;
}
}
@@ -1222,11 +1271,6 @@ pfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet)
return (1);
}
- pt.seconds = seconds;
- if ((pf->opts & PF_OPT_NOACTION) == 0) {
- if (ioctl(pf->dev, DIOCSETTIMEOUT, &pt))
- err(1, "DIOCSETTIMEOUT");
- }
if (pf->opts & PF_OPT_VERBOSE && ! quiet)
printf("set timeout %s %d\n", opt, seconds);
@@ -1235,6 +1279,21 @@ pfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet)
}
int
+pfctl_load_timeout(struct pfctl *pf, unsigned int timeout, unsigned int seconds)
+{
+ struct pfioc_tm pt;
+
+ memset(&pt, 0, sizeof(pt));
+ pt.timeout = timeout;
+ pt.seconds = seconds;
+ if (ioctl(pf->dev, DIOCSETTIMEOUT, &pt)) {
+ warnx("DIOCSETTIMEOUT");
+ return (1);
+ }
+ return (0);
+}
+
+int
pfctl_set_optimization(struct pfctl *pf, const char *opt)
{
const struct pf_hint *hint;
@@ -1267,23 +1326,19 @@ pfctl_set_optimization(struct pfctl *pf, const char *opt)
int
pfctl_set_logif(struct pfctl *pf, char *ifname)
{
- struct pfioc_if pi;
if ((loadopt & PFCTL_FLAG_OPTION) == 0)
return (0);
- memset(&pi, 0, sizeof(pi));
- if ((pf->opts & PF_OPT_NOACTION) == 0) {
- if (!strcmp(ifname, "none"))
- bzero(pi.ifname, sizeof(pi.ifname));
- else {
- if (strlcpy(pi.ifname, ifname,
- sizeof(pi.ifname)) >= sizeof(pi.ifname))
- errx(1, "pfctl_set_logif: strlcpy");
- }
- if (ioctl(pf->dev, DIOCSETSTATUSIF, &pi))
- err(1, "DIOCSETSTATUSIF");
+ if (!strcmp(ifname, "none")) {
+ free(pf->ifname);
+ pf->ifname = NULL;
+ } else {
+ pf->ifname = strdup(ifname);
+ if (!pf->ifname)
+ errx(1, "pfctl_set_logif: strdup");
}
+ pf->ifname_set = 1;
if (pf->opts & PF_OPT_VERBOSE)
printf("set loginterface %s\n", ifname);
@@ -1292,6 +1347,24 @@ pfctl_set_logif(struct pfctl *pf, char *ifname)
}
int
+pfctl_load_logif(struct pfctl *pf, char *ifname)
+{
+ struct pfioc_if pi;
+
+ memset(&pi, 0, sizeof(pi));
+ if (ifname && strlcpy(pi.ifname, ifname,
+ sizeof(pi.ifname)) >= sizeof(pi.ifname)) {
+ warnx("pfctl_set_logif: strlcpy");
+ return (1);
+ }
+ if (ioctl(pf->dev, DIOCSETSTATUSIF, &pi)) {
+ warnx("DIOCSETSTATUSIF");
+ return (1);
+ }
+ return (0);
+}
+
+int
pfctl_set_hostid(struct pfctl *pf, u_int32_t hostid)
{
if ((loadopt & PFCTL_FLAG_OPTION) == 0)
@@ -1299,9 +1372,8 @@ pfctl_set_hostid(struct pfctl *pf, u_int32_t hostid)
HTONL(hostid);
- if ((pf->opts & PF_OPT_NOACTION) == 0)
- if (ioctl(dev, DIOCSETHOSTID, &hostid))
- err(1, "DIOCSETHOSTID");
+ pf->hostid = hostid;
+ pf->hostid_set = 1;
if (pf->opts & PF_OPT_VERBOSE)
printf("set hostid 0x%08x\n", ntohl(hostid));
@@ -1310,6 +1382,16 @@ pfctl_set_hostid(struct pfctl *pf, u_int32_t hostid)
}
int
+pfctl_load_hostid(struct pfctl *pf, u_int32_t hostid)
+{
+ if (ioctl(dev, DIOCSETHOSTID, &hostid)) {
+ warnx("DIOCSETHOSTID");
+ return (1);
+ }
+ return (0);
+}
+
+int
pfctl_set_debug(struct pfctl *pf, char *d)
{
u_int32_t level;
@@ -1318,18 +1400,20 @@ pfctl_set_debug(struct pfctl *pf, char *d)
return (0);
if (!strcmp(d, "none"))
- level = PF_DEBUG_NONE;
+ pf->debug = PF_DEBUG_NONE;
else if (!strcmp(d, "urgent"))
- level = PF_DEBUG_URGENT;
+ pf->debug = PF_DEBUG_URGENT;
else if (!strcmp(d, "misc"))
- level = PF_DEBUG_MISC;
+ pf->debug = PF_DEBUG_MISC;
else if (!strcmp(d, "loud"))
- level = PF_DEBUG_NOISY;
+ pf->debug = PF_DEBUG_NOISY;
else {
warnx("unknown debug level \"%s\"", d);
return (-1);
}
+ pf->debug_set = 1;
+
if ((pf->opts & PF_OPT_NOACTION) == 0)
if (ioctl(dev, DIOCSETDEBUG, &level))
err(1, "DIOCSETDEBUG");
@@ -1341,6 +1425,44 @@ pfctl_set_debug(struct pfctl *pf, char *d)
}
int
+pfctl_load_debug(struct pfctl *pf, unsigned int level)
+{
+ if (ioctl(pf->dev, DIOCSETDEBUG, &level)) {
+ warnx("DIOCSETDEBUG");
+ return (1);
+ }
+ return (0);
+}
+
+int
+pfctl_set_interface_flags(struct pfctl *pf, char *ifname, int flags, int how)
+{
+ struct pfioc_iface pi;
+
+ if ((loadopt & PFCTL_FLAG_OPTION) == 0)
+ return (0);
+
+ bzero(&pi, sizeof(pi));
+
+ pi.pfiio_flags = flags;
+
+ if (strlcpy(pi.pfiio_name, ifname, sizeof(pi.pfiio_name)) >=
+ sizeof(pi.pfiio_name))
+ errx(1, "pfctl_set_interface_flags: strlcpy");
+
+ if ((pf->opts & PF_OPT_NOACTION) == 0) {
+ if (how == 0) {
+ if (ioctl(pf->dev, DIOCCLRIFFLAG, &pi))
+ err(1, "DIOCCLRIFFLAG");
+ } else {
+ if (ioctl(pf->dev, DIOCSETIFFLAG, &pi))
+ err(1, "DIOCSETIFFLAG");
+ }
+ }
+ return (0);
+}
+
+void
pfctl_debug(int dev, u_int32_t level, int opts)
{
if (ioctl(dev, DIOCSETDEBUG, &level))
@@ -1366,7 +1488,6 @@ pfctl_debug(int dev, u_int32_t level, int opts)
}
fprintf(stderr, "'\n");
}
- return (0);
}
int
@@ -1403,48 +1524,37 @@ pfctl_test_altqsupport(int dev, int opts)
int
pfctl_show_anchors(int dev, int opts, char *anchorname)
{
- u_int32_t nr, mnr;
+ struct pfioc_ruleset pr;
+ u_int32_t mnr, nr;
- if (!*anchorname) {
- struct pfioc_anchor pa;
+ memset(&pr, 0, sizeof(pr));
+ memcpy(pr.path, anchorname, sizeof(pr.path));
+ if (ioctl(dev, DIOCGETRULESETS, &pr)) {
+ if (errno == EINVAL)
+ fprintf(stderr, "Anchor '%s' not found.\n",
+ anchorname);
+ else
+ err(1, "DIOCGETRULESETS");
+ return (-1);
+ }
+ mnr = pr.nr;
+ for (nr = 0; nr < mnr; ++nr) {
+ char sub[MAXPATHLEN];
- memset(&pa, 0, sizeof(pa));
- if (ioctl(dev, DIOCGETANCHORS, &pa)) {
- warn("DIOCGETANCHORS");
- return (-1);
- }
- mnr = pa.nr;
- for (nr = 0; nr < mnr; ++nr) {
- pa.nr = nr;
- if (ioctl(dev, DIOCGETANCHOR, &pa)) {
- warn("DIOCGETANCHOR");
- return (-1);
- }
- if (!(opts & PF_OPT_VERBOSE) &&
- !strcmp(pa.name, PF_RESERVED_ANCHOR))
- continue;
- printf(" %s\n", pa.name);
+ pr.nr = nr;
+ if (ioctl(dev, DIOCGETRULESET, &pr))
+ err(1, "DIOCGETRULESET");
+ if (!strcmp(pr.name, PF_RESERVED_ANCHOR))
+ continue;
+ sub[0] = 0;
+ if (pr.path[0]) {
+ strlcat(sub, pr.path, sizeof(sub));
+ strlcat(sub, "/", sizeof(sub));
}
- } else {
- struct pfioc_ruleset pr;
-
- memset(&pr, 0, sizeof(pr));
- memcpy(pr.anchor, anchorname, sizeof(pr.anchor));
- if (ioctl(dev, DIOCGETRULESETS, &pr)) {
- if (errno == EINVAL)
- fprintf(stderr, "No rulesets in anchor '%s'.\n",
- anchorname);
- else
- err(1, "DIOCGETRULESETS");
+ strlcat(sub, pr.name, sizeof(sub));
+ printf(" %s\n", sub);
+ if (opts & PF_OPT_VERBOSE && pfctl_show_anchors(dev, opts, sub))
return (-1);
- }
- mnr = pr.nr;
- for (nr = 0; nr < mnr; ++nr) {
- pr.nr = nr;
- if (ioctl(dev, DIOCGETRULESET, &pr))
- err(1, "DIOCGETRULESET");
- printf(" %s:%s\n", pr.anchor, pr.name);
- }
}
return (0);
}
@@ -1466,14 +1576,13 @@ main(int argc, char *argv[])
int ch;
int mode = O_RDONLY;
int opts = 0;
- char anchorname[PF_ANCHOR_NAME_SIZE];
- char rulesetname[PF_RULESET_NAME_SIZE];
+ char anchorname[MAXPATHLEN];
if (argc < 2)
usage();
while ((ch = getopt(argc, argv,
- "a:AdD:eqf:F:ghi:k:nNOp:rRs:t:T:vx:z")) != -1) {
+ "a:AdD:eqf:F:ghi:k:mnNOop:rRs:t:T:vx:z")) != -1) {
switch (ch) {
case 'a':
anchoropt = optarg;
@@ -1514,6 +1623,9 @@ main(int argc, char *argv[])
state_kill[state_killers++] = optarg;
mode = O_RDWR;
break;
+ case 'm':
+ opts |= PF_OPT_MERGE;
+ break;
case 'n':
opts |= PF_OPT_NOACTION;
break;
@@ -1536,6 +1648,12 @@ main(int argc, char *argv[])
case 'R':
loadopt |= PFCTL_FLAG_FILTER;
break;
+ case 'o':
+ if (opts & PF_OPT_OPTIMIZE)
+ opts |= PF_OPT_OPTIMIZE_PROFILE;
+ else
+ opts |= PF_OPT_OPTIMIZE;
+ break;
case 'O':
loadopt |= PFCTL_FLAG_OPTION;
break;
@@ -1602,31 +1720,11 @@ main(int argc, char *argv[])
loadopt = ~0;
memset(anchorname, 0, sizeof(anchorname));
- memset(rulesetname, 0, sizeof(rulesetname));
if (anchoropt != NULL) {
- char *t;
-
- if ((t = strchr(anchoropt, ':')) == NULL) {
- if (strlcpy(anchorname, anchoropt,
- sizeof(anchorname)) >= sizeof(anchorname))
- errx(1, "anchor name '%s' too long",
- anchoropt);
- } else {
- char *p;
-
- if ((p = strdup(anchoropt)) == NULL)
- err(1, "anchoropt: strdup");
- t = strsep(&p, ":");
- if (*t == '\0' || *p == '\0')
- errx(1, "anchor '%s' invalid", anchoropt);
- if (strlcpy(anchorname, t, sizeof(anchorname)) >=
- sizeof(anchorname))
- errx(1, "anchor name '%s' too long", t);
- if (strlcpy(rulesetname, p, sizeof(rulesetname)) >=
- sizeof(rulesetname))
- errx(1, "ruleset name '%s' too long", p);
- free(t); /* not p */
- }
+ if (strlcpy(anchorname, anchoropt,
+ sizeof(anchorname)) >= sizeof(anchorname))
+ errx(1, "anchor name '%s' too long",
+ anchoropt);
loadopt &= PFCTL_FLAG_FILTER|PFCTL_FLAG_NAT|PFCTL_FLAG_TABLE;
}
@@ -1660,17 +1758,15 @@ main(int argc, char *argv[])
break;
case 'r':
pfctl_load_fingerprints(dev, opts);
- pfctl_show_rules(dev, opts, 0, anchorname,
- rulesetname);
+ pfctl_show_rules(dev, opts, 0, anchorname);
break;
case 'l':
pfctl_load_fingerprints(dev, opts);
- pfctl_show_rules(dev, opts, 1, anchorname,
- rulesetname);
+ pfctl_show_rules(dev, opts, 1, anchorname);
break;
case 'n':
pfctl_load_fingerprints(dev, opts);
- pfctl_show_nat(dev, opts, anchorname, rulesetname);
+ pfctl_show_nat(dev, opts, anchorname);
break;
case 'q':
pfctl_show_altq(dev, ifaceopt, opts,
@@ -1695,21 +1791,20 @@ main(int argc, char *argv[])
opts |= PF_OPT_SHOWALL;
pfctl_load_fingerprints(dev, opts);
- pfctl_show_nat(dev, opts, anchorname, rulesetname);
- pfctl_show_rules(dev, opts, 0, anchorname,
- rulesetname);
+ pfctl_show_nat(dev, opts, anchorname);
+ pfctl_show_rules(dev, opts, 0, anchorname);
pfctl_show_altq(dev, ifaceopt, opts, 0);
pfctl_show_states(dev, ifaceopt, opts);
pfctl_show_src_nodes(dev, opts);
pfctl_show_status(dev, opts);
- pfctl_show_rules(dev, opts, 1, anchorname, rulesetname);
+ pfctl_show_rules(dev, opts, 1, anchorname);
pfctl_show_timeouts(dev, opts);
pfctl_show_limits(dev, opts);
- pfctl_show_tables(anchorname, rulesetname, opts);
+ pfctl_show_tables(anchorname, opts);
pfctl_show_fingerprints(opts);
break;
case 'T':
- pfctl_show_tables(anchorname, rulesetname, opts);
+ pfctl_show_tables(anchorname, opts);
break;
case 'o':
pfctl_load_fingerprints(dev, opts);
@@ -1724,10 +1819,10 @@ main(int argc, char *argv[])
if (clearopt != NULL) {
switch (*clearopt) {
case 'r':
- pfctl_clear_rules(dev, opts, anchorname, rulesetname);
+ pfctl_clear_rules(dev, opts, anchorname);
break;
case 'n':
- pfctl_clear_nat(dev, opts, anchorname, rulesetname);
+ pfctl_clear_nat(dev, opts, anchorname);
break;
case 'q':
pfctl_clear_altq(dev, opts);
@@ -1742,22 +1837,23 @@ main(int argc, char *argv[])
pfctl_clear_stats(dev, opts);
break;
case 'a':
- pfctl_clear_rules(dev, opts, anchorname, rulesetname);
- pfctl_clear_nat(dev, opts, anchorname, rulesetname);
- pfctl_clear_tables(anchorname, rulesetname, opts);
- if (!*anchorname && !*rulesetname) {
+ pfctl_clear_rules(dev, opts, anchorname);
+ pfctl_clear_nat(dev, opts, anchorname);
+ pfctl_clear_tables(anchorname, opts);
+ if (!*anchorname) {
pfctl_clear_altq(dev, opts);
pfctl_clear_states(dev, ifaceopt, opts);
pfctl_clear_src_nodes(dev, opts);
pfctl_clear_stats(dev, opts);
pfctl_clear_fingerprints(dev, opts);
+ pfctl_clear_interface_flags(dev, opts);
}
break;
case 'o':
pfctl_clear_fingerprints(dev, opts);
break;
case 'T':
- pfctl_clear_tables(anchorname, rulesetname, opts);
+ pfctl_clear_tables(anchorname, opts);
break;
}
}
@@ -1766,17 +1862,21 @@ main(int argc, char *argv[])
if (tblcmdopt != NULL) {
error = pfctl_command_tables(argc, argv, tableopt,
- tblcmdopt, rulesopt, anchorname, rulesetname, opts);
+ tblcmdopt, rulesopt, anchorname, opts);
rulesopt = NULL;
}
- if (rulesopt != NULL)
+ if ((rulesopt != NULL) && (!*anchorname))
+ if (pfctl_clear_interface_flags(dev, opts | PF_OPT_QUIET))
+ error = 1;
+
+ if (rulesopt != NULL && !(opts & (PF_OPT_MERGE|PF_OPT_NOACTION)) &&
+ !anchorname[0] && (loadopt & PFCTL_FLAG_OPTION))
if (pfctl_file_fingerprints(dev, opts, PF_OSFP_FILE))
error = 1;
if (rulesopt != NULL) {
- if (pfctl_rules(dev, rulesopt, opts, anchorname, rulesetname,
- NULL))
+ if (pfctl_rules(dev, rulesopt, opts, anchorname, NULL))
error = 1;
else if (!(opts & PF_OPT_NOACTION) &&
(loadopt & PFCTL_FLAG_TABLE))
diff --git a/contrib/pf/pfctl/pfctl.h b/contrib/pf/pfctl/pfctl.h
index 2776f5e..94c6fc8 100644
--- a/contrib/pf/pfctl/pfctl.h
+++ b/contrib/pf/pfctl/pfctl.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl.h,v 1.33 2004/02/19 21:37:01 cedric Exp $ */
+/* $OpenBSD: pfctl.h,v 1.37 2005/01/05 18:23:10 mcbride Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -65,8 +65,6 @@ 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_begin(struct pfr_table *, int *, int *, int);
-int pfr_ina_commit(struct pfr_table *, 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 *);
@@ -80,13 +78,14 @@ int pfi_get_ifaces(const char *, struct pfi_if *, int *, int);
int pfi_clr_istats(const char *, int *, int);
void pfctl_print_title(char *);
-int pfctl_clear_tables(const char *, const char *, int);
-int pfctl_show_tables(const char *, const char *, int);
+int pfctl_clear_tables(const char *, int);
+int pfctl_show_tables(const char *, int);
int pfctl_command_tables(int, char *[], char *, const char *, char *,
- const char *, const char *, int);
+ const char *, int);
int pfctl_show_altq(int, const char *, int, int);
void warn_namespace_collision(const char *);
int pfctl_show_ifaces(const char *, int);
+FILE *pfctl_fopen(const char *, const char *);
#ifdef __FreeBSD__
extern int altqsupport;
@@ -108,6 +107,8 @@ struct segment {
double x, y, d, m;
};
+extern int loadopt;
+
int check_commit_altq(int, int);
void pfaltq_store(struct pf_altq *);
void pfaltq_free(struct pf_altq *);
@@ -121,9 +122,9 @@ void print_state(struct pf_state *, int);
int unmask(struct pf_addr *, sa_family_t);
int pfctl_cmdline_symset(char *);
-int pfctl_add_trans(struct pfr_buffer *, int, const char *, const char *);
+int pfctl_add_trans(struct pfr_buffer *, int, const char *);
u_int32_t
- pfctl_get_ticket(struct pfr_buffer *, int, const char *, const char *);
+ pfctl_get_ticket(struct pfr_buffer *, int, const char *);
int pfctl_trans(int, struct pfr_buffer *, u_long, int);
#endif /* _PFCTL_H_ */
diff --git a/contrib/pf/pfctl/pfctl_altq.c b/contrib/pf/pfctl/pfctl_altq.c
index eeed648..384d1a2 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.83 2004/03/14 21:51:44 dhartmei Exp $ */
+/* $OpenBSD: pfctl_altq.c,v 1.86 2005/02/28 14:04:51 henning Exp $ */
/*
* Copyright (c) 2002
@@ -315,7 +315,8 @@ eval_pfqueue(struct pfctl *pf, struct pf_altq *pa, struct node_queue_bw *bw,
struct node_queue_opt *opts)
{
/* should be merged with expand_queue */
- struct pf_altq *if_pa, *parent;
+ struct pf_altq *if_pa, *parent, *altq;
+ u_int32_t bwsum;
int error = 0;
/* find the corresponding interface and copy fields used by queues */
@@ -347,22 +348,35 @@ eval_pfqueue(struct pfctl *pf, struct pf_altq *pa, struct node_queue_bw *bw,
pa->qlimit = DEFAULT_QLIMIT;
if (pa->scheduler == ALTQT_CBQ || pa->scheduler == ALTQT_HFSC) {
- if ((pa->bandwidth = eval_bwspec(bw,
- parent == NULL ? 0 : parent->bandwidth)) == 0) {
- fprintf(stderr, "bandwidth for %s invalid (%d / %d)\n",
- pa->qname, bw->bw_absolute, bw->bw_percent);
- return (1);
- }
+ pa->bandwidth = eval_bwspec(bw,
+ parent == NULL ? 0 : parent->bandwidth);
if (pa->bandwidth > pa->ifbandwidth) {
fprintf(stderr, "bandwidth for %s higher than "
"interface\n", pa->qname);
return (1);
}
- if (parent != NULL && pa->bandwidth > parent->bandwidth) {
- fprintf(stderr, "bandwidth for %s higher than parent\n",
- pa->qname);
- return (1);
+ /* check the sum of the child bandwidth is under parent's */
+ if (parent != NULL) {
+ if (pa->bandwidth > parent->bandwidth) {
+ warnx("bandwidth for %s higher than parent",
+ pa->qname);
+ return (1);
+ }
+ bwsum = 0;
+ TAILQ_FOREACH(altq, &altqs, entries) {
+ if (strncmp(altq->ifname, pa->ifname,
+ IFNAMSIZ) == 0 &&
+ altq->qname[0] != 0 &&
+ strncmp(altq->parent, pa->parent,
+ PF_QNAME_SIZE) == 0)
+ bwsum += altq->bandwidth;
+ }
+ bwsum += pa->bandwidth;
+ if (bwsum > parent->bandwidth) {
+ warnx("the sum of the child bandwidth higher"
+ " than parent \"%s\"", parent->qname);
+ }
}
}
@@ -706,7 +720,7 @@ eval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa)
* for the real-time service curve, the sum of the service curves
* should not exceed 80% of the interface bandwidth. 20% is reserved
* not to over-commit the actual interface bandwidth.
- * for the link-sharing service curve, the sum of the child service
+ * for the linkshare service curve, the sum of the child service
* curve should not exceed the parent service curve.
* for the upper-limit service curve, the assigned bandwidth should
* be smaller than the interface bandwidth, and the upper-limit should
@@ -733,7 +747,7 @@ eval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa)
if (strncmp(altq->parent, pa->parent, PF_QNAME_SIZE) != 0)
continue;
- /* if the class has a link-sharing service curve, add it. */
+ /* if the class has a linkshare service curve, add it. */
if (opts->lssc_m2 != 0 && altq->pq_u.hfsc_opts.lssc_m2 != 0) {
sc.m1 = altq->pq_u.hfsc_opts.lssc_m1;
sc.d = altq->pq_u.hfsc_opts.lssc_d;
@@ -744,22 +758,35 @@ eval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa)
/* check the real-time service curve. reserve 20% of interface bw */
if (opts->rtsc_m2 != 0) {
+ /* add this queue to the sum */
+ sc.m1 = opts->rtsc_m1;
+ sc.d = opts->rtsc_d;
+ sc.m2 = opts->rtsc_m2;
+ gsc_add_sc(&rtsc, &sc);
+ /* compare the sum with 80% of the interface */
sc.m1 = 0;
sc.d = 0;
sc.m2 = pa->ifbandwidth / 100 * 80;
if (!is_gsc_under_sc(&rtsc, &sc)) {
- warnx("real-time sc exceeds the interface bandwidth");
+ warnx("real-time sc exceeds 80%% of the interface "
+ "bandwidth (%s)", rate2str((double)sc.m2));
goto err_ret;
}
}
- /* check the link-sharing service curve. */
+ /* check the linkshare service curve. */
if (opts->lssc_m2 != 0) {
+ /* add this queue to the child sum */
+ sc.m1 = opts->lssc_m1;
+ sc.d = opts->lssc_d;
+ sc.m2 = opts->lssc_m2;
+ gsc_add_sc(&lssc, &sc);
+ /* compare the sum of the children with parent's sc */
sc.m1 = parent->pq_u.hfsc_opts.lssc_m1;
sc.d = parent->pq_u.hfsc_opts.lssc_d;
sc.m2 = parent->pq_u.hfsc_opts.lssc_m2;
if (!is_gsc_under_sc(&lssc, &sc)) {
- warnx("link-sharing sc exceeds parent's sc");
+ warnx("linkshare sc exceeds parent's sc");
goto err_ret;
}
}
@@ -1108,6 +1135,7 @@ getifspeed(char *ifname)
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
err(1, "socket");
+ bzero(&ifr, sizeof(ifr));
if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >=
sizeof(ifr.ifr_name))
errx(1, "getifspeed: strlcpy");
@@ -1130,6 +1158,7 @@ getifmtu(char *ifname)
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
err(1, "socket");
+ bzero(&ifr, sizeof(ifr));
if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >=
sizeof(ifr.ifr_name))
errx(1, "getifmtu: strlcpy");
diff --git a/contrib/pf/pfctl/pfctl_optimize.c b/contrib/pf/pfctl/pfctl_optimize.c
index 6c6803e..111dc32 100644
--- a/contrib/pf/pfctl/pfctl_optimize.c
+++ b/contrib/pf/pfctl/pfctl_optimize.c
@@ -16,6 +16,9 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
@@ -815,7 +818,11 @@ block_feedback(struct pfctl *pf, struct superblock *block)
break;
}
}
+#ifdef __FreeBSD__
+ if (por2 == NULL)
+#else
if (por2 == TAILQ_END(&block->sb_rules))
+#endif
TAILQ_INSERT_TAIL(&block->sb_rules, por1, por_entry);
}
diff --git a/contrib/pf/pfctl/pfctl_parser.c b/contrib/pf/pfctl/pfctl_parser.c
index c02f7da..2cf82b4 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.194 2004/03/15 15:25:44 dhartmei Exp $ */
+/* $OpenBSD: pfctl_parser.c,v 1.211 2004/12/07 10:33:41 dhartmei Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -37,6 +37,8 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
+#include <sys/param.h>
+#include <sys/proc.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
@@ -66,6 +68,7 @@ void print_ugid (u_int8_t, unsigned, unsigned, const char *, unsigned);
void print_flags (u_int8_t);
void print_fromto(struct pf_rule_addr *, pf_osfp_t,
struct pf_rule_addr *, u_int8_t, u_int8_t, int);
+int ifa_skip_if(const char *filter, struct node_host *p);
struct node_host *host_if(const char *, int);
struct node_host *host_v4(const char *, int);
@@ -186,6 +189,7 @@ const struct pf_timeout pf_timeouts[] = {
{ "tcp.closing", PFTM_TCP_CLOSING },
{ "tcp.finwait", PFTM_TCP_FIN_WAIT },
{ "tcp.closed", PFTM_TCP_CLOSED },
+ { "tcp.tsdiff", PFTM_TS_DIFF },
{ "udp.first", PFTM_UDP_FIRST_PACKET },
{ "udp.single", PFTM_UDP_SINGLE },
{ "udp.multiple", PFTM_UDP_MULTIPLE },
@@ -366,13 +370,13 @@ print_fromto(struct pf_rule_addr *src, pf_osfp_t osfp, struct pf_rule_addr *dst,
PF_AZERO(&src->addr.v.a.mask, AF_INET6) &&
PF_AZERO(&dst->addr.v.a.addr, AF_INET6) &&
PF_AZERO(&dst->addr.v.a.mask, AF_INET6) &&
- !src->not && !dst->not &&
+ !src->neg && !dst->neg &&
!src->port_op && !dst->port_op &&
osfp == PF_OSFP_ANY)
printf(" all");
else {
printf(" from ");
- if (src->not)
+ if (src->neg)
printf("! ");
print_addr(&src->addr, af, verbose);
if (src->port_op)
@@ -384,7 +388,7 @@ print_fromto(struct pf_rule_addr *src, pf_osfp_t osfp, struct pf_rule_addr *dst,
sizeof(buf)));
printf(" to ");
- if (dst->not)
+ if (dst->neg)
printf("! ");
print_addr(&dst->addr, af, verbose);
if (dst->port_op)
@@ -472,6 +476,7 @@ print_pool(struct pf_pool *pool, u_int16_t p1, u_int16_t p2,
}
const char *pf_reasons[PFRES_MAX+1] = PFRES_NAMES;
+const char *pf_lcounters[LCNT_MAX+1] = LCNT_NAMES;
const char *pf_fcounters[FCNT_MAX+1] = FCNT_NAMES;
const char *pf_scounters[FCNT_MAX+1] = FCNT_NAMES;
@@ -574,6 +579,22 @@ print_status(struct pf_status *s, int opts)
else
printf("%14s\n", "");
}
+ if (opts & PF_OPT_VERBOSE) {
+ printf("Limit Counters\n");
+ for (i = 0; i < LCNT_MAX; i++) {
+ printf(" %-25s %14lld ", pf_lcounters[i],
+#ifdef __FreeBSD__
+ (unsigned long long)s->lcounters[i]);
+#else
+ s->lcounters[i]);
+#endif
+ if (runtime > 0)
+ printf("%14.1f/s\n",
+ (double)s->lcounters[i] / (double)runtime);
+ else
+ printf("%14s\n", "");
+ }
+ }
}
void
@@ -593,7 +614,9 @@ print_src_node(struct pf_src_node *sn, int opts)
printf(" -> ");
aw.v.a.addr = sn->raddr;
print_addr(&aw, sn->af, opts & PF_OPT_VERBOSE2);
- printf(" (%d states)\n", sn->states);
+ printf(" ( states %u, connections %u, rate %u.%u/%us )\n", sn->states,
+ sn->conn, sn->conn_rate.count / 1000,
+ (sn->conn_rate.count % 1000) / 100, sn->conn_rate.seconds);
if (opts & PF_OPT_VERBOSE) {
sec = sn->creation % 60;
sn->creation /= 60;
@@ -628,21 +651,22 @@ print_src_node(struct pf_src_node *sn, int opts)
}
void
-print_rule(struct pf_rule *r, int verbose)
+print_rule(struct pf_rule *r, const char *anchor_call, int verbose)
{
- static const char *actiontypes[] = { "pass", "block", "scrub", "nat",
- "no nat", "binat", "no binat", "rdr", "no rdr" };
+ static const char *actiontypes[] = { "pass", "block", "scrub",
+ "no scrub", "nat", "no nat", "binat", "no binat", "rdr", "no rdr" };
static const char *anchortypes[] = { "anchor", "anchor", "anchor",
- "nat-anchor", "nat-anchor", "binat-anchor", "binat-anchor",
- "rdr-anchor", "rdr-anchor" };
+ "anchor", "nat-anchor", "nat-anchor", "binat-anchor",
+ "binat-anchor", "rdr-anchor", "rdr-anchor" };
int i, opts;
if (verbose)
printf("@%d ", r->nr);
if (r->action > PF_NORDR)
printf("action(%d)", r->action);
- else if (r->anchorname[0])
- printf("%s %s", anchortypes[r->action], r->anchorname);
+ else if (anchor_call[0])
+ printf("%s \"%s\"", anchortypes[r->action],
+ anchor_call);
else {
printf("%s", actiontypes[r->action]);
if (r->natpass)
@@ -782,6 +806,21 @@ print_rule(struct pf_rule *r, int verbose)
printf(" modulate state");
else if (r->keep_state == PF_STATE_SYNPROXY)
printf(" synproxy state");
+ if (r->prob) {
+ char buf[20];
+
+ snprintf(buf, sizeof(buf), "%f", r->prob*100.0/(UINT_MAX+1.0));
+ for (i = strlen(buf)-1; i > 0; i--) {
+ if (buf[i] == '0')
+ buf[i] = '\0';
+ else {
+ if (buf[i] == '.')
+ buf[i] = '\0';
+ break;
+ }
+ }
+ printf(" probability %s%%", buf);
+ }
opts = 0;
if (r->max_states || r->max_src_nodes || r->max_src_states)
opts = 1;
@@ -822,12 +861,35 @@ print_rule(struct pf_rule *r, int verbose)
printf("max-src-states %u", r->max_src_states);
opts = 0;
}
+ if (r->max_src_conn) {
+ if (!opts)
+ printf(", ");
+ printf("max-src-conn %u", r->max_src_conn);
+ opts = 0;
+ }
+ if (r->max_src_conn_rate.limit) {
+ if (!opts)
+ printf(", ");
+ printf("max-src-conn-rate %u/%u",
+ r->max_src_conn_rate.limit,
+ r->max_src_conn_rate.seconds);
+ opts = 0;
+ }
if (r->max_src_nodes) {
if (!opts)
printf(", ");
printf("max-src-nodes %u", r->max_src_nodes);
opts = 0;
}
+ if (r->overload_tblname[0]) {
+ if (!opts)
+ printf(", ");
+ printf("overload <%s>", r->overload_tblname);
+ if (r->flush)
+ printf(" flush");
+ if (r->flush & PF_FLUSH_GLOBAL)
+ printf(" global");
+ }
if (r->rule_flag & PFRULE_IFBOUND) {
if (!opts)
printf(", ");
@@ -842,11 +904,17 @@ print_rule(struct pf_rule *r, int verbose)
}
for (i = 0; i < PFTM_MAX; ++i)
if (r->timeout[i]) {
+ int j;
+
if (!opts)
printf(", ");
opts = 0;
- printf("%s %u", pf_timeouts[i].name,
- r->timeout[i]);
+ for (j = 0; j < sizeof(pf_timeouts) /
+ sizeof(pf_timeouts[0]); ++j)
+ if (pf_timeouts[j].timeout == i)
+ break;
+ printf("%s %u", j == PFTM_MAX ? "inv.timeout" :
+ pf_timeouts[j].name, r->timeout[i]);
}
printf(")");
}
@@ -886,7 +954,7 @@ print_rule(struct pf_rule *r, int verbose)
printf(" !");
printf(" tagged %s", r->match_tagname);
}
- if (!r->anchorname[0] && (r->action == PF_NAT ||
+ if (!anchor_call[0] && (r->action == PF_NAT ||
r->action == PF_BINAT || r->action == PF_RDR)) {
printf(" -> ");
print_pool(&r->rpool, r->rpool.proxy_port[0],
@@ -953,9 +1021,7 @@ set_ipmask(struct node_host *h, u_int8_t b)
int i, j = 0;
m = &h->addr.v.a.mask;
-
- for (i = 0; i < 4; i++)
- m->addr32[i] = 0;
+ memset(m, 0, sizeof(*m));
while (b >= 32) {
m->addr32[j++] = 0xffffffff;
@@ -1007,8 +1073,6 @@ ifa_load(void)
{
struct ifaddrs *ifap, *ifa;
struct node_host *n = NULL, *h = NULL;
- struct pfr_buffer b;
- struct pfi_if *p;
if (getifaddrs(&ifap) < 0)
err(1, "getifaddrs");
@@ -1084,43 +1148,6 @@ ifa_load(void)
}
}
- /* add interface groups, including clonable and dynamic stuff */
- bzero(&b, sizeof(b));
- b.pfrb_type = PFRB_IFACES;
- for (;;) {
- if (pfr_buf_grow(&b, b.pfrb_size))
- err(1, "ifa_load: pfr_buf_grow");
- b.pfrb_size = b.pfrb_msize;
- if (pfi_get_ifaces(NULL, b.pfrb_caddr, &b.pfrb_size,
- PFI_FLAG_GROUP))
- err(1, "ifa_load: pfi_get_ifaces");
- if (b.pfrb_size <= b.pfrb_msize)
- break;
- }
- PFRB_FOREACH(p, &b) {
- n = calloc(1, sizeof(struct node_host));
- if (n == NULL)
- err(1, "address: calloc");
- n->af = AF_LINK;
- n->ifa_flags = PF_IFA_FLAG_GROUP;
- if (p->pfif_flags & PFI_IFLAG_DYNAMIC)
- n->ifa_flags |= PF_IFA_FLAG_DYNAMIC;
- if (p->pfif_flags & PFI_IFLAG_CLONABLE)
- n->ifa_flags |= PF_IFA_FLAG_CLONABLE;
- if (!strcmp(p->pfif_name, "lo"))
- n->ifa_flags |= IFF_LOOPBACK;
- if ((n->ifname = strdup(p->pfif_name)) == NULL)
- err(1, "ifa_load: strdup");
- n->next = NULL;
- n->tail = n;
- if (h == NULL)
- h = n;
- else {
- h->tail->next = n;
- h->tail = n;
- }
- }
-
iftab = h;
freeifaddrs(ifap);
}
@@ -1129,12 +1156,7 @@ struct node_host *
ifa_exists(const char *ifa_name, int group_ok)
{
struct node_host *n;
- char *p, buf[IFNAMSIZ];
- int group;
- group = !isdigit(ifa_name[strlen(ifa_name) - 1]);
- if (group && !group_ok)
- return (NULL);
if (iftab == NULL)
ifa_load();
@@ -1142,19 +1164,7 @@ ifa_exists(const char *ifa_name, int group_ok)
if (n->af == AF_LINK && !strncmp(n->ifname, ifa_name, IFNAMSIZ))
return (n);
}
- if (!group) {
- /* look for clonable and/or dynamic interface */
- strlcpy(buf, ifa_name, sizeof(buf));
- for (p = buf + strlen(buf) - 1; p > buf && isdigit(*p); p--)
- *p = '\0';
- for (n = iftab; n != NULL; n = n->next)
- if (n->af == AF_LINK &&
- !strncmp(n->ifname, buf, IFNAMSIZ))
- break;
- if (n != NULL && n->ifa_flags &
- (PF_IFA_FLAG_DYNAMIC | PF_IFA_FLAG_CLONABLE))
- return (n); /* XXX */
- }
+
return (NULL);
}
@@ -1162,19 +1172,17 @@ struct node_host *
ifa_lookup(const char *ifa_name, int flags)
{
struct node_host *p = NULL, *h = NULL, *n = NULL;
- int return_all = 0, got4 = 0, got6 = 0;
+ int got4 = 0, got6 = 0;
const char *last_if = NULL;
if (!strncmp(ifa_name, "self", IFNAMSIZ))
- return_all = 1;
+ ifa_name = NULL;
if (iftab == NULL)
ifa_load();
for (p = iftab; p; p = p->next) {
- if (!((p->af == AF_INET || p->af == AF_INET6) &&
- (!strncmp(p->ifname, ifa_name, strlen(ifa_name)) ||
- return_all)))
+ if (ifa_skip_if(ifa_name, p))
continue;
if ((flags & PFI_AFLAG_BROADCAST) && p->af != AF_INET)
continue;
@@ -1238,6 +1246,28 @@ ifa_lookup(const char *ifa_name, int flags)
return (h);
}
+int
+ifa_skip_if(const char *filter, struct node_host *p)
+{
+ int n;
+
+ if (p->af != AF_INET && p->af != AF_INET6)
+ return (1);
+ if (filter == NULL || !*filter)
+ return (0);
+ if (!strcmp(p->ifname, filter))
+ return (0); /* exact match */
+ n = strlen(filter);
+ if (n < 1 || n >= IFNAMSIZ)
+ return (1); /* sanity check */
+ if (filter[n-1] >= '0' && filter[n-1] <= '9')
+ return (1); /* only do exact match in that case */
+ if (strncmp(p->ifname, filter, n))
+ return (1); /* prefix doesn't match */
+ return (p->ifname[n] < '0' || p->ifname[n] > '9');
+}
+
+
struct node_host *
host(const char *s)
{
@@ -1248,7 +1278,7 @@ host(const char *s)
if ((p = strrchr(s, '/')) != NULL) {
mask = strtol(p+1, &q, 0);
if (!q || *q || mask > 128 || q == (p+1)) {
- fprintf(stderr, "invalid netmask\n");
+ fprintf(stderr, "invalid netmask '%s'\n", p);
return (NULL);
}
if ((ps = malloc(strlen(s) - strlen(p) + 1)) == NULL)
@@ -1402,7 +1432,7 @@ host_dns(const char *s, int v4mask, int v6mask)
char *p, *ps;
if ((ps = strdup(s)) == NULL)
- err(1, "host_if: strdup");
+ err(1, "host_dns: strdup");
if ((p = strrchr(ps, ':')) != NULL && !strcmp(p, ":0")) {
noalias = 1;
*p = '\0';
@@ -1411,8 +1441,10 @@ host_dns(const char *s, int v4mask, int v6mask)
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM; /* DUMMY */
error = getaddrinfo(ps, NULL, &hints, &res0);
- if (error)
+ if (error) {
+ free(ps);
return (h);
+ }
for (res = res0; res; res = res->ai_next) {
if (res->ai_family != AF_INET &&
@@ -1536,33 +1568,28 @@ append_addr_host(struct pfr_buffer *b, struct node_host *n, int test, int not)
}
int
-pfctl_add_trans(struct pfr_buffer *buf, int rs_num, const char *anchor,
- const char *ruleset)
+pfctl_add_trans(struct pfr_buffer *buf, int rs_num, const char *anchor)
{
struct pfioc_trans_e trans;
bzero(&trans, sizeof(trans));
trans.rs_num = rs_num;
if (strlcpy(trans.anchor, anchor,
- sizeof(trans.anchor)) >= sizeof(trans.anchor) ||
- strlcpy(trans.ruleset, ruleset,
- sizeof(trans.ruleset)) >= sizeof(trans.ruleset))
+ sizeof(trans.anchor)) >= sizeof(trans.anchor))
errx(1, "pfctl_add_trans: strlcpy");
return pfr_buf_add(buf, &trans);
}
u_int32_t
-pfctl_get_ticket(struct pfr_buffer *buf, int rs_num, const char *anchor,
- const char *ruleset)
+pfctl_get_ticket(struct pfr_buffer *buf, int rs_num, const char *anchor)
{
struct pfioc_trans_e *p;
PFRB_FOREACH(p, buf)
- if (rs_num == p->rs_num && !strcmp(anchor, p->anchor) &&
- !strcmp(ruleset, p->ruleset))
+ if (rs_num == p->rs_num && !strcmp(anchor, p->anchor))
return (p->ticket);
- errx(1, "pfr_get_ticket: assertion failed");
+ errx(1, "pfctl_get_ticket: assertion failed");
}
int
diff --git a/contrib/pf/pfctl/pfctl_parser.h b/contrib/pf/pfctl/pfctl_parser.h
index 0756cc8..1c075ef 100644
--- a/contrib/pf/pfctl/pfctl_parser.h
+++ b/contrib/pf/pfctl/pfctl_parser.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl_parser.h,v 1.74 2004/02/10 22:26:56 dhartmei Exp $ */
+/* $OpenBSD: pfctl_parser.h,v 1.80 2005/02/07 18:18:14 david Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -47,6 +47,9 @@
#define PF_OPT_DUMMYACTION 0x0100
#define PF_OPT_DEBUG 0x0200
#define PF_OPT_SHOWALL 0x0400
+#define PF_OPT_OPTIMIZE 0x0800
+#define PF_OPT_OPTIMIZE_PROFILE 0x1000
+#define PF_OPT_MERGE 0x2000
#define PF_TH_ALL 0xFF
@@ -60,6 +63,11 @@
NULL \
}
+struct pfr_buffer; /* forward definition */
+struct pf_opt_rule;
+TAILQ_HEAD(pf_opt_queue, pf_opt_rule);
+
+
struct pfctl {
int dev;
int opts;
@@ -73,11 +81,26 @@ struct pfctl {
struct pfr_buffer *trans;
const char *anchor;
const char *ruleset;
+ struct pf_opt_queue opt_queue;
+
+ /* 'set foo' options */
+ u_int32_t timeout[PFTM_MAX];
+ u_int32_t limit[PF_LIMIT_MAX];
+ u_int32_t debug;
+ u_int32_t hostid;
+ char *ifname;
+
+ u_int8_t timeout_set[PFTM_MAX];
+ u_int8_t limit_set[PF_LIMIT_MAX];
+ u_int8_t debug_set;
+ u_int8_t hostid_set;
+ u_int8_t ifname_set;
};
struct node_if {
char ifname[IFNAMSIZ];
u_int8_t not;
+ u_int8_t dynamic; /* antispoof */
u_int ifa_flags;
struct node_if *next;
struct node_if *tail;
@@ -166,11 +189,33 @@ struct node_tinit { /* table initializer */
char *file;
};
-struct pfr_buffer; /* forward definition */
-int pfctl_rules(int, char *, int, char *, char *, struct pfr_buffer *);
+/* optimizer created tables */
+struct pf_opt_tbl {
+ char pt_name[PF_TABLE_NAME_SIZE];
+ int pt_rulecount;
+ int pt_generated;
+ struct node_tinithead pt_nodes;
+ struct pfr_buffer *pt_buf;
+};
+#define PF_OPT_TABLE_PREFIX "__automatic_"
+
+/* optimizer pf_rule container */
+struct pf_opt_rule {
+ struct pf_rule por_rule;
+ struct pf_opt_tbl *por_src_tbl;
+ struct pf_opt_tbl *por_dst_tbl;
+ char por_anchor[MAXPATHLEN];
+ u_int64_t por_profile_count;
+ TAILQ_ENTRY(pf_opt_rule) por_entry;
+ TAILQ_ENTRY(pf_opt_rule) por_skip_entry[PF_SKIP_COUNT];
+};
+
+
+int pfctl_rules(int, char *, int, char *, struct pfr_buffer *);
+int pfctl_optimize_rules(struct pfctl *);
-int pfctl_add_rule(struct pfctl *, struct pf_rule *);
+int pfctl_add_rule(struct pfctl *, struct pf_rule *, const char *);
int pfctl_add_altq(struct pfctl *, struct pf_altq *);
int pfctl_add_pool(struct pfctl *, struct pf_pool *, sa_family_t);
void pfctl_clear_pool(struct pf_pool *);
@@ -181,6 +226,7 @@ int pfctl_set_limit(struct pfctl *, const char *, unsigned int);
int pfctl_set_logif(struct pfctl *, char *);
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_flags(char *);
@@ -188,7 +234,7 @@ int pfctl_load_anchors(int, int, struct pfr_buffer *);
void print_pool(struct pf_pool *, u_int16_t, u_int16_t, sa_family_t, int);
void print_src_node(struct pf_src_node *, int);
-void print_rule(struct pf_rule *, int);
+void print_rule(struct pf_rule *, const char *, int);
void print_tabledef(const char *, int, int, struct node_tinithead *);
void print_status(struct pf_status *, int);
@@ -202,8 +248,8 @@ void print_altq(const struct pf_altq *, unsigned, struct node_queue_bw *,
void print_queue(const struct pf_altq *, unsigned, struct node_queue_bw *,
int, struct node_queue_opt *);
-int pfctl_define_table(char *, int, int, const char *, const char *,
- struct pfr_buffer *, u_int32_t);
+int pfctl_define_table(char *, int, int, const char *, struct pfr_buffer *,
+ u_int32_t);
void pfctl_clear_fingerprints(int, int);
int pfctl_file_fingerprints(int, int, const char *);
@@ -244,6 +290,7 @@ extern const struct pf_timeout pf_timeouts[];
void set_ipmask(struct node_host *, u_int8_t);
int check_netmask(struct node_host *, sa_family_t);
+int unmask(struct pf_addr *, sa_family_t);
void ifa_load(void);
struct node_host *ifa_exists(const char *, int);
struct node_host *ifa_lookup(const char *, int);
diff --git a/contrib/pf/pfctl/pfctl_qstats.c b/contrib/pf/pfctl/pfctl_qstats.c
index a46603c..28535c2 100644
--- a/contrib/pf/pfctl/pfctl_qstats.c
+++ b/contrib/pf/pfctl/pfctl_qstats.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl_qstats.c,v 1.29 2004/03/15 15:25:44 dhartmei Exp $ */
+/* $OpenBSD: pfctl_qstats.c,v 1.30 2004/04/27 21:47:32 kjc Exp $ */
/*
* Copyright (c) Henning Brauer <henning@openbsd.org>
@@ -97,6 +97,8 @@ pfctl_show_altq(int dev, const char *iface, int opts, int verbose2)
if ((nodes = pfctl_update_qstats(dev, &root)) < 0)
return (-1);
+ if (nodes == 0)
+ printf("No queue in use\n");
for (node = root; node != NULL; node = node->next) {
if (iface != NULL && strcmp(node->altq.ifname, iface))
continue;
@@ -107,11 +109,11 @@ pfctl_show_altq(int dev, const char *iface, int opts, int verbose2)
pfctl_print_altq_node(dev, node, 0, opts);
}
- while (verbose2) {
+ while (verbose2 && nodes > 0) {
printf("\n");
fflush(stdout);
sleep(STAT_INTERVAL);
- if (pfctl_update_qstats(dev, &root) == -1)
+ if ((nodes = pfctl_update_qstats(dev, &root)) == -1)
return (-1);
for (node = root; node != NULL; node = node->next) {
if (iface != NULL && strcmp(node->altq.ifname, iface))
diff --git a/contrib/pf/pfctl/pfctl_table.c b/contrib/pf/pfctl/pfctl_table.c
index 7b838b0..ecdd7e2 100644
--- a/contrib/pf/pfctl/pfctl_table.c
+++ b/contrib/pf/pfctl/pfctl_table.c
@@ -1,5 +1,4 @@
-/* $OpenBSD: pfctl_table.c,v 1.59 2004/03/15 15:25:44 dhartmei Exp $ */
-/* add $OpenBSD: pfctl_table.c,v 1.61 2004/06/12 22:22:44 cedric Exp $ */
+/* $OpenBSD: pfctl_table.c,v 1.62 2004/12/22 17:17:55 dhartmei Exp $ */
/*
* Copyright (c) 2002 Cedric Berger
@@ -57,7 +56,7 @@ __FBSDID("$FreeBSD$");
extern void usage(void);
static int pfctl_table(int, char *[], char *, const char *, char *,
- const char *, const char *, int);
+ const char *, int);
static void print_table(struct pfr_table *, int, int);
static void print_tstats(struct pfr_tstats *, int);
static int load_addr(struct pfr_buffer *, int, char *[], char *, int);
@@ -106,31 +105,29 @@ static const char *istats_text[2][2][2] = {
} while(0)
int
-pfctl_clear_tables(const char *anchor, const char *ruleset, int opts)
+pfctl_clear_tables(const char *anchor, int opts)
{
- return pfctl_table(0, NULL, NULL, "-F", NULL, anchor, ruleset, opts);
+ return pfctl_table(0, NULL, NULL, "-F", NULL, anchor, opts);
}
int
-pfctl_show_tables(const char *anchor, const char *ruleset, int opts)
+pfctl_show_tables(const char *anchor, int opts)
{
- return pfctl_table(0, NULL, NULL, "-s", NULL, anchor, ruleset, opts);
+ return pfctl_table(0, NULL, NULL, "-s", NULL, anchor, opts);
}
int
pfctl_command_tables(int argc, char *argv[], char *tname,
- const char *command, char *file, const char *anchor, const char *ruleset,
- int opts)
+ const char *command, char *file, const char *anchor, int opts)
{
if (tname == NULL || command == NULL)
usage();
- return pfctl_table(argc, argv, tname, command, file, anchor, ruleset,
- opts);
+ return pfctl_table(argc, argv, tname, command, file, anchor, opts);
}
int
pfctl_table(int argc, char *argv[], char *tname, const char *command,
- char *file, const char *anchor, const char *ruleset, int opts)
+ char *file, const char *anchor, int opts)
{
struct pfr_table table;
struct pfr_buffer b, b2;
@@ -155,9 +152,7 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command,
errx(1, "pfctl_table: strlcpy");
}
if (strlcpy(table.pfrt_anchor, anchor,
- sizeof(table.pfrt_anchor)) >= sizeof(table.pfrt_anchor) ||
- strlcpy(table.pfrt_ruleset, ruleset,
- sizeof(table.pfrt_ruleset)) >= sizeof(table.pfrt_ruleset))
+ sizeof(table.pfrt_anchor)) >= sizeof(table.pfrt_anchor))
errx(1, "pfctl_table: strlcpy");
if (!strcmp(command, "-F")) {
@@ -347,8 +342,6 @@ print_table(struct pfr_table *ta, int verbose, int debug)
ta->pfrt_name);
if (ta->pfrt_anchor[0])
printf("\t%s", ta->pfrt_anchor);
- if (ta->pfrt_ruleset[0])
- printf(":%s", ta->pfrt_ruleset);
puts("");
} else
puts(ta->pfrt_name);
@@ -466,16 +459,14 @@ radix_perror(void)
int
pfctl_define_table(char *name, int flags, int addrs, const char *anchor,
- const char *ruleset, struct pfr_buffer *ab, u_int32_t ticket)
+ struct pfr_buffer *ab, u_int32_t ticket)
{
struct pfr_table tbl;
bzero(&tbl, sizeof(tbl));
if (strlcpy(tbl.pfrt_name, name, sizeof(tbl.pfrt_name)) >=
sizeof(tbl.pfrt_name) || strlcpy(tbl.pfrt_anchor, anchor,
- sizeof(tbl.pfrt_anchor)) >= sizeof(tbl.pfrt_anchor) ||
- strlcpy(tbl.pfrt_ruleset, ruleset, sizeof(tbl.pfrt_ruleset)) >=
- sizeof(tbl.pfrt_ruleset))
+ sizeof(tbl.pfrt_anchor)) >= sizeof(tbl.pfrt_anchor))
errx(1, "pfctl_define_table: strlcpy");
tbl.pfrt_flags = flags;
@@ -589,7 +580,8 @@ print_iface(struct pfi_if *p, int opts)
oprintf(flags, PFI_IFLAG_GROUP, "group", &first, 0);
oprintf(flags, PFI_IFLAG_CLONABLE, "clonable", &first, 0);
oprintf(flags, PFI_IFLAG_DYNAMIC, "dynamic", &first, 0);
- oprintf(flags, PFI_IFLAG_ATTACHED, "attached", &first, 1);
+ oprintf(flags, PFI_IFLAG_ATTACHED, "attached", &first, 0);
+ oprintf(flags, PFI_IFLAG_SKIP, "skipped", &first, 1);
#ifdef __FreeBSD__
first = 1;
oprintf(flags, PFI_IFLAG_PLACEHOLDER, "placeholder", &first, 1);
OpenPOWER on IntegriCloud