internal void RemoveData(uint firstSequenceNumber, int bytesToRemove) { if (this.dataList.Keys[0] != firstSequenceNumber) { throw new Exception("The data (first data sequence number: " + this.dataList.Keys[0] + ") is not equal to " + firstSequenceNumber); } else { while (this.dataList.Count > 0 && this.dataList.Keys[0] + this.dataList.Values[0].Length <= firstSequenceNumber + bytesToRemove) { this.dataList.RemoveAt(0); } //see if we need to do a partial removal of a tcp packet if (this.dataList.Count > 0 && this.dataList.Keys[0] < firstSequenceNumber + bytesToRemove) { uint newFirstSequenceNumber = firstSequenceNumber + (uint)bytesToRemove; byte[] oldData = this.dataList.Values[0]; byte[] truncatedData = new byte[this.dataList.Keys[0] + oldData.Length - newFirstSequenceNumber]; Array.Copy(oldData, oldData.Length - truncatedData.Length, truncatedData, 0, truncatedData.Length); this.dataList.RemoveAt(0); this.dataList.Add(newFirstSequenceNumber, truncatedData); } this.virtualTcpData = null; } }
internal VirtualTcpData GetNextVirtualTcpData() { if (this.virtualTcpData == null) { if (this.dataList.Count > 0 && this.CountBytesToRead() > 0 && this.CountPacketsToRead() > 0) { if (this.streamIsClientToServer) { this.virtualTcpData = new VirtualTcpData(this, this.networkFlow.FiveTuple.ClientPort, this.networkFlow.FiveTuple.ServerPort); } else { this.virtualTcpData = new VirtualTcpData(this, this.networkFlow.FiveTuple.ServerPort, this.networkFlow.FiveTuple.ClientPort); } return(virtualTcpData); } else { return(null); } } else if (virtualTcpData.TryAppendNextPacket()) { return(virtualTcpData); } else { return(null); } }
internal TcpDataStream(uint initialTcpSequenceNumber, ushort sourcePort, ushort destinationPort, NetworkTcpSession session) { this.initialTcpSequenceNumber = initialTcpSequenceNumber; this.expectedTcpSequenceNumber = initialTcpSequenceNumber; this.sourcePort = sourcePort; this.destinationPort = destinationPort; this.dataList = new SortedList <uint, byte[]>(); this.dataListMaxSize = 64;//i hope I shouldn't need more than 64 packets in the list. It depends on how late a misordered packet might get received. Smaller number gives better performance, larger number gives better tolerance to reordered packets this.totalByteCount = 0; this.virtualTcpData = null; this.session = session; }
public TcpDataStream(uint initialTcpSequenceNumber, bool streamIsClientToServer, NetworkTcpSession session) { this.initialTcpSequenceNumber = initialTcpSequenceNumber; this.expectedTcpSequenceNumber = initialTcpSequenceNumber; //this.sourcePort=sourcePort; //this.destinationPort=destinationPort; this.dataList = new SortedList <uint, byte[]>(); //this.dataListMaxSize=64;//i hope I shouldn't need more than 64 packets in the list. It depends on how late a misordered packet might get received. Smaller number gives better performance, larger number gives better tolerance to reordered packets this.dataListMaxSize = 256;//allows data packets to be out-of-order up to 256 packets apart from each other in the same unidirectional stream //this.totalByteCount=0; this.virtualTcpData = null; this.session = session; this.networkFlow = session.Flow; //this.protocolFinder = session.protocolFinder; this.streamIsClientToServer = streamIsClientToServer; }
internal VirtualTcpData GetNextVirtualTcpData() { if (this.virtualTcpData == null) { if (this.dataList.Count > 0 && this.CountBytesToRead() > 0 && this.CountPacketsToRead() > 0) { this.virtualTcpData = new VirtualTcpData(this, this.sourcePort, this.destinationPort); return(virtualTcpData); } else { return(null); } } else if (virtualTcpData.TryAppendNextPacket()) { return(virtualTcpData); } else { return(null); } }
internal void RemoveData(VirtualTcpData data) { this.RemoveData(data.FirstPacketSequenceNumber, data.ByteCount); }
public void AddTcpData(uint tcpSequenceNumber, byte[] tcpSegmentData) { if (tcpSegmentData.Length > 0)//It is VERY important that no 0 length data arrays are added! There is otherwise a big risk for getting stuck in forever-loops etc. //ensure that only new data is written to the dataList //partially overlapping resent frames are handled here { if ((int)(expectedTcpSequenceNumber - tcpSequenceNumber) > 0 && expectedTcpSequenceNumber - tcpSequenceNumber < tcpSegmentData.Length) { //remove the stuff that has already been parsed uint bytesToSkip = expectedTcpSequenceNumber - tcpSequenceNumber; byte[] newSegmentData = new byte[tcpSegmentData.Length - bytesToSkip]; Array.Copy(tcpSegmentData, bytesToSkip, newSegmentData, 0, newSegmentData.Length); tcpSegmentData = newSegmentData; tcpSequenceNumber += bytesToSkip; } //see if we've missed part of the handshake and are now seeing the first data with lower sequence number if (this.TotalByteCount == 0 && initialTcpSequenceNumber == expectedTcpSequenceNumber && (int)(expectedTcpSequenceNumber - tcpSequenceNumber) > 0 && (int)(tcpSequenceNumber - expectedTcpSequenceNumber) < 12345) { this.initialTcpSequenceNumber = tcpSequenceNumber; this.expectedTcpSequenceNumber = tcpSequenceNumber; } //A check that the tcpSequenceNumber is a reasonable one, i.e. not smaller than expected and not too large if ((int)(expectedTcpSequenceNumber - tcpSequenceNumber) <= 0 && tcpSequenceNumber - expectedTcpSequenceNumber < 1234567) { if (!dataList.ContainsKey(tcpSequenceNumber)) { //handle partially overlapping TCP segments that have arrived previously IList <uint> tcpSequenceNumbers = dataList.Keys; //we wanna know if we already have an already stored sequence nr. where: new tcpSeqNr < stored tcpSeqNr < new tcpSeqNr + new tcpSeqData.Length /* * //METHOD #1 * for (int i = 0; i < tcpSequenceNumbers.Count; i++) { //this part should be replaced by a binary search function to reduce complexity * if (tcpSequenceNumbers[i] > tcpSequenceNumber) { * if (tcpSequenceNumbers[i] < tcpSequenceNumber + tcpSegmentData.Length) { * //we need to truncate the data since parts of it has already been received * uint bytesToKeep = tcpSequenceNumbers[i] - tcpSequenceNumber; * byte[] newSegmentData = new byte[bytesToKeep]; * Array.Copy(tcpSegmentData, 0, newSegmentData, 0, bytesToKeep); * tcpSegmentData = newSegmentData; * } * break; * } * } * */ //METHOD #2 for (int i = tcpSequenceNumbers.Count - 1; i >= 0; i--) { if (tcpSequenceNumbers[i] < tcpSequenceNumber) { break; } else if (tcpSequenceNumbers[i] < tcpSequenceNumber + tcpSegmentData.Length) { //we need to truncate the data since parts of it has already been received uint bytesToKeep = tcpSequenceNumbers[i] - tcpSequenceNumber; byte[] newSegmentData = new byte[bytesToKeep]; Array.Copy(tcpSegmentData, 0, newSegmentData, 0, bytesToKeep); tcpSegmentData = newSegmentData; } } //avoid addint TCP keep-alive null-data (one byte) // a keepalive contains 0 or 1 bytes of data and has a sequence nr that is next_expected-1, never SYN/FIN/RST //if (tcpSegmentData.Length == 1 && tcpSegmentData[0] == 0) // System.Diagnostics.Debugger.Break(); //Avoid adding TCP data for TCP-keepalives with "fake" one-byte L7 data (null value) if (tcpSegmentData.Length > 1 || tcpSegmentData[0] != 0 || this.TotalByteCount > 0) { dataList.Add(tcpSequenceNumber, tcpSegmentData); this.TotalByteCount += tcpSegmentData.Length; } if (expectedTcpSequenceNumber == tcpSequenceNumber) { expectedTcpSequenceNumber += (uint)tcpSegmentData.Length; //check if there are other packets that arrived too early that follows this packet while (dataList.ContainsKey(expectedTcpSequenceNumber)) { expectedTcpSequenceNumber += (uint)dataList[expectedTcpSequenceNumber].Length; } } while (dataList.Count > this.dataListMaxSize) { if (!this.dataListIsTruncated) { Utils.Logger.Log("Too many unparsed queued packets, queue will be truncated for : " + this.networkFlow.FiveTuple.ToString(), System.Diagnostics.EventLogEntryType.Warning); #if DEBUG if (!debugHasBreaked) { System.Diagnostics.Debugger.Break(); debugHasBreaked = true; } #endif } dataList.RemoveAt(0); //remove the oldest TCP data this.dataListIsTruncated = true; this.virtualTcpData = null; //this one has to be reset so that the virtualPacket still will work } } else //let's replace the old TCP packet with the new one //Or maybe just skip it! { } } } }
internal void AddTcpData(uint tcpSequenceNumber, byte[] tcpSegmentData) { if (tcpSegmentData.Length > 0)//It is VERY important that no 0 length data arrays are added! There is otherwise a big risk for getting stuck in forever-loops etc. //ensure that only new data is written to the dataList //partially overlapping resent frames are handled here { if ((int)(expectedTcpSequenceNumber - tcpSequenceNumber) > 0 && expectedTcpSequenceNumber - tcpSequenceNumber < tcpSegmentData.Length) { //remove the stuff that has already been parsed uint bytesToSkip = expectedTcpSequenceNumber - tcpSequenceNumber; byte[] newSegmentData = new byte[tcpSegmentData.Length - bytesToSkip]; Array.Copy(tcpSegmentData, bytesToSkip, newSegmentData, 0, newSegmentData.Length); tcpSegmentData = newSegmentData; tcpSequenceNumber += bytesToSkip; } //A check that the tcpSequenceNumber is a reasonable one, i.e. not smaller that expected and not too large if ((int)(expectedTcpSequenceNumber - tcpSequenceNumber) <= 0 && tcpSequenceNumber - expectedTcpSequenceNumber < 1000000) { if (!dataList.ContainsKey(tcpSequenceNumber)) { //handle partially overlapping TCP segments that have arrived previously IList <uint> tcpSequenceNumbers = dataList.Keys; //we wanna know if we already have an already stored sequence nr. where: new tcpSeqNr < stored tcpSeqNr < new tcpSeqNr + new tcpSeqData.Length /* * //METHOD #1 * for (int i = 0; i < tcpSequenceNumbers.Count; i++) { //this part should be replaced by a binary search function to reduce complexity * if (tcpSequenceNumbers[i] > tcpSequenceNumber) { * if (tcpSequenceNumbers[i] < tcpSequenceNumber + tcpSegmentData.Length) { * //we need to truncate the data since parts of it has already been received * uint bytesToKeep = tcpSequenceNumbers[i] - tcpSequenceNumber; * byte[] newSegmentData = new byte[bytesToKeep]; * Array.Copy(tcpSegmentData, 0, newSegmentData, 0, bytesToKeep); * tcpSegmentData = newSegmentData; * } * break; * } * } * */ //METHOD #2 for (int i = tcpSequenceNumbers.Count - 1; i >= 0; i--) { if (tcpSequenceNumbers[i] < tcpSequenceNumber) { break; } else if (tcpSequenceNumbers[i] < tcpSequenceNumber + tcpSegmentData.Length) { //we need to truncate the data since parts of it has already been received uint bytesToKeep = tcpSequenceNumbers[i] - tcpSequenceNumber; byte[] newSegmentData = new byte[bytesToKeep]; Array.Copy(tcpSegmentData, 0, newSegmentData, 0, bytesToKeep); tcpSegmentData = newSegmentData; } } dataList.Add(tcpSequenceNumber, tcpSegmentData); this.totalByteCount += tcpSegmentData.Length; if (expectedTcpSequenceNumber == tcpSequenceNumber) { expectedTcpSequenceNumber += (uint)tcpSegmentData.Length; //check if there are other packets that arrived too early that follows this packet while (dataList.ContainsKey(expectedTcpSequenceNumber)) { expectedTcpSequenceNumber += (uint)dataList[expectedTcpSequenceNumber].Length; } } while (dataList.Count > this.dataListMaxSize) { dataList.RemoveAt(0); //remove the oldest TCP data this.virtualTcpData = null; //this one has to be reset so that the virtualPacket still will work } } else //let's replace the old TCP packet with the new one //Or maybe just skip it! { } } } }