aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/ip6_output.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/ip6_output.c')
-rw-r--r--net/ipv6/ip6_output.c14
1 files changed, 8 insertions, 6 deletions
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 26ea47930740..92b1aa38f121 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -586,20 +586,22 @@ int ip6_fragment(struct sock *sk, struct sk_buff *skb,
586 frag_id = ipv6_select_ident(net, &ipv6_hdr(skb)->daddr, 586 frag_id = ipv6_select_ident(net, &ipv6_hdr(skb)->daddr,
587 &ipv6_hdr(skb)->saddr); 587 &ipv6_hdr(skb)->saddr);
588 588
589 hroom = LL_RESERVED_SPACE(rt->dst.dev);
589 if (skb_has_frag_list(skb)) { 590 if (skb_has_frag_list(skb)) {
590 int first_len = skb_pagelen(skb); 591 int first_len = skb_pagelen(skb);
591 struct sk_buff *frag2; 592 struct sk_buff *frag2;
592 593
593 if (first_len - hlen > mtu || 594 if (first_len - hlen > mtu ||
594 ((first_len - hlen) & 7) || 595 ((first_len - hlen) & 7) ||
595 skb_cloned(skb)) 596 skb_cloned(skb) ||
597 skb_headroom(skb) < (hroom + sizeof(struct frag_hdr)))
596 goto slow_path; 598 goto slow_path;
597 599
598 skb_walk_frags(skb, frag) { 600 skb_walk_frags(skb, frag) {
599 /* Correct geometry. */ 601 /* Correct geometry. */
600 if (frag->len > mtu || 602 if (frag->len > mtu ||
601 ((frag->len & 7) && frag->next) || 603 ((frag->len & 7) && frag->next) ||
602 skb_headroom(frag) < hlen) 604 skb_headroom(frag) < (hlen + hroom + sizeof(struct frag_hdr)))
603 goto slow_path_clean; 605 goto slow_path_clean;
604 606
605 /* Partially cloned skb? */ 607 /* Partially cloned skb? */
@@ -616,8 +618,6 @@ int ip6_fragment(struct sock *sk, struct sk_buff *skb,
616 618
617 err = 0; 619 err = 0;
618 offset = 0; 620 offset = 0;
619 frag = skb_shinfo(skb)->frag_list;
620 skb_frag_list_init(skb);
621 /* BUILD HEADER */ 621 /* BUILD HEADER */
622 622
623 *prevhdr = NEXTHDR_FRAGMENT; 623 *prevhdr = NEXTHDR_FRAGMENT;
@@ -625,8 +625,11 @@ int ip6_fragment(struct sock *sk, struct sk_buff *skb,
625 if (!tmp_hdr) { 625 if (!tmp_hdr) {
626 IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), 626 IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
627 IPSTATS_MIB_FRAGFAILS); 627 IPSTATS_MIB_FRAGFAILS);
628 return -ENOMEM; 628 err = -ENOMEM;
629 goto fail;
629 } 630 }
631 frag = skb_shinfo(skb)->frag_list;
632 skb_frag_list_init(skb);
630 633
631 __skb_pull(skb, hlen); 634 __skb_pull(skb, hlen);
632 fh = (struct frag_hdr *)__skb_push(skb, sizeof(struct frag_hdr)); 635 fh = (struct frag_hdr *)__skb_push(skb, sizeof(struct frag_hdr));
@@ -723,7 +726,6 @@ slow_path:
723 */ 726 */
724 727
725 *prevhdr = NEXTHDR_FRAGMENT; 728 *prevhdr = NEXTHDR_FRAGMENT;
726 hroom = LL_RESERVED_SPACE(rt->dst.dev);
727 troom = rt->dst.dev->needed_tailroom; 729 troom = rt->dst.dev->needed_tailroom;
728 730
729 /* 731 /*