The Windows Sockets WSAIoctl function controls the mode of a socket.
int WSAIoctl (
SOCKET s,
DWORD dwIoControlCode,
LPVOID lpvInBuffer,
DWORD cbInBuffer,
LPVOID lpvOUTBuffer,
DWORD cbOUTBuffer,
LPDWORD lpcbBytesReturned,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionROUTINE
);
The WSAIoctl function is used to set or retrieve operating parameters associated with the socket, the transport protocol, or the communications subsystem.
If both lpOverlapped and lpCompletionRoutine are NULL, the socket in this function will be treated as a non-overlapped socket. For a non-overlapped socket, lpOverlapped and lpCompletionRoutine parameters are ignored, which cause the function to behave like the standard ioctlsocket function except that WSAIoctl can block if socket s is in the blocking mode. If socket s is in the nonblocking mode, this function can return WSAEWOULDBLOCK when the specified operation cannot be finished immediately. In this case, the application may change the socket to the blocking mode and reissue the request or wait for the corresponding network event (such as FD_ROUTING_INTERFACE_CHANGE or FD_ADDRESS_LIST_CHANGE in case of SIO_ROUTING_INTERFACE_CHANGE or SIO_ADDRESS_LIST_CHANGE) using Windows message (using WSAAsyncSelect) or event (using WSAEventSelect) based notification mechanism
For overlapped sockets, operations that cannot be completed immediately will be initiated, and completion will be indicated at a later time. The final completion status is retrieved through WSAGetOverlappedResult. The lpcbBytesReturned parameter is ignored.
Any ioctl may block indefinitely, depending on the service provider's implementation. If the application cannot tolerate blocking in a WSAIoctl call, overlapped I/O would be advised for ioctls that are especially likely to block including:
SIO_FINDROUTE
SIO_FLUSH
SIO_GET_QOS
SIO_GET_GROUP_QOS
SIO_SET_QOS
SIO_SET_GROUP_QOS
SIO_ROUTING_INTERFACE_CHANGE
SIO_ADDRESS_LIST_CHANGE
Some protocol-specific ioctls may also be especially likely to block. Check the relevant protocol-specific annex for any available information.
It is possible to adopt an encoding scheme that preserves the currently defined ioctlsocket opcodes while providing a convenient way to partition the opcode identifier space in as much as the dwIoControlCode parameter is now a 32-bit entity. The dwIoControlCode parameter is architected to allow for protocol and vendor independence when adding new control codes while retaining backward compatibility with the Windows Sockets 1.1 and Unix control codes. The dwIoControlCode parameter has the following form:
3 | 3 | 2 | 2 2 | 2 2 2 2 2 2 2 1 1 1 1 | 1 1 1 1 1 1 |
1 | 0 | 9 | 8 7 | 6 5 4 3 2 1 0 9 8 7 6 | 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
I | O | V | T | Vendor/Address Family | Code |
I is set if the input buffer is valid for the code, as with IOC_IN.
O is set if the output buffer is valid for the code, as with IOC_OUT. Codes with both input and output parameters set both I and O.
V is set if there are no parameters for the code, as with IOC_VOID.
T is a two-bit quantity that defines the type of ioctl. The following values are defined:
0 – The ioctl is a standard Unix ioctl code, as with FIONREAD and FIONBIO.
1 – The ioctl is a generic Windows Sockets 2 ioctl code. New ioctl codes defined for Windows Sockets 2 will have T == 1.
2 – The ioctl applies only to a specific address family.
3 – The ioctl applies only to a specific vendor's provider. This type allows companies to be assigned a vendor number that appears in the Vendor/Address family field. Then, the vendor can define new ioctls specific to that vendor without having to register the ioctl with a clearinghouse, thereby providing vendor flexibility and privacy.
Vendor/Address family – An 11-bit quantity that defines the vendor who owns the code (if T == 3) or that contains the address family to which the code applies (if T == 2). If this is a Unix ioctl code (T == 0) then this field has the same value as the code on Unix. If this is a generic Windows Sockets 2 ioctl (T == 1) then this field can be used as an extension of the "code" field to provide additional code values.
Code – The 16-bit quantity that contains the specific ioctl code for the operation.
The following Unix ioctl codes (commands) are supported:
The WSAAsyncSelect or WSAEventSelect routine automatically sets a socket to nonblocking mode. If WSAAsyncSelect or WSAEventSelect has been issued on a socket, then any attempt to use WSAIoctl to set the socket back to blocking mode will fail with WSAEINVAL. To set the socket back to blocking mode, an application must first disable WSAAsyncSelect by calling WSAAsyncSelect with the lEvent parameter equal to zero, or disable WSAEventSelect by calling WSAEventSelect with the lNetworkEvents parameter equal to zero.
The following Windows Sockets 2 commands are supported:
A companion interface might be used, for example, if a particular provider provides (1) a great deal of additional controls over the behavior of a socket and (2) the controls are provider-specific enough that they do not map to existing Windows Socket functions or ones likely to be defined in the future. It is recommend that the Component Object Model (COM) be used instead of this ioctl to discover and track other interfaces that might be supported by a socket. This ioctl is present for (reverse) compatibility with systems where COM is not available or cannot be used for some other reason.
It is recommend that the Component Object Model (COM) be used instead of this ioctl to discover and track other interfaces that might be supported by a socket. This ioctl is present for (reverse) compatibility with systems where COM is not available or cannot be used for some other reason.
Note that routes are subject to change. Therefore, applications cannot rely on the information returned by SIO_ROUTING_INTERFACE_QUERY to be persistent. Applications may register for routing change notifications via the SIO_ROUTING_INTERFACE_CHANGE IOCTL which provides for notification via either overlapped IO or FD_ROUTING_INTERFACE_CHANGE event. The following sequence of actions can be used to guarantee that the application always has current routing interface information for a given destination:
If output buffer is not large enough to contain the interface address, SOCKET_ERROR is returned as the result of this IOCTL and WSAGetLastError returns WSAEFAULT. The required size of the output buffer will be returned in lpcbBytesReturned in this case. Note the WSAEFAULT error code is also returned if the lpvInBuffer, lpvOutBuffer or lpcbBytesReturned parameter is not totally contained in a valid part of the user address space.
If the destination address specified in the input buffer cannot be reached via any of the available interfaces, SOCKET_ERROR is returned as the result of this IOCTL and WSAGetLastError returns WSAENETUNREACH or even WSAENETDOWN if all of the network connectivity is lost.
It is assumed (although not required) that the application uses overlapped IO to be notified of routing interface change via completion of SIO_ROUTING_INTERFACE_CHANGE request. Alternatively, if the SIO_ROUTING_INTERFACE_CHANGE IOCTL is issued on non-blocking socket and without overlapped parameters (lpOverlapped / CompletionRoutine are set NULL), it will complete immediately with error WSAEWOULDBLOCK, and the application can then wait for routing change events via call to WSAEventSelect or WSAAsyncSelect with FD_ROUTING_INTERFACE_CHANGE bit set in the network event bitmask
It is recognized that routing information remains stable in most cases so that requiring the application to keep multiple outstanding IOCTLs to get notifications about all destinations that it is interested in as well as having service provider to keep track of all them will unnecessarily tie significant system resources. This situation can be avoided by extending the meaning of the input parameters and relaxing the service provider requirements as follows:
typedef struct _SOCKET_ADDRESS_LIST {
INT iAddressCount;
SOCKET_ADDRESS Address[1];
} SOCKET_ADDRESS_LIST, FAR * LPSOCKET_ADDRESS_LIST;
Members:
iAddressCount - number of address structures in the list;
Address - array of protocol family specific address structures.
Note that in Win32 Plug-n-Play environments addresses can be added/removed dynamically. Therefore, applications cannot rely on the information returned by SIO_ADDRESS_LIST_QUERY to be persistent. Applications may register for address change notifications via the SIO_ADDRESS_LIST_CHANGE IOCTL which provides for notification via either overlapped IO or FD_ADDRESS_LIST_CHANGE event. The following sequence of actions can be used to guarantee that the application always has current address list information:·issue SIO_ADDRESS_LIST_CHANGE IOCTL
If output buffer is not large enough to contain the address list, SOCKET_ERROR is returned as the result of this IOCTL and WSAGetLastError returns WSAEFAULT. The required size of the output buffer will be returned in lpcbBytesReturned in this case. Note the WSAEFAULT error code is also returned if the lpvInBuffer, lpvOutBuffer or lpcbBytesReturned parameter is not totally contained in a valid part of the user address space.
It is assumed (although not required) that the application uses overlapped IO to be notified of change via completion of SIO_ADDRESS_LIST_CHANGE request. Alternatively, if the SIO_ADDRESS_LIST_CHANGE IOCTL is issued on non-blocking socket AND without overlapped parameters (lpOverlapped / lpCompletionRoutine are set to NULL), it will complete immediately with error WSAEWOULDBLOCK. The application can then wait for address list change events via call to WSAEventSelect or WSAAsyncSelect with FD_ADDRESS_LIST_CHANGE bit set in the network event bitmask.
If an overlapped operation completes immediately, WSAIoctl returns a value of zero and the lpcbBytesReturned parameter is updated with the number of bytes in the output buffer. If the overlapped operation is successfully initiated and will complete later, this function returns SOCKET_ERROR and indicates error code WSA_IO_PENDING. In this case, lpcbBytesReturned is not updated. When the overlapped operation completes the amount of data in the output buffer is indicated either through the cbTransferred parameter in the completion routine (if specified), or through the lpcbTransfer parameter in WSAGetOverlappedResult.
When called with an overlapped socket, the lpOverlapped parameter must be valid for the duration of the overlapped operation. The lpOverlapped parameter contains the address of a WSAOVERLAPPED structure.
If the lpCompletionRoutine parameter is NULL, the hEvent field of lpOverlapped is signaled when the overlapped operation completes if it contains a valid event object handle. An application can use WSAWaitForMultipleEvents or WSAGetOverlappedResult to wait or poll on the event object.
If lpCompletionRoutine is not NULL, the hEvent field is ignored and can be used by the application to pass context information to the completion routine. A caller that passes a non-NULL lpCompletionRoutine and later calls WSAGetOverlappedResult for the same overlapped IO request may not set the fWait parameter for that invocation of WSAGetOverlappedResult to TRUE. In this case the usage of the hEvent field is undefined, and attempting to wait on the hEvent field would produce unpredictable results.
The prototype of the completion routine is as follows:
void CALLBACK CompletionRoutine(
IN DWORD dwError,
IN DWORD cbTransferred,
IN LPWSAOVERLAPPED lpOverlapped,
IN DWORD dwFlags
);
This CompletionRoutine is a placeholder for an application-defined or library-defined function. The dwError parameter specifies the completion status for the overlapped operation as indicated by lpOverlapped. The cbTransferred parameter specifies the number of bytes returned. Currently, there are no flag values defined and dwFlags will be zero. The CompletionRoutine function does not return a value.
Returning from this function allows invocation of another pending completion routine for this socket. The completion routines can be called in any order, not necessarily in the same order the overlapped operations are completed.
Windows CE: For secure sockets, the lpcbBytesReturned parameter is a pointer to a DWORD receiving the number of bytes returned in output buffer. Also, the last two parameters, namely, lpOverlapped and lpCompletionRoutine, must be NULL.
In addition to the ioctlsocket control codes (FIONBIO, SIOCATMARK, FIONREAD), the dwIoControlCode parameter may also assume the following SSL-specific control flags:
Value | Meaning |
---|---|
SO_SSL_GET_CAPABILITIES | Retrieves a set of flags describing the WinSock security provider's capabilities. The output buffer must be a pointer to a DWORD bit field. At present, only the SO_CAP_CLIENT flag is defined. |
SO_SSL_GET_FLAGS | Retrieves s-channel specific flags associated with a particular socket. The output buffer must be a pointer to a DWORD bit field. See SO_SSL_SET_FLAGS for details on valid flags. |
SO_SSL_SET_FLAGS | Sets the sockets' current s-channel-specific flag values. The input buffer must be a pointer to a DWORD bit field. Currently, only the SSL_FLAG_DEFER_HANDSHAKE flag is defined to allow the application to send and receive plain text data before switching to cipher text. It is required for setting up communication through proxy servers. Normally the WinSock security provider performs the secure handshake in the WinSock connect API. However, if this flag is set, the handshake is deferred until the application issues the SO_SSL_PERFORM_HANDSHAKE control code. After the handshaking, this flag is reset. |
SO_SSL_GET_PROTOCOLS | Retrieves a list of protocols that the provider currently supports on this socket. The output buffer must be a pointer to a SSLPROTOCOLS structure as described below:
Valid protocols include SSL_PROTOCOL_SSL2, SSL_PROTOCOL_SSL3, and SSL_PROTOCOL_PCT1. |
SO_SSL_SET_PROTOCOLS | Specifies a list of protocols the provider is to support on this socket. The input buffer must be a pointer to SSLPROTOCOLS structure described above. |
SO_SSL_SET_VALIDATE_CERT_HOOK | Sets the pointer to the socket's certificate validation hook. It is used to specify the callback function invoked by the WinSock security provider when a set of credentials is received from the remote party. The input buffer must be a pointer to the SSLVALIDEATECERTHOOK structure, described below:
where HookFunc is a pointer to the certificate validation callback function (see "Certificate Validation Callback" below). pvArg is a pointer to application specific data and may be used by the application for any purpose. |
SO_SSL_PERFORM_HANDSHAKE | Initiates the secure handshake sequence on a connected socket where the SSL_FLAG_DEFER_HANDSHAKE flag has been set prior to the connection. Data buffers are not required, but the SSL_FLAG_DEFER_HANDSHAKE flag will be reset. |
Certificate Validation Callback
The WinSock security provider invokes the certificate validation callback when the remote party receives a certificate for server authentication. All the client applications must implement the callback function to ensure that the certificate should meet the following minimum requirements:
The certificate validation callback function is of the following type:
typedef int (CALLBACK *SSLVALIDATECERTFUNC){
DWORD dwType, // in
LPVOID pvArg, // in
DWORD dwChainLen, // in
LPBLOB pCertChain, // in
DWORD dwFlags // in
};
The parameters are defined in the following table.
Parameters | Meaning |
---|---|
dwType | Specifies the type of data pointed to be pCertChain. This must be SSL_CERT_X59 to specify that pCertChain be a pointer to an X509 style certificate. |
PvArg | An application-defined context passed into the SSLVALIDATECERTHOOK structure. |
DwChainLen | The number of certificates pointed to by pCertChain. In Windows CE this will always be one. |
PCertChain | Pointer to the remote party's certificate. |
DwFlags | To be designed to indicate that the certificate issuer list has been checked with the list of known certificate authorities and that the certificate is either trusted or not. This is required since not all the certificate chain is passed to the application. |
The application-defined callback function will typically return one of the following error codes:
Value | Meaning |
---|---|
SSL_ERR_OKAY | The remote party's certificate is acceptable. |
SSL_ERR_BAD_DATA | The certificate is improperly formatted. |
SSL_ERR_BAD_SIG | The signature check fails. |
SSL_ERR_CERT_EXPIRED | The certificate has expired. |
SSL_ERR_CERT_REVOKED | The certificate has been revoked by its issuer. |
SSL_ERR_CERT_UNKNOWN | The issuer of the certificate is not recognized or some unspecified issue arose in the processing of the certificate, rendering it unacceptable. |
The ioctl codes with T == 0 are a subset of the ioctl codes used in Berkeley sockets. In particular, there is no command that is equivalent to FIOASYNC.
Upon successful completion, the WSAIoctl returns zero. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code can be retrieved by calling WSAGetLastError.
WSAENETDOWN | The network subsystem has failed. |
WSAEFAULT | The lpvInBuffer, lpvOutBuffer lpcbBytesReturned, lpOverlapped, or lpCompletionRoutine argument is not totally contained in a valid part of the user address space, or the cbInBuffer or cbOutBuffer argument is too small. |
WSAEINVAL | dwIoControlCode is not a valid command, or a supplied input parameter is not acceptable, or the command is not applicable to the type of socket supplied. |
WSAEINPROGRESS | The function is invoked when a callback is in progress. |
WSAENOTSOCK | The descriptor s is not a socket. |
WSAEOPNOTSUPP | The specified ioctl command cannot be realized. (For examle, the FLOWSPEC structures specified in SIO_SET_QOS or SIO_SET_GROUP_QOS cannot be satisfied.) |
WSA_IO_PENDING | An overlapped operation was successfully initiated and completion will be indicated at a later time. |
WSAEWOULDBLOCK | The socket is marked as nonblocking and the requested operation would block. |
Windows NT: Yes
Windows: Yes
Windows CE: Unsupported.
Header: Declared in winsock2.h.
Import Library: Link with ws2_32.lib.
getsockopt, ioctlsocket, setsockopt, socket, WSASocket