1 /* $NetBSD: ipsec_output.c,v 1.28 2008/04/28 17:40:11 degroote Exp $ */
4 * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
28 * $FreeBSD: /repoman/r/ncvs/src/sys/netipsec/ipsec_output.c,v 1.3.2.2 2003/03/28 20:32:53 sam Exp $
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: ipsec_output.c,v 1.28 2008/04/28 17:40:11 degroote Exp $");
35 * IPsec output processing.
39 #include "opt_inet6.h"
41 #include "opt_ipsec.h"
43 #include <sys/param.h>
44 #include <sys/systm.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>
53 #include <net/route.h>
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>
63 # include <netinet6/ip6_ecn.h>
67 #include <netinet/ip6.h>
69 #include <netinet6/ip6_var.h>
71 #include <netinet/in_pcb.h>
73 #include <netinet/icmp6.h>
76 #include <netinet/udp.h>
79 #include <netipsec/ipsec.h>
80 #include <netipsec/ipsec_var.h>
81 #include <netipsec/ipsec_private.h>
83 #include <netipsec/ipsec6.h>
85 #include <netipsec/ah_var.h>
86 #include <netipsec/esp_var.h>
87 #include <netipsec/ipcomp_var.h>
89 #include <netipsec/xform.h>
91 #include <netipsec/key.h>
92 #include <netipsec/keydb.h>
93 #include <netipsec/key_debug.h>
94 #include <netipsec/ipsec_osdep.h>
96 #include <net/net_osdep.h> /* ovbcopy() in ipsec6_encapsulate() */
100 * Add a IPSEC_OUT_DONE tag to mark that we have finished the ipsec processing
101 * It will be used by ip{,6}_output to check if we have already or not
102 * processed this packet.
105 ipsec_register_done(struct mbuf
*m
, int * error
)
109 mtag
= m_tag_get(PACKET_TAG_IPSEC_OUT_DONE
, 0, M_NOWAIT
);
111 DPRINTF(("ipsec_register_done: could not get packet tag\n"));
116 m_tag_prepend(m
, mtag
);
121 ipsec_reinject_ipstack(struct mbuf
*m
, int af
)
130 ip
= mtod(m
, struct ip
*);
132 /* FreeBSD ip_output() expects ip_len, ip_off in host endian */
133 ip
->ip_len
= ntohs(ip
->ip_len
);
134 ip
->ip_off
= ntohs(ip
->ip_off
);
135 #endif /* __FreeBSD_ */
136 return ip_output(m
, NULL
, NULL
, IP_RAWOUTPUT
,
137 (struct ip_moptions
*)NULL
, (struct socket
*)NULL
);
143 * We don't need massage, IPv6 header fields are always in
146 return ip6_output(m
, NULL
, NULL
, 0, NULL
, NULL
, NULL
);
150 panic("ipsec_reinject_ipstack : iunknown protocol family %u\n", af
);
151 return -1; /* NOTREACHED */
155 ipsec_process_done(struct mbuf
*m
, struct ipsecrequest
*isr
)
157 struct secasvar
*sav
;
158 struct secasindex
*saidx
;
164 struct ip6_hdr
* ip6
;
168 struct udphdr
*udp
= NULL
;
169 uint64_t * data
= NULL
;
171 #endif /* IPSEC_NAT_T */
173 IPSEC_SPLASSERT_SOFTNET("ipsec_process_done");
175 IPSEC_ASSERT(m
!= NULL
, ("ipsec_process_done: null mbuf"));
176 IPSEC_ASSERT(isr
!= NULL
, ("ipsec_process_done: null ISR"));
178 IPSEC_ASSERT(sav
!= NULL
, ("ipsec_process_done: null SA"));
179 IPSEC_ASSERT(sav
->sah
!= NULL
, ("ipsec_process_done: null SAH"));
181 saidx
= &sav
->sah
->saidx
;
184 if(sav
->natt_type
!= 0) {
185 ip
= mtod(m
, struct ip
*);
187 hlen
= sizeof(struct udphdr
);
188 if (sav
->natt_type
== UDP_ENCAP_ESPINUDP_NON_IKE
)
189 hlen
+= sizeof(uint64_t);
191 mo
= m_makespace(m
, sizeof(struct ip
), hlen
, &roff
);
193 DPRINTF(("ipsec_process_done : failed to inject"
194 "%u byte UDP for SA %s/%08lx\n",
195 hlen
, ipsec_address(&saidx
->dst
),
196 (u_long
) ntohl(sav
->spi
)));
201 udp
= (struct udphdr
*) (mtod(mo
, char*) + roff
);
202 data
= (uint64_t*) (udp
+ 1);
204 if (sav
->natt_type
== UDP_ENCAP_ESPINUDP_NON_IKE
)
205 *data
= 0; /* NON-IKE Marker */
207 if (sav
->natt_type
== UDP_ENCAP_ESPINUDP_NON_IKE
)
208 udp
->uh_sport
= htons(UDP_ENCAP_ESPINUDP_PORT
);
210 udp
->uh_sport
= key_portfromsaddr(&saidx
->src
);
212 udp
->uh_dport
= key_portfromsaddr(&saidx
->dst
);
214 udp
->uh_ulen
= htons(m
->m_pkthdr
.len
- (ip
->ip_hl
<< 2));
216 #endif /* IPSEC_NAT_T */
218 switch (saidx
->dst
.sa
.sa_family
) {
221 /* Fix the header length, for AH processing. */
222 ip
= mtod(m
, struct ip
*);
223 ip
->ip_len
= htons(m
->m_pkthdr
.len
);
225 if (sav
->natt_type
!= 0)
226 ip
->ip_p
= IPPROTO_UDP
;
227 #endif /* IPSEC_NAT_T */
232 /* Fix the header length, for AH processing. */
233 if (m
->m_pkthdr
.len
< sizeof (struct ip6_hdr
)) {
237 if (m
->m_pkthdr
.len
- sizeof (struct ip6_hdr
) > IPV6_MAXPACKET
) {
238 /* No jumbogram support. */
242 ip6
= mtod(m
, struct ip6_hdr
*);
243 ip6
->ip6_plen
= htons(m
->m_pkthdr
.len
- sizeof(struct ip6_hdr
));
245 if (sav
->natt_type
!= 0)
246 ip6
->ip6_nxt
= IPPROTO_UDP
;
247 #endif /* IPSEC_NAT_T */
251 DPRINTF(("ipsec_process_done: unknown protocol family %u\n",
252 saidx
->dst
.sa
.sa_family
));
258 * If there's another (bundled) SA to apply, do so.
259 * Note that this puts a burden on the kernel stack size.
260 * If this is a problem we'll need to introduce a queue
261 * to set the packet on so we can unwind the stack before
262 * doing further processing.
265 IPSEC_STATINC(IPSEC_STAT_OUT_BUNDLESA
);
266 switch ( saidx
->dst
.sa
.sa_family
) {
269 return ipsec4_process_packet(m
, isr
->next
, 0,0);
273 return ipsec6_process_packet(m
,isr
->next
);
276 DPRINTF(("ipsec_process_done: unknown protocol family %u\n",
277 saidx
->dst
.sa
.sa_family
));
284 * We're done with IPsec processing,
285 * mark that we have already processed the packet
286 * transmit it packet using the appropriate network protocol (IP or IPv6).
289 if (ipsec_register_done(m
, &error
) < 0)
292 return ipsec_reinject_ipstack(m
, saidx
->dst
.sa
.sa_family
);
300 * ipsec_nextisr can return :
301 * - isr == NULL and error != 0 => something is bad : the packet must be
303 * - isr == NULL and error == 0 => no more rules to apply, ipsec processing
304 * is done, reinject it in ip stack
305 * - isr != NULL (error == 0) => we need to apply one rule to the packet
307 static struct ipsecrequest
*
310 struct ipsecrequest
*isr
,
312 struct secasindex
*saidx
,
316 #define IPSEC_OSTAT(x, y, z) \
318 switch (isr->saidx.proto) { \
329 } while (/*CONSTCOND*/0)
331 struct secasvar
*sav
;
333 IPSEC_SPLASSERT_SOFTNET("ipsec_nextisr");
334 IPSEC_ASSERT(af
== AF_INET
|| af
== AF_INET6
,
335 ("ipsec_nextisr: invalid address family %u", af
));
338 * Craft SA index to search for proper SA. Note that
339 * we only fillin unspecified SA peers for transport
340 * mode; for tunnel mode they must already be filled in.
343 if (isr
->saidx
.mode
== IPSEC_MODE_TRANSPORT
) {
344 /* Fillin unspecified SA peers only for transport mode */
346 struct sockaddr_in
*sin
;
347 struct ip
*ip
= mtod(m
, struct ip
*);
349 if (saidx
->src
.sa
.sa_len
== 0) {
350 sin
= &saidx
->src
.sin
;
351 sin
->sin_len
= sizeof(*sin
);
352 sin
->sin_family
= AF_INET
;
353 sin
->sin_port
= IPSEC_PORT_ANY
;
354 sin
->sin_addr
= ip
->ip_src
;
356 if (saidx
->dst
.sa
.sa_len
== 0) {
357 sin
= &saidx
->dst
.sin
;
358 sin
->sin_len
= sizeof(*sin
);
359 sin
->sin_family
= AF_INET
;
360 sin
->sin_port
= IPSEC_PORT_ANY
;
361 sin
->sin_addr
= ip
->ip_dst
;
364 struct sockaddr_in6
*sin6
;
365 struct ip6_hdr
*ip6
= mtod(m
, struct ip6_hdr
*);
367 if (saidx
->src
.sin6
.sin6_len
== 0) {
368 sin6
= (struct sockaddr_in6
*)&saidx
->src
;
369 sin6
->sin6_len
= sizeof(*sin6
);
370 sin6
->sin6_family
= AF_INET6
;
371 sin6
->sin6_port
= IPSEC_PORT_ANY
;
372 sin6
->sin6_addr
= ip6
->ip6_src
;
373 if (IN6_IS_SCOPE_LINKLOCAL(&ip6
->ip6_src
)) {
374 /* fix scope id for comparing SPD */
375 sin6
->sin6_addr
.s6_addr16
[1] = 0;
376 sin6
->sin6_scope_id
=
377 ntohs(ip6
->ip6_src
.s6_addr16
[1]);
380 if (saidx
->dst
.sin6
.sin6_len
== 0) {
381 sin6
= (struct sockaddr_in6
*)&saidx
->dst
;
382 sin6
->sin6_len
= sizeof(*sin6
);
383 sin6
->sin6_family
= AF_INET6
;
384 sin6
->sin6_port
= IPSEC_PORT_ANY
;
385 sin6
->sin6_addr
= ip6
->ip6_dst
;
386 if (IN6_IS_SCOPE_LINKLOCAL(&ip6
->ip6_dst
)) {
387 /* fix scope id for comparing SPD */
388 sin6
->sin6_addr
.s6_addr16
[1] = 0;
389 sin6
->sin6_scope_id
=
390 ntohs(ip6
->ip6_dst
.s6_addr16
[1]);
397 * Lookup SA and validate it.
399 *error
= key_checkrequest(isr
, saidx
);
402 * IPsec processing is required, but no SA found.
403 * I assume that key_acquire() had been called
404 * to get/establish the SA. Here I discard
405 * this packet because it is responsibility for
406 * upper layer to retransmit the packet.
408 IPSEC_STATINC(IPSEC_STAT_OUT_NOSA
);
412 /* sav may be NULL here if we have an USE rule */
414 IPSEC_ASSERT(ipsec_get_reqlevel(isr
) == IPSEC_LEVEL_USE
,
415 ("ipsec_nextisr: no SA found, but required; level %u",
416 ipsec_get_reqlevel(isr
)));
419 * No more rules to apply, return NULL isr and no error
420 * It can happen when the last rules are USE rules
430 * Check system global policy controls.
432 if ((isr
->saidx
.proto
== IPPROTO_ESP
&& !esp_enable
) ||
433 (isr
->saidx
.proto
== IPPROTO_AH
&& !ah_enable
) ||
434 (isr
->saidx
.proto
== IPPROTO_IPCOMP
&& !ipcomp_enable
)) {
435 DPRINTF(("ipsec_nextisr: IPsec outbound packet dropped due"
436 " to policy (check your sysctls)\n"));
437 IPSEC_OSTAT(ESP_STAT_PDROPS
, AH_STAT_PDROPS
,
439 *error
= EHOSTUNREACH
;
444 * Sanity check the SA contents for the caller
445 * before they invoke the xform output method.
447 if (sav
->tdb_xform
== NULL
) {
448 DPRINTF(("ipsec_nextisr: no transform for SA\n"));
449 IPSEC_OSTAT(ESP_STAT_NOXFORM
, AH_STAT_NOXFORM
,
450 IPCOMP_STAT_NOXFORM
);
451 *error
= EHOSTUNREACH
;
456 IPSEC_ASSERT(*error
!= 0, ("ipsec_nextisr: error return w/ no error code"));
463 * IPsec output logic for IPv4.
466 ipsec4_process_packet(
468 struct ipsecrequest
*isr
,
473 struct secasindex saidx
;
474 struct secasvar
*sav
;
476 int s
, error
, i
, off
;
478 IPSEC_ASSERT(m
!= NULL
, ("ipsec4_process_packet: null mbuf"));
479 IPSEC_ASSERT(isr
!= NULL
, ("ipsec4_process_packet: null isr"));
481 s
= splsoftnet(); /* insure SA contents don't change */
483 isr
= ipsec_nextisr(m
, isr
, AF_INET
, &saidx
, &error
);
488 if (ipsec_register_done(m
, &error
) < 0)
492 return ipsec_reinject_ipstack(m
, AF_INET
);
498 union sockaddr_union
*dst
= &sav
->sah
->saidx
.dst
;
502 * Collect IP_DF state from the outer header.
504 if (dst
->sa
.sa_family
== AF_INET
) {
505 if (m
->m_len
< sizeof (struct ip
) &&
506 (m
= m_pullup(m
, sizeof (struct ip
))) == NULL
) {
510 ip
= mtod(m
, struct ip
*);
511 /* Honor system-wide control of how to handle IP_DF */
512 switch (ip4_ipsec_dfbit
) {
513 case 0: /* clear in outer header */
514 case 1: /* set in outer header */
515 setdf
= ip4_ipsec_dfbit
;
517 default: /* propagate to outer header */
520 /* On FreeBSD, ip_off and ip_len assumed in host endian. */
521 setdf
= ntohs(setdf
);
523 setdf
= htons(setdf
& IP_DF
);
527 ip
= NULL
; /* keep compiler happy */
530 /* Do the appropriate encapsulation, if necessary */
531 if (isr
->saidx
.mode
== IPSEC_MODE_TUNNEL
|| /* Tunnel requ'd */
532 dst
->sa
.sa_family
!= AF_INET
|| /* PF mismatch */
534 (sav
->flags
& SADB_X_SAFLAGS_TUNNEL
) || /* Tunnel requ'd */
535 sav
->tdb_xform
->xf_type
== XF_IP4
|| /* ditto */
537 (dst
->sa
.sa_family
== AF_INET
&& /* Proxy */
538 dst
->sin
.sin_addr
.s_addr
!= INADDR_ANY
&&
539 dst
->sin
.sin_addr
.s_addr
!= ip
->ip_dst
.s_addr
)) {
542 /* Fix IPv4 header checksum and length */
543 if (m
->m_len
< sizeof (struct ip
) &&
544 (m
= m_pullup(m
, sizeof (struct ip
))) == NULL
) {
548 ip
= mtod(m
, struct ip
*);
549 ip
->ip_len
= htons(m
->m_pkthdr
.len
);
551 ip
->ip_sum
= in_cksum(m
, ip
->ip_hl
<< 2);
553 /* Encapsulate the packet */
554 error
= ipip_output(m
, isr
, &mp
, 0, 0);
555 if (mp
== NULL
&& !error
) {
556 /* Should never happen. */
557 DPRINTF(("ipsec4_process_packet: ipip_output "
558 "returns no mbuf and no error!"));
563 /* XXX: Should never happen! */
566 m
= NULL
; /* ipip_output() already freed it */
571 * ipip_output clears IP_DF in the new header. If
572 * we need to propagate IP_DF from the outer header,
573 * then we have to do it here.
575 * XXX shouldn't assume what ipip_output does.
577 if (dst
->sa
.sa_family
== AF_INET
&& setdf
) {
578 if (m
->m_len
< sizeof (struct ip
) &&
579 (m
= m_pullup(m
, sizeof (struct ip
))) == NULL
) {
583 ip
= mtod(m
, struct ip
*);
584 ip
->ip_off
|= IP_OFF_CONVERT(IP_DF
);
590 * Dispatch to the appropriate IPsec transform logic. The
591 * packet will be returned for transmission after crypto
592 * processing, etc. are completed. For encapsulation we
593 * bypass this call because of the explicit call done above
594 * (necessary to deal with IP_DF handling for IPv4).
596 * NB: m & sav are ``passed to caller'' who's reponsible for
597 * for reclaiming their resources.
599 if (sav
->tdb_xform
->xf_type
!= XF_IP4
) {
600 ip
= mtod(m
, struct ip
*);
602 off
= offsetof(struct ip
, ip_p
);
603 error
= (*sav
->tdb_xform
->xf_output
)(m
, isr
, NULL
, i
, off
);
605 error
= ipsec_process_done(m
, isr
);
619 ipsec6_process_packet(
621 struct ipsecrequest
*isr
624 struct secasindex saidx
;
625 struct secasvar
*sav
;
627 int s
, error
, i
, off
;
629 IPSEC_ASSERT(m
!= NULL
, ("ipsec6_process_packet: null mbuf"));
630 IPSEC_ASSERT(isr
!= NULL
, ("ipsec6_process_packet: null isr"));
632 s
= splsoftnet(); /* insure SA contents don't change */
633 isr
= ipsec_nextisr(m
, isr
, AF_INET6
, &saidx
, &error
);
636 // XXX Should we send a notification ?
639 if (ipsec_register_done(m
, &error
) < 0)
643 return ipsec_reinject_ipstack(m
, AF_INET6
);
648 if (sav
->tdb_xform
->xf_type
!= XF_IP4
) {
649 i
= sizeof(struct ip6_hdr
);
650 off
= offsetof(struct ip6_hdr
, ip6_nxt
);
651 error
= (*sav
->tdb_xform
->xf_output
)(m
, isr
, NULL
, i
, off
);
653 union sockaddr_union
*dst
= &sav
->sah
->saidx
.dst
;
655 ip6
= mtod(m
, struct ip6_hdr
*);
657 /* Do the appropriate encapsulation, if necessary */
658 if (isr
->saidx
.mode
== IPSEC_MODE_TUNNEL
|| /* Tunnel requ'd */
659 dst
->sa
.sa_family
!= AF_INET6
|| /* PF mismatch */
660 ((dst
->sa
.sa_family
== AF_INET6
) &&
661 (!IN6_IS_ADDR_UNSPECIFIED(&dst
->sin6
.sin6_addr
)) &&
662 (!IN6_ARE_ADDR_EQUAL(&dst
->sin6
.sin6_addr
,
667 /* Fix IPv6 header payload length. */
668 if (m
->m_len
< sizeof(struct ip6_hdr
))
669 if ((m
= m_pullup(m
,sizeof(struct ip6_hdr
))) == NULL
)
672 if (m
->m_pkthdr
.len
- sizeof(*ip6
) > IPV6_MAXPACKET
) {
673 /* No jumbogram support. */
675 return ENXIO
; /*XXX*/
677 ip6
= mtod(m
, struct ip6_hdr
*);
678 ip6
->ip6_plen
= htons(m
->m_pkthdr
.len
- sizeof(*ip6
));
680 /* Encapsulate the packet */
681 error
= ipip_output(m
, isr
, &mp
, 0, 0);
682 if (mp
== NULL
&& !error
) {
683 /* Should never happen. */
684 DPRINTF(("ipsec6_process_packet: ipip_output "
685 "returns no mbuf and no error!"));
691 /* XXX: Should never happen! */
694 m
= NULL
; /* ipip_output() already freed it */
702 error
= ipsec_process_done(m
,isr
);