| 3981 | } |
| 3982 | |
| 3983 | static void |
| 3984 | sctp_notify_remote_error(struct sctp_tcb *stcb, uint16_t error, struct sctp_error_chunk *chunk) |
| 3985 | { |
| 3986 | struct mbuf *m_notify; |
| 3987 | struct sctp_remote_error *sre; |
| 3988 | struct sctp_queued_to_read *control; |
| 3989 | unsigned int notif_len; |
| 3990 | uint16_t chunk_len; |
| 3991 | |
| 3992 | if ((stcb == NULL) || |
| 3993 | sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVPEERERR)) { |
| 3994 | return; |
| 3995 | } |
| 3996 | if (chunk != NULL) { |
| 3997 | chunk_len = ntohs(chunk->ch.chunk_length); |
| 3998 | /* |
| 3999 | * Only SCTP_CHUNK_BUFFER_SIZE are guaranteed to be |
| 4000 | * contiguous. |
| 4001 | */ |
| 4002 | if (chunk_len > SCTP_CHUNK_BUFFER_SIZE) { |
| 4003 | chunk_len = SCTP_CHUNK_BUFFER_SIZE; |
| 4004 | } |
| 4005 | } else { |
| 4006 | chunk_len = 0; |
| 4007 | } |
| 4008 | notif_len = (unsigned int)(sizeof(struct sctp_remote_error) + chunk_len); |
| 4009 | m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_NOWAIT, 1, MT_DATA); |
| 4010 | if (m_notify == NULL) { |
| 4011 | /* Retry with smaller value. */ |
| 4012 | notif_len = (unsigned int)sizeof(struct sctp_remote_error); |
| 4013 | m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_NOWAIT, 1, MT_DATA); |
| 4014 | if (m_notify == NULL) { |
| 4015 | return; |
| 4016 | } |
| 4017 | } |
| 4018 | SCTP_BUF_NEXT(m_notify) = NULL; |
| 4019 | sre = mtod(m_notify, struct sctp_remote_error *); |
| 4020 | memset(sre, 0, notif_len); |
| 4021 | sre->sre_type = SCTP_REMOTE_ERROR; |
| 4022 | sre->sre_flags = 0; |
| 4023 | sre->sre_length = sizeof(struct sctp_remote_error); |
| 4024 | sre->sre_error = error; |
| 4025 | sre->sre_assoc_id = sctp_get_associd(stcb); |
| 4026 | if (notif_len > sizeof(struct sctp_remote_error)) { |
| 4027 | memcpy(sre->sre_data, chunk, chunk_len); |
| 4028 | sre->sre_length += chunk_len; |
| 4029 | } |
| 4030 | SCTP_BUF_LEN(m_notify) = sre->sre_length; |
| 4031 | control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, |
| 4032 | 0, 0, stcb->asoc.context, 0, 0, 0, |
| 4033 | m_notify); |
| 4034 | if (control != NULL) { |
| 4035 | control->length = SCTP_BUF_LEN(m_notify); |
| 4036 | control->spec_flags = M_NOTIFICATION; |
| 4037 | /* not that we need this */ |
| 4038 | control->tail_mbuf = m_notify; |
| 4039 | sctp_add_to_readq(stcb->sctp_ep, stcb, |
| 4040 | control, |
no test coverage detected