public static TcpOptions NextTcpOptions(this Random random) { int optionsLength = random.Next(TcpOptions.MaximumBytesLength) / 4 * 4; List <TcpOption> options = new List <TcpOption>(); while (optionsLength > 0) { TcpOption option = random.NextTcpOption(optionsLength); if (option.IsAppearsAtMostOnce && options.FindIndex(option.Equivalent) != -1) { continue; } options.Add(option); optionsLength -= option.Length; if (option.OptionType == TcpOptionType.EndOfOptionList) { break; } } return(new TcpOptions(options)); }
private static bool HandleOptionCommonFields(XElement subfield, TcpOption option) { switch (subfield.Name()) { case "tcp.option_kind": subfield.AssertNoFields(); subfield.AssertShowDecimal((byte)option.OptionType); return(true); case "tcp.options.type": subfield.AssertShowDecimal((byte)option.OptionType); return(true); case "tcp.option_len": subfield.AssertNoFields(); subfield.AssertShowDecimal(option.Length); return(true); default: return(false); } }
internal override bool EqualsData(TcpOption other) { return (other is TcpOptionPartialOrderConnectionPermitted); }
internal void SendTcpSegment(UInt32 sourceIPAddress, UInt32 destinationIPAddress, UInt16 sourceIPPort, UInt16 destinationIPPort, UInt32 sequenceNumber, UInt32 acknowledgementNumber, UInt16 windowSize, bool sendAck, bool sendPsh, bool sendRst, bool sendSyn, bool sendFin, TcpOption[] tcpOptions, byte[] buffer, Int32 offset, Int32 count, Int64 timeoutInMachineTicks) { if (_isDisposed) return; lock (_tcpHeaderBufferLockObject) { Int32 tcpHeaderLength = TCP_HEADER_MIN_LENGTH + (sendSyn ? 4 : 0); // TCP basic header: 20 bytes _tcpHeaderBuffer[0] = (byte)((sourceIPPort >> 8) & 0xFF); _tcpHeaderBuffer[1] = (byte)(sourceIPPort & 0xFF); _tcpHeaderBuffer[2] = (byte)((destinationIPPort >> 8) & 0xFF); _tcpHeaderBuffer[3] = (byte)(destinationIPPort & 0xFF); // sequence number _tcpHeaderBuffer[4] = (byte)((sequenceNumber >> 24) & 0xFF); _tcpHeaderBuffer[5] = (byte)((sequenceNumber >> 16) & 0xFF); _tcpHeaderBuffer[6] = (byte)((sequenceNumber >> 8) & 0xFF); _tcpHeaderBuffer[7] = (byte)(sequenceNumber & 0xFF); // acknowledment number if (sendAck) { _tcpHeaderBuffer[8] = (byte)((acknowledgementNumber >> 24) & 0xFF); _tcpHeaderBuffer[9] = (byte)((acknowledgementNumber >> 16) & 0xFF); _tcpHeaderBuffer[10] = (byte)((acknowledgementNumber >> 8) & 0xFF); _tcpHeaderBuffer[11] = (byte)(acknowledgementNumber & 0xFF); } else { Array.Clear(_tcpHeaderBuffer, 8, 4); } // header length and flags _tcpHeaderBuffer[12] = (byte)((tcpHeaderLength / 4) << 4); // more flags _tcpHeaderBuffer[13] = (byte)( (sendFin ? 1 << 0 : 0) | (sendSyn ? 1 << 1 : 0) | (sendRst ? 1 << 2 : 0) | (sendPsh ? 1 << 3 : 0) | (sendAck ? 1 << 4 : 0) ); // window size (i.e. how much data we are willing to receive) _tcpHeaderBuffer[14] = (byte)((windowSize >> 8) & 0xFF); _tcpHeaderBuffer[15] = (byte)(windowSize & 0xFF); // tcp checksum Array.Clear(_tcpHeaderBuffer, 16, 2); // urgent pointer /* NOTE: bytes 18-19, never populated */ // TCP options: empty by default policy -- but zero-initialized under any circumstance Array.Clear(_tcpHeaderBuffer, TCP_HEADER_MIN_LENGTH, TCP_HEADER_MAX_LENGTH - TCP_HEADER_MIN_LENGTH); /* TCP options */ if (tcpOptions != null) { int headerPos = TCP_HEADER_MIN_LENGTH; for (int iOption = 0; iOption < tcpOptions.Length; iOption++) { _tcpHeaderBuffer[headerPos++] = tcpOptions[iOption].Kind; switch (tcpOptions[iOption].Kind) { case 0: /* EOL = End of Option List */ case 1: /* NOP = No OPeration; used for padding */ break; default: { if (tcpOptions[iOption].Data != null) { _tcpHeaderBuffer[headerPos++] = (byte)(tcpOptions[iOption].Data.Length + 2); Array.Copy(tcpOptions[iOption].Data, 0, _tcpHeaderBuffer, headerPos, tcpOptions[iOption].Data.Length); headerPos += tcpOptions[iOption].Data.Length; } else { _tcpHeaderBuffer[headerPos++] = 2; /* only 2 bytes--the kind and the length--with no data */ } } break; } } } UInt16 checksum; lock (_tcpPseudoHeaderBufferLockObject) { // create temporary pseudo header _tcpPseudoHeaderBuffer[0] = (byte)((sourceIPAddress >> 24) & 0xFF); _tcpPseudoHeaderBuffer[1] = (byte)((sourceIPAddress >> 16) & 0xFF); _tcpPseudoHeaderBuffer[2] = (byte)((sourceIPAddress >> 8) & 0xFF); _tcpPseudoHeaderBuffer[3] = (byte)(sourceIPAddress & 0xFF); _tcpPseudoHeaderBuffer[4] = (byte)((destinationIPAddress >> 24) & 0xFF); _tcpPseudoHeaderBuffer[5] = (byte)((destinationIPAddress >> 16) & 0xFF); _tcpPseudoHeaderBuffer[6] = (byte)((destinationIPAddress >> 8) & 0xFF); _tcpPseudoHeaderBuffer[7] = (byte)(destinationIPAddress & 0xFF); _tcpPseudoHeaderBuffer[8] = 0; // ZERO _tcpPseudoHeaderBuffer[9] = (byte)IPv4Layer.ProtocolType.Tcp; // Protocol Number UInt16 tcpLength = (UInt16)(tcpHeaderLength + count); _tcpPseudoHeaderBuffer[10] = (byte)((tcpLength >> 8) & 0xFF); _tcpPseudoHeaderBuffer[11] = (byte)(tcpLength & 0xFF); // calculate checksum over entire pseudo-header, UDP header and data _checksumBufferArray[0] = _tcpPseudoHeaderBuffer; _checksumOffsetArray[0] = 0; _checksumCountArray[0] = TCP_PSEUDO_HEADER_LENGTH; _checksumBufferArray[1] = _tcpHeaderBuffer; _checksumOffsetArray[1] = 0; _checksumCountArray[1] = tcpHeaderLength; _checksumBufferArray[2] = buffer; _checksumOffsetArray[2] = offset; _checksumCountArray[2] = count; checksum = Utility.CalculateInternetChecksum(_checksumBufferArray, _checksumOffsetArray, _checksumCountArray); /* NOTE: this function will append a pad byte if necessary for 16-bit alignment before calculation */ } // insert checksujm into UDP header _tcpHeaderBuffer[16] = (byte)((checksum >> 8) & 0xFF); _tcpHeaderBuffer[17] = (byte)(checksum & 0xFF); // queue up our buffer arrays _bufferArray[0] = _tcpHeaderBuffer; _indexArray[0] = 0; _countArray[0] = tcpHeaderLength; _bufferArray[1] = buffer; _indexArray[1] = offset; _countArray[1] = count; /* TODO: deal with our flags and timeout_ms; we shouldn't just be sending while blocking -- and ignoring the flags */ _ipv4Layer.Send((byte)IPv4Layer.ProtocolType.Tcp, sourceIPAddress, destinationIPAddress, _bufferArray, _indexArray, _countArray, timeoutInMachineTicks); } }
internal override bool EqualsData(TcpOption other) { return EqualsData(other as TcpOptionMd5Signature); }
internal sealed override bool EqualsData(TcpOption other) { return(EqualsData(other as TcpOptionConnectionCountBase)); }
internal override bool EqualsData(TcpOption other) { return other is TcpOptionSimple; }
internal override bool EqualsData(TcpOption other) { return EqualsData(other as TcpOptionAuthentication); }
internal override bool EqualsData(TcpOption other) { return EqualsData(other as TcpOptionWindowScale); }
internal override bool EqualsData(TcpOption other) { return EqualsData(other as TcpOptionEchoReply); }
private static void CompareTcpOptions(XElement element, TcpOptions options) { int currentOptionIndex = 0; foreach (var field in element.Fields()) { if (field.Name() == "_ws.expert") { continue; } if (currentOptionIndex >= options.Count) { Assert.IsFalse(options.IsValid, "Options IsValid"); Assert.IsTrue( field.Show().StartsWith("Unknown (0x09) ") || // Unknown in Wireshark but known (and invalid) in Pcap.Net. field.Show().StartsWith("Unknown (0x0a) ") || // Unknown in Wireshark but known (and invalid) in Pcap.Net. field.Show().StartsWith("Unknown (0x19) ") || // Unknown in Wireshark but known (and invalid) in Pcap.Net. field.Show().StartsWith("Unknown (0x2d) ") || // Unknown in Wireshark and unknown and invalid in Pcap.Net. field.Show().StartsWith("Unknown (0xa9) ") || // Unknown in Wireshark and unknown and invalid in Pcap.Net. field.Show().StartsWith("Echo reply (with option length = ") || field.Show().Contains("bytes says option goes past end of options") || field.Show().Contains(") (with too-short option length = ") || field.Show().EndsWith(" (length byte past end of options)"), "Options show: " + field.Show()); Assert.AreEqual(options.Count, currentOptionIndex, "Options Count"); return; } TcpOption option = options[currentOptionIndex]; switch (field.Name()) { case "": switch (option.OptionType) { case TcpOptionType.WindowScale: TcpOptionWindowScale windowScale = (TcpOptionWindowScale)option; byte scaleFactorLog = windowScale.ScaleFactorLog; field.AssertShow(string.Format("Window scale: {0} (multiply by {1})", scaleFactorLog, (1L << (scaleFactorLog % 32)))); foreach (var subField in field.Fields()) { if (HandleOptionCommonFields(subField, option)) { continue; } switch (subField.Name()) { case "tcp.options.wscale.shift": subField.AssertShowDecimal(windowScale.ScaleFactorLog); break; case "tcp.options.wscale.multiplier": subField.AssertShowDecimal(1L << (windowScale.ScaleFactorLog % 32)); break; default: throw new InvalidOperationException("Invalid tcp option subfield " + subField.Name()); } } break; case TcpOptionType.SelectiveAcknowledgment: var selectiveAcknowledgmentOption = (TcpOptionSelectiveAcknowledgment)option; IEnumerable <TcpOptionSelectiveAcknowledgmentBlock> blocks = selectiveAcknowledgmentOption.Blocks; field.AssertShow("SACK:" + (blocks.Count() == 0 ? string.Empty : ((TcpOptionSelectiveAcknowledgment)option).Blocks.SequenceToString(" ", " "))); int blockIndex = 0; foreach (var subField in field.Fields()) { if (HandleOptionCommonFields(subField, option)) { continue; } subField.AssertNoFields(); switch (subField.Name()) { case "tcp.options.sack": subField.AssertShowDecimal(true); break; case "tcp.options.sack_le": subField.AssertShowDecimal(selectiveAcknowledgmentOption.Blocks[blockIndex].LeftEdge); break; case "tcp.options.sack_re": subField.AssertShowDecimal(selectiveAcknowledgmentOption.Blocks[blockIndex].RightEdge); ++blockIndex; break; case "tcp.options.sack.count": subField.AssertShowDecimal(selectiveAcknowledgmentOption.Blocks.Count); break; default: throw new InvalidOperationException("Invalid tcp option subfield " + subField.Name()); } } break; case TcpOptionType.Timestamp: var timestampOption = (TcpOptionTimestamp)option; field.AssertShow("Timestamps: TSval " + timestampOption.TimestampValue + ", TSecr " + timestampOption.TimestampEchoReply); foreach (var subField in field.Fields()) { if (HandleOptionCommonFields(subField, option)) { continue; } subField.AssertNoFields(); switch (subField.Name()) { case "tcp.options.timestamp.tsval": subField.AssertShowDecimal(timestampOption.TimestampValue); break; case "tcp.options.timestamp.tsecr": subField.AssertShowDecimal(timestampOption.TimestampEchoReply); break; default: throw new InvalidOperationException("Invalid tcp option subfield " + subField.Name()); } } break; case TcpOptionType.ConnectionCount: field.AssertShow("CC: " + ((TcpOptionConnectionCount)option).ConnectionCount); foreach (var subField in field.Fields()) { if (HandleOptionCommonFields(subField, option)) { continue; } subField.AssertNoFields(); switch (subField.Name()) { default: throw new InvalidOperationException("Invalid tcp option subfield " + subField.Name()); } } break; case TcpOptionType.Echo: field.AssertShow("Echo: " + ((TcpOptionEcho)option).Info); foreach (var subField in field.Fields()) { if (HandleOptionCommonFields(subField, option)) { continue; } subField.AssertNoFields(); switch (subField.Name()) { default: throw new InvalidOperationException("Invalid tcp option subfield " + subField.Name()); } } break; case TcpOptionType.ConnectionCountNew: field.AssertShow("CC.NEW: " + ((TcpOptionConnectionCountNew)option).ConnectionCount); foreach (var subField in field.Fields()) { if (HandleOptionCommonFields(subField, option)) { continue; } subField.AssertNoFields(); switch (subField.Name()) { default: throw new InvalidOperationException("Invalid tcp option subfield " + subField.Name()); } } break; case TcpOptionType.EndOfOptionList: field.AssertShow("End of Option List (EOL)"); foreach (var subField in field.Fields()) { if (HandleOptionCommonFields(subField, option)) { continue; } switch (subField.Name()) { default: subField.AssertNoFields(); throw new InvalidOperationException("Invalid tcp option subfield " + subField.Name()); } } break; case TcpOptionType.ConnectionCountEcho: field.AssertShow("CC.ECHO: " + ((TcpOptionConnectionCountEcho)option).ConnectionCount); foreach (var subField in field.Fields()) { if (HandleOptionCommonFields(subField, option)) { continue; } subField.AssertNoFields(); switch (subField.Name()) { default: throw new InvalidOperationException("Invalid tcp option subfield " + subField.Name()); } } break; case TcpOptionType.Md5Signature: field.AssertShow("TCP MD5 signature"); foreach (var subField in field.Fields()) { if (HandleOptionCommonFields(subField, option)) { continue; } switch (subField.Name()) { case "tcp.options.type": subField.AssertShowDecimal((byte)TcpOptionType.Md5Signature); break; default: subField.AssertNoFields(); throw new InvalidOperationException("Invalid tcp option subfield " + subField.Name()); } } break; case TcpOptionType.NoOperation: field.AssertShow("No-Operation (NOP)"); foreach (var subField in field.Fields()) { if (HandleOptionCommonFields(subField, option)) { continue; } throw new InvalidOperationException("Invalid tcp option subfield " + subField.Name()); } break; case TcpOptionType.EchoReply: field.AssertShow("Echo reply: " + ((TcpOptionEchoReply)option).Info); foreach (var subField in field.Fields()) { if (HandleOptionCommonFields(subField, option)) { continue; } throw new InvalidOperationException("Invalid tcp option subfield " + subField.Name()); } break; case TcpOptionType.SelectiveAcknowledgmentPermitted: field.AssertShow("SACK permitted"); field.AssertNoFields(); break; case TcpOptionType.SelectiveNegativeAcknowledgements: // TODO: Support Selective Negative Acknowledgements. Assert.IsTrue(field.Show().StartsWith("SACK permitted")); field.AssertNoFields(); break; case (TcpOptionType)20: // TODO: Support 20. field.AssertShow("SCPS capabilities" + (option.Length >= 4 ? string.Empty : " (with option length = " + option.Length + " bytes; should be >= 4)")); break; case (TcpOptionType)22: field.AssertShow("SCPS record boundary (with option length = " + option.Length + " bytes; should be 2)"); // TODO: Support 22. break; case (TcpOptionType)23: field.AssertShow("SCPS corruption experienced (with option length = " + option.Length + " bytes; should be 2)"); // TODO: Support 23. break; case (TcpOptionType)30: // TODO: Support 30. Assert.IsTrue(field.Show().StartsWith("Multipath TCP")); break; case (TcpOptionType)78: field.AssertShow("Riverbed Transparency (with option length = " + option.Length + " bytes; should be 16)"); // TODO: Support 78 - Support Riverbed. break; case TcpOptionType.PartialOrderConnectionPermitted: // 9. case TcpOptionType.PartialOrderServiceProfile: // 10. case TcpOptionType.AlternateChecksumRequest: // 14. case TcpOptionType.AlternateChecksumData: // 15. case TcpOptionType.Mood: // 25. case TcpOptionType.TcpAuthentication: // 29. field.AssertShow(string.Format("Unknown (0x{0}) ({1} bytes)", ((byte)option.OptionType).ToString("x2"), option.Length)); field.AssertNoFields(); break; default: field.AssertNoFields(); field.AssertShow("Unknown (0x" + ((byte)option.OptionType).ToString("x") + ") (" + option.Length + " bytes)"); break; } ++currentOptionIndex; break; case "tcp.options.mss": Assert.AreEqual(TcpOptionType.MaximumSegmentSize, option.OptionType); var maximumSegmentSize = (TcpOptionMaximumSegmentSize)option; field.AssertShowname("Maximum segment size: " + maximumSegmentSize.MaximumSegmentSize + " bytes"); foreach (var subField in field.Fields()) { if (HandleOptionCommonFields(subField, option)) { continue; } subField.AssertNoFields(); switch (subField.Name()) { case "tcp.options.mss_val": subField.AssertShowDecimal(maximumSegmentSize.MaximumSegmentSize); break; default: throw new InvalidOperationException("Invalid tcp options subfield " + subField.Name()); } } ++currentOptionIndex; break; case "tcp.options.mss_val": field.AssertShowDecimal(((TcpOptionMaximumSegmentSize)option).MaximumSegmentSize); field.AssertNoFields(); ++currentOptionIndex; break; case "tcp.options.echo": Assert.IsTrue(option is TcpOptionEchoReply || option is TcpOptionEcho); field.AssertShowDecimal(1); field.AssertNoFields(); break; case "tcp.options.cc": Assert.IsTrue(option is TcpOptionConnectionCountBase); field.AssertShowDecimal(1); field.AssertNoFields(); break; case "tcp.options.scps.vector": // TODO: Support 20. Assert.AreEqual((TcpOptionType)20, option.OptionType); // if (field.Show() == "0") // ++currentOptionIndex; ++currentOptionIndex; break; case "tcp.options.scps": // TODO: Support 20. Assert.AreEqual((TcpOptionType)20, option.OptionType); Assert.IsFalse(field.Fields().Any()); break; case "tcp.options.snack": // TODO: Support Selective Negative Acknowledgements. case "tcp.options.snack.offset": case "tcp.options.snack.size": Assert.AreEqual(TcpOptionType.SelectiveNegativeAcknowledgements, option.OptionType); field.AssertNoFields(); break; case "tcp.options.sack_perm": Assert.AreEqual(TcpOptionType.SelectiveAcknowledgmentPermitted, option.OptionType); foreach (var subField in field.Fields()) { if (HandleOptionCommonFields(subField, option)) { continue; } subField.AssertNoFields(); throw new InvalidOperationException("Invalid tcp options subfield " + subField.Name()); } ++currentOptionIndex; break; case "tcp.options.rvbd.probe": Assert.AreEqual((TcpOptionType)76, option.OptionType); // TODO: Support Riverbed. ++currentOptionIndex; break; case "tcp.options.rvbd.trpy": Assert.AreEqual((TcpOptionType)78, option.OptionType); // TODO: Support Riverbed. ++currentOptionIndex; break; case "tcp.options.experimental": Assert.IsTrue(new [] { (TcpOptionType)253, (TcpOptionType)254 }.Contains(option.OptionType)); // TODO: Support Experimental. ++currentOptionIndex; break; default: throw new InvalidOperationException("Invalid tcp options field " + field.Name()); } } }
internal override bool EqualsData(TcpOption other) { return EqualsData(other as TcpOptionSelectiveAcknowledgment); }
internal override bool EqualsData(TcpOption other) { return(other is TcpOptionSimple); }
internal override bool EqualsData(TcpOption other) { return EqualsData(other as TcpOptionTimestamp); }
internal override bool EqualsData(TcpOption other) { return other is TcpOptionSelectiveAcknowledgmentPermitted; }
private static bool HandleOptionCommonFields(XElement subfield, TcpOption option) { switch (subfield.Name()) { case "tcp.option_kind": subfield.AssertNoFields(); subfield.AssertShowDecimal((byte)option.OptionType); return true; case "tcp.options.type": subfield.AssertShowDecimal((byte)option.OptionType); return true; case "tcp.option_len": subfield.AssertNoFields(); subfield.AssertShowDecimal(option.Length); return true; default: return false; } }
internal override sealed bool EqualsData(TcpOption other) { return EqualsData(other as TcpOptionConnectionCountBase); }
internal override bool EqualsData(TcpOption other) { return EqualsData(other as TcpOptionPartialOrderServiceProfile); }
private static void CompareTcpOptions(XElement element, TcpOptions options) { int currentOptionIndex = 0; foreach (var field in element.Fields()) { if (currentOptionIndex >= options.Count) { Assert.IsFalse(options.IsValid, "Options IsValid"); Assert.IsTrue( field.Show().StartsWith("Unknown (0x0a) ") || // Unknown in Wireshark but known (and invalid) in Pcap.Net field.Show().Contains("bytes says option goes past end of options") || field.Show().Contains(") (with too-short option length = "), "Options show: " + field.Show()); Assert.AreEqual(options.Count, currentOptionIndex, "Options Count"); return; } TcpOption option = options[currentOptionIndex]; switch (field.Name()) { case "": switch (option.OptionType) { case TcpOptionType.SelectiveNegativeAcknowledgements: // TODO: Support Selective Negative Acknowledgements. Assert.IsTrue(field.Show().StartsWith(option.GetWiresharkString())); field.AssertNoFields(); break; case (TcpOptionType)78: // TODO: Support Riverbed. break; default: field.AssertShow(option.GetWiresharkString()); break; } switch (option.OptionType) { case TcpOptionType.WindowScale: TcpOptionWindowScale windowScale = (TcpOptionWindowScale)option; foreach (var subField in field.Fields()) { switch (subField.Name()) { case "tcp.option_kind": subField.AssertShowDecimal((byte)windowScale.OptionType); break; case "tcp.option_len": subField.AssertShowDecimal(windowScale.Length); break; case "tcp.options.wscale.shift": subField.AssertShowDecimal(windowScale.ScaleFactorLog); break; case "tcp.options.wscale.multiplier": subField.AssertShowDecimal(1L << (windowScale.ScaleFactorLog % 32)); break; default: throw new InvalidOperationException("Invalid tcp options subfield " + subField.Name()); } } break; case TcpOptionType.SelectiveAcknowledgment: var selectiveAcknowledgmentOption = (TcpOptionSelectiveAcknowledgment)option; int blockIndex = 0; foreach (var subField in field.Fields()) { switch (subField.Name()) { case "tcp.options.sack": subField.AssertShowDecimal(true); break; case "tcp.options.sack_le": subField.AssertShowDecimal(selectiveAcknowledgmentOption.Blocks[blockIndex].LeftEdge); break; case "tcp.options.sack_re": subField.AssertShowDecimal(selectiveAcknowledgmentOption.Blocks[blockIndex].RightEdge); ++blockIndex; break; default: throw new InvalidOperationException("Invalid tcp options subfield " + subField.Name()); } } break; case TcpOptionType.Timestamp: var timestampOption = (TcpOptionTimestamp)option; foreach (var subField in field.Fields()) { switch (subField.Name()) { case "tcp.option_kind": subField.AssertShowDecimal((byte)option.OptionType); break; case "tcp.option_len": subField.AssertShowDecimal(option.Length); break; case "tcp.options.timestamp.tsval": subField.AssertShowDecimal(timestampOption.TimestampValue); break; case "tcp.options.timestamp.tsecr": subField.AssertShowDecimal(timestampOption.TimestampEchoReply); break; default: throw new InvalidOperationException("Invalid tcp options subfield " + subField.Name()); } } break; default: field.AssertNoFields(); break; } ++currentOptionIndex; break; case "tcp.options.mss": Assert.AreEqual(TcpOptionType.MaximumSegmentSize, option.OptionType); field.AssertShowDecimal(true); field.AssertNoFields(); break; case "tcp.options.mss_val": field.AssertShowDecimal(((TcpOptionMaximumSegmentSize)option).MaximumSegmentSize); field.AssertNoFields(); ++currentOptionIndex; break; case "tcp.options.echo": Assert.IsTrue(option is TcpOptionEchoReply || option is TcpOptionEcho); field.AssertShowDecimal(1); field.AssertNoFields(); break; case "tcp.options.cc": Assert.IsTrue(option is TcpOptionConnectionCountBase); field.AssertShowDecimal(1); field.AssertNoFields(); break; case "tcp.options.scps.vector": Assert.AreEqual((TcpOptionType)20, option.OptionType); if (field.Show() == "0") { ++currentOptionIndex; } ++currentOptionIndex; break; case "tcp.options.scps": Assert.AreEqual((TcpOptionType)20, option.OptionType); Assert.IsFalse(field.Fields().Any()); break; case "tcp.options.snack": // TODO: Support Selective Negative Acknowledgements. case "tcp.options.snack.offset": case "tcp.options.snack.size": Assert.AreEqual(TcpOptionType.SelectiveNegativeAcknowledgements, option.OptionType); field.AssertNoFields(); break; case "tcp.options.sack_perm": Assert.AreEqual(TcpOptionType.SelectiveAcknowledgmentPermitted, option.OptionType); field.AssertNoFields(); ++currentOptionIndex; break; case "tcp.options.rvbd.probe": Assert.AreEqual((TcpOptionType)76, option.OptionType); // TODO: Support Riverbed. ++currentOptionIndex; break; case "tcp.options.rvbd.trpy": Assert.AreEqual((TcpOptionType)78, option.OptionType); // TODO: Support Riverbed. ++currentOptionIndex; break; default: throw new InvalidOperationException("Invalid tcp options field " + field.Name()); } } }
internal override bool EqualsData(TcpOption other) { return EqualsData(other as TcpOptionMood); }
internal override bool EqualsData(TcpOption other) { return EqualsData(other as TcpOptionMaximumSegmentSize); }
internal override bool EqualsData(TcpOption other) { return EqualsData(other as TcpOptionAlternateChecksumRequest); }
public static string GetWiresharkString(this TcpOption option) { switch (option.OptionType) { case TcpOptionType.EndOfOptionList: return("End of Option List (EOL)"); case TcpOptionType.NoOperation: return("No-Operation (NOP)"); case TcpOptionType.WindowScale: byte scaleFactorLog = ((TcpOptionWindowScale)option).ScaleFactorLog; return(string.Format("Window scale: {0} (multiply by {1})", scaleFactorLog, (1L << (scaleFactorLog % 32)))); case TcpOptionType.SelectiveAcknowledgmentPermitted: return("SACK permitted"); case TcpOptionType.SelectiveAcknowledgment: IEnumerable <TcpOptionSelectiveAcknowledgmentBlock> blocks = ((TcpOptionSelectiveAcknowledgment)option).Blocks; return("SACK:" + (blocks.Count() == 0 ? string.Empty : ((TcpOptionSelectiveAcknowledgment)option).Blocks.SequenceToString(" ", " "))); case TcpOptionType.Echo: return("Echo: " + ((TcpOptionEcho)option).Info); case TcpOptionType.EchoReply: return("Echo reply: " + ((TcpOptionEchoReply)option).Info); case TcpOptionType.Timestamp: TcpOptionTimestamp timestampOption = (TcpOptionTimestamp)option; return("Timestamps: TSval " + timestampOption.TimestampValue + ", TSecr " + timestampOption.TimestampEchoReply); case TcpOptionType.ConnectionCount: return("CC: " + ((TcpOptionConnectionCount)option).ConnectionCount); case TcpOptionType.ConnectionCountNew: return("CC.NEW: " + ((TcpOptionConnectionCountNew)option).ConnectionCount); case TcpOptionType.ConnectionCountEcho: return("CC.ECHO: " + ((TcpOptionConnectionCountEcho)option).ConnectionCount); case TcpOptionType.Md5Signature: return("TCP MD5 signature"); case (TcpOptionType)20: return("SCPS capabilities" + (option.Length >= 4 ? string.Empty : " (with option length = " + option.Length + " bytes; should be >= 4)")); case (TcpOptionType)21: return("Selective Negative Acknowledgement" + (option.Length == 6 ? string.Empty : " (with option length = " + option.Length + " bytes; should be 6)")); case (TcpOptionType)22: return("SCPS record boundary" + (option.Length == 2 ? string.Empty : " (with option length = " + option.Length + " bytes; should be 2)")); case (TcpOptionType)23: return("SCPS corruption experienced" + (option.Length == 2 ? string.Empty : " (with option length = " + option.Length + " bytes; should be 2)")); case TcpOptionType.PartialOrderConnectionPermitted: // 9. case TcpOptionType.PartialOrderServiceProfile: // 10. case TcpOptionType.AlternateChecksumRequest: // 14. case TcpOptionType.AlternateChecksumData: // 15. case TcpOptionType.Mood: // 25. return(string.Format("Unknown (0x{0}) ({1} bytes)", ((byte)option.OptionType).ToString("x2"), option.Length)); default: if (typeof(TcpOptionType).GetEnumValues <TcpOptionType>().Contains(option.OptionType)) { throw new InvalidOperationException("Invalid option type " + option.OptionType); } return(string.Format("Unknown (0x{0}) ({1} bytes)", ((byte)option.OptionType).ToString("x2"), option.Length)); } }