summaryrefslogtreecommitdiff
path: root/sbin/pfctl
diff options
context:
space:
mode:
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 *);