ipsec_output.c revision 109623
1/*	$FreeBSD: head/sys/netipsec/ipsec_output.c 109623 2003-01-21 08:56:16Z alfred $	*/
2/*	$KAME: ipsec.c,v 1.103 2001/05/24 07:14:18 sakane Exp $	*/
3
4/*
5 * IPsec output processing.
6 */
7#include "opt_inet.h"
8#include "opt_inet6.h"
9#include "opt_ipsec.h"
10
11#include <sys/param.h>
12#include <sys/systm.h>
13#include <sys/mbuf.h>
14#include <sys/domain.h>
15#include <sys/protosw.h>
16#include <sys/socket.h>
17#include <sys/errno.h>
18#include <sys/syslog.h>
19
20#include <net/if.h>
21#include <net/route.h>
22
23#include <netinet/in.h>
24#include <netinet/in_systm.h>
25#include <netinet/ip.h>
26#include <netinet/ip_var.h>
27#include <netinet/in_var.h>
28#include <netinet/ip_ecn.h>
29#ifdef INET6
30#include <netinet6/ip6_ecn.h>
31#endif
32
33#include <netinet/ip6.h>
34#ifdef INET6
35#include <netinet6/ip6_var.h>
36#endif
37#include <netinet/in_pcb.h>
38#ifdef INET6
39#include <netinet/icmp6.h>
40#endif
41
42#include <netipsec/ipsec.h>
43#ifdef INET6
44#include <netipsec/ipsec6.h>
45#endif
46#include <netipsec/ah_var.h>
47#include <netipsec/esp_var.h>
48#include <netipsec/ipcomp_var.h>
49
50#include <netipsec/xform.h>
51
52#include <netipsec/key.h>
53#include <netipsec/keydb.h>
54#include <netipsec/key_debug.h>
55
56#include <machine/in_cksum.h>
57
58int
59ipsec_process_done(struct mbuf *m, struct ipsecrequest *isr)
60{
61	struct tdb_ident *tdbi;
62	struct m_tag *mtag;
63	struct secasvar *sav;
64	struct secasindex *saidx;
65	int error;
66
67#if 0
68	SPLASSERT(net, "ipsec_process_done");
69#endif
70
71	KASSERT(m != NULL, ("ipsec_process_done: null mbuf"));
72	KASSERT(isr != NULL, ("ipsec_process_done: null ISR"));
73	sav = isr->sav;
74	KASSERT(sav != NULL, ("ipsec_process_done: null SA"));
75	KASSERT(sav->sah != NULL, ("ipsec_process_done: null SAH"));
76
77	saidx = &sav->sah->saidx;
78	switch (saidx->dst.sa.sa_family) {
79#ifdef INET
80	case AF_INET:
81		/* Fix the header length, for AH processing. */
82		mtod(m, struct ip *)->ip_len = htons(m->m_pkthdr.len);
83		break;
84#endif /* INET */
85#ifdef INET6
86	case AF_INET6:
87		/* Fix the header length, for AH processing. */
88		if (m->m_pkthdr.len < sizeof (struct ip6_hdr)) {
89			error = ENXIO;
90			goto bad;
91		}
92		if (m->m_pkthdr.len - sizeof (struct ip6_hdr) > IPV6_MAXPACKET) {
93			/* No jumbogram support. */
94			error = ENXIO;	/*?*/
95			goto bad;
96		}
97		mtod(m, struct ip6_hdr *)->ip6_plen =
98			htons(m->m_pkthdr.len - sizeof(struct ip6_hdr));
99		break;
100#endif /* INET6 */
101	default:
102		DPRINTF(("ipsec_process_done: unknown protocol family %u\n",
103		    saidx->dst.sa.sa_family));
104		error = ENXIO;
105		goto bad;
106	}
107
108	/*
109	 * Add a record of what we've done or what needs to be done to the
110	 * packet.
111	 */
112	mtag = m_tag_get(PACKET_TAG_IPSEC_OUT_DONE,
113			sizeof(struct tdb_ident), M_NOWAIT);
114	if (mtag == NULL) {
115		DPRINTF(("ipsec_process_done: could not get packet tag\n"));
116		error = ENOMEM;
117		goto bad;
118	}
119
120	tdbi = (struct tdb_ident *)(mtag + 1);
121	tdbi->dst = saidx->dst;
122	tdbi->proto = saidx->proto;
123	tdbi->spi = sav->spi;
124	m_tag_prepend(m, mtag);
125
126	/*
127	 * If there's another (bundled) SA to apply, do so.
128	 * Note that this puts a burden on the kernel stack size.
129	 * If this is a problem we'll need to introduce a queue
130	 * to set the packet on so we can unwind the stack before
131	 * doing further processing.
132	 */
133	if (isr->next) {
134		newipsecstat.ips_out_bundlesa++;
135		return ipsec4_process_packet(m, isr->next, 0, 0);
136	}
137
138	/*
139	 * We're done with IPsec processing, transmit the packet using the
140	 * appropriate network protocol (IP or IPv6). SPD lookup will be
141	 * performed again there.
142	 */
143	switch (saidx->dst.sa.sa_family) {
144#ifdef INET
145	struct ip *ip;
146	case AF_INET:
147		ip = mtod(m, struct ip *);
148		ip->ip_len = ntohs(ip->ip_len);
149		ip->ip_off = ntohs(ip->ip_off);
150
151		return ip_output(m, NULL, NULL, IP_RAWOUTPUT, NULL, NULL);
152#endif /* INET */
153#ifdef INET6
154	case AF_INET6:
155		/*
156		 * We don't need massage, IPv6 header fields are always in
157		 * net endian.
158		 */
159		return ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL);
160#endif /* INET6 */
161	}
162	panic("ipsec_process_done");
163bad:
164	m_freem(m);
165	KEY_FREESAV(&sav);
166	return (error);
167}
168
169static struct ipsecrequest *
170ipsec_nextisr(
171	struct mbuf *m,
172	struct ipsecrequest *isr,
173	int af,
174	struct secasindex *saidx,
175	int *error
176)
177{
178#define IPSEC_OSTAT(x,y,z) (isr->saidx.proto == IPPROTO_ESP ? (x)++ : \
179			    isr->saidx.proto == IPPROTO_AH ? (y)++ : (z)++)
180	struct secasvar *sav;
181
182#if 0
183	SPLASSERT(net, "ipsec_nextisr");
184#endif
185	KASSERT(af == AF_INET || af == AF_INET6,
186		("ipsec_nextisr: invalid address family %u", af));
187again:
188	/*
189	 * Craft SA index to search for proper SA.  Note that
190	 * we only fillin unspecified SA peers for transport
191	 * mode; for tunnel mode they must already be filled in.
192	 */
193	*saidx = isr->saidx;
194	if (isr->saidx.mode == IPSEC_MODE_TRANSPORT) {
195		/* Fillin unspecified SA peers only for transport mode */
196		if (af == AF_INET) {
197			struct sockaddr_in *sin;
198			struct ip *ip = mtod(m, struct ip *);
199
200			if (saidx->src.sa.sa_len == 0) {
201				sin = &saidx->src.sin;
202				sin->sin_len = sizeof(*sin);
203				sin->sin_family = AF_INET;
204				sin->sin_port = IPSEC_PORT_ANY;
205				sin->sin_addr = ip->ip_src;
206			}
207			if (saidx->dst.sa.sa_len == 0) {
208				sin = &saidx->dst.sin;
209				sin->sin_len = sizeof(*sin);
210				sin->sin_family = AF_INET;
211				sin->sin_port = IPSEC_PORT_ANY;
212				sin->sin_addr = ip->ip_dst;
213			}
214		} else {
215			struct sockaddr_in6 *sin6;
216			struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
217
218			if (saidx->src.sin6.sin6_len == 0) {
219				sin6 = (struct sockaddr_in6 *)&saidx->src;
220				sin6->sin6_len = sizeof(*sin6);
221				sin6->sin6_family = AF_INET6;
222				sin6->sin6_port = IPSEC_PORT_ANY;
223				sin6->sin6_addr = ip6->ip6_src;
224				if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) {
225					/* fix scope id for comparing SPD */
226					sin6->sin6_addr.s6_addr16[1] = 0;
227					sin6->sin6_scope_id =
228					    ntohs(ip6->ip6_src.s6_addr16[1]);
229				}
230			}
231			if (saidx->dst.sin6.sin6_len == 0) {
232				sin6 = (struct sockaddr_in6 *)&saidx->dst;
233				sin6->sin6_len = sizeof(*sin6);
234				sin6->sin6_family = AF_INET6;
235				sin6->sin6_port = IPSEC_PORT_ANY;
236				sin6->sin6_addr = ip6->ip6_dst;
237				if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) {
238					/* fix scope id for comparing SPD */
239					sin6->sin6_addr.s6_addr16[1] = 0;
240					sin6->sin6_scope_id =
241					    ntohs(ip6->ip6_dst.s6_addr16[1]);
242				}
243			}
244		}
245	}
246
247	/*
248	 * Lookup SA and validate it.
249	 */
250	*error = key_checkrequest(isr, saidx);
251	if (*error != 0) {
252		/*
253		 * IPsec processing is required, but no SA found.
254		 * I assume that key_acquire() had been called
255		 * to get/establish the SA. Here I discard
256		 * this packet because it is responsibility for
257		 * upper layer to retransmit the packet.
258		 */
259		newipsecstat.ips_out_nosa++;
260		goto bad;
261	}
262	sav = isr->sav;
263	if (sav == NULL) {		/* XXX valid return */
264		KASSERT(ipsec_get_reqlevel(isr) == IPSEC_LEVEL_USE,
265			("ipsec_nextisr: no SA found, but required; level %u",
266			ipsec_get_reqlevel(isr)));
267		isr = isr->next;
268		if (isr == NULL) {
269			/*XXXstatistic??*/
270			*error = EINVAL;		/*XXX*/
271			return isr;
272		}
273		goto again;
274	}
275
276	/*
277	 * Check system global policy controls.
278	 */
279	if ((isr->saidx.proto == IPPROTO_ESP && !esp_enable) ||
280	    (isr->saidx.proto == IPPROTO_AH && !ah_enable) ||
281	    (isr->saidx.proto == IPPROTO_IPCOMP && !ipcomp_enable)) {
282		DPRINTF(("ipsec_nextisr: IPsec outbound packet dropped due"
283			" to policy (check your sysctls)\n"));
284		IPSEC_OSTAT(espstat.esps_pdrops, ahstat.ahs_pdrops,
285		    ipcompstat.ipcomps_pdrops);
286		*error = EHOSTUNREACH;
287		goto bad;
288	}
289
290	/*
291	 * Sanity check the SA contents for the caller
292	 * before they invoke the xform output method.
293	 */
294	if (sav->tdb_xform == NULL) {
295		DPRINTF(("ipsec_nextisr: no transform for SA\n"));
296		IPSEC_OSTAT(espstat.esps_noxform, ahstat.ahs_noxform,
297		    ipcompstat.ipcomps_noxform);
298		*error = EHOSTUNREACH;
299		goto bad;
300	}
301	return isr;
302bad:
303	KASSERT(*error != 0, ("ipsec_nextisr: error return w/ no error code"));
304	return NULL;
305#undef IPSEC_OSTAT
306}
307
308#ifdef INET
309/*
310 * IPsec output logic for IPv4.
311 */
312int
313ipsec4_process_packet(
314	struct mbuf *m,
315	struct ipsecrequest *isr,
316	int flags,
317	int tunalready)
318{
319	struct secasindex saidx;
320	struct secasvar *sav;
321	struct ip *ip;
322	int s, error, i, off;
323
324	KASSERT(m != NULL, ("ipsec4_process_packet: null mbuf"));
325	KASSERT(isr != NULL, ("ipsec4_process_packet: null isr"));
326
327	s = splnet();			/* insure SA contents don't change */
328
329	isr = ipsec_nextisr(m, isr, AF_INET, &saidx, &error);
330	if (isr == NULL)
331		goto bad;
332
333	sav = isr->sav;
334	if (!tunalready) {
335		union sockaddr_union *dst = &sav->sah->saidx.dst;
336		int setdf;
337
338		/*
339		 * Collect IP_DF state from the outer header.
340		 */
341		if (dst->sa.sa_family == AF_INET) {
342			if (m->m_len < sizeof (struct ip) &&
343			    (m = m_pullup(m, sizeof (struct ip))) == NULL) {
344				error = ENOBUFS;
345				goto bad;
346			}
347			ip = mtod(m, struct ip *);
348			/* Honor system-wide control of how to handle IP_DF */
349			switch (ip4_ipsec_dfbit) {
350			case 0:			/* clear in outer header */
351			case 1:			/* set in outer header */
352				setdf = ip4_ipsec_dfbit;
353				break;
354			default:		/* propagate to outer header */
355				setdf = ntohs(ip->ip_off & IP_DF);
356				break;
357			}
358		} else {
359			ip = NULL;		/* keep compiler happy */
360			setdf = 0;
361		}
362		/* Do the appropriate encapsulation, if necessary */
363		if (isr->saidx.mode == IPSEC_MODE_TUNNEL || /* Tunnel requ'd */
364		    dst->sa.sa_family != AF_INET ||	    /* PF mismatch */
365#if 0
366		    (sav->flags & SADB_X_SAFLAGS_TUNNEL) || /* Tunnel requ'd */
367		    sav->tdb_xform->xf_type == XF_IP4 ||    /* ditto */
368#endif
369		    (dst->sa.sa_family == AF_INET &&	    /* Proxy */
370		     dst->sin.sin_addr.s_addr != INADDR_ANY &&
371		     dst->sin.sin_addr.s_addr != ip->ip_dst.s_addr)) {
372			struct mbuf *mp;
373
374			/* Fix IPv4 header checksum and length */
375			if (m->m_len < sizeof (struct ip) &&
376			    (m = m_pullup(m, sizeof (struct ip))) == NULL) {
377				error = ENOBUFS;
378				goto bad;
379			}
380			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_NOWAIT, MT_HEADER);
473		if (!mh) {
474			m_freem(m);
475			return NULL;
476		}
477		M_MOVE_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_NOWAIT, 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