aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/reassembly.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/reassembly.c')
-rw-r--r--net/ipv6/reassembly.c25
1 files changed, 17 insertions, 8 deletions
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index 1dde449379f..f85e49acb91 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