Commit 3b6b9175 authored by Brickner_cp's avatar Brickner_cp

TCP

parent 97e00f11
......@@ -44,6 +44,15 @@ namespace PcapDotNet.Core.Test
case TcpOptionType.PartialOrderConnectionPermitted:
return "Unknown (0x09) (2 bytes)";
case TcpOptionType.ConnectionCount:
return "CC: " + ((TcpOptionConnectionCount)option).ConnectionCount;
case TcpOptionType.ConnectionCountNew:
return "CC.NEW: " + ((TcpOptionConnectionCountNew)option).ConnectionCount;
case TcpOptionType.ConnectionCountEcho:
return "CC.ECHO: " + ((TcpOptionConnectionCountEcho)option).ConnectionCount;
case (TcpOptionType)20:
return "SCPS capabilities" + (option.Length >= 4
? string.Empty
......@@ -85,6 +94,9 @@ namespace PcapDotNet.Core.Test
case TcpOptionType.TimeStamp:
case TcpOptionType.PartialOrderServiceProfile:
case TcpOptionType.PartialOrderConnectionPermitted:
case TcpOptionType.ConnectionCount:
case TcpOptionType.ConnectionCountNew:
case TcpOptionType.ConnectionCountEcho:
break;
case TcpOptionType.SelectiveAcknowledgment:
......
......@@ -77,10 +77,10 @@ namespace PcapDotNet.Core.Test
[TestMethod]
public void ComparePacketsToWiresharkTest()
{
for (int i = 0; i != 1000; ++i)
for (int i = 0; i != 500; ++i)
{
// Create packets
List<Packet> packets = new List<Packet>(CreateRandomPackets(100));
List<Packet> packets = new List<Packet>(CreateRandomPackets(200));
// Compare packets to wireshark
ComparePacketsToWireshark(packets);
......@@ -422,6 +422,7 @@ namespace PcapDotNet.Core.Test
{
Assert.IsFalse(options.IsValid);
Assert.IsTrue(field.Show() == "Commercial IP security option" ||
field.Show() == "Loose source route (length byte past end of options)" ||
field.Show().StartsWith("Unknown") ||
field.Show().StartsWith("Security") ||
field.Show().StartsWith("Router Alert (with option length = ") ||
......@@ -633,14 +634,27 @@ namespace PcapDotNet.Core.Test
break;
case "tcp.options.echo":
field.AssertShowDecimal(option is TcpOptionEchoReply || option is TcpOptionEcho);
Assert.IsTrue(option is TcpOptionEchoReply || option is TcpOptionEcho);
field.AssertShowDecimal(1);
break;
case "tcp.options.time_stamp":
field.AssertShowDecimal(option is TcpOptionTimeStamp);
Assert.IsTrue(option is TcpOptionTimeStamp);
field.AssertShowDecimal(1);
break;
case "tcp.options.cc":
Assert.IsTrue(option is TcpOptionConnectionCountBase);
field.AssertShowDecimal(1);
break;
case "tcp.options.scps.vector":
Assert.AreEqual((TcpOptionType)20, option.OptionType);
if (field.Show() == "0")
++currentOptionIndex;
break;
case "tcp.options.scps":
Assert.AreEqual((TcpOptionType)20, option.OptionType);
++currentOptionIndex;
break;
......@@ -655,6 +669,9 @@ namespace PcapDotNet.Core.Test
throw new InvalidOperationException(field.Name());
}
if ((option is TcpOptionUnknown))
continue;
var optionShows = from f in field.Fields() select f.Show();
MoreAssert.AreSequenceEqual(optionShows, option.GetWiresharkSubfieldStrings());
}
......
......@@ -293,12 +293,15 @@ namespace PcapDotNet.Packets.TestUtils
impossibleOptionTypes.Add(TcpOptionType.PartialOrderServiceProfile);
if (maximumOptionLength < TcpOptionPartialOrderConnectionPermitted.OptionLength)
impossibleOptionTypes.Add(TcpOptionType.PartialOrderConnectionPermitted);
if (maximumOptionLength < TcpOptionConnectionCountBase.OptionLength)
{
impossibleOptionTypes.Add(TcpOptionType.ConnectionCount);
impossibleOptionTypes.Add(TcpOptionType.ConnectionCountNew);
impossibleOptionTypes.Add(TcpOptionType.ConnectionCountEcho);
}
impossibleOptionTypes.Add(TcpOptionType.AlternateChecksumData);
impossibleOptionTypes.Add(TcpOptionType.AlternateChecksumRequest);
impossibleOptionTypes.Add(TcpOptionType.Cc);
impossibleOptionTypes.Add(TcpOptionType.CcEcho);
impossibleOptionTypes.Add(TcpOptionType.CcNew);
impossibleOptionTypes.Add(TcpOptionType.Md5Signature);
impossibleOptionTypes.Add(TcpOptionType.QuickStartResponse);
impossibleOptionTypes.Add(TcpOptionType.UserTimeout);
......@@ -343,6 +346,15 @@ namespace PcapDotNet.Packets.TestUtils
case TcpOptionType.PartialOrderConnectionPermitted:
return new TcpOptionPartialOrderConnectionPermitted();
case TcpOptionType.ConnectionCount:
return new TcpOptionConnectionCount(random.NextUInt());
case TcpOptionType.ConnectionCountEcho:
return new TcpOptionConnectionCountEcho(random.NextUInt());
case TcpOptionType.ConnectionCountNew:
return new TcpOptionConnectionCountNew(random.NextUInt());
default:
throw new InvalidOperationException("optionType = " + optionType);
}
......
......@@ -112,6 +112,10 @@
<Compile Include="Transport\TcpFlags.cs" />
<Compile Include="Transport\TcpOption.cs" />
<Compile Include="Transport\TcpOptionComplex.cs" />
<Compile Include="Transport\TcpOptionConnectionCount.cs" />
<Compile Include="Transport\TcpOptionConnectionCountBase.cs" />
<Compile Include="Transport\TcpOptionConnectionCountEcho.cs" />
<Compile Include="Transport\TcpOptionConnectionCountNew.cs" />
<Compile Include="Transport\TcpOptionEcho.cs" />
<Compile Include="Transport\TcpOptionEchoReply.cs" />
<Compile Include="Transport\TcpOptionMaximumSegmentSize.cs" />
......
namespace PcapDotNet.Packets.Transport
{
/// <summary>
/// CC Option (RFC 1644).
/// +--------+--------+--------+--------+--------+--------+
/// |00001011|00000110| Connection Count: SEG.CC |
/// +--------+--------+--------+--------+--------+--------+
/// Kind=11 Length=6
///
/// This option may be sent in an initial SYN segment, and it may be sent in other segments if a CC or CC.NEW option
/// has been received for this incarnation of the connection.
/// Its SEG.CC value is the TCB.CCsend value from the sender's TCB.
/// </summary>
[OptionTypeRegistration(typeof(TcpOptionType), TcpOptionType.ConnectionCount)]
public class TcpOptionConnectionCount : TcpOptionConnectionCountBase, IOptionComplexFactory
{
public TcpOptionConnectionCount(uint connectionCount)
: base(TcpOptionType.ConnectionCount, connectionCount)
{
}
public TcpOptionConnectionCount()
: this(0)
{
}
/// <summary>
/// Tries to read the option from a buffer starting from the option value (after the type and length).
/// </summary>
/// <param name="buffer">The buffer to read the option from.</param>
/// <param name="offset">The offset to the first byte to read the buffer. Will be incremented by the number of bytes read.</param>
/// <param name="valueLength">The number of bytes the option value should take according to the length field that was already read.</param>
/// <returns>On success - the complex option read. On failure - null.</returns>
public Option CreateInstance(byte[] buffer, ref int offset, byte valueLength)
{
uint connectionCount;
if (!TryRead(out connectionCount, buffer, ref offset, valueLength))
return null;
return new TcpOptionConnectionCount(connectionCount);
}
}
}
\ No newline at end of file
using System;
namespace PcapDotNet.Packets.Transport
{
public abstract class TcpOptionConnectionCountBase : TcpOptionComplex, IEquatable<TcpOptionConnectionCountBase>
{
/// <summary>
/// The number of bytes this option take.
/// </summary>
public const int OptionLength = 6;
public const int OptionValueLength = OptionLength - OptionHeaderLength;
public uint ConnectionCount { get; private set; }
/// <summary>
/// The number of bytes this option will take.
/// </summary>
public override int Length
{
get { return OptionLength; }
}
/// <summary>
/// True iff this option may appear at most once in a datagram.
/// </summary>
public override bool IsAppearsAtMostOnce
{
get { return true; }
}
public bool Equals(TcpOptionConnectionCountBase other)
{
if (other == null)
return false;
return OptionType == other.OptionType &&
ConnectionCount == other.ConnectionCount;
}
public override bool Equals(TcpOption other)
{
return Equals(other as TcpOptionConnectionCountBase);
}
internal override void Write(byte[] buffer, ref int offset)
{
base.Write(buffer, ref offset);
buffer.Write(ref offset, ConnectionCount, Endianity.Big);
}
protected TcpOptionConnectionCountBase(TcpOptionType optionType, uint connectionCount)
: base(optionType)
{
ConnectionCount = connectionCount;
}
protected static bool TryRead(out uint connectionCount, byte[] buffer, ref int offset, byte valueLength)
{
if (valueLength != OptionValueLength)
{
connectionCount = 0;
return false;
}
connectionCount = buffer.ReadUInt(ref offset, Endianity.Big);
return true;
}
}
}
\ No newline at end of file
namespace PcapDotNet.Packets.Transport
{
/// <summary>
/// CC.ECHO Option (RFC 1644).
/// +--------+--------+--------+--------+--------+--------+
/// |00001101|00000110| Connection Count: SEG.CC |
/// +--------+--------+--------+--------+--------+--------+
/// Kind=13 Length=6
///
/// This option must be sent (in addition to a CC option) in a segment containing both a SYN and an ACK bit,
/// if the initial SYN segment contained a CC or CC.NEW option.
/// Its SEG.CC value is the SEG.CC value from the initial SYN.
///
/// A CC.ECHO option should be sent only in a <SYN,ACK> segment and should be ignored if it is received in any other segment.
/// </summary>
[OptionTypeRegistration(typeof(TcpOptionType), TcpOptionType.ConnectionCountEcho)]
public class TcpOptionConnectionCountEcho : TcpOptionConnectionCountBase, IOptionComplexFactory
{
public TcpOptionConnectionCountEcho(uint connectionCount)
: base(TcpOptionType.ConnectionCountEcho, connectionCount)
{
}
public TcpOptionConnectionCountEcho()
: this(0)
{
}
/// <summary>
/// Tries to read the option from a buffer starting from the option value (after the type and length).
/// </summary>
/// <param name="buffer">The buffer to read the option from.</param>
/// <param name="offset">The offset to the first byte to read the buffer. Will be incremented by the number of bytes read.</param>
/// <param name="valueLength">The number of bytes the option value should take according to the length field that was already read.</param>
/// <returns>On success - the complex option read. On failure - null.</returns>
public Option CreateInstance(byte[] buffer, ref int offset, byte valueLength)
{
uint connectionCount;
if (!TryRead(out connectionCount, buffer, ref offset, valueLength))
return null;
return new TcpOptionConnectionCountEcho(connectionCount);
}
}
}
\ No newline at end of file
namespace PcapDotNet.Packets.Transport
{
/// <summary>
/// CC.NEW Option (RFC 1644).
/// +--------+--------+--------+--------+--------+--------+
/// |00001100|00000110| Connection Count: SEG.CC |
/// +--------+--------+--------+--------+--------+--------+
/// Kind=12 Length=6
///
/// This option may be sent instead of a CC option in an initial <SYN> segment (i.e., SYN but not ACK bit),
/// to indicate that the SEG.CC value may not be larger than the previous value.
/// Its SEG.CC value is the TCB.CCsend value from the sender's TCB.
/// </summary>
[OptionTypeRegistration(typeof(TcpOptionType), TcpOptionType.ConnectionCountNew)]
public class TcpOptionConnectionCountNew : TcpOptionConnectionCountBase, IOptionComplexFactory
{
public TcpOptionConnectionCountNew(uint connectionCount)
: base(TcpOptionType.ConnectionCountNew, connectionCount)
{
}
public TcpOptionConnectionCountNew()
: this(0)
{
}
/// <summary>
/// Tries to read the option from a buffer starting from the option value (after the type and length).
/// </summary>
/// <param name="buffer">The buffer to read the option from.</param>
/// <param name="offset">The offset to the first byte to read the buffer. Will be incremented by the number of bytes read.</param>
/// <param name="valueLength">The number of bytes the option value should take according to the length field that was already read.</param>
/// <returns>On success - the complex option read. On failure - null.</returns>
public Option CreateInstance(byte[] buffer, ref int offset, byte valueLength)
{
uint connectionCount;
if (!TryRead(out connectionCount, buffer, ref offset, valueLength))
return null;
return new TcpOptionConnectionCountNew(connectionCount);
}
}
}
\ No newline at end of file
......@@ -13,9 +13,9 @@ namespace PcapDotNet.Packets.Transport
TimeStamp = 8,
PartialOrderConnectionPermitted = 9,
PartialOrderServiceProfile = 10,
Cc = 11,
CcNew = 12,
CcEcho = 13,
ConnectionCount = 11,
ConnectionCountNew = 12,
ConnectionCountEcho = 13,
AlternateChecksumRequest = 14,
AlternateChecksumData = 15,
Md5Signature = 19,
......
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