Commit af11fe38 authored by Brickner_cp's avatar Brickner_cp

TCP

parent 2611e58a
...@@ -35,6 +35,11 @@ namespace PcapDotNet.Core.Test ...@@ -35,6 +35,11 @@ namespace PcapDotNet.Core.Test
case TcpOptionType.EchoReply: case TcpOptionType.EchoReply:
return "Echo reply: " + ((TcpOptionEchoReply)option).Info; return "Echo reply: " + ((TcpOptionEchoReply)option).Info;
case TcpOptionType.TimeStamp:
TcpOptionTimeStamp timeStampOption = (TcpOptionTimeStamp)option;
return "Timestamps: TSval " + timeStampOption.TimeStampValue + ", TSecr " + timeStampOption.TimeStampEchoReply;
default: default:
throw new InvalidOperationException("Illegal option type " + option.OptionType); throw new InvalidOperationException("Illegal option type " + option.OptionType);
} }
...@@ -51,6 +56,7 @@ namespace PcapDotNet.Core.Test ...@@ -51,6 +56,7 @@ namespace PcapDotNet.Core.Test
case TcpOptionType.SelectiveAcknowledgmentPermitted: case TcpOptionType.SelectiveAcknowledgmentPermitted:
case TcpOptionType.Echo: case TcpOptionType.Echo:
case TcpOptionType.EchoReply: case TcpOptionType.EchoReply:
case TcpOptionType.TimeStamp:
break; break;
case TcpOptionType.SelectiveAcknowledgment: case TcpOptionType.SelectiveAcknowledgment:
......
...@@ -629,6 +629,10 @@ namespace PcapDotNet.Core.Test ...@@ -629,6 +629,10 @@ namespace PcapDotNet.Core.Test
field.AssertShowDecimal(option is TcpOptionEchoReply || option is TcpOptionEcho); field.AssertShowDecimal(option is TcpOptionEchoReply || option is TcpOptionEcho);
break; break;
case "tcp.options.time_stamp":
field.AssertShowDecimal(option is TcpOptionTimeStamp);
break;
default: default:
throw new InvalidOperationException(field.Name()); throw new InvalidOperationException(field.Name());
} }
......
...@@ -249,6 +249,8 @@ namespace PcapDotNet.Packets.TestUtils ...@@ -249,6 +249,8 @@ namespace PcapDotNet.Packets.TestUtils
impossibleOptionTypes.Add(TcpOptionType.Echo); impossibleOptionTypes.Add(TcpOptionType.Echo);
if (maximumOptionLength < TcpOptionEchoReply.OptionLength) if (maximumOptionLength < TcpOptionEchoReply.OptionLength)
impossibleOptionTypes.Add(TcpOptionType.EchoReply); impossibleOptionTypes.Add(TcpOptionType.EchoReply);
if (maximumOptionLength < TcpOptionTimeStamp.OptionLength)
impossibleOptionTypes.Add(TcpOptionType.TimeStamp);
impossibleOptionTypes.Add(TcpOptionType.AlternateChecksumData); impossibleOptionTypes.Add(TcpOptionType.AlternateChecksumData);
impossibleOptionTypes.Add(TcpOptionType.AlternateChecksumRequest); impossibleOptionTypes.Add(TcpOptionType.AlternateChecksumRequest);
...@@ -259,7 +261,6 @@ namespace PcapDotNet.Packets.TestUtils ...@@ -259,7 +261,6 @@ namespace PcapDotNet.Packets.TestUtils
impossibleOptionTypes.Add(TcpOptionType.PartialOrderConnectionPermitted); impossibleOptionTypes.Add(TcpOptionType.PartialOrderConnectionPermitted);
impossibleOptionTypes.Add(TcpOptionType.PartialOrderServiceProfile); impossibleOptionTypes.Add(TcpOptionType.PartialOrderServiceProfile);
impossibleOptionTypes.Add(TcpOptionType.QuickStartResponse); impossibleOptionTypes.Add(TcpOptionType.QuickStartResponse);
impossibleOptionTypes.Add(TcpOptionType.TimeStamp);
impossibleOptionTypes.Add(TcpOptionType.UserTimeout); impossibleOptionTypes.Add(TcpOptionType.UserTimeout);
TcpOptionType optionType = random.NextEnum<TcpOptionType>(impossibleOptionTypes); TcpOptionType optionType = random.NextEnum<TcpOptionType>(impossibleOptionTypes);
...@@ -293,6 +294,9 @@ namespace PcapDotNet.Packets.TestUtils ...@@ -293,6 +294,9 @@ namespace PcapDotNet.Packets.TestUtils
case TcpOptionType.EchoReply: case TcpOptionType.EchoReply:
return new TcpOptionEchoReply(random.NextUInt()); return new TcpOptionEchoReply(random.NextUInt());
case TcpOptionType.TimeStamp:
return new TcpOptionTimeStamp(random.NextUInt(), random.NextUInt());
default: default:
throw new InvalidOperationException("optionType = " + optionType); throw new InvalidOperationException("optionType = " + optionType);
} }
......
...@@ -118,6 +118,7 @@ ...@@ -118,6 +118,7 @@
<Compile Include="Transport\TcpOptionSelectiveAcknowledgmentBlock.cs" /> <Compile Include="Transport\TcpOptionSelectiveAcknowledgmentBlock.cs" />
<Compile Include="Transport\TcpOptionSelectiveAcknowledgmentPermitted.cs" /> <Compile Include="Transport\TcpOptionSelectiveAcknowledgmentPermitted.cs" />
<Compile Include="Transport\TcpOptionSimple.cs" /> <Compile Include="Transport\TcpOptionSimple.cs" />
<Compile Include="Transport\TcpOptionTimeStamp.cs" />
<Compile Include="Transport\TcpOptionType.cs" /> <Compile Include="Transport\TcpOptionType.cs" />
<Compile Include="Transport\TcpOptionWindowScale.cs" /> <Compile Include="Transport\TcpOptionWindowScale.cs" />
<Compile Include="Transport\TransportDatagram.cs" /> <Compile Include="Transport\TransportDatagram.cs" />
......
using System;
namespace PcapDotNet.Packets.Transport
{
/// <summary>
/// TCP Timestamps Option (TSopt):
/// +-------+-------+---------------------+---------------------+
/// |Kind=8 | 10 | TS Value (TSval) |TS Echo Reply (TSecr)|
/// +-------+-------+---------------------+---------------------+
/// 1 1 4 4
///
/// The Timestamps option carries two four-byte timestamp fields.
/// The Timestamp Value field (TSval) contains the current value of the timestamp clock of the TCP sending the option.
///
/// The Timestamp Echo Reply field (TSecr) is only valid if the ACK bit is set in the TCP header;
/// if it is valid, it echos a timestamp value that was sent by the remote TCP in the TSval field of a Timestamps option.
/// When TSecr is not valid, its value must be zero.
/// The TSecr value will generally be from the most recent Timestamp option that was received; however, there are exceptions that are explained below.
///
/// A TCP may send the Timestamps option (TSopt) in an initial <SYN> segment (i.e., segment containing a SYN bit and no ACK bit),
/// and may send a TSopt in other segments only if it received a TSopt in the initial <SYN> segment for the connection.
/// </summary>
[OptionTypeRegistration(typeof(TcpOptionType), TcpOptionType.TimeStamp)]
public class TcpOptionTimeStamp : TcpOptionComplex, IOptionComplexFactory, IEquatable<TcpOptionTimeStamp>
{
/// <summary>
/// The number of bytes this option take.
/// </summary>
public const int OptionLength = 10;
public const int OptionValueLength = OptionLength - OptionHeaderLength;
public TcpOptionTimeStamp(uint timeStampValue, uint timeStampEchoReply)
: base(TcpOptionType.TimeStamp)
{
TimeStampValue = timeStampValue;
TimeStampEchoReply = timeStampEchoReply;
}
public TcpOptionTimeStamp()
: this(0, 0)
{
}
public uint TimeStampValue { get; private set; }
public uint TimeStampEchoReply { 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(TcpOptionTimeStamp other)
{
if (other == null)
return false;
return TimeStampValue == other.TimeStampValue &&
TimeStampEchoReply == other.TimeStampEchoReply;
}
public override bool Equals(TcpOption other)
{
return Equals(other as TcpOptionTimeStamp);
}
/// <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)
{
if (valueLength != OptionValueLength)
return null;
uint timeStampValue = buffer.ReadUInt(ref offset, Endianity.Big);
uint timeStampEchoReply = buffer.ReadUInt(ref offset, Endianity.Big);
return new TcpOptionTimeStamp(timeStampValue, timeStampEchoReply);
}
internal override void Write(byte[] buffer, ref int offset)
{
base.Write(buffer, ref offset);
buffer.Write(ref offset, TimeStampValue, Endianity.Big);
buffer.Write(ref offset, TimeStampEchoReply, Endianity.Big);
}
}
}
\ No newline at end of file
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