diff options
Diffstat (limited to 'net/sctp/output.c')
-rw-r--r-- | net/sctp/output.c | 135 |
1 files changed, 108 insertions, 27 deletions
diff --git a/net/sctp/output.c b/net/sctp/output.c index d85543def754..847639d542c0 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c | |||
@@ -79,7 +79,10 @@ struct sctp_packet *sctp_packet_config(struct sctp_packet *packet, | |||
79 | packet->vtag = vtag; | 79 | packet->vtag = vtag; |
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; | ||
83 | packet->has_data = 0; | ||
82 | packet->ipfragok = 0; | 84 | packet->ipfragok = 0; |
85 | packet->auth = NULL; | ||
83 | 86 | ||
84 | if (ecn_capable && sctp_packet_empty(packet)) { | 87 | if (ecn_capable && sctp_packet_empty(packet)) { |
85 | chunk = sctp_get_ecne_prepend(packet->transport->asoc); | 88 | chunk = sctp_get_ecne_prepend(packet->transport->asoc); |
@@ -121,8 +124,11 @@ struct sctp_packet *sctp_packet_init(struct sctp_packet *packet, | |||
121 | packet->vtag = 0; | 124 | packet->vtag = 0; |
122 | packet->has_cookie_echo = 0; | 125 | packet->has_cookie_echo = 0; |
123 | packet->has_sack = 0; | 126 | packet->has_sack = 0; |
127 | packet->has_auth = 0; | ||
128 | packet->has_data = 0; | ||
124 | packet->ipfragok = 0; | 129 | packet->ipfragok = 0; |
125 | packet->malloced = 0; | 130 | packet->malloced = 0; |
131 | packet->auth = NULL; | ||
126 | return packet; | 132 | return packet; |
127 | } | 133 | } |
128 | 134 | ||
@@ -181,6 +187,39 @@ sctp_xmit_t sctp_packet_transmit_chunk(struct sctp_packet *packet, | |||
181 | return retval; | 187 | return retval; |
182 | } | 188 | } |
183 | 189 | ||
190 | /* Try to bundle an auth chunk into the packet. */ | ||
191 | static 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 | |||
184 | /* Try to bundle a SACK with the packet. */ | 223 | /* Try to bundle a SACK with the packet. */ |
185 | static sctp_xmit_t sctp_packet_bundle_sack(struct sctp_packet *pkt, | 224 | static sctp_xmit_t sctp_packet_bundle_sack(struct sctp_packet *pkt, |
186 | struct sctp_chunk *chunk) | 225 | struct sctp_chunk *chunk) |
@@ -227,12 +266,17 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet, | |||
227 | SCTP_DEBUG_PRINTK("%s: packet:%p chunk:%p\n", __FUNCTION__, packet, | 266 | SCTP_DEBUG_PRINTK("%s: packet:%p chunk:%p\n", __FUNCTION__, packet, |
228 | chunk); | 267 | chunk); |
229 | 268 | ||
230 | retval = sctp_packet_bundle_sack(packet, chunk); | 269 | /* Try to bundle AUTH chunk */ |
231 | psize = packet->size; | 270 | retval = sctp_packet_bundle_auth(packet, chunk); |
271 | if (retval != SCTP_XMIT_OK) | ||
272 | goto finish; | ||
232 | 273 | ||
274 | /* Try to bundle SACK chunk */ | ||
275 | retval = sctp_packet_bundle_sack(packet, chunk); | ||
233 | if (retval != SCTP_XMIT_OK) | 276 | if (retval != SCTP_XMIT_OK) |
234 | goto finish; | 277 | goto finish; |
235 | 278 | ||
279 | psize = packet->size; | ||
236 | pmtu = ((packet->transport->asoc) ? | 280 | pmtu = ((packet->transport->asoc) ? |
237 | (packet->transport->asoc->pathmtu) : | 281 | (packet->transport->asoc->pathmtu) : |
238 | (packet->transport->pathmtu)); | 282 | (packet->transport->pathmtu)); |
@@ -241,10 +285,16 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet, | |||
241 | 285 | ||
242 | /* Decide if we need to fragment or resubmit later. */ | 286 | /* Decide if we need to fragment or resubmit later. */ |
243 | if (too_big) { | 287 | if (too_big) { |
244 | /* Both control chunks and data chunks with TSNs are | 288 | /* It's OK to fragmet at IP level if any one of the following |
245 | * 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. | ||
246 | */ | 295 | */ |
247 | 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)) { | ||
248 | /* We no longer do re-fragmentation. | 298 | /* We no longer do re-fragmentation. |
249 | * Just fragment at the IP layer, if we | 299 | * Just fragment at the IP layer, if we |
250 | * actually hit this condition | 300 | * actually hit this condition |
@@ -266,16 +316,31 @@ append: | |||
266 | /* 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 |
267 | * before we send DATA. | 317 | * before we send DATA. |
268 | */ | 318 | */ |
269 | if (sctp_chunk_is_data(chunk)) { | 319 | switch (chunk->chunk_hdr->type) { |
320 | case SCTP_CID_DATA: | ||
270 | retval = sctp_packet_append_data(packet, chunk); | 321 | retval = sctp_packet_append_data(packet, chunk); |
271 | /* Disallow SACK bundling after DATA. */ | 322 | /* Disallow SACK bundling after DATA. */ |
272 | 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; | ||
273 | if (SCTP_XMIT_OK != retval) | 328 | if (SCTP_XMIT_OK != retval) |
274 | goto finish; | 329 | goto finish; |
275 | } else if (SCTP_CID_COOKIE_ECHO == chunk->chunk_hdr->type) | 330 | break; |
331 | case SCTP_CID_COOKIE_ECHO: | ||
276 | packet->has_cookie_echo = 1; | 332 | packet->has_cookie_echo = 1; |
277 | else if (SCTP_CID_SACK == chunk->chunk_hdr->type) | 333 | break; |
334 | |||
335 | case SCTP_CID_SACK: | ||
278 | 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 | } | ||
279 | 344 | ||
280 | /* It is OK to send this chunk. */ | 345 | /* It is OK to send this chunk. */ |
281 | list_add_tail(&chunk->list, &packet->chunk_list); | 346 | list_add_tail(&chunk->list, &packet->chunk_list); |
@@ -303,6 +368,8 @@ int sctp_packet_transmit(struct sctp_packet *packet) | |||
303 | int padding; /* How much padding do we need? */ | 368 | int padding; /* How much padding do we need? */ |
304 | __u8 has_data = 0; | 369 | __u8 has_data = 0; |
305 | 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); | ||
306 | 373 | ||
307 | SCTP_DEBUG_PRINTK("%s: packet:%p\n", __FUNCTION__, packet); | 374 | SCTP_DEBUG_PRINTK("%s: packet:%p\n", __FUNCTION__, packet); |
308 | 375 | ||
@@ -356,16 +423,6 @@ int sctp_packet_transmit(struct sctp_packet *packet) | |||
356 | sh->vtag = htonl(packet->vtag); | 423 | sh->vtag = htonl(packet->vtag); |
357 | sh->checksum = 0; | 424 | sh->checksum = 0; |
358 | 425 | ||
359 | /* 2) Calculate the Adler-32 checksum of the whole packet, | ||
360 | * including the SCTP common header and all the | ||
361 | * chunks. | ||
362 | * | ||
363 | * Note: Adler-32 is no longer applicable, as has been replaced | ||
364 | * by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>. | ||
365 | */ | ||
366 | if (!(dst->dev->features & NETIF_F_NO_CSUM)) | ||
367 | crc32 = sctp_start_cksum((__u8 *)sh, sizeof(struct sctphdr)); | ||
368 | |||
369 | /** | 426 | /** |
370 | * 6.10 Bundling | 427 | * 6.10 Bundling |
371 | * | 428 | * |
@@ -416,14 +473,16 @@ int sctp_packet_transmit(struct sctp_packet *packet) | |||
416 | if (padding) | 473 | if (padding) |
417 | memset(skb_put(chunk->skb, padding), 0, padding); | 474 | memset(skb_put(chunk->skb, padding), 0, padding); |
418 | 475 | ||
419 | if (dst->dev->features & NETIF_F_NO_CSUM) | 476 | /* if this is the auth chunk that we are adding, |
420 | 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), | ||
421 | chunk->skb->data, chunk->skb->len); | 485 | chunk->skb->data, chunk->skb->len); |
422 | else | ||
423 | crc32 = sctp_update_copy_cksum(skb_put(nskb, | ||
424 | chunk->skb->len), | ||
425 | chunk->skb->data, | ||
426 | chunk->skb->len, crc32); | ||
427 | 486 | ||
428 | 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", |
429 | "*** Chunk", chunk, | 488 | "*** Chunk", chunk, |
@@ -445,9 +504,31 @@ int sctp_packet_transmit(struct sctp_packet *packet) | |||
445 | sctp_chunk_free(chunk); | 504 | sctp_chunk_free(chunk); |
446 | } | 505 | } |
447 | 506 | ||
448 | /* Perform final transformation on checksum. */ | 507 | /* SCTP-AUTH, Section 6.2 |
449 | 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); | ||
450 | crc32 = sctp_end_cksum(crc32); | 530 | crc32 = sctp_end_cksum(crc32); |
531 | } | ||
451 | 532 | ||
452 | /* 3) Put the resultant value into the checksum field in the | 533 | /* 3) Put the resultant value into the checksum field in the |
453 | * common header, and leave the rest of the bits unchanged. | 534 | * common header, and leave the rest of the bits unchanged. |