this is my code for watching IP packets. I am doing project for my self because I want to learn how this things works.
This is my IP Packet class:
public class IPPacket
{
private IPHeader _ipHeader;
private TCPHeader _tcpHeader;
private UDPHeader _udpHeader;
public IPPacket(IPHeader ipHeader, TCPHeader tcpHeader, UDPHeader udpHeader)
{
_ipHeader = ipHeader;
_tcpHeader = tcpHeader;
_udpHeader = udpHeader;
}
public static IPPacket ParseData(byte[] bytes)
{
var ipHeader = new IPHeader(bytes);
UDPHeader udpHeader = null;
TCPHeader tcpHeader = null;
switch (ipHeader.Protocol)
{
case System.Net.Sockets.ProtocolType.Tcp:
tcpHeader = new TCPHeader(ipHeader.Data);
break;
case System.Net.Sockets.ProtocolType.Udp:
udpHeader = new UDPHeader(ipHeader.Data);
break;
default:
if (Debugger.IsAttached) Debugger.Break();
break;
}
return new IPPacket(ipHeader, tcpHeader, udpHeader);
}
}
IP Header class:
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//|Version| IHL |Type of Service| Total Length |
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//| Identification | Flags | Fragment offset |
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//|Time to live | Protocol | Header checksum |
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//| Source IP address |
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//| Destination IP address |
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//| Options | Padding |
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
public class IPHeader
{
public byte Version { get; set; }
public ushort IHL { get; set; }
public byte DifferentiatedServices { get; set; }
public ushort TotalLength { get; set; }
public ushort Identification { get; set; }
public Flags Flags { get; set; }
public ushort FragmentOffset { get; set; }
public byte TimeToLive { get; set; }
public ProtocolType Protocol { get; set; }
public string HeaderChecksum { get; set; }
public IPAddress SourceIPAddress { get; set; }
public IPAddress DestinationIPAddress { get; set; }
public byte[] Data { get; set; }
public IPHeader(byte[] bytes)
{
Version = (byte)((bytes[0] >> 4) & 0x0F); //0000XXXX & 0000FFFF
IHL = (ushort)((bytes[0] & 0x0F) * 4);
DifferentiatedServices = bytes[1];
TotalLength = (ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(bytes, 2));
Identification = (ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(bytes, 4));
Flags = new Flags(bytes[6]);
FragmentOffset = (ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(bytes, 6) << 3);
TimeToLive = bytes[8];
Protocol = (ProtocolType)bytes[9];
HeaderChecksum = string.Format("0x{0:x2}", IPAddress.NetworkToHostOrder(BitConverter.ToInt16(bytes, 10)));
SourceIPAddress = new IPAddress(BitConverter.ToInt32(bytes, 12));
DestinationIPAddress = new IPAddress(BitConverter.ToInt32(bytes, 16));
Data = new byte[TotalLength - IHL];
Array.Copy(bytes, IHL, Data, 0, TotalLength - IHL);
}
}
public class Flags
{
public bool Reserved { get; set; }
public bool DontFragment { get; set; }
public bool MoreFragments { get; set; }
public Flags(byte flags)
{
Reserved = Convert.ToBoolean((flags >> 7) & 0x01);
DontFragment = Convert.ToBoolean((flags >> 6) & 0x01);
MoreFragments = Convert.ToBoolean((flags >> 5) & 0x01);
}
}
TCP Header class:
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//| Source Port | Destination Port |
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//| Sequence Number |
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//| Acknowledgment Number |
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//| Data | |U|A|P|R|S|F| |
//| Offset| Reserved |R|C|S|S|Y|I| Window |
//| | |G|K|H|T|N|N| |
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//| Checksum | Urgent Pointer |
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//| Options | Padding |
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//| data |
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
public class TCPHeader
{
public ushort SourcePort { get; set; }
public ushort DestinationPort { get; set; }
public uint SequenceNumber { get; set; }
public uint AcknowledgmentNumber { get; set; }
public byte DataOffset { get; set; }
public byte Reserved { get; set; }
public ControlBits ControlBits { get; set; }
public ushort Window { get; set; }
public string Checksum { get; set; }
public ushort UrgentPointer { get; set; }
public byte[] Data { get; set; }
public TCPHeader(byte[] bytes)
{
SourcePort = (ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(bytes, 0));
DestinationPort = (ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(bytes, 2));
SequenceNumber = (uint)IPAddress.NetworkToHostOrder(BitConverter.ToInt32(bytes, 4));
AcknowledgmentNumber = (uint)IPAddress.NetworkToHostOrder(BitConverter.ToInt32(bytes, 8));
DataOffset = (byte)((bytes[9] >> 4) & 0x0F);
Reserved = 0;
ControlBits = new ControlBits(bytes[13]);
Window = (ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(bytes, 14));
Checksum = string.Format("0x{0:x2}", (ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(bytes, 16)));
UrgentPointer = (ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(bytes, 18));
Data = new byte[bytes.Length - 20];
Array.Copy(bytes, 20, Data, 0, bytes.Length - 20);
}
}
public class ControlBits
{
public bool URG { get; set; }
public bool ACK { get; set; }
public bool PSH { get; set; }
public bool RST { get; set; }
public bool SYN { get; set; }
public bool FIN { get; set; }
public ControlBits(byte controlBits)
{
URG = Convert.ToBoolean(controlBits >> 5 & 0x01);
ACK = Convert.ToBoolean(controlBits >> 4 & 0x01);
PSH = Convert.ToBoolean(controlBits >> 3 & 0x01);
RST = Convert.ToBoolean(controlBits >> 2 & 0x01);
SYN = Convert.ToBoolean(controlBits >> 1 & 0x01);
FIN = Convert.ToBoolean(controlBits & 0x01);
}
}
UDP Header class:
// 0 7 8 15 16 23 24 31
//+--------+--------+--------+--------+
//| Source | Destination |
//| Port | Port |
//+--------+--------+--------+--------+
//| | |
//| Length | Checksum |
//+--------+--------+--------+--------+
//|
//| data octets...
//+---------------- ...
public class UDPHeader
{
public ushort SourcePort { get; set; }
public ushort DestinationPort { get; set; }
public ushort Length { get; set; }
public ushort Checksum { get; set; }
public byte[] Data { get; set; }
public UDPHeader(byte[] bytes)
{
SourcePort = (ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(bytes, 0));
DestinationPort = (ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(bytes, 2));
Length = (ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(bytes, 4));
Checksum = (ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(bytes, 6));
Data = new byte[Length - 8];
Array.Copy(bytes, 8, Data, 0, Length - 8);
}
}
Can you give some advice what seems bad code practice? And one more thing how would be best to define TCP and UDP header inside IP packet, because one packet can have TCP header second can have UDP header.