Socket hash lookups are made within namespace.
Hash tables are common for all namespaces, with
additional permutation of indexes.

Signed-off-by: Andrey Savochkin <[EMAIL PROTECTED]>
---
 include/linux/ipv6.h             |    3 ++-
 include/net/inet6_hashtables.h   |    6 ++++--
 include/net/inet_hashtables.h    |   38 +++++++++++++++++++++++++-------------
 include/net/inet_sock.h          |    6 ++++--
 include/net/inet_timewait_sock.h |    2 ++
 include/net/sock.h               |    4 ++++
 include/net/udp.h                |   12 +++++++++---
 net/core/sock.c                  |    5 +++++
 net/ipv4/inet_connection_sock.c  |   19 +++++++++++++++----
 net/ipv4/inet_hashtables.c       |   29 ++++++++++++++++++++++-------
 net/ipv4/inet_timewait_sock.c    |    8 ++++++--
 net/ipv4/raw.c                   |    2 ++
 net/ipv4/udp.c                   |   20 +++++++++++++-------
 net/ipv6/inet6_connection_sock.c |    2 ++
 net/ipv6/inet6_hashtables.c      |   25 ++++++++++++++++++-------
 net/ipv6/raw.c                   |    4 ++++
 net/ipv6/udp.c                   |   21 ++++++++++++++-------
 17 files changed, 151 insertions(+), 55 deletions(-)

--- ./include/linux/ipv6.h.venssock     Mon Aug 14 17:02:45 2006
+++ ./include/linux/ipv6.h      Tue Aug 15 13:38:47 2006
@@ -428,10 +428,11 @@ static inline struct raw6_sock *raw6_sk(
 #define inet_v6_ipv6only(__sk)         0
 #endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
 
-#define INET6_MATCH(__sk, __hash, __saddr, __daddr, __ports, __dif)\
+#define INET6_MATCH(__sk, __hash, __saddr, __daddr, __ports, __dif, __ns)\
        (((__sk)->sk_hash == (__hash))                          && \
         ((*((__u32 *)&(inet_sk(__sk)->dport))) == (__ports))   && \
         ((__sk)->sk_family             == AF_INET6)            && \
+        net_ns_match((__sk)->sk_net_ns, __ns)                  && \
         ipv6_addr_equal(&inet6_sk(__sk)->daddr, (__saddr))     && \
         ipv6_addr_equal(&inet6_sk(__sk)->rcv_saddr, (__daddr)) && \
         (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
--- ./include/net/inet6_hashtables.h.venssock   Mon Aug 14 17:02:47 2006
+++ ./include/net/inet6_hashtables.h    Tue Aug 15 13:38:47 2006
@@ -26,11 +26,13 @@ struct inet_hashinfo;
 
 /* I have no idea if this is a good hash for v6 or not. -DaveM */
 static inline unsigned int inet6_ehashfn(const struct in6_addr *laddr, const 
u16 lport,
-                               const struct in6_addr *faddr, const u16 fport)
+                               const struct in6_addr *faddr, const u16 fport,
+                               struct net_namespace *ns)
 {
        unsigned int hashent = (lport ^ fport);
 
        hashent ^= (laddr->s6_addr32[3] ^ faddr->s6_addr32[3]);
+       hashent ^= net_ns_hash(ns);
        hashent ^= hashent >> 16;
        hashent ^= hashent >> 8;
        return hashent;
@@ -44,7 +46,7 @@ static inline int inet6_sk_ehashfn(const
        const struct in6_addr *faddr = &np->daddr;
        const __u16 lport = inet->num;
        const __u16 fport = inet->dport;
-       return inet6_ehashfn(laddr, lport, faddr, fport);
+       return inet6_ehashfn(laddr, lport, faddr, fport, current_net_ns);
 }
 
 extern void __inet6_hash(struct inet_hashinfo *hashinfo, struct sock *sk);
--- ./include/net/inet_hashtables.h.venssock    Mon Aug 14 17:04:04 2006
+++ ./include/net/inet_hashtables.h     Tue Aug 15 13:38:47 2006
@@ -74,6 +74,9 @@ struct inet_ehash_bucket {
  * ports are created in O(1) time?  I thought so. ;-)  -DaveM
  */
 struct inet_bind_bucket {
+#ifdef CONFIG_NET_NS
+       struct net_namespace    *net_ns;
+#endif
        unsigned short          port;
        signed short            fastreuse;
        struct hlist_node       node;
@@ -142,30 +145,34 @@ extern struct inet_bind_bucket *
 extern void inet_bind_bucket_destroy(kmem_cache_t *cachep,
                                     struct inet_bind_bucket *tb);
 
-static inline int inet_bhashfn(const __u16 lport, const int bhash_size)
+static inline int inet_bhashfn(const __u16 lport,
+                              struct net_namespace *ns,
+                              const int bhash_size)
 {
-       return lport & (bhash_size - 1);
+       return (lport ^ net_ns_hash(ns)) & (bhash_size - 1);
 }
 
 extern void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb,
                           const unsigned short snum);
 
 /* These can have wildcards, don't try too hard. */
-static inline int inet_lhashfn(const unsigned short num)
+static inline int inet_lhashfn(const unsigned short num,
+                              struct net_namespace *ns)
 {
-       return num & (INET_LHTABLE_SIZE - 1);
+       return (num ^ net_ns_hash(ns)) & (INET_LHTABLE_SIZE - 1);
 }
 
 static inline int inet_sk_listen_hashfn(const struct sock *sk)
 {
-       return inet_lhashfn(inet_sk(sk)->num);
+       return inet_lhashfn(inet_sk(sk)->num, current_net_ns);
 }
 
 /* Caller must disable local BH processing. */
 static inline void __inet_inherit_port(struct inet_hashinfo *table,
                                       struct sock *sk, struct sock *child)
 {
-       const int bhash = inet_bhashfn(inet_sk(child)->num, table->bhash_size);
+       const int bhash = inet_bhashfn(inet_sk(child)->num, current_net_ns,
+                                       table->bhash_size);
        struct inet_bind_hashbucket *head = &table->bhash[bhash];
        struct inet_bind_bucket *tb;
 
@@ -299,29 +306,33 @@ static inline struct sock *inet_lookup_l
 #define INET_ADDR_COOKIE(__name, __saddr, __daddr) \
        const __u64 __name = (((__u64)(__daddr)) << 32) | ((__u64)(__saddr));
 #endif /* __BIG_ENDIAN */
-#define INET_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)\
+#define INET_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif, 
__ns)\
        (((__sk)->sk_hash == (__hash))                          &&      \
         ((*((__u64 *)&(inet_sk(__sk)->daddr))) == (__cookie))  &&      \
         ((*((__u32 *)&(inet_sk(__sk)->dport))) == (__ports))   &&      \
+        net_ns_match((__sk)->sk_net_ns, __ns)                  &&      \
         (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
-#define INET_TW_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, 
__dif)\
+#define INET_TW_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, 
__dif, __ns)\
        (((__sk)->sk_hash == (__hash))                          &&      \
         ((*((__u64 *)&(inet_twsk(__sk)->tw_daddr))) == (__cookie)) &&  \
         ((*((__u32 *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) &&   \
+        net_ns_match((__sk)->sk_net_ns, __ns)                  &&      \
         (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
 #else /* 32-bit arch */
 #define INET_ADDR_COOKIE(__name, __saddr, __daddr)
-#define INET_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)   
\
+#define INET_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif, 
__ns)\
        (((__sk)->sk_hash == (__hash))                          &&      \
         (inet_sk(__sk)->daddr          == (__saddr))           &&      \
         (inet_sk(__sk)->rcv_saddr      == (__daddr))           &&      \
         ((*((__u32 *)&(inet_sk(__sk)->dport))) == (__ports))   &&      \
+        net_ns_match((__sk)->sk_net_ns, __ns)                  &&      \
         (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
-#define INET_TW_MATCH(__sk, __hash,__cookie, __saddr, __daddr, __ports, __dif) 
\
+#define INET_TW_MATCH(__sk, __hash,__cookie, __saddr, __daddr, __ports, __dif, 
__ns)\
        (((__sk)->sk_hash == (__hash))                          &&      \
         (inet_twsk(__sk)->tw_daddr     == (__saddr))           &&      \
         (inet_twsk(__sk)->tw_rcv_saddr == (__daddr))           &&      \
         ((*((__u32 *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) &&   \
+        net_ns_match((__sk)->sk_net_ns, __ns)                  &&      \
         (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
 #endif /* 64-bit arch */
 
@@ -341,22 +352,23 @@ static inline struct sock *
        const __u32 ports = INET_COMBINED_PORTS(sport, hnum);
        struct sock *sk;
        const struct hlist_node *node;
+       struct net_namespace *ns = current_net_ns;
        /* Optimize here for direct hit, only listening connections can
         * have wildcards anyways.
         */
-       unsigned int hash = inet_ehashfn(daddr, hnum, saddr, sport);
+       unsigned int hash = inet_ehashfn(daddr, hnum, saddr, sport, ns);
        struct inet_ehash_bucket *head = inet_ehash_bucket(hashinfo, hash);
 
        prefetch(head->chain.first);
        read_lock(&head->lock);
        sk_for_each(sk, node, &head->chain) {
-               if (INET_MATCH(sk, hash, acookie, saddr, daddr, ports, dif))
+               if (INET_MATCH(sk, hash, acookie, saddr, daddr, ports, dif, ns))
                        goto hit; /* You sunk my battleship! */
        }
 
        /* Must check for a TIME_WAIT'er before going to listener hash. */
        sk_for_each(sk, node, &(head + hashinfo->ehash_size)->chain) {
-               if (INET_TW_MATCH(sk, hash, acookie, saddr, daddr, ports, dif))
+               if (INET_TW_MATCH(sk, hash, acookie, saddr, daddr, ports, dif, 
ns))
                        goto hit;
        }
        sk = NULL;
--- ./include/net/inet_sock.h.venssock  Mon Aug 14 17:04:04 2006
+++ ./include/net/inet_sock.h   Tue Aug 15 13:38:47 2006
@@ -168,9 +168,11 @@ static inline void inet_sk_copy_descenda
 extern int inet_sk_rebuild_header(struct sock *sk);
 
 static inline unsigned int inet_ehashfn(const __u32 laddr, const __u16 lport,
-                                       const __u32 faddr, const __u16 fport)
+                                       const __u32 faddr, const __u16 fport,
+                                       struct net_namespace *ns)
 {
        unsigned int h = (laddr ^ lport) ^ (faddr ^ fport);
+       h ^= net_ns_hash(ns);
        h ^= h >> 16;
        h ^= h >> 8;
        return h;
@@ -184,7 +186,7 @@ static inline int inet_sk_ehashfn(const 
        const __u32 faddr = inet->daddr;
        const __u16 fport = inet->dport;
 
-       return inet_ehashfn(laddr, lport, faddr, fport);
+       return inet_ehashfn(laddr, lport, faddr, fport, current_net_ns);
 }
 
 #endif /* _INET_SOCK_H */
--- ./include/net/inet_timewait_sock.h.venssock Mon Aug 14 17:02:47 2006
+++ ./include/net/inet_timewait_sock.h  Tue Aug 15 13:38:47 2006
@@ -115,6 +115,7 @@ struct inet_timewait_sock {
 #define tw_refcnt              __tw_common.skc_refcnt
 #define tw_hash                        __tw_common.skc_hash
 #define tw_prot                        __tw_common.skc_prot
+#define tw_net_ns              __tw_common.skc_net_ns
        volatile unsigned char  tw_substate;
        /* 3 bits hole, try to pack */
        unsigned char           tw_rcv_wscale;
@@ -200,6 +201,7 @@ static inline void inet_twsk_put(struct 
                printk(KERN_DEBUG "%s timewait_sock %p released\n",
                       tw->tw_prot->name, tw);
 #endif
+               put_net_ns(tw->tw_net_ns);
                kmem_cache_free(tw->tw_prot->twsk_prot->twsk_slab, tw);
                module_put(owner);
        }
--- ./include/net/sock.h.venssock       Mon Aug 14 17:04:05 2006
+++ ./include/net/sock.h        Tue Aug 15 13:38:47 2006
@@ -118,6 +118,9 @@ struct sock_common {
        atomic_t                skc_refcnt;
        unsigned int            skc_hash;
        struct proto            *skc_prot;
+#ifdef CONFIG_NET_NS
+       struct net_namespace    *skc_net_ns;
+#endif
 };
 
 /**
@@ -194,6 +197,7 @@ struct sock {
 #define sk_refcnt              __sk_common.skc_refcnt
 #define sk_hash                        __sk_common.skc_hash
 #define sk_prot                        __sk_common.skc_prot
+#define sk_net_ns              __sk_common.skc_net_ns
        unsigned char           sk_shutdown : 2,
                                sk_no_check : 2,
                                sk_userlocks : 4;
--- ./include/net/udp.h.venssock        Mon Mar 20 08:53:29 2006
+++ ./include/net/udp.h Tue Aug 15 13:38:47 2006
@@ -39,13 +39,19 @@ extern rwlock_t udp_hash_lock;
 
 extern int udp_port_rover;
 
-static inline int udp_lport_inuse(u16 num)
+static inline int udp_hashfn(u16 num, struct net_namespace *ns)
+{
+       return (num ^ net_ns_hash(ns)) & (UDP_HTABLE_SIZE - 1);
+}
+
+static inline int udp_lport_inuse(u16 num, struct net_namespace *ns)
 {
        struct sock *sk;
        struct hlist_node *node;
 
-       sk_for_each(sk, node, &udp_hash[num & (UDP_HTABLE_SIZE - 1)])
-               if (inet_sk(sk)->num == num)
+       sk_for_each(sk, node, &udp_hash[udp_hashfn(num, ns)])
+               if (inet_sk(sk)->num == num &&
+                   net_ns_match(sk->sk_net_ns, ns))
                        return 1;
        return 0;
 }
--- ./net/core/sock.c.venssock  Mon Aug 14 17:04:05 2006
+++ ./net/core/sock.c   Tue Aug 15 13:38:47 2006
@@ -858,6 +858,9 @@ struct sock *sk_alloc(int family, gfp_t 
                         */
                        sk->sk_prot = sk->sk_prot_creator = prot;
                        sock_lock_init(sk);
+#ifdef CONFIG_NET_NS
+                       sk->sk_net_ns = get_net_ns(current_net_ns);
+#endif
                }
                
                if (security_sk_alloc(sk, family, priority))
@@ -897,6 +900,7 @@ void sk_free(struct sock *sk)
                       __FUNCTION__, atomic_read(&sk->sk_omem_alloc));
 
        security_sk_free(sk);
+       put_net_ns(sk->sk_net_ns);
        if (sk->sk_prot_creator->slab != NULL)
                kmem_cache_free(sk->sk_prot_creator->slab, sk);
        else
@@ -932,6 +936,7 @@ struct sock *sk_clone(const struct sock 
                lockdep_set_class(&newsk->sk_callback_lock,
                                   af_callback_keys + newsk->sk_family);
 
+               (void) get_net_ns(newsk->sk_net_ns);
                newsk->sk_dst_cache     = NULL;
                newsk->sk_wmem_queued   = 0;
                newsk->sk_forward_alloc = 0;
--- ./net/ipv4/inet_connection_sock.c.venssock  Mon Aug 14 17:04:08 2006
+++ ./net/ipv4/inet_connection_sock.c   Tue Aug 15 13:38:47 2006
@@ -43,10 +43,12 @@ int inet_csk_bind_conflict(const struct 
        struct sock *sk2;
        struct hlist_node *node;
        int reuse = sk->sk_reuse;
+       struct net_namespace *ns = current_net_ns;
 
        sk_for_each_bound(sk2, node, &tb->owners) {
                if (sk != sk2 &&
                    !inet_v6_ipv6only(sk2) &&
+                   net_ns_match(sk2->sk_net_ns, ns) &&
                    (!sk->sk_bound_dev_if ||
                     !sk2->sk_bound_dev_if ||
                     sk->sk_bound_dev_if == sk2->sk_bound_dev_if)) {
@@ -75,6 +77,7 @@ int inet_csk_get_port(struct inet_hashin
        struct inet_bind_hashbucket *head;
        struct hlist_node *node;
        struct inet_bind_bucket *tb;
+       struct net_namespace *ns = current_net_ns;
        int ret;
 
        local_bh_disable();
@@ -85,11 +88,15 @@ int inet_csk_get_port(struct inet_hashin
                int rover = net_random() % (high - low) + low;
 
                do {
-                       head = &hashinfo->bhash[inet_bhashfn(rover, 
hashinfo->bhash_size)];
+                       head = &hashinfo->bhash[inet_bhashfn(rover, ns,
+                                                       hashinfo->bhash_size)];
                        spin_lock(&head->lock);
-                       inet_bind_bucket_for_each(tb, node, &head->chain)
+                       inet_bind_bucket_for_each(tb, node, &head->chain) {
+                               if (!net_ns_match(tb->net_ns, ns))
+                                       continue;
                                if (tb->port == rover)
                                        goto next;
+                       }
                        break;
                next:
                        spin_unlock(&head->lock);
@@ -112,11 +119,15 @@ int inet_csk_get_port(struct inet_hashin
                 */
                snum = rover;
        } else {
-               head = &hashinfo->bhash[inet_bhashfn(snum, 
hashinfo->bhash_size)];
+               head = &hashinfo->bhash[inet_bhashfn(snum, ns,
+                                               hashinfo->bhash_size)];
                spin_lock(&head->lock);
-               inet_bind_bucket_for_each(tb, node, &head->chain)
+               inet_bind_bucket_for_each(tb, node, &head->chain) {
+                       if (!net_ns_match(tb->net_ns, ns))
+                               continue;
                        if (tb->port == snum)
                                goto tb_found;
+               }
        }
        tb = NULL;
        goto tb_not_found;
--- ./net/ipv4/inet_hashtables.c.venssock       Mon Aug 14 17:04:08 2006
+++ ./net/ipv4/inet_hashtables.c        Tue Aug 15 13:43:20 2006
@@ -36,6 +36,9 @@ struct inet_bind_bucket *inet_bind_bucke
        if (tb != NULL) {
                tb->port      = snum;
                tb->fastreuse = 0;
+#ifdef CONFIG_NET_NS
+               tb->net_ns = get_net_ns(current_net_ns);
+#endif
                INIT_HLIST_HEAD(&tb->owners);
                hlist_add_head(&tb->node, &head->chain);
        }
@@ -49,6 +52,7 @@ void inet_bind_bucket_destroy(kmem_cache
 {
        if (hlist_empty(&tb->owners)) {
                __hlist_del(&tb->node);
+               put_net_ns(tb->net_ns);
                kmem_cache_free(cachep, tb);
        }
 }
@@ -66,7 +70,8 @@ void inet_bind_hash(struct sock *sk, str
  */
 static void __inet_put_port(struct inet_hashinfo *hashinfo, struct sock *sk)
 {
-       const int bhash = inet_bhashfn(inet_sk(sk)->num, hashinfo->bhash_size);
+       const int bhash = inet_bhashfn(inet_sk(sk)->num, current_net_ns,
+                                       hashinfo->bhash_size);
        struct inet_bind_hashbucket *head = &hashinfo->bhash[bhash];
        struct inet_bind_bucket *tb;
 
@@ -130,12 +135,15 @@ static struct sock *inet_lookup_listener
                                              const int dif)
 {
        struct sock *result = NULL, *sk;
+       struct net_namespace *ns = current_net_ns;
        const struct hlist_node *node;
        int hiscore = -1;
 
        sk_for_each(sk, node, head) {
                const struct inet_sock *inet = inet_sk(sk);
 
+               if (!net_ns_match(sk->sk_net_ns, ns))
+                       continue;
                if (inet->num == hnum && !ipv6_only_sock(sk)) {
                        const __u32 rcv_saddr = inet->rcv_saddr;
                        int score = sk->sk_family == PF_INET ? 1 : 0;
@@ -168,14 +176,16 @@ struct sock *__inet_lookup_listener(stru
 {
        struct sock *sk = NULL;
        const struct hlist_head *head;
+       struct net_namespace *ns = current_net_ns;
 
        read_lock(&hashinfo->lhash_lock);
-       head = &hashinfo->listening_hash[inet_lhashfn(hnum)];
+       head = &hashinfo->listening_hash[inet_lhashfn(hnum, ns)];
        if (!hlist_empty(head)) {
                const struct inet_sock *inet = inet_sk((sk = __sk_head(head)));
 
                if (inet->num == hnum && !sk->sk_node.next &&
                    (!inet->rcv_saddr || inet->rcv_saddr == daddr) &&
+                   net_ns_match(sk->sk_net_ns, ns) &&
                    (sk->sk_family == PF_INET || !ipv6_only_sock(sk)) &&
                    !sk->sk_bound_dev_if)
                        goto sherry_cache;
@@ -202,7 +212,8 @@ static int __inet_check_established(stru
        int dif = sk->sk_bound_dev_if;
        INET_ADDR_COOKIE(acookie, saddr, daddr)
        const __u32 ports = INET_COMBINED_PORTS(inet->dport, lport);
-       unsigned int hash = inet_ehashfn(daddr, lport, saddr, inet->dport);
+       struct net_namespace *ns = current_net_ns;
+       unsigned int hash = inet_ehashfn(daddr, lport, saddr, inet->dport, ns);
        struct inet_ehash_bucket *head = inet_ehash_bucket(hinfo, hash);
        struct sock *sk2;
        const struct hlist_node *node;
@@ -215,7 +226,7 @@ static int __inet_check_established(stru
        sk_for_each(sk2, node, &(head + hinfo->ehash_size)->chain) {
                tw = inet_twsk(sk2);
 
-               if (INET_TW_MATCH(sk2, hash, acookie, saddr, daddr, ports, 
dif)) {
+               if (INET_TW_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif, 
ns)) {
                        if (twsk_unique(sk, sk2, twp))
                                goto unique;
                        else
@@ -226,7 +237,7 @@ static int __inet_check_established(stru
 
        /* And established part... */
        sk_for_each(sk2, node, &head->chain) {
-               if (INET_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif))
+               if (INET_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif, 
ns))
                        goto not_unique;
        }
 
@@ -274,6 +285,7 @@ int inet_hash_connect(struct inet_timewa
 {
        struct inet_hashinfo *hinfo = death_row->hashinfo;
        const unsigned short snum = inet_sk(sk)->num;
+       struct net_namespace *ns = current_net_ns;
        struct inet_bind_hashbucket *head;
        struct inet_bind_bucket *tb;
        int ret;
@@ -292,7 +304,8 @@ int inet_hash_connect(struct inet_timewa
                local_bh_disable();
                for (i = 1; i <= range; i++) {
                        port = low + (i + offset) % range;
-                       head = &hinfo->bhash[inet_bhashfn(port, 
hinfo->bhash_size)];
+                       head = &hinfo->bhash[inet_bhashfn(port, ns,
+                                               hinfo->bhash_size)];
                        spin_lock(&head->lock);
 
                        /* Does not bother with rcv_saddr checks,
@@ -300,6 +313,8 @@ int inet_hash_connect(struct inet_timewa
                         * unique enough.
                         */
                        inet_bind_bucket_for_each(tb, node, &head->chain) {
+                               if (!net_ns_match(tb->net_ns, ns))
+                                       continue;
                                if (tb->port == port) {
                                        BUG_TRAP(!hlist_empty(&tb->owners));
                                        if (tb->fastreuse >= 0)
@@ -347,7 +362,7 @@ ok:
                goto out;
        }
 
-       head = &hinfo->bhash[inet_bhashfn(snum, hinfo->bhash_size)];
+       head = &hinfo->bhash[inet_bhashfn(snum, ns, hinfo->bhash_size)];
        tb  = inet_csk(sk)->icsk_bind_hash;
        spin_lock_bh(&head->lock);
        if (sk_head(&tb->owners) == sk && !sk->sk_bind_node.next) {
--- ./net/ipv4/inet_timewait_sock.c.venssock    Mon Aug 14 17:02:49 2006
+++ ./net/ipv4/inet_timewait_sock.c     Tue Aug 15 13:38:47 2006
@@ -31,7 +31,7 @@ void __inet_twsk_kill(struct inet_timewa
        write_unlock(&ehead->lock);
 
        /* Disassociate with bind bucket. */
-       bhead = &hashinfo->bhash[inet_bhashfn(tw->tw_num, 
hashinfo->bhash_size)];
+       bhead = &hashinfo->bhash[inet_bhashfn(tw->tw_num, current_net_ns, 
hashinfo->bhash_size)];
        spin_lock(&bhead->lock);
        tb = tw->tw_tb;
        __hlist_del(&tw->tw_bind_node);
@@ -65,7 +65,8 @@ void __inet_twsk_hashdance(struct inet_t
           Note, that any socket with inet->num != 0 MUST be bound in
           binding cache, even if it is closed.
         */
-       bhead = &hashinfo->bhash[inet_bhashfn(inet->num, hashinfo->bhash_size)];
+       bhead = &hashinfo->bhash[inet_bhashfn(inet->num, current_net_ns,
+                                       hashinfo->bhash_size)];
        spin_lock(&bhead->lock);
        tw->tw_tb = icsk->icsk_bind_hash;
        BUG_TRAP(icsk->icsk_bind_hash);
@@ -109,6 +110,9 @@ struct inet_timewait_sock *inet_twsk_all
                tw->tw_hash         = sk->sk_hash;
                tw->tw_ipv6only     = 0;
                tw->tw_prot         = sk->sk_prot_creator;
+#ifdef CONFIG_NET_NS
+               tw->tw_net_ns       = get_net_ns(current_net_ns);
+#endif
                atomic_set(&tw->tw_refcnt, 1);
                inet_twsk_dead_node_init(tw);
                __module_get(tw->tw_prot->owner);
--- ./net/ipv4/raw.c.venssock   Mon Aug 14 17:04:10 2006
+++ ./net/ipv4/raw.c    Tue Aug 15 13:38:47 2006
@@ -106,6 +106,7 @@ struct sock *__raw_v4_lookup(struct sock
                             int dif)
 {
        struct hlist_node *node;
+       struct net_namespace *ns = current_net_ns;
 
        sk_for_each_from(sk, node) {
                struct inet_sock *inet = inet_sk(sk);
@@ -113,6 +114,7 @@ struct sock *__raw_v4_lookup(struct sock
                if (inet->num == num                                    &&
                    !(inet->daddr && inet->daddr != raddr)              &&
                    !(inet->rcv_saddr && inet->rcv_saddr != laddr)      &&
+                   net_ns_match(sk->sk_net_ns, ns)                     &&
                    !(sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif))
                        goto found; /* gotcha */
        }
--- ./net/ipv4/udp.c.venssock   Mon Aug 14 17:04:10 2006
+++ ./net/ipv4/udp.c    Tue Aug 15 13:38:47 2006
@@ -125,6 +125,7 @@ static int udp_v4_get_port(struct sock *
 {
        struct hlist_node *node;
        struct sock *sk2;
+       struct net_namespace *ns = current_net_ns;
        struct inet_sock *inet = inet_sk(sk);
 
        write_lock_bh(&udp_hash_lock);
@@ -140,7 +141,7 @@ static int udp_v4_get_port(struct sock *
                        struct hlist_head *list;
                        int size;
 
-                       list = &udp_hash[result & (UDP_HTABLE_SIZE - 1)];
+                       list = &udp_hash[udp_hashfn(result, ns)];
                        if (hlist_empty(list)) {
                                if (result > sysctl_local_port_range[1])
                                        result = sysctl_local_port_range[0] +
@@ -162,7 +163,7 @@ static int udp_v4_get_port(struct sock *
                                result = sysctl_local_port_range[0]
                                        + ((result - 
sysctl_local_port_range[0]) &
                                           (UDP_HTABLE_SIZE - 1));
-                       if (!udp_lport_inuse(result))
+                       if (!udp_lport_inuse(result, ns))
                                break;
                }
                if (i >= (1 << 16) / UDP_HTABLE_SIZE)
@@ -170,13 +171,13 @@ static int udp_v4_get_port(struct sock *
 gotit:
                udp_port_rover = snum = result;
        } else {
-               sk_for_each(sk2, node,
-                           &udp_hash[snum & (UDP_HTABLE_SIZE - 1)]) {
+               sk_for_each(sk2, node, &udp_hash[udp_hashfn(snum, ns)]) {
                        struct inet_sock *inet2 = inet_sk(sk2);
 
                        if (inet2->num == snum &&
                            sk2 != sk &&
                            !ipv6_only_sock(sk2) &&
+                           net_ns_match(sk2->sk_net_ns, ns) &&
                            (!sk2->sk_bound_dev_if ||
                             !sk->sk_bound_dev_if ||
                             sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
@@ -189,7 +190,7 @@ gotit:
        }
        inet->num = snum;
        if (sk_unhashed(sk)) {
-               struct hlist_head *h = &udp_hash[snum & (UDP_HTABLE_SIZE - 1)];
+               struct hlist_head *h = &udp_hash[udp_hashfn(snum, ns)];
 
                sk_add_node(sk, h);
                sock_prot_inc_use(sk->sk_prot);
@@ -225,12 +226,15 @@ static struct sock *udp_v4_lookup_longwa
 {
        struct sock *sk, *result = NULL;
        struct hlist_node *node;
+       struct net_namespace *ns = current_net_ns;
        unsigned short hnum = ntohs(dport);
        int badness = -1;
 
-       sk_for_each(sk, node, &udp_hash[hnum & (UDP_HTABLE_SIZE - 1)]) {
+       sk_for_each(sk, node, &udp_hash[udp_hashfn(hnum, ns)]) {
                struct inet_sock *inet = inet_sk(sk);
 
+               if (!net_ns_match(sk->sk_net_ns, ns))
+                       continue;
                if (inet->num == hnum && !ipv6_only_sock(sk)) {
                        int score = (sk->sk_family == PF_INET ? 1 : 0);
                        if (inet->rcv_saddr) {
@@ -285,6 +289,7 @@ static inline struct sock *udp_v4_mcast_
 {
        struct hlist_node *node;
        struct sock *s = sk;
+       struct net_namespace *ns = current_net_ns;
        unsigned short hnum = ntohs(loc_port);
 
        sk_for_each_from(s, node) {
@@ -295,6 +300,7 @@ static inline struct sock *udp_v4_mcast_
                    (inet->dport != rmt_port && inet->dport)            ||
                    (inet->rcv_saddr && inet->rcv_saddr != loc_addr)    ||
                    ipv6_only_sock(s)                                   ||
+                   !net_ns_match(sk->sk_net_ns, ns)                    ||
                    (s->sk_bound_dev_if && s->sk_bound_dev_if != dif))
                        continue;
                if (!ip_mc_sf_allow(s, loc_addr, rmt_addr, dif))
@@ -1063,7 +1069,7 @@ static int udp_v4_mcast_deliver(struct s
        int dif;
 
        read_lock(&udp_hash_lock);
-       sk = sk_head(&udp_hash[ntohs(uh->dest) & (UDP_HTABLE_SIZE - 1)]);
+       sk = sk_head(&udp_hash[udp_hashfn(ntohs(uh->dest), current_net_ns)]);
        dif = skb->dev->ifindex;
        sk = udp_v4_mcast_next(sk, uh->dest, daddr, uh->source, saddr, dif);
        if (sk) {
--- ./net/ipv6/inet6_connection_sock.c.venssock Mon Aug 14 17:04:10 2006
+++ ./net/ipv6/inet6_connection_sock.c  Tue Aug 15 13:38:47 2006
@@ -31,10 +31,12 @@ int inet6_csk_bind_conflict(const struct
 {
        const struct sock *sk2;
        const struct hlist_node *node;
+       struct net_namespace *ns = current_net_ns;
 
        /* We must walk the whole port owner list in this case. -DaveM */
        sk_for_each_bound(sk2, node, &tb->owners) {
                if (sk != sk2 &&
+                   net_ns_match(sk2->sk_net_ns, ns) &&
                    (!sk->sk_bound_dev_if ||
                     !sk2->sk_bound_dev_if ||
                     sk->sk_bound_dev_if == sk2->sk_bound_dev_if) &&
--- ./net/ipv6/inet6_hashtables.c.venssock      Mon Aug 14 17:02:50 2006
+++ ./net/ipv6/inet6_hashtables.c       Tue Aug 15 13:38:47 2006
@@ -65,17 +65,18 @@ struct sock *__inet6_lookup_established(
        struct sock *sk;
        const struct hlist_node *node;
        const __u32 ports = INET_COMBINED_PORTS(sport, hnum);
+       struct net_namespace *ns = current_net_ns;
        /* Optimize here for direct hit, only listening connections can
         * have wildcards anyways.
         */
-       unsigned int hash = inet6_ehashfn(daddr, hnum, saddr, sport);
+       unsigned int hash = inet6_ehashfn(daddr, hnum, saddr, sport, ns);
        struct inet_ehash_bucket *head = inet_ehash_bucket(hashinfo, hash);
 
        prefetch(head->chain.first);
        read_lock(&head->lock);
        sk_for_each(sk, node, &head->chain) {
                /* For IPV6 do the cheaper port and family tests first. */
-               if (INET6_MATCH(sk, hash, saddr, daddr, ports, dif))
+               if (INET6_MATCH(sk, hash, saddr, daddr, ports, dif, ns))
                        goto hit; /* You sunk my battleship! */
        }
        /* Must check for a TIME_WAIT'er before going to listener hash. */
@@ -83,6 +84,7 @@ struct sock *__inet6_lookup_established(
                const struct inet_timewait_sock *tw = inet_twsk(sk);
 
                if(*((__u32 *)&(tw->tw_dport))  == ports        &&
+                  net_ns_match(sk->sk_net_ns, ns)              &&
                   sk->sk_family                == PF_INET6) {
                        const struct inet6_timewait_sock *tw6 = inet6_twsk(sk);
 
@@ -107,12 +109,15 @@ struct sock *inet6_lookup_listener(struc
                                   const unsigned short hnum, const int dif)
 {
        struct sock *sk;
+       struct net_namespace *ns = current_net_ns;
        const struct hlist_node *node;
        struct sock *result = NULL;
        int score, hiscore = 0;
 
        read_lock(&hashinfo->lhash_lock);
-       sk_for_each(sk, node, &hashinfo->listening_hash[inet_lhashfn(hnum)]) {
+       sk_for_each(sk, node, &hashinfo->listening_hash[inet_lhashfn(hnum, 
ns)]) {
+               if (!net_ns_match(sk->sk_net_ns, ns))
+                       continue;
                if (inet_sk(sk)->num == hnum && sk->sk_family == PF_INET6) {
                        const struct ipv6_pinfo *np = inet6_sk(sk);
                        
@@ -172,8 +177,9 @@ static int __inet6_check_established(str
        const struct in6_addr *saddr = &np->daddr;
        const int dif = sk->sk_bound_dev_if;
        const u32 ports = INET_COMBINED_PORTS(inet->dport, lport);
+       struct net_namespace *ns = current_net_ns;
        const unsigned int hash = inet6_ehashfn(daddr, inet->num, saddr,
-                                               inet->dport);
+                                               inet->dport, ns);
        struct inet_ehash_bucket *head = inet_ehash_bucket(hinfo, hash);
        struct sock *sk2;
        const struct hlist_node *node;
@@ -190,6 +196,7 @@ static int __inet6_check_established(str
 
                if(*((__u32 *)&(tw->tw_dport)) == ports          &&
                   sk2->sk_family              == PF_INET6       &&
+                  net_ns_match(sk2->sk_net_ns, ns)              &&
                   ipv6_addr_equal(&tw6->tw_v6_daddr, saddr)     &&
                   ipv6_addr_equal(&tw6->tw_v6_rcv_saddr, daddr) &&
                   sk2->sk_bound_dev_if == sk->sk_bound_dev_if) {
@@ -203,7 +210,7 @@ static int __inet6_check_established(str
 
        /* And established part... */
        sk_for_each(sk2, node, &head->chain) {
-               if (INET6_MATCH(sk2, hash, saddr, daddr, ports, dif))
+               if (INET6_MATCH(sk2, hash, saddr, daddr, ports, dif, ns))
                        goto not_unique;
        }
 
@@ -249,6 +256,7 @@ int inet6_hash_connect(struct inet_timew
 {
        struct inet_hashinfo *hinfo = death_row->hashinfo;
        const unsigned short snum = inet_sk(sk)->num;
+       struct net_namespace *ns = current_net_ns;
        struct inet_bind_hashbucket *head;
        struct inet_bind_bucket *tb;
        int ret;
@@ -266,7 +274,8 @@ int inet6_hash_connect(struct inet_timew
                local_bh_disable();
                for (i = 1; i <= range; i++) {
                        port = low + (i + offset) % range;
-                       head = &hinfo->bhash[inet_bhashfn(port, 
hinfo->bhash_size)];
+                       head = &hinfo->bhash[inet_bhashfn(port, ns,
+                                               hinfo->bhash_size)];
                        spin_lock(&head->lock);
 
                        /* Does not bother with rcv_saddr checks,
@@ -274,6 +283,8 @@ int inet6_hash_connect(struct inet_timew
                         * unique enough.
                         */
                        inet_bind_bucket_for_each(tb, node, &head->chain) {
+                               if (!net_ns_match(tb->net_ns, ns))
+                                       continue;
                                if (tb->port == port) {
                                        BUG_TRAP(!hlist_empty(&tb->owners));
                                        if (tb->fastreuse >= 0)
@@ -322,7 +333,7 @@ ok:
                goto out;
        }
 
-       head = &hinfo->bhash[inet_bhashfn(snum, hinfo->bhash_size)];
+       head = &hinfo->bhash[inet_bhashfn(snum, ns, hinfo->bhash_size)];
        tb   = inet_csk(sk)->icsk_bind_hash;
        spin_lock_bh(&head->lock);
 
--- ./net/ipv6/raw.c.venssock   Mon Aug 14 17:04:10 2006
+++ ./net/ipv6/raw.c    Tue Aug 15 13:38:47 2006
@@ -87,11 +87,15 @@ struct sock *__raw_v6_lookup(struct sock
 {
        struct hlist_node *node;
        int is_multicast = ipv6_addr_is_multicast(loc_addr);
+       struct net_namespace *ns = current_net_ns;
 
        sk_for_each_from(sk, node)
                if (inet_sk(sk)->num == num) {
                        struct ipv6_pinfo *np = inet6_sk(sk);
 
+                       if (!net_ns_match(sk->sk_net_ns, ns))
+                               continue;
+
                        if (!ipv6_addr_any(&np->daddr) &&
                            !ipv6_addr_equal(&np->daddr, rmt_addr))
                                continue;
--- ./net/ipv6/udp.c.venssock   Mon Aug 14 17:04:10 2006
+++ ./net/ipv6/udp.c    Tue Aug 15 13:38:47 2006
@@ -68,6 +68,7 @@ static int udp_v6_get_port(struct sock *
 {
        struct sock *sk2;
        struct hlist_node *node;
+       struct net_namespace *ns = current_net_ns;
 
        write_lock_bh(&udp_hash_lock);
        if (snum == 0) {
@@ -82,7 +83,7 @@ static int udp_v6_get_port(struct sock *
                        int size;
                        struct hlist_head *list;
 
-                       list = &udp_hash[result & (UDP_HTABLE_SIZE - 1)];
+                       list = &udp_hash[udp_hashfn(result, ns)];
                        if (hlist_empty(list)) {
                                if (result > sysctl_local_port_range[1])
                                        result = sysctl_local_port_range[0] +
@@ -104,7 +105,7 @@ static int udp_v6_get_port(struct sock *
                                result = sysctl_local_port_range[0]
                                        + ((result - 
sysctl_local_port_range[0]) &
                                           (UDP_HTABLE_SIZE - 1));
-                       if (!udp_lport_inuse(result))
+                       if (!udp_lport_inuse(result, ns))
                                break;
                }
                if (i >= (1 << 16) / UDP_HTABLE_SIZE)
@@ -112,10 +113,10 @@ static int udp_v6_get_port(struct sock *
 gotit:
                udp_port_rover = snum = result;
        } else {
-               sk_for_each(sk2, node,
-                           &udp_hash[snum & (UDP_HTABLE_SIZE - 1)]) {
+               sk_for_each(sk2, node, &udp_hash[udp_hashfn(snum, ns)]) {
                        if (inet_sk(sk2)->num == snum &&
                            sk2 != sk &&
+                           net_ns_match(sk2->sk_net_ns, ns) &&
                            (!sk2->sk_bound_dev_if ||
                             !sk->sk_bound_dev_if ||
                             sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
@@ -127,7 +128,7 @@ gotit:
 
        inet_sk(sk)->num = snum;
        if (sk_unhashed(sk)) {
-               sk_add_node(sk, &udp_hash[snum & (UDP_HTABLE_SIZE - 1)]);
+               sk_add_node(sk, &udp_hash[udp_hashfn(snum, ns)]);
                sock_prot_inc_use(sk->sk_prot);
        }
        write_unlock_bh(&udp_hash_lock);
@@ -158,13 +159,16 @@ static struct sock *udp_v6_lookup(struct
 {
        struct sock *sk, *result = NULL;
        struct hlist_node *node;
+       struct net_namespace *ns = current_net_ns;
        unsigned short hnum = ntohs(dport);
        int badness = -1;
 
        read_lock(&udp_hash_lock);
-       sk_for_each(sk, node, &udp_hash[hnum & (UDP_HTABLE_SIZE - 1)]) {
+       sk_for_each(sk, node, &udp_hash[udp_hashfn(hnum, ns)]) {
                struct inet_sock *inet = inet_sk(sk);
 
+               if (!net_ns_match(sk->sk_net_ns, ns))
+                       continue;
                if (inet->num == hnum && sk->sk_family == PF_INET6) {
                        struct ipv6_pinfo *np = inet6_sk(sk);
                        int score = 0;
@@ -372,6 +376,7 @@ static struct sock *udp_v6_mcast_next(st
 {
        struct hlist_node *node;
        struct sock *s = sk;
+       struct net_namespace *ns = current_net_ns;
        unsigned short num = ntohs(loc_port);
 
        sk_for_each_from(s, node) {
@@ -383,6 +388,8 @@ static struct sock *udp_v6_mcast_next(st
                                if (inet->dport != rmt_port)
                                        continue;
                        }
+                       if (!net_ns_match(sk->sk_net_ns, ns))
+                               continue;
                        if (!ipv6_addr_any(&np->daddr) &&
                            !ipv6_addr_equal(&np->daddr, rmt_addr))
                                continue;
@@ -414,7 +421,7 @@ static void udpv6_mcast_deliver(struct u
        int dif;
 
        read_lock(&udp_hash_lock);
-       sk = sk_head(&udp_hash[ntohs(uh->dest) & (UDP_HTABLE_SIZE - 1)]);
+       sk = sk_head(&udp_hash[udp_hashfn(uh->dest, current_net_ns)]);
        dif = skb->dev->ifindex;
        sk = udp_v6_mcast_next(sk, uh->dest, daddr, uh->source, saddr, dif);
        if (!sk) {
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to