/// /// David Bond 1/18/2009 /// Mokon@Mokon.Net /// www.Mokon.Net /// License /// Distributed under the Mozilla Public License /// http://www.mozilla.org/NPL/MPL-1.1.txt /// using System; using System.IO; using AnsiEscapeSequences_Fields = SharpPcap.Packets.Util.AnsiEscapeSequences_Fields; using ArrayHelper = SharpPcap.Packets.Util.ArrayHelper; using Timeval = SharpPcap.Packets.Util.Timeval; namespace SharpPcap.Packets { /// /// This is a implementation of the IPv6 Layer as an object for use with the SharpPcap library. /// /// References /// ---------- /// http://tools.ietf.org/html/rfc2460 /// http://en.wikipedia.org/wiki/IPv6 /// public class IPv6Packet : EthernetPacket { public static int ipVersion = 6; /// /// Constructor with a byte array and the size of the link layer. /// /// The link layer size /// A byte array. public IPv6Packet( int lLen, byte[] bytes ) : base( lLen, bytes ) { } /// /// Constructor with a byte array, a time value, and the size of the link layer. /// /// The link layer size. /// A byte array. /// A time value. public IPv6Packet( int lLen, byte[] bytes, Timeval tv ) : this( lLen, bytes ) { this._timeval = tv; } /// /// TODO No Idea what this is for. /// public override void OnOffsetChanged( ) { base.OnOffsetChanged( ); _ipv6Offset = _ethOffset + IPv6Fields_Fields.IPv6_HEADER_LEN; } /// /// The start of the ipv6 packet. /// protected internal int _ipv6Offset; /// /// The version field of the IPv6 Packet. /// public int IPv6Version { get { return (ArrayHelper.extractInteger(Bytes, _ethOffset + IPv6Fields_Fields.LINE_ONE_POS, IPv6Fields_Fields.LINE_ONE_LEN ) >> 28 ) & 0x0F; } set { ulong org = ((ulong)ArrayHelper.extractLong(Bytes, _ethOffset + IPv6Fields_Fields.LINE_ONE_POS, IPv6Fields_Fields.LINE_ONE_LEN ) & 0x0FFFFFFF ) | ( ( ( (ulong)value ) << 28 ) & 0xF0000000 ); ArrayHelper.insertLong(Bytes, (long)org, _ethOffset + IPv6Fields_Fields.LINE_ONE_POS, 4); } } /// /// The version field of the IPv6 Packet. Delgates to IPv6Version so maybe overridden. /// public virtual int Version { get { return IPv6Version; } set { IPv6Version = value; } } /// /// The traffic class field of the IPv6 Packet. /// public virtual int TrafficClass { get { return (ArrayHelper.extractInteger(Bytes, _ethOffset + IPv6Fields_Fields.LINE_ONE_POS, IPv6Fields_Fields.LINE_ONE_LEN ) >> 20 ) & 0xFF; } set { ulong org = ((ulong)ArrayHelper.extractLong(Bytes, _ethOffset + IPv6Fields_Fields.LINE_ONE_POS, IPv6Fields_Fields.LINE_ONE_LEN ) & 0xF00FFFFF ) | ( ( ( (ulong)value ) << 20 ) & 0x0FF00000 ); ArrayHelper.insertLong(Bytes, (long)org, _ethOffset + IPv6Fields_Fields.LINE_ONE_POS, 4); } } /// /// The flow label field of the IPv6 Packet. /// public virtual int FlowLabel { get { return ArrayHelper.extractInteger(Bytes, _ethOffset + IPv6Fields_Fields.LINE_ONE_POS, IPv6Fields_Fields.LINE_ONE_LEN ) & 0xFFFFF; } set { ulong org = ((ulong)ArrayHelper.extractLong(Bytes, _ethOffset + IPv6Fields_Fields.LINE_ONE_POS, IPv6Fields_Fields.LINE_ONE_LEN ) & 0xFFF00000 ) | ( ( (ulong)value ) & 0x000FFFFF ); ArrayHelper.insertLong(Bytes, (long)org, _ethOffset + IPv6Fields_Fields.LINE_ONE_POS, 4); } } /// /// The payload lengeth field of the IPv6 Packet /// NOTE: Differs from the IPv4 'Total length' field that includes the length of the header as /// payload length is ONLY the size of the payload. /// public virtual int IPPayloadLength { get { return ArrayHelper.extractInteger(Bytes, _ethOffset + IPv6Fields_Fields.PAYLOAD_LENGTH_POS, IPv6Fields_Fields.PAYLOAD_LENGTH_LEN ); } set { ArrayHelper.insertLong(Bytes, value, _ethOffset + IPv6Fields_Fields.PAYLOAD_LENGTH_POS, IPv6Fields_Fields.PAYLOAD_LENGTH_LEN ); } } /// /// The next header field of the IPv6 Packet. /// /// Replaces IPv4's 'protocol' field, has compatible values /// public virtual IPProtocol.IPProtocolType NextHeader { get { return (IPProtocol.IPProtocolType)ArrayHelper.extractInteger(Bytes, _ethOffset + IPv6Fields_Fields.NEXT_HEADER_POS, IPv6Fields_Fields.NEXT_HEADER_LEN ); } set { Bytes[_ethOffset + IPv6Fields_Fields.NEXT_HEADER_POS] = (byte)value; } } /// /// The hop limit field of the IPv6 Packet. /// NOTE: Replaces the 'time to live' field of IPv4 /// /// 8-bit value /// public virtual int HopLimit { get { return ArrayHelper.extractInteger(Bytes, _ethOffset + IPv6Fields_Fields.HOP_LIMIT_POS, IPv6Fields_Fields.HOP_LIMIT_LEN ); } set { Bytes[_ethOffset + IPv6Fields_Fields.HOP_LIMIT_POS] = (byte)value; } } /// /// The source address field of the IPv6 Packet. /// public virtual System.Net.IPAddress SourceAddress { get { return IPPacket.GetIPAddress(System.Net.Sockets.AddressFamily.InterNetworkV6, _ethOffset + IPv6Fields_Fields.SRC_ADDRESS_POS, Bytes); } set { byte[] address = value.GetAddressBytes(); System.Array.Copy(address, 0, Bytes, _ethOffset + IPv6Fields_Fields.SRC_ADDRESS_POS, address.Length); } } /// /// The destination address field of the IPv6 Packet. /// public virtual System.Net.IPAddress DestinationAddress { get { return IPPacket.GetIPAddress(System.Net.Sockets.AddressFamily.InterNetworkV6, _ethOffset + IPv6Fields_Fields.DST_ADDRESS_POS, Bytes); } set { byte[] address = value.GetAddressBytes(); System.Array.Copy(address, 0, Bytes, _ethOffset + IPv6Fields_Fields.DST_ADDRESS_POS, address.Length); } } /// /// Returns the bytes of the IPv6 Header. /// public virtual byte[] IPv6Header { get { return PacketEncoding.extractHeader(_ethOffset, IPv6Fields_Fields.IPv6_HEADER_LEN, Bytes); } } /// /// Returns the bytes of the IPv6 Header. /// override public byte[] Header { get { return IPv6Header; } } /// /// Returns the IP data. /// virtual public byte[] IPData { get { return PacketEncoding.extractData(_ethOffset, IPv6Fields_Fields.IPv6_HEADER_LEN, Bytes, IPPayloadLength ); } } /// /// Returns the IP data. /// public override byte[] Data { get { return IPData; } } // Prepend to the given byte[] origHeader the portion of the IPv6 header used for // generating an tcp checksum // // http://en.wikipedia.org/wiki/Transmission_Control_Protocol#TCP_checksum_using_IPv6 // http://tools.ietf.org/html/rfc2460#page-27 protected internal virtual byte[] AttachPseudoIPHeader(byte[] origHeader) { MemoryStream ms = new MemoryStream(); BinaryWriter bw = new BinaryWriter(ms); // 0-16: ip src addr bw.Write(Bytes, _ethOffset + IPv6Fields_Fields.SRC_ADDRESS_POS, IPv6Fields_Fields.SRC_ADDRESS_LEN); // 17-32: ip dst addr bw.Write(Bytes, _ethOffset + IPv6Fields_Fields.DST_ADDRESS_POS, IPv6Fields_Fields.DST_ADDRESS_LEN); // 33-36: TCP length bw.Write( (UInt32) SharpPcap.Util.IPUtil.Hton( origHeader.Length ) ); // 37-39: 3 bytes of zeros bw.Write((byte)0); bw.Write((byte)0); bw.Write((byte)0); // 40: Next header bw.Write((byte)NextHeader); // prefix the pseudoHeader to the header+data byte[] header = ms.ToArray(); int headerSize = header.Length + origHeader.Length; bool odd = origHeader.Length % 2 != 0; if (odd) headerSize++; byte[] finalData = new byte[headerSize]; // copy the pseudo header in Array.Copy(header, 0, finalData, 0, header.Length); // copy the origHeader in Array.Copy(origHeader, 0, finalData, header.Length, origHeader.Length); //if not even length, pad with a zero if (odd) finalData[finalData.Length - 1] = 0; return finalData; } /// /// Converts the packet to a string. /// /// public override String ToString( ) { return base.ToString( ) + "\r\nIPv6 Packet [\r\n" + "\tIPv6 Source Address: " + SourceAddress.ToString() + ", \r\n" + "\tIPv6 Destination Address: " + DestinationAddress.ToString() + "\r\n" + "]"; // TODO Implement Better ToString } /// Generate string with contents describing this IP packet. /// whether or not the string should contain ansi /// color escape sequences. /// public override System.String ToColoredString(bool colored) { System.Text.StringBuilder buffer = new System.Text.StringBuilder(); buffer.Append('['); if (colored) buffer.Append(Color); buffer.Append("IPv6Packet"); if (colored) buffer.Append(AnsiEscapeSequences_Fields.RESET); buffer.Append(": "); buffer.Append(SourceAddress + " -> " + DestinationAddress); buffer.Append(" next header=" + NextHeader); buffer.Append(" l=" + this.IPPayloadLength); buffer.Append(" sum=" + this.IPPayloadLength); buffer.Append(']'); // append the base class output buffer.Append(base.ToColoredString(colored)); return buffer.ToString(); } /// Convert this IP packet to a more verbose string. public override System.String ToColoredVerboseString(bool colored) { throw new System.NotImplementedException(); } /// /// Converts the packet to a color string. TODO add a method for colored to string. /// override public String Color { get { return AnsiEscapeSequences_Fields.WHITE; } } } }