]> err.no Git - linux-2.6/commitdiff
[INET]: Use jhash + random secret for ehash.
authorDavid S. Miller <davem@davemloft.net>
Fri, 23 Mar 2007 18:40:27 +0000 (11:40 -0700)
committerDavid S. Miller <davem@sunset.davemloft.net>
Thu, 26 Apr 2007 05:28:06 +0000 (22:28 -0700)
The days are gone when this was not an issue, there are folks out
there with huge bot networks that can be used to attack the
established hash tables on remote systems.

So just like the routing cache and connection tracking
hash, use Jenkins hash with random secret input.

Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/inet6_hashtables.h
include/net/inet_sock.h
net/ipv4/af_inet.c
net/ipv6/af_inet6.c

index c28e424f53d9eb5e28d1480d55562668ef0dba16..668056b4bb0b9982b249b96bf8c33ceb5435c912 100644 (file)
@@ -19,6 +19,9 @@
 #include <linux/in6.h>
 #include <linux/ipv6.h>
 #include <linux/types.h>
+#include <linux/jhash.h>
+
+#include <net/inet_sock.h>
 
 #include <net/ipv6.h>
 
@@ -28,12 +31,11 @@ struct inet_hashinfo;
 static inline unsigned int inet6_ehashfn(const struct in6_addr *laddr, const u16 lport,
                                const struct in6_addr *faddr, const __be16 fport)
 {
-       unsigned int hashent = (lport ^ (__force u16)fport);
+       u32 ports = (lport ^ (__force u16)fport);
 
-       hashent ^= (__force u32)(laddr->s6_addr32[3] ^ faddr->s6_addr32[3]);
-       hashent ^= hashent >> 16;
-       hashent ^= hashent >> 8;
-       return hashent;
+       return jhash_3words((__force u32)laddr->s6_addr32[3],
+                           (__force u32)faddr->s6_addr32[3],
+                           ports, inet_ehash_secret);
 }
 
 static inline int inet6_sk_ehashfn(const struct sock *sk)
index ce6da97bc8489d4fc1e5d8838f0dd3541a78cfc5..62daf214931f5ddf825e5cd9b577b9ea2b6159d3 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <linux/string.h>
 #include <linux/types.h>
+#include <linux/jhash.h>
 
 #include <net/flow.h>
 #include <net/sock.h>
@@ -167,13 +168,15 @@ static inline void inet_sk_copy_descendant(struct sock *sk_to,
 
 extern int inet_sk_rebuild_header(struct sock *sk);
 
+extern u32 inet_ehash_secret;
+extern void build_ehash_secret(void);
+
 static inline unsigned int inet_ehashfn(const __be32 laddr, const __u16 lport,
                                        const __be32 faddr, const __be16 fport)
 {
-       unsigned int h = ((__force __u32)laddr ^ lport) ^ ((__force __u32)faddr ^ (__force __u32)fport);
-       h ^= h >> 16;
-       h ^= h >> 8;
-       return h;
+       return jhash_2words((__force __u32) laddr ^ (__force __u32) faddr,
+                           ((__u32) lport) << 16 | (__force __u32)fport,
+                           inet_ehash_secret);
 }
 
 static inline int inet_sk_ehashfn(const struct sock *sk)
index f011390f19c914764e62b98a0f6c131417abf579..b7b7278d801cf23eaf06b740d87f4e99bd4044d3 100644 (file)
@@ -87,6 +87,7 @@
 #include <linux/init.h>
 #include <linux/poll.h>
 #include <linux/netfilter_ipv4.h>
+#include <linux/random.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -217,6 +218,16 @@ out:
        return err;
 }
 
+u32 inet_ehash_secret;
+EXPORT_SYMBOL(inet_ehash_secret);
+
+void build_ehash_secret(void)
+{
+       while (!inet_ehash_secret)
+               get_random_bytes(&inet_ehash_secret, 4);
+}
+EXPORT_SYMBOL(build_ehash_secret);
+
 /*
  *     Create an inet socket.
  */
@@ -233,6 +244,11 @@ static int inet_create(struct socket *sock, int protocol)
        int try_loading_module = 0;
        int err;
 
+       if (sock->type != SOCK_RAW &&
+           sock->type != SOCK_DGRAM &&
+           !inet_ehash_secret)
+               build_ehash_secret();
+
        sock->state = SS_UNCONNECTED;
 
        /* Look for the requested type/protocol pair. */
index 82572b507547e6bfff720a5e0d6dc8fdbe7c847a..df31cdd33cdade02166cc3ca07c4b3487977d1f7 100644 (file)
@@ -98,6 +98,11 @@ static int inet6_create(struct socket *sock, int protocol)
        int try_loading_module = 0;
        int err;
 
+       if (sock->type != SOCK_RAW &&
+           sock->type != SOCK_DGRAM &&
+           !inet_ehash_secret)
+               build_ehash_secret();
+
        /* Look for the requested type/protocol pair. */
        answer = NULL;
 lookup_protocol: