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(