Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=b3da2cf37c5c6e47698957a25ab43a7223dbb90f
Commit:     b3da2cf37c5c6e47698957a25ab43a7223dbb90f
Parent:     d30045a0bcf144753869175dd9d840f7ceaf4aba
Author:     David S. Miller <[EMAIL PROTECTED]>
AuthorDate: Fri Mar 23 11:40:27 2007 -0700
Committer:  David S. Miller <[EMAIL PROTECTED]>
CommitDate: Wed Apr 25 22:28:06 2007 -0700

    [INET]: Use jhash + random secret for ehash.
    
    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 <[EMAIL PROTECTED]>
---
 include/net/inet6_hashtables.h |   12 +++++++-----
 include/net/inet_sock.h        |   11 +++++++----
 net/ipv4/af_inet.c             |   16 ++++++++++++++++
 net/ipv6/af_inet6.c            |    5 +++++
 4 files changed, 35 insertions(+), 9 deletions(-)

diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h
index c28e424..668056b 100644
--- a/include/net/inet6_hashtables.h
+++ b/include/net/inet6_hashtables.h
@@ -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)
diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
index ce6da97..62daf21 100644
--- a/include/net/inet_sock.h
+++ b/include/net/inet_sock.h
@@ -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)
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index f011390..b7b7278 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -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. */
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 82572b5..df31cdd 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -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:
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to