aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/output.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sctp/output.c')
-rw-r--r--net/sctp/output.c131
1 files changed, 104 insertions, 27 deletions
diff --git a/net/sctp/output.c b/net/sctp/output.c
index 49b9f5f031a..847639d542c 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -80,6 +80,7 @@ struct sctp_packet *sctp_packet_config(struct sctp_packet *packet,
80 packet->has_cookie_echo = 0; 80 packet->has_cookie_echo = 0;
81 packet->has_sack = 0; 81 packet->has_sack = 0;
82 packet->has_auth = 0; 82 packet->has_auth = 0;
83 packet->has_data = 0;
83 packet->ipfragok = 0; 84 packet->ipfragok = 0;
84 packet->auth = NULL; 85 packet->auth = NULL;
85 86
@@ -124,6 +125,7 @@ struct sctp_packet *sctp_packet_init(struct sctp_packet *packet,
124 packet->has_cookie_echo = 0; 125 packet->has_cookie_echo = 0;
125 packet->has_sack = 0; 126 packet->has_sack = 0;
126 packet->has_auth = 0; 127 packet->has_auth = 0;
128 packet->has_data = 0;
127 packet->ipfragok = 0; 129 packet->ipfragok = 0;
128 packet->malloced = 0; 130 packet->malloced = 0;
129 packet->auth = NULL; 131 packet->auth = NULL;
@@ -185,6 +187,39 @@ sctp_xmit_t sctp_packet_transmit_chunk(struct sctp_packet *packet,
185 return retval; 187 return retval;
186} 188}
187 189
190/* Try to bundle an auth chunk into the packet. */
191static sctp_xmit_t sctp_packet_bundle_auth(struct sctp_packet *pkt,
192 struct sctp_chunk *chunk)
193{
194 struct sctp_association *asoc = pkt->transport->asoc;
195 struct sctp_chunk *auth;
196 sctp_xmit_t retval = SCTP_XMIT_OK;
197
198 /* if we don't have an association, we can't do authentication */
199 if (!asoc)
200 return retval;
201
202 /* See if this is an auth chunk we are bundling or if
203 * auth is already bundled.
204 */
205 if (chunk->chunk_hdr->type == SCTP_CID_AUTH || pkt->auth)
206 return retval;
207
208 /* if the peer did not request this chunk to be authenticated,
209 * don't do it
210 */
211 if (!chunk->auth)
212 return retval;
213
214 auth = sctp_make_auth(asoc);
215 if (!auth)
216 return retval;
217
218 retval = sctp_packet_append_chunk(pkt, auth);
219
220 return retval;
221}
222
188/* Try to bundle a SACK with the packet. */ 223/* Try to bundle a SACK with the packet. */
189static sctp_xmit_t sctp_packet_bundle_sack(struct sctp_packet *pkt, 224static sctp_xmit_t sctp_packet_bundle_sack(struct sctp_packet *pkt,
190 struct sctp_chunk *chunk) 225 struct sctp_chunk *chunk)
@@ -231,12 +266,17 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet,
231 SCTP_DEBUG_PRINTK("%s: packet:%p chunk:%p\n", __FUNCTION__, packet, 266 SCTP_DEBUG_PRINTK("%s: packet:%p chunk:%p\n", __FUNCTION__, packet,
232 chunk); 267 chunk);
233 268
234 retval = sctp_packet_bundle_sack(packet, chunk); 269 /* Try to bundle AUTH chunk */
235 psize = packet->size; 270 retval = sctp_packet_bundle_auth(packet, chunk);
271 if (retval != SCTP_XMIT_OK)
272 goto finish;
236 273
274 /* Try to bundle SACK chunk */
275 retval = sctp_packet_bundle_sack(packet, chunk);
237 if (retval != SCTP_XMIT_OK) 276 if (retval != SCTP_XMIT_OK)
238 goto finish; 277 goto finish;
239 278
279 psize = packet->size;
240 pmtu = ((packet->transport->asoc) ? 280 pmtu = ((packet->transport->asoc) ?
241 (packet->transport->asoc->pathmtu) : 281 (packet->transport->asoc->pathmtu) :
242 (packet->transport->pathmtu)); 282 (packet->transport->pathmtu));
@@ -245,10 +285,16 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet,
245 285
246 /* Decide if we need to fragment or resubmit later. */ 286 /* Decide if we need to fragment or resubmit later. */
247 if (too_big) { 287 if (too_big) {
248 /* Both control chunks and data chunks with TSNs are 288 /* It's OK to fragmet at IP level if any one of the following
249 * non-fragmentable. 289 * is true:
290 * 1. The packet is empty (meaning this chunk is greater
291 * the MTU)
292 * 2. The chunk we are adding is a control chunk
293 * 3. The packet doesn't have any data in it yet and data
294 * requires authentication.
250 */ 295 */
251 if (sctp_packet_empty(packet) || !sctp_chunk_is_data(chunk)) { 296 if (sctp_packet_empty(packet) || !sctp_chunk_is_data(chunk) ||
297 (!packet->has_data && chunk->auth)) {
252 /* We no longer do re-fragmentation. 298 /* We no longer do re-fragmentation.
253 * Just fragment at the IP layer, if we 299 * Just fragment at the IP layer, if we
254 * actually hit this condition 300 * actually hit this condition
@@ -270,16 +316,31 @@ append:
270 /* DATA is a special case since we must examine both rwnd and cwnd 316 /* DATA is a special case since we must examine both rwnd and cwnd
271 * before we send DATA. 317 * before we send DATA.
272 */ 318 */
273 if (sctp_chunk_is_data(chunk)) { 319 switch (chunk->chunk_hdr->type) {
320 case SCTP_CID_DATA:
274 retval = sctp_packet_append_data(packet, chunk); 321 retval = sctp_packet_append_data(packet, chunk);
275 /* Disallow SACK bundling after DATA. */ 322 /* Disallow SACK bundling after DATA. */
276 packet->has_sack = 1; 323 packet->has_sack = 1;
324 /* Disallow AUTH bundling after DATA */
325 packet->has_auth = 1;
326 /* Let it be knows that packet has DATA in it */
327 packet->has_data = 1;
277 if (SCTP_XMIT_OK != retval) 328 if (SCTP_XMIT_OK != retval)
278 goto finish; 329 goto finish;
279 } else if (SCTP_CID_COOKIE_ECHO == chunk->chunk_hdr->type) 330 break;
331 case SCTP_CID_COOKIE_ECHO:
280 packet->has_cookie_echo = 1; 332 packet->has_cookie_echo = 1;
281 else if (SCTP_CID_SACK == chunk->chunk_hdr->type) 333 break;
334
335 case SCTP_CID_SACK:
282 packet->has_sack = 1; 336 packet->has_sack = 1;
337 break;
338
339 case SCTP_CID_AUTH:
340 packet->has_auth = 1;
341 packet->auth = chunk;
342 break;
343 }
283 344
284 /* It is OK to send this chunk. */ 345 /* It is OK to send this chunk. */
285 list_add_tail(&chunk->list, &packet->chunk_list); 346 list_add_tail(&chunk->list, &packet->chunk_list);
@@ -307,6 +368,8 @@ int sctp_packet_transmit(struct sctp_packet *packet)
307 int padding; /* How much padding do we need? */ 368 int padding; /* How much padding do we need? */
308 __u8 has_data = 0; 369 __u8 has_data = 0;
309 struct dst_entry *dst = tp->dst; 370 struct dst_entry *dst = tp->dst;
371 unsigned char *auth = NULL; /* pointer to auth in skb data */
372 __u32 cksum_buf_len = sizeof(struct sctphdr);
310 373
311 SCTP_DEBUG_PRINTK("%s: packet:%p\n", __FUNCTION__, packet); 374 SCTP_DEBUG_PRINTK("%s: packet:%p\n", __FUNCTION__, packet);
312 375
@@ -360,16 +423,6 @@ int sctp_packet_transmit(struct sctp_packet *packet)
360 sh->vtag = htonl(packet->vtag); 423 sh->vtag = htonl(packet->vtag);
361 sh->checksum = 0; 424 sh->checksum = 0;
362 425
363 /* 2) Calculate the Adler-32 checksum of the whole packet,
364 * including the SCTP common header and all the
365 * chunks.
366 *
367 * Note: Adler-32 is no longer applicable, as has been replaced
368 * by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>.
369 */
370 if (!(dst->dev->features & NETIF_F_NO_CSUM))
371 crc32 = sctp_start_cksum((__u8 *)sh, sizeof(struct sctphdr));
372
373 /** 426 /**
374 * 6.10 Bundling 427 * 6.10 Bundling
375 * 428 *
@@ -420,14 +473,16 @@ int sctp_packet_transmit(struct sctp_packet *packet)
420 if (padding) 473 if (padding)
421 memset(skb_put(chunk->skb, padding), 0, padding); 474 memset(skb_put(chunk->skb, padding), 0, padding);
422 475
423 if (dst->dev->features & NETIF_F_NO_CSUM) 476 /* if this is the auth chunk that we are adding,
424 memcpy(skb_put(nskb, chunk->skb->len), 477 * store pointer where it will be added and put
478 * the auth into the packet.
479 */
480 if (chunk == packet->auth)
481 auth = skb_tail_pointer(nskb);
482
483 cksum_buf_len += chunk->skb->len;
484 memcpy(skb_put(nskb, chunk->skb->len),
425 chunk->skb->data, chunk->skb->len); 485 chunk->skb->data, chunk->skb->len);
426 else
427 crc32 = sctp_update_copy_cksum(skb_put(nskb,
428 chunk->skb->len),
429 chunk->skb->data,
430 chunk->skb->len, crc32);
431 486
432 SCTP_DEBUG_PRINTK("%s %p[%s] %s 0x%x, %s %d, %s %d, %s %d\n", 487 SCTP_DEBUG_PRINTK("%s %p[%s] %s 0x%x, %s %d, %s %d, %s %d\n",
433 "*** Chunk", chunk, 488 "*** Chunk", chunk,
@@ -449,9 +504,31 @@ int sctp_packet_transmit(struct sctp_packet *packet)
449 sctp_chunk_free(chunk); 504 sctp_chunk_free(chunk);
450 } 505 }
451 506
452 /* Perform final transformation on checksum. */ 507 /* SCTP-AUTH, Section 6.2
453 if (!(dst->dev->features & NETIF_F_NO_CSUM)) 508 * The sender MUST calculate the MAC as described in RFC2104 [2]
509 * using the hash function H as described by the MAC Identifier and
510 * the shared association key K based on the endpoint pair shared key
511 * described by the shared key identifier. The 'data' used for the
512 * computation of the AUTH-chunk is given by the AUTH chunk with its
513 * HMAC field set to zero (as shown in Figure 6) followed by all
514 * chunks that are placed after the AUTH chunk in the SCTP packet.
515 */
516 if (auth)
517 sctp_auth_calculate_hmac(asoc, nskb,
518 (struct sctp_auth_chunk *)auth,
519 GFP_ATOMIC);
520
521 /* 2) Calculate the Adler-32 checksum of the whole packet,
522 * including the SCTP common header and all the
523 * chunks.
524 *
525 * Note: Adler-32 is no longer applicable, as has been replaced
526 * by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>.
527 */
528 if (!(dst->dev->features & NETIF_F_NO_CSUM)) {
529 crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len);
454 crc32 = sctp_end_cksum(crc32); 530 crc32 = sctp_end_cksum(crc32);
531 }
455 532
456 /* 3) Put the resultant value into the checksum field in the 533 /* 3) Put the resultant value into the checksum field in the
457 * common header, and leave the rest of the bits unchanged. 534 * common header, and leave the rest of the bits unchanged.