Commit f9bfb007 authored by Brickner_cp's avatar Brickner_cp

TCP

parent 3b6b9175
...@@ -53,6 +53,12 @@ namespace PcapDotNet.Core.Test ...@@ -53,6 +53,12 @@ namespace PcapDotNet.Core.Test
case TcpOptionType.ConnectionCountEcho: case TcpOptionType.ConnectionCountEcho:
return "CC.ECHO: " + ((TcpOptionConnectionCountEcho)option).ConnectionCount; return "CC.ECHO: " + ((TcpOptionConnectionCountEcho)option).ConnectionCount;
case TcpOptionType.AlternateChecksumRequest:
return "Unknown (0x0e) (3 bytes)";
case TcpOptionType.AlternateChecksumData:
return "Unknown (0x0f) (" + option.Length + " bytes)";
case (TcpOptionType)20: case (TcpOptionType)20:
return "SCPS capabilities" + (option.Length >= 4 return "SCPS capabilities" + (option.Length >= 4
? string.Empty ? string.Empty
...@@ -97,6 +103,8 @@ namespace PcapDotNet.Core.Test ...@@ -97,6 +103,8 @@ namespace PcapDotNet.Core.Test
case TcpOptionType.ConnectionCount: case TcpOptionType.ConnectionCount:
case TcpOptionType.ConnectionCountNew: case TcpOptionType.ConnectionCountNew:
case TcpOptionType.ConnectionCountEcho: case TcpOptionType.ConnectionCountEcho:
case TcpOptionType.AlternateChecksumRequest:
case TcpOptionType.AlternateChecksumData:
break; break;
case TcpOptionType.SelectiveAcknowledgment: case TcpOptionType.SelectiveAcknowledgment:
......
...@@ -299,9 +299,11 @@ namespace PcapDotNet.Packets.TestUtils ...@@ -299,9 +299,11 @@ namespace PcapDotNet.Packets.TestUtils
impossibleOptionTypes.Add(TcpOptionType.ConnectionCountNew); impossibleOptionTypes.Add(TcpOptionType.ConnectionCountNew);
impossibleOptionTypes.Add(TcpOptionType.ConnectionCountEcho); impossibleOptionTypes.Add(TcpOptionType.ConnectionCountEcho);
} }
if (maximumOptionLength < TcpOptionAlternateChecksumRequest.OptionLength)
impossibleOptionTypes.Add(TcpOptionType.AlternateChecksumRequest);
if (maximumOptionLength < TcpOptionAlternateChecksumData.OptionMinimumLength)
impossibleOptionTypes.Add(TcpOptionType.AlternateChecksumData);
impossibleOptionTypes.Add(TcpOptionType.AlternateChecksumData);
impossibleOptionTypes.Add(TcpOptionType.AlternateChecksumRequest);
impossibleOptionTypes.Add(TcpOptionType.Md5Signature); impossibleOptionTypes.Add(TcpOptionType.Md5Signature);
impossibleOptionTypes.Add(TcpOptionType.QuickStartResponse); impossibleOptionTypes.Add(TcpOptionType.QuickStartResponse);
impossibleOptionTypes.Add(TcpOptionType.UserTimeout); impossibleOptionTypes.Add(TcpOptionType.UserTimeout);
...@@ -355,6 +357,12 @@ namespace PcapDotNet.Packets.TestUtils ...@@ -355,6 +357,12 @@ namespace PcapDotNet.Packets.TestUtils
case TcpOptionType.ConnectionCountNew: case TcpOptionType.ConnectionCountNew:
return new TcpOptionConnectionCountNew(random.NextUInt()); return new TcpOptionConnectionCountNew(random.NextUInt());
case TcpOptionType.AlternateChecksumRequest:
return new TcpOptionAlternateChecksumRequest(random.NextEnum<TcpOptionAlternateChecksumType>());
case TcpOptionType.AlternateChecksumData:
return new TcpOptionAlternateChecksumData(random.NextBytes(random.Next(maximumOptionLength - TcpOptionAlternateChecksumData.OptionMinimumLength + 1)));
default: default:
throw new InvalidOperationException("optionType = " + optionType); throw new InvalidOperationException("optionType = " + optionType);
} }
......
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using PcapDotNet.Base; using PcapDotNet.Base;
...@@ -37,6 +38,20 @@ namespace PcapDotNet.Packets ...@@ -37,6 +38,20 @@ namespace PcapDotNet.Packets
return result; return result;
} }
public static byte[] ReadBytes(this byte[] buffer, int offset, int length)
{
byte[] bytes = new byte[length];
buffer.BlockCopy(offset, bytes, 0, length);
return bytes;
}
public static byte[] ReadBytes(this byte[] buffer, ref int offset, int length)
{
byte[] result = buffer.ReadBytes(offset, length);
offset += length;
return result;
}
/// <summary> /// <summary>
/// Reads 2 bytes from a specific offset as a short with a given endianity. /// Reads 2 bytes from a specific offset as a short with a given endianity.
/// </summary> /// </summary>
...@@ -254,6 +269,17 @@ namespace PcapDotNet.Packets ...@@ -254,6 +269,17 @@ namespace PcapDotNet.Packets
offset += sizeof(byte); offset += sizeof(byte);
} }
public static void Write(this byte[] buffer, int offset, IEnumerable<byte> value)
{
buffer.Write(ref offset, value);
}
public static void Write(this byte[] buffer, ref int offset, IEnumerable<byte> value)
{
foreach (byte b in value)
buffer.Write(offset++, b);
}
/// <summary> /// <summary>
/// Writes the given value to the buffer using the given endianity. /// Writes the given value to the buffer using the given endianity.
/// </summary> /// </summary>
......
...@@ -111,6 +111,9 @@ ...@@ -111,6 +111,9 @@
<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\TcpOption.cs" />
<Compile Include="Transport\TcpOptionAlternateChecksumData.cs" />
<Compile Include="Transport\TcpOptionAlternateChecksumRequest.cs" />
<Compile Include="Transport\TcpOptionAlternateChecksumType.cs" />
<Compile Include="Transport\TcpOptionComplex.cs" /> <Compile Include="Transport\TcpOptionComplex.cs" />
<Compile Include="Transport\TcpOptionConnectionCount.cs" /> <Compile Include="Transport\TcpOptionConnectionCount.cs" />
<Compile Include="Transport\TcpOptionConnectionCountBase.cs" /> <Compile Include="Transport\TcpOptionConnectionCountBase.cs" />
......
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
namespace PcapDotNet.Packets.Transport
{
/// <summary>
/// TCP Alternate Checksum Data Option (RFC 1146).
///
/// The format of the TCP Alternate Checksum Data Option is:
/// +---------+---------+---------+ +---------+
/// | Kind=15 |Length=N | data | ... | data |
/// +---------+---------+---------+ +---------+
///
/// This field is used only when the alternate checksum that is negotiated is longer than 16 bits.
/// These checksums will not fit in the checksum field of the TCP header and thus at least part of them must be put in an option.
/// Whether the checksum is split between the checksum field in the TCP header and the option or the entire checksum is placed in the option
/// is determined on a checksum by checksum basis.
///
/// The length of this option will depend on the choice of alternate checksum algorithm for this connection.
///
/// While computing the alternate checksum, the TCP checksum field and the data portion TCP Alternate Checksum Data Option are replaced with zeros.
/// </summary>
[OptionTypeRegistration(typeof(TcpOptionType), TcpOptionType.AlternateChecksumData)]
public class TcpOptionAlternateChecksumData : TcpOptionComplex, IOptionComplexFactory, IEquatable<TcpOptionAlternateChecksumData>
{
/// <summary>
/// The minimum number of bytes this option take.
/// </summary>
public const int OptionMinimumLength = OptionHeaderLength;
public const int OptionValueMinimumLength = OptionMinimumLength - OptionHeaderLength;
public TcpOptionAlternateChecksumData(IList<byte> data)
: base(TcpOptionType.AlternateChecksumData)
{
Data = new ReadOnlyCollection<byte>(data);
}
public TcpOptionAlternateChecksumData()
: this(new byte[0])
{
}
public ReadOnlyCollection<byte> Data { get; private set; }
/// <summary>
/// The number of bytes this option will take.
/// </summary>
public override int Length
{
get { return OptionMinimumLength + Data.Count; }
}
/// <summary>
/// True iff this option may appear at most once in a datagram.
/// </summary>
public override bool IsAppearsAtMostOnce
{
get { return true; }
}
public bool Equals(TcpOptionAlternateChecksumData other)
{
if (other == null)
return false;
return Data.SequenceEqual(other.Data);
}
public override bool Equals(TcpOption other)
{
return Equals(other as TcpOptionAlternateChecksumData);
}
public override int GetHashCode()
{
return base.GetHashCode() ^
Data.GetHashCode();
}
/// <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 < OptionValueMinimumLength)
return null;
byte[] data = buffer.ReadBytes(ref offset, valueLength);
return new TcpOptionAlternateChecksumData(data);
}
internal override void Write(byte[] buffer, ref int offset)
{
base.Write(buffer, ref offset);
buffer.Write(ref offset, Data);
}
}
}
\ No newline at end of file
using System;
namespace PcapDotNet.Packets.Transport
{
/// <summary>
/// TCP Alternate Checksum Request Option (RFC 1146).
/// +----------+----------+----------+
/// | Kind=14 | Length=3 | chksum |
/// +----------+----------+----------+
///
/// Here chksum is a number identifying the type of checksum to be used.
///
/// The currently defined values of chksum are:
/// 0 -- TCP checksum.
/// 1 -- 8-bit Fletcher's algorithm.
/// 2 -- 16-bit Fletcher's algorithm.
///
/// Note that the 8-bit Fletcher algorithm gives a 16-bit checksum and the 16-bit algorithm gives a 32-bit checksum.
/// </summary>
[OptionTypeRegistration(typeof(TcpOptionType), TcpOptionType.AlternateChecksumRequest)]
public class TcpOptionAlternateChecksumRequest : TcpOptionComplex, IOptionComplexFactory, IEquatable<TcpOptionAlternateChecksumRequest>
{
/// <summary>
/// The number of bytes this option take.
/// </summary>
public const int OptionLength = 3;
public const int OptionValueLength = OptionLength - OptionHeaderLength;
public TcpOptionAlternateChecksumRequest(TcpOptionAlternateChecksumType checksumType)
: base(TcpOptionType.AlternateChecksumRequest)
{
ChecksumType = checksumType;
}
public TcpOptionAlternateChecksumRequest()
: this(0)
{
}
public TcpOptionAlternateChecksumType ChecksumType { 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(TcpOptionAlternateChecksumRequest other)
{
if (other == null)
return false;
return ChecksumType == other.ChecksumType;
}
public override bool Equals(TcpOption other)
{
return Equals(other as TcpOptionAlternateChecksumRequest);
}
public override int GetHashCode()
{
return base.GetHashCode() ^
ChecksumType.GetHashCode();
}
/// <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;
byte checksumType = buffer.ReadByte(ref offset);
return new TcpOptionAlternateChecksumRequest((TcpOptionAlternateChecksumType)checksumType);
}
internal override void Write(byte[] buffer, ref int offset)
{
base.Write(buffer, ref offset);
buffer.Write(ref offset, (byte)ChecksumType);
}
}
}
\ No newline at end of file
namespace PcapDotNet.Packets.Transport
{
public enum TcpOptionAlternateChecksumType : byte
{
TcpChecksum = 0,
FletchersAlgorithm8Bit = 1,
FletchersAlgorithm16Bit = 2,
}
}
\ No newline at end of file
...@@ -71,18 +71,14 @@ namespace PcapDotNet.Packets.Transport ...@@ -71,18 +71,14 @@ namespace PcapDotNet.Packets.Transport
if (valueLength < OptionValueMinimumLength) if (valueLength < OptionValueMinimumLength)
return null; return null;
byte[] data = new byte[valueLength]; byte[] data = buffer.ReadBytes(ref offset, valueLength);
buffer.BlockCopy(offset, data, 0, valueLength);
offset += valueLength;
return new TcpOptionUnknown(optionType, data); return new TcpOptionUnknown(optionType, data);
} }
internal override void Write(byte[] buffer, ref int offset) internal override void Write(byte[] buffer, ref int offset)
{ {
base.Write(buffer, ref offset); base.Write(buffer, ref offset);
foreach (byte value in Data) buffer.Write(ref offset, Data);
buffer.Write(ref offset, value);
} }
} }
} }
\ No newline at end of file
...@@ -28,6 +28,13 @@ namespace PcapDotNet.TestUtils ...@@ -28,6 +28,13 @@ namespace PcapDotNet.TestUtils
return random.NextByte(byte.MaxValue + 1); return random.NextByte(byte.MaxValue + 1);
} }
public static byte[] NextBytes(this Random random, int length)
{
byte[] bytes = new byte[length];
random.NextBytes(bytes);
return bytes;
}
public static ushort NextUShort(this Random random, int maxValue) public static ushort NextUShort(this Random random, int maxValue)
{ {
return (ushort)random.Next(maxValue); return (ushort)random.Next(maxValue);
......
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