Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=de34ed91c4ffa4727964a832c46e624dd1495cf5
Commit:     de34ed91c4ffa4727964a832c46e624dd1495cf5
Parent:     b7b5f487ab39bc10ed0694af35651a03d9cb97ff
Author:     David S. Miller <[EMAIL PROTECTED]>
AuthorDate: Mon Apr 30 14:51:58 2007 -0700
Committer:  David S. Miller <[EMAIL PROTECTED]>
CommitDate: Mon Apr 30 14:51:58 2007 -0700

    [UDP]: Do not allow specific bind when wildcard bind exists.
    
    When allocating local ports, do not allow a bind to a port
    with a specific local address when a bind to that port with
    a wildcard local address already exists.
    
    Noticed by Linus.
    
    Signed-off-by: David S. Miller <[EMAIL PROTECTED]>
---
 net/ipv4/udp.c |   41 +++++++++++++++++++++++++++++++++--------
 1 files changed, 33 insertions(+), 8 deletions(-)

diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index db313d9..113e0c4 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -203,6 +203,13 @@ int __udp_lib_get_port(struct sock *sk, unsigned short 
snum,
                                result = sysctl_local_port_range[0]
                                        + ((result - 
sysctl_local_port_range[0]) &
                                           (UDP_HTABLE_SIZE - 1));
+                       hash = hash_port_and_addr(result, 0);
+                       if (__udp_lib_port_inuse(hash, result,
+                                                0, udptable))
+                               continue;
+                       if (!inet_sk(sk)->rcv_saddr)
+                               break;
+
                        hash = hash_port_and_addr(result,
                                        inet_sk(sk)->rcv_saddr);
                        if (! __udp_lib_port_inuse(hash, result,
@@ -214,18 +221,36 @@ int __udp_lib_get_port(struct sock *sk, unsigned short 
snum,
 gotit:
                *port_rover = snum = result;
        } else {
-               hash = hash_port_and_addr(snum, inet_sk(sk)->rcv_saddr);
+               hash = hash_port_and_addr(snum, 0);
                head = &udptable[hash & (UDP_HTABLE_SIZE - 1)];
 
                sk_for_each(sk2, node, head)
-                       if (sk2->sk_hash == hash                             &&
-                           sk2 != sk                                        &&
-                           inet_sk(sk2)->num == snum                        &&
-                           (!sk2->sk_reuse        || !sk->sk_reuse)         &&
-                           (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if
-                            || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
-                           (*saddr_comp)(sk, sk2)                             )
+                       if (sk2->sk_hash == hash &&
+                           sk2 != sk &&
+                           inet_sk(sk2)->num == snum &&
+                           (!sk2->sk_reuse || !sk->sk_reuse) &&
+                           (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if ||
+                            sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
+                           (*saddr_comp)(sk, sk2))
                                goto fail;
+
+               if (inet_sk(sk)->rcv_saddr) {
+                       hash = hash_port_and_addr(snum,
+                                                 inet_sk(sk)->rcv_saddr);
+                       head = &udptable[hash & (UDP_HTABLE_SIZE - 1)];
+
+                       sk_for_each(sk2, node, head)
+                               if (sk2->sk_hash == hash &&
+                                   sk2 != sk &&
+                                   inet_sk(sk2)->num == snum &&
+                                   (!sk2->sk_reuse || !sk->sk_reuse) &&
+                                   (!sk2->sk_bound_dev_if ||
+                                    !sk->sk_bound_dev_if ||
+                                    sk2->sk_bound_dev_if ==
+                                    sk->sk_bound_dev_if) &&
+                                   (*saddr_comp)(sk, sk2))
+                                       goto fail;
+               }
        }
        inet_sk(sk)->num = snum;
        sk->sk_hash = hash;
-
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