コード例 #1
0
        private void MapIpV6Data(IpV6Datagram datagram)
        {
            this.SourceIp = datagram.Source.ToString();

            if (string.IsNullOrEmpty(this.DestinationIp))
            {
                // only set if not already set for ipv6, may be routing address
                this.DestinationIp = datagram.CurrentDestination.ToString();
            }

            var payloadProtocol = datagram.ExtensionHeaders.NextHeader ?? datagram.NextHeader;

            switch (payloadProtocol)
            {
            case IpV4Protocol.Tcp:
                this.MapTcpData(datagram.Tcp);
                break;

            case IpV4Protocol.Udp:
                this.MapUdpData(datagram.Udp);
                break;

            case IpV4Protocol.InternetControlMessageProtocolForIpV6:
                this.MapIcmpData(datagram.Icmp);
                break;

            default:
                throw new Exception($"Unsupported IPv6 Protocol. ({payloadProtocol})");
            }
        }
コード例 #2
0
 private void SkipAuthenticationHeaders(IpV6Datagram ipV6Datagram)
 {
     while (_currentExtensionHeaderIndex < ipV6Datagram.ExtensionHeaders.Headers.Count &&
            ipV6Datagram.ExtensionHeaders[_currentExtensionHeaderIndex].Protocol == IpV4Protocol.AuthenticationHeader)
     {
         ++_currentExtensionHeaderIndex;
     }
 }
コード例 #3
0
        private static string GetConnString(PcapDotNet.Packets.Packet packet)
        {
            String           srcIp = "";
            String           dstIp = "";
            TcpDatagram      tcp   = null;
            EthernetDatagram eth   = packet.Ethernet;

            switch (eth.EtherType)
            {
            case EthernetType.IpV4:
                IpV4Datagram ip = eth.IpV4;
                tcp   = ip.Tcp;
                srcIp = ip.Source.ToString();
                dstIp = ip.Destination.ToString();
                break;

            case EthernetType.IpV6:
                IpV6Datagram ip6 = eth.IpV6;
                tcp   = ip6.Tcp;
                srcIp = ip6.Source.ToString();
                dstIp = ip6.CurrentDestination.ToString();
                break;

            default:
                Console.WriteLine("We should never see anything not ipv4 or ipv6 since we filtered by tcp");
                return("");
            }

            StringBuilder sb = new StringBuilder();

            sb.Append(srcIp);
            sb.Append(":");
            sb.Append(tcp.SourcePort);
            sb.Append(" to ");
            sb.Append(dstIp);
            sb.Append(":");
            sb.Append(tcp.DestinationPort);
            return(sb.ToString());
        }
コード例 #4
0
        protected bool CompareDatagram(XElement layer, Datagram parentDatagram, Datagram datagram)
        {
            bool success = true;

            foreach (var element in layer.Fields())
            {
                // TODO: Remove this hack when https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=11802 is fixed.
                IpV6Datagram ipV6ParentDatagram = parentDatagram as IpV6Datagram;
                if (ipV6ParentDatagram != null && (ipV6ParentDatagram.NextHeader == IpV4Protocol.IsoIp || ipV6ParentDatagram.ExtensionHeaders.NextHeader == IpV4Protocol.IsoIp))
                {
                    return(false);
                }
                if (!CompareField(element, parentDatagram, datagram))
                {
                    success = false;
                    break;
                }
            }

            WiresharkCompareTests.CompareProtocols(datagram, layer, success);
            return(success);
        }
コード例 #5
0
        private void HandlePacket(PcapDotNet.Packets.Packet packet)
        {
            //give up if 10 errors are seen to prevent unexpected crashes
            if (numErrors > 10)
            {
                return;
            }
            String           srcIp = "";
            TcpDatagram      tcp   = null;
            EthernetDatagram eth   = packet.Ethernet;
            int dataStart          = eth.HeaderLength;

            switch (eth.EtherType)
            {
            case EthernetType.IpV4:
                IpV4Datagram ip = eth.IpV4;
                tcp        = ip.Tcp;
                srcIp      = ip.Source.ToString();
                dataStart += ip.HeaderLength + tcp.RealHeaderLength;
                break;

            case EthernetType.IpV6:
                IpV6Datagram ip6 = eth.IpV6;
                tcp        = ip6.Tcp;
                srcIp      = ip6.Source.ToString();
                dataStart += 40 + tcp.RealHeaderLength;
                Console.WriteLine("IPv6?");
                break;

            default:
                Console.WriteLine("We should never see anything not ipv4 or ipv6 since we filtered by tcp");
                return;
            }

            ushort srcPort   = tcp.SourcePort;
            int    dataBytes = tcp.PayloadLength;
            bool   syn       = tcp.IsSynchronize;

            //Console.WriteLine("dataStart={0} dataByes={1} srcPort={2} syn={3} srcIp={4}",dataStart,dataBytes,srcPort,syn,srcIp);

            if (syn && dataBytes == 0)
            {
                ct = new ServiceCore.CryptoTransformHeroes();
                ClearBuffer();
                if (myIp == srcIp)
                {
                    int dstPort = tcp.DestinationPort;
                    encryptDict.TryGetValue(dstPort, out encrypt);
                    serviceDict.TryGetValue(dstPort, out serviceType);
                }
                else
                {
                    encryptDict.TryGetValue(srcPort, out encrypt);
                    serviceDict.TryGetValue(srcPort, out serviceType);
                }
                Console.WriteLine("TCP connection starting with type {0} to {1}", encrypt, serviceType);
                SawSyn = true;
                return;
            }
            else if (!SawSyn)
            {
                Console.WriteLine("Haven't seen SYN yet from {0}", srcPort);
                return;
            }
            if (encrypt == EncryptionType.Relay || encrypt == EncryptionType.Pipe)
            {
                Console.WriteLine("Cannot handle type {0} from {1}", encrypt, serviceType);
                return;
            }
            if (dataBytes == 6 || dataBytes == 0)
            {
                //Console.WriteLine("Ping from port {0}", srcPort);
                ClearBuffer();
                return;
            }

            //String timestamp = packet.Timestamp.ToString("yyyy-MM-dd hh:mm:ss.fff");
            //Console.WriteLine("{0}: {1} bytes={2}", timestamp, connString, dataBytes);

            recvSize.AddLast(dataBytes);
            Buffer.BlockCopy(packet.Buffer, dataStart, buffer, bufLen, dataBytes);

            ArraySegment <byte> dataSeg = new ArraySegment <byte>(buffer, bufLen, dataBytes);

            Devcat.Core.Net.Message.Packet p = new Devcat.Core.Net.Message.Packet(dataSeg);
            if (encrypt == EncryptionType.Normal)
            {
                long salt = p.InstanceId;
                ct.Decrypt(dataSeg, salt);
            }

            bufLen += dataBytes;

            while (bufLen != 0)
            {
                dataSeg = new ArraySegment <byte>(buffer, 0, bufLen);
                p       = new Devcat.Core.Net.Message.Packet(dataSeg);
                int pLen = 0;
                try
                {
                    pLen = p.Length + p.BodyOffset;
                    if (pLen == 0)
                    {
                        ClearBuffer();
                        //Console.WriteLine("Received ping");
                        return;
                    }
                    else
                    {
                        //Console.WriteLine("bufLen={0} pLen={1} recvSize={2}", bufLen, pLen, recvSizeToString());
                    }
                }
                catch (System.Runtime.Serialization.SerializationException)
                {
                    //Console.WriteLine("{0}: Bad length {1}", connString, e.Message);
                    RemovePacket();
                    numErrors++;
                    continue;
                }

                if (pLen > bufLen)
                {
                    return;
                }
                if (pLen <= 3 || pLen == 6)
                {
                    //ClearBuffer();
                    ShortenBuffer(pLen);
                    numErrors++;
                    Console.WriteLine("{0}: Invalid data packet with Length={1}", connString, pLen);
                    continue;
                }
                //Console.WriteLine("Read {0} bytes but need {1} bytes, creating object", bufLen, pLen);
                dataSeg = new ArraySegment <byte>(buffer, 0, pLen);
                p       = new Devcat.Core.Net.Message.Packet(dataSeg);
                try
                {
                    Console.WriteLine(p);
                    if (srcIp == myIp)
                    {
                        Console.WriteLine("Client->{0}:", serviceType);
                    }
                    else
                    {
                        Console.WriteLine("Server {0}:", serviceType);
                    }
                    if (classNames.Count == 0)
                    {
                        ProcessTypeConverter(p);
                        Console.WriteLine("Received TypeConverter");
                        //String reverse = reverseConnString(connString);
                        //Console.WriteLine("Sending TypeConverter to Client {0}",reverse);
                        //portHandler[reverse].processTypeConverter(p);
                    }
                    else
                    {
                        mf.Handle(p, null);
                    }
                    ShortenBuffer(pLen);
                }
                catch (InvalidOperationException e)
                {
                    Console.WriteLine(e);
                    String errMsg     = e.Message;
                    String className  = "";
                    int    categoryId = p.CategoryId;
                    ShortenBuffer(pLen);
                    MatchCollection mc;
                    if (classNames.TryGetValue(categoryId, out className))
                    {
                        LogUnhandledClass(className);
                        return;
                    }
                    mc = Regex.Matches(errMsg, @"\.([^,\.]{2,})(,|$)");
                    if (mc.Count != 0)
                    {
                        className = mc[0].Groups[1].ToString();
                        LogUnhandledClass(className);
                        return;
                    }
                    Console.WriteLine("{0}: Unknown class error {1}", connString, errMsg);
                }
                catch (System.Runtime.Serialization.SerializationException e)
                {
                    Console.WriteLine("{0}: The packet wasn't ready {1}", connString, e.Message);
                    RemovePacket();
                    numErrors++;
                }
                catch (System.ArgumentOutOfRangeException e)
                {
                    Console.WriteLine("{0}: The packet was too short: {1}", connString, e.Message);
                    ShortenBuffer(pLen);
                    numErrors++;
                }
                catch (System.ArgumentException e)
                {
                    Console.WriteLine("{0}: Serializing failed bacause a dict was made with 2 identical keys: {1}", connString, e.StackTrace);
                    ClearBuffer();
                    numErrors++;
                }
            }
        }
コード例 #6
0
 private void IncrementCurrentExtensionHeaderIndex(IpV6Datagram ipV6Datagram)
 {
     ++_currentExtensionHeaderIndex;
     SkipAuthenticationHeaders(ipV6Datagram);
 }
コード例 #7
0
        private void CompareOptions(XElement field, ref int optionsIndex, IpV6Datagram ipV6Datagram, IpV6ExtensionHeaderOptions header)
        {
            foreach (var headerField in field.Fields())
            {
                switch (headerField.Name())
                {
                case "ipv6.nxt":
                    headerField.AssertNoFields();
                    headerField.AssertShowDecimal((byte)header.NextHeader);
                    break;

                case "ipv6.opt.length":
                    headerField.AssertNoFields();
                    headerField.AssertShowDecimal((header.Length - 8) / 8);
                    break;

                case "ipv6.opt":
                    foreach (XElement headerSubfield in headerField.Fields())
                    {
                        IpV6Option option           = header.Options[optionsIndex];
                        var        optionCalipso    = option as IpV6OptionCalipso;
                        var        optionQuickStart = option as IpV6OptionQuickStart;
                        switch (headerSubfield.Name())
                        {
                        case "ipv6.opt.type":
                            headerSubfield.AssertNoFields();
                            headerSubfield.AssertShowDecimal((byte)option.OptionType);
                            break;

                        case "ipv6.opt.length":
                            headerSubfield.AssertNoFields();
                            headerSubfield.AssertShowDecimal(option.Length - 2);
                            break;

                        case "ipv6.opt.tel":
                            headerSubfield.AssertNoFields();
                            IpV6OptionTunnelEncapsulationLimit optionTunnelEncapsulationLimit = (IpV6OptionTunnelEncapsulationLimit)option;
                            headerSubfield.AssertShowDecimal(optionTunnelEncapsulationLimit.TunnelEncapsulationLimit);
                            ++optionsIndex;
                            break;

                        case "ipv6.opt.rpl.flag":
                            IpV6OptionRoutingProtocolLowPowerAndLossyNetworks optionRoutingProtocolLowPowerAndLossyNetworks =
                                (IpV6OptionRoutingProtocolLowPowerAndLossyNetworks)option;
                            foreach (XElement optionSubfield in headerSubfield.Fields())
                            {
                                optionSubfield.AssertNoFields();
                                switch (optionSubfield.Name())
                                {
                                case "ipv6.opt.rpl.flag.o":
                                    optionSubfield.AssertShowDecimal(optionRoutingProtocolLowPowerAndLossyNetworks.Down);
                                    break;

                                case "ipv6.opt.rpl.flag.r":
                                    optionSubfield.AssertShowDecimal(optionRoutingProtocolLowPowerAndLossyNetworks.RankError);
                                    break;

                                case "ipv6.opt.rpl.flag.f":
                                    optionSubfield.AssertShowDecimal(optionRoutingProtocolLowPowerAndLossyNetworks.ForwardingError);
                                    break;

                                case "ipv6.opt.rpl.flag.rsv":
                                    optionSubfield.AssertShowDecimal(0);
                                    break;

                                case "ipv6.opt.rpl.instance_id":
                                    optionSubfield.AssertShowDecimal(
                                        optionRoutingProtocolLowPowerAndLossyNetworks.RoutingProtocolLowPowerAndLossyNetworksInstanceId);
                                    break;

                                case "ipv6.opt.rpl.sender_rank":
                                    optionSubfield.AssertShowDecimal(optionRoutingProtocolLowPowerAndLossyNetworks.SenderRank);
                                    break;

                                default:
                                    throw new InvalidOperationException("Invalid ipv6 option subfield " + optionSubfield.Name());
                                }
                            }
                            ++optionsIndex;
                            // TODO: change to break; after https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=10559 is fixed.
                            return;

                        case "ipv6.opt.calipso.doi":
                            headerSubfield.AssertNoFields();
                            headerSubfield.AssertShowDecimal((uint)optionCalipso.DomainOfInterpretation);
                            break;

                        case "ipv6.opt.calipso.cmpt.length":
                            headerSubfield.AssertNoFields();
                            headerSubfield.AssertShowDecimal(optionCalipso.CompartmentLength);
                            break;

                        case "ipv6.opt.calipso.sens_level":
                            headerSubfield.AssertNoFields();
                            headerSubfield.AssertShowDecimal(optionCalipso.SensitivityLevel);
                            break;

                        case "ipv6.opt.calipso.checksum":
                            headerSubfield.AssertNoFields();
                            headerSubfield.AssertShowDecimal(optionCalipso.Checksum);
                            break;

                        case "ipv6.opt.calipso.cmpt_bitmap":
                            headerSubfield.AssertNoFields();
                            headerSubfield.AssertValue(optionCalipso.CompartmentBitmap);
                            ++optionsIndex;
                            break;

                        case "ipv6.opt.router_alert":
                            headerSubfield.AssertNoFields();
                            var optionRouterAlert = (IpV6OptionRouterAlert)option;
                            headerSubfield.AssertShowDecimal((ushort)optionRouterAlert.RouterAlertType);
                            ++optionsIndex;
                            break;

                        case "ipv6.opt.padn":
                            headerSubfield.AssertNoFields();
                            var optionPadN = (IpV6OptionPadN)option;
                            headerSubfield.AssertValue(new byte[optionPadN.PaddingDataLength]);
                            ++optionsIndex;
                            break;

                        case "ipv6.opt.qs_func":
                            headerSubfield.AssertNoFields();
                            headerSubfield.AssertShowDecimal((byte)optionQuickStart.QuickStartFunction);
                            break;

                        case "ipv6.opt.qs_rate":
                            headerSubfield.AssertNoFields();
                            headerSubfield.AssertShowDecimal(optionQuickStart.Rate);
                            break;

                        case "ipv6.opt.qs_ttl":
                            headerSubfield.AssertNoFields();
                            headerSubfield.AssertShowDecimal(optionQuickStart.Ttl);
                            break;

                        case "ipv6.opt.qs_ttl_diff":
                            headerSubfield.AssertNoFields();
                            headerSubfield.AssertShowDecimal((256 + ipV6Datagram.HopLimit - optionQuickStart.Ttl) % 256);
                            break;

                        case "ipv6.opt.qs_unused":
                            headerSubfield.AssertNoFields();
                            headerSubfield.AssertShowDecimal(optionQuickStart.Ttl);
                            break;

                        case "ipv6.opt.qs_nonce":
                            headerSubfield.AssertNoFields();
                            headerSubfield.AssertShowDecimal(optionQuickStart.Nonce);
                            break;

                        case "ipv6.opt.qs_reserved":
                            headerSubfield.AssertNoFields();
                            headerSubfield.AssertShowDecimal(0);
                            ++optionsIndex;
                            break;

                        case "ipv6.opt.pad1":
                            headerSubfield.AssertNoFields();
                            headerSubfield.AssertShow("");
                            Assert.IsTrue(option is IpV6OptionPad1);
                            ++optionsIndex;
                            break;

                        case "ipv6.opt.jumbo":
                            headerSubfield.AssertNoFields();
                            headerSubfield.AssertShowDecimal(((IpV6OptionJumboPayload)option).JumboPayloadLength);
                            ++optionsIndex;
                            break;

                        case "ipv6.mipv6_home_address":
                            headerSubfield.AssertNoFields();
                            headerSubfield.AssertShow(((IpV6OptionHomeAddress)option).HomeAddress.GetWiresharkString());
                            ++optionsIndex;
                            break;

                        case "ipv6.opt.unknown":
                            headerSubfield.AssertNoFields();
                            Assert.IsTrue(new[]
                            {
                                IpV6OptionType.LineIdentification,
                                IpV6OptionType.IdentifierLocatorNetworkProtocolNonce,
                                IpV6OptionType.SimplifiedMulticastForwardingDuplicatePacketDetection,
                                IpV6OptionType.EndpointIdentification,
                            }.Contains(option.OptionType),
                                          option.OptionType.ToString());
                            ++optionsIndex;
                            break;

                        default:
                            throw new InvalidOperationException("Invalid ipv6 header subfield " + headerSubfield.Name());
                        }
                    }
                    break;

                default:
                    throw new InvalidOperationException("Invalid ipv6 options field " + headerField.Name());
                }
            }
        }
コード例 #8
0
        protected override bool CompareField(XElement field, Datagram datagram)
        {
            IpV6Datagram ipV6Datagram = (IpV6Datagram)datagram;

            SkipAuthenticationHeaders(ipV6Datagram);
            int optionsIndex = 0;

            switch (field.Name())
            {
            case "ipv6.version":
                field.AssertShowDecimal(ipV6Datagram.Version);
                foreach (XElement subfield in field.Fields())
                {
                    switch (subfield.Name())
                    {
                    case "ip.version":
                        subfield.AssertShowDecimal(ipV6Datagram.Version);
                        break;

                    default:
                        throw new InvalidOperationException(string.Format("Invalid ipv6 version subfield {0}", subfield.Name()));
                    }
                }
                break;

            case "ipv6.class":
                field.AssertShowDecimal(ipV6Datagram.TrafficClass);
                break;

            case "ipv6.flow":
                field.AssertShowDecimal(ipV6Datagram.FlowLabel);
                field.AssertNoFields();
                break;

            case "ipv6.plen":
                field.AssertShowDecimal(ipV6Datagram.PayloadLength);
                field.AssertNoFields();
                break;

            case "ipv6.nxt":
                field.AssertShowDecimal((byte)ipV6Datagram.NextHeader);
                field.AssertNoFields();
                break;

            case "ipv6.hlim":
                field.AssertShowDecimal(ipV6Datagram.HopLimit);
                field.AssertNoFields();
                break;

            case "ipv6.src":
            case "ipv6.src_host":
                field.AssertShow(ipV6Datagram.Source.GetWiresharkString());
                field.AssertNoFields();
                break;

            case "ipv6.src_6to4_gw_ipv4":
            case "ipv6.src_6to4_sla_id":
            case "ipv6.6to4_gw_ipv4":
            case "ipv6.6to4_sla_id":
                field.AssertNoFields();
                break;

            case "ipv6.dst":
            case "ipv6.dst_host":
                field.AssertShow(ipV6Datagram.CurrentDestination.GetWiresharkString());
                field.AssertNoFields();
                break;

            case "ipv6.addr":
            case "ipv6.host":
                Assert.IsTrue(field.Show() == ipV6Datagram.Source.GetWiresharkString() ||
                              field.Show() == ipV6Datagram.CurrentDestination.GetWiresharkString());
                field.AssertNoFields();
                break;

            case "ipv6.hop_opt":
                if (_currentExtensionHeaderIndex >= ipV6Datagram.ExtensionHeaders.Headers.Count)
                {
                    Assert.IsFalse(ipV6Datagram.ExtensionHeaders.IsValid);
                    int maxLength = ipV6Datagram.Length - IpV6Datagram.HeaderLength - ipV6Datagram.ExtensionHeaders.BytesLength;
                    if (field.Fields().Any(subfield => subfield.Name() == "ipv6.opt.length"))
                    {
                        int length = int.Parse(field.Fields().First(subfield => subfield.Name() == "ipv6.opt.length").Show());
                        MoreAssert.IsBigger(maxLength, length);
                    }
                    else
                    {
                        Assert.AreEqual(6, maxLength);
                    }
                }
                else
                {
                    IpV6ExtensionHeaderHopByHopOptions hopByHopOptions =
                        (IpV6ExtensionHeaderHopByHopOptions)ipV6Datagram.ExtensionHeaders[_currentExtensionHeaderIndex];
                    IncrementCurrentExtensionHeaderIndex(ipV6Datagram);
                    CompareOptions(field, ref optionsIndex, ipV6Datagram, hopByHopOptions);
                }
                break;

            case "ipv6.routing_hdr":
                if (!ipV6Datagram.IsValid)
                {
                    return(false);
                }
                IpV6ExtensionHeaderRouting routing = (IpV6ExtensionHeaderRouting)ipV6Datagram.ExtensionHeaders[_currentExtensionHeaderIndex];
                IpV6ExtensionHeaderRoutingProtocolLowPowerAndLossyNetworks routingProtocolLowPowerAndLossyNetworks =
                    routing as IpV6ExtensionHeaderRoutingProtocolLowPowerAndLossyNetworks;
                int routingProtocolLowPowerAndLossyNetworksAddressIndex = 0;
                IncrementCurrentExtensionHeaderIndex(ipV6Datagram);
                int sourceRouteAddressIndex = 0;
                foreach (var headerField in field.Fields())
                {
                    switch (headerField.Name())
                    {
                    case "":
                        headerField.AssertNoFields();
                        ValidateExtensionHeaderUnnamedField(routing, headerField);
                        break;

                    case "ipv6.routing_hdr.type":
                        headerField.AssertNoFields();
                        headerField.AssertShowDecimal((byte)routing.RoutingType);
                        break;

                    case "ipv6.routing_hdr.left":
                        headerField.AssertNoFields();
                        headerField.AssertShowDecimal(routing.SegmentsLeft);
                        break;

                    case "ipv6.mipv6_home_address":
                        headerField.AssertNoFields();
                        IpV6ExtensionHeaderRoutingHomeAddress routingHomeAddress = (IpV6ExtensionHeaderRoutingHomeAddress)routing;
                        headerField.AssertShow(routingHomeAddress.HomeAddress.ToString("x"));
                        break;

                    case "ipv6.routing_hdr.addr":
                        headerField.AssertNoFields();
                        IpV6ExtensionHeaderRoutingSourceRoute routingSourceRoute = (IpV6ExtensionHeaderRoutingSourceRoute)routing;
                        headerField.AssertShow(routingSourceRoute.Addresses[sourceRouteAddressIndex++].ToString("x"));
                        break;

                    case "ipv6.routing_hdr.rpl.cmprI":
                        headerField.AssertNoFields();
                        headerField.AssertShowDecimal(routingProtocolLowPowerAndLossyNetworks.CommonPrefixLengthForNonLastAddresses);
                        break;

                    case "ipv6.routing_hdr.rpl.cmprE":
                        headerField.AssertNoFields();
                        headerField.AssertShowDecimal(routingProtocolLowPowerAndLossyNetworks.CommonPrefixLengthForLastAddress);
                        break;

                    case "ipv6.routing_hdr.rpl.pad":
                        headerField.AssertNoFields();
                        headerField.AssertShowDecimal(routingProtocolLowPowerAndLossyNetworks.PadSize);
                        break;

                    case "ipv6.routing_hdr.rpl.reserved":
                        headerField.AssertNoFields();
                        headerField.AssertShowDecimal(0);
                        break;

                    case "ipv6.routing_hdr.rpl.segments":
                        if (headerField.Fields().Any())
                        {
                            headerField.AssertNumFields(1);
                            headerField.Fields().First().AssertName("_ws.expert");
                        }
                        // TODO: Remove this condition when https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=11803 is fixed.
                        if (routingProtocolLowPowerAndLossyNetworks.Addresses.Count > 0)
                        {
                            headerField.AssertShowDecimal(routingProtocolLowPowerAndLossyNetworks.Addresses.Count);
                        }
                        break;

                    case "ipv6.routing_hdr.rpl.address":
                        headerField.AssertNoFields();
                        // TODO: Remove this condition when https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=11803 is fixed.
                        if (routingProtocolLowPowerAndLossyNetworks.Addresses.Count > 0)
                        {
                            IpV6Address actualAddress =
                                new IpV6Address(UInt128.Parse(headerField.Value(), NumberStyles.HexNumber, CultureInfo.InvariantCulture));
                            Assert.AreEqual(routingProtocolLowPowerAndLossyNetworks.Addresses[routingProtocolLowPowerAndLossyNetworksAddressIndex],
                                            actualAddress);
                        }
                        break;

                    case "ipv6.routing_hdr.rpl.full_address":
                        headerField.AssertNoFields();
                        // TODO: Uncomment the following code when https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=10673 is fixed.
//                                // TODO: Remove this condition when https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=11803 is fixed.
//                                if (routingProtocolLowPowerAndLossyNetworks.Addresses.Count > 0)
//                                {
//                                    IpV6Address actualFullAddress = new IpV6Address(headerField.Show());
//
//                                    IpV6Address destinationAddress = ipV6Datagram.CurrentDestination;
//                                    for (int i = 0; i < _currentExtensionHeaderIndex; ++i)
//                                    {
//                                        IpV6ExtensionHeaderRoutingHomeAddress ipV6ExtensionHeaderRoutingHomeAddress =
//                                            ipV6Datagram.ExtensionHeaders[i] as IpV6ExtensionHeaderRoutingHomeAddress;
//                                        if (ipV6ExtensionHeaderRoutingHomeAddress != null)
//                                            destinationAddress = ipV6ExtensionHeaderRoutingHomeAddress.HomeAddress;
//
//                                        IpV6ExtensionHeaderRoutingSourceRoute ipV6ExtensionHeaderRoutingSourceRoute =
//                                            ipV6Datagram.ExtensionHeaders[i] as IpV6ExtensionHeaderRoutingSourceRoute;
//                                        if (ipV6ExtensionHeaderRoutingSourceRoute != null && ipV6ExtensionHeaderRoutingSourceRoute.Addresses.Any())
//                                            destinationAddress = ipV6ExtensionHeaderRoutingSourceRoute.Addresses.Last();
//                                    }
//
//                                    int commonPrefixLength =
//                                        routingProtocolLowPowerAndLossyNetworksAddressIndex == routingProtocolLowPowerAndLossyNetworks.Addresses.Count - 1
//                                            ? routingProtocolLowPowerAndLossyNetworks.CommonPrefixLengthForLastAddress
//                                            : routingProtocolLowPowerAndLossyNetworks.CommonPrefixLengthForNonLastAddresses;
//
//                                    byte[] destinationAddressBytes = new byte[IpV6Address.SizeOf];
//                                    destinationAddressBytes.Write(0, destinationAddress, Endianity.Big);
//
//                                    byte[] routingAddressBytes = new byte[IpV6Address.SizeOf];
//                                    routingAddressBytes.Write(0, routingProtocolLowPowerAndLossyNetworks.Addresses[routingProtocolLowPowerAndLossyNetworksAddressIndex], Endianity.Big);
//
//                                    byte[] fullAddressBytes = destinationAddressBytes.Subsegment(0, commonPrefixLength).Concat(routingAddressBytes.Subsegment(commonPrefixLength, IpV6Address.SizeOf - commonPrefixLength)).ToArray();
//                                    IpV6Address expectedFullAddress = fullAddressBytes.ReadIpV6Address(0, Endianity.Big);
//
//                                    Assert.AreEqual(expectedFullAddress, actualFullAddress);
//                                }

                        ++routingProtocolLowPowerAndLossyNetworksAddressIndex;
                        break;

                    default:
                        throw new InvalidOperationException("Invalid IPv6 routing source route field " + headerField.Name());
                    }
                }
                break;

            case "ipv6.dst_opt":
                if (_currentExtensionHeaderIndex >= ipV6Datagram.ExtensionHeaders.Headers.Count)
                {
                    int expectedExtensionHeaderLength = (int.Parse(field.Fields().Skip(1).First().Value(), NumberStyles.HexNumber) + 1) * 8;
                    int actualMaxPossibleLength       = ipV6Datagram.RealPayloadLength -
                                                        ipV6Datagram.ExtensionHeaders.Take(_currentExtensionHeaderIndex).Sum(
                        extensionHeader => extensionHeader.Length);
                    MoreAssert.IsSmaller(expectedExtensionHeaderLength, actualMaxPossibleLength);
                    return(false);
                }
                IpV6ExtensionHeaderDestinationOptions destinationOptions = (IpV6ExtensionHeaderDestinationOptions)ipV6Datagram.ExtensionHeaders[_currentExtensionHeaderIndex];
                IncrementCurrentExtensionHeaderIndex(ipV6Datagram);
                CompareOptions(field, ref optionsIndex, ipV6Datagram, destinationOptions);
                break;

            case "ipv6.shim6":
                // TODO: Implement Shim6.
                IpV4Protocol nextHeader = _currentExtensionHeaderIndex > 0
                                                  ? ipV6Datagram.ExtensionHeaders[_currentExtensionHeaderIndex - 1].NextHeader.Value
                                                  : ipV6Datagram.NextHeader;
                Assert.IsTrue(nextHeader == IpV4Protocol.Shim6);
                break;

            case "ipv6.unknown_hdr":
                Assert.AreEqual(ipV6Datagram.ExtensionHeaders.Count(), _currentExtensionHeaderIndex);
                // TODO: Fix according to https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9996
                return(false);

            case "ipv6.src_sa_mac":
            case "ipv6.dst_sa_mac":
            case "ipv6.sa_mac":
            case "ipv6.dst_6to4_gw_ipv4":
            case "ipv6.dst_6to4_sla_id":
                // TODO: Understand how these are calculated.
                break;

            case "":
                switch (field.Show())
                {
                case "Fragmentation Header":
                    if (_currentExtensionHeaderIndex >= ipV6Datagram.ExtensionHeaders.Headers.Count && !ipV6Datagram.IsValid)
                    {
                        return(false);
                    }
                    IpV6ExtensionHeaderFragmentData fragmentData =
                        (IpV6ExtensionHeaderFragmentData)ipV6Datagram.ExtensionHeaders[_currentExtensionHeaderIndex];
                    IncrementCurrentExtensionHeaderIndex(ipV6Datagram);
                    foreach (var headerField in field.Fields())
                    {
                        switch (headerField.Name())
                        {
                        case "ipv6.fragment.nxt":
                            headerField.AssertValue((byte)fragmentData.NextHeader.Value);
                            break;

                        case "ipv6.fragment.offset":
                            headerField.AssertShowDecimal(fragmentData.FragmentOffset);
                            break;

                        case "ipv6.fragment.more":
                            headerField.AssertShowDecimal(fragmentData.MoreFragments);
                            break;

                        case "ipv6.fragment.id":
                            headerField.AssertShowDecimal(fragmentData.Identification);
                            break;

                        case "ipv6.fragment.reserved_octet":
                        case "ipv6.fragment.reserved_bits":
                            headerField.AssertShowDecimal(0);
                            break;

                        default:
                            throw new InvalidOperationException("Invalid ipv6 fragmentation field " + headerField.Name());
                        }
                    }
                    break;

                default:
                    throw new InvalidOperationException(string.Format("Invalid ipv6 field {0}", field.Show()));
                }
                break;

            default:
                throw new InvalidOperationException(string.Format("Invalid ipv6 field {0}", field.Name()));
            }

            return(true);
        }
        protected override bool CompareField(XElement field, Datagram datagram)
        {
            IpV6Datagram ipV6Datagram = datagram as IpV6Datagram;

            if (ipV6Datagram == null)
            {
                return(true);
            }
            while (_count > 0)
            {
                do
                {
                    ++_currentExtensionHeaderIndex;
                    if (_currentExtensionHeaderIndex >= ipV6Datagram.ExtensionHeaders.Headers.Count)
                    {
                        Assert.IsFalse(ipV6Datagram.ExtensionHeaders.IsValid);
                        return(false);
                    }
                } while (ipV6Datagram.ExtensionHeaders[_currentExtensionHeaderIndex].Protocol != IpV4Protocol.AuthenticationHeader);
                --_count;
            }
            IpV6ExtensionHeaderAuthentication authenticationHeader = (IpV6ExtensionHeaderAuthentication)ipV6Datagram.ExtensionHeaders[_currentExtensionHeaderIndex];

            switch (field.Name())
            {
            case "":
                string[] headerFieldShowParts = field.Show().Split(':');
                string   headerFieldShowName  = headerFieldShowParts[0];
                string   headerFieldShowValue = headerFieldShowParts[1];
                switch (headerFieldShowName)
                {
                case "Next Header":
                    field.AssertValue((byte)authenticationHeader.NextHeader.Value);
                    break;

                case "Length":
                    Assert.AreEqual(string.Format(" {0}", authenticationHeader.Length), headerFieldShowValue);
                    break;

                default:
                    throw new InvalidOperationException("Invalid ipv6 authentication header unnamed field show name " + headerFieldShowName);
                }
                break;

            case "ah.spi":
                field.AssertShowDecimal(authenticationHeader.SecurityParametersIndex);
                break;

            case "ah.sequence":
                field.AssertShowDecimal(authenticationHeader.SequenceNumber);
                break;

            case "ah.icv":
                field.AssertValue(authenticationHeader.AuthenticationData);
                break;

            default:
                throw new InvalidOperationException(string.Format("Invalid ipv6 authentication header field {0}", field.Name()));
            }

            return(true);
        }