[<prev] [next>] [day] [month] [year] [list]
Message-ID: <CAExj=OXWfxxXaSpng5OGcQTVjXGVZqR+DycvSsWaYx-bRb5mDw@mail.gmail.com>
Date: Wed, 24 Jan 2018 10:04:49 +0000
From: Gilberto Bertin <gilberto@...udflare.com>
To: netdev@...r.kernel.org
Subject: SO_REUSEADDR semantics and bind conflicts
I'm trying to understand the details of SO_REUSEADDR behaviour. I think
I've found some inconsistencies in how bind conflicts are handled.
In particular, TCP and UDP behaviour seems to differ.
Let’s start with simplest TCP cases.
Case 1:
* Socket A: bound to 0.0.0.0 tcp/1234; SO_REUSEADDR absent
* Socket B: bound to 127.0.0.1 tcp/1234; SO_REUSEADDR present
(doesn't matter if both servers belong to the same uid or not)
Result: bind() fails with EADDRINUSE
This seems desired. Ok.
Case 2: What if both sockets have SO_REUSEADDR?
* Socket A: bound to 0.0.0.0 tcp/1234; SO_REUSEADDR present
* Socket B: bound to 127.0.0.1 tcp/1234; SO_REUSEADDR present
Result: bind() fails with EADDRINUSE
This seems somewhat confusing.
I would expect this one to work, unless I’m mistaken in my reading of
the socket(7) man page:
SO_REUSEADDR
Indicates that the rules used in validating addresses supplied in a
bind(2) call should allow reuse of local addresses. For AF_INET sockets
this means that a socket may bind, except when there is an active
listening socket bound to the address. When the listening socket is
bound to INADDR_ANY with a specific port then it is not possible to
bind to this port for any local address.
does "except when there is an active listening socket bound to the
address" cover also the case when a socket is bound to 0.0.0.0 and
another one is bound to 127.0.0.1?
More questions arise if we repeat the same experiment with UDP sockets.
Case 3:
* Socket A: bound to 0.0.0.0 udp/1234; SO_REUSEADDR absent
* Socket B: bound 127.0.0.1 udp/1234; SO_REUSEADDR present
Result: bind() fails with EADDRINUSE
Case 4:
* Socket A: 0.0.0.0 udp/1234; SO_REUSEADDR present
* Socket B: 127.0.0.1 udp/1234; SO_REUSEADDR present
Result: bind() succeeds!
In practice this leads to a situation where:
* the INADDR_ANY server receives all the datagrams for for port 1234
except the ones directed to 127.0.0.1
* the INADDR_LOOPBACK server receives all the datagrams for
127.0.0.1
why is UDP behaviour different from TCP?
Another confusing case: case 5:
* Socket A: 0.0.0.0 udp/1234; SO_REUSEADDR present
* Socket B: 0.0.0.0 udp/1234; SO_REUSEADDR present
Result: bind() succeeds!
In this case all the datagrams go to the latest server that has been started.
This looks more like a bug, but again, I'd like first to understand the
exact desired semantics of SO_REUSEADDR with regard to bind conflicts.
Thanks,
gilberto
Powered by blists - more mailing lists