Index: sbin/pfctl/parse.y =================================================================== --- sbin/pfctl/parse.y (revision 261814) +++ sbin/pfctl/parse.y (working copy) @@ -2389,12 +2389,7 @@ } } | DIVERTREPLY { -#ifdef __FreeBSD__ - yyerror("divert-reply has no meaning in FreeBSD pf(4)"); - YYERROR; -#else filter_opts.divert.port = 1; /* some random value */ -#endif } ; Index: sys/netpfil/pf/pf.c =================================================================== --- sys/netpfil/pf/pf.c (revision 261814) +++ sys/netpfil/pf/pf.c (working copy) @@ -271,6 +271,7 @@ struct pf_addr *); static int pf_check_proto_cksum(struct mbuf *, int, int, u_int8_t, sa_family_t); +static struct pf_divert *pf_get_divert(struct mbuf *); static void pf_print_state_parts(struct pf_state *, struct pf_state_key *, struct pf_state_key *); static int pf_addr_wrap_neq(struct pf_addr_wrap *, @@ -5619,7 +5620,23 @@ return (0); } +struct pf_divert * +pf_get_divert(struct mbuf *m) +{ + struct m_tag *mtag; + if ((mtag = m_tag_find(m, PACKET_TAG_PF_DIVERT, NULL)) == NULL) { + mtag = m_tag_get(PACKET_TAG_PF_DIVERT, sizeof(struct pf_divert), + M_NOWAIT); + if (mtag == NULL) + return (NULL); + bzero(mtag + 1, sizeof(struct pf_divert)); + m_tag_prepend(m, mtag); + } + + return ((struct pf_divert *)(mtag + 1)); +} + #ifdef INET int pf_test(int dir, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp) @@ -5904,6 +5921,15 @@ } } + if (action == PF_PASS && r->divert.port && dir == PF_IN /*&& r->direction == PF_OUT*/ ) { + struct pf_divert *divert; + if ((divert = pf_get_divert(m))) { + m->m_flags |= M_FASTFWD_OURS; + divert->port = r->divert.port; + divert->addr.ipv4 = r->divert.addr.v4; + } + } + if (log) { struct pf_rule *lr; @@ -6275,9 +6301,14 @@ IN6_IS_ADDR_LOOPBACK(&pd.dst->v6)) m->m_flags |= M_SKIP_FIREWALL; - /* XXX: Anybody working on it?! */ - if (r->divert.port) - printf("pf: divert(9) is not supported for IPv6\n"); + if (action == PF_PASS && r->divert.port && dir == PF_IN /*&& r->direction == PF_OUT*/) { + struct pf_divert *divert; + if ((divert = pf_get_divert(m))) { + m->m_flags |= M_FASTFWD_OURS; + divert->port = r->divert.port; + divert->addr.ipv6 = r->divert.addr.v6; + } + } if (log) { struct pf_rule *lr; Index: sys/sys/mbuf.h =================================================================== --- sys/sys/mbuf.h (revision 261814) +++ sys/sys/mbuf.h (working copy) @@ -1023,6 +1023,7 @@ #define PACKET_TAG_DUMMYNET 15 /* dummynet info */ #define PACKET_TAG_DIVERT 17 /* divert info */ #define PACKET_TAG_IPFORWARD 18 /* ipforward info */ +#define PACKET_TAG_PF_DIVERT PACKET_TAG_IPFORWARD #define PACKET_TAG_MACLABEL (19 | MTAG_PERSISTENT) /* MAC label */ #define PACKET_TAG_PF (21 | MTAG_PERSISTENT) /* PF/ALTQ information */ #define PACKET_TAG_RTSOCKFAM 25 /* rtsock sa family */