Commit 4ee12458 authored by Brickner_cp's avatar Brickner_cp

IpV4

parent c04ed979
......@@ -33,7 +33,6 @@
<Naming2>
<ExceptionName IsNull="False">
</ExceptionName>
<OverrideDefaultSettings>True</OverrideDefaultSettings>
<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" />
......@@ -61,9 +60,11 @@
</VB>
<GenerateMemberBody />
<Naming2>
<ExceptionName IsNull="False">
</ExceptionName>
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="aaBb" ElementKind="Locals" />
<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="PrivateInstanceFields" />
<PredefinedRule Inspect="True" Prefix="_" Suffix="" Style="aaBb" ElementKind="PrivateStaticFields" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="aaBb" ElementKind="Parameters" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="MethodPropertyEvent" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="TypesAndNamespaces" />
......@@ -74,7 +75,7 @@
<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="PrivateStaticReadonly" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="EnumMember" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="Other" />
</Naming2>
......
using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Text;
namespace PcapDotNet.Base
{
public static class MoreIEnumerable
{
public static IEnumerable<T> Concat<T>(this IEnumerable<T> sequence, T value)
{
return sequence.Concat(new[] {value});
}
public static string SequenceToString<T>(this IEnumerable<T> sequence, string separator, string prefix, string suffix)
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append(prefix);
bool isFirst = true;
foreach (T value in sequence)
{
if (isFirst)
isFirst = false;
else
stringBuilder.Append(separator);
stringBuilder.Append(value);
}
stringBuilder.Append(suffix);
return stringBuilder.ToString();
}
public static string SequenceToString<T>(this IEnumerable<T> sequence, string separator, string prefix)
{
return sequence.SequenceToString(separator, prefix, string.Empty);
}
public static string SequenceToString<T>(this IEnumerable<T> sequence, string separator)
{
return sequence.SequenceToString(separator, string.Empty);
}
public static string SequenceToString<T>(this IEnumerable<T> sequence)
{
return sequence.SequenceToString(string.Empty);
}
}
}
\ No newline at end of file
......@@ -55,6 +55,8 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="MoreIEnumerable.cs" />
<Compile Include="Tuple.cs" />
<Compile Include="UInt24.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
......
namespace PcapDotNet.Base
{
public class Tuple<T1, T2>
{
public Tuple(T1 value1, T2 value2)
{
_value1 = value1;
_value2 = value2;
}
public T1 Value1
{
get { return _value1; }
}
public T2 Value2
{
get { return _value2; }
}
private readonly T1 _value1;
private readonly T2 _value2;
}
}
\ No newline at end of file
......@@ -11,8 +11,8 @@ namespace PcapDotNet.Base
private UInt24(int value)
{
_mostSignificant = (byte)((value >> 16) & 0x00FF);
_leastSignificant = (ushort)(value & 0x0000FFFF);
_mostSignificant = (ushort)(value >> 8);
_leastSignificant = (byte)value;
}
public static explicit operator UInt24(int value)
......@@ -25,15 +25,10 @@ namespace PcapDotNet.Base
return value.ToInt();
}
private int ToInt()
{
return _mostSignificant << 16 + _leastSignificant;
}
public bool Equals(UInt24 other)
{
return other._mostSignificant == _mostSignificant && other._leastSignificant == _leastSignificant;
return _mostSignificant == other._mostSignificant &&
_leastSignificant == other._leastSignificant;
}
public override bool Equals(object obj)
......@@ -57,7 +52,17 @@ namespace PcapDotNet.Base
return this;
}
private readonly byte _mostSignificant;
private readonly ushort _leastSignificant;
public override string ToString()
{
return ((int)this).ToString();
}
private int ToInt()
{
return (_mostSignificant << 8) + _leastSignificant;
}
private readonly ushort _mostSignificant;
private readonly byte _leastSignificant;
}
}
using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using PcapDotNet.Base;
using PcapDotNet.Packets.TestUtils;
using PcapDotNet.TestUtils;
......@@ -113,16 +114,17 @@ namespace PcapDotNet.Packets.Test
IpV4Address ipV4Source = new IpV4Address(random.NextUInt());
IpV4Address ipV4Destination = new IpV4Address(random.NextUInt());
IpV4Options ipV4Options = random.NextIpV4Options();
// IpV4Options ipV4Options = new IpV4Options(new IpV4OptionSecurity(IpV4OptionSecurityLevel.Unclassified, 1, 2, (UInt24)123456));
byte[] ipV4PayloadBuffer = new byte[random.Next(0, 50 * 1024)];
random.NextBytes(ipV4PayloadBuffer);
Datagram ipV4Payload = new Datagram(ipV4PayloadBuffer);
Packet packet = PacketBuilder.EthernetIpV4(DateTime.Now,
ethernetSource, ethernetDestination, ethernetType,
ipV4TypeOfService, ipV4Identification, ipV4Fragmentation, ipV4Ttl, ipV4Protocol,
ipV4Source, ipV4Destination, ipV4Options,
ipV4Payload);
ethernetSource, ethernetDestination, ethernetType,
ipV4TypeOfService, ipV4Identification, ipV4Fragmentation, ipV4Ttl, ipV4Protocol,
ipV4Source, ipV4Destination, ipV4Options,
ipV4Payload);
Assert.IsTrue(packet.IsValid);
......@@ -134,7 +136,7 @@ namespace PcapDotNet.Packets.Test
Assert.AreEqual(ethernetType, packet.Ethernet.EtherType, "Ethernet Type");
// IpV4
Assert.AreEqual(IpV4Datagram.HeaderMinimumLength + ipV4Options.Length, packet.Ethernet.IpV4.HeaderLength, "IP HeaderLength");
Assert.AreEqual(IpV4Datagram.HeaderMinimumLength + ipV4Options.BytesLength, packet.Ethernet.IpV4.HeaderLength, "IP HeaderLength");
Assert.AreEqual(ipV4TypeOfService, packet.Ethernet.IpV4.TypeOfService, "IP TypeOfService");
Assert.AreEqual(packet.Length - EthernetDatagram.HeaderLength, packet.Ethernet.IpV4.TotalLength, "IP TotalLength");
Assert.AreEqual(ipV4Identification, packet.Ethernet.IpV4.Identification, "IP Identification");
......
......@@ -48,6 +48,10 @@
<Compile Include="IpV4AddressTests.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PcapDotNet.Base\PcapDotNet.Base.csproj">
<Project>{83E805C9-4D29-4E34-A27E-5A78690FBD2B}</Project>
<Name>PcapDotNet.Base</Name>
</ProjectReference>
<ProjectReference Include="..\PcapDotNet.Packets\PcapDotNet.Packets.csproj">
<Project>{8A184AF5-E46C-482C-81A3-76D8CE290104}</Project>
<Name>PcapDotNet.Packets</Name>
......
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
......@@ -25,11 +25,8 @@ namespace PcapDotNet.Packets.TestUtils
switch (optionType)
{
case IpV4OptionType.EndOfOptionList:
option = new IpV4OptionEndOfOptionsList();
break;
case IpV4OptionType.NoOperation:
option = new IpV4OptionNoOperation();
option = new IpV4OptionSimple(optionType);
break;
case IpV4OptionType.Security:
......@@ -125,7 +122,7 @@ namespace PcapDotNet.Packets.TestUtils
options.Add(option);
optionsLength -= option.Length;
if (option is IpV4OptionEndOfOptionsList)
if (option.OptionType == IpV4OptionType.EndOfOptionList)
break;
}
return new IpV4Options(options);
......
......@@ -136,7 +136,7 @@ namespace PcapDotNet.Packets
IpV4Address source, IpV4Address destination,
IpV4Options options, int payloadLength)
{
int headerLength = HeaderMinimumLength + options.Length;
int headerLength = HeaderMinimumLength + options.BytesLength;
buffer[offset + Offset.VersionAndHeaderLength] = (byte)((Version << 4) + headerLength / 4);
buffer[offset + Offset.TypeOfService] = typeOfService;
buffer.Write(offset + Offset.TotalLength, (ushort)(headerLength + payloadLength), Endianity.Big);
......
......@@ -4,6 +4,16 @@ namespace PcapDotNet.Packets
{
public abstract class IpV4Option : IEquatable<IpV4Option>
{
public static IpV4OptionSimple End
{
get { return _end; }
}
public static IpV4OptionSimple Nop
{
get { return _nop; }
}
public IpV4OptionType OptionType
{
get { return _type; }
......@@ -41,6 +51,11 @@ namespace PcapDotNet.Packets
return (byte)OptionType;
}
public override string ToString()
{
return OptionType.ToString();
}
protected IpV4Option(IpV4OptionType type)
{
_type = type;
......@@ -56,28 +71,17 @@ namespace PcapDotNet.Packets
switch (optionType)
{
case IpV4OptionType.EndOfOptionList:
return new IpV4OptionEndOfOptionsList();
return End;
case IpV4OptionType.NoOperation:
return new IpV4OptionNoOperation();
return Nop;
case IpV4OptionType.Security:
return IpV4OptionSecurity.ReadOptionSecurity(buffer, ref offset, offsetEnd - offset);
case IpV4OptionType.LooseSourceRouting:
return IpV4OptionLooseSourceRouting.ReadOptionLooseSourceRouting(buffer, ref offset, offsetEnd - offset);
case IpV4OptionType.StrictSourceRouting:
return IpV4OptionStrictSourceRouting.ReadOptionStrictSourceRouting(buffer, ref offset, offsetEnd - offset);
case IpV4OptionType.RecordRoute:
return IpV4OptionRecordRoute.ReadOptionRecordRoute(buffer, ref offset, offsetEnd - offset);
case IpV4OptionType.StreamIdentifier:
return IpV4OptionStreamIdentifier.ReadOptionStreamIdentifier(buffer, ref offset, offsetEnd - offset);
case IpV4OptionType.InternetTimestamp:
return IpV4OptionTimestamp.ReadOptionTimestamp(buffer, ref offset, offsetEnd - offset);
return IpV4OptionComplex.ReadOptionComplex(optionType, buffer, ref offset, offsetEnd - offset);
default:
return null;
......@@ -89,6 +93,9 @@ namespace PcapDotNet.Packets
buffer[offset++] = (byte)OptionType;
}
private static readonly IpV4OptionSimple _end = new IpV4OptionSimple(IpV4OptionType.EndOfOptionList);
private static readonly IpV4OptionSimple _nop = new IpV4OptionSimple(IpV4OptionType.NoOperation);
private readonly IpV4OptionType _type;
}
}
\ No newline at end of file
namespace PcapDotNet.Packets
{
public abstract class IpV4OptionComplex : IpV4Option
{
public const int OptionHeaderLength = 2;
internal static IpV4OptionComplex ReadOptionComplex(IpV4OptionType optionType, byte[] buffer, ref int offset, int length)
{
if (length < 1)
return null;
byte optionLength = buffer[offset++];
if (length + 1 < optionLength)
return null;
byte optionValueLength = (byte)(optionLength - 2);
switch (optionType)
{
case IpV4OptionType.Security:
return IpV4OptionSecurity.ReadOptionSecurity(buffer, ref offset, optionValueLength);
case IpV4OptionType.LooseSourceRouting:
return IpV4OptionLooseSourceRouting.ReadOptionLooseSourceRouting(buffer, ref offset, optionValueLength);
case IpV4OptionType.StrictSourceRouting:
return IpV4OptionStrictSourceRouting.ReadOptionStrictSourceRouting(buffer, ref offset, optionValueLength);
case IpV4OptionType.RecordRoute:
return IpV4OptionRecordRoute.ReadOptionRecordRoute(buffer, ref offset, optionValueLength);
case IpV4OptionType.StreamIdentifier:
return IpV4OptionStreamIdentifier.ReadOptionStreamIdentifier(buffer, ref offset, optionValueLength);
case IpV4OptionType.InternetTimestamp:
return IpV4OptionTimestamp.ReadOptionTimestamp(buffer, ref offset, optionValueLength);
default:
return null;
}
}
protected IpV4OptionComplex(IpV4OptionType type)
: base(type)
{
}
}
}
\ No newline at end of file
......@@ -7,11 +7,11 @@ namespace PcapDotNet.Packets
{
}
internal static IpV4OptionLooseSourceRouting ReadOptionLooseSourceRouting(byte[] buffer, ref int offset, int length)
internal static IpV4OptionLooseSourceRouting ReadOptionLooseSourceRouting(byte[] buffer, ref int offset, byte valueLength)
{
IpV4Address[] addresses;
byte pointedAddressIndex;
if (!TryRead(out addresses, out pointedAddressIndex, buffer, ref offset, length))
if (!TryRead(out addresses, out pointedAddressIndex, buffer, ref offset, valueLength))
return null;
return new IpV4OptionLooseSourceRouting(addresses, pointedAddressIndex);
}
......
namespace PcapDotNet.Packets
{
public class IpV4OptionNoOperation : IpV4Option
{
public const int OptionLength = 1;
public IpV4OptionNoOperation()
: base(IpV4OptionType.NoOperation)
{
}
public override int Length
{
get { return OptionLength; }
}
public override bool IsAppearsAtMostOnce
{
get { return false; }
}
}
}
\ No newline at end of file
......@@ -7,11 +7,11 @@ namespace PcapDotNet.Packets
{
}
internal static IpV4OptionRecordRoute ReadOptionRecordRoute(byte[] buffer, ref int offset, int length)
internal static IpV4OptionRecordRoute ReadOptionRecordRoute(byte[] buffer, ref int offset, byte valueLength)
{
IpV4Address[] addresses;
byte pointedAddressIndex;
if (!TryRead(out addresses, out pointedAddressIndex, buffer, ref offset, length))
if (!TryRead(out addresses, out pointedAddressIndex, buffer, ref offset, valueLength))
return null;
return new IpV4OptionRecordRoute(addresses, pointedAddressIndex);
}
......
......@@ -3,9 +3,10 @@ using System.Linq;
namespace PcapDotNet.Packets
{
public abstract class IpV4OptionRoute : IpV4Option, IEquatable<IpV4OptionRoute>
public abstract class IpV4OptionRoute : IpV4OptionComplex, IEquatable<IpV4OptionRoute>
{
public const int OptionMinimumLength = 3;
public const int OptionValueMinimumLength = OptionMinimumLength - OptionHeaderLength;
public const byte PointedAddressIndexMaxValue = byte.MaxValue / 4 - 1;
public byte PointedAddressIndex
......@@ -55,16 +56,15 @@ namespace PcapDotNet.Packets
}
protected static bool TryRead(out IpV4Address[] addresses, out byte pointedAddressIndex,
byte[] buffer, ref int offset, int length)
byte[] buffer, ref int offset, byte valueLength)
{
addresses = null;
pointedAddressIndex = 0;
if (length < OptionMinimumLength - 1)
if (valueLength < OptionValueMinimumLength)
return false;
byte optionLength = buffer[offset++];
if (optionLength < OptionMinimumLength || optionLength > length + 1 || optionLength % 4 != 3)
if (valueLength % 4 != 1)
return false;
byte pointer = buffer[offset++];
......@@ -73,10 +73,10 @@ namespace PcapDotNet.Packets
pointedAddressIndex = (byte)(pointer / 4 - 1);
int numAddresses = (optionLength - 3) / 4;
int numAddresses = valueLength / 4;
addresses = new IpV4Address[numAddresses];
for (int i = 0; i != numAddresses; ++i)
addresses[i] = new IpV4Address(buffer.ReadUInt(ref offset, Endianity.Big));
addresses[i] = buffer.ReadIpV4Address(ref offset, Endianity.Big);
return true;
}
......
......@@ -3,9 +3,10 @@ using PcapDotNet.Base;
namespace PcapDotNet.Packets
{
public class IpV4OptionSecurity : IpV4Option, IEquatable<IpV4OptionSecurity>
public class IpV4OptionSecurity : IpV4OptionComplex, IEquatable<IpV4OptionSecurity>
{
public const int OptionLength = 11;
public const int OptionValueLength = OptionLength - OptionHeaderLength;
public IpV4OptionSecurity(IpV4OptionSecurityLevel level, ushort compartments,
ushort handlingRestrictions, UInt24 transmissionControlCode)
......@@ -71,12 +72,9 @@ namespace PcapDotNet.Packets
TransmissionControlCode.GetHashCode();
}
internal static IpV4OptionSecurity ReadOptionSecurity(byte[] buffer, ref int offset, int length)
internal static IpV4OptionSecurity ReadOptionSecurity(byte[] buffer, ref int offset, byte valueLength)
{
if (length < OptionLength - 1)
return null;
byte optionLength = buffer[offset++];
if (optionLength != OptionLength)
if (valueLength != OptionValueLength)
return null;
IpV4OptionSecurityLevel level = (IpV4OptionSecurityLevel)buffer.ReadUShort(ref offset, Endianity.Big);
......
using System;
namespace PcapDotNet.Packets
{
public class IpV4OptionEndOfOptionsList : IpV4Option
public class IpV4OptionSimple : IpV4Option
{
public const int OptionLength = 1;
public IpV4OptionEndOfOptionsList()
: base(IpV4OptionType.EndOfOptionList)
public IpV4OptionSimple(IpV4OptionType optionType)
: base(optionType)
{
if (optionType != IpV4OptionType.EndOfOptionList &&
optionType != IpV4OptionType.NoOperation)
{
throw new ArgumentException("OptionType " + optionType + " Can't be a simple option", "optionType");
}
}
public override int Length
......
......@@ -2,9 +2,10 @@ using System;
namespace PcapDotNet.Packets
{
public class IpV4OptionStreamIdentifier : IpV4Option, IEquatable<IpV4OptionStreamIdentifier>
public class IpV4OptionStreamIdentifier : IpV4OptionComplex, IEquatable<IpV4OptionStreamIdentifier>
{
public const int OptionLength = 4;
public const int OptionvalueLength = OptionLength - OptionHeaderLength;
public IpV4OptionStreamIdentifier(ushort identifier)
: base(IpV4OptionType.StreamIdentifier)
......@@ -45,13 +46,9 @@ namespace PcapDotNet.Packets
Identifier.GetHashCode();
}
internal static IpV4OptionStreamIdentifier ReadOptionStreamIdentifier(byte[] buffer, ref int offset, int length)
internal static IpV4OptionStreamIdentifier ReadOptionStreamIdentifier(byte[] buffer, ref int offset, byte valueLength)
{
if (length < OptionLength - 1)
return null;
byte optionLength = buffer[offset++];
if (optionLength != OptionLength)
if (valueLength != OptionHeaderLength)
return null;
ushort identifier = buffer.ReadUShort(ref offset, Endianity.Big);
......
......@@ -7,11 +7,11 @@ namespace PcapDotNet.Packets
{
}
internal static IpV4OptionStrictSourceRouting ReadOptionStrictSourceRouting(byte[] buffer, ref int offset, int length)
internal static IpV4OptionStrictSourceRouting ReadOptionStrictSourceRouting(byte[] buffer, ref int offset, byte valueLength)
{
IpV4Address[] addresses;
byte pointedAddressIndex;
if (!TryRead(out addresses, out pointedAddressIndex, buffer, ref offset, length))
if (!TryRead(out addresses, out pointedAddressIndex, buffer, ref offset, valueLength))
return null;
return new IpV4OptionStrictSourceRouting(addresses, pointedAddressIndex);
}
......
......@@ -2,9 +2,10 @@ using System;
namespace PcapDotNet.Packets
{
public abstract class IpV4OptionTimestamp : IpV4Option, IEquatable<IpV4OptionTimestamp>
public abstract class IpV4OptionTimestamp : IpV4OptionComplex, IEquatable<IpV4OptionTimestamp>
{
public const int OptionMinimumLength = 4;
public const int OptionValueMinimumLength = OptionMinimumLength - OptionHeaderLength;
public const int PointedIndexMaxValue = byte.MaxValue / 4 - 1;
public IpV4OptionTimestampType TimestampType
......@@ -61,13 +62,9 @@ namespace PcapDotNet.Packets
PointedIndex;
}
internal static IpV4OptionTimestamp ReadOptionTimestamp(byte[] buffer, ref int offset, int length)
internal static IpV4OptionTimestamp ReadOptionTimestamp(byte[] buffer, ref int offset, int valueLength)
{
if (length < OptionMinimumLength - 1)
return null;
byte optionLength = buffer[offset++];
if (optionLength < OptionMinimumLength || optionLength > length + 1 || optionLength % 4 != 0)
if (valueLength < OptionValueMinimumLength || valueLength % 4 != 2)
return null;
byte pointer = buffer[offset++];
......@@ -80,7 +77,7 @@ namespace PcapDotNet.Packets
IpV4OptionTimestampType timestampType = (IpV4OptionTimestampType)(overflow & 0x0F);
overflow >>= 4;
int numValues = optionLength / 4 - 1;
int numValues = valueLength / 4;
switch (timestampType)
{
......
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using PcapDotNet.Base;
namespace PcapDotNet.Packets
{
public class IpV4Options : IEquatable<IpV4Options>
public class IpV4Options : ReadOnlyCollection<IpV4Option>, IEquatable<IpV4Options>
{
public const int MaximumLength = IpV4Datagram.HeaderMaximumLength - IpV4Datagram.HeaderMinimumLength;
......@@ -13,50 +15,24 @@ namespace PcapDotNet.Packets
get { return _none; }
}
public IpV4Options(IEnumerable<IpV4Option> options)
public IpV4Options(IList<IpV4Option> options)
: this(EndOptions(options), true)
{
_options.AddRange(options);
foreach (IpV4Option option in _options)
_length += option.Length;
if (_length % 4 != 0)
_length = (_length / 4 + 1) * 4;
}
public IpV4Options(params IpV4Option[] options)
: this((IEnumerable<IpV4Option>)options)
: this((IList<IpV4Option>)options)
{
}
internal IpV4Options()
public int BytesLength
{
get { return _bytesLength; }
}
internal IpV4Options(byte[] buffer, int offset, int length)
{
_length = length;
int offsetEnd = offset + length;
while (offset != offsetEnd)
{
IpV4Option option = IpV4Option.Read(buffer, ref offset, offsetEnd - offset);
if (option == null)
return; // Invalid
if (option.IsAppearsAtMostOnce && _options.FindIndex(option.Equivalent) != -1)
{
return; // Invalid
}
_options.Add(option);
if (option is IpV4OptionEndOfOptionsList)
break; // Valid?
}
}
public int Length
public bool IsValid
{
get { return _length; }
get { return _isValid; }
}
public bool Equals(IpV4Options other)
......@@ -64,10 +40,10 @@ namespace PcapDotNet.Packets
if (other == null)
return false;
if (Length != other.Length)
if (BytesLength != other.BytesLength)
return false;
return _options.SequenceEqual(other._options);
return this.SequenceEqual(other);
}
public override bool Equals(object obj)
......@@ -77,14 +53,77 @@ namespace PcapDotNet.Packets
public override int GetHashCode()
{
return Length.GetHashCode() ^
_options.Aggregate(0, (value, option) => value ^ option.GetHashCode());
return BytesLength.GetHashCode() ^
this.Aggregate(0, (value, option) => value ^ option.GetHashCode());
}
public override string ToString()
{
return this.SequenceToString(", ", typeof(IpV4Options).Name + " {", "}");
}
internal IpV4Options(byte[] buffer, int offset, int length)
: this(Read(buffer, offset, length))
{
_bytesLength = length;
}
private IpV4Options(IList<IpV4Option> options, bool isValid)
: base(options)
{
_isValid = isValid;
_bytesLength = SumBytesLength(this);
if (_bytesLength % 4 != 0)
_bytesLength = (_bytesLength / 4 + 1) * 4;
}
private static IList<IpV4Option> EndOptions(IList<IpV4Option> options)
{
if (options.Count == 0 || options.Last().Equals(IpV4Option.End) || SumBytesLength(options) % 4 == 0)
return options;
return new List<IpV4Option>(options.Concat(IpV4Option.End));
}
private static int SumBytesLength(IEnumerable<IpV4Option> options)
{
return options.Sum(option => option.Length);
}
private IpV4Options(Tuple<IList<IpV4Option>, bool> optionsAndIsValid)
: this(optionsAndIsValid.Value1, optionsAndIsValid.Value2)
{
}
private static Tuple<IList<IpV4Option>, bool> Read(byte[] buffer, int offset, int length)
{
int offsetEnd = offset + length;
List<IpV4Option> options = new List<IpV4Option>();
while (offset != offsetEnd)
{
IpV4Option option = IpV4Option.Read(buffer, ref offset, offsetEnd - offset);
if (option == null ||
option.IsAppearsAtMostOnce && options.Any(option.Equivalent))
{
// Invalid
return new Tuple<IList<IpV4Option>, bool>(options, false);
}
options.Add(option);
if (option.OptionType == IpV4OptionType.EndOfOptionList)
break; // Valid?
}
return new Tuple<IList<IpV4Option>, bool>(options, true);
}
internal void Write(byte[] buffer, int offset)
{
int offsetEnd = offset + Length;
foreach (IpV4Option option in _options)
int offsetEnd = offset + BytesLength;
foreach (IpV4Option option in this)
option.Write(buffer, ref offset);
// Padding
......@@ -92,8 +131,8 @@ namespace PcapDotNet.Packets
buffer[offset++] = 0;
}
private readonly List<IpV4Option> _options = new List<IpV4Option>();
private readonly int _length;
private readonly int _bytesLength;
private readonly bool _isValid;
private static readonly IpV4Options _none = new IpV4Options();
}
}
\ No newline at end of file
......@@ -73,6 +73,17 @@ namespace PcapDotNet.Packets
return value;
}
public static IpV4Address ReadIpV4Address(this byte[] buffer, int offset, Endianity endianity)
{
return new IpV4Address(buffer.ReadUInt(offset, endianity));
}
public static IpV4Address ReadIpV4Address(this byte[] buffer, ref int offset, Endianity endianity)
{
return new IpV4Address(buffer.ReadUInt(ref offset, endianity));
}
public static void Write(this byte[] buffer, int offset, short value, Endianity endianity)
{
if (IsWrongEndianity(endianity))
......@@ -129,14 +140,18 @@ namespace PcapDotNet.Packets
private static UInt24 HostToNetworkOrder(UInt24 value)
{
UInt24 result = value;
UInt24 result;
unsafe
{
UInt24* ptr = &result;
byte* bytePtr = (byte*)ptr;
byte tmp = bytePtr[0];
bytePtr[0] = bytePtr[2];
bytePtr[2] = tmp;
UInt24* resultPtr = &result;
byte* resultBytePtr = (byte*)resultPtr;
UInt24* valuePtr = &value;
byte* valueBytePtr = (byte*)valuePtr;
resultBytePtr[0] = valueBytePtr[2];
resultBytePtr[1] = valueBytePtr[1];
resultBytePtr[2] = valueBytePtr[0];
}
return result;
......
......@@ -22,7 +22,7 @@ namespace PcapDotNet.Packets
IpV4Options ipV4Options,
Datagram ipV4Payload)
{
int ipHeaderLength = IpV4Datagram.HeaderMinimumLength + ipV4Options.Length;
int ipHeaderLength = IpV4Datagram.HeaderMinimumLength + ipV4Options.BytesLength;
byte[] buffer = new byte[EthernetDatagram.HeaderLength + ipHeaderLength + ipV4Payload.Length];
EthernetDatagram.WriteHeader(buffer, 0, ethernetSource, ethernetDestination, ethernetType);
IpV4Datagram.WriteHeader(buffer, EthernetDatagram.HeaderLength,
......
......@@ -72,9 +72,9 @@
<Compile Include="IpV4\IpV4Fragmentation.cs" />
<Compile Include="IpV4\IpV4FragmentationOptions.cs" />
<Compile Include="IpV4\IpV4Option.cs" />
<Compile Include="IpV4\IpV4OptionEndOfOptionsList.cs" />
<Compile Include="IpV4\IpV4OptionComplex.cs" />
<Compile Include="IpV4\IpV4OptionLooseSourceRouting.cs" />
<Compile Include="IpV4\IpV4OptionNoOperation.cs" />
<Compile Include="IpV4\IpV4OptionSimple.cs" />
<Compile Include="IpV4\IpV4OptionRecordRoute.cs" />
<Compile Include="IpV4\IpV4OptionRoute.cs" />
<Compile Include="IpV4\IpV4Options.cs" />
......
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