using System; using System.Text; using sysIO = System.IO; namespace Cosmos.System.Network.IPv4 { /// /// UDPPacket class. /// public class UDPPacket : IPPacket { /// /// UDP CRC. /// private ushort udpCRC; /// /// UDP handler. /// /// Packet data. /// Thrown if UDP_Data array length is greater than Int32.MaxValue. /// Thrown on IO error. internal static void UDPHandler(byte[] packetData) { UDPPacket udp_packet = new UDPPacket(packetData); NetworkStack.debugger.Send("Received UDP packet from " + udp_packet.SourceIP.ToString() + ":" + udp_packet.SourcePort.ToString()); if (CheckCRC(udp_packet)) { if (udp_packet.SourcePort == 68) { //Network.DHCP.DHCPPacket.DHCPHandler(packetData); return; } NetworkStack.debugger.Send("Content: " + Encoding.ASCII.GetString(udp_packet.UDP_Data)); UdpClient receiver = UdpClient.Client(udp_packet.DestinationPort); if (receiver != null) { receiver.receiveData(udp_packet); } } else { NetworkStack.debugger.Send("But checksum incorrect... Packet Passed."); } } /// /// Make header. /// /// Source IP. /// Destination IP. /// UDP length. /// Source port. /// Destination port. /// UDP data. /// byte array value. /// Thrown if UDP_Data array length is greater than Int32.MaxValue. public static byte[] MakeHeader(byte[] sourceIP, byte[] destIP, UInt16 udpLen, UInt16 sourcePort, UInt16 destPort, byte[] UDP_Data) { byte[] header = new byte[18 + UDP_Data.Length]; header[0] = sourceIP[0]; header[1] = sourceIP[1]; header[2] = sourceIP[2]; header[3] = sourceIP[3]; header[4] = destIP[0]; header[5] = destIP[1]; header[6] = destIP[2]; header[7] = destIP[3]; header[8] = 0x00; header[9] = 0x11; header[10] = (byte)((udpLen >> 8) & 0xFF); header[11] = (byte)((udpLen >> 0) & 0xFF); header[12] = (byte)((sourcePort >> 8) & 0xFF); header[13] = (byte)((sourcePort >> 0) & 0xFF); header[14] = (byte)((destPort >> 8) & 0xFF); header[15] = (byte)((destPort >> 0) & 0xFF); header[16] = (byte)((udpLen >> 8) & 0xFF); header[17] = (byte)((udpLen >> 0) & 0xFF); for (int i = 0; i < UDP_Data.Length; i++) { header[18 + i] = UDP_Data[i]; } return header; } /// /// Check CRC. /// /// Packer to be checked. /// bool value. /// Thrown if packet.UDP_Data lenght if greater than Int32.MaxValue. public static bool CheckCRC(UDPPacket packet) { byte[] header = MakeHeader(packet.SourceIP.address, packet.DestinationIP.address, packet.UDP_Length, packet.SourcePort, packet.DestinationPort, packet.UDP_Data); UInt16 calculatedcrc = Check(header, 0, header.Length); //NetworkStack.debugger.Send("Calculated: 0x" + Utils.Conversion.DecToHex(calculatedcrc)); //NetworkStack.debugger.Send("Received: 0x" + Utils.Conversion.DecToHex(packet.udpCRC)); if (calculatedcrc == packet.udpCRC) { return true; } else { return false; } } /// /// Calculate CRC. /// /// Buffer. /// Offset. /// Length. /// ushort value. protected static ushort Check(byte[] buffer, ushort offset, int length) { uint crc = 0; for (ushort w = offset; w < offset + length; w += 2) { crc += (ushort)((buffer[w] << 8) | buffer[w + 1]); } crc = (~((crc & 0xFFFF) + (crc >> 16))); return (ushort)crc; } /// /// Work around to make VMT scanner include the initFields method /// public static void VMTInclude() { new UDPPacket(); } /// /// Create new inctanse of the class. /// internal UDPPacket() { } /// /// Create new inctanse of the class. /// /// Raw data. public UDPPacket(byte[] rawData) : base(rawData) { } /// /// Create new inctanse of the class. /// /// Source address. /// Destination address. /// Source port. /// Destination port. /// Data array. /// Thrown if data array length is greater than Int32.MaxValue. /// Thrown if RawData is invalid or null. public UDPPacket(Address source, Address dest, ushort srcPort, ushort destPort, byte[] data) : base((ushort)(data.Length + 8), 17, source, dest, 0x00) { RawData[DataOffset + 0] = (byte)((srcPort >> 8) & 0xFF); RawData[DataOffset + 1] = (byte)((srcPort >> 0) & 0xFF); RawData[DataOffset + 2] = (byte)((destPort >> 8) & 0xFF); RawData[DataOffset + 3] = (byte)((destPort >> 0) & 0xFF); UDP_Length = (ushort)(data.Length + 8); RawData[DataOffset + 4] = (byte)((UDP_Length >> 8) & 0xFF); RawData[DataOffset + 5] = (byte)((UDP_Length >> 0) & 0xFF); byte[] header = MakeHeader(source.address, dest.address, UDP_Length, srcPort, destPort, data); UInt16 calculatedcrc = Check(header, 0, header.Length); RawData[DataOffset + 6] = (byte)((calculatedcrc >> 8) & 0xFF); RawData[DataOffset + 7] = (byte)((calculatedcrc >> 0) & 0xFF); for (int b = 0; b < data.Length; b++) { RawData[DataOffset + 8 + b] = data[b]; } initFields(); } /// /// Init UDPPacket fields. /// /// Thrown if RawData is invalid or null. protected override void initFields() { base.initFields(); SourcePort = (ushort)((RawData[DataOffset] << 8) | RawData[DataOffset + 1]); DestinationPort = (ushort)((RawData[DataOffset + 2] << 8) | RawData[DataOffset + 3]); UDP_Length = (ushort)((RawData[DataOffset + 4] << 8) | RawData[DataOffset + 5]); udpCRC = (ushort)((RawData[DataOffset + 6] << 8) | RawData[DataOffset + 7]); } /// /// Get destination port. /// public ushort DestinationPort { get; private set; } /// /// Get source port. /// public ushort SourcePort { get; private set; } /// /// Get UDP length. /// public ushort UDP_Length { get; private set; } /// /// Get UDP data lenght. /// public ushort UDP_DataLength => (ushort)(UDP_Length - 8); /// /// Get UDP data. /// /// Thrown on fatal error (contact support). internal byte[] UDP_Data { get { byte[] data = new byte[UDP_DataLength]; for (int b = 0; b < data.Length; b++) { data[b] = RawData[DataOffset + 8 + b]; } return data; } } /// /// To string. /// /// string value. public override string ToString() { return "UDP Packet Src=" + SourceIP + ":" + SourcePort + "," + "Dest=" + DestinationIP + ":" + DestinationPort + ", DataLen=" + UDP_DataLength; } } }