diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/sctp/chunk.c | 32 |
1 files changed, 23 insertions, 9 deletions
diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c index 1748ef90950c..9292294dbc12 100644 --- a/net/sctp/chunk.c +++ b/net/sctp/chunk.c | |||
@@ -158,6 +158,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, | |||
158 | { | 158 | { |
159 | int max, whole, i, offset, over, err; | 159 | int max, whole, i, offset, over, err; |
160 | int len, first_len; | 160 | int len, first_len; |
161 | int max_data; | ||
161 | struct sctp_chunk *chunk; | 162 | struct sctp_chunk *chunk; |
162 | struct sctp_datamsg *msg; | 163 | struct sctp_datamsg *msg; |
163 | struct list_head *pos, *temp; | 164 | struct list_head *pos, *temp; |
@@ -179,8 +180,14 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, | |||
179 | __func__, msg, msg->expires_at, jiffies); | 180 | __func__, msg, msg->expires_at, jiffies); |
180 | } | 181 | } |
181 | 182 | ||
182 | max = asoc->frag_point; | 183 | /* This is the biggest possible DATA chunk that can fit into |
184 | * the packet | ||
185 | */ | ||
186 | max_data = asoc->pathmtu - | ||
187 | sctp_sk(asoc->base.sk)->pf->af->net_header_len - | ||
188 | sizeof(struct sctphdr) - sizeof(struct sctp_data_chunk); | ||
183 | 189 | ||
190 | max = asoc->frag_point; | ||
184 | /* If the the peer requested that we authenticate DATA chunks | 191 | /* If the the peer requested that we authenticate DATA chunks |
185 | * we need to accound for bundling of the AUTH chunks along with | 192 | * we need to accound for bundling of the AUTH chunks along with |
186 | * DATA. | 193 | * DATA. |
@@ -189,23 +196,30 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, | |||
189 | struct sctp_hmac *hmac_desc = sctp_auth_asoc_get_hmac(asoc); | 196 | struct sctp_hmac *hmac_desc = sctp_auth_asoc_get_hmac(asoc); |
190 | 197 | ||
191 | if (hmac_desc) | 198 | if (hmac_desc) |
192 | max -= WORD_ROUND(sizeof(sctp_auth_chunk_t) + | 199 | max_data -= WORD_ROUND(sizeof(sctp_auth_chunk_t) + |
193 | hmac_desc->hmac_len); | 200 | hmac_desc->hmac_len); |
194 | } | 201 | } |
195 | 202 | ||
203 | /* Now, check if we need to reduce our max */ | ||
204 | if (max > max_data) | ||
205 | max = max_data; | ||
206 | |||
196 | whole = 0; | 207 | whole = 0; |
197 | first_len = max; | 208 | first_len = max; |
198 | 209 | ||
199 | /* Encourage Cookie-ECHO bundling. */ | 210 | /* Encourage Cookie-ECHO bundling. */ |
200 | if (asoc->state < SCTP_STATE_COOKIE_ECHOED) { | 211 | if (asoc->state < SCTP_STATE_COOKIE_ECHOED) { |
201 | whole = msg_len / (max - SCTP_ARBITRARY_COOKIE_ECHO_LEN); | 212 | max_data -= SCTP_ARBITRARY_COOKIE_ECHO_LEN; |
202 | 213 | ||
203 | /* Account for the DATA to be bundled with the COOKIE-ECHO. */ | 214 | /* This is the biggesr first_len we can have */ |
204 | if (whole) { | 215 | if (first_len > max_data) |
205 | first_len = max - SCTP_ARBITRARY_COOKIE_ECHO_LEN; | 216 | first_len = max_data; |
206 | msg_len -= first_len; | 217 | } |
207 | whole = 1; | 218 | |
208 | } | 219 | /* Account for a different sized first fragment */ |
220 | if (msg_len >= first_len) { | ||
221 | msg_len -= first_len; | ||
222 | whole = 1; | ||
209 | } | 223 | } |
210 | 224 | ||
211 | /* How many full sized? How many bytes leftover? */ | 225 | /* How many full sized? How many bytes leftover? */ |