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