1

(Running on VS2017, Win7 x64)

I am confused about the point of SO_REUSEADDR and SO_EXCLUSIVEADDRUSE. And yes, I've read the MSDN documentation, but I'm obviously not getting it.

I have the following simple code in two separate processes. As expected, because I enable SO_REUSEADDR on both sockets, the second process's bind succeeds. If I don't enable this on any one of these sockets, the second bind will not succeed.

#define PORT 5150
SOCKET sockListen;
if ((sockListen = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
{
    printf("WSASocket() failed with error %d\n", WSAGetLastError());
    return 1;
}

int optval = 1;
if (setsockopt(sockListen, SOL_SOCKET, `SO_REUSEADDR`, (char*)&optval, sizeof(optval)) == -1)
    return -1;

SOCKADDR_IN InternetAddr;
InternetAddr.sin_family = AF_INET;
InternetAddr.sin_addr.s_addr = inet_addr("10.15.20.97");
InternetAddr.sin_port = htons(PORT);

if (::bind(sockListen, (PSOCKADDR)&InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR)
{
    printf("bind() failed with error %d\n", WSAGetLastError());
    return 1;
}

So doesn't having to enable SO_REUSEADDR for both sockets make SO_EXCLUSIVEADDRUSE unnecessary - if I don't want anyone to foricibly bind to my port, I just don't enable SO_REUSEADDR in that process?

The only difference I can see is that if I enable SO_EXCLUSIVEADDRUSE in the first process, then attempt a bind in the second process, that second bind will fail with

a) WSAEADDRINUSE if I don't enable SO_REUSEADDR in that second process

b) WSAEACCES if I do enable SO_REUSEADDR in that second process

So I tried enabling both SO_EXCLUSIVEADDRUSE and SO_REUSEADDR in the first process but found that whichever one I attempted second failed with WSAEINVAL.

Note also that I have read this past question but what that says isn't what I'm seeing: it states

A socket with SO_REUSEADDR can always bind to exactly the same source address and port as an already bound socket, even if the other socket did not have this option set when it was bound

Now if that were the case then I can definitely see the need for SO_EXCLUSIVEADDRUSE.

I'm pretty sure I'm doing something wrong but I cannot see it; can someone clarify please?

Wad
  • 1,454
  • 1
  • 16
  • 33

1 Answers1

1

As stated in the docs, SO_EXCLUSIVEADDRUSE became available on Windows NT4 SP4; before that there was only SO_REUSEADDR. So both being present has (also) historical reasons.

I think of SO_REUSEADDR as the intention to share an address (which is only really useful for UDP multicast. For unicast or TCP it really doesn´t do much since the bahaviour is non-deterministic for both sockets).

SO_EXCLUSIVEADDRUSE is a security measure to avoid my (server) application´s traffic being hijacked / rendered useless by a later binding to the same IP/port.

As I see it, you need SO_REUSEADDR for UDP multicats, and you need SO_EXCLUSIVEADDRUSE as a security measure for server applications.

C. Gonzalez
  • 689
  • 7
  • 8
  • Thanks. But I still don't see the point of `SO_EXCLUSIVEADDRUSE`; if I don't set `SO_REUSEADDR` in my server, no malicious app can possibly hijack my traffic (as I've shown above) even if it itself sets `SO_REUSEADDR`. Therefore I don't need `SO_EXCLUSIVEADDRUSE`? What is `SO_EXCLUSIVEADDRUSE` giving me that I don't get by not setting `SO_REUSEADDR`? – Wad Apr 05 '18 at 19:14
  • Operationally you´re right, but as the docs mention, "exclusive" was introduced later, and on top they made changes to increase security. So you get a mix of historical stuff (not to speak of differences to UNIX/Linux sockets). Also, I find using "exclusive" explicitly increases code readability... – C. Gonzalez Apr 05 '18 at 19:25
  • 1
    Why introduce `SO_EXCLUSIVEADDRUSE` if simply not setting `SO_REUSEADDR` in the server prevents a malicious client from binding to the same port? The only thing I can think of is that in earlier versions, not setting `SO_REUSEADDR` did *not* prevent a malicious client - hence the introduction of `SO_EXCLUSIVEADDRUSE` to address that-and in more recent versions, the behaviour of `SO_REUSEADDR` has changed so that not setting it in a server prevents a malicious client binding,thus rendering `SO_EXCLUSIVEADDRUSE` not necessary.But this isn't documented anywhere that I can find,what do you think? – Wad Apr 05 '18 at 19:30
  • 2
    That is mentioned in the second table of the MSDN (XP and earlier): if the first bind is done without any option ("default"), then the second (with SO_REUSEADDR) would have succeeded. – C. Gonzalez Apr 05 '18 at 19:49
  • Excellent. I didn't spot that the second table applies to XP and earlier (hence I'm not going to see that behaviour on my Win7 box) and the third table applies to Server 2003 and beyond. Thanks! – Wad Apr 05 '18 at 20:03