Commit 1e9ae76d authored by Brickner_cp's avatar Brickner_cp

IpV4

parent ff28a0d2
...@@ -120,52 +120,62 @@ namespace Packets.Test ...@@ -120,52 +120,62 @@ namespace Packets.Test
public void HttpTest() public void HttpTest()
{ {
Packet packet = HexToPacket( Packet packet = HexToPacket(
"0123456789abba98765432100800" + // Ethernet "feff200001000000010000000800" +
"4500042f" + // IPv4 Version, IHL, Type of Service, Total Length "45000207" + // IPv4 Version, IHL, Type of Service, Total Length
"787a4000" + // IPv4 Identification, Flags, Fragment Offset "0f454000" + // IPv4 Identification, Flags, Fragment Offset
"80061234" + // IPv4 Time to Live, Protocol, Header Checksum "80069010" + // IPv4 Time to Live, Protocol, Header Checksum
"c0a80160" + // IPv4 Source Address "91fea0ed" + // IPv4 Source Address
"12345678" + // IPv4 Destination Address "41d0e4df" + // IPv4 Destination Address
"06d900504a5d60e5f48579935018440c70c70000474554202f20485454502f312e310d0a" + "0d2c005038affe14114c618c501825bca9580000474554202f646f776e6c6f61642e68746d6c20485454502f312e310d0a486f73743a207777772e657468657265616c2e636f6d0d0a557365722d4167656e743a204d6f7a696c6c612f352e30202857696e646f77733b20553b2057696e646f7773204e5420352e313b20656e2d55533b2072763a312e3629204765636b6f2f32303034303131330d0a4163636570743a20746578742f786d6c2c6170706c69636174696f6e2f786d6c2c6170706c69636174696f6e2f7868746d6c2b786d6c2c746578742f68746d6c3b713d302e392c746578742f706c61696e3b713d302e382c696d6167652f706e672c696d6167652f6a7065672c696d6167652f6769663b713d302e322c2a2f2a3b713d302e310d0a4163636570742d4c616e67756167653a20656e2d75732c656e3b713d302e350d0a4163636570742d456e636f64696e673a20677a69702c6465666c6174650d0a4163636570742d436861727365743a2049534f2d383835392d312c7574662d383b713d302e372c2a3b713d302e370d0a4b6565702d416c6976653a203330300d0a436f6e6e656374696f6e3a206b6565702d616c6976650d0a526566657265723a20687474703a2f2f7777772e657468657265616c2e636f6d2f646576656c6f706d656e742e68746d6c0d0a0d0a",
"486f73743a2070636170646f746e65742e636f6465706c65782e636f6d0d0a" +
"557365722d4167656e743a204d6f7a696c6c612f352e30202857696e646f77733b20553b2057696e646f7773204e5420352e313b20656e2d55533b2072763a312e392e302e313229204765636b6f2f323030393037303631312046697265666f782f332e302e313220282e4e455420434c5220332e352e3330373239290d0a" +
"4163636570743a20746578742f68746d6c2c6170706c69636174696f6e2f7868746d6c2b786d6c2c6170706c69636174696f6e2f786d6c3b713d302e392c2a2f2a3b713d302e380d0a" +
"4163636570742d4c616e67756167653a20656e2d75732c656e3b713d302e350d0a" +
"4163636570742d456e636f64696e673a20677a69702c6465666c6174650d0a" +
"4163636570742d436861727365743a2049534f2d383835392d312c7574662d383b713d302e372c2a3b713d302e370d0a" +
"4b6565702d416c6976653a203330300d0a" +
"436f6e6e656374696f6e3a206b6565702d616c6976650d0a" +
"526566657265723a20687474703a2f2f70636170646f746e65742e636f6465706c65782e636f6d2f77696b692f636f6d6d656e74732f766965773f7469746c653d486f6d650d0a" +
"526566657265723a20687474703a2f2f70636170646f746e65742e636f6465706c65782e636f6d2f77696b692f636f6d6d656e74732f766965773f7469746c653d486f6d65" +
"526566657265723a20687474703a2f2f70636170646f746e65742e636f6465706c65782e636f6d2f77696b692f636f6d6d656e74732f766965773f7469746c653d486f6d65" +
"526566657265723a20687474703a2f2f70636170646f746e65742e636f6465706c65782e636f6d2f77696b692f636f6d6d656e74732f766965773f7469746c653d486f6d65" +
"526566657265723a20687474703a2f2f70636170646f746e65742e636f6465706c65782e636f6d2f77696b692f636f6d6d656e74732f766965773f7469746c653d486f6d65" +
"526566657265723a20687474703a2f2f70636170646f746e65742e636f6465706c65782e636f6d2f77696b692f636f6d6d656e74732f766965773f7469746c653d486f6d65" +
"526566657265723a20687474703a2f2f70636170646f746e65742e636f6465706c65782e636f6d2f77696b692f636f6d6d656e74732f766965773f7469746c653d486f6d65" +
"526566657265723a20687474703a2f2f70636170646f746e65742e636f6465706c65782e636f6d2f77696b692f636f6d6d656e74732f766965773f7469746c653d486f6d65" +
"526566657265723a20687474703a2f2f70636170646f746e65742e636f6465706c65782e636f6d2f77696b692f636f6d6d656e74732f766965773f7469746c653d486f6d65" +
"123456780d0a" +
"0d0a",
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);
Assert.AreEqual(packet.Length - EthernetDatagram.HeaderLength, packet.Ethernet.PayloadLength); Assert.AreEqual(packet.Length - EthernetDatagram.HeaderLength, packet.Ethernet.PayloadLength, "PayloadLength");
Assert.AreEqual(new MacAddress("ba:98:76:54:32:10"), packet.Ethernet.Source); Assert.AreEqual(new MacAddress("00:00:01:00:00:00"), packet.Ethernet.Source, "Ethernet Source");
Assert.AreEqual(new MacAddress("01:23:45:67:89:ab"), packet.Ethernet.Destination); Assert.AreEqual(new MacAddress("fe:ff:20:00:01:00"), packet.Ethernet.Destination, "Ethernet Destination");
Assert.AreEqual(EthernetType.IpV4, packet.Ethernet.EtherType); Assert.AreEqual(EthernetType.IpV4, packet.Ethernet.EtherType, "Ethernet Type");
Assert.AreEqual(IpV4Datagram.HeaderMinimumLength, packet.Ethernet.IpV4.HeaderLength); Assert.AreEqual(IpV4Datagram.HeaderMinimumLength, packet.Ethernet.IpV4.HeaderLength, "IP HeaderLength");
Assert.AreEqual(0, packet.Ethernet.IpV4.TypeOfService); Assert.AreEqual(0, packet.Ethernet.IpV4.TypeOfService, "IP TypeOfService");
Assert.AreEqual(packet.Length - EthernetDatagram.HeaderLength, packet.Ethernet.IpV4.TotalLength); Assert.AreEqual(packet.Length - EthernetDatagram.HeaderLength, packet.Ethernet.IpV4.TotalLength, "IP TotalLength");
Assert.AreEqual(new IpV4Fragmentation(IpV4FragmentationFlags.DontFragment, 0), packet.Ethernet.IpV4.Fragmentation); Assert.AreEqual(new IpV4Fragmentation(IpV4FragmentationFlags.DontFragment, 0), packet.Ethernet.IpV4.Fragmentation, "IP Fragmentation");
Assert.AreEqual(128, packet.Ethernet.IpV4.Ttl); Assert.AreEqual(128, packet.Ethernet.IpV4.Ttl, "IP Ttl");
Assert.AreEqual(IpV4Protocol.Tcp, packet.Ethernet.IpV4.Protocol); Assert.AreEqual(IpV4Protocol.Tcp, packet.Ethernet.IpV4.Protocol, "IP Protocol");
Assert.AreEqual(0x1234, packet.Ethernet.IpV4.HeaderChecksum); Assert.AreEqual(0x9010, packet.Ethernet.IpV4.HeaderChecksum, "IP HeaderChecksum");
// Assert.AreEqual(true, packet.Ethernet.IpV4.IsHeaderChecksumCorrect); Assert.AreEqual(true, packet.Ethernet.IpV4.IsHeaderChecksumCorrect, "IP HeaderChecksumCorrect");
Assert.AreEqual(new IpV4Address("192.168.1.96"), packet.Ethernet.IpV4.Source); Assert.AreEqual(new IpV4Address("145.254.160.237"), packet.Ethernet.IpV4.Source, "IP Source");
Assert.AreEqual(new IpV4Address("18.52.86.120"), packet.Ethernet.IpV4.Destination); Assert.AreEqual(new IpV4Address("65.208.228.223"), packet.Ethernet.IpV4.Destination, "IP Destination");
// Assert.AreEqual(IpV4Options.None, packet.Ethernet.IpV4.Options); Assert.AreEqual(IpV4Options.None, packet.Ethernet.IpV4.Options, "IP Options");
} }
private static Packet HexToPacket(string hexString, DataLinkKind dataLinkKind) private static Packet HexToPacket(string hexString, DataLinkKind dataLinkKind)
......
...@@ -85,7 +85,12 @@ namespace Packets ...@@ -85,7 +85,12 @@ namespace Packets
public bool IsHeaderChecksumCorrect public bool IsHeaderChecksumCorrect
{ {
get { throw new NotImplementedException(); } get
{
if (_isHeaderChecksumCorrect == null)
_isHeaderChecksumCorrect = (CalculateHeaderChecksum() == HeaderChecksum);
return _isHeaderChecksumCorrect.Value;
}
} }
public IpV4Address Source public IpV4Address Source
...@@ -100,7 +105,7 @@ namespace Packets ...@@ -100,7 +105,7 @@ namespace Packets
public IpV4Options Options public IpV4Options Options
{ {
get { return new IpV4Options(Buffer, StartOffset + Offset.Options); } get { return new IpV4Options(Buffer, StartOffset + Offset.Options, HeaderLength - HeaderMinimumLength); }
} }
internal IpV4Datagram(byte[] buffer, int offset, int length) internal IpV4Datagram(byte[] buffer, int offset, int length)
...@@ -128,6 +133,25 @@ namespace Packets ...@@ -128,6 +133,25 @@ namespace Packets
// buffer.Write(offset + Offset.Destination, destination, Endianity.Big); // buffer.Write(offset + Offset.Destination, destination, Endianity.Big);
// options.Write(offset + Offset.Options); // options.Write(offset + Offset.Options);
} }
private ushort CalculateHeaderChecksum()
{
// and 16 bits
uint sum = 0;
for (int offset = 0; offset < Offset.HeaderChecksum; offset += 2)
sum += ReadUShort(offset, Endianity.Big);
for (int offset = Offset.HeaderChecksum + 2; offset < HeaderLength; offset += 2)
sum += ReadUShort(offset, Endianity.Big);
// take only 16 bits out of the 32 bit sum and add up the carrier
sum = (sum & 0x0000FFFF) + (sum >> 16);
// one's complement the result
sum = ~sum;
return (ushort)sum;
}
private bool? _isHeaderChecksumCorrect;
} }
[Flags] [Flags]
...@@ -185,9 +209,19 @@ namespace Packets ...@@ -185,9 +209,19 @@ namespace Packets
{ {
} }
internal IpV4Options(byte[] buffer, int offset) internal IpV4Options(byte[] buffer, int offset, int length)
{ {
throw new NotImplementedException(); int offsetEnd = offset + length;
while (offset != offsetEnd)
{
IpV4Option option = IpV4Option.Read(buffer, ref offset, offsetEnd - offset);
if (option == null)
break;
_options.Add(option);
if (option is IpV4OptionEndOfOptionsList)
break;
}
} }
public int Length public int Length
...@@ -195,6 +229,160 @@ namespace Packets ...@@ -195,6 +229,160 @@ namespace Packets
get { throw new NotImplementedException(); } get { throw new NotImplementedException(); }
} }
private List<IpV4Option> _options = new List<IpV4Option>();
private static IpV4Options _none = new IpV4Options(); private static IpV4Options _none = new IpV4Options();
} }
public enum IpV4OptionType : byte
{
EndOfOptionList = 0,
NoOperation = 1,
Security = 130,
LooseSourceRouting = 131,
StrictSourceRouting = 137,
RecordRoute = 7,
StreamIdentifier = 136,
InternetTimestamp = 68
}
public abstract class IpV4Option
{
protected IpV4Option(IpV4OptionType type)
{
_type = type;
}
internal static IpV4Option Read(byte[] buffer, ref int offset, int length)
{
int offsetEnd = offset + length;
if (offset == offsetEnd)
return null;
IpV4OptionType optionType = (IpV4OptionType)buffer[offset++];
switch (optionType)
{
case IpV4OptionType.EndOfOptionList:
return new IpV4OptionEndOfOptionsList(optionType);
case IpV4OptionType.NoOperation:
return new IpV4OptionNoOperation(optionType);
case IpV4OptionType.Security:
return IpV4OptionSecurity.Read(optionType, buffer, ref offset, offsetEnd - offset);
// Todo support more option types
// case IpV4OptionType.LooseSourceRouting:
// return IpV4OptionLooseSourceRouting.Read(optionType, buffer, ref offset, offsetEnd - offset);
// case IpV4OptionType.StrictSourceRouting:
// return IpV4OptionStrictSourceRouting.Read(optionType, buffer, ref offset, offsetEnd - offset);
// case IpV4OptionType.RecordRoute:
// return IpV4OptionRecordRoute.Read(optionType, buffer, ref offset, offsetEnd - offset);
// case IpV4OptionType.StreamIdentifier:
// return IpV4OptionStreamIdentifier.Read(optionType, buffer, ref offset, offsetEnd - offset);
// case IpV4OptionType.InternetTimestamp:
// return IpV4OptionInternetTimestamp.Read(optionType, buffer, ref offset, offsetEnd - offset);
default:
return null;
}
}
private IpV4OptionType _type;
}
// public class IpV4OptionInternetTimestamp : IpV4Option
// {
// internal static IpV4OptionInternetTimestamp Read(IpV4OptionType optionType, byte[] buffer, ref int offset, int length)
// {
// }
// }
//
// public class IpV4OptionStreamIdentifier : IpV4Option
// {
// internal static IpV4OptionStreamIdentifier Read(IpV4OptionType optionType, byte[] buffer, ref int offset, int length)
// {
// }
// }
//
// public class IpV4OptionRecordRoute : IpV4Option
// {
// internal static IpV4OptionRecordRoute Read(IpV4OptionType optionType, byte[] buffer, ref int offset, int length)
// {
// }
// }
//
// public class IpV4OptionStrictSourceRouting : IpV4Option
// {
// internal static IpV4OptionStrictSourceRouting Read(IpV4OptionType optionType, byte[] buffer, ref int offset, int length)
// {
// }
// }
//
// public class IpV4OptionLooseSourceRouting : IpV4Option
// {
// internal static IpV4OptionLooseSourceRouting Read(IpV4OptionType optionType, byte[] buffer, ref int offset, int length)
// {
// }
// }
public enum IpV4OptionSecurityLevel : ushort
{
Unclassified = 0x0000,
Confidential = 0xF135,
EFTO = 0x789A,
MMMM = 0xBC4D,
PROG = 0x5E26,
Restricted = 0xAF13,
Secret = 0xD788,
TopSecret = 0x6BC5
}
public class IpV4OptionSecurity : IpV4Option
{
internal static IpV4OptionSecurity Read(IpV4OptionType optionType, byte[] buffer, ref int offset, int length)
{
if (length < 12)
return null;
byte optionLength = buffer[offset++];
if (optionLength != 11)
return null;
IpV4OptionSecurityLevel level = (IpV4OptionSecurityLevel)buffer.ReadUShort(ref offset, Endianity.Big);
ushort compartments = buffer.ReadUShort(ref offset, Endianity.Big);
ushort handlingRestrictions = buffer.ReadUShort(ref offset, Endianity.Big);
uint transmissionControlCode = (uint)((buffer.ReadUShort(ref offset, Endianity.Big) << 8) +
buffer[offset++]);
return new IpV4OptionSecurity(optionType, level, compartments, handlingRestrictions, transmissionControlCode);
}
private IpV4OptionSecurity(IpV4OptionType optionType,
IpV4OptionSecurityLevel level, ushort compartments,
ushort handlingRestrictions, uint transmissionControlCode)
: base(optionType)
{
_level = level;
_compartments = compartments;
_handlingRestrictions = handlingRestrictions;
_transmissionControlCode = transmissionControlCode;
}
private IpV4OptionSecurityLevel _level;
private ushort _compartments;
private ushort _handlingRestrictions;
private uint _transmissionControlCode; // this could actually be 24 bits
}
public class IpV4OptionNoOperation : IpV4Option
{
public IpV4OptionNoOperation(IpV4OptionType type)
: base(type)
{
}
}
public class IpV4OptionEndOfOptionsList : IpV4Option
{
public IpV4OptionEndOfOptionsList(IpV4OptionType type)
: base(type)
{
}
}
} }
...@@ -26,6 +26,13 @@ namespace Packets ...@@ -26,6 +26,13 @@ namespace Packets
return (ushort)ReadShort(buffer, offset, endianity); return (ushort)ReadShort(buffer, offset, endianity);
} }
public static ushort ReadUShort(this byte[] buffer, ref int offset, Endianity endianity)
{
ushort result = ReadUShort(buffer, offset, endianity);
offset += 2;
return result;
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "uint")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "uint")]
public static uint ReadUInt(this byte[] buffer, int offset, Endianity endianity) public static uint ReadUInt(this byte[] buffer, int offset, Endianity endianity)
{ {
......
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