1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/types.h> 30 #include <sys/stream.h> 31 #include <sys/sunddi.h> 32 #include <sys/strlog.h> 33 34 #include <inet/common.h> 35 #include <inet/mib2.h> 36 #include <inet/ip.h> 37 #include <inet/ip6.h> 38 #include <inet/ipdrop.h> 39 40 #include <net/pfkeyv2.h> 41 #include <inet/ipsec_info.h> 42 #include <inet/sadb.h> 43 #include <inet/ipsec_impl.h> 44 #include <inet/ipsecesp.h> 45 #include <inet/ipsecah.h> 46 #include <sys/kstat.h> 47 48 /* stats */ 49 static kstat_t *ipsec_ksp; 50 ipsec_kstats_t *ipsec_kstats; 51 52 /* The IPsec SADBs for AH and ESP */ 53 sadbp_t ah_sadb, esp_sadb; 54 55 /* Packet dropper for IP IPsec processing failures */ 56 extern ipdropper_t ip_dropper; 57 58 void 59 ipsec_kstat_init(void) 60 { 61 ipsec_ksp = kstat_create("ip", 0, "ipsec_stat", "net", 62 KSTAT_TYPE_NAMED, sizeof (*ipsec_kstats) / sizeof (kstat_named_t), 63 KSTAT_FLAG_PERSISTENT); 64 65 ASSERT(ipsec_ksp != NULL); 66 67 ipsec_kstats = ipsec_ksp->ks_data; 68 69 #define KI(x) kstat_named_init(&ipsec_kstats->x, #x, KSTAT_DATA_UINT64) 70 KI(esp_stat_in_requests); 71 KI(esp_stat_in_discards); 72 KI(esp_stat_lookup_failure); 73 KI(ah_stat_in_requests); 74 KI(ah_stat_in_discards); 75 KI(ah_stat_lookup_failure); 76 #undef KI 77 78 kstat_install(ipsec_ksp); 79 } 80 81 void 82 ipsec_kstat_destroy(void) 83 { 84 kstat_delete(ipsec_ksp); 85 } 86 87 /* 88 * Returns B_TRUE if the identities in the SA match the identities 89 * in the "latch" structure. 90 */ 91 92 static boolean_t 93 ipsec_match_outbound_ids(ipsec_latch_t *ipl, ipsa_t *sa) 94 { 95 ASSERT(ipl->ipl_ids_latched == B_TRUE); 96 return ipsid_equal(ipl->ipl_local_cid, sa->ipsa_src_cid) && 97 ipsid_equal(ipl->ipl_remote_cid, sa->ipsa_dst_cid); 98 } 99 100 /* 101 * Look up a security association based on the unique ID generated by IP and 102 * transport information, such as ports and upper-layer protocol, and the 103 * address(es). Used for uniqueness testing and outbound packets. The 104 * source address may be ignored. 105 * 106 * I expect an SA hash bucket, and that its per-bucket mutex is held. 107 * The SA ptr I return will have its reference count incremented by one. 108 */ 109 ipsa_t * 110 ipsec_getassocbyconn(isaf_t *bucket, ipsec_out_t *io, uint32_t *src, 111 uint32_t *dst, sa_family_t af, uint8_t protocol) 112 { 113 ipsa_t *retval, *candidate; 114 ipsec_action_t *candact; 115 boolean_t need_unique; 116 uint64_t unique_id; 117 uint32_t old_flags, excludeflags; 118 ipsec_policy_t *pp = io->ipsec_out_policy; 119 ipsec_action_t *actlist = io->ipsec_out_act; 120 ipsec_action_t *act; 121 ipsec_latch_t *ipl = io->ipsec_out_latch; 122 ipsa_ref_t *ipr = NULL; 123 124 ASSERT(MUTEX_HELD(&bucket->isaf_lock)); 125 126 /* 127 * Fast path: do we have a latch structure, is it for this bucket, 128 * and does the generation number match? If so, refhold and return. 129 */ 130 131 if (ipl != NULL) { 132 ASSERT((protocol == IPPROTO_AH) || (protocol == IPPROTO_ESP)); 133 ipr = &ipl->ipl_ref[protocol - IPPROTO_ESP]; 134 135 retval = ipr->ipsr_sa; 136 137 /* 138 * NOTE: The isaf_gen check (incremented upon 139 * sadb_unlinkassoc()) protects against retval being a freed 140 * SA. (We're exploiting short-circuit evaluation.) 141 */ 142 if ((bucket == ipr->ipsr_bucket) && 143 (bucket->isaf_gen == ipr->ipsr_gen) && 144 (retval->ipsa_state != IPSA_STATE_DEAD) && 145 !(retval->ipsa_flags & IPSA_F_CINVALID)) { 146 IPSA_REFHOLD(retval); 147 return (retval); 148 } 149 } 150 151 ASSERT((pp != NULL) || (actlist != NULL)); 152 if (actlist == NULL) 153 actlist = pp->ipsp_act; 154 ASSERT(actlist != NULL); 155 156 need_unique = actlist->ipa_want_unique; 157 unique_id = SA_FORM_UNIQUE_ID(io); 158 159 /* 160 * Precompute mask for SA flags comparison: If we need a 161 * unique SA and an SA has already been used, or if the SA has 162 * a unique value which doesn't match, we aren't interested in 163 * the SA.. 164 */ 165 166 excludeflags = IPSA_F_UNIQUE; 167 if (need_unique) 168 excludeflags |= IPSA_F_USED; 169 170 /* 171 * Walk the hash bucket, matching on: 172 * 173 * - unique_id 174 * - destination 175 * - source 176 * - algorithms 177 * - <MORE TBD> 178 * 179 * Make sure that wildcard sources are inserted at the end of the hash 180 * bucket. 181 * 182 * DEFINITIONS: A _shared_ SA is one with unique_id == 0 and USED. 183 * An _unused_ SA is one with unique_id == 0 and not USED. 184 * A _unique_ SA is one with unique_id != 0 and USED. 185 * An SA with unique_id != 0 and not USED never happens. 186 */ 187 188 candidate = NULL; 189 190 for (retval = bucket->isaf_ipsa; retval != NULL; 191 retval = retval->ipsa_next) { 192 ASSERT((candidate == NULL) || 193 MUTEX_HELD(&candidate->ipsa_lock)); 194 195 /* 196 * Q: Should I lock this SA? 197 * A: For now, yes. I change and use too many fields in here 198 * (e.g. unique_id) that I may be racing with other threads. 199 * Also, the refcnt needs to be bumped up. 200 */ 201 202 mutex_enter(&retval->ipsa_lock); 203 204 /* My apologies for the use of goto instead of continue. */ 205 if (!IPSA_ARE_ADDR_EQUAL(dst, retval->ipsa_dstaddr, af)) 206 goto next_ipsa; /* Destination mismatch. */ 207 if (!IPSA_ARE_ADDR_EQUAL(src, retval->ipsa_srcaddr, af) && 208 !IPSA_IS_ADDR_UNSPEC(retval->ipsa_srcaddr, af)) 209 goto next_ipsa; /* Specific source and not matched. */ 210 211 /* 212 * XXX should be able to use cached/latched action 213 * to dodge this loop 214 */ 215 for (act = actlist; act != NULL; act = act->ipa_next) { 216 ipsec_act_t *ap = &act->ipa_act; 217 if (ap->ipa_type != IPSEC_POLICY_APPLY) 218 continue; 219 220 /* 221 * XXX ugly. should be better way to do this test 222 */ 223 if (protocol == IPPROTO_AH) { 224 if (!(ap->ipa_apply.ipp_use_ah)) 225 continue; 226 if (ap->ipa_apply.ipp_auth_alg != 227 retval->ipsa_auth_alg) 228 continue; 229 if (ap->ipa_apply.ipp_ah_minbits > 230 retval->ipsa_authkeybits) 231 continue; 232 } else { 233 if (!(ap->ipa_apply.ipp_use_esp)) 234 continue; 235 236 if ((ap->ipa_apply.ipp_encr_alg != 237 retval->ipsa_encr_alg)) 238 continue; 239 240 if (ap->ipa_apply.ipp_espe_minbits > 241 retval->ipsa_encrkeybits) 242 continue; 243 244 if (ap->ipa_apply.ipp_esp_auth_alg != 0) { 245 if (ap->ipa_apply.ipp_esp_auth_alg != 246 retval->ipsa_auth_alg) 247 continue; 248 if (ap->ipa_apply.ipp_espa_minbits > 249 retval->ipsa_authkeybits) 250 continue; 251 } 252 } 253 254 /* 255 * Check key mgmt proto, cookie 256 */ 257 if ((ap->ipa_apply.ipp_km_proto != 0) && 258 (retval->ipsa_kmp != 0) && 259 (ap->ipa_apply.ipp_km_proto != retval->ipsa_kmp)) 260 continue; 261 262 if ((ap->ipa_apply.ipp_km_cookie != 0) && 263 (retval->ipsa_kmc != 0) && 264 (ap->ipa_apply.ipp_km_cookie != retval->ipsa_kmc)) 265 continue; 266 267 break; 268 } 269 if (act == NULL) 270 goto next_ipsa; /* nothing matched */ 271 272 /* 273 * Do identities match? 274 */ 275 if (ipl && ipl->ipl_ids_latched && 276 !ipsec_match_outbound_ids(ipl, retval)) 277 goto next_ipsa; 278 279 /* 280 * At this point, we know that we have at least a match on: 281 * 282 * - dest 283 * - source (if source is specified, i.e. non-zeroes) 284 * - auth alg (if auth alg is specified, i.e. non-zero) 285 * - encrypt. alg (if encrypt. alg is specified, i.e. non-zero) 286 * and we know that the SA keylengths are appropriate. 287 * 288 * (Keep in mind known-src SAs are hit before zero-src SAs, 289 * thanks to sadb_insertassoc().) 290 * If we need a unique asssociation, optimally we have 291 * ipsa_unique_id == unique_id, otherwise NOT USED 292 * is held in reserve (stored in candidate). 293 * 294 * For those stored in candidate, take best-match (i.e. given 295 * a choice, candidate should have non-zero ipsa_src). 296 */ 297 298 /* 299 * If SA has a unique value which matches, we're all set... 300 * "key management knows best" 301 */ 302 if ((retval->ipsa_flags & IPSA_F_UNIQUE) && 303 ((unique_id & retval->ipsa_unique_mask) == 304 retval->ipsa_unique_id)) 305 break; 306 307 /* 308 * If we need a unique SA and this SA has already been used, 309 * or if the SA has a unique value which doesn't match, 310 * this isn't for us. 311 */ 312 313 if (retval->ipsa_flags & excludeflags) 314 goto next_ipsa; 315 316 317 /* 318 * I found a candidate.. 319 */ 320 if (candidate == NULL) { 321 /* 322 * and didn't already have one.. 323 */ 324 candidate = retval; 325 candact = act; 326 continue; 327 } else { 328 /* 329 * If candidate's source address is zero and 330 * the current match (i.e. retval) address is 331 * not zero, we have a better candidate.. 332 */ 333 if (IPSA_IS_ADDR_UNSPEC(candidate->ipsa_srcaddr, af) && 334 !IPSA_IS_ADDR_UNSPEC(retval->ipsa_srcaddr, af)) { 335 mutex_exit(&candidate->ipsa_lock); 336 candidate = retval; 337 candact = act; 338 continue; 339 } 340 } 341 next_ipsa: 342 mutex_exit(&retval->ipsa_lock); 343 } 344 ASSERT((retval == NULL) || MUTEX_HELD(&retval->ipsa_lock)); 345 ASSERT((candidate == NULL) || MUTEX_HELD(&candidate->ipsa_lock)); 346 ASSERT((retval == NULL) || (act != NULL)); 347 ASSERT((candidate == NULL) || (candact != NULL)); 348 349 /* Let caller react to a lookup failure when it gets NULL. */ 350 if (retval == NULL && candidate == NULL) 351 return (NULL); 352 353 if (retval == NULL) { 354 ASSERT(MUTEX_HELD(&candidate->ipsa_lock)); 355 retval = candidate; 356 act = candact; 357 } else if (candidate != NULL) { 358 mutex_exit(&candidate->ipsa_lock); 359 } 360 ASSERT(MUTEX_HELD(&retval->ipsa_lock)); 361 ASSERT(act != NULL); 362 363 /* 364 * Even though I hold the mutex, since the reference counter is an 365 * atomic operation, I really have to use the IPSA_REFHOLD macro. 366 */ 367 IPSA_REFHOLD(retval); 368 369 /* 370 * This association is no longer unused. 371 */ 372 old_flags = retval->ipsa_flags; 373 retval->ipsa_flags |= IPSA_F_USED; 374 375 /* 376 * Cache a reference to this SA for the fast path. 377 */ 378 if (ipr != NULL) { 379 ipr->ipsr_bucket = bucket; 380 ipr->ipsr_gen = bucket->isaf_gen; 381 ipr->ipsr_sa = retval; 382 /* I'm now caching, so the cache-invalid flag goes away! */ 383 retval->ipsa_flags &= ~IPSA_F_CINVALID; 384 } 385 /* 386 * Latch various things while we're here.. 387 */ 388 if (ipl != NULL) { 389 if (!ipl->ipl_ids_latched) { 390 ipsec_latch_ids(ipl, 391 retval->ipsa_src_cid, retval->ipsa_dst_cid); 392 } 393 if (!ipl->ipl_out_action_latched) { 394 IPACT_REFHOLD(act); 395 ipl->ipl_out_action = act; 396 ipl->ipl_out_action_latched = B_TRUE; 397 } 398 } 399 400 /* 401 * Set the uniqueness only first time. 402 */ 403 if (need_unique && !(old_flags & IPSA_F_USED)) { 404 if (retval->ipsa_unique_id == 0) { 405 ASSERT((retval->ipsa_flags & IPSA_F_UNIQUE) == 0); 406 /* 407 * From now on, only this src, dst[ports, addr], 408 * proto, should use it. 409 */ 410 retval->ipsa_flags |= IPSA_F_UNIQUE; 411 retval->ipsa_unique_id = unique_id; 412 retval->ipsa_unique_mask = SA_UNIQUE_MASK( 413 io->ipsec_out_src_port, io->ipsec_out_dst_port, 414 protocol); 415 } 416 417 /* 418 * Set the source address and adjust the hash 419 * buckets only if src_addr is zero. 420 */ 421 if (IPSA_IS_ADDR_UNSPEC(retval->ipsa_srcaddr, af)) { 422 /* 423 * sadb_unlinkassoc() will decrement the refcnt. Bump 424 * up when we have the lock so that we don't have to 425 * acquire locks when we come back from 426 * sadb_insertassoc(). 427 * 428 * We don't need to bump the bucket's gen since 429 * we aren't moving to a new bucket. 430 */ 431 IPSA_REFHOLD(retval); 432 IPSA_COPY_ADDR(retval->ipsa_srcaddr, src, af); 433 mutex_exit(&retval->ipsa_lock); 434 sadb_unlinkassoc(retval); 435 /* 436 * Since the bucket lock is held, we know 437 * sadb_insertassoc() will succeed. 438 */ 439 #ifdef DEBUG 440 if (sadb_insertassoc(retval, bucket) != 0) { 441 cmn_err(CE_PANIC, 442 "sadb_insertassoc() failed in " 443 "ipsec_getassocbyconn().\n"); 444 } 445 #else /* non-DEBUG */ 446 (void) sadb_insertassoc(retval, bucket); 447 #endif /* DEBUG */ 448 return (retval); 449 } 450 } 451 mutex_exit(&retval->ipsa_lock); 452 453 return (retval); 454 } 455 456 /* 457 * Look up a security association based on the security parameters index (SPI) 458 * and address(es). This is used for inbound packets and general SA lookups 459 * (even in outbound SA tables). The source address may be ignored. Return 460 * NULL if no association is available. If an SA is found, return it, with 461 * its refcnt incremented. The caller must REFRELE after using the SA. 462 * The hash bucket must be locked down before calling. 463 */ 464 ipsa_t * 465 ipsec_getassocbyspi(isaf_t *bucket, uint32_t spi, uint32_t *src, uint32_t *dst, 466 sa_family_t af) 467 { 468 ipsa_t *retval; 469 470 ASSERT(MUTEX_HELD(&bucket->isaf_lock)); 471 472 /* 473 * Walk the hash bucket, matching exactly on SPI, then destination, 474 * then source. 475 * 476 * Per-SA locking doesn't need to happen, because I'm only matching 477 * on addresses. Addresses are only changed during insertion/deletion 478 * from the hash bucket. Since the hash bucket lock is held, we don't 479 * need to worry about addresses changing. 480 */ 481 482 for (retval = bucket->isaf_ipsa; retval != NULL; 483 retval = retval->ipsa_next) { 484 if (retval->ipsa_spi != spi) 485 continue; 486 if (!IPSA_ARE_ADDR_EQUAL(dst, retval->ipsa_dstaddr, af)) 487 continue; 488 489 /* 490 * Assume that wildcard source addresses are inserted at the 491 * end of the hash bucket. (See sadb_insertassoc().) 492 * The following check for source addresses is a weak form 493 * of access control/source identity verification. If an 494 * SA has a source address, I only match an all-zeroes 495 * source address, or that particular one. If the SA has 496 * an all-zeroes source, then I match regardless. 497 * 498 * There is a weakness here in that a packet with all-zeroes 499 * for an address will match regardless of the source address 500 * stored in the packet. 501 */ 502 if (IPSA_ARE_ADDR_EQUAL(src, retval->ipsa_srcaddr, af) || 503 IPSA_IS_ADDR_UNSPEC(retval->ipsa_srcaddr, af) || 504 IPSA_IS_ADDR_UNSPEC(src, af)) 505 break; 506 } 507 508 if (retval != NULL) { 509 /* 510 * Just refhold the return value. The caller will then 511 * make the appropriate calls to set the USED flag. 512 */ 513 IPSA_REFHOLD(retval); 514 } 515 516 return (retval); 517 } 518 519 boolean_t 520 ipsec_outbound_sa(mblk_t *mp, uint_t proto) 521 { 522 mblk_t *data_mp; 523 ipsec_out_t *io; 524 ipaddr_t dst; 525 uint32_t *dst_ptr, *src_ptr; 526 isaf_t *bucket; 527 ipsa_t *assoc; 528 ip6_pkt_t ipp; 529 in6_addr_t dst6; 530 ipsa_t **sa; 531 sadbp_t *sadbp; 532 sadb_t *sp; 533 sa_family_t af; 534 535 data_mp = mp->b_cont; 536 io = (ipsec_out_t *)mp->b_rptr; 537 538 if (proto == IPPROTO_ESP) { 539 sa = &io->ipsec_out_esp_sa; 540 sadbp = &esp_sadb; 541 } else { 542 ASSERT(proto == IPPROTO_AH); 543 sa = &io->ipsec_out_ah_sa; 544 sadbp = &ah_sadb; 545 } 546 547 ASSERT(*sa == NULL); 548 549 if (io->ipsec_out_v4) { 550 ipha_t *ipha = (ipha_t *)data_mp->b_rptr; 551 552 ASSERT(IPH_HDR_VERSION(ipha) == IPV4_VERSION); 553 dst = ip_get_dst(ipha); 554 sp = &sadbp->s_v4; 555 af = AF_INET; 556 557 /* 558 * NOTE:Getting the outbound association is considerably 559 * painful. ipsec_getassocbyconn() will require more 560 * parameters as policy implementations mature. 561 */ 562 bucket = OUTBOUND_BUCKET_V4(sp, dst); 563 src_ptr = (uint32_t *)&ipha->ipha_src; 564 dst_ptr = (uint32_t *)&dst; 565 } else { 566 ip6_t *ip6h = (ip6_t *)data_mp->b_rptr; 567 568 ASSERT(IPH_HDR_VERSION(ip6h) == IPV6_VERSION); 569 dst6 = ip_get_dst_v6(ip6h, NULL); 570 af = AF_INET6; 571 572 bzero(&ipp, sizeof (ipp)); 573 sp = &sadbp->s_v6; 574 575 /* Same NOTE: applies here! */ 576 bucket = OUTBOUND_BUCKET_V6(sp, dst6); 577 src_ptr = (uint32_t *)&ip6h->ip6_src; 578 dst_ptr = (uint32_t *)&dst6; 579 } 580 581 mutex_enter(&bucket->isaf_lock); 582 assoc = ipsec_getassocbyconn(bucket, io, src_ptr, dst_ptr, af, proto); 583 mutex_exit(&bucket->isaf_lock); 584 585 if (assoc == NULL) 586 return (B_FALSE); 587 588 if (assoc->ipsa_state == IPSA_STATE_DEAD) { 589 IPSA_REFRELE(assoc); 590 return (B_FALSE); 591 } 592 593 ASSERT(assoc->ipsa_state != IPSA_STATE_LARVAL); 594 595 *sa = assoc; 596 return (B_TRUE); 597 } 598 599 /* 600 * Inbound IPsec SA selection. 601 */ 602 603 ah_t * 604 ipsec_inbound_ah_sa(mblk_t *mp) 605 { 606 mblk_t *ipsec_in; 607 ipha_t *ipha; 608 ipsa_t *assoc; 609 ah_t *ah; 610 isaf_t *hptr; 611 ipsec_in_t *ii; 612 boolean_t isv6; 613 ip6_t *ip6h; 614 int ah_offset; 615 uint32_t *src_ptr, *dst_ptr; 616 int pullup_len; 617 sadb_t *sp; 618 sa_family_t af; 619 620 IP_AH_BUMP_STAT(in_requests); 621 622 ASSERT(mp->b_datap->db_type == M_CTL); 623 624 ipsec_in = mp; 625 ii = (ipsec_in_t *)ipsec_in->b_rptr; 626 mp = mp->b_cont; 627 628 ASSERT(mp->b_datap->db_type == M_DATA); 629 630 isv6 = !ii->ipsec_in_v4; 631 if (isv6) { 632 ip6h = (ip6_t *)mp->b_rptr; 633 ah_offset = ipsec_ah_get_hdr_size_v6(mp, B_TRUE); 634 } else { 635 ipha = (ipha_t *)mp->b_rptr; 636 ASSERT(ipha->ipha_protocol == IPPROTO_AH); 637 ah_offset = ipha->ipha_version_and_hdr_length - 638 (uint8_t)((IP_VERSION << 4)); 639 ah_offset <<= 2; 640 } 641 642 /* 643 * We assume that the IP header is pulled up until 644 * the options. We need to see whether we have the 645 * AH header in the same mblk or not. 646 */ 647 pullup_len = ah_offset + sizeof (ah_t); 648 if (mp->b_rptr + pullup_len > mp->b_wptr) { 649 if (!pullupmsg(mp, pullup_len)) { 650 ipsecah_rl_strlog(0, SL_WARN | SL_ERROR, 651 "ipsec_inbound_ah_sa: Small AH header\n"); 652 IP_AH_BUMP_STAT(in_discards); 653 ip_drop_packet(ipsec_in, B_TRUE, NULL, NULL, 654 &ipdrops_ah_bad_length, &ip_dropper); 655 return (NULL); 656 } 657 if (isv6) 658 ip6h = (ip6_t *)mp->b_rptr; 659 else 660 ipha = (ipha_t *)mp->b_rptr; 661 } 662 663 ah = (ah_t *)(mp->b_rptr + ah_offset); 664 665 if (isv6) { 666 src_ptr = (uint32_t *)&ip6h->ip6_src; 667 dst_ptr = (uint32_t *)&ip6h->ip6_dst; 668 sp = &ah_sadb.s_v6; 669 af = AF_INET6; 670 } else { 671 src_ptr = (uint32_t *)&ipha->ipha_src; 672 dst_ptr = (uint32_t *)&ipha->ipha_dst; 673 sp = &ah_sadb.s_v4; 674 af = AF_INET; 675 } 676 677 hptr = INBOUND_BUCKET(sp, ah->ah_spi); 678 mutex_enter(&hptr->isaf_lock); 679 assoc = ipsec_getassocbyspi(hptr, ah->ah_spi, src_ptr, dst_ptr, af); 680 mutex_exit(&hptr->isaf_lock); 681 682 if (assoc == NULL || assoc->ipsa_state == IPSA_STATE_DEAD) { 683 IP_AH_BUMP_STAT(lookup_failure); 684 IP_AH_BUMP_STAT(in_discards); 685 ipsecah_in_assocfailure(ipsec_in, 0, 686 SL_ERROR | SL_CONSOLE | SL_WARN, 687 "ipsec_inbound_ah_sa: No association found for " 688 "spi 0x%x, dst addr %s\n", 689 ah->ah_spi, dst_ptr, af); 690 if (assoc != NULL) { 691 IPSA_REFRELE(assoc); 692 } 693 return (NULL); 694 } 695 696 if (assoc->ipsa_state == IPSA_STATE_LARVAL) { 697 /* Not fully baked; swap the packet under a rock until then */ 698 sadb_set_lpkt(assoc, ipsec_in); 699 IPSA_REFRELE(assoc); 700 return (NULL); 701 } 702 703 /* 704 * Save a reference to the association so that it can 705 * be retrieved after execution. We free any AH SA reference 706 * already there (innermost SA "wins". The reference to 707 * the SA will also be used later when doing the policy checks. 708 */ 709 if (ii->ipsec_in_ah_sa != NULL) { 710 IPSA_REFRELE(ii->ipsec_in_ah_sa); 711 } 712 ii->ipsec_in_ah_sa = assoc; 713 714 return (ah); 715 } 716 717 esph_t * 718 ipsec_inbound_esp_sa(mblk_t *ipsec_in_mp) 719 { 720 mblk_t *data_mp, *placeholder; 721 uint32_t *src_ptr, *dst_ptr; 722 ipsec_in_t *ii; 723 ipha_t *ipha; 724 ip6_t *ip6h; 725 esph_t *esph; 726 ipsa_t *ipsa; 727 isaf_t *bucket; 728 uint_t preamble; 729 sa_family_t af; 730 boolean_t isv6; 731 sadb_t *sp; 732 733 IP_ESP_BUMP_STAT(in_requests); 734 ASSERT(ipsec_in_mp->b_datap->db_type == M_CTL); 735 736 /* We have IPSEC_IN already! */ 737 ii = (ipsec_in_t *)ipsec_in_mp->b_rptr; 738 data_mp = ipsec_in_mp->b_cont; 739 740 ASSERT(ii->ipsec_in_type == IPSEC_IN); 741 742 isv6 = !ii->ipsec_in_v4; 743 if (isv6) { 744 ip6h = (ip6_t *)data_mp->b_rptr; 745 } else { 746 ipha = (ipha_t *)data_mp->b_rptr; 747 } 748 749 /* 750 * Put all data into one mblk if it's not there already. 751 * XXX This is probably bad long-term. Figure out better ways of doing 752 * this. Much of the inbound path depends on all of the data being 753 * in one mblk. 754 * 755 * XXX Jumbogram issues will have to be dealt with here. 756 * If the plen is 0, we'll have to scan for a HBH header with the 757 * actual packet length. 758 */ 759 if (data_mp->b_datap->db_ref > 1 || 760 (data_mp->b_wptr - data_mp->b_rptr) < 761 (isv6 ? (ntohs(ip6h->ip6_plen) + sizeof (ip6_t)) 762 : ntohs(ipha->ipha_length))) { 763 placeholder = msgpullup(data_mp, -1); 764 if (placeholder == NULL) { 765 IP_ESP_BUMP_STAT(in_discards); 766 /* 767 * TODO: Extract inbound interface from the IPSEC_IN 768 * message's ii->ipsec_in_rill_index. 769 */ 770 ip_drop_packet(ipsec_in_mp, B_TRUE, NULL, NULL, 771 &ipdrops_esp_nomem, &ip_dropper); 772 return (NULL); 773 } else { 774 /* Reset packet with new pulled up mblk. */ 775 freemsg(data_mp); 776 data_mp = placeholder; 777 ipsec_in_mp->b_cont = data_mp; 778 } 779 } 780 781 /* 782 * Find the ESP header, point the address pointers at the appropriate 783 * IPv4/IPv6 places. 784 */ 785 if (isv6) { 786 ip6h = (ip6_t *)data_mp->b_rptr; 787 src_ptr = (uint32_t *)&ip6h->ip6_src; 788 dst_ptr = (uint32_t *)&ip6h->ip6_dst; 789 if (ip6h->ip6_nxt != IPPROTO_ESP) { 790 /* There are options that need to be processed. */ 791 preamble = ip_hdr_length_v6(data_mp, ip6h); 792 } else { 793 preamble = sizeof (ip6_t); 794 } 795 796 sp = &esp_sadb.s_v6; 797 af = AF_INET6; 798 } else { 799 ipha = (ipha_t *)data_mp->b_rptr; 800 src_ptr = (uint32_t *)&ipha->ipha_src; 801 dst_ptr = (uint32_t *)&ipha->ipha_dst; 802 preamble = IPH_HDR_LENGTH(ipha); 803 804 sp = &esp_sadb.s_v4; 805 af = AF_INET; 806 } 807 808 esph = (esph_t *)(data_mp->b_rptr + preamble); 809 810 /* Since hash is common on inbound (SPI value), hash here. */ 811 bucket = INBOUND_BUCKET(sp, esph->esph_spi); 812 mutex_enter(&bucket->isaf_lock); 813 ipsa = ipsec_getassocbyspi(bucket, esph->esph_spi, src_ptr, dst_ptr, 814 af); 815 mutex_exit(&bucket->isaf_lock); 816 817 if (ipsa == NULL || ipsa->ipsa_state == IPSA_STATE_DEAD) { 818 /* This is a loggable error! AUDIT ME! */ 819 IP_ESP_BUMP_STAT(lookup_failure); 820 IP_ESP_BUMP_STAT(in_discards); 821 ipsecesp_in_assocfailure(ipsec_in_mp, 0, 822 SL_ERROR | SL_CONSOLE | SL_WARN, 823 "ipsec_inbound_esp_sa: No association found for " 824 "spi 0x%x, dst addr %s\n", 825 esph->esph_spi, dst_ptr, af); 826 if (ipsa != NULL) { 827 IPSA_REFRELE(ipsa); 828 } 829 return (NULL); 830 } 831 832 if (ipsa->ipsa_state == IPSA_STATE_LARVAL) { 833 /* Not fully baked; swap the packet under a rock until then */ 834 sadb_set_lpkt(ipsa, ipsec_in_mp); 835 IPSA_REFRELE(ipsa); 836 return (NULL); 837 } 838 839 /* 840 * Save a reference to the association so that it can 841 * be retrieved after execution. We free any AH SA reference 842 * already there (innermost SA "wins". The reference to 843 * the SA will also be used later when doing the policy checks. 844 */ 845 if (ii->ipsec_in_esp_sa != NULL) { 846 IPSA_REFRELE(ii->ipsec_in_esp_sa); 847 } 848 ii->ipsec_in_esp_sa = ipsa; 849 850 return (esph); 851 } 852