summaryrefslogtreecommitdiff
path: root/sys/netinet/ip_input.c
diff options
context:
space:
mode:
authorjonathan <jonathan@NetBSD.org>2003-08-15 03:42:00 +0000
committerjonathan <jonathan@NetBSD.org>2003-08-15 03:42:00 +0000
commit28b5f5dfabb831ea8baec8eba121fa1d14aa5138 (patch)
tree6e6f1fcd7eef12f388fa2883f9e0bf69657c98be /sys/netinet/ip_input.c
parentbc73aa40f55fc89ab83adcff00d2421b868a93d8 (diff)
(fast-ipsec): Add hooks to pass IPv4 IPsec traffic into fast-ipsec, if
configured with ``options FAST_IPSEC''. Kernels with KAME IPsec or with no IPsec should work as before. All calls to ip_output() now always pass an additional compulsory argument: the inpcb associated with the packet being sent, or 0 if no inpcb is available. Fast-ipsec tested with ICMP or UDP over ESP. TCP doesn't work, yet.
Diffstat (limited to 'sys/netinet/ip_input.c')
-rw-r--r--sys/netinet/ip_input.c95
1 files changed, 89 insertions, 6 deletions
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index 73f6ec69b4f..7835c52a847 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ip_input.c,v 1.172 2003/08/07 16:33:12 agc Exp $ */
+/* $NetBSD: ip_input.c,v 1.173 2003/08/15 03:42:02 jonathan Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -98,7 +98,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.172 2003/08/07 16:33:12 agc Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.173 2003/08/15 03:42:02 jonathan Exp $");
#include "opt_gateway.h"
#include "opt_pfil_hooks.h"
@@ -147,6 +147,10 @@ __KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.172 2003/08/07 16:33:12 agc Exp $");
#include <netinet6/ipsec.h>
#include <netkey/key.h>
#endif
+#ifdef FAST_IPSEC
+#include <netipsec/ipsec.h>
+#include <netipsec/key.h>
+#endif /* FAST_IPSEC*/
#ifndef IPFORWARDING
#ifdef GATEWAY
@@ -429,6 +433,12 @@ ip_input(struct mbuf *m)
int downmatch;
int checkif;
int srcrt = 0;
+#ifdef FAST_IPSEC
+ struct m_tag *mtag;
+ struct tdb_ident *tdbi;
+ struct secpolicy *sp;
+ int s, error;
+#endif /* FAST_IPSEC */
MCLAIM(m, &ip_rx_mowner);
#ifdef DIAGNOSTIC
@@ -762,6 +772,34 @@ ip_input(struct mbuf *m)
goto bad;
}
#endif
+#ifdef FAST_IPSEC
+ mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL);
+ s = splsoftnet();
+ if (mtag != NULL) {
+ tdbi = (struct tdb_ident *)(mtag + 1);
+ sp = ipsec_getpolicy(tdbi, IPSEC_DIR_INBOUND);
+ } else {
+ sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_INBOUND,
+ IP_FORWARDING, &error);
+ }
+ if (sp == NULL) { /* NB: can happen if error */
+ splx(s);
+ /*XXX error stat???*/
+ DPRINTF(("ip_input: no SP for forwarding\n")); /*XXX*/
+ goto bad;
+ }
+
+ /*
+ * Check security policy against packet attributes.
+ */
+ error = ipsec_in_reject(sp, m);
+ KEY_FREESP(&sp);
+ splx(s);
+ if (error) {
+ ipstat.ips_cantforward++;
+ goto bad;
+ }
+#endif /* FAST_IPSEC */
ip_forward(m, srcrt);
}
@@ -850,7 +888,7 @@ found:
IPQ_UNLOCK();
}
-#ifdef IPSEC
+#if defined(IPSEC)
/*
* enforce IPsec policy checking if we are seeing last header.
* note that we do not visit this with protocols with pcb layer
@@ -862,6 +900,45 @@ found:
goto bad;
}
#endif
+#if FAST_IPSEC
+ /*
+ * enforce IPsec policy checking if we are seeing last header.
+ * note that we do not visit this with protocols with pcb layer
+ * code - like udp/tcp/raw ip.
+ */
+ if ((inetsw[ip_protox[ip->ip_p]].pr_flags & PR_LASTHDR) != 0) {
+ /*
+ * Check if the packet has already had IPsec processing
+ * done. If so, then just pass it along. This tag gets
+ * set during AH, ESP, etc. input handling, before the
+ * packet is returned to the ip input queue for delivery.
+ */
+ mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL);
+ s = splsoftnet();
+ if (mtag != NULL) {
+ tdbi = (struct tdb_ident *)(mtag + 1);
+ sp = ipsec_getpolicy(tdbi, IPSEC_DIR_INBOUND);
+ } else {
+ sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_INBOUND,
+ IP_FORWARDING, &error);
+ }
+ if (sp != NULL) {
+ /*
+ * Check security policy against packet attributes.
+ */
+ error = ipsec_in_reject(sp, m);
+ KEY_FREESP(&sp);
+ } else {
+ /* XXX error stat??? */
+ error = EINVAL;
+DPRINTF(("ip_input: no SP, packet discarded\n"));/*XXX*/
+ goto bad;
+ }
+ splx(s);
+ if (error)
+ goto bad;
+ }
+#endif /* FAST_IPSEC */
/*
* Switch out to protocol's input routine.
@@ -1566,7 +1643,7 @@ ip_forward(m, srcrt)
struct mbuf *mcopy;
n_long dest;
struct ifnet *destifp;
-#ifdef IPSEC
+#if defined(IPSEC) || defined(FAST_IPSEC)
struct ifnet dummyifp;
#endif
@@ -1664,7 +1741,9 @@ ip_forward(m, srcrt)
(void)ipsec_setsocket(m, NULL);
#endif
error = ip_output(m, (struct mbuf *)0, &ipforward_rt,
- (IP_FORWARDING | (ip_directedbcast ? IP_ALLOWBROADCAST : 0)), 0);
+ (IP_FORWARDING | (ip_directedbcast ? IP_ALLOWBROADCAST : 0)),
+ (struct ip_moptions *)0, (struct inpcb *)0);
+
if (error)
ipstat.ips_cantforward++;
else {
@@ -1704,7 +1783,7 @@ ip_forward(m, srcrt)
case EMSGSIZE:
type = ICMP_UNREACH;
code = ICMP_UNREACH_NEEDFRAG;
-#ifndef IPSEC
+#if !defined(IPSEC) && !defined(FAST_IPSEC)
if (ipforward_rt.ro_rt)
destifp = ipforward_rt.ro_rt->rt_ifp;
#else
@@ -1755,7 +1834,11 @@ ip_forward(m, srcrt)
}
}
+#ifdef IPSEC
key_freesp(sp);
+#else
+ KEY_FREESP(&sp);
+#endif
}
}
#endif /*IPSEC*/