4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #include <sys/types.h>
27 #include <sys/stream.h>
28 #include <sys/stropts.h>
29 #include <sys/errno.h>
30 #include <sys/strlog.h>
31 #include <sys/tihdr.h>
32 #include <sys/socket.h>
33 #include <sys/ddi.h>
34 #include <sys/sunddi.h>
35 #include <sys/mkdev.h>
36 #include <sys/kmem.h>
37 #include <sys/zone.h>
38 #include <sys/sysmacros.h>
39 #include <sys/cmn_err.h>
40 #include <sys/vtrace.h>
41 #include <sys/debug.h>
42 #include <sys/atomic.h>
43 #include <sys/strsun.h>
230 netstackid_t stackid = (netstackid_t)(uintptr_t)kp->ks_private;
231 netstack_t *ns;
232 ipsec_stack_t *ipss;
233
234 if ((kp == NULL) || (kp->ks_data == NULL))
235 return (EIO);
236
237 if (rw == KSTAT_WRITE)
238 return (EACCES);
239
240 ns = netstack_find_by_stackid(stackid);
241 if (ns == NULL)
242 return (-1);
243 ipss = ns->netstack_ipsec;
244 if (ipss == NULL) {
245 netstack_rele(ns);
246 return (-1);
247 }
248 ekp = (ah_kstats_t *)kp->ks_data;
249
250 mutex_enter(&ipss->ipsec_alg_lock);
251 ekp->ah_stat_num_aalgs.value.ui64 = ipss->ipsec_nalgs[IPSEC_ALG_AUTH];
252 mutex_exit(&ipss->ipsec_alg_lock);
253
254 netstack_rele(ns);
255 return (0);
256 }
257
258 /*
259 * Don't have to lock ipsec_age_interval, as only one thread will access it at
260 * a time, because I control the one function that does a qtimeout() on
261 * ah_pfkey_q.
262 */
263 static void
264 ah_ager(void *arg)
265 {
266 ipsecah_stack_t *ahstack = (ipsecah_stack_t *)arg;
267 netstack_t *ns = ahstack->ipsecah_netstack;
268 hrtime_t begin = gethrtime();
269
270 sadb_ager(&ahstack->ah_sadb.s_v4, ahstack->ah_pfkey_q,
271 ahstack->ipsecah_reap_delay, ns);
272 sadb_ager(&ahstack->ah_sadb.s_v6, ahstack->ah_pfkey_q,
556 mp = sadb_keysock_out(serial);
557 if (mp == NULL) {
558 ah0dbg(("ah_register_out: couldn't allocate mblk.\n"));
559 return (B_FALSE);
560 }
561
562 if (is_system_labeled() && (cr != NULL)) {
563 sens_tsl = crgetlabel(cr);
564 if (sens_tsl != NULL) {
565 sens_len = sadb_sens_len_from_label(sens_tsl);
566 allocsize += sens_len;
567 }
568 }
569
570 /*
571 * Allocate the PF_KEY message that follows KEYSOCK_OUT.
572 * The alg reader lock needs to be held while allocating
573 * the variable part (i.e. the algorithms) of the message.
574 */
575
576 mutex_enter(&ipss->ipsec_alg_lock);
577
578 /*
579 * Return only valid algorithms, so the number of algorithms
580 * to send up may be less than the number of algorithm entries
581 * in the table.
582 */
583 authalgs = ipss->ipsec_alglists[IPSEC_ALG_AUTH];
584 for (num_aalgs = 0, i = 0; i < IPSEC_MAX_ALGS; i++)
585 if (authalgs[i] != NULL && ALG_VALID(authalgs[i]))
586 num_aalgs++;
587
588 /*
589 * Fill SADB_REGISTER message's algorithm descriptors. Hold
590 * down the lock while filling it.
591 */
592 if (num_aalgs != 0) {
593 allocsize += (num_aalgs * sizeof (*saalg));
594 allocsize += sizeof (*sasupp);
595 }
596 mp->b_cont = allocb(allocsize, BPRI_HI);
597 if (mp->b_cont == NULL) {
598 mutex_exit(&ipss->ipsec_alg_lock);
599 freemsg(mp);
600 return (B_FALSE);
601 }
602
603 mp->b_cont->b_wptr += allocsize;
604 nextext = (sadb_ext_t *)(mp->b_cont->b_rptr + sizeof (*samsg));
605
606 if (num_aalgs != 0) {
607
608 saalg = (sadb_alg_t *)(((uint8_t *)nextext) + sizeof (*sasupp));
609 ASSERT(((ulong_t)saalg & 0x7) == 0);
610
611 numalgs_snap = 0;
612 for (i = 0;
613 ((i < IPSEC_MAX_ALGS) && (numalgs_snap < num_aalgs));
614 i++) {
615 if (authalgs[i] == NULL || !ALG_VALID(authalgs[i]))
616 continue;
617
618 saalg->sadb_alg_id = authalgs[i]->alg_id;
625 ASSERT(authalgs[i]->alg_saltlen == 0);
626 saalg->sadb_x_alg_saltbits =
627 SADB_8TO1(authalgs[i]->alg_saltlen);
628 numalgs_snap++;
629 saalg++;
630 }
631 ASSERT(numalgs_snap == num_aalgs);
632 #ifdef DEBUG
633 /*
634 * Reality check to make sure I snagged all of the
635 * algorithms.
636 */
637 for (; i < IPSEC_MAX_ALGS; i++)
638 if (authalgs[i] != NULL && ALG_VALID(authalgs[i]))
639 cmn_err(CE_PANIC,
640 "ah_register_out()! Missed #%d.\n", i);
641 #endif /* DEBUG */
642 nextext = (sadb_ext_t *)saalg;
643 }
644
645 mutex_exit(&ipss->ipsec_alg_lock);
646
647 if (sens_tsl != NULL) {
648 sens = (sadb_sens_t *)nextext;
649 sadb_sens_from_label(sens, SADB_EXT_SENSITIVITY,
650 sens_tsl, sens_len);
651
652 nextext = (sadb_ext_t *)(((uint8_t *)sens) + sens_len);
653 }
654
655 /* Now fill the restof the SADB_REGISTER message. */
656
657 samsg = (sadb_msg_t *)mp->b_cont->b_rptr;
658 samsg->sadb_msg_version = PF_KEY_V2;
659 samsg->sadb_msg_type = SADB_REGISTER;
660 samsg->sadb_msg_errno = 0;
661 samsg->sadb_msg_satype = SADB_SATYPE_AH;
662 samsg->sadb_msg_len = SADB_8TO64(allocsize);
663 samsg->sadb_msg_reserved = 0;
664 /*
665 * Assume caller has sufficient sequence/pid number info. If it's one
1106 /* Stuff I don't support, for now. XXX Diagnostic? */
1107 if (ksi->ks_in_extv[SADB_EXT_LIFETIME_CURRENT] != NULL)
1108 return (EOPNOTSUPP);
1109
1110 if (ksi->ks_in_extv[SADB_EXT_SENSITIVITY] != NULL) {
1111 if (!is_system_labeled())
1112 return (EOPNOTSUPP);
1113 }
1114
1115 if (ksi->ks_in_extv[SADB_X_EXT_OUTER_SENS] != NULL) {
1116 if (!is_system_labeled())
1117 return (EOPNOTSUPP);
1118 }
1119 /*
1120 * XXX Policy : I'm not checking identities at this time, but
1121 * if I did, I'd do them here, before I sent the weak key
1122 * check up to the algorithm.
1123 */
1124
1125 /* verify that there is a mapping for the specified algorithm */
1126 mutex_enter(&ipss->ipsec_alg_lock);
1127 aalg = ipss->ipsec_alglists[IPSEC_ALG_AUTH][assoc->sadb_sa_auth];
1128 if (aalg == NULL || !ALG_VALID(aalg)) {
1129 mutex_exit(&ipss->ipsec_alg_lock);
1130 ah1dbg(ahstack, ("Couldn't find auth alg #%d.\n",
1131 assoc->sadb_sa_auth));
1132 *diagnostic = SADB_X_DIAGNOSTIC_BAD_AALG;
1133 return (EINVAL);
1134 }
1135 ASSERT(aalg->alg_mech_type != CRYPTO_MECHANISM_INVALID);
1136
1137 /* sanity check key sizes */
1138 if (!ipsec_valid_key_size(key->sadb_key_bits, aalg)) {
1139 mutex_exit(&ipss->ipsec_alg_lock);
1140 *diagnostic = SADB_X_DIAGNOSTIC_BAD_AKEYBITS;
1141 return (EINVAL);
1142 }
1143
1144 /* check key and fix parity if needed */
1145 if (ipsec_check_key(aalg->alg_mech_type, key, B_TRUE,
1146 diagnostic) != 0) {
1147 mutex_exit(&ipss->ipsec_alg_lock);
1148 return (EINVAL);
1149 }
1150
1151 mutex_exit(&ipss->ipsec_alg_lock);
1152
1153 return (ah_add_sa_finish(mp, (sadb_msg_t *)mp->b_cont->b_rptr, ksi,
1154 diagnostic, ahstack));
1155 }
1156
1157 /* Refactor me */
1158 /*
1159 * Update a security association. Updates come in two varieties. The first
1160 * is an update of lifetimes on a non-larval SA. The second is an update of
1161 * a larval SA, which ends up looking a lot more like an add.
1162 */
1163 static int
1164 ah_update_sa(mblk_t *mp, keysock_in_t *ksi, int *diagnostic,
1165 ipsecah_stack_t *ahstack, uint8_t sadb_msg_type)
1166 {
1167 sadb_sa_t *assoc = (sadb_sa_t *)ksi->ks_in_extv[SADB_EXT_SA];
1168 sadb_address_t *dstext =
1169 (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_DST];
1170 mblk_t *buf_pkt;
1171 int rcode;
1732 IPSA_REFRELE(inassoc);
1733 }
1734
1735 return (inrc && outrc);
1736 }
1737
1738 /*
1739 * Perform the really difficult work of inserting the proposed situation.
1740 * Called while holding the algorithm lock.
1741 */
1742 static void
1743 ah_insert_prop(sadb_prop_t *prop, ipsacq_t *acqrec, uint_t combs,
1744 netstack_t *ns)
1745 {
1746 sadb_comb_t *comb = (sadb_comb_t *)(prop + 1);
1747 ipsec_action_t *ap;
1748 ipsec_prot_t *prot;
1749 ipsecah_stack_t *ahstack = ns->netstack_ipsecah;
1750 ipsec_stack_t *ipss = ns->netstack_ipsec;
1751
1752 ASSERT(MUTEX_HELD(&ipss->ipsec_alg_lock));
1753
1754 prop->sadb_prop_exttype = SADB_EXT_PROPOSAL;
1755 prop->sadb_prop_len = SADB_8TO64(sizeof (sadb_prop_t));
1756 *(uint32_t *)(&prop->sadb_prop_replay) = 0; /* Quick zero-out! */
1757
1758 prop->sadb_prop_replay = ahstack->ipsecah_replay_size;
1759
1760 /*
1761 * Based upon algorithm properties, and what-not, prioritize a
1762 * proposal, based on the ordering of the AH algorithms in the
1763 * alternatives in the policy rule or socket that was placed
1764 * in the acquire record.
1765 */
1766
1767 for (ap = acqrec->ipsacq_act; ap != NULL;
1768 ap = ap->ipa_next) {
1769 ipsec_alginfo_t *aalg;
1770
1771 if ((ap->ipa_act.ipa_type != IPSEC_POLICY_APPLY) ||
1772 (!ap->ipa_act.ipa_apply.ipp_use_ah))
1844 sadb_prop_t *prop;
1845 mblk_t *pfkeymp, *msgmp;
1846 ipsecah_stack_t *ahstack = ns->netstack_ipsecah;
1847 ipsec_stack_t *ipss = ns->netstack_ipsec;
1848
1849 AH_BUMP_STAT(ahstack, acquire_requests);
1850
1851 if (ahstack->ah_pfkey_q == NULL) {
1852 mutex_exit(&acqrec->ipsacq_lock);
1853 return;
1854 }
1855
1856 /* Set up ACQUIRE. */
1857 pfkeymp = sadb_setup_acquire(acqrec, SADB_SATYPE_AH,
1858 ns->netstack_ipsec);
1859 if (pfkeymp == NULL) {
1860 ah0dbg(("sadb_setup_acquire failed.\n"));
1861 mutex_exit(&acqrec->ipsacq_lock);
1862 return;
1863 }
1864 ASSERT(MUTEX_HELD(&ipss->ipsec_alg_lock));
1865 combs = ipss->ipsec_nalgs[IPSEC_ALG_AUTH];
1866 msgmp = pfkeymp->b_cont;
1867 samsg = (sadb_msg_t *)(msgmp->b_rptr);
1868
1869 /* Insert proposal here. */
1870
1871 prop = (sadb_prop_t *)(((uint64_t *)samsg) + samsg->sadb_msg_len);
1872 ah_insert_prop(prop, acqrec, combs, ns);
1873 samsg->sadb_msg_len += prop->sadb_prop_len;
1874 msgmp->b_wptr += SADB_64TO8(samsg->sadb_msg_len);
1875
1876 mutex_exit(&ipss->ipsec_alg_lock);
1877
1878 /*
1879 * Must mutex_exit() before sending PF_KEY message up, in
1880 * order to avoid recursive mutex_enter() if there are no registered
1881 * listeners.
1882 *
1883 * Once I've sent the message, I'm cool anyway.
1884 */
1885 mutex_exit(&acqrec->ipsacq_lock);
1886 if (extended != NULL) {
1887 putnext(ahstack->ah_pfkey_q, extended);
1888 }
1889 putnext(ahstack->ah_pfkey_q, pfkeymp);
1890 }
1891
1892 /* Refactor me */
1893 /*
1894 * Handle the SADB_GETSPI message. Create a larval SA.
1895 */
1896 static void
|
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright (c) 2012 Nexenta Systems, Inc. All rights reserved.
25 */
26
27 #include <sys/types.h>
28 #include <sys/stream.h>
29 #include <sys/stropts.h>
30 #include <sys/errno.h>
31 #include <sys/strlog.h>
32 #include <sys/tihdr.h>
33 #include <sys/socket.h>
34 #include <sys/ddi.h>
35 #include <sys/sunddi.h>
36 #include <sys/mkdev.h>
37 #include <sys/kmem.h>
38 #include <sys/zone.h>
39 #include <sys/sysmacros.h>
40 #include <sys/cmn_err.h>
41 #include <sys/vtrace.h>
42 #include <sys/debug.h>
43 #include <sys/atomic.h>
44 #include <sys/strsun.h>
231 netstackid_t stackid = (netstackid_t)(uintptr_t)kp->ks_private;
232 netstack_t *ns;
233 ipsec_stack_t *ipss;
234
235 if ((kp == NULL) || (kp->ks_data == NULL))
236 return (EIO);
237
238 if (rw == KSTAT_WRITE)
239 return (EACCES);
240
241 ns = netstack_find_by_stackid(stackid);
242 if (ns == NULL)
243 return (-1);
244 ipss = ns->netstack_ipsec;
245 if (ipss == NULL) {
246 netstack_rele(ns);
247 return (-1);
248 }
249 ekp = (ah_kstats_t *)kp->ks_data;
250
251 rw_enter(&ipss->ipsec_alg_lock, RW_READER);
252 ekp->ah_stat_num_aalgs.value.ui64 = ipss->ipsec_nalgs[IPSEC_ALG_AUTH];
253 rw_exit(&ipss->ipsec_alg_lock);
254
255 netstack_rele(ns);
256 return (0);
257 }
258
259 /*
260 * Don't have to lock ipsec_age_interval, as only one thread will access it at
261 * a time, because I control the one function that does a qtimeout() on
262 * ah_pfkey_q.
263 */
264 static void
265 ah_ager(void *arg)
266 {
267 ipsecah_stack_t *ahstack = (ipsecah_stack_t *)arg;
268 netstack_t *ns = ahstack->ipsecah_netstack;
269 hrtime_t begin = gethrtime();
270
271 sadb_ager(&ahstack->ah_sadb.s_v4, ahstack->ah_pfkey_q,
272 ahstack->ipsecah_reap_delay, ns);
273 sadb_ager(&ahstack->ah_sadb.s_v6, ahstack->ah_pfkey_q,
557 mp = sadb_keysock_out(serial);
558 if (mp == NULL) {
559 ah0dbg(("ah_register_out: couldn't allocate mblk.\n"));
560 return (B_FALSE);
561 }
562
563 if (is_system_labeled() && (cr != NULL)) {
564 sens_tsl = crgetlabel(cr);
565 if (sens_tsl != NULL) {
566 sens_len = sadb_sens_len_from_label(sens_tsl);
567 allocsize += sens_len;
568 }
569 }
570
571 /*
572 * Allocate the PF_KEY message that follows KEYSOCK_OUT.
573 * The alg reader lock needs to be held while allocating
574 * the variable part (i.e. the algorithms) of the message.
575 */
576
577 rw_enter(&ipss->ipsec_alg_lock, RW_READER);
578
579 /*
580 * Return only valid algorithms, so the number of algorithms
581 * to send up may be less than the number of algorithm entries
582 * in the table.
583 */
584 authalgs = ipss->ipsec_alglists[IPSEC_ALG_AUTH];
585 for (num_aalgs = 0, i = 0; i < IPSEC_MAX_ALGS; i++)
586 if (authalgs[i] != NULL && ALG_VALID(authalgs[i]))
587 num_aalgs++;
588
589 /*
590 * Fill SADB_REGISTER message's algorithm descriptors. Hold
591 * down the lock while filling it.
592 */
593 if (num_aalgs != 0) {
594 allocsize += (num_aalgs * sizeof (*saalg));
595 allocsize += sizeof (*sasupp);
596 }
597 mp->b_cont = allocb(allocsize, BPRI_HI);
598 if (mp->b_cont == NULL) {
599 rw_exit(&ipss->ipsec_alg_lock);
600 freemsg(mp);
601 return (B_FALSE);
602 }
603
604 mp->b_cont->b_wptr += allocsize;
605 nextext = (sadb_ext_t *)(mp->b_cont->b_rptr + sizeof (*samsg));
606
607 if (num_aalgs != 0) {
608
609 saalg = (sadb_alg_t *)(((uint8_t *)nextext) + sizeof (*sasupp));
610 ASSERT(((ulong_t)saalg & 0x7) == 0);
611
612 numalgs_snap = 0;
613 for (i = 0;
614 ((i < IPSEC_MAX_ALGS) && (numalgs_snap < num_aalgs));
615 i++) {
616 if (authalgs[i] == NULL || !ALG_VALID(authalgs[i]))
617 continue;
618
619 saalg->sadb_alg_id = authalgs[i]->alg_id;
626 ASSERT(authalgs[i]->alg_saltlen == 0);
627 saalg->sadb_x_alg_saltbits =
628 SADB_8TO1(authalgs[i]->alg_saltlen);
629 numalgs_snap++;
630 saalg++;
631 }
632 ASSERT(numalgs_snap == num_aalgs);
633 #ifdef DEBUG
634 /*
635 * Reality check to make sure I snagged all of the
636 * algorithms.
637 */
638 for (; i < IPSEC_MAX_ALGS; i++)
639 if (authalgs[i] != NULL && ALG_VALID(authalgs[i]))
640 cmn_err(CE_PANIC,
641 "ah_register_out()! Missed #%d.\n", i);
642 #endif /* DEBUG */
643 nextext = (sadb_ext_t *)saalg;
644 }
645
646 rw_exit(&ipss->ipsec_alg_lock);
647
648 if (sens_tsl != NULL) {
649 sens = (sadb_sens_t *)nextext;
650 sadb_sens_from_label(sens, SADB_EXT_SENSITIVITY,
651 sens_tsl, sens_len);
652
653 nextext = (sadb_ext_t *)(((uint8_t *)sens) + sens_len);
654 }
655
656 /* Now fill the restof the SADB_REGISTER message. */
657
658 samsg = (sadb_msg_t *)mp->b_cont->b_rptr;
659 samsg->sadb_msg_version = PF_KEY_V2;
660 samsg->sadb_msg_type = SADB_REGISTER;
661 samsg->sadb_msg_errno = 0;
662 samsg->sadb_msg_satype = SADB_SATYPE_AH;
663 samsg->sadb_msg_len = SADB_8TO64(allocsize);
664 samsg->sadb_msg_reserved = 0;
665 /*
666 * Assume caller has sufficient sequence/pid number info. If it's one
1107 /* Stuff I don't support, for now. XXX Diagnostic? */
1108 if (ksi->ks_in_extv[SADB_EXT_LIFETIME_CURRENT] != NULL)
1109 return (EOPNOTSUPP);
1110
1111 if (ksi->ks_in_extv[SADB_EXT_SENSITIVITY] != NULL) {
1112 if (!is_system_labeled())
1113 return (EOPNOTSUPP);
1114 }
1115
1116 if (ksi->ks_in_extv[SADB_X_EXT_OUTER_SENS] != NULL) {
1117 if (!is_system_labeled())
1118 return (EOPNOTSUPP);
1119 }
1120 /*
1121 * XXX Policy : I'm not checking identities at this time, but
1122 * if I did, I'd do them here, before I sent the weak key
1123 * check up to the algorithm.
1124 */
1125
1126 /* verify that there is a mapping for the specified algorithm */
1127 rw_enter(&ipss->ipsec_alg_lock, RW_READER);
1128 aalg = ipss->ipsec_alglists[IPSEC_ALG_AUTH][assoc->sadb_sa_auth];
1129 if (aalg == NULL || !ALG_VALID(aalg)) {
1130 rw_exit(&ipss->ipsec_alg_lock);
1131 ah1dbg(ahstack, ("Couldn't find auth alg #%d.\n",
1132 assoc->sadb_sa_auth));
1133 *diagnostic = SADB_X_DIAGNOSTIC_BAD_AALG;
1134 return (EINVAL);
1135 }
1136 ASSERT(aalg->alg_mech_type != CRYPTO_MECHANISM_INVALID);
1137
1138 /* sanity check key sizes */
1139 if (!ipsec_valid_key_size(key->sadb_key_bits, aalg)) {
1140 rw_exit(&ipss->ipsec_alg_lock);
1141 *diagnostic = SADB_X_DIAGNOSTIC_BAD_AKEYBITS;
1142 return (EINVAL);
1143 }
1144
1145 /* check key and fix parity if needed */
1146 if (ipsec_check_key(aalg->alg_mech_type, key, B_TRUE,
1147 diagnostic) != 0) {
1148 rw_exit(&ipss->ipsec_alg_lock);
1149 return (EINVAL);
1150 }
1151
1152 rw_exit(&ipss->ipsec_alg_lock);
1153
1154 return (ah_add_sa_finish(mp, (sadb_msg_t *)mp->b_cont->b_rptr, ksi,
1155 diagnostic, ahstack));
1156 }
1157
1158 /* Refactor me */
1159 /*
1160 * Update a security association. Updates come in two varieties. The first
1161 * is an update of lifetimes on a non-larval SA. The second is an update of
1162 * a larval SA, which ends up looking a lot more like an add.
1163 */
1164 static int
1165 ah_update_sa(mblk_t *mp, keysock_in_t *ksi, int *diagnostic,
1166 ipsecah_stack_t *ahstack, uint8_t sadb_msg_type)
1167 {
1168 sadb_sa_t *assoc = (sadb_sa_t *)ksi->ks_in_extv[SADB_EXT_SA];
1169 sadb_address_t *dstext =
1170 (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_DST];
1171 mblk_t *buf_pkt;
1172 int rcode;
1733 IPSA_REFRELE(inassoc);
1734 }
1735
1736 return (inrc && outrc);
1737 }
1738
1739 /*
1740 * Perform the really difficult work of inserting the proposed situation.
1741 * Called while holding the algorithm lock.
1742 */
1743 static void
1744 ah_insert_prop(sadb_prop_t *prop, ipsacq_t *acqrec, uint_t combs,
1745 netstack_t *ns)
1746 {
1747 sadb_comb_t *comb = (sadb_comb_t *)(prop + 1);
1748 ipsec_action_t *ap;
1749 ipsec_prot_t *prot;
1750 ipsecah_stack_t *ahstack = ns->netstack_ipsecah;
1751 ipsec_stack_t *ipss = ns->netstack_ipsec;
1752
1753 ASSERT(RW_READ_HELD(&ipss->ipsec_alg_lock));
1754
1755 prop->sadb_prop_exttype = SADB_EXT_PROPOSAL;
1756 prop->sadb_prop_len = SADB_8TO64(sizeof (sadb_prop_t));
1757 *(uint32_t *)(&prop->sadb_prop_replay) = 0; /* Quick zero-out! */
1758
1759 prop->sadb_prop_replay = ahstack->ipsecah_replay_size;
1760
1761 /*
1762 * Based upon algorithm properties, and what-not, prioritize a
1763 * proposal, based on the ordering of the AH algorithms in the
1764 * alternatives in the policy rule or socket that was placed
1765 * in the acquire record.
1766 */
1767
1768 for (ap = acqrec->ipsacq_act; ap != NULL;
1769 ap = ap->ipa_next) {
1770 ipsec_alginfo_t *aalg;
1771
1772 if ((ap->ipa_act.ipa_type != IPSEC_POLICY_APPLY) ||
1773 (!ap->ipa_act.ipa_apply.ipp_use_ah))
1845 sadb_prop_t *prop;
1846 mblk_t *pfkeymp, *msgmp;
1847 ipsecah_stack_t *ahstack = ns->netstack_ipsecah;
1848 ipsec_stack_t *ipss = ns->netstack_ipsec;
1849
1850 AH_BUMP_STAT(ahstack, acquire_requests);
1851
1852 if (ahstack->ah_pfkey_q == NULL) {
1853 mutex_exit(&acqrec->ipsacq_lock);
1854 return;
1855 }
1856
1857 /* Set up ACQUIRE. */
1858 pfkeymp = sadb_setup_acquire(acqrec, SADB_SATYPE_AH,
1859 ns->netstack_ipsec);
1860 if (pfkeymp == NULL) {
1861 ah0dbg(("sadb_setup_acquire failed.\n"));
1862 mutex_exit(&acqrec->ipsacq_lock);
1863 return;
1864 }
1865 ASSERT(RW_READ_HELD(&ipss->ipsec_alg_lock));
1866 combs = ipss->ipsec_nalgs[IPSEC_ALG_AUTH];
1867 msgmp = pfkeymp->b_cont;
1868 samsg = (sadb_msg_t *)(msgmp->b_rptr);
1869
1870 /* Insert proposal here. */
1871
1872 prop = (sadb_prop_t *)(((uint64_t *)samsg) + samsg->sadb_msg_len);
1873 ah_insert_prop(prop, acqrec, combs, ns);
1874 samsg->sadb_msg_len += prop->sadb_prop_len;
1875 msgmp->b_wptr += SADB_64TO8(samsg->sadb_msg_len);
1876
1877 rw_exit(&ipss->ipsec_alg_lock);
1878
1879 /*
1880 * Must mutex_exit() before sending PF_KEY message up, in
1881 * order to avoid recursive mutex_enter() if there are no registered
1882 * listeners.
1883 *
1884 * Once I've sent the message, I'm cool anyway.
1885 */
1886 mutex_exit(&acqrec->ipsacq_lock);
1887 if (extended != NULL) {
1888 putnext(ahstack->ah_pfkey_q, extended);
1889 }
1890 putnext(ahstack->ah_pfkey_q, pfkeymp);
1891 }
1892
1893 /* Refactor me */
1894 /*
1895 * Handle the SADB_GETSPI message. Create a larval SA.
1896 */
1897 static void
|