xref: /freebsd/sys/netipsec/ipsec_output.c (revision becbad1f6e18fec7c3bf286778a766ffca4457be)
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$
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 
46 #include <net/if.h>
47 #include <net/if_var.h>
48 #include <net/pfil.h>
49 #include <net/vnet.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 #include <netinet6/scope6_var.h>
65 #endif
66 #include <netinet/in_pcb.h>
67 #ifdef INET6
68 #include <netinet/icmp6.h>
69 #endif
70 
71 #include <netipsec/ipsec.h>
72 #ifdef INET6
73 #include <netipsec/ipsec6.h>
74 #endif
75 #include <netipsec/ah_var.h>
76 #include <netipsec/esp_var.h>
77 #include <netipsec/ipcomp_var.h>
78 
79 #include <netipsec/xform.h>
80 
81 #include <netipsec/key.h>
82 #include <netipsec/keydb.h>
83 #include <netipsec/key_debug.h>
84 
85 #include <machine/in_cksum.h>
86 
87 #ifdef IPSEC_NAT_T
88 #include <netinet/udp.h>
89 #endif
90 
91 #ifdef DEV_ENC
92 #include <net/if_enc.h>
93 #endif
94 
95 
96 int
97 ipsec_process_done(struct mbuf *m, struct ipsecrequest *isr)
98 {
99 	struct tdb_ident *tdbi;
100 	struct m_tag *mtag;
101 	struct secasvar *sav;
102 	struct secasindex *saidx;
103 	int error;
104 
105 	IPSEC_ASSERT(m != NULL, ("null mbuf"));
106 	IPSEC_ASSERT(isr != NULL, ("null ISR"));
107 	IPSEC_ASSERT(isr->sp != NULL, ("NULL isr->sp"));
108 	sav = isr->sav;
109 	IPSEC_ASSERT(sav != NULL, ("null SA"));
110 	IPSEC_ASSERT(sav->sah != NULL, ("null SAH"));
111 
112 	saidx = &sav->sah->saidx;
113 	switch (saidx->dst.sa.sa_family) {
114 #ifdef INET
115 	case AF_INET:
116 		/* Fix the header length, for AH processing. */
117 		mtod(m, struct ip *)->ip_len = htons(m->m_pkthdr.len);
118 		break;
119 #endif /* INET */
120 #ifdef INET6
121 	case AF_INET6:
122 		/* Fix the header length, for AH processing. */
123 		if (m->m_pkthdr.len < sizeof (struct ip6_hdr)) {
124 			error = ENXIO;
125 			goto bad;
126 		}
127 		if (m->m_pkthdr.len - sizeof (struct ip6_hdr) > IPV6_MAXPACKET) {
128 			/* No jumbogram support. */
129 			error = ENXIO;	/*?*/
130 			goto bad;
131 		}
132 		mtod(m, struct ip6_hdr *)->ip6_plen =
133 			htons(m->m_pkthdr.len - sizeof(struct ip6_hdr));
134 		break;
135 #endif /* INET6 */
136 	default:
137 		DPRINTF(("%s: unknown protocol family %u\n", __func__,
138 		    saidx->dst.sa.sa_family));
139 		error = ENXIO;
140 		goto bad;
141 	}
142 
143 	/*
144 	 * Add a record of what we've done or what needs to be done to the
145 	 * packet.
146 	 */
147 	mtag = m_tag_get(PACKET_TAG_IPSEC_OUT_DONE,
148 			sizeof(struct tdb_ident), M_NOWAIT);
149 	if (mtag == NULL) {
150 		DPRINTF(("%s: could not get packet tag\n", __func__));
151 		error = ENOMEM;
152 		goto bad;
153 	}
154 
155 	tdbi = (struct tdb_ident *)(mtag + 1);
156 	tdbi->dst = saidx->dst;
157 	tdbi->proto = saidx->proto;
158 	tdbi->spi = sav->spi;
159 	m_tag_prepend(m, mtag);
160 
161 	key_sa_recordxfer(sav, m);		/* record data transfer */
162 
163 	/*
164 	 * If there's another (bundled) SA to apply, do so.
165 	 * Note that this puts a burden on the kernel stack size.
166 	 * If this is a problem we'll need to introduce a queue
167 	 * to set the packet on so we can unwind the stack before
168 	 * doing further processing.
169 	 */
170 	if (isr->next) {
171 		/* XXX-BZ currently only support same AF bundles. */
172 		switch (saidx->dst.sa.sa_family) {
173 #ifdef INET
174 		case AF_INET:
175 			IPSECSTAT_INC(ips_out_bundlesa);
176 			return (ipsec4_process_packet(m, isr->next));
177 			/* NOTREACHED */
178 #endif
179 #ifdef notyet
180 #ifdef INET6
181 		case AF_INET6:
182 			/* XXX */
183 			IPSEC6STAT_INC(ips_out_bundlesa);
184 			return (ipsec6_process_packet(m, isr->next));
185 			/* NOTREACHED */
186 #endif /* INET6 */
187 #endif
188 		default:
189 			DPRINTF(("%s: unknown protocol family %u\n", __func__,
190 			    saidx->dst.sa.sa_family));
191 			error = ENXIO;
192 			goto bad;
193 		}
194 	}
195 
196 	/*
197 	 * We're done with IPsec processing, transmit the packet using the
198 	 * appropriate network protocol (IP or IPv6).
199 	 */
200 	switch (saidx->dst.sa.sa_family) {
201 #ifdef INET
202 	case AF_INET:
203 #ifdef IPSEC_NAT_T
204 		/*
205 		 * If NAT-T is enabled, now that all IPsec processing is done
206 		 * insert UDP encapsulation header after IP header.
207 		 */
208 		if (sav->natt_type) {
209 			struct ip *ip = mtod(m, struct ip *);
210 			const int hlen = (ip->ip_hl << 2);
211 			int size, off;
212 			struct mbuf *mi;
213 			struct udphdr *udp;
214 
215 			size = sizeof(struct udphdr);
216 			if (sav->natt_type == UDP_ENCAP_ESPINUDP_NON_IKE) {
217 				/*
218 				 * draft-ietf-ipsec-nat-t-ike-0[01].txt and
219 				 * draft-ietf-ipsec-udp-encaps-(00/)01.txt,
220 				 * ignoring possible AH mode
221 				 * non-IKE marker + non-ESP marker
222 				 * from draft-ietf-ipsec-udp-encaps-00.txt.
223 				 */
224 				size += sizeof(u_int64_t);
225 			}
226 			mi = m_makespace(m, hlen, size, &off);
227 			if (mi == NULL) {
228 				DPRINTF(("%s: m_makespace for udphdr failed\n",
229 				    __func__));
230 				error = ENOBUFS;
231 				goto bad;
232 			}
233 
234 			udp = (struct udphdr *)(mtod(mi, caddr_t) + off);
235 			if (sav->natt_type == UDP_ENCAP_ESPINUDP_NON_IKE)
236 				udp->uh_sport = htons(UDP_ENCAP_ESPINUDP_PORT);
237 			else
238 				udp->uh_sport =
239 					KEY_PORTFROMSADDR(&sav->sah->saidx.src);
240 			udp->uh_dport = KEY_PORTFROMSADDR(&sav->sah->saidx.dst);
241 			udp->uh_sum = 0;
242 			udp->uh_ulen = htons(m->m_pkthdr.len - hlen);
243 			ip->ip_len = htons(m->m_pkthdr.len);
244 			ip->ip_p = IPPROTO_UDP;
245 
246 			if (sav->natt_type == UDP_ENCAP_ESPINUDP_NON_IKE)
247 				*(u_int64_t *)(udp + 1) = 0;
248 		}
249 #endif /* IPSEC_NAT_T */
250 
251 		return ip_output(m, NULL, NULL, IP_RAWOUTPUT, NULL, NULL);
252 #endif /* INET */
253 #ifdef INET6
254 	case AF_INET6:
255 		/*
256 		 * We don't need massage, IPv6 header fields are always in
257 		 * net endian.
258 		 */
259 		return ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL);
260 #endif /* INET6 */
261 	}
262 	panic("ipsec_process_done");
263 bad:
264 	m_freem(m);
265 	return (error);
266 }
267 
268 static struct ipsecrequest *
269 ipsec_nextisr(
270 	struct mbuf *m,
271 	struct ipsecrequest *isr,
272 	int af,
273 	struct secasindex *saidx,
274 	int *error
275 )
276 {
277 #define	IPSEC_OSTAT(name)	do {		\
278 	if (isr->saidx.proto == IPPROTO_ESP)	\
279 		ESPSTAT_INC(esps_##name);	\
280 	else if (isr->saidx.proto == IPPROTO_AH)\
281 		AHSTAT_INC(ahs_##name);		\
282 	else					\
283 		IPCOMPSTAT_INC(ipcomps_##name);	\
284 } while (0)
285 	struct secasvar *sav;
286 
287 	IPSECREQUEST_LOCK_ASSERT(isr);
288 
289 	IPSEC_ASSERT(af == AF_INET || af == AF_INET6,
290 		("invalid address family %u", af));
291 again:
292 	/*
293 	 * Craft SA index to search for proper SA.  Note that
294 	 * we only fillin unspecified SA peers for transport
295 	 * mode; for tunnel mode they must already be filled in.
296 	 */
297 	*saidx = isr->saidx;
298 	if (isr->saidx.mode == IPSEC_MODE_TRANSPORT) {
299 		/* Fillin unspecified SA peers only for transport mode */
300 		if (af == AF_INET) {
301 			struct sockaddr_in *sin;
302 			struct ip *ip = mtod(m, struct ip *);
303 
304 			if (saidx->src.sa.sa_len == 0) {
305 				sin = &saidx->src.sin;
306 				sin->sin_len = sizeof(*sin);
307 				sin->sin_family = AF_INET;
308 				sin->sin_port = IPSEC_PORT_ANY;
309 				sin->sin_addr = ip->ip_src;
310 			}
311 			if (saidx->dst.sa.sa_len == 0) {
312 				sin = &saidx->dst.sin;
313 				sin->sin_len = sizeof(*sin);
314 				sin->sin_family = AF_INET;
315 				sin->sin_port = IPSEC_PORT_ANY;
316 				sin->sin_addr = ip->ip_dst;
317 			}
318 		} else {
319 			struct sockaddr_in6 *sin6;
320 			struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
321 
322 			if (saidx->src.sin6.sin6_len == 0) {
323 				sin6 = (struct sockaddr_in6 *)&saidx->src;
324 				sin6->sin6_len = sizeof(*sin6);
325 				sin6->sin6_family = AF_INET6;
326 				sin6->sin6_port = IPSEC_PORT_ANY;
327 				sin6->sin6_addr = ip6->ip6_src;
328 				if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) {
329 					/* fix scope id for comparing SPD */
330 					sin6->sin6_addr.s6_addr16[1] = 0;
331 					sin6->sin6_scope_id =
332 					    ntohs(ip6->ip6_src.s6_addr16[1]);
333 				}
334 			}
335 			if (saidx->dst.sin6.sin6_len == 0) {
336 				sin6 = (struct sockaddr_in6 *)&saidx->dst;
337 				sin6->sin6_len = sizeof(*sin6);
338 				sin6->sin6_family = AF_INET6;
339 				sin6->sin6_port = IPSEC_PORT_ANY;
340 				sin6->sin6_addr = ip6->ip6_dst;
341 				if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) {
342 					/* fix scope id for comparing SPD */
343 					sin6->sin6_addr.s6_addr16[1] = 0;
344 					sin6->sin6_scope_id =
345 					    ntohs(ip6->ip6_dst.s6_addr16[1]);
346 				}
347 			}
348 		}
349 	}
350 
351 	/*
352 	 * Lookup SA and validate it.
353 	 */
354 	*error = key_checkrequest(isr, saidx);
355 	if (*error != 0) {
356 		/*
357 		 * IPsec processing is required, but no SA found.
358 		 * I assume that key_acquire() had been called
359 		 * to get/establish the SA. Here I discard
360 		 * this packet because it is responsibility for
361 		 * upper layer to retransmit the packet.
362 		 */
363 		switch(af) {
364 		case AF_INET:
365 			IPSECSTAT_INC(ips_out_nosa);
366 			break;
367 #ifdef INET6
368 		case AF_INET6:
369 			IPSEC6STAT_INC(ips_out_nosa);
370 			break;
371 #endif
372 		}
373 		goto bad;
374 	}
375 	sav = isr->sav;
376 	if (sav == NULL) {
377 		IPSEC_ASSERT(ipsec_get_reqlevel(isr) == IPSEC_LEVEL_USE,
378 			("no SA found, but required; level %u",
379 			ipsec_get_reqlevel(isr)));
380 		IPSECREQUEST_UNLOCK(isr);
381 		isr = isr->next;
382 		/*
383 		 * If isr is NULL, we found a 'use' policy w/o SA.
384 		 * Return w/o error and w/o isr so we can drop out
385 		 * and continue w/o IPsec processing.
386 		 */
387 		if (isr == NULL)
388 			return isr;
389 		IPSECREQUEST_LOCK(isr);
390 		goto again;
391 	}
392 
393 	/*
394 	 * Check system global policy controls.
395 	 */
396 	if ((isr->saidx.proto == IPPROTO_ESP && !V_esp_enable) ||
397 	    (isr->saidx.proto == IPPROTO_AH && !V_ah_enable) ||
398 	    (isr->saidx.proto == IPPROTO_IPCOMP && !V_ipcomp_enable)) {
399 		DPRINTF(("%s: IPsec outbound packet dropped due"
400 			" to policy (check your sysctls)\n", __func__));
401 		IPSEC_OSTAT(pdrops);
402 		*error = EHOSTUNREACH;
403 		goto bad;
404 	}
405 
406 	/*
407 	 * Sanity check the SA contents for the caller
408 	 * before they invoke the xform output method.
409 	 */
410 	if (sav->tdb_xform == NULL) {
411 		DPRINTF(("%s: no transform for SA\n", __func__));
412 		IPSEC_OSTAT(noxform);
413 		*error = EHOSTUNREACH;
414 		goto bad;
415 	}
416 	return isr;
417 bad:
418 	IPSEC_ASSERT(*error != 0, ("error return w/ no error code"));
419 	IPSECREQUEST_UNLOCK(isr);
420 	return NULL;
421 #undef IPSEC_OSTAT
422 }
423 
424 static int
425 ipsec_encap(struct mbuf **mp, struct secasindex *saidx)
426 {
427 #ifdef INET6
428 	struct ip6_hdr *ip6;
429 #endif
430 	struct ip *ip;
431 	int setdf;
432 	uint8_t itos, proto;
433 
434 	ip = mtod(*mp, struct ip *);
435 	switch (ip->ip_v) {
436 #ifdef INET
437 	case IPVERSION:
438 		proto = IPPROTO_IPIP;
439 		/*
440 		 * Collect IP_DF state from the inner header
441 		 * and honor system-wide control of how to handle it.
442 		 */
443 		switch (V_ip4_ipsec_dfbit) {
444 		case 0:	/* clear in outer header */
445 		case 1:	/* set in outer header */
446 			setdf = V_ip4_ipsec_dfbit;
447 			break;
448 		default:/* propagate to outer header */
449 			setdf = (ip->ip_off & ntohs(IP_DF)) != 0;
450 		}
451 		itos = ip->ip_tos;
452 		break;
453 #endif
454 #ifdef INET6
455 	case (IPV6_VERSION >> 4):
456 		proto = IPPROTO_IPV6;
457 		ip6 = mtod(*mp, struct ip6_hdr *);
458 		itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
459 		setdf = V_ip4_ipsec_dfbit ? 1: 0;
460 		/* scoped address handling */
461 		in6_clearscope(&ip6->ip6_src);
462 		in6_clearscope(&ip6->ip6_dst);
463 		break;
464 #endif
465 	default:
466 		return (EAFNOSUPPORT);
467 	}
468 	switch (saidx->dst.sa.sa_family) {
469 #ifdef INET
470 	case AF_INET:
471 		if (saidx->src.sa.sa_family != AF_INET ||
472 		    saidx->src.sin.sin_addr.s_addr == INADDR_ANY ||
473 		    saidx->dst.sin.sin_addr.s_addr == INADDR_ANY)
474 			return (EINVAL);
475 		M_PREPEND(*mp, sizeof(struct ip), M_NOWAIT);
476 		if (*mp == NULL)
477 			return (ENOBUFS);
478 		ip = mtod(*mp, struct ip *);
479 		ip->ip_v = IPVERSION;
480 		ip->ip_hl = sizeof(struct ip) >> 2;
481 		ip->ip_p = proto;
482 		ip->ip_len = htons((*mp)->m_pkthdr.len);
483 		ip->ip_ttl = V_ip_defttl;
484 		ip->ip_sum = 0;
485 		ip->ip_off = setdf ? htons(IP_DF): 0;
486 		ip->ip_src = saidx->src.sin.sin_addr;
487 		ip->ip_dst = saidx->dst.sin.sin_addr;
488 		ip_ecn_ingress(V_ip4_ipsec_ecn, &ip->ip_tos, &itos);
489 		ip_fillid(ip);
490 		break;
491 #endif /* INET */
492 #ifdef INET6
493 	case AF_INET6:
494 		if (saidx->src.sa.sa_family != AF_INET6 ||
495 		    IN6_IS_ADDR_UNSPECIFIED(&saidx->src.sin6.sin6_addr) ||
496 		    IN6_IS_ADDR_UNSPECIFIED(&saidx->dst.sin6.sin6_addr))
497 			return (EINVAL);
498 		M_PREPEND(*mp, sizeof(struct ip6_hdr), M_NOWAIT);
499 		if (*mp == NULL)
500 			return (ENOBUFS);
501 		ip6 = mtod(*mp, struct ip6_hdr *);
502 		ip6->ip6_flow = 0;
503 		ip6->ip6_vfc = IPV6_VERSION;
504 		ip6->ip6_hlim = V_ip6_defhlim;
505 		ip6->ip6_nxt = proto;
506 		ip6->ip6_dst = saidx->dst.sin6.sin6_addr;
507 		/* For link-local address embed scope zone id */
508 		if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
509 			ip6->ip6_dst.s6_addr16[1] =
510 			    htons(saidx->dst.sin6.sin6_scope_id & 0xffff);
511 		ip6->ip6_src = saidx->src.sin6.sin6_addr;
512 		if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
513 			ip6->ip6_src.s6_addr16[1] =
514 			    htons(saidx->src.sin6.sin6_scope_id & 0xffff);
515 		ip6->ip6_plen = htons((*mp)->m_pkthdr.len - sizeof(*ip6));
516 		ip_ecn_ingress(V_ip6_ipsec_ecn, &proto, &itos);
517 		ip6->ip6_flow |= htonl((uint32_t)proto << 20);
518 		break;
519 #endif /* INET6 */
520 	default:
521 		return (EAFNOSUPPORT);
522 	}
523 	return (0);
524 }
525 
526 #ifdef INET
527 /*
528  * IPsec output logic for IPv4.
529  */
530 int
531 ipsec4_process_packet(struct mbuf *m, struct ipsecrequest *isr)
532 {
533 	char sbuf[INET6_ADDRSTRLEN], dbuf[INET6_ADDRSTRLEN];
534 	union sockaddr_union *dst;
535 	struct secasindex saidx;
536 	struct secasvar *sav;
537 	struct ip *ip;
538 	int error, i, off;
539 
540 	IPSEC_ASSERT(m != NULL, ("null mbuf"));
541 	IPSEC_ASSERT(isr != NULL, ("null isr"));
542 
543 	IPSECREQUEST_LOCK(isr);		/* insure SA contents don't change */
544 
545 	isr = ipsec_nextisr(m, isr, AF_INET, &saidx, &error);
546 	if (isr == NULL) {
547 		if (error != 0)
548 			goto bad;
549 		return EJUSTRETURN;
550 	}
551 
552 	sav = isr->sav;
553 	if (m->m_len < sizeof(struct ip) &&
554 	    (m = m_pullup(m, sizeof (struct ip))) == NULL) {
555 		error = ENOBUFS;
556 		goto bad;
557 	}
558 	ip = mtod(m, struct ip *);
559 	dst = &sav->sah->saidx.dst;
560 #ifdef DEV_ENC
561 	if_inc_counter(encif, IFCOUNTER_OPACKETS, 1);
562 	if_inc_counter(encif, IFCOUNTER_OBYTES, m->m_pkthdr.len);
563 
564 	/* pass the mbuf to enc0 for bpf processing */
565 	ipsec_bpf(m, sav, AF_INET, ENC_OUT|ENC_BEFORE);
566 	/* pass the mbuf to enc0 for packet filtering */
567 	if ((error = ipsec_filter(&m, PFIL_OUT, ENC_OUT|ENC_BEFORE)) != 0)
568 		goto bad;
569 	ip = mtod(m, struct ip *);
570 #endif
571 	/* Do the appropriate encapsulation, if necessary */
572 	if (isr->saidx.mode == IPSEC_MODE_TUNNEL || /* Tunnel requ'd */
573 	    dst->sa.sa_family != AF_INET ||	    /* PF mismatch */
574 	    (dst->sa.sa_family == AF_INET &&	    /* Proxy */
575 	     dst->sin.sin_addr.s_addr != INADDR_ANY &&
576 	     dst->sin.sin_addr.s_addr != ip->ip_dst.s_addr)) {
577 		/* Fix IPv4 header checksum and length */
578 		ip->ip_len = htons(m->m_pkthdr.len);
579 		ip->ip_sum = 0;
580 		ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
581 		error = ipsec_encap(&m, &sav->sah->saidx);
582 		if (error != 0) {
583 			DPRINTF(("%s: encapsulation for SA %s->%s "
584 			    "SPI 0x%08x failed with error %d\n", __func__,
585 			    ipsec_address(&sav->sah->saidx.src, sbuf,
586 				sizeof(sbuf)),
587 			    ipsec_address(&sav->sah->saidx.dst, dbuf,
588 				sizeof(dbuf)), ntohl(sav->spi), error));
589 			goto bad;
590 		}
591 	}
592 #ifdef DEV_ENC
593 	/* pass the mbuf to enc0 for bpf processing */
594 	ipsec_bpf(m, sav, sav->sah->saidx.dst.sa.sa_family, ENC_OUT|ENC_AFTER);
595 	/* pass the mbuf to enc0 for packet filtering */
596 	if ((error = ipsec_filter(&m, PFIL_OUT, ENC_OUT|ENC_AFTER)) != 0)
597 		goto bad;
598 #endif
599 
600 	/*
601 	 * Dispatch to the appropriate IPsec transform logic.  The
602 	 * packet will be returned for transmission after crypto
603 	 * processing, etc. are completed.
604 	 *
605 	 * NB: m & sav are ``passed to caller'' who's reponsible for
606 	 *     for reclaiming their resources.
607 	 */
608 	switch(dst->sa.sa_family) {
609 	case AF_INET:
610 		ip = mtod(m, struct ip *);
611 		i = ip->ip_hl << 2;
612 		off = offsetof(struct ip, ip_p);
613 		break;
614 #ifdef INET6
615 	case AF_INET6:
616 		i = sizeof(struct ip6_hdr);
617 		off = offsetof(struct ip6_hdr, ip6_nxt);
618 		break;
619 #endif /* INET6 */
620 	default:
621 		DPRINTF(("%s: unsupported protocol family %u\n",
622 		    __func__, dst->sa.sa_family));
623 		error = EPFNOSUPPORT;
624 		IPSECSTAT_INC(ips_out_inval);
625 		goto bad;
626 	}
627 	error = (*sav->tdb_xform->xf_output)(m, isr, NULL, i, off);
628 	IPSECREQUEST_UNLOCK(isr);
629 	return (error);
630 bad:
631 	if (isr)
632 		IPSECREQUEST_UNLOCK(isr);
633 	if (m)
634 		m_freem(m);
635 	return error;
636 }
637 #endif
638 
639 
640 #ifdef INET6
641 static int
642 in6_sa_equal_addrwithscope(const struct sockaddr_in6 *sa, const struct in6_addr *ia)
643 {
644 	struct in6_addr ia2;
645 
646 	memcpy(&ia2, &sa->sin6_addr, sizeof(ia2));
647 	if (IN6_IS_SCOPE_LINKLOCAL(&sa->sin6_addr))
648 		ia2.s6_addr16[1] = htons(sa->sin6_scope_id);
649 
650 	return IN6_ARE_ADDR_EQUAL(ia, &ia2);
651 }
652 
653 /*
654  * IPsec output logic for IPv6.
655  */
656 int
657 ipsec6_process_packet(struct mbuf *m, struct ipsecrequest *isr)
658 {
659 	char sbuf[INET6_ADDRSTRLEN], dbuf[INET6_ADDRSTRLEN];
660 	struct secasindex saidx;
661 	struct secasvar *sav;
662 	struct ip6_hdr *ip6;
663 	int error, i, off;
664 	union sockaddr_union *dst;
665 
666 	IPSEC_ASSERT(m != NULL, ("ipsec6_process_packet: null mbuf"));
667 	IPSEC_ASSERT(isr != NULL, ("ipsec6_process_packet: null isr"));
668 
669 	IPSECREQUEST_LOCK(isr);		/* insure SA contents don't change */
670 
671 	isr = ipsec_nextisr(m, isr, AF_INET6, &saidx, &error);
672 	if (isr == NULL) {
673 		if (error != 0)
674 			goto bad;
675 		return EJUSTRETURN;
676 	}
677 	sav = isr->sav;
678 	dst = &sav->sah->saidx.dst;
679 
680 	ip6 = mtod(m, struct ip6_hdr *);
681 	ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(*ip6));
682 #ifdef DEV_ENC
683 	if_inc_counter(encif, IFCOUNTER_OPACKETS, 1);
684 	if_inc_counter(encif, IFCOUNTER_OBYTES, m->m_pkthdr.len);
685 
686 	/* pass the mbuf to enc0 for bpf processing */
687 	ipsec_bpf(m, isr->sav, AF_INET6, ENC_OUT|ENC_BEFORE);
688 	/* pass the mbuf to enc0 for packet filtering */
689 	if ((error = ipsec_filter(&m, PFIL_OUT, ENC_OUT|ENC_BEFORE)) != 0)
690 		goto bad;
691 	ip6 = mtod(m, struct ip6_hdr *);
692 #endif /* DEV_ENC */
693 
694 	/* Do the appropriate encapsulation, if necessary */
695 	if (isr->saidx.mode == IPSEC_MODE_TUNNEL || /* Tunnel requ'd */
696 	    dst->sa.sa_family != AF_INET6 ||        /* PF mismatch */
697 	    ((dst->sa.sa_family == AF_INET6) &&
698 	     (!IN6_IS_ADDR_UNSPECIFIED(&dst->sin6.sin6_addr)) &&
699 	     (!in6_sa_equal_addrwithscope(&dst->sin6,
700 				  &ip6->ip6_dst)))) {
701 		if (m->m_pkthdr.len - sizeof(*ip6) > IPV6_MAXPACKET) {
702 			/* No jumbogram support. */
703 			error = ENXIO;   /*XXX*/
704 			goto bad;
705 		}
706 		error = ipsec_encap(&m, &sav->sah->saidx);
707 		if (error != 0) {
708 			DPRINTF(("%s: encapsulation for SA %s->%s "
709 			    "SPI 0x%08x failed with error %d\n", __func__,
710 			    ipsec_address(&sav->sah->saidx.src, sbuf,
711 				sizeof(sbuf)),
712 			    ipsec_address(&sav->sah->saidx.dst, dbuf,
713 				sizeof(dbuf)), ntohl(sav->spi), error));
714 			goto bad;
715 		}
716 	}
717 
718 #ifdef DEV_ENC
719 	ipsec_bpf(m, isr->sav, dst->sa.sa_family, ENC_OUT|ENC_AFTER);
720 	/* pass the mbuf to enc0 for packet filtering */
721 	if ((error = ipsec_filter(&m, PFIL_OUT, ENC_OUT|ENC_AFTER)) != 0)
722 		goto bad;
723 #endif /* DEV_ENC */
724 
725 	switch(dst->sa.sa_family) {
726 #ifdef INET
727 	case AF_INET:
728 		{
729 		struct ip *ip;
730 		ip = mtod(m, struct ip *);
731 		i = ip->ip_hl << 2;
732 		off = offsetof(struct ip, ip_p);
733 		}
734 		break;
735 #endif /* AF_INET */
736 	case AF_INET6:
737 		i = sizeof(struct ip6_hdr);
738 		off = offsetof(struct ip6_hdr, ip6_nxt);
739 		break;
740 	default:
741 		DPRINTF(("%s: unsupported protocol family %u\n",
742 				 __func__, dst->sa.sa_family));
743 		error = EPFNOSUPPORT;
744 		IPSEC6STAT_INC(ips_out_inval);
745 		goto bad;
746 	}
747 	error = (*sav->tdb_xform->xf_output)(m, isr, NULL, i, off);
748 	IPSECREQUEST_UNLOCK(isr);
749 	return error;
750 bad:
751 
752 	if (isr)
753 		IPSECREQUEST_UNLOCK(isr);
754 	if (m)
755 		m_freem(m);
756 	return error;
757 }
758 #endif /*INET6*/
759