aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/ipv6/output_core.c27
1 files changed, 15 insertions, 12 deletions
diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c
index d1b35d377e62..6313abd53c9d 100644
--- a/net/ipv6/output_core.c
+++ b/net/ipv6/output_core.c
@@ -6,24 +6,24 @@
6#include <net/ipv6.h> 6#include <net/ipv6.h>
7#include <net/ip6_fib.h> 7#include <net/ip6_fib.h>
8#include <net/addrconf.h> 8#include <net/addrconf.h>
9#include <net/secure_seq.h>
9 10
10void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt) 11void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
11{ 12{
12 static atomic_t ipv6_fragmentation_id; 13 static atomic_t ipv6_fragmentation_id;
14 struct in6_addr addr;
13 int old, new; 15 int old, new;
14 16
15#if IS_ENABLED(CONFIG_IPV6) 17#if IS_ENABLED(CONFIG_IPV6)
16 if (rt) { 18 struct inet_peer *peer;
17 struct inet_peer *peer; 19 struct net *net;
18 struct net *net; 20
19 21 net = dev_net(rt->dst.dev);
20 net = dev_net(rt->dst.dev); 22 peer = inet_getpeer_v6(net->ipv6.peers, &rt->rt6i_dst.addr, 1);
21 peer = inet_getpeer_v6(net->ipv6.peers, &rt->rt6i_dst.addr, 1); 23 if (peer) {
22 if (peer) { 24 fhdr->identification = htonl(inet_getid(peer, 0));
23 fhdr->identification = htonl(inet_getid(peer, 0)); 25 inet_putpeer(peer);
24 inet_putpeer(peer); 26 return;
25 return;
26 }
27 } 27 }
28#endif 28#endif
29 do { 29 do {
@@ -32,7 +32,10 @@ void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
32 if (!new) 32 if (!new)
33 new = 1; 33 new = 1;
34 } while (atomic_cmpxchg(&ipv6_fragmentation_id, old, new) != old); 34 } while (atomic_cmpxchg(&ipv6_fragmentation_id, old, new) != old);
35 fhdr->identification = htonl(new); 35
36 addr = rt->rt6i_dst.addr;
37 addr.s6_addr32[0] ^= (__force __be32)new;
38 fhdr->identification = htonl(secure_ipv6_id(addr.s6_addr32));
36} 39}
37EXPORT_SYMBOL(ipv6_select_ident); 40EXPORT_SYMBOL(ipv6_select_ident);
38 41