diff options
-rw-r--r-- | include/net/ipv6.h | 3 | ||||
-rw-r--r-- | net/ipv6/ip6_output.c | 17 | ||||
-rw-r--r-- | net/ipv6/output_core.c | 5 |
3 files changed, 9 insertions, 16 deletions
diff --git a/include/net/ipv6.h b/include/net/ipv6.h index aab8190d16e8..8c4f881edbd2 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h | |||
@@ -671,8 +671,7 @@ static inline int ipv6_addr_diff(const struct in6_addr *a1, const struct in6_add | |||
671 | return __ipv6_addr_diff(a1, a2, sizeof(struct in6_addr)); | 671 | return __ipv6_addr_diff(a1, a2, sizeof(struct in6_addr)); |
672 | } | 672 | } |
673 | 673 | ||
674 | void ipv6_select_ident(struct net *net, struct frag_hdr *fhdr, | 674 | u32 ipv6_select_ident(struct net *net, struct rt6_info *rt); |
675 | struct rt6_info *rt); | ||
676 | void ipv6_proxy_select_ident(struct net *net, struct sk_buff *skb); | 675 | void ipv6_proxy_select_ident(struct net *net, struct sk_buff *skb); |
677 | 676 | ||
678 | int ip6_dst_hoplimit(struct dst_entry *dst); | 677 | int ip6_dst_hoplimit(struct dst_entry *dst); |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index bc09cb97b840..05e2cdf938bd 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -551,7 +551,7 @@ int ip6_fragment(struct sock *sk, struct sk_buff *skb, | |||
551 | struct frag_hdr *fh; | 551 | struct frag_hdr *fh; |
552 | unsigned int mtu, hlen, left, len; | 552 | unsigned int mtu, hlen, left, len; |
553 | int hroom, troom; | 553 | int hroom, troom; |
554 | __be32 frag_id = 0; | 554 | __be32 frag_id; |
555 | int ptr, offset = 0, err = 0; | 555 | int ptr, offset = 0, err = 0; |
556 | u8 *prevhdr, nexthdr = 0; | 556 | u8 *prevhdr, nexthdr = 0; |
557 | struct net *net = dev_net(skb_dst(skb)->dev); | 557 | struct net *net = dev_net(skb_dst(skb)->dev); |
@@ -584,6 +584,8 @@ int ip6_fragment(struct sock *sk, struct sk_buff *skb, | |||
584 | } | 584 | } |
585 | mtu -= hlen + sizeof(struct frag_hdr); | 585 | mtu -= hlen + sizeof(struct frag_hdr); |
586 | 586 | ||
587 | frag_id = ipv6_select_ident(net, rt); | ||
588 | |||
587 | if (skb_has_frag_list(skb)) { | 589 | if (skb_has_frag_list(skb)) { |
588 | int first_len = skb_pagelen(skb); | 590 | int first_len = skb_pagelen(skb); |
589 | struct sk_buff *frag2; | 591 | struct sk_buff *frag2; |
@@ -632,11 +634,10 @@ int ip6_fragment(struct sock *sk, struct sk_buff *skb, | |||
632 | skb_reset_network_header(skb); | 634 | skb_reset_network_header(skb); |
633 | memcpy(skb_network_header(skb), tmp_hdr, hlen); | 635 | memcpy(skb_network_header(skb), tmp_hdr, hlen); |
634 | 636 | ||
635 | ipv6_select_ident(net, fh, rt); | ||
636 | fh->nexthdr = nexthdr; | 637 | fh->nexthdr = nexthdr; |
637 | fh->reserved = 0; | 638 | fh->reserved = 0; |
638 | fh->frag_off = htons(IP6_MF); | 639 | fh->frag_off = htons(IP6_MF); |
639 | frag_id = fh->identification; | 640 | fh->identification = frag_id; |
640 | 641 | ||
641 | first_len = skb_pagelen(skb); | 642 | first_len = skb_pagelen(skb); |
642 | skb->data_len = first_len - skb_headlen(skb); | 643 | skb->data_len = first_len - skb_headlen(skb); |
@@ -778,11 +779,7 @@ slow_path: | |||
778 | */ | 779 | */ |
779 | fh->nexthdr = nexthdr; | 780 | fh->nexthdr = nexthdr; |
780 | fh->reserved = 0; | 781 | fh->reserved = 0; |
781 | if (!frag_id) { | 782 | fh->identification = frag_id; |
782 | ipv6_select_ident(net, fh, rt); | ||
783 | frag_id = fh->identification; | ||
784 | } else | ||
785 | fh->identification = frag_id; | ||
786 | 783 | ||
787 | /* | 784 | /* |
788 | * Copy a block of the IP datagram. | 785 | * Copy a block of the IP datagram. |
@@ -1064,7 +1061,6 @@ static inline int ip6_ufo_append_data(struct sock *sk, | |||
1064 | 1061 | ||
1065 | { | 1062 | { |
1066 | struct sk_buff *skb; | 1063 | struct sk_buff *skb; |
1067 | struct frag_hdr fhdr; | ||
1068 | int err; | 1064 | int err; |
1069 | 1065 | ||
1070 | /* There is support for UDP large send offload by network | 1066 | /* There is support for UDP large send offload by network |
@@ -1106,8 +1102,7 @@ static inline int ip6_ufo_append_data(struct sock *sk, | |||
1106 | skb_shinfo(skb)->gso_size = (mtu - fragheaderlen - | 1102 | skb_shinfo(skb)->gso_size = (mtu - fragheaderlen - |
1107 | sizeof(struct frag_hdr)) & ~7; | 1103 | sizeof(struct frag_hdr)) & ~7; |
1108 | skb_shinfo(skb)->gso_type = SKB_GSO_UDP; | 1104 | skb_shinfo(skb)->gso_type = SKB_GSO_UDP; |
1109 | ipv6_select_ident(sock_net(sk), &fhdr, rt); | 1105 | skb_shinfo(skb)->ip6_frag_id = ipv6_select_ident(sock_net(sk), rt); |
1110 | skb_shinfo(skb)->ip6_frag_id = fhdr.identification; | ||
1111 | 1106 | ||
1112 | append: | 1107 | append: |
1113 | return skb_append_datato_frags(sk, skb, getfrag, from, | 1108 | return skb_append_datato_frags(sk, skb, getfrag, from, |
diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c index 85892af57364..ef0e2326496b 100644 --- a/net/ipv6/output_core.c +++ b/net/ipv6/output_core.c | |||
@@ -60,8 +60,7 @@ void ipv6_proxy_select_ident(struct net *net, struct sk_buff *skb) | |||
60 | } | 60 | } |
61 | EXPORT_SYMBOL_GPL(ipv6_proxy_select_ident); | 61 | EXPORT_SYMBOL_GPL(ipv6_proxy_select_ident); |
62 | 62 | ||
63 | void ipv6_select_ident(struct net *net, struct frag_hdr *fhdr, | 63 | u32 ipv6_select_ident(struct net *net, struct rt6_info *rt) |
64 | struct rt6_info *rt) | ||
65 | { | 64 | { |
66 | static u32 ip6_idents_hashrnd __read_mostly; | 65 | static u32 ip6_idents_hashrnd __read_mostly; |
67 | u32 id; | 66 | u32 id; |
@@ -70,7 +69,7 @@ void ipv6_select_ident(struct net *net, struct frag_hdr *fhdr, | |||
70 | 69 | ||
71 | id = __ipv6_select_ident(net, ip6_idents_hashrnd, &rt->rt6i_dst.addr, | 70 | id = __ipv6_select_ident(net, ip6_idents_hashrnd, &rt->rt6i_dst.addr, |
72 | &rt->rt6i_src.addr); | 71 | &rt->rt6i_src.addr); |
73 | fhdr->identification = htonl(id); | 72 | return htonl(id); |
74 | } | 73 | } |
75 | EXPORT_SYMBOL(ipv6_select_ident); | 74 | EXPORT_SYMBOL(ipv6_select_ident); |
76 | 75 | ||