Index: parse.y =================================================================== RCS file: /home/cvs/src/sbin/pfctl/parse.y,v retrieving revision 1.599 diff -u -p -r1.599 parse.y --- parse.y 6 Apr 2011 13:19:55 -0000 1.599 +++ parse.y 15 Apr 2011 14:13:27 -0000 @@ -227,6 +227,7 @@ struct redirspec { struct redirection *rdr; struct pool_opts pool_opts; int binat; + int af; }; struct filter_opts { @@ -238,6 +239,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 struct node_uid *uid; @@ -466,7 +468,7 @@ int parseport(char *, struct range *r, i %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 STRING %token NUMBER %token PORTBINARY @@ -918,6 +920,7 @@ anchorrule : ANCHOR anchorname dir quick 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, @@ -1731,7 +1734,20 @@ pfrule : action dir logquick interface if ($8.marker & FOM_SCRUB_TCP) r.scrub_flags |= PFSTATE_SCRUB_TCP; + 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) { @@ -2015,6 +2031,7 @@ pfrule : action dir logquick interface 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) { @@ -2273,6 +2290,61 @@ filter_opt : USER uids { memcpy(&filter_opts.nat.pool_opts, &$3, sizeof(filter_opts.nat.pool_opts)); } + | AFTO af redirpool { + if (filter_opts.nat.rdr) { + yyerror("cannot respecify af-to"); + YYERROR; + } + if ($2 == 0) { + yyerror("no address family specified"); + YYERROR; + } + if ($3->host->af && $3->host->af != $2) { + yyerror("af-to addresses must be in the " + "target address family"); + YYERROR; + } + filter_opts.nat.af = $2; + filter_opts.nat.rdr = $3; + bzero(&filter_opts.nat.pool_opts, + sizeof(filter_opts.nat.pool_opts)); + if ($3->host->addr.type == PF_ADDR_DYNIFTL) + filter_opts.nat.pool_opts.type = + PF_POOL_ROUNDROBIN; + 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 '(' redirpool redirpool ')' { + 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) || + ($5->host->af && $5->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; + bzero(&filter_opts.nat.pool_opts, + sizeof(filter_opts.nat.pool_opts)); + if ($4->host->addr.type == PF_ADDR_DYNIFTL) + filter_opts.nat.pool_opts.type = + PF_POOL_ROUNDROBIN; + filter_opts.rdr.af = $2; + filter_opts.rdr.rdr = $5; + bzero(&filter_opts.rdr.pool_opts, + sizeof(filter_opts.rdr.pool_opts)); + filter_opts.marker |= FOM_AFTO; + } | RDRTO redirpool pool_opts { if (filter_opts.rdr.rdr) { yyerror("cannot respecify rdr-to"); @@ -4045,6 +4117,10 @@ rule_consistent(struct pf_rule *r, int a "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); } @@ -4544,6 +4620,8 @@ collapse_redirspec(struct pf_pool *rpool 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; @@ -4552,7 +4630,7 @@ collapse_redirspec(struct pf_pool *rpool /* 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; @@ -4565,7 +4643,7 @@ collapse_redirspec(struct pf_pool *rpool 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) { @@ -4585,7 +4663,7 @@ collapse_redirspec(struct pf_pool *rpool 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) { @@ -5040,6 +5118,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}, Index: pf_print_state.c =================================================================== RCS file: /home/cvs/src/sbin/pfctl/pf_print_state.c,v retrieving revision 1.58 diff -u -p -r1.58 pf_print_state.c --- pf_print_state.c 12 Nov 2010 13:14:41 -0000 1.58 +++ pf_print_state.c 6 Apr 2011 15:59:24 -0000 @@ -213,6 +213,8 @@ print_state(struct pfsync_state *s, int 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 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(")"); } Index: pfctl_parser.c =================================================================== RCS file: /home/cvs/src/sbin/pfctl/pfctl_parser.c,v retrieving revision 1.275 diff -u -p -r1.275 pfctl_parser.c --- pfctl_parser.c 6 Apr 2011 13:19:55 -0000 1.275 +++ pfctl_parser.c 7 Apr 2011 13:33:14 -0000 @@ -442,7 +442,7 @@ print_fromto(struct pf_rule_addr *src, p void print_pool(struct pf_pool *pool, u_int16_t p1, u_int16_t p2, - sa_family_t af, int id, int verbose) + sa_family_t af, int id, int verbose, int hideopts) { if (pool->ifname[0]) { if (!PF_AZERO(&pool->addr.v.a.addr, af)) { @@ -472,6 +472,8 @@ print_pool(struct pf_pool *pool, u_int16 default: break; } + if (hideopts) + return; switch (pool->opts & PF_POOL_TYPEMASK) { case PF_POOL_NONE: break; @@ -641,7 +643,8 @@ print_src_node(struct pf_src_node *sn, i 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, @@ -1045,15 +1048,31 @@ print_rule(struct pf_rule *r, const char } 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 ", r->naf == AF_INET ? "inet" : "inet6"); + if (r->rdr.addr.type != PF_ADDR_NONE) + printf("("); + print_pool(&r->nat, r->nat.proxy_port[0], + r->nat.proxy_port[1], r->naf ? r->naf : r->af, + PF_POOL_NAT, verbose, 1); + if (r->rdr.addr.type != PF_ADDR_NONE) { + printf(" "); + print_pool(&r->rdr, r->rdr.proxy_port[0], + r->rdr.proxy_port[1], r->naf ? r->naf : r->af, + PF_POOL_RDR, verbose, 1); + printf(")"); + } + } 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, 0); + } 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); + r->rdr.proxy_port[1], r->af, PF_POOL_RDR, verbose, 0); } if (r->rt) { if (r->rt == PF_ROUTETO) @@ -1063,7 +1082,7 @@ print_rule(struct pf_rule *r, const char else if (r->rt == PF_DUPTO) printf(" dup-to"); printf(" "); - print_pool(&r->route, 0, 0, r->af, PF_POOL_ROUTE, verbose); + print_pool(&r->route, 0, 0, r->af, PF_POOL_ROUTE, verbose, 0); } } Index: pfctl_parser.h =================================================================== RCS file: /home/cvs/src/sbin/pfctl/pfctl_parser.h,v retrieving revision 1.95 diff -u -p -r1.95 pfctl_parser.h --- pfctl_parser.h 6 Apr 2011 13:19:55 -0000 1.95 +++ pfctl_parser.h 7 Apr 2011 13:33:14 -0000 @@ -214,7 +214,8 @@ int parse_config(char *, struct pfctl *) int parse_flags(char *); int pfctl_load_anchors(int, struct pfctl *, struct pfr_buffer *); -void print_pool(struct pf_pool *, u_int16_t, u_int16_t, sa_family_t, int, int); +void print_pool(struct pf_pool *, u_int16_t, u_int16_t, sa_family_t, int, + int, int); void print_src_node(struct pf_src_node *, int); void print_rule(struct pf_rule *, const char *, int); void print_tabledef(const char *, int, int, struct node_tinithead *);