This patch fixes two bugs related to the SCTP message recovery
for messages which have been put on the send queue: * Do not report any DATA or I-DATA chunk padding. * Correctly deal with the I-DATA chunk header instead of the DATA chunk header when the I-DATA extension is used. Approved by: re (kib) MFC after: 1 week
This commit is contained in:
parent
6ee52c658c
commit
ab3373140d
@ -2933,7 +2933,8 @@ sctp_notify_send_failed(struct sctp_tcb *stcb, uint8_t sent, uint32_t error,
|
||||
struct sctp_send_failed *ssf;
|
||||
struct sctp_send_failed_event *ssfe;
|
||||
struct sctp_queued_to_read *control;
|
||||
int length;
|
||||
struct sctp_chunkhdr *chkhdr;
|
||||
int notifhdr_len, chk_len, chkhdr_len, padding_len, payload_len;
|
||||
|
||||
if ((stcb == NULL) ||
|
||||
(sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT) &&
|
||||
@ -2942,27 +2943,49 @@ sctp_notify_send_failed(struct sctp_tcb *stcb, uint8_t sent, uint32_t error,
|
||||
return;
|
||||
}
|
||||
if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) {
|
||||
length = sizeof(struct sctp_send_failed_event);
|
||||
notifhdr_len = sizeof(struct sctp_send_failed_event);
|
||||
} else {
|
||||
length = sizeof(struct sctp_send_failed);
|
||||
notifhdr_len = sizeof(struct sctp_send_failed);
|
||||
}
|
||||
m_notify = sctp_get_mbuf_for_msg(length, 0, M_NOWAIT, 1, MT_DATA);
|
||||
m_notify = sctp_get_mbuf_for_msg(notifhdr_len, 0, M_NOWAIT, 1, MT_DATA);
|
||||
if (m_notify == NULL)
|
||||
/* no space left */
|
||||
return;
|
||||
SCTP_BUF_LEN(m_notify) = 0;
|
||||
SCTP_BUF_LEN(m_notify) = notifhdr_len;
|
||||
if (stcb->asoc.idata_supported) {
|
||||
chkhdr_len = sizeof(struct sctp_idata_chunk);
|
||||
} else {
|
||||
chkhdr_len = sizeof(struct sctp_data_chunk);
|
||||
}
|
||||
/* Use some defaults in case we can't access the chunk header */
|
||||
if (chk->send_size >= chkhdr_len) {
|
||||
payload_len = chk->send_size - chkhdr_len;
|
||||
} else {
|
||||
payload_len = 0;
|
||||
}
|
||||
padding_len = 0;
|
||||
if (chk->data != NULL) {
|
||||
chkhdr = mtod(chk->data, struct sctp_chunkhdr *);
|
||||
if (chkhdr != NULL) {
|
||||
chk_len = ntohs(chkhdr->chunk_length);
|
||||
if ((chk_len >= chkhdr_len) &&
|
||||
(chk->send_size >= chk_len) &&
|
||||
(chk->send_size - chk_len < 4)) {
|
||||
padding_len = chk->send_size - chk_len;
|
||||
payload_len = chk->send_size - chkhdr_len - padding_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) {
|
||||
ssfe = mtod(m_notify, struct sctp_send_failed_event *);
|
||||
memset(ssfe, 0, length);
|
||||
memset(ssfe, 0, notifhdr_len);
|
||||
ssfe->ssfe_type = SCTP_SEND_FAILED_EVENT;
|
||||
if (sent) {
|
||||
ssfe->ssfe_flags = SCTP_DATA_SENT;
|
||||
} else {
|
||||
ssfe->ssfe_flags = SCTP_DATA_UNSENT;
|
||||
}
|
||||
length += chk->send_size;
|
||||
length -= sizeof(struct sctp_data_chunk);
|
||||
ssfe->ssfe_length = length;
|
||||
ssfe->ssfe_length = (uint32_t) (notifhdr_len + payload_len);
|
||||
ssfe->ssfe_error = error;
|
||||
/* not exactly what the user sent in, but should be close :) */
|
||||
ssfe->ssfe_info.snd_sid = chk->rec.data.stream_number;
|
||||
@ -2971,39 +2994,33 @@ sctp_notify_send_failed(struct sctp_tcb *stcb, uint8_t sent, uint32_t error,
|
||||
ssfe->ssfe_info.snd_context = chk->rec.data.context;
|
||||
ssfe->ssfe_info.snd_assoc_id = sctp_get_associd(stcb);
|
||||
ssfe->ssfe_assoc_id = sctp_get_associd(stcb);
|
||||
SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed_event);
|
||||
} else {
|
||||
ssf = mtod(m_notify, struct sctp_send_failed *);
|
||||
memset(ssf, 0, length);
|
||||
memset(ssf, 0, notifhdr_len);
|
||||
ssf->ssf_type = SCTP_SEND_FAILED;
|
||||
if (sent) {
|
||||
ssf->ssf_flags = SCTP_DATA_SENT;
|
||||
} else {
|
||||
ssf->ssf_flags = SCTP_DATA_UNSENT;
|
||||
}
|
||||
length += chk->send_size;
|
||||
length -= sizeof(struct sctp_data_chunk);
|
||||
ssf->ssf_length = length;
|
||||
ssf->ssf_length = (uint32_t) (notifhdr_len + payload_len);
|
||||
ssf->ssf_error = error;
|
||||
/* not exactly what the user sent in, but should be close :) */
|
||||
bzero(&ssf->ssf_info, sizeof(ssf->ssf_info));
|
||||
ssf->ssf_info.sinfo_stream = chk->rec.data.stream_number;
|
||||
ssf->ssf_info.sinfo_ssn = chk->rec.data.stream_seq;
|
||||
ssf->ssf_info.sinfo_ssn = (uint16_t) chk->rec.data.stream_seq;
|
||||
ssf->ssf_info.sinfo_flags = chk->rec.data.rcv_flags;
|
||||
ssf->ssf_info.sinfo_ppid = chk->rec.data.payloadtype;
|
||||
ssf->ssf_info.sinfo_context = chk->rec.data.context;
|
||||
ssf->ssf_info.sinfo_assoc_id = sctp_get_associd(stcb);
|
||||
ssf->ssf_assoc_id = sctp_get_associd(stcb);
|
||||
SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed);
|
||||
}
|
||||
if (chk->data) {
|
||||
/*
|
||||
* trim off the sctp chunk header(it should be there)
|
||||
*/
|
||||
if (chk->send_size >= sizeof(struct sctp_data_chunk)) {
|
||||
m_adj(chk->data, sizeof(struct sctp_data_chunk));
|
||||
if (chk->data != NULL) {
|
||||
/* Trim off the sctp chunk header (it should be there) */
|
||||
if (chk->send_size == chkhdr_len + payload_len + padding_len) {
|
||||
m_adj(chk->data, chkhdr_len);
|
||||
m_adj(chk->data, -padding_len);
|
||||
sctp_mbuf_crush(chk->data);
|
||||
chk->send_size -= sizeof(struct sctp_data_chunk);
|
||||
chk->send_size -= (chkhdr_len + padding_len);
|
||||
}
|
||||
}
|
||||
SCTP_BUF_NEXT(m_notify) = chk->data;
|
||||
@ -3048,7 +3065,7 @@ sctp_notify_send_failed2(struct sctp_tcb *stcb, uint32_t error,
|
||||
struct sctp_send_failed *ssf;
|
||||
struct sctp_send_failed_event *ssfe;
|
||||
struct sctp_queued_to_read *control;
|
||||
int length;
|
||||
int notifhdr_len;
|
||||
|
||||
if ((stcb == NULL) ||
|
||||
(sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT) &&
|
||||
@ -3057,23 +3074,22 @@ sctp_notify_send_failed2(struct sctp_tcb *stcb, uint32_t error,
|
||||
return;
|
||||
}
|
||||
if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) {
|
||||
length = sizeof(struct sctp_send_failed_event);
|
||||
notifhdr_len = sizeof(struct sctp_send_failed_event);
|
||||
} else {
|
||||
length = sizeof(struct sctp_send_failed);
|
||||
notifhdr_len = sizeof(struct sctp_send_failed);
|
||||
}
|
||||
m_notify = sctp_get_mbuf_for_msg(length, 0, M_NOWAIT, 1, MT_DATA);
|
||||
m_notify = sctp_get_mbuf_for_msg(notifhdr_len, 0, M_NOWAIT, 1, MT_DATA);
|
||||
if (m_notify == NULL) {
|
||||
/* no space left */
|
||||
return;
|
||||
}
|
||||
SCTP_BUF_LEN(m_notify) = 0;
|
||||
SCTP_BUF_LEN(m_notify) = notifhdr_len;
|
||||
if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) {
|
||||
ssfe = mtod(m_notify, struct sctp_send_failed_event *);
|
||||
memset(ssfe, 0, length);
|
||||
memset(ssfe, 0, notifhdr_len);
|
||||
ssfe->ssfe_type = SCTP_SEND_FAILED_EVENT;
|
||||
ssfe->ssfe_flags = SCTP_DATA_UNSENT;
|
||||
length += sp->length;
|
||||
ssfe->ssfe_length = length;
|
||||
ssfe->ssfe_length = (uint32_t) (notifhdr_len + sp->length);
|
||||
ssfe->ssfe_error = error;
|
||||
/* not exactly what the user sent in, but should be close :) */
|
||||
ssfe->ssfe_info.snd_sid = sp->stream;
|
||||
@ -3086,14 +3102,12 @@ sctp_notify_send_failed2(struct sctp_tcb *stcb, uint32_t error,
|
||||
ssfe->ssfe_info.snd_context = sp->context;
|
||||
ssfe->ssfe_info.snd_assoc_id = sctp_get_associd(stcb);
|
||||
ssfe->ssfe_assoc_id = sctp_get_associd(stcb);
|
||||
SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed_event);
|
||||
} else {
|
||||
ssf = mtod(m_notify, struct sctp_send_failed *);
|
||||
memset(ssf, 0, length);
|
||||
memset(ssf, 0, notifhdr_len);
|
||||
ssf->ssf_type = SCTP_SEND_FAILED;
|
||||
ssf->ssf_flags = SCTP_DATA_UNSENT;
|
||||
length += sp->length;
|
||||
ssf->ssf_length = length;
|
||||
ssf->ssf_length = (uint32_t) (notifhdr_len + sp->length);
|
||||
ssf->ssf_error = error;
|
||||
/* not exactly what the user sent in, but should be close :) */
|
||||
ssf->ssf_info.sinfo_stream = sp->stream;
|
||||
@ -3107,7 +3121,6 @@ sctp_notify_send_failed2(struct sctp_tcb *stcb, uint32_t error,
|
||||
ssf->ssf_info.sinfo_context = sp->context;
|
||||
ssf->ssf_info.sinfo_assoc_id = sctp_get_associd(stcb);
|
||||
ssf->ssf_assoc_id = sctp_get_associd(stcb);
|
||||
SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed);
|
||||
}
|
||||
SCTP_BUF_NEXT(m_notify) = sp->data;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user