Split IPsec code in ip_input() and ip_forward() into the separate routines

ipsec4_input() and ipsec4_forward().  Tested by christos@.
This commit is contained in:
rmind 2013-06-08 13:50:22 +00:00
parent 415d109c2c
commit 7cb08cfdd0
4 changed files with 130 additions and 142 deletions

View File

@ -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 1.304 2013/06/05 19:01:26 christos Exp
#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*/
/* Perform IPsec, if any. */
if (ipsec4_input(m, IP_FORWARDING | (ip_directedbcast ?
IP_ALLOWBROADCAST : 0)) != 0) {
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);
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;

View File

@ -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.
*/

View File

@ -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.59 2013/06/08 03:26:05 rmind Exp $");
#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 socket *so, int flags,
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,

View File

@ -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(struct mbuf *, u_int,
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(