internal override IpV6MobilityOption CreateInstance(DataSegment data)
        {
            if (data.Length < OptionDataMinimumLength)
            {
                return(null);
            }

            bool isIpV4 = data.ReadBool(Offset.IsIpV4, Mask.IsIpV4);
            bool isIpV6 = data.ReadBool(Offset.IsIpV6, Mask.IsIpV6);

            if (isIpV4 && !isIpV6)
            {
                if (data.Length != OptionDataMinimumLength + IpV4Address.SizeOf)
                {
                    return(null);
                }
                IpV4Address localMobilityAddress = data.ReadIpV4Address(Offset.LocalMobilityAddress, Endianity.Big);
                return(new IpV6MobilityOptionRedirect(localMobilityAddress));
            }
            if (isIpV6 && !isIpV4)
            {
                if (data.Length != OptionDataMinimumLength + IpV6Address.SizeOf)
                {
                    return(null);
                }
                IpV6Address localMobilityAddress = data.ReadIpV6Address(Offset.LocalMobilityAddress, Endianity.Big);
                return(new IpV6MobilityOptionRedirect(localMobilityAddress));
            }

            return(null);
        }
        internal static IpV6ExtensionHeaderMobilityHomeAgentSwitchMessage ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
        {
            if (messageData.Length < MinimumMessageDataLength)
            {
                return(null);
            }

            byte numberOfAddresses      = messageData[MessageDataOffset.NumberOfAddresses];
            int  homeAgentAddressesSize = numberOfAddresses * IpV6Address.SizeOf;

            if (messageData.Length < MinimumMessageDataLength + homeAgentAddressesSize)
            {
                return(null);
            }

            IpV6Address[] homeAgentAddresses = new IpV6Address[numberOfAddresses];
            for (int i = 0; i != numberOfAddresses; ++i)
            {
                homeAgentAddresses[i] = messageData.ReadIpV6Address(MessageDataOffset.HomeAgentAddresses + i * IpV6Address.SizeOf, Endianity.Big);
            }

            int optionsOffset           = MessageDataOffset.HomeAgentAddresses + homeAgentAddressesSize;
            IpV6MobilityOptions options = new IpV6MobilityOptions(messageData.Subsegment(optionsOffset, messageData.Length - optionsOffset));

            return(new IpV6ExtensionHeaderMobilityHomeAgentSwitchMessage(nextHeader, checksum, homeAgentAddresses, options));
        }
        internal override IpV6MobilityOption CreateInstance(DataSegment data)
        {
            if (data.Length < OptionDataMinimumLength)
            {
                return(null);
            }

            ushort bindingId = data.ReadUShort(Offset.BindingId, Endianity.Big);
            IpV6BindingAcknowledgementStatus status = (IpV6BindingAcknowledgementStatus)data[Offset.Status];
            bool simultaneousHomeAndForeignBinding  = data.ReadBool(Offset.SimultaneousHomeAndForeignBinding, Mask.SimultaneousHomeAndForeignBinding);
            byte priority = (byte)(data[Offset.Priority] & Mask.Priority);

            if (data.Length == OptionDataMinimumLength)
            {
                return(new IpV6MobilityOptionBindingIdentifier(bindingId, status, simultaneousHomeAndForeignBinding, priority));
            }
            if (data.Length == OptionDataMinimumLength + IpV4Address.SizeOf)
            {
                IpV4Address careOfAddress = data.ReadIpV4Address(Offset.CareOfAddress, Endianity.Big);
                return(new IpV6MobilityOptionBindingIdentifier(bindingId, status, simultaneousHomeAndForeignBinding, priority, careOfAddress));
            }
            if (data.Length == OptionDataMinimumLength + IpV6Address.SizeOf)
            {
                IpV6Address careOfAddress = data.ReadIpV6Address(Offset.CareOfAddress, Endianity.Big);
                return(new IpV6MobilityOptionBindingIdentifier(bindingId, status, simultaneousHomeAndForeignBinding, priority, careOfAddress));
            }
            return(null);
        }
        internal override IpV6MobilityOption CreateInstance(DataSegment data)
        {
            if (data.Length < OptionDataMinimumLength)
            {
                return(null);
            }

            IpV6LocalMobilityAnchorAddressCode code = (IpV6LocalMobilityAnchorAddressCode)data[Offset.Code];

            switch (code)
            {
            case IpV6LocalMobilityAnchorAddressCode.IpV6:
            {
                if (data.Length != Offset.LocalMobilityAnchorAddress + IpV6Address.SizeOf)
                {
                    return(null);
                }
                IpV6Address localMobilityAnchorAddress = data.ReadIpV6Address(Offset.LocalMobilityAnchorAddress, Endianity.Big);
                return(new IpV6MobilityOptionLocalMobilityAnchorAddress(localMobilityAnchorAddress));
            }

            case IpV6LocalMobilityAnchorAddressCode.IpV4:
            {
                if (data.Length != Offset.LocalMobilityAnchorAddress + IpV4Address.SizeOf)
                {
                    return(null);
                }
                IpV4Address localMobilityAnchorAddress = data.ReadIpV4Address(Offset.LocalMobilityAnchorAddress, Endianity.Big);
                return(new IpV6MobilityOptionLocalMobilityAnchorAddress(localMobilityAnchorAddress));
            }

            default:
                return(null);
            }
        }
 /// <summary>
 /// Creates an instance from next header, checksum, status, home address and options.
 /// </summary>
 /// <param name="nextHeader">
 /// Identifies the type of header immediately following this extension header.
 /// </param>
 /// <param name="checksum">
 /// Contains the checksum of the Mobility Header.
 /// The checksum is calculated from the octet string consisting of a "pseudo-header"
 /// followed by the entire Mobility Header starting with the Payload Proto field.
 /// The checksum is the 16-bit one's complement of the one's complement sum of this string.
 /// </param>
 /// <param name="status">Indicating the reason for this message.</param>
 /// <param name="homeAddress">
 /// The home address that was contained in the Home Address destination option.
 /// The mobile node uses this information to determine which binding does not exist, in cases where the mobile node has several home addresses.
 /// </param>
 /// <param name="options">
 /// Zero or more TLV-encoded mobility options.
 /// </param>
 public IpV6ExtensionHeaderMobilityBindingError(IpV4Protocol? nextHeader, ushort checksum, IpV6BindingErrorStatus status, IpV6Address homeAddress,
                                                IpV6MobilityOptions options)
     : base(nextHeader, checksum, options, MessageDataOffset.Options)
 {
     Status = status;
     HomeAddress = homeAddress;
 }
Пример #6
0
 /// <summary>
 /// Creates an instance from next header, checksum, status, home address and options.
 /// </summary>
 /// <param name="nextHeader">
 /// Identifies the type of header immediately following this extension header.
 /// </param>
 /// <param name="checksum">
 /// Contains the checksum of the Mobility Header.
 /// The checksum is calculated from the octet string consisting of a "pseudo-header"
 /// followed by the entire Mobility Header starting with the Payload Proto field.
 /// The checksum is the 16-bit one's complement of the one's complement sum of this string.
 /// </param>
 /// <param name="status">Indicating the reason for this message.</param>
 /// <param name="homeAddress">
 /// The home address that was contained in the Home Address destination option.
 /// The mobile node uses this information to determine which binding does not exist, in cases where the mobile node has several home addresses.
 /// </param>
 /// <param name="options">
 /// Zero or more TLV-encoded mobility options.
 /// </param>
 public IpV6ExtensionHeaderMobilityBindingError(IpV4Protocol?nextHeader, ushort checksum, IpV6BindingErrorStatus status, IpV6Address homeAddress,
                                                IpV6MobilityOptions options)
     : base(nextHeader, checksum, options, MessageDataOffset.Options)
 {
     Status      = status;
     HomeAddress = homeAddress;
 }
Пример #7
0
        internal static void WriteHeader(byte[] buffer, int offset,
                                         byte trafficClass, int flowLabel, ushort payloadLength, IpV4Protocol?nextHeader, IpV4Protocol?nextLayerProtocol,
                                         byte hopLimit, IpV6Address source, IpV6Address currentDestination, IpV6ExtensionHeaders extensionHeaders)
        {
            buffer.Write(offset + Offset.Version, (uint)((((DefaultVersion << 8) | trafficClass) << 20) | flowLabel), Endianity.Big);
            buffer.Write(offset + Offset.PayloadLength, payloadLength, Endianity.Big);
            IpV4Protocol actualNextHeader;

            if (nextHeader.HasValue)
            {
                actualNextHeader = nextHeader.Value;
            }
            else if (extensionHeaders.Any())
            {
                actualNextHeader = extensionHeaders.FirstHeader.Value;
            }
            else if (nextLayerProtocol.HasValue)
            {
                actualNextHeader = nextLayerProtocol.Value;
            }
            else
            {
                throw new InvalidOperationException("Can't determine next header. No extension headers and no known next layer protocol.");
            }
            buffer.Write(offset + Offset.NextHeader, (byte)actualNextHeader);
            buffer.Write(offset + Offset.HopLimit, hopLimit);
            buffer.Write(offset + Offset.SourceAddress, source, Endianity.Big);
            buffer.Write(offset + Offset.DestinationAddress, currentDestination, Endianity.Big);
            extensionHeaders.Write(buffer, offset + HeaderLength, nextLayerProtocol);
        }
 private IpV6MobilityOptionLocalMobilityAnchorAddress(IpV6LocalMobilityAnchorAddressCode code, IpV4Address? localMobilityAnchorAddressIpV4,
                                                      IpV6Address? localMobilityAnchorAddressIpV6)
     : base(IpV6MobilityOptionType.LocalMobilityAnchorAddress)
 {
     Code = code;
     LocalMobilityAnchorAddressIpV6 = localMobilityAnchorAddressIpV6;
     LocalMobilityAnchorAddressIpV4 = localMobilityAnchorAddressIpV4;
 }
        internal static IpV6ExtensionHeaderRoutingHomeAddress ParseRoutingData(IpV4Protocol nextHeader, byte segmentsLeft, DataSegment routingData)
        {
            if (routingData.Length != ConstRoutingDataLength)
            {
                return(null);
            }

            IpV6Address homeAddress = routingData.ReadIpV6Address(RoutingDataOffset.HomeAddress, Endianity.Big);

            return(new IpV6ExtensionHeaderRoutingHomeAddress(nextHeader, segmentsLeft, homeAddress));
        }
Пример #10
0
 internal static void WriteHeader(byte[] buffer, int offset,
                                  byte version, byte trafficClass, int flowLabel, ushort payloadLength, IpV4Protocol nextHeader, byte hopLimit,
                                  IpV6Address source, IpV6Address currentDestination)
 {
     buffer.Write(offset + Offset.Version, (uint)(((((version << Shift.Version) << 8) | trafficClass) << 16) | flowLabel), Endianity.Big);
     buffer.Write(offset + Offset.PayloadLength, payloadLength, Endianity.Big);
     buffer.Write(offset + Offset.NextHeader, (byte)nextHeader);
     buffer.Write(offset + Offset.HopLimit, hopLimit);
     buffer.Write(offset + Offset.SourceAddress, source, Endianity.Big);
     buffer.Write(offset + Offset.DestinationAddress, currentDestination, Endianity.Big);
 }
        /// <summary>
        /// Creates an instance from code, prefix length and address or prefix.
        /// </summary>
        /// <param name="code">Describes the kind of the address or the prefix.</param>
        /// <param name="prefixLength">
        /// Indicates the length of the IPv6 Address Prefix.
        /// The value ranges from 0 to 128.
        /// </param>
        /// <param name="addressOrPrefix">The IP address/prefix defined by the Option-Code field.</param>
        public IpV6MobilityOptionIpV6AddressPrefix(IpV6MobilityIpV6AddressPrefixCode code, byte prefixLength, IpV6Address addressOrPrefix)
            : base(IpV6MobilityOptionType.IpV6AddressPrefix)
        {
            if (prefixLength > MaxPrefixLength)
                throw new ArgumentOutOfRangeException("prefixLength", prefixLength,
                                                      string.Format(CultureInfo.InvariantCulture, "Max value is {0}", MaxPrefixLength));

            Code = code;
            PrefixLength = prefixLength;
            AddressOrPrefix = addressOrPrefix;
        }
Пример #12
0
        private static void ValidateCommonPrefixForAddress(IpV6Address[] addresses, int addressIndex, byte commonPrefixLength)
        {
            IpV6Address address = addresses[addressIndex];

            if (address.ToValue() >> (8 * (IpV6Address.SizeOf - commonPrefixLength)) != 0)
            {
                throw new ArgumentOutOfRangeException("addresses", address,
                                                      string.Format(CultureInfo.InvariantCulture,
                                                                    "When an address has {0} common bytes, it should start with {0} zero bytes.",
                                                                    commonPrefixLength));
            }
        }
Пример #13
0
        internal override IpV6MobilityOption CreateInstance(DataSegment data)
        {
            if (data.Length != OptionDataLength)
            {
                return(null);
            }

            IpV6MobilityIpV6AddressPrefixCode code = (IpV6MobilityIpV6AddressPrefixCode)data[Offset.Code];
            byte        prefixLength    = data[Offset.PrefixLength];
            IpV6Address addressOrPrefix = data.ReadIpV6Address(Offset.AddressOrPrefix, Endianity.Big);

            return(new IpV6MobilityOptionIpV6AddressPrefix(code, prefixLength, addressOrPrefix));
        }
Пример #14
0
        /// <summary>
        /// Creates an instance from code, prefix length and address or prefix.
        /// </summary>
        /// <param name="code">Describes the kind of the address or the prefix.</param>
        /// <param name="prefixLength">
        /// Indicates the length of the IPv6 Address Prefix.
        /// The value ranges from 0 to 128.
        /// </param>
        /// <param name="addressOrPrefix">The IP address/prefix defined by the Option-Code field.</param>
        public IpV6MobilityOptionIpV6AddressPrefix(IpV6MobilityIpV6AddressPrefixCode code, byte prefixLength, IpV6Address addressOrPrefix)
            : base(IpV6MobilityOptionType.IpV6AddressPrefix)
        {
            if (prefixLength > MaxPrefixLength)
            {
                throw new ArgumentOutOfRangeException("prefixLength", prefixLength,
                                                      string.Format(CultureInfo.InvariantCulture, "Max value is {0}", MaxPrefixLength));
            }

            Code            = code;
            PrefixLength    = prefixLength;
            AddressOrPrefix = addressOrPrefix;
        }
Пример #15
0
        internal static IpV6ExtensionHeaderMobilityBindingError ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
        {
            if (messageData.Length < MinimumMessageDataLength)
            {
                return(null);
            }

            IpV6BindingErrorStatus status      = (IpV6BindingErrorStatus)messageData[MessageDataOffset.Status];
            IpV6Address            homeAddress = messageData.ReadIpV6Address(MessageDataOffset.HomeAddress, Endianity.Big);
            IpV6MobilityOptions    options     = new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.Options, messageData.Length - MessageDataOffset.Options));

            return(new IpV6ExtensionHeaderMobilityBindingError(nextHeader, checksum, status, homeAddress, options));
        }
        internal static bool Read(DataSegment data, out byte prefixLength, out IpV6Address networkPrefix)
        {
            if (data.Length != OptionDataLength)
            {
                prefixLength  = 0;
                networkPrefix = IpV6Address.Zero;
                return(false);
            }

            prefixLength  = data[Offset.PrefixLength];
            networkPrefix = data.ReadIpV6Address(Offset.NetworkPrefix, Endianity.Big);
            return(true);
        }
        internal static bool Read(DataSegment data, out byte prefixLength, out IpV6Address networkPrefix)
        {
            if (data.Length != OptionDataLength)
            {
                prefixLength = 0;
                networkPrefix = IpV6Address.Zero;
                return false;
            }

            prefixLength = data[Offset.PrefixLength];
            networkPrefix = data.ReadIpV6Address(Offset.NetworkPrefix, Endianity.Big);
            return true;
        }
Пример #18
0
        /// <summary>
        /// Parses an option from the given data.
        /// </summary>
        /// <param name="data">The data to parse.</param>
        /// <returns>The option if parsing was successful, null otherwise.</returns>
        public IpV6Option CreateInstance(DataSegment data)
        {
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }
            if (data.Length != OptionDataLength)
            {
                return(null);
            }
            IpV6Address homeAddress = data.ReadIpV6Address(0, Endianity.Big);

            return(new IpV6OptionHomeAddress(homeAddress));
        }
        internal static IpV6ExtensionHeaderRoutingSourceRoute ParseRoutingData(IpV4Protocol nextHeader, byte segmentsLeft, DataSegment routingData)
        {
            if (routingData.Length < RoutingDataMinimumLength)
                return null;

            if ((routingData.Length - RoutingDataMinimumLength) % IpV6Address.SizeOf != 0)
                return null;

            int numAddresses = (routingData.Length - RoutingDataMinimumLength) / 8;
            IpV6Address[] addresses = new IpV6Address[numAddresses];
            for (int i = 0; i != numAddresses; ++i)
                addresses[i] = routingData.ReadIpV6Address(RoutingDataOffset.Addresses + i * IpV6Address.SizeOf, Endianity.Big);
            return new IpV6ExtensionHeaderRoutingSourceRoute(nextHeader, segmentsLeft, addresses);
        }
        internal static IpV6ExtensionHeaderRoutingSourceRoute ParseRoutingData(IpV4Protocol nextHeader, byte segmentsLeft, DataSegment routingData)
        {
            if (routingData.Length < RoutingDataMinimumLength)
                return null;

            if ((routingData.Length - RoutingDataMinimumLength) % IpV6Address.SizeOf != 0)
                return null;

            int numAddresses = (routingData.Length - RoutingDataMinimumLength) / 8;
            IpV6Address[] addresses = new IpV6Address[numAddresses];
            for (int i = 0; i != numAddresses; ++i)
                addresses[i] = routingData.ReadIpV6Address(RoutingDataOffset.Addresses + i * IpV6Address.SizeOf, Endianity.Big);
            return new IpV6ExtensionHeaderRoutingSourceRoute(nextHeader, segmentsLeft, addresses);
        }
        internal static IpV6OptionSimplifiedMulticastForwardingDuplicatePacketDetectionSequenceBased CreateSpecificInstance(DataSegment data)
        {
            IpV6TaggerIdType taggerIdType = (IpV6TaggerIdType)((data[Offset.TaggerIdType] & Mask.TaggerIdType) >> Shift.TaggerIdType);
            int taggerIdLength            = (taggerIdType == IpV6TaggerIdType.Null ? 0 : (data[Offset.TaggerIdLength] & Mask.TaggerIdLength) + 1);

            if (data.Length < Offset.TaggerId + taggerIdLength)
            {
                return(null);
            }
            DataSegment identifier = data.Subsegment(Offset.TaggerId + taggerIdLength, data.Length - Offset.TaggerId - taggerIdLength);

            switch (taggerIdType)
            {
            case IpV6TaggerIdType.Null:
                return(new IpV6OptionSimplifiedMulticastForwardingDuplicatePacketDetectionNull(identifier));

            case IpV6TaggerIdType.Default:
                return(new IpV6OptionSimplifiedMulticastForwardingDuplicatePacketDetectionDefault(data.Subsegment(Offset.TaggerId, taggerIdLength), identifier));

            case IpV6TaggerIdType.IpV4:
                if (taggerIdLength != IpV4Address.SizeOf)
                {
                    return(null);
                }
                IpV4Address ipV4Address = data.ReadIpV4Address(Offset.TaggerId, Endianity.Big);
                return(new IpV6OptionSimplifiedMulticastForwardingDuplicatePacketDetectionIpV4(ipV4Address, identifier));

            case IpV6TaggerIdType.IpV6:
                if (taggerIdLength != IpV6Address.SizeOf)
                {
                    return(null);
                }
                IpV6Address ipV6Address = data.ReadIpV6Address(Offset.TaggerId, Endianity.Big);
                return(new IpV6OptionSimplifiedMulticastForwardingDuplicatePacketDetectionIpV6(ipV6Address, identifier));

            default:
                return(null);
            }
        }
Пример #22
0
 /// <summary>
 /// Two addresses are equal if the have the exact same value.
 /// </summary>
 public bool Equals(IpV6Address other)
 {
     return(_value == other._value);
 }
 internal IpV6MobilityOptionNetworkPrefix(IpV6MobilityOptionType type, byte prefixLength, IpV6Address networkPrefix)
     : base(type)
 {
     PrefixLength = prefixLength;
     NetworkPrefix = networkPrefix;
 }
Пример #24
0
 internal static void WriteTransportChecksum(byte[] buffer, int offset, int headerLength, uint transportLength, int transportChecksumOffset,
                                             bool isChecksumOptional, ushort? checksum, IpV6Address destination)
 {
     ushort checksumValue =
         checksum ?? CalculateTransportChecksum(buffer, offset, headerLength, transportLength, transportChecksumOffset, isChecksumOptional, destination);
     buffer.Write(offset + headerLength + transportChecksumOffset, checksumValue, Endianity.Big);
 }
        internal static IpV6ExtensionHeaderMobilityHomeAgentSwitchMessage ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
        {
            if (messageData.Length < MinimumMessageDataLength)
                return null;

            byte numberOfAddresses = messageData[MessageDataOffset.NumberOfAddresses];
            int homeAgentAddressesSize = numberOfAddresses * IpV6Address.SizeOf;
            if (messageData.Length < MinimumMessageDataLength + homeAgentAddressesSize)
                return null;

            IpV6Address[] homeAgentAddresses = new IpV6Address[numberOfAddresses];
            for (int i = 0; i != numberOfAddresses; ++i)
                homeAgentAddresses[i] = messageData.ReadIpV6Address(MessageDataOffset.HomeAgentAddresses + i * IpV6Address.SizeOf, Endianity.Big);

            int optionsOffset = MessageDataOffset.HomeAgentAddresses + homeAgentAddressesSize;
            IpV6MobilityOptions options = new IpV6MobilityOptions(messageData.Subsegment(optionsOffset, messageData.Length - optionsOffset));
            return new IpV6ExtensionHeaderMobilityHomeAgentSwitchMessage(nextHeader, checksum, homeAgentAddresses, options);
        }
Пример #26
0
 /// <summary>
 /// Creates an instance from an IPv6 local mobility address.
 /// </summary>
 /// <param name="localMobilityAddress">The unicast IPv6 address of the r2LMA.</param>
 public IpV6MobilityOptionRedirect(IpV6Address localMobilityAddress)
     : this(null, localMobilityAddress)
 {
 }
 private static string GetWiresharkIpV6(IpV6Address data)
 {
     return data.ToString().ToLowerInvariant().TrimStart('0').Replace(":0", ":").Replace(":0", ":").Replace(":0", ":");
 }
Пример #28
0
        private static ushort CalculateTransportChecksum(byte[] buffer, int offset, int fullHeaderLength, uint transportLength, int transportChecksumOffset, bool isChecksumOptional, IpV6Address destination)
        {
            int  offsetAfterChecksum = offset + fullHeaderLength + transportChecksumOffset + sizeof(ushort);
            uint sum = Sum16Bits(buffer, offset + Offset.SourceAddress, IpV6Address.SizeOf) +
                       Sum16Bits(destination) +
                       Sum16Bits(transportLength) + buffer[offset + Offset.NextHeader] +
                       Sum16Bits(buffer, offset + fullHeaderLength, transportChecksumOffset) +
                       Sum16Bits(buffer, offsetAfterChecksum, (int)(transportLength - transportChecksumOffset - sizeof(ushort)));

            ushort checksumResult = Sum16BitsToChecksum(sum);

            if (checksumResult == 0 && isChecksumOptional)
            {
                return(0xFFFF);
            }
            return(checksumResult);
        }
Пример #29
0
 internal static void WriteHeader(byte[] buffer, int offset,
                                  byte version, byte trafficClass, int flowLabel, ushort payloadLength, IpV4Protocol nextHeader, byte hopLimit,
                                  IpV6Address source, IpV6Address currentDestination)
 {
     buffer.Write(offset + Offset.Version, (uint)(((((version << Shift.Version) << 8) | trafficClass) << 16) | flowLabel), Endianity.Big);
     buffer.Write(offset + Offset.PayloadLength, payloadLength, Endianity.Big);
     buffer.Write(offset + Offset.NextHeader, (byte)nextHeader);
     buffer.Write(offset + Offset.HopLimit, hopLimit);
     buffer.Write(offset + Offset.SourceAddress, source, Endianity.Big);
     buffer.Write(offset + Offset.DestinationAddress, currentDestination, Endianity.Big);
 }
Пример #30
0
 /// <summary>
 /// Creates an instance from home address.
 /// </summary>
 /// <param name="homeAddress">
 /// The home address of the mobile node sending the packet.
 /// This address must be a unicast routable address.
 /// </param>
 public IpV6OptionHomeAddress(IpV6Address homeAddress)
     : base(IpV6OptionType.HomeAddress)
 {
     HomeAddress = homeAddress;
 }
Пример #31
0
        internal static void WriteTransportChecksum(byte[] buffer, int offset, int headerLength, uint transportLength, int transportChecksumOffset,
                                                    bool isChecksumOptional, ushort?checksum, IpV6Address destination)
        {
            ushort checksumValue =
                checksum ?? CalculateTransportChecksum(buffer, offset, headerLength, transportLength, transportChecksumOffset, isChecksumOptional, destination);

            buffer.Write(offset + headerLength + transportChecksumOffset, checksumValue, Endianity.Big);
        }
 private IpV6MobilityOptionBindingIdentifier(ushort bindingId, IpV6BindingAcknowledgementStatus status, bool simultaneousHomeAndForeignBinding,
                                             byte priority, IpV4Address? ipV4CareOfAddress, IpV6Address? ipV6CareOfAddress)
     : base(IpV6MobilityOptionType.BindingIdentifier)
 {
     if (priority > MaxPriority)
         throw new ArgumentOutOfRangeException("priority", priority, string.Format(CultureInfo.InvariantCulture, "Must not exceed {0}", MaxPriority));
     BindingId = bindingId;
     Status = status;
     SimultaneousHomeAndForeignBinding = simultaneousHomeAndForeignBinding;
     Priority = priority;
     IpV4CareOfAddress = ipV4CareOfAddress;
     IpV6CareOfAddress = ipV6CareOfAddress;
 }
 /// <summary>
 /// Creates an instance from binding id, status, simulatneous home and foreign binding, priority and IPv6 care of address.
 /// </summary>
 /// <param name="bindingId">
 /// The BID that is assigned to the binding indicated by the care-of address in the Binding Update or the Binding Identifier mobility option.
 /// The value of zero is reserved and should not be used.
 /// </param>
 /// <param name="status">
 /// When the Binding Identifier mobility option is included in a Binding Acknowledgement,
 /// this field overwrites the Status field in the Binding Acknowledgement only for this BID.
 /// If this field is set to zero, the receiver ignores this field and uses the registration status stored in the Binding Acknowledgement message.
 /// The receiver must ignore this field if the Binding Identifier mobility option is not carried within either the Binding Acknowledgement
 /// or the Care-of Test messages.
 /// The possible status codes are the same as the status codes of the Binding Acknowledgement.
 /// This Status field is also used to carry error information related to the care-of address test in the Care-of Test message.
 /// </param>
 /// <param name="simultaneousHomeAndForeignBinding">
 /// Indicates that the mobile node registers multiple bindings to the home agent while it is attached to the home link.
 /// This flag is valid only for a Binding Update sent to the home agent.
 /// </param>
 /// <param name="priority">
 /// Places each BID to a relative priority (PRI) with other registered BIDs.
 /// Value '0' is reserved and must not be used.
 /// A lower number in this field indicates a higher priority, while BIDs with the same BID-PRI value have equal priority meaning that,
 /// the BID used is an implementation issue.
 /// This is consistent with current practice in packet classifiers.
 /// </param>
 /// <param name="careOfAddress">
 /// The IPv6 care-of address for the corresponding BID.
 /// </param>
 public IpV6MobilityOptionBindingIdentifier(ushort bindingId, IpV6BindingAcknowledgementStatus status, bool simultaneousHomeAndForeignBinding,
                                            byte priority, IpV6Address careOfAddress)
     : this(bindingId, status, simultaneousHomeAndForeignBinding, priority, null, careOfAddress)
 {
 }
Пример #34
0
        private static ushort CalculateTransportChecksum(byte[] buffer, int offset, int fullHeaderLength, uint transportLength, int transportChecksumOffset, bool isChecksumOptional, IpV6Address destination)
        {
            int offsetAfterChecksum = offset + fullHeaderLength + transportChecksumOffset + sizeof(ushort);
            uint sum = Sum16Bits(buffer, offset + Offset.SourceAddress, IpV6Address.SizeOf) +
                       Sum16Bits(destination) +
                       Sum16Bits(transportLength) + buffer[offset + Offset.NextHeader] +
                       Sum16Bits(buffer, offset + fullHeaderLength, transportChecksumOffset) +
                       Sum16Bits(buffer, offsetAfterChecksum, (int)(transportLength - transportChecksumOffset - sizeof(ushort)));

            ushort checksumResult = Sum16BitsToChecksum(sum);
            if (checksumResult == 0 && isChecksumOptional)
                return 0xFFFF;
            return checksumResult;
        }
 /// <summary>
 /// Creates an instance from IPv6 local mobility anchor address with IPv6 code.
 /// </summary>
 /// <param name="localMobilityAnchorAddress">The LMA IPv6 address (LMAA).</param>
 public IpV6MobilityOptionLocalMobilityAnchorAddress(IpV6Address localMobilityAnchorAddress)
     : this(IpV6LocalMobilityAnchorAddressCode.IpV6, null, localMobilityAnchorAddress)
 {
 }
 /// <summary>
 /// Creates an instance from next header, segments left and home address.
 /// </summary>
 /// <param name="nextHeader">
 /// Identifies the type of header immediately following this extension header.
 /// </param>
 /// <param name="segmentsLeft">
 /// Number of route segments remaining, i.e., number of explicitly listed intermediate nodes still to be visited before reaching the final destination.
 /// </param>
 /// <param name="homeAddress">
 /// The home address of the destination mobile node.
 /// </param>
 public IpV6ExtensionHeaderRoutingHomeAddress(IpV4Protocol?nextHeader, byte segmentsLeft, IpV6Address homeAddress)
     : base(nextHeader, segmentsLeft)
 {
     HomeAddress = homeAddress;
 }
 /// <summary>
 /// Creates an instance from binding id, status, simulatneous home and foreign binding, priority and IPv6 care of address.
 /// </summary>
 /// <param name="bindingId">
 /// The BID that is assigned to the binding indicated by the care-of address in the Binding Update or the Binding Identifier mobility option.
 /// The value of zero is reserved and should not be used.
 /// </param>
 /// <param name="status">
 /// When the Binding Identifier mobility option is included in a Binding Acknowledgement,
 /// this field overwrites the Status field in the Binding Acknowledgement only for this BID.
 /// If this field is set to zero, the receiver ignores this field and uses the registration status stored in the Binding Acknowledgement message.
 /// The receiver must ignore this field if the Binding Identifier mobility option is not carried within either the Binding Acknowledgement
 /// or the Care-of Test messages.
 /// The possible status codes are the same as the status codes of the Binding Acknowledgement.
 /// This Status field is also used to carry error information related to the care-of address test in the Care-of Test message.
 /// </param>
 /// <param name="simultaneousHomeAndForeignBinding">
 /// Indicates that the mobile node registers multiple bindings to the home agent while it is attached to the home link.
 /// This flag is valid only for a Binding Update sent to the home agent.
 /// </param>
 /// <param name="priority">
 /// Places each BID to a relative priority (PRI) with other registered BIDs.
 /// Value '0' is reserved and must not be used.
 /// A lower number in this field indicates a higher priority, while BIDs with the same BID-PRI value have equal priority meaning that,
 /// the BID used is an implementation issue.
 /// This is consistent with current practice in packet classifiers.
 /// </param>
 /// <param name="careOfAddress">
 /// The IPv6 care-of address for the corresponding BID.
 /// </param>
 public IpV6MobilityOptionBindingIdentifier(ushort bindingId, IpV6BindingAcknowledgementStatus status, bool simultaneousHomeAndForeignBinding,
                                            byte priority, IpV6Address careOfAddress)
     : this(bindingId, status, simultaneousHomeAndForeignBinding, priority, null, careOfAddress)
 {
 }
 /// <summary>
 /// Creates an instance from IPv6 local mobility anchor address with IPv6 code.
 /// </summary>
 /// <param name="localMobilityAnchorAddress">The LMA IPv6 address (LMAA).</param>
 public IpV6MobilityOptionLocalMobilityAnchorAddress(IpV6Address localMobilityAnchorAddress)
     : this(IpV6LocalMobilityAnchorAddressCode.IpV6, null, localMobilityAnchorAddress)
 {
 }
Пример #39
0
 private IpV6MobilityOptionRedirect(IpV4Address? localMobilityAddressIpV4, IpV6Address? localMobilityAddressIpV6)
     : base(IpV6MobilityOptionType.Redirect)
 {
     LocalMobilityAddressIpV4 = localMobilityAddressIpV4;
     LocalMobilityAddressIpV6 = localMobilityAddressIpV6;
 }
 private static void ValidateCommonPrefixForAddress(IpV6Address[] addresses, int addressIndex, byte commonPrefixLength)
 {
     IpV6Address address = addresses[addressIndex];
     if (address.ToValue() >> (8 * (IpV6Address.SizeOf - commonPrefixLength)) != 0)
     {
         throw new ArgumentOutOfRangeException("addresses", address,
                                               string.Format(CultureInfo.InvariantCulture,
                                                             "When an address has {0} common bytes, it should start with {0} zero bytes.",
                                                             commonPrefixLength));
     }
 }
Пример #41
0
 /// <summary>
 /// Writes the given value to the buffer using the given endianity and increments the offset by the number of bytes written.
 /// </summary>
 /// <param name="buffer">The buffer to write the value to.</param>
 /// <param name="offset">The offset in the buffer to start writing.</param>
 /// <param name="value">The value to write.</param>
 /// <param name="endianity">The endianity to use when converting the value to bytes.</param>
 public static void Write(this byte[] buffer, ref int offset, IpV6Address value, Endianity endianity)
 {
     buffer.Write(ref offset, value.ToValue(), endianity);
 }
 internal IpV6MobilityOptionNetworkPrefix(IpV6MobilityOptionType type, byte prefixLength, IpV6Address networkPrefix)
     : base(type)
 {
     PrefixLength  = prefixLength;
     NetworkPrefix = networkPrefix;
 }
Пример #43
0
 public void IpV6AddressNoColonTest()
 {
     IpV6Address ipV6Address = new IpV6Address("123");
     Assert.AreEqual(ipV6Address,ipV6Address);
 }
Пример #44
0
 internal static void WriteHeader(byte[] buffer, int offset,
                                  byte trafficClass, int flowLabel, ushort payloadLength, IpV4Protocol? nextHeader, IpV4Protocol? nextLayerProtocol,
                                  byte hopLimit, IpV6Address source, IpV6Address currentDestination, IpV6ExtensionHeaders extensionHeaders)
 {
     buffer.Write(offset + Offset.Version, (uint)((((DefaultVersion << 8) | trafficClass) << 20) | flowLabel), Endianity.Big);
     buffer.Write(offset + Offset.PayloadLength, payloadLength, Endianity.Big);
     IpV4Protocol actualNextHeader;
     if (nextHeader.HasValue)
         actualNextHeader = nextHeader.Value;
     else if (extensionHeaders.Any())
         actualNextHeader = extensionHeaders.FirstHeader.Value;
     else if (nextLayerProtocol.HasValue)
         actualNextHeader = nextLayerProtocol.Value;
     else
         throw new InvalidOperationException("Can't determine next header. No extension headers and no known next layer protocol.");
     buffer.Write(offset + Offset.NextHeader, (byte)actualNextHeader);
     buffer.Write(offset + Offset.HopLimit, hopLimit);
     buffer.Write(offset + Offset.SourceAddress, source, Endianity.Big);
     buffer.Write(offset + Offset.DestinationAddress, currentDestination, Endianity.Big);
     extensionHeaders.Write(buffer, offset + HeaderLength, nextLayerProtocol);
 }
Пример #45
0
 /// <summary>
 /// Creates an instance from home address.
 /// </summary>
 /// <param name="homeAddress">
 /// The home address of the mobile node sending the packet.  
 /// This address must be a unicast routable address.
 /// </param>
 public IpV6OptionHomeAddress(IpV6Address homeAddress)
     : base(IpV6OptionType.HomeAddress)
 {
     HomeAddress = homeAddress;
 }
Пример #46
0
 /// <summary>
 /// Two addresses are equal if the have the exact same value.
 /// </summary>
 public bool Equals(IpV6Address other)
 {
     return _value == other._value;
 }
        internal static IpV6ExtensionHeaderRoutingRpl ParseRoutingData(IpV4Protocol nextHeader, byte segmentsLeft, DataSegment routingData)
        {
            if (routingData.Length < RoutingDataMinimumLength)
                return null;

            byte commonPrefixLengthForNonLastAddresses =
                (byte)((routingData[RoutingDataOffset.CommonPrefixLengthForNonLastAddresses] & RoutingDataMask.CommonPrefixLengthForNonLastAddresses) >>
                       RoutingDataShift.CommonPrefixLengthForNonLastAddresses);
            if (commonPrefixLengthForNonLastAddresses >= MaxCommonPrefixLength)
                return null;

            byte commonPrefixLengthForLastAddress =
                (byte)(routingData[RoutingDataOffset.CommonPrefixLengthForLastAddress] & RoutingDataMask.CommonPrefixLengthForLastAddress);
            if (commonPrefixLengthForLastAddress > MaxCommonPrefixLength)
                return null;

            byte padSize = (byte)((routingData[RoutingDataOffset.PadSize] & RoutingDataMask.PadSize) >> RoutingDataShift.PadSize);
            if (padSize > MaxPadSize)
                return null;

            int numAddresses = (routingData.Length - RoutingDataOffset.Addresses - padSize - (IpV6Address.SizeOf - commonPrefixLengthForLastAddress)) /
                               (IpV6Address.SizeOf - commonPrefixLengthForNonLastAddresses) + 1;
            if (numAddresses < 0)
                return null;

            IpV6Address[] addresses = new IpV6Address[numAddresses];
            if (numAddresses > 0)
            {
                byte[] addressBytes = new byte[IpV6Address.SizeOf];
                for (int i = 0; i < numAddresses - 1; ++i)
                {
                    DataSegment addressSegment =
                        routingData.Subsegment(RoutingDataOffset.Addresses + i * (IpV6Address.SizeOf - commonPrefixLengthForNonLastAddresses),
                                               commonPrefixLengthForNonLastAddresses);
                    addressSegment.Write(addressBytes, 0);
                    addresses[i] = addressBytes.ReadIpV6Address(0, Endianity.Big);
                }

                addressBytes = new byte[IpV6Address.SizeOf];
                DataSegment lastAddressSegment =
                    routingData.Subsegment(RoutingDataOffset.Addresses + (numAddresses - 1) * (IpV6Address.SizeOf - commonPrefixLengthForNonLastAddresses),
                                           commonPrefixLengthForLastAddress);
                lastAddressSegment.Write(addressBytes, 0);
                addresses[numAddresses - 1] = addressBytes.ReadIpV6Address(0, Endianity.Big);
            }
            return new IpV6ExtensionHeaderRoutingRpl(nextHeader, segmentsLeft, commonPrefixLengthForNonLastAddresses, commonPrefixLengthForLastAddress, padSize,
                                                     addresses);
        }
Пример #48
0
 public void IpV6AddressDoubleColonsWithoutMissingColonsTest()
 {
     IpV6Address ipV6Address = new IpV6Address("1::2:3:4:5:6:7:8");
     Assert.AreEqual(ipV6Address, ipV6Address);
 }
 public IpV6ExtensionHeaderRoutingHomeAddress(IpV4Protocol nextHeader, byte segmentsLeft, IpV6Address homeAddress)
     : base(nextHeader, segmentsLeft)
 {
     HomeAddress = homeAddress;
 }
        internal static IpV6ExtensionHeaderRoutingRpl ParseRoutingData(IpV4Protocol nextHeader, byte segmentsLeft, DataSegment routingData)
        {
            if (routingData.Length < RoutingDataMinimumLength)
            {
                return(null);
            }

            byte commonPrefixLengthForNonLastAddresses =
                (byte)((routingData[RoutingDataOffset.CommonPrefixLengthForNonLastAddresses] & RoutingDataMask.CommonPrefixLengthForNonLastAddresses) >>
                       RoutingDataShift.CommonPrefixLengthForNonLastAddresses);

            if (commonPrefixLengthForNonLastAddresses >= MaxCommonPrefixLength)
            {
                return(null);
            }

            byte commonPrefixLengthForLastAddress =
                (byte)(routingData[RoutingDataOffset.CommonPrefixLengthForLastAddress] & RoutingDataMask.CommonPrefixLengthForLastAddress);

            if (commonPrefixLengthForLastAddress > MaxCommonPrefixLength)
            {
                return(null);
            }

            byte padSize = (byte)((routingData[RoutingDataOffset.PadSize] & RoutingDataMask.PadSize) >> RoutingDataShift.PadSize);

            if (padSize > MaxPadSize)
            {
                return(null);
            }

            int numAddresses = (routingData.Length - RoutingDataOffset.Addresses - padSize - (IpV6Address.SizeOf - commonPrefixLengthForLastAddress)) /
                               (IpV6Address.SizeOf - commonPrefixLengthForNonLastAddresses) + 1;

            if (numAddresses < 0)
            {
                return(null);
            }

            IpV6Address[] addresses = new IpV6Address[numAddresses];
            if (numAddresses > 0)
            {
                byte[] addressBytes = new byte[IpV6Address.SizeOf];
                for (int i = 0; i < numAddresses - 1; ++i)
                {
                    DataSegment addressSegment =
                        routingData.Subsegment(RoutingDataOffset.Addresses + i * (IpV6Address.SizeOf - commonPrefixLengthForNonLastAddresses),
                                               commonPrefixLengthForNonLastAddresses);
                    addressSegment.Write(addressBytes, 0);
                    addresses[i] = addressBytes.ReadIpV6Address(0, Endianity.Big);
                }

                addressBytes = new byte[IpV6Address.SizeOf];
                DataSegment lastAddressSegment =
                    routingData.Subsegment(RoutingDataOffset.Addresses + (numAddresses - 1) * (IpV6Address.SizeOf - commonPrefixLengthForNonLastAddresses),
                                           commonPrefixLengthForLastAddress);
                lastAddressSegment.Write(addressBytes, 0);
                addresses[numAddresses - 1] = addressBytes.ReadIpV6Address(0, Endianity.Big);
            }
            return(new IpV6ExtensionHeaderRoutingRpl(nextHeader, segmentsLeft, commonPrefixLengthForNonLastAddresses, commonPrefixLengthForLastAddress, padSize,
                                                     addresses));
        }
Пример #51
0
 /// <summary>
 /// Creates an instance from an IPv6 local mobility address.
 /// </summary>
 /// <param name="localMobilityAddress">The unicast IPv6 address of the r2LMA.</param>
 public IpV6MobilityOptionRedirect(IpV6Address localMobilityAddress)
     : this(null, localMobilityAddress)
 {
 }
        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;
        }