From patchwork Wed Oct 8 22:31:32 2008 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Dumazet X-Patchwork-Id: 3404 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by ozlabs.org (Postfix) with ESMTP id 51689DDF13 for ; Thu, 9 Oct 2008 09:32:15 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755548AbYJHWcK (ORCPT ); Wed, 8 Oct 2008 18:32:10 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1755534AbYJHWcJ (ORCPT ); Wed, 8 Oct 2008 18:32:09 -0400 Received: from smtp2f.orange.fr ([80.12.242.150]:49396 "EHLO smtp2f.orange.fr" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755339AbYJHWcI (ORCPT ); Wed, 8 Oct 2008 18:32:08 -0400 Received: from me-wanadoo.net (localhost [127.0.0.1]) by mwinf2f28.orange.fr (SMTP Server) with ESMTP id 7FD5B7000090; Thu, 9 Oct 2008 00:32:07 +0200 (CEST) Received: from dniepr.adsl.jetmultimedia.fr (LNeuilly-152-23-22-3.w193-252.abo.wanadoo.fr [193.252.36.3]) by mwinf2f28.orange.fr (SMTP Server) with SMTP id AAFFF7000082; Thu, 9 Oct 2008 00:32:06 +0200 (CEST) X-ME-UUID: 20081008223206700.AAFFF7000082@mwinf2f28.orange.fr Received: from [127.0.0.1] (edumazet.at.jetmultimedia.fr [192.168.224.40] (may be forged)) by dniepr.adsl.jetmultimedia.fr (8.11.7+Sun/8.11.7) with SMTP id m98MW4N11314; Thu, 9 Oct 2008 00:32:04 +0200 (MEST) Message-ID: <48ED34C4.3080203@cosmosbay.com> Date: Thu, 09 Oct 2008 00:31:32 +0200 From: Eric Dumazet User-Agent: Thunderbird 2.0.0.17 (Windows/20080914) MIME-Version: 1.0 To: "David S. Miller" Cc: Linux Netdev List Subject: [RFC, PATCH] udp: complete port availability checking Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org While looking at UDP port randomization, I noticed it was litle bit pessimistic, not looking at type of sockets (IPV6/IPV4) and not looking at bound addresses if any. We should perform same tests than when binding to a specific port. This permits a cleanup of udp_lib_get_port() Signed-off-by: Eric Dumazet diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 67d8430..eacf4cf 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -122,14 +122,23 @@ EXPORT_SYMBOL(sysctl_udp_wmem_min); atomic_t udp_memory_allocated; EXPORT_SYMBOL(udp_memory_allocated); -static inline int __udp_lib_lport_inuse(struct net *net, __u16 num, - const struct hlist_head udptable[]) +static int udp_lib_lport_inuse(struct net *net, __u16 num, + const struct hlist_head udptable[], + struct sock *sk, + int (*saddr_comp)(const struct sock *sk1, + const struct sock *sk2)) { - struct sock *sk; + struct sock *sk2; struct hlist_node *node; - sk_for_each(sk, node, &udptable[udp_hashfn(net, num)]) - if (net_eq(sock_net(sk), net) && sk->sk_hash == num) + sk_for_each(sk2, node, &udptable[udp_hashfn(net, num)]) + if (net_eq(sock_net(sk2), net) && + sk2 != sk && + sk2->sk_hash == num && + (!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)) return 1; return 0; } @@ -146,9 +155,6 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum, const struct sock *sk2 ) ) { struct hlist_head *udptable = sk->sk_prot->h.udp_hash; - struct hlist_node *node; - struct hlist_head *head; - struct sock *sk2; int error = 1; struct net *net = sock_net(sk); @@ -165,32 +171,21 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum, rand = net_random(); snum = first = rand % remaining + low; rand |= 1; - while (__udp_lib_lport_inuse(net, snum, udptable)) { + while (udp_lib_lport_inuse(net, snum, udptable, sk, + saddr_comp)) { do { snum = snum + rand; } while (snum < low || snum > high); if (snum == first) goto fail; } - } else { - head = &udptable[udp_hashfn(net, snum)]; - - sk_for_each(sk2, node, head) - if (sk2->sk_hash == snum && - sk2 != sk && - net_eq(sock_net(sk2), net) && - (!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; - } + } else if (udp_lib_lport_inuse(net, snum, udptable, sk, saddr_comp)) + goto fail; inet_sk(sk)->num = snum; sk->sk_hash = snum; if (sk_unhashed(sk)) { - head = &udptable[udp_hashfn(net, snum)]; - sk_add_node(sk, head); + sk_add_node(sk, &udptable[udp_hashfn(net, snum)]); sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); } error = 0;