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)
|