| 3145 | } |
| 3146 | |
| 3147 | static void |
| 3148 | sctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb, |
| 3149 | uint16_t error, struct sctp_abort_chunk *abort, uint8_t from_peer, int so_locked) |
| 3150 | { |
| 3151 | struct mbuf *m_notify; |
| 3152 | struct sctp_assoc_change *sac; |
| 3153 | struct sctp_queued_to_read *control; |
| 3154 | unsigned int notif_len; |
| 3155 | uint16_t abort_len; |
| 3156 | unsigned int i; |
| 3157 | |
| 3158 | if (stcb == NULL) { |
| 3159 | return; |
| 3160 | } |
| 3161 | if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT)) { |
| 3162 | notif_len = (unsigned int)sizeof(struct sctp_assoc_change); |
| 3163 | if (abort != NULL) { |
| 3164 | abort_len = ntohs(abort->ch.chunk_length); |
| 3165 | /* |
| 3166 | * Only SCTP_CHUNK_BUFFER_SIZE are guaranteed to be |
| 3167 | * contiguous. |
| 3168 | */ |
| 3169 | if (abort_len > SCTP_CHUNK_BUFFER_SIZE) { |
| 3170 | abort_len = SCTP_CHUNK_BUFFER_SIZE; |
| 3171 | } |
| 3172 | } else { |
| 3173 | abort_len = 0; |
| 3174 | } |
| 3175 | if ((state == SCTP_COMM_UP) || (state == SCTP_RESTART)) { |
| 3176 | notif_len += SCTP_ASSOC_SUPPORTS_MAX; |
| 3177 | } else if ((state == SCTP_COMM_LOST) || (state == SCTP_CANT_STR_ASSOC)) { |
| 3178 | notif_len += abort_len; |
| 3179 | } |
| 3180 | m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_NOWAIT, 1, MT_DATA); |
| 3181 | if (m_notify == NULL) { |
| 3182 | /* Retry with smaller value. */ |
| 3183 | notif_len = (unsigned int)sizeof(struct sctp_assoc_change); |
| 3184 | m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_NOWAIT, 1, MT_DATA); |
| 3185 | if (m_notify == NULL) { |
| 3186 | goto set_error; |
| 3187 | } |
| 3188 | } |
| 3189 | SCTP_BUF_NEXT(m_notify) = NULL; |
| 3190 | sac = mtod(m_notify, struct sctp_assoc_change *); |
| 3191 | memset(sac, 0, notif_len); |
| 3192 | sac->sac_type = SCTP_ASSOC_CHANGE; |
| 3193 | sac->sac_flags = 0; |
| 3194 | sac->sac_length = sizeof(struct sctp_assoc_change); |
| 3195 | sac->sac_state = state; |
| 3196 | sac->sac_error = error; |
| 3197 | /* XXX verify these stream counts */ |
| 3198 | sac->sac_outbound_streams = stcb->asoc.streamoutcnt; |
| 3199 | sac->sac_inbound_streams = stcb->asoc.streamincnt; |
| 3200 | sac->sac_assoc_id = sctp_get_associd(stcb); |
| 3201 | if (notif_len > sizeof(struct sctp_assoc_change)) { |
| 3202 | if ((state == SCTP_COMM_UP) || (state == SCTP_RESTART)) { |
| 3203 | i = 0; |
| 3204 | if (stcb->asoc.prsctp_supported == 1) { |
no test coverage detected