< FIONBIO, FIONREAD & SIO | Socket Options & IOCTLs Main | IP_TOS & SIO_ADDRESS_LIST_QUERY Examples >
What do we have in this chapter 7 part 4?
|
Secure Socket Layer Ioctl Commands
SO_SSL_GET_CAPABILITIES
This command retrieves a set of flags describing the Windows Sockets security provider's capabilities. The output buffer must be a pointer to a DWORD bit field. At present, only the flag SO_CAP_CLIENT is defined.
SO_SSL_GET_FLAGS
This command 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 below for details of valid flags.
SO_SSL_SET_FLAGS
The input buffer here must be a pointer to a DWORD bit field. Currently, the only flag defined is SSL_FLAG_DEFER_HANDSHAKE, which allows the application to send and receive plain text data before switching to cipher text. This flag is required for setting up communication through proxy servers. Normally, the Windows Sockets security provider performs the secure handshake in the Windows Sockets connect function. However, if this flag is set, the handshake is deferred until the application issues the SO_SSL_PERFORM_HANDSHAKE control code. After the handshake, this flag is reset. |
Which Function? |
Input |
Output |
Description |
WSAIoctl() |
None |
SSLPROTOCOLS |
Returns a list of protocols that the security provider supports |
This command 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 here:
typedef struct _SSLPROTOCOL
{
DWORD dwProtocol;
DWORD dwVersion;
DWORD dwFlags;
} SSLPROTOCOL, *LPSSLPROTOCOL;
typedef struct _SSLPROTOCOLS
{
DWORD dwCount;
SSLPROTOCOL ProtocolList[1];
} SSLPROTOCOLS, FAR *LPSSLPROTOCOLS;
Valid protocols for the dwProtocol field include SSL_PROTOCOL_SSL2, SSL_PROTOCOL_SSL3, and SSL_PROTOCOL_PCT1.
Which Function? |
Input |
Output |
Description |
WSAIoctl() |
SSLPROTOCOLS |
None |
Sets a list of protocols that the underlying provider should support |
This ioctl command specifies a list of protocols that the provider is to support on this socket. The input buffer must be a pointer to the SSLPROTOCOLS structure described previously.
Which Function? |
Input |
Output |
Description |
WSAIoctl() |
SSLVALIDATECERTHOOK |
None |
Sets the validation function for accepting SSL certificates |
This ioctl command sets the pointer to the socket's certificate validation hook. It is used to specify the callback function the Windows Sockets security provider invokes when it receives a set of credentials from the remote party. The input buffer must be a pointer to the SSLVALIDATECERTHOOK structure, described as follows:
typedef struct
{
SSLVALIDATECERTFUNC HookFunc;
LPVOID pvArg;
} SSLVALIDATECERTHOOK, *PSSLVALIDATECERTHOOK;
The HookFunc field is a pointer to a certificate validation callback function; pvArg is a pointer to application-specific data and can be used by the application for any purpose.
Which Function? |
Input |
Output |
Description |
WSAIoctl() |
None |
None |
Initiates a secure handshake on a connected socket |
This ioctl command initiates the secure handshake sequence on a connected socket in which 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.
The ioctl commands in this section are specific to the ATM protocol family. They are fairly basic, dealing mainly with obtaining the number of ATM devices and ATM addresses of the local interfaces.
Which Function? |
Input |
Output |
Winsock Version |
Description |
WSAIoctl() |
None |
DWORD |
2+ |
Returns the number of ATM adapters |
This ioctl command fills the output buffer pointed to by lpvOutBuffer with a DWORD containing the number of ATM devices in the system. Each specific device is identified by a unique ID, in the range 0 to the number returned by this ioctl command minus 1.
Which Function? |
Input |
Output |
Winsock Version |
Description |
WSAIoctl() |
DWORD |
ATM_ADDRESS |
2+ |
Returns the ATM address for the given device |
This ioctl command retrieves the local ATM address associated with the specified device. A device ID of type DWORD is specified in the input buffer for this ioctl command, and the output buffer pointed to by lpvOutBuffer will be filled with an ATM_ADDRESS structure containing a local ATM address suitable for use with bind().
Which Function? |
Input |
Output |
Winsock Version |
Description |
WSAIoctl() |
ATM_PVC_PARAMS |
None |
2+ |
Associates socket with a permanent virtual circuit |
This ioctl command associates the socket with a permanent virtual circuit (PVC), as indicated in the input buffer, which contains the ATM_PVC_PARAMS structure. The socket should be of the AF_ATM address family. After successfully returning from this function, the application is able to start sending and receiving data as if the connection has been set up. The ATM_PVC_PARAMS structure is defined as:
typedef struct
{
ATM_CONNECTION_ID PvcConnectionId;
QOS PvcQos;
} ATM_PVC_PARAMS;
typedef struct
{
DWORD DeviceNumber;
DWORD VPI;
DWORD VCI;
} ATM_CONNECTION_ID;
Which Function? |
Input |
Output |
Winsock Version |
Description |
Both |
None |
ATM_CONNECTION_ID |
2+ |
Determines whether OOB data has been read |
This ioctl command retrieves the ATM Connection ID associated with the socket. Upon successfully returning from this function, the output buffer pointed to by lpvOutBuffer is filled with an ATM_CONNECTION_ID structure containing the device number and Virtual Path/Channel Identifier (VPI/VCI) values, which are defined in the earlier entry for SIO_ASSOCIATE_PVC.
The following program example demonstrates the multicast application which uses the IP_TTL option to modify the time-to-live (TTL) field.
Add the following source code.
// Description:
// This is a simple multicast application which illustrates
// the use of the IP_TTL option to modify the time-to-live
// field of the IP header similar to the SIO_MULTIPOINT_SCOPE
// ioctl does except this applies to any kind of IP traffic.
//
// Command line arguments:
// ip_multicast_ttl [s|r] ttl
// s Sender
// r Receiver
// ttl Integer TTL value
//
// Vista issue: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=329162
//
// A program that includes Winsock.h should only link with Wsock32.lib
//
// Link to ws2_32.lib
#include <winsock2.h>
// Windows Server 2003 and Windows XP
#include <Ws2tcpip.h>
#include <stdio.h>
#define MAX_BUF 64
// Change the IP accordingly for testing
// Multicast address range 224.0.0.0 - 239.255.255.255
// http://www.iana.org/assignments/multicast-addresses/
#define MULTICAST_IP "192.168.1.1"
#define MULTICAST_PORT 24000
// Function: usage
// Description: Prints usage information
int usage(char *progname)
{
printf("Usage: %s s|r ttl\n", progname);
printf(" s = sender\n");
printf(" r = receiver\n");
printf(" ttl = multicast TTL value\n");
printf("Example: %s s 100\n", progname);
printf("Example: %s r 100\n", progname);
return 0;
}
// Function: main
// Description:
// Load Winsock, parse the arguments and start either the
// multicast sender or receiver. Before sending data set the IP_TTL to the specified value.
int main(int argc, char **argv)
{
WSADATA wsd;
SOCKET s;
// struct ipv6_mreq for IPv6
struct ip_mreq mcast; // IPv4
// or better one, use struct ip_mreq_source/IP_MREQ_SOURCE/*PIP_MREQ_SOURCE
// http://msdn.microsoft.com/en-us/library/ms738704(VS.85).aspx
// Vista or later use GROUP_REQ and the GROUP_SOURCE_REQ structures which for both IPv6 and IPv4
SOCKADDR_IN local, from;
int ttl, ttlsz, fromsz, ret;
char databuf[MAX_BUF];
BOOL bReceive=FALSE;
// Parse the command line
if (argc < 2)
{
usage(argv[0]);
exit(1);
}
if (tolower(argv[1][0]) == 's')
bReceive = FALSE;
else if (tolower(argv[1][0]) == 'r')
bReceive = TRUE;
else
usage(argv[0]);
ttl = atoi(argv[2]);
// Load winsock
if (WSAStartup(MAKEWORD(2,2), &wsd))
{
printf("WSAStartup() failed with error code %d\n", WSAGetLastError());
return -1;
}
else
printf("WSAStartup() is OK!\n");
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s == INVALID_SOCKET)
{
printf("socket() failed with error code %d\n", WSAGetLastError());
return -1;
}
else
printf("socket() is OK!\n");
if (bReceive)
{
local.sin_family = AF_INET;
local.sin_port = htons(MULTICAST_PORT);
local.sin_addr.s_addr = INADDR_ANY;
if (bind(s, (SOCKADDR *)&local, sizeof(local)) == SOCKET_ERROR)
{
printf("bind() failed with error code %d\n", WSAGetLastError());
return -1;
}
else
printf("bind() is OK!\n");
}
// Join the multicast group
// For XP sp2 and Windows 2003 not needed in order to send,
// only the receivers need to join a multicast group in order to receive
if(bReceive)
{
mcast.imr_multiaddr.s_addr = inet_addr(MULTICAST_IP);
mcast.imr_interface.s_addr = INADDR_ANY;
if (setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mcast, sizeof(mcast)) == SOCKET_ERROR)
{
printf("setsockopt(IP_ADD_MEMBERSHIP) failed with error code %d\n", WSAGetLastError());
return -1;
}
else
printf("setsockopt(IP_ADD_MEMBERSHIP) is OK!\n");
}
// Set the TTL to our value
ttlsz = sizeof(ttl);
if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&ttl, sizeof(ttl)) == SOCKET_ERROR)
{
printf("setsockopt(IP_MULTICAST_TTL) failed with error code %d\n", WSAGetLastError());
return -1;
}
else
printf("setsockopt(IP_MULTICAST_TTL) is OK!\n");
// Verify
if (getsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&ttl, &ttlsz) == SOCKET_ERROR)
{
printf("getsockopt(IP_MULTICAST_TTL) failed: %d\n", WSAGetLastError());
return -1;
}
else
printf("getsockopt(IP_MULTICAST_TTL) is OK!\n");
printf("Multicast TTL is set to: %d\n", ttl);
if (bReceive)
{
// Receive some data
fromsz = sizeof(from);
ret = recvfrom(s, databuf, MAX_BUF, 0, (SOCKADDR *)&from, &fromsz);
if (ret == SOCKET_ERROR)
{
printf("recvfrom() failed with error code %d\n", WSAGetLastError());
return -1;
}
else
printf("recvfrom() is OK!\n");
databuf[ret] = 0;
printf("read: [%s] from [%s]\n", databuf, inet_ntoa(from.sin_addr));
}
else
{
// Send some data
SOCKADDR_IN to;
memset(databuf, '$', MAX_BUF);
to.sin_family = AF_INET;
to.sin_port = htons(MULTICAST_PORT);
to.sin_addr.s_addr = inet_addr(MULTICAST_IP);
ret = sendto(s, databuf, MAX_BUF-1, 0, (SOCKADDR *)&to, sizeof(to));
if (ret == SOCKET_ERROR)
{
printf("sendto() failed with error code %d\n", WSAGetLastError());
return -1;
}
else
printf("sendto() is OK!\n");
printf("Sent %d bytes to %s\n", ret, inet_ntoa(to.sin_addr));
}
// Cleanup
if(closesocket(s) == 0)
printf("closesocket() should be fine!\n");
else
printf("closesocket() failed with error code %d\n", WSAGetLastError());
if(WSACleanup() == 0)
printf("WSACleanup() is OK!\n");
else
printf("WSACleanup() failed with error code %d\n", WSAGetLastError());
return 0;
}
Build and run the project.
----------------------------------------------------------------
Run the project as receiver.
Run the project as sender.
The previous receiver screenshot sample when the communication was completed.
< FIONBIO, FIONREAD & SIO | Socket Options & IOCTLs Main | IP_TOS & SIO_ADDRESS_LIST_QUERY Examples >