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);
 }
示例#4
0
        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);
            }
        }
示例#5
0
 internal override bool EqualsData(TcpOption other)
 {
     return EqualsData(other as TcpOptionMd5Signature);
 }
 internal sealed override bool EqualsData(TcpOption other)
 {
     return(EqualsData(other as TcpOptionConnectionCountBase));
 }
示例#7
0
 internal override bool EqualsData(TcpOption other)
 {
     return other is TcpOptionSimple;
 }
 internal override bool EqualsData(TcpOption other)
 {
     return EqualsData(other as TcpOptionAuthentication);
 }
示例#9
0
 internal override bool EqualsData(TcpOption other)
 {
     return EqualsData(other as TcpOptionWindowScale);
 }
示例#10
0
 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);
 }
示例#13
0
 internal override bool EqualsData(TcpOption other)
 {
     return(other is TcpOptionSimple);
 }
示例#14
0
 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);
 }
示例#19
0
        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());
                }
            }
        }
示例#20
0
 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));
            }
        }