xref: /netbsd-src/sys/netipsec/ipsec_output.c (revision 0df165c04d0a9ca1adde9ed2b890344c937954a6)
1 /*	$NetBSD: ipsec_output.c,v 1.23 2007/10/28 15:48:23 adrianp Exp $	*/
2 
3 /*-
4  * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  * $FreeBSD: /repoman/r/ncvs/src/sys/netipsec/ipsec_output.c,v 1.3.2.2 2003/03/28 20:32:53 sam Exp $
29  */
30 
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: ipsec_output.c,v 1.23 2007/10/28 15:48:23 adrianp Exp $");
33 
34 /*
35  * IPsec output processing.
36  */
37 #include "opt_inet.h"
38 #ifdef __FreeBSD__
39 #include "opt_inet6.h"
40 #endif
41 #include "opt_ipsec.h"
42 
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/mbuf.h>
46 #include <sys/domain.h>
47 #include <sys/protosw.h>
48 #include <sys/socket.h>
49 #include <sys/errno.h>
50 #include <sys/syslog.h>
51 
52 #include <net/if.h>
53 #include <net/route.h>
54 
55 #include <netinet/in.h>
56 #include <netinet/in_systm.h>
57 #include <netinet/ip.h>
58 #include <netinet/ip_var.h>
59 #include <netinet/in_var.h>
60 #include <netinet/ip_ecn.h>
61 #ifdef INET6
62 #  ifdef __FreeBSD__
63 #  include <netinet6/ip6_ecn.h>
64 #  endif
65 #endif
66 
67 #include <netinet/ip6.h>
68 #ifdef INET6
69 #include <netinet6/ip6_var.h>
70 #endif
71 #include <netinet/in_pcb.h>
72 #ifdef INET6
73 #include <netinet/icmp6.h>
74 #endif
75 #ifdef IPSEC_NAT_T
76 #include <netinet/udp.h>
77 #endif
78 
79 #include <netipsec/ipsec.h>
80 #include <netipsec/ipsec_var.h>
81 #ifdef INET6
82 #include <netipsec/ipsec6.h>
83 #endif
84 #include <netipsec/ah_var.h>
85 #include <netipsec/esp_var.h>
86 #include <netipsec/ipcomp_var.h>
87 
88 #include <netipsec/xform.h>
89 
90 #include <netipsec/key.h>
91 #include <netipsec/keydb.h>
92 #include <netipsec/key_debug.h>
93 #include <netipsec/ipsec_osdep.h>
94 
95 #include <net/net_osdep.h>		/* ovbcopy() in ipsec6_encapsulate() */
96 
97 int
98 ipsec_process_done(struct mbuf *m, struct ipsecrequest *isr)
99 {
100 	struct tdb_ident *tdbi;
101 	struct m_tag *mtag;
102 	struct secasvar *sav;
103 	struct secasindex *saidx;
104 	int error;
105 #ifdef INET
106 	struct ip * ip;
107 #endif /* INET */
108 #ifdef INET6
109 	struct ip6_hdr * ip6;
110 #endif /* INET6 */
111 #ifdef IPSEC_NAT_T
112 	struct mbuf * mo;
113 	struct udphdr *udp = NULL;
114 	uint64_t * data = NULL;
115 	int hlen, roff;
116 #endif /* IPSEC_NAT_T */
117 
118 	IPSEC_SPLASSERT_SOFTNET("ipsec_process_done");
119 
120 	IPSEC_ASSERT(m != NULL, ("ipsec_process_done: null mbuf"));
121 	IPSEC_ASSERT(isr != NULL, ("ipsec_process_done: null ISR"));
122 	sav = isr->sav;
123 	IPSEC_ASSERT(sav != NULL, ("ipsec_process_done: null SA"));
124 	IPSEC_ASSERT(sav->sah != NULL, ("ipsec_process_done: null SAH"));
125 
126 	saidx = &sav->sah->saidx;
127 
128 #ifdef IPSEC_NAT_T
129 	if(sav->natt_type != 0) {
130 		ip = mtod(m, struct ip *);
131 
132 		hlen = sizeof(struct udphdr);
133 		if (sav->natt_type == UDP_ENCAP_ESPINUDP_NON_IKE)
134 			hlen += sizeof(uint64_t);
135 
136 		mo = m_makespace(m, sizeof(struct ip), hlen, &roff);
137 		if (mo == NULL) {
138 			DPRINTF(("ipsec_process_done : failed to inject"
139 				 "%u byte UDP for SA %s/%08lx\n",
140 					 hlen, ipsec_address(&saidx->dst),
141 					 (u_long) ntohl(sav->spi)));
142 			error = ENOBUFS;
143 			goto bad;
144 		}
145 
146 		udp = (struct udphdr*) (mtod(mo, char*) + roff);
147 		data = (uint64_t*) (udp + 1);
148 
149 		if (sav->natt_type == UDP_ENCAP_ESPINUDP_NON_IKE)
150 			*data = 0; /* NON-IKE Marker */
151 
152 		if (sav->natt_type == UDP_ENCAP_ESPINUDP_NON_IKE)
153 			udp->uh_sport = htons(UDP_ENCAP_ESPINUDP_PORT);
154 		else
155 			udp->uh_sport = key_portfromsaddr(&saidx->src);
156 
157 		udp->uh_dport = key_portfromsaddr(&saidx->dst);
158 		udp->uh_sum = 0;
159 #ifdef _IP_VHL
160         	udp->uh_ulen = htons(m->m_pkthdr.len -
161 				    (IP_VHL_HL(ip->ip_vhl) << 2));
162 #else
163         	udp->uh_ulen = htons(m->m_pkthdr.len - (ip->ip_hl << 2));
164 #endif
165 	}
166 #endif /* IPSEC_NAT_T */
167 
168 	switch (saidx->dst.sa.sa_family) {
169 #ifdef INET
170 	case AF_INET:
171 		/* Fix the header length, for AH processing. */
172 		ip = mtod(m, struct ip *);
173 		ip->ip_len = htons(m->m_pkthdr.len);
174 #ifdef IPSEC_NAT_T
175 		if (sav->natt_type != 0)
176 			ip->ip_p = IPPROTO_UDP;
177 #endif /* IPSEC_NAT_T */
178 		break;
179 #endif /* INET */
180 #ifdef INET6
181 	case AF_INET6:
182 		/* Fix the header length, for AH processing. */
183 		if (m->m_pkthdr.len < sizeof (struct ip6_hdr)) {
184 			error = ENXIO;
185 			goto bad;
186 		}
187 		if (m->m_pkthdr.len - sizeof (struct ip6_hdr) > IPV6_MAXPACKET) {
188 			/* No jumbogram support. */
189 			error = ENXIO;	/*?*/
190 			goto bad;
191 		}
192 		ip6 = mtod(m, struct ip6_hdr *);
193 		ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr));
194 #ifdef IPSEC_NAT_T
195 		if (sav->natt_type != 0)
196 			ip6->ip6_nxt = IPPROTO_UDP;
197 #endif /* IPSEC_NAT_T */
198 		break;
199 #endif /* INET6 */
200 	default:
201 		DPRINTF(("ipsec_process_done: unknown protocol family %u\n",
202 		    saidx->dst.sa.sa_family));
203 		error = ENXIO;
204 		goto bad;
205 	}
206 
207 	/*
208 	 * Add a record of what we've done or what needs to be done to the
209 	 * packet.
210 	 */
211 	mtag = m_tag_get(PACKET_TAG_IPSEC_OUT_DONE,
212 			sizeof(struct tdb_ident), M_NOWAIT);
213 	if (mtag == NULL) {
214 		DPRINTF(("ipsec_process_done: could not get packet tag\n"));
215 		error = ENOMEM;
216 		goto bad;
217 	}
218 
219 	tdbi = (struct tdb_ident *)(mtag + 1);
220 	tdbi->dst = saidx->dst;
221 	tdbi->proto = saidx->proto;
222 	tdbi->spi = sav->spi;
223 	m_tag_prepend(m, mtag);
224 
225 	/*
226 	 * If there's another (bundled) SA to apply, do so.
227 	 * Note that this puts a burden on the kernel stack size.
228 	 * If this is a problem we'll need to introduce a queue
229 	 * to set the packet on so we can unwind the stack before
230 	 * doing further processing.
231 	 */
232 	if (isr->next) {
233 		newipsecstat.ips_out_bundlesa++;
234         switch ( saidx->dst.sa.sa_family ) {
235 #ifdef INET
236         case AF_INET:
237 			return ipsec4_process_packet(m, isr->next, 0,0);
238 #endif /* INET */
239 #ifdef INET6
240 		case AF_INET6:
241         	return ipsec6_process_packet(m,isr->next);
242 #endif /* INET6 */
243 		default :
244 			DPRINTF(("ipsec_process_done: unknown protocol family %u\n",
245                                saidx->dst.sa.sa_family));
246 			error = ENXIO;
247 			goto bad;
248         }
249 	}
250 
251 	/*
252 	 * We're done with IPsec processing, transmit the packet using the
253 	 * appropriate network protocol (IP or IPv6). SPD lookup will be
254 	 * performed again there.
255 	 */
256 	switch (saidx->dst.sa.sa_family) {
257 #ifdef INET
258 	case AF_INET:
259 		ip = mtod(m, struct ip *);
260 #ifdef __FreeBSD__
261 		/* FreeBSD ip_output() expects ip_len, ip_off in host endian */
262 		ip->ip_len = ntohs(ip->ip_len);
263 		ip->ip_off = ntohs(ip->ip_off);
264 #endif /* __FreeBSD_ */
265 		return ip_output(m, NULL, NULL, IP_RAWOUTPUT,
266 		    (struct ip_moptions *)NULL, (struct socket *)NULL);
267 
268 #endif /* INET */
269 #ifdef INET6
270 	case AF_INET6:
271 		/*
272 		 * We don't need massage, IPv6 header fields are always in
273 		 * net endian.
274 		 */
275 		return ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL);
276 #endif /* INET6 */
277 	}
278 	panic("ipsec_process_done");
279 bad:
280 	m_freem(m);
281 	KEY_FREESAV(&sav);
282 	return (error);
283 }
284 
285 static struct ipsecrequest *
286 ipsec_nextisr(
287 	struct mbuf *m,
288 	struct ipsecrequest *isr,
289 	int af,
290 	struct secasindex *saidx,
291 	int *error
292 )
293 {
294 #define IPSEC_OSTAT(x,y,z) (isr->saidx.proto == IPPROTO_ESP ? (x)++ : \
295 			    isr->saidx.proto == IPPROTO_AH ? (y)++ : (z)++)
296 	struct secasvar *sav;
297 
298 	IPSEC_SPLASSERT_SOFTNET("ipsec_nextisr");
299 	IPSEC_ASSERT(af == AF_INET || af == AF_INET6,
300 		("ipsec_nextisr: invalid address family %u", af));
301 again:
302 	/*
303 	 * Craft SA index to search for proper SA.  Note that
304 	 * we only fillin unspecified SA peers for transport
305 	 * mode; for tunnel mode they must already be filled in.
306 	 */
307 	*saidx = isr->saidx;
308 	if (isr->saidx.mode == IPSEC_MODE_TRANSPORT) {
309 		/* Fillin unspecified SA peers only for transport mode */
310 		if (af == AF_INET) {
311 			struct sockaddr_in *sin;
312 			struct ip *ip = mtod(m, struct ip *);
313 
314 			if (saidx->src.sa.sa_len == 0) {
315 				sin = &saidx->src.sin;
316 				sin->sin_len = sizeof(*sin);
317 				sin->sin_family = AF_INET;
318 				sin->sin_port = IPSEC_PORT_ANY;
319 				sin->sin_addr = ip->ip_src;
320 			}
321 			if (saidx->dst.sa.sa_len == 0) {
322 				sin = &saidx->dst.sin;
323 				sin->sin_len = sizeof(*sin);
324 				sin->sin_family = AF_INET;
325 				sin->sin_port = IPSEC_PORT_ANY;
326 				sin->sin_addr = ip->ip_dst;
327 			}
328 		} else {
329 			struct sockaddr_in6 *sin6;
330 			struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
331 
332 			if (saidx->src.sin6.sin6_len == 0) {
333 				sin6 = (struct sockaddr_in6 *)&saidx->src;
334 				sin6->sin6_len = sizeof(*sin6);
335 				sin6->sin6_family = AF_INET6;
336 				sin6->sin6_port = IPSEC_PORT_ANY;
337 				sin6->sin6_addr = ip6->ip6_src;
338 				if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) {
339 					/* fix scope id for comparing SPD */
340 					sin6->sin6_addr.s6_addr16[1] = 0;
341 					sin6->sin6_scope_id =
342 					    ntohs(ip6->ip6_src.s6_addr16[1]);
343 				}
344 			}
345 			if (saidx->dst.sin6.sin6_len == 0) {
346 				sin6 = (struct sockaddr_in6 *)&saidx->dst;
347 				sin6->sin6_len = sizeof(*sin6);
348 				sin6->sin6_family = AF_INET6;
349 				sin6->sin6_port = IPSEC_PORT_ANY;
350 				sin6->sin6_addr = ip6->ip6_dst;
351 				if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) {
352 					/* fix scope id for comparing SPD */
353 					sin6->sin6_addr.s6_addr16[1] = 0;
354 					sin6->sin6_scope_id =
355 					    ntohs(ip6->ip6_dst.s6_addr16[1]);
356 				}
357 			}
358 		}
359 	}
360 
361 	/*
362 	 * Lookup SA and validate it.
363 	 */
364 	*error = key_checkrequest(isr, saidx);
365 	if (*error != 0) {
366 		/*
367 		 * IPsec processing is required, but no SA found.
368 		 * I assume that key_acquire() had been called
369 		 * to get/establish the SA. Here I discard
370 		 * this packet because it is responsibility for
371 		 * upper layer to retransmit the packet.
372 		 */
373 		newipsecstat.ips_out_nosa++;
374 		goto bad;
375 	}
376 	sav = isr->sav;
377 	if (sav == NULL) {		/* XXX valid return */
378 		IPSEC_ASSERT(ipsec_get_reqlevel(isr) == IPSEC_LEVEL_USE,
379 			("ipsec_nextisr: no SA found, but required; level %u",
380 			ipsec_get_reqlevel(isr)));
381 		isr = isr->next;
382 		if (isr == NULL) {
383 			/*XXXstatistic??*/
384 			*error = EINVAL;		/*XXX*/
385 			return isr;
386 		}
387 		goto again;
388 	}
389 
390 	/*
391 	 * Check system global policy controls.
392 	 */
393 	if ((isr->saidx.proto == IPPROTO_ESP && !esp_enable) ||
394 	    (isr->saidx.proto == IPPROTO_AH && !ah_enable) ||
395 	    (isr->saidx.proto == IPPROTO_IPCOMP && !ipcomp_enable)) {
396 		DPRINTF(("ipsec_nextisr: IPsec outbound packet dropped due"
397 			" to policy (check your sysctls)\n"));
398 		IPSEC_OSTAT(espstat.esps_pdrops, ahstat.ahs_pdrops,
399 		    ipcompstat.ipcomps_pdrops);
400 		*error = EHOSTUNREACH;
401 		goto bad;
402 	}
403 
404 	/*
405 	 * Sanity check the SA contents for the caller
406 	 * before they invoke the xform output method.
407 	 */
408 	if (sav->tdb_xform == NULL) {
409 		DPRINTF(("ipsec_nextisr: no transform for SA\n"));
410 		IPSEC_OSTAT(espstat.esps_noxform, ahstat.ahs_noxform,
411 		    ipcompstat.ipcomps_noxform);
412 		*error = EHOSTUNREACH;
413 		goto bad;
414 	}
415 	return isr;
416 bad:
417 	IPSEC_ASSERT(*error != 0, ("ipsec_nextisr: error return w/ no error code"));
418 	return NULL;
419 #undef IPSEC_OSTAT
420 }
421 
422 #ifdef INET
423 /*
424  * IPsec output logic for IPv4.
425  */
426 int
427 ipsec4_process_packet(
428     struct mbuf *m,
429     struct ipsecrequest *isr,
430     int flags,
431     int tunalready
432 )
433 {
434 	struct secasindex saidx;
435 	struct secasvar *sav;
436 	struct ip *ip;
437 	int s, error, i, off;
438 
439 	IPSEC_ASSERT(m != NULL, ("ipsec4_process_packet: null mbuf"));
440 	IPSEC_ASSERT(isr != NULL, ("ipsec4_process_packet: null isr"));
441 
442 	s = splsoftnet();			/* insure SA contents don't change */
443 
444 	isr = ipsec_nextisr(m, isr, AF_INET, &saidx, &error);
445 	if (isr == NULL)
446 		goto bad;
447 
448 	sav = isr->sav;
449 	if (!tunalready) {
450 		union sockaddr_union *dst = &sav->sah->saidx.dst;
451 		int setdf;
452 
453 		/*
454 		 * Collect IP_DF state from the outer header.
455 		 */
456 		if (dst->sa.sa_family == AF_INET) {
457 			if (m->m_len < sizeof (struct ip) &&
458 			    (m = m_pullup(m, sizeof (struct ip))) == NULL) {
459 				error = ENOBUFS;
460 				goto bad;
461 			}
462 			ip = mtod(m, struct ip *);
463 			/* Honor system-wide control of how to handle IP_DF */
464 			switch (ip4_ipsec_dfbit) {
465 			case 0:			/* clear in outer header */
466 			case 1:			/* set in outer header */
467 				setdf = ip4_ipsec_dfbit;
468 				break;
469 			default:		/* propagate to outer header */
470 				setdf = ip->ip_off;
471 #ifndef __FreeBSD__
472 		/* On FreeBSD, ip_off and ip_len assumed in host endian. */
473 				setdf = ntohs(setdf);
474 #endif
475 				setdf = htons(setdf & IP_DF);
476 				break;
477 			}
478 		} else {
479 			ip = NULL;		/* keep compiler happy */
480 			setdf = 0;
481 		}
482 		/* Do the appropriate encapsulation, if necessary */
483 		if (isr->saidx.mode == IPSEC_MODE_TUNNEL || /* Tunnel requ'd */
484 		    dst->sa.sa_family != AF_INET ||	    /* PF mismatch */
485 #if 0
486 		    (sav->flags & SADB_X_SAFLAGS_TUNNEL) || /* Tunnel requ'd */
487 		    sav->tdb_xform->xf_type == XF_IP4 ||    /* ditto */
488 #endif
489 		    (dst->sa.sa_family == AF_INET &&	    /* Proxy */
490 		     dst->sin.sin_addr.s_addr != INADDR_ANY &&
491 		     dst->sin.sin_addr.s_addr != ip->ip_dst.s_addr)) {
492 			struct mbuf *mp;
493 
494 			/* Fix IPv4 header checksum and length */
495 			if (m->m_len < sizeof (struct ip) &&
496 			    (m = m_pullup(m, sizeof (struct ip))) == NULL) {
497 				error = ENOBUFS;
498 				goto bad;
499 			}
500 			ip = mtod(m, struct ip *);
501 			ip->ip_len = htons(m->m_pkthdr.len);
502 			ip->ip_sum = 0;
503 #ifdef _IP_VHL
504 			if (ip->ip_vhl == IP_VHL_BORING)
505 				ip->ip_sum = in_cksum_hdr(ip);
506 			else
507 				ip->ip_sum = in_cksum(m,
508 					_IP_VHL_HL(ip->ip_vhl) << 2);
509 #else
510 			ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
511 #endif
512 
513 			/* Encapsulate the packet */
514 			error = ipip_output(m, isr, &mp, 0, 0);
515 			if (mp == NULL && !error) {
516 				/* Should never happen. */
517 				DPRINTF(("ipsec4_process_packet: ipip_output "
518 					"returns no mbuf and no error!"));
519 				error = EFAULT;
520 			}
521 			if (error) {
522 				if (mp) {
523 					/* XXX: Should never happen! */
524 					m_freem(mp);
525 				}
526 				m = NULL; /* ipip_output() already freed it */
527 				goto bad;
528 			}
529 			m = mp, mp = NULL;
530 			/*
531 			 * ipip_output clears IP_DF in the new header.  If
532 			 * we need to propagate IP_DF from the outer header,
533 			 * then we have to do it here.
534 			 *
535 			 * XXX shouldn't assume what ipip_output does.
536 			 */
537 			if (dst->sa.sa_family == AF_INET && setdf) {
538 				if (m->m_len < sizeof (struct ip) &&
539 				    (m = m_pullup(m, sizeof (struct ip))) == NULL) {
540 					error = ENOBUFS;
541 					goto bad;
542 				}
543 				ip = mtod(m, struct ip *);
544 				ip->ip_off |= IP_OFF_CONVERT(IP_DF);
545 			}
546 		}
547 	}
548 
549 	/*
550 	 * Dispatch to the appropriate IPsec transform logic.  The
551 	 * packet will be returned for transmission after crypto
552 	 * processing, etc. are completed.  For encapsulation we
553 	 * bypass this call because of the explicit call done above
554 	 * (necessary to deal with IP_DF handling for IPv4).
555 	 *
556 	 * NB: m & sav are ``passed to caller'' who's reponsible for
557 	 *     for reclaiming their resources.
558 	 */
559 	if (sav->tdb_xform->xf_type != XF_IP4) {
560 		ip = mtod(m, struct ip *);
561 		i = ip->ip_hl << 2;
562 		off = offsetof(struct ip, ip_p);
563 		error = (*sav->tdb_xform->xf_output)(m, isr, NULL, i, off);
564 	} else {
565 		error = ipsec_process_done(m, isr);
566 	}
567 	splx(s);
568 	return error;
569 bad:
570 	splx(s);
571 	if (m)
572 		m_freem(m);
573 	return error;
574 }
575 #endif
576 
577 #ifdef INET6
578 int
579 ipsec6_process_packet(
580 	struct mbuf *m,
581  	struct ipsecrequest *isr
582     )
583 {
584 	struct secasindex saidx;
585 	struct secasvar *sav;
586 	struct ip6_hdr *ip6;
587 	int s, error, i, off;
588 
589 	IPSEC_ASSERT(m != NULL, ("ipsec6_process_packet: null mbuf"));
590 	IPSEC_ASSERT(isr != NULL, ("ipsec6_process_packet: null isr"));
591 
592 	s = splsoftnet();   /* insure SA contents don't change */
593 	isr = ipsec_nextisr(m, isr, AF_INET6, &saidx, &error);
594 	if (isr == NULL) {
595 		// XXX Should we send a notification ?
596 		goto bad;
597 	}
598 
599 	sav = isr->sav;
600 	if (sav->tdb_xform->xf_type != XF_IP4) {
601 		i = sizeof(struct ip6_hdr);
602 		off = offsetof(struct ip6_hdr, ip6_nxt);
603 		error = (*sav->tdb_xform->xf_output)(m, isr, NULL, i, off);
604        } else {
605 		union sockaddr_union *dst = &sav->sah->saidx.dst;
606 
607         ip6 = mtod(m, struct ip6_hdr *);
608 
609 		/* Do the appropriate encapsulation, if necessary */
610 		if (isr->saidx.mode == IPSEC_MODE_TUNNEL || /* Tunnel requ'd */
611                dst->sa.sa_family != AF_INET6 ||        /* PF mismatch */
612             ((dst->sa.sa_family == AF_INET6) &&
613                 (!IN6_IS_ADDR_UNSPECIFIED(&dst->sin6.sin6_addr)) &&
614                 (!IN6_ARE_ADDR_EQUAL(&dst->sin6.sin6_addr,
615                 &ip6->ip6_dst)))
616             )
617 		{
618 			struct mbuf *mp;
619             /* Fix IPv6 header payload length. */
620             if (m->m_len < sizeof(struct ip6_hdr))
621                 if ((m = m_pullup(m,sizeof(struct ip6_hdr))) == NULL)
622                    return ENOBUFS;
623 
624             if (m->m_pkthdr.len - sizeof(*ip6) > IPV6_MAXPACKET) {
625                 /* No jumbogram support. */
626                 m_freem(m);
627                 return ENXIO;   /*XXX*/
628             }
629             ip6 = mtod(m, struct ip6_hdr *);
630             ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(*ip6));
631 
632 			/* Encapsulate the packet */
633 			error = ipip_output(m, isr, &mp, 0, 0);
634 			if (mp == NULL && !error) {
635 				/* Should never happen. */
636 				DPRINTF(("ipsec6_process_packet: ipip_output "
637 						 "returns no mbuf and no error!"));
638 				 error = EFAULT;
639 			}
640 
641 			if (error) {
642 				if (mp) {
643 					/* XXX: Should never happen! */
644 					m_freem(mp);
645 				}
646 				m = NULL; /* ipip_output() already freed it */
647 				goto bad;
648 			}
649 
650 			m = mp;
651 			mp = NULL;
652 		}
653 
654 		error = ipsec_process_done(m,isr);
655 		}
656 		splx(s);
657 		return error;
658 bad:
659 	splx(s);
660 	if (m)
661 		m_freem(m);
662 	return error;
663 }
664 #endif /*INET6*/
665