Using SO_EXCLUSIVEADDRUSE

This section describes use of the SO_EXCLUSIVEADDRUSE socket option.

The SO_EXCLUSIVEADDRUSE option prevents other sockets from being forcibly bound to the same address and port, a practice enabled by the SO_REUSEADDR option; such reuse can be executed by malicious applications to disrupt the application. The SO_EXCLUSIVEADDRUSE option is very useful to system services requiring high availability. This option is available on Microsoft Windows. The following code example illustrates setting this option.

    SOCKET      s;
    SOCKADDR_IN saLocal;
    int     optval,
            rc;
    
    // Create the socket
    s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    // Set the exclusive address option
    optval = 1;
    rc = setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE,
        (char *)&optval, sizeof(optval));
    
    saLocal.sin_family = AF_INET;
    saLocal.sin_port   = htons(5150);
    saLocal.sin_addr.s_addr = htonl(INADDR_ANY);

    // Bind the socket
    rc = bind(s, (SOCKADDR *)&saLocal, sizeof(saLocal));
    if (rc == SOCKET_ERROR)
    {
        // Errors related to setting SO_EXCLUSIVEADDRUSE
        //    will occur at bind.
    }

To have any effect, the SO_EXCLUSIVADDRUSE option must be set before the bind function is called (this also applies to the SO_REUSEADDR option). Table 1 lists the effects of setting the SO_EXCLUSIVEADDRUSE option. Wildcard indicates binding to the wildcard address, such as 0.0.0.0 for IPv4 and :: for IPv6. Specific indicates binding to a specific interface, such as binding an IP address assigned to an adapter. Specific2 indicates binding to a specific address other than the address bound to in the Specific case.

Note  The Specific2 case is applicable only when the first bind is performed with a specific address; for the case in which the first socket is bound to the wildcard, the entry for Specific covers all specific address cases.

For example, consider a computer with two IP interfaces: 10.0.0.1 and 10.99.99.99. If the first bind is to 10.0.0.1 and port 5150 with the SO_EXCLUSIVEADDRUSE option set, then the second bind to 10.99.99.99 and port 5150 with any or no options set succeeds. However, if the first socket is bound to the wildcard address (0.0.0.0) and port 5150 with SO_EXCLUSIVEADDRUSE set, any subsequent bind to the same port—regardless of IP address—will fail with either WSAEADDRINUSE (10048) or WSAEACCESS (10013), depending on which options were set on the second bind socket.

Bind Behavior with Various Options Set

Second bind First bind
SO_EXCLUSIVEADDRUSE No options or SO_REUSEADDR
Wildcard Specific Wildcard Specific
SO_EXCLUSIVEADDRUSE Wildcard Fail (10048) Fail (10048) Fail (10048) Fail (10048)
Specific Fail (10048) Fail (10048) Fail (10048) Fail (10048)
Specific2 n/a Success n/a Success
No options Wildcard Fail (10048) Fail (10048) Fail (10048) Fail (10048)
Specific Fail (10048) Fail (10048) Fail (10048) Fail (10048)
Specific2 n/a Success n/a Success
SO_REUSEADDR Wildcard Fail (10013) Fail (10013) Success* Success
Specific Fail (10013) Fail (10013) Success Success*
Specific2 n/a Success n/a Success
* The behavior is undefined as to which socket will receive packets.

In the case where the first bind sets no options or SO_REUSEADDR, and the second bind performs a SO_REUSEADDR, the second socket has overtaken the port and behavior regarding which socket will receive packets is undetermined. SO_EXCLUSIVEADDRUSE was introduced to address this situation.

An important caveat to using the SO_EXCLUSIVEADDRUSE option exists: If one or more connections originating from (or accepted on) a port bound with SO_EXCLUSIVEADDRUSE is active, all bind attempts to that port will fail. In this case, a connection is defined as a socket explicitly connected to a peer through connect, WSAConnect, or ConnectEx with SO_EXCLUSIVEADDRUSE set, or a connection returned from a listening socket (such as from accept, WSAAccept, or AcceptEx) the SO_EXCLUSIVEADDRUSE option set (on the listening socket). An active port for TCP is defined as being in the ESTABLISHED, FIN_WAIT, FIN_WAIT_2, or LAST_ACK states. For ports without the SO_EXCLUSIVEADDRUSE option set, the port can be reused as soon as the socket on which bind was called (that is, the socket the connection was originated on or the listening socket) is closed.

A socket with SO_EXCLUSIVEADDRUSE set cannot always be reused immediately after socket closure. For example, if a listening socket with the exclusive flag set accepts a connection after which the listening socket is closed, another socket cannot bind to the same port as the first listening socket with the exclusive flag until the accepted connection is no longer active.

This situation can be quite complicated; even though the socket has been closed, the underlying transport may not terminate its connection. Even after the socket is closed, the system must send all of the buffered data, transmit a graceful disconnect to the peer, and wait for a graceful disconnect from the peer. It is therefore possible that the underlying transport may never release the connection, such as when the peer advertises a zero-size window, or other such attacks. In the previous example, the listening socket was closed after a client connection was accepted. Now even if the client connection is closed, the port still may not be reused if the client connection remains in an active state because of unacknowledged data, and so forth.

To avoid this situation, applications should ensure a graceful shutdown: call shutdown with the SD_SEND flag, then wait in a recv loop until zero bytes are returned. Doing so avoids the problem associated with port reuse, guarantees all data was received by the peer, and assures the peer that all its data was successfully received.

The SO_LINGER option may be set on a socket to prevent the port going into one of the active wait states; however, doing so is discouraged because it can lead to undesired effects, because it can cause the connection to be reset. For example, if data has been received but not yet acknowledged by the peer, and the local computer closes the socket with SO_LINGER set, the connection is reset and the peer discards the unacknowledged data. Also, picking a suitable time to linger is difficult; a value too small results in many aborted connections, while a large timeout can leave the system vulnerable to denial of service attacks by establishing many connections, and thereby stalling numerous application threads.

Note  A socket that is using the SO_EXCLUSIVEADDRUSE option must be shut down properly prior to closing it. Failure to do so can cause a denial of service attack if the associated service needs to restart.

Send comments about this topic to Microsoft

Build date: 1/10/2008