Commit 3d7eb78d authored by Brickner_cp's avatar Brickner_cp

Trace Route IpV4 option

parent 65e2570e
......@@ -34,6 +34,9 @@ namespace PcapDotNet.Core.Test
case IpV4OptionType.InternetTimestamp:
return "Time stamp" + (option.Length < 5 ? " (with option length = " + option.Length + " bytes; should be >= 5)" : ":");
case IpV4OptionType.TraceRoute:
return "Unknown (0x52) (12 bytes)";
default:
throw new InvalidOperationException("Illegal option type " + option.OptionType);
}
......
......@@ -308,7 +308,8 @@ namespace PcapDotNet.Core.Test
break;
}
IpV4Option option = options[currentOptionIndex++];
if (option.OptionType == IpV4OptionType.BasicSecurity)
if (option.OptionType == IpV4OptionType.BasicSecurity ||
option.OptionType == IpV4OptionType.TraceRoute)
{
Assert.IsTrue(field.Show().StartsWith(option.GetWiresharkString()));
continue; // Wireshark doesn't support
......
......@@ -104,6 +104,8 @@ namespace PcapDotNet.Packets.TestUtils
impossibleOptionTypes.Add(IpV4OptionType.StreamIdentifier);
if (maximumOptionLength < IpV4OptionTimestamp.OptionMinimumLength)
impossibleOptionTypes.Add(IpV4OptionType.InternetTimestamp);
if (maximumOptionLength < IpV4OptionTraceRoute.OptionLength)
impossibleOptionTypes.Add(IpV4OptionType.TraceRoute);
IpV4OptionType optionType = random.NextEnum<IpV4OptionType>(impossibleOptionTypes);
switch (optionType)
......@@ -185,6 +187,9 @@ namespace PcapDotNet.Packets.TestUtils
throw new InvalidOperationException("timestampType = " + timestampType);
}
case IpV4OptionType.TraceRoute:
return new IpV4OptionTraceRoute(random.NextUShort(), random.NextUShort(), random.NextUShort(), random.NextIpV4Address());
default:
throw new InvalidOperationException("optionType = " + optionType);
}
......
......@@ -115,6 +115,7 @@ namespace PcapDotNet.Packets.IpV4
case IpV4OptionType.RecordRoute:
case IpV4OptionType.StreamIdentifier:
case IpV4OptionType.InternetTimestamp:
case IpV4OptionType.TraceRoute:
return IpV4OptionComplex.ReadOptionComplex(optionType, buffer, ref offset, offsetEnd - offset);
default:
......
......@@ -110,7 +110,7 @@ namespace PcapDotNet.Packets.IpV4
}
/// <summary>
/// Two security options are equal iff they have the exam same field values.
/// Two security options are equal iff they have the exact same field values.
/// </summary>
public bool Equals(IpV4OptionBasicSecurity other)
{
......@@ -123,7 +123,7 @@ namespace PcapDotNet.Packets.IpV4
}
/// <summary>
/// Two security options are equal iff they have the exam same field values.
/// Two security options are equal iff they have the exact same field values.
/// </summary>
public override bool Equals(IpV4Option other)
{
......@@ -179,7 +179,6 @@ namespace PcapDotNet.Packets.IpV4
internal override void Write(byte[] buffer, ref int offset)
{
base.Write(buffer, ref offset);
buffer[offset++] = (byte)Length;
buffer[offset++] = (byte)ClassificationLevel;
int protectionAuthorityLength = Length - OptionMinimumLength;
......
......@@ -41,12 +41,21 @@ namespace PcapDotNet.Packets.IpV4
case IpV4OptionType.InternetTimestamp:
return IpV4OptionTimestamp.ReadOptionTimestamp(buffer, ref offset, optionValueLength);
case IpV4OptionType.TraceRoute:
return IpV4OptionTraceRoute.ReadOptionTraceRoute(buffer, ref offset, optionValueLength);
default:
return null;
}
}
internal override void Write(byte[] buffer, ref int offset)
{
base.Write(buffer, ref offset);
buffer[offset++] = (byte)Length;
}
/// <summary>
/// Constructs the option by type.
/// </summary>
......
......@@ -92,7 +92,6 @@ namespace PcapDotNet.Packets.IpV4
internal override void Write(byte[] buffer, ref int offset)
{
base.Write(buffer, ref offset);
buffer[offset++] = (byte)Length;
buffer[offset++] = (byte)(OptionMinimumLength + 1 + PointedAddressIndex * 4);
foreach (IpV4Address address in Route)
buffer.Write(ref offset, address, Endianity.Big);
......
......@@ -99,7 +99,6 @@ namespace PcapDotNet.Packets.IpV4
internal override void Write(byte[] buffer, ref int offset)
{
base.Write(buffer, ref offset);
buffer[offset++] = (byte)Length;
buffer.Write(ref offset, Identifier, Endianity.Big);
}
......
......@@ -188,7 +188,6 @@ namespace PcapDotNet.Packets.IpV4
internal override void Write(byte[] buffer, ref int offset)
{
base.Write(buffer, ref offset);
buffer[offset++] = (byte)Length;
buffer[offset++] = (byte)(OptionMinimumLength + 1 + PointedIndex * 4);
buffer[offset++] = (byte)(((byte)(Overflow << 4)) | (byte)TimestampType);
WriteValues(buffer, ref offset);
......
using System;
namespace PcapDotNet.Packets.IpV4
{
/// <summary>
/// The presence of this option in an ICMP Echo (or any other) packet, hereinafter referred to as the Outbound Packet,
/// will cause a router to send the newly defined ICMP Traceroute message to the originator of the Outbound Packet.
/// In this way, the path of the Outbound Packet will be logged by the originator with only n+1 (instead of 2n) packets.
/// This algorithm does not suffer from a changing path and allows the response to the Outbound Packet,
/// hereinafter refered to as the Return Packet, to be traced
/// (provided the Outbound Packet's destination preserves the IP Traceroute option in the Return Packet).
///
/// IP Traceroute option format
/// 0 8 16 24
/// +-+---+---------+---------------+-------------------------------+
/// |F| C | Number | Length | ID Number |
/// +-+---+-------------------------+-------------------------------+
/// | Outbound Hop Count | Return Hop Count |
/// +-------------------------------+-------------------------------+
/// | Originator IP Address |
/// +---------------------------------------------------------------+
///
/// F (copy to fragments): 0 (do not copy to fragments)
/// C (class): 2 (Debugging & Measurement)
/// Number: 18 (F+C+Number = 82)
/// </summary>
public class IpV4OptionTraceRoute : IpV4OptionComplex, IEquatable<IpV4OptionTraceRoute>
{
/// <summary>
/// The number of bytes this option take.
/// </summary>
public const int OptionLength = 12;
/// <summary>
/// The number of bytes this option's value take.
/// </summary>
public const int OptionValueLength = OptionLength - OptionHeaderLength;
/// <summary>
/// Create the trace route option from the trace route option values.
/// </summary>
/// <param name="identification">
/// An arbitrary number used by the originator of the Outbound Packet to identify the ICMP Traceroute messages.
/// It is NOT related to the ID number in the IP header.
/// </param>
/// <param name="outboundHopCount">
/// Outbound Hop Count (OHC)
/// The number of routers through which the Outbound Packet has passed.
/// This field is not incremented by the Outbound Packet's destination.
/// </param>
/// <param name="returnHopCount"></param>
/// Return Hop Count (RHC)
/// The number of routers through which the Return Packet has passed.
/// This field is not incremented by the Return Packet's destination.
/// <param name="originatorIpAddress">
/// The IP address of the originator of the Outbound Packet.
/// This isneeded so the routers know where to send the ICMP Traceroute message for Return Packets.
/// It is also needed for Outbound Packets which have a Source Route option.
/// </param>
public IpV4OptionTraceRoute(ushort identification, ushort outboundHopCount, ushort returnHopCount, IpV4Address originatorIpAddress)
: base(IpV4OptionType.TraceRoute)
{
_identification = identification;
_outboundHopCount = outboundHopCount;
_returnHopCount = returnHopCount;
_originatorIpAddress = originatorIpAddress;
}
/// <summary>
/// An arbitrary number used by the originator of the Outbound Packet to identify the ICMP Traceroute messages.
/// It is NOT related to the ID number in the IP header.
/// </summary>
public ushort Identification
{
get { return _identification; }
}
/// <summary>
/// The IP address of the originator of the Outbound Packet.
/// This isneeded so the routers know where to send the ICMP Traceroute message for Return Packets.
/// It is also needed for Outbound Packets which have a Source Route option.
/// </summary>
public IpV4Address OriginatorIpAddress
{
get { return _originatorIpAddress; }
}
/// <summary>
/// Outbound Hop Count (OHC)
/// The number of routers through which the Outbound Packet has passed.
/// This field is not incremented by the Outbound Packet's destination.
/// </summary>
public ushort OutboundHopCount
{
get { return _outboundHopCount; }
}
/// <summary>
/// Return Hop Count (RHC)
/// The number of routers through which the Return Packet has passed.
/// This field is not incremented by the Return Packet's destination.
/// /// </summary>
public ushort ReturnHopCount
{
get { return _returnHopCount; }
}
/// <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; }
}
/// <summary>
/// Two trace route options are equal iff they have the exact same field values.
/// </summary>
public bool Equals(IpV4OptionTraceRoute other)
{
if (other == null)
return false;
return Identification == other.Identification &&
OutboundHopCount == other.OutboundHopCount &&
ReturnHopCount == other.ReturnHopCount &&
OriginatorIpAddress == other.OriginatorIpAddress;
}
/// <summary>
/// Two trace route options are equal iff they have the exact same field values.
/// </summary>
public override bool Equals(IpV4Option other)
{
return Equals(other as IpV4OptionTraceRoute);
}
/// <summary>
/// The hash code is the xor of the base class hash code with the following values hash code:
/// The identification, the combination of the outbound and return hop count, the originator address.
/// </summary>
public override int GetHashCode()
{
return base.GetHashCode() ^
Identification.GetHashCode() ^
((OutboundHopCount << 16) | (ReturnHopCount << 16)).GetHashCode() ^
OriginatorIpAddress.GetHashCode();
}
internal static IpV4OptionTraceRoute ReadOptionTraceRoute(byte[] buffer, ref int offset, byte valueLength)
{
if (valueLength != OptionValueLength)
return null;
ushort identification = buffer.ReadUShort(ref offset, Endianity.Big);
ushort outboundHopCount = buffer.ReadUShort(ref offset, Endianity.Big);
ushort returnHopCount = buffer.ReadUShort(ref offset, Endianity.Big);
IpV4Address originatorIpAddress = buffer.ReadIpV4Address(ref offset, Endianity.Big);
return new IpV4OptionTraceRoute(identification, outboundHopCount, returnHopCount, originatorIpAddress);
}
internal override void Write(byte[] buffer, ref int offset)
{
base.Write(buffer, ref offset);
buffer.Write(ref offset, Identification, Endianity.Big);
buffer.Write(ref offset, OutboundHopCount, Endianity.Big);
buffer.Write(ref offset, ReturnHopCount, Endianity.Big);
buffer.Write(ref offset, OriginatorIpAddress, Endianity.Big);
}
private readonly ushort _identification;
private readonly ushort _outboundHopCount;
private readonly ushort _returnHopCount;
private readonly IpV4Address _originatorIpAddress;
}
}
\ No newline at end of file
......@@ -33,6 +33,12 @@ namespace PcapDotNet.Packets.IpV4
/// </summary>
NoOperation = 1,
/// <summary>
/// Traceroute Using an IP Option.
/// RFC 1393.
/// </summary>
TraceRoute = 82,
/// <summary>
/// DoD Basic Security:
/// Used to carry the classification level and protection authority flags.
......
......@@ -90,6 +90,7 @@
<Compile Include="IpV4\IpV4OptionTimestampAndAddress.cs" />
<Compile Include="IpV4\IpV4OptionTimestampOnly.cs" />
<Compile Include="IpV4\IpV4OptionTimestampType.cs" />
<Compile Include="IpV4\IpV4OptionTraceRoute.cs" />
<Compile Include="IpV4\IpV4OptionType.cs" />
<Compile Include="IpV4\IpV4Protocol.cs" />
<Compile Include="MoreByteArray.cs" />
......
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