public static PCapPacket DecodeIP4(byte[] data, byte byVersionAndHeaderLength, int size, PCapPacket result = null)
 {
     using (var stream = new BinaryReader(new MemoryStream(data)))
     {
         return(DecodeIP4(stream, byVersionAndHeaderLength, size, result));
     }
 }
        public static PCapPacket DecodeIP4(BinaryReader stream, byte byVersionAndHeaderLength, int size, PCapPacket result = null)
        {
            if (result == null)
            {
                result = new PCapPacket();
            }

            //The next eight bits contain the Differentiated services
            var byDifferentiatedServices = stream.ReadByte();
            //Next eight bits hold the total length of the datagram
            var usTotalLength = (ushort)IPAddress.NetworkToHostOrder(stream.ReadInt16());
            //Next sixteen have the identification bytes
            var usIdentification = (ushort)IPAddress.NetworkToHostOrder(stream.ReadInt16());
            //Next sixteen bits contain the flags and fragmentation offset
            var usFlagsAndOffset = (ushort)IPAddress.NetworkToHostOrder(stream.ReadInt16());
            //Next eight bits have the TTL value
            var byTTL = stream.ReadByte();

            /*//Next eight represent the protocol encapsulated in the datagram
             * var byProtocol = stream.ReadByte();
             *
             * //Next sixteen bits contain the checksum of the header
             * var sChecksum = IPAddress.NetworkToHostOrder(stream.ReadInt16());
             *
             * //Next thirty two bits have the source IP address
             * var uiSourceIPAddress = (uint)(stream.ReadInt32());
             *
             * //Next thirty two hold the destination IP address
             * var uiDestinationIPAddress = (uint)(stream.ReadInt32());*/

            //Now we calculate the header length
            var byHeaderLength = byVersionAndHeaderLength;

            //The last four bits of the version and header length field contain the
            //header length, we perform some simple binary arithmetic operations to
            //extract them
            byHeaderLength <<= 4;
            byHeaderLength >>= 4;
            //Multiply by four to get the exact header length
            byHeaderLength *= 4;


            // Skip TCP/IP Header
            //stream.ReadBytes(9);
            var protocolType = stream.ReadByte();

            if (protocolType == 0x11) // UDP
            {
                stream.ReadBytes(2);  // Checksum
                result.IpSource        = stream.ReadBytes(4);
                result.IpDestination   = stream.ReadBytes(4);
                result.PortSource      = ReadBigEndianUInt16(stream);
                result.PortDestination = ReadBigEndianUInt16(stream);
                result.PacketType      = PCapPacketType.UDP;

                var udpLength = ReadBigEndianUInt16(stream) - 8;
                ReadBigEndianUInt16(stream); // Checksum
                result.Data = stream.ReadBytes(udpLength);
                // Skip to end
            }
            else if (protocolType == 0x6) // TCP
            {
                stream.ReadBytes(2);      // Checksum
                result.IpSource        = stream.ReadBytes(4);
                result.IpDestination   = stream.ReadBytes(4);
                result.PortSource      = ReadBigEndianUInt16(stream);
                result.PortDestination = ReadBigEndianUInt16(stream);
                result.PacketType      = PCapPacketType.TCP;

                result.SequenceNumber       = ReadBigEndianUInt32(stream);
                result.AcknowledgmentNumber = ReadBigEndianUInt32(stream);
                result.Flags = stream.ReadBytes(2);
                var windowSize = ReadBigEndianUInt16(stream);
                stream.ReadBytes(2); // checksum
                stream.ReadBytes(2); // urgent pointer
                var dataOffset = ((result.Flags[0] & 0b11110000) >> 4) * 4 - 20;

                if (dataOffset >= 0)
                {
                    stream.ReadBytes(dataOffset); // Skip offset
                    if (size - (38 + 16 + dataOffset) > 0)
                    {
                        result.Data = stream.ReadBytes(size - (38 + 16 + dataOffset));
                    }
                }
            }
            else
            {
                result.PacketType = PCapPacketType.Other;
            }
            return(result);
        }
        public static PCapPacket DecodeIP6(BinaryReader stream, byte byVersionAndHeaderLength, int size, PCapPacket result = null)
        {
            if (result == null)
            {
                result = new PCapPacket();
            }

            //The next eight bits contain the Differentiated services
            var byDifferentiatedServices = stream.ReadBytes(3);
            //Next eight bits hold the total length of the datagram
            var payloadLength = (ushort)IPAddress.NetworkToHostOrder(stream.ReadInt16());
            var nextHeader    = stream.ReadByte();
            var hopLimi       = stream.ReadByte();

            result.IpSource      = stream.ReadBytes(16);
            result.IpDestination = stream.ReadBytes(16);
            result.PacketType    = PCapPacketType.Other;

            while (nextHeader != 59)
            {
                switch (nextHeader)
                {
                case 60:                  // Destination options
                case 0:                   // Hop-by-hop
                    nextHeader = stream.ReadByte();
                    stream.ReadBytes(15); // Skip header
                    payloadLength -= 16;
                    break;

                case 43:                  // Routing
                    nextHeader = stream.ReadByte();
                    stream.ReadBytes(15); // Skip header
                    payloadLength -= 16;
                    break;

                case 44:                 // Fragment
                    nextHeader = stream.ReadByte();
                    stream.ReadBytes(7); // Skip header
                    payloadLength -= 8;
                    break;

                case 17:     // UDP
                    result.PacketType      = PCapPacketType.UDP;
                    result.PortSource      = ReadBigEndianUInt16(stream);
                    result.PortDestination = ReadBigEndianUInt16(stream);
                    var udpLength = ReadBigEndianUInt16(stream) - 8;
                    ReadBigEndianUInt16(stream);     // Checksum

                    result.Data = stream.ReadBytes(udpLength);
                    return(result);

                case 6:     // TCP
                    result.PortSource      = ReadBigEndianUInt16(stream);
                    result.PortDestination = ReadBigEndianUInt16(stream);
                    result.PacketType      = PCapPacketType.TCP;

                    result.SequenceNumber       = ReadBigEndianUInt32(stream);
                    result.AcknowledgmentNumber = ReadBigEndianUInt32(stream);
                    result.Flags = stream.ReadBytes(2);
                    var windowSize = ReadBigEndianUInt16(stream);
                    stream.ReadBytes(2);     // checksum
                    stream.ReadBytes(2);     // urgent pointer
                    var dataOffset = ((result.Flags[0] & 0b11110000) >> 4) * 4 - 20;

                    if (dataOffset >= 0)
                    {
                        stream.ReadBytes(dataOffset);     // Skip offset
                        if (payloadLength - (20 + dataOffset) > 0)
                        {
                            result.Data = stream.ReadBytes(payloadLength - (20 + dataOffset));
                        }
                    }
                    return(result);

                default:
                    nextHeader = 59;     // No next
                    break;
                }
            }
            return(result);
        }