ipsec_output.c revision 105197
11366Scsgr/*	$FreeBSD: head/sys/netipsec/ipsec_output.c 105197 2002-10-16 02:10:08Z sam $	*/
21366Scsgr/*	$KAME: ipsec.c,v 1.103 2001/05/24 07:14:18 sakane Exp $	*/
31366Scsgr
41366Scsgr/*
51366Scsgr * IPsec output processing.
61366Scsgr */
71366Scsgr#include "opt_inet.h"
81366Scsgr#include "opt_inet6.h"
91366Scsgr#include "opt_ipsec.h"
101366Scsgr
111366Scsgr#include <sys/param.h>
121366Scsgr#include <sys/systm.h>
131366Scsgr#include <sys/mbuf.h>
141366Scsgr#include <sys/domain.h>
151366Scsgr#include <sys/protosw.h>
161366Scsgr#include <sys/socket.h>
171366Scsgr#include <sys/errno.h>
181366Scsgr#include <sys/syslog.h>
191366Scsgr
201366Scsgr#include <net/if.h>
211366Scsgr#include <net/route.h>
221366Scsgr
231366Scsgr#include <netinet/in.h>
241366Scsgr#include <netinet/in_systm.h>
251366Scsgr#include <netinet/ip.h>
261366Scsgr#include <netinet/ip_var.h>
271366Scsgr#include <netinet/in_var.h>
281366Scsgr#include <netinet/ip_ecn.h>
291366Scsgr#ifdef INET6
301366Scsgr#include <netinet6/ip6_ecn.h>
311366Scsgr#endif
321366Scsgr
3350479Speter#include <netinet/ip6.h>
341366Scsgr#ifdef INET6
351366Scsgr#include <netinet6/ip6_var.h>
361366Scsgr#endif
371366Scsgr#include <netinet/in_pcb.h>
381366Scsgr#ifdef INET6
391376Scsgr#include <netinet/icmp6.h>
401376Scsgr#endif
411366Scsgr
421366Scsgr#include <netipsec/ipsec.h>
431366Scsgr#ifdef INET6
441366Scsgr#include <netipsec/ipsec6.h>
451366Scsgr#endif
461366Scsgr#include <netipsec/ah_var.h>
471366Scsgr#include <netipsec/esp_var.h>
481366Scsgr#include <netipsec/ipcomp_var.h>
4919411Swosch
501366Scsgr#include <netipsec/xform.h>
511366Scsgr
521366Scsgr#include <netipsec/key.h>
531366Scsgr#include <netipsec/keydb.h>
541366Scsgr#include <netipsec/key_debug.h>
551366Scsgr
561366Scsgr#include <machine/in_cksum.h>
571366Scsgr
581366Scsgrint
591366Scsgripsec_process_done(struct mbuf *m, struct ipsecrequest *isr)
601366Scsgr{
611366Scsgr	struct tdb_ident *tdbi;
621366Scsgr	struct m_tag *mtag;
631366Scsgr	struct secasvar *sav;
641366Scsgr	struct secasindex *saidx;
651366Scsgr	int error;
661366Scsgr
671366Scsgr#if 0
681366Scsgr	SPLASSERT(net, "ipsec_process_done");
691366Scsgr#endif
701366Scsgr
711366Scsgr	KASSERT(m != NULL, ("ipsec_process_done: null mbuf"));
721366Scsgr	KASSERT(isr != NULL, ("ipsec_process_done: null ISR"));
731366Scsgr	sav = isr->sav;
741366Scsgr	KASSERT(sav != NULL, ("ipsec_process_done: null SA"));
751366Scsgr	KASSERT(sav->sah != NULL, ("ipsec_process_done: null SAH"));
761366Scsgr
771366Scsgr	saidx = &sav->sah->saidx;
781366Scsgr	switch (saidx->dst.sa.sa_family) {
791366Scsgr#ifdef INET
801366Scsgr	case AF_INET:
811366Scsgr		/* Fix the header length, for AH processing. */
821366Scsgr		mtod(m, struct ip *)->ip_len = htons(m->m_pkthdr.len);
831366Scsgr		break;
841366Scsgr#endif /* INET */
851366Scsgr#ifdef INET6
861366Scsgr	case AF_INET6:
871366Scsgr		/* Fix the header length, for AH processing. */
881366Scsgr		if (m->m_pkthdr.len < sizeof (struct ip6_hdr)) {
891366Scsgr			error = ENXIO;
901366Scsgr			goto bad;
911366Scsgr		}
921366Scsgr		if (m->m_pkthdr.len - sizeof (struct ip6_hdr) > IPV6_MAXPACKET) {
931366Scsgr			/* No jumbogram support. */
941366Scsgr			error = ENXIO;	/*?*/
951366Scsgr			goto bad;
961366Scsgr		}
9771293Sjedgar		mtod(m, struct ip6_hdr *)->ip6_plen =
9871293Sjedgar			htons(m->m_pkthdr.len - sizeof(struct ip6_hdr));
991366Scsgr		break;
10071293Sjedgar#endif /* INET6 */
1011366Scsgr	default:
1021366Scsgr		DPRINTF(("ipsec_process_done: unknown protocol family %u\n",
10371293Sjedgar		    saidx->dst.sa.sa_family));
1041366Scsgr		error = ENXIO;
1051366Scsgr		goto bad;
1061366Scsgr	}
1071366Scsgr
1081366Scsgr	/*
1091366Scsgr	 * Add a record of what we've done or what needs to be done to the
1101366Scsgr	 * packet.
1111366Scsgr	 */
1121366Scsgr	mtag = m_tag_get(PACKET_TAG_IPSEC_OUT_DONE,
1131366Scsgr			sizeof(struct tdb_ident), M_NOWAIT);
1141366Scsgr	if (mtag == NULL) {
1151366Scsgr		DPRINTF(("ipsec_process_done: could not get packet tag\n"));
1161366Scsgr		error = ENOMEM;
1171366Scsgr		goto bad;
1181366Scsgr	}
1191366Scsgr
1201366Scsgr	tdbi = (struct tdb_ident *)(mtag + 1);
1211366Scsgr	tdbi->dst = saidx->dst;
1221366Scsgr	tdbi->proto = saidx->proto;
1231366Scsgr	tdbi->spi = sav->spi;
1241366Scsgr	m_tag_prepend(m, mtag);
1251366Scsgr
1261366Scsgr	/*
1271366Scsgr	 * If there's another (bundled) SA to apply, do so.
1281369Scsgr	 * Note that this puts a burden on the kernel stack size.
1291366Scsgr	 * If this is a problem we'll need to introduce a queue
1301369Scsgr	 * to set the packet on so we can unwind the stack before
1311366Scsgr	 * doing further processing.
1321366Scsgr	 */
1331366Scsgr	if (isr->next) {
1341369Scsgr		newipsecstat.ips_out_bundlesa++;
1351370Scsgr		return ipsec4_process_packet(m, isr->next, 0, 0);
1361366Scsgr	}
1371366Scsgr
1381366Scsgr	/*
1391366Scsgr	 * We're done with IPsec processing, transmit the packet using the
1401366Scsgr	 * appropriate network protocol (IP or IPv6). SPD lookup will be
1411366Scsgr	 * performed again there.
1421366Scsgr	 */
1431366Scsgr	switch (saidx->dst.sa.sa_family) {
1441366Scsgr#ifdef INET
1451366Scsgr	struct ip *ip;
1461366Scsgr	case AF_INET:
1471366Scsgr		ip = mtod(m, struct ip *);
1481369Scsgr		ip->ip_len = ntohs(ip->ip_len);
1491366Scsgr		ip->ip_off = ntohs(ip->ip_off);
1501366Scsgr
1511366Scsgr		return ip_output(m, NULL, NULL, IP_RAWOUTPUT, NULL, NULL);
1521366Scsgr#endif /* INET */
1531366Scsgr#ifdef INET6
1541366Scsgr	case AF_INET6:
1551366Scsgr		/*
1561366Scsgr		 * We don't need massage, IPv6 header fields are always in
1571376Scsgr		 * net endian.
1581376Scsgr		 */
1591376Scsgr		return ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL);
1601376Scsgr#endif /* INET6 */
1611376Scsgr	}
1621376Scsgr	panic("ipsec_process_done");
1631376Scsgrbad:
1641376Scsgr	m_freem(m);
1651376Scsgr	KEY_FREESAV(&sav);
1666403Sjkh	return (error);
1671376Scsgr}
1681376Scsgr
1691376Scsgrstatic struct ipsecrequest *
1701376Scsgripsec_nextisr(
1711376Scsgr	struct mbuf *m,
1721376Scsgr	struct ipsecrequest *isr,
1731376Scsgr	int af,
1741376Scsgr	struct secasindex *saidx,
1751376Scsgr	int *error
1761376Scsgr)
1771376Scsgr{
1781376Scsgr#define IPSEC_OSTAT(x,y,z) (isr->saidx.proto == IPPROTO_ESP ? (x)++ : \
1791376Scsgr			    isr->saidx.proto == IPPROTO_AH ? (y)++ : (z)++)
1801376Scsgr	struct secasvar *sav;
1811376Scsgr
1821376Scsgr#if 0
1831376Scsgr	SPLASSERT(net, "ipsec_nextisr");
18471293Sjedgar#endif
1851376Scsgr	KASSERT(af == AF_INET || af == AF_INET6,
18671293Sjedgar		("ipsec_nextisr: invalid address family %u", af));
1871376Scsgragain:
18871293Sjedgar	/*
1891376Scsgr	 * Craft SA index to search for proper SA.  Note that
19071293Sjedgar	 * we only fillin unspecified SA peers for transport
1911376Scsgr	 * mode; for tunnel mode they must already be filled in.
1921376Scsgr	 */
1931376Scsgr	*saidx = isr->saidx;
1941376Scsgr	if (isr->saidx.mode == IPSEC_MODE_TRANSPORT) {
1951376Scsgr		/* Fillin unspecified SA peers only for transport mode */
1961376Scsgr		if (af == AF_INET) {
1971376Scsgr			struct sockaddr_in *sin;
1981376Scsgr			struct ip *ip = mtod(m, struct ip *);
1991376Scsgr
2001376Scsgr			if (saidx->src.sa.sa_len == 0) {
2011376Scsgr				sin = &saidx->src.sin;
2021376Scsgr				sin->sin_len = sizeof(*sin);
2031376Scsgr				sin->sin_family = AF_INET;
2041376Scsgr				sin->sin_port = IPSEC_PORT_ANY;
2051376Scsgr				sin->sin_addr = ip->ip_src;
2061376Scsgr			}
2071376Scsgr			if (saidx->dst.sa.sa_len == 0) {
2081376Scsgr				sin = &saidx->dst.sin;
2091376Scsgr				sin->sin_len = sizeof(*sin);
2101376Scsgr				sin->sin_family = AF_INET;
2111376Scsgr				sin->sin_port = IPSEC_PORT_ANY;
2121376Scsgr				sin->sin_addr = ip->ip_dst;
2131376Scsgr			}
2141376Scsgr		} else {
2151376Scsgr			struct sockaddr_in6 *sin6;
2161376Scsgr			struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
2171376Scsgr
2181376Scsgr			if (saidx->src.sin6.sin6_len == 0) {
2191376Scsgr				sin6 = (struct sockaddr_in6 *)&saidx->src;
2201376Scsgr				sin6->sin6_len = sizeof(*sin6);
2211376Scsgr				sin6->sin6_family = AF_INET6;
2221376Scsgr				sin6->sin6_port = IPSEC_PORT_ANY;
2231376Scsgr				sin6->sin6_addr = ip6->ip6_src;
2241376Scsgr				if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) {
2251376Scsgr					/* fix scope id for comparing SPD */
2261376Scsgr					sin6->sin6_addr.s6_addr16[1] = 0;
2271376Scsgr					sin6->sin6_scope_id =
2281376Scsgr					    ntohs(ip6->ip6_src.s6_addr16[1]);
2291376Scsgr				}
2301376Scsgr			}
2311376Scsgr			if (saidx->dst.sin6.sin6_len == 0) {
2321376Scsgr				sin6 = (struct sockaddr_in6 *)&saidx->dst;
2331376Scsgr				sin6->sin6_len = sizeof(*sin6);
2341376Scsgr				sin6->sin6_family = AF_INET6;
2351376Scsgr				sin6->sin6_port = IPSEC_PORT_ANY;
2361376Scsgr				sin6->sin6_addr = ip6->ip6_dst;
2371376Scsgr				if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) {
2381376Scsgr					/* fix scope id for comparing SPD */
2391376Scsgr					sin6->sin6_addr.s6_addr16[1] = 0;
2401376Scsgr					sin6->sin6_scope_id =
2411376Scsgr					    ntohs(ip6->ip6_dst.s6_addr16[1]);
2421376Scsgr				}
2431376Scsgr			}
2441376Scsgr		}
2451376Scsgr	}
2461376Scsgr
2471376Scsgr	/*
2481376Scsgr	 * Lookup SA and validate it.
2491376Scsgr	 */
2501366Scsgr	*error = key_checkrequest(isr, saidx);
2511366Scsgr	if (*error != 0) {
2521366Scsgr		/*
2531366Scsgr		 * IPsec processing is required, but no SA found.
2541366Scsgr		 * I assume that key_acquire() had been called
2551366Scsgr		 * to get/establish the SA. Here I discard
2561366Scsgr		 * this packet because it is responsibility for
2571366Scsgr		 * upper layer to retransmit the packet.
2581366Scsgr		 */
2591366Scsgr		newipsecstat.ips_out_nosa++;
2601366Scsgr		goto bad;
2611366Scsgr	}
2621366Scsgr	sav = isr->sav;
2631366Scsgr	if (sav == NULL) {		/* XXX valid return */
2641366Scsgr		KASSERT(ipsec_get_reqlevel(isr) == IPSEC_LEVEL_USE,
2651366Scsgr			("ipsec_nextisr: no SA found, but required; level %u",
2661366Scsgr			ipsec_get_reqlevel(isr)));
2671366Scsgr		isr = isr->next;
2681366Scsgr		if (isr == NULL) {
2691366Scsgr			/*XXXstatistic??*/
2701366Scsgr			*error = EINVAL;		/*XXX*/
2711366Scsgr			return isr;
2721366Scsgr		}
2731366Scsgr		goto again;
2741366Scsgr	}
2751366Scsgr
2761366Scsgr	/*
2771366Scsgr	 * Check system global policy controls.
2781366Scsgr	 */
2791366Scsgr	if ((isr->saidx.proto == IPPROTO_ESP && !esp_enable) ||
2801366Scsgr	    (isr->saidx.proto == IPPROTO_AH && !ah_enable) ||
2811366Scsgr	    (isr->saidx.proto == IPPROTO_IPCOMP && !ipcomp_enable)) {
2821366Scsgr		DPRINTF(("ipsec_nextisr: IPsec outbound packet dropped due"
2831366Scsgr			" to policy (check your sysctls)\n"));
2841366Scsgr		IPSEC_OSTAT(espstat.esps_pdrops, ahstat.ahs_pdrops,
28571293Sjedgar		    ipcompstat.ipcomps_pdrops);
2861370Scsgr		*error = EHOSTUNREACH;
28771293Sjedgar		goto bad;
2881366Scsgr	}
28971293Sjedgar
2901366Scsgr	/*
2911366Scsgr	 * Sanity check the SA contents for the caller
29271293Sjedgar	 * before they invoke the xform output method.
2931366Scsgr	 */
2941366Scsgr	if (sav->tdb_xform == NULL) {
2951366Scsgr		DPRINTF(("ipsec_nextisr: no transform for SA\n"));
2961366Scsgr		IPSEC_OSTAT(espstat.esps_noxform, ahstat.ahs_noxform,
2971366Scsgr		    ipcompstat.ipcomps_noxform);
2981366Scsgr		*error = EHOSTUNREACH;
2991366Scsgr		goto bad;
3001366Scsgr	}
3011366Scsgr	return isr;
3021366Scsgrbad:
3031366Scsgr	KASSERT(*error != 0, ("ipsec_nextisr: error return w/ no error code"));
3041366Scsgr	return NULL;
3051366Scsgr#undef IPSEC_OSTAT
3061366Scsgr}
3071366Scsgr
3081366Scsgr#ifdef INET
3091366Scsgr/*
3101366Scsgr * IPsec output logic for IPv4.
3111366Scsgr */
3121376Scsgrint
3131366Scsgripsec4_process_packet(
3141366Scsgr	struct mbuf *m,
3151366Scsgr	struct ipsecrequest *isr,
3161369Scsgr	int flags,
3171376Scsgr	int tunalready)
3181366Scsgr{
3191376Scsgr	struct secasindex saidx;
3201376Scsgr	struct secasvar *sav;
3211369Scsgr	struct ip *ip;
3221366Scsgr	int s, error, i, off;
3231366Scsgr
3241366Scsgr	KASSERT(m != NULL, ("ipsec4_process_packet: null mbuf"));
3251369Scsgr	KASSERT(isr != NULL, ("ipsec4_process_packet: null isr"));
3261369Scsgr
3271366Scsgr	s = splnet();			/* insure SA contents don't change */
3281366Scsgr
3291366Scsgr	isr = ipsec_nextisr(m, isr, AF_INET, &saidx, &error);
3301366Scsgr	if (isr == NULL)
3311376Scsgr		goto bad;
3321366Scsgr
3331366Scsgr	sav = isr->sav;
3341376Scsgr	if (!tunalready) {
3351366Scsgr		union sockaddr_union *dst = &sav->sah->saidx.dst;
3361366Scsgr		int setdf;
3371366Scsgr
3381366Scsgr		/*
3391369Scsgr		 * Collect IP_DF state from the outer header.
3401366Scsgr		 */
3411366Scsgr		if (dst->sa.sa_family == AF_INET) {
3421366Scsgr			if (m->m_len < sizeof (struct ip) &&
3431366Scsgr			    (m = m_pullup(m, sizeof (struct ip))) == NULL) {
3441366Scsgr				error = ENOBUFS;
3451366Scsgr				goto bad;
3461366Scsgr			}
3471366Scsgr			ip = mtod(m, struct ip *);
3481366Scsgr			/* Honor system-wide control of how to handle IP_DF */
3491366Scsgr			switch (ip4_ipsec_dfbit) {
3501366Scsgr			case 0:			/* clear in outer header */
3511366Scsgr			case 1:			/* set in outer header */
35229847Scharnier				setdf = ip4_ipsec_dfbit;
35329847Scharnier				break;
35429847Scharnier			default:		/* propagate to outer header */
35529847Scharnier				setdf = ntohs(ip->ip_off & IP_DF);
3561366Scsgr				break;
3571366Scsgr			}
3581366Scsgr		} else {
3591376Scsgr			ip = NULL;		/* keep compiler happy */
3601376Scsgr			setdf = 0;
3611376Scsgr		}
3621376Scsgr		/* Do the appropriate encapsulation, if necessary */
3631376Scsgr		if (isr->saidx.mode == IPSEC_MODE_TUNNEL || /* Tunnel requ'd */
3641376Scsgr		    dst->sa.sa_family != AF_INET ||	    /* PF mismatch */
3651376Scsgr#if 0
3661376Scsgr		    (sav->flags & SADB_X_SAFLAGS_TUNNEL) || /* Tunnel requ'd */
3671376Scsgr		    sav->tdb_xform->xf_type == XF_IP4 ||    /* ditto */
3681376Scsgr#endif
3691366Scsgr		    (dst->sa.sa_family == AF_INET &&	    /* Proxy */
3701366Scsgr		     dst->sin.sin_addr.s_addr != INADDR_ANY &&
3711366Scsgr		     dst->sin.sin_addr.s_addr != ip->ip_dst.s_addr)) {
3721366Scsgr			struct mbuf *mp;
37313601Swosch
3741366Scsgr			/* Fix IPv4 header checksum and length */
3751366Scsgr			if (m->m_len < sizeof (struct ip) &&
3761366Scsgr			    (m = m_pullup(m, sizeof (struct ip))) == NULL) {
3771366Scsgr				error = ENOBUFS;
3781366Scsgr				goto bad;
3791366Scsgr			}
3801366Scsgr			ip = mtod(m, struct ip *);
381			ip->ip_len = htons(m->m_pkthdr.len);
382			ip->ip_sum = 0;
383#ifdef _IP_VHL
384			if (ip->ip_vhl == IP_VHL_BORING)
385				ip->ip_sum = in_cksum_hdr(ip);
386			else
387				ip->ip_sum = in_cksum(m,
388					_IP_VHL_HL(ip->ip_vhl) << 2);
389#else
390			ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
391#endif
392
393			/* Encapsulate the packet */
394			error = ipip_output(m, isr, &mp, 0, 0);
395			if (mp == NULL && !error) {
396				/* Should never happen. */
397				DPRINTF(("ipsec4_process_packet: ipip_output "
398					"returns no mbuf and no error!"));
399				error = EFAULT;
400			}
401			if (error) {
402				if (mp)
403					m_freem(mp);
404				goto bad;
405			}
406			m = mp, mp = NULL;
407			/*
408			 * ipip_output clears IP_DF in the new header.  If
409			 * we need to propagate IP_DF from the outer header,
410			 * then we have to do it here.
411			 *
412			 * XXX shouldn't assume what ipip_output does.
413			 */
414			if (dst->sa.sa_family == AF_INET && setdf) {
415				if (m->m_len < sizeof (struct ip) &&
416				    (m = m_pullup(m, sizeof (struct ip))) == NULL) {
417					error = ENOBUFS;
418					goto bad;
419				}
420				ip = mtod(m, struct ip *);
421				ip->ip_off = ntohs(ip->ip_off);
422				ip->ip_off |= IP_DF;
423				ip->ip_off = htons(ip->ip_off);
424			}
425		}
426	}
427
428	/*
429	 * Dispatch to the appropriate IPsec transform logic.  The
430	 * packet will be returned for transmission after crypto
431	 * processing, etc. are completed.  For encapsulation we
432	 * bypass this call because of the explicit call done above
433	 * (necessary to deal with IP_DF handling for IPv4).
434	 *
435	 * NB: m & sav are ``passed to caller'' who's reponsible for
436	 *     for reclaiming their resources.
437	 */
438	if (sav->tdb_xform->xf_type != XF_IP4) {
439		ip = mtod(m, struct ip *);
440		i = ip->ip_hl << 2;
441		off = offsetof(struct ip, ip_p);
442		error = (*sav->tdb_xform->xf_output)(m, isr, NULL, i, off);
443	} else {
444		error = ipsec_process_done(m, isr);
445	}
446	splx(s);
447	return error;
448bad:
449	splx(s);
450	if (m)
451		m_freem(m);
452	return error;
453}
454#endif
455
456#ifdef INET6
457/*
458 * Chop IP6 header from the payload.
459 */
460static struct mbuf *
461ipsec6_splithdr(struct mbuf *m)
462{
463	struct mbuf *mh;
464	struct ip6_hdr *ip6;
465	int hlen;
466
467	KASSERT(m->m_len >= sizeof (struct ip6_hdr),
468		("ipsec6_splithdr: first mbuf too short, len %u", m->m_len));
469	ip6 = mtod(m, struct ip6_hdr *);
470	hlen = sizeof(struct ip6_hdr);
471	if (m->m_len > hlen) {
472		MGETHDR(mh, M_DONTWAIT, MT_HEADER);
473		if (!mh) {
474			m_freem(m);
475			return NULL;
476		}
477		M_COPY_PKTHDR(mh, m);
478		MH_ALIGN(mh, hlen);
479		m->m_len -= hlen;
480		m->m_data += hlen;
481		mh->m_next = m;
482		m = mh;
483		m->m_len = hlen;
484		bcopy((caddr_t)ip6, mtod(m, caddr_t), hlen);
485	} else if (m->m_len < hlen) {
486		m = m_pullup(m, hlen);
487		if (!m)
488			return NULL;
489	}
490	return m;
491}
492
493/*
494 * IPsec output logic for IPv6, transport mode.
495 */
496int
497ipsec6_output_trans(
498	struct ipsec_output_state *state,
499	u_char *nexthdrp,
500	struct mbuf *mprev,
501	struct secpolicy *sp,
502	int flags,
503	int *tun)
504{
505	struct ipsecrequest *isr;
506	struct secasindex saidx;
507	int error = 0;
508	struct mbuf *m;
509
510	KASSERT(state != NULL, ("ipsec6_output: null state"));
511	KASSERT(state->m != NULL, ("ipsec6_output: null m"));
512	KASSERT(nexthdrp != NULL, ("ipsec6_output: null nexthdrp"));
513	KASSERT(mprev != NULL, ("ipsec6_output: null mprev"));
514	KASSERT(sp != NULL, ("ipsec6_output: null sp"));
515	KASSERT(tun != NULL, ("ipsec6_output: null tun"));
516
517	KEYDEBUG(KEYDEBUG_IPSEC_DATA,
518		printf("ipsec6_output_trans: applyed SP\n");
519		kdebug_secpolicy(sp));
520
521	isr = sp->req;
522	if (isr->saidx.mode == IPSEC_MODE_TUNNEL) {
523		/* the rest will be handled by ipsec6_output_tunnel() */
524		*tun = 1;		/* need tunnel-mode processing */
525		return 0;
526	}
527
528	*tun = 0;
529	m = state->m;
530
531	isr = ipsec_nextisr(m, isr, AF_INET6, &saidx, &error);
532	if (isr == NULL) {
533#ifdef notdef
534		/* XXX should notification be done for all errors ? */
535		/*
536		 * Notify the fact that the packet is discarded
537		 * to ourselves. I believe this is better than
538		 * just silently discarding. (jinmei@kame.net)
539		 * XXX: should we restrict the error to TCP packets?
540		 * XXX: should we directly notify sockets via
541		 *      pfctlinputs?
542		 */
543		icmp6_error(m, ICMP6_DST_UNREACH,
544			    ICMP6_DST_UNREACH_ADMIN, 0);
545		m = NULL;	/* NB: icmp6_error frees mbuf */
546#endif
547		goto bad;
548	}
549
550	return (*isr->sav->tdb_xform->xf_output)(m, isr, NULL,
551		sizeof (struct ip6_hdr),
552		offsetof(struct ip6_hdr, ip6_nxt));
553bad:
554	if (m)
555		m_freem(m);
556	state->m = NULL;
557	return error;
558}
559
560static int
561ipsec6_encapsulate(struct mbuf *m, struct secasvar *sav)
562{
563	struct ip6_hdr *oip6;
564	struct ip6_hdr *ip6;
565	size_t plen;
566
567	/* can't tunnel between different AFs */
568	if (sav->sah->saidx.src.sa.sa_family != AF_INET6 ||
569	    sav->sah->saidx.dst.sa.sa_family != AF_INET6) {
570		m_freem(m);
571		return EINVAL;
572	}
573	KASSERT(m->m_len != sizeof (struct ip6_hdr),
574		("ipsec6_encapsulate: mbuf wrong size; len %u", m->m_len));
575
576
577	/*
578	 * grow the mbuf to accomodate the new IPv6 header.
579	 */
580	plen = m->m_pkthdr.len;
581	if (M_LEADINGSPACE(m->m_next) < sizeof(struct ip6_hdr)) {
582		struct mbuf *n;
583		MGET(n, M_DONTWAIT, MT_DATA);
584		if (!n) {
585			m_freem(m);
586			return ENOBUFS;
587		}
588		n->m_len = sizeof(struct ip6_hdr);
589		n->m_next = m->m_next;
590		m->m_next = n;
591		m->m_pkthdr.len += sizeof(struct ip6_hdr);
592		oip6 = mtod(n, struct ip6_hdr *);
593	} else {
594		m->m_next->m_len += sizeof(struct ip6_hdr);
595		m->m_next->m_data -= sizeof(struct ip6_hdr);
596		m->m_pkthdr.len += sizeof(struct ip6_hdr);
597		oip6 = mtod(m->m_next, struct ip6_hdr *);
598	}
599	ip6 = mtod(m, struct ip6_hdr *);
600	ovbcopy((caddr_t)ip6, (caddr_t)oip6, sizeof(struct ip6_hdr));
601
602	/* Fake link-local scope-class addresses */
603	if (IN6_IS_SCOPE_LINKLOCAL(&oip6->ip6_src))
604		oip6->ip6_src.s6_addr16[1] = 0;
605	if (IN6_IS_SCOPE_LINKLOCAL(&oip6->ip6_dst))
606		oip6->ip6_dst.s6_addr16[1] = 0;
607
608	/* construct new IPv6 header. see RFC 2401 5.1.2.2 */
609	/* ECN consideration. */
610	ip6_ecn_ingress(ip6_ipsec_ecn, &ip6->ip6_flow, &oip6->ip6_flow);
611	if (plen < IPV6_MAXPACKET - sizeof(struct ip6_hdr))
612		ip6->ip6_plen = htons(plen);
613	else {
614		/* ip6->ip6_plen will be updated in ip6_output() */
615	}
616	ip6->ip6_nxt = IPPROTO_IPV6;
617	sav->sah->saidx.src.sin6.sin6_addr = ip6->ip6_src;
618	sav->sah->saidx.dst.sin6.sin6_addr = ip6->ip6_dst;
619	ip6->ip6_hlim = IPV6_DEFHLIM;
620
621	/* XXX Should ip6_src be updated later ? */
622
623	return 0;
624}
625
626/*
627 * IPsec output logic for IPv6, tunnel mode.
628 */
629int
630ipsec6_output_tunnel(struct ipsec_output_state *state, struct secpolicy *sp, int flags)
631{
632	struct ip6_hdr *ip6;
633	struct ipsecrequest *isr;
634	struct secasindex saidx;
635	int error;
636	struct sockaddr_in6* dst6;
637	struct mbuf *m;
638
639	KASSERT(state != NULL, ("ipsec6_output: null state"));
640	KASSERT(state->m != NULL, ("ipsec6_output: null m"));
641	KASSERT(sp != NULL, ("ipsec6_output: null sp"));
642
643	KEYDEBUG(KEYDEBUG_IPSEC_DATA,
644		printf("ipsec6_output_tunnel: applyed SP\n");
645		kdebug_secpolicy(sp));
646
647	m = state->m;
648	/*
649	 * transport mode ipsec (before the 1st tunnel mode) is already
650	 * processed by ipsec6_output_trans().
651	 */
652	for (isr = sp->req; isr; isr = isr->next) {
653		if (isr->saidx.mode == IPSEC_MODE_TUNNEL)
654			break;
655	}
656	isr = ipsec_nextisr(m, isr, AF_INET6, &saidx, &error);
657	if (isr == NULL)
658		goto bad;
659
660	/*
661	 * There may be the case that SA status will be changed when
662	 * we are refering to one. So calling splsoftnet().
663	 */
664	if (isr->saidx.mode == IPSEC_MODE_TUNNEL) {
665		/*
666		 * build IPsec tunnel.
667		 */
668		/* XXX should be processed with other familiy */
669		if (isr->sav->sah->saidx.src.sa.sa_family != AF_INET6) {
670			ipseclog((LOG_ERR, "ipsec6_output_tunnel: "
671			    "family mismatched between inner and outer, spi=%u\n",
672			    ntohl(isr->sav->spi)));
673			newipsecstat.ips_out_inval++;
674			error = EAFNOSUPPORT;
675			goto bad;
676		}
677
678		m = ipsec6_splithdr(m);
679		if (!m) {
680			newipsecstat.ips_out_nomem++;
681			error = ENOMEM;
682			goto bad;
683		}
684		error = ipsec6_encapsulate(m, isr->sav);
685		if (error) {
686			m = NULL;
687			goto bad;
688		}
689		ip6 = mtod(m, struct ip6_hdr *);
690
691		state->ro = &isr->sav->sah->sa_route;
692		state->dst = (struct sockaddr *)&state->ro->ro_dst;
693		dst6 = (struct sockaddr_in6 *)state->dst;
694		if (state->ro->ro_rt
695		 && ((state->ro->ro_rt->rt_flags & RTF_UP) == 0
696		  || !IN6_ARE_ADDR_EQUAL(&dst6->sin6_addr, &ip6->ip6_dst))) {
697			RTFREE(state->ro->ro_rt);
698			state->ro->ro_rt = NULL;
699		}
700		if (state->ro->ro_rt == 0) {
701			bzero(dst6, sizeof(*dst6));
702			dst6->sin6_family = AF_INET6;
703			dst6->sin6_len = sizeof(*dst6);
704			dst6->sin6_addr = ip6->ip6_dst;
705			rtalloc(state->ro);
706		}
707		if (state->ro->ro_rt == 0) {
708			ip6stat.ip6s_noroute++;
709			newipsecstat.ips_out_noroute++;
710			error = EHOSTUNREACH;
711			goto bad;
712		}
713
714		/* adjust state->dst if tunnel endpoint is offlink */
715		if (state->ro->ro_rt->rt_flags & RTF_GATEWAY) {
716			state->dst = (struct sockaddr *)state->ro->ro_rt->rt_gateway;
717			dst6 = (struct sockaddr_in6 *)state->dst;
718		}
719	}
720
721	m = ipsec6_splithdr(m);
722	if (!m) {
723		newipsecstat.ips_out_nomem++;
724		error = ENOMEM;
725		goto bad;
726	}
727	ip6 = mtod(m, struct ip6_hdr *);
728	return (*isr->sav->tdb_xform->xf_output)(m, isr, NULL,
729		sizeof (struct ip6_hdr),
730		offsetof(struct ip6_hdr, ip6_nxt));
731bad:
732	if (m)
733		m_freem(m);
734	state->m = NULL;
735	return error;
736}
737#endif /*INET6*/
738