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; }
/// <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; }
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)); }
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; }
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)); } }
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)); }
/// <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; }
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; }
/// <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 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); } }
/// <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; }
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); }
/// <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", ":"); }
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 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; }
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) { }
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; }
private IpV6MobilityOptionRedirect(IpV4Address? localMobilityAddressIpV4, IpV6Address? localMobilityAddressIpV6) : base(IpV6MobilityOptionType.Redirect) { LocalMobilityAddressIpV4 = localMobilityAddressIpV4; LocalMobilityAddressIpV6 = localMobilityAddressIpV6; }
/// <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); }
public void IpV6AddressNoColonTest() { IpV6Address ipV6Address = new IpV6Address("123"); Assert.AreEqual(ipV6Address,ipV6Address); }
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); }
/// <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); }
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)); }
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; }