560 
 561         mp = allocb(sizeof (ipsec_info_t), BPRI_HI);
 562         if (mp != NULL) {
 563                 mp->b_datap->db_type = M_CTL;
 564                 mp->b_wptr += sizeof (ipsec_info_t);
 565                 kso = (keysock_out_t *)mp->b_rptr;
 566                 kso->ks_out_type = KEYSOCK_OUT;
 567                 kso->ks_out_len = sizeof (*kso);
 568                 kso->ks_out_serial = serial;
 569         }
 570 
 571         return (mp);
 572 }
 573 
 574 /*
 575  * Perform an SADB_DUMP, spewing out every SA in an array of SA fanouts
 576  * to keysock.
 577  */
 578 static int
 579 sadb_dump_fanout(queue_t *pfkey_q, mblk_t *mp, minor_t serial, isaf_t *fanout,
 580     int num_entries, boolean_t do_peers, time_t active_time)
 581 {
 582         int i, error = 0;
 583         mblk_t *original_answer;
 584         ipsa_t *walker;
 585         sadb_msg_t *samsg;
 586         time_t  current;
 587 
 588         /*
 589          * For each IPSA hash bucket do:
 590          *      - Hold the mutex
 591          *      - Walk each entry, doing an sadb_dump_deliver() on it.
 592          */
 593         ASSERT(mp->b_cont != NULL);
 594         samsg = (sadb_msg_t *)mp->b_cont->b_rptr;
 595 
 596         original_answer = sadb_keysock_out(serial);
 597         if (original_answer == NULL)
 598                 return (ENOMEM);
 599 
 600         current = gethrestime_sec();
 601         for (i = 0; i < num_entries; i++) {
 602                 mutex_enter(&fanout[i].isaf_lock);
 603                 for (walker = fanout[i].isaf_ipsa; walker != NULL;
 604                     walker = walker->ipsa_next) {
 605                         if (!do_peers && walker->ipsa_haspeer)
 606                                 continue;
 607                         if ((active_time != 0) &&
 608                             ((current - walker->ipsa_lastuse) > active_time))
 609                                 continue;
 610                         error = sadb_dump_deliver(pfkey_q, original_answer,
 611                             walker, samsg);
 612                         if (error == ENOBUFS) {
 613                                 mblk_t *new_original_answer;
 614 
 615                                 /* Ran out of dupb's.  Try a copyb. */
 616                                 new_original_answer = copyb(original_answer);
 617                                 if (new_original_answer == NULL) {
 618                                         error = ENOMEM;
 619                                 } else {
 620                                         freeb(original_answer);
 621                                         original_answer = new_original_answer;
 622                                         error = sadb_dump_deliver(pfkey_q,
 623                                             original_answer, walker, samsg);
 624                                 }
 625                         }
 626                         if (error != 0)
 627                                 break;  /* out of for loop. */
 628                 }
 629                 mutex_exit(&fanout[i].isaf_lock);
 630                 if (error != 0)
 631                         break;  /* out of for loop. */
 632         }
 633 
 634         freeb(original_answer);
 635         return (error);
 636 }
 637 
 638 /*
 639  * Dump an entire SADB; outbound first, then inbound.
 640  */
 641 
 642 int
 643 sadb_dump(queue_t *pfkey_q, mblk_t *mp, keysock_in_t *ksi, sadb_t *sp)
 644 {
 645         int error;
 646         time_t  active_time = 0;
 647         sadb_x_edump_t  *edump =
 648             (sadb_x_edump_t *)ksi->ks_in_extv[SADB_X_EXT_EDUMP];
 649 
 650         if (edump != NULL) {
 651                 active_time = edump->sadb_x_edump_timeout;
 652         }
 653 
 654         /* Dump outbound */
 655         error = sadb_dump_fanout(pfkey_q, mp, ksi->ks_in_serial, sp->sdb_of,
 656             sp->sdb_hashsize, B_TRUE, active_time);
 657         if (error)
 658                 return (error);
 659 
 660         /* Dump inbound */
 661         return sadb_dump_fanout(pfkey_q, mp, ksi->ks_in_serial, sp->sdb_if,
 662             sp->sdb_hashsize, B_FALSE, active_time);
 663 }
 664 
 665 /*
 666  * Generic sadb table walker.
 667  *
 668  * Call "walkfn" for each SA in each bucket in "table"; pass the
 669  * bucket, the entry and "cookie" to the callback function.
 670  * Take care to ensure that walkfn can delete the SA without screwing
 671  * up our traverse.
 672  *
 673  * The bucket is locked for the duration of the callback, both so that the
 674  * callback can just call sadb_unlinkassoc() when it wants to delete something,
 675  * and so that no new entries are added while we're walking the list.
 676  */
 677 static void
 678 sadb_walker(isaf_t *table, uint_t numentries,
 679     void (*walkfn)(isaf_t *head, ipsa_t *entry, void *cookie),
 680     void *cookie)
 681 {
 682         int i;
 683         for (i = 0; i < numentries; i++) {
 684                 ipsa_t *entry, *next;
 685 
 686                 mutex_enter(&table[i].isaf_lock);
 687 
 688                 for (entry = table[i].isaf_ipsa; entry != NULL;
 689                     entry = next) {
 690                         next = entry->ipsa_next;
 691                         (*walkfn)(&table[i], entry, cookie);
 692                 }
 693                 mutex_exit(&table[i].isaf_lock);
 694         }
 695 }
 696 
 697 /*
 698  * Call me to free up a security association fanout.  Use the forever
 699  * variable to indicate freeing up the SAs (forever == B_FALSE, e.g.
 700  * an SADB_FLUSH message), or destroying everything (forever == B_TRUE,
 701  * when a module is unloaded).
 702  */
 703 static void
 704 sadb_destroyer(isaf_t **tablep, uint_t numentries, boolean_t forever,
 705     boolean_t inbound)
 706 {
 707         int i;
 708         isaf_t *table = *tablep;
 709         ipsa_t *sa;
 710 
 711         if (table == NULL)
 712                 return;
 713 
 714         for (i = 0; i < numentries; i++) {
 715                 mutex_enter(&table[i].isaf_lock);
 716                 while ((sa = table[i].isaf_ipsa) != NULL) {
 717                         sadb_unlinkassoc(sa);
 718                 }
 719                 table[i].isaf_gen++;
 720                 mutex_exit(&table[i].isaf_lock);
 721                 if (forever)
 722                         mutex_destroy(&(table[i].isaf_lock));
 723         }
 724 
 725         if (forever) {
 726                 *tablep = NULL;
 727                 kmem_free(table, numentries * sizeof (*table));
 728         }
 729 }
 730 
 731 /*
 732  * Entry points to sadb_destroyer().
 733  */
 734 static void
 735 sadb_flush(sadb_t *sp, netstack_t *ns)
 736 {
 737         /*
 738          * Flush out each bucket, one at a time.  Were it not for keysock's
 739          * enforcement, there would be a subtlety where I could add on the
 740          * heels of a flush.  With keysock's enforcement, however, this
 741          * makes ESP's job easy.
 742          */
 743         sadb_destroyer(&sp->sdb_of, sp->sdb_hashsize, B_FALSE, B_FALSE);
 744         sadb_destroyer(&sp->sdb_if, sp->sdb_hashsize, B_FALSE, B_TRUE);
 745 
 746         /* For each acquire, destroy it; leave the bucket mutex alone. */
 747         sadb_destroy_acqlist(&sp->sdb_acq, sp->sdb_hashsize, B_FALSE, ns);
 748 }
 749 
 750 static void
 751 sadb_destroy(sadb_t *sp, netstack_t *ns)
 752 {
 753         sadb_destroyer(&sp->sdb_of, sp->sdb_hashsize, B_TRUE, B_FALSE);
 754         sadb_destroyer(&sp->sdb_if, sp->sdb_hashsize, B_TRUE, B_TRUE);
 755 
 756         /* For each acquire, destroy it, including the bucket mutex. */
 757         sadb_destroy_acqlist(&sp->sdb_acq, sp->sdb_hashsize, B_TRUE, ns);
 758 
 759         ASSERT(sp->sdb_of == NULL);
 760         ASSERT(sp->sdb_if == NULL);
 761         ASSERT(sp->sdb_acq == NULL);
 762 }
 763 
 764 void
 765 sadbp_flush(sadbp_t *spp, netstack_t *ns)
 766 {
 767         sadb_flush(&spp->s_v4, ns);
 768         sadb_flush(&spp->s_v6, ns);
 769 }
 770 
 771 void
 772 sadbp_destroy(sadbp_t *spp, netstack_t *ns)
 773 {
 774         sadb_destroy(&spp->s_v4, ns);
 
1476  *
1477  * +------+----+-------------+-----------+---------------+
1478  * | base | SA | source addr | dest addr | soft lifetime |
1479  * +------+----+-------------+-----------+---------------+
1480  */
1481 static void
1482 sadb_strip(sadb_msg_t *samsg)
1483 {
1484         sadb_ext_t *ext;
1485         uint8_t *target = NULL;
1486         uint8_t *msgend;
1487         int sofar = SADB_8TO64(sizeof (*samsg));
1488         int copylen;
1489 
1490         ext = (sadb_ext_t *)(samsg + 1);
1491         msgend = (uint8_t *)samsg;
1492         msgend += SADB_64TO8(samsg->sadb_msg_len);
1493         while ((uint8_t *)ext < msgend) {
1494                 if (ext->sadb_ext_type == SADB_EXT_RESERVED ||
1495                     ext->sadb_ext_type == SADB_EXT_KEY_AUTH ||
1496                     ext->sadb_ext_type == SADB_X_EXT_EDUMP ||
1497                     ext->sadb_ext_type == SADB_EXT_KEY_ENCRYPT) {
1498                         /*
1499                          * Aha!  I found a header to be erased.
1500                          */
1501 
1502                         if (target != NULL) {
1503                                 /*
1504                                  * If I had a previous header to be erased,
1505                                  * copy over it.  I can get away with just
1506                                  * copying backwards because the target will
1507                                  * always be 8 bytes behind the source.
1508                                  */
1509                                 copylen = ((uint8_t *)ext) - (target +
1510                                     SADB_64TO8(
1511                                     ((sadb_ext_t *)target)->sadb_ext_len));
1512                                 ovbcopy(((uint8_t *)ext - copylen), target,
1513                                     copylen);
1514                                 target += copylen;
1515                                 ((sadb_ext_t *)target)->sadb_ext_len =
1516                                     SADB_8TO64(((uint8_t *)ext) - target +
 
1593  * and NULL if not.  BTW, that ipsa will have its refcnt appropriately held,
1594  * and the caller will release said refcnt.
1595  */
1596 void
1597 sadb_pfkey_echo(queue_t *pfkey_q, mblk_t *mp, sadb_msg_t *samsg,
1598     keysock_in_t *ksi, ipsa_t *ipsa)
1599 {
1600         keysock_out_t *kso;
1601         mblk_t *mp1;
1602         sadb_msg_t *newsamsg;
1603         uint8_t *oldend;
1604 
1605         ASSERT((mp->b_cont != NULL) &&
1606             ((void *)samsg == (void *)mp->b_cont->b_rptr) &&
1607             ((void *)mp->b_rptr == (void *)ksi));
1608 
1609         switch (samsg->sadb_msg_type) {
1610         case SADB_ADD:
1611         case SADB_UPDATE:
1612         case SADB_X_UPDATEPAIR:
1613         case SADB_X_DELPAIR_STATE:
1614         case SADB_FLUSH:
1615         case SADB_DUMP:
1616                 /*
1617                  * I have all of the message already.  I just need to strip
1618                  * out the keying material and echo the message back.
1619                  *
1620                  * NOTE: for SADB_DUMP, the function sadb_dump() did the
1621                  * work.  When DUMP reaches here, it should only be a base
1622                  * message.
1623                  */
1624         justecho:
1625                 if (ksi->ks_in_extv[SADB_EXT_KEY_AUTH] != NULL ||
1626                     ksi->ks_in_extv[SADB_EXT_KEY_ENCRYPT] != NULL ||
1627                     ksi->ks_in_extv[SADB_X_EXT_EDUMP] != NULL) {
1628                         sadb_strip(samsg);
1629                         /* Assume PF_KEY message is contiguous. */
1630                         ASSERT(mp->b_cont->b_cont == NULL);
1631                         oldend = mp->b_cont->b_wptr;
1632                         mp->b_cont->b_wptr = mp->b_cont->b_rptr +
1633                             SADB_64TO8(samsg->sadb_msg_len);
1634                         bzero(mp->b_cont->b_wptr, oldend - mp->b_cont->b_wptr);
1635                 }
1636                 break;
1637         case SADB_GET:
1638                 /*
1639                  * Do a lot of work here, because of the ipsa I just found.
1640                  * First construct the new PF_KEY message, then abandon
1641                  * the old one.
1642                  */
1643                 mp1 = sadb_sa2msg(ipsa, samsg);
1644                 if (mp1 == NULL) {
1645                         sadb_pfkey_error(pfkey_q, mp, ENOMEM,
1646                             SADB_X_DIAGNOSTIC_NONE, ksi->ks_in_serial);
1647                         return;
 
2350  */
2351 boolean_t
2352 sadb_match_query(ipsa_query_t *sq, ipsa_t *sa)
2353 {
2354         ipsa_match_fn_t *mfpp = &(sq->matchers[0]);
2355         ipsa_match_fn_t mfp;
2356 
2357         for (mfp = *mfpp++; mfp != NULL; mfp = *mfpp++) {
2358                 if (!mfp(sq, sa))
2359                         return (B_FALSE);
2360         }
2361         return (B_TRUE);
2362 }
2363 
2364 /*
2365  * Walker callback function to delete sa's based on src/dst address.
2366  * Assumes that we're called with *head locked, no other locks held;
2367  * Conveniently, and not coincidentally, this is both what sadb_walker
2368  * gives us and also what sadb_unlinkassoc expects.
2369  */
2370 struct sadb_purge_state
2371 {
2372         ipsa_query_t sq;
2373         boolean_t inbnd;
2374         uint8_t sadb_sa_state;
2375 };
2376 
2377 static void
2378 sadb_purge_cb(isaf_t *head, ipsa_t *entry, void *cookie)
2379 {
2380         struct sadb_purge_state *ps = (struct sadb_purge_state *)cookie;
2381 
2382         ASSERT(MUTEX_HELD(&head->isaf_lock));
2383 
2384         mutex_enter(&entry->ipsa_lock);
2385 
2386         if (entry->ipsa_state == IPSA_STATE_LARVAL ||
2387             !sadb_match_query(&ps->sq, entry)) {
2388                 mutex_exit(&entry->ipsa_lock);
2389                 return;
2390         }
2391 
2392         entry->ipsa_state = IPSA_STATE_DEAD;
2393         (void) sadb_torch_assoc(head, entry);
2394 }
2395 
2396 /*
2397  * Common code to purge an SA with a matching src or dst address.
2398  * Don't kill larval SA's in such a purge.
2399  */
2400 int
2401 sadb_purge_sa(mblk_t *mp, keysock_in_t *ksi, sadb_t *sp,
2402         int *diagnostic, queue_t *pfkey_q)
2403 {
2404         struct sadb_purge_state ps;
2405         int error = sadb_form_query(ksi, 0,
2406             IPSA_Q_SRC|IPSA_Q_DST|IPSA_Q_SRCID|IPSA_Q_DSTID|IPSA_Q_KMC,
2407             &ps.sq, diagnostic);
2408 
2409         if (error != 0)
2410                 return (error);
2411 
2412         /*
2413          * This is simple, crude, and effective.
2414          * Unimplemented optimizations (TBD):
2415          * - we can limit how many places we search based on where we
2416          * think the SA is filed.
2417          * - if we get a dst address, we can hash based on dst addr to find
2418          * the correct bucket in the outbound table.
2419          */
2420         ps.inbnd = B_TRUE;
2421         sadb_walker(sp->sdb_if, sp->sdb_hashsize, sadb_purge_cb, &ps);
2422         ps.inbnd = B_FALSE;
2423         sadb_walker(sp->sdb_of, sp->sdb_hashsize, sadb_purge_cb, &ps);
2424 
2425         ASSERT(mp->b_cont != NULL);
2426         sadb_pfkey_echo(pfkey_q, mp, (sadb_msg_t *)mp->b_cont->b_rptr, ksi,
2427             NULL);
2428         return (0);
2429 }
2430 
2431 static void
2432 sadb_delpair_state_one(isaf_t *head, ipsa_t *entry, void *cookie)
2433 {
2434         struct sadb_purge_state *ps = (struct sadb_purge_state *)cookie;
2435         isaf_t  *inbound_bucket;
2436         ipsa_t *peer_assoc;
2437         ipsa_query_t *sq = &ps->sq;
2438 
2439         ASSERT(MUTEX_HELD(&head->isaf_lock));
2440 
2441         mutex_enter(&entry->ipsa_lock);
2442 
2443         if ((entry->ipsa_state != ps->sadb_sa_state) ||
2444             ((sq->srcaddr != NULL) &&
2445             !IPSA_ARE_ADDR_EQUAL(entry->ipsa_srcaddr, sq->srcaddr, sq->af))) {
2446                 mutex_exit(&entry->ipsa_lock);
2447                 return;
2448         }
2449 
2450         /*
2451          * The isaf_t *, which is passed in , is always an outbound bucket,
2452          * and we are preserving the outbound-then-inbound hash-bucket lock
2453          * ordering. The sadb_walker() which triggers this function is called
2454          * only on the outbound fanout, and the corresponding inbound bucket
2455          * lock is safe to acquire here.
2456          */
2457 
2458         if (entry->ipsa_haspeer) {
2459                 inbound_bucket = INBOUND_BUCKET(sq->sp, entry->ipsa_spi);
2460                 mutex_enter(&inbound_bucket->isaf_lock);
2461                 peer_assoc = ipsec_getassocbyspi(inbound_bucket,
2462                     entry->ipsa_spi, entry->ipsa_srcaddr,
2463                     entry->ipsa_dstaddr, entry->ipsa_addrfam);
2464         } else {
2465                 inbound_bucket = INBOUND_BUCKET(sq->sp, entry->ipsa_otherspi);
2466                 mutex_enter(&inbound_bucket->isaf_lock);
2467                 peer_assoc = ipsec_getassocbyspi(inbound_bucket,
2468                     entry->ipsa_otherspi, entry->ipsa_dstaddr,
2469                     entry->ipsa_srcaddr, entry->ipsa_addrfam);
2470         }
2471 
2472         entry->ipsa_state = IPSA_STATE_DEAD;
2473         (void) sadb_torch_assoc(head, entry);
2474         if (peer_assoc != NULL) {
2475                 mutex_enter(&peer_assoc->ipsa_lock);
2476                 peer_assoc->ipsa_state = IPSA_STATE_DEAD;
2477                 (void) sadb_torch_assoc(inbound_bucket, peer_assoc);
2478         }
2479         mutex_exit(&inbound_bucket->isaf_lock);
2480 }
2481 
2482 static int
2483 sadb_delpair_state(mblk_t *mp, keysock_in_t *ksi, sadbp_t *spp,
2484     int *diagnostic, queue_t *pfkey_q)
2485 {
2486         sadb_sa_t *assoc = (sadb_sa_t *)ksi->ks_in_extv[SADB_EXT_SA];
2487         struct sadb_purge_state ps;
2488         int error;
2489 
2490         ps.sq.spp = spp;                /* XXX param */
2491 
2492         error = sadb_form_query(ksi, IPSA_Q_DST|IPSA_Q_SRC,
2493             IPSA_Q_SRC|IPSA_Q_DST|IPSA_Q_SRCID|IPSA_Q_DSTID|IPSA_Q_KMC,
2494             &ps.sq, diagnostic);
2495         if (error != 0)
2496                 return (error);
2497 
2498         ps.inbnd = B_FALSE;
2499         ps.sadb_sa_state = assoc->sadb_sa_state;
2500         sadb_walker(ps.sq.sp->sdb_of, ps.sq.sp->sdb_hashsize,
2501             sadb_delpair_state_one, &ps);
2502 
2503         ASSERT(mp->b_cont != NULL);
2504         sadb_pfkey_echo(pfkey_q, mp, (sadb_msg_t *)mp->b_cont->b_rptr,
2505             ksi, NULL);
2506         return (0);
2507 }
2508 
2509 /*
2510  * Common code to delete/get an SA.
2511  */
2512 int
2513 sadb_delget_sa(mblk_t *mp, keysock_in_t *ksi, sadbp_t *spp,
2514     int *diagnostic, queue_t *pfkey_q, uint8_t sadb_msg_type)
2515 {
2516         ipsa_query_t sq;
2517         ipsa_t *echo_target = NULL;
2518         ipsap_t ipsapp;
2519         uint_t  error = 0;
2520 
2521         if (sadb_msg_type == SADB_X_DELPAIR_STATE)
2522                 return (sadb_delpair_state(mp, ksi, spp, diagnostic, pfkey_q));
2523 
2524         sq.spp = spp;           /* XXX param */
2525         error = sadb_form_query(ksi, IPSA_Q_DST|IPSA_Q_SA,
2526             IPSA_Q_SRC|IPSA_Q_DST|IPSA_Q_SA|IPSA_Q_INBOUND|IPSA_Q_OUTBOUND,
2527             &sq, diagnostic);
2528         if (error != 0)
2529                 return (error);
2530 
2531         error = get_ipsa_pair(&sq, &ipsapp, diagnostic);
2532         if (error != 0) {
2533                 return (error);
2534         }
2535 
2536         echo_target = ipsapp.ipsap_sa_ptr;
2537         if (echo_target == NULL)
2538                 echo_target = ipsapp.ipsap_psa_ptr;
2539 
2540         if (sadb_msg_type == SADB_DELETE || sadb_msg_type == SADB_X_DELPAIR) {
2541                 /*
2542                  * Bucket locks will be required if SA is actually unlinked.
2543                  * get_ipsa_pair() returns valid hash bucket pointers even
 
3026                 newbie->ipsa_unique_mask = SA_UNIQUE_MASK(isrc->sin_port,
3027                     idst->sin_port, dstext->sadb_address_proto,
3028                     idstext->sadb_address_proto);
3029         } else {
3030                 /* ... and outer-ports for Transport Mode. */
3031                 newbie->ipsa_unique_id = SA_UNIQUE_ID(src->sin_port,
3032                     dst->sin_port, dstext->sadb_address_proto, 0);
3033                 newbie->ipsa_unique_mask = SA_UNIQUE_MASK(src->sin_port,
3034                     dst->sin_port, dstext->sadb_address_proto, 0);
3035         }
3036         if (newbie->ipsa_unique_mask != (uint64_t)0)
3037                 newbie->ipsa_flags |= IPSA_F_UNIQUE;
3038 
3039         sadb_nat_calculations(newbie,
3040             (sadb_address_t *)ksi->ks_in_extv[SADB_X_EXT_ADDRESS_NATT_LOC],
3041             (sadb_address_t *)ksi->ks_in_extv[SADB_X_EXT_ADDRESS_NATT_REM],
3042             src_addr_ptr, dst_addr_ptr);
3043 
3044         newbie->ipsa_type = samsg->sadb_msg_satype;
3045 
3046         ASSERT((assoc->sadb_sa_state == SADB_SASTATE_MATURE) ||
3047             (assoc->sadb_sa_state == SADB_X_SASTATE_ACTIVE_ELSEWHERE));
3048         newbie->ipsa_auth_alg = assoc->sadb_sa_auth;
3049         newbie->ipsa_encr_alg = assoc->sadb_sa_encrypt;
3050 
3051         newbie->ipsa_flags |= assoc->sadb_sa_flags;
3052         if (newbie->ipsa_flags & SADB_X_SAFLAGS_NATT_LOC &&
3053             ksi->ks_in_extv[SADB_X_EXT_ADDRESS_NATT_LOC] == NULL) {
3054                 mutex_exit(&newbie->ipsa_lock);
3055                 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_NATT_LOC;
3056                 error = EINVAL;
3057                 goto error;
3058         }
3059         if (newbie->ipsa_flags & SADB_X_SAFLAGS_NATT_REM &&
3060             ksi->ks_in_extv[SADB_X_EXT_ADDRESS_NATT_REM] == NULL) {
3061                 mutex_exit(&newbie->ipsa_lock);
3062                 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_NATT_REM;
3063                 error = EINVAL;
3064                 goto error;
3065         }
3066         if (newbie->ipsa_flags & SADB_X_SAFLAGS_TUNNEL &&
3067             ksi->ks_in_extv[SADB_X_EXT_ADDRESS_INNER_SRC] == NULL) {
 
3934                 return (B_TRUE);
3935         }
3936         return (B_FALSE);
3937 }
3938 
3939 /*
3940  * Return "assoc" if haspeer is true and I send an expire.  This allows
3941  * the consumers' aging functions to tidy up an expired SA's peer.
3942  */
3943 static ipsa_t *
3944 sadb_age_assoc(isaf_t *head, queue_t *pfkey_q, ipsa_t *assoc,
3945     time_t current, int reap_delay, boolean_t inbound)
3946 {
3947         ipsa_t *retval = NULL;
3948         boolean_t dropped_mutex = B_FALSE;
3949 
3950         ASSERT(MUTEX_HELD(&head->isaf_lock));
3951 
3952         mutex_enter(&assoc->ipsa_lock);
3953 
3954         if (((assoc->ipsa_state == IPSA_STATE_LARVAL) ||
3955             ((assoc->ipsa_state == IPSA_STATE_IDLE) ||
3956             (assoc->ipsa_state == IPSA_STATE_ACTIVE_ELSEWHERE) &&
3957             (assoc->ipsa_hardexpiretime != 0))) &&
3958             (assoc->ipsa_hardexpiretime <= current)) {
3959                 assoc->ipsa_state = IPSA_STATE_DEAD;
3960                 return (sadb_torch_assoc(head, assoc));
3961         }
3962 
3963         /*
3964          * Check lifetimes.  Fortunately, SA setup is done
3965          * such that there are only two times to look at,
3966          * softexpiretime, and hardexpiretime.
3967          *
3968          * Check hard first.
3969          */
3970 
3971         if (assoc->ipsa_hardexpiretime != 0 &&
3972             assoc->ipsa_hardexpiretime <= current) {
3973                 if (assoc->ipsa_state == IPSA_STATE_DEAD)
3974                         return (sadb_torch_assoc(head, assoc));
3975 
3976                 /*
3977                  * Send SADB_EXPIRE with hard lifetime, delay for unlinking.
3978                  */
 
4003                 assoc->ipsa_state = IPSA_STATE_DYING;
4004                 if (assoc->ipsa_haspeer) {
4005                         /*
4006                          * If the SA has a peer, update the peer's state
4007                          * on SOFT_EXPIRE, this is mostly to prevent two
4008                          * expire messages from effectively the same SA.
4009                          *
4010                          * Don't care about paired SA's, then can (and should)
4011                          * be able to soft expire at different times.
4012                          *
4013                          * If I return assoc, I have to bump up its
4014                          * reference count to keep with the ipsa_t reference
4015                          * count semantics.
4016                          */
4017                         IPSA_REFHOLD(assoc);
4018                         retval = assoc;
4019                 }
4020                 sadb_expire_assoc(pfkey_q, assoc);
4021         } else if (assoc->ipsa_idletime != 0 &&
4022             assoc->ipsa_idleexpiretime <= current) {
4023                 if (assoc->ipsa_state == IPSA_STATE_ACTIVE_ELSEWHERE) {
4024                         assoc->ipsa_state = IPSA_STATE_IDLE;
4025                 }
4026 
4027                 /*
4028                  * Need to handle Mature case
4029                  */
4030                 if (assoc->ipsa_state == IPSA_STATE_MATURE) {
4031                         sadb_expire_assoc(pfkey_q, assoc);
4032                 }
4033         } else {
4034                 /* Check idle time activities. */
4035                 dropped_mutex = sadb_idle_activities(assoc,
4036                     current - assoc->ipsa_lastuse, inbound);
4037         }
4038 
4039         if (!dropped_mutex)
4040                 mutex_exit(&assoc->ipsa_lock);
4041         return (retval);
4042 }
4043 
4044 /*
4045  * Called by a consumer protocol to do ther dirty work of reaping dead
4046  * Security Associations.
4047  *
4048  * NOTE: sadb_age_assoc() marks expired SA's as DEAD but only removed
4049  * SA's that are already marked DEAD, so expired SA's are only reaped
 
4304                         assoc->ipsa_idleexpiretime =
4305                             current + idle->sadb_lifetime_addtime;
4306                         assoc->ipsa_idletime = idle->sadb_lifetime_addtime;
4307                 }
4308                 if (assoc->ipsa_idleuselt != 0) {
4309                         if (assoc->ipsa_idletime != 0) {
4310                                 assoc->ipsa_idletime = min(assoc->ipsa_idletime,
4311                                     assoc->ipsa_idleuselt);
4312                         assoc->ipsa_idleexpiretime =
4313                             current + assoc->ipsa_idletime;
4314                         } else {
4315                                 assoc->ipsa_idleexpiretime =
4316                                     current + assoc->ipsa_idleuselt;
4317                                 assoc->ipsa_idletime = assoc->ipsa_idleuselt;
4318                         }
4319                 }
4320         }
4321         mutex_exit(&assoc->ipsa_lock);
4322 }
4323 
4324 static int
4325 sadb_update_state(ipsa_t *assoc, uint_t new_state, mblk_t **ipkt_lst)
4326 {
4327         int rcode = 0;
4328         time_t current = gethrestime_sec();
4329 
4330         mutex_enter(&assoc->ipsa_lock);
4331 
4332         switch (new_state) {
4333         case SADB_X_SASTATE_ACTIVE_ELSEWHERE:
4334                 if (assoc->ipsa_state == SADB_X_SASTATE_IDLE) {
4335                         assoc->ipsa_state = IPSA_STATE_ACTIVE_ELSEWHERE;
4336                         assoc->ipsa_idleexpiretime =
4337                             current + assoc->ipsa_idletime;
4338                 }
4339                 break;
4340         case SADB_X_SASTATE_IDLE:
4341                 if (assoc->ipsa_state == SADB_X_SASTATE_ACTIVE_ELSEWHERE) {
4342                         assoc->ipsa_state = IPSA_STATE_IDLE;
4343                         assoc->ipsa_idleexpiretime =
4344                             current + assoc->ipsa_idletime;
4345                 } else {
4346                         rcode = EINVAL;
4347                 }
4348                 break;
4349 
4350         case SADB_X_SASTATE_ACTIVE:
4351                 if (assoc->ipsa_state != SADB_X_SASTATE_IDLE) {
4352                         rcode = EINVAL;
4353                         break;
4354                 }
4355                 assoc->ipsa_state = IPSA_STATE_MATURE;
4356                 assoc->ipsa_idleexpiretime = current + assoc->ipsa_idletime;
4357 
4358                 if (ipkt_lst == NULL) {
4359                         break;
4360                 }
4361 
4362                 if (assoc->ipsa_bpkt_head != NULL) {
4363                         *ipkt_lst = assoc->ipsa_bpkt_head;
4364                         assoc->ipsa_bpkt_head = assoc->ipsa_bpkt_tail = NULL;
4365                         assoc->ipsa_mblkcnt = 0;
4366                 } else {
4367                         *ipkt_lst = NULL;
4368                 }
4369                 break;
4370         default:
4371                 rcode = EINVAL;
4372                 break;
4373         }
4374 
4375         mutex_exit(&assoc->ipsa_lock);
4376         return (rcode);
4377 }
4378 
4379 /*
4380  * Check a proposed KMC update for sanity.
4381  */
4382 static int
4383 sadb_check_kmc(ipsa_query_t *sq, ipsa_t *sa, int *diagnostic)
4384 {
4385         uint32_t kmp = sq->kmp;
4386         uint32_t kmc = sq->kmc;
4387 
4388         if (sa == NULL)
4389                 return (0);
4390 
4391         if (sa->ipsa_state == IPSA_STATE_DEAD)
4392                 return (ESRCH); /* DEAD == Not there, in this case. */
4393 
4394         if ((kmp != 0) && ((sa->ipsa_kmp != 0) || (sa->ipsa_kmp != kmp))) {
4395                 *diagnostic = SADB_X_DIAGNOSTIC_DUPLICATE_KMP;
4396                 return (EINVAL);
4397         }
4398 
 
4407 /*
4408  * Actually update the KMC info.
4409  */
4410 static void
4411 sadb_update_kmc(ipsa_query_t *sq, ipsa_t *sa)
4412 {
4413         uint32_t kmp = sq->kmp;
4414         uint32_t kmc = sq->kmc;
4415 
4416         if (kmp != 0)
4417                 sa->ipsa_kmp = kmp;
4418         if (kmc != 0)
4419                 sa->ipsa_kmc = kmc;
4420 }
4421 
4422 /*
4423  * Common code to update an SA.
4424  */
4425 
4426 int
4427 sadb_update_sa(mblk_t *mp, keysock_in_t *ksi, mblk_t **ipkt_lst,
4428     sadbp_t *spp, int *diagnostic, queue_t *pfkey_q,
4429     int (*add_sa_func)(mblk_t *, keysock_in_t *, int *, netstack_t *),
4430     netstack_t *ns, uint8_t sadb_msg_type)
4431 {
4432         sadb_key_t *akey = (sadb_key_t *)ksi->ks_in_extv[SADB_EXT_KEY_AUTH];
4433         sadb_key_t *ekey = (sadb_key_t *)ksi->ks_in_extv[SADB_EXT_KEY_ENCRYPT];
4434         sadb_x_replay_ctr_t *replext =
4435             (sadb_x_replay_ctr_t *)ksi->ks_in_extv[SADB_X_EXT_REPLAY_VALUE];
4436         sadb_lifetime_t *soft =
4437             (sadb_lifetime_t *)ksi->ks_in_extv[SADB_EXT_LIFETIME_SOFT];
4438         sadb_lifetime_t *hard =
4439             (sadb_lifetime_t *)ksi->ks_in_extv[SADB_EXT_LIFETIME_HARD];
4440         sadb_lifetime_t *idle =
4441             (sadb_lifetime_t *)ksi->ks_in_extv[SADB_X_EXT_LIFETIME_IDLE];
4442         sadb_x_pair_t *pair_ext =
4443             (sadb_x_pair_t *)ksi->ks_in_extv[SADB_X_EXT_PAIR];
4444         ipsa_t *echo_target = NULL;
4445         ipsap_t ipsapp;
4446         ipsa_query_t sq;
4447         time_t current = gethrestime_sec();
4448 
4449         sq.spp = spp;           /* XXX param */
4450         int error = sadb_form_query(ksi, IPSA_Q_SRC|IPSA_Q_DST|IPSA_Q_SA,
4451             IPSA_Q_SRC|IPSA_Q_DST|IPSA_Q_SA|IPSA_Q_INBOUND|IPSA_Q_OUTBOUND,
4452             &sq, diagnostic);
4453 
4454         if (error != 0)
4455                 return (error);
4456 
4457         error = get_ipsa_pair(&sq, &ipsapp, diagnostic);
4458         if (error != 0)
4459                 return (error);
4460 
4461         if (ipsapp.ipsap_psa_ptr == NULL && ipsapp.ipsap_sa_ptr != NULL) {
4462                 if (ipsapp.ipsap_sa_ptr->ipsa_state == IPSA_STATE_LARVAL) {
4463                         /*
4464                          * REFRELE the target and let the add_sa_func()
4465                          * deal with updating a larval SA.
4466                          */
4467                         destroy_ipsa_pair(&ipsapp);
4468                         return (add_sa_func(mp, ksi, diagnostic, ns));
4469                 }
4470         }
4471 
4472         /*
4473          * At this point we have an UPDATE to a MATURE SA. There should
4474          * not be any keying material present.
4475          */
4476         if (akey != NULL) {
4477                 *diagnostic = SADB_X_DIAGNOSTIC_AKEY_PRESENT;
4478                 error = EINVAL;
4479                 goto bail;
4480         }
4481         if (ekey != NULL) {
4482                 *diagnostic = SADB_X_DIAGNOSTIC_EKEY_PRESENT;
4483                 error = EINVAL;
4484                 goto bail;
4485         }
4486 
4487         if (sq.assoc->sadb_sa_state == SADB_X_SASTATE_ACTIVE_ELSEWHERE) {
4488                 if (ipsapp.ipsap_sa_ptr != NULL &&
4489                     ipsapp.ipsap_sa_ptr->ipsa_state == IPSA_STATE_IDLE) {
4490                         if ((error = sadb_update_state(ipsapp.ipsap_sa_ptr,
4491                             sq.assoc->sadb_sa_state, NULL)) != 0) {
4492                                 *diagnostic = SADB_X_DIAGNOSTIC_BAD_SASTATE;
4493                                 goto bail;
4494                         }
4495                 }
4496                 if (ipsapp.ipsap_psa_ptr != NULL &&
4497                     ipsapp.ipsap_psa_ptr->ipsa_state == IPSA_STATE_IDLE) {
4498                         if ((error = sadb_update_state(ipsapp.ipsap_psa_ptr,
4499                             sq.assoc->sadb_sa_state, NULL)) != 0) {
4500                                 *diagnostic = SADB_X_DIAGNOSTIC_BAD_SASTATE;
4501                                 goto bail;
4502                         }
4503                 }
4504         }
4505         if (sq.assoc->sadb_sa_state == SADB_X_SASTATE_ACTIVE) {
4506                 if (ipsapp.ipsap_sa_ptr != NULL) {
4507                         error = sadb_update_state(ipsapp.ipsap_sa_ptr,
4508                             sq.assoc->sadb_sa_state,
4509                             (ipsapp.ipsap_sa_ptr->ipsa_flags &
4510                             IPSA_F_INBOUND) ? ipkt_lst : NULL);
4511                         if (error) {
4512                                 *diagnostic = SADB_X_DIAGNOSTIC_BAD_SASTATE;
4513                                 goto bail;
4514                         }
4515                 }
4516                 if (ipsapp.ipsap_psa_ptr != NULL) {
4517                         error = sadb_update_state(ipsapp.ipsap_psa_ptr,
4518                             sq.assoc->sadb_sa_state,
4519                             (ipsapp.ipsap_psa_ptr->ipsa_flags &
4520                             IPSA_F_INBOUND) ? ipkt_lst : NULL);
4521                         if (error) {
4522                                 *diagnostic = SADB_X_DIAGNOSTIC_BAD_SASTATE;
4523                                 goto bail;
4524                         }
4525                 }
4526                 sadb_pfkey_echo(pfkey_q, mp, (sadb_msg_t *)mp->b_cont->b_rptr,
4527                     ksi, echo_target);
4528                 goto bail;
4529         }
4530 
4531         /*
4532          * Reality checks for updates of active associations.
4533          * Sundry first-pass UPDATE-specific reality checks.
4534          * Have to do the checks here, because it's after the add_sa code.
4535          * XXX STATS : logging/stats here?
4536          */
4537 
4538         if (!((sq.assoc->sadb_sa_state == SADB_SASTATE_MATURE) ||
4539             (sq.assoc->sadb_sa_state == SADB_X_SASTATE_ACTIVE_ELSEWHERE))) {
4540                 *diagnostic = SADB_X_DIAGNOSTIC_BAD_SASTATE;
4541                 error = EINVAL;
4542                 goto bail;
4543         }
4544         if (sq.assoc->sadb_sa_flags & ~spp->s_updateflags) {
4545                 *diagnostic = SADB_X_DIAGNOSTIC_BAD_SAFLAGS;
4546                 error = EINVAL;
4547                 goto bail;
4548         }
4549         if (ksi->ks_in_extv[SADB_EXT_LIFETIME_CURRENT] != NULL) {
4550                 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_LIFETIME;
4551                 error = EOPNOTSUPP;
4552                 goto bail;
4553         }
4554 
4555         if ((*diagnostic = sadb_hardsoftchk(hard, soft, idle)) != 0) {
4556                 error = EINVAL;
4557                 goto bail;
4558         }
4559 
4560         if ((*diagnostic = sadb_labelchk(ksi)) != 0)
4561                 return (EINVAL);
4562 
4563         error = sadb_check_kmc(&sq, ipsapp.ipsap_sa_ptr, diagnostic);
4564         if (error != 0)
4565                 goto bail;
4566 
4567         error = sadb_check_kmc(&sq, ipsapp.ipsap_psa_ptr, diagnostic);
4568         if (error != 0)
4569                 goto bail;
4570 
4571 
4572         if (ipsapp.ipsap_sa_ptr != NULL) {
4573                 /*
4574                  * Do not allow replay value change for MATURE or LARVAL SA.
4575                  */
4576 
4577                 if ((replext != NULL) &&
4578                     ((ipsapp.ipsap_sa_ptr->ipsa_state == IPSA_STATE_LARVAL) ||
4579                     (ipsapp.ipsap_sa_ptr->ipsa_state == IPSA_STATE_MATURE))) {
4580                         *diagnostic = SADB_X_DIAGNOSTIC_BAD_SASTATE;
4581                         error = EINVAL;
4582                         goto bail;
4583                 }
4584         }
4585 
4586 
4587         if (ipsapp.ipsap_sa_ptr != NULL) {
4588                 sadb_update_lifetimes(ipsapp.ipsap_sa_ptr, hard, soft,
4589                     idle, B_TRUE);
4590                 sadb_update_kmc(&sq, ipsapp.ipsap_sa_ptr);
4591                 if ((replext != NULL) &&
4592                     (ipsapp.ipsap_sa_ptr->ipsa_replay_wsize != 0)) {
4593                         /*
4594                          * If an inbound SA, update the replay counter
4595                          * and check off all the other sequence number
4596                          */
4597                         if (ksi->ks_in_dsttype == KS_IN_ADDR_ME) {
4598                                 if (!sadb_replay_check(ipsapp.ipsap_sa_ptr,
4599                                     replext->sadb_x_rc_replay32)) {
4600                                         *diagnostic =
4601                                             SADB_X_DIAGNOSTIC_INVALID_REPLAY;
4602                                         error = EINVAL;
4603                                         goto bail;
4604                                 }
4605                                 mutex_enter(&ipsapp.ipsap_sa_ptr->ipsa_lock);
4606                                 ipsapp.ipsap_sa_ptr->ipsa_idleexpiretime =
4607                                     current +
4608                                     ipsapp.ipsap_sa_ptr->ipsa_idletime;
4609                                 mutex_exit(&ipsapp.ipsap_sa_ptr->ipsa_lock);
4610                         } else {
4611                                 mutex_enter(&ipsapp.ipsap_sa_ptr->ipsa_lock);
4612                                 ipsapp.ipsap_sa_ptr->ipsa_replay =
4613                                     replext->sadb_x_rc_replay32;
4614                                 ipsapp.ipsap_sa_ptr->ipsa_idleexpiretime =
4615                                     current +
4616                                     ipsapp.ipsap_sa_ptr->ipsa_idletime;
4617                                 mutex_exit(&ipsapp.ipsap_sa_ptr->ipsa_lock);
4618                         }
4619                 }
4620         }
4621 
4622         if (sadb_msg_type == SADB_X_UPDATEPAIR) {
4623                 if (ipsapp.ipsap_psa_ptr != NULL) {
4624                         sadb_update_lifetimes(ipsapp.ipsap_psa_ptr, hard, soft,
4625                             idle, B_FALSE);
4626                         sadb_update_kmc(&sq, ipsapp.ipsap_psa_ptr);
4627                 } else {
4628                         *diagnostic = SADB_X_DIAGNOSTIC_PAIR_SA_NOTFOUND;
4629                         error = ESRCH;
4630                         goto bail;
4631                 }
4632         }
4633 
4634         if (pair_ext != NULL)
4635                 error = update_pairing(&ipsapp, &sq, ksi, diagnostic);
4636 
4637         if (error == 0)
4638                 sadb_pfkey_echo(pfkey_q, mp, (sadb_msg_t *)mp->b_cont->b_rptr,
4639                     ksi, echo_target);
4640 bail:
 
5804         /* XXXMLS Insert sensitivity information here. */
5805 
5806         if (cur != NULL)
5807                 samsg->sadb_msg_len = SADB_8TO64(cur - msgmp->b_rptr);
5808         else
5809                 mutex_exit(&ipss->ipsec_alg_lock);
5810 
5811         return (pfkeymp);
5812 }
5813 
5814 /*
5815  * Given an SADB_GETSPI message, find an appropriately ranged SA and
5816  * allocate an SA.  If there are message improprieties, return (ipsa_t *)-1.
5817  * If there was a memory allocation error, return NULL.  (Assume NULL !=
5818  * (ipsa_t *)-1).
5819  *
5820  * master_spi is passed in host order.
5821  */
5822 ipsa_t *
5823 sadb_getspi(keysock_in_t *ksi, uint32_t master_spi, int *diagnostic,
5824     netstack_t *ns, uint_t sa_type)
5825 {
5826         sadb_address_t *src =
5827             (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_SRC],
5828             *dst = (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_DST];
5829         sadb_spirange_t *range =
5830             (sadb_spirange_t *)ksi->ks_in_extv[SADB_EXT_SPIRANGE];
5831         struct sockaddr_in *ssa, *dsa;
5832         struct sockaddr_in6 *ssa6, *dsa6;
5833         uint32_t *srcaddr, *dstaddr;
5834         sa_family_t af;
5835         uint32_t add, min, max;
5836 
5837         if (src == NULL) {
5838                 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_SRC;
5839                 return ((ipsa_t *)-1);
5840         }
5841         if (dst == NULL) {
5842                 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_DST;
5843                 return ((ipsa_t *)-1);
5844         }
 
6887         return (npkt);
6888 }
6889 
6890 /*
6891  * sadb_clear_lpkt: Atomically clear ipsa->ipsa_lpkt and return the
6892  * previous value.
6893  */
6894 mblk_t *
6895 sadb_clear_lpkt(ipsa_t *ipsa)
6896 {
6897         mblk_t *opkt;
6898 
6899         mutex_enter(&ipsa->ipsa_lock);
6900         opkt = ipsa->ipsa_lpkt;
6901         ipsa->ipsa_lpkt = NULL;
6902         mutex_exit(&ipsa->ipsa_lock);
6903         return (opkt);
6904 }
6905 
6906 /*
6907  * Buffer a packet that's in IDLE state as set by Solaris Clustering.
6908  */
6909 void
6910 sadb_buf_pkt(ipsa_t *ipsa, mblk_t *bpkt, ip_recv_attr_t *ira)
6911 {
6912         netstack_t      *ns = ira->ira_ill->ill_ipst->ips_netstack;
6913         ipsec_stack_t   *ipss = ns->netstack_ipsec;
6914 
6915         ASSERT(ipsa->ipsa_state == IPSA_STATE_IDLE);
6916 
6917         ip_drop_packet(bpkt, B_TRUE, ira->ira_ill,
6918             DROPPER(ipss, ipds_sadb_inidle_overflow),
6919             &ipss->ipsec_sadb_dropper);
6920         return;
6921 }
6922 
6923 /*
6924  * Stub function that taskq_dispatch() invokes to take the mblk (in arg)
6925  * and put into STREAMS again.
6926  */
6927 void
6928 sadb_clear_buf_pkt(void *ipkt)
6929 {
6930         mblk_t  *tmp, *buf_pkt;
6931         ip_recv_attr_t  iras;
6932 
6933         buf_pkt = (mblk_t *)ipkt;
6934 
6935         while (buf_pkt != NULL) {
6936                 mblk_t *data_mp;
6937 
6938                 tmp = buf_pkt->b_next;
6939                 buf_pkt->b_next = NULL;
6940 
6941                 data_mp = buf_pkt->b_cont;
6942                 buf_pkt->b_cont = NULL;
6943                 if (!ip_recv_attr_from_mblk(buf_pkt, &iras)) {
6944                         /* The ill or ip_stack_t disappeared on us. */
6945                         ip_drop_input("ip_recv_attr_from_mblk", data_mp, NULL);
6946                         freemsg(data_mp);
6947                 } else {
6948                         ip_input_post_ipsec(data_mp, &iras);
6949                 }
6950                 ira_cleanup(&iras, B_TRUE);
6951                 buf_pkt = tmp;
6952         }
6953 }
6954 /*
6955  * Walker callback used by sadb_alg_update() to free/create crypto
6956  * context template when a crypto software provider is removed or
6957  * added.
6958  */
6959 
6960 struct sadb_update_alg_state {
6961         ipsec_algtype_t alg_type;
6962         uint8_t alg_id;
6963         boolean_t is_added;
6964         boolean_t async_auth;
6965         boolean_t async_encr;
6966 };
6967 
6968 static void
6969 sadb_alg_update_cb(isaf_t *head, ipsa_t *entry, void *cookie)
6970 {
6971         struct sadb_update_alg_state *update_state =
6972             (struct sadb_update_alg_state *)cookie;
6973         crypto_ctx_template_t *ctx_tmpl = NULL;
6974 
 
 | 
 
 
 560 
 561         mp = allocb(sizeof (ipsec_info_t), BPRI_HI);
 562         if (mp != NULL) {
 563                 mp->b_datap->db_type = M_CTL;
 564                 mp->b_wptr += sizeof (ipsec_info_t);
 565                 kso = (keysock_out_t *)mp->b_rptr;
 566                 kso->ks_out_type = KEYSOCK_OUT;
 567                 kso->ks_out_len = sizeof (*kso);
 568                 kso->ks_out_serial = serial;
 569         }
 570 
 571         return (mp);
 572 }
 573 
 574 /*
 575  * Perform an SADB_DUMP, spewing out every SA in an array of SA fanouts
 576  * to keysock.
 577  */
 578 static int
 579 sadb_dump_fanout(queue_t *pfkey_q, mblk_t *mp, minor_t serial, isaf_t *fanout,
 580     int num_entries, boolean_t do_peers)
 581 {
 582         int i, error = 0;
 583         mblk_t *original_answer;
 584         ipsa_t *walker;
 585         sadb_msg_t *samsg;
 586 
 587         /*
 588          * For each IPSA hash bucket do:
 589          *      - Hold the mutex
 590          *      - Walk each entry, doing an sadb_dump_deliver() on it.
 591          */
 592         ASSERT(mp->b_cont != NULL);
 593         samsg = (sadb_msg_t *)mp->b_cont->b_rptr;
 594 
 595         original_answer = sadb_keysock_out(serial);
 596         if (original_answer == NULL)
 597                 return (ENOMEM);
 598 
 599         for (i = 0; i < num_entries; i++) {
 600                 mutex_enter(&fanout[i].isaf_lock);
 601                 for (walker = fanout[i].isaf_ipsa; walker != NULL;
 602                     walker = walker->ipsa_next) {
 603                         if (!do_peers && walker->ipsa_haspeer)
 604                                 continue;
 605                         error = sadb_dump_deliver(pfkey_q, original_answer,
 606                             walker, samsg);
 607                         if (error == ENOBUFS) {
 608                                 mblk_t *new_original_answer;
 609 
 610                                 /* Ran out of dupb's.  Try a copyb. */
 611                                 new_original_answer = copyb(original_answer);
 612                                 if (new_original_answer == NULL) {
 613                                         error = ENOMEM;
 614                                 } else {
 615                                         freeb(original_answer);
 616                                         original_answer = new_original_answer;
 617                                         error = sadb_dump_deliver(pfkey_q,
 618                                             original_answer, walker, samsg);
 619                                 }
 620                         }
 621                         if (error != 0)
 622                                 break;  /* out of for loop. */
 623                 }
 624                 mutex_exit(&fanout[i].isaf_lock);
 625                 if (error != 0)
 626                         break;  /* out of for loop. */
 627         }
 628 
 629         freeb(original_answer);
 630         return (error);
 631 }
 632 
 633 /*
 634  * Dump an entire SADB; outbound first, then inbound.
 635  */
 636 
 637 int
 638 sadb_dump(queue_t *pfkey_q, mblk_t *mp, keysock_in_t *ksi, sadb_t *sp)
 639 {
 640         int error;
 641 
 642         /* Dump outbound */
 643         error = sadb_dump_fanout(pfkey_q, mp, ksi->ks_in_serial, sp->sdb_of,
 644             sp->sdb_hashsize, B_TRUE);
 645         if (error)
 646                 return (error);
 647 
 648         /* Dump inbound */
 649         return (sadb_dump_fanout(pfkey_q, mp, ksi->ks_in_serial, sp->sdb_if,
 650             sp->sdb_hashsize, B_FALSE));
 651 }
 652 
 653 /*
 654  * Generic sadb table walker.
 655  *
 656  * Call "walkfn" for each SA in each bucket in "table"; pass the
 657  * bucket, the entry and "cookie" to the callback function.
 658  * Take care to ensure that walkfn can delete the SA without screwing
 659  * up our traverse.
 660  *
 661  * The bucket is locked for the duration of the callback, both so that the
 662  * callback can just call sadb_unlinkassoc() when it wants to delete something,
 663  * and so that no new entries are added while we're walking the list.
 664  */
 665 static void
 666 sadb_walker(isaf_t *table, uint_t numentries,
 667     void (*walkfn)(isaf_t *head, ipsa_t *entry, void *cookie),
 668     void *cookie)
 669 {
 670         int i;
 671         for (i = 0; i < numentries; i++) {
 672                 ipsa_t *entry, *next;
 673 
 674                 mutex_enter(&table[i].isaf_lock);
 675 
 676                 for (entry = table[i].isaf_ipsa; entry != NULL;
 677                     entry = next) {
 678                         next = entry->ipsa_next;
 679                         (*walkfn)(&table[i], entry, cookie);
 680                 }
 681                 mutex_exit(&table[i].isaf_lock);
 682         }
 683 }
 684 
 685 /*
 686  * Call me to free up a security association fanout.  Use the forever
 687  * variable to indicate freeing up the SAs (forever == B_FALSE, e.g.
 688  * an SADB_FLUSH message), or destroying everything (forever == B_TRUE,
 689  * when a netstack is destroyed or a module is unloaded).
 690  */
 691 static void
 692 sadb_destroyer(isaf_t **tablep, uint_t numentries, boolean_t forever)
 693 {
 694         int i;
 695         isaf_t *table = *tablep;
 696         ipsa_t *sa;
 697 
 698         if (table == NULL)
 699                 return;
 700 
 701         for (i = 0; i < numentries; i++) {
 702                 mutex_enter(&table[i].isaf_lock);
 703                 while ((sa = table[i].isaf_ipsa) != NULL) {
 704                         sadb_unlinkassoc(sa);
 705                 }
 706                 table[i].isaf_gen++;
 707                 mutex_exit(&table[i].isaf_lock);
 708                 if (forever)
 709                         mutex_destroy(&(table[i].isaf_lock));
 710         }
 711 
 712         if (forever) {
 713                 *tablep = NULL;
 714                 kmem_free(table, numentries * sizeof (*table));
 715         }
 716 }
 717 
 718 /*
 719  * Entry points to sadb_destroyer().
 720  */
 721 static void
 722 sadb_flush(sadb_t *sp, netstack_t *ns)
 723 {
 724         /*
 725          * Flush out each bucket, one at a time.  Were it not for keysock's
 726          * enforcement, there would be a subtlety where I could add on the
 727          * heels of a flush.  With keysock's enforcement, however, this
 728          * makes ESP's job easy.
 729          */
 730         sadb_destroyer(&sp->sdb_of, sp->sdb_hashsize, B_FALSE);
 731         sadb_destroyer(&sp->sdb_if, sp->sdb_hashsize, B_FALSE);
 732 
 733         /* For each acquire, destroy it; leave the bucket mutex alone. */
 734         sadb_destroy_acqlist(&sp->sdb_acq, sp->sdb_hashsize, B_FALSE, ns);
 735 }
 736 
 737 static void
 738 sadb_destroy(sadb_t *sp, netstack_t *ns)
 739 {
 740         sadb_destroyer(&sp->sdb_of, sp->sdb_hashsize, B_TRUE);
 741         sadb_destroyer(&sp->sdb_if, sp->sdb_hashsize, B_TRUE);
 742 
 743         /* For each acquire, destroy it, including the bucket mutex. */
 744         sadb_destroy_acqlist(&sp->sdb_acq, sp->sdb_hashsize, B_TRUE, ns);
 745 
 746         ASSERT(sp->sdb_of == NULL);
 747         ASSERT(sp->sdb_if == NULL);
 748         ASSERT(sp->sdb_acq == NULL);
 749 }
 750 
 751 void
 752 sadbp_flush(sadbp_t *spp, netstack_t *ns)
 753 {
 754         sadb_flush(&spp->s_v4, ns);
 755         sadb_flush(&spp->s_v6, ns);
 756 }
 757 
 758 void
 759 sadbp_destroy(sadbp_t *spp, netstack_t *ns)
 760 {
 761         sadb_destroy(&spp->s_v4, ns);
 
1463  *
1464  * +------+----+-------------+-----------+---------------+
1465  * | base | SA | source addr | dest addr | soft lifetime |
1466  * +------+----+-------------+-----------+---------------+
1467  */
1468 static void
1469 sadb_strip(sadb_msg_t *samsg)
1470 {
1471         sadb_ext_t *ext;
1472         uint8_t *target = NULL;
1473         uint8_t *msgend;
1474         int sofar = SADB_8TO64(sizeof (*samsg));
1475         int copylen;
1476 
1477         ext = (sadb_ext_t *)(samsg + 1);
1478         msgend = (uint8_t *)samsg;
1479         msgend += SADB_64TO8(samsg->sadb_msg_len);
1480         while ((uint8_t *)ext < msgend) {
1481                 if (ext->sadb_ext_type == SADB_EXT_RESERVED ||
1482                     ext->sadb_ext_type == SADB_EXT_KEY_AUTH ||
1483                     ext->sadb_ext_type == SADB_EXT_KEY_ENCRYPT) {
1484                         /*
1485                          * Aha!  I found a header to be erased.
1486                          */
1487 
1488                         if (target != NULL) {
1489                                 /*
1490                                  * If I had a previous header to be erased,
1491                                  * copy over it.  I can get away with just
1492                                  * copying backwards because the target will
1493                                  * always be 8 bytes behind the source.
1494                                  */
1495                                 copylen = ((uint8_t *)ext) - (target +
1496                                     SADB_64TO8(
1497                                     ((sadb_ext_t *)target)->sadb_ext_len));
1498                                 ovbcopy(((uint8_t *)ext - copylen), target,
1499                                     copylen);
1500                                 target += copylen;
1501                                 ((sadb_ext_t *)target)->sadb_ext_len =
1502                                     SADB_8TO64(((uint8_t *)ext) - target +
 
1579  * and NULL if not.  BTW, that ipsa will have its refcnt appropriately held,
1580  * and the caller will release said refcnt.
1581  */
1582 void
1583 sadb_pfkey_echo(queue_t *pfkey_q, mblk_t *mp, sadb_msg_t *samsg,
1584     keysock_in_t *ksi, ipsa_t *ipsa)
1585 {
1586         keysock_out_t *kso;
1587         mblk_t *mp1;
1588         sadb_msg_t *newsamsg;
1589         uint8_t *oldend;
1590 
1591         ASSERT((mp->b_cont != NULL) &&
1592             ((void *)samsg == (void *)mp->b_cont->b_rptr) &&
1593             ((void *)mp->b_rptr == (void *)ksi));
1594 
1595         switch (samsg->sadb_msg_type) {
1596         case SADB_ADD:
1597         case SADB_UPDATE:
1598         case SADB_X_UPDATEPAIR:
1599         case SADB_FLUSH:
1600         case SADB_DUMP:
1601                 /*
1602                  * I have all of the message already.  I just need to strip
1603                  * out the keying material and echo the message back.
1604                  *
1605                  * NOTE: for SADB_DUMP, the function sadb_dump() did the
1606                  * work.  When DUMP reaches here, it should only be a base
1607                  * message.
1608                  */
1609         justecho:
1610                 ASSERT(samsg->sadb_msg_type != SADB_DUMP ||
1611                     samsg->sadb_msg_len == SADB_8TO64(sizeof (sadb_msg_t)));
1612                 if (ksi->ks_in_extv[SADB_EXT_KEY_AUTH] != NULL ||
1613                     ksi->ks_in_extv[SADB_EXT_KEY_ENCRYPT] != NULL) {
1614                         sadb_strip(samsg);
1615                         /* Assume PF_KEY message is contiguous. */
1616                         ASSERT(mp->b_cont->b_cont == NULL);
1617                         oldend = mp->b_cont->b_wptr;
1618                         mp->b_cont->b_wptr = mp->b_cont->b_rptr +
1619                             SADB_64TO8(samsg->sadb_msg_len);
1620                         bzero(mp->b_cont->b_wptr, oldend - mp->b_cont->b_wptr);
1621                 }
1622                 break;
1623         case SADB_GET:
1624                 /*
1625                  * Do a lot of work here, because of the ipsa I just found.
1626                  * First construct the new PF_KEY message, then abandon
1627                  * the old one.
1628                  */
1629                 mp1 = sadb_sa2msg(ipsa, samsg);
1630                 if (mp1 == NULL) {
1631                         sadb_pfkey_error(pfkey_q, mp, ENOMEM,
1632                             SADB_X_DIAGNOSTIC_NONE, ksi->ks_in_serial);
1633                         return;
 
2336  */
2337 boolean_t
2338 sadb_match_query(ipsa_query_t *sq, ipsa_t *sa)
2339 {
2340         ipsa_match_fn_t *mfpp = &(sq->matchers[0]);
2341         ipsa_match_fn_t mfp;
2342 
2343         for (mfp = *mfpp++; mfp != NULL; mfp = *mfpp++) {
2344                 if (!mfp(sq, sa))
2345                         return (B_FALSE);
2346         }
2347         return (B_TRUE);
2348 }
2349 
2350 /*
2351  * Walker callback function to delete sa's based on src/dst address.
2352  * Assumes that we're called with *head locked, no other locks held;
2353  * Conveniently, and not coincidentally, this is both what sadb_walker
2354  * gives us and also what sadb_unlinkassoc expects.
2355  */
2356 static void
2357 sadb_purge_cb(isaf_t *head, ipsa_t *entry, void *cookie)
2358 {
2359         ipsa_query_t *query = (ipsa_query_t *)cookie;
2360 
2361         ASSERT(MUTEX_HELD(&head->isaf_lock));
2362 
2363         mutex_enter(&entry->ipsa_lock);
2364 
2365         if (entry->ipsa_state == IPSA_STATE_LARVAL ||
2366             !sadb_match_query(query, entry)) {
2367                 mutex_exit(&entry->ipsa_lock);
2368                 return;
2369         }
2370 
2371         entry->ipsa_state = IPSA_STATE_DEAD;
2372         (void) sadb_torch_assoc(head, entry);
2373 }
2374 
2375 /*
2376  * Common code to purge an SA with a matching src or dst address.
2377  * Don't kill larval SA's in such a purge.
2378  */
2379 int
2380 sadb_purge_sa(mblk_t *mp, keysock_in_t *ksi, sadb_t *sp,
2381         int *diagnostic, queue_t *pfkey_q)
2382 {
2383         ipsa_query_t query;
2384         int error = sadb_form_query(ksi, 0,
2385             IPSA_Q_SRC|IPSA_Q_DST|IPSA_Q_SRCID|IPSA_Q_DSTID|IPSA_Q_KMC,
2386             &query, diagnostic);
2387 
2388         if (error != 0)
2389                 return (error);
2390 
2391         /*
2392          * This is simple, crude, and effective.
2393          * Unimplemented optimizations (TBD):
2394          * - we can limit how many places we search based on where we
2395          * think the SA is filed.
2396          * - if we get a dst address, we can hash based on dst addr to find
2397          * the correct bucket in the outbound table.
2398          */
2399         sadb_walker(sp->sdb_if, sp->sdb_hashsize, sadb_purge_cb, &query);
2400         sadb_walker(sp->sdb_of, sp->sdb_hashsize, sadb_purge_cb, &query);
2401 
2402         ASSERT(mp->b_cont != NULL);
2403         sadb_pfkey_echo(pfkey_q, mp, (sadb_msg_t *)mp->b_cont->b_rptr, ksi,
2404             NULL);
2405         return (0);
2406 }
2407 
2408 /*
2409  * Common code to delete/get an SA.
2410  */
2411 int
2412 sadb_delget_sa(mblk_t *mp, keysock_in_t *ksi, sadbp_t *spp,
2413     int *diagnostic, queue_t *pfkey_q, uint8_t sadb_msg_type)
2414 {
2415         ipsa_query_t sq;
2416         ipsa_t *echo_target = NULL;
2417         ipsap_t ipsapp;
2418         uint_t  error = 0;
2419 
2420         sq.spp = spp;           /* XXX param */
2421         error = sadb_form_query(ksi, IPSA_Q_DST|IPSA_Q_SA,
2422             IPSA_Q_SRC|IPSA_Q_DST|IPSA_Q_SA|IPSA_Q_INBOUND|IPSA_Q_OUTBOUND,
2423             &sq, diagnostic);
2424         if (error != 0)
2425                 return (error);
2426 
2427         error = get_ipsa_pair(&sq, &ipsapp, diagnostic);
2428         if (error != 0) {
2429                 return (error);
2430         }
2431 
2432         echo_target = ipsapp.ipsap_sa_ptr;
2433         if (echo_target == NULL)
2434                 echo_target = ipsapp.ipsap_psa_ptr;
2435 
2436         if (sadb_msg_type == SADB_DELETE || sadb_msg_type == SADB_X_DELPAIR) {
2437                 /*
2438                  * Bucket locks will be required if SA is actually unlinked.
2439                  * get_ipsa_pair() returns valid hash bucket pointers even
 
2922                 newbie->ipsa_unique_mask = SA_UNIQUE_MASK(isrc->sin_port,
2923                     idst->sin_port, dstext->sadb_address_proto,
2924                     idstext->sadb_address_proto);
2925         } else {
2926                 /* ... and outer-ports for Transport Mode. */
2927                 newbie->ipsa_unique_id = SA_UNIQUE_ID(src->sin_port,
2928                     dst->sin_port, dstext->sadb_address_proto, 0);
2929                 newbie->ipsa_unique_mask = SA_UNIQUE_MASK(src->sin_port,
2930                     dst->sin_port, dstext->sadb_address_proto, 0);
2931         }
2932         if (newbie->ipsa_unique_mask != (uint64_t)0)
2933                 newbie->ipsa_flags |= IPSA_F_UNIQUE;
2934 
2935         sadb_nat_calculations(newbie,
2936             (sadb_address_t *)ksi->ks_in_extv[SADB_X_EXT_ADDRESS_NATT_LOC],
2937             (sadb_address_t *)ksi->ks_in_extv[SADB_X_EXT_ADDRESS_NATT_REM],
2938             src_addr_ptr, dst_addr_ptr);
2939 
2940         newbie->ipsa_type = samsg->sadb_msg_satype;
2941 
2942         ASSERT(assoc->sadb_sa_state == SADB_SASTATE_MATURE);
2943         newbie->ipsa_auth_alg = assoc->sadb_sa_auth;
2944         newbie->ipsa_encr_alg = assoc->sadb_sa_encrypt;
2945 
2946         newbie->ipsa_flags |= assoc->sadb_sa_flags;
2947         if (newbie->ipsa_flags & SADB_X_SAFLAGS_NATT_LOC &&
2948             ksi->ks_in_extv[SADB_X_EXT_ADDRESS_NATT_LOC] == NULL) {
2949                 mutex_exit(&newbie->ipsa_lock);
2950                 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_NATT_LOC;
2951                 error = EINVAL;
2952                 goto error;
2953         }
2954         if (newbie->ipsa_flags & SADB_X_SAFLAGS_NATT_REM &&
2955             ksi->ks_in_extv[SADB_X_EXT_ADDRESS_NATT_REM] == NULL) {
2956                 mutex_exit(&newbie->ipsa_lock);
2957                 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_NATT_REM;
2958                 error = EINVAL;
2959                 goto error;
2960         }
2961         if (newbie->ipsa_flags & SADB_X_SAFLAGS_TUNNEL &&
2962             ksi->ks_in_extv[SADB_X_EXT_ADDRESS_INNER_SRC] == NULL) {
 
3829                 return (B_TRUE);
3830         }
3831         return (B_FALSE);
3832 }
3833 
3834 /*
3835  * Return "assoc" if haspeer is true and I send an expire.  This allows
3836  * the consumers' aging functions to tidy up an expired SA's peer.
3837  */
3838 static ipsa_t *
3839 sadb_age_assoc(isaf_t *head, queue_t *pfkey_q, ipsa_t *assoc,
3840     time_t current, int reap_delay, boolean_t inbound)
3841 {
3842         ipsa_t *retval = NULL;
3843         boolean_t dropped_mutex = B_FALSE;
3844 
3845         ASSERT(MUTEX_HELD(&head->isaf_lock));
3846 
3847         mutex_enter(&assoc->ipsa_lock);
3848 
3849         /*
3850          * Be aggressive in reaping expired LARVAL SAs.
3851          */
3852         if (assoc->ipsa_state == IPSA_STATE_LARVAL &&
3853             assoc->ipsa_hardexpiretime <= current) {
3854                 assoc->ipsa_state = IPSA_STATE_DEAD;
3855                 return (sadb_torch_assoc(head, assoc));
3856         }
3857 
3858         /*
3859          * Check lifetimes.  Fortunately, SA setup is done
3860          * such that there are only two times to look at,
3861          * softexpiretime, and hardexpiretime.
3862          *
3863          * Check hard first.
3864          */
3865 
3866         if (assoc->ipsa_hardexpiretime != 0 &&
3867             assoc->ipsa_hardexpiretime <= current) {
3868                 if (assoc->ipsa_state == IPSA_STATE_DEAD)
3869                         return (sadb_torch_assoc(head, assoc));
3870 
3871                 /*
3872                  * Send SADB_EXPIRE with hard lifetime, delay for unlinking.
3873                  */
 
3898                 assoc->ipsa_state = IPSA_STATE_DYING;
3899                 if (assoc->ipsa_haspeer) {
3900                         /*
3901                          * If the SA has a peer, update the peer's state
3902                          * on SOFT_EXPIRE, this is mostly to prevent two
3903                          * expire messages from effectively the same SA.
3904                          *
3905                          * Don't care about paired SA's, then can (and should)
3906                          * be able to soft expire at different times.
3907                          *
3908                          * If I return assoc, I have to bump up its
3909                          * reference count to keep with the ipsa_t reference
3910                          * count semantics.
3911                          */
3912                         IPSA_REFHOLD(assoc);
3913                         retval = assoc;
3914                 }
3915                 sadb_expire_assoc(pfkey_q, assoc);
3916         } else if (assoc->ipsa_idletime != 0 &&
3917             assoc->ipsa_idleexpiretime <= current) {
3918                 /* Only issue an IDLE expiration if we're in mature state. */
3919                 if (assoc->ipsa_state == IPSA_STATE_MATURE) {
3920                         sadb_expire_assoc(pfkey_q, assoc);
3921                 }
3922         } else {
3923                 /* Check idle time activities. */
3924                 dropped_mutex = sadb_idle_activities(assoc,
3925                     current - assoc->ipsa_lastuse, inbound);
3926         }
3927 
3928         if (!dropped_mutex)
3929                 mutex_exit(&assoc->ipsa_lock);
3930         return (retval);
3931 }
3932 
3933 /*
3934  * Called by a consumer protocol to do ther dirty work of reaping dead
3935  * Security Associations.
3936  *
3937  * NOTE: sadb_age_assoc() marks expired SA's as DEAD but only removed
3938  * SA's that are already marked DEAD, so expired SA's are only reaped
 
4193                         assoc->ipsa_idleexpiretime =
4194                             current + idle->sadb_lifetime_addtime;
4195                         assoc->ipsa_idletime = idle->sadb_lifetime_addtime;
4196                 }
4197                 if (assoc->ipsa_idleuselt != 0) {
4198                         if (assoc->ipsa_idletime != 0) {
4199                                 assoc->ipsa_idletime = min(assoc->ipsa_idletime,
4200                                     assoc->ipsa_idleuselt);
4201                         assoc->ipsa_idleexpiretime =
4202                             current + assoc->ipsa_idletime;
4203                         } else {
4204                                 assoc->ipsa_idleexpiretime =
4205                                     current + assoc->ipsa_idleuselt;
4206                                 assoc->ipsa_idletime = assoc->ipsa_idleuselt;
4207                         }
4208                 }
4209         }
4210         mutex_exit(&assoc->ipsa_lock);
4211 }
4212 
4213 /*
4214  * Check a proposed KMC update for sanity.
4215  */
4216 static int
4217 sadb_check_kmc(ipsa_query_t *sq, ipsa_t *sa, int *diagnostic)
4218 {
4219         uint32_t kmp = sq->kmp;
4220         uint32_t kmc = sq->kmc;
4221 
4222         if (sa == NULL)
4223                 return (0);
4224 
4225         if (sa->ipsa_state == IPSA_STATE_DEAD)
4226                 return (ESRCH); /* DEAD == Not there, in this case. */
4227 
4228         if ((kmp != 0) && ((sa->ipsa_kmp != 0) || (sa->ipsa_kmp != kmp))) {
4229                 *diagnostic = SADB_X_DIAGNOSTIC_DUPLICATE_KMP;
4230                 return (EINVAL);
4231         }
4232 
 
4241 /*
4242  * Actually update the KMC info.
4243  */
4244 static void
4245 sadb_update_kmc(ipsa_query_t *sq, ipsa_t *sa)
4246 {
4247         uint32_t kmp = sq->kmp;
4248         uint32_t kmc = sq->kmc;
4249 
4250         if (kmp != 0)
4251                 sa->ipsa_kmp = kmp;
4252         if (kmc != 0)
4253                 sa->ipsa_kmc = kmc;
4254 }
4255 
4256 /*
4257  * Common code to update an SA.
4258  */
4259 
4260 int
4261 sadb_update_sa(mblk_t *mp, keysock_in_t *ksi,
4262     sadbp_t *spp, int *diagnostic, queue_t *pfkey_q,
4263     int (*add_sa_func)(mblk_t *, keysock_in_t *, int *, netstack_t *),
4264     netstack_t *ns, uint8_t sadb_msg_type)
4265 {
4266         sadb_key_t *akey = (sadb_key_t *)ksi->ks_in_extv[SADB_EXT_KEY_AUTH];
4267         sadb_key_t *ekey = (sadb_key_t *)ksi->ks_in_extv[SADB_EXT_KEY_ENCRYPT];
4268         sadb_lifetime_t *soft =
4269             (sadb_lifetime_t *)ksi->ks_in_extv[SADB_EXT_LIFETIME_SOFT];
4270         sadb_lifetime_t *hard =
4271             (sadb_lifetime_t *)ksi->ks_in_extv[SADB_EXT_LIFETIME_HARD];
4272         sadb_lifetime_t *idle =
4273             (sadb_lifetime_t *)ksi->ks_in_extv[SADB_X_EXT_LIFETIME_IDLE];
4274         sadb_x_pair_t *pair_ext =
4275             (sadb_x_pair_t *)ksi->ks_in_extv[SADB_X_EXT_PAIR];
4276         ipsa_t *echo_target = NULL;
4277         ipsap_t ipsapp;
4278         ipsa_query_t sq;
4279 
4280         sq.spp = spp;           /* XXX param */
4281         int error = sadb_form_query(ksi, IPSA_Q_SRC|IPSA_Q_DST|IPSA_Q_SA,
4282             IPSA_Q_SRC|IPSA_Q_DST|IPSA_Q_SA|IPSA_Q_INBOUND|IPSA_Q_OUTBOUND,
4283             &sq, diagnostic);
4284 
4285         if (error != 0)
4286                 return (error);
4287 
4288         error = get_ipsa_pair(&sq, &ipsapp, diagnostic);
4289         if (error != 0)
4290                 return (error);
4291 
4292         if (ipsapp.ipsap_psa_ptr == NULL && ipsapp.ipsap_sa_ptr != NULL) {
4293                 if (ipsapp.ipsap_sa_ptr->ipsa_state == IPSA_STATE_LARVAL) {
4294                         /*
4295                          * REFRELE the target and let the add_sa_func()
4296                          * deal with updating a larval SA.
4297                          */
4298                         destroy_ipsa_pair(&ipsapp);
4299                         return (add_sa_func(mp, ksi, diagnostic, ns));
4300                 }
4301         }
4302 
4303         /*
4304          * At this point we have an UPDATE to a MATURE SA. There should
4305          * not be any keying material present.
4306          */
4307         if (akey != NULL) {
4308                 *diagnostic = SADB_X_DIAGNOSTIC_AKEY_PRESENT;
4309                 error = EINVAL;
4310                 goto bail;
4311         }
4312         if (ekey != NULL) {
4313                 *diagnostic = SADB_X_DIAGNOSTIC_EKEY_PRESENT;
4314                 error = EINVAL;
4315                 goto bail;
4316         }
4317 
4318         /*
4319          * Reality checks for updates of active associations.
4320          * Sundry first-pass UPDATE-specific reality checks.
4321          * Have to do the checks here, because it's after the add_sa code.
4322          * XXX STATS : logging/stats here?
4323          */
4324 
4325         if (sq.assoc->sadb_sa_state != SADB_SASTATE_MATURE) {
4326                 *diagnostic = SADB_X_DIAGNOSTIC_BAD_SASTATE;
4327                 error = EINVAL;
4328                 goto bail;
4329         }
4330         if (sq.assoc->sadb_sa_flags & ~spp->s_updateflags) {
4331                 *diagnostic = SADB_X_DIAGNOSTIC_BAD_SAFLAGS;
4332                 error = EINVAL;
4333                 goto bail;
4334         }
4335         if (ksi->ks_in_extv[SADB_EXT_LIFETIME_CURRENT] != NULL) {
4336                 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_LIFETIME;
4337                 error = EOPNOTSUPP;
4338                 goto bail;
4339         }
4340 
4341         if ((*diagnostic = sadb_hardsoftchk(hard, soft, idle)) != 0) {
4342                 error = EINVAL;
4343                 goto bail;
4344         }
4345 
4346         if ((*diagnostic = sadb_labelchk(ksi)) != 0)
4347                 return (EINVAL);
4348 
4349         error = sadb_check_kmc(&sq, ipsapp.ipsap_sa_ptr, diagnostic);
4350         if (error != 0)
4351                 goto bail;
4352 
4353         error = sadb_check_kmc(&sq, ipsapp.ipsap_psa_ptr, diagnostic);
4354         if (error != 0)
4355                 goto bail;
4356 
4357         if (ipsapp.ipsap_sa_ptr != NULL) {
4358                 sadb_update_lifetimes(ipsapp.ipsap_sa_ptr, hard, soft,
4359                     idle, B_TRUE);
4360                 sadb_update_kmc(&sq, ipsapp.ipsap_sa_ptr);
4361         }
4362 
4363         if (sadb_msg_type == SADB_X_UPDATEPAIR) {
4364                 if (ipsapp.ipsap_psa_ptr != NULL) {
4365                         sadb_update_lifetimes(ipsapp.ipsap_psa_ptr, hard, soft,
4366                             idle, B_FALSE);
4367                         sadb_update_kmc(&sq, ipsapp.ipsap_psa_ptr);
4368                 } else {
4369                         *diagnostic = SADB_X_DIAGNOSTIC_PAIR_SA_NOTFOUND;
4370                         error = ESRCH;
4371                         goto bail;
4372                 }
4373         }
4374 
4375         if (pair_ext != NULL)
4376                 error = update_pairing(&ipsapp, &sq, ksi, diagnostic);
4377 
4378         if (error == 0)
4379                 sadb_pfkey_echo(pfkey_q, mp, (sadb_msg_t *)mp->b_cont->b_rptr,
4380                     ksi, echo_target);
4381 bail:
 
5545         /* XXXMLS Insert sensitivity information here. */
5546 
5547         if (cur != NULL)
5548                 samsg->sadb_msg_len = SADB_8TO64(cur - msgmp->b_rptr);
5549         else
5550                 mutex_exit(&ipss->ipsec_alg_lock);
5551 
5552         return (pfkeymp);
5553 }
5554 
5555 /*
5556  * Given an SADB_GETSPI message, find an appropriately ranged SA and
5557  * allocate an SA.  If there are message improprieties, return (ipsa_t *)-1.
5558  * If there was a memory allocation error, return NULL.  (Assume NULL !=
5559  * (ipsa_t *)-1).
5560  *
5561  * master_spi is passed in host order.
5562  */
5563 ipsa_t *
5564 sadb_getspi(keysock_in_t *ksi, uint32_t master_spi, int *diagnostic,
5565     netstack_t *ns)
5566 {
5567         sadb_address_t *src =
5568             (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_SRC],
5569             *dst = (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_DST];
5570         sadb_spirange_t *range =
5571             (sadb_spirange_t *)ksi->ks_in_extv[SADB_EXT_SPIRANGE];
5572         struct sockaddr_in *ssa, *dsa;
5573         struct sockaddr_in6 *ssa6, *dsa6;
5574         uint32_t *srcaddr, *dstaddr;
5575         sa_family_t af;
5576         uint32_t add, min, max;
5577 
5578         if (src == NULL) {
5579                 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_SRC;
5580                 return ((ipsa_t *)-1);
5581         }
5582         if (dst == NULL) {
5583                 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_DST;
5584                 return ((ipsa_t *)-1);
5585         }
 
6628         return (npkt);
6629 }
6630 
6631 /*
6632  * sadb_clear_lpkt: Atomically clear ipsa->ipsa_lpkt and return the
6633  * previous value.
6634  */
6635 mblk_t *
6636 sadb_clear_lpkt(ipsa_t *ipsa)
6637 {
6638         mblk_t *opkt;
6639 
6640         mutex_enter(&ipsa->ipsa_lock);
6641         opkt = ipsa->ipsa_lpkt;
6642         ipsa->ipsa_lpkt = NULL;
6643         mutex_exit(&ipsa->ipsa_lock);
6644         return (opkt);
6645 }
6646 
6647 /*
6648  * Walker callback used by sadb_alg_update() to free/create crypto
6649  * context template when a crypto software provider is removed or
6650  * added.
6651  */
6652 
6653 struct sadb_update_alg_state {
6654         ipsec_algtype_t alg_type;
6655         uint8_t alg_id;
6656         boolean_t is_added;
6657         boolean_t async_auth;
6658         boolean_t async_encr;
6659 };
6660 
6661 static void
6662 sadb_alg_update_cb(isaf_t *head, ipsa_t *entry, void *cookie)
6663 {
6664         struct sadb_update_alg_state *update_state =
6665             (struct sadb_update_alg_state *)cookie;
6666         crypto_ctx_template_t *ctx_tmpl = NULL;
6667 
 
 |