Next, add the ICMP for Ipv4 header definition class.
public ref class IcmpHeader : ProtocolHeader { private: Byte icmpType; // ICMP message type Byte icmpCode; // ICMP message code unsigned short icmpChecksum; // Checksum of ICMP header and payload unsigned short icmpId; // Message ID unsigned short icmpSequence; // ICMP sequence number
public: static Byte EchoRequestType = 8; // ICMP echo request static Byte EchoRequestCode = 0; // ICMP echo request code static Byte EchoReplyType = 0; // ICMP echo reply static Byte EchoReplyCode = 0; // ICMP echo reply code static int IcmpHeaderLength = 8; // Length of ICMP header
/// <summary> /// Default constructor for ICMP packet /// </summary> public: IcmpHeader() { icmpType = 0; icmpCode = 0; icmpChecksum = 0; icmpId = 0; icmpSequence = 0; }
/// <summary> /// ICMP message type. /// </summary> public: property Byte Type { Byte get() { return icmpType; } void set(Byte value) { icmpType = value; } }
/// <summary> /// ICMP message code. /// </summary> public: property Byte Code { Byte get() { return icmpCode; } void set(Byte value) { icmpCode = value; } }
/// <summary> /// Checksum of ICMP packet and payload. Performs the necessary byte order conversion. /// </summary> public: property unsigned short Checksum { unsigned short get() { return (unsigned short)IPAddress::NetworkToHostOrder((short)icmpChecksum); } void set(unsigned short value) { icmpChecksum = (unsigned short)IPAddress::HostToNetworkOrder((short)value); } }
/// <summary> /// ICMP message ID. Used to uniquely identify the source of the ICMP packet. /// Performs the necessary byte order conversion. /// </summary> public: property unsigned short Id { unsigned short get() { return (unsigned short)IPAddress::NetworkToHostOrder((short)icmpId); } void set(unsigned short value) { icmpId = (unsigned short)IPAddress::HostToNetworkOrder((short)value); } }
/// <summary> /// ICMP sequence number. As each ICMP message is sent the sequence should be incremented. /// Performs the necessary byte order conversion. /// </summary> public: property unsigned short Sequence { unsigned short get() { return (unsigned short)IPAddress::NetworkToHostOrder((short)icmpSequence); } void set(unsigned short value) { icmpSequence = (unsigned short)IPAddress::HostToNetworkOrder((short)value); } }
/// <summary> /// This routine creates an instance of the IcmpHeader class from a byte /// array that is a received IGMP packet. This is useful when a packet /// is received from the network and the header object needs to be /// constructed from those values. /// </summary> /// <param name="icmpPacket">Byte array containing the binary ICMP header</param> /// <param name="bytesCopied">Number of bytes used in header</param> /// <returns>Returns the IcmpHeader object created from the byte array</returns> public: static IcmpHeader^ Create(array<Byte>^ icmpPacket, int bytesCopied) { IcmpHeader^ icmpHeader = gcnew IcmpHeader(); int offset = 0;
// Make sure byte array is large enough to contain an ICMP header if (icmpPacket->Length < IcmpHeader::IcmpHeaderLength) return nullptr;
icmpHeader->icmpType = icmpPacket[offset++]; icmpHeader->icmpCode = icmpPacket[offset++]; icmpHeader->icmpChecksum = BitConverter::ToUInt16(icmpPacket, offset); offset += 2; icmpHeader->icmpId = BitConverter::ToUInt16(icmpPacket, offset); offset += 2; icmpHeader->icmpSequence = BitConverter::ToUInt16(icmpPacket, offset); bytesCopied = IcmpHeader::IcmpHeaderLength; return icmpHeader; }
/// <summary> /// This routine builds the ICMP packet suitable for sending on a raw socket. /// It builds the ICMP packet and payload into a byte array and computes /// the checksum. /// </summary> /// <param name="payLoad">Data payload of the ICMP packet</param> /// <returns>Byte array representing the ICMP packet and payload</returns> public: virtual array<Byte>^ GetProtocolPacketBytes(array<Byte>^ payLoad) override { array<Byte>^ icmpPacket; array<Byte>^ byteValue; int offset = 0;
icmpPacket = gcnew array<Byte>(IcmpHeaderLength + payLoad->Length); icmpPacket[offset++] = icmpType; icmpPacket[offset++] = icmpCode; icmpPacket[offset++] = 0; // Zero out the checksum until the packet is assembled icmpPacket[offset++] = 0;
byteValue = BitConverter::GetBytes(icmpId); Array::Copy(byteValue, 0, icmpPacket, offset, byteValue->Length); offset += byteValue->Length;
byteValue = BitConverter::GetBytes(icmpSequence); Array::Copy(byteValue, 0, icmpPacket, offset, byteValue->Length); offset += byteValue->Length;
if (payLoad->Length > 0) { Array::Copy(payLoad, 0, icmpPacket, offset, payLoad->Length); offset += payLoad->Length; }
// Compute the checksum over the entire packet Checksum = ComputeChecksum(icmpPacket);
// Put the checksum back into the packet byteValue = BitConverter::GetBytes(icmpChecksum); Array::Copy(byteValue, 0, icmpPacket, 2, byteValue->Length);
return icmpPacket; } }; |
Then, add the IGMP for Ipv4 header definition class.
public ref class IgmpHeader : ProtocolHeader { private: Byte igmpVersionType; Byte igmpMaxResponseTime; unsigned short igmpChecksum; IPAddress^ igmpGroupAddress; public: static int IgmpHeaderLength = 8; // IGMP message types v1 static Byte IgmpMembershipQuery = 0x11; static Byte IgmpMembershipReport = 0x12; // IGMP message types v2 static Byte IgmpMembershipReportV2 = 0x16; static Byte IgmpLeaveGroup = 0x17; // IGMP queries and responses are send to the all systems address static IPAddress^ AllSystemsAddress = IPAddress::Parse("224.0.0.1");
/// <summary> /// Simple constructor for the IGMP header that initializes the member fields. /// </summary> public: IgmpHeader() { igmpVersionType = IgmpMembershipQuery; igmpMaxResponseTime = 0; igmpChecksum = 0; igmpGroupAddress = IPAddress::Any; }
/// <summary> /// Sets both the version and type codes. Since the version and type codes /// are tied together there is only one property which sets both values. /// </summary> public: property Byte VersionType { Byte get() { return igmpVersionType; } void set(Byte value) { igmpVersionType = value; } }
/// <summary> /// The maximum response time for the IGMP query. /// </summary> public: property Byte MaximumResponseTime { Byte get() { return igmpMaxResponseTime; } void set(Byte value) { igmpMaxResponseTime = value; } }
/// <summary> /// The multicast group address for the IGMP message. /// </summary> public: property IPAddress^ GroupAddress { IPAddress^ get() { return igmpGroupAddress; } void set(IPAddress^ value) { igmpGroupAddress = value; } }
/// <summary> /// Checksum value for the IGMP packet and payload. /// </summary> public: property unsigned short Checksum { unsigned short get() { return (unsigned short)IPAddress::NetworkToHostOrder((short)igmpChecksum); } void set(unsigned short value) { igmpChecksum = (unsigned short)IPAddress::HostToNetworkOrder((short)value); } }
/// <summary> /// This routine creates an instance of the IgmpHeader class from a byte /// array that is a received IGMP packet. This is useful when a packet /// is received from the network and the header object needs to be /// constructed from those values. /// </summary> /// <param name="igmpPacket">Byte array containing the binary IGMP header</param> /// <param name="bytesCopied">Number of bytes used in header</param> /// <returns>Returns the IgmpHeader object created from the byte array</returns> public: static IgmpHeader^ Create(array<Byte>^ igmpPacket, int bytesCopied) { IgmpHeader^ igmpHeader = gcnew IgmpHeader(); int offset = 0;
// Verify byte array is large enough to contain IGMP header if (igmpPacket->Length < IgmpHeader::IgmpHeaderLength) return nullptr;
igmpHeader->igmpVersionType = igmpPacket[offset++]; igmpHeader->igmpMaxResponseTime = igmpPacket[offset++]; igmpHeader->igmpChecksum = BitConverter::ToUInt16(igmpPacket, offset);
bytesCopied = IgmpHeader::IgmpHeaderLength;
return igmpHeader; }
/// <summary> /// This routine creates the byte array representation of the IGMP packet as it /// would look on the wire. /// </summary> /// <param name="payLoad">Payload to copy after the IGMP header</param> /// <returns>Byte array representing the IGMP header and payload</returns> public: virtual array<Byte>^ GetProtocolPacketBytes(array<Byte>^ payLoad) override { array<Byte>^ igmpPacket; array<Byte>^ addressBytes; array<Byte>^ byteValue; int offset = 0;
igmpPacket = gcnew array<Byte>(IgmpHeaderLength + payLoad->Length); // Build the IGMP packet igmpPacket[offset++] = igmpVersionType; igmpPacket[offset++] = igmpMaxResponseTime; igmpPacket[offset++] = 0; // Zero the checksum for now igmpPacket[offset++] = 0;
// Copy the group address bytes addressBytes = igmpGroupAddress->GetAddressBytes(); Array::Copy(addressBytes, 0, igmpPacket, offset, addressBytes->Length); offset += addressBytes->Length;
// Copy the payload if specified. Normally, there is no payload to the IGMP // packet -- only the IGMP header. if (payLoad->Length > 0) { Array::Copy(payLoad, 0, igmpPacket, offset, payLoad->Length); offset += payLoad->Length; }
// Compute the checksum on the IGMP packet and payload Checksum = ComputeChecksum(igmpPacket);
// Put the checksum value into the packet byteValue = BitConverter::GetBytes(igmpChecksum); Array::Copy(byteValue, 0, igmpPacket, 2, byteValue->Length);
return igmpPacket; } }; |
< Adding Ipv6 & Ipv6 Fragment C++ Header Definition Classes 2 | Main | Adding ICMP For Ipv6 & For Ipv6 Echo Request C++ Classes 4 >