Commit 4ee12458 authored by Brickner_cp's avatar Brickner_cp

IpV4

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