Commit ff28a0d2 authored by Brickner_cp's avatar Brickner_cp

IpV4

parent c35ed863
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Packets.Test namespace Packets.Test
...@@ -61,4 +62,127 @@ namespace Packets.Test ...@@ -61,4 +62,127 @@ namespace Packets.Test
// PacketBuilder.IpV4(DateT) // PacketBuilder.IpV4(DateT)
} }
} }
/// <summary>
/// Summary description for PacketsTests
/// </summary>
[TestClass]
public class PacketsTests
{
public PacketsTests()
{
//
// 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 HttpTest()
{
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.AreEqual(packet.Length - EthernetDatagram.HeaderLength, packet.Ethernet.PayloadLength);
Assert.AreEqual(new MacAddress("ba:98:76:54:32:10"), packet.Ethernet.Source);
Assert.AreEqual(new MacAddress("01:23:45:67:89:ab"), packet.Ethernet.Destination);
Assert.AreEqual(EthernetType.IpV4, packet.Ethernet.EtherType);
Assert.AreEqual(IpV4Datagram.HeaderMinimumLength, packet.Ethernet.IpV4.HeaderLength);
Assert.AreEqual(0, packet.Ethernet.IpV4.TypeOfService);
Assert.AreEqual(packet.Length - EthernetDatagram.HeaderLength, packet.Ethernet.IpV4.TotalLength);
Assert.AreEqual(new IpV4Fragmentation(IpV4FragmentationFlags.DontFragment, 0), packet.Ethernet.IpV4.Fragmentation);
Assert.AreEqual(128, packet.Ethernet.IpV4.Ttl);
Assert.AreEqual(IpV4Protocol.Tcp, packet.Ethernet.IpV4.Protocol);
Assert.AreEqual(0x1234, packet.Ethernet.IpV4.HeaderChecksum);
// Assert.AreEqual(true, packet.Ethernet.IpV4.IsHeaderChecksumCorrect);
Assert.AreEqual(new IpV4Address("192.168.1.96"), packet.Ethernet.IpV4.Source);
Assert.AreEqual(new IpV4Address("18.52.86.120"), packet.Ethernet.IpV4.Destination);
// Assert.AreEqual(IpV4Options.None, packet.Ethernet.IpV4.Options);
}
private static Packet HexToPacket(string hexString, DataLinkKind dataLinkKind)
{
return HexToPacket(hexString, DateTime.MinValue, dataLinkKind);
}
private static Packet HexToPacket(string hexString, DateTime timestamp, DataLinkKind dataLinkKind)
{
byte[] bytes = new byte[hexString.Length / 2];
for (int i = 0; i < hexString.Length; i += 2)
{
bytes[i / 2] = Convert.ToByte(hexString.Substring(i, 2), 16);
}
return new Packet(bytes, timestamp, dataLinkKind);
}
}
} }
\ No newline at end of file
...@@ -87,6 +87,11 @@ namespace Packets ...@@ -87,6 +87,11 @@ namespace Packets
return _buffer.ReadUShort(StartOffset + offset, endianity); return _buffer.ReadUShort(StartOffset + offset, endianity);
} }
protected uint ReadUInt(int offset, Endianity endianity)
{
return _buffer.ReadUInt(StartOffset + offset, endianity);
}
private static readonly Datagram _empty = new Datagram(new byte[0], 0, 0); private static readonly Datagram _empty = new Datagram(new byte[0], 0, 0);
private readonly byte[] _buffer; private readonly byte[] _buffer;
private readonly int _startOffset; private readonly int _startOffset;
......
using System;
namespace Packets namespace Packets
{ {
/// <summary> /// <summary>
...@@ -20,9 +22,9 @@ namespace Packets ...@@ -20,9 +22,9 @@ namespace Packets
public const int HeaderLength = 14; public const int HeaderLength = 14;
internal EthernetDatagram(byte[] buffer, int offset, int length) public int PayloadLength
: base(buffer, offset, length)
{ {
get { return Math.Max(0, Length - HeaderLength); }
} }
public MacAddress Source public MacAddress Source
...@@ -58,7 +60,9 @@ namespace Packets ...@@ -58,7 +60,9 @@ namespace Packets
{ {
case EthernetType.Arp: case EthernetType.Arp:
case EthernetType.Ieee8021Q: case EthernetType.Ieee8021Q:
return true;
case EthernetType.IpV4: case EthernetType.IpV4:
return IpV4.IsValid;
case EthernetType.IpV6: case EthernetType.IpV6:
return true; return true;
...@@ -67,6 +71,21 @@ namespace Packets ...@@ -67,6 +71,21 @@ namespace Packets
} }
} }
public IpV4Datagram IpV4
{
get
{
if (_ipV4 == null && Length >= HeaderLength)
_ipV4 = new IpV4Datagram(Buffer, StartOffset + HeaderLength, Length - HeaderLength);
return _ipV4;
}
}
internal EthernetDatagram(byte[] buffer, int offset, int length)
: base(buffer, offset, length)
{
}
internal static void WriteHeader(byte[] buffer, int offset, MacAddress ethernetSource, MacAddress ethernetDestination, EthernetType ethernetType) internal static void WriteHeader(byte[] buffer, int offset, MacAddress ethernetSource, MacAddress ethernetDestination, EthernetType ethernetType)
{ {
ethernetSource.Write(buffer, offset + Offset.Source); ethernetSource.Write(buffer, offset + Offset.Source);
...@@ -74,5 +93,7 @@ namespace Packets ...@@ -74,5 +93,7 @@ namespace Packets
ethernetDestination.Write(buffer, offset + Offset.Destination); ethernetDestination.Write(buffer, offset + Offset.Destination);
buffer.Write(offset + Offset.EtherTypeLength, (ushort)ethernetType, Endianity.Big); buffer.Write(offset + Offset.EtherTypeLength, (ushort)ethernetType, Endianity.Big);
} }
private IpV4Datagram _ipV4;
} }
} }
\ No newline at end of file
...@@ -6,9 +6,9 @@ using System.Text; ...@@ -6,9 +6,9 @@ using System.Text;
namespace Packets namespace Packets
{ {
/// <summary> /// <summary>
/// +-----+---------+-----+-----------------+-------+-------+---------+ /// +-----+---------+-----+-----------------+-------+-----------------+
/// | Bit | 0-3 | 4-7 | 8-15 | 16-18 | 19-23 | 24-31 | /// | Bit | 0-3 | 4-7 | 8-15 | 16-18 | 19-31 |
/// +-----+---------+-----+-----------------+-------+-------+---------+ /// +-----+---------+-----+-----------------+-------+-----------------+
/// | 0 | Version | IHL | Type of Service | Total Length | /// | 0 | Version | IHL | Type of Service | Total Length |
/// +-----+---------+-----+-----------------+-------+-----------------+ /// +-----+---------+-----+-----------------+-------+-----------------+
/// | 32 | Identification | Flags | Fragment Offset | /// | 32 | Identification | Flags | Fragment Offset |
...@@ -18,45 +18,183 @@ namespace Packets ...@@ -18,45 +18,183 @@ namespace Packets
/// | 96 | Source Address | /// | 96 | Source Address |
/// +-----+-----------------------------------------------------------+ /// +-----+-----------------------------------------------------------+
/// | 128 | Destination Address | /// | 128 | Destination Address |
/// +-----+-------------------------------------------------+---------+ /// +-----+-----------------------------------------------------------+
/// | 160 | Options | Padding | /// | 160 | Options with padding |
/// +-----+-------------------------------------------------+---------+ /// +-----+-----------------------------------------------------------+
/// </summary> /// </summary>
public class IpV4Datagram : Datagram public class IpV4Datagram : Datagram
{ {
public const int HeaderMinimumLength = 20; public const int HeaderMinimumLength = 20;
private static class Offset
{
public const int VersionAndHeaderLength = 0;
public const int TypeOfService = 1;
public const int TotalLength = 2;
public const int Identification = 4;
public const int Fragmentation = 6;
public const int Ttl = 8;
public const int Protocol = 9;
public const int HeaderChecksum = 10;
public const int Source = 12;
public const int Destination = 16;
public const int Options = 20;
}
public const int Version = 0x4;
public int HeaderLength
{
get { return (this[Offset.VersionAndHeaderLength] & 0x0F) * 4; }
}
public byte TypeOfService
{
get { return this[Offset.TypeOfService];}
}
public ushort TotalLength
{
get { return ReadUShort(Offset.TotalLength, Endianity.Big); }
}
public ushort Identification
{
get { return ReadUShort(Offset.Identification, Endianity.Big); }
}
public IpV4Fragmentation Fragmentation
{
get { return new IpV4Fragmentation(ReadUShort(Offset.Fragmentation, Endianity.Big)); }
}
public byte Ttl
{
get { return this[Offset.Ttl]; }
}
public IpV4Protocol Protocol
{
get { return (IpV4Protocol)this[Offset.Protocol]; }
}
public ushort HeaderChecksum
{
get { return ReadUShort(Offset.HeaderChecksum, Endianity.Big); }
}
public bool IsHeaderChecksumCorrect
{
get { throw new NotImplementedException(); }
}
public IpV4Address Source
{
get { return new IpV4Address(ReadUInt(Offset.Source, Endianity.Big)); }
}
public IpV4Address Destination
{
get { return new IpV4Address(ReadUInt(Offset.Destination, Endianity.Big)); }
}
public IpV4Options Options
{
get { return new IpV4Options(Buffer, StartOffset + Offset.Options); }
}
internal IpV4Datagram(byte[] buffer, int offset, int length) internal IpV4Datagram(byte[] buffer, int offset, int length)
: base(buffer, offset, length) : base(buffer, offset, length)
{ {
} }
internal static void WriteHeader(byte[] buffer, int offset, IpV4TypeOfService typeOfService, ushort identification, IpV4Fragmentation fragmentation, byte ttl, IpV4Protocol protocol, IpV4Address source, IpV4Address destinationAddress, IpV4Options options) internal static void WriteHeader(byte[] buffer, int offset,
byte typeOfService, ushort identification,
IpV4Fragmentation fragmentation,
byte ttl, IpV4Protocol protocol,
IpV4Address source, IpV4Address destination,
IpV4Options options, int payloadLength)
{ {
throw new NotImplementedException(); int headerLength = HeaderMinimumLength + options.Length;
buffer[offset + Offset.VersionAndHeaderLength] = (byte)(Version << 4 + headerLength / 4);
buffer[offset + Offset.TypeOfService] = typeOfService;
buffer.Write(offset + Offset.TotalLength, (ushort)(headerLength + payloadLength), Endianity.Big);
buffer.Write(offset + Offset.Identification, identification, Endianity.Big);
fragmentation.Write(buffer, offset + Offset.Fragmentation);
buffer[offset + Offset.Ttl] = ttl;
buffer[offset + Offset.Protocol] = (byte)protocol;
// Todo Checksum
// buffer.Write(offset + Offset.Source, source, Endianity.Big);
// buffer.Write(offset + Offset.Destination, destination, Endianity.Big);
// options.Write(offset + Offset.Options);
} }
} }
public struct IpV4TypeOfService [Flags]
public enum IpV4FragmentationFlags : byte
{ {
private byte _value; Reserved = 0x1,
DontFragment = 0x2,
MoreFragments = 0x4
} }
public struct IpV4Fragmentation 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;
}
internal void Write(byte[] buffer, int offset)
{
buffer.Write(offset, _value, Endianity.Big);
}
private ushort _value; private ushort _value;
} }
public enum IpV4Protocol : byte public enum IpV4Protocol : byte
{ {
Tcp = 0x06
} }
public class IpV4Options public class IpV4Options
{ {
public static IpV4Options None
{
get { return _none; }
}
internal IpV4Options()
{
}
internal IpV4Options(byte[] buffer, int offset)
{
throw new NotImplementedException();
}
public int Length public int Length
{ {
get { throw new NotImplementedException(); } get { throw new NotImplementedException(); }
} }
private static IpV4Options _none = new IpV4Options();
} }
} }
...@@ -9,6 +9,15 @@ namespace Packets ...@@ -9,6 +9,15 @@ namespace Packets
_value = value; _value = value;
} }
public IpV4Address(string value)
{
string[] values = value.Split('.');
_value = (uint)((byte.Parse(values[0]) << 24) +
(byte.Parse(values[1]) << 16) +
(byte.Parse(values[2]) << 8) +
(byte.Parse(values[3])));
}
public uint ToValue() public uint ToValue()
{ {
return _value; return _value;
......
...@@ -6,6 +6,11 @@ namespace Packets ...@@ -6,6 +6,11 @@ namespace Packets
{ {
public class Packet : IEquatable<Packet> public class Packet : IEquatable<Packet>
{ {
public Packet(byte[] data, DateTime timestamp, DataLinkKind dataLink)
:this(data, timestamp, new DataLink(dataLink))
{
}
public Packet(byte[] data, DateTime timestamp, IDataLink dataLink) public Packet(byte[] data, DateTime timestamp, IDataLink dataLink)
{ {
_data = data; _data = data;
......
...@@ -16,7 +16,7 @@ namespace Packets ...@@ -16,7 +16,7 @@ namespace Packets
public static Packet IpV4(DateTime timestamp, public static Packet IpV4(DateTime timestamp,
MacAddress ethernetSource, MacAddress ethernetDestination, EthernetType ethernetType, MacAddress ethernetSource, MacAddress ethernetDestination, EthernetType ethernetType,
IpV4TypeOfService ipV4TypeOfService, ushort ipV4Identification, IpV4Fragmentation ipV4Fragmentation, byte ipV4TypeOfService, ushort ipV4Identification, IpV4Fragmentation ipV4Fragmentation,
byte ipV4Ttl, IpV4Protocol ipV4Protocol, byte ipV4Ttl, IpV4Protocol ipV4Protocol,
IpV4Address ipV4SourceAddress, IpV4Address ipV4DestinationAddress, IpV4Address ipV4SourceAddress, IpV4Address ipV4DestinationAddress,
IpV4Options ipV4Options, IpV4Options ipV4Options,
...@@ -29,7 +29,7 @@ namespace Packets ...@@ -29,7 +29,7 @@ namespace Packets
ipV4TypeOfService, ipV4Identification, ipV4Fragmentation, ipV4TypeOfService, ipV4Identification, ipV4Fragmentation,
ipV4Ttl, ipV4Protocol, ipV4Ttl, ipV4Protocol,
ipV4SourceAddress, ipV4DestinationAddress, ipV4SourceAddress, ipV4DestinationAddress,
ipV4Options); ipV4Options, ipV4Payload.Length);
ipV4Payload.Write(buffer, EthernetDatagram.HeaderLength + ipHeaderLength); ipV4Payload.Write(buffer, EthernetDatagram.HeaderLength + ipHeaderLength);
return new Packet(buffer, timestamp, new DataLink(DataLinkKind.Ethernet)); return new Packet(buffer, timestamp, new DataLink(DataLinkKind.Ethernet));
} }
......
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