Esempio n. 1
0
        /// <summary>
        ///     Attempts to parse raw data into a structured packet
        /// </summary>
        /// <param name="buffer">Raw data to parse</param>
        /// <param name="packet">Parsed packet</param>
        /// <param name="count">The length of the packet in bytes</param>
        /// <param name="index">The index into the buffer at which the packet begins</param>
        /// <returns>True if parsing was successful, false if it is not.</returns>
        internal static bool TryParse(byte[] buffer, int index, int count, out ICMP packet)
        {
            try
            {
                if (count < MinimumParseableBytes)
                {
                    packet = null;
                    return(false);
                }

                using (var ms = new MemoryStream(buffer, index, count, false))
                {
                    using (var br = new BinaryReader(ms))
                    {
                        packet          = new ICMP();
                        packet.Type     = br.ReadByte();
                        packet.Code     = br.ReadByte();
                        packet.Checksum = ByteOrder.NetworkToHostOrder(br.ReadUInt16());
                        packet.ID       = ByteOrder.NetworkToHostOrder(br.ReadUInt16());
                        packet.Sequence = ByteOrder.NetworkToHostOrder(br.ReadUInt16());
                        packet.Data     = br.ReadBytes(count - 8);

                        return(true);
                    }
                }
            }
            catch (Exception)
            {
                packet = null;
                return(false);
            }
        }
Esempio n. 2
0
        /// <summary>
        ///     Attempts to parse raw data into a structured packet
        /// </summary>
        /// <param name="buffer">Raw data to parse</param>
        /// <param name="packet">Parsed packet</param>
        /// <param name="count">The length of the packet in bytes</param>
        /// <param name="index">The index into the buffer at which the packet begins</param>
        /// <returns>True if parsing was successful, false if it is not.</returns>
        internal static bool TryParse(byte[] buffer, int index, int count, out ARP packet)
        {
            try
            {
                if (count < MinimumParseableBytes)
                {
                    packet = null;
                    return(false);
                }

                using (var ms = new MemoryStream(buffer, index, count, false))
                {
                    using (var br = new BinaryReader(ms))
                    {
                        packet           = new ARP();
                        packet.HType     = ByteOrder.NetworkToHostOrder(br.ReadUInt16());
                        packet.PType     = ByteOrder.NetworkToHostOrder(br.ReadUInt16());
                        packet.HLen      = br.ReadByte();
                        packet.PLen      = br.ReadByte();
                        packet.Operation = ByteOrder.NetworkToHostOrder(br.ReadUInt16());
                        if (count < 6 + packet.HLen * 2 + packet.PLen * 2)
                        {
                            packet.SenderHardwareAddress = new byte[packet.HLen];
                            packet.SenderProtocolAddress = new byte[packet.PLen];
                            packet.TargetHardwareAddress = new byte[packet.HLen];
                            packet.TargetProtocolAddress = new byte[packet.PLen];
                        }
                        else
                        {
                            packet.SenderHardwareAddress = br.ReadBytes(packet.HLen);
                            packet.SenderProtocolAddress = br.ReadBytes(packet.PLen);
                            packet.TargetHardwareAddress = br.ReadBytes(packet.HLen);
                            packet.TargetProtocolAddress = br.ReadBytes(packet.PLen);
                        }

                        return(true);
                    }
                }
            }
            catch (Exception)
            {
                packet = null;
                return(false);
            }
        }
        /// <summary>
        ///     Attempts to parse raw data into a structured packet
        /// </summary>
        /// <param name="buffer">Raw data to parse</param>
        /// <param name="packet">Parsed packet</param>
        /// <param name="count">The length of the packet in bytes</param>
        /// <param name="index">The index into the buffer at which the packet begins</param>
        /// <returns>True if parsing was successful, false if it is not.</returns>
        internal static bool TryParse(byte[] buffer, int index, int count, out EapolKey packet)
        {
            try
            {
                if (count < MinimumParseableBytes)
                {
                    packet = null;
                    return(false);
                }

                using (var ms = new MemoryStream(buffer, index, count, false))
                {
                    using (var br = new BinaryReader(ms))
                    {
                        packet = new EapolKey();
                        packet.KeyDescriptorType = br.ReadByte();
                        packet.KeyInformation    = ByteOrder.NetworkToHostOrder(br.ReadUInt16());
                        packet.KeyLength         = ByteOrder.NetworkToHostOrder(br.ReadUInt16());
                        packet.ReplayCounter     = br.ReadBytes(8);
                        packet.Nonce             = br.ReadBytes(32);
                        packet.IV      = br.ReadBytes(16);
                        packet.RSC     = br.ReadBytes(8);
                        packet.ID      = br.ReadBytes(8);
                        packet.MIC     = br.ReadBytes(16);
                        packet.DataLen = ByteOrder.NetworkToHostOrder(br.ReadUInt16());
                        packet.Data    = br.ReadBytes((int)(count - br.BaseStream.Position));

                        return(true);
                    }
                }
            }
            catch (Exception)
            {
                packet = null;
                return(false);
            }
        }
Esempio n. 4
0
        /// <summary>
        ///     Attempts to parse raw data into a structured packet
        /// </summary>
        /// <param name="buffer">Raw data to parse</param>
        /// <param name="packet">Parsed packet</param>
        /// <param name="count">The length of the packet in bytes</param>
        /// <param name="index">The index into the buffer at which the packet begins</param>
        /// <returns>True if parsing was successful, false if it is not.</returns>
        internal static bool TryParse(byte[] buffer, int index, int count, out SNAP packet)
        {
            try
            {
                if (count < MinimumParseableBytes)
                {
                    packet = null;
                    return(false);
                }

                using (var ms = new MemoryStream(buffer, index, count, false))
                {
                    using (var br = new BinaryReader(ms))
                    {
                        var organizationCode = br.ReadBytes(3);
                        var etherType        = ByteOrder.NetworkToHostOrder(br.ReadUInt16());

                        packet = null;
                        if (organizationCode[0] == 0 && organizationCode[1] == 0 && organizationCode[2] == 0)
                        {
                            switch (etherType)
                            {
                            case (ushort)EtherTypes.IPv4:
                            {
                                IPv4 payload;
                                if (IPv4.TryParse(
                                        buffer,
                                        index + (int)br.BaseStream.Position,
                                        (int)(count - br.BaseStream.Position),
                                        out payload))
                                {
                                    packet = new SNAP <IPv4> {
                                        Payload = payload
                                    };
                                }
                            }
                            break;

                            case (ushort)EtherTypes.ARP:
                            {
                                ARP payload;
                                if (ARP.TryParse(
                                        buffer,
                                        index + (int)br.BaseStream.Position,
                                        (int)(count - br.BaseStream.Position),
                                        out payload))
                                {
                                    packet = new SNAP <ARP> {
                                        Payload = payload
                                    };
                                }
                            }
                            break;

                            case (ushort)EtherTypes.EAPoLAN:
                            {
                                IEEE802_1x payload;
                                if (IEEE802_1x.TryParse(
                                        buffer,
                                        index + (int)br.BaseStream.Position,
                                        (int)(count - br.BaseStream.Position),
                                        out payload))
                                {
                                    packet = new SNAP <IEEE802_1x> {
                                        Payload = payload
                                    };
                                }
                            }
                            break;
                            }
                        }

                        if (packet == null)
                        {
                            Generic payload;
                            Generic.TryParse(
                                buffer,
                                index + (int)br.BaseStream.Position,
                                (int)(count - br.BaseStream.Position),
                                out payload);

                            // This can never fail, so I'm not checking the output
                            packet = new SNAP <Generic> {
                                Payload = payload
                            };
                        }

                        packet.OrganizationCode = organizationCode;
                        packet.ProtocolID       = etherType;

                        return(true);
                    }
                }
            }
            catch (Exception)
            {
                packet = null;
                return(false);
            }
        }
Esempio n. 5
0
        /// <summary>
        ///     Attempts to parse raw data into a structured packet
        /// </summary>
        /// <param name="buffer">Raw data to parse</param>
        /// <param name="packet">Parsed packet</param>
        /// <param name="count">The length of the packet in bytes</param>
        /// <param name="index">The index into the buffer at which the packet begins</param>
        /// <returns>True if parsing was successful, false if it is not.</returns>
        internal static bool TryParse(byte[] buffer, int index, int count, out IPv4 packet)
        {
            try
            {
                if (count < MinimumParseableBytes)
                {
                    packet = null;
                    return(false);
                }

                using (var ms = new MemoryStream(buffer, index, count, false))
                {
                    using (var br = new BinaryReader(ms))
                    {
                        var versionAndHeaderLen = br.ReadByte();
                        var version             = versionAndHeaderLen >> 4;
                        var headerLength        = versionAndHeaderLen & 0x0F;

                        var differentiatedServices = br.ReadByte();
                        var totalLength            = ByteOrder.NetworkToHostOrder(br.ReadUInt16());
                        var id = ByteOrder.NetworkToHostOrder(br.ReadUInt16());
                        var flagsAndFragOff = new BitVector32(ByteOrder.NetworkToHostOrder(br.ReadUInt16()));
                        var ttl             = br.ReadByte();
                        var protocol        = br.ReadByte();
                        var headerChecksum  = ByteOrder.NetworkToHostOrder(br.ReadUInt16());
                        var sourceAddress   = new IPv4Address(br.ReadBytes(4));
                        var destAddress     = new IPv4Address(br.ReadBytes(4));

                        if (headerLength == 0 || (headerLength * 32 / 8 > count))
                        {
                            // Specified header length is larger than available bytes
                            packet = null;
                            return(false);
                        }

                        byte[] optionsAndPadding;
                        if (headerLength * 32 / 8 < br.BaseStream.Position)
                        {
                            optionsAndPadding = br.ReadBytes(headerLength * 32 / 8 - (int)br.BaseStream.Position);
                        }
                        else
                        {
                            optionsAndPadding = Array.Empty <byte>();
                        }

                        br.BaseStream.Seek(headerLength * 32 / 8, SeekOrigin.Begin);

                        // TODO: Accept option for IgnoreLength
                        int payloadLength;
                        if (true /*IgnoreLength*/)
                        {
                            payloadLength = count - (int)br.BaseStream.Position;
                        }

                        /*else
                         * {
                         *  payloadLength = (totalLength - (headerLength * 32 / 8)
                         * }*/

                        packet = null;

                        switch (protocol)
                        {
                        case (byte)Protocols.UDP:
                        {
                            UDP payload;
                            if (UDP.TryParse(
                                    buffer,
                                    index + (int)br.BaseStream.Position,
                                    payloadLength,
                                    out payload))
                            {
                                packet = new IPv4 <UDP> {
                                    Payload = payload
                                };
                            }
                        }

                        break;

                        case (byte)Protocols.ICMP:
                        {
                            ICMP payload;
                            if (ICMP.TryParse(
                                    buffer,
                                    index + (int)br.BaseStream.Position,
                                    payloadLength,
                                    out payload))
                            {
                                packet = new IPv4 <ICMP> {
                                    Payload = payload
                                };
                            }
                        }

                        break;

                        case (byte)Protocols.TCP:
                        {
                            TCP payload;
                            if (TCP.TryParse(
                                    buffer,
                                    index + (int)br.BaseStream.Position,
                                    payloadLength,
                                    out payload))
                            {
                                packet = new IPv4 <TCP> {
                                    Payload = payload
                                };
                            }
                        }
                        break;
                        }

                        if (packet == null)
                        {
                            Generic payload;
                            Generic.TryParse(buffer, index + (int)br.BaseStream.Position, payloadLength, out payload);
                            // This can never fail, so I'm not checking the output
                            packet = new IPv4 <Generic> {
                                Payload = payload
                            };
                        }

                        packet.Version                = version;
                        packet.HeaderLength           = headerLength;
                        packet.DifferentiatedServices = differentiatedServices;
                        packet.TotalLength            = totalLength;
                        packet.ID = id;
                        packet.FlagsAndFragOff   = flagsAndFragOff;
                        packet.TTL               = ttl;
                        packet.Protocol          = protocol;
                        packet.HeaderChecksum    = headerChecksum;
                        packet.SourceAddress     = sourceAddress;
                        packet.DestAddress       = destAddress;
                        packet.OptionsAndPadding = optionsAndPadding;

                        return(true);
                    }
                }
            }
            catch (Exception)
            {
                packet = null;
                return(false);
            }
        }
        /// <summary>
        ///     Attempts to parse raw data into a structured packet
        /// </summary>
        /// <param name="buffer">Raw data to parse</param>
        /// <param name="packet">Parsed packet</param>
        /// <param name="count">The length of the packet in bytes</param>
        /// <param name="index">The index into the buffer at which the packet begins</param>
        /// <returns>True if parsing was successful, false if it is not.</returns>
        internal static bool TryParse(byte[] buffer, int index, int count, out IEEE802_1x packet)
        {
            try
            {
                if (count < MinimumParseableBytes)
                {
                    packet = null;
                    return(false);
                }

                using (var ms = new MemoryStream(buffer, index, count, false))
                {
                    using (var br = new BinaryReader(ms))
                    {
                        var version    = br.ReadByte();
                        var type       = br.ReadByte();
                        var bodyLength = ByteOrder.NetworkToHostOrder(br.ReadUInt16());

                        var payloadLength = Math.Min(bodyLength, (int)(count - br.BaseStream.Position));

                        packet = null;

                        switch (type)
                        {
                        case (byte)Types.EAPOL_KEY:
                        {
                            EapolKey payload;
                            if (EapolKey.TryParse(
                                    buffer,
                                    index + (int)br.BaseStream.Position,
                                    payloadLength,
                                    out payload))
                            {
                                packet = new IEEE802_1x <EapolKey> {
                                    Payload = payload
                                };
                            }
                        }
                        break;
                        }

                        if (packet == null)
                        {
                            Generic payload;
                            Generic.TryParse(
                                buffer,
                                index + (int)br.BaseStream.Position,
                                (int)(count - br.BaseStream.Position),
                                out payload);

                            // This can never fail, so I'm not checking the output
                            packet = new IEEE802_1x <Generic> {
                                Payload = payload
                            };
                        }

                        packet.Version    = version;
                        packet.Type       = type;
                        packet.BodyLength = bodyLength;

                        return(true);
                    }
                }
            }
            catch (Exception)
            {
                packet = null;
                return(false);
            }
        }
Esempio n. 7
0
        /// <summary>
        ///     Attempts to parse raw data into a structured packet
        /// </summary>
        /// <param name="buffer">Raw data to parse</param>
        /// <param name="packet">Parsed packet</param>
        /// <param name="count">The length of the packet in bytes</param>
        /// <param name="index">The index into the buffer at which the packet begins</param>
        /// <returns>True if parsing was successful, false if it is not.</returns>
        internal static bool TryParse(byte[] buffer, int index, int count, out TCP packet)
        {
            try
            {
                if (count < MinimumParseableBytes)
                {
                    packet = null;
                    return(false);
                }

                using (var ms = new MemoryStream(buffer, index, count, false))
                {
                    using (var br = new BinaryReader(ms))
                    {
                        var    sourcePort            = ByteOrder.NetworkToHostOrder(br.ReadUInt16());
                        var    destPort              = ByteOrder.NetworkToHostOrder(br.ReadUInt16());
                        var    seqNumber             = ByteOrder.NetworkToHostOrder(br.ReadUInt32());
                        var    ackNumber             = ByteOrder.NetworkToHostOrder(br.ReadUInt32());
                        var    dataOffsetAndReserved = br.ReadByte();
                        var    dataOffset            = dataOffsetAndReserved >> 4;
                        var    reserved              = dataOffsetAndReserved & 0x0F;
                        var    flags             = new BitVector32(br.ReadByte());
                        var    windowSize        = ByteOrder.NetworkToHostOrder(br.ReadUInt16());
                        var    checksum          = ByteOrder.NetworkToHostOrder(br.ReadUInt16());
                        var    urgentPointer     = ByteOrder.NetworkToHostOrder(br.ReadUInt16());
                        byte[] optionsAndPadding = null;

                        if (dataOffset > 5)
                        {
                            if (br.BaseStream.Position + (dataOffset - 5) * 4 > count)
                            {
                                // throw new ArgumentException("Header specifies more bytes than available");
                                packet = null;
                                return(false);
                            }
                            optionsAndPadding = br.ReadBytes((dataOffset - 5) * 4);
                        }

                        Generic payload;
                        Generic.TryParse(
                            buffer,
                            index + (int)br.BaseStream.Position,
                            count - dataOffset * 32 / 8,
                            out payload);
                        // This can never fail, so I'm not checking the output
                        var newPacket = new TCP <Generic>();
                        newPacket.Payload = payload;
                        packet            = newPacket;

                        packet.SourcePort        = sourcePort;
                        packet.DestPort          = destPort;
                        packet.SeqNumber         = seqNumber;
                        packet.AckNumber         = ackNumber;
                        packet.DataOffset        = dataOffset;
                        packet.Reserved          = reserved;
                        packet.Flags             = flags;
                        packet.WindowSize        = windowSize;
                        packet.Checksum          = checksum;
                        packet.UrgentPointer     = urgentPointer;
                        packet.OptionsAndPadding = optionsAndPadding ?? Array.Empty <byte>();

                        return(true);
                    }
                }
            }
            catch (Exception)
            {
                packet = null;
                return(false);
            }
        }
Esempio n. 8
0
        /// <summary>
        ///     Attempts to parse raw data into a structured packet
        /// </summary>
        /// <param name="buffer">Raw data to parse</param>
        /// <param name="packet">Parsed packet</param>
        /// <param name="count">The length of the packet in bytes</param>
        /// <param name="index">The index into the buffer at which the packet begins</param>
        /// <returns>True if parsing was successful, false if it is not.</returns>
        internal static bool TryParse(byte[] buffer, int index, int count, out IEEE802_11 packet)
        {
            try
            {
                if (count < MinimumParseableBytes)
                {
                    packet = null;
                    return(false);
                }

                using (var ms = new MemoryStream(buffer, index, count, false))
                {
                    using (var br = new BinaryReader(ms))
                    {
                        var frameControlVersionTypeAndSubtype = new BitVector32(br.ReadByte());
                        var frameControlFlags = new BitVector32(br.ReadByte());
                        var durationID        = br.ReadUInt16();

                        var toDS   = frameControlFlags[1];
                        var fromDS = frameControlFlags[2];

                        byte[] destination;
                        byte[] source;
                        byte[] bssid;
                        byte[] receiver    = null;
                        byte[] transmitter = null;
                        UInt16 sequenceControl;

                        if (!toDS)
                        {
                            destination = br.ReadBytes(6);

                            if (!fromDS)
                            {
                                source = br.ReadBytes(6);
                                bssid  = br.ReadBytes(6);
                            }
                            else
                            {
                                bssid  = br.ReadBytes(6);
                                source = br.ReadBytes(6);
                            }
                            sequenceControl = br.ReadUInt16(); //Was NTHO, wireshark disagrees
                        }
                        else
                        {
                            if (!fromDS)
                            {
                                bssid           = br.ReadBytes(6);
                                source          = br.ReadBytes(6);
                                destination     = br.ReadBytes(6);
                                sequenceControl = br.ReadUInt16(); //Was NTHO, wireshark disagrees
                            }
                            else
                            {
                                receiver        = br.ReadBytes(6);
                                transmitter     = br.ReadBytes(6);
                                bssid           = transmitter;     //Per airdecap-ng
                                destination     = br.ReadBytes(6);
                                sequenceControl = br.ReadUInt16(); //Was NTHO, wireshark disagrees
                                source          = br.ReadBytes(6);
                            }
                        }

                        var frameType =
                            frameControlVersionTypeAndSubtype[BitVector32.CreateSection(3, BitVector32.CreateSection(3))
                            ];
                        var subType =
                            frameControlVersionTypeAndSubtype[
                                BitVector32.CreateSection(15, BitVector32.CreateSection(15))];

                        byte[] qosControl = null;
                        if (frameType == (int)FrameTypes.Data && subType == (int)DataSubTypes.QoS)
                        {
                            qosControl = br.ReadBytes(2);
                        }

                        var    isProtected   = frameControlFlags[64];
                        byte[] ccmp_WEP_Data = null;

                        if (isProtected)
                        {
                            if (count - br.BaseStream.Position < 4)
                            {
                                packet = null;
                                return(false);
                            }
                            var firstFour = br.ReadBytes(4);
                            if (firstFour[3] == 0)
                            {
                                ccmp_WEP_Data = firstFour;
                            }
                            else
                            {
                                if (count - br.BaseStream.Position < 4)
                                {
                                    packet = null;
                                    return(false);
                                }
                                ccmp_WEP_Data = new byte[8];
                                firstFour.CopyTo(ccmp_WEP_Data, 0);
                                br.ReadBytes(4).CopyTo(ccmp_WEP_Data, 4);
                            }
                        }

                        var isWep = isProtected && ccmp_WEP_Data?.Length == 4;

                        if (count - br.BaseStream.Position - (isWep ? 4 : 0) < 0)
                        {
                            packet = null;
                            return(false);
                        }

                        var unsafePayloadLen = count - (int)br.BaseStream.Position - (isWep ? 4 : 0);
                        var safePayloadLen   = Math.Max(0, unsafePayloadLen);

                        packet = null;

                        if (frameType == (int)FrameTypes.Data && ((subType & 4) != 1) && !isProtected)
                        {
                            LLC payload;
                            if (LLC.TryParse(buffer, index + (int)br.BaseStream.Position, safePayloadLen, out payload))
                            {
                                packet = new IEEE802_11 <LLC> {
                                    Payload = payload
                                };
                            }
                        }
                        else if (frameType == (int)FrameTypes.Management && subType == (int)ManagementSubTypes.Beacon)
                        {
                            Beacon802_11 payload;
                            if (Beacon802_11.TryParse(
                                    buffer,
                                    index + (int)br.BaseStream.Position,
                                    safePayloadLen,
                                    out payload))
                            {
                                packet = new IEEE802_11 <Beacon802_11> {
                                    Payload = payload
                                };
                            }
                        }

                        if (packet == null)
                        {
                            Generic payload;
                            Generic.TryParse(buffer, index + (int)br.BaseStream.Position, safePayloadLen, out payload);

                            // This can never fail, so I'm not checking the output
                            packet = new IEEE802_11 <Generic> {
                                Payload = payload
                            };
                        }

                        br.BaseStream.Seek(packet.Payload.Length(), SeekOrigin.Current);

                        UInt32 wep_ICV = 0;
                        if (isWep)
                        {
                            wep_ICV = ByteOrder.NetworkToHostOrder(br.ReadUInt32());
                        }

                        packet.FrameControlVersionTypeAndSubtype = frameControlVersionTypeAndSubtype;
                        packet.FrameControlFlags = frameControlFlags;
                        packet.DurationID        = durationID;
                        packet.Destination       = destination;
                        packet.Source            = source;
                        packet.BSSID             = bssid;
                        packet.SequenceControl   = sequenceControl;
                        packet.Receiver          = receiver;
                        packet.Transmitter       = transmitter;
                        packet.QosControl        = qosControl;
                        packet.CCMP_WEP_Data     = ccmp_WEP_Data;
                        packet.WEP_ICV           = wep_ICV;

                        if (br.BaseStream.Position == count - 4)
                        {
                            packet.FrameCheckSequence = br.ReadUInt32();
                        }

                        return(true);
                    }
                }
            }
            catch (Exception)
            {
                packet = null;
                return(false);
            }
        }
Esempio n. 9
0
        /// <summary>
        ///     Attempts to parse raw data into a structured packet
        /// </summary>
        /// <param name="buffer">Raw data to parse</param>
        /// <param name="packet">Parsed packet</param>
        /// <param name="count">The length of the packet in bytes</param>
        /// <param name="index">The index into the buffer at which the packet begins</param>
        /// <returns>True if parsing was successful, false if it is not.</returns>
        internal static bool TryParse(byte[] buffer, int index, int count, out UDP packet)
        {
            try
            {
                if (count < MinimumParseableBytes)
                {
                    packet = null;
                    return(false);
                }

                using (var ms = new MemoryStream(buffer, index, count, false))
                {
                    using (var br = new BinaryReader(ms))
                    {
                        var sourcePort  = ByteOrder.NetworkToHostOrder(br.ReadUInt16());
                        var destPort    = ByteOrder.NetworkToHostOrder(br.ReadUInt16());
                        var totalLength = ByteOrder.NetworkToHostOrder(br.ReadUInt16());
                        var checksum    = ByteOrder.NetworkToHostOrder(br.ReadUInt16());

                        packet = null;

                        if (destPort == 53)
                        {
                            if (DNSQuery.TryParse(buffer, index + (int)br.BaseStream.Position, count - 8, out DNSQuery payload))
                            {
                                packet = new UDP <DNSQuery> {
                                    Payload = payload
                                };
                            }
                        }
                        else if (sourcePort == 53)
                        {
                            if (DNSReply.TryParse(buffer, index + (int)br.BaseStream.Position, count - 8, out DNSReply payload))
                            {
                                packet = new UDP <DNSReply> {
                                    Payload = payload
                                };
                            }
                        }

                        if (packet == null)
                        {
                            // This can never fail, so I'm not checking the output
                            Generic.TryParse(buffer, index + (int)br.BaseStream.Position, count - 8, out Generic payload);

                            packet = new UDP <Generic>()
                            {
                                Payload = payload
                            };
                        }
                        packet.SourcePort  = sourcePort;
                        packet.DestPort    = destPort;
                        packet.TotalLength = totalLength;
                        packet.Checksum    = checksum;

                        return(true);
                    }
                }
            }
            catch (Exception)
            {
                packet = null;
                return(false);
            }
        }
        /// <summary>
        ///     Attempts to parse raw data into a structured packet
        /// </summary>
        /// <param name="buffer">Raw data to parse</param>
        /// <param name="packet">Parsed packet</param>
        /// <param name="count">The length of the packet in bytes</param>
        /// <param name="index">The index into the buffer at which the packet begins</param>
        /// <returns>True if parsing was successful, false if it is not.</returns>
        internal static bool TryParse(byte[] buffer, int index, int count, out EthernetII packet)
        {
            try
            {
                if (count < MinimumParseableBytes)
                {
                    packet = null;
                    return(false);
                }

                using (var ms = new MemoryStream(buffer, index, count, false))
                {
                    using (var br = new BinaryReader(ms))
                    {
                        var dstMac    = br.ReadBytes(6);
                        var srcMac    = br.ReadBytes(6);
                        var etherType = ByteOrder.NetworkToHostOrder(br.ReadUInt16());

                        packet = null;
                        switch (etherType)
                        {
                        case (ushort)EtherTypes.IPv4:
                        {
                            IPv4 payload;
                            if (IPv4.TryParse(
                                    buffer,
                                    index + (int)br.BaseStream.Position,
                                    (int)(count - br.BaseStream.Position),
                                    out payload))
                            {
                                packet = new EthernetII <IPv4> {
                                    Payload = payload
                                };
                            }
                        }
                        break;

                        case (ushort)EtherTypes.ARP:
                        {
                            ARP payload;
                            if (ARP.TryParse(
                                    buffer,
                                    index + (int)br.BaseStream.Position,
                                    (int)(count - br.BaseStream.Position),
                                    out payload))
                            {
                                packet = new EthernetII <ARP> {
                                    Payload = payload
                                };
                            }
                        }
                        break;
                        }

                        if (packet == null)
                        {
                            Generic payload;
                            Generic.TryParse(
                                buffer,
                                index + (int)br.BaseStream.Position,
                                (int)(count - br.BaseStream.Position),
                                out payload);

                            // This can never fail, so I'm not checking the output
                            packet = new EthernetII <Generic> {
                                Payload = payload
                            };
                        }

                        packet.DstMac    = dstMac;
                        packet.EtherType = etherType;
                        packet.SrcMac    = srcMac;

                        return(true);
                    }
                }
            }
            catch (Exception)
            {
                packet = null;
                return(false);
            }
        }