|
|
@@ -10,15 +10,25 @@
|
|
|
#include <net/secure_seq.h>
|
|
|
#include <linux/netfilter.h>
|
|
|
|
|
|
-static u32 __ipv6_select_ident(struct net *net, u32 hashrnd,
|
|
|
+static u32 __ipv6_select_ident(struct net *net,
|
|
|
const struct in6_addr *dst,
|
|
|
const struct in6_addr *src)
|
|
|
{
|
|
|
+ const struct {
|
|
|
+ struct in6_addr dst;
|
|
|
+ struct in6_addr src;
|
|
|
+ } __aligned(SIPHASH_ALIGNMENT) combined = {
|
|
|
+ .dst = *dst,
|
|
|
+ .src = *src,
|
|
|
+ };
|
|
|
u32 hash, id;
|
|
|
|
|
|
- hash = __ipv6_addr_jhash(dst, hashrnd);
|
|
|
- hash = __ipv6_addr_jhash(src, hash);
|
|
|
- hash ^= net_hash_mix(net);
|
|
|
+ /* Note the following code is not safe, but this is okay. */
|
|
|
+ if (unlikely(siphash_key_is_zero(&net->ipv4.ip_id_key)))
|
|
|
+ get_random_bytes(&net->ipv4.ip_id_key,
|
|
|
+ sizeof(net->ipv4.ip_id_key));
|
|
|
+
|
|
|
+ hash = siphash(&combined, sizeof(combined), &net->ipv4.ip_id_key);
|
|
|
|
|
|
/* Treat id of 0 as unset and if we get 0 back from ip_idents_reserve,
|
|
|
* set the hight order instead thus minimizing possible future
|
|
|
@@ -41,7 +51,6 @@ static u32 __ipv6_select_ident(struct net *net, u32 hashrnd,
|
|
|
*/
|
|
|
__be32 ipv6_proxy_select_ident(struct net *net, struct sk_buff *skb)
|
|
|
{
|
|
|
- static u32 ip6_proxy_idents_hashrnd __read_mostly;
|
|
|
struct in6_addr buf[2];
|
|
|
struct in6_addr *addrs;
|
|
|
u32 id;
|
|
|
@@ -53,11 +62,7 @@ __be32 ipv6_proxy_select_ident(struct net *net, struct sk_buff *skb)
|
|
|
if (!addrs)
|
|
|
return 0;
|
|
|
|
|
|
- net_get_random_once(&ip6_proxy_idents_hashrnd,
|
|
|
- sizeof(ip6_proxy_idents_hashrnd));
|
|
|
-
|
|
|
- id = __ipv6_select_ident(net, ip6_proxy_idents_hashrnd,
|
|
|
- &addrs[1], &addrs[0]);
|
|
|
+ id = __ipv6_select_ident(net, &addrs[1], &addrs[0]);
|
|
|
return htonl(id);
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(ipv6_proxy_select_ident);
|
|
|
@@ -66,12 +71,9 @@ __be32 ipv6_select_ident(struct net *net,
|
|
|
const struct in6_addr *daddr,
|
|
|
const struct in6_addr *saddr)
|
|
|
{
|
|
|
- static u32 ip6_idents_hashrnd __read_mostly;
|
|
|
u32 id;
|
|
|
|
|
|
- net_get_random_once(&ip6_idents_hashrnd, sizeof(ip6_idents_hashrnd));
|
|
|
-
|
|
|
- id = __ipv6_select_ident(net, ip6_idents_hashrnd, daddr, saddr);
|
|
|
+ id = __ipv6_select_ident(net, daddr, saddr);
|
|
|
return htonl(id);
|
|
|
}
|
|
|
EXPORT_SYMBOL(ipv6_select_ident);
|