Esempio n. 1
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());
                }
            }
        }
        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());
                }
            }
        }