120
121 hindex = SCTP_IPIF_ADDR_HASH(sctp_ipif->sctp_ipif_saddr,
122 sctp_ipif->sctp_ipif_isv6);
123
124 sctp_ill = sctp_ipif->sctp_ipif_ill;
125 ASSERT(sctp_ill != NULL);
126 ill_index = SCTP_ILL_HASH_FN(sctp_ill->sctp_ill_index);
127 if (sctp_ipif->sctp_ipif_state != SCTP_IPIFS_CONDEMNED ||
128 sctp_ipif->sctp_ipif_refcnt != 0) {
129 rw_exit(&sctps->sctps_g_ipifs_lock);
130 rw_exit(&sctps->sctps_g_ills_lock);
131 return;
132 }
133 list_remove(&sctps->sctps_g_ipifs[hindex].sctp_ipif_list,
134 sctp_ipif);
135 sctps->sctps_g_ipifs[hindex].ipif_count--;
136 sctps->sctps_g_ipifs_count--;
137 rw_destroy(&sctp_ipif->sctp_ipif_lock);
138 kmem_free(sctp_ipif, sizeof (sctp_ipif_t));
139
140 (void) atomic_dec_32_nv(&sctp_ill->sctp_ill_ipifcnt);
141 if (rw_tryupgrade(&sctps->sctps_g_ills_lock) != 0) {
142 rw_downgrade(&sctps->sctps_g_ipifs_lock);
143 if (sctp_ill->sctp_ill_ipifcnt == 0 &&
144 sctp_ill->sctp_ill_state == SCTP_ILLS_CONDEMNED) {
145 list_remove(&sctps->sctps_g_ills[ill_index].
146 sctp_ill_list, (void *)sctp_ill);
147 sctps->sctps_g_ills[ill_index].ill_count--;
148 sctps->sctps_ills_count--;
149 kmem_free(sctp_ill->sctp_ill_name,
150 sctp_ill->sctp_ill_name_length);
151 kmem_free(sctp_ill, sizeof (sctp_ill_t));
152 }
153 }
154 rw_exit(&sctps->sctps_g_ipifs_lock);
155 rw_exit(&sctps->sctps_g_ills_lock);
156 }
157
158 /*
159 * Lookup an SCTP IPIF given an IP address. Increments sctp_ipif refcnt.
160 * We are either looking for a IPIF with the given address before
867 ipif->ipif_ill->ill_isv6);
868 sctp_ipif = list_head(&sctps->sctps_g_ipifs[hindex].sctp_ipif_list);
869 for (i = 0; i < sctps->sctps_g_ipifs[hindex].ipif_count; i++) {
870 if (sctp_ipif->sctp_ipif_id == ipif->ipif_seqid)
871 break;
872 sctp_ipif = list_next(
873 &sctps->sctps_g_ipifs[hindex].sctp_ipif_list, sctp_ipif);
874 }
875 /* Should be an ASSERT? */
876 if (fsctp_ill == NULL || tsctp_ill == NULL || sctp_ipif == NULL) {
877 ip1dbg(("sctp_move_ipif: error moving ipif %p from %p to %p\n",
878 (void *)ipif, (void *)f_ill, (void *)t_ill));
879 rw_exit(&sctps->sctps_g_ipifs_lock);
880 rw_exit(&sctps->sctps_g_ills_lock);
881 return;
882 }
883 rw_enter(&sctp_ipif->sctp_ipif_lock, RW_WRITER);
884 ASSERT(sctp_ipif->sctp_ipif_ill == fsctp_ill);
885 sctp_ipif->sctp_ipif_ill = tsctp_ill;
886 rw_exit(&sctp_ipif->sctp_ipif_lock);
887 (void) atomic_dec_32_nv(&fsctp_ill->sctp_ill_ipifcnt);
888 atomic_inc_32(&tsctp_ill->sctp_ill_ipifcnt);
889 rw_exit(&sctps->sctps_g_ipifs_lock);
890 rw_exit(&sctps->sctps_g_ills_lock);
891 }
892
893 /*
894 * Walk the list of SCTPs and find each that has oipif in it's saddr list, and
895 * if so replace it with nipif.
896 */
897 void
898 sctp_update_saddrs(sctp_ipif_t *oipif, sctp_ipif_t *nipif, int idx,
899 sctp_stack_t *sctps)
900 {
901 sctp_t *sctp;
902 sctp_t *sctp_prev = NULL;
903 sctp_saddr_ipif_t *sobj;
904 int count;
905
906 mutex_enter(&sctps->sctps_g_lock);
907 sctp = list_head(&sctps->sctps_g_list);
1080 if (osctp_ipif->sctp_ipif_refcnt != 0) {
1081 osctp_ipif->sctp_ipif_state = SCTP_IPIFS_CONDEMNED;
1082 } else {
1083 list_t *ipif_list;
1084 int ohindex;
1085
1086 osctp_ill = osctp_ipif->sctp_ipif_ill;
1087 /* hash index for the old one */
1088 ohindex = SCTP_IPIF_ADDR_HASH(
1089 osctp_ipif->sctp_ipif_saddr,
1090 osctp_ipif->sctp_ipif_isv6);
1091
1092 ipif_list =
1093 &sctps->sctps_g_ipifs[ohindex].sctp_ipif_list;
1094
1095 list_remove(ipif_list, (void *)osctp_ipif);
1096 sctps->sctps_g_ipifs[ohindex].ipif_count--;
1097 sctps->sctps_g_ipifs_count--;
1098 rw_destroy(&osctp_ipif->sctp_ipif_lock);
1099 kmem_free(osctp_ipif, sizeof (sctp_ipif_t));
1100 (void) atomic_dec_32_nv(&osctp_ill->sctp_ill_ipifcnt);
1101 }
1102 }
1103
1104 sctp_ipif = kmem_zalloc(sizeof (sctp_ipif_t), KM_NOSLEEP);
1105 /* Try again? */
1106 if (sctp_ipif == NULL) {
1107 cmn_err(CE_WARN, "sctp_update_ipif_addr: error adding "
1108 "IPIF %p to SCTP's IPIF list", (void *)ipif);
1109 rw_exit(&sctps->sctps_g_ipifs_lock);
1110 rw_exit(&sctps->sctps_g_ills_lock);
1111 return;
1112 }
1113 sctps->sctps_g_ipifs_count++;
1114 rw_init(&sctp_ipif->sctp_ipif_lock, NULL, RW_DEFAULT, NULL);
1115 sctp_ipif->sctp_ipif_saddr = ipif->ipif_v6lcl_addr;
1116 sctp_ipif->sctp_ipif_ill = sctp_ill;
1117 sctp_ipif->sctp_ipif_isv6 = ill->ill_isv6;
1118 sctp_ipif->sctp_ipif_zoneid = ipif->ipif_zoneid;
1119 sctp_ipif->sctp_ipif_id = ipif->ipif_seqid;
1120 if (ipif->ipif_flags & IPIF_UP)
1192 ASSERT(sctp_ill == sctp_ipif->sctp_ipif_ill);
1193 switch (op) {
1194 case SCTP_IPIF_REMOVE:
1195 {
1196 list_t *ipif_list;
1197 list_t *ill_list;
1198
1199 ill_list = &sctps->sctps_g_ills[ill_index].sctp_ill_list;
1200 ipif_list = &sctps->sctps_g_ipifs[hindex].sctp_ipif_list;
1201 if (sctp_ipif->sctp_ipif_refcnt != 0) {
1202 sctp_ipif->sctp_ipif_state = SCTP_IPIFS_CONDEMNED;
1203 rw_exit(&sctps->sctps_g_ipifs_lock);
1204 rw_exit(&sctps->sctps_g_ills_lock);
1205 return;
1206 }
1207 list_remove(ipif_list, (void *)sctp_ipif);
1208 sctps->sctps_g_ipifs[hindex].ipif_count--;
1209 sctps->sctps_g_ipifs_count--;
1210 rw_destroy(&sctp_ipif->sctp_ipif_lock);
1211 kmem_free(sctp_ipif, sizeof (sctp_ipif_t));
1212 (void) atomic_dec_32_nv(&sctp_ill->sctp_ill_ipifcnt);
1213 if (rw_tryupgrade(&sctps->sctps_g_ills_lock) != 0) {
1214 rw_downgrade(&sctps->sctps_g_ipifs_lock);
1215 if (sctp_ill->sctp_ill_ipifcnt == 0 &&
1216 sctp_ill->sctp_ill_state == SCTP_ILLS_CONDEMNED) {
1217 list_remove(ill_list, (void *)sctp_ill);
1218 sctps->sctps_ills_count--;
1219 sctps->sctps_g_ills[ill_index].ill_count--;
1220 kmem_free(sctp_ill->sctp_ill_name,
1221 sctp_ill->sctp_ill_name_length);
1222 kmem_free(sctp_ill, sizeof (sctp_ill_t));
1223 }
1224 }
1225 break;
1226 }
1227
1228 case SCTP_IPIF_UP:
1229
1230 rw_downgrade(&sctps->sctps_g_ipifs_lock);
1231 rw_enter(&sctp_ipif->sctp_ipif_lock, RW_WRITER);
1232 sctp_ipif->sctp_ipif_state = SCTP_IPIFS_UP;
2012
2013 static void
2014 sctp_free_ipifs(sctp_stack_t *sctps)
2015 {
2016 int i;
2017 int l;
2018 sctp_ipif_t *sctp_ipif;
2019 sctp_ill_t *sctp_ill;
2020
2021 if (sctps->sctps_g_ipifs_count == 0)
2022 return;
2023
2024 for (i = 0; i < SCTP_IPIF_HASH; i++) {
2025 sctp_ipif = list_tail(&sctps->sctps_g_ipifs[i].sctp_ipif_list);
2026 for (l = 0; l < sctps->sctps_g_ipifs[i].ipif_count; l++) {
2027 sctp_ill = sctp_ipif->sctp_ipif_ill;
2028
2029 list_remove(&sctps->sctps_g_ipifs[i].sctp_ipif_list,
2030 sctp_ipif);
2031 sctps->sctps_g_ipifs_count--;
2032 (void) atomic_dec_32_nv(&sctp_ill->sctp_ill_ipifcnt);
2033 kmem_free(sctp_ipif, sizeof (sctp_ipif_t));
2034 sctp_ipif =
2035 list_tail(&sctps->sctps_g_ipifs[i].sctp_ipif_list);
2036 }
2037 sctps->sctps_g_ipifs[i].ipif_count = 0;
2038 }
2039 ASSERT(sctps->sctps_g_ipifs_count == 0);
2040 }
2041
2042
2043 /* Initialize the SCTP ILL list and lock */
2044 void
2045 sctp_saddr_init(sctp_stack_t *sctps)
2046 {
2047 int i;
2048
2049 sctps->sctps_g_ills = kmem_zalloc(sizeof (sctp_ill_hash_t) *
2050 SCTP_ILL_HASH, KM_SLEEP);
2051 sctps->sctps_g_ipifs = kmem_zalloc(sizeof (sctp_ipif_hash_t) *
2052 SCTP_IPIF_HASH, KM_SLEEP);
|
120
121 hindex = SCTP_IPIF_ADDR_HASH(sctp_ipif->sctp_ipif_saddr,
122 sctp_ipif->sctp_ipif_isv6);
123
124 sctp_ill = sctp_ipif->sctp_ipif_ill;
125 ASSERT(sctp_ill != NULL);
126 ill_index = SCTP_ILL_HASH_FN(sctp_ill->sctp_ill_index);
127 if (sctp_ipif->sctp_ipif_state != SCTP_IPIFS_CONDEMNED ||
128 sctp_ipif->sctp_ipif_refcnt != 0) {
129 rw_exit(&sctps->sctps_g_ipifs_lock);
130 rw_exit(&sctps->sctps_g_ills_lock);
131 return;
132 }
133 list_remove(&sctps->sctps_g_ipifs[hindex].sctp_ipif_list,
134 sctp_ipif);
135 sctps->sctps_g_ipifs[hindex].ipif_count--;
136 sctps->sctps_g_ipifs_count--;
137 rw_destroy(&sctp_ipif->sctp_ipif_lock);
138 kmem_free(sctp_ipif, sizeof (sctp_ipif_t));
139
140 atomic_dec_32(&sctp_ill->sctp_ill_ipifcnt);
141 if (rw_tryupgrade(&sctps->sctps_g_ills_lock) != 0) {
142 rw_downgrade(&sctps->sctps_g_ipifs_lock);
143 if (sctp_ill->sctp_ill_ipifcnt == 0 &&
144 sctp_ill->sctp_ill_state == SCTP_ILLS_CONDEMNED) {
145 list_remove(&sctps->sctps_g_ills[ill_index].
146 sctp_ill_list, (void *)sctp_ill);
147 sctps->sctps_g_ills[ill_index].ill_count--;
148 sctps->sctps_ills_count--;
149 kmem_free(sctp_ill->sctp_ill_name,
150 sctp_ill->sctp_ill_name_length);
151 kmem_free(sctp_ill, sizeof (sctp_ill_t));
152 }
153 }
154 rw_exit(&sctps->sctps_g_ipifs_lock);
155 rw_exit(&sctps->sctps_g_ills_lock);
156 }
157
158 /*
159 * Lookup an SCTP IPIF given an IP address. Increments sctp_ipif refcnt.
160 * We are either looking for a IPIF with the given address before
867 ipif->ipif_ill->ill_isv6);
868 sctp_ipif = list_head(&sctps->sctps_g_ipifs[hindex].sctp_ipif_list);
869 for (i = 0; i < sctps->sctps_g_ipifs[hindex].ipif_count; i++) {
870 if (sctp_ipif->sctp_ipif_id == ipif->ipif_seqid)
871 break;
872 sctp_ipif = list_next(
873 &sctps->sctps_g_ipifs[hindex].sctp_ipif_list, sctp_ipif);
874 }
875 /* Should be an ASSERT? */
876 if (fsctp_ill == NULL || tsctp_ill == NULL || sctp_ipif == NULL) {
877 ip1dbg(("sctp_move_ipif: error moving ipif %p from %p to %p\n",
878 (void *)ipif, (void *)f_ill, (void *)t_ill));
879 rw_exit(&sctps->sctps_g_ipifs_lock);
880 rw_exit(&sctps->sctps_g_ills_lock);
881 return;
882 }
883 rw_enter(&sctp_ipif->sctp_ipif_lock, RW_WRITER);
884 ASSERT(sctp_ipif->sctp_ipif_ill == fsctp_ill);
885 sctp_ipif->sctp_ipif_ill = tsctp_ill;
886 rw_exit(&sctp_ipif->sctp_ipif_lock);
887 atomic_dec_32(&fsctp_ill->sctp_ill_ipifcnt);
888 atomic_inc_32(&tsctp_ill->sctp_ill_ipifcnt);
889 rw_exit(&sctps->sctps_g_ipifs_lock);
890 rw_exit(&sctps->sctps_g_ills_lock);
891 }
892
893 /*
894 * Walk the list of SCTPs and find each that has oipif in it's saddr list, and
895 * if so replace it with nipif.
896 */
897 void
898 sctp_update_saddrs(sctp_ipif_t *oipif, sctp_ipif_t *nipif, int idx,
899 sctp_stack_t *sctps)
900 {
901 sctp_t *sctp;
902 sctp_t *sctp_prev = NULL;
903 sctp_saddr_ipif_t *sobj;
904 int count;
905
906 mutex_enter(&sctps->sctps_g_lock);
907 sctp = list_head(&sctps->sctps_g_list);
1080 if (osctp_ipif->sctp_ipif_refcnt != 0) {
1081 osctp_ipif->sctp_ipif_state = SCTP_IPIFS_CONDEMNED;
1082 } else {
1083 list_t *ipif_list;
1084 int ohindex;
1085
1086 osctp_ill = osctp_ipif->sctp_ipif_ill;
1087 /* hash index for the old one */
1088 ohindex = SCTP_IPIF_ADDR_HASH(
1089 osctp_ipif->sctp_ipif_saddr,
1090 osctp_ipif->sctp_ipif_isv6);
1091
1092 ipif_list =
1093 &sctps->sctps_g_ipifs[ohindex].sctp_ipif_list;
1094
1095 list_remove(ipif_list, (void *)osctp_ipif);
1096 sctps->sctps_g_ipifs[ohindex].ipif_count--;
1097 sctps->sctps_g_ipifs_count--;
1098 rw_destroy(&osctp_ipif->sctp_ipif_lock);
1099 kmem_free(osctp_ipif, sizeof (sctp_ipif_t));
1100 atomic_dec_32(&osctp_ill->sctp_ill_ipifcnt);
1101 }
1102 }
1103
1104 sctp_ipif = kmem_zalloc(sizeof (sctp_ipif_t), KM_NOSLEEP);
1105 /* Try again? */
1106 if (sctp_ipif == NULL) {
1107 cmn_err(CE_WARN, "sctp_update_ipif_addr: error adding "
1108 "IPIF %p to SCTP's IPIF list", (void *)ipif);
1109 rw_exit(&sctps->sctps_g_ipifs_lock);
1110 rw_exit(&sctps->sctps_g_ills_lock);
1111 return;
1112 }
1113 sctps->sctps_g_ipifs_count++;
1114 rw_init(&sctp_ipif->sctp_ipif_lock, NULL, RW_DEFAULT, NULL);
1115 sctp_ipif->sctp_ipif_saddr = ipif->ipif_v6lcl_addr;
1116 sctp_ipif->sctp_ipif_ill = sctp_ill;
1117 sctp_ipif->sctp_ipif_isv6 = ill->ill_isv6;
1118 sctp_ipif->sctp_ipif_zoneid = ipif->ipif_zoneid;
1119 sctp_ipif->sctp_ipif_id = ipif->ipif_seqid;
1120 if (ipif->ipif_flags & IPIF_UP)
1192 ASSERT(sctp_ill == sctp_ipif->sctp_ipif_ill);
1193 switch (op) {
1194 case SCTP_IPIF_REMOVE:
1195 {
1196 list_t *ipif_list;
1197 list_t *ill_list;
1198
1199 ill_list = &sctps->sctps_g_ills[ill_index].sctp_ill_list;
1200 ipif_list = &sctps->sctps_g_ipifs[hindex].sctp_ipif_list;
1201 if (sctp_ipif->sctp_ipif_refcnt != 0) {
1202 sctp_ipif->sctp_ipif_state = SCTP_IPIFS_CONDEMNED;
1203 rw_exit(&sctps->sctps_g_ipifs_lock);
1204 rw_exit(&sctps->sctps_g_ills_lock);
1205 return;
1206 }
1207 list_remove(ipif_list, (void *)sctp_ipif);
1208 sctps->sctps_g_ipifs[hindex].ipif_count--;
1209 sctps->sctps_g_ipifs_count--;
1210 rw_destroy(&sctp_ipif->sctp_ipif_lock);
1211 kmem_free(sctp_ipif, sizeof (sctp_ipif_t));
1212 atomic_dec_32(&sctp_ill->sctp_ill_ipifcnt);
1213 if (rw_tryupgrade(&sctps->sctps_g_ills_lock) != 0) {
1214 rw_downgrade(&sctps->sctps_g_ipifs_lock);
1215 if (sctp_ill->sctp_ill_ipifcnt == 0 &&
1216 sctp_ill->sctp_ill_state == SCTP_ILLS_CONDEMNED) {
1217 list_remove(ill_list, (void *)sctp_ill);
1218 sctps->sctps_ills_count--;
1219 sctps->sctps_g_ills[ill_index].ill_count--;
1220 kmem_free(sctp_ill->sctp_ill_name,
1221 sctp_ill->sctp_ill_name_length);
1222 kmem_free(sctp_ill, sizeof (sctp_ill_t));
1223 }
1224 }
1225 break;
1226 }
1227
1228 case SCTP_IPIF_UP:
1229
1230 rw_downgrade(&sctps->sctps_g_ipifs_lock);
1231 rw_enter(&sctp_ipif->sctp_ipif_lock, RW_WRITER);
1232 sctp_ipif->sctp_ipif_state = SCTP_IPIFS_UP;
2012
2013 static void
2014 sctp_free_ipifs(sctp_stack_t *sctps)
2015 {
2016 int i;
2017 int l;
2018 sctp_ipif_t *sctp_ipif;
2019 sctp_ill_t *sctp_ill;
2020
2021 if (sctps->sctps_g_ipifs_count == 0)
2022 return;
2023
2024 for (i = 0; i < SCTP_IPIF_HASH; i++) {
2025 sctp_ipif = list_tail(&sctps->sctps_g_ipifs[i].sctp_ipif_list);
2026 for (l = 0; l < sctps->sctps_g_ipifs[i].ipif_count; l++) {
2027 sctp_ill = sctp_ipif->sctp_ipif_ill;
2028
2029 list_remove(&sctps->sctps_g_ipifs[i].sctp_ipif_list,
2030 sctp_ipif);
2031 sctps->sctps_g_ipifs_count--;
2032 atomic_dec_32(&sctp_ill->sctp_ill_ipifcnt);
2033 kmem_free(sctp_ipif, sizeof (sctp_ipif_t));
2034 sctp_ipif =
2035 list_tail(&sctps->sctps_g_ipifs[i].sctp_ipif_list);
2036 }
2037 sctps->sctps_g_ipifs[i].ipif_count = 0;
2038 }
2039 ASSERT(sctps->sctps_g_ipifs_count == 0);
2040 }
2041
2042
2043 /* Initialize the SCTP ILL list and lock */
2044 void
2045 sctp_saddr_init(sctp_stack_t *sctps)
2046 {
2047 int i;
2048
2049 sctps->sctps_g_ills = kmem_zalloc(sizeof (sctp_ill_hash_t) *
2050 SCTP_ILL_HASH, KM_SLEEP);
2051 sctps->sctps_g_ipifs = kmem_zalloc(sizeof (sctp_ipif_hash_t) *
2052 SCTP_IPIF_HASH, KM_SLEEP);
|