ipsec_output.c revision 181627
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: head/sys/netipsec/ipsec_output.c 181627 2008-08-12 09:05:01Z vanhu $ 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/pfil.h> 48#include <net/route.h> 49 50#include <netinet/in.h> 51#include <netinet/in_systm.h> 52#include <netinet/ip.h> 53#include <netinet/ip_var.h> 54#include <netinet/in_var.h> 55#include <netinet/ip_ecn.h> 56#ifdef INET6 57#include <netinet6/ip6_ecn.h> 58#endif 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 69#include <netipsec/ipsec.h> 70#ifdef INET6 71#include <netipsec/ipsec6.h> 72#endif 73#include <netipsec/ah_var.h> 74#include <netipsec/esp_var.h> 75#include <netipsec/ipcomp_var.h> 76 77#include <netipsec/xform.h> 78 79#include <netipsec/key.h> 80#include <netipsec/keydb.h> 81#include <netipsec/key_debug.h> 82 83#include <machine/in_cksum.h> 84 85#ifdef DEV_ENC 86#include <net/if_enc.h> 87#endif 88 89 90int 91ipsec_process_done(struct mbuf *m, struct ipsecrequest *isr) 92{ 93 struct tdb_ident *tdbi; 94 struct m_tag *mtag; 95 struct secasvar *sav; 96 struct secasindex *saidx; 97 int error; 98 99 IPSEC_ASSERT(m != NULL, ("null mbuf")); 100 IPSEC_ASSERT(isr != NULL, ("null ISR")); 101 sav = isr->sav; 102 IPSEC_ASSERT(sav != NULL, ("null SA")); 103 IPSEC_ASSERT(sav->sah != NULL, ("null SAH")); 104 105 saidx = &sav->sah->saidx; 106 switch (saidx->dst.sa.sa_family) { 107#ifdef INET 108 case AF_INET: 109 /* Fix the header length, for AH processing. */ 110 mtod(m, struct ip *)->ip_len = htons(m->m_pkthdr.len); 111 break; 112#endif /* INET */ 113#ifdef INET6 114 case AF_INET6: 115 /* Fix the header length, for AH processing. */ 116 if (m->m_pkthdr.len < sizeof (struct ip6_hdr)) { 117 error = ENXIO; 118 goto bad; 119 } 120 if (m->m_pkthdr.len - sizeof (struct ip6_hdr) > IPV6_MAXPACKET) { 121 /* No jumbogram support. */ 122 error = ENXIO; /*?*/ 123 goto bad; 124 } 125 mtod(m, struct ip6_hdr *)->ip6_plen = 126 htons(m->m_pkthdr.len - sizeof(struct ip6_hdr)); 127 break; 128#endif /* INET6 */ 129 default: 130 DPRINTF(("%s: unknown protocol family %u\n", __func__, 131 saidx->dst.sa.sa_family)); 132 error = ENXIO; 133 goto bad; 134 } 135 136 /* 137 * Add a record of what we've done or what needs to be done to the 138 * packet. 139 */ 140 mtag = m_tag_get(PACKET_TAG_IPSEC_OUT_DONE, 141 sizeof(struct tdb_ident), M_NOWAIT); 142 if (mtag == NULL) { 143 DPRINTF(("%s: could not get packet tag\n", __func__)); 144 error = ENOMEM; 145 goto bad; 146 } 147 148 tdbi = (struct tdb_ident *)(mtag + 1); 149 tdbi->dst = saidx->dst; 150 tdbi->proto = saidx->proto; 151 tdbi->spi = sav->spi; 152 m_tag_prepend(m, mtag); 153 154 /* 155 * If there's another (bundled) SA to apply, do so. 156 * Note that this puts a burden on the kernel stack size. 157 * If this is a problem we'll need to introduce a queue 158 * to set the packet on so we can unwind the stack before 159 * doing further processing. 160 */ 161 if (isr->next) { 162 ipsec4stat.ips_out_bundlesa++; 163 return ipsec4_process_packet(m, isr->next, 0, 0); 164 } 165 key_sa_recordxfer(sav, m); /* record data transfer */ 166 167 /* 168 * We're done with IPsec processing, transmit the packet using the 169 * appropriate network protocol (IP or IPv6). SPD lookup will be 170 * performed again there. 171 */ 172 switch (saidx->dst.sa.sa_family) { 173#ifdef INET 174 struct ip *ip; 175 case AF_INET: 176 ip = mtod(m, struct ip *); 177 ip->ip_len = ntohs(ip->ip_len); 178 ip->ip_off = ntohs(ip->ip_off); 179 180 return ip_output(m, NULL, NULL, IP_RAWOUTPUT, NULL, NULL); 181#endif /* INET */ 182#ifdef INET6 183 case AF_INET6: 184 /* 185 * We don't need massage, IPv6 header fields are always in 186 * net endian. 187 */ 188 return ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL); 189#endif /* INET6 */ 190 } 191 panic("ipsec_process_done"); 192bad: 193 m_freem(m); 194 KEY_FREESAV(&sav); 195 return (error); 196} 197 198static struct ipsecrequest * 199ipsec_nextisr( 200 struct mbuf *m, 201 struct ipsecrequest *isr, 202 int af, 203 struct secasindex *saidx, 204 int *error 205) 206{ 207#define IPSEC_OSTAT(x,y,z) (isr->saidx.proto == IPPROTO_ESP ? (x)++ : \ 208 isr->saidx.proto == IPPROTO_AH ? (y)++ : (z)++) 209 struct secasvar *sav; 210 211 IPSECREQUEST_LOCK_ASSERT(isr); 212 213 IPSEC_ASSERT(af == AF_INET || af == AF_INET6, 214 ("invalid address family %u", af)); 215again: 216 /* 217 * Craft SA index to search for proper SA. Note that 218 * we only fillin unspecified SA peers for transport 219 * mode; for tunnel mode they must already be filled in. 220 */ 221 *saidx = isr->saidx; 222 if (isr->saidx.mode == IPSEC_MODE_TRANSPORT) { 223 /* Fillin unspecified SA peers only for transport mode */ 224 if (af == AF_INET) { 225 struct sockaddr_in *sin; 226 struct ip *ip = mtod(m, struct ip *); 227 228 if (saidx->src.sa.sa_len == 0) { 229 sin = &saidx->src.sin; 230 sin->sin_len = sizeof(*sin); 231 sin->sin_family = AF_INET; 232 sin->sin_port = IPSEC_PORT_ANY; 233 sin->sin_addr = ip->ip_src; 234 } 235 if (saidx->dst.sa.sa_len == 0) { 236 sin = &saidx->dst.sin; 237 sin->sin_len = sizeof(*sin); 238 sin->sin_family = AF_INET; 239 sin->sin_port = IPSEC_PORT_ANY; 240 sin->sin_addr = ip->ip_dst; 241 } 242 } else { 243 struct sockaddr_in6 *sin6; 244 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 245 246 if (saidx->src.sin6.sin6_len == 0) { 247 sin6 = (struct sockaddr_in6 *)&saidx->src; 248 sin6->sin6_len = sizeof(*sin6); 249 sin6->sin6_family = AF_INET6; 250 sin6->sin6_port = IPSEC_PORT_ANY; 251 sin6->sin6_addr = ip6->ip6_src; 252 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) { 253 /* fix scope id for comparing SPD */ 254 sin6->sin6_addr.s6_addr16[1] = 0; 255 sin6->sin6_scope_id = 256 ntohs(ip6->ip6_src.s6_addr16[1]); 257 } 258 } 259 if (saidx->dst.sin6.sin6_len == 0) { 260 sin6 = (struct sockaddr_in6 *)&saidx->dst; 261 sin6->sin6_len = sizeof(*sin6); 262 sin6->sin6_family = AF_INET6; 263 sin6->sin6_port = IPSEC_PORT_ANY; 264 sin6->sin6_addr = ip6->ip6_dst; 265 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) { 266 /* fix scope id for comparing SPD */ 267 sin6->sin6_addr.s6_addr16[1] = 0; 268 sin6->sin6_scope_id = 269 ntohs(ip6->ip6_dst.s6_addr16[1]); 270 } 271 } 272 } 273 } 274 275 /* 276 * Lookup SA and validate it. 277 */ 278 *error = key_checkrequest(isr, saidx); 279 if (*error != 0) { 280 /* 281 * IPsec processing is required, but no SA found. 282 * I assume that key_acquire() had been called 283 * to get/establish the SA. Here I discard 284 * this packet because it is responsibility for 285 * upper layer to retransmit the packet. 286 */ 287 ipsec4stat.ips_out_nosa++; 288 goto bad; 289 } 290 sav = isr->sav; 291 if (sav == NULL) { 292 IPSEC_ASSERT(ipsec_get_reqlevel(isr) == IPSEC_LEVEL_USE, 293 ("no SA found, but required; level %u", 294 ipsec_get_reqlevel(isr))); 295 IPSECREQUEST_UNLOCK(isr); 296 isr = isr->next; 297 /* 298 * If isr is NULL, we found a 'use' policy w/o SA. 299 * Return w/o error and w/o isr so we can drop out 300 * and continue w/o IPsec processing. 301 */ 302 if (isr == NULL) 303 return isr; 304 IPSECREQUEST_LOCK(isr); 305 goto again; 306 } 307 308 /* 309 * Check system global policy controls. 310 */ 311 if ((isr->saidx.proto == IPPROTO_ESP && !esp_enable) || 312 (isr->saidx.proto == IPPROTO_AH && !ah_enable) || 313 (isr->saidx.proto == IPPROTO_IPCOMP && !ipcomp_enable)) { 314 DPRINTF(("%s: IPsec outbound packet dropped due" 315 " to policy (check your sysctls)\n", __func__)); 316 IPSEC_OSTAT(espstat.esps_pdrops, ahstat.ahs_pdrops, 317 ipcompstat.ipcomps_pdrops); 318 *error = EHOSTUNREACH; 319 goto bad; 320 } 321 322 /* 323 * Sanity check the SA contents for the caller 324 * before they invoke the xform output method. 325 */ 326 if (sav->tdb_xform == NULL) { 327 DPRINTF(("%s: no transform for SA\n", __func__)); 328 IPSEC_OSTAT(espstat.esps_noxform, ahstat.ahs_noxform, 329 ipcompstat.ipcomps_noxform); 330 *error = EHOSTUNREACH; 331 goto bad; 332 } 333 return isr; 334bad: 335 IPSEC_ASSERT(*error != 0, ("error return w/ no error code")); 336 IPSECREQUEST_UNLOCK(isr); 337 return NULL; 338#undef IPSEC_OSTAT 339} 340 341#ifdef INET 342/* 343 * IPsec output logic for IPv4. 344 */ 345int 346ipsec4_process_packet( 347 struct mbuf *m, 348 struct ipsecrequest *isr, 349 int flags, 350 int tunalready) 351{ 352 struct secasindex saidx; 353 struct secasvar *sav; 354 struct ip *ip; 355 int error, i, off; 356 357 IPSEC_ASSERT(m != NULL, ("null mbuf")); 358 IPSEC_ASSERT(isr != NULL, ("null isr")); 359 360 IPSECREQUEST_LOCK(isr); /* insure SA contents don't change */ 361 362 isr = ipsec_nextisr(m, isr, AF_INET, &saidx, &error); 363 if (isr == NULL) { 364 if (error != 0) 365 goto bad; 366 return EJUSTRETURN; 367 } 368 369 sav = isr->sav; 370 371#ifdef DEV_ENC 372 encif->if_opackets++; 373 encif->if_obytes += m->m_pkthdr.len; 374 375 /* pass the mbuf to enc0 for bpf processing */ 376 ipsec_bpf(m, sav, AF_INET, ENC_OUT|ENC_BEFORE); 377 /* pass the mbuf to enc0 for packet filtering */ 378 if ((error = ipsec_filter(&m, PFIL_OUT, ENC_OUT|ENC_BEFORE)) != 0) 379 goto bad; 380#endif 381 382 if (!tunalready) { 383 union sockaddr_union *dst = &sav->sah->saidx.dst; 384 int setdf; 385 386 /* 387 * Collect IP_DF state from the outer header. 388 */ 389 if (dst->sa.sa_family == AF_INET) { 390 if (m->m_len < sizeof (struct ip) && 391 (m = m_pullup(m, sizeof (struct ip))) == NULL) { 392 error = ENOBUFS; 393 goto bad; 394 } 395 ip = mtod(m, struct ip *); 396 /* Honor system-wide control of how to handle IP_DF */ 397 switch (ip4_ipsec_dfbit) { 398 case 0: /* clear in outer header */ 399 case 1: /* set in outer header */ 400 setdf = ip4_ipsec_dfbit; 401 break; 402 default: /* propagate to outer header */ 403 setdf = ntohs(ip->ip_off & IP_DF); 404 break; 405 } 406 } else { 407 ip = NULL; /* keep compiler happy */ 408 setdf = 0; 409 } 410 /* Do the appropriate encapsulation, if necessary */ 411 if (isr->saidx.mode == IPSEC_MODE_TUNNEL || /* Tunnel requ'd */ 412 dst->sa.sa_family != AF_INET || /* PF mismatch */ 413#if 0 414 (sav->flags & SADB_X_SAFLAGS_TUNNEL) || /* Tunnel requ'd */ 415 sav->tdb_xform->xf_type == XF_IP4 || /* ditto */ 416#endif 417 (dst->sa.sa_family == AF_INET && /* Proxy */ 418 dst->sin.sin_addr.s_addr != INADDR_ANY && 419 dst->sin.sin_addr.s_addr != ip->ip_dst.s_addr)) { 420 struct mbuf *mp; 421 422 /* Fix IPv4 header checksum and length */ 423 if (m->m_len < sizeof (struct ip) && 424 (m = m_pullup(m, sizeof (struct ip))) == NULL) { 425 error = ENOBUFS; 426 goto bad; 427 } 428 ip = mtod(m, struct ip *); 429 ip->ip_len = htons(m->m_pkthdr.len); 430 ip->ip_sum = 0; 431#ifdef _IP_VHL 432 if (ip->ip_vhl == IP_VHL_BORING) 433 ip->ip_sum = in_cksum_hdr(ip); 434 else 435 ip->ip_sum = in_cksum(m, 436 _IP_VHL_HL(ip->ip_vhl) << 2); 437#else 438 ip->ip_sum = in_cksum(m, ip->ip_hl << 2); 439#endif 440 441 /* Encapsulate the packet */ 442 error = ipip_output(m, isr, &mp, 0, 0); 443 if (mp == NULL && !error) { 444 /* Should never happen. */ 445 DPRINTF(("%s: ipip_output returns no mbuf and " 446 "no error!", __func__)); 447 error = EFAULT; 448 } 449 if (error) { 450 if (mp) { 451 /* XXX: Should never happen! */ 452 m_freem(mp); 453 } 454 m = NULL; /* ipip_output() already freed it */ 455 goto bad; 456 } 457 m = mp, mp = NULL; 458 /* 459 * ipip_output clears IP_DF in the new header. If 460 * we need to propagate IP_DF from the outer header, 461 * then we have to do it here. 462 * 463 * XXX shouldn't assume what ipip_output does. 464 */ 465 if (dst->sa.sa_family == AF_INET && setdf) { 466 if (m->m_len < sizeof (struct ip) && 467 (m = m_pullup(m, sizeof (struct ip))) == NULL) { 468 error = ENOBUFS; 469 goto bad; 470 } 471 ip = mtod(m, struct ip *); 472 ip->ip_off = ntohs(ip->ip_off); 473 ip->ip_off |= IP_DF; 474 ip->ip_off = htons(ip->ip_off); 475 } 476 } 477 } 478 479#ifdef DEV_ENC 480 /* pass the mbuf to enc0 for bpf processing */ 481 ipsec_bpf(m, sav, AF_INET, ENC_OUT|ENC_AFTER); 482 /* pass the mbuf to enc0 for packet filtering */ 483 if ((error = ipsec_filter(&m, PFIL_OUT, ENC_OUT|ENC_AFTER)) != 0) 484 goto bad; 485#endif 486 487 /* 488 * Dispatch to the appropriate IPsec transform logic. The 489 * packet will be returned for transmission after crypto 490 * processing, etc. are completed. For encapsulation we 491 * bypass this call because of the explicit call done above 492 * (necessary to deal with IP_DF handling for IPv4). 493 * 494 * NB: m & sav are ``passed to caller'' who's reponsible for 495 * for reclaiming their resources. 496 */ 497 if (sav->tdb_xform->xf_type != XF_IP4) { 498 ip = mtod(m, struct ip *); 499 i = ip->ip_hl << 2; 500 off = offsetof(struct ip, ip_p); 501 error = (*sav->tdb_xform->xf_output)(m, isr, NULL, i, off); 502 } else { 503 error = ipsec_process_done(m, isr); 504 } 505 IPSECREQUEST_UNLOCK(isr); 506 return error; 507bad: 508 if (isr) 509 IPSECREQUEST_UNLOCK(isr); 510 if (m) 511 m_freem(m); 512 return error; 513} 514#endif 515 516#ifdef INET6 517/* 518 * Chop IP6 header from the payload. 519 */ 520static struct mbuf * 521ipsec6_splithdr(struct mbuf *m) 522{ 523 struct mbuf *mh; 524 struct ip6_hdr *ip6; 525 int hlen; 526 527 IPSEC_ASSERT(m->m_len >= sizeof (struct ip6_hdr), 528 ("first mbuf too short, len %u", m->m_len)); 529 ip6 = mtod(m, struct ip6_hdr *); 530 hlen = sizeof(struct ip6_hdr); 531 if (m->m_len > hlen) { 532 MGETHDR(mh, M_DONTWAIT, MT_DATA); 533 if (!mh) { 534 m_freem(m); 535 return NULL; 536 } 537 M_MOVE_PKTHDR(mh, m); 538 MH_ALIGN(mh, hlen); 539 m->m_len -= hlen; 540 m->m_data += hlen; 541 mh->m_next = m; 542 m = mh; 543 m->m_len = hlen; 544 bcopy((caddr_t)ip6, mtod(m, caddr_t), hlen); 545 } else if (m->m_len < hlen) { 546 m = m_pullup(m, hlen); 547 if (!m) 548 return NULL; 549 } 550 return m; 551} 552 553/* 554 * IPsec output logic for IPv6, transport mode. 555 */ 556int 557ipsec6_output_trans( 558 struct ipsec_output_state *state, 559 u_char *nexthdrp, 560 struct mbuf *mprev, 561 struct secpolicy *sp, 562 int flags, 563 int *tun) 564{ 565 struct ipsecrequest *isr; 566 struct secasindex saidx; 567 int error = 0; 568 struct mbuf *m; 569 570 IPSEC_ASSERT(state != NULL, ("null state")); 571 IPSEC_ASSERT(state->m != NULL, ("null m")); 572 IPSEC_ASSERT(nexthdrp != NULL, ("null nexthdrp")); 573 IPSEC_ASSERT(mprev != NULL, ("null mprev")); 574 IPSEC_ASSERT(sp != NULL, ("null sp")); 575 IPSEC_ASSERT(tun != NULL, ("null tun")); 576 577 KEYDEBUG(KEYDEBUG_IPSEC_DATA, 578 printf("%s: applied SP\n", __func__); 579 kdebug_secpolicy(sp)); 580 581 isr = sp->req; 582 if (isr->saidx.mode == IPSEC_MODE_TUNNEL) { 583 /* the rest will be handled by ipsec6_output_tunnel() */ 584 *tun = 1; /* need tunnel-mode processing */ 585 return 0; 586 } 587 588 *tun = 0; 589 m = state->m; 590 591 IPSECREQUEST_LOCK(isr); /* insure SA contents don't change */ 592 isr = ipsec_nextisr(m, isr, AF_INET6, &saidx, &error); 593 if (isr == NULL) { 594 if (error != 0) { 595#ifdef notdef 596 /* XXX should notification be done for all errors ? */ 597 /* 598 * Notify the fact that the packet is discarded 599 * to ourselves. I believe this is better than 600 * just silently discarding. (jinmei@kame.net) 601 * XXX: should we restrict the error to TCP packets? 602 * XXX: should we directly notify sockets via 603 * pfctlinputs? 604 */ 605 icmp6_error(m, ICMP6_DST_UNREACH, 606 ICMP6_DST_UNREACH_ADMIN, 0); 607 m = NULL; /* NB: icmp6_error frees mbuf */ 608#endif 609 goto bad; 610 } 611 return EJUSTRETURN; 612 } 613 614 error = (*isr->sav->tdb_xform->xf_output)(m, isr, NULL, 615 sizeof (struct ip6_hdr), 616 offsetof(struct ip6_hdr, 617 ip6_nxt)); 618 IPSECREQUEST_UNLOCK(isr); 619 return error; 620bad: 621 if (isr) 622 IPSECREQUEST_UNLOCK(isr); 623 if (m) 624 m_freem(m); 625 state->m = NULL; 626 return error; 627} 628 629static int 630ipsec6_encapsulate(struct mbuf *m, struct secasvar *sav) 631{ 632 struct ip6_hdr *oip6; 633 struct ip6_hdr *ip6; 634 size_t plen; 635 636 /* can't tunnel between different AFs */ 637 if (sav->sah->saidx.src.sa.sa_family != AF_INET6 || 638 sav->sah->saidx.dst.sa.sa_family != AF_INET6) { 639 m_freem(m); 640 return EINVAL; 641 } 642 IPSEC_ASSERT(m->m_len == sizeof (struct ip6_hdr), 643 ("mbuf wrong size; len %u", m->m_len)); 644 645 646 /* 647 * grow the mbuf to accomodate the new IPv6 header. 648 */ 649 plen = m->m_pkthdr.len; 650 if (M_LEADINGSPACE(m->m_next) < sizeof(struct ip6_hdr)) { 651 struct mbuf *n; 652 MGET(n, M_DONTWAIT, MT_DATA); 653 if (!n) { 654 m_freem(m); 655 return ENOBUFS; 656 } 657 n->m_len = sizeof(struct ip6_hdr); 658 n->m_next = m->m_next; 659 m->m_next = n; 660 m->m_pkthdr.len += sizeof(struct ip6_hdr); 661 oip6 = mtod(n, struct ip6_hdr *); 662 } else { 663 m->m_next->m_len += sizeof(struct ip6_hdr); 664 m->m_next->m_data -= sizeof(struct ip6_hdr); 665 m->m_pkthdr.len += sizeof(struct ip6_hdr); 666 oip6 = mtod(m->m_next, struct ip6_hdr *); 667 } 668 ip6 = mtod(m, struct ip6_hdr *); 669 bcopy((caddr_t)ip6, (caddr_t)oip6, sizeof(struct ip6_hdr)); 670 671 /* Fake link-local scope-class addresses */ 672 if (IN6_IS_SCOPE_LINKLOCAL(&oip6->ip6_src)) 673 oip6->ip6_src.s6_addr16[1] = 0; 674 if (IN6_IS_SCOPE_LINKLOCAL(&oip6->ip6_dst)) 675 oip6->ip6_dst.s6_addr16[1] = 0; 676 677 /* construct new IPv6 header. see RFC 2401 5.1.2.2 */ 678 /* ECN consideration. */ 679 ip6_ecn_ingress(ip6_ipsec_ecn, &ip6->ip6_flow, &oip6->ip6_flow); 680 if (plen < IPV6_MAXPACKET - sizeof(struct ip6_hdr)) 681 ip6->ip6_plen = htons(plen); 682 else { 683 /* ip6->ip6_plen will be updated in ip6_output() */ 684 } 685 ip6->ip6_nxt = IPPROTO_IPV6; 686 ip6->ip6_src = sav->sah->saidx.src.sin6.sin6_addr; 687 ip6->ip6_dst = sav->sah->saidx.dst.sin6.sin6_addr; 688 ip6->ip6_hlim = IPV6_DEFHLIM; 689 690 /* XXX Should ip6_src be updated later ? */ 691 692 return 0; 693} 694 695/* 696 * IPsec output logic for IPv6, tunnel mode. 697 */ 698int 699ipsec6_output_tunnel(struct ipsec_output_state *state, struct secpolicy *sp, int flags) 700{ 701 struct ip6_hdr *ip6; 702 struct ipsecrequest *isr; 703 struct secasindex saidx; 704 int error; 705 struct sockaddr_in6* dst6; 706 struct mbuf *m; 707 708 IPSEC_ASSERT(state != NULL, ("null state")); 709 IPSEC_ASSERT(state->m != NULL, ("null m")); 710 IPSEC_ASSERT(sp != NULL, ("null sp")); 711 712 KEYDEBUG(KEYDEBUG_IPSEC_DATA, 713 printf("%s: applied SP\n", __func__); 714 kdebug_secpolicy(sp)); 715 716 m = state->m; 717 /* 718 * transport mode ipsec (before the 1st tunnel mode) is already 719 * processed by ipsec6_output_trans(). 720 */ 721 for (isr = sp->req; isr; isr = isr->next) { 722 if (isr->saidx.mode == IPSEC_MODE_TUNNEL) 723 break; 724 } 725 726 IPSECREQUEST_LOCK(isr); /* insure SA contents don't change */ 727 isr = ipsec_nextisr(m, isr, AF_INET6, &saidx, &error); 728 if (isr == NULL) { 729 if (error != 0) 730 goto bad; 731 return EJUSTRETURN; 732 } 733 734#ifdef DEV_ENC 735 encif->if_opackets++; 736 encif->if_obytes += m->m_pkthdr.len; 737 738 /* pass the mbuf to enc0 for bpf processing */ 739 ipsec_bpf(m, isr->sav, AF_INET6, ENC_OUT|ENC_BEFORE); 740 /* pass the mbuf to enc0 for packet filtering */ 741 if ((error = ipsec_filter(&m, PFIL_OUT, ENC_OUT|ENC_BEFORE)) != 0) 742 goto bad; 743#endif 744 745 /* 746 * There may be the case that SA status will be changed when 747 * we are refering to one. So calling splsoftnet(). 748 */ 749 if (isr->saidx.mode == IPSEC_MODE_TUNNEL) { 750 /* 751 * build IPsec tunnel. 752 */ 753 /* XXX should be processed with other familiy */ 754 if (isr->sav->sah->saidx.src.sa.sa_family != AF_INET6) { 755 ipseclog((LOG_ERR, "%s: family mismatched between " 756 "inner and outer, spi=%u\n", __func__, 757 ntohl(isr->sav->spi))); 758 ipsec6stat.ips_out_inval++; 759 error = EAFNOSUPPORT; 760 goto bad; 761 } 762 763 m = ipsec6_splithdr(m); 764 if (!m) { 765 ipsec6stat.ips_out_nomem++; 766 error = ENOMEM; 767 goto bad; 768 } 769 error = ipsec6_encapsulate(m, isr->sav); 770 if (error) { 771 m = NULL; 772 goto bad; 773 } 774 ip6 = mtod(m, struct ip6_hdr *); 775 776 state->ro = &isr->sav->sah->sa_route; 777 state->dst = (struct sockaddr *)&state->ro->ro_dst; 778 dst6 = (struct sockaddr_in6 *)state->dst; 779 if (state->ro->ro_rt 780 && ((state->ro->ro_rt->rt_flags & RTF_UP) == 0 781 || !IN6_ARE_ADDR_EQUAL(&dst6->sin6_addr, &ip6->ip6_dst))) { 782 RTFREE(state->ro->ro_rt); 783 state->ro->ro_rt = NULL; 784 } 785 if (state->ro->ro_rt == 0) { 786 bzero(dst6, sizeof(*dst6)); 787 dst6->sin6_family = AF_INET6; 788 dst6->sin6_len = sizeof(*dst6); 789 dst6->sin6_addr = ip6->ip6_dst; 790 rtalloc(state->ro); 791 } 792 if (state->ro->ro_rt == 0) { 793 ip6stat.ip6s_noroute++; 794 ipsec6stat.ips_out_noroute++; 795 error = EHOSTUNREACH; 796 goto bad; 797 } 798 799 /* adjust state->dst if tunnel endpoint is offlink */ 800 if (state->ro->ro_rt->rt_flags & RTF_GATEWAY) { 801 state->dst = (struct sockaddr *)state->ro->ro_rt->rt_gateway; 802 dst6 = (struct sockaddr_in6 *)state->dst; 803 } 804 } 805 806 m = ipsec6_splithdr(m); 807 if (!m) { 808 ipsec6stat.ips_out_nomem++; 809 error = ENOMEM; 810 goto bad; 811 } 812 ip6 = mtod(m, struct ip6_hdr *); 813 814#ifdef DEV_ENC 815 /* pass the mbuf to enc0 for bpf processing */ 816 ipsec_bpf(m, isr->sav, AF_INET6, ENC_OUT|ENC_AFTER); 817 /* pass the mbuf to enc0 for packet filtering */ 818 if ((error = ipsec_filter(&m, PFIL_OUT, ENC_OUT|ENC_AFTER)) != 0) 819 goto bad; 820#endif 821 822 error = (*isr->sav->tdb_xform->xf_output)(m, isr, NULL, 823 sizeof (struct ip6_hdr), 824 offsetof(struct ip6_hdr, ip6_nxt)); 825 IPSECREQUEST_UNLOCK(isr); 826 return error; 827bad: 828 if (isr) 829 IPSECREQUEST_UNLOCK(isr); 830 if (m) 831 m_freem(m); 832 state->m = NULL; 833 return error; 834} 835#endif /*INET6*/ 836