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:
parent
415d109c2c
commit
7cb08cfdd0
@ -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;
|
||||
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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,
|
||||
|
@ -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(
|
||||
|
Loading…
Reference in New Issue
Block a user