diff options
author | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2017-05-11 12:14:44 +0000 |
---|---|---|
committer | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2017-05-11 12:14:44 +0000 |
commit | 44ca2bc5aee9c7efbfa5299e94142e205b893f44 (patch) | |
tree | 112b75f6d0c709d3797ae94f35230eb5f7bebe29 /sys/netinet/ipsec_input.c | |
parent | ad2227ce541f4680147d70e42e7d4191100ecad4 (diff) |
IPv6 IPsec transport mode did not work if pf is enabled. The
decrypted packets in the input path were not checked with pf. So
with stateful filtering on enc0, direction aware protocols like
ping or TCP did not pass. Add an explicit pf_test() in
ipsec_common_input_cb() for IPv6 transport mode to fix this.
OK mikeb@
Diffstat (limited to 'sys/netinet/ipsec_input.c')
-rw-r--r-- | sys/netinet/ipsec_input.c | 28 |
1 files changed, 27 insertions, 1 deletions
diff --git a/sys/netinet/ipsec_input.c b/sys/netinet/ipsec_input.c index 8ded384c8d9..133a0e69422 100644 --- a/sys/netinet/ipsec_input.c +++ b/sys/netinet/ipsec_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ipsec_input.c,v 1.148 2017/05/05 11:04:18 bluhm Exp $ */ +/* $OpenBSD: ipsec_input.c,v 1.149 2017/05/11 12:14:43 bluhm Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr) and @@ -591,6 +591,32 @@ ipsec_common_input_cb(struct mbuf *m, struct tdb *tdbp, int skip, int protoff) return; #ifdef INET6 case AF_INET6: +#if NPF > 0 + /* + * In the IPv4 case all packets run through ipv4_input() + * twice. As the ip6_local() shortcut avoids this, IPv6 + * packets in transport mode have to be be passed to pf + * explicitly. In tunnel mode the inner IP header will + * run through ip_input() and pf already. + */ + if ((tdbp->tdb_flags & TDBF_TUNNELING) == 0) { + struct ifnet *ifp; + + /* This is the enc0 interface unless for ipcomp. */ + if ((ifp = if_get(m->m_pkthdr.ph_ifidx)) == NULL) { + m_freem(m); + return; + } + if (pf_test(AF_INET6, PF_IN, ifp, &m) != PF_PASS) { + if_put(ifp); + m_freem(m); + return; + } + if_put(ifp); + if (m == NULL) + return; + } +#endif ip6_local(m, skip, prot); return; #endif /* INET6 */ |