* [Patch] SO_REUSEADDR fix in ipv4/ipv6 (n connects + 1 listen)
@ 2004-12-15 16:08 Ilya Pashkovsky
0 siblings, 0 replies; only message in thread
From: Ilya Pashkovsky @ 2004-12-15 16:08 UTC (permalink / raw)
To: netdev
[-- Attachment #1: Type: text/plain, Size: 2040 bytes --]
Hello, fellow developers.
This is a proper documentation for the reuse patch, along with
its adoption for 2.6.10rc3-mm1 patchset.
Current implementation of SO_REUSEADDR in the kernel disallows
same port binding if a listening socket is already bound to it.
This limits the options for firewall/nat piercing for applications,
and is non-standard.
The current limit was made because of the security risk
of allowing free binds to same socket. This allowed listen
call preemption and, since no unambiguous and secure fix
was not found, the option to reuse port after listen-bind
was removed. (the problem is that of multiple listeners
bound to same port. this patch does not fix it, since the
behaviour is ambiguos and not defined clearly, though maybe
a userid check along with another flag telling to allow listen
preemption (SO_REUSEPORT can be reused for this purpose) may
solve that.)
Also, SO_REUSEADDR option value is boolean, but is checked
to be more than 1 in code. This check was removed.
The way multiple listeners was removed is by disallowing
any reuse of a port with a bound listener. This is implemented
by a check in tcp_ipv4.c (and tcp_ipv4.c) in function
tcp_bind_conflict(). There's a check for any existing sockets
matching the source port and having a TCP_LISTEN state.
This check was changed to allow binding unless the new
socket is also in TCP_LISTEN state. This still disallows
multiple listeners but allows reuse of the port for
outgoing connections. This check is made/modified in both
ipv4 and ipv6 code.
Testing was done using normal workloads on 2 i386 linux
installations with normal workloads and also the netcat test.
Test with netcat (uses SO_REUSEADDR by default):
host A: nc -v -l -p 9999
host B: nc -v -l -p 9000
host A: nc -v -p 9999 host.B.ip.addr 9000
host B: nc -v host.A.ip.addr 9999
host A and B can be same host.
Testing did not reveal any problems and networking software
worked fine in both ipv4 and ipv6 networks.
Signed-off-by: Ilya Pashkovsky <ilya.pashkovsky@gmail.com>
--
--
ilya
[-- Attachment #2: patch-rc3-mm1-reuse --]
[-- Type: application/octet-stream, Size: 2072 bytes --]
--- linux/net/ipv4/tcp_ipv4.c.orig 2004-12-15 12:30:11.723133016 +0200
+++ linux/net/ipv4/tcp_ipv4.c 2004-12-15 12:30:31.212170232 +0200
@@ -50,6 +50,8 @@
* YOSHIFUJI Hideaki @USAGI and: Support IPV6_V6ONLY socket option, which
* Alexey Kuznetsov allow both IPv4 and IPv6 sockets to bind
* a single port at the same time.
+ * Ilya Pashkovsky : allow reuse of port with single listener
+ * remove boolean sk_reuse > 1 check
*/
#include <linux/config.h>
@@ -193,7 +195,8 @@ static inline int tcp_bind_conflict(stru
!sk2->sk_bound_dev_if ||
sk->sk_bound_dev_if == sk2->sk_bound_dev_if)) {
if (!reuse || !sk2->sk_reuse ||
- sk2->sk_state == TCP_LISTEN) {
+ (sk2->sk_state == TCP_LISTEN &&
+ sk->sk_state == TCP_LISTEN)) {
const u32 sk2_rcv_saddr = tcp_v4_rcv_saddr(sk2);
if (!sk2_rcv_saddr || !sk_rcv_saddr ||
sk2_rcv_saddr == sk_rcv_saddr)
@@ -259,8 +262,6 @@ static int tcp_v4_get_port(struct sock *
goto tb_not_found;
tb_found:
if (!hlist_empty(&tb->owners)) {
- if (sk->sk_reuse > 1)
- goto success;
if (tb->fastreuse > 0 &&
sk->sk_reuse && sk->sk_state != TCP_LISTEN) {
goto success;
--- linux/net/ipv6/tcp_ipv6.c.orig 2004-12-15 12:31:41.888425808 +0200
+++ linux/net/ipv6/tcp_ipv6.c 2004-12-15 01:42:08.603265728 +0200
@@ -18,6 +18,7 @@
* Alexey Kuznetsov allow both IPv4 and IPv6 sockets to bind
* a single port at the same time.
* YOSHIFUJI Hideaki @USAGI: convert /proc/net/tcp6 to seq_file.
+ * Ilya Pashkovsky : allow reuse of port with single listener
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -111,7 +112,8 @@ static inline int tcp_v6_bind_conflict(s
!sk2->sk_bound_dev_if ||
sk->sk_bound_dev_if == sk2->sk_bound_dev_if) &&
(!sk->sk_reuse || !sk2->sk_reuse ||
- sk2->sk_state == TCP_LISTEN) &&
+ (sk2->sk_state == TCP_LISTEN &&
+ sk->sk_state == TCP_LISTEN)) &&
ipv6_rcv_saddr_equal(sk, sk2))
break;
}
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2004-12-15 16:08 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-12-15 16:08 [Patch] SO_REUSEADDR fix in ipv4/ipv6 (n connects + 1 listen) Ilya Pashkovsky
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).