From nobody@FreeBSD.org  Tue Jun 26 09:26:38 2012
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52])
	by hub.freebsd.org (Postfix) with ESMTP id 430721065672
	for <freebsd-gnats-submit@FreeBSD.org>; Tue, 26 Jun 2012 09:26:38 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from red.freebsd.org (red.freebsd.org [IPv6:2001:4f8:fff6::22])
	by mx1.freebsd.org (Postfix) with ESMTP id 2E63A8FC0A
	for <freebsd-gnats-submit@FreeBSD.org>; Tue, 26 Jun 2012 09:26:38 +0000 (UTC)
Received: from red.freebsd.org (localhost [127.0.0.1])
	by red.freebsd.org (8.14.4/8.14.4) with ESMTP id q5Q9QcF4030159
	for <freebsd-gnats-submit@FreeBSD.org>; Tue, 26 Jun 2012 09:26:38 GMT
	(envelope-from nobody@red.freebsd.org)
Received: (from nobody@localhost)
	by red.freebsd.org (8.14.4/8.14.4/Submit) id q5Q9QbZn030158;
	Tue, 26 Jun 2012 09:26:37 GMT
	(envelope-from nobody)
Message-Id: <201206260926.q5Q9QbZn030158@red.freebsd.org>
Date: Tue, 26 Jun 2012 09:26:37 GMT
From: Sakuma Takayuki <sakuma.takayuki@jp.fujitsu.com>
To: freebsd-gnats-submit@FreeBSD.org
Subject: [ipsec] ipv4-in-ipv6 tunnel mode IPsec does not work
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         169438
>Category:       kern
>Synopsis:       [ipsec] ipv4-in-ipv6 tunnel mode IPsec does not work
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    vanhu
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Jun 26 09:30:07 UTC 2012
>Closed-Date:    Wed May 28 12:48:37 UTC 2014
>Last-Modified:  Wed May 28 12:50:00 UTC 2014
>Originator:     Sakuma Takayuki
>Release:        9.0-RELEASE
>Organization:
>Environment:
FreeBSD freebsd9 9.0-RELEASE FreeBSD 9.0-RELEASE #2: Tue Jun 26 17:01:53 JST 2012     root@freebsd9:/sys/i386/compile/IPSEC  i386
>Description:
Sending IPv4 packet by tunnel mode IPsec of IPv6 transport does not work.
No packet is sent.
>How-To-Repeat:
set SPD and SAD by 'setkey -c' as follows:

spdadd 192.0.2.1/32[any] 198.51.100.1/32[any] any -P out ipsec esp/tunnel/2001:db8:c000:200::1-2001:db8:c633:6400::1/require;
add 2001:db8:c000:200::2 2001:db8:c633:6400::1 esp 0x10001 -m tunnel -E des-cbc 0x2001db8c000ffff;

interface address and routes are set up appropriately.
>Fix:
quick hack:

*** sys/netipsec/ipsec_output.c.orig    2012-06-26 18:25:11.000000000 +0900
--- sys/netipsec/ipsec_output.c 2012-06-26 17:01:38.000000000 +0900
***************
*** 575,582 ****
         */
        if (sav->tdb_xform->xf_type != XF_IP4) {
                ip = mtod(m, struct ip *);
!               i = ip->ip_hl << 2;
!               off = offsetof(struct ip, ip_p);
                error = (*sav->tdb_xform->xf_output)(m, isr, NULL, i, off);
        } else {
                error = ipsec_process_done(m, isr);
--- 575,587 ----
         */
        if (sav->tdb_xform->xf_type != XF_IP4) {
                ip = mtod(m, struct ip *);
!               if (ip->ip_v == 6) {
!                       i = sizeof(struct ip6_hdr);
!                       off = offsetof(struct ip6_hdr, ip6_nxt);
!               } else {
!                       i = ip->ip_hl << 2;
!                       off = offsetof(struct ip, ip_p);
!               }
                error = (*sav->tdb_xform->xf_output)(m, isr, NULL, i, off);
        } else {
                error = ipsec_process_done(m, isr);


>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->freebsd-net 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Wed Jun 27 03:43:04 UTC 2012 
Responsible-Changed-Why:  

Over to maintainer(s). 

http://www.freebsd.org/cgi/query-pr.cgi?pr=169438 

From: George Kontostanos <gkontos.mail@gmail.com>
To: bug-followup@FreeBSD.org, sakuma.takayuki@jp.fujitsu.com
Cc:  
Subject: re:kern/169438: [ipsec] ipv4-in-ipv6 tunnel mode IPsec does not work
Date: Thu, 31 Jan 2013 17:44:39 +0200

 I am facing the same problem in 2 FreeBSD 9.1 boxes. I was wondering
 if this has been resolved or if there is an patch for this.
 
 Thanks
 
 -- 
 George Kontostanos
 ---
 http://www.aisecure.net
Responsible-Changed-From-To: freebsd-net->vanhu 
Responsible-Changed-By: vanhu 
Responsible-Changed-When: jeu 30 jan 2014 09:34:17 UTC 
Responsible-Changed-Why:  
Hi. 

Your hack solves the issue for ipv4-in-ipv6, but the same issue exists 
for ipv6-in-ipv4, and requires some more refactoring of the code. 

We're working on such a patch for both ways, and I hope we'll have a version 
ready to commit within the next few weeks. 


http://www.freebsd.org/cgi/query-pr.cgi?pr=169438 
State-Changed-From-To: open->closed 
State-Changed-By: vanhu 
State-Changed-When: Wed May 28 12:46:15 UTC 2014 
State-Changed-Why:  
Fixed for both IPv4-in-IPv6 and IPv6-in-IPv4 


http://www.freebsd.org/cgi/query-pr.cgi?pr=169438 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/169438: commit references a PR
Date: Wed, 28 May 2014 12:45:34 +0000 (UTC)

 Author: vanhu
 Date: Wed May 28 12:45:27 2014
 New Revision: 266800
 URL: http://svnweb.freebsd.org/changeset/base/266800
 
 Log:
   Fixed IPv4-in-IPv6 and IPv6-in-IPv4 IPsec tunnels.
   For IPv6-in-IPv4, you may need to do the following command
   on the tunnel interface if it is configured as IPv4 only:
   ifconfig <interface> inet6 -ifdisabled
   
   Code logic inspired from NetBSD.
   
   PR: kern/169438
   Submitted by: emeric.poupon@netasq.com
   Reviewed by: fabient, ae
   Obtained from: NETASQ
 
 Modified:
   head/sys/netinet6/ip6_forward.c
   head/sys/netinet6/ip6_ipsec.c
   head/sys/netinet6/ip6_ipsec.h
   head/sys/netinet6/ip6_output.c
   head/sys/netinet6/ip6_var.h
   head/sys/netipsec/ipsec6.h
   head/sys/netipsec/ipsec_input.c
   head/sys/netipsec/ipsec_output.c
   head/sys/netipsec/xform_ipip.c
 
 Modified: head/sys/netinet6/ip6_forward.c
 ==============================================================================
 --- head/sys/netinet6/ip6_forward.c	Wed May 28 12:32:07 2014	(r266799)
 +++ head/sys/netinet6/ip6_forward.c	Wed May 28 12:45:27 2014	(r266800)
 @@ -252,7 +252,6 @@ ip6_forward(struct mbuf *m, int srcrt)
  
      {
  	struct ipsecrequest *isr = NULL;
 -	struct ipsec_output_state state;
  
  	/*
  	 * when the kernel forwards a packet, it is not proper to apply
 @@ -285,18 +284,27 @@ ip6_forward(struct mbuf *m, int srcrt)
  	 *
  	 * IPv6 [ESP|AH] IPv6 [extension headers] payload
  	 */
 -	bzero(&state, sizeof(state));
 -	state.m = m;
 -	state.ro = NULL;	/* update at ipsec6_output_tunnel() */
 -	state.dst = NULL;	/* update at ipsec6_output_tunnel() */
  
 -	error = ipsec6_output_tunnel(&state, sp, 0);
 +	/*
 +	 * If we need to encapsulate the packet, do it here
 +	 * ipsec6_proces_packet will send the packet using ip6_output
 +	 */
 +	error = ipsec6_process_packet(m, sp->req);
  
 -	m = state.m;
  	KEY_FREESP(&sp);
  
 +	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.
 +		 */
 +		error = 0;
 +		goto skip_ipsec;
 +	}
 +
  	if (error) {
 -		/* mbuf is already reclaimed in ipsec6_output_tunnel. */
 +		/* mbuf is already reclaimed in ipsec6_process_packet. */
  		switch (error) {
  		case EHOSTUNREACH:
  		case ENETUNREACH:
 @@ -319,7 +327,6 @@ ip6_forward(struct mbuf *m, int srcrt)
  			m_freem(mcopy);
  #endif
  		}
 -		m_freem(m);
  		return;
  	} else {
  		/*
 @@ -331,25 +338,7 @@ ip6_forward(struct mbuf *m, int srcrt)
  		m = NULL;
  		goto freecopy;
  	}
 -
 -	if ((m != NULL) && (ip6 != mtod(m, struct ip6_hdr *)) ){
 -		/*
 -		 * now tunnel mode headers are added.  we are originating
 -		 * packet instead of forwarding the packet.
 -		 */
 -		ip6_output(m, NULL, NULL, IPV6_FORWARDING/*XXX*/, NULL, NULL,
 -		    NULL);
 -		goto freecopy;
 -	}
 -
 -	/* adjust pointer */
 -	dst = (struct sockaddr_in6 *)state.dst;
 -	rt = state.ro ? state.ro->ro_rt : NULL;
 -	if (dst != NULL && rt != NULL)
 -		ipsecrt = 1;
      }
 -	if (ipsecrt)
 -		goto skip_routing;
  skip_ipsec:
  #endif
  again:
 @@ -372,9 +361,6 @@ again2:
  		goto bad;
  	}
  	rt = rin6.ro_rt;
 -#ifdef IPSEC
 -skip_routing:
 -#endif
  
  	/*
  	 * Source scope check: if a packet can't be delivered to its
 
 Modified: head/sys/netinet6/ip6_ipsec.c
 ==============================================================================
 --- head/sys/netinet6/ip6_ipsec.c	Wed May 28 12:32:07 2014	(r266799)
 +++ head/sys/netinet6/ip6_ipsec.c	Wed May 28 12:45:27 2014	(r266800)
 @@ -221,23 +221,22 @@ ip6_ipsec_input(struct mbuf *m, int nxt)
  
  int
  ip6_ipsec_output(struct mbuf **m, struct inpcb *inp, int *flags, int *error,
 -    struct ifnet **ifp, struct secpolicy **sp)
 +    struct ifnet **ifp)
  {
  #ifdef IPSEC
 +	struct secpolicy *sp = NULL;
  	struct tdb_ident *tdbi;
  	struct m_tag *mtag;
  	/* XXX int s; */
 -	if (sp == NULL)
 -		return 1;
  	mtag = m_tag_find(*m, PACKET_TAG_IPSEC_PENDING_TDB, NULL);
  	if (mtag != NULL) {
  		tdbi = (struct tdb_ident *)(mtag + 1);
 -		*sp = ipsec_getpolicy(tdbi, IPSEC_DIR_OUTBOUND);
 -		if (*sp == NULL)
 +		sp = ipsec_getpolicy(tdbi, IPSEC_DIR_OUTBOUND);
 +		if (sp == NULL)
  			*error = -EINVAL;	/* force silent drop */
  		m_tag_delete(*m, mtag);
  	} else {
 -		*sp = ipsec4_checkpolicy(*m, IPSEC_DIR_OUTBOUND, *flags,
 +		sp = ipsec4_checkpolicy(*m, IPSEC_DIR_OUTBOUND, *flags,
  					error, inp);
  	}
  
 @@ -248,9 +247,9 @@ ip6_ipsec_output(struct mbuf **m, struct
  	 *    sp == NULL, error == -EINVAL  discard packet w/o error
  	 *    sp == NULL, error != 0	    discard packet, report error
  	 */
 -	if (*sp != NULL) {
 +	if (sp != NULL) {
  		/* Loop detection, check if ipsec processing already done */
 -		KASSERT((*sp)->req != NULL, ("ip_output: no ipsec request"));
 +		KASSERT(sp->req != NULL, ("ip_output: no ipsec request"));
  		for (mtag = m_tag_first(*m); mtag != NULL;
  		     mtag = m_tag_next(*m, mtag)) {
  			if (mtag->m_tag_cookie != MTAG_ABI_COMPAT)
 @@ -264,12 +263,12 @@ ip6_ipsec_output(struct mbuf **m, struct
  			 * an SA; e.g. on first reference.  If it occurs,
  			 * then we let ipsec4_process_packet do its thing.
  			 */
 -			if ((*sp)->req->sav == NULL)
 +			if (sp->req->sav == NULL)
  				break;
  			tdbi = (struct tdb_ident *)(mtag + 1);
 -			if (tdbi->spi == (*sp)->req->sav->spi &&
 -			    tdbi->proto == (*sp)->req->sav->sah->saidx.proto &&
 -			    bcmp(&tdbi->dst, &(*sp)->req->sav->sah->saidx.dst,
 +			if (tdbi->spi == sp->req->sav->spi &&
 +			    tdbi->proto == sp->req->sav->sah->saidx.proto &&
 +			    bcmp(&tdbi->dst, &sp->req->sav->sah->saidx.dst,
  				 sizeof (union sockaddr_union)) == 0) {
  				/*
  				 * No IPsec processing is needed, free
 @@ -278,7 +277,7 @@ ip6_ipsec_output(struct mbuf **m, struct
  				 * NB: null pointer to avoid free at
  				 *     done: below.
  				 */
 -				KEY_FREESP(sp), *sp = NULL;
 +				KEY_FREESP(&sp), sp = NULL;
  				goto done;
  			}
  		}
 @@ -286,16 +285,37 @@ ip6_ipsec_output(struct mbuf **m, struct
  		/*
  		 * Do delayed checksums now because we send before
  		 * this is done in the normal processing path.
 -		 * For IPv6 we do delayed checksums in ip6_output.c.
  		 */
  #ifdef INET
  		if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
 -			ipseclog((LOG_DEBUG,
 -			    "%s: we do not support IPv4 over IPv6", __func__));
  			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;
 +		}
 +#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;
 +		}
 +#endif
 +
 +		/* NB: callee frees mbuf */
 +		*error = ipsec6_process_packet(*m, sp->req);
 +
 +		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.
 +			 */
 +			*error = 0;
 +			goto done;
 +		}
  
  		/*
  		 * Preserve KAME behaviour: ENOENT can be returned
 @@ -306,7 +326,7 @@ ip6_ipsec_output(struct mbuf **m, struct
  		 */
  		if (*error == ENOENT)
  			*error = 0;
 -		goto do_ipsec;
 +		goto reinjected;
  	} else {	/* sp == NULL */
  		if (*error != 0) {
  			/*
 @@ -323,10 +343,16 @@ ip6_ipsec_output(struct mbuf **m, struct
  		}
  	}
  done:
 +	if (sp != NULL)
 +		KEY_FREESP(&sp);
  	return 0;
 -do_ipsec:
 +reinjected:
 +	if (sp != NULL)
 +		KEY_FREESP(&sp);
  	return -1;
  bad:
 +	if (sp != NULL)
 +		KEY_FREESP(&sp);
  	return 1;
  #endif /* IPSEC */
  	return 0;
 
 Modified: head/sys/netinet6/ip6_ipsec.h
 ==============================================================================
 --- head/sys/netinet6/ip6_ipsec.h	Wed May 28 12:32:07 2014	(r266799)
 +++ head/sys/netinet6/ip6_ipsec.h	Wed May 28 12:45:27 2014	(r266800)
 @@ -36,7 +36,7 @@ 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 *,
 -	    struct ifnet **, struct secpolicy **sp);
 +	    struct ifnet **);
  #if 0
  int	ip6_ipsec_mtu(struct mbuf *);
  #endif
 
 Modified: head/sys/netinet6/ip6_output.c
 ==============================================================================
 --- head/sys/netinet6/ip6_output.c	Wed May 28 12:32:07 2014	(r266799)
 +++ head/sys/netinet6/ip6_output.c	Wed May 28 12:45:27 2014	(r266800)
 @@ -185,7 +185,7 @@ static int copypktopts(struct ip6_pktopt
  	}\
      } while (/*CONSTCOND*/ 0)
  
 -static void
 +void
  in6_delayed_cksum(struct mbuf *m, uint32_t plen, u_short offset)
  {
  	u_short csum;
 @@ -249,15 +249,7 @@ ip6_output(struct mbuf *m0, struct ip6_p
  	u_int32_t zone;
  	struct route_in6 *ro_pmtu = NULL;
  	int hdrsplit = 0;
 -	int needipsec = 0;
  	int sw_csum, tso;
 -#ifdef IPSEC
 -	struct ipsec_output_state state;
 -	struct ip6_rthdr *rh = NULL;
 -	int needipsectun = 0;
 -	int segleft_org = 0;
 -	struct secpolicy *sp = NULL;
 -#endif /* IPSEC */
  	struct m_tag *fwd_tag = NULL;
  
  	ip6 = mtod(m, struct ip6_hdr *);
 @@ -299,26 +291,12 @@ ip6_output(struct mbuf *m0, struct ip6_p
  	 * IPSec checking which handles several cases.
  	 * FAST IPSEC: We re-injected the packet.
  	 */
 -	switch(ip6_ipsec_output(&m, inp, &flags, &error, &ifp, &sp))
 +	switch(ip6_ipsec_output(&m, inp, &flags, &error, &ifp))
  	{
  	case 1:                 /* Bad packet */
  		goto freehdrs;
 -	case -1:                /* Do IPSec */
 -		needipsec = 1;
 -		/*
 -		 * Do delayed checksums now, as we may send before returning.
 -		 */
 -		if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6) {
 -			plen = m->m_pkthdr.len - sizeof(*ip6);
 -			in6_delayed_cksum(m, plen, 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;
 -		}
 -#endif
 +	case -1:                /* IPSec done */
 +		goto done;
  	case 0:                 /* No IPSec */
  	default:
  		break;
 @@ -338,15 +316,15 @@ ip6_output(struct mbuf *m0, struct ip6_p
  		optlen += exthdrs.ip6e_rthdr->m_len;
  	unfragpartlen = optlen + sizeof(struct ip6_hdr);
  
 -	/* NOTE: we don't add AH/ESP length here. do that later. */
 +	/* NOTE: we don't add AH/ESP length here (done in ip6_ipsec_output) */
  	if (exthdrs.ip6e_dest2)
  		optlen += exthdrs.ip6e_dest2->m_len;
  
  	/*
 -	 * If we need IPsec, or there is at least one extension header,
 +	 * If there is at least one extension header,
  	 * separate IP6 header from the payload.
  	 */
 -	if ((needipsec || optlen) && !hdrsplit) {
 +	if (optlen && !hdrsplit) {
  		if ((error = ip6_splithdr(m, &exthdrs)) != 0) {
  			m = NULL;
  			goto freehdrs;
 @@ -421,72 +399,6 @@ ip6_output(struct mbuf *m0, struct ip6_p
  	MAKE_CHAIN(exthdrs.ip6e_rthdr, mprev, nexthdrp,
  		   IPPROTO_ROUTING);
  
 -#ifdef IPSEC
 -	if (!needipsec)
 -		goto skip_ipsec2;
 -
 -	/*
 -	 * pointers after IPsec headers are not valid any more.
 -	 * other pointers need a great care too.
 -	 * (IPsec routines should not mangle mbufs prior to AH/ESP)
 -	 */
 -	exthdrs.ip6e_dest2 = NULL;
 -
 -	if (exthdrs.ip6e_rthdr) {
 -		rh = mtod(exthdrs.ip6e_rthdr, struct ip6_rthdr *);
 -		segleft_org = rh->ip6r_segleft;
 -		rh->ip6r_segleft = 0;
 -	}
 -
 -	bzero(&state, sizeof(state));
 -	state.m = m;
 -	error = ipsec6_output_trans(&state, nexthdrp, mprev, sp, flags,
 -				    &needipsectun);
 -	m = state.m;
 -	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.
 -		 */
 -		;
 -	} else if (error) {
 -		/* mbuf is already reclaimed in ipsec6_output_trans. */
 -		m = NULL;
 -		switch (error) {
 -		case EHOSTUNREACH:
 -		case ENETUNREACH:
 -		case EMSGSIZE:
 -		case ENOBUFS:
 -		case ENOMEM:
 -			break;
 -		default:
 -			printf("[%s:%d] (ipsec): error code %d\n",
 -			    __func__, __LINE__, error);
 -			/* FALLTHROUGH */
 -		case ENOENT:
 -			/* don't show these error codes to the user */
 -			error = 0;
 -			break;
 -		}
 -		goto bad;
 -	} else if (!needipsectun) {
 -		/*
 -		 * In the FAST IPSec case we have already
 -		 * re-injected the packet and it has been freed
 -		 * by the ipsec_done() function.  So, just clean
 -		 * up after ourselves.
 -		 */
 -		m = NULL;
 -		goto done;
 -	}
 -	if (exthdrs.ip6e_rthdr) {
 -		/* ah6_output doesn't modify mbuf chain */
 -		rh->ip6r_segleft = segleft_org;
 -	}
 -skip_ipsec2:;
 -#endif /* IPSEC */
 -
  	/*
  	 * If there is a routing header, discard the packet.
  	 */
 @@ -552,77 +464,6 @@ again:
  			ip6->ip6_hlim = V_ip6_defmcasthlim;
  	}
  
 -#ifdef IPSEC
 -	/*
 -	 * We may re-inject packets into the stack here.
 -	 */
 -	if (needipsec && needipsectun) {
 -		struct ipsec_output_state state;
 -
 -		/*
 -		 * All the extension headers will become inaccessible
 -		 * (since they can be encrypted).
 -		 * Don't panic, we need no more updates to extension headers
 -		 * on inner IPv6 packet (since they are now encapsulated).
 -		 *
 -		 * IPv6 [ESP|AH] IPv6 [extension headers] payload
 -		 */
 -		bzero(&exthdrs, sizeof(exthdrs));
 -		exthdrs.ip6e_ip6 = m;
 -
 -		bzero(&state, sizeof(state));
 -		state.m = m;
 -		state.ro = (struct route *)ro;
 -		state.dst = (struct sockaddr *)dst;
 -
 -		error = ipsec6_output_tunnel(&state, sp, flags);
 -
 -		m = state.m;
 -		ro = (struct route_in6 *)state.ro;
 -		dst = (struct sockaddr_in6 *)state.dst;
 -		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.
 -			 */
 -			;
 -		} else if (error) {
 -			/* mbuf is already reclaimed in ipsec6_output_tunnel. */
 -			m0 = m = NULL;
 -			m = NULL;
 -			switch (error) {
 -			case EHOSTUNREACH:
 -			case ENETUNREACH:
 -			case EMSGSIZE:
 -			case ENOBUFS:
 -			case ENOMEM:
 -				break;
 -			default:
 -				printf("[%s:%d] (ipsec): error code %d\n",
 -				    __func__, __LINE__, error);
 -				/* FALLTHROUGH */
 -			case ENOENT:
 -				/* don't show these error codes to the user */
 -				error = 0;
 -				break;
 -			}
 -			goto bad;
 -		} else {
 -			/*
 -			 * In the FAST IPSec case we have already
 -			 * re-injected the packet and it has been freed
 -			 * by the ipsec_done() function.  So, just clean
 -			 * up after ourselves.
 -			 */
 -			m = NULL;
 -			goto done;
 -		}
 -
 -		exthdrs.ip6e_ip6 = m;
 -	}
 -#endif /* IPSEC */
 -
  	/* adjust pointer */
  	ip6 = mtod(m, struct ip6_hdr *);
  
 @@ -1185,11 +1026,6 @@ done:
  		RO_RTFREE(ro);
  	if (ro_pmtu == &ip6route)
  		RO_RTFREE(ro_pmtu);
 -#ifdef IPSEC
 -	if (sp != NULL)
 -		KEY_FREESP(&sp);
 -#endif
 -
  	return (error);
  
  freehdrs:
 
 Modified: head/sys/netinet6/ip6_var.h
 ==============================================================================
 --- head/sys/netinet6/ip6_var.h	Wed May 28 12:32:07 2014	(r266799)
 +++ head/sys/netinet6/ip6_var.h	Wed May 28 12:45:27 2014	(r266800)
 @@ -456,6 +456,7 @@ int	in6_selectroute_fib(struct sockaddr_
  	    struct rtentry **, u_int);
  u_int32_t ip6_randomid(void);
  u_int32_t ip6_randomflowlabel(void);
 +void in6_delayed_cksum(struct mbuf *m, uint32_t plen, u_short offset);
  #endif /* _KERNEL */
  
  #endif /* !_NETINET6_IP6_VAR_H_ */
 
 Modified: head/sys/netipsec/ipsec6.h
 ==============================================================================
 --- head/sys/netipsec/ipsec6.h	Wed May 28 12:32:07 2014	(r266799)
 +++ head/sys/netipsec/ipsec6.h	Wed May 28 12:45:27 2014	(r266800)
 @@ -76,6 +76,7 @@ extern int ipsec6_output_trans __P((stru
  	struct mbuf *, struct secpolicy *, int, int *));
  extern int ipsec6_output_tunnel __P((struct ipsec_output_state *,
  	struct secpolicy *, int));
 +extern int ipsec6_process_packet(struct mbuf *, struct ipsecrequest *);
  #endif /*_KERNEL*/
  
  #endif /*_NETIPSEC_IPSEC6_H_*/
 
 Modified: head/sys/netipsec/ipsec_input.c
 ==============================================================================
 --- head/sys/netipsec/ipsec_input.c	Wed May 28 12:32:07 2014	(r266799)
 +++ head/sys/netipsec/ipsec_input.c	Wed May 28 12:45:27 2014	(r266800)
 @@ -296,7 +296,7 @@ int
  ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav,
  			int skip, int protoff, struct m_tag *mt)
  {
 -	int prot, af, sproto;
 +	int prot, af, sproto, isr_prot;
  	struct ip *ip;
  	struct m_tag *mtag;
  	struct tdb_ident *tdbi;
 @@ -350,20 +350,33 @@ ipsec4_common_input_cb(struct mbuf *m, s
  	}
  	prot = ip->ip_p;
  
 -#ifdef notyet
 +#ifdef DEV_ENC
 +	encif->if_ipackets++;
 +	encif->if_ibytes += m->m_pkthdr.len;
 +
 +	/*
 +	 * Pass the mbuf to enc0 for bpf and pfil. We will filter the IPIP
 +	 * packet later after it has been decapsulated.
 +	 */
 +	ipsec_bpf(m, sav, AF_INET, ENC_IN|ENC_BEFORE);
 +
 +	if (prot != IPPROTO_IPIP)
 +		if ((error = ipsec_filter(&m, PFIL_IN, ENC_IN|ENC_BEFORE)) != 0)
 +			return (error);
 +#endif /* DEV_ENC */
 +
  	/* IP-in-IP encapsulation */
  	if (prot == IPPROTO_IPIP) {
 -		struct ip ipn;
  
  		if (m->m_pkthdr.len - skip < sizeof(struct ip)) {
  			IPSEC_ISTAT(sproto, hdrops);
  			error = EINVAL;
  			goto bad;
  		}
 -		/* ipn will now contain the inner IPv4 header */
 -		m_copydata(m, ip->ip_hl << 2, sizeof(struct ip),
 -		    (caddr_t) &ipn);
 +		/* enc0: strip outer IPv4 header */
 +		m_striphdr(m, 0, ip->ip_hl << 2);
  
 +#ifdef notyet
  		/* XXX PROXY address isn't recorded in SAH */
  		/*
  		 * Check that the inner source address is the same as
 @@ -389,21 +402,20 @@ ipsec4_common_input_cb(struct mbuf *m, s
  			error = EACCES;
  			goto bad;
  		}
 +#endif /* notyet */
  	}
  #ifdef INET6
  	/* IPv6-in-IP encapsulation. */
  	if (prot == IPPROTO_IPV6) {
 -		struct ip6_hdr ip6n;
  
  		if (m->m_pkthdr.len - skip < sizeof(struct ip6_hdr)) {
  			IPSEC_ISTAT(sproto, hdrops);
  			error = EINVAL;
  			goto bad;
  		}
 -		/* ip6n will now contain the inner IPv6 header. */
 -		m_copydata(m, ip->ip_hl << 2, sizeof(struct ip6_hdr),
 -		    (caddr_t) &ip6n);
 -
 +		/* enc0: strip IPv4 header, keep IPv6 header only */
 +		m_striphdr(m, 0, ip->ip_hl << 2);
 +#ifdef notyet 
  		/*
  		 * Check that the inner source address is the same as
  		 * the proxy address, if available.
 @@ -427,9 +439,9 @@ ipsec4_common_input_cb(struct mbuf *m, s
  			error = EACCES;
  			goto bad;
  		}
 +#endif /* notyet */
  	}
  #endif /* INET6 */
 -#endif /*XXX*/
  
  	/*
  	 * Record what we've done to the packet (under what SA it was
 @@ -466,24 +478,43 @@ ipsec4_common_input_cb(struct mbuf *m, s
  	key_sa_recordxfer(sav, m);		/* record data transfer */
  
  #ifdef DEV_ENC
 -	encif->if_ipackets++;
 -	encif->if_ibytes += m->m_pkthdr.len;
 -
  	/*
 -	 * Pass the mbuf to enc0 for bpf and pfil. We will filter the IPIP
 -	 * packet later after it has been decapsulated.
 +	 * Pass the mbuf to enc0 for bpf and pfil.
  	 */
 -	ipsec_bpf(m, sav, AF_INET, ENC_IN|ENC_BEFORE);
 -
 -	if (prot != IPPROTO_IPIP)
 -		if ((error = ipsec_filter(&m, PFIL_IN, ENC_IN|ENC_BEFORE)) != 0)
 -			return (error);
 +	if (prot == IPPROTO_IPIP)
 +		ipsec_bpf(m, sav, AF_INET, ENC_IN|ENC_AFTER);
 +#ifdef INET6
 +	if (prot == IPPROTO_IPV6)
 +		ipsec_bpf(m, sav, AF_INET6, ENC_IN|ENC_AFTER);
  #endif
  
 +	if ((error = ipsec_filter(&m, PFIL_IN, ENC_IN|ENC_AFTER)) != 0)
 +		return (error);
 +#endif /* DEV_ENC */
 +
  	/*
  	 * Re-dispatch via software interrupt.
  	 */
 -	if ((error = netisr_queue_src(NETISR_IP, (uintptr_t)sav->spi, m))) {
 +
 +	switch (prot) {
 +	case IPPROTO_IPIP:
 +		isr_prot = NETISR_IP;
 +		break;
 +#ifdef INET6
 +	case IPPROTO_IPV6:
 +		isr_prot = NETISR_IPV6;
 +		break;
 +#endif
 +	default:
 +		DPRINTF(("%s: cannot handle inner ip proto %d\n",
 +			    __func__, prot));
 +		IPSEC_ISTAT(sproto, nopf);
 +		error = EPFNOSUPPORT;
 +		goto bad;
 +	}
 +
 +	error = netisr_queue_src(isr_prot, (uintptr_t)sav->spi, m);
 +	if (error) {
  		IPSEC_ISTAT(sproto, qfull);
  		DPRINTF(("%s: queue full; proto %u packet dropped\n",
  			__func__, sproto));
 @@ -606,20 +637,34 @@ ipsec6_common_input_cb(struct mbuf *m, s
  	prot = 0;
  	m_copydata(m, protoff, 1, (unsigned char *) &prot);
  
 -#ifdef notyet
 +#ifdef DEV_ENC
 +	encif->if_ipackets++;
 +	encif->if_ibytes += m->m_pkthdr.len;
 +
 +	/*
 +	 * Pass the mbuf to enc0 for bpf and pfil. We will filter the IPIP
 +	 * packet later after it has been decapsulated.
 +	 */
 +	ipsec_bpf(m, sav, AF_INET6, ENC_IN|ENC_BEFORE);
 +
 +	/* XXX-BZ does not make sense. */
 +	if (prot != IPPROTO_IPIP)
 +		if ((error = ipsec_filter(&m, PFIL_IN, ENC_IN|ENC_BEFORE)) != 0)
 +			return (error);
 +#endif /* DEV_ENC */
 +
  #ifdef INET
  	/* IP-in-IP encapsulation */
  	if (prot == IPPROTO_IPIP) {
 -		struct ip ipn;
 -
  		if (m->m_pkthdr.len - skip < sizeof(struct ip)) {
  			IPSEC_ISTAT(sproto, hdrops);
  			error = EINVAL;
  			goto bad;
  		}
  		/* ipn will now contain the inner IPv4 header */
 -		m_copydata(m, skip, sizeof(struct ip), (caddr_t) &ipn);
 -
 +	 	m_striphdr(m, 0, skip);
 +		skip = 0;
 +#ifdef notyet
  		/*
  		 * Check that the inner source address is the same as
  		 * the proxy address, if available.
 @@ -642,22 +687,20 @@ ipsec6_common_input_cb(struct mbuf *m, s
  			error = EACCES;
  			goto bad;
  		}
 +#endif /* notyet */
  	}
  #endif /* INET */
 -
  	/* IPv6-in-IP encapsulation */
  	if (prot == IPPROTO_IPV6) {
 -		struct ip6_hdr ip6n;
 -
  		if (m->m_pkthdr.len - skip < sizeof(struct ip6_hdr)) {
  			IPSEC_ISTAT(sproto, hdrops);
  			error = EINVAL;
  			goto bad;
  		}
  		/* ip6n will now contain the inner IPv6 header. */
 -		m_copydata(m, skip, sizeof(struct ip6_hdr),
 -		    (caddr_t) &ip6n);
 -
 +		m_striphdr(m, 0, skip);
 +		skip = 0;
 +#ifdef notyet
  		/*
  		 * Check that the inner source address is the same as
  		 * the proxy address, if available.
 @@ -681,8 +724,8 @@ ipsec6_common_input_cb(struct mbuf *m, s
  			error = EACCES;
  			goto bad;
  		}
 +#endif /* notyet */
  	}
 -#endif /*XXX*/
  
  	/*
  	 * Record what we've done to the packet (under what SA it was
 @@ -720,23 +763,22 @@ ipsec6_common_input_cb(struct mbuf *m, s
  	key_sa_recordxfer(sav, m);
  
  #ifdef DEV_ENC
 -	encif->if_ipackets++;
 -	encif->if_ibytes += m->m_pkthdr.len;
 -
  	/*
 -	 * Pass the mbuf to enc0 for bpf and pfil. We will filter the IPIP
 -	 * packet later after it has been decapsulated.
 +	 * Pass the mbuf to enc0 for bpf and pfil.
  	 */
 -	ipsec_bpf(m, sav, AF_INET6, ENC_IN|ENC_BEFORE);
 -
 -	/* XXX-BZ does not make sense. */
 -	if (prot != IPPROTO_IPIP)
 -		if ((error = ipsec_filter(&m, PFIL_IN, ENC_IN|ENC_BEFORE)) != 0)
 -			return (error);
 +#ifdef INET
 +	if (prot == IPPROTO_IPIP)
 +		ipsec_bpf(m, sav, AF_INET, ENC_IN|ENC_AFTER);
  #endif
 +	if (prot == IPPROTO_IPV6)
 +		ipsec_bpf(m, sav, AF_INET6, ENC_IN|ENC_AFTER);
  
 +	if ((error = ipsec_filter(&m, PFIL_IN, ENC_IN|ENC_AFTER)) != 0)
 +		return (error);
 +#endif /* DEV_ENC */
  	/* Retrieve new protocol */
 -	m_copydata(m, protoff, sizeof(u_int8_t), (caddr_t) &nxt8);
 +	/* We have stripped the IP6 header from the mbuf, we have to use the backuped proto value instead */
 +	nxt8 = prot;
  
  	/*
  	 * See the end of ip6_input for this logic.
 
 Modified: head/sys/netipsec/ipsec_output.c
 ==============================================================================
 --- head/sys/netipsec/ipsec_output.c	Wed May 28 12:32:07 2014	(r266799)
 +++ head/sys/netipsec/ipsec_output.c	Wed May 28 12:45:27 2014	(r266800)
 @@ -177,8 +177,7 @@ ipsec_process_done(struct mbuf *m, struc
  #ifdef INET6
  		case AF_INET6:
  			/* XXX */
 -			ipsec6_output_trans()
 -			ipsec6_output_tunnel()
 +			return ipsec6_process_packet(m, isr->next);
  			/* NOTREACHED */
  #endif /* INET6 */
  #endif
 @@ -543,7 +542,7 @@ ipsec4_process_packet(
  
  #ifdef DEV_ENC
  	/* pass the mbuf to enc0 for bpf processing */
 -	ipsec_bpf(m, sav, AF_INET, ENC_OUT|ENC_AFTER);
 +	ipsec_bpf(m, sav, sav->sah->saidx.dst.sa.sa_family, ENC_OUT|ENC_AFTER);
  	/* pass the mbuf to enc0 for packet filtering */
  	if ((error = ipsec_filter(&m, PFIL_OUT, ENC_OUT|ENC_AFTER)) != 0)
  		goto bad;
 @@ -560,9 +559,26 @@ ipsec4_process_packet(
  	 *     for reclaiming their resources.
  	 */
  	if (sav->tdb_xform->xf_type != XF_IP4) {
 -		ip = mtod(m, struct ip *);
 -		i = ip->ip_hl << 2;
 -		off = offsetof(struct ip, ip_p);
 +		union sockaddr_union *dst = &sav->sah->saidx.dst;
 +		switch(dst->sa.sa_family) {
 +		case AF_INET:
 +			ip = mtod(m, struct ip *);
 +			i = ip->ip_hl << 2;
 +			off = offsetof(struct ip, ip_p);
 +			break;
 +#ifdef INET6
 +		case AF_INET6:
 +			i = sizeof(struct ip6_hdr);
 +			off = offsetof(struct ip6_hdr, ip6_nxt);
 +			break;
 +#endif /* INET6 */
 +		default:
 +		DPRINTF(("%s: unsupported protocol family %u\n",
 +				 __func__, dst->sa.sa_family));
 +			error = EPFNOSUPPORT;
 +			IPSEC6STAT_INC(ips_out_inval);
 +			goto bad;
 +		}
  		error = (*sav->tdb_xform->xf_output)(m, isr, NULL, i, off);
  	} else {
  		error = ipsec_process_done(m, isr);
 @@ -578,224 +594,50 @@ bad:
  }
  #endif
  
 -#ifdef INET6
 -/*
 - * Chop IP6 header from the payload.
 - */
 -static struct mbuf *
 -ipsec6_splithdr(struct mbuf *m)
 -{
 -	struct mbuf *mh;
 -	struct ip6_hdr *ip6;
 -	int hlen;
 -
 -	IPSEC_ASSERT(m->m_len >= sizeof (struct ip6_hdr),
 -		("first mbuf too short, len %u", m->m_len));
 -	ip6 = mtod(m, struct ip6_hdr *);
 -	hlen = sizeof(struct ip6_hdr);
 -	if (m->m_len > hlen) {
 -		MGETHDR(mh, M_NOWAIT, MT_DATA);
 -		if (!mh) {
 -			m_freem(m);
 -			return NULL;
 -		}
 -		M_MOVE_PKTHDR(mh, m);
 -		MH_ALIGN(mh, hlen);
 -		m->m_len -= hlen;
 -		m->m_data += hlen;
 -		mh->m_next = m;
 -		m = mh;
 -		m->m_len = hlen;
 -		bcopy((caddr_t)ip6, mtod(m, caddr_t), hlen);
 -	} else if (m->m_len < hlen) {
 -		m = m_pullup(m, hlen);
 -		if (!m)
 -			return NULL;
 -	}
 -	return m;
 -}
 -
 -/*
 - * IPsec output logic for IPv6, transport mode.
 - */
 -int
 -ipsec6_output_trans(
 -	struct ipsec_output_state *state,
 -	u_char *nexthdrp,
 -	struct mbuf *mprev,
 -	struct secpolicy *sp,
 -	int flags,
 -	int *tun)
 -{
 -	struct ipsecrequest *isr;
 -	struct secasindex saidx;
 -	int error = 0;
 -	struct mbuf *m;
 -
 -	IPSEC_ASSERT(state != NULL, ("null state"));
 -	IPSEC_ASSERT(state->m != NULL, ("null m"));
 -	IPSEC_ASSERT(nexthdrp != NULL, ("null nexthdrp"));
 -	IPSEC_ASSERT(mprev != NULL, ("null mprev"));
 -	IPSEC_ASSERT(sp != NULL, ("null sp"));
 -	IPSEC_ASSERT(tun != NULL, ("null tun"));
 -
 -	KEYDEBUG(KEYDEBUG_IPSEC_DATA,
 -		printf("%s: applied SP\n", __func__);
 -		kdebug_secpolicy(sp));
 -
 -	isr = sp->req;
 -	if (isr->saidx.mode == IPSEC_MODE_TUNNEL) {
 -		/* the rest will be handled by ipsec6_output_tunnel() */
 -		*tun = 1;		/* need tunnel-mode processing */
 -		return 0;
 -	}
 -
 -	*tun = 0;
 -	m = state->m;
 -
 -	IPSECREQUEST_LOCK(isr);		/* insure SA contents don't change */
 -	isr = ipsec_nextisr(m, isr, AF_INET6, &saidx, &error);
 -	if (isr == NULL) {
 -		if (error != 0) {
 -#ifdef notdef
 -			/* XXX should notification be done for all errors ? */
 -			/*
 -			 * Notify the fact that the packet is discarded
 -			 * to ourselves. I believe this is better than
 -			 * just silently discarding. (jinmei@kame.net)
 -			 * XXX: should we restrict the error to TCP packets?
 -			 * XXX: should we directly notify sockets via
 -			 *      pfctlinputs?
 -			 */
 -			icmp6_error(m, ICMP6_DST_UNREACH,
 -				    ICMP6_DST_UNREACH_ADMIN, 0);
 -			m = NULL;	/* NB: icmp6_error frees mbuf */
 -#endif
 -			goto bad;
 -		}
 -		return EJUSTRETURN;
 -	}
 -
 -	error = (*isr->sav->tdb_xform->xf_output)(m, isr, NULL,
 -						  sizeof (struct ip6_hdr),
 -						  offsetof(struct ip6_hdr, 
 -							   ip6_nxt));
 -	IPSECREQUEST_UNLOCK(isr);
 -	return error;
 -bad:
 -	if (isr)
 -		IPSECREQUEST_UNLOCK(isr);
 -	if (m)
 -		m_freem(m);
 -	state->m = NULL;
 -	return error;
 -}
  
 +#ifdef INET6
  static int
 -ipsec6_encapsulate(struct mbuf *m, struct secasvar *sav)
 +in6_sa_equal_addrwithscope(const struct sockaddr_in6 *sa, const struct in6_addr *ia)
  {
 -	struct ip6_hdr *oip6;
 -	struct ip6_hdr *ip6;
 -	size_t plen;
 -
 -	/* can't tunnel between different AFs */
 -	if (sav->sah->saidx.src.sa.sa_family != AF_INET6 ||
 -	    sav->sah->saidx.dst.sa.sa_family != AF_INET6) {
 -		m_freem(m);
 -		return EINVAL;
 -	}
 -	IPSEC_ASSERT(m->m_len == sizeof (struct ip6_hdr),
 -		("mbuf wrong size; len %u", m->m_len));
 -
 -
 -	/*
 -	 * grow the mbuf to accomodate the new IPv6 header.
 -	 */
 -	plen = m->m_pkthdr.len;
 -	if (M_LEADINGSPACE(m->m_next) < sizeof(struct ip6_hdr)) {
 -		struct mbuf *n;
 -		MGET(n, M_NOWAIT, MT_DATA);
 -		if (!n) {
 -			m_freem(m);
 -			return ENOBUFS;
 -		}
 -		n->m_len = sizeof(struct ip6_hdr);
 -		n->m_next = m->m_next;
 -		m->m_next = n;
 -		m->m_pkthdr.len += sizeof(struct ip6_hdr);
 -		oip6 = mtod(n, struct ip6_hdr *);
 -	} else {
 -		m->m_next->m_len += sizeof(struct ip6_hdr);
 -		m->m_next->m_data -= sizeof(struct ip6_hdr);
 -		m->m_pkthdr.len += sizeof(struct ip6_hdr);
 -		oip6 = mtod(m->m_next, struct ip6_hdr *);
 -	}
 -	ip6 = mtod(m, struct ip6_hdr *);
 -	bcopy((caddr_t)ip6, (caddr_t)oip6, sizeof(struct ip6_hdr));
 -
 -	/* Fake link-local scope-class addresses */
 -	if (IN6_IS_SCOPE_LINKLOCAL(&oip6->ip6_src))
 -		oip6->ip6_src.s6_addr16[1] = 0;
 -	if (IN6_IS_SCOPE_LINKLOCAL(&oip6->ip6_dst))
 -		oip6->ip6_dst.s6_addr16[1] = 0;
 -
 -	/* construct new IPv6 header. see RFC 2401 5.1.2.2 */
 -	/* ECN consideration. */
 -	ip6_ecn_ingress(V_ip6_ipsec_ecn, &ip6->ip6_flow, &oip6->ip6_flow);
 -	if (plen < IPV6_MAXPACKET - sizeof(struct ip6_hdr))
 -		ip6->ip6_plen = htons(plen);
 -	else {
 -		/* ip6->ip6_plen will be updated in ip6_output() */
 -	}
 -	ip6->ip6_nxt = IPPROTO_IPV6;
 -	ip6->ip6_src = sav->sah->saidx.src.sin6.sin6_addr;
 -	ip6->ip6_dst = sav->sah->saidx.dst.sin6.sin6_addr;
 -	ip6->ip6_hlim = IPV6_DEFHLIM;
 +	struct in6_addr ia2;
  
 -	/* XXX Should ip6_src be updated later ? */
 +	memcpy(&ia2, &sa->sin6_addr, sizeof(ia2));
 +	if (IN6_IS_SCOPE_LINKLOCAL(&sa->sin6_addr))
 +		ia2.s6_addr16[1] = htons(sa->sin6_scope_id);
  
 -	return 0;
 +	return IN6_ARE_ADDR_EQUAL(ia, &ia2);
  }
  
  /*
 - * IPsec output logic for IPv6, tunnel mode.
 + * IPsec output logic for IPv6.
   */
  int
 -ipsec6_output_tunnel(struct ipsec_output_state *state, struct secpolicy *sp, int flags)
 +ipsec6_process_packet(
 +	struct mbuf *m,
 + 	struct ipsecrequest *isr
 
 *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
>Unformatted:
