summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2011-10-13 18:30:55 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2011-10-13 18:30:55 +0000
commitb5007cc677518df9758320bd9fa7aa6113ca8b53 (patch)
tree6e89857fedf03ae1fa17fc9be46b14caa27f38d2
parentd0ab30fdb97104766da99fa8da4eb3371d2d4163 (diff)
pfctl change for af-to / NAT64 support.
The general syntax is: pass in inet from any to 192.168.1.1 af-to inet6 from 2001::1 to 2001::2 In the NAT64 case the "to" is not needed in af-to and the IP is extraced from the IPv6 dst (assuming a /64 prefix). Again most work by sperreault@, mikeb@ and reyk@ OK mcbride@, put it in deraadt@
-rw-r--r--sbin/pfctl/parse.y84
-rw-r--r--sbin/pfctl/pf_print_state.c22
-rw-r--r--sbin/pfctl/pfctl_parser.c26
3 files changed, 113 insertions, 19 deletions
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
index 8bf5604583f..b90334cb59d 100644
--- a/sbin/pfctl/parse.y
+++ b/sbin/pfctl/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.609 2011/09/07 23:40:52 haesbaert Exp $ */
+/* $OpenBSD: parse.y,v 1.610 2011/10/13 18:30:54 claudio Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
@@ -217,6 +217,7 @@ struct redirspec {
struct redirection *rdr;
struct pool_opts pool_opts;
int binat;
+ int af;
};
struct filter_opts {
@@ -228,6 +229,7 @@ struct filter_opts {
#define FOM_SRCTRACK 0x0010
#define FOM_MINTTL 0x0020
#define FOM_MAXMSS 0x0040
+#define FOM_AFTO 0x0080
#define FOM_SETTOS 0x0100
#define FOM_SCRUB_TCP 0x0200
#define FOM_PRIO 0x0400
@@ -460,7 +462,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 DIVERTPACKET NATTO RDRTO RECEIVEDON NE LE GE
+%token DIVERTTO DIVERTREPLY DIVERTPACKET NATTO AFTO RDRTO RECEIVEDON NE LE GE
%token <v.string> STRING
%token <v.number> NUMBER
%token <v.i> PORTBINARY
@@ -897,6 +899,7 @@ 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);
+ r.naf = r.af;
expand_rule(&r, 0, $5, NULL, NULL, NULL, $7, $8.src_os,
$8.src.host, $8.src.port, $8.dst.host, $8.dst.port,
@@ -1715,7 +1718,20 @@ pfrule : action dir logquick interface af proto fromto
if ($8.marker & FOM_ONCE)
r.rule_flag |= PFRULE_ONCE;
+ if ($8.marker & FOM_AFTO) {
+ if (!$5) {
+ yyerror("must indicate source address "
+ "family with af-to");
+ YYERROR;
+ }
+ if ($5 == $8.nat.af) {
+ yyerror("incorrect address family "
+ "translation");
+ YYERROR;
+ }
+ }
r.af = $5;
+
if ($8.tag)
if (strlcpy(r.tagname, $8.tag,
PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
@@ -1999,6 +2015,7 @@ pfrule : action dir logquick interface af proto fromto
decide_address_family($7.src.host, &r.af);
decide_address_family($7.dst.host, &r.af);
+ r.naf = r.af;
if ($8.route.rt) {
if (!r.direction) {
@@ -2265,6 +2282,55 @@ filter_opt : USER uids {
memcpy(&filter_opts.nat.pool_opts, &$3,
sizeof(filter_opts.nat.pool_opts));
}
+ | AFTO af FROM redirpool pool_opts {
+ if (filter_opts.nat.rdr) {
+ yyerror("cannot respecify af-to");
+ YYERROR;
+ }
+ if ($2 == 0) {
+ yyerror("no address family specified");
+ YYERROR;
+ }
+ if ($4->host->af && $4->host->af != $2) {
+ yyerror("af-to addresses must be in the "
+ "target address family");
+ YYERROR;
+ }
+ filter_opts.nat.af = $2;
+ filter_opts.nat.rdr = $4;
+ memcpy(&filter_opts.nat.pool_opts, &$5,
+ sizeof(filter_opts.nat.pool_opts));
+ filter_opts.rdr.rdr =
+ calloc(1, sizeof(struct redirection));
+ bzero(&filter_opts.rdr.pool_opts,
+ sizeof(filter_opts.rdr.pool_opts));
+ filter_opts.marker |= FOM_AFTO;
+ }
+ | AFTO af FROM redirpool pool_opts TO redirpool pool_opts {
+ if (filter_opts.nat.rdr) {
+ yyerror("cannot respecify af-to");
+ YYERROR;
+ }
+ if ($2 == 0) {
+ yyerror("no address family specified");
+ YYERROR;
+ }
+ if (($4->host->af && $4->host->af != $2) ||
+ ($7->host->af && $7->host->af != $2)) {
+ yyerror("af-to addresses must be in the "
+ "target address family");
+ YYERROR;
+ }
+ filter_opts.nat.af = $2;
+ filter_opts.nat.rdr = $4;
+ memcpy(&filter_opts.nat.pool_opts, &$5,
+ sizeof(filter_opts.nat.pool_opts));
+ filter_opts.rdr.af = $2;
+ filter_opts.rdr.rdr = $7;
+ memcpy(&filter_opts.nat.pool_opts, &$8,
+ sizeof(filter_opts.nat.pool_opts));
+ filter_opts.marker |= FOM_AFTO;
+ }
| RDRTO redirpool pool_opts {
if (filter_opts.rdr.rdr) {
yyerror("cannot respecify rdr-to");
@@ -4131,6 +4197,10 @@ rule_consistent(struct pf_rule *r, int anchor_call)
"must not be used on match rules");
problems++;
}
+ if (r->nat.addr.type != PF_ADDR_NONE && r->naf != r->af) {
+ yyerror("af-to is not supported on match rules");
+ problems++;
+ }
}
return (-problems);
}
@@ -4630,6 +4700,9 @@ collapse_redirspec(struct pf_pool *rpool, struct pf_rule *r,
struct pf_rule_addr ra;
int i = 0;
+ if (rs && rs->af)
+ r->naf = rs->af;
+
if (!rs || !rs->rdr || rs->rdr->host == NULL) {
rpool->addr.type = PF_ADDR_NONE;
return (0);
@@ -4637,7 +4710,7 @@ collapse_redirspec(struct pf_pool *rpool, struct pf_rule *r,
/* count matching addresses */
for (h = rs->rdr->host; h != NULL; h = h->next) {
- if (!r->af || !h->af || h->af == r->af) {
+ if (!r->af || !h->af || rs->af || h->af == r->af) {
i++;
if (h->af && !r->af)
r->af = h->af;
@@ -4650,7 +4723,7 @@ collapse_redirspec(struct pf_pool *rpool, struct pf_rule *r,
return (1);
} else if (i == 1) { /* only one address */
for (h = rs->rdr->host; h != NULL; h = h->next)
- if (!h->af || !r->af || r->af == h->af)
+ if (!h->af || !r->af || rs->af || r->af == h->af)
break;
rpool->addr = h->addr;
if (!allow_if && h->ifname) {
@@ -4672,7 +4745,7 @@ collapse_redirspec(struct pf_pool *rpool, struct pf_rule *r,
return (1);
}
for (h = rs->rdr->host; h != NULL; h = h->next) {
- if (r->af != h->af)
+ if (!rs->af && r->af != h->af)
continue;
if (h->addr.type != PF_ADDR_ADDRMASK &&
h->addr.type != PF_ADDR_NONE) {
@@ -5117,6 +5190,7 @@ lookup(char *s)
{
/* this has to be sorted always */
static const struct keywords keywords[] = {
+ { "af-to", AFTO},
{ "all", ALL},
{ "allow-opts", ALLOWOPTS},
{ "altq", ALTQ},
diff --git a/sbin/pfctl/pf_print_state.c b/sbin/pfctl/pf_print_state.c
index 657044da17a..63a76d3315b 100644
--- a/sbin/pfctl/pf_print_state.c
+++ b/sbin/pfctl/pf_print_state.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_print_state.c,v 1.58 2010/11/12 13:14:41 claudio Exp $ */
+/* $OpenBSD: pf_print_state.c,v 1.59 2011/10/13 18:30:54 claudio Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -213,6 +213,8 @@ print_state(struct pfsync_state *s, int opts)
struct pfsync_state_key *sk, *nk;
struct protoent *p;
int min, sec;
+ int afto = (s->key[PF_SK_STACK].af != s->key[PF_SK_WIRE].af);
+ int idx;
if (s->direction == PF_OUT) {
src = &s->src;
@@ -235,24 +237,28 @@ print_state(struct pfsync_state *s, int opts)
else
printf("%u ", s->proto);
- print_host(&nk->addr[1], nk->port[1], s->af, nk->rdomain, opts);
- if (PF_ANEQ(&nk->addr[1], &sk->addr[1], s->af) ||
+ print_host(&nk->addr[1], nk->port[1], nk->af, nk->rdomain, opts);
+ if (nk->af != sk->af || PF_ANEQ(&nk->addr[1], &sk->addr[1], nk->af) ||
nk->port[1] != sk->port[1] ||
nk->rdomain != sk->rdomain) {
+ idx = afto ? 0 : 1;
printf(" (");
- print_host(&sk->addr[1], sk->port[1], s->af, sk->rdomain, opts);
+ print_host(&sk->addr[idx], sk->port[idx], sk->af,
+ sk->rdomain, opts);
printf(")");
}
- if (s->direction == PF_OUT)
+ if (s->direction == PF_OUT || (afto && s->direction == PF_IN))
printf(" -> ");
else
printf(" <- ");
- print_host(&nk->addr[0], nk->port[0], s->af, nk->rdomain, opts);
- if (PF_ANEQ(&nk->addr[0], &sk->addr[0], s->af) ||
+ print_host(&nk->addr[0], nk->port[0], nk->af, nk->rdomain, opts);
+ if (nk->af != sk->af || PF_ANEQ(&nk->addr[0], &sk->addr[0], nk->af) ||
nk->port[0] != sk->port[0] ||
nk->rdomain != sk->rdomain) {
+ idx = afto ? 1 : 0;
printf(" (");
- print_host(&sk->addr[0], sk->port[0], s->af, sk->rdomain, opts);
+ print_host(&sk->addr[idx], sk->port[idx], sk->af,
+ sk->rdomain, opts);
printf(")");
}
diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c
index 10dc9c94f5e..2b92e133a16 100644
--- a/sbin/pfctl/pfctl_parser.c
+++ b/sbin/pfctl/pfctl_parser.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl_parser.c,v 1.280 2011/08/30 00:43:57 mikeb Exp $ */
+/* $OpenBSD: pfctl_parser.c,v 1.281 2011/10/13 18:30:54 claudio Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -644,7 +644,8 @@ print_src_node(struct pf_src_node *sn, int opts)
else
printf(" ??? (%u) ", sn->type);
aw.v.a.addr = sn->raddr;
- print_addr(&aw, sn->af, opts & PF_OPT_VERBOSE2);
+ print_addr(&aw, sn->naf ? sn->naf : sn->af,
+ opts & PF_OPT_VERBOSE2);
}
printf(" ( states %u, connections %u, rate %u.%u/%us )\n", sn->states,
@@ -1052,12 +1053,25 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose)
}
if (r->divert_packet.port)
printf(" divert-packet port %u", ntohs(r->divert_packet.port));
- if (!anchor_call[0] && r->nat.addr.type != PF_ADDR_NONE) {
+
+ if (!anchor_call[0] && r->nat.addr.type != PF_ADDR_NONE &&
+ r->naf != r->af) {
+ printf(" af-to %s from ", r->naf == AF_INET ? "inet" : "inet6");
+ print_pool(&r->nat, r->nat.proxy_port[0],
+ r->nat.proxy_port[1], r->naf ? r->naf : r->af,
+ PF_POOL_NAT, verbose);
+ if (r->rdr.addr.type != PF_ADDR_NONE) {
+ printf(" to ");
+ print_pool(&r->rdr, r->rdr.proxy_port[0],
+ r->rdr.proxy_port[1], r->naf ? r->naf : r->af,
+ PF_POOL_RDR, verbose);
+ }
+ } else if (!anchor_call[0] && r->nat.addr.type != PF_ADDR_NONE) {
printf (" nat-to ");
print_pool(&r->nat, r->nat.proxy_port[0],
- r->nat.proxy_port[1], r->af, PF_POOL_NAT, verbose);
- }
- if (!anchor_call[0] && r->rdr.addr.type != PF_ADDR_NONE) {
+ r->nat.proxy_port[1], r->naf ? r->naf : r->af,
+ PF_POOL_NAT, verbose);
+ } else if (!anchor_call[0] && r->rdr.addr.type != PF_ADDR_NONE) {
printf (" rdr-to ");
print_pool(&r->rdr, r->rdr.proxy_port[0],
r->rdr.proxy_port[1], r->af, PF_POOL_RDR, verbose);