Next, add the Ipv6 header class.
class Ipv6Header : ProtocolHeader { private byte ipVersion; private byte ipTrafficClass; private uint ipFlow; private ushort ipPayloadLength; private byte ipNextHeader; private byte ipHopLimit; private IPAddress ipSourceAddress; private IPAddress ipDestinationAddress;
static public int Ipv6HeaderLength = 40;
/// <summary> /// Simple constructor for the IPv6 header that initializes the fields to zero. /// </summary> public Ipv6Header() : base() { 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 byte Version { get { return ipVersion; } set { ipVersion = value; } }
/// <summary> /// Gets and sets the traffic class for the header. /// </summary> public byte TrafficClass { get { return ipTrafficClass; } set { ipTrafficClass = value; } }
/// <summary> /// Gets and sets the flow value for the packet. Byte order conversion /// is required for this field. /// </summary> public uint Flow { get { return (uint)IPAddress.NetworkToHostOrder((int)ipFlow); } set { ipFlow = (uint)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 ushort PayloadLength { get { return (ushort)IPAddress.NetworkToHostOrder((short)ipPayloadLength); } set { ipPayloadLength = (ushort)IPAddress.HostToNetworkOrder((short)value); } }
/// <summary> /// The protocol value of the header encapsulated by the IPv6 header. /// </summary> public byte NextHeader { get { return ipNextHeader; } set { ipNextHeader = value; } }
/// <summary> /// Time-to-live (TTL) of the IPv6 header. /// </summary> public byte HopLimit { get { return ipHopLimit; } set { ipHopLimit = value; } }
/// <summary> /// IPv6 source address in the IPv6 header. /// </summary> public IPAddress SourceAddress { get { return ipSourceAddress; } set { ipSourceAddress = value; } }
/// <summary> /// IPv6 destination address in the IPv6 header. /// </summary> public IPAddress DestinationAddress { get { return ipDestinationAddress; } set { 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> static public Ipv6Header Create(byte[] ipv6Packet, ref int bytesCopied) { Ipv6Header ipv6Header = new Ipv6Header(); byte[ ] addressBytes = new byte[16]; uint tempVal = 0, tempVal2 = 0;
// Ensure byte array is large enough to contain an IPv6 header if (ipv6Packet.Length < Ipv6Header.Ipv6HeaderLength) return null;
tempVal = ipv6Packet[0]; tempVal = (tempVal >> 4) & 0xF; ipv6Header.ipVersion = (byte)tempVal;
tempVal = ipv6Packet[0]; tempVal = (tempVal & 0xF) >> 4; ipv6Header.ipTrafficClass = (byte)(tempVal | (uint)((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 = new IPAddress(addressBytes);
Array.Copy(ipv6Packet, 24, addressBytes, 0, 16); ipv6Header.DestinationAddress = new 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 override byte[ ] GetProtocolPacketBytes(byte[ ] payLoad) { byte[ ] byteValue, ipv6Packet; int offset = 0;
ipv6Packet = new 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)((uint)((ipTrafficClass << 4) & 0xF0) | (uint)((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.
class Ipv6FragmentHeader { private byte fragmentNextHeader; private byte fragmentReserved; private ushort fragmentOffset; private uint fragmentId; static public 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 byte NextHeader { get { return fragmentNextHeader; } set { fragmentNextHeader = value; } }
/// <summary> /// Gets and sets the reserved field. Performs the necessary byte order conversion. /// </summary> public byte Reserved { get { return fragmentReserved; } set { fragmentReserved = value; } }
/// <summary> /// Gets and sets the offset field. Performs the necessary byte order conversion. /// </summary> public ushort Offset { get { return (ushort)IPAddress.NetworkToHostOrder((short)fragmentOffset); } set { fragmentOffset = (ushort)IPAddress.HostToNetworkOrder((short)value); } }
/// <summary> /// Gets and sets the id property. Performs the necessary byte order conversion. /// </summary> public uint Id { get { return (uint)IPAddress.NetworkToHostOrder((int)fragmentId); } set { fragmentId = (uint)IPAddress.HostToNetworkOrder((int)value); } } } |