Module Name: src Committed By: rmind Date: Sat Jun 8 03:26:05 UTC 2013
Modified Files: src/sys/netinet: ip_output.c src/sys/netipsec: ipsec.c ipsec.h Log Message: Split IPSec logic from ip_output() into a separate routine - ipsec4_output(). No change to the mechanism intended. Tested by christos@. To generate a diff of this commit: cvs rdiff -u -r1.220 -r1.221 src/sys/netinet/ip_output.c cvs rdiff -u -r1.58 -r1.59 src/sys/netipsec/ipsec.c cvs rdiff -u -r1.32 -r1.33 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_output.c diff -u src/sys/netinet/ip_output.c:1.220 src/sys/netinet/ip_output.c:1.221 --- src/sys/netinet/ip_output.c:1.220 Wed Jun 5 19:01:26 2013 +++ src/sys/netinet/ip_output.c Sat Jun 8 03:26:05 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: ip_output.c,v 1.220 2013/06/05 19:01:26 christos Exp $ */ +/* $NetBSD: ip_output.c,v 1.221 2013/06/08 03:26:05 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.220 2013/06/05 19:01:26 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ip_output.c,v 1.221 2013/06/08 03:26:05 rmind Exp $"); #include "opt_pfil_hooks.h" #include "opt_inet.h" @@ -132,12 +132,8 @@ __KERNEL_RCSID(0, "$NetBSD: ip_output.c, #include <netinet/ip_mroute.h> #endif -#ifdef IPSEC #include <netipsec/ipsec.h> #include <netipsec/key.h> -#include <netipsec/xform.h> -#endif /* IPSEC*/ - static struct mbuf *ip_insertoptions(struct mbuf *, struct mbuf *, int *); static struct ifnet *ip_multicast_if(struct in_addr *, int *); @@ -171,18 +167,14 @@ ip_output(struct mbuf *m0, ...) struct ifaddr *xifa; struct mbuf *opt; struct route *ro; - int flags, sw_csum; - int *mtu_p; + int flags, sw_csum, *mtu_p; u_long mtu; struct ip_moptions *imo; struct socket *so; va_list ap; - int natt_frag = 0; -#ifdef IPSEC - struct inpcb *inp; struct secpolicy *sp = NULL; - int s; -#endif + bool natt_frag = false; + bool __unused done = false; union { struct sockaddr dst; struct sockaddr_in dst4; @@ -205,12 +197,6 @@ ip_output(struct mbuf *m0, ...) va_end(ap); MCLAIM(m, &ip_tx_mowner); -#ifdef IPSEC - if (so != NULL && so->so_proto->pr_domain->dom_family == AF_INET) - inp = (struct inpcb *)so->so_pcb; - else - inp = NULL; -#endif /* IPSEC */ #ifdef DIAGNOSTIC if ((m->m_flags & M_PKTHDR) == 0) @@ -488,94 +474,12 @@ sendit: ip->ip_off |= htons(IP_DF); #ifdef IPSEC - /* - * Check the security policy (SP) for the packet and, if - * required, do IPsec-related processing. There are two - * cases here; the first time a packet is sent through - * it will be untagged and handled by ipsec4_checkpolicy. - * If the packet is resubmitted to ip_output (e.g. after - * AH, ESP, etc. processing), there will be a tag to bypass - * the lookup and related policy checking. - */ - if (!ipsec_outdone(m)) { - s = splsoftnet(); - if (inp != NULL && - IPSEC_PCB_SKIP_IPSEC(inp->inp_sp, IPSEC_DIR_OUTBOUND)) { - splx(s); - goto spd_done; - } - sp = ipsec4_checkpolicy(m, IPSEC_DIR_OUTBOUND, flags, - &error, inp); - /* - * There are four return cases: - * sp != NULL apply IPsec policy - * sp == NULL, error == 0 no IPsec handling needed - * sp == NULL, error == -EINVAL discard packet w/o error - * sp == NULL, error != 0 discard packet, report error - */ - if (sp != NULL) { - /* - * NAT-T ESP fragmentation: don't do IPSec processing - * now, we'll do it on each fragmented packet. - */ - if (sp->req->sav && (sp->req->sav->natt_type & - (UDP_ENCAP_ESPINUDP|UDP_ENCAP_ESPINUDP_NON_IKE))) { - if (ntohs(ip->ip_len) > sp->req->sav->esp_frag) - { - natt_frag = 1; - mtu = sp->req->sav->esp_frag; - splx(s); - goto spd_done; - } - } - - /* - * Do delayed checksums now because we send before - * this is done in the normal processing path. - */ - if (m->m_pkthdr.csum_flags & (M_CSUM_TCPv4|M_CSUM_UDPv4)) { - in_delayed_cksum(m); - m->m_pkthdr.csum_flags &= ~(M_CSUM_TCPv4|M_CSUM_UDPv4); - } - -#ifdef __FreeBSD__ - ip->ip_len = htons(ip->ip_len); - ip->ip_off = htons(ip->ip_off); -#endif - - /* NB: callee frees mbuf */ - error = ipsec4_process_packet(m, sp->req, flags, 0); - /* - * Preserve KAME behaviour: ENOENT can be returned - * when an SA acquire is in progress. Don't propagate - * this to user-level; it confuses applications. - * - * XXX this will go away when the SADB is redone. - */ - if (error == ENOENT) - error = 0; - splx(s); - goto done; - } else { - splx(s); - - if (error != 0) { - /* - * Hack: -EINVAL is used to signal that a packet - * should be silently discarded. This is typically - * because we asked key management for an SA and - * it was delayed (e.g. kicked up to IKE). - */ - if (error == -EINVAL) - error = 0; - goto bad; - } else { - /* No IPsec processing for this packet. */ - } - } + /* Perform IPSec processing, if any. */ + error = ipsec4_output(m, so, flags, &sp, &mtu, &natt_frag, &done); + if (error || done) { + goto done; } -spd_done: -#endif /* IPSEC */ +#endif #ifdef PFIL_HOOKS /* @@ -733,13 +637,12 @@ spd_done: IP_STATINC(IP_STAT_FRAGMENTED); done: rtcache_free(&iproute); - + if (sp) { #ifdef IPSEC - if (sp != NULL) KEY_FREESP(&sp); -#endif /* IPSEC */ - - return (error); +#endif + } + return error; bad: m_freem(m); goto done; Index: src/sys/netipsec/ipsec.c diff -u src/sys/netipsec/ipsec.c:1.58 src/sys/netipsec/ipsec.c:1.59 --- src/sys/netipsec/ipsec.c:1.58 Tue Jun 4 22:47:37 2013 +++ src/sys/netipsec/ipsec.c Sat Jun 8 03:26:05 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: ipsec.c,v 1.58 2013/06/04 22:47:37 christos Exp $ */ +/* $NetBSD: ipsec.c,v 1.59 2013/06/08 03:26:05 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.58 2013/06/04 22:47:37 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ipsec.c,v 1.59 2013/06/08 03:26:05 rmind Exp $"); /* * IPsec controller part. @@ -733,6 +733,102 @@ ipsec4_checkpolicy(struct mbuf *m, u_int return sp; } +int +ipsec4_output(struct mbuf *m, struct socket *so, int flags, + struct secpolicy **sp_out, u_long *mtu, bool *natt_frag, bool *done) +{ + const struct ip *ip = mtod(m, const struct ip *); + struct secpolicy *sp = NULL; + struct inpcb *inp; + int error, s; + + inp = (so && so->so_proto->pr_domain->dom_family == AF_INET) ? + (struct inpcb *)so->so_pcb : NULL; + + /* + * Check the security policy (SP) for the packet and, if required, + * do IPsec-related processing. There are two cases here; the first + * time a packet is sent through it will be untagged and handled by + * ipsec4_checkpolicy(). If the packet is resubmitted to ip_output + * (e.g. after AH, ESP, etc. processing), there will be a tag to + * bypass the lookup and related policy checking. + */ + if (ipsec_outdone(m)) { + return 0; + } + s = splsoftnet(); + if (inp && IPSEC_PCB_SKIP_IPSEC(inp->inp_sp, IPSEC_DIR_OUTBOUND)) { + splx(s); + return 0; + } + sp = ipsec4_checkpolicy(m, IPSEC_DIR_OUTBOUND, flags, &error, inp); + + /* + * There are four return cases: + * sp != NULL apply IPsec policy + * sp == NULL, error == 0 no IPsec handling needed + * sp == NULL, error == -EINVAL discard packet w/o error + * sp == NULL, error != 0 discard packet, report error + */ + if (sp == NULL) { + splx(s); + if (error) { + /* + * Hack: -EINVAL is used to signal that a packet + * should be silently discarded. This is typically + * because we asked key management for an SA and + * it was delayed (e.g. kicked up to IKE). + */ + if (error == -EINVAL) + error = 0; + m_freem(m); + *done = true; + return error; + } + /* No IPsec processing for this packet. */ + return 0; + } + *sp_out = sp; + + /* + * NAT-T ESP fragmentation: do not do IPSec processing now, + * we will do it on each fragmented packet. + */ + if (sp->req->sav && (sp->req->sav->natt_type & + (UDP_ENCAP_ESPINUDP|UDP_ENCAP_ESPINUDP_NON_IKE))) { + if (ntohs(ip->ip_len) > sp->req->sav->esp_frag) { + *mtu = sp->req->sav->esp_frag; + *natt_frag = true; + splx(s); + return 0; + } + } + + /* + * Do delayed checksums now because we send before + * this is done in the normal processing path. + */ + if (m->m_pkthdr.csum_flags & (M_CSUM_TCPv4|M_CSUM_UDPv4)) { + in_delayed_cksum(m); + m->m_pkthdr.csum_flags &= ~(M_CSUM_TCPv4|M_CSUM_UDPv4); + } + + /* Note: callee frees mbuf */ + error = ipsec4_process_packet(m, sp->req, flags, 0); + /* + * Preserve KAME behaviour: ENOENT can be returned + * when an SA acquire is in progress. Don't propagate + * this to user-level; it confuses applications. + * + * XXX this will go away when the SADB is redone. + */ + if (error == ENOENT) + error = 0; + splx(s); + *done = true; + return error; +} + #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.32 src/sys/netipsec/ipsec.h:1.33 --- src/sys/netipsec/ipsec.h:1.32 Tue Jun 4 22:47:37 2013 +++ src/sys/netipsec/ipsec.h Sat Jun 8 03:26:05 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: ipsec.h,v 1.32 2013/06/04 22:47:37 christos Exp $ */ +/* $NetBSD: ipsec.h,v 1.33 2013/06/08 03:26:05 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 $ */ @@ -256,7 +256,8 @@ struct secpolicy *ipsec4_checkpolicy (st int *, struct inpcb *); struct secpolicy * ipsec_getpolicybyaddr(struct mbuf *, u_int, int, int *); - +int ipsec4_output(struct mbuf *, struct socket *, int, + struct secpolicy **, u_long *, bool *, bool *); static __inline struct secpolicy* ipsec4_getpolicybysock(