diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2007-09-16 19:32:11 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-10-10 19:51:24 -0400 |
commit | 52886051ffdc087a4f7f11540395fd64040101ad (patch) | |
tree | 5b72ca9a1313fb5c0d73b8a4117f59bc3a1a63f2 /net/core | |
parent | 0cfad07555312468296ea3bbbcdf99038f58678b (diff) |
[SKBUFF]: Fix up csum_start when head room changes
Thanks for noticing the bug where csum_start is not updated
when the head room changes.
This patch fixes that. It also moves the csum/ip_summed
copying into copy_skb_header so that skb_copy_expand gets
it too. I've checked its callers and no one should be upset
by this.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/skbuff.c | 18 |
1 files changed, 8 insertions, 10 deletions
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 35021eb3ed07..944189d96323 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -472,6 +472,9 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old) | |||
472 | #ifdef CONFIG_INET | 472 | #ifdef CONFIG_INET |
473 | new->sp = secpath_get(old->sp); | 473 | new->sp = secpath_get(old->sp); |
474 | #endif | 474 | #endif |
475 | new->csum_start = old->csum_start; | ||
476 | new->csum_offset = old->csum_offset; | ||
477 | new->ip_summed = old->ip_summed; | ||
475 | new->transport_header = old->transport_header; | 478 | new->transport_header = old->transport_header; |
476 | new->network_header = old->network_header; | 479 | new->network_header = old->network_header; |
477 | new->mac_header = old->mac_header; | 480 | new->mac_header = old->mac_header; |
@@ -545,8 +548,6 @@ struct sk_buff *skb_copy(const struct sk_buff *skb, gfp_t gfp_mask) | |||
545 | skb_reserve(n, headerlen); | 548 | skb_reserve(n, headerlen); |
546 | /* Set the tail pointer and length */ | 549 | /* Set the tail pointer and length */ |
547 | skb_put(n, skb->len); | 550 | skb_put(n, skb->len); |
548 | n->csum = skb->csum; | ||
549 | n->ip_summed = skb->ip_summed; | ||
550 | 551 | ||
551 | if (skb_copy_bits(skb, -headerlen, n->head, headerlen + skb->len)) | 552 | if (skb_copy_bits(skb, -headerlen, n->head, headerlen + skb->len)) |
552 | BUG(); | 553 | BUG(); |
@@ -589,8 +590,6 @@ struct sk_buff *pskb_copy(struct sk_buff *skb, gfp_t gfp_mask) | |||
589 | skb_put(n, skb_headlen(skb)); | 590 | skb_put(n, skb_headlen(skb)); |
590 | /* Copy the bytes */ | 591 | /* Copy the bytes */ |
591 | skb_copy_from_linear_data(skb, n->data, n->len); | 592 | skb_copy_from_linear_data(skb, n->data, n->len); |
592 | n->csum = skb->csum; | ||
593 | n->ip_summed = skb->ip_summed; | ||
594 | 593 | ||
595 | n->truesize += skb->data_len; | 594 | n->truesize += skb->data_len; |
596 | n->data_len = skb->data_len; | 595 | n->data_len = skb->data_len; |
@@ -686,6 +685,7 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, | |||
686 | skb->transport_header += off; | 685 | skb->transport_header += off; |
687 | skb->network_header += off; | 686 | skb->network_header += off; |
688 | skb->mac_header += off; | 687 | skb->mac_header += off; |
688 | skb->csum_start += off; | ||
689 | skb->cloned = 0; | 689 | skb->cloned = 0; |
690 | skb->hdr_len = 0; | 690 | skb->hdr_len = 0; |
691 | skb->nohdr = 0; | 691 | skb->nohdr = 0; |
@@ -734,9 +734,6 @@ struct sk_buff *skb_realloc_headroom(struct sk_buff *skb, unsigned int headroom) | |||
734 | * | 734 | * |
735 | * You must pass %GFP_ATOMIC as the allocation priority if this function | 735 | * You must pass %GFP_ATOMIC as the allocation priority if this function |
736 | * is called from an interrupt. | 736 | * is called from an interrupt. |
737 | * | ||
738 | * BUG ALERT: ip_summed is not copied. Why does this work? Is it used | ||
739 | * only by netfilter in the cases when checksum is recalculated? --ANK | ||
740 | */ | 737 | */ |
741 | struct sk_buff *skb_copy_expand(const struct sk_buff *skb, | 738 | struct sk_buff *skb_copy_expand(const struct sk_buff *skb, |
742 | int newheadroom, int newtailroom, | 739 | int newheadroom, int newtailroom, |
@@ -749,7 +746,7 @@ struct sk_buff *skb_copy_expand(const struct sk_buff *skb, | |||
749 | gfp_mask); | 746 | gfp_mask); |
750 | int oldheadroom = skb_headroom(skb); | 747 | int oldheadroom = skb_headroom(skb); |
751 | int head_copy_len, head_copy_off; | 748 | int head_copy_len, head_copy_off; |
752 | int off = 0; | 749 | int off; |
753 | 750 | ||
754 | if (!n) | 751 | if (!n) |
755 | return NULL; | 752 | return NULL; |
@@ -773,12 +770,13 @@ struct sk_buff *skb_copy_expand(const struct sk_buff *skb, | |||
773 | 770 | ||
774 | copy_skb_header(n, skb); | 771 | copy_skb_header(n, skb); |
775 | 772 | ||
776 | #ifdef NET_SKBUFF_DATA_USES_OFFSET | ||
777 | off = newheadroom - oldheadroom; | 773 | off = newheadroom - oldheadroom; |
778 | #endif | 774 | n->csum_start += off; |
775 | #ifdef NET_SKBUFF_DATA_USES_OFFSET | ||
779 | n->transport_header += off; | 776 | n->transport_header += off; |
780 | n->network_header += off; | 777 | n->network_header += off; |
781 | n->mac_header += off; | 778 | n->mac_header += off; |
779 | #endif | ||
782 | 780 | ||
783 | return n; | 781 | return n; |
784 | } | 782 | } |