Ejemplo n.º 1
0
        /// <summary>
        /// Reconstructs the tcp session
        /// </summary>
        /// <param name="sequence">Sequence number of the tcp packet</param>
        /// <param name="length">The size of the original packet data</param>
        /// <param name="data">The captured data</param>
        /// <param name="dataLength">The length of the captured data</param>
        /// <param name="synFlag"></param>
        /// <param name="srcIp">The source ip address</param>
        /// <param name="srcPort">The source port</param>
        private void ReassembleTcp(ulong sequence, ulong length, byte[] data, ulong dataLength, bool synFlag,
                                   long srcIp, ushort srcPort)
        {
            bool first = false;

            /* Check to see if we have seen this source IP and port before.
             * (Yes, we have to check both source IP and port; the connection
             * might be between two different ports on the same machine.) */
            int srcIndex = -1;

            for (int i = 0; i < 2; i++)
            {
                if (this.srcIp[i] == srcIp && this.srcPort[i] == srcPort)
                {
                    srcIndex = i;
                }
            }

            /* we didn't find it if srcIndex == -1 */
            if (srcIndex < 0)
            {
                /* assign it to a srcIndex and get going */
                for (int i = 0; i < 2; i++)
                {
                    if (this.srcPort[i] == 0)
                    {
                        this.srcIp[i]   = srcIp;
                        this.srcPort[i] = srcPort;
                        srcIndex        = i;
                        first           = true;
                        break;
                    }
                }
            }

            if (srcIndex < 0)
            {
                throw new InvalidOperationException("ERROR in ReassembleTcp: Too many addresses!");
            }

            /* now that we have filed away the srcs, lets get the sequence number stuff figured out */
            if (first)
            {
                /* this is the first time we have seen this src's sequence number */
                this.sequence[srcIndex] = sequence + length;
                if (synFlag)
                {
                    this.sequence[srcIndex]++;
                }

                /* write out the packet data */
                WritePacketData(srcIndex, data);
                return;
            }

            /* if we are here, we have already seen this src, let's
             * try and figure out if this packet is in the right place */
            if (sequence < this.sequence[srcIndex])   // retransmitted packet
            /* this sequence number seems dated, but it may have more info than we have already seen. */
            {
                ulong newSequence = sequence + length;
                if (newSequence > this.sequence[srcIndex])
                {
                    /* this one has more than we have seen. let's get the payload that we have not seen. */
                    ulong offset = this.sequence[srcIndex] - sequence;
                    if (dataLength > offset)
                    {
                        WritePacketData(srcIndex, data, (int)offset);
                    }

                    this.sequence[srcIndex] = newSequence;

                    /* done with the packet, see if it caused a fragment to fit */
                    while (CheckFragments(srcIndex))
                    {
                    }
                }
            }
            else if (sequence == this.sequence[srcIndex])     // right on time
            {
                this.sequence[srcIndex] += length;
                if (synFlag)
                {
                    this.sequence[srcIndex]++;
                }

                if (data != null)
                {
                    WritePacketData(srcIndex, data);
                }

                /* done with the packet, see if it caused a fragment to fit */
                while (CheckFragments(srcIndex))
                {
                }
            }
            else if (dataLength > 0 && sequence > this.sequence[srcIndex])     // out of order packet
            {
                var tmpFragment = new TcpFragment {
                    Data       = data,
                    Sequence   = sequence,
                    Length     = length,
                    DataLength = dataLength,
                    Next       = fragments[srcIndex],
                };

                fragments[srcIndex] = tmpFragment;
            }
        }
Ejemplo n.º 2
0
        /* here we search through all the frag we have collected to see if one fits */
        private bool CheckFragments(int index)
        {
            TcpFragment prev        = null;
            TcpFragment current     = fragments[index];
            ulong       minSequence = current?.Sequence ?? 0;

            while (current != null)
            {
                if (minSequence > current.Sequence)
                {
                    minSequence = current.Sequence;
                }

                if (current.Sequence < sequence[index])
                {
                    /* this sequence number seems dated, but check the end to make
                     * sure it has no more info than we have already seen */
                    ulong newSequence = current.Sequence + current.Length;
                    if (newSequence > sequence[index])
                    {
                        /* this one has more than we have seen. let's get the payload that we have not seen.
                         * This happens when part of this frame has been retransmitted */
                        ulong offset = sequence[index] - current.Sequence;
                        if (current.DataLength > offset)
                        {
                            WritePacketData(index, current.Data, (int)offset);
                        }

                        sequence[index] = newSequence;
                    }

                    /* Remove the fragment from the list as the "new" part of it has been processed
                     * or its data has been seen already in another packet. */
                    if (prev != null)
                    {
                        prev.Next = current.Next;
                    }
                    else
                    {
                        fragments[index] = current.Next;
                    }

                    return(true);
                }

                if (current.Sequence == sequence[index])
                {
                    /* this fragment fits the stream */
                    if (current.Data != null)
                    {
                        WritePacketData(index, current.Data);
                    }

                    sequence[index] += current.Length;
                    if (prev != null)
                    {
                        prev.Next = current.Next;
                    }
                    else
                    {
                        fragments[index] = current.Next;
                    }

                    return(true);
                }

                prev    = current;
                current = current.Next;
            }

            return(false);
        }