ipsec_output.c revision 1.80 1 /* $NetBSD: ipsec_output.c,v 1.80 2018/05/31 15:06:45 maxv 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: 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.80 2018/05/31 15:06:45 maxv Exp $");
33
34 #if defined(_KERNEL_OPT)
35 #include "opt_inet.h"
36 #include "opt_net_mpsafe.h"
37 #endif
38
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/mbuf.h>
42 #include <sys/domain.h>
43 #include <sys/protosw.h>
44 #include <sys/socket.h>
45 #include <sys/errno.h>
46 #include <sys/syslog.h>
47
48 #include <net/if.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
58 #include <netinet/ip6.h>
59 #ifdef INET6
60 #include <netinet6/ip6_var.h>
61 #endif
62 #include <netinet/in_pcb.h>
63 #ifdef INET6
64 #include <netinet/icmp6.h>
65 #endif
66 #include <netinet/udp.h>
67
68 #include <netipsec/ipsec.h>
69 #include <netipsec/ipsec_var.h>
70 #include <netipsec/ipsec_private.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 static percpu_t *ipsec_rtcache_percpu __cacheline_aligned;
85
86 /*
87 * Add a IPSEC_OUT_DONE tag to mark that we have finished the ipsec processing
88 * It will be used by ip{,6}_output to check if we have already or not
89 * processed this packet.
90 */
91 static int
92 ipsec_register_done(struct mbuf *m, int *error)
93 {
94 struct m_tag *mtag;
95
96 mtag = m_tag_get(PACKET_TAG_IPSEC_OUT_DONE, 0, M_NOWAIT);
97 if (mtag == NULL) {
98 IPSECLOG(LOG_DEBUG, "could not get packet tag\n");
99 *error = ENOMEM;
100 return -1;
101 }
102
103 m_tag_prepend(m, mtag);
104 return 0;
105 }
106
107 static int
108 ipsec_reinject_ipstack(struct mbuf *m, int af)
109 {
110 int rv = -1;
111 struct route *ro;
112
113 KASSERT(af == AF_INET || af == AF_INET6);
114
115 KERNEL_LOCK_UNLESS_NET_MPSAFE();
116 ro = percpu_getref(ipsec_rtcache_percpu);
117 switch (af) {
118 #ifdef INET
119 case AF_INET:
120 rv = ip_output(m, NULL, ro, IP_RAWOUTPUT|IP_NOIPNEWID,
121 NULL, NULL);
122 break;
123 #endif
124 #ifdef INET6
125 case AF_INET6:
126 /*
127 * We don't need massage, IPv6 header fields are always in
128 * net endian.
129 */
130 rv = ip6_output(m, NULL, ro, 0, NULL, NULL, NULL);
131 break;
132 #endif
133 }
134 percpu_putref(ipsec_rtcache_percpu);
135 KERNEL_UNLOCK_UNLESS_NET_MPSAFE();
136
137 return rv;
138 }
139
140 int
141 ipsec_process_done(struct mbuf *m, const struct ipsecrequest *isr,
142 struct secasvar *sav)
143 {
144 struct secasindex *saidx;
145 int error;
146 #ifdef INET
147 struct ip *ip;
148 #endif
149 #ifdef INET6
150 struct ip6_hdr *ip6;
151 #endif
152 struct mbuf *mo;
153 struct udphdr *udp = NULL;
154 int hlen, roff;
155
156 KASSERT(m != NULL);
157 KASSERT(isr != NULL);
158 KASSERT(sav != NULL);
159
160 saidx = &sav->sah->saidx;
161
162 if (sav->natt_type != 0) {
163 ip = mtod(m, struct ip *);
164
165 hlen = sizeof(struct udphdr);
166
167 mo = m_makespace(m, sizeof(struct ip), hlen, &roff);
168 if (mo == NULL) {
169 char buf[IPSEC_ADDRSTRLEN];
170 IPSECLOG(LOG_DEBUG,
171 "failed to inject %u byte UDP for SA %s/%08lx\n",
172 hlen, ipsec_address(&saidx->dst, buf, sizeof(buf)),
173 (u_long)ntohl(sav->spi));
174 error = ENOBUFS;
175 goto bad;
176 }
177
178 udp = (struct udphdr *)(mtod(mo, char *) + roff);
179 udp->uh_sport = key_portfromsaddr(&saidx->src);
180 udp->uh_dport = key_portfromsaddr(&saidx->dst);
181 udp->uh_sum = 0;
182 udp->uh_ulen = htons(m->m_pkthdr.len - (ip->ip_hl << 2));
183 }
184
185 /*
186 * Fix the header length, for AH processing.
187 */
188 switch (saidx->dst.sa.sa_family) {
189 #ifdef INET
190 case AF_INET:
191 ip = mtod(m, struct ip *);
192 ip->ip_len = htons(m->m_pkthdr.len);
193 if (sav->natt_type != 0)
194 ip->ip_p = IPPROTO_UDP;
195 break;
196 #endif
197 #ifdef INET6
198 case AF_INET6:
199 if (m->m_pkthdr.len < sizeof(struct ip6_hdr)) {
200 error = ENXIO;
201 goto bad;
202 }
203 if (m->m_pkthdr.len - sizeof(struct ip6_hdr) > IPV6_MAXPACKET) {
204 /* No jumbogram support. */
205 error = ENXIO; /*?*/
206 goto bad;
207 }
208 ip6 = mtod(m, struct ip6_hdr *);
209 ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr));
210 if (sav->natt_type != 0)
211 ip6->ip6_nxt = IPPROTO_UDP;
212 break;
213 #endif
214 default:
215 IPSECLOG(LOG_DEBUG, "unknown protocol family %u\n",
216 saidx->dst.sa.sa_family);
217 error = ENXIO;
218 goto bad;
219 }
220
221 key_sa_recordxfer(sav, m);
222
223 /*
224 * If there's another (bundled) SA to apply, do so.
225 * Note that this puts a burden on the kernel stack size.
226 * If this is a problem we'll need to introduce a queue
227 * to set the packet on so we can unwind the stack before
228 * doing further processing.
229 */
230 if (isr->next) {
231 IPSEC_STATINC(IPSEC_STAT_OUT_BUNDLESA);
232 switch (saidx->dst.sa.sa_family) {
233 #ifdef INET
234 case AF_INET:
235 return ipsec4_process_packet(m, isr->next, NULL);
236 #endif
237 #ifdef INET6
238 case AF_INET6:
239 return ipsec6_process_packet(m, isr->next);
240 #endif
241 default:
242 IPSECLOG(LOG_DEBUG, "unknown protocol family %u\n",
243 saidx->dst.sa.sa_family);
244 error = ENXIO;
245 goto bad;
246 }
247 }
248
249 /*
250 * We're done with IPsec processing, mark the packet as processed,
251 * and transmit it using the appropriate network protocol
252 * (IPv4/IPv6).
253 */
254
255 if (ipsec_register_done(m, &error) < 0)
256 goto bad;
257
258 return ipsec_reinject_ipstack(m, saidx->dst.sa.sa_family);
259
260 bad:
261 m_freem(m);
262 return error;
263 }
264
265 static void
266 ipsec_fill_saidx_bymbuf(struct secasindex *saidx, const struct mbuf *m,
267 const int af)
268 {
269
270 if (af == AF_INET) {
271 struct sockaddr_in *sin;
272 struct ip *ip = mtod(m, struct ip *);
273
274 if (saidx->src.sa.sa_len == 0) {
275 sin = &saidx->src.sin;
276 sin->sin_len = sizeof(*sin);
277 sin->sin_family = AF_INET;
278 sin->sin_port = IPSEC_PORT_ANY;
279 sin->sin_addr = ip->ip_src;
280 }
281 if (saidx->dst.sa.sa_len == 0) {
282 sin = &saidx->dst.sin;
283 sin->sin_len = sizeof(*sin);
284 sin->sin_family = AF_INET;
285 sin->sin_port = IPSEC_PORT_ANY;
286 sin->sin_addr = ip->ip_dst;
287 }
288 } else {
289 struct sockaddr_in6 *sin6;
290 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
291
292 if (saidx->src.sin6.sin6_len == 0) {
293 sin6 = (struct sockaddr_in6 *)&saidx->src;
294 sin6->sin6_len = sizeof(*sin6);
295 sin6->sin6_family = AF_INET6;
296 sin6->sin6_port = IPSEC_PORT_ANY;
297 sin6->sin6_addr = ip6->ip6_src;
298 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) {
299 /* fix scope id for comparing SPD */
300 sin6->sin6_addr.s6_addr16[1] = 0;
301 sin6->sin6_scope_id =
302 ntohs(ip6->ip6_src.s6_addr16[1]);
303 }
304 }
305 if (saidx->dst.sin6.sin6_len == 0) {
306 sin6 = (struct sockaddr_in6 *)&saidx->dst;
307 sin6->sin6_len = sizeof(*sin6);
308 sin6->sin6_family = AF_INET6;
309 sin6->sin6_port = IPSEC_PORT_ANY;
310 sin6->sin6_addr = ip6->ip6_dst;
311 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) {
312 /* fix scope id for comparing SPD */
313 sin6->sin6_addr.s6_addr16[1] = 0;
314 sin6->sin6_scope_id =
315 ntohs(ip6->ip6_dst.s6_addr16[1]);
316 }
317 }
318 }
319 }
320
321 struct secasvar *
322 ipsec_lookup_sa(const struct ipsecrequest *isr, const struct mbuf *m)
323 {
324 struct secasindex saidx;
325
326 saidx = isr->saidx;
327 if (isr->saidx.mode == IPSEC_MODE_TRANSPORT) {
328 /* Fillin unspecified SA peers only for transport mode */
329 ipsec_fill_saidx_bymbuf(&saidx, m, isr->saidx.dst.sa.sa_family);
330 }
331
332 return key_lookup_sa_bysaidx(&saidx);
333 }
334
335 /*
336 * ipsec_nextisr can return :
337 * - isr == NULL and error != 0 => something is bad : the packet must be
338 * discarded
339 * - isr == NULL and error == 0 => no more rules to apply, ipsec processing
340 * is done, reinject it in ip stack
341 * - isr != NULL (error == 0) => we need to apply one rule to the packet
342 */
343 static const struct ipsecrequest *
344 ipsec_nextisr(struct mbuf *m, const struct ipsecrequest *isr, int af,
345 int *error, struct secasvar **ret)
346 {
347 #define IPSEC_OSTAT(type) \
348 do { \
349 switch (isr->saidx.proto) { \
350 case IPPROTO_ESP: \
351 ESP_STATINC(ESP_STAT_ ## type); \
352 break; \
353 case IPPROTO_AH: \
354 AH_STATINC(AH_STAT_ ## type); \
355 break; \
356 default: \
357 IPCOMP_STATINC(IPCOMP_STAT_ ## type); \
358 break; \
359 } \
360 } while (/*CONSTCOND*/0)
361
362 struct secasvar *sav = NULL;
363 struct secasindex saidx;
364
365 KASSERTMSG(af == AF_INET || af == AF_INET6,
366 "invalid address family %u", af);
367 again:
368 /*
369 * Craft SA index to search for proper SA. Note that
370 * we only fillin unspecified SA peers for transport
371 * mode; for tunnel mode they must already be filled in.
372 */
373 saidx = isr->saidx;
374 if (isr->saidx.mode == IPSEC_MODE_TRANSPORT) {
375 /* Fillin unspecified SA peers only for transport mode */
376 ipsec_fill_saidx_bymbuf(&saidx, m, af);
377 }
378
379 /*
380 * Lookup SA and validate it.
381 */
382 *error = key_checkrequest(isr, &saidx, &sav);
383 if (*error != 0) {
384 /*
385 * IPsec processing is required, but no SA found.
386 * I assume that key_acquire() had been called
387 * to get/establish the SA. Here I discard
388 * this packet because it is responsibility for
389 * upper layer to retransmit the packet.
390 */
391 IPSEC_STATINC(IPSEC_STAT_OUT_NOSA);
392 goto bad;
393 }
394 /* sav may be NULL here if we have an USE rule */
395 if (sav == NULL) {
396 KASSERTMSG(ipsec_get_reqlevel(isr) == IPSEC_LEVEL_USE,
397 "no SA found, but required; level %u",
398 ipsec_get_reqlevel(isr));
399 isr = isr->next;
400 /*
401 * No more rules to apply, return NULL isr and no error.
402 * It can happen when the last rules are USE rules.
403 */
404 if (isr == NULL) {
405 *ret = NULL;
406 *error = 0;
407 return isr;
408 }
409 goto again;
410 }
411
412 /*
413 * Check system global policy controls.
414 */
415 if ((isr->saidx.proto == IPPROTO_ESP && !esp_enable) ||
416 (isr->saidx.proto == IPPROTO_AH && !ah_enable) ||
417 (isr->saidx.proto == IPPROTO_IPCOMP && !ipcomp_enable)) {
418 IPSECLOG(LOG_DEBUG, "IPsec outbound packet dropped due"
419 " to policy (check your sysctls)\n");
420 IPSEC_OSTAT(PDROPS);
421 *error = EHOSTUNREACH;
422 KEY_SA_UNREF(&sav);
423 goto bad;
424 }
425
426 /*
427 * Sanity check the SA contents for the caller
428 * before they invoke the xform output method.
429 */
430 KASSERT(sav->tdb_xform != NULL);
431 *ret = sav;
432 return isr;
433
434 bad:
435 KASSERTMSG(*error != 0, "error return w/ no error code");
436 return NULL;
437 #undef IPSEC_OSTAT
438 }
439
440 #ifdef INET
441 /*
442 * IPsec output logic for IPv4.
443 */
444 int
445 ipsec4_process_packet(struct mbuf *m, const struct ipsecrequest *isr,
446 u_long *mtu)
447 {
448 struct secasvar *sav = NULL;
449 struct ip *ip;
450 int s, error, i, off;
451 union sockaddr_union *dst;
452 int setdf;
453
454 KASSERT(m != NULL);
455 KASSERT(m->m_nextpkt == NULL);
456 KASSERT(isr != NULL);
457
458 s = splsoftnet(); /* insure SA contents don't change */
459
460 isr = ipsec_nextisr(m, isr, AF_INET, &error, &sav);
461 if (isr == NULL) {
462 if (error != 0) {
463 goto bad;
464 } else {
465 if (ipsec_register_done(m, &error) < 0)
466 goto bad;
467
468 splx(s);
469 return ipsec_reinject_ipstack(m, AF_INET);
470 }
471 }
472 KASSERT(sav != NULL);
473
474 if (m->m_len < sizeof(struct ip) &&
475 (m = m_pullup(m, sizeof(struct ip))) == NULL) {
476 error = ENOBUFS;
477 goto unrefsav;
478 }
479
480 /*
481 * Check if we need to handle NAT-T fragmentation.
482 */
483 if (isr == isr->sp->req) { /* Check only if called from ipsec4_output */
484 KASSERT(mtu != NULL);
485 ip = mtod(m, struct ip *);
486 if (!(sav->natt_type & UDP_ENCAP_ESPINUDP)) {
487 goto noneed;
488 }
489 if (ntohs(ip->ip_len) <= sav->esp_frag)
490 goto noneed;
491 *mtu = sav->esp_frag;
492 KEY_SA_UNREF(&sav);
493 splx(s);
494 return 0;
495 }
496 noneed:
497 dst = &sav->sah->saidx.dst;
498
499 /*
500 * Collect IP_DF state from the outer header.
501 */
502 if (dst->sa.sa_family == AF_INET) {
503 ip = mtod(m, struct ip *);
504 /* Honor system-wide control of how to handle IP_DF */
505 switch (ip4_ipsec_dfbit) {
506 case 0: /* clear in outer header */
507 case 1: /* set in outer header */
508 setdf = ip4_ipsec_dfbit;
509 break;
510 default: /* propagate to outer header */
511 setdf = ip->ip_off;
512 setdf = ntohs(setdf);
513 setdf = htons(setdf & IP_DF);
514 break;
515 }
516 } else {
517 ip = NULL; /* keep compiler happy */
518 setdf = 0;
519 }
520
521 /* Do the appropriate encapsulation, if necessary */
522 if (isr->saidx.mode == IPSEC_MODE_TUNNEL || /* Tunnel requ'd */
523 dst->sa.sa_family != AF_INET || /* PF mismatch */
524 (dst->sa.sa_family == AF_INET && /* Proxy */
525 dst->sin.sin_addr.s_addr != INADDR_ANY &&
526 dst->sin.sin_addr.s_addr != ip->ip_dst.s_addr)) {
527 struct mbuf *mp;
528
529 /* Fix IPv4 header checksum and length */
530 ip = mtod(m, struct ip *);
531 ip->ip_len = htons(m->m_pkthdr.len);
532 ip->ip_sum = 0;
533 ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
534
535 /* Encapsulate the packet */
536 error = ipip_output(m, sav, &mp);
537 if (mp == NULL && !error) {
538 /* Should never happen. */
539 IPSECLOG(LOG_DEBUG,
540 "ipip_output returns no mbuf and no error!");
541 error = EFAULT;
542 }
543 if (error) {
544 if (mp) {
545 /* XXX: Should never happen! */
546 m_freem(mp);
547 }
548 m = NULL; /* ipip_output() already freed it */
549 goto unrefsav;
550 }
551 m = mp, mp = NULL;
552
553 /*
554 * ipip_output clears IP_DF in the new header. If
555 * we need to propagate IP_DF from the outer header,
556 * then we have to do it here.
557 *
558 * XXX shouldn't assume what ipip_output does.
559 */
560 if (dst->sa.sa_family == AF_INET && setdf) {
561 if (m->m_len < sizeof(struct ip) &&
562 (m = m_pullup(m, sizeof(struct ip))) == NULL) {
563 error = ENOBUFS;
564 goto unrefsav;
565 }
566 ip = mtod(m, struct ip *);
567 ip->ip_off |= htons(IP_DF);
568 }
569 }
570
571 /*
572 * Dispatch to the appropriate IPsec transform logic. The
573 * packet will be returned for transmission after crypto
574 * processing, etc. are completed. For encapsulation we
575 * bypass this call because of the explicit call done above
576 * (necessary to deal with IP_DF handling for IPv4).
577 *
578 * NB: m & sav are ``passed to caller'' who's reponsible for
579 * for reclaiming their resources.
580 */
581 if (sav->tdb_xform->xf_type != XF_IP4) {
582 if (dst->sa.sa_family == AF_INET) {
583 ip = mtod(m, struct ip *);
584 i = ip->ip_hl << 2;
585 off = offsetof(struct ip, ip_p);
586 } else {
587 i = sizeof(struct ip6_hdr);
588 off = offsetof(struct ip6_hdr, ip6_nxt);
589 }
590 error = (*sav->tdb_xform->xf_output)(m, isr, sav, i, off);
591 } else {
592 error = ipsec_process_done(m, isr, sav);
593 }
594 KEY_SA_UNREF(&sav);
595 splx(s);
596 return error;
597
598 unrefsav:
599 KEY_SA_UNREF(&sav);
600 bad:
601 splx(s);
602 if (m)
603 m_freem(m);
604 return error;
605 }
606 #endif
607
608 #ifdef INET6
609 static int
610 compute_ipsec_pos(struct mbuf *m, int *i, int *off)
611 {
612 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
613 struct ip6_ext ip6e;
614 int dstopt = 0;
615 int nxt;
616
617 *i = sizeof(struct ip6_hdr);
618 *off = offsetof(struct ip6_hdr, ip6_nxt);
619 nxt = ip6->ip6_nxt;
620
621 /*
622 * chase mbuf chain to find the appropriate place to
623 * put AH/ESP/IPcomp header.
624 * IPv6 hbh dest1 rthdr ah* [esp* dest2 payload]
625 */
626 while (1) {
627 switch (nxt) {
628 case IPPROTO_AH:
629 case IPPROTO_ESP:
630 case IPPROTO_IPCOMP:
631 /*
632 * We should not skip security header added
633 * beforehand.
634 */
635 return 0;
636
637 case IPPROTO_HOPOPTS:
638 case IPPROTO_DSTOPTS:
639 case IPPROTO_ROUTING:
640 if (*i + sizeof(ip6e) > m->m_pkthdr.len) {
641 return EINVAL;
642 }
643
644 /*
645 * If we see 2nd destination option header,
646 * we should stop there.
647 */
648 if (nxt == IPPROTO_DSTOPTS && dstopt)
649 return 0;
650
651 if (nxt == IPPROTO_DSTOPTS) {
652 /*
653 * Seen 1st or 2nd destination option.
654 * next time we see one, it must be 2nd.
655 */
656 dstopt = 1;
657 } else if (nxt == IPPROTO_ROUTING) {
658 /*
659 * If we see destination option next
660 * time, it must be dest2.
661 */
662 dstopt = 2;
663 }
664
665 /* skip this header */
666 m_copydata(m, *i, sizeof(ip6e), &ip6e);
667 nxt = ip6e.ip6e_nxt;
668 *off = *i + offsetof(struct ip6_ext, ip6e_nxt);
669 *i += (ip6e.ip6e_len + 1) << 3;
670 if (*i > m->m_pkthdr.len) {
671 return EINVAL;
672 }
673 break;
674 default:
675 return 0;
676 }
677 }
678
679 return 0;
680 }
681
682 static int
683 in6_sa_equal_addrwithscope(const struct sockaddr_in6 *sa,
684 const struct in6_addr *ia)
685 {
686 struct in6_addr ia2;
687
688 memcpy(&ia2, &sa->sin6_addr, sizeof(ia2));
689 if (IN6_IS_SCOPE_LINKLOCAL(&sa->sin6_addr))
690 ia2.s6_addr16[1] = htons(sa->sin6_scope_id);
691
692 return IN6_ARE_ADDR_EQUAL(ia, &ia2);
693 }
694
695 int
696 ipsec6_process_packet(struct mbuf *m, const struct ipsecrequest *isr)
697 {
698 struct secasvar *sav = NULL;
699 struct ip6_hdr *ip6;
700 int s, error, i, off;
701 union sockaddr_union *dst;
702
703 KASSERT(m != NULL);
704 KASSERT(m->m_nextpkt == NULL);
705 KASSERT(isr != NULL);
706
707 s = splsoftnet(); /* insure SA contents don't change */
708
709 isr = ipsec_nextisr(m, isr, AF_INET6, &error, &sav);
710 if (isr == NULL) {
711 if (error != 0) {
712 /* XXX Should we send a notification ? */
713 goto bad;
714 } else {
715 if (ipsec_register_done(m, &error) < 0)
716 goto bad;
717
718 splx(s);
719 return ipsec_reinject_ipstack(m, AF_INET6);
720 }
721 }
722
723 KASSERT(sav != NULL);
724 dst = &sav->sah->saidx.dst;
725
726 if (m->m_len < sizeof(struct ip6_hdr)) {
727 if ((m = m_pullup(m,sizeof(struct ip6_hdr))) == NULL) {
728 error = ENOBUFS;
729 goto unrefsav;
730 }
731 }
732 ip6 = mtod(m, struct ip6_hdr *);
733
734 /* Do the appropriate encapsulation, if necessary */
735 if (isr->saidx.mode == IPSEC_MODE_TUNNEL || /* Tunnel requ'd */
736 dst->sa.sa_family != AF_INET6 || /* AF mismatch */
737 ((dst->sa.sa_family == AF_INET6) &&
738 (!IN6_IS_ADDR_UNSPECIFIED(&dst->sin6.sin6_addr)) &&
739 (!in6_sa_equal_addrwithscope(&dst->sin6, &ip6->ip6_dst)))) {
740 struct mbuf *mp;
741
742 if (m->m_pkthdr.len - sizeof(*ip6) > IPV6_MAXPACKET) {
743 /* No jumbogram support. */
744 error = ENXIO; /*XXX*/
745 goto unrefsav;
746 }
747
748 /* Fix IPv6 header payload length. */
749 ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(*ip6));
750
751 /* Encapsulate the packet */
752 error = ipip_output(m, sav, &mp);
753 if (mp == NULL && !error) {
754 /* Should never happen. */
755 IPSECLOG(LOG_DEBUG,
756 "ipip_output returns no mbuf and no error!");
757 error = EFAULT;
758 }
759
760 if (error) {
761 if (mp) {
762 /* XXX: Should never happen! */
763 m_freem(mp);
764 }
765 m = NULL; /* ipip_output() already freed it */
766 goto unrefsav;
767 }
768
769 m = mp;
770 mp = NULL;
771 }
772
773 if (dst->sa.sa_family == AF_INET) {
774 struct ip *ip;
775 ip = mtod(m, struct ip *);
776 i = ip->ip_hl << 2;
777 off = offsetof(struct ip, ip_p);
778 } else {
779 error = compute_ipsec_pos(m, &i, &off);
780 if (error)
781 goto unrefsav;
782 }
783 error = (*sav->tdb_xform->xf_output)(m, isr, sav, i, off);
784 KEY_SA_UNREF(&sav);
785 splx(s);
786 return error;
787
788 unrefsav:
789 KEY_SA_UNREF(&sav);
790 bad:
791 splx(s);
792 if (m)
793 m_freem(m);
794 return error;
795 }
796 #endif /* INET6 */
797
798 void
799 ipsec_output_init(void)
800 {
801
802 ipsec_rtcache_percpu = percpu_alloc(sizeof(struct route));
803 }
804