Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Socket.IOControl - Ambiguous Documentation

Tags:

c#

.net

socket.io

I tried - for the first time - to control a socket by such a low level way
Walking through tutorial, I faced these lines :

byte[] byTrue = new byte [4] {1, 0, 0, 0};
byte[] byOut = new byte [4] {1, 0, 0, 0};

_Socket.IOControl(IOControlCode.ReceiveAll, byTrue, byOut);  

I referred to the MSDN documentation, but it's really very ambiguous.

Question:

What are these 2 bytes' arrays? What are they used in?
The documentation says OPTIONS - what options?

like image 680
Ahmed Ghoneim Avatar asked Feb 25 '12 00:02

Ahmed Ghoneim


1 Answers

The byte array arguments to Socket.IOControl() are specific to the IOControlCode that is specified as the first argument.

The first array is for input data, the second array is for output data.

To find more information about the specific layout for these arrays, it is helpful to start by looking at the enumeration, which lists all the possible operations for you. From there, you should cross reference with the documentation listed for the C-operable functions that Socket.IOControl() wraps. These are WSAIoctl() and ioctlsocket().

IOControlCode Enumeration @ MSDN

WSAIoctl() function @ MSDN
ioctlsocket() function @ MSDN

Per the documentation for IOControlCode.ReceiveAll:

Enable receiving all IPv4 packets on the network. The socket must have address family InterNetwork, the socket type must be Raw, and the protocol type must be IP. The current user must belong to the Administrators group on the local computer, and the socket must be bound to a specific port. This control code is supported on Windows 2000 and later operating systems. This value is equal to the Winsock 2 SIO_RCVALL constant.

Cross referencing SIO_RCVALL, we find it has an entry in the winsock documentation.

SIO_RCVALL control code @ MSDN

Reading through this entry, it mentions that the input buffer is required to select a mode of operation, with minimum size corresponding to a RCVALL_VALUE. In your statement you are passing the value 1 in the input argument array. We can check header files to see what this should mean.

You should double check this with C header files at hand, but the interface-compatible copy for wine (windows emulator) says the value for mode RCVALL_ON is 1. The .NET method should wrap the details of managing array size for you, so the code snippet you encountered is trying to enable RCVALL_ON for the socket.

Here is the link to the C header file at winehq.org: mstcpip.h at winehq.org

If you've installed C/C++ support for visual studio, you may be able to locate mstcpip.h and winsock2.h locally at a path similar to the following:

C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Include\

My copy says:

//
// Values for use with SIO_RCVALL* options
//
typedef enum {
    RCVALL_OFF             = 0,
    RCVALL_ON              = 1,
    RCVALL_SOCKETLEVELONLY = 2,
    RCVALL_IPLEVEL         = 3,
} RCVALL_VALUE, *PRCVALL_VALUE;

I couldn't find any documentation that specifically says what size byte array should be used to pass a RCVALL_VALUE, but if you look at the the samples for IOControl(), they use BitConverter.GetBytes(0) for default parameters which would have a size of 4 bytes (corresponding to a .NET int) and matches your example. This is large enough to fit a RCVALL_VALUE in C operation as well.

like image 152
meklarian Avatar answered Nov 07 '22 23:11

meklarian