Using Raw Sockets





Using Raw Sockets

Because ICMP packets do not use either TCP or UDP, you cannot use either of the socket helper classes, TcpClient or UdpClient. Instead, you have to use what are called raw sockets, which are a feature of the Socket class. Raw sockets allow you to define your own network packet above the IP layer. Of course, this means that you must do all the work of manually creating all the individual fields in the ICMP packet, rather than having the .NET library create the packet for you, as it does with TCP and UDP.

Raw Sockets Format

To create a raw socket, you must use the SocketType.Raw socket type when the socket is created. There are several ProtocolType values that you can use to match with the raw socket type; they’re listed in Figure.

Figure: The Raw Socket ProtocolType Values

Value

Description

Ggp

Gateway-to-Gateway Protocol

Icmp

Internet Control Message Protocol

Idp

IDP Protocol

Igmp

Internet Group Management Protocol

IP

A raw IP packet

Ipx

Novell IPX Protocol

ND

Net Disk Protocol

Pup

Xerox PARC Universal Protocol (PUP)

Raw

A raw IP packet

Spx

Novell SPX Protocol

SpxII

Novell SPX Version 2 Protocol

Unknown

An unknown protocol

Unspecified

An unspecified protocol

The specific protocols listed for a raw socket allows the .NET library to properly create the underlying IP packet. By using the ProtocolType.Icmp value, the IP packet created by the socket defines the next layer protocol as ICMP (IP value Type 1). This allows the remote host to immediately identify the packet as an ICMP packet, and process it accordingly.

Obviously, for the applications in this chapter, you will use the ProtocolType.Icmp value. Here’s the command to create a socket for ICMP packets:

Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Raw,
  ProtocolType.Icmp);

Sending Raw Packets

Because ICMP is a connectionless protocol, you do not have to bind the socket to a specific local port to send a packet or use the Connect() method to connect it to a specific remote host. You must use the SendTo() method to specify the IPEndPoint object of the destination address. ICMP does not use ports, so the value of the port property of the IPEndPoint object is not important. The following creates an IPEndPoint destination object with no port and sends a packet to it:

IPEndPoint iep = new IPEndPoint(IPAddress.Parse("192.168.1.2"), 0);
sock.SendTo(packet, iep);
Warning 

Remember that because the raw socket does not format the data, whatever value entered in the packet byte array will be forwarded "as-is" to the remote host. This means you must manually create the ICMP packet in the byte array and then send it to the remote host. Any mistakes in creating the packet will result in an error on the receiving host, and most likely you will not get a return ICMP packet.

Receiving Raw Packets

Receiving data from a raw socket is trickier than sending data in a raw socket. To receive data from the raw socket, you must use the ReceiveFrom() method. Because the raw socket does not identify a higher-layer protocol, the data returned from a ReceiveFrom() method call contains the entire IP packet contents. You must extract the data from the raw IP packet information to create the ICMP packet elements. As you can see in Figure, the IP packet data starts at byte 20. Therefore, to extract the ICMP packet data and header, you start reading the byte array at the 20th position in the received data packet.

Warning 

Because the ReceiveFrom() method returns the entire IP packet, you must remember to declare the receiving buffer size to be at least 20 bytes larger than your expected data.


 Python   SQL   Java   php   Perl 
 game development   web development   internet   *nix   graphics   hardware 
 telecommunications   C++ 
 Flash   Active Directory   Windows