@@ -25,6 +25,7 @@
#include <linux/security.h>
#include <linux/skbuff.h>
#include <linux/errno.h>
+#include <linux/hash.h>
#include <linux/netlink.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
@@ -443,9 +444,44 @@ static int ctnetlink_dump_ct_seq_adj(struct sk_buff *skb, struct nf_conn *ct)
return -1;
}
+static __be32 ct_to_id(const struct nf_conn *ct)
+{
+ static u32 seed __read_mostly;
+ u32 a, b, c;
+
+ if (!ct)
+ return 0;
+
+ if (!seed)
+ seed = get_random_u32();
+
+ a = jhash2((u32 *)ct->tuplehash, sizeof(ct->tuplehash) / sizeof(u32),
+ hash32_ptr(ct));
+ b = ct_to_id(ct->master) ^ net_hash_mix(nf_ct_net(ct));
+ c = hash32_ptr(ct->ext);
+
+ return (__force __be32)jhash_3words(a, b, c, seed);
+}
+
+static __be32 ctexp_to_id(const struct nf_conntrack_expect *exp)
+{
+ static u32 seed __read_mostly;
+ u32 a, b, c;
+
+ if (!seed)
+ seed = get_random_u32();
+
+ a = ct_to_id(exp->master);
+ b = hash32_ptr(exp->helper);
+ c = jhash2((u32 *)&exp->tuple, sizeof(exp->tuple) / sizeof(u32),
+ hash32_ptr(exp));
+
+ return (__force __be32)jhash_3words(a, b, c, seed);
+}
+
static int ctnetlink_dump_id(struct sk_buff *skb, const struct nf_conn *ct)
{
- if (nla_put_be32(skb, CTA_ID, htonl((unsigned long)ct)))
+ if (nla_put_be32(skb, CTA_ID, ct_to_id(ct)))
goto nla_put_failure;
return 0;
@@ -1164,8 +1200,8 @@ static int ctnetlink_del_conntrack(struct net *net, struct sock *ctnl,
ct = nf_ct_tuplehash_to_ctrack(h);
if (cda[CTA_ID]) {
- u_int32_t id = ntohl(nla_get_be32(cda[CTA_ID]));
- if (id != (u32)(unsigned long)ct) {
+ __be32 id = nla_get_be32(cda[CTA_ID]);
+ if (id != ct_to_id(ct)) {
nf_ct_put(ct);
return -ENOENT;
}
@@ -2563,7 +2599,7 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb,
}
#endif
if (nla_put_be32(skb, CTA_EXPECT_TIMEOUT, htonl(timeout)) ||
- nla_put_be32(skb, CTA_EXPECT_ID, htonl((unsigned long)exp)) ||
+ nla_put_be32(skb, CTA_EXPECT_ID, ctexp_to_id(exp)) ||
nla_put_be32(skb, CTA_EXPECT_FLAGS, htonl(exp->flags)) ||
nla_put_be32(skb, CTA_EXPECT_CLASS, htonl(exp->class)))
goto nla_put_failure;
@@ -2871,7 +2907,7 @@ static int ctnetlink_get_expect(struct net *net, struct sock *ctnl,
if (cda[CTA_EXPECT_ID]) {
__be32 id = nla_get_be32(cda[CTA_EXPECT_ID]);
- if (ntohl(id) != (u32)(unsigned long)exp) {
+ if (id != ctexp_to_id(exp)) {
nf_ct_expect_put(exp);
return -ENOENT;
}