Commit 13e7b291 authored by Brickner_cp's avatar Brickner_cp

IpV4

parent 990042d6
...@@ -4,72 +4,12 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; ...@@ -4,72 +4,12 @@ using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Packets.Test namespace Packets.Test
{ {
/// <summary> /// <summary>
/// Summary description for IpV4DatagramTests /// Summary description for IpV4Tests
/// </summary> /// </summary>
[TestClass] [TestClass]
public class IpV4DatagramTests public class IpV4Tests
{ {
public IpV4DatagramTests() public IpV4Tests()
{
//
// TODO: Add constructor logic here
//
}
private TestContext testContextInstance;
/// <summary>
///Gets or sets the test context which provides
///information about and functionality for the current test run.
///</summary>
public TestContext TestContext
{
get
{
return testContextInstance;
}
set
{
testContextInstance = value;
}
}
#region Additional test attributes
//
// You can use the following additional attributes as you write your tests:
//
// Use ClassInitialize to run code before running the first test in the class
// [ClassInitialize()]
// public static void MyClassInitialize(TestContext testContext) { }
//
// Use ClassCleanup to run code after all tests in a class have run
// [ClassCleanup()]
// public static void MyClassCleanup() { }
//
// Use TestInitialize to run code before running each test
// [TestInitialize()]
// public void MyTestInitialize() { }
//
// Use TestCleanup to run code after each test has run
// [TestCleanup()]
// public void MyTestCleanup() { }
//
#endregion
[TestMethod]
public void IpV4DatagramTest()
{
// PacketBuilder.IpV4(DateT)
}
}
/// <summary>
/// Summary description for PacketsTests
/// </summary>
[TestClass]
public class PacketsTests
{
public PacketsTests()
{ {
// //
// TODO: Add constructor logic here // TODO: Add constructor logic here
...@@ -128,35 +68,6 @@ namespace Packets.Test ...@@ -128,35 +68,6 @@ namespace Packets.Test
"41d0e4df" + // IPv4 Destination Address "41d0e4df" + // IPv4 Destination Address
"0d2c005038affe14114c618c501825bca9580000474554202f646f776e6c6f61642e68746d6c20485454502f312e310d0a486f73743a207777772e657468657265616c2e636f6d0d0a557365722d4167656e743a204d6f7a696c6c612f352e30202857696e646f77733b20553b2057696e646f7773204e5420352e313b20656e2d55533b2072763a312e3629204765636b6f2f32303034303131330d0a4163636570743a20746578742f786d6c2c6170706c69636174696f6e2f786d6c2c6170706c69636174696f6e2f7868746d6c2b786d6c2c746578742f68746d6c3b713d302e392c746578742f706c61696e3b713d302e382c696d6167652f706e672c696d6167652f6a7065672c696d6167652f6769663b713d302e322c2a2f2a3b713d302e310d0a4163636570742d4c616e67756167653a20656e2d75732c656e3b713d302e350d0a4163636570742d456e636f64696e673a20677a69702c6465666c6174650d0a4163636570742d436861727365743a2049534f2d383835392d312c7574662d383b713d302e372c2a3b713d302e370d0a4b6565702d416c6976653a203330300d0a436f6e6e656374696f6e3a206b6565702d616c6976650d0a526566657265723a20687474703a2f2f7777772e657468657265616c2e636f6d2f646576656c6f706d656e742e68746d6c0d0a0d0a", "0d2c005038affe14114c618c501825bca9580000474554202f646f776e6c6f61642e68746d6c20485454502f312e310d0a486f73743a207777772e657468657265616c2e636f6d0d0a557365722d4167656e743a204d6f7a696c6c612f352e30202857696e646f77733b20553b2057696e646f7773204e5420352e313b20656e2d55533b2072763a312e3629204765636b6f2f32303034303131330d0a4163636570743a20746578742f786d6c2c6170706c69636174696f6e2f786d6c2c6170706c69636174696f6e2f7868746d6c2b786d6c2c746578742f68746d6c3b713d302e392c746578742f706c61696e3b713d302e382c696d6167652f706e672c696d6167652f6a7065672c696d6167652f6769663b713d302e322c2a2f2a3b713d302e310d0a4163636570742d4c616e67756167653a20656e2d75732c656e3b713d302e350d0a4163636570742d456e636f64696e673a20677a69702c6465666c6174650d0a4163636570742d436861727365743a2049534f2d383835392d312c7574662d383b713d302e372c2a3b713d302e370d0a4b6565702d416c6976653a203330300d0a436f6e6e656374696f6e3a206b6565702d616c6976650d0a526566657265723a20687474703a2f2f7777772e657468657265616c2e636f6d2f646576656c6f706d656e742e68746d6c0d0a0d0a",
DataLinkKind.Ethernet); DataLinkKind.Ethernet);
// Packet packet = HexToPacket(
//
// "0123456789abba98765432100800" + // Ethernet
// "4500042f" + // IPv4 Version, IHL, Type of Service, Total Length
// "787a4000" + // IPv4 Identification, Flags, Fragment Offset
// "80061234" + // IPv4 Time to Live, Protocol, Header Checksum
// "c0a80160" + // IPv4 Source Address
// "12345678" + // IPv4 Destination Address
// "06d900504a5d60e5f48579935018440c70c70000474554202f20485454502f312e310d0a" +
// "486f73743a2070636170646f746e65742e636f6465706c65782e636f6d0d0a" +
// "557365722d4167656e743a204d6f7a696c6c612f352e30202857696e646f77733b20553b2057696e646f7773204e5420352e313b20656e2d55533b2072763a312e392e302e313229204765636b6f2f323030393037303631312046697265666f782f332e302e313220282e4e455420434c5220332e352e3330373239290d0a" +
// "4163636570743a20746578742f68746d6c2c6170706c69636174696f6e2f7868746d6c2b786d6c2c6170706c69636174696f6e2f786d6c3b713d302e392c2a2f2a3b713d302e380d0a" +
// "4163636570742d4c616e67756167653a20656e2d75732c656e3b713d302e350d0a" +
// "4163636570742d456e636f64696e673a20677a69702c6465666c6174650d0a" +
// "4163636570742d436861727365743a2049534f2d383835392d312c7574662d383b713d302e372c2a3b713d302e370d0a" +
// "4b6565702d416c6976653a203330300d0a" +
// "436f6e6e656374696f6e3a206b6565702d616c6976650d0a" +
// "526566657265723a20687474703a2f2f70636170646f746e65742e636f6465706c65782e636f6d2f77696b692f636f6d6d656e74732f766965773f7469746c653d486f6d650d0a" +
// "526566657265723a20687474703a2f2f70636170646f746e65742e636f6465706c65782e636f6d2f77696b692f636f6d6d656e74732f766965773f7469746c653d486f6d65" +
// "526566657265723a20687474703a2f2f70636170646f746e65742e636f6465706c65782e636f6d2f77696b692f636f6d6d656e74732f766965773f7469746c653d486f6d65" +
// "526566657265723a20687474703a2f2f70636170646f746e65742e636f6465706c65782e636f6d2f77696b692f636f6d6d656e74732f766965773f7469746c653d486f6d65" +
// "526566657265723a20687474703a2f2f70636170646f746e65742e636f6465706c65782e636f6d2f77696b692f636f6d6d656e74732f766965773f7469746c653d486f6d65" +
// "526566657265723a20687474703a2f2f70636170646f746e65742e636f6465706c65782e636f6d2f77696b692f636f6d6d656e74732f766965773f7469746c653d486f6d65" +
// "526566657265723a20687474703a2f2f70636170646f746e65742e636f6465706c65782e636f6d2f77696b692f636f6d6d656e74732f766965773f7469746c653d486f6d65" +
// "526566657265723a20687474703a2f2f70636170646f746e65742e636f6465706c65782e636f6d2f77696b692f636f6d6d656e74732f766965773f7469746c653d486f6d65" +
// "526566657265723a20687474703a2f2f70636170646f746e65742e636f6465706c65782e636f6d2f77696b692f636f6d6d656e74732f766965773f7469746c653d486f6d65" +
// "123456780d0a" +
// "0d0a",
// DataLinkKind.Ethernet);
Assert.IsTrue(packet.IsValid); Assert.IsTrue(packet.IsValid);
...@@ -178,6 +89,66 @@ namespace Packets.Test ...@@ -178,6 +89,66 @@ namespace Packets.Test
Assert.AreEqual(IpV4Options.None, packet.Ethernet.IpV4.Options, "IP Options"); Assert.AreEqual(IpV4Options.None, packet.Ethernet.IpV4.Options, "IP Options");
} }
[TestMethod]
public void SimplePacketTest()
{
MacAddress ethernetSource = new MacAddress("00:01:02:03:04:05");
MacAddress ethernetDestination = new MacAddress("A0:A1:A2:A3:A4:A5");
const EthernetType ethernetType = EthernetType.IpV4;
Random random = new Random();
for (int i = 0; i != 100; ++i)
{
byte ipV4TypeOfService = (byte)random.Next(256);
ushort ipV4Identification = (ushort)random.Next(65536);
byte ipV4Ttl = (byte)random.Next(256);
IpV4FragmentationFlags ipV4FragmentationFlags = (IpV4FragmentationFlags)(random.Next(4) << 13);
ushort ipV4FragmentationOffset = (ushort)random.Next(65536);
IpV4Fragmentation ipV4Fragmentation = new IpV4Fragmentation(ipV4FragmentationFlags, ipV4FragmentationOffset);
const IpV4Protocol ipV4Protocol = IpV4Protocol.Tcp;
IpV4Address ipV4Source = new IpV4Address((uint)random.Next());
IpV4Address ipV4Destination = new IpV4Address((uint)random.Next());
IpV4Options ipV4Options = IpV4Options.None;
byte[] ipV4PayloadBuffer = new byte[random.Next(0, 50 * 1024)];
random.NextBytes(ipV4PayloadBuffer);
Datagram ipV4Payload = new Datagram(ipV4PayloadBuffer);
Packet packet = PacketBuilder.IpV4(DateTime.Now,
ethernetSource, ethernetDestination, ethernetType,
ipV4TypeOfService, ipV4Identification, ipV4Fragmentation, ipV4Ttl, ipV4Protocol,
ipV4Source, ipV4Destination, ipV4Options,
ipV4Payload);
Assert.IsTrue(packet.IsValid);
// Ethernet
Assert.AreEqual(packet.Length - EthernetDatagram.HeaderLength, packet.Ethernet.PayloadLength, "PayloadLength");
Assert.AreEqual(ethernetSource, packet.Ethernet.Source, "Ethernet Source");
Assert.AreEqual(ethernetDestination, packet.Ethernet.Destination, "Ethernet Destination");
Assert.AreEqual(ethernetType, packet.Ethernet.EtherType, "Ethernet Type");
// IpV4
Assert.AreEqual(IpV4Datagram.HeaderMinimumLength + ipV4Options.Length, 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(ipV4Fragmentation, packet.Ethernet.IpV4.Fragmentation, "IP Fragmentation");
Assert.AreEqual(ipV4Fragmentation.Flags, packet.Ethernet.IpV4.Fragmentation.Flags, "IP Fragmentation");
Assert.AreEqual(ipV4Fragmentation.Offset, packet.Ethernet.IpV4.Fragmentation.Offset, "IP Fragmentation");
Assert.AreEqual(ipV4Ttl, packet.Ethernet.IpV4.Ttl, "IP Ttl");
Assert.AreEqual(ipV4Protocol, packet.Ethernet.IpV4.Protocol, "IP Protocol");
// Assert.AreEqual(0x9010, packet.Ethernet.IpV4.HeaderChecksum, "IP HeaderChecksum");
Assert.AreEqual(true, packet.Ethernet.IpV4.IsHeaderChecksumCorrect, "IP HeaderChecksumCorrect");
Assert.AreEqual(ipV4Source, packet.Ethernet.IpV4.Source, "IP Source");
Assert.AreEqual(ipV4Destination, packet.Ethernet.IpV4.Destination, "IP Destination");
Assert.AreEqual(ipV4Options, packet.Ethernet.IpV4.Options, "IP Options");
Assert.AreEqual(ipV4Payload, packet.Ethernet.IpV4.Payload, "IP Payload");
}
}
private static Packet HexToPacket(string hexString, DataLinkKind dataLinkKind) private static Packet HexToPacket(string hexString, DataLinkKind dataLinkKind)
{ {
return HexToPacket(hexString, DateTime.MinValue, dataLinkKind); return HexToPacket(hexString, DateTime.MinValue, dataLinkKind);
......
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="EthernetDatagramTests.cs" /> <Compile Include="EthernetDatagramTests.cs" />
<Compile Include="IpV4DatagramTests.cs" /> <Compile Include="IpV4Tests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="IpV4AddressTests.cs" /> <Compile Include="IpV4AddressTests.cs" />
</ItemGroup> </ItemGroup>
......
...@@ -81,6 +81,7 @@ namespace Packets ...@@ -81,6 +81,7 @@ namespace Packets
} }
} }
internal EthernetDatagram(byte[] buffer, int offset, int length) internal EthernetDatagram(byte[] buffer, int offset, int length)
: base(buffer, offset, length) : base(buffer, offset, length)
{ {
......
...@@ -18,6 +18,11 @@ namespace Packets ...@@ -18,6 +18,11 @@ namespace Packets
(byte.Parse(values[3]))); (byte.Parse(values[3])));
} }
public static IpV4Address Zero
{
get { return _zero; }
}
public uint ToValue() public uint ToValue()
{ {
return _value; return _value;
...@@ -74,5 +79,6 @@ namespace Packets ...@@ -74,5 +79,6 @@ namespace Packets
} }
private readonly uint _value; private readonly uint _value;
private static readonly IpV4Address _zero = new IpV4Address(0);
} }
} }
\ No newline at end of file
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
...@@ -108,6 +109,22 @@ namespace Packets ...@@ -108,6 +109,22 @@ namespace Packets
get { return new IpV4Options(Buffer, StartOffset + Offset.Options, HeaderLength - HeaderMinimumLength); } get { return new IpV4Options(Buffer, StartOffset + Offset.Options, HeaderLength - HeaderMinimumLength); }
} }
public Datagram Payload
{
get { return Tcp; }
}
public Datagram Tcp
{
get
{
if (_tcp == null && Length >= HeaderLength)
_tcp = new Datagram(Buffer, StartOffset + HeaderLength, Length - HeaderLength);
return _tcp;
}
}
internal IpV4Datagram(byte[] buffer, int offset, int length) internal IpV4Datagram(byte[] buffer, int offset, int length)
: base(buffer, offset, length) : base(buffer, offset, length)
{ {
...@@ -121,28 +138,31 @@ namespace Packets ...@@ -121,28 +138,31 @@ namespace Packets
IpV4Options options, int payloadLength) IpV4Options options, int payloadLength)
{ {
int headerLength = HeaderMinimumLength + options.Length; int headerLength = HeaderMinimumLength + options.Length;
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);
buffer.Write(offset + Offset.Identification, identification, Endianity.Big); buffer.Write(offset + Offset.Identification, identification, Endianity.Big);
fragmentation.Write(buffer, offset + Offset.Fragmentation); fragmentation.Write(buffer, offset + Offset.Fragmentation);
buffer[offset + Offset.Ttl] = ttl; buffer[offset + Offset.Ttl] = ttl;
buffer[offset + Offset.Protocol] = (byte)protocol; buffer[offset + Offset.Protocol] = (byte)protocol;
// Todo Checksum
// buffer.Write(offset + Offset.Source, source, Endianity.Big); buffer.Write(offset + Offset.Source, source.ToValue(), Endianity.Big);
// buffer.Write(offset + Offset.Destination, destination, Endianity.Big); buffer.Write(offset + Offset.Destination, destination.ToValue(), Endianity.Big);
// options.Write(offset + Offset.Options); // options.Write(offset + Offset.Options);
buffer.Write(offset + Offset.HeaderChecksum, Sum16BitsToChecksum(Sum16Bits(buffer, offset, headerLength)), Endianity.Big);
} }
private ushort CalculateHeaderChecksum() private ushort CalculateHeaderChecksum()
{ {
// and 16 bits uint sum = Sum16Bits(Buffer, StartOffset, Offset.HeaderChecksum) +
uint sum = 0; Sum16Bits(Buffer, StartOffset + Offset.HeaderChecksum + 2, HeaderLength - Offset.HeaderChecksum - 2);
for (int offset = 0; offset < Offset.HeaderChecksum; offset += 2)
sum += ReadUShort(offset, Endianity.Big); return Sum16BitsToChecksum(sum);
for (int offset = Offset.HeaderChecksum + 2; offset < HeaderLength; offset += 2) }
sum += ReadUShort(offset, Endianity.Big);
private static ushort Sum16BitsToChecksum(uint sum)
{
// take only 16 bits out of the 32 bit sum and add up the carrier // take only 16 bits out of the 32 bit sum and add up the carrier
sum = (sum & 0x0000FFFF) + (sum >> 16); sum = (sum & 0x0000FFFF) + (sum >> 16);
...@@ -151,54 +171,20 @@ namespace Packets ...@@ -151,54 +171,20 @@ namespace Packets
return (ushort)sum; return (ushort)sum;
} }
private bool? _isHeaderChecksumCorrect; private static uint Sum16Bits(byte[] buffer, int offset, int length)
}
[Flags]
public enum IpV4FragmentationFlags : byte
{
Reserved = 0x1,
DontFragment = 0x2,
MoreFragments = 0x4
}
public struct IpV4Fragmentation : IEquatable<IpV4Fragmentation>
{
public IpV4Fragmentation(IpV4FragmentationFlags flags, ushort offset)
: this((ushort)((byte)flags << 13 | offset))
{
}
public bool Equals(IpV4Fragmentation other)
{
return _value == other._value;
}
public override bool Equals(object obj)
{
return (obj is IpV4Fragmentation &&
Equals((IpV4Fragmentation)obj));
}
internal IpV4Fragmentation(ushort value)
{ {
_value = value; int endOffset = offset + length;
} uint sum = 0;
while (offset < endOffset - 1)
internal void Write(byte[] buffer, int offset) sum += buffer.ReadUShort(ref offset, Endianity.Big);
{ return sum;
buffer.Write(offset, _value, Endianity.Big);
} }
private ushort _value; private bool? _isHeaderChecksumCorrect;
} private Datagram _tcp;
public enum IpV4Protocol : byte
{
Tcp = 0x06
} }
public class IpV4Options public class IpV4Options : IEquatable<IpV4Options>
{ {
public static IpV4Options None public static IpV4Options None
{ {
...@@ -211,28 +197,78 @@ namespace Packets ...@@ -211,28 +197,78 @@ namespace Packets
internal IpV4Options(byte[] buffer, int offset, int length) internal IpV4Options(byte[] buffer, int offset, int length)
{ {
_length = length;
int offsetEnd = offset + length; int offsetEnd = offset + length;
while (offset != offsetEnd) while (offset != offsetEnd)
{ {
IpV4Option option = IpV4Option.Read(buffer, ref offset, offsetEnd - offset); IpV4Option option = IpV4Option.Read(buffer, ref offset, offsetEnd - offset);
if (option == null) if (option == null)
break; return; // Invalid
if (option.IsAppearsAtMostOnce)
{
foreach (IpV4Option previousOption in _options)
{
if (option.GetType() == previousOption.GetType())
return; // Invalid
}
}
_options.Add(option); _options.Add(option);
if (option is IpV4OptionEndOfOptionsList) if (option is IpV4OptionEndOfOptionsList)
break; break; // Valid?
} }
} }
public int Length public int Length
{ {
get { throw new NotImplementedException(); } get { return _length; }
}
public bool Equals(IpV4Options other)
{
if (other == null)
return false;
if (Length != other.Length)
return false;
return _options.EqualCollection(other._options);
}
public override bool Equals(object obj)
{
return Equals(obj as IpV4Options);
} }
private List<IpV4Option> _options = new List<IpV4Option>(); private List<IpV4Option> _options = new List<IpV4Option>();
private int _length;
private static IpV4Options _none = new IpV4Options(); private static IpV4Options _none = new IpV4Options();
} }
public static class MoreIEnumerable
{
public static bool EqualCollection<T>(this IEnumerable<T> collection1, IEnumerable<T> collection2)
{
IEnumerator<T> enumerator1 = collection1.GetEnumerator();
IEnumerator<T> enumerator2 = collection1.GetEnumerator();
while (enumerator1.MoveNext())
{
if (!enumerator2.MoveNext())
return false;
if (!enumerator1.Current.Equals(enumerator2.Current))
return false;
}
if (enumerator2.MoveNext())
return false;
return true;
}
}
public enum IpV4OptionType : byte public enum IpV4OptionType : byte
{ {
EndOfOptionList = 0, EndOfOptionList = 0,
...@@ -247,6 +283,11 @@ namespace Packets ...@@ -247,6 +283,11 @@ namespace Packets
public abstract class IpV4Option public abstract class IpV4Option
{ {
public abstract bool IsAppearsAtMostOnce
{
get;
}
protected IpV4Option(IpV4OptionType type) protected IpV4Option(IpV4OptionType type)
{ {
_type = type; _type = type;
...@@ -268,17 +309,16 @@ namespace Packets ...@@ -268,17 +309,16 @@ namespace Packets
case IpV4OptionType.Security: case IpV4OptionType.Security:
return IpV4OptionSecurity.Read(optionType, buffer, ref offset, offsetEnd - offset); return IpV4OptionSecurity.Read(optionType, buffer, ref offset, offsetEnd - offset);
// Todo support more option types case IpV4OptionType.LooseSourceRouting:
// case IpV4OptionType.LooseSourceRouting: return IpV4OptionLooseSourceRouting.Read(optionType, buffer, ref offset, offsetEnd - offset);
// return IpV4OptionLooseSourceRouting.Read(optionType, buffer, ref offset, offsetEnd - offset); case IpV4OptionType.StrictSourceRouting:
// case IpV4OptionType.StrictSourceRouting: return IpV4OptionStrictSourceRouting.Read(optionType, buffer, ref offset, offsetEnd - offset);
// return IpV4OptionStrictSourceRouting.Read(optionType, buffer, ref offset, offsetEnd - offset); case IpV4OptionType.RecordRoute:
// case IpV4OptionType.RecordRoute: return IpV4OptionRecordRoute.Read(optionType, buffer, ref offset, offsetEnd - offset);
// return IpV4OptionRecordRoute.Read(optionType, buffer, ref offset, offsetEnd - offset); case IpV4OptionType.StreamIdentifier:
// case IpV4OptionType.StreamIdentifier: return IpV4OptionStreamIdentifier.Read(optionType, buffer, ref offset, offsetEnd - offset);
// return IpV4OptionStreamIdentifier.Read(optionType, buffer, ref offset, offsetEnd - offset); case IpV4OptionType.InternetTimestamp:
// case IpV4OptionType.InternetTimestamp: return IpV4OptionInternetTimestamp.Read(optionType, buffer, ref offset, offsetEnd - offset);
// return IpV4OptionInternetTimestamp.Read(optionType, buffer, ref offset, offsetEnd - offset);
default: default:
return null; return null;
} }
...@@ -287,40 +327,212 @@ namespace Packets ...@@ -287,40 +327,212 @@ namespace Packets
private IpV4OptionType _type; private IpV4OptionType _type;
} }
// public class IpV4OptionInternetTimestamp : IpV4Option [Flags]
// { public enum IpV4OptionInternetTimestampType : byte
// internal static IpV4OptionInternetTimestamp Read(IpV4OptionType optionType, byte[] buffer, ref int offset, int length) {
// { TimestampOnly = 0,
// } AddressAndTimestamp = 1,
// } AddressPrespecified = 3
// }
// public class IpV4OptionStreamIdentifier : IpV4Option
// { public class IpV4OptionInternetTimestamp : IpV4Option
// internal static IpV4OptionStreamIdentifier Read(IpV4OptionType optionType, byte[] buffer, ref int offset, int length) {
// { private IpV4OptionInternetTimestamp(IpV4OptionType optionType, IpV4OptionInternetTimestampType timestampType, byte overflow, KeyValuePair<IpV4Address, DateTime>[] values, int pointedIndex)
// } : base(optionType)
// } {
// _timestampType = timestampType;
// public class IpV4OptionRecordRoute : IpV4Option _overflow = overflow;
// { _values = values;
// internal static IpV4OptionRecordRoute Read(IpV4OptionType optionType, byte[] buffer, ref int offset, int length) _pointedIndex = pointedIndex;
// { }
// }
// } public override bool IsAppearsAtMostOnce
// {
// public class IpV4OptionStrictSourceRouting : IpV4Option get { return true; }
// { }
// internal static IpV4OptionStrictSourceRouting Read(IpV4OptionType optionType, byte[] buffer, ref int offset, int length)
// { internal static IpV4OptionInternetTimestamp Read(IpV4OptionType optionType, byte[] buffer, ref int offset, int length)
// } {
// } if (length < 3)
// return null;
// public class IpV4OptionLooseSourceRouting : IpV4Option
// { byte optionLength = buffer[offset++];
// internal static IpV4OptionLooseSourceRouting Read(IpV4OptionType optionType, byte[] buffer, ref int offset, int length) if (optionLength > length + 1 || optionLength % 4 != 0)
// { return null;
// }
// } byte pointer = buffer[offset++];
if (pointer % 4 != 1)
return null;
int pointedIndex = pointer / 4 - 1;
if (pointedIndex < 0)
return null;
byte overflow = buffer[offset++];
IpV4OptionInternetTimestampType type = (IpV4OptionInternetTimestampType)(overflow & 0x0F);
overflow >>= 4;
int numValues = optionLength / 4 - 1;
if (type != IpV4OptionInternetTimestampType.TimestampOnly)
numValues = numValues / 2 - numValues % 2;
KeyValuePair<IpV4Address, DateTime>[] values = new KeyValuePair<IpV4Address, DateTime>[numValues];
for (int i = 0; i < numValues; ++i)
{
switch (type)
{
case IpV4OptionInternetTimestampType.TimestampOnly:
values[i] = new KeyValuePair<IpV4Address, DateTime>(IpV4Address.Zero, ReadTimeOfDay(buffer, ref offset));
break;
case IpV4OptionInternetTimestampType.AddressAndTimestamp:
case IpV4OptionInternetTimestampType.AddressPrespecified:
IpV4Address address = new IpV4Address(buffer.ReadUInt(ref offset, Endianity.Big));
values[i] = new KeyValuePair<IpV4Address, DateTime>(address, ReadTimeOfDay(buffer, ref offset));
break;
}
}
return new IpV4OptionInternetTimestamp(optionType, type, overflow, values, pointedIndex);
}
private static DateTime ReadTimeOfDay(byte[] buffer, ref int offset)
{
return DateTime.MinValue.Date.AddMilliseconds(buffer.ReadUInt(ref offset, Endianity.Big));
}
private IpV4OptionInternetTimestampType _timestampType;
private byte _overflow;
private KeyValuePair<IpV4Address, DateTime>[] _values;
private int _pointedIndex;
}
public class IpV4OptionStreamIdentifier : IpV4Option
{
public override bool IsAppearsAtMostOnce
{
get { return true; }
}
internal static IpV4OptionStreamIdentifier Read(IpV4OptionType optionType, byte[] buffer, ref int offset, int length)
{
if (length < 3)
return null;
byte optionLength = buffer[offset++];
if (optionLength != 4)
return null;
ushort identifier = buffer.ReadUShort(ref offset, Endianity.Big);
return new IpV4OptionStreamIdentifier(optionType, identifier);
}
private IpV4OptionStreamIdentifier(IpV4OptionType optionType, ushort identifier)
: base(optionType)
{
_identifier = identifier;
}
private ushort _identifier;
}
public class IpV4OptionRecordRoute : IpV4OptionRoute
{
internal static IpV4OptionRecordRoute Read(IpV4OptionType optionType, byte[] buffer, ref int offset, int length)
{
IpV4Address[] addresses;
int pointedAddressIndex;
if (!TryRead(out addresses, out pointedAddressIndex, buffer, ref offset, length, true))
return null;
return new IpV4OptionRecordRoute(optionType, addresses, pointedAddressIndex);
}
private IpV4OptionRecordRoute(IpV4OptionType optionType, IpV4Address[] addresses, int pointedAddressIndex)
: base(optionType, addresses, pointedAddressIndex)
{
}
}
public abstract class IpV4OptionRoute : IpV4Option
{
public override bool IsAppearsAtMostOnce
{
get { return true; }
}
protected static bool TryRead(out IpV4Address[] addresses, out int pointedAddressIndex,
byte[] buffer, ref int offset, int length, bool readUpToPointer)
{
addresses = null;
pointedAddressIndex = 0;
if (length < 2)
return false;
byte optionLength = buffer[offset++];
if (optionLength > length + 1 || optionLength % 4 != 3)
return false;
byte pointer = buffer[offset++];
if (pointer % 4 != 0)
return false;
pointedAddressIndex = pointer / 4 - 1;
if (pointedAddressIndex < 0)
return false;
int numAddresses = readUpToPointer ? pointedAddressIndex : (optionLength - 3) / 4;
addresses = new IpV4Address[numAddresses];
for (int i = 0; i != numAddresses; ++i)
addresses[i] = new IpV4Address(buffer.ReadUInt(ref offset, Endianity.Big));
return true;
}
protected IpV4OptionRoute(IpV4OptionType optionType, IpV4Address[] addresses, int pointedAddressIndex)
: base(optionType)
{
_addresses = addresses;
_pointedAddressIndex = pointedAddressIndex;
}
private IpV4Address[] _addresses;
private int _pointedAddressIndex;
}
public class IpV4OptionStrictSourceRouting : IpV4OptionRoute
{
internal static IpV4OptionStrictSourceRouting Read(IpV4OptionType optionType, byte[] buffer, ref int offset, int length)
{
IpV4Address[] addresses;
int pointedAddressIndex;
if (!TryRead(out addresses, out pointedAddressIndex, buffer, ref offset, length, false))
return null;
return new IpV4OptionStrictSourceRouting(optionType, addresses, pointedAddressIndex);
}
private IpV4OptionStrictSourceRouting(IpV4OptionType optionType, IpV4Address[] addresses, int pointedAddressIndex)
: base(optionType, addresses, pointedAddressIndex)
{
}
}
public class IpV4OptionLooseSourceRouting : IpV4OptionRoute
{
internal static IpV4OptionLooseSourceRouting Read(IpV4OptionType optionType, byte[] buffer, ref int offset, int length)
{
IpV4Address[] addresses;
int pointedAddressIndex;
if (!TryRead(out addresses, out pointedAddressIndex, buffer, ref offset, length, false))
return null;
return new IpV4OptionLooseSourceRouting(optionType, addresses, pointedAddressIndex);
}
private IpV4OptionLooseSourceRouting(IpV4OptionType optionType, IpV4Address[] addresses, int pointedAddressIndex)
: base(optionType, addresses, pointedAddressIndex)
{
}
}
public enum IpV4OptionSecurityLevel : ushort public enum IpV4OptionSecurityLevel : ushort
{ {
...@@ -336,9 +548,14 @@ namespace Packets ...@@ -336,9 +548,14 @@ namespace Packets
public class IpV4OptionSecurity : IpV4Option public class IpV4OptionSecurity : IpV4Option
{ {
public override bool IsAppearsAtMostOnce
{
get { return true; }
}
internal static IpV4OptionSecurity Read(IpV4OptionType optionType, byte[] buffer, ref int offset, int length) internal static IpV4OptionSecurity Read(IpV4OptionType optionType, byte[] buffer, ref int offset, int length)
{ {
if (length < 12) if (length < 10)
return null; return null;
byte optionLength = buffer[offset++]; byte optionLength = buffer[offset++];
if (optionLength != 11) if (optionLength != 11)
...@@ -372,7 +589,12 @@ namespace Packets ...@@ -372,7 +589,12 @@ namespace Packets
public class IpV4OptionNoOperation : IpV4Option public class IpV4OptionNoOperation : IpV4Option
{ {
public IpV4OptionNoOperation(IpV4OptionType type) public override bool IsAppearsAtMostOnce
{
get { return false; }
}
internal IpV4OptionNoOperation(IpV4OptionType type)
: base(type) : base(type)
{ {
} }
...@@ -380,7 +602,12 @@ namespace Packets ...@@ -380,7 +602,12 @@ namespace Packets
public class IpV4OptionEndOfOptionsList : IpV4Option public class IpV4OptionEndOfOptionsList : IpV4Option
{ {
public IpV4OptionEndOfOptionsList(IpV4OptionType type) public override bool IsAppearsAtMostOnce
{
get { return false; }
}
internal IpV4OptionEndOfOptionsList(IpV4OptionType type)
: base(type) : base(type)
{ {
} }
......
using System;
namespace Packets
{
public struct IpV4Fragmentation : IEquatable<IpV4Fragmentation>
{
public static IpV4Fragmentation None
{
get { return _none; }
}
public IpV4Fragmentation(IpV4FragmentationFlags flags, ushort offset)
: this((ushort)((ushort)flags | (offset / 8)))
{
}
public IpV4FragmentationFlags Flags
{
get { return (IpV4FragmentationFlags)(_value & 0xE000); }
}
public ushort Offset
{
get { return (ushort)((_value & 0x1FFF) * 8); }
}
public bool Equals(IpV4Fragmentation other)
{
return _value == other._value;
}
public override bool Equals(object obj)
{
return (obj is IpV4Fragmentation &&
Equals((IpV4Fragmentation)obj));
}
internal IpV4Fragmentation(ushort value)
{
_value = value;
}
internal void Write(byte[] buffer, int offset)
{
buffer.Write(offset, _value, Endianity.Big);
}
private static readonly IpV4Fragmentation _none = new IpV4Fragmentation(IpV4FragmentationFlags.None, 0);
private readonly ushort _value;
}
}
\ No newline at end of file
using System;
namespace Packets
{
[Flags]
public enum IpV4FragmentationFlags : ushort
{
None = 0x0 << 13,
Reserved = 0x4 << 13,
DontFragment = 0x2 << 13,
MoreFragments = 0x1 << 13
}
}
\ No newline at end of file
namespace Packets
{
public enum IpV4Protocol : byte
{
Tcp = 0x06
}
}
\ No newline at end of file
...@@ -39,6 +39,13 @@ namespace Packets ...@@ -39,6 +39,13 @@ namespace Packets
return (uint)ReadInt(buffer, offset, endianity); return (uint)ReadInt(buffer, offset, endianity);
} }
public static uint ReadUInt(this byte[] buffer, ref int offset, Endianity endianity)
{
uint result = ReadUInt(buffer, offset, endianity);
offset += 4;
return result;
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "int")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "int")]
public static int ReadInt(this byte[] buffer, int offset, Endianity endianity) public static int ReadInt(this byte[] buffer, int offset, Endianity endianity)
{ {
...@@ -60,6 +67,18 @@ namespace Packets ...@@ -60,6 +67,18 @@ namespace Packets
Write(buffer, offset, (short)value, endianity); Write(buffer, offset, (short)value, endianity);
} }
public static void Write(this byte[] buffer, int offset, int value, Endianity endianity)
{
if (IsWrongEndianity(endianity))
value = IPAddress.HostToNetworkOrder(value);
Write(buffer, offset, value);
}
public static void Write(this byte[] buffer, int offset, uint value, Endianity endianity)
{
Write(buffer, offset, (int)value, endianity);
}
private static bool IsWrongEndianity(Endianity endianity) private static bool IsWrongEndianity(Endianity endianity)
{ {
return (BitConverter.IsLittleEndian == (endianity == Endianity.Big)); return (BitConverter.IsLittleEndian == (endianity == Endianity.Big));
...@@ -97,5 +116,16 @@ namespace Packets ...@@ -97,5 +116,16 @@ namespace Packets
} }
} }
} }
private static void Write(byte[] buffer, int offset, int value)
{
unsafe
{
fixed (byte* ptr = &buffer[offset])
{
*((int*)ptr) = value;
}
}
}
} }
} }
\ No newline at end of file
...@@ -67,6 +67,9 @@ ...@@ -67,6 +67,9 @@
<Compile Include="IDataLink.cs" /> <Compile Include="IDataLink.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\IpV4FragmentationFlags.cs" />
<Compile Include="IpV4\IpV4Protocol.cs" />
<Compile Include="MoreByteArray.cs" /> <Compile Include="MoreByteArray.cs" />
<Compile Include="Packet.cs" /> <Compile Include="Packet.cs" />
<Compile Include="PacketBuilder.cs" /> <Compile Include="PacketBuilder.cs" />
......
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Packets;
namespace PcapDotNet.Core.Test
{
/// <summary>
/// Summary description for DumpPacketsTests
/// </summary>
[TestClass]
public class DumpPacketsTests
{
public DumpPacketsTests()
{
//
// TODO: Add constructor logic here
//
}
private TestContext testContextInstance;
/// <summary>
///Gets or sets the test context which provides
///information about and functionality for the current test run.
///</summary>
public TestContext TestContext
{
get
{
return testContextInstance;
}
set
{
testContextInstance = value;
}
}
#region Additional test attributes
//
// You can use the following additional attributes as you write your tests:
//
// Use ClassInitialize to run code before running the first test in the class
// [ClassInitialize()]
// public static void MyClassInitialize(TestContext testContext) { }
//
// Use ClassCleanup to run code after all tests in a class have run
// [ClassCleanup()]
// public static void MyClassCleanup() { }
//
// Use TestInitialize to run code before running each test
// [TestInitialize()]
// public void MyTestInitialize() { }
//
// Use TestCleanup to run code after each test has run
// [TestCleanup()]
// public void MyTestCleanup() { }
//
#endregion
[TestMethod]
public void DumpIpV4PacketTest()
{
MacAddress ethernetSource = new MacAddress("00:01:02:03:04:05");
MacAddress ethernetDestination = new MacAddress("A0:A1:A2:A3:A4:A5");
const EthernetType ethernetType = EthernetType.IpV4;
Random random = new Random();
byte ipV4TypeOfService = (byte)random.Next(256);
ushort ipV4Identification = (ushort)random.Next(65536);
byte ipV4Ttl = (byte)random.Next(256);
IpV4FragmentationFlags ipV4FragmentationFlags = (IpV4FragmentationFlags)(random.Next(4) << 13);
ushort ipV4FragmentationOffset = (ushort)random.Next(65536);
IpV4Fragmentation ipV4Fragmentation = new IpV4Fragmentation(ipV4FragmentationFlags, ipV4FragmentationOffset);
const IpV4Protocol ipV4Protocol = IpV4Protocol.Tcp;
IpV4Address ipV4Source = new IpV4Address((uint)random.Next());
IpV4Address ipV4Destination = new IpV4Address((uint)random.Next());
IpV4Options ipV4Options = IpV4Options.None;
byte[] ipV4PayloadBuffer = new byte[random.Next(0, 50 * 1024)];
random.NextBytes(ipV4PayloadBuffer);
Datagram ipV4Payload = new Datagram(ipV4PayloadBuffer);
Packet packet = PacketBuilder.IpV4(DateTime.Now,
ethernetSource, ethernetDestination, ethernetType,
ipV4TypeOfService, ipV4Identification, ipV4Fragmentation, ipV4Ttl, ipV4Protocol,
ipV4Source, ipV4Destination, ipV4Options,
ipV4Payload);
using (PacketCommunicator communicator = LivePacketDeviceTests.OpenLiveDevice())
{
// using (PacketDumpFile dumpFile = communicator.OpenDump(@"c:\wow.pcap"))
// {
// dumpFile.Dump(packet);
// }
}
}
}
}
\ No newline at end of file
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="BerkeleyPacketFilterTests.cs" /> <Compile Include="BerkeleyPacketFilterTests.cs" />
<Compile Include="DumpPacketsTests.cs" />
<Compile Include="MoreAssert.cs" /> <Compile Include="MoreAssert.cs" />
<Compile Include="LivePacketDeviceTests.cs" /> <Compile Include="LivePacketDeviceTests.cs" />
<Compile Include="MoreRandom.cs" /> <Compile Include="MoreRandom.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