| 3222 | } |
| 3223 | |
| 3224 | static void |
| 3225 | sctp_iterator_inp_being_freed(struct sctp_inpcb *inp) |
| 3226 | { |
| 3227 | struct sctp_iterator *it, *nit; |
| 3228 | |
| 3229 | /* |
| 3230 | * We enter with the only the ITERATOR_LOCK in place and a write |
| 3231 | * lock on the inp_info stuff. |
| 3232 | */ |
| 3233 | it = sctp_it_ctl.cur_it; |
| 3234 | if (it && (it->vn != curvnet)) { |
| 3235 | /* Its not looking at our VNET */ |
| 3236 | return; |
| 3237 | } |
| 3238 | if (it && (it->inp == inp)) { |
| 3239 | /* |
| 3240 | * This is tricky and we hold the iterator lock, but when it |
| 3241 | * returns and gets the lock (when we release it) the |
| 3242 | * iterator will try to operate on inp. We need to stop that |
| 3243 | * from happening. But of course the iterator has a |
| 3244 | * reference on the stcb and inp. We can mark it and it will |
| 3245 | * stop. |
| 3246 | * |
| 3247 | * If its a single iterator situation, we set the end |
| 3248 | * iterator flag. Otherwise we set the iterator to go to the |
| 3249 | * next inp. |
| 3250 | * |
| 3251 | */ |
| 3252 | if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) { |
| 3253 | sctp_it_ctl.iterator_flags |= SCTP_ITERATOR_STOP_CUR_IT; |
| 3254 | } else { |
| 3255 | sctp_it_ctl.iterator_flags |= SCTP_ITERATOR_STOP_CUR_INP; |
| 3256 | } |
| 3257 | } |
| 3258 | /* |
| 3259 | * Now go through and remove any single reference to our inp that |
| 3260 | * may be still pending on the list |
| 3261 | */ |
| 3262 | SCTP_IPI_ITERATOR_WQ_LOCK(); |
| 3263 | TAILQ_FOREACH_SAFE(it, &sctp_it_ctl.iteratorhead, sctp_nxt_itr, nit) { |
| 3264 | if (it->vn != curvnet) { |
| 3265 | continue; |
| 3266 | } |
| 3267 | if (it->inp == inp) { |
| 3268 | /* This one points to me is it inp specific? */ |
| 3269 | if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) { |
| 3270 | /* Remove and free this one */ |
| 3271 | TAILQ_REMOVE(&sctp_it_ctl.iteratorhead, |
| 3272 | it, sctp_nxt_itr); |
| 3273 | if (it->function_atend != NULL) { |
| 3274 | (*it->function_atend) (it->pointer, it->val); |
| 3275 | } |
| 3276 | SCTP_FREE(it, SCTP_M_ITER); |
| 3277 | } else { |
| 3278 | it->inp = LIST_NEXT(it->inp, sctp_list); |
| 3279 | if (it->inp) { |
| 3280 | SCTP_INP_INCR_REF(it->inp); |
| 3281 | } |