ipsec_output.c revision 181803
1/*-
2 * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/sys/netipsec/ipsec_output.c 181803 2008-08-17 23:27:27Z bz $
27 */
28
29/*
30 * IPsec output processing.
31 */
32#include "opt_inet.h"
33#include "opt_inet6.h"
34#include "opt_ipsec.h"
35#include "opt_enc.h"
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/mbuf.h>
40#include <sys/domain.h>
41#include <sys/protosw.h>
42#include <sys/socket.h>
43#include <sys/errno.h>
44#include <sys/syslog.h>
45#include <sys/vimage.h>
46
47#include <net/if.h>
48#include <net/pfil.h>
49#include <net/route.h>
50
51#include <netinet/in.h>
52#include <netinet/in_systm.h>
53#include <netinet/ip.h>
54#include <netinet/ip_var.h>
55#include <netinet/in_var.h>
56#include <netinet/ip_ecn.h>
57#ifdef INET6
58#include <netinet6/ip6_ecn.h>
59#endif
60
61#include <netinet/ip6.h>
62#ifdef INET6
63#include <netinet6/ip6_var.h>
64#endif
65#include <netinet/in_pcb.h>
66#ifdef INET6
67#include <netinet/icmp6.h>
68#endif
69
70#include <netipsec/ipsec.h>
71#ifdef INET6
72#include <netipsec/ipsec6.h>
73#endif
74#include <netipsec/ah_var.h>
75#include <netipsec/esp_var.h>
76#include <netipsec/ipcomp_var.h>
77
78#include <netipsec/xform.h>
79
80#include <netipsec/key.h>
81#include <netipsec/keydb.h>
82#include <netipsec/key_debug.h>
83
84#include <machine/in_cksum.h>
85
86#ifdef DEV_ENC
87#include <net/if_enc.h>
88#endif
89
90
91int
92ipsec_process_done(struct mbuf *m, struct ipsecrequest *isr)
93{
94	struct tdb_ident *tdbi;
95	struct m_tag *mtag;
96	struct secasvar *sav;
97	struct secasindex *saidx;
98	int error;
99
100	IPSEC_ASSERT(m != NULL, ("null mbuf"));
101	IPSEC_ASSERT(isr != NULL, ("null ISR"));
102	sav = isr->sav;
103	IPSEC_ASSERT(sav != NULL, ("null SA"));
104	IPSEC_ASSERT(sav->sah != NULL, ("null SAH"));
105
106	saidx = &sav->sah->saidx;
107	switch (saidx->dst.sa.sa_family) {
108#ifdef INET
109	case AF_INET:
110		/* Fix the header length, for AH processing. */
111		mtod(m, struct ip *)->ip_len = htons(m->m_pkthdr.len);
112		break;
113#endif /* INET */
114#ifdef INET6
115	case AF_INET6:
116		/* Fix the header length, for AH processing. */
117		if (m->m_pkthdr.len < sizeof (struct ip6_hdr)) {
118			error = ENXIO;
119			goto bad;
120		}
121		if (m->m_pkthdr.len - sizeof (struct ip6_hdr) > IPV6_MAXPACKET) {
122			/* No jumbogram support. */
123			error = ENXIO;	/*?*/
124			goto bad;
125		}
126		mtod(m, struct ip6_hdr *)->ip6_plen =
127			htons(m->m_pkthdr.len - sizeof(struct ip6_hdr));
128		break;
129#endif /* INET6 */
130	default:
131		DPRINTF(("%s: unknown protocol family %u\n", __func__,
132		    saidx->dst.sa.sa_family));
133		error = ENXIO;
134		goto bad;
135	}
136
137	/*
138	 * Add a record of what we've done or what needs to be done to the
139	 * packet.
140	 */
141	mtag = m_tag_get(PACKET_TAG_IPSEC_OUT_DONE,
142			sizeof(struct tdb_ident), M_NOWAIT);
143	if (mtag == NULL) {
144		DPRINTF(("%s: could not get packet tag\n", __func__));
145		error = ENOMEM;
146		goto bad;
147	}
148
149	tdbi = (struct tdb_ident *)(mtag + 1);
150	tdbi->dst = saidx->dst;
151	tdbi->proto = saidx->proto;
152	tdbi->spi = sav->spi;
153	m_tag_prepend(m, mtag);
154
155	/*
156	 * If there's another (bundled) SA to apply, do so.
157	 * Note that this puts a burden on the kernel stack size.
158	 * If this is a problem we'll need to introduce a queue
159	 * to set the packet on so we can unwind the stack before
160	 * doing further processing.
161	 */
162	if (isr->next) {
163		V_ipsec4stat.ips_out_bundlesa++;
164		return ipsec4_process_packet(m, isr->next, 0, 0);
165	}
166	key_sa_recordxfer(sav, m);		/* record data transfer */
167
168	/*
169	 * We're done with IPsec processing, transmit the packet using the
170	 * appropriate network protocol (IP or IPv6). SPD lookup will be
171	 * performed again there.
172	 */
173	switch (saidx->dst.sa.sa_family) {
174#ifdef INET
175	struct ip *ip;
176	case AF_INET:
177		ip = mtod(m, struct ip *);
178		ip->ip_len = ntohs(ip->ip_len);
179		ip->ip_off = ntohs(ip->ip_off);
180
181		return ip_output(m, NULL, NULL, IP_RAWOUTPUT, NULL, NULL);
182#endif /* INET */
183#ifdef INET6
184	case AF_INET6:
185		/*
186		 * We don't need massage, IPv6 header fields are always in
187		 * net endian.
188		 */
189		return ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL);
190#endif /* INET6 */
191	}
192	panic("ipsec_process_done");
193bad:
194	m_freem(m);
195	KEY_FREESAV(&sav);
196	return (error);
197}
198
199static struct ipsecrequest *
200ipsec_nextisr(
201	struct mbuf *m,
202	struct ipsecrequest *isr,
203	int af,
204	struct secasindex *saidx,
205	int *error
206)
207{
208#define IPSEC_OSTAT(x,y,z) (isr->saidx.proto == IPPROTO_ESP ? (x)++ : \
209			    isr->saidx.proto == IPPROTO_AH ? (y)++ : (z)++)
210	struct secasvar *sav;
211
212	IPSECREQUEST_LOCK_ASSERT(isr);
213
214	IPSEC_ASSERT(af == AF_INET || af == AF_INET6,
215		("invalid address family %u", af));
216again:
217	/*
218	 * Craft SA index to search for proper SA.  Note that
219	 * we only fillin unspecified SA peers for transport
220	 * mode; for tunnel mode they must already be filled in.
221	 */
222	*saidx = isr->saidx;
223	if (isr->saidx.mode == IPSEC_MODE_TRANSPORT) {
224		/* Fillin unspecified SA peers only for transport mode */
225		if (af == AF_INET) {
226			struct sockaddr_in *sin;
227			struct ip *ip = mtod(m, struct ip *);
228
229			if (saidx->src.sa.sa_len == 0) {
230				sin = &saidx->src.sin;
231				sin->sin_len = sizeof(*sin);
232				sin->sin_family = AF_INET;
233				sin->sin_port = IPSEC_PORT_ANY;
234				sin->sin_addr = ip->ip_src;
235			}
236			if (saidx->dst.sa.sa_len == 0) {
237				sin = &saidx->dst.sin;
238				sin->sin_len = sizeof(*sin);
239				sin->sin_family = AF_INET;
240				sin->sin_port = IPSEC_PORT_ANY;
241				sin->sin_addr = ip->ip_dst;
242			}
243		} else {
244			struct sockaddr_in6 *sin6;
245			struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
246
247			if (saidx->src.sin6.sin6_len == 0) {
248				sin6 = (struct sockaddr_in6 *)&saidx->src;
249				sin6->sin6_len = sizeof(*sin6);
250				sin6->sin6_family = AF_INET6;
251				sin6->sin6_port = IPSEC_PORT_ANY;
252				sin6->sin6_addr = ip6->ip6_src;
253				if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) {
254					/* fix scope id for comparing SPD */
255					sin6->sin6_addr.s6_addr16[1] = 0;
256					sin6->sin6_scope_id =
257					    ntohs(ip6->ip6_src.s6_addr16[1]);
258				}
259			}
260			if (saidx->dst.sin6.sin6_len == 0) {
261				sin6 = (struct sockaddr_in6 *)&saidx->dst;
262				sin6->sin6_len = sizeof(*sin6);
263				sin6->sin6_family = AF_INET6;
264				sin6->sin6_port = IPSEC_PORT_ANY;
265				sin6->sin6_addr = ip6->ip6_dst;
266				if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) {
267					/* fix scope id for comparing SPD */
268					sin6->sin6_addr.s6_addr16[1] = 0;
269					sin6->sin6_scope_id =
270					    ntohs(ip6->ip6_dst.s6_addr16[1]);
271				}
272			}
273		}
274	}
275
276	/*
277	 * Lookup SA and validate it.
278	 */
279	*error = key_checkrequest(isr, saidx);
280	if (*error != 0) {
281		/*
282		 * IPsec processing is required, but no SA found.
283		 * I assume that key_acquire() had been called
284		 * to get/establish the SA. Here I discard
285		 * this packet because it is responsibility for
286		 * upper layer to retransmit the packet.
287		 */
288		V_ipsec4stat.ips_out_nosa++;
289		goto bad;
290	}
291	sav = isr->sav;
292	if (sav == NULL) {
293		IPSEC_ASSERT(ipsec_get_reqlevel(isr) == IPSEC_LEVEL_USE,
294			("no SA found, but required; level %u",
295			ipsec_get_reqlevel(isr)));
296		IPSECREQUEST_UNLOCK(isr);
297		isr = isr->next;
298		/*
299		 * If isr is NULL, we found a 'use' policy w/o SA.
300		 * Return w/o error and w/o isr so we can drop out
301		 * and continue w/o IPsec processing.
302		 */
303		if (isr == NULL)
304			return isr;
305		IPSECREQUEST_LOCK(isr);
306		goto again;
307	}
308
309	/*
310	 * Check system global policy controls.
311	 */
312	if ((isr->saidx.proto == IPPROTO_ESP && !V_esp_enable) ||
313	    (isr->saidx.proto == IPPROTO_AH && !V_ah_enable) ||
314	    (isr->saidx.proto == IPPROTO_IPCOMP && !V_ipcomp_enable)) {
315		DPRINTF(("%s: IPsec outbound packet dropped due"
316			" to policy (check your sysctls)\n", __func__));
317		IPSEC_OSTAT(V_espstat.esps_pdrops, V_ahstat.ahs_pdrops,
318		    V_ipcompstat.ipcomps_pdrops);
319		*error = EHOSTUNREACH;
320		goto bad;
321	}
322
323	/*
324	 * Sanity check the SA contents for the caller
325	 * before they invoke the xform output method.
326	 */
327	if (sav->tdb_xform == NULL) {
328		DPRINTF(("%s: no transform for SA\n", __func__));
329		IPSEC_OSTAT(V_espstat.esps_noxform, V_ahstat.ahs_noxform,
330		    V_ipcompstat.ipcomps_noxform);
331		*error = EHOSTUNREACH;
332		goto bad;
333	}
334	return isr;
335bad:
336	IPSEC_ASSERT(*error != 0, ("error return w/ no error code"));
337	IPSECREQUEST_UNLOCK(isr);
338	return NULL;
339#undef IPSEC_OSTAT
340}
341
342#ifdef INET
343/*
344 * IPsec output logic for IPv4.
345 */
346int
347ipsec4_process_packet(
348	struct mbuf *m,
349	struct ipsecrequest *isr,
350	int flags,
351	int tunalready)
352{
353	struct secasindex saidx;
354	struct secasvar *sav;
355	struct ip *ip;
356	int error, i, off;
357
358	IPSEC_ASSERT(m != NULL, ("null mbuf"));
359	IPSEC_ASSERT(isr != NULL, ("null isr"));
360
361	IPSECREQUEST_LOCK(isr);		/* insure SA contents don't change */
362
363	isr = ipsec_nextisr(m, isr, AF_INET, &saidx, &error);
364	if (isr == NULL) {
365		if (error != 0)
366			goto bad;
367		return EJUSTRETURN;
368	}
369
370	sav = isr->sav;
371
372#ifdef DEV_ENC
373	encif->if_opackets++;
374	encif->if_obytes += m->m_pkthdr.len;
375
376	/* pass the mbuf to enc0 for bpf processing */
377	ipsec_bpf(m, sav, AF_INET, ENC_OUT|ENC_BEFORE);
378	/* pass the mbuf to enc0 for packet filtering */
379	if ((error = ipsec_filter(&m, PFIL_OUT, ENC_OUT|ENC_BEFORE)) != 0)
380		goto bad;
381#endif
382
383	if (!tunalready) {
384		union sockaddr_union *dst = &sav->sah->saidx.dst;
385		int setdf;
386
387		/*
388		 * Collect IP_DF state from the outer header.
389		 */
390		if (dst->sa.sa_family == AF_INET) {
391			if (m->m_len < sizeof (struct ip) &&
392			    (m = m_pullup(m, sizeof (struct ip))) == NULL) {
393				error = ENOBUFS;
394				goto bad;
395			}
396			ip = mtod(m, struct ip *);
397			/* Honor system-wide control of how to handle IP_DF */
398			switch (V_ip4_ipsec_dfbit) {
399			case 0:			/* clear in outer header */
400			case 1:			/* set in outer header */
401				setdf = V_ip4_ipsec_dfbit;
402				break;
403			default:		/* propagate to outer header */
404				setdf = ntohs(ip->ip_off & IP_DF);
405				break;
406			}
407		} else {
408			ip = NULL;		/* keep compiler happy */
409			setdf = 0;
410		}
411		/* Do the appropriate encapsulation, if necessary */
412		if (isr->saidx.mode == IPSEC_MODE_TUNNEL || /* Tunnel requ'd */
413		    dst->sa.sa_family != AF_INET ||	    /* PF mismatch */
414#if 0
415		    (sav->flags & SADB_X_SAFLAGS_TUNNEL) || /* Tunnel requ'd */
416		    sav->tdb_xform->xf_type == XF_IP4 ||    /* ditto */
417#endif
418		    (dst->sa.sa_family == AF_INET &&	    /* Proxy */
419		     dst->sin.sin_addr.s_addr != INADDR_ANY &&
420		     dst->sin.sin_addr.s_addr != ip->ip_dst.s_addr)) {
421			struct mbuf *mp;
422
423			/* Fix IPv4 header checksum and length */
424			if (m->m_len < sizeof (struct ip) &&
425			    (m = m_pullup(m, sizeof (struct ip))) == NULL) {
426				error = ENOBUFS;
427				goto bad;
428			}
429			ip = mtod(m, struct ip *);
430			ip->ip_len = htons(m->m_pkthdr.len);
431			ip->ip_sum = 0;
432#ifdef _IP_VHL
433			if (ip->ip_vhl == IP_VHL_BORING)
434				ip->ip_sum = in_cksum_hdr(ip);
435			else
436				ip->ip_sum = in_cksum(m,
437					_IP_VHL_HL(ip->ip_vhl) << 2);
438#else
439			ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
440#endif
441
442			/* Encapsulate the packet */
443			error = ipip_output(m, isr, &mp, 0, 0);
444			if (mp == NULL && !error) {
445				/* Should never happen. */
446				DPRINTF(("%s: ipip_output returns no mbuf and "
447					"no error!", __func__));
448				error = EFAULT;
449			}
450			if (error) {
451				if (mp) {
452					/* XXX: Should never happen! */
453					m_freem(mp);
454				}
455				m = NULL; /* ipip_output() already freed it */
456				goto bad;
457			}
458			m = mp, mp = NULL;
459			/*
460			 * ipip_output clears IP_DF in the new header.  If
461			 * we need to propagate IP_DF from the outer header,
462			 * then we have to do it here.
463			 *
464			 * XXX shouldn't assume what ipip_output does.
465			 */
466			if (dst->sa.sa_family == AF_INET && setdf) {
467				if (m->m_len < sizeof (struct ip) &&
468				    (m = m_pullup(m, sizeof (struct ip))) == NULL) {
469					error = ENOBUFS;
470					goto bad;
471				}
472				ip = mtod(m, struct ip *);
473				ip->ip_off = ntohs(ip->ip_off);
474				ip->ip_off |= IP_DF;
475				ip->ip_off = htons(ip->ip_off);
476			}
477		}
478	}
479
480#ifdef DEV_ENC
481	/* pass the mbuf to enc0 for bpf processing */
482	ipsec_bpf(m, sav, AF_INET, ENC_OUT|ENC_AFTER);
483	/* pass the mbuf to enc0 for packet filtering */
484	if ((error = ipsec_filter(&m, PFIL_OUT, ENC_OUT|ENC_AFTER)) != 0)
485		goto bad;
486#endif
487
488	/*
489	 * Dispatch to the appropriate IPsec transform logic.  The
490	 * packet will be returned for transmission after crypto
491	 * processing, etc. are completed.  For encapsulation we
492	 * bypass this call because of the explicit call done above
493	 * (necessary to deal with IP_DF handling for IPv4).
494	 *
495	 * NB: m & sav are ``passed to caller'' who's reponsible for
496	 *     for reclaiming their resources.
497	 */
498	if (sav->tdb_xform->xf_type != XF_IP4) {
499		ip = mtod(m, struct ip *);
500		i = ip->ip_hl << 2;
501		off = offsetof(struct ip, ip_p);
502		error = (*sav->tdb_xform->xf_output)(m, isr, NULL, i, off);
503	} else {
504		error = ipsec_process_done(m, isr);
505	}
506	IPSECREQUEST_UNLOCK(isr);
507	return error;
508bad:
509	if (isr)
510		IPSECREQUEST_UNLOCK(isr);
511	if (m)
512		m_freem(m);
513	return error;
514}
515#endif
516
517#ifdef INET6
518/*
519 * Chop IP6 header from the payload.
520 */
521static struct mbuf *
522ipsec6_splithdr(struct mbuf *m)
523{
524	struct mbuf *mh;
525	struct ip6_hdr *ip6;
526	int hlen;
527
528	IPSEC_ASSERT(m->m_len >= sizeof (struct ip6_hdr),
529		("first mbuf too short, len %u", m->m_len));
530	ip6 = mtod(m, struct ip6_hdr *);
531	hlen = sizeof(struct ip6_hdr);
532	if (m->m_len > hlen) {
533		MGETHDR(mh, M_DONTWAIT, MT_DATA);
534		if (!mh) {
535			m_freem(m);
536			return NULL;
537		}
538		M_MOVE_PKTHDR(mh, m);
539		MH_ALIGN(mh, hlen);
540		m->m_len -= hlen;
541		m->m_data += hlen;
542		mh->m_next = m;
543		m = mh;
544		m->m_len = hlen;
545		bcopy((caddr_t)ip6, mtod(m, caddr_t), hlen);
546	} else if (m->m_len < hlen) {
547		m = m_pullup(m, hlen);
548		if (!m)
549			return NULL;
550	}
551	return m;
552}
553
554/*
555 * IPsec output logic for IPv6, transport mode.
556 */
557int
558ipsec6_output_trans(
559	struct ipsec_output_state *state,
560	u_char *nexthdrp,
561	struct mbuf *mprev,
562	struct secpolicy *sp,
563	int flags,
564	int *tun)
565{
566	struct ipsecrequest *isr;
567	struct secasindex saidx;
568	int error = 0;
569	struct mbuf *m;
570
571	IPSEC_ASSERT(state != NULL, ("null state"));
572	IPSEC_ASSERT(state->m != NULL, ("null m"));
573	IPSEC_ASSERT(nexthdrp != NULL, ("null nexthdrp"));
574	IPSEC_ASSERT(mprev != NULL, ("null mprev"));
575	IPSEC_ASSERT(sp != NULL, ("null sp"));
576	IPSEC_ASSERT(tun != NULL, ("null tun"));
577
578	KEYDEBUG(KEYDEBUG_IPSEC_DATA,
579		printf("%s: applied SP\n", __func__);
580		kdebug_secpolicy(sp));
581
582	isr = sp->req;
583	if (isr->saidx.mode == IPSEC_MODE_TUNNEL) {
584		/* the rest will be handled by ipsec6_output_tunnel() */
585		*tun = 1;		/* need tunnel-mode processing */
586		return 0;
587	}
588
589	*tun = 0;
590	m = state->m;
591
592	IPSECREQUEST_LOCK(isr);		/* insure SA contents don't change */
593	isr = ipsec_nextisr(m, isr, AF_INET6, &saidx, &error);
594	if (isr == NULL) {
595		if (error != 0) {
596#ifdef notdef
597			/* XXX should notification be done for all errors ? */
598			/*
599			 * Notify the fact that the packet is discarded
600			 * to ourselves. I believe this is better than
601			 * just silently discarding. (jinmei@kame.net)
602			 * XXX: should we restrict the error to TCP packets?
603			 * XXX: should we directly notify sockets via
604			 *      pfctlinputs?
605			 */
606			icmp6_error(m, ICMP6_DST_UNREACH,
607				    ICMP6_DST_UNREACH_ADMIN, 0);
608			m = NULL;	/* NB: icmp6_error frees mbuf */
609#endif
610			goto bad;
611		}
612		return EJUSTRETURN;
613	}
614
615	error = (*isr->sav->tdb_xform->xf_output)(m, isr, NULL,
616						  sizeof (struct ip6_hdr),
617						  offsetof(struct ip6_hdr,
618							   ip6_nxt));
619	IPSECREQUEST_UNLOCK(isr);
620	return error;
621bad:
622	if (isr)
623		IPSECREQUEST_UNLOCK(isr);
624	if (m)
625		m_freem(m);
626	state->m = NULL;
627	return error;
628}
629
630static int
631ipsec6_encapsulate(struct mbuf *m, struct secasvar *sav)
632{
633	struct ip6_hdr *oip6;
634	struct ip6_hdr *ip6;
635	size_t plen;
636
637	/* can't tunnel between different AFs */
638	if (sav->sah->saidx.src.sa.sa_family != AF_INET6 ||
639	    sav->sah->saidx.dst.sa.sa_family != AF_INET6) {
640		m_freem(m);
641		return EINVAL;
642	}
643	IPSEC_ASSERT(m->m_len == sizeof (struct ip6_hdr),
644		("mbuf wrong size; len %u", m->m_len));
645
646
647	/*
648	 * grow the mbuf to accomodate the new IPv6 header.
649	 */
650	plen = m->m_pkthdr.len;
651	if (M_LEADINGSPACE(m->m_next) < sizeof(struct ip6_hdr)) {
652		struct mbuf *n;
653		MGET(n, M_DONTWAIT, MT_DATA);
654		if (!n) {
655			m_freem(m);
656			return ENOBUFS;
657		}
658		n->m_len = sizeof(struct ip6_hdr);
659		n->m_next = m->m_next;
660		m->m_next = n;
661		m->m_pkthdr.len += sizeof(struct ip6_hdr);
662		oip6 = mtod(n, struct ip6_hdr *);
663	} else {
664		m->m_next->m_len += sizeof(struct ip6_hdr);
665		m->m_next->m_data -= sizeof(struct ip6_hdr);
666		m->m_pkthdr.len += sizeof(struct ip6_hdr);
667		oip6 = mtod(m->m_next, struct ip6_hdr *);
668	}
669	ip6 = mtod(m, struct ip6_hdr *);
670	bcopy((caddr_t)ip6, (caddr_t)oip6, sizeof(struct ip6_hdr));
671
672	/* Fake link-local scope-class addresses */
673	if (IN6_IS_SCOPE_LINKLOCAL(&oip6->ip6_src))
674		oip6->ip6_src.s6_addr16[1] = 0;
675	if (IN6_IS_SCOPE_LINKLOCAL(&oip6->ip6_dst))
676		oip6->ip6_dst.s6_addr16[1] = 0;
677
678	/* construct new IPv6 header. see RFC 2401 5.1.2.2 */
679	/* ECN consideration. */
680	ip6_ecn_ingress(V_ip6_ipsec_ecn, &ip6->ip6_flow, &oip6->ip6_flow);
681	if (plen < IPV6_MAXPACKET - sizeof(struct ip6_hdr))
682		ip6->ip6_plen = htons(plen);
683	else {
684		/* ip6->ip6_plen will be updated in ip6_output() */
685	}
686	ip6->ip6_nxt = IPPROTO_IPV6;
687	ip6->ip6_src = sav->sah->saidx.src.sin6.sin6_addr;
688	ip6->ip6_dst = sav->sah->saidx.dst.sin6.sin6_addr;
689	ip6->ip6_hlim = IPV6_DEFHLIM;
690
691	/* XXX Should ip6_src be updated later ? */
692
693	return 0;
694}
695
696/*
697 * IPsec output logic for IPv6, tunnel mode.
698 */
699int
700ipsec6_output_tunnel(struct ipsec_output_state *state, struct secpolicy *sp, int flags)
701{
702	struct ip6_hdr *ip6;
703	struct ipsecrequest *isr;
704	struct secasindex saidx;
705	int error;
706	struct sockaddr_in6* dst6;
707	struct mbuf *m;
708
709	IPSEC_ASSERT(state != NULL, ("null state"));
710	IPSEC_ASSERT(state->m != NULL, ("null m"));
711	IPSEC_ASSERT(sp != NULL, ("null sp"));
712
713	KEYDEBUG(KEYDEBUG_IPSEC_DATA,
714		printf("%s: applied SP\n", __func__);
715		kdebug_secpolicy(sp));
716
717	m = state->m;
718	/*
719	 * transport mode ipsec (before the 1st tunnel mode) is already
720	 * processed by ipsec6_output_trans().
721	 */
722	for (isr = sp->req; isr; isr = isr->next) {
723		if (isr->saidx.mode == IPSEC_MODE_TUNNEL)
724			break;
725	}
726
727	IPSECREQUEST_LOCK(isr);		/* insure SA contents don't change */
728	isr = ipsec_nextisr(m, isr, AF_INET6, &saidx, &error);
729	if (isr == NULL) {
730		if (error != 0)
731			goto bad;
732		return EJUSTRETURN;
733	}
734
735#ifdef DEV_ENC
736	encif->if_opackets++;
737	encif->if_obytes += m->m_pkthdr.len;
738
739	/* pass the mbuf to enc0 for bpf processing */
740	ipsec_bpf(m, isr->sav, AF_INET6, ENC_OUT|ENC_BEFORE);
741	/* pass the mbuf to enc0 for packet filtering */
742	if ((error = ipsec_filter(&m, PFIL_OUT, ENC_OUT|ENC_BEFORE)) != 0)
743		goto bad;
744#endif
745
746	/*
747	 * There may be the case that SA status will be changed when
748	 * we are refering to one. So calling splsoftnet().
749	 */
750	if (isr->saidx.mode == IPSEC_MODE_TUNNEL) {
751		/*
752		 * build IPsec tunnel.
753		 */
754		/* XXX should be processed with other familiy */
755		if (isr->sav->sah->saidx.src.sa.sa_family != AF_INET6) {
756			ipseclog((LOG_ERR, "%s: family mismatched between "
757			    "inner and outer, spi=%u\n", __func__,
758			    ntohl(isr->sav->spi)));
759			V_ipsec6stat.ips_out_inval++;
760			error = EAFNOSUPPORT;
761			goto bad;
762		}
763
764		m = ipsec6_splithdr(m);
765		if (!m) {
766			V_ipsec6stat.ips_out_nomem++;
767			error = ENOMEM;
768			goto bad;
769		}
770		error = ipsec6_encapsulate(m, isr->sav);
771		if (error) {
772			m = NULL;
773			goto bad;
774		}
775		ip6 = mtod(m, struct ip6_hdr *);
776
777		state->ro = &isr->sav->sah->sa_route;
778		state->dst = (struct sockaddr *)&state->ro->ro_dst;
779		dst6 = (struct sockaddr_in6 *)state->dst;
780		if (state->ro->ro_rt
781		 && ((state->ro->ro_rt->rt_flags & RTF_UP) == 0
782		  || !IN6_ARE_ADDR_EQUAL(&dst6->sin6_addr, &ip6->ip6_dst))) {
783			RTFREE(state->ro->ro_rt);
784			state->ro->ro_rt = NULL;
785		}
786		if (state->ro->ro_rt == 0) {
787			bzero(dst6, sizeof(*dst6));
788			dst6->sin6_family = AF_INET6;
789			dst6->sin6_len = sizeof(*dst6);
790			dst6->sin6_addr = ip6->ip6_dst;
791			rtalloc(state->ro);
792		}
793		if (state->ro->ro_rt == 0) {
794			V_ip6stat.ip6s_noroute++;
795			V_ipsec6stat.ips_out_noroute++;
796			error = EHOSTUNREACH;
797			goto bad;
798		}
799
800		/* adjust state->dst if tunnel endpoint is offlink */
801		if (state->ro->ro_rt->rt_flags & RTF_GATEWAY) {
802			state->dst = (struct sockaddr *)state->ro->ro_rt->rt_gateway;
803			dst6 = (struct sockaddr_in6 *)state->dst;
804		}
805	}
806
807	m = ipsec6_splithdr(m);
808	if (!m) {
809		V_ipsec6stat.ips_out_nomem++;
810		error = ENOMEM;
811		goto bad;
812	}
813	ip6 = mtod(m, struct ip6_hdr *);
814
815#ifdef DEV_ENC
816	/* pass the mbuf to enc0 for bpf processing */
817	ipsec_bpf(m, isr->sav, AF_INET6, ENC_OUT|ENC_AFTER);
818	/* pass the mbuf to enc0 for packet filtering */
819	if ((error = ipsec_filter(&m, PFIL_OUT, ENC_OUT|ENC_AFTER)) != 0)
820		goto bad;
821#endif
822
823	error = (*isr->sav->tdb_xform->xf_output)(m, isr, NULL,
824		sizeof (struct ip6_hdr),
825		offsetof(struct ip6_hdr, ip6_nxt));
826	IPSECREQUEST_UNLOCK(isr);
827	return error;
828bad:
829	if (isr)
830		IPSECREQUEST_UNLOCK(isr);
831	if (m)
832		m_freem(m);
833	state->m = NULL;
834	return error;
835}
836#endif /*INET6*/
837