< Chap 7: Index | Winsock2 Main | IP, IPV6, RM & IPX >


 

 

Socket Options and Ioctls 7 part 1

 

 

What do we have in this chapter 7 part 1?

  1. Socket Options

  2. SOL_SOCKET Option Level

  3. SO_ACCEPTCONN

  4. SO_BROADCAST

  5. SO_CONDITIONAL_ACCEPT

  6. SO_CONNECT_TIME

  7. SO_DEBUG

  8. SO_DONTLINGER

  9. SO_DONTROUTE

  10. SO_ERROR

  11. SO_ EXCLUSIVEADDRUSE

  12. SO_KEEPALIVE

  13. SO_LINGER

  14. SO_MAX_MSG_SIZE

  15. SO_OOBINLINE

  16. SO_OPENTYPE

  17. SO_PROTOCOL_INFO

  18. SO_RCVBUF

  19. SO_RCVTIMEO

  20. SO_REUSEADDR

  21. SO_SNDBUF

  22. SO_SNDTIMEO

  23. SO_TYPE

  24. SO_UPDATE_ACCEPT_CONTEXT

  25. SOL_APPLETALK Option Level

  26. SO_CONFIRM_NAME

  27. SO_DEREGISTER_NAME, SO_REMOVE_NAME

  28. SO_LOOKUP_MYZONE, SO_GETMYZONE

  29. SO_LOOKUP_NAME

  30. SO_LOOKUP_ZONES, SO_GETZONELIST

  31. SO_LOOKUP_ZONES_ON_ADAPTER, SO_GETLOCALZONES

  32. SO_LOOKUP_NETDEF_ON_ADAPTER, SO_GETNETINFO

  33. SO_PAP_GET_SERVER_STATUS

  34. SO_PAP_PRIME_READ

  35. SO_PAP_SET_SERVER_STATUS

  36. SO_REGISTER_NAME

  37. SOL_IRLMP Option Level

  38. IRLMP_9WIRE_MODE

  39. IRLMP_ENUMDEVICES

  40. IRLMP_EXCLUSIVE_MODE

  41. IRLMP_IAS_QUERY

  42. IRLMP_IAS_SET

  43. IRLMP_IRLPT_MODE

  44. IRLMP_SEND_PDU_LEN

  45. IPPROTO_IP Option Level

 

Once a socket has been created, various attributes can be manipulated with socket options and ioctl commands to affect the socket's behavior. Some of these options simply return information, and others affect the way the socket behaves in your application. An ioctl is an I/O control command that also affects the behavior of the socket. This chapter is dedicated to discussing four Winsock functions: getsockopt(), setsockopt(), ioctlsocket(), and WSAIoctl(). Each function has numerous commands, many of which have never been properly documented. In the following sections, we will discuss the required parameters and available options for each function as well as the platforms that support those options. Every option is assumed to work on all Windows platforms (Windows CE, Windows 95, Windows 98, Windows Me, Windows NT, Windows 2000, Windows XP and so on) unless otherwise noted.

Most of these ioctl commands and options are defined in either WINSOCK.H or WINSOCK2.H, depending on whether they are specific to Winsock 1 or Winsock 2; however, a few of the options are specific either to the Microsoft provider or to a particular transport protocol. Microsoft-specific extensions are defined in WINSOCK2.H and MSWSOCK.H. Transport provider extensions are defined in their protocol-specific header files. For the transport-specific options, we will indicate the correct header file along with the option. Applications using the Microsoft-specific extensions must link with MSWSOCK.LIB.

 

Socket Options

 

The getsockopt() function is most frequently used to get information about the given socket. The prototype for this function is:

 

int getsockopt(

    SOCKET s,

    int level,

    int optname,

    char FAR* optval,

    int FAR* optlen

);

 

The first parameter, s, is the socket on which you want to perform the specified option. This must be a valid socket for the given protocol you are using. A number of options are specific to a particular protocol and socket type, while others pertain to all types of sockets. This ties in with the second parameter, level. An option of level SOL_SOCKET means it is a generic option that isn't necessarily specific to a given protocol. We say “necessarily” because not all protocols implement each socket option of level SOL_SOCKET. For example, SO_BROADCAST puts the socket into broadcast mode, but not all supported protocols support the notion of broadcast sockets. The optname parameter is the actual option you are interested in.

These option names are constant values defined in the Winsock header files. The most common and protocol-independent options (such as those with the SOL_SOCKET level) are defined in WINSOCK.H and WINSOCK2.H. Each specific protocol has its own header file that defines options specific to it. Finally, the optval and optlen parameters are the variables returned with the value of the desired option. In most cases, but not all, the option value is an integer.

The setsockopt() function is used to set socket options on either a socket level or a protocol-specific level. The function is defined as:

 

int setsockopt(

    SOCKET s,

    int level,

    int optname,

    const char FAR * optval,

    int optlen

);

 

The parameters are the same as in getsockopt() except that you pass in a value as the optval and optlen parameters, which are the values to set for the specified option. As with getsockopt(), optval is often, but not always, an integer. Consult each option for the specifics on what is passed as the option value.

The most common mistake associated with calling either getsockopt() or setsockopt() is attempting to obtain socket information for a socket whose underlying protocol doesn't possess that particular characteristic. For example, a socket of type SOCK_STREAM is not capable of broadcasting data; therefore, attempting to set or get the SO_BROADCAST option results in the error WSAENOPROTOOPT.

 

SOL_SOCKET Option Level

 

This section describes the socket options that return information based on the socket's characteristics and are not specific to that socket's protocol.

 

SO_ACCEPTCONN

 

optval Type

Get/Set

Winsock Version

Description

BOOL

Get only

1+

If TRUE, socket is in listening mode.

 

If the socket has been put into listening mode by the listen function, this option returns TRUE. Sockets of type SOCK_DGRAM do not support this option.

 

SO_BROADCAST

 

optval Type

Get/Set

Winsock Version

Description

BOOL

Both

1+

If TRUE, socket is configured for sending broadcast messages.

 

If the given socket has been configured for sending or receiving broadcast data, querying this socket option returns TRUE. Use setsockopt() with SO_BROADCAST to enable broadcast capabilities on the socket. This option is valid for sockets that aren't of type SOCK_STREAM.

Broadcasting is the capability to send data so that every machine on the local subnet receives the data. Of course, there must be some process on each machine that listens for incoming broadcast data. The drawback of broadcasting is that if many processes are all sending broadcast data, the network can become saturated and network performance suffers. To receive a broadcast message, you must enable the broadcast option and then use one of the datagram receive functions, such as recvfrom() or WSARecvfrom(). You can also connect the socket to the broadcast address by calling connect() or WSAConnect() and then use recv() or WSARecv(). For UDP broadcasts, you must specify a port number to send the datagram to; likewise, the receiver must request to receive the broadcast data on that port also. The following code example illustrates how to send a broadcast message with UDP.

 

SOCKET       s;

BOOL         bBroadcast;

char         *sMsg = "This is a test string";

SOCKADDR_IN bcast;

 

s = WSASocket(AF_INET, SOCK_DGRAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);

bBroadcast = TRUE;

setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char *)&bBroadcast, sizeof(BOOL));

bcast.sin_family = AF_INET;

bcast.sin_addr.s_addr = inet_addr(INADDR_BROADCAST);

bcast.sin_port = htons(5150);

sendto(s, sMsg, strlen(sMsg), 0, (SOCKADDR *)&bcast, sizeof(bcast));

 

For UDP, a special broadcast address exists to which broadcast data should be sent. This address is 255.255.255.255. A #define directive for INADDR_BROADCAST is provided to make things a bit simpler and easier to read.

AppleTalk is another protocol capable of sending broadcast messages. AppleTalk also has a special address used by broadcast data. You learned in Chapter 4 that an AppleTalk address has three parts: network, node, and socket (destination). For broadcasting, set the destination to ATADDR_BROADCAST (0xFF), which causes the datagram to be sent to all endpoints on the given network.

Normally, you need to set only the SO_BROADCAST option when sending broadcast datagrams. To receive a broadcast datagram, you need to be listening only for incoming datagrams on that specified port.

 

SO_CONDITIONAL_ACCEPT

 

optval Type

Get/Set

Winsock Version

Description

BOOL

Both

2+

Allows true connection acceptance or rejection from WSAAccept().

 

This option allows applications to conditionally accept or reject incoming connections at the protocol level. For example, by default, this option is off for TCP and any incoming SYN packet is acknowledged with an ACK+SYN even if the application has not called the accept(), WSAAccept(), or AcceptEx() functions. When this option is enabled, the connection is not acknowledged until the application calls one of the accept functions. In the case of WSAAccept() and a conditional accept function, the connection is not acknowledged until the conditional accept function returns CF_ACCEPT. This option must be set before the listen call.

The drawback to enabling this is if the application does not post an accept or return CF_ACCEPT in a timely fashion, the client's connection request will time out with an error (WSAETIMEDOUT). For TCP/IP this option is off by default while for ATM, it is enabled by default. This option is available on Windows 2000 and later versions.

 

SO_CONNECT_TIME

 

optval Type

Get/Set

Winsock Version

Description

int

Get only

1+

Returns the number of seconds the socket has been connected

 

SO_CONNECT_TIME is a Microsoft-specific option that returns the number of seconds a connection has been established. The most frequent use of this option is with the AcceptEx() function. AcceptEx() requires that a valid socket handle be passed for the incoming client connection. This option can be called on the client's SOCKET handle to determine whether the connection has been made and how long it has been established. If the socket is not currently connected, the value returned is 0xFFFFFFFF.

This option is especially relevant in the case of AcceptEx(). If an application posts an AcceptEx() with a receive buffer, then the AcceptEx() will not complete until data is received on the client connection. A malicious application could perform a denial of service attack by making many connections without sending data. To prevent this, the server should cycle through all client sockets outstanding in AcceptEx() calls to see if they have been connected but the accept has not completed. Refer to previous chapter for more details.

 

SO_DEBUG

 

optval Type

Get/Set

Winsock Version

Description

BOOL

Both

1+

If TRUE, debug output is enabled.

 

Winsock service providers are encouraged (but not required) to supply output debug information if the SO_DEBUG option is set by an application. How the debug information is presented depends on the underlying service provider's implementation. To turn debug information on, call setsockopt() with SO_DEBUG and a Boolean variable set to TRUE. Calling getsockopt() with SO_DEBUG returns TRUE or FALSE if debugging is enabled or disabled, respectively. Unfortunately, no Windows platform currently implements the SO_DEBUG option, as described in Knowledge Base article Q138965. No error is returned when the option is set, but the underlying network provider ignores the option.

 

SO_DONTLINGER

 

optval Type

Get/Set

Winsock Version

Description

BOOL

Both

1+

If TRUE, SO_LINGER is disabled.

 

For protocols that support graceful socket connection closure, a mechanism is implemented so that if one or both sides close the socket, any data still pending or in transmission will be sent or received by both parties. It is possible, with setsockopt and the SO_LINGER option, to change this behavior so that after a specified period of time, the socket and all its resources will be torn down. Any pending or arriving data associated with that socket is discarded and the peer's connection is reset (WSAECONNRESET). The SO_DONTLINGER option can be checked to ensure that a linger period has not been set. Calling getsockopt() with SO_DONTLINGER will return a Boolean TRUE or FALSE if a linger value is set or not set, respectively. A call to setsockopt() with SO_DONTLINGER disables lingering. Sockets of type SOCK_DGRAM do not support this option.

 

SO_DONTROUTE

 

optval Type

Get/Set

Winsock Version

Description

BOOL

Both

1+

If TRUE, messages are sent directly to the network interface without consulting the routing table.

 

The SO_DONTROUTE option tells the underlying network stack to ignore the routing table and to send the data out on the interface the socket is bound to. For example, if you create a IPv4 UDP socket and bind it to interface A and then send a packet destined for a machine on the network attached to interface B, the packet will in fact be routed so that it is sent on interface B. Using setsockopt with the Boolean value TRUE prevents this because the packet goes out on the bound interface. The getsockopt() function can be called to determine if routing is enabled (which it is by default).

Calling this option on a Windows platform will succeed; however, the Microsoft provider silently ignores the request and always uses the routing table to determine the appropriate interface for outgoing data.

 

SO_ERROR

 

optval Type

Get/Set

Winsock Version

Description

int

Get only

1+

Returns the error status

 

The SO_ERROR option returns and resets the per-socket-based error code, which is different from the per-thread–based error code that is handled using the WSAGetLastError() and WSASetLastError() function calls. A successful call using the socket does not reset the per-socket–based error code returned by the SO_ERROR option. Calling this option will not fail; however, the error value is not always updated immediately, so there is a possibility of this option returning 0 (indicating no error). It is best to use WSAGetLastError().

 

SO_ EXCLUSIVEADDRUSE

 

optval Type

Get/Set

Winsock Version

Description

BOOL

Set only

2+

If TRUE, the local port that the socket is bound to cannot be reused by another process.

 

This option is the complement of SO_REUSEADDR, which we will describe shortly. This option exists to prevent other processes from using the SO_REUSEADDR on a local address that your application is using. If two separate processes are bound to the same local address (assuming that SO_REUSEADDR is set earlier), which of the two sockets receives notifications for incoming connections is not defined. The SO_EXCLUSIVEADDRUSE option locks down the local address to which the socket is bound, so if any other process tries to use SO_REUSEADDR with the same local address, that process fails. Administrator rights are required to set this option. It is available on only Windows 2000 or later versions.

 

SO_KEEPALIVE

 

optval Type

Get/Set

Winsock Version

Description

BOOL

Both

1+

If TRUE, socket is configured to send keepalive messages on the session.

 

For a TCP-based socket, an application can request that the underlying service provider enable the use of keepalive packets on TCP connections by turning on the SO_KEEPALIVE socket option. On Windows platforms, keep-alives are implemented in accordance with section 4.2.3.6 of RFC 1122. If a connection is dropped as the result of keepalives, the error code WSAENETRESET is returned to any calls in progress on the socket, and any subsequent calls will fail with WSAENOTCONN. For the exact implementation details, consult the RFC. The important point is that keepalives are sent at intervals no less than two hours apart. The two-hour keepalive time is configurable via the Registry; however, changing the default value changes the keepalive behavior for all TCP connections on the system, which is generally discouraged. Another solution is to implement your own keepalive strategy. Sockets of type SOCK_DGRAM do not support this option.

The Registry keys for keepalives are KeepAliveInterval and KeepAliveTime. Both keys store values of type REG_DWORD in milliseconds. The former key is the interval separating keepalive retransmissions until a response is received; the latter entry controls how often TCP sends a keepalive packet in an attempt to verify that an ideal connection is still valid. In Windows 95, Windows 98, and Windows Me, these keys are located under the following Registry path:

\HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\VxD\MSTCP

In Windows NT, store the keys under:

\HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\TCPIP\Parameters

 

In Windows 2000, a new socket ioctl command, SIO_KEEPALIVE_VALS, allows you to change the keepalive value and interval on a per-socket basis, as opposed to a system-wide basis. This ioctl command is described later in this chapter.

 

SO_LINGER

 

optval Type

Get/Set

Winsock Version

Description

struct

Both

1+

Sets or gets the current linger values linger

 

SO_LINGER controls the action taken when unsent data is queued on a socket and a closesocket() is performed. A call to getsockopt() with this socket option returns the current linger times in a linger structure, which is defined as:

 

struct linger {

    u_short l_onoff;

    u_short l_linger;

}...;

 

A nonzero value for l_onoff means that lingering is enabled, and l_linger is the timeout in seconds, at which point any pending data to be sent or received is discarded and the connection with the peer is reset. Conversely, you can call setsockopt() to turn lingering on and specify the length of time before discarding any queued data. This is accomplished by setting the desired values in a variable of type struct linger. When setting a linger value with setsockopt(), you must set the l_onoff field of the structure to a nonzero value. To turn lingering off once it has been enabled, you can call setsockopt() with the SO_LINGER option and the l_onoff field of the linger structure set to 0, or call setsockopt() with the SO_DONTLINGER option, passing the value TRUE for the optval parameter. Sockets of type SOCK_DGRAM do not support this option. Setting the linger option directly affects how a connection behaves when the closesocket function is called. Table 7-1 lists these behaviors.

 

Table 7-1 Linger Options

 

Option

Interval

Type of Close

Wait for Close?

SO_DONTLINGER

Not applicable

Graceful

No

SO_LINGER

0

Hard

No

SO_LINGER

Non-zero

Graceful

Yes

 

If SO_LINGER is set with a zero timeout interval (that is, the linger structure member l_onoff is not 0 and l_linger is 0), closesocket() is not blocked, even if queued data has not yet been sent or acknowledged. This is called a hard, or abortive, close because the socket's virtual circuit is reset immediately and any unsent data is lost. Any receive call on the remote side of the circuit fails with WSAECONNRESET.

If SO_LINGER is set with a nonzero timeout interval on a blocking socket, the closesocket() call blocks on a blocking socket until the remaining data has been sent or until the timeout expires. This is called a graceful disconnect. If the timeout expires before all data has been sent, the Windows Sockets implementation terminates the connection before closesocket() returns.

 

SO_MAX_MSG_SIZE

 

optval Type

Get/Set

Winsock Version

Description

unsigned int

Get only

2+

The maximum size of a message for a message-oriented socket

 

This is a get-only socket option that indicates the maximum outbound (send) size of a message for message-oriented socket types as implemented by a particular service provider. It has no meaning for byte-stream-oriented sockets.

 

SO_OOBINLINE

 

optval Type

Get/Set

Winsock Version

Description

BOOL

Both

1+

If TRUE, any OOB data is returned in the normal data stream.

 

By default, OOB data is not inlined, so a call to a receive() function (with the appropriate MSG_OOB flag set) returns the OOB data in a single call. If this option is set, the OOB data appears within the data stream returned from a receive() call, and a call to ioctlsocket() with the SIOCATMARK option is required to determine which byte is the OOB data. Sockets of type SOCK_DGRAM do not support this option.

 

SO_OPENTYPE

 

optval Type

Get/Set

Winsock Version

Description

BOOL

Both

1+

When set, subsequent calls to socket will return non-overlapped handles.

 

The socket API returns handles that are overlapped capable by default. However, if the socket is to be used in the C runtime routines, the socket must have been created without the overlapped flag. With Winsock 2, the WSASocket() function can be called without specifying the WSA_FLAG_OVERLAPPED flag. Otherwise, this socket option may be set, which affects all subsequent calls to socket from the current thread so that non-overlapped handles are returned. To set this option, INVALID_SOCKET is passed for the SOCKET parameter to setsockopt() with a non-zero optval. To change it back, specify a zero optval. A socket created non-overlapped cannot be used with an overlapped fashion (such as completion routines or completion ports), the operation will fail.

 

SO_PROTOCOL_INFO

 

optval Type

Get/Set

Winsock Version

Description

WSAPROTOCOL_INFO

Get only

2+

Returns the Winsock catalog entry for the socket's protocol.

 

This is another get-only option that fills in the supplied WSAPROTOCOL_INFO structure with the characteristics of the protocol associated with the socket.

 

SO_RCVBUF

 

optval Type

Get/Set

Winsock Version

Description

Int

Both

1+

Gets or sets the per-socket buffer size for receive operations.

 

This is a simple option that either returns the size or sets the size of the buffer allocated to this socket for receiving data. When a socket is created, a send buffer and a receive buffer are assigned to the socket for sending and receiving data. When requesting to set the receive buffer size to a value, the call to setsockopt() can succeed even when the implementation does not provide the entire amount requested. To ensure that the requested buffer size is allocated, call getsockopt() to get the actual size allocated. All Windows platforms can get or set the receive buffer size except Windows CE, which does not allow you to change the value, you can get only the receive buffer size.

One possible reason for changing the buffer size is to tailor buffer sizes according to your application's behavior. For example, when writing code to receive UDP datagrams, you should generally make the receive buffer size an even multiple of the datagram size. For overlapped I/O, setting the buffer sizes to 0 can increase performance in certain situations; when the buffers are non-zero, an extra memory copy is involved in moving data from the system buffer to the user-supplied buffer. If there is no intermediate buffer, data is immediately copied to the user-supplied buffer. The one caveat is that this is efficient only with multiple outstanding receive calls. Posting only a single receive can hurt performance because the local system cannot accept any incoming data unless you have a buffer posted and ready to receive the data.

 

SO_RCVTIMEO

 

optval Type

Get/Set

Winsock Version

Description

int

Both

1+

Gets or sets the timeout value (in milliseconds) associated with receiving data on the socket.

 

The SO_RCVTIMEO option sets the receive timeout value on a blocking socket. The timeout value is an integer in milliseconds that indicates how long a Winsock receive function should block when attempting to receive data. If you need to use the SO_RCVTIMEO option and you use the WSASocket() function to create the socket, you must specify WSA_FLAG_OVERLAPPED as part of WSASocket()'s dwFlags parameter. Subsequent calls to any Winsock receive function (such as recv(), recvfrom(), WSARecv(), or WSARecvFrom()) block only for the amount of time specified. If no data arrives within that time, the call fails with the error 10060 (WSAETIMEDOUT). If the receiver operation does time out the socket is in an indeterminate state and should not be used.

For performance reasons, this option was disabled in Windows CE 2.1. If you attempt to set this option, it is silently ignored and no failure returns. Previous versions of Windows CE do implement this option.

 

SO_REUSEADDR

 

optval Type

Get/Set

Winsock Version

Description

BOOL

Both

1+

If TRUE, the socket can be bound to an address already in use by another socket or to an address in the TIME_WAIT state.

 

By default, a socket cannot be bound to a local address that is already in use; however, occasionally it is necessary to reuse an address this way. A connection is uniquely identified by the combination of its local and remote addresses. As long as the address you are connecting to is unique in the slightest respect (such as a different port number in TCP/IP), the binding will be allowed.

The only exception is for a listening socket. Two separate sockets cannot bind to the same local interface (and port, in the case of TCP/IP) to await incoming connections. If two sockets are actively listening on the same port, the behavior is undefined as to which socket will receive notification of an incoming connection. The SO_REUSEADDR option is most useful in TCP when a server shuts down or exits abnormally so that the local address and port are in the TIME_WAIT state, which prevents any other sockets from binding to that port. By setting this option, the server can listen on the same local interface and port when it is restarted.

 

SO_SNDBUF

 

optval Type

Get/Set

Winsock Version

Description

BOOL

Both

1+

Gets or sets the per-socket buffer size for send operations.

 

This is a simple option that either returns the size or sets the size of the buffer allocated to this socket for sending data. When a socket is created, a send buffer and a receive buffer are assigned to the socket for sending and receiving data. When requesting to set the size of the send buffer, the call to setsockopt() can succeed even when the implementation does not provide the entire amount requested. To ensure that the requested buffer size is allocated, call getsockopt() to get the actual size allocated. All Windows platforms can get or set the send buffer size except Windows CE, which does not allow you to change the value, you can get only the receive buffer size.

As with SO_RCVBUF, you can use the SO_SNDBUF option to set the size of the send buffer to 0. The advantage of the buffer size being 0 for blocking send() calls is that when the call completes you know that your data is on the wire. Also, as in the case of a receive operation with a zero-length buffer, there is no extra memory copy of your data to system buffers. The drawback is that you lose the pipelining gained by the default stack buffering when the send buffers are nonzero in size. In other words, if you have a loop performing sends, the local network stack can copy your data to a system buffer to be sent when possible (depending on the I/O model being used). On the other hand, if your application is concerned with other logistics, disabling the send buffers can save you a few machine instructions in the memory copy.

 

 

SO_SNDTIMEO

 

optval Type

Get/Set

Winsock Version

Description

Int

Both

1+

Gets or sets the timeout value (in milliseconds) associated with sending data on the socket.

 

The SO_SNDTIMEO option sets the timeout value on a blocking socket when calling a Winsock send function. The timeout value is an integer in milliseconds that indicates how long the send function should block when attempting to send data. If you need to use the SO_SNDTIMEO option and you use the WSASocket() function to create the socket, you must specify WSA_FLAG_OVERLAPPED as part of WSASocket()'s dwFlags parameter. Subsequent calls to any Winsock send() function (such as send(), sendto(), WSASend(), or WSASendTo()) block for only the amount of time specified. If the send operation cannot complete within that time, the call fails with error 10060 (WSAETIMEDOUT). If the send operation times out the socket is in an indeterminate state and should not be used.

For performance reasons, this option was disabled in Windows CE 2.1. If you attempt to set this option, the option is silently ignored and no failure is returned. Previous versions of Windows CE do implement this option.

 

SO_TYPE

 

optval Type

Get/Set

Winsock Version

Description

Int

Get only

1+

Returns the socket type (for example, SOCK_DGRAM, SOCK_STREAM) of the given socket.

 

The SO_TYPE option is a get-only option that simply returns the socket type of the given socket. The possible socket types are SOCK_DGRAM, SOCK_ STREAM, SOCK_SEQPACKET, SOCK_RDM, and SOCK_RAW.

 

SO_UPDATE_ACCEPT_CONTEXT

 

optval Type

Get/Set

Winsock Version

Description

SOCKET

Both

1+

Updates a client socket with the same properties of the listening socket.

 

This option is a Microsoft-specific extension used in conjunction with the AcceptEx() function. The unique characteristic of this function is that it is part of the Winsock 1 specification and allows the use of overlapped I/O for an accept call. The function takes the listening socket as a parameter as well as a socket handle that becomes the accepted client. This socket option must be set for the characteristics of the listening socket to be carried over to the client socket. This is particularly important for QOS-enabled listening sockets. For the client socket to be QOS-enabled, this option must be set. To set this option on a socket, use the listening socket as the SOCKET parameter to setsockopt() and pass the accepting socket handle (for example, the client handle) as optval. This option is specific to Windows.

 

SOL_APPLETALK Option Level

 

The following options are socket options specific to the AppleTalk protocol and can be used only with sockets created using socket or WSASocket() with the AF_APPLETALK flag. A majority of the options listed here deal with either setting or obtaining AppleTalk names. Some AppleTalk socket options, such as SO_DEREGISTER_NAME, have more than one option name. In such cases, all of the option's names can be used interchangeably.

 

SO_CONFIRM_NAME

 

optval Type

Get/Set

Winsock Version

Description

WSH_NBP_TUPLE

Get only

1

Confirms that the given AppleTalk name is bound to the given address.

 

The SO_CONFIRM_NAME option is used to verify that a given AppleTalk name is bound to the supplied address. This results in a Name Binding Protocol (NBP) lookup request being sent to the address to verify the name. If the call fails with the error WSAEADDRNOTAVAIL, the name is no longer bound to the address given.

 

SO_DEREGISTER_NAME, SO_REMOVE_NAME

 

optval Type

Get/Set

Winsock Version

Description

WSH_REGISTER_NAME

Set only

1

Deregisters the given name from the network.

 

This option is used to deregister a name from the network. If the name does not currently exist on the network, the call will return indicating success.

 

SO_LOOKUP_MYZONE, SO_GETMYZONE

 

optval Type

Get/Set

Winsock Version

Description

char*

Get only

1

Returns the default zone on the network.

 

This option returns the default zone on the network. The optval parameter to getsockopt() should be a character string of at least 33 characters. Remember that the maximum length of an NBP name is MAX_ENTITY_LEN, which is defined as 32. The extra character is required for the null terminator.

 

SO_LOOKUP_NAME

 

optval Type

Get/Set

Winsock Version

Description

WSH_LOOKUP_NAME

Get only

1

Looks up a specified NBP name and returns the matching tuples of names and NBP information.

 

This option is used to look up a specified name on the network (for example, when a client wants to connect to a server). The well-known textual name must be resolved to an AppleTalk address before a connection can be established.

One point to be aware of is that upon successful return, the WSH_NBP_ TUPLE structures occupy the space in the supplied buffer after the WSH_LOOKUP_NAME information. That is, you should supply getsockopt() with a buffer large enough to hold the WSH_LOOKUP_NAME information at the start of the buffer and a number of WSH_NBP_TUPLE structures in the remaining space. Figure 7-1 illustrates how the buffer should be prepared prior to the call (with respect to WSH_LOOKUP_NAME) and where the WSH_NBP_TUPLE structures are placed upon return.

 

 

Figure 7-1 SO_LOOKUP_NAME buffer

 

SO_LOOKUP_ZONES, SO_GETZONELIST

 

optval Type

Get/Set

Winsock Version

Description

WSH_LOOKUP_ZONES

Get only

1

Returns zone names from the Internet zone list.

 

This option requires a buffer large enough to contain a WSH_LOOKUP_ ZONES structure at the head. Upon successful return, the space after the WSH_LOOKUP_ZONES structure contains the list of null-terminated zone names. The following code demonstrates how to use the SO_LOOKUP_ZONES option:

 

PWSH_LOOKUP_NAME     atlookup;

PWSH_LOOKUP_ZONES    zonelookup;

char                 cLookupBuffer[4096], *pTupleBuffer = NULL;

 

atlookup = (PWSH_LOOKUP_NAME)cLookupBuffer;

zonelookup = (PWSH_LOOKUP_ZONES)cLookupBuffer;

ret = getsockopt(s, SOL_APPLETALK, SO_LOOKUP_ZONES, (char *)atlookup, &dwSize);

pTupleBuffer = (char *)cLookupBuffer + sizeof(WSH_LOOKUP_ZONES);

 

for(i = 0; i < zonelookup->NoZones; i++)

{

    printf("%3d: '%s'\n", i + 1, pTupleBuffer);

    while (*pTupleBuffer++);

}

 

SO_LOOKUP_ZONES_ON_ADAPTER, SO_GETLOCALZONES

 

optval Type

Get/Set

Winsock Version

Description

WSH_LOOKUP_ZONES

Get only

1

Returns a list of zone names known to the given adapter name.

 

This option is similar to SO_LOOKUP_ZONES except that you specify the adapter name for which you want to obtain a list of zones local to the network that that adapter is connected to. Again, you must supply a sufficiently large buffer that has a WSH_LOOKUP_ZONES structure at the head. The returned list of null-terminated zone names begins in the space after the WSH_LOOKUP_ZONES structure. In addition, the name of the adapter must be passed in as a UNICODE string (WCHAR).

 

SO_LOOKUP_NETDEF_ON_ADAPTER, SO_GETNETINFO

 

optval Type

Get/Set

Winsock Version

Description

WSH_LOOKUP_NETDEF_ ON_ADAPTER

Set only

1

Returns the seeded values for the network as well as the default zone.

 

This option returns the seeded values for the network numbers and a null-terminated ANSI string containing the default zone for the network on the indicated adapter. The adapter is passed as a UNICODE (WCHAR) string following the structure and is overwritten by the default zone upon function return. If the network is not seeded, the network range 1–0xFFFE is returned and the null-terminated ANSI string contains the default zone “*”.

 

SO_PAP_GET_SERVER_STATUS

 

optval Type

Get/Set

Winsock Version

Description

WSH_PAP_GET_SERVER_STATUS

Get only

1

Returns the PAP status from a given server.

 

This option gets the Printer Access Protocol (PAP) status registered on the address specified in ServerAddr (usually obtained via an NBP lookup). The four reserved bytes correspond to the four reserved bytes in the PAP status packet. These will be in network byte order. A PAP status string can be arbitrary and is set with the option SO_PAP_SET_SERVER_STATUS, which we'll explain later in this chapter. The WSH_PAP_GET_SERVER_STATUS structure is defined as:

 

#define    MAX_PAP_STATUS_SIZE        255

#define    PAP_UNUSED_STATUS_BYTES        4

 

typedef struct _WSH_PAP_GET_SERVER_STATUS

{

    SOCKADDR_AT            ServerAddr;

    UCHAR                  Reserved[PAP_UNUSED_STATUS_BYTES];

    UCHAR                  ServerStatus[MAX_PAP_STATUS_SIZE + 1];

} WSH_PAP_GET_SERVER_STATUS, *PWSH_PAP_GET_SERVER_STATUS;

 

The following code snippet is a quick example of how to request the PAP status. The length of the status string is the first byte of the ServerStatus field.

 

WSH_PAP_GET_SERVER_STATUS  status;

int   nSize = sizeof(status);

 

status.ServerAddr.sat_family = AF_APPLETALK;

ret = getsockopt(s, SOL_APPLETALK, SO_PAP_GET_SERVER_STATUS, (char *)&status, &nSize);

 

SO_PAP_PRIME_READ

 

optval Type

Get/Set

Winsock Version

Description

char [ ]

Set only

1

This call primes a read on a PAP connection so that the sender can actually send the data.

 

When this option is called on a socket describing a PAP connection, it enables the remote client to send the data without the local application having called recv() or WSARecvEx(). After this option is set, the application can block on a select call and then the actual reading of the data can occur. The optval parameter to this call is the buffer that is to receive the data, which must be at least MIN_PAP_READ_BUF_SIZE (4096) bytes in length. This option allows support for non-blocking sockets on the read-driven PAP protocol. Note that for each buffer you want to read, you must make a call to setsockopt() with the SO_PAP_PRIME_READ option.

 

SO_PAP_SET_SERVER_STATUS

 

optval Type

Get/Set

Winsock Version

Description

char [ ]

Set only

1

Sets the status to be sent if another client requests the status.

 

A client can request to obtain the PAP status by using SO_PAP_GET_SERVER_ STATUS. This option can be used to set the status so that if clients request the PAP status, the buffer submitted to the set command will be returned on the get command. The status is a buffer of at most 255 bytes containing the status of the associated socket. If the set option is called with a null buffer, the previous status value set is erased.

 

SO_REGISTER_NAME

 

optval Type

Get/Set

Winsock Version

Description

WSH_REGISTER_NAME

Set only

1

Registers the given name on the AppleTalk network.

 

This option is used to register the supplied name on the AppleTalk network. If the name already exists on the network, the error WSAEADDRINUSE is returned.

 

SOL_IRLMP Option Level

 

The SOL_IRLMP level deals with the IrDA protocol, whose address family is AF_IRDA. Keep in mind when using IrDA socket options that the implementation of infrared sockets varies among platforms. Because Windows CE first offered IR support, it does not have all the options available that were introduced in Windows 98 and later versions. In this section, each option is followed by the platforms it is supported on.

 

IRLMP_9WIRE_MODE

 

optval Type

Get/Set

Winsock Version

Description

BOOL

Both

1+

Puts the IrDA socket into IrCOMM mode.

 

This is another rarely used option needed to communicate with Windows 98 via IrCOMM, which is at a lower level than the level at which IrSock normally operates. In 9-wire mode, each TinyTP or IrLMP packet contains an additional 1-byte IrCOMM header. To accomplish this through the socket interface, you need to first get the maximum PDU size of an IrLMP packet with the IRLMP_SEND_PDU_LEN option. The socket is then put into 9-wire mode with setsockopt() before connecting or accepting a connection. This tells the stack to add the 1-byte IrCOMM header (always set to 0) to each outgoing frame. Each send must be of a size less than the maximum PDU length to leave room for the added IrCOMM byte. IrCOMM is beyond the scope of this book. This option is available in Windows 98 and later versions.

 

IRLMP_ENUMDEVICES

 

optval Type

Get/Set

Winsock Version

Description

DEVICELIST

Get only

1+

Returns a list of IrDA device IDs for IR-capable devices within range.

 

Because of the nature of infrared networking, devices capable of communicating are mobile and can move in and out of range. This option “queries” which IR devices are within range, and to connect to another device you must perform this step to obtain the device ID for each device you want to connect to.

The DEVICELIST structures are different on the various platforms that support IrSock because the latest platforms that added support also added functionality. Recall that Windows CE offered IrSock support first and as a result the data structures are somewhat different. The DEVICELIST structure definition for Windows 98 and later versions is:

 

typedef struct _WINDOWS_DEVICELIST

{

    ULONG                       numDevice;

    WINDOWS_IRDA_DEVICE_INFO    Device[1];

} WINDOWS_DEVICELIST, *PWINDOWS_DEVICELIST, FAR LPWINDOWS_DEVICELIST;

 

typedef struct _WINDOWS_IRDA_DEVICE_INFO

{

    u_char  irdaDeviceID[4];

    char      irdaDeviceName[22];

    u_char  irdaDeviceHints1;

    u_char  irdaDeviceHints2;

    u_char  irdaCharSet;

} WINDOWS_IRDA_DEVICE_INFO, *PWINDOWS_IRDA_DEVICE_INFO, FAR *LPWINDOWS_IRDA_DEVICE_INFO;

 

In Windows CE, the DEVICELIST structure is defined as:

 

typedef struct _WCE_DEVICELIST

{

    ULONG    numDevice;

    WCE_IRDA_DEVICE_INFO    Device[1];

} WCE_DEVICELIST, *PWCE_DEVICELIST;

 

typedef struct _WCE_IRDA_DEVICE_INFO

{

    u_char  irdaDeviceID[4];

    char    irdaDeviceName[22];

    u_char  Reserved[2];

} WCE_IRDA_DEVICE_INFO, *PWCE_IRDA_DEVICE_INFO;

 

Each of these structures contains a field, irdaDeviceID, which is a 4-byte identification tag used to uniquely identify that device. You need this field to fill out the SOCKADDR_IRDA structure used to connect to a specific device or to manipulate or obtain an IAS entry with the options IRLMP_IAS_SET and IRLMP_IAS_QUERY.

When you call getsockopt() to enumerate infrared devices, the optval parameter must be a DEVICELIST structure. The only requirement is that the numDevice field be set to 0 at first. The call to getsockopt() does not return an error if no IR devices are discovered. After a call, the numDevice field should be checked to see whether it is greater than 0, which means that one or more devices were found. The Device field returns with a number of structures equal to the value returned in numDevice.

 

IRLMP_EXCLUSIVE_MODE

 

optval Type

Get/Set

Winsock Version

Description

BOOL

Both

1+

If TRUE, socket connection is in exclusive mode.

 

This option isn't normally used by user applications because it bypasses the TinyTP layer in the IrDA stack and communicates directly with IrLMP. If you are really interested in using this option, you should consult the IrDA specification at irda.org. This option is available on Windows CE and Windows 2000 or later versions.

 

IRLMP_IAS_QUERY

 

optval Type

Get/Set

Winsock Version

Description

IAS_QUERY

Get only

1+

Queries IAS on a given service and class name for its attributes.

 

This socket option is the complement of IRLMP_IAS_SET because it retrieves information about a class name and its service. Before making the call to getsockopt(), you must first fill out the irdaDeviceID field to the device you are querying. Set the irdaAttribName field to the property string on which you want to retrieve its value. The most common query would be for the LSAP-SEL number; its property string is “IrDA:IrLMP:LsapSel”. Next, you need to set the irdaClassName field to the name of the service that the given property string applies to. Once these fields are filled, make the call to getsockopt. Upon success, the irdaAttribType field indicates which field in the union to obtain the information from. Use the identifiers in Table 7-2 to decode this entry. The most common error is WSASERVICE_NOT_FOUND, which is returned when the given service is not found on that device.

 

IRLMP_IAS_SET

 

optval Type

Get/Set

Winsock Version

Description

IAS_QUERY

Set only

1+

Sets an attribute value for a given class name and attribute.

 

IAS is a dynamic service registration entity that can be queried and modified. The IRLMP_IAS_SET option allows you to set a single attribute for a single class within the local IAS. As with IRLMP_ENUMDEVICES, there are separate structures for Windows CE and for Windows 98 and later versions. The structure for these is:

 

typedef struct _WINDOWS_IAS_QUERY

{

    u_char     irdaDeviceID[4];

    char       irdaClassName[IAS_MAX_CLASSNAME];

    char       irdaAttribName[IAS_MAX_ATTRIBNAME];

    u_long     irdaAttribType;

    union

    {

        LONG   irdaAttribInt;

        struct

        {

            u_long   Len;

            u_char   OctetSeq[IAS_MAX_OCTET_STRING];

        } irdaAttribOctetSeq;

        struct

        {

            u_long   Len;

            u_long   CharSet;

            u_char   UsrStr[IAS_MAX_USER_STRING];

        } irdaAttribUsrStr;

    } irdaAttribute;

} WINDOWS_IAS_QUERY, *PWINDOWS_IAS_QUERY, FAR *LPWINDOWS_IAS_QUERY;

 

The IAS query structure for Windows CE is:

 

typedef struct _WCE_IAS_QUERY

{

    u_char     irdaDeviceID[4];

    char       irdaClassName[61];

    char       irdaAttribName[61];

    u_short    irdaAttribType;

    union

    {

        int    irdaAttribInt;

         struct

        {

            int      Len;

            u_char   OctetSeq[1];

            u_char   Reserved[3];

        } irdaAttribOctetSeq;

        struct

        {

            int      Len;

            u_char   CharSet;

            u_char   UsrStr[1];

            u_char   Reserved[2];

        } irdaAttribUsrStr;

    } irdaAttribute;

} WCE_IAS_QUERY, *PWCE_IAS_QUERY;

 

Table 7-2 provides the different constants for the irdaAttribType field, which indicates which type the attribute belongs to. The last two entries are not values that you can set, but values that a call to getsockopt() with an IRLMP_IAS_QUERY socket option can return in the irdaAttribType field. These are included in the table for the sake of completeness.

 

Table 7-2 IAS Attribute Types

 

irdaAttribType Value

Field to Set

IAS_ATTRIB_INT

IrdaAttribInt

IAS_ATTRIB_OCTETSEQ

IrdaAttribOctetSeq

IAS_ATTRIB_STR

IrdaAttribUsrStr

IAS_ATTRIB_NO_CLASS

None

IAS_ATTRIB_NO_ATTRIB

None

 

To set a value, you must fill in irdaDeviceID to the IR device on which to modify the IAS entry. Also, irdaAttribName must be set to the class on which to set the attribute, while irdaClassName usually refers to the service on which to set the attribute. Remember that with IrSock, socket servers are services registered with IAS that have an associated LSAP-SEL number that clients use to connect to the server. The LSAP-SEL number is an attribute associated with that service. To modify the LSAP-SEL number in the service's IAS entry, set the irdaDeviceID field to the device ID on which the service is running. Set the irdaAttribName field to the property string “IrDA:IrLMP:LsapSel” and the irdaClassName field to the name of the service (for example, “MySocketServer”). From there, set irdaAttribType to IAS_ATTRIB_INT and irdaAttribInt to the new LSAP-SEL number. Of course, changing the service's LSAP-SEL number is a bad idea, but this example is for illustration only.

 

IRLMP_IRLPT_MODE

 

optval Type

Get/Set

Winsock Version

Description

BOOL

Both

1+

If TRUE, socket is configured to communicate to IR-capable printers.

 

It is possible to connect to an infrared printer using Winsock and send data to be printed. This is accomplished by putting the socket in IRLPT mode before establishing the connection. Simply pass the Boolean value TRUE to this option after socket creation. You can use the option IRLMP_ENUMDEVICES to find infrared-capable printers within range. Note that some legacy IR printers do not register themselves with IAS; you might need to connect to them directly using the “LSAP-SEL-xxx” identifier. This option is available on Windows CE, and Windows 2000 and later.

 

IRLMP_SEND_PDU_LEN

 

optval Type

Get/Set

Winsock Version

Description

int

Get only

1+

Gets the maximum PDU length

 

This option retrieves the maximum Protocol Data Unit (PDU) size needed when using the option IRLMP_9WIRE_MODE. See the description of IRLMP_9WIRE_MODE for more information about this option, which is available on Windows CE and Windows 2000 and later.

 

IPPROTO_IP Option Level

 

The socket options on the IPPROTO_IP level pertain to attributes specific to the IPv4 protocol, such as modifying certain fields in the IPv4 header and adding a socket to an IPv4 multicast group. Many of these options are declared in both WINSOCK.H and WINSOCK2.H with different values. Note that if you load Winsock 1, you must include the correct header and link with Wsock32.lib. Likewise for Winsock 2, you should include the Winsock 2 header file and link with Ws2_32.lib. This is especially relevant to multicasting, which is available under both versions. Multicasting is supported on all Windows platforms except Windows CE, in which it is available on versions 2.1 and later. The new IGMPv3-related multicasting options are defined in Ws2tcpip.h.

 

 

 


< Chap 7: Index | Winsock2 Main | IP, IPV6, RM & IPX >