Commit 8f749c59 authored by Brickner_cp's avatar Brickner_cp

TCP.

Fixed DateTime randomization.
parent 7fc31eea
...@@ -71,6 +71,10 @@ ...@@ -71,6 +71,10 @@
<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="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" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="PrivateConstants" />
<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="PrivateStaticReadonly" />
</Naming2> </Naming2>
</CodeStyleSettings> </CodeStyleSettings>
</Configuration> </Configuration>
\ No newline at end of file
...@@ -139,9 +139,10 @@ namespace PcapDotNet.Base.Test ...@@ -139,9 +139,10 @@ namespace PcapDotNet.Base.Test
{ {
const long ticks = 633737178954260865; const long ticks = 633737178954260865;
Assert.AreEqual("Jerusalem Daylight Time", TimeZone.CurrentTimeZone.DaylightName); Assert.AreEqual("Jerusalem Daylight Time", TimeZone.CurrentTimeZone.DaylightName);
Assert.AreEqual("Israel Standard Time", TimeZoneInfo.Local.Id);
DateTime dateTime = new DateTime(ticks, DateTimeKind.Local); DateTime dateTime = new DateTime(ticks, DateTimeKind.Local);
// Assert.AreEqual(dateTime.ToLocalTime(), dateTime.ToUniversalTime().ToLocalTime()); Assert.IsTrue(TimeZoneInfo.Local.IsInvalidTime(dateTime));
} }
} }
} }
\ No newline at end of file
using System.Reflection;
namespace PcapDotNet.Base
{
public static class MorePropertyInfo
{
public static object GetValue(this PropertyInfo propertyInfo, object obj)
{
return propertyInfo.GetValue(obj, null);
}
}
}
\ No newline at end of file
...@@ -57,6 +57,7 @@ ...@@ -57,6 +57,7 @@
<ItemGroup> <ItemGroup>
<Compile Include="MoreIEnumerable.cs" /> <Compile Include="MoreIEnumerable.cs" />
<Compile Include="MoreIList.cs" /> <Compile Include="MoreIList.cs" />
<Compile Include="MorePropertyInfo.cs" />
<Compile Include="Tuple.cs" /> <Compile Include="Tuple.cs" />
<Compile Include="UInt24.cs" /> <Compile Include="UInt24.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
......
...@@ -39,7 +39,10 @@ namespace PcapDotNet.Core.Test ...@@ -39,7 +39,10 @@ namespace PcapDotNet.Core.Test
return "Unknown (0x52) (12 bytes)"; return "Unknown (0x52) (12 bytes)";
case IpV4OptionType.RouterAlert: case IpV4OptionType.RouterAlert:
return "Router Alert: Unknown (" + ((IpV4OptionRouterAlert)option).Value + ")"; ushort routerAlertValue = ((IpV4OptionRouterAlert)option).Value;
return "Router Alert: " + ((routerAlertValue != 0)
? "Unknown (" + routerAlertValue + ")"
: "Every router examines packet");
case IpV4OptionType.QuickStart: case IpV4OptionType.QuickStart:
IpV4OptionQuickStart quickStart = (IpV4OptionQuickStart)option; IpV4OptionQuickStart quickStart = (IpV4OptionQuickStart)option;
......
...@@ -8,6 +8,7 @@ using System.Reflection; ...@@ -8,6 +8,7 @@ using System.Reflection;
using System.Threading; using System.Threading;
using System.Xml.Linq; using System.Xml.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using PcapDotNet.Base;
using PcapDotNet.Packets; using PcapDotNet.Packets;
using PcapDotNet.Packets.Ethernet; using PcapDotNet.Packets.Ethernet;
using PcapDotNet.Packets.IpV4; using PcapDotNet.Packets.IpV4;
...@@ -76,7 +77,7 @@ namespace PcapDotNet.Core.Test ...@@ -76,7 +77,7 @@ namespace PcapDotNet.Core.Test
[TestMethod] [TestMethod]
public void ComparePacketsToWiresharkTest() public void ComparePacketsToWiresharkTest()
{ {
for (int i = 0; i != 10; ++i) for (int i = 0; i != 1000; ++i)
{ {
// Create packets // Create packets
List<Packet> packets = new List<Packet>(CreateRandomPackets(100)); List<Packet> packets = new List<Packet>(CreateRandomPackets(100));
...@@ -103,7 +104,8 @@ namespace PcapDotNet.Core.Test ...@@ -103,7 +104,8 @@ namespace PcapDotNet.Core.Test
{ {
Ethernet, Ethernet,
IpV4, IpV4,
Udp Udp,
Tcp
} }
private static IEnumerable<Packet> CreateRandomPackets(int numPackets) private static IEnumerable<Packet> CreateRandomPackets(int numPackets)
...@@ -112,8 +114,8 @@ namespace PcapDotNet.Core.Test ...@@ -112,8 +114,8 @@ namespace PcapDotNet.Core.Test
for (int i = 0; i != numPackets; ++i) for (int i = 0; i != numPackets; ++i)
{ {
DateTime packetTimestamp = random.NextDateTime(PacketTimestamp.MinimumPacketTimestamp, PacketTimestamp.MaximumPacketTimestamp).ToUniversalTime().ToLocalTime(); DateTime packetTimestamp = random.NextDateTime(PacketTimestamp.MinimumPacketTimestamp, PacketTimestamp.MaximumPacketTimestamp).ToUniversalTime().ToLocalTime();
switch (random.NextEnum<PacketType>(PacketType.Udp)) // switch (PacketType.Tcp)
// switch (PacketType.Udp) switch (random.NextEnum<PacketType>())
{ {
case PacketType.Ethernet: case PacketType.Ethernet:
yield return PacketBuilder.Ethernet(packetTimestamp, yield return PacketBuilder.Ethernet(packetTimestamp,
...@@ -134,14 +136,26 @@ namespace PcapDotNet.Core.Test ...@@ -134,14 +136,26 @@ namespace PcapDotNet.Core.Test
case PacketType.Udp: case PacketType.Udp:
yield return PacketBuilder.EthernetIpV4Udp(packetTimestamp, yield return PacketBuilder.EthernetIpV4Udp(packetTimestamp,
random.NextMacAddress(), random.NextMacAddress(), random.NextMacAddress(), random.NextMacAddress(),
random.NextByte(), random.NextUShort(), random.NextByte(), random.NextUShort(),
new IpV4Fragmentation(), random.NextBool() ? IpV4Fragmentation.None : random.NextIpV4Fragmentation(),
// random.NextIpV4Fragmentation(),
random.NextByte(), random.NextByte(),
random.NextIpV4Address(), random.NextIpV4Address(), random.NextIpV4Options(), random.NextIpV4Address(), random.NextIpV4Address(), random.NextIpV4Options(),
random.NextUShort(), random.NextUShort(), random.NextBool(), random.NextUShort(), random.NextUShort(), random.NextBool(),
random.NextDatagram(random.Next(100))); random.NextDatagram(random.Next(100)));
break; break;
case PacketType.Tcp:
yield return PacketBuilder.EthernetIpV4Tcp(packetTimestamp,
random.NextMacAddress(), random.NextMacAddress(),
random.NextByte(), random.NextUShort(),
random.NextBool() ? IpV4Fragmentation.None : random.NextIpV4Fragmentation(),
random.NextByte(),
random.NextIpV4Address(), random.NextIpV4Address(), random.NextIpV4Options(),
random.NextUShort(), random.NextUShort(), random.NextUInt(), random.NextUInt(),
random.NextFlags<TcpFlags>(),
random.NextUShort(), random.NextUShort(), new TcpOptions(),
random.NextDatagram(random.Next(100)));
break;
} }
} }
} }
...@@ -158,7 +172,13 @@ namespace PcapDotNet.Core.Test ...@@ -158,7 +172,13 @@ namespace PcapDotNet.Core.Test
process.StartInfo = new ProcessStartInfo() process.StartInfo = new ProcessStartInfo()
{ {
FileName = WiresharkTsharkPath, FileName = WiresharkTsharkPath,
Arguments = " -o udp.check_checksum:TRUE -t r -n -r \"" + pcapFilename + "\" -T pdml", Arguments = "-o udp.check_checksum:TRUE " +
"-o tcp.relative_sequence_numbers:FALSE " +
"-o tcp.analyze_sequence_numbers:FALSE " +
"-o tcp.track_bytes_in_flight:FALSE " +
"-o tcp.desegment_tcp_streams:FALSE " +
"-o tcp.check_checksum:TRUE " +
"-t r -n -r \"" + pcapFilename + "\" -T pdml",
WorkingDirectory = WiresharkDiretory, WorkingDirectory = WiresharkDiretory,
UseShellExecute = false, UseShellExecute = false,
RedirectStandardOutput = true, RedirectStandardOutput = true,
...@@ -215,7 +235,7 @@ namespace PcapDotNet.Core.Test ...@@ -215,7 +235,7 @@ namespace PcapDotNet.Core.Test
PropertyInfo ethernetProperty = currentDatagram.GetType().GetProperty("Ethernet"); PropertyInfo ethernetProperty = currentDatagram.GetType().GetProperty("Ethernet");
if (ethernetProperty == null) if (ethernetProperty == null)
break; break;
currentDatagram = ethernetProperty.GetValue(currentDatagram, new object[] {}); currentDatagram = ethernetProperty.GetValue(currentDatagram);
CompareEtherent(layer, (EthernetDatagram)currentDatagram); CompareEtherent(layer, (EthernetDatagram)currentDatagram);
break; break;
...@@ -223,7 +243,7 @@ namespace PcapDotNet.Core.Test ...@@ -223,7 +243,7 @@ namespace PcapDotNet.Core.Test
PropertyInfo ipV4Property = currentDatagram.GetType().GetProperty("IpV4"); PropertyInfo ipV4Property = currentDatagram.GetType().GetProperty("IpV4");
if (ipV4Property == null) if (ipV4Property == null)
break; break;
currentDatagram = ipV4Property.GetValue(currentDatagram, new object[] {}); currentDatagram = ipV4Property.GetValue(currentDatagram);
CompareIpV4(layer, (IpV4Datagram)currentDatagram); CompareIpV4(layer, (IpV4Datagram)currentDatagram);
break; break;
...@@ -231,9 +251,22 @@ namespace PcapDotNet.Core.Test ...@@ -231,9 +251,22 @@ namespace PcapDotNet.Core.Test
PropertyInfo udpProperty = currentDatagram.GetType().GetProperty("Udp"); PropertyInfo udpProperty = currentDatagram.GetType().GetProperty("Udp");
if (udpProperty == null) if (udpProperty == null)
break; break;
Datagram previousDatagram = (Datagram)currentDatagram; {
currentDatagram = udpProperty.GetValue(currentDatagram, new object[] { }); Datagram ipDatagram = (Datagram)currentDatagram;
CompareUdp(layer, (IpV4Datagram)previousDatagram); currentDatagram = udpProperty.GetValue(currentDatagram);
CompareUdp(layer, (IpV4Datagram)ipDatagram);
}
break;
case "tcp":
PropertyInfo tcpProperty = currentDatagram.GetType().GetProperty("Tcp");
if (tcpProperty == null)
break;
{
Datagram ipDatagram = (Datagram)currentDatagram;
currentDatagram = tcpProperty.GetValue(currentDatagram);
CompareTcp(layer, (IpV4Datagram)ipDatagram);
}
break; break;
default: default:
...@@ -386,9 +419,13 @@ namespace PcapDotNet.Core.Test ...@@ -386,9 +419,13 @@ namespace PcapDotNet.Core.Test
if (currentOptionIndex >= options.Count) if (currentOptionIndex >= options.Count)
{ {
Assert.IsFalse(options.IsValid); Assert.IsFalse(options.IsValid);
Assert.IsTrue(field.Show().StartsWith("Unknown") || Assert.IsTrue(field.Show() == "Commercial IP security option" ||
field.Show().StartsWith("Unknown") ||
field.Show().StartsWith("Security") ||
field.Show().StartsWith("Router Alert (with option length = ") ||
field.Show().Contains("with too") || field.Show().Contains("with too") ||
field.Show().Contains(" bytes says option goes past end of options"), field.Show()); field.Show().Contains(" bytes says option goes past end of options") ||
field.Fields().Where(value => value.Show() == "(suboption would go past end of option)").Count() != 0, field.Show());
break; break;
} }
IpV4Option option = options[currentOptionIndex++]; IpV4Option option = options[currentOptionIndex++];
...@@ -427,20 +464,120 @@ namespace PcapDotNet.Core.Test ...@@ -427,20 +464,120 @@ namespace PcapDotNet.Core.Test
case "udp.checksum": case "udp.checksum":
field.AssertShowHex(udpDatagram.Checksum); field.AssertShowHex(udpDatagram.Checksum);
if (udpDatagram.Checksum != 0)
{
foreach (var checksumField in field.Fields())
{
switch (checksumField.Name())
{
case "udp.checksum_good":
checksumField.AssertShowDecimal(ipV4Datagram.IsTransportChecksumCorrect);
break;
case "udp.checksum_bad":
checksumField.AssertShowDecimal(!ipV4Datagram.IsTransportChecksumCorrect);
break;
}
}
}
break;
}
}
}
private static void CompareTcp(XElement tcpElement, IpV4Datagram ipV4Datagram)
{
TcpDatagram tcpDatagram = ipV4Datagram.Tcp;
foreach (var field in tcpElement.Fields())
{
switch (field.Name())
{
case "tcp.srcport":
field.AssertShowDecimal(tcpDatagram.SourcePort);
break;
case "tcp.dstport":
field.AssertShowDecimal(tcpDatagram.DestinationPort);
break;
case "tcp.seq":
field.AssertShowDecimal(tcpDatagram.SequenceNumber);
break;
case "tcp.ack":
field.AssertShowDecimal(tcpDatagram.AcknowledgmentNumber);
break;
case "tcp.hdr_len":
field.AssertShowDecimal(tcpDatagram.HeaderLength);
break;
case "tcp.flags":
field.AssertShowHex((byte)tcpDatagram.Flags);
foreach (var flagField in field.Fields())
{
switch (flagField.Name())
{
case "tcp.flags.cwr":
flagField.AssertShowDecimal(tcpDatagram.IsCwr);
break;
case "tcp.flags.ecn":
flagField.AssertShowDecimal(tcpDatagram.IsEce);
break;
case "tcp.flags.urg":
flagField.AssertShowDecimal(tcpDatagram.IsUrg);
break;
case "tcp.flags.ack":
flagField.AssertShowDecimal(tcpDatagram.IsAck);
break;
case "tcp.flags.push":
flagField.AssertShowDecimal(tcpDatagram.IsPush);
break;
case "tcp.flags.reset":
flagField.AssertShowDecimal(tcpDatagram.IsReset);
break;
case "tcp.flags.syn":
flagField.AssertShowDecimal(tcpDatagram.IsSyn);
break;
case "tcp.flags.fin":
flagField.AssertShowDecimal(tcpDatagram.IsFin);
break;
}
}
break;
case "tcp.window_size":
field.AssertShowDecimal(tcpDatagram.Window);
break;
case "tcp.checksum":
field.AssertShowHex(tcpDatagram.Checksum);
foreach (var checksumField in field.Fields()) foreach (var checksumField in field.Fields())
{ {
switch (checksumField.Name()) switch (checksumField.Name())
{ {
case "udp.checksum_good": case "tcp.checksum_good":
checksumField.AssertShowDecimal(ipV4Datagram.IsTransportChecksumCorrect); checksumField.AssertShowDecimal(ipV4Datagram.IsTransportChecksumCorrect);
break; break;
case "ip.checksum_bad": case "tcp.checksum_bad":
checksumField.AssertShowDecimal(!ipV4Datagram.IsTransportChecksumCorrect); checksumField.AssertShowDecimal(!ipV4Datagram.IsTransportChecksumCorrect);
break; break;
} }
} }
break; break;
case "tcp.urgent_pointer":
field.AssertShowDecimal(tcpDatagram.UrgentPointer);
break;
} }
} }
} }
......
...@@ -129,7 +129,7 @@ namespace PcapDotNet.Packets.Test ...@@ -129,7 +129,7 @@ namespace PcapDotNet.Packets.Test
ipV4Payload); ipV4Payload);
Assert.IsTrue(ipV4Protocol == IpV4Protocol.Udp || packet.IsValid, "IsValid"); Assert.IsTrue(ipV4Protocol == IpV4Protocol.Udp || ipV4Protocol == IpV4Protocol.Tcp || packet.IsValid, "IsValid");
// Ethernet // Ethernet
Assert.AreEqual(packet.Length - EthernetDatagram.HeaderLength, packet.Ethernet.PayloadLength, "PayloadLength"); Assert.AreEqual(packet.Length - EthernetDatagram.HeaderLength, packet.Ethernet.PayloadLength, "PayloadLength");
......
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
<Compile Include="PacketTests.cs" /> <Compile Include="PacketTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="IpV4AddressTests.cs" /> <Compile Include="IpV4AddressTests.cs" />
<Compile Include="TcpTests.cs" />
<Compile Include="UdpTests.cs" /> <Compile Include="UdpTests.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
......
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using PcapDotNet.Packets.Ethernet;
using PcapDotNet.Packets.IpV4;
using PcapDotNet.Packets.TestUtils;
using PcapDotNet.Packets.Transport;
using PcapDotNet.TestUtils;
namespace PcapDotNet.Packets.Test
{
/// <summary>
/// Summary description for TcpTests
/// </summary>
[TestClass]
public class TcpTests
{
public TcpTests()
{
//
// 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 RandomTcpTest()
{
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 = random.NextByte();
ushort ipV4Identification = random.NextUShort();
byte ipV4Ttl = random.NextByte();
IpV4FragmentationOptions ipV4FragmentationOptions = random.NextEnum<IpV4FragmentationOptions>();
ushort ipV4FragmentationOffset = (ushort)(random.NextUShort(ushort.MaxValue / 8) * 8);
IpV4Fragmentation ipV4Fragmentation = new IpV4Fragmentation(ipV4FragmentationOptions, ipV4FragmentationOffset);
IpV4Protocol ipV4Protocol = random.NextEnum<IpV4Protocol>();
IpV4Address ipV4Source = new IpV4Address(random.NextUInt());
IpV4Address ipV4Destination = new IpV4Address(random.NextUInt());
IpV4Options ipV4Options = random.NextIpV4Options();
for (int i = 0; i != 1000; ++i)
{
ushort tcpSourcePort = random.NextUShort();
ushort tcpDestinationPort = random.NextUShort();
uint tcpSequenceNumber = random.NextUInt();
uint tcpAcknowledgmentNumber = random.NextUInt();
TcpFlags tcpFlags = random.NextFlags<TcpFlags>();
ushort tcpWindow = random.NextUShort();
ushort tcpUrgentPointer = random.NextUShort();
TcpOptions tcpOptions = new TcpOptions();
Datagram tcpPayload = random.NextDatagram(random.Next(60000));
Packet packet = PacketBuilder.EthernetIpV4Tcp(DateTime.Now,
ethernetSource, ethernetDestination,
ipV4TypeOfService, ipV4Identification, ipV4Fragmentation, ipV4Ttl,
ipV4Source, ipV4Destination, ipV4Options,
tcpSourcePort, tcpDestinationPort, tcpSequenceNumber, tcpAcknowledgmentNumber, tcpFlags, tcpWindow, tcpUrgentPointer,
tcpOptions,
tcpPayload);
Assert.IsTrue(packet.IsValid);
// UDP
Assert.AreEqual(tcpSourcePort, packet.Ethernet.IpV4.Tcp.SourcePort, "Source Port");
Assert.AreEqual(tcpDestinationPort, packet.Ethernet.IpV4.Tcp.DestinationPort, "Destination Port");
Assert.AreEqual(tcpSequenceNumber, packet.Ethernet.IpV4.Tcp.SequenceNumber, "Sequence Number");
Assert.AreEqual(tcpAcknowledgmentNumber, packet.Ethernet.IpV4.Tcp.AcknowledgmentNumber, "Acknowledgment Number");
Assert.AreEqual(tcpFlags, packet.Ethernet.IpV4.Tcp.Flags, "Flags");
Assert.AreEqual(tcpWindow, packet.Ethernet.IpV4.Tcp.Window, "Window");
Assert.AreEqual(tcpUrgentPointer, packet.Ethernet.IpV4.Tcp.UrgentPointer, "Urgent Pointer");
Assert.AreEqual(TcpDatagram.HeaderMinimumLength + tcpOptions.BytesLength + tcpPayload.Length, packet.Ethernet.IpV4.Tcp.Length, "Total Length");
Assert.IsTrue(packet.Ethernet.IpV4.IsTransportChecksumCorrect, "IsTransportChecksumCorrect");
Assert.AreEqual(tcpPayload, packet.Ethernet.IpV4.Tcp.Payload, "Payload");
}
}
[TestMethod]
public void UdpChecksumTest()
{
Packet packet = Packet.FromHexadecimalString(
"3352c58e71ffc4f39ec3bae508004cfe0043361200008611eec22ea2c8d11e9eb7b9520c2a33f2bbbed998980bba4404f941019404eb51880496ce00000005a87a270013a683f572c10e1504a0df15448a",
DateTime.Now, DataLinkKind.Ethernet);
Assert.IsTrue(packet.Ethernet.IpV4.IsTransportChecksumCorrect);
}
}
}
\ No newline at end of file
...@@ -189,8 +189,9 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -189,8 +189,9 @@ namespace PcapDotNet.Packets.IpV4
{ {
if (_isTransportChecksumCorrect == null) if (_isTransportChecksumCorrect == null)
{ {
ushort transportChecksum = Udp.Checksum; ushort transportChecksum = Transport.Checksum;
_isTransportChecksumCorrect = (transportChecksum != 0) && (CalculateTransportChecksum() == transportChecksum); _isTransportChecksumCorrect = (Transport.IsChecksumOptional && transportChecksum == 0) ||
(CalculateTransportChecksum() == transportChecksum);
} }
return _isTransportChecksumCorrect.Value; return _isTransportChecksumCorrect.Value;
} }
...@@ -207,12 +208,12 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -207,12 +208,12 @@ namespace PcapDotNet.Packets.IpV4
/// <summary> /// <summary>
/// The payload of the datagram as a TCP datagram. /// The payload of the datagram as a TCP datagram.
/// </summary> /// </summary>
public Datagram Tcp public TcpDatagram Tcp
{ {
get get
{ {
if (_tcp == null && Length >= HeaderLength) if (_tcp == null && Length >= HeaderLength)
_tcp = new Datagram(Buffer, StartOffset + HeaderLength, Length - HeaderLength); _tcp = new TcpDatagram(Buffer, StartOffset + HeaderLength, Length - HeaderLength);
return _tcp; return _tcp;
} }
...@@ -232,6 +233,24 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -232,6 +233,24 @@ namespace PcapDotNet.Packets.IpV4
} }
} }
public TransportDatagram Transport
{
get
{
switch (Protocol)
{
case IpV4Protocol.Tcp:
return Tcp;
case IpV4Protocol.Udp:
return Udp;
default:
return null;
}
}
}
internal IpV4Datagram(byte[] buffer, int offset, int length) internal IpV4Datagram(byte[] buffer, int offset, int length)
: base(buffer, offset, length) : base(buffer, offset, length)
{ {
...@@ -245,6 +264,7 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -245,6 +264,7 @@ namespace PcapDotNet.Packets.IpV4
IpV4Options options, int payloadLength) IpV4Options options, int payloadLength)
{ {
int headerLength = HeaderMinimumLength + options.BytesLength; int headerLength = HeaderMinimumLength + options.BytesLength;
buffer[offset + Offset.VersionAndHeaderLength] = (byte)((DefaultVersion << 4) + headerLength / 4); buffer[offset + Offset.VersionAndHeaderLength] = (byte)((DefaultVersion << 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);
...@@ -260,18 +280,18 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -260,18 +280,18 @@ namespace PcapDotNet.Packets.IpV4
buffer.Write(offset + Offset.HeaderChecksum, Sum16BitsToChecksum(Sum16Bits(buffer, offset, headerLength)), Endianity.Big); buffer.Write(offset + Offset.HeaderChecksum, Sum16BitsToChecksum(Sum16Bits(buffer, offset, headerLength)), Endianity.Big);
} }
internal static void WriteTransportChecksum(byte[] buffer, int offset, int headerLength, ushort transportLength, int transportChecksumOffset) internal static void WriteTransportChecksum(byte[] buffer, int offset, int headerLength, ushort transportLength, int transportChecksumOffset, bool isChecksumOptional)
{ {
ushort checksum = CalculateTransportChecksum(buffer, offset, headerLength, transportLength, transportChecksumOffset); ushort checksum = CalculateTransportChecksum(buffer, offset, headerLength, transportLength, transportChecksumOffset, isChecksumOptional);
buffer.Write(offset + headerLength + transportChecksumOffset, checksum, Endianity.Big); buffer.Write(offset + headerLength + transportChecksumOffset, checksum, Endianity.Big);
} }
private ushort CalculateTransportChecksum() private ushort CalculateTransportChecksum()
{ {
return CalculateTransportChecksum(Buffer, StartOffset, HeaderLength, (ushort)(TotalLength - HeaderLength), UdpDatagram.ChecksumOffset); return CalculateTransportChecksum(Buffer, StartOffset, HeaderLength, (ushort)(TotalLength - HeaderLength), Transport.ChecksumOffset, Transport.IsChecksumOptional);
} }
private static ushort CalculateTransportChecksum(byte[] buffer, int offset, int headerLength, ushort transportLength, int transportChecksumOffset) private static ushort CalculateTransportChecksum(byte[] buffer, int offset, int headerLength, ushort transportLength, int transportChecksumOffset, bool isChecksumOptional)
{ {
uint sum = Sum16Bits(buffer, offset + Offset.Source, 2 * IpV4Address.SizeOf) + uint sum = Sum16Bits(buffer, offset + Offset.Source, 2 * IpV4Address.SizeOf) +
buffer[offset + Offset.Protocol] + transportLength + buffer[offset + Offset.Protocol] + transportLength +
...@@ -279,7 +299,7 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -279,7 +299,7 @@ namespace PcapDotNet.Packets.IpV4
Sum16Bits(buffer, offset + headerLength + transportChecksumOffset + 2, transportLength - transportChecksumOffset - 2); Sum16Bits(buffer, offset + headerLength + transportChecksumOffset + 2, transportLength - transportChecksumOffset - 2);
ushort checksumResult = Sum16BitsToChecksum(sum); ushort checksumResult = Sum16BitsToChecksum(sum);
if (checksumResult == 0) if (checksumResult == 0 && isChecksumOptional)
return 0xFFFF; return 0xFFFF;
return checksumResult; return checksumResult;
} }
...@@ -300,8 +320,10 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -300,8 +320,10 @@ namespace PcapDotNet.Packets.IpV4
{ {
// case IpV4Protocol.Tcp: // case IpV4Protocol.Tcp:
// return Tcp.IsValid; //&& IsTransportChecksumCorrect; // return Tcp.IsValid; //&& IsTransportChecksumCorrect;
case IpV4Protocol.Tcp:
case IpV4Protocol.Udp: case IpV4Protocol.Udp:
return Udp.IsValid && (Udp.Checksum == 0 || IsTransportChecksumCorrect); return Transport.IsValid && (Transport.IsChecksumOptional && Transport.Checksum == 0 ||
IsTransportChecksumCorrect);
default: default:
// Todo check more protocols // Todo check more protocols
return true; return true;
...@@ -343,7 +365,7 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -343,7 +365,7 @@ namespace PcapDotNet.Packets.IpV4
private bool? _isHeaderChecksumCorrect; private bool? _isHeaderChecksumCorrect;
private bool? _isTransportChecksumCorrect; private bool? _isTransportChecksumCorrect;
private IpV4Options _options; private IpV4Options _options;
private Datagram _tcp; private TcpDatagram _tcp;
private UdpDatagram _udp; private UdpDatagram _udp;
} }
} }
\ No newline at end of file
...@@ -110,7 +110,64 @@ namespace PcapDotNet.Packets ...@@ -110,7 +110,64 @@ namespace PcapDotNet.Packets
udpPayload.Write(buffer, ethernetIpV4HeadersLength + UdpDatagram.HeaderLength); udpPayload.Write(buffer, ethernetIpV4HeadersLength + UdpDatagram.HeaderLength);
if (udpCalculateChecksum) if (udpCalculateChecksum)
IpV4Datagram.WriteTransportChecksum(buffer, EthernetDatagram.HeaderLength, ipV4HeaderLength, (ushort)transportLength, UdpDatagram.ChecksumOffset); IpV4Datagram.WriteTransportChecksum(buffer, EthernetDatagram.HeaderLength, ipV4HeaderLength, (ushort)transportLength, UdpDatagram.Offset.Checksum, true);
return new Packet(buffer, timestamp, new DataLink(DataLinkKind.Ethernet));
}
/// <summary>
/// Builds a UDP over IPv4 over Ethernet packet.
/// </summary>
/// <param name="timestamp">The packet timestamp.</param>
/// <param name="ethernetSource">The ethernet source mac address.</param>
/// <param name="ethernetDestination">The ethernet destination mac address.</param>
/// <param name="ipV4TypeOfService">The IPv4 Type of Service.</param>
/// <param name="ipV4Identification">The IPv4 Identification.</param>
/// <param name="ipV4Fragmentation">The IPv4 Fragmentation.</param>
/// <param name="ipV4Ttl">The IPv4 TTL.</param>
/// <param name="ipV4SourceAddress">The IPv4 source address.</param>
/// <param name="ipV4DestinationAddress">The IPv4 destination address.</param>
/// <param name="ipV4Options">The IPv4 options.</param>
/// <param name="tcpSourcePort">The source udp port.</param>
/// <param name="tcpDestinationPort">The destination udp port.</param>
/// <param name="tcpPayload">The payload of UDP datagram.</param>
/// <returns>A packet with a UDP over IPv4 over Ethernet datagram.</returns>
public static Packet EthernetIpV4Tcp(DateTime timestamp,
MacAddress ethernetSource, MacAddress ethernetDestination,
byte ipV4TypeOfService, ushort ipV4Identification, IpV4Fragmentation ipV4Fragmentation,
byte ipV4Ttl,
IpV4Address ipV4SourceAddress, IpV4Address ipV4DestinationAddress,
IpV4Options ipV4Options,
ushort tcpSourcePort, ushort tcpDestinationPort,
uint tcpSequenceNumber, uint tcpAcknowledgmentNumber,
TcpFlags tcpFlags, ushort tcpWindow, ushort tcpUrgentPointer,
TcpOptions tcpOptions,
Datagram tcpPayload)
{
int ipV4HeaderLength = IpV4Datagram.HeaderMinimumLength + ipV4Options.BytesLength;
int tcpHeaderLength = TcpDatagram.HeaderMinimumLength + tcpOptions.BytesLength;
int transportLength = tcpHeaderLength + tcpPayload.Length;
int ethernetIpV4HeadersLength = EthernetDatagram.HeaderLength + ipV4HeaderLength;
byte[] buffer = new byte[ethernetIpV4HeadersLength + transportLength];
EthernetDatagram.WriteHeader(buffer, 0, ethernetSource, ethernetDestination, EthernetType.IpV4);
IpV4Datagram.WriteHeader(buffer, EthernetDatagram.HeaderLength,
ipV4TypeOfService, ipV4Identification, ipV4Fragmentation,
ipV4Ttl, IpV4Protocol.Tcp,
ipV4SourceAddress, ipV4DestinationAddress,
ipV4Options, transportLength);
TcpDatagram.WriteHeader(buffer, ethernetIpV4HeadersLength,
tcpSourcePort, tcpDestinationPort,
tcpSequenceNumber, tcpAcknowledgmentNumber,
tcpFlags, tcpWindow, tcpUrgentPointer,
tcpOptions);
tcpPayload.Write(buffer, ethernetIpV4HeadersLength + tcpHeaderLength);
IpV4Datagram.WriteTransportChecksum(buffer, EthernetDatagram.HeaderLength, ipV4HeaderLength, (ushort)transportLength, TcpDatagram.Offset.Checksum, false);
return new Packet(buffer, timestamp, new DataLink(DataLinkKind.Ethernet)); return new Packet(buffer, timestamp, new DataLink(DataLinkKind.Ethernet));
} }
......
...@@ -103,6 +103,8 @@ ...@@ -103,6 +103,8 @@
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Transport\TcpDatagram.cs" /> <Compile Include="Transport\TcpDatagram.cs" />
<Compile Include="Transport\TcpFlags.cs" /> <Compile Include="Transport\TcpFlags.cs" />
<Compile Include="Transport\TcpOption.cs" />
<Compile Include="Transport\TcpOptions.cs" />
<Compile Include="Transport\TransportDatagram.cs" /> <Compile Include="Transport\TransportDatagram.cs" />
<Compile Include="Transport\UdpDatagram.cs" /> <Compile Include="Transport\UdpDatagram.cs" />
</ItemGroup> </ItemGroup>
......
using System;
namespace PcapDotNet.Packets.Transport namespace PcapDotNet.Packets.Transport
{ {
/// <summary> /// <summary>
...@@ -20,12 +22,13 @@ namespace PcapDotNet.Packets.Transport ...@@ -20,12 +22,13 @@ namespace PcapDotNet.Packets.Transport
/// </summary> /// </summary>
public class TcpDatagram : TransportDatagram public class TcpDatagram : TransportDatagram
{ {
private static class Offset public const int HeaderMinimumLength = 20;
internal static class Offset
{ {
public const int SequenceNumber = 4; public const int SequenceNumber = 4;
public const int AcknowledgmentNumber = 8; public const int AcknowledgmentNumber = 8;
public const int HeaderLength = 12; public const int HeaderLengthAndFlags = 12;
public const int Flags = 12;
public const int Window = 14; public const int Window = 14;
public const int Checksum = 16; public const int Checksum = 16;
public const int UrgentPointer = 18; public const int UrgentPointer = 18;
...@@ -63,12 +66,17 @@ namespace PcapDotNet.Packets.Transport ...@@ -63,12 +66,17 @@ namespace PcapDotNet.Packets.Transport
/// </summary> /// </summary>
public int HeaderLength public int HeaderLength
{ {
get { return 4 * (this[Offset.HeaderLength] >> 4); } get { return 4 * (this[Offset.HeaderLengthAndFlags] >> 4); }
}
public int RealHeaderLength
{
get { return Math.Min(HeaderLength, Length); }
} }
public TcpFlags Flags public TcpFlags Flags
{ {
get { return (TcpFlags)(ReadUShort(Offset.Flags, Endianity.Big) & 0x01FF); } get { return (TcpFlags)(ReadUShort(Offset.HeaderLengthAndFlags, Endianity.Big) & 0x01FF); }
} }
public ushort Window public ushort Window
...@@ -76,14 +84,101 @@ namespace PcapDotNet.Packets.Transport ...@@ -76,14 +84,101 @@ namespace PcapDotNet.Packets.Transport
get { return ReadUShort(Offset.Window, Endianity.Big); } get { return ReadUShort(Offset.Window, Endianity.Big); }
} }
public ushort Checksum public override ushort Checksum
{ {
get { return ReadUShort(Offset.Checksum, Endianity.Big); } get { return ReadUShort(Offset.Checksum, Endianity.Big); }
} }
public override int ChecksumOffset
{
get { return Offset.Checksum; }
}
public override bool IsChecksumOptional
{
get { return false; }
}
public ushort UrgentPointer public ushort UrgentPointer
{ {
get { return ReadUShort(Offset.UrgentPointer, Endianity.Big); } get { return ReadUShort(Offset.UrgentPointer, Endianity.Big); }
} }
public TcpOptions Options
{
get
{
if (_options == null)
_options = new TcpOptions(Buffer, StartOffset + Offset.Options, RealHeaderLength - HeaderMinimumLength);
return _options;
}
}
/// <summary>
/// The payload of the TCP datagram.
/// </summary>
public Datagram Payload
{
get { return new Datagram(Buffer, StartOffset + HeaderLength, Length - HeaderLength); }
}
public bool IsCwr
{
get { return (Flags & TcpFlags.Cwr) == TcpFlags.Cwr; }
}
public bool IsEce
{
get { return (Flags & TcpFlags.Ece) == TcpFlags.Ece; }
}
public bool IsUrg
{
get { return (Flags & TcpFlags.Urg) == TcpFlags.Urg; }
}
public bool IsAck
{
get { return (Flags & TcpFlags.Ack) == TcpFlags.Ack; }
}
public bool IsPush
{
get { return (Flags & TcpFlags.Psh) == TcpFlags.Psh; }
}
public bool IsReset
{
get { return (Flags & TcpFlags.Rst) == TcpFlags.Rst; }
}
public bool IsSyn
{
get { return (Flags & TcpFlags.Syn) == TcpFlags.Syn; }
}
public bool IsFin
{
get { return (Flags & TcpFlags.Fin) == TcpFlags.Fin; }
}
internal static void WriteHeader(byte[] buffer, int offset,
ushort sourcePort, ushort destinationPort,
uint sequenceNumber, uint acknowledgmentNumber,
TcpFlags flags, ushort window, ushort urgentPointer,
TcpOptions options)
{
int headerLength = HeaderMinimumLength + options.BytesLength;
WriteHeader(buffer, offset, sourcePort, destinationPort);
buffer.Write(offset + Offset.SequenceNumber, sequenceNumber, Endianity.Big);
buffer.Write(offset + Offset.AcknowledgmentNumber, acknowledgmentNumber, Endianity.Big);
buffer.Write(offset + Offset.HeaderLengthAndFlags, (ushort)(((ushort)((headerLength / 4) << 12)) | (ushort)flags), Endianity.Big);
buffer.Write(offset + Offset.Window, window, Endianity.Big);
buffer.Write(offset + Offset.UrgentPointer, urgentPointer, Endianity.Big);
options.Write(buffer, offset + Offset.Options);
}
private TcpOptions _options;
} }
} }
\ No newline at end of file
using System;
namespace PcapDotNet.Packets.Transport
{
/// <summary>
/// TCP Header Format
/// +-----+-----+----+-----+-----+-----+-----+-----+-----+-----+-----+
/// | Bit | 0-6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
/// +-----+-----+----+-----+-----+-----+-----+-----+-----+-----+-----+
/// | 0 | | NS | CWR | ECE | URG | ACK | PSH | RST | SYN | FIN |
/// +-----+-----+----+-----+-----+-----+-----+-----+-----+-----+-----+
/// </summary>
[Flags]
public enum TcpFlags : ushort
{
None = 0x0000,
Fin = 0x0001,
Syn = 0x0002,
Rst = 0x0004,
Psh = 0x0008,
Ack = 0x0010,
Urg = 0x0020,
Ece = 0x0040,
Cwr = 0x0080,
Ns = 0x0100,
}
}
\ No newline at end of file
namespace PcapDotNet.Packets.Transport
{
public class TcpOption
{
}
}
\ No newline at end of file
using System;
namespace PcapDotNet.Packets.Transport
{
public class TcpOptions
{
public static TcpOptions None
{
get { return _none; }
}
/// <summary>
/// Creates options from a list of options.
/// </summary>
/// <param name="options">The list of options.</param>
public TcpOptions(params TcpOption[] options)
{
_bytesLength = 0;
}
internal TcpOptions(byte[] buffer, int offset, int length)
// : this(Read(buffer, offset, length))
{
_bytesLength = length;
}
public int BytesLength
{
get { return _bytesLength; }
}
internal void Write(byte[] buffer, int offset)
{
// throw new NotImplementedException();
}
private readonly int _bytesLength;
private readonly bool _isValid;
private static readonly TcpOptions _none = new TcpOptions();
}
}
\ No newline at end of file
using System;
namespace PcapDotNet.Packets.Transport namespace PcapDotNet.Packets.Transport
{ {
/// <summary> /// <summary>
...@@ -39,6 +41,12 @@ namespace PcapDotNet.Packets.Transport ...@@ -39,6 +41,12 @@ namespace PcapDotNet.Packets.Transport
get { return ReadUShort(Offset.DestinationPort, Endianity.Big); } get { return ReadUShort(Offset.DestinationPort, Endianity.Big); }
} }
public abstract ushort Checksum { get; }
public abstract int ChecksumOffset { get; }
public abstract bool IsChecksumOptional { get; }
protected static void WriteHeader(byte[] buffer, int offset, ushort sourcePort, ushort destinationPort) protected static void WriteHeader(byte[] buffer, int offset, ushort sourcePort, ushort destinationPort)
{ {
buffer.Write(offset + Offset.SourcePort, sourcePort, Endianity.Big); buffer.Write(offset + Offset.SourcePort, sourcePort, Endianity.Big);
......
...@@ -33,7 +33,7 @@ namespace PcapDotNet.Packets.Transport ...@@ -33,7 +33,7 @@ namespace PcapDotNet.Packets.Transport
/// </summary> /// </summary>
public const int HeaderLength = 8; public const int HeaderLength = 8;
private static class Offset internal static class Offset
{ {
// public const int SourcePort = 0; // public const int SourcePort = 0;
// public const int DestinationPort = 2; // public const int DestinationPort = 2;
...@@ -41,8 +41,6 @@ namespace PcapDotNet.Packets.Transport ...@@ -41,8 +41,6 @@ namespace PcapDotNet.Packets.Transport
public const int Checksum = 6; public const int Checksum = 6;
} }
internal const int ChecksumOffset = Offset.Checksum;
/// <summary> /// <summary>
/// The length in octets of this user datagram including this header and the data. /// The length in octets of this user datagram including this header and the data.
/// (This means the minimum value of the length is eight.) /// (This means the minimum value of the length is eight.)
...@@ -56,11 +54,21 @@ namespace PcapDotNet.Packets.Transport ...@@ -56,11 +54,21 @@ namespace PcapDotNet.Packets.Transport
/// Checksum is the 16-bit one's complement of the one's complement sum of a pseudo header of information from the IP header, /// Checksum is the 16-bit one's complement of the one's complement sum of a pseudo header of information from the IP header,
/// the UDP header, and the data, padded with zero octets at the end (if necessary) to make a multiple of two octets. /// the UDP header, and the data, padded with zero octets at the end (if necessary) to make a multiple of two octets.
/// </summary> /// </summary>
public ushort Checksum public override ushort Checksum
{ {
get { return ReadUShort(Offset.Checksum, Endianity.Big); } get { return ReadUShort(Offset.Checksum, Endianity.Big); }
} }
public override int ChecksumOffset
{
get { return Offset.Checksum; }
}
public override bool IsChecksumOptional
{
get { return true; }
}
/// <summary> /// <summary>
/// The payload of the UDP datagram. /// The payload of the UDP datagram.
/// </summary> /// </summary>
......
...@@ -85,7 +85,8 @@ namespace PcapDotNet.TestUtils ...@@ -85,7 +85,8 @@ namespace PcapDotNet.TestUtils
public static DateTime NextDateTime(this Random random, DateTime minimumValue, DateTime maximumValue) public static DateTime NextDateTime(this Random random, DateTime minimumValue, DateTime maximumValue)
{ {
return new DateTime(random.NextLong(minimumValue.Ticks, maximumValue.Ticks + 1)); return new DateTime(random.NextLong(minimumValue.ToUniversalTime().Ticks,
maximumValue.ToUniversalTime().Ticks + 1), DateTimeKind.Utc).ToLocalTime();
} }
public static DateTime NextDateTime(this Random random) public static DateTime NextDateTime(this Random random)
...@@ -115,5 +116,29 @@ namespace PcapDotNet.TestUtils ...@@ -115,5 +116,29 @@ namespace PcapDotNet.TestUtils
{ {
return values[random.Next(values.Count)]; return values[random.Next(values.Count)];
} }
public static T NextFlags<T>(this Random random)
{
Type type = typeof(T);
if (!type.IsEnum)
throw new ArgumentException("T must be an Enum");
IEnumerable<T> enumValues = (IEnumerable<T>)Enum.GetValues(type);
Type underlyingType = Enum.GetUnderlyingType(type);
List<object> enumValuesAsUnderlyingType = new List<object>(enumValues.Select(value => Convert.ChangeType(value, underlyingType)));
List<ulong> enumValuesAsULong;
if (underlyingType == typeof(ushort))
enumValuesAsULong = new List<ulong>(enumValuesAsUnderlyingType.Cast<ushort>().Select(value => (ulong)value));
else
throw new ArgumentException("Type " + underlyingType + " is not supported");
ulong resultValue = enumValuesAsULong.Aggregate(default(ulong),
(result, value) => random.NextBool()
? result | value
: result);
T resultEnum = (T)Convert.ChangeType(resultValue, underlyingType);
return resultEnum;
}
} }
} }
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