2
votes

In my company, we develop a network product, which acts like a sniffer.

In order to capture all IPV4 packets, we follow the next procedure:

  1. create a raw socket (exact code : new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Udp);
  2. bind it to the IPV4 address of the network interface, port 0 (exact code: socket.Bind(new IPEndPoint(address, 0));)
  3. If we're on Windows, set the socket to promiscuous mode (exact code: socket.IOControl(IOControlCode.ReceiveAll, new byte[]{ 1, 0, 0, 0 }, null);

And this is everything we need in order to capture all IPV4 packets from a network interface. the rest is a simple read operation inside a loop. On Windows, the process has to be executed with admin permissions.

Now, we also want to support IPV6. It's supposed to be easy, but we can't come up with a working solution. Even if nothing throws an exception, the socket is still "stuck" on the read operation. nothing is never received there.

In order to capture IPV6 packets, we modify the above procedure just a bit

  1. Create a socket with Socket(AddressFamily.InterNetworkV6, SocketType.Raw, ProtocolType.IPv6) (note: using ProtocolType.Udp doesn't help either)
  2. Bind to a link-local address (example: socket.Bind(new IPEndPoint(IPAddress.Parse("fe80::dd37:936f:d87:b70c"), 0));). Note: adding a scope-id (like fe80::dd37:936f:d87:b70c%9) doesn't help either.
  3. On Windows, set the socket to promiscuous mode just like the IPV4 procedure.

Another things I've tried:

  • setting the socket to dual mode by calling socket.DualMode = true; between (1) and (2).
  • disabling IPV6-only option on the socket by calling socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, false); between (1) and (2).

I test this by opening Chrome - Chrome fires an MDNS packet both for IPV6 and IPV4 for its chrome-cast feature. Wireshark (which uses a kernel driver), sees this packet and displays it correctly. My code doesn't unblock from the read operation.

I use Windows 10 that supports IPV6.

An ideas how to read all IPV6 packets from the network interface like in IPV4? Thanks.

1
Listen at IPAddress.IPv6Any : IPEndPoint(IPAddress.IPv6Any, 0));).jdweng
doesn't help. it makes step 3 throw an exception and if I comment out step 3 it still get stuck on reading.David Haim
@jdweng This doesn't work with raw socket in Windows.NN_
The IOControl valid values are shown on following pages : referencesource.microsoft.com/#System/net/System/Net/Sockets/… and referencesource.microsoft.com/#System/net/System/Net/Sockets/… 0x80000000 doesn't seem to be a valid value (new byte[]{ 1, 0, 0, 0 }).jdweng
Don't get window and the net library confused. The windows socket will work with any type socket. The managed c# library is very limited on types of sockets that are valid. It doesn't look like c# have any support for raw sockets. So your issue is really raw sockets and not IPV6. Microsoft decided in Net Library to create their own socket class rather than use the Windows Class for sockets. So using the windows dll for sockets will work. See : pinvoke.net/default.aspx/ws2_32.SendTojdweng

1 Answers

1
votes

The solution is to use ProtocolType.IP instead of ProtocolType.IPv6.