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