mirror of
https://github.com/torvalds/linux.git
synced 2024-12-30 14:52:05 +00:00
sctp: Fix data segmentation with small frag_size
Since an application may specify the maximum SCTP fragment size that all data should be fragmented to, we need to fix how we do segmentation. Right now, if a user specifies a small fragment size, the segment size can go negative in the presence of AUTH or COOKIE_ECHO bundling. What we need to do is track the largest possbile DATA chunk that can fit into the mtu. Then if the fragment size specified is bigger then this maximum length, we'll shrink it down. Otherwise, we just use the smaller segment size without changing it further. Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
This commit is contained in:
parent
bec9640bb0
commit
3e62abf92f
@ -158,6 +158,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
|
||||
{
|
||||
int max, whole, i, offset, over, err;
|
||||
int len, first_len;
|
||||
int max_data;
|
||||
struct sctp_chunk *chunk;
|
||||
struct sctp_datamsg *msg;
|
||||
struct list_head *pos, *temp;
|
||||
@ -179,8 +180,14 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
|
||||
__func__, msg, msg->expires_at, jiffies);
|
||||
}
|
||||
|
||||
max = asoc->frag_point;
|
||||
/* This is the biggest possible DATA chunk that can fit into
|
||||
* the packet
|
||||
*/
|
||||
max_data = asoc->pathmtu -
|
||||
sctp_sk(asoc->base.sk)->pf->af->net_header_len -
|
||||
sizeof(struct sctphdr) - sizeof(struct sctp_data_chunk);
|
||||
|
||||
max = asoc->frag_point;
|
||||
/* If the the peer requested that we authenticate DATA chunks
|
||||
* we need to accound for bundling of the AUTH chunks along with
|
||||
* DATA.
|
||||
@ -189,23 +196,30 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
|
||||
struct sctp_hmac *hmac_desc = sctp_auth_asoc_get_hmac(asoc);
|
||||
|
||||
if (hmac_desc)
|
||||
max -= WORD_ROUND(sizeof(sctp_auth_chunk_t) +
|
||||
max_data -= WORD_ROUND(sizeof(sctp_auth_chunk_t) +
|
||||
hmac_desc->hmac_len);
|
||||
}
|
||||
|
||||
/* Now, check if we need to reduce our max */
|
||||
if (max > max_data)
|
||||
max = max_data;
|
||||
|
||||
whole = 0;
|
||||
first_len = max;
|
||||
|
||||
/* Encourage Cookie-ECHO bundling. */
|
||||
if (asoc->state < SCTP_STATE_COOKIE_ECHOED) {
|
||||
whole = msg_len / (max - SCTP_ARBITRARY_COOKIE_ECHO_LEN);
|
||||
max_data -= SCTP_ARBITRARY_COOKIE_ECHO_LEN;
|
||||
|
||||
/* Account for the DATA to be bundled with the COOKIE-ECHO. */
|
||||
if (whole) {
|
||||
first_len = max - SCTP_ARBITRARY_COOKIE_ECHO_LEN;
|
||||
msg_len -= first_len;
|
||||
whole = 1;
|
||||
}
|
||||
/* This is the biggesr first_len we can have */
|
||||
if (first_len > max_data)
|
||||
first_len = max_data;
|
||||
}
|
||||
|
||||
/* Account for a different sized first fragment */
|
||||
if (msg_len >= first_len) {
|
||||
msg_len -= first_len;
|
||||
whole = 1;
|
||||
}
|
||||
|
||||
/* How many full sized? How many bytes leftover? */
|
||||
|
Loading…
Reference in New Issue
Block a user