diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/sctp/input.c | 3 | ||||
-rw-r--r-- | net/sctp/output.c | 48 |
2 files changed, 29 insertions, 22 deletions
diff --git a/net/sctp/input.c b/net/sctp/input.c index 70d6606e2812..42b66e74bbb5 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c | |||
@@ -141,7 +141,8 @@ int sctp_rcv(struct sk_buff *skb) | |||
141 | __skb_pull(skb, skb->h.raw - skb->data); | 141 | __skb_pull(skb, skb->h.raw - skb->data); |
142 | if (skb->len < sizeof(struct sctphdr)) | 142 | if (skb->len < sizeof(struct sctphdr)) |
143 | goto discard_it; | 143 | goto discard_it; |
144 | if (sctp_rcv_checksum(skb) < 0) | 144 | if ((skb->ip_summed != CHECKSUM_UNNECESSARY) && |
145 | (sctp_rcv_checksum(skb) < 0)) | ||
145 | goto discard_it; | 146 | goto discard_it; |
146 | 147 | ||
147 | skb_pull(skb, sizeof(struct sctphdr)); | 148 | skb_pull(skb, sizeof(struct sctphdr)); |
diff --git a/net/sctp/output.c b/net/sctp/output.c index 437cba7260a4..cdc5a3936766 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c | |||
@@ -295,14 +295,14 @@ int sctp_packet_transmit(struct sctp_packet *packet) | |||
295 | struct sctp_transport *tp = packet->transport; | 295 | struct sctp_transport *tp = packet->transport; |
296 | struct sctp_association *asoc = tp->asoc; | 296 | struct sctp_association *asoc = tp->asoc; |
297 | struct sctphdr *sh; | 297 | struct sctphdr *sh; |
298 | __u32 crc32; | 298 | __u32 crc32 = 0; |
299 | struct sk_buff *nskb; | 299 | struct sk_buff *nskb; |
300 | struct sctp_chunk *chunk, *tmp; | 300 | struct sctp_chunk *chunk, *tmp; |
301 | struct sock *sk; | 301 | struct sock *sk; |
302 | int err = 0; | 302 | int err = 0; |
303 | int padding; /* How much padding do we need? */ | 303 | int padding; /* How much padding do we need? */ |
304 | __u8 has_data = 0; | 304 | __u8 has_data = 0; |
305 | struct dst_entry *dst; | 305 | struct dst_entry *dst = tp->dst; |
306 | 306 | ||
307 | SCTP_DEBUG_PRINTK("%s: packet:%p\n", __FUNCTION__, packet); | 307 | SCTP_DEBUG_PRINTK("%s: packet:%p\n", __FUNCTION__, packet); |
308 | 308 | ||
@@ -327,6 +327,19 @@ int sctp_packet_transmit(struct sctp_packet *packet) | |||
327 | */ | 327 | */ |
328 | skb_set_owner_w(nskb, sk); | 328 | skb_set_owner_w(nskb, sk); |
329 | 329 | ||
330 | /* The 'obsolete' field of dst is set to 2 when a dst is freed. */ | ||
331 | if (!dst || (dst->obsolete > 1)) { | ||
332 | dst_release(dst); | ||
333 | sctp_transport_route(tp, NULL, sctp_sk(sk)); | ||
334 | if (asoc && (asoc->param_flags & SPP_PMTUD_ENABLE)) { | ||
335 | sctp_assoc_sync_pmtu(asoc); | ||
336 | } | ||
337 | } | ||
338 | nskb->dst = dst_clone(tp->dst); | ||
339 | if (!nskb->dst) | ||
340 | goto no_route; | ||
341 | dst = nskb->dst; | ||
342 | |||
330 | /* Build the SCTP header. */ | 343 | /* Build the SCTP header. */ |
331 | sh = (struct sctphdr *)skb_push(nskb, sizeof(struct sctphdr)); | 344 | sh = (struct sctphdr *)skb_push(nskb, sizeof(struct sctphdr)); |
332 | sh->source = htons(packet->source_port); | 345 | sh->source = htons(packet->source_port); |
@@ -350,7 +363,8 @@ int sctp_packet_transmit(struct sctp_packet *packet) | |||
350 | * Note: Adler-32 is no longer applicable, as has been replaced | 363 | * Note: Adler-32 is no longer applicable, as has been replaced |
351 | * by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>. | 364 | * by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>. |
352 | */ | 365 | */ |
353 | crc32 = sctp_start_cksum((__u8 *)sh, sizeof(struct sctphdr)); | 366 | if (!(dst->dev->features & NETIF_F_NO_CSUM)) |
367 | crc32 = sctp_start_cksum((__u8 *)sh, sizeof(struct sctphdr)); | ||
354 | 368 | ||
355 | /** | 369 | /** |
356 | * 6.10 Bundling | 370 | * 6.10 Bundling |
@@ -402,9 +416,14 @@ int sctp_packet_transmit(struct sctp_packet *packet) | |||
402 | if (padding) | 416 | if (padding) |
403 | memset(skb_put(chunk->skb, padding), 0, padding); | 417 | memset(skb_put(chunk->skb, padding), 0, padding); |
404 | 418 | ||
405 | crc32 = sctp_update_copy_cksum(skb_put(nskb, chunk->skb->len), | 419 | if (dst->dev->features & NETIF_F_NO_CSUM) |
406 | chunk->skb->data, | 420 | memcpy(skb_put(nskb, chunk->skb->len), |
407 | chunk->skb->len, crc32); | 421 | 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); | ||
408 | 427 | ||
409 | SCTP_DEBUG_PRINTK("%s %p[%s] %s 0x%x, %s %d, %s %d, %s %d\n", | 428 | SCTP_DEBUG_PRINTK("%s %p[%s] %s 0x%x, %s %d, %s %d, %s %d\n", |
410 | "*** Chunk", chunk, | 429 | "*** Chunk", chunk, |
@@ -427,7 +446,8 @@ int sctp_packet_transmit(struct sctp_packet *packet) | |||
427 | } | 446 | } |
428 | 447 | ||
429 | /* Perform final transformation on checksum. */ | 448 | /* Perform final transformation on checksum. */ |
430 | crc32 = sctp_end_cksum(crc32); | 449 | if (!(dst->dev->features & NETIF_F_NO_CSUM)) |
450 | crc32 = sctp_end_cksum(crc32); | ||
431 | 451 | ||
432 | /* 3) Put the resultant value into the checksum field in the | 452 | /* 3) Put the resultant value into the checksum field in the |
433 | * common header, and leave the rest of the bits unchanged. | 453 | * common header, and leave the rest of the bits unchanged. |
@@ -477,20 +497,6 @@ int sctp_packet_transmit(struct sctp_packet *packet) | |||
477 | } | 497 | } |
478 | } | 498 | } |
479 | 499 | ||
480 | dst = tp->dst; | ||
481 | /* The 'obsolete' field of dst is set to 2 when a dst is freed. */ | ||
482 | if (!dst || (dst->obsolete > 1)) { | ||
483 | dst_release(dst); | ||
484 | sctp_transport_route(tp, NULL, sctp_sk(sk)); | ||
485 | if (asoc->param_flags & SPP_PMTUD_ENABLE) { | ||
486 | sctp_assoc_sync_pmtu(asoc); | ||
487 | } | ||
488 | } | ||
489 | |||
490 | nskb->dst = dst_clone(tp->dst); | ||
491 | if (!nskb->dst) | ||
492 | goto no_route; | ||
493 | |||
494 | SCTP_DEBUG_PRINTK("***sctp_transmit_packet*** skb len %d\n", | 500 | SCTP_DEBUG_PRINTK("***sctp_transmit_packet*** skb len %d\n", |
495 | nskb->len); | 501 | nskb->len); |
496 | 502 | ||