Print this page
8927 sadb_x_kmc_t's KM cookie should be 64-bits
Reviewed by: Jason King <jason.king@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Yuri Pankov <yuripv@gmx.com>


1026                 sin6->sin6_port = port;
1027                 IPSA_COPY_ADDR(&sin6->sin6_addr, addr, af);
1028                 break;
1029         }
1030 
1031         addrext_len = roundup(cur - start, sizeof (uint64_t));
1032         addrext->sadb_address_len = SADB_8TO64(addrext_len);
1033 
1034         cur = start + addrext_len;
1035         if (cur > end)
1036                 cur = NULL;
1037 
1038         return (cur);
1039 }
1040 
1041 /*
1042  * Construct a key management cookie extension.
1043  */
1044 
1045 static uint8_t *
1046 sadb_make_kmc_ext(uint8_t *cur, uint8_t *end, uint32_t kmp, uint32_t kmc)
1047 {
1048         sadb_x_kmc_t *kmcext = (sadb_x_kmc_t *)cur;
1049 
1050         if (cur == NULL)
1051                 return (NULL);
1052 
1053         cur += sizeof (*kmcext);
1054 
1055         if (cur > end)
1056                 return (NULL);
1057 
1058         kmcext->sadb_x_kmc_len = SADB_8TO64(sizeof (*kmcext));
1059         kmcext->sadb_x_kmc_exttype = SADB_X_EXT_KM_COOKIE;
1060         kmcext->sadb_x_kmc_proto = kmp;
1061         kmcext->sadb_x_kmc_cookie = kmc;
1062         kmcext->sadb_x_kmc_reserved = 0;
1063 
1064         return (cur);
1065 }
1066 
1067 /*
1068  * Given an original message header with sufficient space following it, and an
1069  * SA, construct a full PF_KEY message with all of the relevant extensions.
1070  * This is mostly used for SADB_GET, and SADB_DUMP.
1071  */
1072 static mblk_t *
1073 sadb_sa2msg(ipsa_t *ipsa, sadb_msg_t *samsg)
1074 {
1075         int alloclen, addrsize, paddrsize, authsize, encrsize;
1076         int srcidsize, dstidsize, senslen, osenslen;
1077         sa_family_t fam, pfam;  /* Address family for SADB_EXT_ADDRESS */
1078                                 /* src/dst and proxy sockaddrs. */
1079         /*
1080          * The following are pointers into the PF_KEY message this PF_KEY
1081          * message creates.
1082          */


2313         sq->dstid = (sadb_ident_t *)ksi->ks_in_extv[SADB_EXT_IDENTITY_DST];
2314         if ((match & IPSA_Q_DSTID) && (sq->dstid != NULL)) {
2315                 sq->didstr = (char *)(sq->dstid + 1);
2316                 sq->didtype = sq->dstid->sadb_ident_type;
2317                 *mfpp++ = sadb_match_dstid;
2318         }
2319 
2320         sq->srcid = (sadb_ident_t *)ksi->ks_in_extv[SADB_EXT_IDENTITY_SRC];
2321 
2322         if ((match & IPSA_Q_SRCID) && (sq->srcid != NULL)) {
2323                 sq->sidstr = (char *)(sq->srcid + 1);
2324                 sq->sidtype = sq->srcid->sadb_ident_type;
2325                 *mfpp++ = sadb_match_srcid;
2326         }
2327 
2328         sq->kmcext = (sadb_x_kmc_t *)ksi->ks_in_extv[SADB_X_EXT_KM_COOKIE];
2329         sq->kmc = 0;
2330         sq->kmp = 0;
2331 
2332         if ((match & IPSA_Q_KMC) && (sq->kmcext)) {
2333                 sq->kmc = sq->kmcext->sadb_x_kmc_cookie;
2334                 sq->kmp = sq->kmcext->sadb_x_kmc_proto;






2335                 *mfpp++ = sadb_match_kmc;
2336         }
2337 
2338         if (match & (IPSA_Q_INBOUND|IPSA_Q_OUTBOUND)) {
2339                 if (sq->af == AF_INET6)
2340                         sq->sp = &sq->spp->s_v6;
2341                 else
2342                         sq->sp = &sq->spp->s_v4;
2343         } else {
2344                 sq->sp = NULL;
2345         }
2346 
2347         if (match & IPSA_Q_INBOUND) {
2348                 sq->inhash = INBOUND_HASH(sq->sp, sq->assoc->sadb_sa_spi);
2349                 sq->inbound = &sq->sp->sdb_if[sq->inhash];
2350         } else {
2351                 sq->inhash = 0;
2352                 sq->inbound = NULL;
2353         }
2354 


3116                 mutex_exit(&newbie->ipsa_lock);
3117                 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_INNER_SRC;
3118                 error = EINVAL;
3119                 goto error;
3120         }
3121         /*
3122          * If unspecified source address, force replay_wsize to 0.
3123          * This is because an SA that has multiple sources of secure
3124          * traffic cannot enforce a replay counter w/o synchronizing the
3125          * senders.
3126          */
3127         if (ksi->ks_in_srctype != KS_IN_ADDR_UNSPEC)
3128                 newbie->ipsa_replay_wsize = assoc->sadb_sa_replay;
3129         else
3130                 newbie->ipsa_replay_wsize = 0;
3131 
3132         newbie->ipsa_addtime = gethrestime_sec();
3133 
3134         if (kmcext != NULL) {
3135                 newbie->ipsa_kmp = kmcext->sadb_x_kmc_proto;
3136                 newbie->ipsa_kmc = kmcext->sadb_x_kmc_cookie;



3137         }


3138 
3139         /*
3140          * XXX CURRENT lifetime checks MAY BE needed for an UPDATE.
3141          * The spec says that one can update current lifetimes, but
3142          * that seems impractical, especially in the larval-to-mature
3143          * update that this function performs.
3144          */
3145         if (soft != NULL) {
3146                 newbie->ipsa_softaddlt = soft->sadb_lifetime_addtime;
3147                 newbie->ipsa_softuselt = soft->sadb_lifetime_usetime;
3148                 newbie->ipsa_softbyteslt = soft->sadb_lifetime_bytes;
3149                 newbie->ipsa_softalloc = soft->sadb_lifetime_allocations;
3150                 SET_EXPIRE(newbie, softaddlt, softexpiretime);
3151         }
3152         if (hard != NULL) {
3153                 newbie->ipsa_hardaddlt = hard->sadb_lifetime_addtime;
3154                 newbie->ipsa_harduselt = hard->sadb_lifetime_usetime;
3155                 newbie->ipsa_hardbyteslt = hard->sadb_lifetime_bytes;
3156                 newbie->ipsa_hardalloc = hard->sadb_lifetime_allocations;
3157                 SET_EXPIRE(newbie, hardaddlt, hardexpiretime);


4419                 } else {
4420                         *ipkt_lst = NULL;
4421                 }
4422                 break;
4423         default:
4424                 rcode = EINVAL;
4425                 break;
4426         }
4427 
4428         mutex_exit(&assoc->ipsa_lock);
4429         return (rcode);
4430 }
4431 
4432 /*
4433  * Check a proposed KMC update for sanity.
4434  */
4435 static int
4436 sadb_check_kmc(ipsa_query_t *sq, ipsa_t *sa, int *diagnostic)
4437 {
4438         uint32_t kmp = sq->kmp;
4439         uint32_t kmc = sq->kmc;
4440 
4441         if (sa == NULL)
4442                 return (0);
4443 
4444         if (sa->ipsa_state == IPSA_STATE_DEAD)
4445                 return (ESRCH); /* DEAD == Not there, in this case. */
4446 
4447         if ((kmp != 0) && ((sa->ipsa_kmp != 0) || (sa->ipsa_kmp != kmp))) {
4448                 *diagnostic = SADB_X_DIAGNOSTIC_DUPLICATE_KMP;
4449                 return (EINVAL);
4450         }
4451 
4452         if ((kmc != 0) && ((sa->ipsa_kmc != 0) || (sa->ipsa_kmc != kmc))) {
4453                 *diagnostic = SADB_X_DIAGNOSTIC_DUPLICATE_KMC;
4454                 return (EINVAL);
4455         }
4456 
4457         return (0);
4458 }
4459 
4460 /*
4461  * Actually update the KMC info.
4462  */
4463 static void
4464 sadb_update_kmc(ipsa_query_t *sq, ipsa_t *sa)
4465 {
4466         uint32_t kmp = sq->kmp;
4467         uint32_t kmc = sq->kmc;
4468 
4469         if (kmp != 0)
4470                 sa->ipsa_kmp = kmp;
4471         if (kmc != 0)
4472                 sa->ipsa_kmc = kmc;
4473 }
4474 
4475 /*
4476  * Common code to update an SA.
4477  */
4478 
4479 int
4480 sadb_update_sa(mblk_t *mp, keysock_in_t *ksi, mblk_t **ipkt_lst,
4481     sadbp_t *spp, int *diagnostic, queue_t *pfkey_q,
4482     int (*add_sa_func)(mblk_t *, keysock_in_t *, int *, netstack_t *),
4483     netstack_t *ns, uint8_t sadb_msg_type)
4484 {
4485         sadb_key_t *akey = (sadb_key_t *)ksi->ks_in_extv[SADB_EXT_KEY_AUTH];
4486         sadb_key_t *ekey = (sadb_key_t *)ksi->ks_in_extv[SADB_EXT_KEY_ENCRYPT];
4487         sadb_x_replay_ctr_t *replext =
4488             (sadb_x_replay_ctr_t *)ksi->ks_in_extv[SADB_X_EXT_REPLAY_VALUE];
4489         sadb_lifetime_t *soft =
4490             (sadb_lifetime_t *)ksi->ks_in_extv[SADB_EXT_LIFETIME_SOFT];
4491         sadb_lifetime_t *hard =
4492             (sadb_lifetime_t *)ksi->ks_in_extv[SADB_EXT_LIFETIME_HARD];
4493         sadb_lifetime_t *idle =
4494             (sadb_lifetime_t *)ksi->ks_in_extv[SADB_X_EXT_LIFETIME_IDLE];
4495         sadb_x_pair_t *pair_ext =
4496             (sadb_x_pair_t *)ksi->ks_in_extv[SADB_X_EXT_PAIR];
4497         ipsa_t *echo_target = NULL;
4498         ipsap_t ipsapp;
4499         ipsa_query_t sq;
4500         time_t current = gethrestime_sec();
4501 
4502         sq.spp = spp;           /* XXX param */
4503         int error = sadb_form_query(ksi, IPSA_Q_SRC|IPSA_Q_DST|IPSA_Q_SA,
4504             IPSA_Q_SRC|IPSA_Q_DST|IPSA_Q_SA|IPSA_Q_INBOUND|IPSA_Q_OUTBOUND,

4505             &sq, diagnostic);
4506 
4507         if (error != 0)
4508                 return (error);
4509 
4510         error = get_ipsa_pair(&sq, &ipsapp, diagnostic);
4511         if (error != 0)
4512                 return (error);
4513 
4514         if (ipsapp.ipsap_psa_ptr == NULL && ipsapp.ipsap_sa_ptr != NULL) {
4515                 if (ipsapp.ipsap_sa_ptr->ipsa_state == IPSA_STATE_LARVAL) {
4516                         /*
4517                          * REFRELE the target and let the add_sa_func()
4518                          * deal with updating a larval SA.
4519                          */
4520                         destroy_ipsa_pair(&ipsapp);
4521                         return (add_sa_func(mp, ksi, diagnostic, ns));
4522                 }
4523         }
4524 


5090         return (mp);
5091 }
5092 
5093 /*
5094  * Generate a regular ACQUIRE's proposal extension and KMC information..
5095  */
5096 static mblk_t *
5097 sadb_acquire_prop(ipsec_action_t *ap, netstack_t *ns, boolean_t do_esp)
5098 {
5099         ipsec_stack_t *ipss = ns->netstack_ipsec;
5100         ipsecesp_stack_t *espstack = ns->netstack_ipsecesp;
5101         ipsecah_stack_t *ahstack = ns->netstack_ipsecah;
5102         mblk_t *mp = NULL;
5103         sadb_prop_t *prop;
5104         sadb_comb_t *comb;
5105         ipsec_action_t *walker;
5106         int ncombs, allocsize, ealgid, aalgid, aminbits, amaxbits, eminbits,
5107             emaxbits, replay;
5108         uint64_t softbytes, hardbytes, softaddtime, hardaddtime, softusetime,
5109             hardusetime;
5110         uint32_t kmc = 0, kmp = 0;

5111 
5112         /*
5113          * Since it's an rwlock read, AND writing to the IPsec algorithms is
5114          * rare, just acquire it once up top, and drop it upon return.
5115          */
5116         rw_enter(&ipss->ipsec_alg_lock, RW_READER);
5117         if (do_esp) {
5118                 uint64_t num_aalgs, num_ealgs;
5119 
5120                 if (espstack->esp_kstats == NULL)
5121                         goto bail;
5122 
5123                 num_aalgs = ipss->ipsec_nalgs[IPSEC_ALG_AUTH];
5124                 num_ealgs = ipss->ipsec_nalgs[IPSEC_ALG_ENCR];
5125                 if (num_ealgs == 0)
5126                         goto bail;      /* IPsec not loaded yet, apparently. */
5127                 num_aalgs++;    /* No-auth or self-auth-crypto ESP. */
5128 
5129                 /* Use netstack's maximum loaded algorithms... */
5130                 ncombs = num_ealgs * num_aalgs;


5280         /* Don't include KMC extension if there's no room. */
5281         if (((kmp != 0) || (kmc != 0)) && allocsize >= sizeof (sadb_x_kmc_t)) {
5282                 if (sadb_make_kmc_ext(mp->b_wptr,
5283                     mp->b_wptr + sizeof (sadb_x_kmc_t), kmp, kmc) == NULL) {
5284                         freeb(mp);
5285                         mp = NULL;
5286                         goto bail;
5287                 }
5288                 mp->b_wptr += sizeof (sadb_x_kmc_t);
5289                 prop->sadb_prop_len += SADB_8TO64(sizeof (sadb_x_kmc_t));
5290         }
5291 
5292 bail:
5293         rw_exit(&ipss->ipsec_alg_lock);
5294         return (mp);
5295 }
5296 
5297 /*
5298  * Generate an extended ACQUIRE's extended-proposal extension.
5299  */
5300 /* ARGSUSED */
5301 static mblk_t *
5302 sadb_acquire_extended_prop(ipsec_action_t *ap, netstack_t *ns)
5303 {
5304         sadb_prop_t *eprop;
5305         uint8_t *cur, *end;
5306         mblk_t *mp;
5307         int allocsize, numecombs = 0, numalgdescs = 0;
5308         uint32_t kmc = 0, kmp = 0, replay = 0;

5309         ipsec_action_t *walker;
5310 
5311         allocsize = sizeof (*eprop);
5312 
5313         /*
5314          * Going to walk through the action list twice.  Once for allocation
5315          * measurement, and once for actual construction.
5316          */
5317         for (walker = ap; walker != NULL; walker = walker->ipa_next) {
5318                 ipsec_prot_t *ipp;
5319 
5320                 /*
5321                  * Skip non-IPsec policies
5322                  */
5323                 if (walker->ipa_act.ipa_type != IPSEC_ACT_APPLY)
5324                         continue;
5325 
5326                 ipp = &walker->ipa_act.ipa_apply;
5327 
5328                 if (walker->ipa_act.ipa_apply.ipp_km_proto)




1026                 sin6->sin6_port = port;
1027                 IPSA_COPY_ADDR(&sin6->sin6_addr, addr, af);
1028                 break;
1029         }
1030 
1031         addrext_len = roundup(cur - start, sizeof (uint64_t));
1032         addrext->sadb_address_len = SADB_8TO64(addrext_len);
1033 
1034         cur = start + addrext_len;
1035         if (cur > end)
1036                 cur = NULL;
1037 
1038         return (cur);
1039 }
1040 
1041 /*
1042  * Construct a key management cookie extension.
1043  */
1044 
1045 static uint8_t *
1046 sadb_make_kmc_ext(uint8_t *cur, uint8_t *end, uint32_t kmp, uint64_t kmc)
1047 {
1048         sadb_x_kmc_t *kmcext = (sadb_x_kmc_t *)cur;
1049 
1050         if (cur == NULL)
1051                 return (NULL);
1052 
1053         cur += sizeof (*kmcext);
1054 
1055         if (cur > end)
1056                 return (NULL);
1057 
1058         kmcext->sadb_x_kmc_len = SADB_8TO64(sizeof (*kmcext));
1059         kmcext->sadb_x_kmc_exttype = SADB_X_EXT_KM_COOKIE;
1060         kmcext->sadb_x_kmc_proto = kmp;
1061         kmcext->sadb_x_kmc_cookie64 = kmc;

1062 
1063         return (cur);
1064 }
1065 
1066 /*
1067  * Given an original message header with sufficient space following it, and an
1068  * SA, construct a full PF_KEY message with all of the relevant extensions.
1069  * This is mostly used for SADB_GET, and SADB_DUMP.
1070  */
1071 static mblk_t *
1072 sadb_sa2msg(ipsa_t *ipsa, sadb_msg_t *samsg)
1073 {
1074         int alloclen, addrsize, paddrsize, authsize, encrsize;
1075         int srcidsize, dstidsize, senslen, osenslen;
1076         sa_family_t fam, pfam;  /* Address family for SADB_EXT_ADDRESS */
1077                                 /* src/dst and proxy sockaddrs. */
1078         /*
1079          * The following are pointers into the PF_KEY message this PF_KEY
1080          * message creates.
1081          */


2312         sq->dstid = (sadb_ident_t *)ksi->ks_in_extv[SADB_EXT_IDENTITY_DST];
2313         if ((match & IPSA_Q_DSTID) && (sq->dstid != NULL)) {
2314                 sq->didstr = (char *)(sq->dstid + 1);
2315                 sq->didtype = sq->dstid->sadb_ident_type;
2316                 *mfpp++ = sadb_match_dstid;
2317         }
2318 
2319         sq->srcid = (sadb_ident_t *)ksi->ks_in_extv[SADB_EXT_IDENTITY_SRC];
2320 
2321         if ((match & IPSA_Q_SRCID) && (sq->srcid != NULL)) {
2322                 sq->sidstr = (char *)(sq->srcid + 1);
2323                 sq->sidtype = sq->srcid->sadb_ident_type;
2324                 *mfpp++ = sadb_match_srcid;
2325         }
2326 
2327         sq->kmcext = (sadb_x_kmc_t *)ksi->ks_in_extv[SADB_X_EXT_KM_COOKIE];
2328         sq->kmc = 0;
2329         sq->kmp = 0;
2330 
2331         if ((match & IPSA_Q_KMC) && (sq->kmcext)) {

2332                 sq->kmp = sq->kmcext->sadb_x_kmc_proto;
2333                 /* Be liberal in what we receive.  Special-case IKEv1. */
2334                 if (sq->kmp == SADB_X_KMP_IKE) {
2335                         /* Just in case in.iked is misbehaving... */
2336                         sq->kmcext->sadb_x_kmc_reserved = 0;
2337                 }
2338                 sq->kmc = sq->kmcext->sadb_x_kmc_cookie64;
2339                 *mfpp++ = sadb_match_kmc;
2340         }
2341 
2342         if (match & (IPSA_Q_INBOUND|IPSA_Q_OUTBOUND)) {
2343                 if (sq->af == AF_INET6)
2344                         sq->sp = &sq->spp->s_v6;
2345                 else
2346                         sq->sp = &sq->spp->s_v4;
2347         } else {
2348                 sq->sp = NULL;
2349         }
2350 
2351         if (match & IPSA_Q_INBOUND) {
2352                 sq->inhash = INBOUND_HASH(sq->sp, sq->assoc->sadb_sa_spi);
2353                 sq->inbound = &sq->sp->sdb_if[sq->inhash];
2354         } else {
2355                 sq->inhash = 0;
2356                 sq->inbound = NULL;
2357         }
2358 


3120                 mutex_exit(&newbie->ipsa_lock);
3121                 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_INNER_SRC;
3122                 error = EINVAL;
3123                 goto error;
3124         }
3125         /*
3126          * If unspecified source address, force replay_wsize to 0.
3127          * This is because an SA that has multiple sources of secure
3128          * traffic cannot enforce a replay counter w/o synchronizing the
3129          * senders.
3130          */
3131         if (ksi->ks_in_srctype != KS_IN_ADDR_UNSPEC)
3132                 newbie->ipsa_replay_wsize = assoc->sadb_sa_replay;
3133         else
3134                 newbie->ipsa_replay_wsize = 0;
3135 
3136         newbie->ipsa_addtime = gethrestime_sec();
3137 
3138         if (kmcext != NULL) {
3139                 newbie->ipsa_kmp = kmcext->sadb_x_kmc_proto;
3140                 /* Be liberal in what we receive.  Special-case IKEv1. */
3141                 if (newbie->ipsa_kmp == SADB_X_KMP_IKE) {
3142                         /* Just in case in.iked is misbehaving... */
3143                         kmcext->sadb_x_kmc_reserved = 0;
3144                 }
3145                 newbie->ipsa_kmc = kmcext->sadb_x_kmc_cookie64;
3146         }
3147 
3148         /*
3149          * XXX CURRENT lifetime checks MAY BE needed for an UPDATE.
3150          * The spec says that one can update current lifetimes, but
3151          * that seems impractical, especially in the larval-to-mature
3152          * update that this function performs.
3153          */
3154         if (soft != NULL) {
3155                 newbie->ipsa_softaddlt = soft->sadb_lifetime_addtime;
3156                 newbie->ipsa_softuselt = soft->sadb_lifetime_usetime;
3157                 newbie->ipsa_softbyteslt = soft->sadb_lifetime_bytes;
3158                 newbie->ipsa_softalloc = soft->sadb_lifetime_allocations;
3159                 SET_EXPIRE(newbie, softaddlt, softexpiretime);
3160         }
3161         if (hard != NULL) {
3162                 newbie->ipsa_hardaddlt = hard->sadb_lifetime_addtime;
3163                 newbie->ipsa_harduselt = hard->sadb_lifetime_usetime;
3164                 newbie->ipsa_hardbyteslt = hard->sadb_lifetime_bytes;
3165                 newbie->ipsa_hardalloc = hard->sadb_lifetime_allocations;
3166                 SET_EXPIRE(newbie, hardaddlt, hardexpiretime);


4428                 } else {
4429                         *ipkt_lst = NULL;
4430                 }
4431                 break;
4432         default:
4433                 rcode = EINVAL;
4434                 break;
4435         }
4436 
4437         mutex_exit(&assoc->ipsa_lock);
4438         return (rcode);
4439 }
4440 
4441 /*
4442  * Check a proposed KMC update for sanity.
4443  */
4444 static int
4445 sadb_check_kmc(ipsa_query_t *sq, ipsa_t *sa, int *diagnostic)
4446 {
4447         uint32_t kmp = sq->kmp;
4448         uint64_t kmc = sq->kmc;
4449 
4450         if (sa == NULL)
4451                 return (0);
4452 
4453         if (sa->ipsa_state == IPSA_STATE_DEAD)
4454                 return (ESRCH); /* DEAD == Not there, in this case. */
4455 
4456         if ((kmp != 0) && (sa->ipsa_kmp != 0) && (sa->ipsa_kmp != kmp)) {
4457                 *diagnostic = SADB_X_DIAGNOSTIC_DUPLICATE_KMP;
4458                 return (EINVAL);
4459         }
4460 
4461         if ((kmc != 0) && (sa->ipsa_kmc != 0) && (sa->ipsa_kmc != kmc)) {
4462                 *diagnostic = SADB_X_DIAGNOSTIC_DUPLICATE_KMC;
4463                 return (EINVAL);
4464         }
4465 
4466         return (0);
4467 }
4468 
4469 /*
4470  * Actually update the KMC info.
4471  */
4472 static void
4473 sadb_update_kmc(ipsa_query_t *sq, ipsa_t *sa)
4474 {
4475         uint32_t kmp = sq->kmp;
4476         uint64_t kmc = sq->kmc;
4477 
4478         if (kmp != 0)
4479                 sa->ipsa_kmp = kmp;
4480         if (kmc != 0)
4481                 sa->ipsa_kmc = kmc;
4482 }
4483 
4484 /*
4485  * Common code to update an SA.
4486  */
4487 
4488 int
4489 sadb_update_sa(mblk_t *mp, keysock_in_t *ksi, mblk_t **ipkt_lst,
4490     sadbp_t *spp, int *diagnostic, queue_t *pfkey_q,
4491     int (*add_sa_func)(mblk_t *, keysock_in_t *, int *, netstack_t *),
4492     netstack_t *ns, uint8_t sadb_msg_type)
4493 {
4494         sadb_key_t *akey = (sadb_key_t *)ksi->ks_in_extv[SADB_EXT_KEY_AUTH];
4495         sadb_key_t *ekey = (sadb_key_t *)ksi->ks_in_extv[SADB_EXT_KEY_ENCRYPT];
4496         sadb_x_replay_ctr_t *replext =
4497             (sadb_x_replay_ctr_t *)ksi->ks_in_extv[SADB_X_EXT_REPLAY_VALUE];
4498         sadb_lifetime_t *soft =
4499             (sadb_lifetime_t *)ksi->ks_in_extv[SADB_EXT_LIFETIME_SOFT];
4500         sadb_lifetime_t *hard =
4501             (sadb_lifetime_t *)ksi->ks_in_extv[SADB_EXT_LIFETIME_HARD];
4502         sadb_lifetime_t *idle =
4503             (sadb_lifetime_t *)ksi->ks_in_extv[SADB_X_EXT_LIFETIME_IDLE];
4504         sadb_x_pair_t *pair_ext =
4505             (sadb_x_pair_t *)ksi->ks_in_extv[SADB_X_EXT_PAIR];
4506         ipsa_t *echo_target = NULL;
4507         ipsap_t ipsapp;
4508         ipsa_query_t sq;
4509         time_t current = gethrestime_sec();
4510 
4511         sq.spp = spp;           /* XXX param */
4512         int error = sadb_form_query(ksi, IPSA_Q_SRC|IPSA_Q_DST|IPSA_Q_SA,
4513             IPSA_Q_SRC|IPSA_Q_DST|IPSA_Q_SA|IPSA_Q_INBOUND|IPSA_Q_OUTBOUND|
4514             IPSA_Q_KMC,
4515             &sq, diagnostic);
4516 
4517         if (error != 0)
4518                 return (error);
4519 
4520         error = get_ipsa_pair(&sq, &ipsapp, diagnostic);
4521         if (error != 0)
4522                 return (error);
4523 
4524         if (ipsapp.ipsap_psa_ptr == NULL && ipsapp.ipsap_sa_ptr != NULL) {
4525                 if (ipsapp.ipsap_sa_ptr->ipsa_state == IPSA_STATE_LARVAL) {
4526                         /*
4527                          * REFRELE the target and let the add_sa_func()
4528                          * deal with updating a larval SA.
4529                          */
4530                         destroy_ipsa_pair(&ipsapp);
4531                         return (add_sa_func(mp, ksi, diagnostic, ns));
4532                 }
4533         }
4534 


5100         return (mp);
5101 }
5102 
5103 /*
5104  * Generate a regular ACQUIRE's proposal extension and KMC information..
5105  */
5106 static mblk_t *
5107 sadb_acquire_prop(ipsec_action_t *ap, netstack_t *ns, boolean_t do_esp)
5108 {
5109         ipsec_stack_t *ipss = ns->netstack_ipsec;
5110         ipsecesp_stack_t *espstack = ns->netstack_ipsecesp;
5111         ipsecah_stack_t *ahstack = ns->netstack_ipsecah;
5112         mblk_t *mp = NULL;
5113         sadb_prop_t *prop;
5114         sadb_comb_t *comb;
5115         ipsec_action_t *walker;
5116         int ncombs, allocsize, ealgid, aalgid, aminbits, amaxbits, eminbits,
5117             emaxbits, replay;
5118         uint64_t softbytes, hardbytes, softaddtime, hardaddtime, softusetime,
5119             hardusetime;
5120         uint64_t kmc = 0;
5121         uint32_t kmp = 0;
5122 
5123         /*
5124          * Since it's an rwlock read, AND writing to the IPsec algorithms is
5125          * rare, just acquire it once up top, and drop it upon return.
5126          */
5127         rw_enter(&ipss->ipsec_alg_lock, RW_READER);
5128         if (do_esp) {
5129                 uint64_t num_aalgs, num_ealgs;
5130 
5131                 if (espstack->esp_kstats == NULL)
5132                         goto bail;
5133 
5134                 num_aalgs = ipss->ipsec_nalgs[IPSEC_ALG_AUTH];
5135                 num_ealgs = ipss->ipsec_nalgs[IPSEC_ALG_ENCR];
5136                 if (num_ealgs == 0)
5137                         goto bail;      /* IPsec not loaded yet, apparently. */
5138                 num_aalgs++;    /* No-auth or self-auth-crypto ESP. */
5139 
5140                 /* Use netstack's maximum loaded algorithms... */
5141                 ncombs = num_ealgs * num_aalgs;


5291         /* Don't include KMC extension if there's no room. */
5292         if (((kmp != 0) || (kmc != 0)) && allocsize >= sizeof (sadb_x_kmc_t)) {
5293                 if (sadb_make_kmc_ext(mp->b_wptr,
5294                     mp->b_wptr + sizeof (sadb_x_kmc_t), kmp, kmc) == NULL) {
5295                         freeb(mp);
5296                         mp = NULL;
5297                         goto bail;
5298                 }
5299                 mp->b_wptr += sizeof (sadb_x_kmc_t);
5300                 prop->sadb_prop_len += SADB_8TO64(sizeof (sadb_x_kmc_t));
5301         }
5302 
5303 bail:
5304         rw_exit(&ipss->ipsec_alg_lock);
5305         return (mp);
5306 }
5307 
5308 /*
5309  * Generate an extended ACQUIRE's extended-proposal extension.
5310  */

5311 static mblk_t *
5312 sadb_acquire_extended_prop(ipsec_action_t *ap, netstack_t *ns)
5313 {
5314         sadb_prop_t *eprop;
5315         uint8_t *cur, *end;
5316         mblk_t *mp;
5317         int allocsize, numecombs = 0, numalgdescs = 0;
5318         uint32_t kmp = 0, replay = 0;
5319         uint64_t kmc = 0;
5320         ipsec_action_t *walker;
5321 
5322         allocsize = sizeof (*eprop);
5323 
5324         /*
5325          * Going to walk through the action list twice.  Once for allocation
5326          * measurement, and once for actual construction.
5327          */
5328         for (walker = ap; walker != NULL; walker = walker->ipa_next) {
5329                 ipsec_prot_t *ipp;
5330 
5331                 /*
5332                  * Skip non-IPsec policies
5333                  */
5334                 if (walker->ipa_act.ipa_type != IPSEC_ACT_APPLY)
5335                         continue;
5336 
5337                 ipp = &walker->ipa_act.ipa_apply;
5338 
5339                 if (walker->ipa_act.ipa_apply.ipp_km_proto)