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 2004 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 sa_family_t af; 533 534 data_mp = mp->b_cont; 535 io = (ipsec_out_t *)mp->b_rptr; 536 537 if (proto == IPPROTO_ESP) { 538 sa = &io->ipsec_out_esp_sa; 539 sadbp = &esp_sadb; 540 } else { 541 ASSERT(proto == IPPROTO_AH); 542 sa = &io->ipsec_out_ah_sa; 543 sadbp = &ah_sadb; 544 } 545 546 ASSERT(*sa == NULL); 547 548 if (io->ipsec_out_v4) { 549 ipha_t *ipha = (ipha_t *)data_mp->b_rptr; 550 551 ASSERT(IPH_HDR_VERSION(ipha) == IPV4_VERSION); 552 dst = ip_get_dst(ipha); 553 af = AF_INET; 554 555 /* 556 * NOTE:Getting the outbound association is considerably 557 * painful. ipsec_getassocbyconn() will require more 558 * parameters as policy implementations mature. 559 */ 560 bucket = &sadbp->s_v4.sdb_of[OUTBOUND_HASH_V4(dst)]; 561 src_ptr = (uint32_t *)&ipha->ipha_src; 562 dst_ptr = (uint32_t *)&dst; 563 } else { 564 ip6_t *ip6h = (ip6_t *)data_mp->b_rptr; 565 566 ASSERT(IPH_HDR_VERSION(ip6h) == IPV6_VERSION); 567 dst6 = ip_get_dst_v6(ip6h, NULL); 568 af = AF_INET6; 569 570 bzero(&ipp, sizeof (ipp)); 571 572 /* Same NOTE: applies here! */ 573 bucket = &sadbp->s_v6.sdb_of[OUTBOUND_HASH_V6(dst6)]; 574 src_ptr = (uint32_t *)&ip6h->ip6_src; 575 dst_ptr = (uint32_t *)&dst6; 576 } 577 578 mutex_enter(&bucket->isaf_lock); 579 assoc = ipsec_getassocbyconn(bucket, io, src_ptr, dst_ptr, af, proto); 580 mutex_exit(&bucket->isaf_lock); 581 582 if (assoc == NULL) 583 return (B_FALSE); 584 585 if (assoc->ipsa_state == IPSA_STATE_DEAD) { 586 IPSA_REFRELE(assoc); 587 return (B_FALSE); 588 } 589 590 ASSERT(assoc->ipsa_state != IPSA_STATE_LARVAL); 591 592 *sa = assoc; 593 return (B_TRUE); 594 } 595 596 /* 597 * Inbound IPsec SA selection. 598 */ 599 600 ah_t * 601 ipsec_inbound_ah_sa(mblk_t *mp) 602 { 603 mblk_t *ipsec_in; 604 ipha_t *ipha; 605 ipsa_t *assoc; 606 ah_t *ah; 607 isaf_t *hptr; 608 ipsec_in_t *ii; 609 boolean_t isv6; 610 ip6_t *ip6h; 611 int ah_offset; 612 uint32_t *src_ptr, *dst_ptr; 613 int pullup_len; 614 sa_family_t af; 615 616 IP_AH_BUMP_STAT(in_requests); 617 618 ASSERT(mp->b_datap->db_type == M_CTL); 619 620 ipsec_in = mp; 621 ii = (ipsec_in_t *)ipsec_in->b_rptr; 622 mp = mp->b_cont; 623 624 ASSERT(mp->b_datap->db_type == M_DATA); 625 626 isv6 = !ii->ipsec_in_v4; 627 if (isv6) { 628 ip6h = (ip6_t *)mp->b_rptr; 629 ah_offset = ipsec_ah_get_hdr_size_v6(mp, B_TRUE); 630 } else { 631 ipha = (ipha_t *)mp->b_rptr; 632 ASSERT(ipha->ipha_protocol == IPPROTO_AH); 633 ah_offset = ipha->ipha_version_and_hdr_length - 634 (uint8_t)((IP_VERSION << 4)); 635 ah_offset <<= 2; 636 } 637 638 /* 639 * We assume that the IP header is pulled up until 640 * the options. We need to see whether we have the 641 * AH header in the same mblk or not. 642 */ 643 pullup_len = ah_offset + sizeof (ah_t); 644 if (mp->b_rptr + pullup_len > mp->b_wptr) { 645 if (!pullupmsg(mp, pullup_len)) { 646 ipsecah_rl_strlog(0, SL_WARN | SL_ERROR, 647 "ipsec_inbound_ah_sa: Small AH header\n"); 648 IP_AH_BUMP_STAT(in_discards); 649 ip_drop_packet(ipsec_in, B_TRUE, NULL, NULL, 650 &ipdrops_ah_bad_length, &ip_dropper); 651 return (NULL); 652 } 653 if (isv6) 654 ip6h = (ip6_t *)mp->b_rptr; 655 else 656 ipha = (ipha_t *)mp->b_rptr; 657 } 658 659 ah = (ah_t *)(mp->b_rptr + ah_offset); 660 661 if (isv6) { 662 src_ptr = (uint32_t *)&ip6h->ip6_src; 663 dst_ptr = (uint32_t *)&ip6h->ip6_dst; 664 hptr = ah_sadb.s_v6.sdb_if; 665 af = AF_INET6; 666 } else { 667 src_ptr = (uint32_t *)&ipha->ipha_src; 668 dst_ptr = (uint32_t *)&ipha->ipha_dst; 669 hptr = ah_sadb.s_v4.sdb_if; 670 af = AF_INET; 671 } 672 673 hptr += INBOUND_HASH(ah->ah_spi); 674 mutex_enter(&hptr->isaf_lock); 675 assoc = ipsec_getassocbyspi(hptr, ah->ah_spi, src_ptr, dst_ptr, af); 676 mutex_exit(&hptr->isaf_lock); 677 678 if (assoc == NULL || assoc->ipsa_state == IPSA_STATE_DEAD) { 679 IP_AH_BUMP_STAT(lookup_failure); 680 IP_AH_BUMP_STAT(in_discards); 681 ipsecah_in_assocfailure(ipsec_in, 0, 682 SL_ERROR | SL_CONSOLE | SL_WARN, 683 "ipsec_inbound_ah_sa: No association found for " 684 "spi 0x%x, dst addr %s\n", 685 ah->ah_spi, dst_ptr, af); 686 if (assoc != NULL) { 687 IPSA_REFRELE(assoc); 688 } 689 return (NULL); 690 } 691 692 if (assoc->ipsa_state == IPSA_STATE_LARVAL) { 693 /* Not fully baked; swap the packet under a rock until then */ 694 sadb_set_lpkt(assoc, ipsec_in); 695 IPSA_REFRELE(assoc); 696 return (NULL); 697 } 698 699 /* 700 * Save a reference to the association so that it can 701 * be retrieved after execution. We free any AH SA reference 702 * already there (innermost SA "wins". The reference to 703 * the SA will also be used later when doing the policy checks. 704 */ 705 if (ii->ipsec_in_ah_sa != NULL) { 706 IPSA_REFRELE(ii->ipsec_in_ah_sa); 707 } 708 ii->ipsec_in_ah_sa = assoc; 709 710 return (ah); 711 } 712 713 esph_t * 714 ipsec_inbound_esp_sa(mblk_t *ipsec_in_mp) 715 { 716 mblk_t *data_mp, *placeholder; 717 uint32_t *src_ptr, *dst_ptr; 718 ipsec_in_t *ii; 719 ipha_t *ipha; 720 ip6_t *ip6h; 721 esph_t *esph; 722 ipsa_t *ipsa; 723 isaf_t *bucket; 724 uint_t preamble; 725 sa_family_t af; 726 boolean_t isv6; 727 728 IP_ESP_BUMP_STAT(in_requests); 729 ASSERT(ipsec_in_mp->b_datap->db_type == M_CTL); 730 731 /* We have IPSEC_IN already! */ 732 ii = (ipsec_in_t *)ipsec_in_mp->b_rptr; 733 data_mp = ipsec_in_mp->b_cont; 734 735 ASSERT(ii->ipsec_in_type == IPSEC_IN); 736 737 isv6 = !ii->ipsec_in_v4; 738 if (isv6) { 739 ip6h = (ip6_t *)data_mp->b_rptr; 740 } else { 741 ipha = (ipha_t *)data_mp->b_rptr; 742 } 743 744 /* 745 * Put all data into one mblk if it's not there already. 746 * XXX This is probably bad long-term. Figure out better ways of doing 747 * this. Much of the inbound path depends on all of the data being 748 * in one mblk. 749 * 750 * XXX Jumbogram issues will have to be dealt with here. 751 * If the plen is 0, we'll have to scan for a HBH header with the 752 * actual packet length. 753 */ 754 if (data_mp->b_datap->db_ref > 1 || 755 (data_mp->b_wptr - data_mp->b_rptr) < 756 (isv6 ? (ntohs(ip6h->ip6_plen) + sizeof (ip6_t)) 757 : ntohs(ipha->ipha_length))) { 758 placeholder = msgpullup(data_mp, -1); 759 if (placeholder == NULL) { 760 IP_ESP_BUMP_STAT(in_discards); 761 /* 762 * TODO: Extract inbound interface from the IPSEC_IN 763 * message's ii->ipsec_in_rill_index. 764 */ 765 ip_drop_packet(ipsec_in_mp, B_TRUE, NULL, NULL, 766 &ipdrops_esp_nomem, &ip_dropper); 767 return (NULL); 768 } else { 769 /* Reset packet with new pulled up mblk. */ 770 freemsg(data_mp); 771 data_mp = placeholder; 772 ipsec_in_mp->b_cont = data_mp; 773 } 774 } 775 776 /* 777 * Find the ESP header, point the address pointers at the appropriate 778 * IPv4/IPv6 places. 779 */ 780 if (isv6) { 781 ip6h = (ip6_t *)data_mp->b_rptr; 782 src_ptr = (uint32_t *)&ip6h->ip6_src; 783 dst_ptr = (uint32_t *)&ip6h->ip6_dst; 784 if (ip6h->ip6_nxt != IPPROTO_ESP) { 785 /* There are options that need to be processed. */ 786 preamble = ip_hdr_length_v6(data_mp, ip6h); 787 } else { 788 preamble = sizeof (ip6_t); 789 } 790 791 bucket = esp_sadb.s_v6.sdb_if; 792 af = AF_INET6; 793 } else { 794 ipha = (ipha_t *)data_mp->b_rptr; 795 src_ptr = (uint32_t *)&ipha->ipha_src; 796 dst_ptr = (uint32_t *)&ipha->ipha_dst; 797 preamble = IPH_HDR_LENGTH(ipha); 798 799 bucket = esp_sadb.s_v4.sdb_if; 800 af = AF_INET; 801 } 802 803 esph = (esph_t *)(data_mp->b_rptr + preamble); 804 805 /* Since hash is common on inbound (SPI value), hash here. */ 806 bucket += INBOUND_HASH(esph->esph_spi); 807 mutex_enter(&bucket->isaf_lock); 808 ipsa = ipsec_getassocbyspi(bucket, esph->esph_spi, src_ptr, dst_ptr, 809 af); 810 mutex_exit(&bucket->isaf_lock); 811 812 if (ipsa == NULL || ipsa->ipsa_state == IPSA_STATE_DEAD) { 813 /* This is a loggable error! AUDIT ME! */ 814 IP_ESP_BUMP_STAT(lookup_failure); 815 IP_ESP_BUMP_STAT(in_discards); 816 ipsecesp_in_assocfailure(ipsec_in_mp, 0, 817 SL_ERROR | SL_CONSOLE | SL_WARN, 818 "ipsec_inbound_esp_sa: No association found for " 819 "spi 0x%x, dst addr %s\n", 820 esph->esph_spi, dst_ptr, af); 821 if (ipsa != NULL) { 822 IPSA_REFRELE(ipsa); 823 } 824 return (NULL); 825 } 826 827 if (ipsa->ipsa_state == IPSA_STATE_LARVAL) { 828 /* Not fully baked; swap the packet under a rock until then */ 829 sadb_set_lpkt(ipsa, ipsec_in_mp); 830 IPSA_REFRELE(ipsa); 831 return (NULL); 832 } 833 834 /* 835 * Save a reference to the association so that it can 836 * be retrieved after execution. We free any AH SA reference 837 * already there (innermost SA "wins". The reference to 838 * the SA will also be used later when doing the policy checks. 839 */ 840 if (ii->ipsec_in_esp_sa != NULL) { 841 IPSA_REFRELE(ii->ipsec_in_esp_sa); 842 } 843 ii->ipsec_in_esp_sa = ipsa; 844 845 return (esph); 846 } 847