diff options
Diffstat (limited to 'net/ipv6/reassembly.c')
-rw-r--r-- | net/ipv6/reassembly.c | 25 |
1 files changed, 17 insertions, 8 deletions
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 1dde449379fb..f85e49acb91a 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
@@ -436,13 +436,18 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
436 | if ((unsigned int)end > IPV6_MAXPLEN) { | 436 | if ((unsigned int)end > IPV6_MAXPLEN) { |
437 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), | 437 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
438 | IPSTATS_MIB_INHDRERRORS); | 438 | IPSTATS_MIB_INHDRERRORS); |
439 | icmpv6_param_prob(skb,ICMPV6_HDR_FIELD, (u8*)&fhdr->frag_off - skb->nh.raw); | 439 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, |
440 | ((u8 *)&fhdr->frag_off - | ||
441 | skb_network_header(skb))); | ||
440 | return; | 442 | return; |
441 | } | 443 | } |
442 | 444 | ||
443 | if (skb->ip_summed == CHECKSUM_COMPLETE) | 445 | if (skb->ip_summed == CHECKSUM_COMPLETE) { |
446 | const unsigned char *nh = skb_network_header(skb); | ||
444 | skb->csum = csum_sub(skb->csum, | 447 | skb->csum = csum_sub(skb->csum, |
445 | csum_partial(skb->nh.raw, (u8*)(fhdr+1)-skb->nh.raw, 0)); | 448 | csum_partial(nh, (u8 *)(fhdr + 1) - nh, |
449 | 0)); | ||
450 | } | ||
446 | 451 | ||
447 | /* Is this the final fragment? */ | 452 | /* Is this the final fragment? */ |
448 | if (!(fhdr->frag_off & htons(IP6_MF))) { | 453 | if (!(fhdr->frag_off & htons(IP6_MF))) { |
@@ -605,7 +610,9 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in, | |||
605 | BUG_TRAP(FRAG6_CB(head)->offset == 0); | 610 | BUG_TRAP(FRAG6_CB(head)->offset == 0); |
606 | 611 | ||
607 | /* Unfragmented part is taken from the first segment. */ | 612 | /* Unfragmented part is taken from the first segment. */ |
608 | payload_len = (head->data - head->nh.raw) - sizeof(struct ipv6hdr) + fq->len - sizeof(struct frag_hdr); | 613 | payload_len = ((head->data - skb_network_header(head)) - |
614 | sizeof(struct ipv6hdr) + fq->len - | ||
615 | sizeof(struct frag_hdr)); | ||
609 | if (payload_len > IPV6_MAXPLEN) | 616 | if (payload_len > IPV6_MAXPLEN) |
610 | goto out_oversize; | 617 | goto out_oversize; |
611 | 618 | ||
@@ -639,7 +646,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in, | |||
639 | /* We have to remove fragment header from datagram and to relocate | 646 | /* We have to remove fragment header from datagram and to relocate |
640 | * header in order to calculate ICV correctly. */ | 647 | * header in order to calculate ICV correctly. */ |
641 | nhoff = fq->nhoffset; | 648 | nhoff = fq->nhoffset; |
642 | head->nh.raw[nhoff] = head->h.raw[0]; | 649 | skb_network_header(head)[nhoff] = head->h.raw[0]; |
643 | memmove(head->head + sizeof(struct frag_hdr), head->head, | 650 | memmove(head->head + sizeof(struct frag_hdr), head->head, |
644 | (head->data - head->head) - sizeof(struct frag_hdr)); | 651 | (head->data - head->head) - sizeof(struct frag_hdr)); |
645 | head->mac.raw += sizeof(struct frag_hdr); | 652 | head->mac.raw += sizeof(struct frag_hdr); |
@@ -647,7 +654,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in, | |||
647 | 654 | ||
648 | skb_shinfo(head)->frag_list = head->next; | 655 | skb_shinfo(head)->frag_list = head->next; |
649 | head->h.raw = head->data; | 656 | head->h.raw = head->data; |
650 | skb_push(head, head->data - head->nh.raw); | 657 | skb_push(head, head->data - skb_network_header(head)); |
651 | atomic_sub(head->truesize, &ip6_frag_mem); | 658 | atomic_sub(head->truesize, &ip6_frag_mem); |
652 | 659 | ||
653 | for (fp=head->next; fp; fp = fp->next) { | 660 | for (fp=head->next; fp; fp = fp->next) { |
@@ -671,7 +678,9 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in, | |||
671 | 678 | ||
672 | /* Yes, and fold redundant checksum back. 8) */ | 679 | /* Yes, and fold redundant checksum back. 8) */ |
673 | if (head->ip_summed == CHECKSUM_COMPLETE) | 680 | if (head->ip_summed == CHECKSUM_COMPLETE) |
674 | head->csum = csum_partial(head->nh.raw, head->h.raw-head->nh.raw, head->csum); | 681 | head->csum = csum_partial(skb_network_header(head), |
682 | head->h.raw - head->nh.raw, | ||
683 | head->csum); | ||
675 | 684 | ||
676 | rcu_read_lock(); | 685 | rcu_read_lock(); |
677 | IP6_INC_STATS_BH(__in6_dev_get(dev), IPSTATS_MIB_REASMOKS); | 686 | IP6_INC_STATS_BH(__in6_dev_get(dev), IPSTATS_MIB_REASMOKS); |
@@ -725,7 +734,7 @@ static int ipv6_frag_rcv(struct sk_buff **skbp) | |||
725 | skb->h.raw += sizeof(struct frag_hdr); | 734 | skb->h.raw += sizeof(struct frag_hdr); |
726 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMOKS); | 735 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMOKS); |
727 | 736 | ||
728 | IP6CB(skb)->nhoff = (u8*)fhdr - skb->nh.raw; | 737 | IP6CB(skb)->nhoff = (u8 *)fhdr - skb_network_header(skb); |
729 | return 1; | 738 | return 1; |
730 | } | 739 | } |
731 | 740 | ||