/// <summary> /// Writes the layer to the buffer. /// </summary> /// <param name="buffer">The buffer to write the layer to.</param> /// <param name="offset">The offset in the buffer to start writing the layer at.</param> /// <param name="payloadLength">The length of the layer's payload (the number of bytes after the layer in the packet).</param> /// <param name="previousLayer">The layer that comes before this layer. null if this is the first layer.</param> /// <param name="nextLayer">The layer that comes after this layer. null if this is the last layer.</param> public override void Write(byte[] buffer, int offset, int payloadLength, ILayer previousLayer, ILayer nextLayer) { IpV4Protocol?nextLayerProtocol = null; if (nextLayer != null) { IIpNextLayer ipNextLayer = nextLayer as IIpNextLayer; if (ipNextLayer != null) { nextLayerProtocol = ipNextLayer.PreviousLayerProtocol; } } if (nextLayer != null && ExtensionHeaders.LastHeader == IpV4Protocol.EncapsulatingSecurityPayload) { throw new ArgumentException("Cannot have a layer after IpV6Layer with EncapsulatingSecurityPayload extension header.", "nextLayer"); } if (payloadLength + ExtensionHeaders.BytesLength > ushort.MaxValue) { throw new ArgumentOutOfRangeException("payloadLength", payloadLength, "Consider the extension headers, this must be no more than " + (ushort.MaxValue - ExtensionHeaders.BytesLength)); } IpV6Datagram.WriteHeader(buffer, offset, TrafficClass, FlowLabel, (ushort)(payloadLength + ExtensionHeaders.BytesLength), NextHeader, nextLayerProtocol, HopLimit, Source, CurrentDestination, ExtensionHeaders); }
/// <summary> /// Finalizes the layer data in the buffer. /// Used for fields that must be calculated according to the layer's payload (like checksum). /// </summary> /// <param name="buffer">The buffer to finalize the layer in.</param> /// <param name="offset">The offset in the buffer the layer starts.</param> /// <param name="payloadLength">The length of the layer's payload (the number of bytes after the layer in the packet).</param> /// <param name="nextLayer">The layer that comes after this layer. null if this is the last layer.</param> public override void Finalize(byte[] buffer, int offset, int payloadLength, ILayer nextLayer) { IIpNextTransportLayer nextTransportLayer = nextLayer as IIpNextTransportLayer; if (nextTransportLayer == null || !nextTransportLayer.CalculateChecksum) { return; } IpV6Datagram.WriteTransportChecksum(buffer, offset, Length, (uint)payloadLength, nextTransportLayer.ChecksumOffset, nextTransportLayer.IsChecksumOptional, nextTransportLayer.Checksum, CurrentDestination); }
private void SkipAuthenticationHeaders(IpV6Datagram ipV6Datagram) { while (_currentExtensionHeaderIndex < ipV6Datagram.ExtensionHeaders.Headers.Count && ipV6Datagram.ExtensionHeaders[_currentExtensionHeaderIndex].Protocol == IpV4Protocol.AuthenticationHeader) { ++_currentExtensionHeaderIndex; } }
private void IncrementCurrentExtensionHeaderIndex(IpV6Datagram ipV6Datagram) { ++_currentExtensionHeaderIndex; SkipAuthenticationHeaders(ipV6Datagram); }
private void CompareOptions(XElement field, ref int optionsIndex, IpV6Datagram ipV6Datagram, IpV6ExtensionHeaderOptions header) { foreach (var headerField in field.Fields()) { switch (headerField.Name()) { case "ipv6.nxt": headerField.AssertNoFields(); headerField.AssertShowDecimal((byte)header.NextHeader); break; case "ipv6.opt.length": headerField.AssertNoFields(); headerField.AssertShowDecimal((header.Length - 8) / 8); break; case "ipv6.opt": foreach (XElement headerSubfield in headerField.Fields()) { IpV6Option option = header.Options[optionsIndex]; var optionCalipso = option as IpV6OptionCalipso; var optionQuickStart = option as IpV6OptionQuickStart; switch (headerSubfield.Name()) { case "ipv6.opt.type": headerSubfield.AssertNoFields(); headerSubfield.AssertShowDecimal((byte)option.OptionType); break; case "ipv6.opt.length": headerSubfield.AssertNoFields(); headerSubfield.AssertShowDecimal(option.Length - 2); break; case "ipv6.opt.tel": headerSubfield.AssertNoFields(); IpV6OptionTunnelEncapsulationLimit optionTunnelEncapsulationLimit = (IpV6OptionTunnelEncapsulationLimit)option; headerSubfield.AssertShowDecimal(optionTunnelEncapsulationLimit.TunnelEncapsulationLimit); ++optionsIndex; break; case "ipv6.opt.rpl.flag": IpV6OptionRoutingProtocolLowPowerAndLossyNetworks optionRoutingProtocolLowPowerAndLossyNetworks = (IpV6OptionRoutingProtocolLowPowerAndLossyNetworks)option; foreach (XElement optionSubfield in headerSubfield.Fields()) { optionSubfield.AssertNoFields(); switch (optionSubfield.Name()) { case "ipv6.opt.rpl.flag.o": optionSubfield.AssertShowDecimal(optionRoutingProtocolLowPowerAndLossyNetworks.Down); break; case "ipv6.opt.rpl.flag.r": optionSubfield.AssertShowDecimal(optionRoutingProtocolLowPowerAndLossyNetworks.RankError); break; case "ipv6.opt.rpl.flag.f": optionSubfield.AssertShowDecimal(optionRoutingProtocolLowPowerAndLossyNetworks.ForwardingError); break; case "ipv6.opt.rpl.flag.rsv": optionSubfield.AssertShowDecimal(0); break; case "ipv6.opt.rpl.instance_id": optionSubfield.AssertShowDecimal( optionRoutingProtocolLowPowerAndLossyNetworks.RoutingProtocolLowPowerAndLossyNetworksInstanceId); break; case "ipv6.opt.rpl.sender_rank": optionSubfield.AssertShowDecimal(optionRoutingProtocolLowPowerAndLossyNetworks.SenderRank); break; default: throw new InvalidOperationException("Invalid ipv6 option subfield " + optionSubfield.Name()); } } ++optionsIndex; // TODO: change to break; after https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=10559 is fixed. return; case "ipv6.opt.calipso.doi": headerSubfield.AssertNoFields(); headerSubfield.AssertShowDecimal((uint)optionCalipso.DomainOfInterpretation); break; case "ipv6.opt.calipso.cmpt.length": headerSubfield.AssertNoFields(); headerSubfield.AssertShowDecimal(optionCalipso.CompartmentLength); break; case "ipv6.opt.calipso.sens_level": headerSubfield.AssertNoFields(); headerSubfield.AssertShowDecimal(optionCalipso.SensitivityLevel); break; case "ipv6.opt.calipso.checksum": headerSubfield.AssertNoFields(); headerSubfield.AssertShowDecimal(optionCalipso.Checksum); break; case "ipv6.opt.calipso.cmpt_bitmap": headerSubfield.AssertNoFields(); headerSubfield.AssertValue(optionCalipso.CompartmentBitmap); ++optionsIndex; break; case "ipv6.opt.router_alert": headerSubfield.AssertNoFields(); var optionRouterAlert = (IpV6OptionRouterAlert)option; headerSubfield.AssertShowDecimal((ushort)optionRouterAlert.RouterAlertType); ++optionsIndex; break; case "ipv6.opt.padn": headerSubfield.AssertNoFields(); var optionPadN = (IpV6OptionPadN)option; headerSubfield.AssertValue(new byte[optionPadN.PaddingDataLength]); ++optionsIndex; break; case "ipv6.opt.qs_func": headerSubfield.AssertNoFields(); headerSubfield.AssertShowDecimal((byte)optionQuickStart.QuickStartFunction); break; case "ipv6.opt.qs_rate": headerSubfield.AssertNoFields(); headerSubfield.AssertShowDecimal(optionQuickStart.Rate); break; case "ipv6.opt.qs_ttl": headerSubfield.AssertNoFields(); headerSubfield.AssertShowDecimal(optionQuickStart.Ttl); break; case "ipv6.opt.qs_ttl_diff": headerSubfield.AssertNoFields(); headerSubfield.AssertShowDecimal((256 + ipV6Datagram.HopLimit - optionQuickStart.Ttl) % 256); break; case "ipv6.opt.qs_unused": headerSubfield.AssertNoFields(); headerSubfield.AssertShowDecimal(optionQuickStart.Ttl); break; case "ipv6.opt.qs_nonce": headerSubfield.AssertNoFields(); headerSubfield.AssertShowDecimal(optionQuickStart.Nonce); break; case "ipv6.opt.qs_reserved": headerSubfield.AssertNoFields(); headerSubfield.AssertShowDecimal(0); ++optionsIndex; break; case "ipv6.opt.pad1": headerSubfield.AssertNoFields(); headerSubfield.AssertShow(""); Assert.IsTrue(option is IpV6OptionPad1); ++optionsIndex; break; case "ipv6.opt.jumbo": headerSubfield.AssertNoFields(); headerSubfield.AssertShowDecimal(((IpV6OptionJumboPayload)option).JumboPayloadLength); ++optionsIndex; break; case "ipv6.mipv6_home_address": headerSubfield.AssertNoFields(); headerSubfield.AssertShow(((IpV6OptionHomeAddress)option).HomeAddress.GetWiresharkString()); ++optionsIndex; break; case "ipv6.opt.unknown": headerSubfield.AssertNoFields(); Assert.IsTrue(new[] { IpV6OptionType.LineIdentification, IpV6OptionType.IdentifierLocatorNetworkProtocolNonce, IpV6OptionType.SimplifiedMulticastForwardingDuplicatePacketDetection, IpV6OptionType.EndpointIdentification, }.Contains(option.OptionType), option.OptionType.ToString()); ++optionsIndex; break; default: throw new InvalidOperationException("Invalid ipv6 header subfield " + headerSubfield.Name()); } } break; default: throw new InvalidOperationException("Invalid ipv6 options field " + headerField.Name()); } } }