Module Name: src
Committed By: rmind
Date: Sat Jun 8 13:50:22 UTC 2013
Modified Files:
src/sys/netinet: ip_input.c ip_output.c
src/sys/netipsec: ipsec.c ipsec.h
Log Message:
Split IPsec code in ip_input() and ip_forward() into the separate routines
ipsec4_input() and ipsec4_forward(). Tested by christos@.
To generate a diff of this commit:
cvs rdiff -u -r1.304 -r1.305 src/sys/netinet/ip_input.c
cvs rdiff -u -r1.221 -r1.222 src/sys/netinet/ip_output.c
cvs rdiff -u -r1.59 -r1.60 src/sys/netipsec/ipsec.c
cvs rdiff -u -r1.33 -r1.34 src/sys/netipsec/ipsec.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/netinet/ip_input.c
diff -u src/sys/netinet/ip_input.c:1.304 src/sys/netinet/ip_input.c:1.305
--- src/sys/netinet/ip_input.c:1.304 Wed Jun 5 19:01:26 2013
+++ src/sys/netinet/ip_input.c Sat Jun 8 13:50:22 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: ip_input.c,v 1.304 2013/06/05 19:01:26 christos Exp $ */
+/* $NetBSD: ip_input.c,v 1.305 2013/06/08 13:50:22 rmind Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -91,7 +91,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.304 2013/06/05 19:01:26 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.305 2013/06/08 13:50:22 rmind Exp $");
#include "opt_inet.h"
#include "opt_compat_netbsd.h"
@@ -143,8 +143,7 @@ __KERNEL_RCSID(0, "$NetBSD: ip_input.c,v
#ifdef IPSEC
#include <netipsec/ipsec.h>
-#include <netipsec/key.h>
-#endif /* IPSEC*/
+#endif
#ifndef IPFORWARDING
#ifdef GATEWAY
@@ -405,12 +404,6 @@ ip_input(struct mbuf *m)
int downmatch;
int checkif;
int srcrt = 0;
-#ifdef IPSEC
- struct m_tag *mtag;
- struct tdb_ident *tdbi;
- struct secpolicy *sp;
- int error, s;
-#endif /* IPSEC */
MCLAIM(m, &ip_rx_mowner);
KASSERT((m->m_flags & M_PKTHDR) != 0);
@@ -733,54 +726,12 @@ ip_input(struct mbuf *m)
return;
}
#ifdef 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) {
- IP_STATINC(IP_STAT_CANTFORWARD);
+ /* Perform IPsec, if any. */
+ if (ipsec4_input(m, IP_FORWARDING | (ip_directedbcast ?
+ IP_ALLOWBROADCAST : 0)) != 0) {
goto bad;
}
-
- /*
- * Peek at the outbound SP for this packet to determine if
- * it's a Fast Forward candidate.
- */
- mtag = m_tag_find(m, PACKET_TAG_IPSEC_PENDING_TDB, NULL);
- if (mtag != NULL)
- m->m_flags &= ~M_CANFASTFWD;
- else {
- s = splsoftnet();
- sp = ipsec4_checkpolicy(m, IPSEC_DIR_OUTBOUND,
- (IP_FORWARDING |
- (ip_directedbcast ? IP_ALLOWBROADCAST : 0)),
- &error, NULL);
- if (sp != NULL) {
- m->m_flags &= ~M_CANFASTFWD;
- KEY_FREESP(&sp);
- }
- splx(s);
- }
-#endif /* IPSEC */
-
+#endif
ip_forward(m, srcrt);
}
return;
@@ -811,42 +762,16 @@ ours:
#ifdef 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.
+ * 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*/
- }
- splx(s);
- if (error)
+ if (ipsec4_input(m, 0) != 0) {
goto bad;
+ }
}
-#endif /* IPSEC */
+#endif
/*
* Switch out to protocol's input routine.
@@ -1422,53 +1347,9 @@ ip_forward(struct mbuf *m, int srcrt)
if ((rt = rtcache_validate(&ipforward_rt)) != NULL)
destmtu = rt->rt_ifp->if_mtu;
-
-#if defined(IPSEC)
- {
- /*
- * If the packet is routed over IPsec tunnel, tell the
- * originator the tunnel MTU.
- * tunnel MTU = if MTU - sizeof(IP) - ESP/AH hdrsiz
- * XXX quickhack!!!
- */
-
- struct secpolicy *sp;
- int ipsecerror;
- size_t ipsechdr;
- struct route *ro;
-
- sp = ipsec4_getpolicybyaddr(mcopy,
- IPSEC_DIR_OUTBOUND, IP_FORWARDING,
- &ipsecerror);
-
- if (sp != NULL) {
- /* count IPsec header size */
- ipsechdr = ipsec4_hdrsiz(mcopy,
- IPSEC_DIR_OUTBOUND, NULL);
-
- /*
- * find the correct route for outer IPv4
- * header, compute tunnel MTU.
- */
-
- if (sp->req != NULL
- && sp->req->sav != NULL
- && sp->req->sav->sah != NULL) {
- ro = &sp->req->sav->sah->sa_route;
- rt = rtcache_validate(ro);
- if (rt && rt->rt_ifp) {
- destmtu =
- rt->rt_rmx.rmx_mtu ?
- rt->rt_rmx.rmx_mtu :
- rt->rt_ifp->if_mtu;
- destmtu -= ipsechdr;
- }
- }
-
- KEY_FREESP(&sp);
- }
- }
-#endif /*defined(IPSEC)*/
+#ifdef IPSEC
+ (void)ipsec4_forward(mcopy, &destmtu);
+#endif
IP_STATINC(IP_STAT_CANTFRAG);
break;
Index: src/sys/netinet/ip_output.c
diff -u src/sys/netinet/ip_output.c:1.221 src/sys/netinet/ip_output.c:1.222
--- src/sys/netinet/ip_output.c:1.221 Sat Jun 8 03:26:05 2013
+++ src/sys/netinet/ip_output.c Sat Jun 8 13:50:22 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: ip_output.c,v 1.221 2013/06/08 03:26:05 rmind Exp $ */
+/* $NetBSD: ip_output.c,v 1.222 2013/06/08 13:50:22 rmind Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -91,7 +91,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_output.c,v 1.221 2013/06/08 03:26:05 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_output.c,v 1.222 2013/06/08 13:50:22 rmind Exp $");
#include "opt_pfil_hooks.h"
#include "opt_inet.h"
@@ -474,7 +474,7 @@ sendit:
ip->ip_off |= htons(IP_DF);
#ifdef IPSEC
- /* Perform IPSec processing, if any. */
+ /* Perform IPsec processing, if any. */
error = ipsec4_output(m, so, flags, &sp, &mtu, &natt_frag, &done);
if (error || done) {
goto done;
@@ -611,7 +611,7 @@ sendit:
#endif
/*
* If we get there, the packet has not been handled by
- * IPSec whereas it should have. Now that it has been
+ * IPsec whereas it should have. Now that it has been
* fragmented, re-inject it in ip_output so that IPsec
* processing can occur.
*/
Index: src/sys/netipsec/ipsec.c
diff -u src/sys/netipsec/ipsec.c:1.59 src/sys/netipsec/ipsec.c:1.60
--- src/sys/netipsec/ipsec.c:1.59 Sat Jun 8 03:26:05 2013
+++ src/sys/netipsec/ipsec.c Sat Jun 8 13:50:22 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: ipsec.c,v 1.59 2013/06/08 03:26:05 rmind Exp $ */
+/* $NetBSD: ipsec.c,v 1.60 2013/06/08 13:50:22 rmind Exp $ */
/* $FreeBSD: /usr/local/www/cvsroot/FreeBSD/src/sys/netipsec/ipsec.c,v 1.2.2.2 2003/07/01 01:38:13 sam Exp $ */
/* $KAME: ipsec.c,v 1.103 2001/05/24 07:14:18 sakane Exp $ */
@@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ipsec.c,v 1.59 2013/06/08 03:26:05 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ipsec.c,v 1.60 2013/06/08 13:50:22 rmind Exp $");
/*
* IPsec controller part.
@@ -73,6 +73,7 @@ __KERNEL_RCSID(0, "$NetBSD: ipsec.c,v 1.
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
+#include <netinet/ip_private.h>
#include <netinet/ip6.h>
#ifdef INET6
@@ -829,6 +830,110 @@ ipsec4_output(struct mbuf *m, struct soc
return error;
}
+int
+ipsec4_input(struct mbuf *m, int flags)
+{
+ struct m_tag *mtag;
+ struct tdb_ident *tdbi;
+ struct secpolicy *sp;
+ int error, s;
+
+ /*
+ * 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) {
+ splx(s);
+ return EINVAL;
+ }
+
+ /*
+ * Check security policy against packet attributes.
+ */
+ error = ipsec_in_reject(sp, m);
+ KEY_FREESP(&sp);
+ splx(s);
+ if (error) {
+ return error;
+ }
+
+ if (flags == 0) {
+ /* We are done. */
+ return 0;
+ }
+
+ /*
+ * Peek at the outbound SP for this packet to determine if
+ * it is a Fast Forward candidate.
+ */
+ mtag = m_tag_find(m, PACKET_TAG_IPSEC_PENDING_TDB, NULL);
+ if (mtag != NULL) {
+ m->m_flags &= ~M_CANFASTFWD;
+ return 0;
+ }
+
+ s = splsoftnet();
+ sp = ipsec4_checkpolicy(m, IPSEC_DIR_OUTBOUND, flags, &error, NULL);
+ if (sp != NULL) {
+ m->m_flags &= ~M_CANFASTFWD;
+ KEY_FREESP(&sp);
+ }
+ splx(s);
+ return 0;
+}
+
+int
+ipsec4_forward(struct mbuf *m, int *destmtu)
+{
+ /*
+ * If the packet is routed over IPsec tunnel, tell the
+ * originator the tunnel MTU.
+ * tunnel MTU = if MTU - sizeof(IP) - ESP/AH hdrsiz
+ * XXX quickhack!!!
+ */
+ struct secpolicy *sp;
+ size_t ipsechdr;
+ int error;
+
+ sp = ipsec4_getpolicybyaddr(m,
+ IPSEC_DIR_OUTBOUND, IP_FORWARDING, &error);
+ if (sp == NULL) {
+ return EINVAL;
+ }
+
+ /* Count IPsec header size. */
+ ipsechdr = ipsec4_hdrsiz(m, IPSEC_DIR_OUTBOUND, NULL);
+
+ /*
+ * Find the correct route for outer IPv4 header, compute tunnel MTU.
+ */
+ if (sp->req && sp->req->sav && sp->req->sav->sah) {
+ struct route *ro;
+ struct rtentry *rt;
+
+ ro = &sp->req->sav->sah->sa_route;
+ rt = rtcache_validate(ro);
+ if (rt && rt->rt_ifp) {
+ *destmtu = rt->rt_rmx.rmx_mtu ?
+ rt->rt_rmx.rmx_mtu : rt->rt_ifp->if_mtu;
+ *destmtu -= ipsechdr;
+ }
+ }
+ KEY_FREESP(&sp);
+ return 0;
+}
+
#ifdef INET6
struct secpolicy *
ipsec6_checkpolicy(struct mbuf *m, u_int dir, u_int flag, int *error,
Index: src/sys/netipsec/ipsec.h
diff -u src/sys/netipsec/ipsec.h:1.33 src/sys/netipsec/ipsec.h:1.34
--- src/sys/netipsec/ipsec.h:1.33 Sat Jun 8 03:26:05 2013
+++ src/sys/netipsec/ipsec.h Sat Jun 8 13:50:22 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: ipsec.h,v 1.33 2013/06/08 03:26:05 rmind Exp $ */
+/* $NetBSD: ipsec.h,v 1.34 2013/06/08 13:50:22 rmind Exp $ */
/* $FreeBSD: /usr/local/www/cvsroot/FreeBSD/src/sys/netipsec/ipsec.h,v 1.2.4.2 2004/02/14 22:23:23 bms Exp $ */
/* $KAME: ipsec.h,v 1.53 2001/11/20 08:32:38 itojun Exp $ */
@@ -258,6 +258,8 @@ struct secpolicy * ipsec_getpolicybyaddr
int, int *);
int ipsec4_output(struct mbuf *, struct socket *, int,
struct secpolicy **, u_long *, bool *, bool *);
+int ipsec4_input(struct mbuf *, int);
+int ipsec4_forward(struct mbuf *, int *);
static __inline struct secpolicy*
ipsec4_getpolicybysock(