summaryrefslogtreecommitdiff
path: root/sbin/pfctl
diff options
context:
space:
mode:
authorHenning Brauer <henning@cvs.openbsd.org>2009-09-01 13:42:01 +0000
committerHenning Brauer <henning@cvs.openbsd.org>2009-09-01 13:42:01 +0000
commit46b57908d298e78fe239fb227fea78ff8c2b0038 (patch)
tree86bbe48b2e41e2e866aea8515522091d4cd47368 /sbin/pfctl
parent8d04a68ef40c12c6955fb36c9e75c15dc0198c72 (diff)
the diff theo calls me insanae for:
rewrite of the NAT code, basically. nat and rdr become actions on regular rules, seperate nat/rdr/binat rules do not exist any more. match in on $intf rdr-to 1.2.3.4 match out on $intf nat-to 5.6.7.8 the code is capable of doing nat and rdr in any direction, but we prevent this in pfctl for now, there are implications that need to be documented better. the address rewrite happens inline, subsequent rules will see the already changed addresses. nat / rdr can be applied multiple times as well. match in on $intf rdr-to 1.2.3.4 match in on $intf to 1.2.3.4 rdr-to 5.6.7.8 help and ok dlg sthen claudio, reyk tested too
Diffstat (limited to 'sbin/pfctl')
-rw-r--r--sbin/pfctl/parse.y859
-rw-r--r--sbin/pfctl/pfctl.c138
-rw-r--r--sbin/pfctl/pfctl_optimize.c36
-rw-r--r--sbin/pfctl/pfctl_parser.c26
-rw-r--r--sbin/pfctl/pfctl_parser.h4
5 files changed, 278 insertions, 785 deletions
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
index 318f447380b..45a4247f323 100644
--- a/sbin/pfctl/parse.y
+++ b/sbin/pfctl/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.562 2009/07/28 13:26:52 claudio Exp $ */
+/* $OpenBSD: parse.y,v 1.563 2009/09/01 13:42:00 henning Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
@@ -202,6 +202,32 @@ struct node_qassign {
char *pqname;
};
+struct range {
+ int a;
+ int b;
+ int t;
+};
+struct redirection {
+ struct node_host *host;
+ struct range rport;
+};
+
+struct pool_opts {
+ int marker;
+#define POM_TYPE 0x01
+#define POM_STICKYADDRESS 0x02
+ u_int8_t opts;
+ int type;
+ int staticport;
+ struct pf_poolhashkey *key;
+
+} pool_opts;
+
+struct redirspec {
+ struct redirection *rdr;
+ struct pool_opts pool_opts;
+};
+
struct filter_opts {
int marker;
#define FOM_FLAGS 0x0001
@@ -240,6 +266,8 @@ struct filter_opts {
struct node_host *addr;
u_int16_t port;
} divert;
+ struct redirspec nat;
+ struct redirspec rdr;
/* scrub opts */
int nodf;
@@ -284,18 +312,6 @@ struct table_opts {
struct node_tinithead init_nodes;
} table_opts;
-struct pool_opts {
- int marker;
-#define POM_TYPE 0x01
-#define POM_STICKYADDRESS 0x02
- u_int8_t opts;
- int type;
- int staticport;
- struct pf_poolhashkey *key;
-
-} pool_opts;
-
-
struct node_hfsc_opts hfsc_opts;
struct node_state_opt *keep_state_defaults = NULL;
@@ -303,9 +319,6 @@ int disallow_table(struct node_host *, const char *);
int disallow_urpf_failed(struct node_host *, const char *);
int disallow_alias(struct node_host *, const char *);
int rule_consistent(struct pf_rule *, int);
-int filter_consistent(struct pf_rule *, int);
-int nat_consistent(struct pf_rule *);
-int rdr_consistent(struct pf_rule *);
int process_tabledef(char *, struct table_opts *);
void expand_label_str(char *, size_t, const char *, const char *);
void expand_label_if(const char *, char *, size_t, const char *);
@@ -318,11 +331,13 @@ void expand_label_nr(const char *, char *, size_t);
void expand_label(char *, size_t, const char *, u_int8_t,
struct node_host *, struct node_port *, struct node_host *,
struct node_port *, u_int8_t);
+int apply_redirspec(struct pf_pool *, struct pf_rule *,
+ struct redirspec *, int, struct node_port *);
void expand_rule(struct pf_rule *, struct node_if *,
- struct node_host *, struct node_proto *, struct node_os *,
- struct node_host *, struct node_port *, struct node_host *,
- struct node_port *, struct node_uid *, struct node_gid *,
- struct node_icmp *, const char *);
+ struct redirspec *, struct redirspec *, struct node_proto *,
+ struct node_os *, struct node_host *, struct node_port *,
+ struct node_host *, struct node_port *, struct node_uid *,
+ struct node_gid *, struct node_icmp *, const char *);
int expand_altq(struct pf_altq *, struct node_if *,
struct node_queue *, struct node_queue_bw bwspec,
struct node_queue_opt *);
@@ -365,11 +380,7 @@ typedef struct {
u_int16_t w;
u_int16_t w2;
} b;
- struct range {
- int a;
- int b;
- int t;
- } range;
+ struct range range;
struct node_if *interface;
struct node_proto *proto;
struct node_icmp *icmp;
@@ -391,10 +402,7 @@ typedef struct {
sa_family_t af;
struct pf_poolhashkey *key;
} route;
- struct redirection {
- struct node_host *host;
- struct range rport;
- } *redirection;
+ struct redirection *redirection;
struct {
int action;
struct node_state_opt *options;
@@ -436,7 +444,7 @@ int parseport(char *, struct range *r, int);
%token PASS BLOCK MATCH SCRUB RETURN IN OS OUT LOG QUICK ON FROM TO FLAGS
%token RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE
-%token ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF
+%token ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT NODF
%token MINTTL ERROR ALLOWOPTS FASTROUTE FILENAME ROUTETO DUPTO REPLYTO NO LABEL
%token NOROUTE URPFFAILED FRAGMENT USER GROUP MAXMSS MAXIMUM TTL TOS DROP TABLE
%token REASSEMBLE FRAGDROP FRAGCROP ANCHOR NATANCHOR RDRANCHOR BINATANCHOR
@@ -450,7 +458,7 @@ int parseport(char *, struct range *r, int);
%token STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE
%token MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH SLOPPY PFLOW
%token TAGGED TAG IFBOUND FLOATING STATEPOLICY STATEDEFAULTS ROUTE SETTOS
-%token DIVERTTO DIVERTREPLY
+%token DIVERTTO DIVERTREPLY NATTO RDRTO
%token <v.string> STRING
%token <v.number> NUMBER
%token <v.i> PORTBINARY
@@ -458,9 +466,9 @@ int parseport(char *, struct range *r, int);
%type <v.number> number icmptype icmp6type uid gid
%type <v.number> tos not yesno optnodf
%type <v.probability> probability
-%type <v.i> no dir af optimizer
+%type <v.i> dir af optimizer
%type <v.i> sourcetrack flush unaryop statelock
-%type <v.b> action nataction natpasslog
+%type <v.b> action
%type <v.b> flags flag blockspec
%type <v.range> portplain portstar portrange
%type <v.hashkey> hashkey
@@ -472,7 +480,7 @@ int parseport(char *, struct range *r, int);
%type <v.number> reticmpspec reticmp6spec
%type <v.fromto> fromto
%type <v.peer> ipportspec from to
-%type <v.host> ipspec toipspec xhost host dynaddr host_list
+%type <v.host> ipspec xhost host dynaddr host_list
%type <v.host> redir_host_list redirspec
%type <v.host> route_host route_host_list routespec
%type <v.os> os xos os_list
@@ -480,8 +488,8 @@ int parseport(char *, struct range *r, int);
%type <v.uid> uids uid_list uid_item
%type <v.gid> gids gid_list gid_item
%type <v.route> route
-%type <v.redirection> redirection redirpool
-%type <v.string> label stringall tag anchorname
+%type <v.redirection> redirpool
+%type <v.string> label stringall anchorname
%type <v.string> string varstring numberstring
%type <v.keep_state> keep
%type <v.state_opt> state_opt_spec state_opt_list state_opt_item
@@ -500,16 +508,12 @@ int parseport(char *, struct range *r, int);
%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
-%type <v.rtableid> rtable
%%
ruleset : /* empty */
| ruleset include '\n'
| ruleset '\n'
| ruleset option '\n'
- | ruleset natrule '\n'
- | ruleset binatrule '\n'
| ruleset pfrule '\n'
| ruleset anchorrule '\n'
| ruleset loadrule '\n'
@@ -543,8 +547,6 @@ include : INCLUDE STRING {
*/
fakeanchor : fakeanchor '\n'
| fakeanchor anchorrule '\n'
- | fakeanchor binatrule '\n'
- | fakeanchor natrule '\n'
| fakeanchor pfrule '\n'
| fakeanchor error '\n'
;
@@ -892,111 +894,13 @@ anchorrule : ANCHOR anchorname dir quick interface af proto fromto
decide_address_family($8.src.host, &r.af);
decide_address_family($8.dst.host, &r.af);
- expand_rule(&r, $5, NULL, $7, $8.src_os,
+ expand_rule(&r, $5, NULL, NULL, $7, $8.src_os,
$8.src.host, $8.src.port, $8.dst.host, $8.dst.port,
$9.uid, $9.gid, $9.icmpspec,
pf->astack[pf->asd + 1] ? pf->alast->name : $2);
free($2);
pf->astack[pf->asd + 1] = NULL;
}
- | NATANCHOR string interface af proto fromto rtable {
- struct pf_rule r;
-
- if (check_rulestate(PFCTL_STATE_NAT)) {
- free($2);
- YYERROR;
- }
-
- memset(&r, 0, sizeof(r));
- r.action = PF_NAT;
- r.af = $4;
- r.rtableid = $7;
-
- decide_address_family($6.src.host, &r.af);
- decide_address_family($6.dst.host, &r.af);
-
- expand_rule(&r, $3, NULL, $5, $6.src_os,
- $6.src.host, $6.src.port, $6.dst.host, $6.dst.port,
- 0, 0, 0, $2);
- free($2);
- }
- | RDRANCHOR string interface af proto fromto rtable {
- struct pf_rule r;
-
- if (check_rulestate(PFCTL_STATE_NAT)) {
- free($2);
- YYERROR;
- }
-
- memset(&r, 0, sizeof(r));
- r.action = PF_RDR;
- r.af = $4;
- r.rtableid = $7;
-
- decide_address_family($6.src.host, &r.af);
- decide_address_family($6.dst.host, &r.af);
-
- if ($6.src.port != NULL) {
- yyerror("source port parameter not supported"
- " in rdr-anchor");
- YYERROR;
- }
- if ($6.dst.port != NULL) {
- if ($6.dst.port->next != NULL) {
- yyerror("destination port list "
- "expansion not supported in "
- "rdr-anchor");
- YYERROR;
- } else if ($6.dst.port->op != PF_OP_EQ) {
- yyerror("destination port operators"
- " not supported in rdr-anchor");
- YYERROR;
- }
- r.dst.port[0] = $6.dst.port->port[0];
- r.dst.port[1] = $6.dst.port->port[1];
- r.dst.port_op = $6.dst.port->op;
- }
-
- expand_rule(&r, $3, NULL, $5, $6.src_os,
- $6.src.host, $6.src.port, $6.dst.host, $6.dst.port,
- 0, 0, 0, $2);
- free($2);
- }
- | BINATANCHOR string interface af proto fromto rtable {
- struct pf_rule r;
-
- if (check_rulestate(PFCTL_STATE_NAT)) {
- free($2);
- YYERROR;
- }
-
- memset(&r, 0, sizeof(r));
- r.action = PF_BINAT;
- r.af = $4;
- r.rtableid = $7;
- if ($5 != NULL) {
- if ($5->next != NULL) {
- yyerror("proto list expansion"
- " not supported in binat-anchor");
- YYERROR;
- }
- r.proto = $5->proto;
- free($5);
- }
-
- if ($6.src.host != NULL || $6.src.port != NULL ||
- $6.dst.host != NULL || $6.dst.port != NULL) {
- yyerror("fromto parameter not supported"
- " in binat-anchor");
- YYERROR;
- }
-
- decide_address_family($6.src.host, &r.af);
- decide_address_family($6.dst.host, &r.af);
-
- pfctl_add_rule(pf, &r, $2);
- free($2);
- }
;
loadrule : LOAD ANCHOR string FROM string {
@@ -1159,9 +1063,9 @@ antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts {
}
if (h != NULL)
- expand_rule(&r, j, NULL, NULL, NULL, h,
- NULL, NULL, NULL, NULL, NULL,
- NULL, "");
+ expand_rule(&r, j, NULL, NULL, NULL,
+ NULL, h, NULL, NULL, NULL, NULL,
+ NULL, NULL, "");
if ((i->ifa_flags & IFF_LOOPBACK) == 0) {
bzero(&r, sizeof(r));
@@ -1181,8 +1085,9 @@ antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts {
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, h, NULL,
+ NULL, NULL, NULL, NULL,
+ NULL, "");
} else
free(hh);
}
@@ -2094,9 +1999,9 @@ pfrule : action dir logquick interface route af proto fromto
YYERROR;
}
r.rt = $5.rt;
- r.rpool.opts = $5.pool_opts;
+ r.rdr.opts = $5.pool_opts;
if ($5.key != NULL)
- memcpy(&r.rpool.key, $5.key,
+ memcpy(&r.rdr.key, $5.key,
sizeof(struct pf_poolhashkey));
}
if (r.rt && r.rt != PF_FASTROUTE) {
@@ -2107,30 +2012,35 @@ pfrule : action dir logquick interface route af proto fromto
"matching address family found.");
YYERROR;
}
- if ((r.rpool.opts & PF_POOL_TYPEMASK) ==
+ if ((r.rdr.opts & PF_POOL_TYPEMASK) ==
PF_POOL_NONE && ($5.host->next != NULL ||
$5.host->addr.type == PF_ADDR_TABLE ||
DYNIF_MULTIADDR($5.host->addr)))
- r.rpool.opts |= PF_POOL_ROUNDROBIN;
- if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
+ r.rdr.opts |= PF_POOL_ROUNDROBIN;
+ if ((r.rdr.opts & PF_POOL_TYPEMASK) !=
PF_POOL_ROUNDROBIN &&
disallow_table($5.host, "tables are only "
"supported in round-robin routing pools"))
YYERROR;
- if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
+ if ((r.rdr.opts & PF_POOL_TYPEMASK) !=
PF_POOL_ROUNDROBIN &&
disallow_alias($5.host, "interface (%s) "
"is only supported in round-robin "
"routing pools"))
YYERROR;
if ($5.host->next != NULL) {
- if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
+ if ((r.rdr.opts & PF_POOL_TYPEMASK) !=
PF_POOL_ROUNDROBIN) {
yyerror("r.rpool.opts must "
"be PF_POOL_ROUNDROBIN");
YYERROR;
}
}
+ /* fake redirspec */
+ if (($9.rdr.rdr = calloc(1,
+ sizeof(*$9.rdr.rdr))) == NULL)
+ err(1, "$9.rdr.rdr");
+ $9.rdr.rdr->host = $5.host;
}
if ($9.queues.qname != NULL) {
if (strlcpy(r.qname, $9.queues.qname,
@@ -2175,7 +2085,7 @@ pfrule : action dir logquick interface route af proto fromto
}
}
- expand_rule(&r, $4, $5.host, $7, $8.src_os,
+ expand_rule(&r, $4, &$9.nat, &$9.rdr, $7, $8.src_os,
$8.src.host, $8.src.port, $8.dst.host, $8.dst.port,
$9.uid, $9.gid, $9.icmpspec, "");
}
@@ -2317,6 +2227,24 @@ filter_opt : USER uids {
filter_opts.marker |= FOM_SCRUB_TCP;
filter_opts.marker |= $3.marker;
}
+ | NATTO redirpool pool_opts {
+ if (filter_opts.nat.rdr) {
+ yyerror("cannot respecify nat-to");
+ YYERROR;
+ }
+ filter_opts.nat.rdr = $2;
+ memcpy(&filter_opts.nat.pool_opts, &$3,
+ sizeof(filter_opts.nat.pool_opts));
+ }
+ | RDRTO redirpool pool_opts {
+ if (filter_opts.rdr.rdr) {
+ yyerror("cannot respecify rdr-to");
+ YYERROR;
+ }
+ filter_opts.rdr.rdr = $2;
+ memcpy(&filter_opts.rdr.pool_opts, &$3,
+ sizeof(filter_opts.rdr.pool_opts));
+ }
;
probability : STRING {
@@ -2671,10 +2599,6 @@ ipspec : ANY { $$ = NULL; }
| '{' optnl host_list '}' { $$ = $3; }
;
-toipspec : TO ipspec { $$ = $2; }
- | /* empty */ { $$ = NULL; }
- ;
-
host_list : ipspec optnl { $$ = $1; }
| host_list comma ipspec optnl {
if ($3 == NULL)
@@ -3561,10 +3485,6 @@ qname : QUEUE STRING {
}
;
-no : /* empty */ { $$ = 0; }
- | NO { $$ = 1; }
- ;
-
portstar : numberstring {
if (parseport($1, &$$, PPORT_RANGE|PPORT_STAR) == -1) {
free($1);
@@ -3586,20 +3506,19 @@ redir_host_list : host optnl { $$ = $1; }
}
;
-redirpool : /* empty */ { $$ = NULL; }
- | ARROW redirspec {
+redirpool : redirspec {
$$ = calloc(1, sizeof(struct redirection));
if ($$ == NULL)
err(1, "redirection: calloc");
- $$->host = $2;
+ $$->host = $1;
$$->rport.a = $$->rport.b = $$->rport.t = 0;
}
- | ARROW redirspec PORT portstar {
+ | redirspec PORT portstar {
$$ = calloc(1, sizeof(struct redirection));
if ($$ == NULL)
err(1, "redirection: calloc");
- $$->host = $2;
- $$->rport = $4;
+ $$->host = $1;
+ $$->rport = $3;
}
;
@@ -3712,401 +3631,6 @@ pool_opt : BITMASK {
}
;
-redirection : /* empty */ { $$ = NULL; }
- | ARROW host {
- $$ = calloc(1, sizeof(struct redirection));
- if ($$ == NULL)
- err(1, "redirection: calloc");
- $$->host = $2;
- $$->rport.a = $$->rport.b = $$->rport.t = 0;
- }
- | ARROW host PORT portstar {
- $$ = calloc(1, sizeof(struct redirection));
- if ($$ == NULL)
- err(1, "redirection: calloc");
- $$->host = $2;
- $$->rport = $4;
- }
- ;
-
-natpasslog : /* empty */ { $$.b1 = $$.b2 = 0; $$.w2 = 0; }
- | PASS { $$.b1 = 1; $$.b2 = 0; $$.w2 = 0; }
- | PASS log { $$.b1 = 1; $$.b2 = $2.log; $$.w2 = $2.logif; }
- | log { $$.b1 = 0; $$.b2 = $1.log; $$.w2 = $1.logif; }
- ;
-
-nataction : no NAT natpasslog {
- if ($1 && $3.b1) {
- yyerror("\"pass\" not valid with \"no\"");
- YYERROR;
- }
- if ($1)
- $$.b1 = PF_NONAT;
- else
- $$.b1 = PF_NAT;
- $$.b2 = $3.b1;
- $$.w = $3.b2;
- $$.w2 = $3.w2;
- }
- | no RDR natpasslog {
- if ($1 && $3.b1) {
- yyerror("\"pass\" not valid with \"no\"");
- YYERROR;
- }
- if ($1)
- $$.b1 = PF_NORDR;
- else
- $$.b1 = PF_RDR;
- $$.b2 = $3.b1;
- $$.w = $3.b2;
- $$.w2 = $3.w2;
- }
- ;
-
-natrule : nataction interface af proto fromto tag tagged rtable
- redirpool pool_opts
- {
- struct pf_rule r;
-
- if (check_rulestate(PFCTL_STATE_NAT))
- YYERROR;
-
- memset(&r, 0, sizeof(r));
-
- r.action = $1.b1;
- r.natpass = $1.b2;
- r.log = $1.w;
- r.logif = $1.w2;
- r.af = $3;
-
- if (!r.af) {
- if ($5.src.host && $5.src.host->af &&
- !$5.src.host->ifindex)
- r.af = $5.src.host->af;
- else if ($5.dst.host && $5.dst.host->af &&
- !$5.dst.host->ifindex)
- r.af = $5.dst.host->af;
- }
-
- if ($6 != NULL)
- if (strlcpy(r.tagname, $6, PF_TAG_NAME_SIZE) >=
- PF_TAG_NAME_SIZE) {
- yyerror("tag too long, max %u chars",
- PF_TAG_NAME_SIZE - 1);
- 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;
- r.rtableid = $8;
-
- if (r.action == PF_NONAT || r.action == PF_NORDR) {
- if ($9 != NULL) {
- yyerror("translation rule with 'no' "
- "does not need '->'");
- YYERROR;
- }
- } else {
- if ($9 == NULL || $9->host == NULL) {
- yyerror("translation rule requires '-> "
- "address'");
- YYERROR;
- }
- if (!r.af && ! $9->host->ifindex)
- r.af = $9->host->af;
-
- remove_invalid_hosts(&$9->host, &r.af);
- if (invalid_redirect($9->host, r.af))
- YYERROR;
- if (check_netmask($9->host, r.af))
- YYERROR;
-
- r.rpool.proxy_port[0] = ntohs($9->rport.a);
-
- switch (r.action) {
- case PF_RDR:
- if (!$9->rport.b && $9->rport.t &&
- $5.dst.port != NULL) {
- r.rpool.proxy_port[1] =
- ntohs($9->rport.a) +
- (ntohs(
- $5.dst.port->port[1]) -
- ntohs(
- $5.dst.port->port[0]));
- } else
- r.rpool.proxy_port[1] =
- ntohs($9->rport.b);
- break;
- case PF_NAT:
- r.rpool.proxy_port[1] =
- ntohs($9->rport.b);
- if (!r.rpool.proxy_port[0] &&
- !r.rpool.proxy_port[1]) {
- r.rpool.proxy_port[0] =
- PF_NAT_PROXY_PORT_LOW;
- r.rpool.proxy_port[1] =
- PF_NAT_PROXY_PORT_HIGH;
- } else if (!r.rpool.proxy_port[1])
- r.rpool.proxy_port[1] =
- r.rpool.proxy_port[0];
- break;
- default:
- break;
- }
-
- r.rpool.opts = $10.type;
- if ((r.rpool.opts & PF_POOL_TYPEMASK) ==
- PF_POOL_NONE && ($9->host->next != NULL ||
- $9->host->addr.type == PF_ADDR_TABLE ||
- DYNIF_MULTIADDR($9->host->addr)))
- r.rpool.opts = PF_POOL_ROUNDROBIN;
- if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
- PF_POOL_ROUNDROBIN &&
- disallow_table($9->host, "tables are only "
- "supported in round-robin redirection "
- "pools"))
- YYERROR;
- if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
- PF_POOL_ROUNDROBIN &&
- disallow_alias($9->host, "interface (%s) "
- "is only supported in round-robin "
- "redirection pools"))
- YYERROR;
- if ($9->host->next != NULL) {
- if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
- PF_POOL_ROUNDROBIN) {
- yyerror("only round-robin "
- "valid for multiple "
- "redirection addresses");
- YYERROR;
- }
- }
- }
-
- if ($10.key != NULL)
- memcpy(&r.rpool.key, $10.key,
- sizeof(struct pf_poolhashkey));
-
- if ($10.opts)
- r.rpool.opts |= $10.opts;
-
- if ($10.staticport) {
- if (r.action != PF_NAT) {
- yyerror("the 'static-port' option is "
- "only valid with nat rules");
- YYERROR;
- }
- if (r.rpool.proxy_port[0] !=
- PF_NAT_PROXY_PORT_LOW &&
- r.rpool.proxy_port[1] !=
- PF_NAT_PROXY_PORT_HIGH) {
- yyerror("the 'static-port' option can't"
- " be used when specifying a port"
- " range");
- YYERROR;
- }
- r.rpool.proxy_port[0] = 0;
- r.rpool.proxy_port[1] = 0;
- }
-
- expand_rule(&r, $2, $9 == NULL ? NULL : $9->host, $4,
- $5.src_os, $5.src.host, $5.src.port, $5.dst.host,
- $5.dst.port, 0, 0, 0, "");
- free($9);
- }
- ;
-
-binatrule : no BINAT natpasslog interface af proto FROM host toipspec tag
- tagged rtable redirection
- {
- struct pf_rule binat;
- struct pf_pooladdr *pa;
-
- if (check_rulestate(PFCTL_STATE_NAT))
- YYERROR;
- if (disallow_urpf_failed($9, "\"urpf-failed\" is not "
- "permitted as a binat destination"))
- YYERROR;
-
- memset(&binat, 0, sizeof(binat));
-
- if ($1 && $3.b1) {
- yyerror("\"pass\" not valid with \"no\"");
- YYERROR;
- }
- if ($1)
- binat.action = PF_NOBINAT;
- else
- binat.action = PF_BINAT;
- binat.natpass = $3.b1;
- binat.log = $3.b2;
- binat.logif = $3.w2;
- binat.af = $5;
- if (!binat.af && $8 != NULL && $8->af)
- binat.af = $8->af;
- if (!binat.af && $9 != NULL && $9->af)
- binat.af = $9->af;
-
- if (!binat.af && $13 != NULL && $13->host)
- binat.af = $13->host->af;
- if (!binat.af) {
- yyerror("address family (inet/inet6) "
- "undefined");
- YYERROR;
- }
-
- if ($4 != NULL) {
- memcpy(binat.ifname, $4->ifname,
- sizeof(binat.ifname));
- binat.ifnot = $4->not;
- free($4);
- }
-
- if ($10 != NULL)
- if (strlcpy(binat.tagname, $10,
- PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
- yyerror("tag too long, max %u chars",
- PF_TAG_NAME_SIZE - 1);
- YYERROR;
- }
- if ($11.name)
- if (strlcpy(binat.match_tagname, $11.name,
- PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
- yyerror("tag too long, max %u chars",
- PF_TAG_NAME_SIZE - 1);
- YYERROR;
- }
- binat.match_tag_not = $11.neg;
- binat.rtableid = $12;
-
- if ($6 != NULL) {
- binat.proto = $6->proto;
- free($6);
- }
-
- if ($8 != NULL && disallow_table($8, "invalid use of "
- "table <%s> as the source address of a binat rule"))
- YYERROR;
- if ($8 != NULL && disallow_alias($8, "invalid use of "
- "interface (%s) as the source address of a binat "
- "rule"))
- YYERROR;
- 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 ($13 != NULL && $13->host != NULL && disallow_alias(
- $13->host, "invalid use of interface (%s) as the "
- "redirect address of a binat rule"))
- YYERROR;
-
- if ($8 != NULL) {
- if ($8->next) {
- yyerror("multiple binat ip addresses");
- YYERROR;
- }
- if ($8->addr.type == PF_ADDR_DYNIFTL)
- $8->af = binat.af;
- if ($8->af != binat.af) {
- yyerror("binat ip versions must match");
- YYERROR;
- }
- if (check_netmask($8, binat.af))
- YYERROR;
- memcpy(&binat.src.addr, &$8->addr,
- sizeof(binat.src.addr));
- free($8);
- }
- if ($9 != NULL) {
- if ($9->next) {
- yyerror("multiple binat ip addresses");
- YYERROR;
- }
- if ($9->af != binat.af && $9->af) {
- yyerror("binat ip versions must match");
- YYERROR;
- }
- if (check_netmask($9, binat.af))
- YYERROR;
- memcpy(&binat.dst.addr, &$9->addr,
- sizeof(binat.dst.addr));
- binat.dst.neg = $9->not;
- free($9);
- }
-
- if (binat.action == PF_NOBINAT) {
- if ($13 != NULL) {
- yyerror("'no binat' rule does not need"
- " '->'");
- YYERROR;
- }
- } else {
- if ($13 == NULL || $13->host == NULL) {
- yyerror("'binat' rule requires"
- " '-> address'");
- YYERROR;
- }
-
- remove_invalid_hosts(&$13->host, &binat.af);
- if (invalid_redirect($13->host, binat.af))
- YYERROR;
- if ($13->host->next != NULL) {
- yyerror("binat rule must redirect to "
- "a single address");
- YYERROR;
- }
- 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,
- &$13->host->addr.v.a.mask, binat.af)) {
- yyerror("'binat' source mask and "
- "redirect mask must be the same");
- YYERROR;
- }
-
- TAILQ_INIT(&binat.rpool.list);
- pa = calloc(1, sizeof(struct pf_pooladdr));
- if (pa == NULL)
- err(1, "binat: calloc");
- pa->addr = $13->host->addr;
- pa->ifname[0] = 0;
- TAILQ_INSERT_TAIL(&binat.rpool.list,
- pa, entries);
-
- free($13);
- }
-
- pfctl_add_rule(pf, &binat, "");
- }
- ;
-
-tag : /* empty */ { $$ = NULL; }
- | TAG STRING { $$ = $2; }
- ;
-
-tagged : /* empty */ { $$.neg = 0; $$.name = NULL; }
- | not TAGGED string { $$.neg = $1; $$.name = $3; }
- ;
-
-rtable : /* empty */ { $$ = -1; }
- | RTABLE NUMBER {
- if ($2 < 0 || $2 > RT_TABLEID_MAX) {
- yyerror("invalid rtable id");
- YYERROR;
- }
- $$ = $2;
- }
- ;
-
route_host : STRING {
$$ = calloc(1, sizeof(struct node_host));
if ($$ == NULL)
@@ -4300,33 +3824,6 @@ rule_consistent(struct pf_rule *r, int anchor_call)
{
int problems = 0;
- switch (r->action) {
- case PF_PASS:
- case PF_MATCH:
- case PF_DROP:
- problems = filter_consistent(r, anchor_call);
- break;
- case PF_NAT:
- case PF_NONAT:
- problems = nat_consistent(r);
- break;
- case PF_RDR:
- case PF_NORDR:
- problems = rdr_consistent(r);
- break;
- case PF_BINAT:
- case PF_NOBINAT:
- default:
- break;
- }
- return (problems);
-}
-
-int
-filter_consistent(struct pf_rule *r, int anchor_call)
-{
- int problems = 0;
-
if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP &&
(r->src.port_op || r->dst.port_op)) {
yyerror("port only applies to tcp/udp");
@@ -4382,6 +3879,20 @@ filter_consistent(struct pf_rule *r, int anchor_call)
"synproxy state or modulate state");
problems++;
}
+ if ((!TAILQ_EMPTY(&r->nat.list) || !TAILQ_EMPTY(&r->rdr.list)) &&
+ r->action != PF_MATCH && !r->keep_state) {
+ yyerror("nat-to and rdr-to require keep state");
+ problems++;
+ }
+ if (!TAILQ_EMPTY(&r->nat.list) && r->direction != PF_OUT) {
+ yyerror("nat-to can only be used outbound");
+ problems++;
+ }
+ if (!TAILQ_EMPTY(&r->rdr.list) && r->direction != PF_IN) {
+ yyerror("rdr-to can only be used inbound");
+ problems++;
+ }
+
/* match rules rules */
if (r->action == PF_MATCH) {
if (r->divert.port) {
@@ -4398,39 +3909,6 @@ filter_consistent(struct pf_rule *r, int anchor_call)
}
int
-nat_consistent(struct pf_rule *r)
-{
- return (0); /* yeah! */
-}
-
-int
-rdr_consistent(struct pf_rule *r)
-{
- int problems = 0;
-
- if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP) {
- if (r->src.port_op) {
- yyerror("src port only applies to tcp/udp");
- problems++;
- }
- if (r->dst.port_op) {
- yyerror("dst port only applies to tcp/udp");
- problems++;
- }
- if (r->rpool.proxy_port[0]) {
- yyerror("rpool port only applies to tcp/udp");
- problems++;
- }
- }
- if (r->dst.port_op &&
- r->dst.port_op != PF_OP_EQ && r->dst.port_op != PF_OP_RRG) {
- yyerror("invalid port operator for rdr destination port");
- problems++;
- }
- return (-problems);
-}
-
-int
process_tabledef(char *name, struct table_opts *opts)
{
struct pfr_buffer ab;
@@ -4924,9 +4402,108 @@ expand_queue(struct pf_altq *a, struct node_if *interfaces,
return (0);
}
+int
+apply_redirspec(struct pf_pool *rpool, struct pf_rule *r, struct redirspec *rs,
+ int isrdr, struct node_port *np)
+{
+ struct node_host *h;
+ struct pf_pooladdr *pa;
+
+ if (!rs || !rs->rdr)
+ return (0);
+
+ if (!r->af && ! rs->rdr->host->ifindex)
+ r->af = rs->rdr->host->af;
+
+ remove_invalid_hosts(&rs->rdr->host, &r->af);
+ if (invalid_redirect(rs->rdr->host, r->af))
+ return (1);
+ if (check_netmask(rs->rdr->host, r->af))
+ return (1);
+
+ rpool->proxy_port[0] = ntohs(rs->rdr->rport.a);
+
+ if (isrdr) {
+ if (!rs->rdr->rport.b && rs->rdr->rport.t && np->port != NULL) {
+ rpool->proxy_port[1] = ntohs(rs->rdr->rport.a) +
+ (ntohs(np->port[1]) - ntohs(np->port[0]));
+ } else
+ rpool->proxy_port[1] = ntohs(rs->rdr->rport.b);
+ } else {
+ rpool->proxy_port[1] = ntohs(rs->rdr->rport.b);
+ if (!rpool->proxy_port[0] && !rpool->proxy_port[1]) {
+ rpool->proxy_port[0] = PF_NAT_PROXY_PORT_LOW;
+ rpool->proxy_port[1] = PF_NAT_PROXY_PORT_HIGH;
+ } else if (!rpool->proxy_port[1])
+ rpool->proxy_port[1] = rpool->proxy_port[0];
+ }
+
+ rpool->opts = rs->pool_opts.type;
+ if ((rpool->opts & PF_POOL_TYPEMASK) == PF_POOL_NONE &&
+ (rs->rdr->host->next != NULL ||
+ rs->rdr->host->addr.type == PF_ADDR_TABLE ||
+ DYNIF_MULTIADDR(rs->rdr->host->addr)))
+ rpool->opts = PF_POOL_ROUNDROBIN;
+ if ((rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN &&
+ disallow_table(rs->rdr->host, "tables are only supported in "
+ "round-robin redirection pools"))
+ return (1);
+ if ((rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN &&
+ disallow_alias(rs->rdr->host, "interface (%s) is only supported in "
+ "round-robin redirection pools"))
+ return (1);
+ if (rs->rdr->host->next != NULL) {
+ if ((rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN) {
+ yyerror("only round-robin valid for multiple "
+ "redirection addresses");
+ return (1);
+ }
+ }
+
+ if (rs->pool_opts.key != NULL)
+ memcpy(&rpool->key, rs->pool_opts.key,
+ sizeof(struct pf_poolhashkey));
+
+ if (rs->pool_opts.opts)
+ rpool->opts |= rs->pool_opts.opts;
+
+ if (rs->pool_opts.staticport) {
+ if (isrdr) {
+ yyerror("the 'static-port' option is only valid with "
+ "nat rules");
+ return (1);
+ }
+ if (rpool->proxy_port[0] != PF_NAT_PROXY_PORT_LOW &&
+ rpool->proxy_port[1] != PF_NAT_PROXY_PORT_HIGH) {
+ yyerror("the 'static-port' option can't be used when "
+ "specifying a port range");
+ return (1);
+ }
+ rpool->proxy_port[0] = 0;
+ rpool->proxy_port[1] = 0;
+ }
+
+ TAILQ_INIT(&rpool->list);
+ for (h = rs->rdr->host; h != NULL; h = h->next) {
+ if ((pa = calloc(1, sizeof(struct pf_pooladdr))) == NULL)
+ err(1, "expand_rule: calloc");
+ pa->addr = h->addr;
+ if (h->ifname != NULL) {
+ if (strlcpy(pa->ifname, h->ifname, sizeof pa->ifname) >=
+ sizeof(pa->ifname))
+ errx(1, "expand_rule: strlcpy");
+ } else
+ pa->ifname[0] = 0;
+ TAILQ_INSERT_TAIL(&rpool->list, pa, entries);
+ }
+
+ return (0);
+}
+
+
void
-expand_rule(struct pf_rule *r,
- struct node_if *interfaces, struct node_host *rpool_hosts,
+expand_rule(struct pf_rule *r, struct node_if *interfaces,
+ struct redirspec *nat, struct redirspec *rdr,
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,
@@ -4939,8 +4516,6 @@ expand_rule(struct pf_rule *r,
char label[PF_RULE_LABEL_SIZE];
char tagname[PF_TAG_NAME_SIZE];
char match_tagname[PF_TAG_NAME_SIZE];
- struct pf_pooladdr *pa;
- struct node_host *h;
u_int8_t flags, flagset, keep_state;
if (strlcpy(label, r->label, sizeof(label)) >= sizeof(label))
@@ -5064,21 +4639,8 @@ expand_rule(struct pf_rule *r,
r->os_fingerprint = PF_OSFP_ANY;
}
- TAILQ_INIT(&r->rpool.list);
- for (h = rpool_hosts; h != NULL; h = h->next) {
- pa = calloc(1, sizeof(struct pf_pooladdr));
- if (pa == NULL)
- err(1, "expand_rule: calloc");
- pa->addr = h->addr;
- if (h->ifname != NULL) {
- if (strlcpy(pa->ifname, h->ifname,
- sizeof(pa->ifname)) >=
- sizeof(pa->ifname))
- errx(1, "expand_rule: strlcpy");
- } else
- pa->ifname[0] = 0;
- TAILQ_INSERT_TAIL(&r->rpool.list, pa, entries);
- }
+ error += apply_redirspec(&r->nat, r, nat, 0, dst_port);
+ error += apply_redirspec(&r->rdr, r, rdr, 1, dst_port);
if (rule_consistent(r, anchor_call[0]) < 0 || error)
yyerror("skipping rule due to errors");
@@ -5100,7 +4662,10 @@ expand_rule(struct pf_rule *r,
FREE_LIST(struct node_uid, uids);
FREE_LIST(struct node_gid, gids);
FREE_LIST(struct node_icmp, icmp_types);
- FREE_LIST(struct node_host, rpool_hosts);
+ if (nat && nat->rdr)
+ FREE_LIST(struct node_host, nat->rdr->host);
+ if (rdr && rdr->rdr)
+ FREE_LIST(struct node_host, rdr->rdr->host);
if (!added)
yyerror("rule expands to no valid combination");
@@ -5227,6 +4792,7 @@ lookup(char *s)
{ "modulate", MODULATE},
{ "nat", NAT},
{ "nat-anchor", NATANCHOR},
+ { "nat-to", NATTO},
{ "no", NO},
{ "no-df", NODF},
{ "no-route", NOROUTE},
@@ -5250,6 +4816,7 @@ lookup(char *s)
{ "random-id", RANDOMID},
{ "rdr", RDR},
{ "rdr-anchor", RDRANCHOR},
+ { "rdr-to", RDRTO},
{ "realtime", REALTIME},
{ "reassemble", REASSEMBLE},
{ "reply-to", REPLYTO},
@@ -5491,12 +5058,6 @@ top:
}
lungetc(next);
break;
- case '-':
- next = lgetc(0);
- if (next == '>')
- return (ARROW);
- lungetc(next);
- break;
}
#define allowed_to_end_number(x) \
diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
index ef0d04a2f4b..984f29c0806 100644
--- a/sbin/pfctl/pfctl.c
+++ b/sbin/pfctl/pfctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl.c,v 1.284 2009/08/21 05:27:57 ratchov Exp $ */
+/* $OpenBSD: pfctl.c,v 1.285 2009/09/01 13:42:00 henning Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -62,7 +62,6 @@ int pfctl_disable(int, int);
int pfctl_clear_stats(int, int);
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);
@@ -80,10 +79,9 @@ int pfctl_load_logif(struct pfctl *, char *);
int pfctl_load_hostid(struct pfctl *, unsigned int);
int pfctl_load_reassembly(struct pfctl *, u_int32_t);
int pfctl_get_pool(int, struct pf_pool *, u_int32_t, u_int32_t, int,
- char *);
+ char *, int);
void pfctl_print_rule_counters(struct pf_rule *, int);
int pfctl_show_rules(int, char *, int, enum pfctl_show, char *, int);
-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);
@@ -201,12 +199,12 @@ static const struct {
};
static const char *clearopt_list[] = {
- "nat", "queue", "rules", "Sources",
+ "queue", "rules", "Sources",
"states", "info", "Tables", "osfp", "all", NULL
};
static const char *showopt_list[] = {
- "nat", "queue", "rules", "Anchors", "Sources", "states", "info",
+ "queue", "rules", "Anchors", "Sources", "states", "info",
"Interfaces", "labels", "timeouts", "memory", "Tables", "osfp",
"all", NULL
};
@@ -321,24 +319,6 @@ pfctl_clear_rules(int dev, int opts, char *anchorname)
}
int
-pfctl_clear_nat(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_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");
- if ((opts & PF_OPT_QUIET) == 0)
- fprintf(stderr, "nat cleared\n");
- return (0);
-}
-
-int
pfctl_clear_altq(int dev, int opts)
{
struct pfr_buffer t;
@@ -706,7 +686,7 @@ pfctl_id_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)
+ u_int32_t ticket, int r_action, char *anchorname, int which)
{
struct pfioc_pooladdr pp;
struct pf_pooladdr *pa;
@@ -717,6 +697,7 @@ pfctl_get_pool(int dev, struct pf_pool *pool, u_int32_t nr,
pp.r_action = r_action;
pp.r_num = nr;
pp.ticket = ticket;
+ pp.which = which;
if (ioctl(dev, DIOCGETADDRS, &pp)) {
warn("DIOCGETADDRS");
return (-1);
@@ -857,8 +838,11 @@ pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format,
goto error;
}
- if (pfctl_get_pool(dev, &pr.rule.rpool,
- nr, pr.ticket, PF_PASS, path) != 0)
+ if (pfctl_get_pool(dev, &pr.rule.rdr,
+ nr, pr.ticket, PF_PASS, path, PF_RDR) != 0)
+ goto error;
+ if (pfctl_get_pool(dev, &pr.rule.nat,
+ nr, pr.ticket, PF_PASS, path, PF_NAT) != 0)
goto error;
switch (format) {
@@ -913,7 +897,8 @@ pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format,
case PFCTL_SHOW_NOTHING:
break;
}
- pfctl_clear_pool(&pr.rule.rpool);
+ pfctl_clear_pool(&pr.rule.rdr);
+ pfctl_clear_pool(&pr.rule.nat);
}
path[len] = '\0';
return (0);
@@ -924,46 +909,6 @@ pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format,
}
int
-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;
-
- memset(&pr, 0, sizeof(pr));
- memcpy(pr.anchor, anchorname, sizeof(pr.anchor));
- for (i = 0; i < 3; i++) {
- pr.rule.action = nattype[i];
- if (ioctl(dev, DIOCGETRULES, &pr)) {
- warn("DIOCGETRULES");
- return (-1);
- }
- mnr = pr.nr;
- for (nr = 0; nr < mnr; ++nr) {
- pr.nr = nr;
- if (ioctl(dev, DIOCGETRULE, &pr)) {
- warn("DIOCGETRULE");
- return (-1);
- }
- if (pfctl_get_pool(dev, &pr.rule.rpool, nr,
- pr.ticket, nattype[i], anchorname) != 0)
- return (-1);
- if (dotitle) {
- pfctl_print_title("TRANSLATION RULES:");
- dotitle = 0;
- }
- print_rule(&pr.rule, pr.anchor_call,
- opts & PF_OPT_VERBOSE2);
- printf("\n");
- pfctl_print_rule_counters(&pr.rule, opts);
- pfctl_clear_pool(&pr.rule.rpool);
- }
- }
- return (0);
-}
-
-int
pfctl_show_src_nodes(int dev, int opts)
{
struct pfioc_src_nodes psn;
@@ -1120,22 +1065,16 @@ pfctl_show_limits(int dev, int opts)
/* callbacks for rule/nat/rdr/addr */
int
-pfctl_add_pool(struct pfctl *pf, struct pf_pool *p, sa_family_t af)
+pfctl_add_pool(struct pfctl *pf, struct pf_pool *p, sa_family_t af, int which)
{
struct pf_pooladdr *pa;
- if ((pf->opts & PF_OPT_NOACTION) == 0) {
- if (ioctl(pf->dev, DIOCBEGINADDRS, &pf->paddr))
- err(1, "DIOCBEGINADDRS");
- }
-
pf->paddr.af = af;
TAILQ_FOREACH(pa, &p->list, entries) {
+ pf->paddr.which = which;
memcpy(&pf->paddr.addr, pa, sizeof(struct pf_pooladdr));
- if ((pf->opts & PF_OPT_NOACTION) == 0) {
- if (ioctl(pf->dev, DIOCADDADDR, &pf->paddr))
- err(1, "DIOCADDADDR");
- }
+ if (ioctl(pf->dev, DIOCADDADDR, &pf->paddr))
+ err(1, "DIOCADDADDR");
}
return (0);
}
@@ -1181,8 +1120,10 @@ pfctl_add_rule(struct pfctl *pf, struct pf_rule *r, const char *anchor_call)
if ((rule = calloc(1, sizeof(*rule))) == NULL)
err(1, "calloc");
bcopy(r, rule, sizeof(*rule));
- TAILQ_INIT(&rule->rpool.list);
- pfctl_move_pool(&r->rpool, &rule->rpool);
+ TAILQ_INIT(&rule->rdr.list);
+ pfctl_move_pool(&r->rdr, &rule->rdr);
+ TAILQ_INIT(&rule->nat.list);
+ pfctl_move_pool(&r->nat, &rule->nat);
TAILQ_INSERT_TAIL(rs->rules[rs_num].active.ptr, rule, entries);
return (0);
@@ -1193,12 +1134,6 @@ pfctl_ruleset_trans(struct pfctl *pf, char *path, struct pf_anchor *a)
{
int osize = pf->trans->pfrb_size;
- if ((pf->loadopt & PFCTL_FLAG_NAT) != 0) {
- if (pfctl_add_trans(pf->trans, PF_RULESET_NAT, path) ||
- pfctl_add_trans(pf->trans, PF_RULESET_BINAT, path) ||
- pfctl_add_trans(pf->trans, PF_RULESET_RDR, path))
- return (1);
- }
if (a == pf->astack[0] && ((altqsupport &&
(pf->loadopt & PFCTL_FLAG_ALTQ) != 0))) {
if (pfctl_add_trans(pf->trans, PF_RULESET_ALTQ, path))
@@ -1307,7 +1242,11 @@ pfctl_load_rule(struct pfctl *pf, char *path, struct pf_rule *r, int depth)
name = "";
if ((pf->opts & PF_OPT_NOACTION) == 0) {
- if (pfctl_add_pool(pf, &r->rpool, r->af))
+ if (ioctl(pf->dev, DIOCBEGINADDRS, &pf->paddr))
+ err(1, "DIOCBEGINADDRS");
+ if (pfctl_add_pool(pf, &r->rdr, r->af, PF_RDR))
+ return (1);
+ if (pfctl_add_pool(pf, &r->nat, r->af, PF_NAT))
return (1);
pr.pool_ticket = pf->paddr.ticket;
memcpy(&pr.rule, r, sizeof(pr.rule));
@@ -1324,7 +1263,8 @@ pfctl_load_rule(struct pfctl *pf, char *path, struct pf_rule *r, int depth)
pf->opts & PF_OPT_VERBOSE2);
}
path[len] = '\0';
- pfctl_clear_pool(&r->rpool);
+ pfctl_clear_pool(&r->rdr);
+ pfctl_clear_pool(&r->nat);
return (0);
}
@@ -1438,11 +1378,7 @@ pfctl_rules(int dev, char *filename, int opts, int optimize,
goto _error;
}
- if ((pf.loadopt & PFCTL_FLAG_NAT &&
- (pfctl_load_ruleset(&pf, path, rs, PF_RULESET_NAT, 0) ||
- pfctl_load_ruleset(&pf, path, rs, PF_RULESET_RDR, 0) ||
- pfctl_load_ruleset(&pf, path, rs, PF_RULESET_BINAT, 0))) ||
- (pf.loadopt & PFCTL_FLAG_FILTER &&
+ if ((pf.loadopt & PFCTL_FLAG_FILTER &&
pfctl_load_ruleset(&pf, path, rs, PF_RULESET_FILTER, 0))) {
if ((opts & PF_OPT_NOACTION) == 0)
ERRX("Unable to load rules into kernel");
@@ -2013,7 +1949,7 @@ main(int argc, char *argv[])
usage();
while ((ch = getopt(argc, argv,
- "a:AdD:eqf:F:ghi:k:K:mnNOo:p:rRs:t:T:vx:z")) != -1) {
+ "a:AdD:eqf:F:ghi:k:K:mnOo:p:rRs:t:T:vx:z")) != -1) {
switch (ch) {
case 'a':
anchoropt = optarg;
@@ -2069,9 +2005,6 @@ main(int argc, char *argv[])
case 'n':
opts |= PF_OPT_NOACTION;
break;
- case 'N':
- loadopt |= PFCTL_FLAG_NAT;
- break;
case 'r':
opts |= PF_OPT_USEDNS;
break;
@@ -2178,7 +2111,7 @@ main(int argc, char *argv[])
sizeof(anchorname)) >= sizeof(anchorname))
errx(1, "anchor name '%s' too long",
anchoropt);
- loadopt &= PFCTL_FLAG_FILTER|PFCTL_FLAG_NAT|PFCTL_FLAG_TABLE;
+ loadopt &= PFCTL_FLAG_FILTER|PFCTL_FLAG_TABLE;
}
if ((opts & PF_OPT_NOACTION) == 0) {
@@ -2215,10 +2148,6 @@ main(int argc, char *argv[])
pfctl_show_rules(dev, path, opts, PFCTL_SHOW_LABELS,
anchorname, 0);
break;
- case 'n':
- pfctl_load_fingerprints(dev, opts);
- pfctl_show_nat(dev, opts, anchorname);
- break;
case 'q':
pfctl_show_altq(dev, ifaceopt, opts,
opts & PF_OPT_VERBOSE2);
@@ -2242,7 +2171,6 @@ main(int argc, char *argv[])
opts |= PF_OPT_SHOWALL;
pfctl_load_fingerprints(dev, opts);
- pfctl_show_nat(dev, opts, anchorname);
pfctl_show_rules(dev, path, opts, 0, anchorname, 0);
pfctl_show_altq(dev, ifaceopt, opts, 0);
pfctl_show_states(dev, ifaceopt, opts);
@@ -2280,9 +2208,6 @@ main(int argc, char *argv[])
case 'r':
pfctl_clear_rules(dev, opts, anchorname);
break;
- case 'n':
- pfctl_clear_nat(dev, opts, anchorname);
- break;
case 'q':
pfctl_clear_altq(dev, opts);
break;
@@ -2297,7 +2222,6 @@ main(int argc, char *argv[])
break;
case 'a':
pfctl_clear_rules(dev, opts, anchorname);
- pfctl_clear_nat(dev, opts, anchorname);
pfctl_clear_tables(anchorname, opts);
if (!*anchorname) {
pfctl_clear_altq(dev, opts);
diff --git a/sbin/pfctl/pfctl_optimize.c b/sbin/pfctl/pfctl_optimize.c
index bbed611d2fe..88d44115331 100644
--- a/sbin/pfctl/pfctl_optimize.c
+++ b/sbin/pfctl/pfctl_optimize.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl_optimize.c,v 1.18 2008/05/07 06:23:30 markus Exp $ */
+/* $OpenBSD: pfctl_optimize.c,v 1.19 2009/09/01 13:42:00 henning Exp $ */
/*
* Copyright (c) 2004 Mike Frantzen <frantzen@openbsd.org>
@@ -134,7 +134,8 @@ struct pf_rule_field {
PF_RULE_FIELD(return_ttl, BREAK),
PF_RULE_FIELD(overload_tblname, BREAK),
PF_RULE_FIELD(flush, BREAK),
- PF_RULE_FIELD(rpool, BREAK),
+ PF_RULE_FIELD(rdr, BREAK),
+ PF_RULE_FIELD(nat, BREAK),
PF_RULE_FIELD(logif, BREAK),
/*
@@ -287,12 +288,18 @@ pfctl_optimize_ruleset(struct pfctl *pf, struct pf_ruleset *rs)
if ((por = calloc(1, sizeof(*por))) == NULL)
err(1, "calloc");
memcpy(&por->por_rule, r, sizeof(*r));
- if (TAILQ_FIRST(&r->rpool.list) != NULL) {
- TAILQ_INIT(&por->por_rule.rpool.list);
- pfctl_move_pool(&r->rpool, &por->por_rule.rpool);
+ if (TAILQ_FIRST(&r->rdr.list) != NULL) {
+ TAILQ_INIT(&por->por_rule.rdr.list);
+ pfctl_move_pool(&r->rdr, &por->por_rule.rdr);
} else
- bzero(&por->por_rule.rpool,
- sizeof(por->por_rule.rpool));
+ bzero(&por->por_rule.rdr,
+ sizeof(por->por_rule.rdr));
+ if (TAILQ_FIRST(&r->nat.list) != NULL) {
+ TAILQ_INIT(&por->por_rule.nat.list);
+ pfctl_move_pool(&r->nat, &por->por_rule.nat);
+ } else
+ bzero(&por->por_rule.nat,
+ sizeof(por->por_rule.nat));
TAILQ_INSERT_TAIL(&opt_queue, por, por_entry);
@@ -322,8 +329,10 @@ pfctl_optimize_ruleset(struct pfctl *pf, struct pf_ruleset *rs)
if ((r = calloc(1, sizeof(*r))) == NULL)
err(1, "calloc");
memcpy(r, &por->por_rule, sizeof(*r));
- TAILQ_INIT(&r->rpool.list);
- pfctl_move_pool(&por->por_rule.rpool, &r->rpool);
+ TAILQ_INIT(&r->rdr.list);
+ TAILQ_INIT(&r->nat.list);
+ pfctl_move_pool(&por->por_rule.rdr, &r->rdr);
+ pfctl_move_pool(&por->por_rule.nat, &r->nat);
TAILQ_INSERT_TAIL(
rs->rules[PF_RULESET_FILTER].active.ptr,
r, entries);
@@ -908,9 +917,12 @@ load_feedback_profile(struct pfctl *pf, struct superblocks *superblocks)
memcpy(&por->por_rule, &pr.rule, sizeof(por->por_rule));
rs = pf_find_or_create_ruleset(pr.anchor_call);
por->por_rule.anchor = rs->anchor;
- if (TAILQ_EMPTY(&por->por_rule.rpool.list))
- memset(&por->por_rule.rpool, 0,
- sizeof(por->por_rule.rpool));
+ if (TAILQ_EMPTY(&por->por_rule.rdr.list))
+ memset(&por->por_rule.rdr, 0,
+ sizeof(por->por_rule.rdr));
+ if (TAILQ_EMPTY(&por->por_rule.nat.list))
+ memset(&por->por_rule.nat, 0,
+ sizeof(por->por_rule.nat));
TAILQ_INSERT_TAIL(&queue, por, por_entry);
/* XXX pfctl_get_pool(pf->dev, &pr.rule.rpool, nr, pr.ticket,
diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c
index b86759166b0..1f1d4899150 100644
--- a/sbin/pfctl/pfctl_parser.c
+++ b/sbin/pfctl/pfctl_parser.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl_parser.c,v 1.244 2009/04/15 05:07:02 david Exp $ */
+/* $OpenBSD: pfctl_parser.c,v 1.245 2009/09/01 13:42:00 henning Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -643,14 +643,6 @@ print_src_node(struct pf_src_node *sn, int opts)
sn->packets[0] + sn->packets[1],
sn->bytes[0] + sn->bytes[1]);
switch (sn->ruletype) {
- case PF_NAT:
- if (sn->rule.nr != -1)
- printf(", nat rule %u", sn->rule.nr);
- break;
- case PF_RDR:
- if (sn->rule.nr != -1)
- printf(", rdr rule %u", sn->rule.nr);
- break;
case PF_PASS:
case PF_MATCH:
if (sn->rule.nr != -1)
@@ -772,7 +764,7 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose)
printf(" fastroute");
if (r->rt != PF_FASTROUTE) {
printf(" ");
- print_pool(&r->rpool, 0, 0, r->af, PF_PASS);
+ print_pool(&r->rdr, 0, 0, r->af, PF_PASS);
}
}
if (r->af) {
@@ -1037,11 +1029,15 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose)
printf(" port %u", ntohs(r->divert.port));
}
}
- 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],
- r->rpool.proxy_port[1], r->af, r->action);
+ if (!anchor_call[0] && !TAILQ_EMPTY(&r->nat.list)) {
+ printf (" nat-to ");
+ print_pool(&r->nat, r->nat.proxy_port[0],
+ r->nat.proxy_port[1], r->af, PF_NAT);
+ }
+ if (!r->rt && !anchor_call[0] && !TAILQ_EMPTY(&r->rdr.list)) {
+ printf (" rdr-to ");
+ print_pool(&r->rdr, r->rdr.proxy_port[0],
+ r->rdr.proxy_port[1], r->af, PF_RDR);
}
}
diff --git a/sbin/pfctl/pfctl_parser.h b/sbin/pfctl/pfctl_parser.h
index 758c576b4c4..8b7eca95a2d 100644
--- a/sbin/pfctl/pfctl_parser.h
+++ b/sbin/pfctl/pfctl_parser.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl_parser.h,v 1.88 2009/04/06 12:05:55 henning Exp $ */
+/* $OpenBSD: pfctl_parser.h,v 1.89 2009/09/01 13:42:00 henning Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -194,7 +194,7 @@ int pfctl_optimize_ruleset(struct pfctl *, struct pf_ruleset *);
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);
+int pfctl_add_pool(struct pfctl *, struct pf_pool *, sa_family_t, int);
void pfctl_move_pool(struct pf_pool *, struct pf_pool *);
void pfctl_clear_pool(struct pf_pool *);