/* * PROJECT: Aura Operating System Development * CONTENT: ICMP Packet (to ping for exemple) * PROGRAMMERS: Valentin Charbonnier * Port of Cosmos Code. */ using System; namespace Cosmos.System.Network.IPv4 { /// /// ICMPPacket class. See also: . /// public class ICMPPacket : IPPacket { /// /// Packet type. /// protected byte icmpType; /// /// Packet code. /// protected byte icmpCode; /// /// Packet CRC. /// protected ushort icmpCRC; /// /// Received reply. /// /// /// Create new instance of the class. /// /// Packet data. /// Thrown if packetData is invalid. internal static void ICMPHandler(byte[] packetData) { Global.mDebugger.Send("ICMP Handler called"); var icmp_packet = new ICMPPacket(packetData); switch (icmp_packet.ICMPType) { case 0: var receiver = ICMPClient.GetClient(icmp_packet.SourceIP.Hash); if (receiver != null) { receiver.ReceiveData(icmp_packet); } Global.mDebugger.Send("Received ICMP Echo reply from " + icmp_packet.SourceIP.ToString()); break; case 8: var request = new ICMPEchoRequest(packetData); var reply = new ICMPEchoReply(request); Global.mDebugger.Send("Sending ICMP Echo reply to " + reply.DestinationIP.ToString()); OutgoingBuffer.AddPacket(reply); NetworkStack.Update(); break; } } /// /// Create new instance of the class. /// internal ICMPPacket() : base() { } /// /// Create new instance of the class. /// /// Raw data. internal ICMPPacket(byte[] rawData) : base(rawData) { } /// /// Init ICMPPacket fields.1 /// /// Thrown if RawData is invalid or null. protected override void InitFields() { //Sys.Console.WriteLine("ICMPPacket.InitFields() called;"); base.InitFields(); icmpType = RawData[DataOffset]; icmpCode = RawData[DataOffset + 1]; icmpCRC = (ushort)((RawData[DataOffset + 2] << 8) | RawData[DataOffset + 3]); } /// /// Create new instance of the class. /// /// Source address. /// Destination address. /// Type. /// Code. /// ID. /// SEQ. /// Data size. /// Thrown if RawData is invalid or null. internal ICMPPacket(Address source, Address dest, byte type, byte code, ushort id, ushort seq, ushort icmpDataSize) : base(icmpDataSize, 1, source, dest, 0x00) { RawData[DataOffset] = type; RawData[DataOffset + 1] = code; RawData[DataOffset + 2] = 0x00; RawData[DataOffset + 3] = 0x00; RawData[DataOffset + 4] = (byte)((id >> 8) & 0xFF); RawData[DataOffset + 5] = (byte)((id >> 0) & 0xFF); RawData[DataOffset + 6] = (byte)((seq >> 8) & 0xFF); RawData[DataOffset + 7] = (byte)((seq >> 0) & 0xFF); icmpCRC = CalcICMPCRC((ushort)(icmpDataSize)); RawData[DataOffset + 2] = (byte)((icmpCRC >> 8) & 0xFF); RawData[DataOffset + 3] = (byte)((icmpCRC >> 0) & 0xFF); InitFields(); } /// /// Calculate ICMP CRC3. /// /// Lenght. /// protected ushort CalcICMPCRC(ushort length) { return CalcOcCRC(DataOffset, length); } /// /// Get ICMP type. /// internal byte ICMPType => icmpType; /// /// Get ICMP code. /// internal byte ICMPCode => icmpCode; /// /// Get ICMP CRC. /// internal ushort ICMPCRC => icmpCRC; /// /// Get ICMP data length. /// internal ushort ICMPDataLength => (ushort)(DataLength - 8); /// /// Get ICMP data. /// /// byte array value. internal byte[] GetICMPData() { byte[] data = new byte[ICMPDataLength]; for (int b = 0; b < ICMPDataLength; b++) { data[b] = RawData[DataOffset + 8 + b]; } return data; } /// /// To string. /// /// string value. public override string ToString() { return "ICMP Packet Src=" + SourceIP + ", Dest=" + DestinationIP + ", Type=" + icmpType + ", Code=" + icmpCode; } } /// /// ICMPEchoRequest class. See also: . /// internal class ICMPEchoRequest : ICMPPacket { protected ushort icmpID; protected ushort icmpSequence; /// /// Create new instance of the class. /// internal ICMPEchoRequest() : base() { } /// /// Create new instance of the class. /// /// Raw data. internal ICMPEchoRequest(byte[] rawData) : base(rawData) { } /// /// Create new instance of the class. /// /// Source address. /// Destination address. /// ID. /// Sequence. /// Thrown if RawData is invalid or null. internal ICMPEchoRequest(Address source, Address dest, ushort id, ushort sequence) : base(source, dest, 8, 0, id, sequence, 40) { for (int b = 8; b < ICMPDataLength; b++) { RawData[DataOffset + b] = (byte)b; } RawData[DataOffset + 2] = 0x00; RawData[DataOffset + 3] = 0x00; icmpCRC = CalcICMPCRC((ushort)(ICMPDataLength + 8)); RawData[DataOffset + 2] = (byte)((icmpCRC >> 8) & 0xFF); RawData[DataOffset + 3] = (byte)((icmpCRC >> 0) & 0xFF); } /// /// Init ICMPPacket fields.1 /// /// Thrown if RawData is invalid or null. protected override void InitFields() { base.InitFields(); icmpID = (ushort)((RawData[DataOffset + 4] << 8) | RawData[DataOffset + 5]); icmpSequence = (ushort)((RawData[DataOffset + 6] << 8) | RawData[DataOffset + 7]); } /// /// Get ICMP ID. /// internal ushort ICMPID => icmpID; /// /// Get ICMP Sequence. /// internal ushort ICMPSequence => icmpSequence; /// /// To string. /// /// string value. public override string ToString() { return "ICMP Echo Request Src=" + SourceIP + ", Dest=" + DestinationIP + ", ID=" + icmpID + ", Sequence=" + icmpSequence; } } /// /// ICMPEchoReply class. See also: . /// internal class ICMPEchoReply : ICMPPacket { protected ushort icmpID; protected ushort icmpSequence; /// /// Create new instance of the class. /// internal ICMPEchoReply() : base() { } /// /// Create new instance of the class. /// /// Raw data. internal ICMPEchoReply(byte[] rawData) : base(rawData) { } /// /// Init ICMPEchoReply fields. /// /// Thrown if RawData is invalid or null. protected override void InitFields() { //Sys.Console.WriteLine("ICMPEchoReply.InitFields() called;"); base.InitFields(); icmpID = (ushort)((RawData[DataOffset + 4] << 8) | RawData[DataOffset + 5]); icmpSequence = (ushort)((RawData[DataOffset + 6] << 8) | RawData[DataOffset + 7]); } /// /// Create new instance of the class. /// /// ICMP echo request. /// Thrown if RawData is invalid or null. internal ICMPEchoReply(ICMPEchoRequest request) : base(request.DestinationIP, request.SourceIP, 0, 0, request.ICMPID, request.ICMPSequence, (ushort)(request.ICMPDataLength)) { for (int b = 0; b < ICMPDataLength; b++) { RawData[DataOffset + 8 + b] = request.RawData[DataOffset + 8 + b]; } RawData[DataOffset + 2] = 0x00; RawData[DataOffset + 3] = 0x00; icmpCRC = CalcICMPCRC((ushort)(ICMPDataLength + 8)); RawData[DataOffset + 2] = (byte)((icmpCRC >> 8) & 0xFF); RawData[DataOffset + 3] = (byte)((icmpCRC >> 0) & 0xFF); } /// /// Get ICMP ID. /// internal ushort ICMPID => icmpID; /// /// Get ICMP sequence. /// internal ushort ICMPSequence => icmpSequence; /// /// To string. /// /// string value. public override string ToString() { return "ICMP Echo Reply Src=" + SourceIP + ", Dest=" + DestinationIP + ", ID=" + icmpID + ", Sequence=" + icmpSequence; } } }