Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 19 Nov 2016 19:23:11 +0000 (UTC)
From:      "Andrey V. Elsukov" <ae@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r308862 - projects/ipsec/sys/netinet6
Message-ID:  <201611191923.uAJJNB2i037885@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ae
Date: Sat Nov 19 19:23:11 2016
New Revision: 308862
URL: https://svnweb.freebsd.org/changeset/base/308862

Log:
  Change ip6_ipsec_output() to return only two values 0 and 1.
  
  It returns 1 when IPSec consumes mbuf or some fatal error occured.
  In case of error it frees mbuf. When no IPSec processing is required,
  it returns zero. Also change its prototype to take mbuf pointer,
  since we don't expect that mbuf can be changed, but not consumed.
  
  Add IPSEC_OUTPUT() wrapper macro to hide call to ip6_ipsec_output().
  
  Add ipsec6_checkpolicy() function similar to ipsec4_checkpolicy().
  Also change ipsec6_process_packet() to take security policy returned by
  ipsec6_checkpolicy() instead of accessing to ipsecrequest. Add inpcb
  pointer to arguments list, it will be needed to update hdrsz field of
  struct inpcbpolicy.
  
  Move IPSEC block to the top of ip6_output() to fix possible mbufs
  leak when IPv6 extension headers are present (MAKE_EXTHDR allocates
  mbufs).

Modified:
  projects/ipsec/sys/netinet6/ip6_ipsec.c
  projects/ipsec/sys/netinet6/ip6_ipsec.h
  projects/ipsec/sys/netinet6/ip6_output.c

Modified: projects/ipsec/sys/netinet6/ip6_ipsec.c
==============================================================================
--- projects/ipsec/sys/netinet6/ip6_ipsec.c	Sat Nov 19 19:06:29 2016	(r308861)
+++ projects/ipsec/sys/netinet6/ip6_ipsec.c	Sat Nov 19 19:23:11 2016	(r308862)
@@ -141,15 +141,13 @@ ip6_ipsec_input(struct mbuf *m, int nxt)
 
 /*
  * Called from ip6_output().
- * 1 = drop packet, 0 = continue processing packet,
- * -1 = packet was reinjected and stop processing packet
+ * 0 = continue processing packet
+ * 1 = packet was consumed, stop processing
  */
-
 int
-ip6_ipsec_output(struct mbuf **m, struct inpcb *inp, int *error)
+ip6_ipsec_output(struct mbuf *m, struct inpcb *inp, int *error)
 {
 	struct secpolicy *sp;
-
 	/*
 	 * Check the security policy (SP) for the packet and, if
 	 * required, do IPsec-related processing.  There are two
@@ -159,11 +157,10 @@ ip6_ipsec_output(struct mbuf **m, struct
 	 * AH, ESP, etc. processing), there will be a tag to bypass
 	 * the lookup and related policy checking.
 	 */
-	if (m_tag_find(*m, PACKET_TAG_IPSEC_OUT_DONE, NULL) != NULL) {
-		*error = 0;
+	*error = 0;
+	if (m_tag_find(m, PACKET_TAG_IPSEC_OUT_DONE, NULL) != NULL)
 		return (0);
-	}
-	sp = ipsec4_checkpolicy(*m, IPSEC_DIR_OUTBOUND, error, inp);
+	sp = ipsec6_checkpolicy(m, inp, error);
 	/*
 	 * There are four return cases:
 	 *    sp != NULL		    apply IPsec policy
@@ -177,46 +174,35 @@ ip6_ipsec_output(struct mbuf **m, struct
 		 * this is done in the normal processing path.
 		 */
 #ifdef INET
-		if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
-			in_delayed_cksum(*m);
-			(*m)->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
+		if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
+			in_delayed_cksum(m);
+			m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
 		}
 #endif
-		if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6) {
-			in6_delayed_cksum(*m, (*m)->m_pkthdr.len - sizeof(struct ip6_hdr),
-							sizeof(struct ip6_hdr));
-			(*m)->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA_IPV6;
+		if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6) {
+			in6_delayed_cksum(m, m->m_pkthdr.len -
+			    sizeof(struct ip6_hdr), sizeof(struct ip6_hdr));
+			m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA_IPV6;
 		}
 #ifdef SCTP
-		if ((*m)->m_pkthdr.csum_flags & CSUM_SCTP_IPV6) {
-			sctp_delayed_cksum(*m, sizeof(struct ip6_hdr));
-			(*m)->m_pkthdr.csum_flags &= ~CSUM_SCTP_IPV6;
+		if (m->m_pkthdr.csum_flags & CSUM_SCTP_IPV6) {
+			sctp_delayed_cksum(m, sizeof(struct ip6_hdr));
+			m->m_pkthdr.csum_flags &= ~CSUM_SCTP_IPV6;
 		}
 #endif
 
-		/* NB: callee frees mbuf */
-		*error = ipsec6_process_packet(*m, sp->req);
-		KEY_FREESP(&sp);
+		/* NB: callee frees mbuf and releases reference to SP */
+		*error = ipsec6_process_packet(m, sp, inp);
 		if (*error == EJUSTRETURN) {
 			/*
 			 * We had a SP with a level of 'use' and no SA. We
 			 * will just continue to process the packet without
-			 * IPsec processing.
+			 * IPsec processing and return without error.
 			 */
 			*error = 0;
-			goto done;
+			return (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;
-		goto reinjected;
+		return (1);	/* mbuf consumed by IPsec */
 	} else {	/* sp == NULL */
 		if (*error != 0) {
 			/*
@@ -227,18 +213,12 @@ ip6_ipsec_output(struct mbuf **m, struct
 			 */
 			if (*error == -EINVAL)
 				*error = 0;
-			goto bad;
+			m_freem(m);
+			return (1);
 		}
 		/* No IPsec processing for this packet. */
 	}
-done:
 	return (0);
-reinjected:
-	return (-1);
-bad:
-	if (sp != NULL)
-		KEY_FREESP(&sp);
-	return (1);
 }
 
 #if 0

Modified: projects/ipsec/sys/netinet6/ip6_ipsec.h
==============================================================================
--- projects/ipsec/sys/netinet6/ip6_ipsec.h	Sat Nov 19 19:06:29 2016	(r308861)
+++ projects/ipsec/sys/netinet6/ip6_ipsec.h	Sat Nov 19 19:23:11 2016	(r308862)
@@ -32,10 +32,12 @@
 #ifndef _NETINET_IP6_IPSEC_H_
 #define _NETINET_IP6_IPSEC_H_
 
+#define	IPSEC_OUTPUT(sc, m, inp, perr)	ip6_ipsec_output((m), (inp), (perr))
+
 int	ip6_ipsec_filtertunnel(struct mbuf *);
 int	ip6_ipsec_fwd(struct mbuf *);
 int	ip6_ipsec_input(struct mbuf *, int);
-int	ip6_ipsec_output(struct mbuf **, struct inpcb *, int *);
+int	ip6_ipsec_output(struct mbuf *, struct inpcb *, int *);
 #if 0
 int	ip6_ipsec_mtu(struct mbuf *);
 #endif

Modified: projects/ipsec/sys/netinet6/ip6_output.c
==============================================================================
--- projects/ipsec/sys/netinet6/ip6_output.c	Sat Nov 19 19:06:29 2016	(r308861)
+++ projects/ipsec/sys/netinet6/ip6_output.c	Sat Nov 19 19:23:11 2016	(r308862)
@@ -335,6 +335,16 @@ ip6_output(struct mbuf *m0, struct ip6_p
 		}
 	}
 
+#ifdef IPSEC
+	/*
+	 * IPSec checking which handles several cases.
+	 * FAST IPSEC: We re-injected the packet.
+	 * XXX: need scope argument.
+	 */
+	if (IPSEC_OUTPUT(ipv6, m, inp, &error) != 0)
+		goto done;
+#endif /* IPSEC */
+
 	bzero(&exthdrs, sizeof(exthdrs));
 	if (opt) {
 		/* Hop-by-Hop options header */
@@ -359,24 +369,6 @@ ip6_output(struct mbuf *m0, struct ip6_p
 		MAKE_EXTHDR(opt->ip6po_dest2, &exthdrs.ip6e_dest2);
 	}
 
-#ifdef IPSEC
-	/*
-	 * IPSec checking which handles several cases.
-	 * FAST IPSEC: We re-injected the packet.
-	 * XXX: need scope argument.
-	 */
-	switch(ip6_ipsec_output(&m, inp, &error))
-	{
-	case 1:                 /* Bad packet */
-		goto freehdrs;
-	case -1:                /* IPSec done */
-		goto done;
-	case 0:                 /* No IPSec */
-	default:
-		break;
-	}
-#endif /* IPSEC */
-
 	/*
 	 * Calculate the total length of the extension header chain.
 	 * Keep the length of the unfragmentable part for fragmentation.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201611191923.uAJJNB2i037885>