Commit 2e45fef3 authored by Brickner_cp's avatar Brickner_cp

Code Analysis and Documentation - 8 warnings left.

parent 8aeae762
...@@ -11,6 +11,13 @@ namespace PcapDotNet.Core.Extensions ...@@ -11,6 +11,13 @@ namespace PcapDotNet.Core.Extensions
/// </summary> /// </summary>
public static class LivePacketDeviceExtensions public static class LivePacketDeviceExtensions
{ {
/// <summary>
/// Returns the network interface of the packet device.
/// The interface is found using its id.
/// If no interface is found, null is returned.
/// </summary>
/// <param name="livePacketDevice">The LivePacketDevice to look for a matching network interface for.</param>
/// <returns>The network interface found according to the given device or null if none is found.</returns>
public static NetworkInterface GetNetworkInterface(this LivePacketDevice livePacketDevice) public static NetworkInterface GetNetworkInterface(this LivePacketDevice livePacketDevice)
{ {
foreach (NetworkInterface networkInterface in NetworkInterface.GetAllNetworkInterfaces()) foreach (NetworkInterface networkInterface in NetworkInterface.GetAllNetworkInterfaces())
...@@ -22,6 +29,12 @@ namespace PcapDotNet.Core.Extensions ...@@ -22,6 +29,12 @@ namespace PcapDotNet.Core.Extensions
return null; return null;
} }
/// <summary>
/// Returns the MacAddress of the network interface of the given device.
/// If no interface matches the given packet device, an exception is thrown.
/// </summary>
/// <param name="livePacketDevice">The packet device to look for the matching interface.</param>
/// <returns>The MacAddress of the given device's matching interface.</returns>
public static MacAddress GetMacAddress(this LivePacketDevice livePacketDevice) public static MacAddress GetMacAddress(this LivePacketDevice livePacketDevice)
{ {
NetworkInterface networkInterface = livePacketDevice.GetNetworkInterface(); NetworkInterface networkInterface = livePacketDevice.GetNetworkInterface();
......
...@@ -104,7 +104,7 @@ namespace PcapDotNet.Core.Test ...@@ -104,7 +104,7 @@ namespace PcapDotNet.Core.Test
TestReceiveSomePackets(NumPacketsToSend, NumPacketsToSend, int.MaxValue, PacketSize, false, PacketCommunicatorReceiveResult.Ok, NumPacketsToSend, 0, 0.02); TestReceiveSomePackets(NumPacketsToSend, NumPacketsToSend, int.MaxValue, PacketSize, false, PacketCommunicatorReceiveResult.Ok, NumPacketsToSend, 0, 0.02);
TestReceiveSomePackets(NumPacketsToSend, 0, int.MaxValue, PacketSize, false, PacketCommunicatorReceiveResult.Ok, NumPacketsToSend, 0, 0.02); TestReceiveSomePackets(NumPacketsToSend, 0, int.MaxValue, PacketSize, false, PacketCommunicatorReceiveResult.Ok, NumPacketsToSend, 0, 0.02);
TestReceiveSomePackets(NumPacketsToSend, -1, int.MaxValue, PacketSize, false, PacketCommunicatorReceiveResult.Ok, NumPacketsToSend, 0, 0.02); TestReceiveSomePackets(NumPacketsToSend, -1, int.MaxValue, PacketSize, false, PacketCommunicatorReceiveResult.Ok, NumPacketsToSend, 0, 0.02);
TestReceiveSomePackets(NumPacketsToSend, NumPacketsToSend + 1, int.MaxValue, PacketSize, false, PacketCommunicatorReceiveResult.Ok, NumPacketsToSend, 0, 0.02); TestReceiveSomePackets(NumPacketsToSend, NumPacketsToSend + 1, int.MaxValue, PacketSize, false, PacketCommunicatorReceiveResult.Ok, NumPacketsToSend, 0, 0.031);
// Test non blocking // Test non blocking
TestReceiveSomePackets(0, 0, int.MaxValue, PacketSize, true, PacketCommunicatorReceiveResult.Ok, 0, 0, 0.02); TestReceiveSomePackets(0, 0, int.MaxValue, PacketSize, true, PacketCommunicatorReceiveResult.Ok, 0, 0, 0.02);
......
...@@ -78,38 +78,38 @@ namespace PcapDotNet.Core.Test ...@@ -78,38 +78,38 @@ namespace PcapDotNet.Core.Test
} }
} }
[TestMethod] // [TestMethod]
public void Temp() // public void Temp()
{ // {
EthernetLayer ethernetLayer = new EthernetLayer // EthernetLayer ethernetLayer = new EthernetLayer
{ // {
Source = new MacAddress("00:01:02:03:04:05"), // Source = new MacAddress("00:01:02:03:04:05"),
Destination = new MacAddress("A0:A1:A2:A3:A4:A5") // Destination = new MacAddress("A0:A1:A2:A3:A4:A5")
}; // };
//
IpV4Layer ipV4Layer = new IpV4Layer // IpV4Layer ipV4Layer = new IpV4Layer
{ // {
Source = new IpV4Address("1.2.3.4"), // Source = new IpV4Address("1.2.3.4"),
Ttl = 128, // Ttl = 128,
}; // };
//
IcmpEchoLayer icmpLayer = new IcmpEchoLayer(); // IcmpEchoLayer icmpLayer = new IcmpEchoLayer();
//
PacketBuilder builder = new PacketBuilder(ethernetLayer, ipV4Layer, icmpLayer); // PacketBuilder builder = new PacketBuilder(ethernetLayer, ipV4Layer, icmpLayer);
//
List<Packet> packets = new List<Packet>(); // List<Packet> packets = new List<Packet>();
//
for (int i = 0; i != 100; ++i) // for (int i = 0; i != 100; ++i)
{ // {
ipV4Layer.Destination = new IpV4Address("2.3.4." + i); // ipV4Layer.Destination = new IpV4Address("2.3.4." + i);
ipV4Layer.Identification = (ushort)i; // ipV4Layer.Identification = (ushort)i;
icmpLayer.SequenceNumber = (ushort)i; // icmpLayer.SequenceNumber = (ushort)i;
icmpLayer.Identifier = (ushort)i; // icmpLayer.Identifier = (ushort)i;
//
packets.Add(builder.Build(DateTime.Now)); // packets.Add(builder.Build(DateTime.Now));
} // }
//
PacketDumpFile.Dump(@"c:\users\boaz\temp.pcap", new PcapDataLink(DataLinkKind.Ethernet), int.MaxValue, packets); // PacketDumpFile.Dump(@"c:\users\boaz\temp.pcap", new PcapDataLink(DataLinkKind.Ethernet), int.MaxValue, packets);
} // }
} }
} }
\ No newline at end of file
...@@ -376,5 +376,20 @@ namespace PcapDotNet.Packets.Test ...@@ -376,5 +376,20 @@ namespace PcapDotNet.Packets.Test
}); });
Assert.IsNull(packet); Assert.IsNull(packet);
} }
[TestMethod]
public void DifferentIgmpSimpleLayersTest()
{
IgmpSimpleLayer layer1 = new IgmpQueryVersion1Layer
{
GroupAddress = new IpV4Address("1.2.3.4")
};
IgmpSimpleLayer layer2 = new IgmpQueryVersion2Layer
{
GroupAddress = new IpV4Address("1.2.3.4"),
MaxResponseTime = TimeSpan.FromMinutes(55)
};
Assert.IsFalse(layer1.Equals(layer2));
}
} }
} }
\ No newline at end of file
...@@ -596,6 +596,17 @@ namespace PcapDotNet.Packets.Test ...@@ -596,6 +596,17 @@ namespace PcapDotNet.Packets.Test
Assert.IsNull(packet); Assert.IsNull(packet);
} }
[TestMethod]
public void IpV4LayerNullChecksumAndProtocolGetHashCodeTest()
{
IpV4Layer layer = new IpV4Layer
{
HeaderChecksum = null,
Protocol = null,
};
Assert.IsNotNull(layer.GetHashCode());
}
private static Packet HexToPacket(string hexString, DataLinkKind dataLinkKind) private static Packet HexToPacket(string hexString, DataLinkKind dataLinkKind)
{ {
return Packet.FromHexadecimalString(hexString, DateTime.MinValue, dataLinkKind); return Packet.FromHexadecimalString(hexString, DateTime.MinValue, dataLinkKind);
......
...@@ -132,11 +132,20 @@ namespace PcapDotNet.Packets.Arp ...@@ -132,11 +132,20 @@ namespace PcapDotNet.Packets.Arp
TargetProtocolAddress.SequenceEqual(other.TargetProtocolAddress); TargetProtocolAddress.SequenceEqual(other.TargetProtocolAddress);
} }
/// <summary>
/// True iff the two ARP layers have equal protocol type, operation and addresses.
/// </summary>
/// <param name="other">The ARP layer to compare the layer to.</param>
/// <returns>True iff the two layers are equal.</returns>
public override sealed bool Equals(Layer other) public override sealed bool Equals(Layer other)
{ {
return base.Equals(other) && Equals(other as ArpLayer); return Equals(other as ArpLayer);
} }
/// <summary>
/// Returns a hash code for the layer.
/// The hash code is a XOR of a combination of the protocol type and operation and the hash codes of the layer length and data link.
/// </summary>
public override int GetHashCode() public override int GetHashCode()
{ {
return base.GetHashCode() ^ return base.GetHashCode() ^
......
...@@ -90,23 +90,37 @@ namespace PcapDotNet.Packets.Ethernet ...@@ -90,23 +90,37 @@ namespace PcapDotNet.Packets.Ethernet
get { return ArpHardwareType.Ethernet; } get { return ArpHardwareType.Ethernet; }
} }
/// <summary>
/// Two Ethernet layers are equal if they have the same source, destination and ethernet type.
/// </summary>
public bool Equals(EthernetLayer other) public bool Equals(EthernetLayer other)
{ {
return other != null && return other != null &&
Source == other.Source && Destination == other.Destination && EtherType == other.EtherType; Source == other.Source && Destination == other.Destination && EtherType == other.EtherType;
} }
/// <summary>
/// Two Ethernet layers are equal if they have the same source, destination and ethernet type.
/// </summary>
public override sealed bool Equals(Layer other) public override sealed bool Equals(Layer other)
{ {
return base.Equals(other) && Equals(other as EthernetLayer); return Equals(other as EthernetLayer);
} }
/// <summary>
/// Returns a hash code for the layer.
/// The hash code is a XOR of the hash codes of the layer length, data link, source and destination addresses and the ethernet type.
/// </summary>
public override int GetHashCode() public override int GetHashCode()
{ {
return base.GetHashCode() ^ return base.GetHashCode() ^
Source.GetHashCode() ^ Destination.GetHashCode() ^ EtherType.GetHashCode(); Source.GetHashCode() ^ Destination.GetHashCode() ^ EtherType.GetHashCode();
} }
/// <summary>
/// Contains the source, destination and ether type.
/// </summary>
/// <returns></returns>
public override string ToString() public override string ToString()
{ {
return Source + " -> " + Destination + " (" + EtherType + ")"; return Source + " -> " + Destination + " (" + EtherType + ")";
......
...@@ -61,6 +61,9 @@ namespace PcapDotNet.Packets.Icmp ...@@ -61,6 +61,9 @@ namespace PcapDotNet.Packets.Icmp
}; };
} }
/// <summary>
/// ICMP is valid if the datagram's length is OK, the checksum is correct and the code is in the expected range.
/// </summary>
protected override bool CalculateIsValid() protected override bool CalculateIsValid()
{ {
return base.CalculateIsValid() && Length == DatagramLength; return base.CalculateIsValid() && Length == DatagramLength;
......
...@@ -42,20 +42,19 @@ namespace PcapDotNet.Packets.Icmp ...@@ -42,20 +42,19 @@ namespace PcapDotNet.Packets.Icmp
} }
/// <summary> /// <summary>
/// Two ICMP Address Mask Request layers are equal if they have the same sequence number, identifier and address mask. /// True iff the address mask is equal to the other address mask.
/// </summary> /// </summary>
public bool Equals(IcmpAddressMaskRequestLayer other) protected override bool EqualPayload(IcmpLayer other)
{ {
return other != null && return EqualPayload(other as IcmpAddressMaskRequestLayer);
AddressMask == other.AddressMask;
} }
/// <summary> /// <summary>
/// Two ICMP Address Mask Request layers are equal if they have the same sequence number, identifier and address mask. /// True iff the address mask is equal to the other address mask.
/// </summary> /// </summary>
public override sealed bool Equals(IcmpLayer other) private bool EqualPayload(IcmpAddressMaskRequestLayer other)
{ {
return base.Equals(other) && Equals(other as IcmpAddressMaskRequestLayer); return other != null && AddressMask.Equals(other.AddressMask);
} }
} }
} }
\ No newline at end of file
...@@ -55,6 +55,11 @@ namespace PcapDotNet.Packets.Icmp ...@@ -55,6 +55,11 @@ namespace PcapDotNet.Packets.Icmp
}; };
} }
/// <summary>
/// Valid if the datagram's length is OK, the checksum is correct, the code is in the expected range
/// and the IPv4 payload contains at least an IPv4 header and the transport header.
/// If the code is for unsupported transport protocol, the IPv4 payload should contain 256 bytes of the original datagram.
/// </summary>
protected override bool CalculateIsValid() protected override bool CalculateIsValid()
{ {
if (!base.CalculateIsValid()) if (!base.CalculateIsValid())
......
...@@ -95,6 +95,10 @@ namespace PcapDotNet.Packets.Icmp ...@@ -95,6 +95,10 @@ namespace PcapDotNet.Packets.Icmp
/// </summary> /// </summary>
public override abstract ILayer ExtractLayer(); public override abstract ILayer ExtractLayer();
/// <summary>
/// The payload of the ICMP.
/// All the data without the header.
/// </summary>
public Datagram Payload public Datagram Payload
{ {
get get
...@@ -163,9 +167,13 @@ namespace PcapDotNet.Packets.Icmp ...@@ -163,9 +167,13 @@ namespace PcapDotNet.Packets.Icmp
return Sum16BitsToChecksum(sum); return Sum16BitsToChecksum(sum);
} }
private bool? _isChecksumCorrect; /// <summary>
private Datagram _payload; /// Creates an IcmpDatagram from a buffer according to the message type.
/// </summary>
/// <param name="buffer">The buffer of the datagram.</param>
/// <param name="offset">The offset where the datagram starts.</param>
/// <param name="length">The length of the datagram in the buffer.</param>
/// <returns>An IcmpDatagram according to the Icmp message type.</returns>
public static IcmpDatagram CreateDatagram(byte[] buffer, int offset, int length) public static IcmpDatagram CreateDatagram(byte[] buffer, int offset, int length)
{ {
if (length <= Offset.Type) if (length <= Offset.Type)
...@@ -236,5 +244,8 @@ namespace PcapDotNet.Packets.Icmp ...@@ -236,5 +244,8 @@ namespace PcapDotNet.Packets.Icmp
return new IcmpUnknownDatagram(buffer, offset, length); return new IcmpUnknownDatagram(buffer, offset, length);
} }
} }
private bool? _isChecksumCorrect;
private Datagram _payload;
} }
} }
\ No newline at end of file
...@@ -21,6 +21,11 @@ namespace PcapDotNet.Packets.Icmp ...@@ -21,6 +21,11 @@ namespace PcapDotNet.Packets.Icmp
/// </summary> /// </summary>
public class IcmpDestinationUnreachableDatagram : IcmpIpV4HeaderPlus64BitsPayloadDatagram public class IcmpDestinationUnreachableDatagram : IcmpIpV4HeaderPlus64BitsPayloadDatagram
{ {
/// <summary>
/// The minimum value of the maximum transmission unit for FragmentationNeededAndDoNotFragmentSet code.
/// </summary>
public const ushort MinimumMaximumTransmissionUnit = 68;
private static class Offset private static class Offset
{ {
public const int NextHopMtu = 6; public const int NextHopMtu = 6;
...@@ -54,11 +59,20 @@ namespace PcapDotNet.Packets.Icmp ...@@ -54,11 +59,20 @@ namespace PcapDotNet.Packets.Icmp
}; };
} }
/// <summary>
/// Valid if the datagram's length is OK, the checksum is correct, the code is in the expected range,
/// the IPv4 payload contains at least an IPv4 header, the IPv4's payload is in the expected size
/// and if the NextHopMaximumTransmissionUnit is at least 68 for FragmentationNeededAndDoNotFragmentSet code or exactly 0 for other codes.
/// </summary>
protected override bool CalculateIsValid() protected override bool CalculateIsValid()
{ {
return base.CalculateIsValid() && if (!base.CalculateIsValid())
(((IcmpCodeDestinationUnreachable)Code == IcmpCodeDestinationUnreachable.FragmentationNeededAndDoNotFragmentSet) || return false;
NextHopMaximumTransmissionUnit == 0);
if ((IcmpCodeDestinationUnreachable)Code == IcmpCodeDestinationUnreachable.FragmentationNeededAndDoNotFragmentSet)
return NextHopMaximumTransmissionUnit >= MinimumMaximumTransmissionUnit;
return NextHopMaximumTransmissionUnit == 0;
} }
/// <summary> /// <summary>
......
...@@ -85,6 +85,14 @@ namespace PcapDotNet.Packets.Icmp ...@@ -85,6 +85,14 @@ namespace PcapDotNet.Packets.Icmp
{ {
} }
/// <summary>
/// Finalizes the layer data in the buffer.
/// Used for the ICMP checksum.
/// </summary>
/// <param name="buffer">The buffer to finalize the layer in.</param>
/// <param name="offset">The offset in the buffer the layer starts.</param>
/// <param name="payloadLength">The length of the layer's payload (the number of bytes after the layer in the packet).</param>
/// <param name="nextLayer">The layer that comes after this layer. null if this is the last layer.</param>
public override sealed void Finalize(byte[] buffer, int offset, int payloadLength, ILayer nextLayer) public override sealed void Finalize(byte[] buffer, int offset, int payloadLength, ILayer nextLayer)
{ {
IcmpDatagram.WriteChecksum(buffer, offset, Length + payloadLength, Checksum); IcmpDatagram.WriteChecksum(buffer, offset, Length + payloadLength, Checksum);
...@@ -98,28 +106,50 @@ namespace PcapDotNet.Packets.Icmp ...@@ -98,28 +106,50 @@ namespace PcapDotNet.Packets.Icmp
get { return IpV4Protocol.InternetControlMessageProtocol; } get { return IpV4Protocol.InternetControlMessageProtocol; }
} }
public virtual bool Equals(IcmpLayer other) /// <summary>
/// ICMP layers are equal if they have the same message type, code, checksum, variable and payload.
/// </summary>
public bool Equals(IcmpLayer other)
{ {
return other != null && return other != null &&
MessageType == other.MessageType && CodeValue == other.CodeValue && MessageType == other.MessageType && CodeValue == other.CodeValue &&
Checksum == other.Checksum && Checksum == other.Checksum &&
Variable == other.Variable; Variable == other.Variable &&
EqualPayload(other);
} }
/// <summary>
/// ICMP layers are equal if they have the same message type, code, checksum, variable and payload.
/// </summary>
public sealed override bool Equals(Layer other) public sealed override bool Equals(Layer other)
{ {
return base.Equals(other) && Equals(other as IcmpLayer); return Equals(other as IcmpLayer);
} }
/// <summary>
/// Returns a hash code for the layer.
/// The hash code is a XOR of the layer length, data link, message type and code, checksum and variable.
/// </summary>
public override int GetHashCode() public override int GetHashCode()
{ {
return base.GetHashCode() ^ return base.GetHashCode() ^
MessageTypeAndCode.GetHashCode() ^ Checksum.GetHashCode() ^ Variable.GetHashCode(); MessageTypeAndCode.GetHashCode() ^ Checksum.GetHashCode() ^ Variable.GetHashCode();
} }
/// <summary>
/// Returns a string containing the message type, code and variable.
/// </summary>
public override string ToString() public override string ToString()
{ {
return MessageType + "." + CodeValue + "(" + Variable + ")"; return MessageType + "." + CodeValue + "(" + Variable + ")";
} }
/// <summary>
/// True iff the ICMP payload is equal to the other ICMP payload.
/// </summary>
protected virtual bool EqualPayload(IcmpLayer other)
{
return true;
}
} }
} }
\ No newline at end of file
...@@ -51,6 +51,11 @@ namespace PcapDotNet.Packets.Icmp ...@@ -51,6 +51,11 @@ namespace PcapDotNet.Packets.Icmp
}; };
} }
/// <summary>
/// Valid if the datagram's length is OK, the checksum is correct, the code is in the expected range,
/// the IPv4 payload contains at least an IPv4 header, the IPv4's payload is in the expected size
/// and the pointer points to a byte within the IPv4 header.
/// </summary>
protected override bool CalculateIsValid() protected override bool CalculateIsValid()
{ {
return base.CalculateIsValid() && Pointer < IpV4.Length; return base.CalculateIsValid() && Pointer < IpV4.Length;
......
...@@ -41,6 +41,9 @@ namespace PcapDotNet.Packets.Icmp ...@@ -41,6 +41,9 @@ namespace PcapDotNet.Packets.Icmp
{ {
} }
/// <summary>
/// Creates a Layer that represents the datagram to be used with PacketBuilder.
/// </summary>
public override ILayer ExtractLayer() public override ILayer ExtractLayer()
{ {
return new IcmpRedirectLayer return new IcmpRedirectLayer
......
...@@ -114,6 +114,10 @@ namespace PcapDotNet.Packets.Icmp ...@@ -114,6 +114,10 @@ namespace PcapDotNet.Packets.Icmp
}; };
} }
/// <summary>
/// Valid if the datagram's length is OK, the checksum is correct, the code is in the expected range
/// and the address entry size is the default address entry size.
/// </summary>
protected override bool CalculateIsValid() protected override bool CalculateIsValid()
{ {
return base.CalculateIsValid() && return base.CalculateIsValid() &&
......
...@@ -54,6 +54,9 @@ namespace PcapDotNet.Packets.Icmp ...@@ -54,6 +54,9 @@ namespace PcapDotNet.Packets.Icmp
return Equals(obj as IcmpRouterAdvertisementEntry); return Equals(obj as IcmpRouterAdvertisementEntry);
} }
/// <summary>
/// A xor of the hash codes of the router address and preference.
/// </summary>
public override int GetHashCode() public override int GetHashCode()
{ {
return RouterAddress.GetHashCode() ^ RouterAddressPreference.GetHashCode(); return RouterAddress.GetHashCode() ^ RouterAddressPreference.GetHashCode();
......
...@@ -77,15 +77,21 @@ namespace PcapDotNet.Packets.Icmp ...@@ -77,15 +77,21 @@ namespace PcapDotNet.Packets.Icmp
IcmpRouterAdvertisementDatagram.WriteHeaderAdditional(buffer, offset, Entries); IcmpRouterAdvertisementDatagram.WriteHeaderAdditional(buffer, offset, Entries);
} }
public bool Equals(IcmpRouterAdvertisementLayer other) /// <summary>
/// True iff the Entries are equal to the other ICMP entries.
/// </summary>
protected override bool EqualPayload(IcmpLayer other)
{ {
return other != null && return EqualPayload(other as IcmpRouterAdvertisementLayer);
Entries.SequenceEqual(other.Entries);
} }
public sealed override bool Equals(IcmpLayer other) /// <summary>
/// True iff the Entries are equal to the other ICMP entries.
/// </summary>
private bool EqualPayload(IcmpRouterAdvertisementLayer other)
{ {
return base.Equals(other) && Equals(other as IcmpRouterAdvertisementLayer); return other != null &&
Entries.SequenceEqual(other.Entries);
} }
private readonly IList<IcmpRouterAdvertisementEntry> _entries; private readonly IList<IcmpRouterAdvertisementEntry> _entries;
......
...@@ -54,6 +54,10 @@ namespace PcapDotNet.Packets.Icmp ...@@ -54,6 +54,10 @@ namespace PcapDotNet.Packets.Icmp
}; };
} }
/// <summary>
/// Valid if the datagram's length is OK, the checksum is correct, the code is in the expected range,
/// the IPv4 payload contains at least an IPv4 header, the IPv4's payload is in the expected size and the Pointer points to a byte in the IPv4 payload.
/// </summary>
protected override bool CalculateIsValid() protected override bool CalculateIsValid()
{ {
return base.CalculateIsValid() && Pointer < IpV4.Length; return base.CalculateIsValid() && Pointer < IpV4.Length;
......
...@@ -85,6 +85,9 @@ namespace PcapDotNet.Packets.Icmp ...@@ -85,6 +85,9 @@ namespace PcapDotNet.Packets.Icmp
}; };
} }
/// <summary>
/// Valid if the datagram's length is OK, the checksum is correct and the code is in the expected range.
/// </summary>
protected override bool CalculateIsValid() protected override bool CalculateIsValid()
{ {
return base.CalculateIsValid() && Length == DatagramLength; return base.CalculateIsValid() && Length == DatagramLength;
......
...@@ -52,17 +52,23 @@ namespace PcapDotNet.Packets.Icmp ...@@ -52,17 +52,23 @@ namespace PcapDotNet.Packets.Icmp
OriginateTimestamp, ReceiveTimestamp, TransmitTimestamp); OriginateTimestamp, ReceiveTimestamp, TransmitTimestamp);
} }
public bool Equals(IcmpTimestampLayer other) /// <summary>
/// True iff the OriginateTimestamp, ReceiveTimestamp and the TransmitTimestamp fields are equal.
/// </summary>
protected override bool EqualPayload(IcmpLayer other)
{
return EqualPayload(other as IcmpTimestampLayer);
}
/// <summary>
/// True iff the OriginateTimestamp, ReceiveTimestamp and the TransmitTimestamp fields are equal.
/// </summary>
private bool EqualPayload(IcmpTimestampLayer other)
{ {
return other != null && return other != null &&
OriginateTimestamp == other.OriginateTimestamp && OriginateTimestamp == other.OriginateTimestamp &&
ReceiveTimestamp == other.ReceiveTimestamp && ReceiveTimestamp == other.ReceiveTimestamp &&
TransmitTimestamp == other.TransmitTimestamp; TransmitTimestamp == other.TransmitTimestamp;
} }
public sealed override bool Equals(IcmpLayer other)
{
return base.Equals(other) && Equals(other as IcmpTimestampLayer);
}
} }
} }
\ No newline at end of file
...@@ -98,6 +98,10 @@ namespace PcapDotNet.Packets.Icmp ...@@ -98,6 +98,10 @@ namespace PcapDotNet.Packets.Icmp
get { return ReadUInt(Offset.OutputLinkMtu, Endianity.Big); } get { return ReadUInt(Offset.OutputLinkMtu, Endianity.Big); }
} }
/// <summary>
/// Is the packet an Outbound packet.
/// This is indicated by a value of 0xFFFF in the ReturnHopCount field.
/// </summary>
public bool IsOutbound public bool IsOutbound
{ {
get { return ReturnHopCount == OutboundReturnHopCountValue; } get { return ReturnHopCount == OutboundReturnHopCountValue; }
...@@ -120,6 +124,9 @@ namespace PcapDotNet.Packets.Icmp ...@@ -120,6 +124,9 @@ namespace PcapDotNet.Packets.Icmp
}; };
} }
/// <summary>
/// Valid if the datagram's length is OK, the checksum is correct and the code is in the expected range.
/// </summary>
protected override bool CalculateIsValid() protected override bool CalculateIsValid()
{ {
return base.CalculateIsValid() && Length == DatagramLength; return base.CalculateIsValid() && Length == DatagramLength;
......
...@@ -87,7 +87,18 @@ namespace PcapDotNet.Packets.Icmp ...@@ -87,7 +87,18 @@ namespace PcapDotNet.Packets.Icmp
IcmpTraceRouteDatagram.WriteHeaderAdditional(buffer, offset, OutboundHopCount, ReturnHopCount, OutputLinkSpeed, OutputLinkMaximumTransmissionUnit); IcmpTraceRouteDatagram.WriteHeaderAdditional(buffer, offset, OutboundHopCount, ReturnHopCount, OutputLinkSpeed, OutputLinkMaximumTransmissionUnit);
} }
public bool Equals(IcmpTraceRouteLayer other) /// <summary>
/// True iff the OutboundHopCount, ReturnHopCount, OutputLinkSpeed and OutputLinkMaximumTransmissionUnit fields are equal to the other layer fields.
/// </summary>
protected override bool EqualPayload(IcmpLayer other)
{
return EqualPayload(other as IcmpTraceRouteLayer);
}
/// <summary>
/// True iff the OutboundHopCount, ReturnHopCount, OutputLinkSpeed and OutputLinkMaximumTransmissionUnit fields are equal to the other layer fields.
/// </summary>
private bool EqualPayload(IcmpTraceRouteLayer other)
{ {
return other != null && return other != null &&
OutboundHopCount == other.OutboundHopCount && OutboundHopCount == other.OutboundHopCount &&
...@@ -95,10 +106,5 @@ namespace PcapDotNet.Packets.Icmp ...@@ -95,10 +106,5 @@ namespace PcapDotNet.Packets.Icmp
OutputLinkSpeed == other.OutputLinkSpeed && OutputLinkSpeed == other.OutputLinkSpeed &&
OutputLinkMaximumTransmissionUnit == other.OutputLinkMaximumTransmissionUnit; OutputLinkMaximumTransmissionUnit == other.OutputLinkMaximumTransmissionUnit;
} }
public override sealed bool Equals(IcmpLayer other)
{
return base.Equals(other) && Equals(other as IcmpTraceRouteLayer);
}
} }
} }
\ No newline at end of file
...@@ -37,23 +37,43 @@ namespace PcapDotNet.Packets.Igmp ...@@ -37,23 +37,43 @@ namespace PcapDotNet.Packets.Igmp
get { return IpV4Protocol.InternetGroupManagementProtocol; } get { return IpV4Protocol.InternetGroupManagementProtocol; }
} }
public virtual bool Equals(IgmpLayer other) /// <summary>
/// IGMP layers are equal if they have the same message type, query version, similar max response time and the same specific type fields.
/// </summary>
public bool Equals(IgmpLayer other)
{ {
return other != null && return other != null &&
MessageType == other.MessageType && MessageType == other.MessageType &&
QueryVersion == other.QueryVersion && QueryVersion == other.QueryVersion &&
MaxResponseTimeValue.Divide(2) <= other.MaxResponseTimeValue && MaxResponseTimeValue.Multiply(2) >= other.MaxResponseTimeValue; EqualMaxResponseTime(MaxResponseTimeValue, other.MaxResponseTimeValue) &&
EqualFields(other);
} }
/// <summary>
/// IGMP layers are equal if they have the same message type, query version, similar max response time and the same specific type fields.
/// </summary>
public sealed override bool Equals(Layer other) public sealed override bool Equals(Layer other)
{ {
return base.Equals(other) && Equals(other as IgmpLayer); return Equals(other as IgmpLayer);
} }
/// <summary>
/// Xor of the hash codes of the layer length, datalink, message type and query version.
/// </summary>
public override int GetHashCode() public override int GetHashCode()
{ {
return base.GetHashCode() ^ return base.GetHashCode() ^
MessageType.GetHashCode() ^ QueryVersion.GetHashCode(); MessageType.GetHashCode() ^ QueryVersion.GetHashCode();
} }
/// <summary>
/// true iff the fields that are not mutual to all IGMP layers are equal.
/// </summary>
protected abstract bool EqualFields(IgmpLayer other);
private static bool EqualMaxResponseTime(TimeSpan value1, TimeSpan value2)
{
return value1.Divide(2) <= value2 && value1.Multiply(2) >= value2;
}
} }
} }
\ No newline at end of file
...@@ -115,21 +115,10 @@ namespace PcapDotNet.Packets.Igmp ...@@ -115,21 +115,10 @@ namespace PcapDotNet.Packets.Igmp
get { return MaxResponseTime; } get { return MaxResponseTime; }
} }
public bool Equals(IgmpQueryVersion3Layer other) /// <summary>
{ /// Xor of the combination of the IsSuppressRouterSideProcessing and QueryRobustnessVariable fields with
return other != null && /// the hash codes of the layer length, datalink, message type, query version, group address and all the source addresses.
GroupAddress == other.GroupAddress && /// </summary>
IsSuppressRouterSideProcessing == other.IsSuppressRouterSideProcessing &&
QueryRobustnessVariable == other.QueryRobustnessVariable &&
QueryInterval.Divide(2) <= other.QueryInterval && QueryInterval.Multiply(2) >= other.QueryInterval &&
SourceAddresses.SequenceEqual(other.SourceAddresses);
}
public override sealed bool Equals(IgmpLayer other)
{
return base.Equals(other) && Equals(other as IgmpQueryVersion3Layer);
}
public override int GetHashCode() public override int GetHashCode()
{ {
return base.GetHashCode() ^ return base.GetHashCode() ^
...@@ -139,6 +128,29 @@ namespace PcapDotNet.Packets.Igmp ...@@ -139,6 +128,29 @@ namespace PcapDotNet.Packets.Igmp
} }
/// <summary>
/// true iff the GroupAddress, IsSuppressRouterSideProcessing, QueryRobustnessVariable and SourceAddresses fields are equal
/// and the QueryInterval is similar.
/// </summary>
protected override bool EqualFields(IgmpLayer other)
{
return EqualFields(other as IgmpQueryVersion3Layer);
}
/// <summary>
/// true iff the GroupAddress, IsSuppressRouterSideProcessing, QueryRobustnessVariable and SourceAddresses fields are equal
/// and the QueryInterval is similar.
/// </summary>
private bool EqualFields(IgmpQueryVersion3Layer other)
{
return other != null &&
GroupAddress == other.GroupAddress &&
IsSuppressRouterSideProcessing == other.IsSuppressRouterSideProcessing &&
QueryRobustnessVariable == other.QueryRobustnessVariable &&
QueryInterval.Divide(2) <= other.QueryInterval && QueryInterval.Multiply(2) >= other.QueryInterval &&
SourceAddresses.SequenceEqual(other.SourceAddresses);
}
private readonly IList<IpV4Address> _sourceAddresses; private readonly IList<IpV4Address> _sourceAddresses;
} }
} }
\ No newline at end of file
...@@ -75,23 +75,32 @@ namespace PcapDotNet.Packets.Igmp ...@@ -75,23 +75,32 @@ namespace PcapDotNet.Packets.Igmp
get { return TimeSpan.Zero; } get { return TimeSpan.Zero; }
} }
public bool Equals(IgmpReportVersion3Layer other) /// <summary>
/// Xor of the hash codes of the layer length, datalink, message type, query version and the group records.
/// </summary>
public override int GetHashCode()
{ {
return other != null && return base.GetHashCode() ^
GroupRecords.SequenceEqual(other.GroupRecords); GroupRecords.SequenceGetHashCode();
} }
public sealed override bool Equals(IgmpLayer other) /// <summary>
/// true iff the group records are equal.
/// </summary>
protected override bool EqualFields(IgmpLayer other)
{ {
return base.Equals(other) && Equals(other as IgmpReportVersion3Layer); return EqualFields(other as IgmpReportVersion3Layer);
} }
public override int GetHashCode() /// <summary>
/// true iff the group records are equal.
/// </summary>
private bool EqualFields(IgmpReportVersion3Layer other)
{ {
return base.GetHashCode() ^ return other != null &&
GroupRecords.SequenceGetHashCode(); GroupRecords.SequenceEqual(other.GroupRecords);
} }
private readonly IList<IgmpGroupRecord> _groupRecords; private readonly IList<IgmpGroupRecord> _groupRecords;
} }
} }
\ No newline at end of file
...@@ -37,21 +37,30 @@ namespace PcapDotNet.Packets.Igmp ...@@ -37,21 +37,30 @@ namespace PcapDotNet.Packets.Igmp
MessageType, MaxResponseTimeValue, GroupAddress); MessageType, MaxResponseTimeValue, GroupAddress);
} }
public bool Equals(IgmpSimpleLayer other) /// <summary>
/// Xor of the hash codes of the layer length, datalink, message type, query version and group address.
/// </summary>
public override sealed int GetHashCode()
{ {
return other != null && return base.GetHashCode() ^
GroupAddress == other.GroupAddress; GroupAddress.GetHashCode();
} }
public override sealed bool Equals(IgmpLayer other) /// <summary>
/// true iff the the group address is equal.
/// </summary>
protected override sealed bool EqualFields(IgmpLayer other)
{ {
return base.Equals(other) && Equals(other as IgmpSimpleLayer); return EqualFields(other as IgmpSimpleLayer);
} }
public override int GetHashCode() /// <summary>
/// true iff the the group address is equal.
/// </summary>
private bool EqualFields(IgmpSimpleLayer other)
{ {
return base.GetHashCode() ^ return other != null &&
GroupAddress.GetHashCode(); GroupAddress == other.GroupAddress;
} }
} }
} }
\ No newline at end of file
...@@ -234,6 +234,9 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -234,6 +234,9 @@ namespace PcapDotNet.Packets.IpV4
get { return Tcp; } get { return Tcp; }
} }
/// <summary>
/// The payload of the datagram as an ICMP datagram.
/// </summary>
public IcmpDatagram Icmp public IcmpDatagram Icmp
{ {
get get
......
...@@ -146,6 +146,9 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -146,6 +146,9 @@ namespace PcapDotNet.Packets.IpV4
nextTransportLayer.Checksum); nextTransportLayer.Checksum);
} }
/// <summary>
/// True iff the two IPv4 layers have the same TypeOfService, Identification, Fragmentation, Ttl, Protocol, HeaderChecksum, Source, Destination and Options.
/// </summary>
public bool Equals(IpV4Layer other) public bool Equals(IpV4Layer other)
{ {
return other != null && return other != null &&
...@@ -157,11 +160,18 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -157,11 +160,18 @@ namespace PcapDotNet.Packets.IpV4
Options.Equals(other.Options); Options.Equals(other.Options);
} }
/// <summary>
/// True iff the two IPv4 layers have the same TypeOfService, Identification, Fragmentation, Ttl, Protocol, HeaderChecksum, Source, Destination and Options.
/// </summary>
public override sealed bool Equals(Layer other) public override sealed bool Equals(Layer other)
{ {
return base.Equals(other) && Equals(other as IpV4Layer); return Equals(other as IpV4Layer);
} }
/// <summary>
/// Returns a hash code for the layer.
/// The hash code is a XOR of the TypeOfService and Identification combined and the hash codes of the layer length, data link, Fragmentation, Protocol, HeaderChecksum, Source, Destination, Options.
/// </summary>
public override int GetHashCode() public override int GetHashCode()
{ {
return base.GetHashCode() ^ return base.GetHashCode() ^
...@@ -174,6 +184,9 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -174,6 +184,9 @@ namespace PcapDotNet.Packets.IpV4
} }
/// <summary>
/// Contains the Source, Destination and Protocol.
/// </summary>
public override string ToString() public override string ToString()
{ {
return Source + " -> " + Destination + " (" + Protocol + ")"; return Source + " -> " + Destination + " (" + Protocol + ")";
......
...@@ -47,17 +47,11 @@ namespace PcapDotNet.Packets ...@@ -47,17 +47,11 @@ namespace PcapDotNet.Packets
/// <summary> /// <summary>
/// True iff the two objects are equal Layers. /// True iff the two objects are equal Layers.
/// In order to be equal, the two layers must have identical length and data link.
/// </summary> /// </summary>
public virtual bool Equals(Layer other) public abstract bool Equals(Layer other);
{
return other != null &&
Length == other.Length && DataLink == other.DataLink;
}
/// <summary> /// <summary>
/// True iff the two objects are equal Layers. /// True iff the two objects are equal Layers.
/// In order to be equal, the two layers must have identical length and data link.
/// </summary> /// </summary>
public override sealed bool Equals(object obj) public override sealed bool Equals(object obj)
{ {
...@@ -66,7 +60,7 @@ namespace PcapDotNet.Packets ...@@ -66,7 +60,7 @@ namespace PcapDotNet.Packets
/// <summary> /// <summary>
/// Returns a hash code for the layer. /// Returns a hash code for the layer.
/// The hash code base is a XOR of the layer length and data link. /// The hash code base is a XOR of the hash codes of the layer length and data link.
/// </summary> /// </summary>
public override int GetHashCode() public override int GetHashCode()
{ {
......
...@@ -412,6 +412,13 @@ namespace PcapDotNet.Packets ...@@ -412,6 +412,13 @@ namespace PcapDotNet.Packets
Write(buffer, offset, value); Write(buffer, offset, value);
} }
/// <summary>
/// Writes the given value to the buffer using the given endianity and increments the offset by the number of bytes written.
/// </summary>
/// <param name="buffer">The buffer to write the value to.</param>
/// <param name="offset">The offset in the buffer to start writing.</param>
/// <param name="value">The value to write.</param>
/// <param name="endianity">The endianity to use when converting the value to bytes.</param>
public static void Write(this byte[] buffer, ref int offset, int value, Endianity endianity) public static void Write(this byte[] buffer, ref int offset, int value, Endianity endianity)
{ {
Write(buffer, offset, value, endianity); Write(buffer, offset, value, endianity);
...@@ -541,6 +548,13 @@ namespace PcapDotNet.Packets ...@@ -541,6 +548,13 @@ namespace PcapDotNet.Packets
buffer.Write(ref offset, value.ToValue(), endianity); buffer.Write(ref offset, value.ToValue(), endianity);
} }
/// <summary>
/// Writes the given value to the buffer using the given endianity.
/// </summary>
/// <param name="buffer">The buffer to write the value to.</param>
/// <param name="offset">The offset in the buffer to start writing.</param>
/// <param name="value">The value to write.</param>
/// <param name="endianity">The endianity to use when converting the value to bytes.</param>
public static void Write(this byte[] buffer, int offset, IpV4TimeOfDay value, Endianity endianity) public static void Write(this byte[] buffer, int offset, IpV4TimeOfDay value, Endianity endianity)
{ {
buffer.Write(offset, value.MillisecondsSinceMidnightUniversalTime, endianity); buffer.Write(offset, value.MillisecondsSinceMidnightUniversalTime, endianity);
......
...@@ -44,16 +44,33 @@ namespace PcapDotNet.Packets ...@@ -44,16 +44,33 @@ namespace PcapDotNet.Packets
/// </summary> /// </summary>
public class PacketBuilder public class PacketBuilder
{ {
/// <summary>
/// Builds a single packet using the given layers with the given timestamp.
/// </summary>
/// <param name="timestamp">The packet's timestamp.</param>
/// <param name="layers">The layers to build the packet accordingly and by their order.</param>
/// <returns>A packet built from the given layers with the given timestamp.</returns>
public static Packet Build(DateTime timestamp, params ILayer[] layers) public static Packet Build(DateTime timestamp, params ILayer[] layers)
{ {
return new PacketBuilder(layers).Build(timestamp); return new PacketBuilder(layers).Build(timestamp);
} }
/// <summary>
/// Builds a single packet using the given layers with the given timestamp.
/// </summary>
/// <param name="timestamp">The packet's timestamp.</param>
/// <param name="layers">The layers to build the packet accordingly and by their order.</param>
/// <returns>A packet built from the given layers with the given timestamp.</returns>
public static Packet Build(DateTime timestamp, IEnumerable<ILayer> layers) public static Packet Build(DateTime timestamp, IEnumerable<ILayer> layers)
{ {
return new PacketBuilder(layers).Build(timestamp); return new PacketBuilder(layers).Build(timestamp);
} }
/// <summary>
/// Creates a PacketBuilder that can build packets according to the given layers and with different timestamps.
/// The layers' properties can be modified after the builder is built and this will affect the packets built.
/// </summary>
/// <param name="layers">The layers to build the packet accordingly and by their order.</param>
public PacketBuilder(params ILayer[] layers) public PacketBuilder(params ILayer[] layers)
{ {
if (layers.Length == 0) if (layers.Length == 0)
...@@ -67,11 +84,22 @@ namespace PcapDotNet.Packets ...@@ -67,11 +84,22 @@ namespace PcapDotNet.Packets
_dataLink = new DataLink(dataLinkKind.Value); _dataLink = new DataLink(dataLinkKind.Value);
} }
/// <summary>
/// Creates a PacketBuilder that can build packets according to the given layers and with different timestamps.
/// The layers' properties can be modified after the builder is built and this will affect the packets built.
/// </summary>
/// <param name="layers">The layers to build the packet accordingly and by their order.</param>
public PacketBuilder(IEnumerable<ILayer> layers) public PacketBuilder(IEnumerable<ILayer> layers)
:this(layers.ToArray()) :this(layers.ToArray())
{ {
} }
/// <summary>
/// Builds a single packet using the builder's layers with the given timestamp.
/// </summary>
/// <param name="timestamp">The packet's timestamp.</param>
/// <returns>A packet built from the builder's layers with the given timestamp.</returns>
public Packet Build(DateTime timestamp) public Packet Build(DateTime timestamp)
{ {
int length = _layers.Select(layer => layer.Length).Sum(); int length = _layers.Select(layer => layer.Length).Sum();
......
...@@ -43,7 +43,7 @@ namespace PcapDotNet.Packets ...@@ -43,7 +43,7 @@ namespace PcapDotNet.Packets
/// </summary> /// </summary>
public override sealed bool Equals(Layer other) public override sealed bool Equals(Layer other)
{ {
return base.Equals(other) && Equals(other as PayloadLayer); return Equals(other as PayloadLayer);
} }
/// <summary> /// <summary>
......
...@@ -93,7 +93,18 @@ namespace PcapDotNet.Packets.Transport ...@@ -93,7 +93,18 @@ namespace PcapDotNet.Packets.Transport
Options); Options);
} }
public bool Equals(TcpLayer other) /// <summary>
/// True iff the SequenceNumber, AcknowledgmentNumber, ControlBits, Window, UrgentPointer and Options fields are equal.
/// </summary>
protected override sealed bool EqualFields(TransportLayer other)
{
return EqualFields(other as TcpLayer);
}
/// <summary>
/// True iff the SequenceNumber, AcknowledgmentNumber, ControlBits, Window, UrgentPointer and Options fields are equal.
/// </summary>
private bool EqualFields(TcpLayer other)
{ {
return other != null && return other != null &&
SequenceNumber == other.SequenceNumber && AcknowledgmentNumber == other.AcknowledgmentNumber && SequenceNumber == other.SequenceNumber && AcknowledgmentNumber == other.AcknowledgmentNumber &&
...@@ -101,10 +112,5 @@ namespace PcapDotNet.Packets.Transport ...@@ -101,10 +112,5 @@ namespace PcapDotNet.Packets.Transport
Window == other.Window && UrgentPointer == other.UrgentPointer && Window == other.Window && UrgentPointer == other.UrgentPointer &&
Options.Equals(other.Options); Options.Equals(other.Options);
} }
public override sealed bool Equals(TransportLayer other)
{
return base.Equals(other) && Equals(other as TcpLayer);
}
} }
} }
\ No newline at end of file
...@@ -51,24 +51,45 @@ namespace PcapDotNet.Packets.Transport ...@@ -51,24 +51,45 @@ namespace PcapDotNet.Packets.Transport
/// </summary> /// </summary>
public abstract bool IsChecksumOptional { get; } public abstract bool IsChecksumOptional { get; }
public virtual bool Equals(TransportLayer other) /// <summary>
/// Two Transport layers are equal if they have they have the same previous layer protocol value, checksum, source and destination ports,
/// and if the specific transport protocol fields are equal.
/// </summary>
public bool Equals(TransportLayer other)
{ {
return other != null && return other != null &&
PreviousLayerProtocol == other.PreviousLayerProtocol && PreviousLayerProtocol == other.PreviousLayerProtocol &&
Checksum == other.Checksum && Checksum == other.Checksum &&
SourcePort == other.SourcePort && DestinationPort == other.DestinationPort; SourcePort == other.SourcePort && DestinationPort == other.DestinationPort &&
EqualFields(other);
} }
/// <summary>
/// Two Transport layers are equal if they have they have the same previous layer protocol value, checksum, source and destination ports,
/// and if the specific transport protocol fields are equal.
/// </summary>
public override sealed bool Equals(Layer other) public override sealed bool Equals(Layer other)
{ {
return base.Equals(other) && Equals(other as TransportLayer); return Equals(other as TransportLayer);
} }
/// <summary>
/// Returns a hash code for the layer.
/// The hash code is a XOR of the combination of the source and destination ports and the hash codes of the layer length, data link and checksum.
/// </summary>
public override int GetHashCode() public override int GetHashCode()
{ {
return base.GetHashCode() ^ return base.GetHashCode() ^
Checksum.GetHashCode() ^ Checksum.GetHashCode() ^
((SourcePort << 16) + DestinationPort); ((SourcePort << 16) + DestinationPort);
} }
/// <summary>
/// True iff the specific transport layer fields are equal.
/// </summary>
protected virtual bool EqualFields(TransportLayer other)
{
return true;
}
} }
} }
\ 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