Next, add the Ipv6 header class.
public ref class Ipv6Header : ProtocolHeader { private: Byte ipVersion; Byte ipTrafficClass; unsigned int ipFlow; unsigned short ipPayloadLength; Byte ipNextHeader; Byte ipHopLimit; IPAddress^ ipSourceAddress; IPAddress^ ipDestinationAddress;
public: static int Ipv6HeaderLength = 40;
/// <summary> /// Simple constructor for the IPv6 header that initializes the fields to zero. /// </summary> public: Ipv6Header() { ipVersion = 6; ipTrafficClass = 0; ipFlow = 0; ipPayloadLength = 0; ipNextHeader = 0; ipHopLimit = 32; ipSourceAddress = IPAddress::IPv6Any; ipDestinationAddress = IPAddress::IPv6Any; }
/// <summary> /// Gets and sets the IP version. This value should be 6. /// </summary> public: property Byte Version { Byte get() { return ipVersion; } void set(Byte value) { ipVersion = value; } }
/// <summary> /// Gets and sets the traffic class for the header. /// </summary> public: property Byte TrafficClass { Byte get() { return ipTrafficClass; } void set(Byte value) { ipTrafficClass = value; } }
/// <summary> /// Gets and sets the flow value for the packet. Byte order conversion /// is required for this field. /// </summary> public: property unsigned int Flow { unsigned int get() { return (unsigned int)IPAddress::NetworkToHostOrder((int)ipFlow); } void set(unsigned int value) { ipFlow = (unsigned int)IPAddress::HostToNetworkOrder((int)value); } }
/// <summary> /// Gets and sets the payload length for the IPv6 packet. Note for IPv6, the /// payload length counts only the payload and not the IPv6 header (since /// the IPv6 header is a fixed length). Byte order conversion is required. /// </summary> public: property unsigned short PayloadLength { unsigned short get() { return (unsigned short)IPAddress::NetworkToHostOrder((short)ipPayloadLength); } void set(unsigned short value) { ipPayloadLength = (unsigned short)IPAddress::HostToNetworkOrder((short)value); } }
/// <summary> /// The protocol value of the header encapsulated by the IPv6 header. /// </summary> public: property Byte NextHeader { Byte get() { return ipNextHeader; } void set(Byte value) { ipNextHeader = value; } }
/// <summary> /// Time-to-live (TTL) of the IPv6 header. /// </summary> public: property Byte HopLimit { Byte get() { return ipHopLimit; } void set(Byte value) { ipHopLimit = value; } }
/// <summary> /// IPv6 source address in the IPv6 header. /// </summary> public: property IPAddress^ SourceAddress { IPAddress^ get() { return ipSourceAddress; } void set(IPAddress^ value) { ipSourceAddress = value; } }
/// <summary> /// IPv6 destination address in the IPv6 header. /// </summary> public: property IPAddress^ DestinationAddress { IPAddress^ get() { return ipDestinationAddress; } void set(IPAddress^ value) { ipDestinationAddress = value; } }
/// <summary> /// This routine creates an instance of the Ipv6Header 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="ipv6Packet">Byte array containing the binary IPv6 header</param> /// <param name="bytesCopied">Number of bytes used in header</param> /// <returns>Returns the Ipv6Header object created from the byte array</returns> public: static Ipv6Header^ Create(array<Byte>^ ipv6Packet, int bytesCopied) { Ipv6Header^ ipv6Header = gcnew Ipv6Header(); array<Byte>^ addressBytes = gcnew array<Byte>(16); unsigned int tempVal = 0, tempVal2 = 0;
// Ensure byte array is large enough to contain an IPv6 header if (ipv6Packet->Length < Ipv6Header::Ipv6HeaderLength) return nullptr;
tempVal = ipv6Packet[0]; tempVal = (tempVal >> 4) & 0xF; ipv6Header->ipVersion = (Byte)tempVal;
tempVal = ipv6Packet[0]; tempVal = (tempVal & 0xF) >> 4; ipv6Header->ipTrafficClass = (Byte)(tempVal | (unsigned int)((ipv6Packet[1] >> 4) & 0xF));
tempVal2 = ipv6Packet[1]; tempVal2 = (tempVal2 & 0xF) << 16; tempVal = ipv6Packet[2]; tempVal = tempVal << 8; ipv6Header->ipFlow = tempVal2 | tempVal | ipv6Packet[3];
ipv6Header->ipNextHeader = ipv6Packet[4]; ipv6Header->ipHopLimit = ipv6Packet[5];
Array::Copy(ipv6Packet, 6, addressBytes, 0, 16); ipv6Header->SourceAddress = gcnew IPAddress(addressBytes);
Array::Copy(ipv6Packet, 24, addressBytes, 0, 16); ipv6Header->DestinationAddress = gcnew IPAddress(addressBytes);
bytesCopied = Ipv6Header::Ipv6HeaderLength;
return ipv6Header; }
/// <summary> /// Packages up the IPv6 header and the given payload into a byte array /// suitable for sending on a socket. /// </summary> /// <param name="payLoad">Data encapsulated by the IPv6 header</param> /// <returns>Byte array of the IPv6 packet and payload</returns> public: virtual array<Byte>^ GetProtocolPacketBytes(array<Byte>^ payLoad) override { array<Byte>^ byteValue; array<Byte>^ ipv6Packet; int offset = 0;
ipv6Packet = gcnew array<Byte>(Ipv6HeaderLength + payLoad->Length); ipv6Packet[offset++] = (Byte)((ipVersion << 4) | ((ipTrafficClass >> 4) & 0xF));
// tmpbyte1 = (byte) ( ( ipTrafficClass << 4) & 0xF0); // tmpbyte2 = (byte) ( ( ipFlow >> 16 ) & 0xF );
ipv6Packet[offset++] = (Byte)((unsigned int)((ipTrafficClass << 4) & 0xF0) | (unsigned int)((Flow >> 16) & 0xF)); ipv6Packet[offset++] = (Byte)((Flow >> 8) & 0xFF); ipv6Packet[offset++] = (Byte)(Flow & 0xFF);
Console::WriteLine("Next header = {0}", ipNextHeader);
byteValue = BitConverter::GetBytes(ipPayloadLength); Array::Copy(byteValue, 0, ipv6Packet, offset, byteValue->Length); offset += byteValue->Length;
ipv6Packet[offset++] = (Byte)ipNextHeader; ipv6Packet[offset++] = (Byte)ipHopLimit;
byteValue = ipSourceAddress->GetAddressBytes(); Array::Copy(byteValue, 0, ipv6Packet, offset, byteValue->Length); offset += byteValue->Length;
byteValue = ipDestinationAddress->GetAddressBytes(); Array::Copy(byteValue, 0, ipv6Packet, offset, byteValue->Length); offset += byteValue->Length;
Array::Copy(payLoad, 0, ipv6Packet, offset, payLoad->Length);
return ipv6Packet; } }; |
Then add the Ipv6 fragment header definition class.
public ref class Ipv6FragmentHeader { private: Byte fragmentNextHeader; Byte fragmentReserved; unsigned short fragmentOffset; unsigned short fragmentId; public: static int Ipv6FragmentHeaderLength = 8;
/// <summary> /// Simple constructor that initializes the member properties. /// </summary> public: Ipv6FragmentHeader() { fragmentNextHeader = 0; fragmentReserved = 0; fragmentOffset = 0; fragmentId = 0; }
/// <summary> /// Gets and sets the next protocol value field. /// </summary> public: property Byte NextHeader { Byte get() { return fragmentNextHeader; } void set(Byte value) { fragmentNextHeader = value; } }
/// <summary> /// Gets and sets the reserved field. Performs the necessary byte order conversion. /// </summary> public: property Byte Reserved { Byte get() { return fragmentReserved; } void set(Byte value) { fragmentReserved = value; } }
/// <summary> /// Gets and sets the offset field. Performs the necessary byte order conversion. /// </summary> public: property unsigned short Offset { unsigned short get() { return (unsigned short)IPAddress::NetworkToHostOrder((short)fragmentOffset); } void set(unsigned short value) { fragmentOffset = (unsigned short)IPAddress::HostToNetworkOrder((short)value); } }
/// <summary> /// Gets and sets the id property. Performs the necessary byte order conversion. /// </summary> public: property unsigned int Id { unsigned int get() { return (unsigned int)IPAddress::NetworkToHostOrder((int)fragmentId); } void set(unsigned int value) { fragmentId = (unsigned int)IPAddress::HostToNetworkOrder((int)value); } } }; |