summaryrefslogtreecommitdiff
path: root/sys/netinet/ipsec_input.c
diff options
context:
space:
mode:
authorAlexander Bluhm <bluhm@cvs.openbsd.org>2017-05-11 12:14:44 +0000
committerAlexander Bluhm <bluhm@cvs.openbsd.org>2017-05-11 12:14:44 +0000
commit44ca2bc5aee9c7efbfa5299e94142e205b893f44 (patch)
tree112b75f6d0c709d3797ae94f35230eb5f7bebe29 /sys/netinet/ipsec_input.c
parentad2227ce541f4680147d70e42e7d4191100ecad4 (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.c28
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 */