Commit b12c6b77 authored by Brickner_cp's avatar Brickner_cp

IPv6.

Rafactored Options so it can be used for IPv6 options.
Moved general options classes to a new PcapDotNet.Packets.Ip namespace.
Upgrade to Resharper 7.
parent a399a230
<Configuration>
<CodeStyleSettings>
<ExternalPath IsNull="False">
</ExternalPath>
<Sharing>SOLUTION</Sharing>
<CSharp>
<FormatSettings>
<ANONYMOUS_METHOD_DECLARATION_BRACES>NEXT_LINE</ANONYMOUS_METHOD_DECLARATION_BRACES>
<CASE_BLOCK_BRACES>NEXT_LINE</CASE_BLOCK_BRACES>
<INITIALIZER_BRACES>NEXT_LINE</INITIALIZER_BRACES>
<MODIFIERS_ORDER IsNull="False">
<Item>public</Item>
<Item>protected</Item>
<Item>internal</Item>
<Item>private</Item>
<Item>new</Item>
<Item>abstract</Item>
<Item>virtual</Item>
<Item>override</Item>
<Item>sealed</Item>
<Item>static</Item>
<Item>readonly</Item>
<Item>extern</Item>
<Item>unsafe</Item>
<Item>volatile</Item>
</MODIFIERS_ORDER>
<SPACE_AFTER_TYPECAST_PARENTHESES>False</SPACE_AFTER_TYPECAST_PARENTHESES>
<SPACE_AROUND_MULTIPLICATIVE_OP>True</SPACE_AROUND_MULTIPLICATIVE_OP>
<SPACE_BEFORE_SIZEOF_PARENTHESES>False</SPACE_BEFORE_SIZEOF_PARENTHESES>
<SPACE_BEFORE_TYPEOF_PARENTHESES>False</SPACE_BEFORE_TYPEOF_PARENTHESES>
<WRAP_LIMIT>160</WRAP_LIMIT>
</FormatSettings>
<UsingsSettings />
<Naming2>
<EventHandlerPatternLong>$object$_On$event$</EventHandlerPatternLong>
<EventHandlerPatternShort>$event$Handler</EventHandlerPatternShort>
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="TypesAndNamespaces" />
<PredefinedRule Inspect="True" Prefix="I" Suffix="" Style="AaBb" ElementKind="Interfaces" />
<PredefinedRule Inspect="True" Prefix="T" Suffix="" Style="AaBb" ElementKind="TypeParameters" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="MethodPropertyEvent" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="aaBb" ElementKind="Locals" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="aaBb" ElementKind="LocalConstants" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="aaBb" ElementKind="Parameters" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="PublicFields" />
<PredefinedRule Inspect="True" Prefix="_" Suffix="" Style="aaBb" ElementKind="PrivateInstanceFields" />
<PredefinedRule Inspect="True" Prefix="_" Suffix="" Style="aaBb" ElementKind="PrivateStaticFields" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="Constants" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="PrivateConstants" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="StaticReadonly" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="PrivateStaticReadonly" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="EnumMember" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="Other" />
</Naming2>
</CSharp>
<VB>
<FormatSettings />
<ImportsSettings />
<Naming2>
<EventHandlerPatternLong>$object$_On$event$</EventHandlerPatternLong>
<EventHandlerPatternShort>$event$Handler</EventHandlerPatternShort>
</Naming2>
</VB>
<Web>
<Naming2 />
</Web>
<Xaml>
<Naming2 />
</Xaml>
<XML>
<FormatSettings />
</XML>
<GenerateMemberBody />
<Naming2>
<EventHandlerPatternLong>$object$_On$event$</EventHandlerPatternLong>
<EventHandlerPatternShort>$event$Handler</EventHandlerPatternShort>
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="aaBb" ElementKind="Parameters" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="TypesAndNamespaces" />
<PredefinedRule Inspect="True" Prefix="I" Suffix="" Style="AaBb" ElementKind="Interfaces" />
<PredefinedRule Inspect="True" Prefix="T" Suffix="" Style="AaBb" ElementKind="TypeParameters" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="MethodPropertyEvent" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="aaBb" ElementKind="Locals" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="LocalConstants" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="PublicFields" />
<PredefinedRule Inspect="True" Prefix="_" Suffix="" Style="aaBb" ElementKind="PrivateInstanceFields" />
<PredefinedRule Inspect="True" Prefix="_" Suffix="" Style="aaBb" ElementKind="PrivateStaticFields" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="Constants" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="PrivateConstants" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="StaticReadonly" />
<PredefinedRule Inspect="True" Prefix="_" Suffix="" Style="aaBb" ElementKind="PrivateStaticReadonly" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="EnumMember" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="Other" />
</Naming2>
</CodeStyleSettings>
</Configuration>
\ No newline at end of file
using PcapDotNet.Packets.IpV4;
namespace PcapDotNet.Packets.Ip
{
public interface IIpOptionQuickStart
{
/// <summary>
/// The function of this quick start option.
/// </summary>
IpV4OptionQuickStartFunction Function { get; }
/// <summary>
/// If function is request then this field is the rate request.
/// If function is report then this field is the rate report.
/// </summary>
byte Rate { get; }
/// <summary>
/// The rate translated to KBPS.
/// </summary>
int RateKbps { get; }
/// <summary>
/// The Quick-Start TTL (QS TTL) field.
/// The sender MUST set the QS TTL field to a random value.
/// Routers that approve the Quick-Start Request decrement the QS TTL (mod 256) by the same amount that they decrement the IP TTL.
/// The QS TTL is used by the sender to detect if all the routers along the path understood and approved the Quick-Start option.
///
/// <para>
/// For a Rate Request, the transport sender MUST calculate and store the TTL Diff,
/// the difference between the IP TTL value, and the QS TTL value in the Quick-Start Request packet, as follows:
/// TTL Diff = ( IP TTL - QS TTL ) mod 256
/// </para>
/// </summary>
byte Ttl { get; }
/// <summary>
/// The QS Nonce gives the Quick-Start sender some protection against receivers lying about the value of the received Rate Request.
/// This is particularly important if the receiver knows the original value of the Rate Request
/// (e.g., when the sender always requests the same value, and the receiver has a long history of communication with that sender).
/// Without the QS Nonce, there is nothing to prevent the receiver from reporting back to the sender a Rate Request of K,
/// when the received Rate Request was, in fact, less than K.
///
/// <para>
/// The format for the 30-bit QS Nonce.
/// <list type="table">
/// <listheader>
/// <term>Bits</term>
/// <description>Purpose</description>
/// </listheader>
/// <item><term>Bits 0-1</term><description>Rate 15 -> Rate 14</description></item>
/// <item><term>Bits 2-3</term><description>Rate 14 -> Rate 13</description></item>
/// <item><term>Bits 4-5</term><description>Rate 13 -> Rate 12</description></item>
/// <item><term>Bits 6-7</term><description>Rate 12 -> Rate 11</description></item>
/// <item><term>Bits 8-9</term><description>Rate 11 -> Rate 10</description></item>
/// <item><term>Bits 10-11</term><description>Rate 10 -> Rate 9</description></item>
/// <item><term>Bits 12-13</term><description>Rate 9 -> Rate 8</description></item>
/// <item><term>Bits 14-15</term><description>Rate 8 -> Rate 7</description></item>
/// <item><term>Bits 16-17</term><description>Rate 7 -> Rate 6</description></item>
/// <item><term>Bits 18-19</term><description>Rate 6 -> Rate 5</description></item>
/// <item><term>Bits 20-21</term><description>Rate 5 -> Rate 4</description></item>
/// <item><term>Bits 22-23</term><description>Rate 4 -> Rate 3</description></item>
/// <item><term>Bits 24-25</term><description>Rate 3 -> Rate 2</description></item>
/// <item><term>Bits 26-27</term><description>Rate 2 -> Rate 1</description></item>
/// <item><term>Bits 28-29</term><description>Rate 1 -> Rate 0</description></item>
/// </list>
/// </para>
///
/// <para>
/// The transport sender MUST initialize the QS Nonce to a random value.
/// If the router reduces the Rate Request from rate K to rate K-1,
/// then the router MUST set the field in the QS Nonce for "Rate K -> Rate K-1" to a new random value.
/// Similarly, if the router reduces the Rate Request by N steps,
/// the router MUST set the 2N bits in the relevant fields in the QS Nonce to a new random value.
/// The receiver MUST report the QS Nonce back to the sender.
/// </para>
///
/// <para>
/// If the Rate Request was not decremented in the network, then the QS Nonce should have its original value.
/// Similarly, if the Rate Request was decremented by N steps in the network,
/// and the receiver reports back a Rate Request of K, then the last 2K bits of the QS Nonce should have their original value.
/// </para>
/// </summary>
uint Nonce { get; }
}
}
\ No newline at end of file
namespace PcapDotNet.Packets namespace PcapDotNet.Packets.Ip
{ {
/// <summary> /// <summary>
/// This interface is used to create all complex options. /// This interface is used to create all complex options.
......
namespace PcapDotNet.Packets namespace PcapDotNet.Packets.Ip
{ {
/// <summary> /// <summary>
/// A factory interface for an unknown option. /// A factory interface for an unknown option.
......
using System;
using PcapDotNet.Packets.IpV4;
namespace PcapDotNet.Packets.Ip
{
internal static class IpOptionQuickStartCommon
{
public const int DataLength = 6;
/// <summary>
/// The maximum value for the rate field.
/// </summary>
public const byte RateMaximumValue = 0x0F;
private static class Offset
{
public const int Function = 0;
public const int Rate = Function;
public const int Ttl = Rate + sizeof(byte);
public const int Nonce = Ttl + sizeof(byte);
}
private static class Mask
{
public const byte Function = 0xF0;
public const byte Rate = 0x0F;
}
public static void AssertValidParameters(IpV4OptionQuickStartFunction function, byte rate, byte ttl, uint nonce)
{
if (function != IpV4OptionQuickStartFunction.RateRequest &&
function != IpV4OptionQuickStartFunction.RateReport)
{
throw new ArgumentException("Illegal function " + function, "function");
}
if (rate > RateMaximumValue)
throw new ArgumentOutOfRangeException("rate", rate, "Rate maximum value is " + RateMaximumValue);
if ((nonce & 0x00000003) != 0)
throw new ArgumentException("nonce last two bits are reserved and must be zero", "nonce");
}
public static int CalcRateKbps(byte rate)
{
if (rate == 0)
return 0;
return 40*(1 << rate);
}
public static void ReadData(DataSegment data, out IpV4OptionQuickStartFunction function, out byte rate, out byte ttl, out uint nonce)
{
function = (IpV4OptionQuickStartFunction)(data[Offset.Function] & Mask.Function);
rate = (byte)(data[Offset.Rate] & Mask.Rate);
ttl = data[Offset.Ttl];
nonce = data.ReadUInt(Offset.Nonce, Endianity.Big);
}
public static void WriteData(byte[] buffer, ref int offset, IpV4OptionQuickStartFunction function, byte rate, byte ttl, uint nonce)
{
buffer[offset + Offset.Function] = (byte)(((byte)function & Mask.Function) | (rate & Mask.Rate));
buffer[offset + Offset.Ttl] = ttl;
buffer.Write(offset + Offset.Nonce, nonce, Endianity.Big);
offset += DataLength;
}
}
}
\ No newline at end of file
namespace PcapDotNet.Packets namespace PcapDotNet.Packets.Ip
{ {
/// <summary> /// <summary>
/// A generic option (for IPv4 and TCP). /// A generic option (for IPv4, IPv6 and TCP).
/// The option is read from buffer and can be of different length. /// The option is read from buffer and can be of different length.
/// </summary> /// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Option")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Option")]
...@@ -12,19 +12,6 @@ namespace PcapDotNet.Packets ...@@ -12,19 +12,6 @@ namespace PcapDotNet.Packets
/// </summary> /// </summary>
public abstract int Length { get; } public abstract int Length { get; }
/// <summary>
/// True iff this option may appear at most once in a datagram.
/// </summary>
public abstract bool IsAppearsAtMostOnce { get; }
/// <summary>
/// Checks whether two options have equivalent type.
/// Useful to check if an option that must appear at most once appears in the list.
/// </summary>
public abstract bool Equivalent(Option other);
internal abstract Option Read(byte[] buffer, ref int offset, int length);
internal abstract void Write(byte[] buffer, ref int offset); internal abstract void Write(byte[] buffer, ref int offset);
} }
} }
\ No newline at end of file
...@@ -4,7 +4,7 @@ using System.Linq; ...@@ -4,7 +4,7 @@ using System.Linq;
using System.Reflection; using System.Reflection;
using PcapDotNet.Base; using PcapDotNet.Base;
namespace PcapDotNet.Packets namespace PcapDotNet.Packets.Ip
{ {
internal static class OptionComplexFactory<TOptionType> internal static class OptionComplexFactory<TOptionType>
{ {
......
using System;
namespace PcapDotNet.Packets.Ip
{
internal abstract class OptionTypeRegistrationAttribute : Attribute
{
public abstract object OptionType { get; }
public abstract Type OptionTypeType { get; }
}
}
\ No newline at end of file
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using PcapDotNet.Base; using PcapDotNet.Base;
namespace PcapDotNet.Packets namespace PcapDotNet.Packets.Ip
{ {
/// <summary> /// <summary>
/// A generic Options class. /// A generic Options class.
/// Represents a list of options (either IPv4 options or TCP options). /// Represents a list of options (either IPv4 options, IPv6 options or TCP options).
/// </summary> /// </summary>
/// <typeparam name="T">The Option type this collection contains.</typeparam> /// <typeparam name="T">The Option type this collection contains.</typeparam>
public abstract class Options<T> where T : Option public abstract class Options<T> where T : Option
...@@ -88,12 +87,6 @@ namespace PcapDotNet.Packets ...@@ -88,12 +87,6 @@ namespace PcapDotNet.Packets
return OptionsCollection.SequenceToString(", ", GetType().Name + " {", "}"); return OptionsCollection.SequenceToString(", ", GetType().Name + " {", "}");
} }
internal Options(byte[] buffer, int offset, int length, T end)
: this(Read(buffer, offset, length, end))
{
BytesLength = length;
}
internal void Write(byte[] buffer, int offset) internal void Write(byte[] buffer, int offset)
{ {
int offsetEnd = offset + BytesLength; int offsetEnd = offset + BytesLength;
...@@ -105,66 +98,30 @@ namespace PcapDotNet.Packets ...@@ -105,66 +98,30 @@ namespace PcapDotNet.Packets
buffer[offset++] = 0; buffer[offset++] = 0;
} }
internal Options(IList<T> options, T end, int maximumBytesLength) internal Options(IList<T> options, bool isValid, int? length)
: this(EndOptions(options, end), true)
{
if (BytesLength > maximumBytesLength)
throw new ArgumentException("given options take " + BytesLength + " bytes and maximum number of bytes for options is " + maximumBytesLength, "options");
}
private Options(IList<T> options, bool isValid)
{ {
_options = options.AsReadOnly(); _options = options.AsReadOnly();
IsValid = isValid; IsValid = isValid;
BytesLength = SumBytesLength(OptionsCollection); if (length.HasValue)
{
if (BytesLength % 4 != 0) BytesLength = length.Value;
BytesLength = (BytesLength / 4 + 1) * 4; }
} else
{
private static IList<T> EndOptions(IList<T> options, T end) BytesLength = SumBytesLength(OptionsCollection);
{
if (options.Count == 0 || options.Last().Equivalent(end) || SumBytesLength(options) % 4 == 0)
return options;
return new List<T>(options.Concat(end)); if (BytesLength % 4 != 0)
BytesLength = (BytesLength / 4 + 1) * 4;
}
} }
private static int SumBytesLength(IEnumerable<T> options) internal static int SumBytesLength(IEnumerable<T> options)
{ {
return options.Sum(option => option.Length); return options.Sum(option => option.Length);
} }
private Options(Tuple<IList<T>, bool> optionsAndIsValid)
: this(optionsAndIsValid.Item1, optionsAndIsValid.Item2)
{
}
private static Tuple<IList<T>, bool> Read(byte[] buffer, int offset, int length, T end)
{
int offsetEnd = offset + length;
List<T> options = new List<T>();
while (offset != offsetEnd)
{
T option = (T)end.Read(buffer, ref offset, offsetEnd - offset);
if (option == null ||
option.IsAppearsAtMostOnce && options.Any(option.Equivalent))
{
// Invalid
return new Tuple<IList<T>, bool>(options, false);
}
options.Add(option);
if (option.Equivalent(end))
break; // Valid?
}
return new Tuple<IList<T>, bool>(options, true);
}
private readonly ReadOnlyCollection<T> _options; private readonly ReadOnlyCollection<T> _options;
} }
} }
\ No newline at end of file
namespace PcapDotNet.Packets.Ip
{
public abstract class V4Option : Option
{
/// <summary>
/// True iff this option may appear at most once in a datagram.
/// </summary>
public abstract bool IsAppearsAtMostOnce { get; }
/// <summary>
/// Checks whether two options have equivalent type.
/// Useful to check if an option that must appear at most once appears in the list.
/// </summary>
public abstract bool Equivalent(Option other);
internal abstract V4Option Read(byte[] buffer, ref int offset, int length);
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Linq;
using PcapDotNet.Base;
namespace PcapDotNet.Packets.Ip
{
public abstract class V4Options<T> : Options<T> where T : V4Option
{
internal V4Options(byte[] buffer, int offset, int length, T end)
: this(Read(buffer, offset, length, end), length)
{
}
internal V4Options(IList<T> options, T end, int maximumBytesLength)
: this(EndOptions(options, end), true, null)
{
if (BytesLength > maximumBytesLength)
throw new ArgumentException("given options take " + BytesLength + " bytes and maximum number of bytes for options is " + maximumBytesLength, "options");
}
private V4Options(Tuple<IList<T>, bool> optionsAndIsValid, int? length)
: this(optionsAndIsValid.Item1, optionsAndIsValid.Item2, length)
{
}
private V4Options(IList<T> options, bool isValid, int? length)
:base(options, isValid, length)
{
}
private static Tuple<IList<T>, bool> Read(byte[] buffer, int offset, int length, T end)
{
int offsetEnd = offset + length;
List<T> options = new List<T>();
while (offset != offsetEnd)
{
T option = (T)end.Read(buffer, ref offset, offsetEnd - offset);
if (option == null ||
option.IsAppearsAtMostOnce && options.Any(option.Equivalent))
{
// Invalid
return new Tuple<IList<T>, bool>(options, false);
}
options.Add(option);
if (option.Equivalent(end))
break; // Valid?
}
return new Tuple<IList<T>, bool>(options, true);
}
private static IList<T> EndOptions(IList<T> options, T end)
{
if (options.Count == 0 || options.Last().Equivalent(end) || SumBytesLength(options) % 4 == 0)
return options;
return new List<T>(options.Concat(end));
}
}
}
\ No newline at end of file
using System; using System;
using PcapDotNet.Packets.Ip;
namespace PcapDotNet.Packets.IpV4 namespace PcapDotNet.Packets.IpV4
{ {
/// <summary> /// <summary>
/// Represents an ip option according to rfc 791. /// Represents an ip option according to rfc 791.
/// </summary> /// </summary>
public abstract class IpV4Option : Option, IEquatable<IpV4Option> public abstract class IpV4Option : V4Option, IEquatable<IpV4Option>
{ {
///<summary> ///<summary>
/// This option indicates the end of the option list.<br/> /// This option indicates the end of the option list.<br/>
...@@ -28,7 +29,7 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -28,7 +29,7 @@ namespace PcapDotNet.Packets.IpV4
} }
/// <summary> /// <summary>
/// The type of the ip option. /// The type of the IP option.
/// </summary> /// </summary>
public IpV4OptionType OptionType public IpV4OptionType OptionType
{ {
...@@ -79,7 +80,7 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -79,7 +80,7 @@ namespace PcapDotNet.Packets.IpV4
return OptionType.ToString(); return OptionType.ToString();
} }
internal sealed override Option Read(byte[] buffer, ref int offset, int length) internal sealed override V4Option Read(byte[] buffer, ref int offset, int length)
{ {
int offsetEnd = offset + length; int offsetEnd = offset + length;
if (offset == offsetEnd) if (offset == offsetEnd)
...@@ -94,7 +95,7 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -94,7 +95,7 @@ namespace PcapDotNet.Packets.IpV4
return Nop; return Nop;
default: default:
return OptionComplexFactory<IpV4OptionType>.Read(optionType, buffer, ref offset, offsetEnd - offset); return (V4Option)OptionComplexFactory<IpV4OptionType>.Read(optionType, buffer, ref offset, offsetEnd - offset);
} }
} }
......
using System; using System;
using PcapDotNet.Base; using PcapDotNet.Base;
using PcapDotNet.Packets.Ip;
namespace PcapDotNet.Packets.IpV4 namespace PcapDotNet.Packets.IpV4
{ {
...@@ -40,7 +41,7 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -40,7 +41,7 @@ namespace PcapDotNet.Packets.IpV4
/// </pre> /// </pre>
/// </para> /// </para>
/// </summary> /// </summary>
[OptionTypeRegistration(typeof(IpV4OptionType), IpV4OptionType.BasicSecurity)] [IpV4OptionTypeRegistration(IpV4OptionType.BasicSecurity)]
public sealed class IpV4OptionBasicSecurity : IpV4OptionComplex, IOptionComplexFactory, IEquatable<IpV4OptionBasicSecurity> public sealed class IpV4OptionBasicSecurity : IpV4OptionComplex, IOptionComplexFactory, IEquatable<IpV4OptionBasicSecurity>
{ {
/// <summary> /// <summary>
......
using System.Collections.Generic; using System.Collections.Generic;
using PcapDotNet.Packets.Ip;
namespace PcapDotNet.Packets.IpV4 namespace PcapDotNet.Packets.IpV4
{ {
...@@ -56,7 +57,7 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -56,7 +57,7 @@ namespace PcapDotNet.Packets.IpV4
/// Appears at most once in a datagram. /// Appears at most once in a datagram.
/// </para> /// </para>
/// </summary> /// </summary>
[OptionTypeRegistration(typeof(IpV4OptionType), IpV4OptionType.LooseSourceRouting)] [IpV4OptionTypeRegistration(IpV4OptionType.LooseSourceRouting)]
public class IpV4OptionLooseSourceRouting : IpV4OptionRoute, IOptionComplexFactory public class IpV4OptionLooseSourceRouting : IpV4OptionRoute, IOptionComplexFactory
{ {
/// <summary> /// <summary>
......
using System; using System;
using PcapDotNet.Base; using PcapDotNet.Base;
using PcapDotNet.Packets.Ip;
namespace PcapDotNet.Packets.IpV4 namespace PcapDotNet.Packets.IpV4
{ {
/// <summary> /// <summary>
/// RFC 4782.
/// The Quick-Start Option for IPv4 /// The Quick-Start Option for IPv4
///
/// <para> /// <para>
/// The Quick-Start Request for IPv4 is defined as follows: /// The Quick-Start Request for IPv4 is defined as follows:
/// <pre> /// <pre>
...@@ -20,23 +21,23 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -20,23 +21,23 @@ namespace PcapDotNet.Packets.IpV4
/// </pre> /// </pre>
/// </para> /// </para>
/// </summary> /// </summary>
[OptionTypeRegistration(typeof(IpV4OptionType), IpV4OptionType.QuickStart)] [IpV4OptionTypeRegistration(IpV4OptionType.QuickStart)]
public sealed class IpV4OptionQuickStart : IpV4OptionComplex, IOptionComplexFactory, IEquatable<IpV4OptionQuickStart> public sealed class IpV4OptionQuickStart : IpV4OptionComplex, IIpOptionQuickStart, IOptionComplexFactory, IEquatable<IpV4OptionQuickStart>
{ {
/// <summary> /// <summary>
/// The number of bytes this option take. /// The number of bytes this option take.
/// </summary> /// </summary>
public const int OptionLength = 8; public const int OptionLength = OptionValueLength + OptionHeaderLength;
/// <summary> /// <summary>
/// The number of bytes this option's value take. /// The number of bytes this option's value take.
/// </summary> /// </summary>
public const int OptionValueLength = OptionLength - OptionHeaderLength; public const int OptionValueLength = IpOptionQuickStartCommon.DataLength;
/// <summary> /// <summary>
/// The maximum value for the rate field. /// The maximum value for the rate field.
/// </summary> /// </summary>
public const byte RateMaximumValue = 0x0F; public const byte RateMaximumValue = IpOptionQuickStartCommon.RateMaximumValue;
/// <summary> /// <summary>
/// Create a quick start option according to the given field values. /// Create a quick start option according to the given field values.
...@@ -55,22 +56,12 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -55,22 +56,12 @@ namespace PcapDotNet.Packets.IpV4
public IpV4OptionQuickStart(IpV4OptionQuickStartFunction function, byte rate, byte ttl, uint nonce) public IpV4OptionQuickStart(IpV4OptionQuickStartFunction function, byte rate, byte ttl, uint nonce)
: base(IpV4OptionType.QuickStart) : base(IpV4OptionType.QuickStart)
{ {
if (function != IpV4OptionQuickStartFunction.RateRequest && IpOptionQuickStartCommon.AssertValidParameters(function, rate, ttl, nonce);
function != IpV4OptionQuickStartFunction.RateReport)
{
throw new ArgumentException("Illegal function " + function, "function");
}
if (rate > RateMaximumValue) Function = function;
throw new ArgumentOutOfRangeException("rate", rate, "Rate maximum value is " + RateMaximumValue); Rate = rate;
Ttl = ttl;
if ((nonce & 0x00000003) != 0) Nonce = nonce;
throw new ArgumentException("nonce last two bits are reserved and must be zero", "nonce");
_function = function;
_rate = rate;
_ttl = ttl;
_nonce = nonce;
} }
/// <summary> /// <summary>
...@@ -84,32 +75,20 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -84,32 +75,20 @@ namespace PcapDotNet.Packets.IpV4
/// <summary> /// <summary>
/// The function of this quick start option. /// The function of this quick start option.
/// </summary> /// </summary>
public IpV4OptionQuickStartFunction Function public IpV4OptionQuickStartFunction Function { get; private set; }
{
get { return _function; }
}
/// <summary> /// <summary>
/// If function is request then this field is the rate request. /// If function is request then this field is the rate request.
/// If function is report then this field is the rate report. /// If function is report then this field is the rate report.
/// </summary> /// </summary>
public byte Rate public byte Rate { get; private set; }
{
get { return _rate; }
}
/// <summary> /// <summary>
/// The rate translated to KBPS. /// The rate translated to KBPS.
/// </summary> /// </summary>
public int RateKbps public int RateKbps
{ {
get get { return IpOptionQuickStartCommon.CalcRateKbps(Rate); }
{
if (Rate == 0)
return 0;
return 40 * (1 << Rate);
}
} }
/// <summary> /// <summary>
...@@ -124,10 +103,7 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -124,10 +103,7 @@ namespace PcapDotNet.Packets.IpV4
/// TTL Diff = ( IP TTL - QS TTL ) mod 256 /// TTL Diff = ( IP TTL - QS TTL ) mod 256
/// </para> /// </para>
/// </summary> /// </summary>
public byte Ttl public byte Ttl { get; private set; }
{
get { return _ttl; }
}
/// <summary> /// <summary>
/// The QS Nonce gives the Quick-Start sender some protection against receivers lying about the value of the received Rate Request. /// The QS Nonce gives the Quick-Start sender some protection against receivers lying about the value of the received Rate Request.
...@@ -176,10 +152,7 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -176,10 +152,7 @@ namespace PcapDotNet.Packets.IpV4
/// and the receiver reports back a Rate Request of K, then the last 2K bits of the QS Nonce should have their original value. /// and the receiver reports back a Rate Request of K, then the last 2K bits of the QS Nonce should have their original value.
/// </para> /// </para>
/// </summary> /// </summary>
public uint Nonce public uint Nonce { get; private set; }
{
get { return _nonce; }
}
/// <summary> /// <summary>
/// The number of bytes this option will take. /// The number of bytes this option will take.
...@@ -241,12 +214,12 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -241,12 +214,12 @@ namespace PcapDotNet.Packets.IpV4
if (valueLength != OptionValueLength) if (valueLength != OptionValueLength)
return null; return null;
byte functionAndRate = buffer[offset++]; IpV4OptionQuickStartFunction function;
IpV4OptionQuickStartFunction function = (IpV4OptionQuickStartFunction)(functionAndRate & 0xF0); byte rate;
byte rate = (byte)(functionAndRate & 0x0F); byte ttl;
uint nonce;
byte ttl = buffer[offset++]; IpOptionQuickStartCommon.ReadData(new DataSegment(buffer, offset, valueLength), out function, out rate, out ttl, out nonce);
uint nonce = buffer.ReadUInt(ref offset, Endianity.Big); offset += OptionValueLength;
return new IpV4OptionQuickStart(function, rate, ttl, nonce); return new IpV4OptionQuickStart(function, rate, ttl, nonce);
} }
...@@ -255,14 +228,7 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -255,14 +228,7 @@ namespace PcapDotNet.Packets.IpV4
{ {
base.Write(buffer, ref offset); base.Write(buffer, ref offset);
buffer[offset++] = (byte)((byte)Function | Rate); IpOptionQuickStartCommon.WriteData(buffer, ref offset, Function, Rate, Ttl, Nonce);
buffer[offset++] = Ttl;
buffer.Write(ref offset, Nonce, Endianity.Big);
} }
private readonly IpV4OptionQuickStartFunction _function;
private readonly byte _rate;
private readonly byte _ttl;
private readonly uint _nonce;
} }
} }
\ No newline at end of file
namespace PcapDotNet.Packets.IpV4 namespace PcapDotNet.Packets.IpV4
{ {
/// <summary> /// <summary>
/// RFC 4782.
/// Defines the possible quick start functions. /// Defines the possible quick start functions.
/// </summary> /// </summary>
public enum IpV4OptionQuickStartFunction : byte public enum IpV4OptionQuickStartFunction : byte
...@@ -14,6 +15,5 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -14,6 +15,5 @@ namespace PcapDotNet.Packets.IpV4
/// Reports on a specific rate that was agreed (or disagreed). /// Reports on a specific rate that was agreed (or disagreed).
/// </summary> /// </summary>
RateReport = 0x80 RateReport = 0x80
} }
} }
\ No newline at end of file
using System.Collections.Generic; using System.Collections.Generic;
using PcapDotNet.Packets.Ip;
namespace PcapDotNet.Packets.IpV4 namespace PcapDotNet.Packets.IpV4
{ {
...@@ -52,7 +53,7 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -52,7 +53,7 @@ namespace PcapDotNet.Packets.IpV4
/// Appears at most once in a datagram. /// Appears at most once in a datagram.
/// </para> /// </para>
/// </summary> /// </summary>
[OptionTypeRegistration(typeof(IpV4OptionType), IpV4OptionType.RecordRoute)] [IpV4OptionTypeRegistration(IpV4OptionType.RecordRoute)]
public class IpV4OptionRecordRoute : IpV4OptionRoute, IOptionComplexFactory public class IpV4OptionRecordRoute : IpV4OptionRoute, IOptionComplexFactory
{ {
/// <summary> /// <summary>
......
using System; using System;
using PcapDotNet.Packets.Ip;
namespace PcapDotNet.Packets.IpV4 namespace PcapDotNet.Packets.IpV4
{ {
...@@ -31,7 +32,7 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -31,7 +32,7 @@ namespace PcapDotNet.Packets.IpV4
/// </pre> /// </pre>
/// </para> /// </para>
/// </summary> /// </summary>
[OptionTypeRegistration(typeof(IpV4OptionType), IpV4OptionType.RouterAlert)] [IpV4OptionTypeRegistration(IpV4OptionType.RouterAlert)]
public sealed class IpV4OptionRouterAlert : IpV4OptionComplex, IOptionComplexFactory, IEquatable<IpV4OptionRouterAlert> public sealed class IpV4OptionRouterAlert : IpV4OptionComplex, IOptionComplexFactory, IEquatable<IpV4OptionRouterAlert>
{ {
/// <summary> /// <summary>
......
using System; using System;
using PcapDotNet.Packets.Ip;
namespace PcapDotNet.Packets.IpV4 namespace PcapDotNet.Packets.IpV4
{ {
...@@ -16,7 +17,7 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -16,7 +17,7 @@ namespace PcapDotNet.Packets.IpV4
/// Must be copied on fragmentation. /// Must be copied on fragmentation.
/// Appears at most once in a datagram. /// Appears at most once in a datagram.
/// </summary> /// </summary>
[OptionTypeRegistration(typeof(IpV4OptionType), IpV4OptionType.StreamIdentifier)] [IpV4OptionTypeRegistration(IpV4OptionType.StreamIdentifier)]
public sealed class IpV4OptionStreamIdentifier : IpV4OptionComplex, IOptionComplexFactory, IEquatable<IpV4OptionStreamIdentifier> public sealed class IpV4OptionStreamIdentifier : IpV4OptionComplex, IOptionComplexFactory, IEquatable<IpV4OptionStreamIdentifier>
{ {
/// <summary> /// <summary>
......
using System.Collections.Generic; using System.Collections.Generic;
using PcapDotNet.Packets.Ip;
namespace PcapDotNet.Packets.IpV4 namespace PcapDotNet.Packets.IpV4
{ {
...@@ -60,7 +61,7 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -60,7 +61,7 @@ namespace PcapDotNet.Packets.IpV4
/// Appears at most once in a datagram. /// Appears at most once in a datagram.
/// </para> /// </para>
/// </summary> /// </summary>
[OptionTypeRegistration(typeof(IpV4OptionType), IpV4OptionType.StrictSourceRouting)] [IpV4OptionTypeRegistration(IpV4OptionType.StrictSourceRouting)]
public class IpV4OptionStrictSourceRouting : IpV4OptionRoute, IOptionComplexFactory public class IpV4OptionStrictSourceRouting : IpV4OptionRoute, IOptionComplexFactory
{ {
/// <summary> /// <summary>
......
using System; using System;
using PcapDotNet.Base; using PcapDotNet.Base;
using PcapDotNet.Packets.Ip;
namespace PcapDotNet.Packets.IpV4 namespace PcapDotNet.Packets.IpV4
{ {
...@@ -73,7 +74,7 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -73,7 +74,7 @@ namespace PcapDotNet.Packets.IpV4
/// </summary> /// </summary>
public abstract class IpV4OptionTimestamp : IpV4OptionComplex, IEquatable<IpV4OptionTimestamp> public abstract class IpV4OptionTimestamp : IpV4OptionComplex, IEquatable<IpV4OptionTimestamp>
{ {
[OptionTypeRegistration(typeof(IpV4OptionType), IpV4OptionType.InternetTimestamp)] [IpV4OptionTypeRegistration(IpV4OptionType.InternetTimestamp)]
internal class IpV4OptionTimestampFactory : IOptionComplexFactory internal class IpV4OptionTimestampFactory : IOptionComplexFactory
{ {
Option IOptionComplexFactory.CreateInstance(byte[] buffer, ref int offset, byte valueLength) Option IOptionComplexFactory.CreateInstance(byte[] buffer, ref int offset, byte valueLength)
......
using System; using System;
using PcapDotNet.Base; using PcapDotNet.Base;
using PcapDotNet.Packets.Ip;
namespace PcapDotNet.Packets.IpV4 namespace PcapDotNet.Packets.IpV4
{ {
...@@ -31,7 +32,7 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -31,7 +32,7 @@ namespace PcapDotNet.Packets.IpV4
/// Number: 18 (F+C+Number = 82) /// Number: 18 (F+C+Number = 82)
/// </para> /// </para>
/// </summary> /// </summary>
[OptionTypeRegistration(typeof(IpV4OptionType), IpV4OptionType.TraceRoute)] [IpV4OptionTypeRegistration(IpV4OptionType.TraceRoute)]
public sealed class IpV4OptionTraceRoute : IpV4OptionComplex, IOptionComplexFactory, IEquatable<IpV4OptionTraceRoute> public sealed class IpV4OptionTraceRoute : IpV4OptionComplex, IOptionComplexFactory, IEquatable<IpV4OptionTraceRoute>
{ {
/// <summary> /// <summary>
......
using System;
using PcapDotNet.Packets.Ip;
using PcapDotNet.Packets.IpV4;
namespace PcapDotNet.Packets
{
internal sealed class IpV4OptionTypeRegistrationAttribute : OptionTypeRegistrationAttribute
{
public IpV4OptionTypeRegistrationAttribute(IpV4OptionType optionType)
{
IpV4OptionType = optionType;
}
public IpV4OptionType IpV4OptionType { get; private set; }
public override object OptionType
{
get { return IpV4OptionType; }
}
public override Type OptionTypeType
{
get { return typeof(IpV4OptionType); }
}
}
}
\ No newline at end of file
...@@ -3,6 +3,7 @@ using System.Collections.Generic; ...@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using PcapDotNet.Base; using PcapDotNet.Base;
using PcapDotNet.Packets.Ip;
namespace PcapDotNet.Packets.IpV4 namespace PcapDotNet.Packets.IpV4
{ {
......
using System.Collections.Generic; using System.Collections.Generic;
using PcapDotNet.Packets.Ip;
namespace PcapDotNet.Packets.IpV4 namespace PcapDotNet.Packets.IpV4
{ {
...@@ -8,7 +9,7 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -8,7 +9,7 @@ namespace PcapDotNet.Packets.IpV4
/// They must be implemented by all IP modules (host and gateways). /// They must be implemented by all IP modules (host and gateways).
/// What is optional is their transmission in any particular datagram, not their implementation. /// What is optional is their transmission in any particular datagram, not their implementation.
/// </summary> /// </summary>
public class IpV4Options : Options<IpV4Option> public class IpV4Options : V4Options<IpV4Option>
{ {
/// <summary> /// <summary>
/// The maximum number of bytes the options may take. /// The maximum number of bytes the options may take.
......
...@@ -206,9 +206,9 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -206,9 +206,9 @@ namespace PcapDotNet.Packets.IpV4
/// </summary> /// </summary>
Bna = 0x31, Bna = 0x31,
/// <summary> /// <summary>
/// Encapsulating Security Payload RFC 2406 /// ESP. Encapsulating Security Payload RFC 2406.
/// </summary> /// </summary>
Esp = 0x32, EncapsulatingSecurityPayload = 0x32,
/// <summary> /// <summary>
/// Authentication Header RFC 2402 /// Authentication Header RFC 2402
/// </summary> /// </summary>
......
using System; using System;
using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using System.Reflection;
using PcapDotNet.Base; using PcapDotNet.Base;
using PcapDotNet.Packets.Ip;
using PcapDotNet.Packets.IpV4; using PcapDotNet.Packets.IpV4;
namespace PcapDotNet.Packets.IpV6 namespace PcapDotNet.Packets.IpV6
{ {
/// <summary> /// <summary>
/// RFC 2460.
/// Represents an IPv6 datagram. /// Represents an IPv6 datagram.
/// <pre> /// <pre>
/// +-----+---------+---------------+-------+-------------+-----------+ /// +-----+---------+---------------+-------+-------------+-----------+
...@@ -27,7 +31,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -27,7 +31,7 @@ namespace PcapDotNet.Packets.IpV6
/// | | | /// | | |
/// +-----+-----------------------------------------------------------+ /// +-----+-----------------------------------------------------------+
/// | 320 | Extension Headers (optional) | /// | 320 | Extension Headers (optional) |
/// | | ... | /// | ... | |
/// +-----+-----------------------------------------------------------+ /// +-----+-----------------------------------------------------------+
/// </pre> /// </pre>
/// </summary> /// </summary>
...@@ -104,6 +108,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -104,6 +108,11 @@ namespace PcapDotNet.Packets.IpV6
get { return ReadUShort(Offset.PayloadLength, Endianity.Big); } get { return ReadUShort(Offset.PayloadLength, Endianity.Big); }
} }
public ushort RealPayloadLength
{
get { return (ushort)Math.Min(PayloadLength, Length); }
}
/// <summary> /// <summary>
/// Identifies the type of header immediately following the IPv6 header. /// Identifies the type of header immediately following the IPv6 header.
/// Uses the same values as the IPv4 Protocol field. /// Uses the same values as the IPv4 Protocol field.
...@@ -138,6 +147,91 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -138,6 +147,91 @@ namespace PcapDotNet.Packets.IpV6
get { return ReadIpV6Address(Offset.DestinationAddress, Endianity.Big); } get { return ReadIpV6Address(Offset.DestinationAddress, Endianity.Big); }
} }
public ReadOnlyCollection<IpV6ExtensionHeader> ExtensionHeaders
{
get
{
ParseExtensionHeaders();
return _extensionHeaders;
}
}
private void ParseExtensionHeaders()
{
if (_extensionHeaders != null)
return;
List<IpV6ExtensionHeader> extensionHeaders = new List<IpV6ExtensionHeader>();
if (HeaderLength > RealPayloadLength)
{
_isValid = false;
_extensionHeaders = extensionHeaders.AsReadOnly();
return;
}
int extendedHeaderLength = HeaderLength;
IpV4Protocol nextHeader = NextHeader;
while (extendedHeaderLength + 8 <= RealPayloadLength && IsExtensionHeader(nextHeader))
{
int numBytesRead;
IpV6ExtensionHeader extensionHeader = CreateExtensionHeader(nextHeader, Subsegment(extendedHeaderLength, Length - extendedHeaderLength), out numBytesRead);
if (extensionHeader == null)
break;
nextHeader = extensionHeader.NextHeader;
extendedHeaderLength += numBytesRead;
}
_isValid = !IsExtensionHeader(nextHeader) && (HeaderLength + _extensionHeadersLength == PayloadLength);
_extensionHeaders = extensionHeaders.AsReadOnly();
_extensionHeadersLength = extendedHeaderLength - HeaderLength;
}
private IpV6ExtensionHeader CreateExtensionHeader(IpV4Protocol nextHeader, DataSegment data, out int numBytesRead)
{
switch (nextHeader)
{
case IpV4Protocol.IpV6HopByHopOption: // 0
return IpV6ExtensionHeaderHopByHopOptions.Parse(data, out numBytesRead);
/*
case IpV4Protocol.IpV6Route: // 43
return IpV6ExtensionHeaderRouting.Parse(data);
case IpV4Protocol.FragmentHeaderForIpV6: // 44
return IpV6ExtensionHeaderFragment.Parse(data);
case IpV4Protocol.EncapsulatingSecurityPayload: // 50
return IpV6ExtensionHeaderEncapsulatingSecurityPayload.Parse(data);
case IpV4Protocol.AuthenticationHeader: // 51
return IpV6ExtensionHeaderAuthentication.Parse(data);
case IpV4Protocol.IpV6Opts: // 60
return IpV6ExtensionHeaderDestinationOptions.Parse(data);
case IpV4Protocol.MobilityHeader: // 135
return IpV6MobilityExtensionHeader.Parse(data);
*/
default:
throw new InvalidOperationException(string.Format("Invalid next header value {0}", nextHeader));
}
}
private static bool IsExtensionHeader(IpV4Protocol nextHeader)
{
switch (nextHeader)
{
case IpV4Protocol.IpV6HopByHopOption: // 0
case IpV4Protocol.IpV6Route: // 43
case IpV4Protocol.FragmentHeaderForIpV6: // 44
case IpV4Protocol.EncapsulatingSecurityPayload: // 50
case IpV4Protocol.AuthenticationHeader: // 51
case IpV4Protocol.IpV6Opts: // 60
case IpV4Protocol.MobilityHeader: // 135
return true;
default:
return false;
}
}
/// <summary> /// <summary>
/// Creates a Layer that represents the datagram to be used with PacketBuilder. /// Creates a Layer that represents the datagram to be used with PacketBuilder.
/// </summary> /// </summary>
...@@ -179,8 +273,1123 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -179,8 +273,1123 @@ namespace PcapDotNet.Packets.IpV6
protected override bool CalculateIsValid() protected override bool CalculateIsValid()
{ {
// TODO: Implement. ParseExtensionHeaders();
return true; return _isValid;
}
private ReadOnlyCollection<IpV6ExtensionHeader> _extensionHeaders;
private int _extensionHeadersLength;
private bool _isValid;
}
/// <summary>
/// RFC 2460.
/// </summary>
public abstract class IpV6ExtensionHeader
{
protected IpV6ExtensionHeader(IpV4Protocol nextHeader)
{
NextHeader = nextHeader;
}
public IpV4Protocol NextHeader { get; private set; }
}
/// <summary>
/// RFC 2460.
/// +-----+-------------+-------------------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+-------------------------+
/// | 0 | Next Header | Header Extension Length |
/// +-----+-------------+-------------------------+
/// | 16 | Options |
/// | ... | |
/// +-----+---------------------------------------+
/// </summary>
public class IpV6ExtensionHeaderHopByHopOptions : IpV6ExtensionHeader
{
private static class Offset
{
public const int NextHeader = 0;
public const int HeaderExtensionLength = 1;
public const int Options = 2;
}
public const int MinimumLength = 8;
private IpV6ExtensionHeaderHopByHopOptions(IpV4Protocol nextHeader, IpV6Options options)
: base(nextHeader)
{
Options = options;
}
public IpV6Options Options { get; private set; }
internal static IpV6ExtensionHeaderHopByHopOptions Parse(DataSegment data, out int numBytesRead)
{
numBytesRead = 0;
if (data.Length < MinimumLength)
return null;
IpV4Protocol nextHeader = (IpV4Protocol)data[Offset.NextHeader];
int length = (data[Offset.HeaderExtensionLength] + 1) * 8;
if (data.Length < length)
return null;
IpV6Options options = new IpV6Options(data.Subsegment(Offset.Options, length - Offset.Options));
numBytesRead = length;
return new IpV6ExtensionHeaderHopByHopOptions(nextHeader, options);
}
}
public enum IpV6OptionType : byte
{
/// <summary>
/// RFC 2460.
/// </summary>
Pad1 = 0x00,
/// <summary>
/// RFC 2460.
/// </summary>
PadN = 0x01,
/// <summary>
/// RFC 2675.
/// </summary>
JumboPayload = 0xC2,
/// <summary>
/// RFC 2473.
/// </summary>
TunnelEncapsulationLimit = 0x04,
/// <summary>
/// RFC 2711.
/// </summary>
RouterAlert = 0x05,
/// <summary>
/// RFC 4782, Errata 2034.
/// </summary>
QuickStart = 0x26,
/// <summary>
/// RFC 5570.
/// </summary>
Calipso = 0x07,
/// <summary>
/// RFC 6621.
/// </summary>
SmfDpd = 0x08,
/// <summary>
/// RFC 6275.
/// </summary>
HomeAddress = 0xC9,
/// <summary>
/// Charles Lynn.
/// </summary>
EndpointIdentification = 0x8A,
/// <summary>
/// RFC 6553.
/// </summary>
RplOption = 0x63,
/// <summary>
/// RFC irtf-rrg-ilnp-noncev6-06.
/// </summary>
IlnpNonce = 0x8B,
}
/// <summary>
/// RFC 2460.
/// <pre>
/// +-----+-------------+-------------------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+-------------------------+
/// | 0 | Option Type | Opt Data Len (optional) |
/// +-----+-------------+-------------------------+
/// | 16 | Option Data (optional) |
/// | ... | |
/// +-----+---------------------------------------+
/// </pre>
/// </summary>
public abstract class IpV6Option : Option
{
/// <summary>
/// The type of the IP option.
/// </summary>
public IpV6OptionType OptionType { get; private set; }
internal abstract IpV6Option CreateInstance(DataSegment data);
protected IpV6Option(IpV6OptionType type)
{
OptionType = type;
}
internal override void Write(byte[] buffer, ref int offset)
{
buffer[offset++] = (byte)OptionType;
}
public override int Length
{
get { return sizeof(byte); }
}
}
/// <summary>
/// RFC 2460.
/// <pre>
/// +-----+-------------+
/// | Bit | 0-7 |
/// +-----+-------------+
/// | 0 | Option Type |
/// +-----+-------------+
/// </pre>
/// </summary>
public abstract class IpV6OptionSimple : IpV6Option
{
protected IpV6OptionSimple(IpV6OptionType type) : base(type)
{
}
public override sealed int Length
{
get { return base.Length; }
}
internal override sealed void Write(byte[] buffer, ref int offset)
{
base.Write(buffer, ref offset);
}
}
/// <summary>
/// RFC 2460.
/// <pre>
/// +-----+-------------+--------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+--------------+
/// | 0 | Option Type | Opt Data Len |
/// +-----+-------------+--------------+
/// | 16 | Option Data |
/// | ... | |
/// +-----+----------------------------+
/// </pre>
/// </summary>
public abstract class IpV6OptionComplex : IpV6Option
{
protected IpV6OptionComplex(IpV6OptionType type)
: base(type)
{
}
public override sealed int Length
{
get { return base.Length + sizeof (byte) + DataLength; }
}
internal abstract int DataLength { get; }
internal override sealed void Write(byte[] buffer, ref int offset)
{
base.Write(buffer, ref offset);
buffer[offset++] = (byte)DataLength;
WriteData(buffer, ref offset);
}
internal abstract void WriteData(byte[] buffer, ref int offset);
}
/// <summary>
/// RFC 2460.
/// <pre>
/// +-----+-------------+--------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+--------------+
/// | 0 | Option Type | Opt Data Len |
/// +-----+-------------+--------------+
/// | 16 | Option Data |
/// | ... | |
/// +-----+----------------------------+
/// </pre>
/// </summary>
public class IpV6OptionUnknown : IpV6OptionComplex
{
public IpV6OptionUnknown(IpV6OptionType type, DataSegment data)
: base(type)
{
Data = data;
}
public DataSegment Data { get; private set; }
internal Option Read(byte[] buffer, ref int offset, int length)
{
throw new NotImplementedException();
}
internal override IpV6Option CreateInstance(DataSegment data)
{
throw new InvalidOperationException("IpV6OptionUnknown shouldn't be registered.");
}
internal override int DataLength
{
get { return Data.Length; }
}
internal override void WriteData(byte[] buffer, ref int offset)
{
buffer.Write(ref offset, Data);
}
}
/// <summary>
/// +-----+-----+
/// | Bit | 0-7 |
/// +-----+-----+
/// | 0 | 0 |
/// +-----+-----+
/// </summary>
[IpV6OptionTypeRegistration(IpV6OptionType.Pad1)]
public class IpV6OptionPad1 : IpV6OptionSimple
{
public const int OptionLength = sizeof(byte);
public IpV6OptionPad1()
: base(IpV6OptionType.Pad1)
{
}
internal override IpV6Option CreateInstance(DataSegment data)
{
return new IpV6OptionPad1();
}
}
/// <summary>
/// RFC 2460.
/// <pre>
/// +-----+-------------+--------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+--------------+
/// | 0 | Option Type | N |
/// +-----+-------------+--------------+
/// | 16 | 0 |
/// | ... | |
/// +-----+----------------------------+
/// </pre>
/// </summary>
[IpV6OptionTypeRegistration(IpV6OptionType.PadN)]
public class IpV6OptionPadN : IpV6OptionComplex
{
public IpV6OptionPadN(int paddingDataLength) : base(IpV6OptionType.PadN)
{
PaddingDataLength = paddingDataLength;
}
public int PaddingDataLength { get; private set; }
internal override IpV6Option CreateInstance(DataSegment data)
{
return new IpV6OptionPadN(data.Length);
}
internal override int DataLength
{
get { return PaddingDataLength; }
}
internal override void WriteData(byte[] buffer, ref int offset)
{
offset += PaddingDataLength;
}
}
/// <summary>
/// RFC 2675.
/// <pre>
/// +-----+-------------+--------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+--------+
/// | 0 | Option Type | 4 |
/// +-----+-------------+--------+
/// | 16 | Jumbo Payload Length |
/// | | |
/// +-----+----------------------+
/// </pre>
/// </summary>
[IpV6OptionTypeRegistration(IpV6OptionType.JumboPayload)]
public class IpV6OptionJumboPayload : IpV6OptionComplex
{
public const int OptionDataLength = sizeof(uint);
public IpV6OptionJumboPayload(uint jumboPayloadLength) : base(IpV6OptionType.JumboPayload)
{
JumboPayloadLength = jumboPayloadLength;
}
/// <summary>
/// Length of the IPv6 packet in octets, excluding the IPv6 header but including the Hop-by-Hop Options header and any other extension headers present.
/// Must be greater than 65,535.
/// </summary>
public uint JumboPayloadLength { get; private set; }
internal override IpV6Option CreateInstance(DataSegment data)
{
if (data.Length != OptionDataLength)
return null;
return new IpV6OptionJumboPayload(data.ReadUInt(0, Endianity.Big));
}
internal override int DataLength
{
get { return OptionDataLength; }
}
internal override void WriteData(byte[] buffer, ref int offset)
{
buffer.Write(ref offset, JumboPayloadLength, Endianity.Big);
}
}
/// <summary>
/// RFC 2473.
/// <pre>
/// +-----+----------------------------+--------+
/// | Bit | 0-7 | 8-15 |
/// +-----+----------------------------+--------+
/// | 0 | Option Type | 1 |
/// +-----+----------------------------+--------+
/// | 16 | Tunnel Encapsulation Limit |
/// +-----+----------------------------+
/// </pre>
/// </summary>
[IpV6OptionTypeRegistration(IpV6OptionType.TunnelEncapsulationLimit)]
public class IpV6OptionTunnelEncapsulationLimit : IpV6OptionComplex
{
public const int OptionDataLength = sizeof(byte);
public IpV6OptionTunnelEncapsulationLimit(byte tunnelEncapsulationLimit)
: base(IpV6OptionType.JumboPayload)
{
TunnelEncapsulationLimit = tunnelEncapsulationLimit;
}
/// <summary>
/// How many further levels of encapsulation are permitted for the packet.
/// </summary>
public byte TunnelEncapsulationLimit { get; private set; }
internal override IpV6Option CreateInstance(DataSegment data)
{
if (data.Length != OptionDataLength)
return null;
return new IpV6OptionTunnelEncapsulationLimit(data[0]);
}
internal override int DataLength
{
get { return OptionDataLength; }
} }
internal override void WriteData(byte[] buffer, ref int offset)
{
buffer.Write(ref offset, TunnelEncapsulationLimit);
}
}
/// <summary>
/// RFC 2711.
/// </summary>
public enum IpV6RouterAlertType : ushort
{
/// <summary>
/// RFC 2710.
/// Datagram contains a Multicast Listener Discovery message.
/// </summary>
MulticastListenerDiscovery = 0x0000,
/// <summary>
/// RFC 2711.
/// Datagram contains RSVP message.
/// </summary>
Rsvp = 0x0001,
/// <summary>
/// RFC 2711.
/// Datagram contains an Active Networks message.
/// </summary>
ActiveNetwork = 0x0002,
/// <summary>
/// RFC 3175.
/// 1 depth of nesting of aggregation.
/// </summary>
AggregationNestingDepth1 = 0x0004,
/// <summary>
/// RFC 3175.
/// 2 depth of nesting of aggregation.
/// </summary>
AggregationNestingDepth2 = 0x0005,
/// <summary>
/// RFC 3175.
/// 3 depth of nesting of aggregation.
/// </summary>
AggregationNestingDepth3 = 0x0006,
/// <summary>
/// RFC 3175.
/// 4 depth of nesting of aggregation.
/// </summary>
AggregationNestingDepth4 = 0x0007,
/// <summary>
/// RFC 3175.
/// 5 depth of nesting of aggregation.
/// </summary>
AggregationNestingDepth5 = 0x0008,
/// <summary>
/// RFC 3175.
/// 6 depth of nesting of aggregation.
/// </summary>
AggregationNestingDepth6 = 0x0009,
/// <summary>
/// RFC 3175.
/// 7 depth of nesting of aggregation.
/// </summary>
AggregationNestingDepth7 = 0x000A,
/// <summary>
/// RFC 3175.
/// 8 depth of nesting of aggregation.
/// </summary>
AggregationNestingDepth8 = 0x000B,
/// <summary>
/// RFC 3175.
/// 9 depth of nesting of aggregation.
/// </summary>
AggregationNestingDepth9 = 0x000C,
/// <summary>
/// RFC 3175.
/// 10 depth of nesting of aggregation.
/// </summary>
AggregationNestingDepth10 = 0x000D,
/// <summary>
/// RFC 3175.
/// 11 depth of nesting of aggregation.
/// </summary>
AggregationNestingDepth11 = 0x000E,
/// <summary>
/// RFC 3175.
/// 12 depth of nesting of aggregation.
/// </summary>
AggregationNestingDepth12 = 0x000F,
/// <summary>
/// RFC 3175.
/// 13 depth of nesting of aggregation.
/// </summary>
AggregationNestingDepth13 = 0x0010,
/// <summary>
/// RFC 3175.
/// 14 depth of nesting of aggregation.
/// </summary>
AggregationNestingDepth14 = 0x0011,
/// <summary>
/// RFC 3175.
/// 15 depth of nesting of aggregation.
/// </summary>
AggregationNestingDepth15 = 0x0012,
/// <summary>
/// RFC 3175.
/// 16 depth of nesting of aggregation.
/// </summary>
AggregationNestingDepth16 = 0x0013,
/// <summary>
/// RFC 3175.
/// 17 depth of nesting of aggregation.
/// </summary>
AggregationNestingDepth17 = 0x0014,
/// <summary>
/// RFC 3175.
/// 18 depth of nesting of aggregation.
/// </summary>
AggregationNestingDepth18 = 0x0015,
/// <summary>
/// RFC 3175.
/// 19 depth of nesting of aggregation.
/// </summary>
AggregationNestingDepth19 = 0x0016,
/// <summary>
/// RFC 3175.
/// 20 depth of nesting of aggregation.
/// </summary>
AggregationNestingDepth20 = 0x0017,
/// <summary>
/// RFC 3175.
/// 21 depth of nesting of aggregation.
/// </summary>
AggregationNestingDepth21 = 0x0018,
/// <summary>
/// RFC 3175.
/// 22 depth of nesting of aggregation.
/// </summary>
AggregationNestingDepth22 = 0x0019,
/// <summary>
/// RFC 3175.
/// 23 depth of nesting of aggregation.
/// </summary>
AggregationNestingDepth23 = 0x001A,
/// <summary>
/// RFC 3175.
/// 24 depth of nesting of aggregation.
/// </summary>
AggregationNestingDepth24 = 0x001B,
/// <summary>
/// RFC 3175.
/// 25 depth of nesting of aggregation.
/// </summary>
AggregationNestingDepth25 = 0x001C,
/// <summary>
/// RFC 3175.
/// 26 depth of nesting of aggregation.
/// </summary>
AggregationNestingDepth26 = 0x001D,
/// <summary>
/// RFC 3175.
/// 27 depth of nesting of aggregation.
/// </summary>
AggregationNestingDepth27 = 0x001E,
/// <summary>
/// RFC 3175.
/// 28 depth of nesting of aggregation.
/// </summary>
AggregationNestingDepth28 = 0x001F,
/// <summary>
/// RFC 3175.
/// 29 depth of nesting of aggregation.
/// </summary>
AggregationNestingDepth29 = 0x0020,
/// <summary>
/// RFC 3175.
/// 30 depth of nesting of aggregation.
/// </summary>
AggregationNestingDepth30 = 0x0021,
/// <summary>
/// RFC 3175.
/// 31 depth of nesting of aggregation.
/// </summary>
AggregationNestingDepth31 = 0x0022,
/// <summary>
/// RFC 3175.
/// 32 depth of nesting of aggregation.
/// </summary>
AggregationNestingDepth32 = 0x0023,
/// <summary>
/// RFC 5974.
/// QoS NSLP Aggregation Level 0.
/// </summary>
QoSNslpAggregationLevel0 = 0x0024,
/// <summary>
/// RFC 5974.
/// QoS NSLP Aggregation Level 1.
/// </summary>
QoSNslpAggregationLevel1 = 0x0025,
/// <summary>
/// RFC 5974.
/// QoS NSLP Aggregation Level 2.
/// </summary>
QoSNslpAggregationLevel2 = 0x0026,
/// <summary>
/// RFC 5974.
/// QoS NSLP Aggregation Level 3.
/// </summary>
QoSNslpAggregationLevel3 = 0x0027,
/// <summary>
/// RFC 5974.
/// QoS NSLP Aggregation Level 4.
/// </summary>
QoSNslpAggregationLevel4 = 0x0028,
/// <summary>
/// RFC 5974.
/// QoS NSLP Aggregation Level 5.
/// </summary>
QoSNslpAggregationLevel5 = 0x0029,
/// <summary>
/// RFC 5974.
/// QoS NSLP Aggregation Level 6.
/// </summary>
QoSNslpAggregationLevel6 = 0x002A,
/// <summary>
/// RFC 5974.
/// QoS NSLP Aggregation Level 7.
/// </summary>
QoSNslpAggregationLevel7 = 0x002B,
/// <summary>
/// RFC 5974.
/// QoS NSLP Aggregation Level 8.
/// </summary>
QoSNslpAggregationLevel8 = 0x002C,
/// <summary>
/// RFC 5974.
/// QoS NSLP Aggregation Level 9.
/// </summary>
QoSNslpAggregationLevel9 = 0x002D,
/// <summary>
/// RFC 5974.
/// QoS NSLP Aggregation Level 10.
/// </summary>
QoSNslpAggregationLevel10 = 0x002E,
/// <summary>
/// RFC 5974.
/// QoS NSLP Aggregation Level 11.
/// </summary>
QoSNslpAggregationLevel11 = 0x002F,
/// <summary>
/// RFC 5974.
/// QoS NSLP Aggregation Level 12.
/// </summary>
QoSNslpAggregationLevel12 = 0x0030,
/// <summary>
/// RFC 5974.
/// QoS NSLP Aggregation Level 13.
/// </summary>
QoSNslpAggregationLevel13 = 0x0031,
/// <summary>
/// RFC 5974.
/// QoS NSLP Aggregation Level 14.
/// </summary>
QoSNslpAggregationLevel14 = 0x0032,
/// <summary>
/// RFC 5974.
/// QoS NSLP Aggregation Level 15.
/// </summary>
QoSNslpAggregationLevel15 = 0x0033,
/// <summary>
/// RFC 5974.
/// QoS NSLP Aggregation Level 16.
/// </summary>
QoSNslpAggregationLevel16 = 0x0034,
/// <summary>
/// RFC 5974.
/// QoS NSLP Aggregation Level 17.
/// </summary>
QoSNslpAggregationLevel17 = 0x0035,
/// <summary>
/// RFC 5974.
/// QoS NSLP Aggregation Level 18.
/// </summary>
QoSNslpAggregationLevel18 = 0x0036,
/// <summary>
/// RFC 5974.
/// QoS NSLP Aggregation Level 19.
/// </summary>
QoSNslpAggregationLevel19 = 0x0037,
/// <summary>
/// RFC 5974.
/// QoS NSLP Aggregation Level 20.
/// </summary>
QoSNslpAggregationLevel20 = 0x0038,
/// <summary>
/// RFC 5974.
/// QoS NSLP Aggregation Level 21.
/// </summary>
QoSNslpAggregationLevel21 = 0x0039,
/// <summary>
/// RFC 5974.
/// QoS NSLP Aggregation Level 22.
/// </summary>
QoSNslpAggregationLevel22 = 0x003A,
/// <summary>
/// RFC 5974.
/// QoS NSLP Aggregation Level 23.
/// </summary>
QoSNslpAggregationLevel23 = 0x003B,
/// <summary>
/// RFC 5974.
/// QoS NSLP Aggregation Level 24.
/// </summary>
QoSNslpAggregationLevel24 = 0x003C,
/// <summary>
/// RFC 5974.
/// QoS NSLP Aggregation Level 25.
/// </summary>
QoSNslpAggregationLevel25 = 0x003D,
/// <summary>
/// RFC 5974.
/// QoS NSLP Aggregation Level 26.
/// </summary>
QoSNslpAggregationLevel26 = 0x003E,
/// <summary>
/// RFC 5974.
/// QoS NSLP Aggregation Level 27.
/// </summary>
QoSNslpAggregationLevel27 = 0x003F,
/// <summary>
/// RFC 5974.
/// QoS NSLP Aggregation Level 28.
/// </summary>
QoSNslpAggregationLevel28 = 0x0040,
/// <summary>
/// RFC 5974.
/// QoS NSLP Aggregation Level 29.
/// </summary>
QoSNslpAggregationLevel29 = 0x0041,
/// <summary>
/// RFC 5974.
/// QoS NSLP Aggregation Level 30.
/// </summary>
QoSNslpAggregationLevel30 = 0x0042,
/// <summary>
/// RFC 5974.
/// QoS NSLP Aggregation Level 31.
/// </summary>
QoSNslpAggregationLevel31 = 0x0043,
/// <summary>
/// RFC 5973.
/// NSIS NATFW NSLP.
/// </summary>
NsisNatfwNslp = 0x0044,
}
/// <summary>
/// RFC 2711.
/// <pre>
/// +-----+-------------+--------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+--------+
/// | 0 | Option Type | 2 |
/// +-----+-------------+--------+
/// | 16 | Router Alert Type |
/// +-----+----------------------+
/// </pre>
/// </summary>
[IpV6OptionTypeRegistration(IpV6OptionType.RouterAlert)]
public class IpV6OptionRouterAlert : IpV6OptionComplex
{
public const int OptionDataLength = sizeof(ushort);
public IpV6OptionRouterAlert(IpV6RouterAlertType routerAlertType)
: base(IpV6OptionType.RouterAlert)
{
RouterAlertType = routerAlertType;
}
/// <summary>
/// Type of router alert.
/// </summary>
public IpV6RouterAlertType RouterAlertType { get; private set; }
internal override IpV6Option CreateInstance(DataSegment data)
{
if (data.Length != OptionDataLength)
return null;
return new IpV6OptionRouterAlert((IpV6RouterAlertType)data.ReadUShort(0, Endianity.Big));
}
internal override int DataLength
{
get { return OptionDataLength; }
}
internal override void WriteData(byte[] buffer, ref int offset)
{
buffer.Write(ref offset, (ushort)RouterAlertType, Endianity.Big);
}
}
/// <summary>
/// RFC 4782.
/// <pre>
/// +-----+-------------+------+----------+--------------+-------+-------+
/// | Bit | 0-7 | 8-15 | 16-19 | 20-23 | 24-29 | 30-31 |
/// +-----+-------------+------+----------+--------------+-------+-------+
/// | 0 | Option Type | 6 | Function | Rate Request | QS TTL |
/// +-----+-------------+------+----------+--------------+-------+-------+
/// | 32 | QS Nonce | R |
/// +-----+------------------------------------------------------+-------+
/// </pre>
/// </summary>
[IpV6OptionTypeRegistration(IpV6OptionType.QuickStart)]
public class IpV6OptionQuickStart : IpV6OptionComplex, IIpOptionQuickStart
{
public const int OptionDataLength = IpOptionQuickStartCommon.DataLength;
public IpV6OptionQuickStart(IpV4OptionQuickStartFunction function, byte rate, byte ttl, uint nonce)
: base(IpV6OptionType.QuickStart)
{
IpOptionQuickStartCommon.AssertValidParameters(function, rate, ttl, nonce);
Function = function;
Rate = rate;
Ttl = ttl;
Nonce = nonce;
}
public IpV4OptionQuickStartFunction Function { get; private set; }
public byte Rate { get; private set; }
public int RateKbps
{
get { return IpOptionQuickStartCommon.CalcRateKbps(Rate); }
}
public byte Ttl { get; private set; }
public uint Nonce { get; private set; }
internal override int DataLength
{
get { return OptionDataLength; }
}
internal override IpV6Option CreateInstance(DataSegment data)
{
if (data.Length != OptionDataLength)
return null;
IpV4OptionQuickStartFunction function;
byte rate;
byte ttl;
uint nonce;
IpOptionQuickStartCommon.ReadData(data, out function, out rate, out ttl, out nonce);
return new IpV6OptionQuickStart(function, rate, ttl, nonce);
}
internal override void WriteData(byte[] buffer, ref int offset)
{
IpOptionQuickStartCommon.WriteData(buffer, ref offset, Function, Rate, Ttl, Nonce);
}
}
// Calipso = 0x07,
// SmfDpd = 0x08,
// HomeAddress = 0xC9,
// EndpointIdentification = 0x8A,
// RplOption = 0x63,
// IlnpNonce = 0x8B,
public class IpV6Options : Options<IpV6Option>
{
public IpV6Options(DataSegment data) : this(Read(data))
{
}
private IpV6Options(Tuple<IList<IpV6Option>, bool> optionsAndIsValid) : base(optionsAndIsValid.Item1, optionsAndIsValid.Item2, null)
{
}
public static Tuple<IList<IpV6Option>, bool> Read(DataSegment data)
{
int offset = 0;
List<IpV6Option> options = new List<IpV6Option>();
bool isValid = true;
while (offset < data.Length)
{
IpV6OptionType optionType = (IpV6OptionType)data[offset++];
if (optionType == IpV6OptionType.Pad1)
{
options.Add(new IpV6OptionPad1());
continue;
}
if (offset >= data.Length)
{
isValid = false;
break;
}
byte optionDataLength = data[offset++];
if (offset + optionDataLength > data.Length)
{
isValid = false;
break;
}
IpV6Option option = CreateOption(optionType, data.Subsegment(ref offset, optionDataLength));
if (option == null)
{
isValid = false;
break;
}
options.Add(option);
}
return new Tuple<IList<IpV6Option>, bool>(options, isValid);
}
private static IpV6Option CreateOption(IpV6OptionType optionType, DataSegment data)
{
IpV6Option prototype;
if (!_prototypes.TryGetValue(optionType, out prototype))
return new IpV6OptionUnknown(optionType, data);
return prototype.CreateInstance(data);
}
private static readonly Dictionary<IpV6OptionType, IpV6Option> _prototypes = InitializePrototypes();
private static Dictionary<IpV6OptionType, IpV6Option> InitializePrototypes()
{
var prototypes =
from type in Assembly.GetExecutingAssembly().GetTypes()
where typeof(IpV6Option).IsAssignableFrom(type) &&
GetRegistrationAttribute(type) != null
select new
{
GetRegistrationAttribute(type).OptionType,
Option = (IpV6Option)Activator.CreateInstance(type)
};
return prototypes.ToDictionary(option => option.OptionType, option => option.Option);
}
private static IpV6OptionTypeRegistrationAttribute GetRegistrationAttribute(Type type)
{
var registraionAttributes = type.GetCustomAttributes<IpV6OptionTypeRegistrationAttribute>(false);
if (!registraionAttributes.Any())
return null;
return registraionAttributes.First();
}
}
internal sealed class IpV6OptionTypeRegistrationAttribute : Attribute
{
public IpV6OptionTypeRegistrationAttribute(IpV6OptionType optionType)
{
OptionType = optionType;
}
public IpV6OptionType OptionType { get; private set; }
}
/*
/// <summary>
/// RFC 2460.
/// +-----+-------------+-------------------------+--------------+---------------+
/// | Bit | 0-7 | 8-15 | 16-23 | 24-31 |
/// +-----+-------------+-------------------------+--------------+---------------+
/// | 0 | Next Header | Header Extension Length | Routing Type | Segments Left |
/// +-----+-------------+-------------------------+--------------+---------------+
/// | 32 | type-specific data |
/// | ... | |
/// +-----+----------------------------------------------------------------------+
/// </summary>
public class IpV6ExtensionHeaderRouting : IpV6ExtensionHeader
{
}
/// <summary>
/// RFC 2460.
/// +-----+-------------+----------+-----------------+----------+----+
/// | Bit | 0-7 | 8-15 | 16-28 | 29-30 | 31 |
/// +-----+-------------+----------+-----------------+----------+----+
/// | 0 | Next Header | Reserved | Fragment Offset | Reserved | M |
/// +-----+-------------+----------+-----------------+----------+----+
/// | 32 | Identification |
/// +-----+----------------------------------------------------------+
/// </summary>
public class IpV6ExtensionHeaderFragment : IpV6ExtensionHeader
{
}
/// <summary>
/// RFC 2460.
/// +-----+-------------+-------------------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+-------------------------+
/// | 0 | Next Header | Header Extension Length |
/// +-----+-------------+-------------------------+
/// | 16 | Options |
/// | ... | |
/// +-----+---------------------------------------+
/// </summary>
public class IpV6ExtensionHeaderDestinationOptions : IpV6ExtensionHeader
{
}
/// <summary>
/// RFC 2402.
/// </summary>
public class IpV6ExtensionHeaderAuthentication : IpV6ExtensionHeader
{
}
/// <summary>
/// RFC 2406.
/// </summary>
public class IpV6ExtensionHeaderEncapsulatingSecurityPayload : IpV6ExtensionHeader
{
} }
*/
} }
using System;
namespace PcapDotNet.Packets
{
internal sealed class OptionTypeRegistrationAttribute : Attribute
{
public OptionTypeRegistrationAttribute(Type optionTypeType, object optionType)
{
OptionTypeType = optionTypeType;
OptionType = optionType;
}
public object OptionType { get; private set; }
public Type OptionTypeType { get; private set; }
}
}
\ No newline at end of file
...@@ -316,17 +316,22 @@ ...@@ -316,17 +316,22 @@
<Compile Include="Igmp\IgmpRecordType.cs" /> <Compile Include="Igmp\IgmpRecordType.cs" />
<Compile Include="Igmp\IgmpMessageType.cs" /> <Compile Include="Igmp\IgmpMessageType.cs" />
<Compile Include="Igmp\IIgmpLayerWithGroupAddress.cs" /> <Compile Include="Igmp\IIgmpLayerWithGroupAddress.cs" />
<Compile Include="Ip\V4Option.cs" />
<Compile Include="Ip\IIpOptionQuickStart.cs" />
<Compile Include="IpV4\IpV4OptionTypeRegistrationAttribute.cs" />
<Compile Include="IpV4\IIpV4NextLayer.cs" /> <Compile Include="IpV4\IIpV4NextLayer.cs" />
<Compile Include="IpV4\IIpV4NextTransportLayer.cs" /> <Compile Include="IpV4\IIpV4NextTransportLayer.cs" />
<Compile Include="ILayer.cs" /> <Compile Include="ILayer.cs" />
<Compile Include="IOptionUnknownFactory.cs" /> <Compile Include="Ip\IOptionUnknownFactory.cs" />
<Compile Include="IpV4\IpV4Layer.cs" /> <Compile Include="IpV4\IpV4Layer.cs" />
<Compile Include="IpV4\IpV4OptionUnknown.cs" /> <Compile Include="IpV4\IpV4OptionUnknown.cs" />
<Compile Include="Ip\IpOptionQuickStartCommon.cs" />
<Compile Include="Transport\TcpOptionTypeRegistrationAttribute.cs" />
<Compile Include="IpV6\IpV6Address.cs" /> <Compile Include="IpV6\IpV6Address.cs" />
<Compile Include="IpV6\IpV6Datagram.cs" /> <Compile Include="IpV6\IpV6Datagram.cs" />
<Compile Include="Layer.cs" /> <Compile Include="Layer.cs" />
<Compile Include="Option.cs" /> <Compile Include="Ip\Option.cs" />
<Compile Include="IOptionComplexFactory.cs" /> <Compile Include="Ip\IOptionComplexFactory.cs" />
<Compile Include="IpV4\IpV4Address.cs" /> <Compile Include="IpV4\IpV4Address.cs" />
<Compile Include="IpV4\IpV4Datagram.cs" /> <Compile Include="IpV4\IpV4Datagram.cs" />
<Compile Include="IpV4\IpV4Fragmentation.cs" /> <Compile Include="IpV4\IpV4Fragmentation.cs" />
...@@ -356,9 +361,9 @@ ...@@ -356,9 +361,9 @@
<Compile Include="IpV4\IpV4OptionType.cs" /> <Compile Include="IpV4\IpV4OptionType.cs" />
<Compile Include="IpV4\IpV4Protocol.cs" /> <Compile Include="IpV4\IpV4Protocol.cs" />
<Compile Include="ByteArrayExtensions.cs" /> <Compile Include="ByteArrayExtensions.cs" />
<Compile Include="OptionComplexFactory.cs" /> <Compile Include="Ip\OptionComplexFactory.cs" />
<Compile Include="Options.cs" /> <Compile Include="Ip\Options.cs" />
<Compile Include="OptionTypeRegistrationAttribute.cs" /> <Compile Include="Ip\OptionTypeRegistrationAttribute.cs" />
<Compile Include="Packet.cs" /> <Compile Include="Packet.cs" />
<Compile Include="PacketBuilder.cs" /> <Compile Include="PacketBuilder.cs" />
<Compile Include="PayloadLayer.cs" /> <Compile Include="PayloadLayer.cs" />
...@@ -400,6 +405,7 @@ ...@@ -400,6 +405,7 @@
<Compile Include="Ethernet\ClassOfService.cs" /> <Compile Include="Ethernet\ClassOfService.cs" />
<Compile Include="Ethernet\VLanTaggedFrameDatagram.cs" /> <Compile Include="Ethernet\VLanTaggedFrameDatagram.cs" />
<Compile Include="Ethernet\VLanTaggedFrameLayer.cs" /> <Compile Include="Ethernet\VLanTaggedFrameLayer.cs" />
<Compile Include="Ip\V4Options.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\PcapDotNet.snk" /> <None Include="..\PcapDotNet.snk" />
......
using System; using System;
using PcapDotNet.Packets.Ip;
using PcapDotNet.Packets.IpV4;
namespace PcapDotNet.Packets.Transport namespace PcapDotNet.Packets.Transport
{ {
/// <summary> /// <summary>
/// Represents a TCP option according to rfc 793. /// Represents a TCP option according to rfc 793.
/// </summary> /// </summary>
public abstract class TcpOption : Option, IEquatable<TcpOption> public abstract class TcpOption : V4Option, IEquatable<TcpOption>
{ {
/// <summary> /// <summary>
/// This option code indicates the end of the option list. /// This option code indicates the end of the option list.
...@@ -78,7 +80,7 @@ namespace PcapDotNet.Packets.Transport ...@@ -78,7 +80,7 @@ namespace PcapDotNet.Packets.Transport
return OptionType.ToString(); return OptionType.ToString();
} }
internal sealed override Option Read(byte[] buffer, ref int offset, int length) internal sealed override V4Option Read(byte[] buffer, ref int offset, int length)
{ {
int offsetEnd = offset + length; int offsetEnd = offset + length;
if (offset == offsetEnd) if (offset == offsetEnd)
...@@ -93,7 +95,7 @@ namespace PcapDotNet.Packets.Transport ...@@ -93,7 +95,7 @@ namespace PcapDotNet.Packets.Transport
return Nop; return Nop;
default: default:
return OptionComplexFactory<TcpOptionType>.Read(optionType, buffer, ref offset, offsetEnd - offset); return (V4Option)OptionComplexFactory<TcpOptionType>.Read(optionType, buffer, ref offset, offsetEnd - offset);
} }
} }
......
...@@ -3,6 +3,7 @@ using System.Collections.Generic; ...@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using PcapDotNet.Base; using PcapDotNet.Base;
using PcapDotNet.Packets.Ip;
namespace PcapDotNet.Packets.Transport namespace PcapDotNet.Packets.Transport
{ {
...@@ -33,7 +34,7 @@ namespace PcapDotNet.Packets.Transport ...@@ -33,7 +34,7 @@ namespace PcapDotNet.Packets.Transport
/// While computing the alternate checksum, the TCP checksum field and the data portion TCP Alternate Checksum Data Option are replaced with zeros. /// While computing the alternate checksum, the TCP checksum field and the data portion TCP Alternate Checksum Data Option are replaced with zeros.
/// </para> /// </para>
/// </summary> /// </summary>
[OptionTypeRegistration(typeof(TcpOptionType), TcpOptionType.AlternateChecksumData)] [TcpOptionTypeRegistration(TcpOptionType.AlternateChecksumData)]
public sealed class TcpOptionAlternateChecksumData : TcpOptionComplex, IOptionComplexFactory, IEquatable<TcpOptionAlternateChecksumData> public sealed class TcpOptionAlternateChecksumData : TcpOptionComplex, IOptionComplexFactory, IEquatable<TcpOptionAlternateChecksumData>
{ {
/// <summary> /// <summary>
......
using System; using System;
using PcapDotNet.Packets.Ip;
namespace PcapDotNet.Packets.Transport namespace PcapDotNet.Packets.Transport
{ {
...@@ -27,7 +28,7 @@ namespace PcapDotNet.Packets.Transport ...@@ -27,7 +28,7 @@ namespace PcapDotNet.Packets.Transport
/// Note that the 8-bit Fletcher algorithm gives a 16-bit checksum and the 16-bit algorithm gives a 32-bit checksum. /// Note that the 8-bit Fletcher algorithm gives a 16-bit checksum and the 16-bit algorithm gives a 32-bit checksum.
/// </para> /// </para>
/// </summary> /// </summary>
[OptionTypeRegistration(typeof(TcpOptionType), TcpOptionType.AlternateChecksumRequest)] [TcpOptionTypeRegistration(TcpOptionType.AlternateChecksumRequest)]
public sealed class TcpOptionAlternateChecksumRequest : TcpOptionComplex, IOptionComplexFactory, IEquatable<TcpOptionAlternateChecksumRequest> public sealed class TcpOptionAlternateChecksumRequest : TcpOptionComplex, IOptionComplexFactory, IEquatable<TcpOptionAlternateChecksumRequest>
{ {
/// <summary> /// <summary>
......
using PcapDotNet.Packets.Ip;
namespace PcapDotNet.Packets.Transport namespace PcapDotNet.Packets.Transport
{ {
/// <summary> /// <summary>
...@@ -15,7 +17,7 @@ namespace PcapDotNet.Packets.Transport ...@@ -15,7 +17,7 @@ namespace PcapDotNet.Packets.Transport
/// Its SEG.CC value is the TCB.CCsend value from the sender's TCB. /// Its SEG.CC value is the TCB.CCsend value from the sender's TCB.
/// </para> /// </para>
/// </summary> /// </summary>
[OptionTypeRegistration(typeof(TcpOptionType), TcpOptionType.ConnectionCount)] [TcpOptionTypeRegistration(TcpOptionType.ConnectionCount)]
public class TcpOptionConnectionCount : TcpOptionConnectionCountBase, IOptionComplexFactory public class TcpOptionConnectionCount : TcpOptionConnectionCountBase, IOptionComplexFactory
{ {
/// <summary> /// <summary>
......
using PcapDotNet.Packets.Ip;
namespace PcapDotNet.Packets.Transport namespace PcapDotNet.Packets.Transport
{ {
/// <summary> /// <summary>
...@@ -19,7 +21,7 @@ namespace PcapDotNet.Packets.Transport ...@@ -19,7 +21,7 @@ namespace PcapDotNet.Packets.Transport
/// A CC.ECHO option should be sent only in a &lt;SYN,ACK&gt; segment and should be ignored if it is received in any other segment. /// A CC.ECHO option should be sent only in a &lt;SYN,ACK&gt; segment and should be ignored if it is received in any other segment.
/// </para> /// </para>
/// </summary> /// </summary>
[OptionTypeRegistration(typeof(TcpOptionType), TcpOptionType.ConnectionCountEcho)] [TcpOptionTypeRegistration(TcpOptionType.ConnectionCountEcho)]
public class TcpOptionConnectionCountEcho : TcpOptionConnectionCountBase, IOptionComplexFactory public class TcpOptionConnectionCountEcho : TcpOptionConnectionCountBase, IOptionComplexFactory
{ {
/// <summary> /// <summary>
......
using PcapDotNet.Packets.Ip;
namespace PcapDotNet.Packets.Transport namespace PcapDotNet.Packets.Transport
{ {
/// <summary> /// <summary>
...@@ -16,7 +18,7 @@ namespace PcapDotNet.Packets.Transport ...@@ -16,7 +18,7 @@ namespace PcapDotNet.Packets.Transport
/// </para> /// </para>
/// </summary> /// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")]
[OptionTypeRegistration(typeof(TcpOptionType), TcpOptionType.ConnectionCountNew)] [TcpOptionTypeRegistration(TcpOptionType.ConnectionCountNew)]
public class TcpOptionConnectionCountNew : TcpOptionConnectionCountBase, IOptionComplexFactory public class TcpOptionConnectionCountNew : TcpOptionConnectionCountBase, IOptionComplexFactory
{ {
/// <summary> /// <summary>
......
using System; using System;
using PcapDotNet.Packets.Ip;
namespace PcapDotNet.Packets.Transport namespace PcapDotNet.Packets.Transport
{ {
...@@ -20,7 +21,7 @@ namespace PcapDotNet.Packets.Transport ...@@ -20,7 +21,7 @@ namespace PcapDotNet.Packets.Transport
/// and the four information bytes will define the time at which the data segment was transmitted in any format convenient to the sender. /// and the four information bytes will define the time at which the data segment was transmitted in any format convenient to the sender.
/// </para> /// </para>
/// </summary> /// </summary>
[OptionTypeRegistration(typeof(TcpOptionType), TcpOptionType.Echo)] [TcpOptionTypeRegistration(TcpOptionType.Echo)]
public sealed class TcpOptionEcho : TcpOptionComplex, IOptionComplexFactory, IEquatable<TcpOptionEcho> public sealed class TcpOptionEcho : TcpOptionComplex, IOptionComplexFactory, IEquatable<TcpOptionEcho>
{ {
/// <summary> /// <summary>
......
using System; using System;
using PcapDotNet.Packets.Ip;
namespace PcapDotNet.Packets.Transport namespace PcapDotNet.Packets.Transport
{ {
...@@ -27,7 +28,7 @@ namespace PcapDotNet.Packets.Transport ...@@ -27,7 +28,7 @@ namespace PcapDotNet.Packets.Transport
/// However, a TCP should not receive one of these options in a non-SYN segment unless it included a TCP Echo option in its own SYN segment. /// However, a TCP should not receive one of these options in a non-SYN segment unless it included a TCP Echo option in its own SYN segment.
/// </para> /// </para>
/// </summary> /// </summary>
[OptionTypeRegistration(typeof(TcpOptionType), TcpOptionType.EchoReply)] [TcpOptionTypeRegistration(TcpOptionType.EchoReply)]
public sealed class TcpOptionEchoReply : TcpOptionComplex, IOptionComplexFactory, IEquatable<TcpOptionEchoReply> public sealed class TcpOptionEchoReply : TcpOptionComplex, IOptionComplexFactory, IEquatable<TcpOptionEchoReply>
{ {
/// <summary> /// <summary>
......
using System; using System;
using PcapDotNet.Packets.Ip;
namespace PcapDotNet.Packets.Transport namespace PcapDotNet.Packets.Transport
{ {
...@@ -17,7 +18,7 @@ namespace PcapDotNet.Packets.Transport ...@@ -17,7 +18,7 @@ namespace PcapDotNet.Packets.Transport
/// If this option is not used, any segment size is allowed. /// If this option is not used, any segment size is allowed.
/// </para> /// </para>
/// </summary> /// </summary>
[OptionTypeRegistration(typeof(TcpOptionType), TcpOptionType.MaximumSegmentSize)] [TcpOptionTypeRegistration(TcpOptionType.MaximumSegmentSize)]
public sealed class TcpOptionMaximumSegmentSize : TcpOptionComplex, IOptionComplexFactory, IEquatable<TcpOptionMaximumSegmentSize> public sealed class TcpOptionMaximumSegmentSize : TcpOptionComplex, IOptionComplexFactory, IEquatable<TcpOptionMaximumSegmentSize>
{ {
/// <summary> /// <summary>
......
...@@ -3,6 +3,7 @@ using System.Collections.Generic; ...@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using PcapDotNet.Base; using PcapDotNet.Base;
using PcapDotNet.Packets.Ip;
namespace PcapDotNet.Packets.Transport namespace PcapDotNet.Packets.Transport
{ {
...@@ -25,7 +26,7 @@ namespace PcapDotNet.Packets.Transport ...@@ -25,7 +26,7 @@ namespace PcapDotNet.Packets.Transport
/// The MD5 digest is always 16 bytes in length, and the option would appear in every segment of a connection. /// The MD5 digest is always 16 bytes in length, and the option would appear in every segment of a connection.
/// </para> /// </para>
/// </summary> /// </summary>
[OptionTypeRegistration(typeof(TcpOptionType), TcpOptionType.Md5Signature)] [TcpOptionTypeRegistration(TcpOptionType.Md5Signature)]
public sealed class TcpOptionMd5Signature: TcpOptionComplex, IOptionComplexFactory, IEquatable<TcpOptionMd5Signature> public sealed class TcpOptionMd5Signature: TcpOptionComplex, IOptionComplexFactory, IEquatable<TcpOptionMd5Signature>
{ {
/// <summary> /// <summary>
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using PcapDotNet.Packets.Ip;
namespace PcapDotNet.Packets.Transport namespace PcapDotNet.Packets.Transport
{ {
...@@ -62,7 +63,7 @@ namespace PcapDotNet.Packets.Transport ...@@ -62,7 +63,7 @@ namespace PcapDotNet.Packets.Transport
/// </pre> /// </pre>
/// </para> /// </para>
/// </summary> /// </summary>
[OptionTypeRegistration(typeof(TcpOptionType), TcpOptionType.Mood)] [TcpOptionTypeRegistration(TcpOptionType.Mood)]
public sealed class TcpOptionMood : TcpOptionComplex, IOptionComplexFactory, IEquatable<TcpOptionMood> public sealed class TcpOptionMood : TcpOptionComplex, IOptionComplexFactory, IEquatable<TcpOptionMood>
{ {
/// <summary> /// <summary>
......
using System; using System;
using PcapDotNet.Packets.Ip;
namespace PcapDotNet.Packets.Transport namespace PcapDotNet.Packets.Transport
{ {
...@@ -10,7 +11,7 @@ namespace PcapDotNet.Packets.Transport ...@@ -10,7 +11,7 @@ namespace PcapDotNet.Packets.Transport
/// +-----------+-------------+ /// +-----------+-------------+
/// </pre> /// </pre>
/// </summary> /// </summary>
[OptionTypeRegistration(typeof(TcpOptionType), TcpOptionType.PartialOrderConnectionPermitted)] [TcpOptionTypeRegistration(TcpOptionType.PartialOrderConnectionPermitted)]
public sealed class TcpOptionPartialOrderConnectionPermitted : TcpOptionComplex, IOptionComplexFactory, IEquatable<TcpOptionPartialOrderConnectionPermitted> public sealed class TcpOptionPartialOrderConnectionPermitted : TcpOptionComplex, IOptionComplexFactory, IEquatable<TcpOptionPartialOrderConnectionPermitted>
{ {
/// <summary> /// <summary>
......
using System; using System;
using PcapDotNet.Base; using PcapDotNet.Base;
using PcapDotNet.Packets.Ip;
namespace PcapDotNet.Packets.Transport namespace PcapDotNet.Packets.Transport
{ {
...@@ -23,7 +24,7 @@ namespace PcapDotNet.Packets.Transport ...@@ -23,7 +24,7 @@ namespace PcapDotNet.Packets.Transport
/// The "Filler" field serves merely to complete the third byte of the option. /// The "Filler" field serves merely to complete the third byte of the option.
/// </para> /// </para>
/// </summary> /// </summary>
[OptionTypeRegistration(typeof(TcpOptionType), TcpOptionType.PartialOrderServiceProfile)] [TcpOptionTypeRegistration(TcpOptionType.PartialOrderServiceProfile)]
public sealed class TcpOptionPartialOrderServiceProfile : TcpOptionComplex, IOptionComplexFactory, IEquatable<TcpOptionPartialOrderServiceProfile> public sealed class TcpOptionPartialOrderServiceProfile : TcpOptionComplex, IOptionComplexFactory, IEquatable<TcpOptionPartialOrderServiceProfile>
{ {
private const byte NoFlags = 0x00; private const byte NoFlags = 0x00;
......
...@@ -3,6 +3,7 @@ using System.Collections.Generic; ...@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using PcapDotNet.Base; using PcapDotNet.Base;
using PcapDotNet.Packets.Ip;
namespace PcapDotNet.Packets.Transport namespace PcapDotNet.Packets.Transport
{ {
...@@ -53,7 +54,7 @@ namespace PcapDotNet.Packets.Transport ...@@ -53,7 +54,7 @@ namespace PcapDotNet.Packets.Transport
/// The SACK option is advisory, in that, while it notifies the data sender that the data receiver has received the indicated segments, /// The SACK option is advisory, in that, while it notifies the data sender that the data receiver has received the indicated segments,
/// the data receiver is permitted to later discard data which have been reported in a SACK option. /// the data receiver is permitted to later discard data which have been reported in a SACK option.
/// </summary> /// </summary>
[OptionTypeRegistration(typeof(TcpOptionType), TcpOptionType.SelectiveAcknowledgment)] [TcpOptionTypeRegistration(TcpOptionType.SelectiveAcknowledgment)]
public sealed class TcpOptionSelectiveAcknowledgment : TcpOptionComplex, IOptionComplexFactory, IEquatable<TcpOptionSelectiveAcknowledgment> public sealed class TcpOptionSelectiveAcknowledgment : TcpOptionComplex, IOptionComplexFactory, IEquatable<TcpOptionSelectiveAcknowledgment>
{ {
/// <summary> /// <summary>
......
using System; using System;
using PcapDotNet.Packets.Ip;
namespace PcapDotNet.Packets.Transport namespace PcapDotNet.Packets.Transport
{ {
...@@ -14,7 +15,7 @@ namespace PcapDotNet.Packets.Transport ...@@ -14,7 +15,7 @@ namespace PcapDotNet.Packets.Transport
/// +---------+---------+ /// +---------+---------+
/// </pre> /// </pre>
/// </summary> /// </summary>
[OptionTypeRegistration(typeof(TcpOptionType), TcpOptionType.SelectiveAcknowledgmentPermitted)] [TcpOptionTypeRegistration(TcpOptionType.SelectiveAcknowledgmentPermitted)]
public sealed class TcpOptionSelectiveAcknowledgmentPermitted : TcpOptionComplex, IOptionComplexFactory, IEquatable<TcpOptionSelectiveAcknowledgmentPermitted> public sealed class TcpOptionSelectiveAcknowledgmentPermitted : TcpOptionComplex, IOptionComplexFactory, IEquatable<TcpOptionSelectiveAcknowledgmentPermitted>
{ {
/// <summary> /// <summary>
......
using System; using System;
using PcapDotNet.Packets.Ip;
namespace PcapDotNet.Packets.Transport namespace PcapDotNet.Packets.Transport
{ {
...@@ -28,7 +29,7 @@ namespace PcapDotNet.Packets.Transport ...@@ -28,7 +29,7 @@ namespace PcapDotNet.Packets.Transport
/// and may send a TSopt in other segments only if it received a TSopt in the initial &lt;SYN&gt; segment for the connection. /// and may send a TSopt in other segments only if it received a TSopt in the initial &lt;SYN&gt; segment for the connection.
/// </para> /// </para>
/// </summary> /// </summary>
[OptionTypeRegistration(typeof(TcpOptionType), TcpOptionType.Timestamp)] [TcpOptionTypeRegistration(TcpOptionType.Timestamp)]
public sealed class TcpOptionTimestamp : TcpOptionComplex, IOptionComplexFactory, IEquatable<TcpOptionTimestamp> public sealed class TcpOptionTimestamp : TcpOptionComplex, IOptionComplexFactory, IEquatable<TcpOptionTimestamp>
{ {
/// <summary> /// <summary>
......
using System;
using PcapDotNet.Packets.Ip;
using PcapDotNet.Packets.Transport;
namespace PcapDotNet.Packets
{
internal sealed class TcpOptionTypeRegistrationAttribute : OptionTypeRegistrationAttribute
{
public TcpOptionTypeRegistrationAttribute(TcpOptionType optionType)
{
TcpOptionType = optionType;
}
public TcpOptionType TcpOptionType { get; private set; }
public override object OptionType
{
get { return TcpOptionType; }
}
public override Type OptionTypeType
{
get { return typeof(TcpOptionType); }
}
}
}
\ No newline at end of file
...@@ -3,6 +3,7 @@ using System.Collections.Generic; ...@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using PcapDotNet.Base; using PcapDotNet.Base;
using PcapDotNet.Packets.Ip;
namespace PcapDotNet.Packets.Transport namespace PcapDotNet.Packets.Transport
{ {
......
using System; using System;
using PcapDotNet.Packets.Ip;
namespace PcapDotNet.Packets.Transport namespace PcapDotNet.Packets.Transport
{ {
...@@ -33,7 +34,7 @@ namespace PcapDotNet.Packets.Transport ...@@ -33,7 +34,7 @@ namespace PcapDotNet.Packets.Transport
/// The Window field in a SYN (i.e., a SYN or SYN,ACK) segment itself is never scaled. /// The Window field in a SYN (i.e., a SYN or SYN,ACK) segment itself is never scaled.
/// </para> /// </para>
/// </summary> /// </summary>
[OptionTypeRegistration(typeof(TcpOptionType), TcpOptionType.WindowScale)] [TcpOptionTypeRegistration(TcpOptionType.WindowScale)]
public sealed class TcpOptionWindowScale: TcpOptionComplex, IOptionComplexFactory, IEquatable<TcpOptionWindowScale> public sealed class TcpOptionWindowScale: TcpOptionComplex, IOptionComplexFactory, IEquatable<TcpOptionWindowScale>
{ {
/// <summary> /// <summary>
......
using System.Collections.Generic; using System.Collections.Generic;
using PcapDotNet.Packets.Ip;
namespace PcapDotNet.Packets.Transport namespace PcapDotNet.Packets.Transport
{ {
/// <summary> /// <summary>
/// A collection of TCP options. /// A collection of TCP options.
/// </summary> /// </summary>
public class TcpOptions : Options<TcpOption> public class TcpOptions : V4Options<TcpOption>
{ {
/// <summary> /// <summary>
/// The maximum number of bytes the options can take. /// The maximum number of bytes the options can take.
......
...@@ -4,9 +4,9 @@ Microsoft Visual Studio Solution File, Format Version 11.00 ...@@ -4,9 +4,9 @@ Microsoft Visual Studio Solution File, Format Version 11.00
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0D5DCCC5-A509-4B4E-90B0-92390C6EA06F}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0D5DCCC5-A509-4B4E-90B0-92390C6EA06F}"
ProjectSection(SolutionItems) = preProject ProjectSection(SolutionItems) = preProject
LocalTestRun.testrunconfig = LocalTestRun.testrunconfig LocalTestRun.testrunconfig = LocalTestRun.testrunconfig
PcapDotNet.5.0.ReSharper = PcapDotNet.5.0.ReSharper
PcapDotNet.CodeAnalysisDictionary.xml = PcapDotNet.CodeAnalysisDictionary.xml PcapDotNet.CodeAnalysisDictionary.xml = PcapDotNet.CodeAnalysisDictionary.xml
PcapDotNet.ruleset = PcapDotNet.ruleset PcapDotNet.ruleset = PcapDotNet.ruleset
PcapDotNet.sln.DotSettings = PcapDotNet.sln.DotSettings
PcapDotNet.vsmdi = PcapDotNet.vsmdi PcapDotNet.vsmdi = PcapDotNet.vsmdi
EndProjectSection EndProjectSection
EndProject EndProject
......
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_ARRAY_AND_OBJECT_INITIALIZER/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_ANONYMOUS_METHOD_BLOCK/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_EMBRACED_INITIALIZER_BLOCK/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_AFTER_TYPECAST_PARENTHESES/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_BEFORE_SIZEOF_PARENTHESES/@EntryValue">False</s:Boolean>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_LIMIT/@EntryValue">160</s:Int64>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/EventHandlerPatternLong/@EntryValue">$object$_On$event$</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/VBNaming/EventHandlerPatternLong/@EntryValue">$object$_On$event$</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/JavaScriptCodeFormatting/JavaScriptFormatOther/ALIGN_MULTIPLE_DECLARATION/@EntryValue">True</s:Boolean></wpf:ResourceDictionary>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment