Socket Options and Ioctls

éÓÔÏÞÎÉË: Anthony Jones and Jim Ohlund "Windows Network Programming" - published by Microsoft Press, 1999

Socket Options

The getsockopt function is most frequently used to obtain information regarding the given socket. The prototype for this function is as follows:

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 characteristics of the socket itself and are not specific to the protocol of that socket.

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 abilities on the socket. This option is valid for sockets that aren't of type SOCK_STREAM.

Broadcasting is the ability 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. In order 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";  
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 6 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. However, on Windows 95 when using IPX, the receiving socket must set the SO_BROADCAST option in order to receive broadcast data, as described in Knowledge Base article Q137914, which can be found at http://support.microsoft.com/support/search. This is a bug in Windows 95.

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 the connection as been established. If the socket is not currently connected, the value returned is 0xFFFFFFFF.

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 Win32 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 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 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 whether routing is enabled (which it is by default).

Calling this option on a Win32 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 unless it is absolutely necessary to rely on the individual error code.

SO_EXCLUSIVEADDRUSE

optval Type Get/Set Winsock Version Description
BOOL Both 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. This is extremely unfortunate if your application is mission-critical. 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 only on Windows 2000.

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 Win32 platforms, keepalives 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 thing to note here is that keepalives are sent at intervals no less than 2 hours apart. The 2-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. Chapter 7 discusses this kind of 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 and Windows 98, these keys are located under the following Registry path:

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

In Windows NT and Windows 2000, store the keys under

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

With 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 linger Both 1+ Sets or gets the current linger values

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, while 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 you can 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.

Option Interval Type of Close Wait for Close?
SO_DONTLINGER Not applicable Graceful No
SO_LINGER 0 Hard No
SO_LINGER Nonzero 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. There is no provision for finding the maximum inbound message size.

SO_OOBINLINE

optval Type Get/Set Winsock Version Description
BOOL Both 1+ If TRUE, any out-of-band data is returned in the normal data stream.

By default, out-of-band (OOB) data is not inlined. That means 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. Unfortunately, this socket option is broken on all current Win32 implementations. See Chapter 7 for more details on OOB data.

SO_PROTOCOL_INFO

optval Type Get/Set Winsock Version Description
WSAPROTOCOL_INFO Get only 2+ The protocol characteristics for the protocol that the socket is bound to

This is another get-only option that fills in the supplied WSAPROTOCOL_INFO structure with the characteristics of the protocol associated with the socket. See Chapterš6 for a description of the WSAPROTOCOL_INFO structure and its member fields.

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 Win32 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 specifically 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 these buffers are nonzero, 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, as the local system cannot accept any incoming data unless you have a buffer posted and ready to receive the data. For more information, see the section called "Other Issues" under the completion port I/O model in Chapter 8.

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 in this way. Remember from Chapter 7 that each connection is uniquely identified by the combination of its local and remote addresses. As long as the address to which you are connecting 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+ TRUE (nonzero) means socket is configured for sending broadcast messages.

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 Win32 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. For additional information, see the section entitled "Other Issues" under the completion port I/O model in Chapter 8.

SO_TYPE

optval Type Get/Set Winsock Version Description
int Get only 1+ Returns the socket type (e.g., SOCK_DGRAM, SOCK_STREAM, etc.) 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_SNDTIMEO

optval Type Get/Set Winsock Version Description
int Both 1+ Gets/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 (send, sendto, WSASend, WSASendTo, and so on) block only for the amount of time specified. If the send operation cannot complete within that time, the call fails with error 10060 (WSAETIMEDOUT).

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_RCVTIMEO

optval Type Get/Set Winsock Version Description
int Both 1+ Gets/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 (recv, recvfrom, WSARecv, WSARecvFrom, and so on) block only for the amount of time specified. If no data arrives within that time, the call fails with the error 10060 (WSAETIMEDOUT).

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_UPDATE_ACCEPT_CONTEXT

optval Type Get/Set Winsock Version Description
SOCKET Both 1+ Gets/sets the timeout value (in milliseconds) associated with receiving data on the socket

This option is a Microsoft-specific extension most commonly 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 in order for the characteristics of the listening socket to be carried over to the client socket. This is particularly important for Quality of Service (QOS)-enabled listening sockets. In order 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 NT and Windows 2000.

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. For more information on the AppleTalk address family, refer back to Chapter 6. Some AppleTalk socket options-such as SO_DEREGISTER_NAME-have more than one option name. In such cases, all 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. Refer to the section entitled "Registering an AppleTalk Name" in Chapter 6 for a description of the WSH_REGISTER_NAME structure, which is simply another name for the WSH_NBP_NAME structure.

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. See the section "Resolving an AppleTalk Name" in Chapter 6 for sample code on how to look up an AppleTalk name.

One thing 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 9-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.

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 lists

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. Additionally, 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 nonblocking 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. Refer to Chapter 6 for a description of the WSH_REGISTER_NAME structure.

SOL_IRLMP Option Level

The SOL_IRLMP level deals with the IrDA protocol, whose address family is AF_IRDA. One important thing to keep in mind when using IrDA socket options is 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 later, in Windows 98 or Windows 2000. 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+ Gets/sets IP options within the IP header

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 in 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 on Windows 98 and Windows 2000.

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.