Commit 68437e53 authored by Brickner_cp's avatar Brickner_cp

Documentation. 0 documentation warnings left.

parent b7a3df08
...@@ -71,8 +71,10 @@ ...@@ -71,8 +71,10 @@
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="StaticReadonly" /> <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="StaticReadonly" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="EnumMember" /> <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="EnumMember" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="Other" /> <PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="Other" />
<PredefinedRule Inspect="True" Prefix="_" Suffix="" Style="aaBb" ElementKind="NotPublicInstanceFields" /> <PredefinedRule Inspect="True" Prefix="_" Suffix="" Style="aaBb" ElementKind="PrivateInstanceFields" />
<PredefinedRule Inspect="True" Prefix="_" Suffix="" Style="aaBb" ElementKind="NotPublicStaticFields" /> <PredefinedRule Inspect="True" Prefix="_" Suffix="" Style="aaBb" ElementKind="PrivateStaticFields" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="PrivateConstants" />
<PredefinedRule Inspect="True" Prefix="_" Suffix="" Style="aaBb" ElementKind="PrivateStaticReadonly" />
</Naming2> </Naming2>
</CodeStyleSettings> </CodeStyleSettings>
</Configuration> </Configuration>
\ No newline at end of file
...@@ -95,5 +95,17 @@ namespace PcapDotNet.Base ...@@ -95,5 +95,17 @@ namespace PcapDotNet.Base
{ {
return sequence.Aggregate(0, (valueSoFar, element) => valueSoFar ^ element.GetHashCode()); return sequence.Aggregate(0, (valueSoFar, element) => valueSoFar ^ element.GetHashCode());
} }
/// <summary>
/// Returns a hash code by xoring all the bytes.
/// Each byte is xored with the next 8 bits of the integer.
/// </summary>
/// <param name="sequence">The bytes to xor.</param>
/// <returns>The hash code resulted by xoring all the bytes.</returns>
public static int BytesSequenceGetHashCode(this IEnumerable<byte> sequence)
{
int i = 0;
return sequence.Aggregate(0, (value, b) => value ^ (b << (8 * (i++ % 4))));
}
} }
} }
\ No newline at end of file
...@@ -123,7 +123,7 @@ namespace PcapDotNet.Packets.Test ...@@ -123,7 +123,7 @@ namespace PcapDotNet.Packets.Test
Datagram ipV4Payload = new Datagram(ipV4PayloadBuffer); Datagram ipV4Payload = new Datagram(ipV4PayloadBuffer);
Packet packet = PacketBuilder.EthernetIpV4(DateTime.Now, Packet packet = PacketBuilder.EthernetIpV4(DateTime.Now,
ethernetSource, ethernetDestination, ethernetType, ethernetSource, ethernetDestination,
ipV4TypeOfService, ipV4Identification, ipV4Fragmentation, ipV4Ttl, ipV4Protocol, ipV4TypeOfService, ipV4Identification, ipV4Fragmentation, ipV4Ttl, ipV4Protocol,
ipV4Source, ipV4Destination, ipV4Options, ipV4Source, ipV4Destination, ipV4Options,
ipV4Payload); ipV4Payload);
...@@ -215,7 +215,13 @@ namespace PcapDotNet.Packets.Test ...@@ -215,7 +215,13 @@ namespace PcapDotNet.Packets.Test
[ExpectedException(typeof(ArgumentException))] [ExpectedException(typeof(ArgumentException))]
public void IpV4OptionsTooLongErrorTest() public void IpV4OptionsTooLongErrorTest()
{ {
IpV4Options options = new IpV4Options(new IpV4OptionTimestampOnly(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)); IpV4Options options = new IpV4Options(
new IpV4OptionTimestampOnly(1, 2,
new IpV4OptionTimeOfDay(3), new IpV4OptionTimeOfDay(4), new IpV4OptionTimeOfDay(5),
new IpV4OptionTimeOfDay(6), new IpV4OptionTimeOfDay(7), new IpV4OptionTimeOfDay(8),
new IpV4OptionTimeOfDay(9), new IpV4OptionTimeOfDay(10), new IpV4OptionTimeOfDay(11),
new IpV4OptionTimeOfDay(12), new IpV4OptionTimeOfDay(13), new IpV4OptionTimeOfDay(14),
new IpV4OptionTimeOfDay(15), new IpV4OptionTimeOfDay(16), new IpV4OptionTimeOfDay(17)));
Assert.IsNotNull(options); Assert.IsNotNull(options);
Assert.Fail(); Assert.Fail();
} }
......
...@@ -70,6 +70,11 @@ namespace PcapDotNet.Packets.TestUtils ...@@ -70,6 +70,11 @@ namespace PcapDotNet.Packets.TestUtils
return new IpV4Address(random.NextUInt()); return new IpV4Address(random.NextUInt());
} }
public static IpV4OptionTimeOfDay NextIpV4OptionTimeOfDay(this Random random)
{
return new IpV4OptionTimeOfDay(random.NextUInt());
}
public static IpV4Option NextIpV4Option(this Random random, int maximumOptionLength) public static IpV4Option NextIpV4Option(this Random random, int maximumOptionLength)
{ {
if (maximumOptionLength == 0) if (maximumOptionLength == 0)
...@@ -146,9 +151,9 @@ namespace PcapDotNet.Packets.TestUtils ...@@ -146,9 +151,9 @@ namespace PcapDotNet.Packets.TestUtils
{ {
case IpV4OptionTimestampType.TimestampOnly: case IpV4OptionTimestampType.TimestampOnly:
int numTimestamps = random.Next((maximumOptionLength - IpV4OptionTimestamp.OptionMinimumLength) / 4 + 1); int numTimestamps = random.Next((maximumOptionLength - IpV4OptionTimestamp.OptionMinimumLength) / 4 + 1);
uint[] timestamps = new uint[numTimestamps]; IpV4OptionTimeOfDay[] timestamps = new IpV4OptionTimeOfDay[numTimestamps];
for (int i = 0; i != numTimestamps; ++i) for (int i = 0; i != numTimestamps; ++i)
timestamps[i] = random.NextUInt(); timestamps[i] = random.NextIpV4OptionTimeOfDay();
return new IpV4OptionTimestampOnly(overflow, pointedIndex, timestamps); return new IpV4OptionTimestampOnly(overflow, pointedIndex, timestamps);
case IpV4OptionTimestampType.AddressAndTimestamp: case IpV4OptionTimestampType.AddressAndTimestamp:
...@@ -156,7 +161,7 @@ namespace PcapDotNet.Packets.TestUtils ...@@ -156,7 +161,7 @@ namespace PcapDotNet.Packets.TestUtils
int numPairs = random.Next((maximumOptionLength - IpV4OptionTimestamp.OptionMinimumLength) / 8 + 1); int numPairs = random.Next((maximumOptionLength - IpV4OptionTimestamp.OptionMinimumLength) / 8 + 1);
IpV4OptionTimedAddress[] pairs = new IpV4OptionTimedAddress[numPairs]; IpV4OptionTimedAddress[] pairs = new IpV4OptionTimedAddress[numPairs];
for (int i = 0; i != numPairs; ++i) for (int i = 0; i != numPairs; ++i)
pairs[i] = new IpV4OptionTimedAddress(random.NextIpV4Address(), random.NextUInt()); pairs[i] = new IpV4OptionTimedAddress(random.NextIpV4Address(), random.NextIpV4OptionTimeOfDay());
return new IpV4OptionTimestampAndAddress(timestampType, overflow, pointedIndex, pairs); return new IpV4OptionTimestampAndAddress(timestampType, overflow, pointedIndex, pairs);
......
using System;
namespace PcapDotNet.Packets namespace PcapDotNet.Packets
{ {
public struct DataLink : IDataLink
/// <summary>
/// Represents the DataLink type.
/// </summary>
public struct DataLink : IDataLink, IEquatable<DataLink>
{ {
/// <summary>
/// Etherent DataLink.
/// </summary>
public static DataLink Ethernet public static DataLink Ethernet
{ {
get { return _ethernet; } get { return _ethernet; }
} }
/// <summary>
/// Create the DataLink from a kind.
/// </summary>
public DataLink(DataLinkKind kind) public DataLink(DataLinkKind kind)
{ {
_kind = kind; _kind = kind;
} }
/// <summary>
/// The kind of the DataLink.
/// </summary>
public DataLinkKind Kind public DataLinkKind Kind
{ {
get { return _kind; } get { return _kind; }
} }
/// <summary>
/// Two DataLinks are equal if they are of the same kind.
/// </summary>
public bool Equals(DataLink other) public bool Equals(DataLink other)
{ {
return Kind == other.Kind; return Kind == other.Kind;
} }
/// <summary>
/// Two DataLinks are equal if they are of the same type and the same kind.
/// </summary>
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
return (obj is DataLink && return (obj is DataLink &&
Equals((DataLink)obj)); Equals((DataLink)obj));
} }
/// <summary>
/// Two DataLinks are equal if they are of the same kind.
/// </summary>
public static bool operator ==(DataLink dataLink1, DataLink dataLink2) public static bool operator ==(DataLink dataLink1, DataLink dataLink2)
{ {
return dataLink1.Equals(dataLink2); return dataLink1.Equals(dataLink2);
} }
/// <summary>
/// Two DataLinks are different if they have different kinds.
/// </summary>
public static bool operator !=(DataLink dataLink1, DataLink dataLink2) public static bool operator !=(DataLink dataLink1, DataLink dataLink2)
{ {
return !(dataLink1 == dataLink2); return !(dataLink1 == dataLink2);
} }
/// <summary>
/// The hash code of the datalink is the hash code of its kind.
/// </summary>
public override int GetHashCode() public override int GetHashCode()
{ {
return _kind.GetHashCode(); return _kind.GetHashCode();
} }
/// <summary>
/// The string is the kind's string.
/// </summary>
public override string ToString() public override string ToString()
{ {
return Kind.ToString(); return Kind.ToString();
......
namespace PcapDotNet.Packets namespace PcapDotNet.Packets
{ {
/// <summary>
/// Represents the different data links kinds.
/// </summary>
public enum DataLinkKind public enum DataLinkKind
{ {
/// <summary>
/// Ethernet data link kind.
/// </summary>
Ethernet Ethernet
} }
} }
\ No newline at end of file
...@@ -2,17 +2,33 @@ using System; ...@@ -2,17 +2,33 @@ using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using PcapDotNet.Base;
using PcapDotNet.Packets.Ethernet; using PcapDotNet.Packets.Ethernet;
namespace PcapDotNet.Packets namespace PcapDotNet.Packets
{ {
/// <summary>
/// Represents a packet datagram.
/// A datagram is part of the packet bytes that can be treated as a specific protocol data (usually header + payload).
/// Never copies the given buffer.
/// </summary>
public class Datagram : IEquatable<Datagram>, IEnumerable<byte> public class Datagram : IEquatable<Datagram>, IEnumerable<byte>
{ {
/// <summary>
/// Take all the bytes as a datagram.
/// </summary>
/// <param name="buffer">The buffer to take as a datagram.</param>
public Datagram(byte[] buffer) public Datagram(byte[] buffer)
: this(buffer, 0, buffer.Length) : this(buffer, 0, buffer.Length)
{ {
} }
/// <summary>
/// Take only part of the bytes as a datagarm.
/// </summary>
/// <param name="buffer">The bytes to take the datagram from.</param>
/// <param name="offset">The offset in the buffer to start taking the bytes from.</param>
/// <param name="length">The number of bytes to take.</param>
public Datagram(byte[] buffer, int offset, int length) public Datagram(byte[] buffer, int offset, int length)
{ {
_buffer = buffer; _buffer = buffer;
...@@ -20,21 +36,35 @@ namespace PcapDotNet.Packets ...@@ -20,21 +36,35 @@ namespace PcapDotNet.Packets
_length = length; _length = length;
} }
/// <summary>
/// An empty datagram.
/// Useful for empty payloads.
/// </summary>
public static Datagram Empty public static Datagram Empty
{ {
get { return _empty; } get { return _empty; }
} }
/// <summary>
/// The number of bytes in this datagram.
/// </summary>
public int Length public int Length
{ {
get { return _length; } get { return _length; }
} }
/// <summary>
/// The value of the byte in the given offset in the datagram.
/// </summary>
/// <param name="offset">The offset in the datagram to take the byte from.</param>
public byte this[int offset] public byte this[int offset]
{ {
get { return _buffer[StartOffset + offset]; } get { return _buffer[StartOffset + offset]; }
} }
/// <summary>
/// A datagram is checked for validity according to the protocol.
/// </summary>
public bool IsValid public bool IsValid
{ {
get get
...@@ -45,11 +75,9 @@ namespace PcapDotNet.Packets ...@@ -45,11 +75,9 @@ namespace PcapDotNet.Packets
} }
} }
public virtual bool CalculateIsValid() /// <summary>
{ /// Iterate through all the bytes in the datagram.
return true; /// </summary>
}
public IEnumerator<byte> GetEnumerator() public IEnumerator<byte> GetEnumerator()
{ {
for (int i = 0; i != Length; ++i) for (int i = 0; i != Length; ++i)
...@@ -61,6 +89,9 @@ namespace PcapDotNet.Packets ...@@ -61,6 +89,9 @@ namespace PcapDotNet.Packets
return GetEnumerator(); return GetEnumerator();
} }
/// <summary>
/// Two datagrams are equal if the have the same data.
/// </summary>
public bool Equals(Datagram other) public bool Equals(Datagram other)
{ {
if (Length != other.Length) if (Length != other.Length)
...@@ -75,46 +106,82 @@ namespace PcapDotNet.Packets ...@@ -75,46 +106,82 @@ namespace PcapDotNet.Packets
return true; return true;
} }
/// <summary>
/// Two datagrams are equal if the have the same data.
/// </summary>
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
return Equals(obj as Datagram); return Equals(obj as Datagram);
} }
/// <summary>
/// The hash code of a datagram is the hash code of its length xored with all its bytes (each byte is xored with the next byte in the integer).
/// </summary>
public override int GetHashCode() public override int GetHashCode()
{ {
int i = 0; return Length.GetHashCode() ^ this.BytesSequenceGetHashCode();
return Length.GetHashCode() ^
this.Aggregate(0, (value, b) => value ^ (b << (8 * (i++ % 4))));
} }
internal void Write(byte[] buffer, int offset) internal void Write(byte[] buffer, int offset)
{ {
System.Buffer.BlockCopy(_buffer, StartOffset, buffer, offset, Length); _buffer.BlockCopy(StartOffset, buffer, offset, Length);
} }
/// <summary>
/// The original buffer that holds all the data for the datagram.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]
protected byte[] Buffer protected byte[] Buffer
{ {
get { return _buffer; } get { return _buffer; }
} }
/// <summary>
/// The offset of the first byte of the datagram in the buffer.
/// </summary>
protected int StartOffset protected int StartOffset
{ {
get { return _startOffset; } get { return _startOffset; }
} }
/// <summary>
/// The default validity check always returns true.
/// </summary>
protected virtual bool CalculateIsValid()
{
return true;
}
/// <summary>
/// Reads 2 bytes from a specific offset in the datagram as a ushort with a given endianity.
/// </summary>
/// <param name="offset">The offset in the datagram to start reading.</param>
/// <param name="endianity">The endianity to use to translate the bytes to the value.</param>
/// <returns>The value converted from the read bytes according to the endianity.</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "ushort")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "ushort")]
protected ushort ReadUShort(int offset, Endianity endianity) protected ushort ReadUShort(int offset, Endianity endianity)
{ {
return Buffer.ReadUShort(StartOffset + offset, endianity); return Buffer.ReadUShort(StartOffset + offset, endianity);
} }
/// <summary>
/// Reads 4 bytes from a specific offset in the datagram as a uint with a given endianity.
/// </summary>
/// <param name="offset">The offset in the datagram to start reading.</param>
/// <param name="endianity">The endianity to use to translate the bytes to the value.</param>
/// <returns>The value converted from the read bytes according to the endianity.</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "uint")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "uint")]
protected uint ReadUInt(int offset, Endianity endianity) protected uint ReadUInt(int offset, Endianity endianity)
{ {
return Buffer.ReadUInt(StartOffset + offset, endianity); return Buffer.ReadUInt(StartOffset + offset, endianity);
} }
/// <summary>
/// Reads 6 bytes from a specific offset in the datagram as a MacAddress with a given endianity.
/// </summary>
/// <param name="offset">The offset in the datagram to start reading.</param>
/// <param name="endianity">The endianity to use to translate the bytes to the value.</param>
/// <returns>The value converted from the read bytes according to the endianity.</returns>
protected MacAddress ReadMacAddress(int offset, Endianity endianity) protected MacAddress ReadMacAddress(int offset, Endianity endianity)
{ {
return Buffer.ReadMacAddress(StartOffset + offset, endianity); return Buffer.ReadMacAddress(StartOffset + offset, endianity);
......
namespace PcapDotNet.Packets namespace PcapDotNet.Packets
{ {
/// <summary>
/// The two possible endianities.
/// </summary>
public enum Endianity : byte public enum Endianity : byte
{ {
/// <summary>
/// Small endianity - bytes are read from the high offset to the low offset.
/// </summary>
Small, Small,
/// <summary>
/// Big endianity - bytes are read from the low offset to the high offset.
/// </summary>
Big Big
} }
} }
\ No newline at end of file
...@@ -4,6 +4,8 @@ using PcapDotNet.Packets.IpV4; ...@@ -4,6 +4,8 @@ using PcapDotNet.Packets.IpV4;
namespace PcapDotNet.Packets.Ethernet namespace PcapDotNet.Packets.Ethernet
{ {
/// <summary> /// <summary>
/// Represents an Ethernet datagram.
///
/// +------+-----------------+------------+------------------+ /// +------+-----------------+------------+------------------+
/// | Byte | 0-5 | 6-11 | 12-13 | /// | Byte | 0-5 | 6-11 | 12-13 |
/// +------+-----------------+------------+------------------+ /// +------+-----------------+------------+------------------+
...@@ -21,18 +23,30 @@ namespace PcapDotNet.Packets.Ethernet ...@@ -21,18 +23,30 @@ namespace PcapDotNet.Packets.Ethernet
public const int EtherTypeLength = 12; public const int EtherTypeLength = 12;
} }
/// <summary>
/// Ethernet header length in bytes.
/// </summary>
public const int HeaderLength = 14; public const int HeaderLength = 14;
/// <summary>
/// The Ethernet payload.
/// </summary>
public Datagram Payload public Datagram Payload
{ {
get { return IpV4; } get { return IpV4; }
} }
/// <summary>
/// The Ethernet payload length in bytes.
/// </summary>
public int PayloadLength public int PayloadLength
{ {
get { return Math.Max(0, Length - HeaderLength); } get { return Math.Max(0, Length - HeaderLength); }
} }
/// <summary>
/// Ethernet source address.
/// </summary>
public MacAddress Source public MacAddress Source
{ {
get get
...@@ -41,6 +55,9 @@ namespace PcapDotNet.Packets.Ethernet ...@@ -41,6 +55,9 @@ namespace PcapDotNet.Packets.Ethernet
} }
} }
/// <summary>
/// Ethernet destination address.
/// </summary>
public MacAddress Destination public MacAddress Destination
{ {
get get
...@@ -49,6 +66,9 @@ namespace PcapDotNet.Packets.Ethernet ...@@ -49,6 +66,9 @@ namespace PcapDotNet.Packets.Ethernet
} }
} }
/// <summary>
/// Ethernet type (next protocol).
/// </summary>
public EthernetType EtherType public EthernetType EtherType
{ {
get get
...@@ -57,20 +77,9 @@ namespace PcapDotNet.Packets.Ethernet ...@@ -57,20 +77,9 @@ namespace PcapDotNet.Packets.Ethernet
} }
} }
public override bool CalculateIsValid() /// <summary>
{ /// The Ethernet payload as an IPv4 datagram.
if (Length < HeaderLength) /// </summary>
return false;
switch (EtherType)
{
case EthernetType.IpV4:
return IpV4.IsValid;
default:
return true;
}
}
public IpV4Datagram IpV4 public IpV4Datagram IpV4
{ {
get get
...@@ -81,7 +90,6 @@ namespace PcapDotNet.Packets.Ethernet ...@@ -81,7 +90,6 @@ namespace PcapDotNet.Packets.Ethernet
} }
} }
internal EthernetDatagram(byte[] buffer, int offset, int length) internal EthernetDatagram(byte[] buffer, int offset, int length)
: base(buffer, offset, length) : base(buffer, offset, length)
{ {
...@@ -94,6 +102,23 @@ namespace PcapDotNet.Packets.Ethernet ...@@ -94,6 +102,23 @@ namespace PcapDotNet.Packets.Ethernet
buffer.Write(offset + Offset.EtherTypeLength, (ushort)ethernetType, Endianity.Big); buffer.Write(offset + Offset.EtherTypeLength, (ushort)ethernetType, Endianity.Big);
} }
/// <summary>
/// An Ethernet datagram is valid iff its length is big enough for the header and its payload is valid.
/// </summary>
protected override bool CalculateIsValid()
{
if (Length < HeaderLength)
return false;
switch (EtherType)
{
case EthernetType.IpV4:
return IpV4.IsValid;
default:
return true;
}
}
private IpV4Datagram _ipV4; private IpV4Datagram _ipV4;
} }
} }
\ No newline at end of file
...@@ -4,15 +4,29 @@ using PcapDotNet.Base; ...@@ -4,15 +4,29 @@ using PcapDotNet.Base;
namespace PcapDotNet.Packets.Ethernet namespace PcapDotNet.Packets.Ethernet
{ {
public struct MacAddress /// <summary>
/// Ethernet MacAddress struct.
/// </summary>
public struct MacAddress : IEquatable<MacAddress>
{ {
/// <summary>
/// The number of bytes the struct takes.
/// </summary>
public const int SizeOf = UInt48.SizeOf; public const int SizeOf = UInt48.SizeOf;
/// <summary>
/// Constructs the address from a 48 bit integer.
/// </summary>
/// <param name="value">The 48 bit integer to create the address from.</param>
public MacAddress(UInt48 value) public MacAddress(UInt48 value)
{ {
_value = value; _value = value;
} }
/// <summary>
/// Create the address from a string in the format XX:XX:XX:XX:XX:XX.
/// </summary>
/// <param name="address">The string value in hexadecimal format. Every two digits are separated by a colon.</param>
public MacAddress(string address) public MacAddress(string address)
{ {
string[] hexes = address.Split(':'); string[] hexes = address.Split(':');
...@@ -27,37 +41,59 @@ namespace PcapDotNet.Packets.Ethernet ...@@ -27,37 +41,59 @@ namespace PcapDotNet.Packets.Ethernet
Convert.ToByte(hexes[5], 16)); Convert.ToByte(hexes[5], 16));
} }
/// <summary>
/// Converts the address to a 48 bit integer.
/// </summary>
/// <returns>A 48 bit integer representing the address.</returns>
public UInt48 ToValue() public UInt48 ToValue()
{ {
return _value; return _value;
} }
/// <summary>
/// Two addresses are equal if they have the exact same value.
/// </summary>
public bool Equals(MacAddress other) public bool Equals(MacAddress other)
{ {
return _value == other._value; return _value == other._value;
} }
/// <summary>
/// Two addresses are equal if they have the exact same value.
/// </summary>
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
return (obj is MacAddress && return (obj is MacAddress &&
Equals((MacAddress)obj)); Equals((MacAddress)obj));
} }
/// <summary>
/// Two addresses are equal if they have the exact same value.
/// </summary>
public static bool operator ==(MacAddress macAddress1, MacAddress macAddress2) public static bool operator ==(MacAddress macAddress1, MacAddress macAddress2)
{ {
return macAddress1.Equals(macAddress2); return macAddress1.Equals(macAddress2);
} }
/// <summary>
/// Two addresses are different if they have different values.
/// </summary>
public static bool operator !=(MacAddress macAddress1, MacAddress macAddress2) public static bool operator !=(MacAddress macAddress1, MacAddress macAddress2)
{ {
return !(macAddress1 == macAddress2); return !(macAddress1 == macAddress2);
} }
/// <summary>
/// The hash code of the address is the hash code of its 48 bit integer value.
/// </summary>
public override int GetHashCode() public override int GetHashCode()
{ {
return _value.GetHashCode(); return _value.GetHashCode();
} }
/// <summary>
/// Converts the address to a string in the format XX:XX:XX:XX:XX:XX.
/// </summary>
public override string ToString() public override string ToString()
{ {
return string.Format(CultureInfo.InvariantCulture, "{0:X2}:{1:X2}:{2:X2}:{3:X2}:{4:X2}:{5:X2}", return string.Format(CultureInfo.InvariantCulture, "{0:X2}:{1:X2}:{2:X2}:{3:X2}:{4:X2}:{5:X2}",
......
namespace PcapDotNet.Packets namespace PcapDotNet.Packets
{ {
/// <summary>
/// Represents a datalink.
/// </summary>
public interface IDataLink public interface IDataLink
{ {
/// <summary>
/// The kind of the datalink.
/// </summary>
DataLinkKind Kind { get; } DataLinkKind Kind { get; }
} }
} }
\ No newline at end of file
...@@ -3,15 +3,30 @@ using System.Text; ...@@ -3,15 +3,30 @@ using System.Text;
namespace PcapDotNet.Packets.IpV4 namespace PcapDotNet.Packets.IpV4
{ {
/// <summary>
/// Represents an IPv4 address.
/// </summary>
public struct IpV4Address public struct IpV4Address
{ {
/// <summary>
/// The number of bytes the address take.
/// </summary>
public const int SizeOf = sizeof(uint); public const int SizeOf = sizeof(uint);
/// <summary>
/// Create an address from a 32 bit integer.
/// 0 -> 0.0.0.0
/// 1 -> 0.0.0.1
/// 256 -> 0.0.1.0
/// </summary>
public IpV4Address(uint value) public IpV4Address(uint value)
{ {
_value = value; _value = value;
} }
/// <summary>
/// Creates an address from an address string (1.2.3.4).
/// </summary>
public IpV4Address(string value) public IpV4Address(string value)
{ {
string[] values = value.Split('.'); string[] values = value.Split('.');
...@@ -21,42 +36,66 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -21,42 +36,66 @@ namespace PcapDotNet.Packets.IpV4
(byte.Parse(values[3], CultureInfo.InvariantCulture))); (byte.Parse(values[3], CultureInfo.InvariantCulture)));
} }
/// <summary>
/// The zero address (0.0.0.0).
/// </summary>
public static IpV4Address Zero public static IpV4Address Zero
{ {
get { return _zero; } get { return _zero; }
} }
/// <summary>
/// Gets the address valud as a 32 bit integer.
/// </summary>
public uint ToValue() public uint ToValue()
{ {
return _value; return _value;
} }
/// <summary>
/// Two addresses are equal if the have the exact same value.
/// </summary>
public bool Equals(IpV4Address other) public bool Equals(IpV4Address other)
{ {
return ToValue() == other.ToValue(); return ToValue() == other.ToValue();
} }
/// <summary>
/// Two addresses are equal if the have the exact same value.
/// </summary>
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
return (obj is IpV4Address && return (obj is IpV4Address &&
Equals((IpV4Address)obj)); Equals((IpV4Address)obj));
} }
/// <summary>
/// Two addresses are equal if the have the exact same value.
/// </summary>
public static bool operator ==(IpV4Address value1, IpV4Address value2) public static bool operator ==(IpV4Address value1, IpV4Address value2)
{ {
return value1.Equals(value2); return value1.Equals(value2);
} }
/// <summary>
/// Two addresses are different if the have different values.
/// </summary>
public static bool operator !=(IpV4Address value1, IpV4Address value2) public static bool operator !=(IpV4Address value1, IpV4Address value2)
{ {
return !(value1 == value2); return !(value1 == value2);
} }
/// <summary>
/// The hash code of an address is the hash code of its 32 bit integer value.
/// </summary>
public override int GetHashCode() public override int GetHashCode()
{ {
return _value.GetHashCode(); return _value.GetHashCode();
} }
/// <summary>
/// Translates the address to a string (1.2.3.4).
/// </summary>
public override string ToString() public override string ToString()
{ {
StringBuilder stringBuilder = new StringBuilder(15); StringBuilder stringBuilder = new StringBuilder(15);
......
...@@ -5,6 +5,8 @@ using System.Text; ...@@ -5,6 +5,8 @@ using System.Text;
namespace PcapDotNet.Packets.IpV4 namespace PcapDotNet.Packets.IpV4
{ {
/// <summary> /// <summary>
/// Represents an IPv4 datagram.
///
/// +-----+---------+-----+-----------------+-------+-----------------+ /// +-----+---------+-----+-----------------+-------+-----------------+
/// | Bit | 0-3 | 4-7 | 8-15 | 16-18 | 19-31 | /// | Bit | 0-3 | 4-7 | 8-15 | 16-18 | 19-31 |
/// +-----+---------+-----+-----------------+-------+-----------------+ /// +-----+---------+-----+-----------------+-------+-----------------+
...@@ -20,10 +22,21 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -20,10 +22,21 @@ namespace PcapDotNet.Packets.IpV4
/// +-----+-----------------------------------------------------------+ /// +-----+-----------------------------------------------------------+
/// | 160 | Options with padding | /// | 160 | Options with padding |
/// +-----+-----------------------------------------------------------+ /// +-----+-----------------------------------------------------------+
/// | 160 | Data |
/// | to | |
/// | 360 | |
/// +-----+-----------------------------------------------------------+
/// </summary> /// </summary>
public class IpV4Datagram : Datagram public class IpV4Datagram : Datagram
{ {
/// <summary>
/// The minimum length of the header in bytes.
/// </summary>
public const int HeaderMinimumLength = 20; public const int HeaderMinimumLength = 20;
/// <summary>
/// The maximum length of the header in bytes.
/// </summary>
public const int HeaderMaximumLength = 60; public const int HeaderMaximumLength = 60;
private static class Offset private static class Offset
...@@ -41,48 +54,78 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -41,48 +54,78 @@ namespace PcapDotNet.Packets.IpV4
public const int Options = 20; public const int Options = 20;
} }
/// <summary>
/// The version (4).
/// </summary>
public const int Version = 0x4; public const int Version = 0x4;
/// <summary>
/// The header length in bytes.
/// </summary>
public int HeaderLength public int HeaderLength
{ {
get { return (this[Offset.VersionAndHeaderLength] & 0x0F) * 4; } get { return (this[Offset.VersionAndHeaderLength] & 0x0F) * 4; }
} }
/// <summary>
/// Type of Service field.
/// </summary>
public byte TypeOfService public byte TypeOfService
{ {
get { return this[Offset.TypeOfService];} get { return this[Offset.TypeOfService];}
} }
/// <summary>
/// The length of the entire datagram as stated in the total length field.
/// </summary>
public ushort TotalLength public ushort TotalLength
{ {
get { return ReadUShort(Offset.TotalLength, Endianity.Big); } get { return ReadUShort(Offset.TotalLength, Endianity.Big); }
} }
/// <summary>
/// The value of the IPv4 ID field.
/// </summary>
public ushort Identification public ushort Identification
{ {
get { return ReadUShort(Offset.Identification, Endianity.Big); } get { return ReadUShort(Offset.Identification, Endianity.Big); }
} }
/// <summary>
/// The fragmentation information field.
/// </summary>
public IpV4Fragmentation Fragmentation public IpV4Fragmentation Fragmentation
{ {
get { return new IpV4Fragmentation(ReadUShort(Offset.Fragmentation, Endianity.Big)); } get { return new IpV4Fragmentation(ReadUShort(Offset.Fragmentation, Endianity.Big)); }
} }
/// <summary>
/// The TTL field.
/// </summary>
public byte Ttl public byte Ttl
{ {
get { return this[Offset.Ttl]; } get { return this[Offset.Ttl]; }
} }
/// <summary>
/// The IPv4 (next) protocol field.
/// </summary>
public IpV4Protocol Protocol public IpV4Protocol Protocol
{ {
get { return (IpV4Protocol)this[Offset.Protocol]; } get { return (IpV4Protocol)this[Offset.Protocol]; }
} }
/// <summary>
/// The header check sum value.
/// </summary>
public ushort HeaderChecksum public ushort HeaderChecksum
{ {
get { return ReadUShort(Offset.HeaderChecksum, Endianity.Big); } get { return ReadUShort(Offset.HeaderChecksum, Endianity.Big); }
} }
/// <summary>
/// True iff the header checksum value is correct according to the header.
/// </summary>
public bool IsHeaderChecksumCorrect public bool IsHeaderChecksumCorrect
{ {
get get
...@@ -93,16 +136,25 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -93,16 +136,25 @@ namespace PcapDotNet.Packets.IpV4
} }
} }
/// <summary>
/// The source address.
/// </summary>
public IpV4Address Source public IpV4Address Source
{ {
get { return new IpV4Address(ReadUInt(Offset.Source, Endianity.Big)); } get { return new IpV4Address(ReadUInt(Offset.Source, Endianity.Big)); }
} }
/// <summary>
/// The destination address.
/// </summary>
public IpV4Address Destination public IpV4Address Destination
{ {
get { return new IpV4Address(ReadUInt(Offset.Destination, Endianity.Big)); } get { return new IpV4Address(ReadUInt(Offset.Destination, Endianity.Big)); }
} }
/// <summary>
/// The options field with all the parsed options if any exist.
/// </summary>
public IpV4Options Options public IpV4Options Options
{ {
get get
...@@ -113,26 +165,17 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -113,26 +165,17 @@ namespace PcapDotNet.Packets.IpV4
} }
} }
/// <summary>
/// The payload of the datagram.
/// </summary>
public Datagram Payload public Datagram Payload
{ {
get { return Tcp; } get { return Tcp; }
} }
public override bool CalculateIsValid() /// <summary>
{ /// The payload of the datagram as a TCP datagram.
if (Length < HeaderMinimumLength || Length < HeaderLength) /// </summary>
return false;
switch (Protocol)
{
case IpV4Protocol.Tcp:
return Tcp.IsValid;
default:
// Todo check the protocl further
return true;
}
}
public Datagram Tcp public Datagram Tcp
{ {
get get
...@@ -172,6 +215,28 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -172,6 +215,28 @@ namespace PcapDotNet.Packets.IpV4
buffer.Write(offset + Offset.HeaderChecksum, Sum16BitsToChecksum(Sum16Bits(buffer, offset, headerLength)), Endianity.Big); buffer.Write(offset + Offset.HeaderChecksum, Sum16BitsToChecksum(Sum16Bits(buffer, offset, headerLength)), Endianity.Big);
} }
/// <summary>
/// An IPv4 datagram is valid if its length is big enough for the header, the header checksum is correct and the payload is valid.
/// </summary>
/// <returns></returns>
protected override bool CalculateIsValid()
{
if (Length < HeaderMinimumLength || Length < HeaderLength)
return false;
if (!IsHeaderChecksumCorrect)
return false;
switch (Protocol)
{
case IpV4Protocol.Tcp:
return Tcp.IsValid;
default:
// Todo check the protocl further
return true;
}
}
private ushort CalculateHeaderChecksum() private ushort CalculateHeaderChecksum()
{ {
uint sum = Sum16Bits(Buffer, StartOffset, Offset.HeaderChecksum) + uint sum = Sum16Bits(Buffer, StartOffset, Offset.HeaderChecksum) +
......
...@@ -2,13 +2,24 @@ using System; ...@@ -2,13 +2,24 @@ using System;
namespace PcapDotNet.Packets.IpV4 namespace PcapDotNet.Packets.IpV4
{ {
/// <summary>
/// Represents IPv4 Fragmentation information.
/// </summary>
public struct IpV4Fragmentation : IEquatable<IpV4Fragmentation> public struct IpV4Fragmentation : IEquatable<IpV4Fragmentation>
{ {
/// <summary>
/// No fragmentation.
/// </summary>
public static IpV4Fragmentation None public static IpV4Fragmentation None
{ {
get { return _none; } get { return _none; }
} }
/// <summary>
/// Creates fragmentation field value according to the given information.
/// </summary>
/// <param name="options">Options for fragmentation (must be one of the values of the enum).</param>
/// <param name="offset">This field indicates where in the complete datagram this fragment belongs. Measured in bytes but must divide by 8.</param>
public IpV4Fragmentation(IpV4FragmentationOptions options, ushort offset) public IpV4Fragmentation(IpV4FragmentationOptions options, ushort offset)
: this((ushort)((ushort)options | (offset / 8))) : this((ushort)((ushort)options | (offset / 8)))
{ {
...@@ -19,40 +30,62 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -19,40 +30,62 @@ namespace PcapDotNet.Packets.IpV4
throw new ArgumentException("invalid options " + options); throw new ArgumentException("invalid options " + options);
} }
/// <summary>
/// Options for fragmentation.
/// </summary>
public IpV4FragmentationOptions Options public IpV4FragmentationOptions Options
{ {
get { return (IpV4FragmentationOptions)(_value & 0xE000); } get { return (IpV4FragmentationOptions)(_value & 0xE000); }
} }
/// <summary>
/// This field indicates where in the complete datagram this fragment belongs. Measured in bytes but must divide by 8.
/// </summary>
public ushort Offset public ushort Offset
{ {
get { return (ushort)((_value & 0x1FFF) * 8); } get { return (ushort)((_value & 0x1FFF) * 8); }
} }
/// <summary>
/// Two framentations are equal if they are exactly the same fragmentation (options and offset).
/// </summary>
public bool Equals(IpV4Fragmentation other) public bool Equals(IpV4Fragmentation other)
{ {
return _value == other._value; return _value == other._value;
} }
/// <summary>
/// Two framentations are equal if they are exactly the same fragmentation (options and offset).
/// </summary>
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
return (obj is IpV4Fragmentation && return (obj is IpV4Fragmentation &&
Equals((IpV4Fragmentation)obj)); Equals((IpV4Fragmentation)obj));
} }
/// <summary>
/// Two framentations are equal if they are exactly the same fragmentation (options and offset).
/// </summary>
public static bool operator ==(IpV4Fragmentation value1, IpV4Fragmentation value2) public static bool operator ==(IpV4Fragmentation value1, IpV4Fragmentation value2)
{ {
return value1.Equals(value2); return value1.Equals(value2);
} }
/// <summary>
/// Two framentations are different if they are different fragmentation (options or offset).
/// </summary>
public static bool operator !=(IpV4Fragmentation value1, IpV4Fragmentation value2) public static bool operator !=(IpV4Fragmentation value1, IpV4Fragmentation value2)
{ {
return !(value1 == value2); return !(value1 == value2);
} }
/// <summary>
/// The hash code of the fragmentation is the hash code of its combined flags and offset 16 bit field.
/// </summary>
/// <returns></returns>
public override int GetHashCode() public override int GetHashCode()
{ {
return _value; return _value.GetHashCode();
} }
internal IpV4Fragmentation(ushort value) internal IpV4Fragmentation(ushort value)
......
...@@ -2,12 +2,27 @@ using System; ...@@ -2,12 +2,27 @@ using System;
namespace PcapDotNet.Packets.IpV4 namespace PcapDotNet.Packets.IpV4
{ {
/// <summary>
/// Fragmentation information flags for IPv4 datagram.
/// </summary>
[Flags] [Flags]
public enum IpV4FragmentationOptions : ushort public enum IpV4FragmentationOptions : ushort
{ {
None = 0x0 << 13, /// <summary>
// Reserved = 0x4 << 13, /// May Fragment, Last Fragment.
DoNotFragment = 0x2 << 13, /// </summary>
MoreFragments = 0x1 << 13 None = 0x0 << 13,
/// <summary>
/// More Fragments.
/// </summary>
MoreFragments = 0x1 << 13,
/// <summary>
/// Don't Fragment.
/// </summary>
DoNotFragment = 0x2 << 13
// Reserved = 0x4 << 13,
} }
} }
\ No newline at end of file
...@@ -79,34 +79,22 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -79,34 +79,22 @@ namespace PcapDotNet.Packets.IpV4
} }
/// <summary> /// <summary>
/// Serves as a hash function for a particular type. /// The hash code of the option is the hash code of the option type.
/// </summary> /// </summary>
/// <returns> /// <returns></returns>
/// A hash code for the current <see cref="T:System.Object"/>.
/// </returns>
/// <filterpriority>2</filterpriority>
public override int GetHashCode() public override int GetHashCode()
{ {
return (byte)OptionType; return OptionType.GetHashCode();
} }
/// <summary> /// <summary>
/// Returns a <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>. /// The string of the option is the string of the option type.
/// </summary> /// </summary>
/// <returns>
/// A <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
/// </returns>
/// <filterpriority>2</filterpriority>
public override string ToString() public override string ToString()
{ {
return OptionType.ToString(); return OptionType.ToString();
} }
protected IpV4Option(IpV4OptionType type)
{
_type = type;
}
internal static IpV4Option Read(byte[] buffer, ref int offset, int length) internal static IpV4Option Read(byte[] buffer, ref int offset, int length)
{ {
int offsetEnd = offset + length; int offsetEnd = offset + length;
...@@ -139,6 +127,14 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -139,6 +127,14 @@ namespace PcapDotNet.Packets.IpV4
buffer[offset++] = (byte)OptionType; buffer[offset++] = (byte)OptionType;
} }
/// <summary>
/// Constructs the option by type.
/// </summary>
protected IpV4Option(IpV4OptionType type)
{
_type = type;
}
private static readonly IpV4OptionSimple _end = new IpV4OptionSimple(IpV4OptionType.EndOfOptionList); private static readonly IpV4OptionSimple _end = new IpV4OptionSimple(IpV4OptionType.EndOfOptionList);
private static readonly IpV4OptionSimple _nop = new IpV4OptionSimple(IpV4OptionType.NoOperation); private static readonly IpV4OptionSimple _nop = new IpV4OptionSimple(IpV4OptionType.NoOperation);
......
namespace PcapDotNet.Packets.IpV4 namespace PcapDotNet.Packets.IpV4
{ {
/// <summary>
/// Represents a complex IPv4 option.
/// Complex option means that it contains data and not just the type.
/// </summary>
public abstract class IpV4OptionComplex : IpV4Option public abstract class IpV4OptionComplex : IpV4Option
{ {
/// <summary>
/// The header length in bytes for the option (type and size).
/// </summary>
public const int OptionHeaderLength = 2; public const int OptionHeaderLength = 2;
internal static IpV4OptionComplex ReadOptionComplex(IpV4OptionType optionType, byte[] buffer, ref int offset, int length) internal static IpV4OptionComplex ReadOptionComplex(IpV4OptionType optionType, byte[] buffer, ref int offset, int length)
...@@ -40,6 +47,9 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -40,6 +47,9 @@ namespace PcapDotNet.Packets.IpV4
} }
} }
/// <summary>
/// Constructs the option by type.
/// </summary>
protected IpV4OptionComplex(IpV4OptionType type) protected IpV4OptionComplex(IpV4OptionType type)
: base(type) : base(type)
{ {
......
...@@ -44,8 +44,13 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -44,8 +44,13 @@ namespace PcapDotNet.Packets.IpV4
/// </summary> /// </summary>
public class IpV4OptionLooseSourceRouting : IpV4OptionRoute public class IpV4OptionLooseSourceRouting : IpV4OptionRoute
{ {
public IpV4OptionLooseSourceRouting(IList<IpV4Address> addresses, byte pointedAddressIndex) /// <summary>
: base(IpV4OptionType.LooseSourceRouting, addresses, pointedAddressIndex) /// Constructs the option from the given values.
/// </summary>
/// <param name="route">The route addresses values.</param>
/// <param name="pointedAddressIndex">The pointed index in the route.</param>
public IpV4OptionLooseSourceRouting(IList<IpV4Address> route, byte pointedAddressIndex)
: base(IpV4OptionType.LooseSourceRouting, route, pointedAddressIndex)
{ {
} }
......
...@@ -41,13 +41,23 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -41,13 +41,23 @@ namespace PcapDotNet.Packets.IpV4
/// </summary> /// </summary>
public class IpV4OptionRecordRoute : IpV4OptionRoute public class IpV4OptionRecordRoute : IpV4OptionRoute
{ {
public IpV4OptionRecordRoute(byte pointedAddressIndex, IList<IpV4Address> addresses) /// <summary>
: base(IpV4OptionType.RecordRoute, addresses, pointedAddressIndex) /// Constructs the option from the given values.
/// </summary>
/// <param name="route">The route addresses values.</param>
/// <param name="pointedAddressIndex">The pointed index in the route.</param>
public IpV4OptionRecordRoute(byte pointedAddressIndex, IList<IpV4Address> route)
: base(IpV4OptionType.RecordRoute, route, pointedAddressIndex)
{ {
} }
public IpV4OptionRecordRoute(byte pointedAddressIndex, params IpV4Address[] addresses) /// <summary>
: this(pointedAddressIndex, (IList<IpV4Address>)addresses) /// Constructs the option from the given values.
/// </summary>
/// <param name="route">The route addresses values.</param>
/// <param name="pointedAddressIndex">The pointed index in the route.</param>
public IpV4OptionRecordRoute(byte pointedAddressIndex, params IpV4Address[] route)
: this(pointedAddressIndex, (IList<IpV4Address>)route)
{ {
} }
......
...@@ -6,27 +6,61 @@ using PcapDotNet.Base; ...@@ -6,27 +6,61 @@ using PcapDotNet.Base;
namespace PcapDotNet.Packets.IpV4 namespace PcapDotNet.Packets.IpV4
{ {
/// <summary>
/// The base class for route tracking options (loose, strict, record).
/// </summary>
public abstract class IpV4OptionRoute : IpV4OptionComplex, IEquatable<IpV4OptionRoute> public abstract class IpV4OptionRoute : IpV4OptionComplex, IEquatable<IpV4OptionRoute>
{ {
/// <summary>
/// The minimum option length in bytes (type, length, pointer).
/// </summary>
public const int OptionMinimumLength = 3; public const int OptionMinimumLength = 3;
/// <summary>
/// The minimum option value length in bytes (pointer).
/// </summary>
public const int OptionValueMinimumLength = OptionMinimumLength - OptionHeaderLength; public const int OptionValueMinimumLength = OptionMinimumLength - OptionHeaderLength;
/// <summary>
/// The maximum value for the index pointed the route.
/// </summary>
public const byte PointedAddressIndexMaxValue = byte.MaxValue / 4 - 1; public const byte PointedAddressIndexMaxValue = byte.MaxValue / 4 - 1;
/// <summary>
/// The pointed index in the route.
/// </summary>
public byte PointedAddressIndex public byte PointedAddressIndex
{ {
get { return _pointedAddressIndex; } get { return _pointedAddressIndex; }
} }
/// <summary>
/// The route tracked - the collection of addresses written.
/// </summary>
public ReadOnlyCollection<IpV4Address> Route
{
get { return _route; }
}
/// <summary>
/// The number of bytes this option will take.
/// </summary>
public override int Length public override int Length
{ {
get { return OptionMinimumLength + IpV4Address.SizeOf * Route.Count; } get { return OptionMinimumLength + IpV4Address.SizeOf * Route.Count; }
} }
/// <summary>
/// True iff this option may appear at most once in a datagram.
/// </summary>
public override bool IsAppearsAtMostOnce public override bool IsAppearsAtMostOnce
{ {
get { return true; } get { return true; }
} }
/// <summary>
/// Two routes options are equal iff they have the same type, same pointed address index and same route.
/// </summary>
public bool Equals(IpV4OptionRoute other) public bool Equals(IpV4OptionRoute other)
{ {
if (other == null) if (other == null)
...@@ -37,23 +71,24 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -37,23 +71,24 @@ namespace PcapDotNet.Packets.IpV4
Route.SequenceEqual(other.Route); Route.SequenceEqual(other.Route);
} }
/// <summary>
/// Two routes options are equal iff they have the same type, same pointed address index and same route.
/// </summary>
public override bool Equals(IpV4Option other) public override bool Equals(IpV4Option other)
{ {
return Equals(other as IpV4OptionRoute); return Equals(other as IpV4OptionRoute);
} }
/// <summary>
/// The hash code of the route option is the xor of the following hash codes: base class, pointed address index and all the addresses in the route.
/// </summary>
public override int GetHashCode() public override int GetHashCode()
{ {
return base.GetHashCode() ^ return base.GetHashCode() ^
PointedAddressIndex ^ PointedAddressIndex.GetHashCode() ^
Route.SequenceGetHashCode(); Route.SequenceGetHashCode();
} }
public ReadOnlyCollection<IpV4Address> Route
{
get { return _addresses; }
}
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);
...@@ -63,6 +98,15 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -63,6 +98,15 @@ namespace PcapDotNet.Packets.IpV4
buffer.Write(ref offset, address, Endianity.Big); buffer.Write(ref offset, address, Endianity.Big);
} }
/// <summary>
/// Tries to read the value of the route option from the given buffer.
/// </summary>
/// <param name="addresses">The route read from the buffer.</param>
/// <param name="pointedAddressIndex">The index pointed in the route read from the buffer.</param>
/// <param name="buffer">The buffer to read the value from.</param>
/// <param name="offset">The offset in the buffer to start reading the value from.</param>
/// <param name="valueLength">The number of bytes that the value should be.</param>
/// <returns>True iff the read was successful.</returns>
protected static bool TryRead(out IpV4Address[] addresses, out byte pointedAddressIndex, protected static bool TryRead(out IpV4Address[] addresses, out byte pointedAddressIndex,
byte[] buffer, ref int offset, byte valueLength) byte[] buffer, ref int offset, byte valueLength)
{ {
...@@ -89,17 +133,20 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -89,17 +133,20 @@ namespace PcapDotNet.Packets.IpV4
return true; return true;
} }
protected IpV4OptionRoute(IpV4OptionType optionType, IList<IpV4Address> addresses, byte pointedAddressIndex) /// <summary>
/// Construct a route option from the given values.
/// </summary>
protected IpV4OptionRoute(IpV4OptionType optionType, IList<IpV4Address> route, byte pointedAddressIndex)
: base(optionType) : base(optionType)
{ {
if (pointedAddressIndex > PointedAddressIndexMaxValue) if (pointedAddressIndex > PointedAddressIndexMaxValue)
throw new ArgumentOutOfRangeException("pointedAddressIndex", pointedAddressIndex, "Maximum value is " + PointedAddressIndexMaxValue); throw new ArgumentOutOfRangeException("pointedAddressIndex", pointedAddressIndex, "Maximum value is " + PointedAddressIndexMaxValue);
_addresses = addresses.AsReadOnly(); _route = route.AsReadOnly();
_pointedAddressIndex = pointedAddressIndex; _pointedAddressIndex = pointedAddressIndex;
} }
private readonly ReadOnlyCollection<IpV4Address> _addresses; private readonly ReadOnlyCollection<IpV4Address> _route;
private readonly byte _pointedAddressIndex; private readonly byte _pointedAddressIndex;
} }
} }
\ No newline at end of file
...@@ -17,9 +17,35 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -17,9 +17,35 @@ namespace PcapDotNet.Packets.IpV4
/// </summary> /// </summary>
public class IpV4OptionSecurity : IpV4OptionComplex, IEquatable<IpV4OptionSecurity> public class IpV4OptionSecurity : IpV4OptionComplex, IEquatable<IpV4OptionSecurity>
{ {
/// <summary>
/// The number of bytes this option take.
/// </summary>
public const int OptionLength = 11; public const int OptionLength = 11;
/// <summary>
/// The number of bytes this option's value take.
/// </summary>
public const int OptionValueLength = OptionLength - OptionHeaderLength; public const int OptionValueLength = OptionLength - OptionHeaderLength;
/// <summary>
/// Create the security option from the different security field values.
/// </summary>
/// <param name="level">Specifies one of the levels of security.</param>
/// <param name="compartments">
/// Compartments (C field): 16 bits
/// An all zero value is used when the information transmitted is not compartmented.
/// Other values for the compartments field may be obtained from the Defense Intelligence Agency.
/// </param>
/// <param name="handlingRestrictions">
/// Handling Restrictions (H field): 16 bits
/// The values for the control and release markings are alphanumeric digraphs
/// and are defined in the Defense Intelligence Agency Manual DIAM 65-19, "Standard Security Markings".
/// </param>
/// <param name="transmissionControlCode">
/// Transmission Control Code (TCC field): 24 bits
/// Provides a means to segregate traffic and define controlled communities of interest among subscribers.
/// The TCC values are trigraphs, and are available from HQ DCA Code 530.
/// </param>
public IpV4OptionSecurity(IpV4OptionSecurityLevel level, ushort compartments, public IpV4OptionSecurity(IpV4OptionSecurityLevel level, ushort compartments,
ushort handlingRestrictions, UInt24 transmissionControlCode) ushort handlingRestrictions, UInt24 transmissionControlCode)
: base(IpV4OptionType.Security) : base(IpV4OptionType.Security)
...@@ -68,16 +94,25 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -68,16 +94,25 @@ namespace PcapDotNet.Packets.IpV4
get { return _transmissionControlCode; } get { return _transmissionControlCode; }
} }
/// <summary>
/// The number of bytes this option will take.
/// </summary>
public override int Length public override int Length
{ {
get { return OptionLength; } get { return OptionLength; }
} }
/// <summary>
/// True iff this option may appear at most once in a datagram.
/// </summary>
public override bool IsAppearsAtMostOnce public override bool IsAppearsAtMostOnce
{ {
get { return true; } get { return true; }
} }
/// <summary>
/// Two security options are equal iff they have the exam same field values.
/// </summary>
public bool Equals(IpV4OptionSecurity other) public bool Equals(IpV4OptionSecurity other)
{ {
if (other == null) if (other == null)
...@@ -89,16 +124,23 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -89,16 +124,23 @@ namespace PcapDotNet.Packets.IpV4
TransmissionControlCode == other.TransmissionControlCode; TransmissionControlCode == other.TransmissionControlCode;
} }
/// <summary>
/// Two security options are equal iff they have the exam same field values.
/// </summary>
public override bool Equals(IpV4Option other) public override bool Equals(IpV4Option other)
{ {
return Equals(other as IpV4OptionSecurity); return Equals(other as IpV4OptionSecurity);
} }
/// <summary>
/// The hash code is the xor of the following hash code: base class hash code, level and compartments, handling restrictions, transmission control code.
/// </summary>
/// <returns></returns>
public override int GetHashCode() public override int GetHashCode()
{ {
return base.GetHashCode() ^ return base.GetHashCode() ^
(((ushort)Level << 16) | Compartments) ^ (((ushort)Level << 16) | Compartments).GetHashCode() ^
(HandlingRestrictions << 16) ^ (HandlingRestrictions << 16).GetHashCode() ^
TransmissionControlCode.GetHashCode(); TransmissionControlCode.GetHashCode();
} }
......
...@@ -2,15 +2,27 @@ using System; ...@@ -2,15 +2,27 @@ using System;
namespace PcapDotNet.Packets.IpV4 namespace PcapDotNet.Packets.IpV4
{ {
/// <summary>
/// A simple IPv4 option - holds only the type.
/// </summary>
public class IpV4OptionSimple : IpV4Option public class IpV4OptionSimple : IpV4Option
{ {
/// <summary>
/// The number of bytes this option will take.
/// </summary>
public const int OptionLength = 1; public const int OptionLength = 1;
/// <summary>
/// The number of bytes this option will take.
/// </summary>
public override int Length public override int Length
{ {
get { return OptionLength; } get { return OptionLength; }
} }
/// <summary>
/// True iff this option may appear at most once in a datagram.
/// </summary>
public override bool IsAppearsAtMostOnce public override bool IsAppearsAtMostOnce
{ {
get { return false; } get { return false; }
......
...@@ -3,7 +3,7 @@ using System; ...@@ -3,7 +3,7 @@ using System;
namespace PcapDotNet.Packets.IpV4 namespace PcapDotNet.Packets.IpV4
{ {
/// <summary> /// <summary>
/// Stream Identifier /// Stream Identifier option.
/// +--------+--------+--------+--------+ /// +--------+--------+--------+--------+
/// |10001000|00000010| Stream ID | /// |10001000|00000010| Stream ID |
/// +--------+--------+--------+--------+ /// +--------+--------+--------+--------+
...@@ -16,30 +16,52 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -16,30 +16,52 @@ namespace PcapDotNet.Packets.IpV4
/// </summary> /// </summary>
public class IpV4OptionStreamIdentifier : IpV4OptionComplex, IEquatable<IpV4OptionStreamIdentifier> public class IpV4OptionStreamIdentifier : IpV4OptionComplex, IEquatable<IpV4OptionStreamIdentifier>
{ {
/// <summary>
/// The number of bytes this option take.
/// </summary>
public const int OptionLength = 4; public const int OptionLength = 4;
/// <summary>
/// The number of bytes this option's value take.
/// </summary>
public const int OptionValueLength = OptionLength - OptionHeaderLength; public const int OptionValueLength = OptionLength - OptionHeaderLength;
/// <summary>
/// Create the option according to the given identifier.
/// </summary>
public IpV4OptionStreamIdentifier(ushort identifier) public IpV4OptionStreamIdentifier(ushort identifier)
: base(IpV4OptionType.StreamIdentifier) : base(IpV4OptionType.StreamIdentifier)
{ {
_identifier = identifier; _identifier = identifier;
} }
/// <summary>
/// The identifier of the stream.
/// </summary>
public ushort Identifier public ushort Identifier
{ {
get { return _identifier; } get { return _identifier; }
} }
/// <summary>
/// The number of bytes this option will take.
/// </summary>
public override int Length public override int Length
{ {
get { return OptionLength; } get { return OptionLength; }
} }
/// <summary>
/// True iff this option may appear at most once in a datagram.
/// </summary>
public override bool IsAppearsAtMostOnce public override bool IsAppearsAtMostOnce
{ {
get { return true; } get { return true; }
} }
/// <summary>
/// Two stream identifier options are equal if they have the same identifier.
/// </summary>
public bool Equals(IpV4OptionStreamIdentifier other) public bool Equals(IpV4OptionStreamIdentifier other)
{ {
if (other == null) if (other == null)
...@@ -47,11 +69,18 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -47,11 +69,18 @@ namespace PcapDotNet.Packets.IpV4
return Identifier == other.Identifier; return Identifier == other.Identifier;
} }
/// <summary>
/// Two stream identifier options are equal if they have the same identifier.
/// </summary>
public override bool Equals(IpV4Option other) public override bool Equals(IpV4Option other)
{ {
return Equals(other as IpV4OptionStreamIdentifier); return Equals(other as IpV4OptionStreamIdentifier);
} }
/// <summary>
/// The hash code value is the xor of the base class hash code and the identifier hash code.
/// </summary>
/// <returns></returns>
public override int GetHashCode() public override int GetHashCode()
{ {
return base.GetHashCode() ^ return base.GetHashCode() ^
......
...@@ -45,8 +45,11 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -45,8 +45,11 @@ namespace PcapDotNet.Packets.IpV4
/// </summary> /// </summary>
public class IpV4OptionStrictSourceRouting : IpV4OptionRoute public class IpV4OptionStrictSourceRouting : IpV4OptionRoute
{ {
public IpV4OptionStrictSourceRouting(IList<IpV4Address> addresses, byte pointedAddressIndex) /// <summary>
: base(IpV4OptionType.StrictSourceRouting, addresses, pointedAddressIndex) /// Create the option according to the given values.
/// </summary>
public IpV4OptionStrictSourceRouting(IList<IpV4Address> route, byte pointedAddressIndex)
: base(IpV4OptionType.StrictSourceRouting, route, pointedAddressIndex)
{ {
} }
......
using System;
namespace PcapDotNet.Packets.IpV4
{
/// <summary>
/// Represents the time passed since midnight UT.
/// </summary>
public struct IpV4OptionTimeOfDay : IEquatable<IpV4OptionTimeOfDay>
{
/// <summary>
/// Create the time from milliseconds since midnight UT.
/// </summary>
public IpV4OptionTimeOfDay(uint millisecondsSinceMidnightUniversalTime)
{
_millisecondsSinceMidnightUniversalTime = millisecondsSinceMidnightUniversalTime;
}
/// <summary>
/// Create the time from TimeSpan since midnight UT.
/// </summary>
public IpV4OptionTimeOfDay(TimeSpan timeOfDaySinceMidnightUniversalTime)
: this((uint)timeOfDaySinceMidnightUniversalTime.TotalMilliseconds)
{
}
/// <summary>
/// Number of milliseconds passed since midnight UT.
/// </summary>
public uint MillisecondsSinceMidnightUniversalTime
{
get { return _millisecondsSinceMidnightUniversalTime; }
}
/// <summary>
/// Time passed since midnight UT.
/// </summary>
public TimeSpan TimeSinceMidnightUniversalTime
{
get { return TimeSpan.FromMilliseconds(MillisecondsSinceMidnightUniversalTime); }
}
/// <summary>
/// Two times are equal if the have the exact same value.
/// </summary>
public bool Equals(IpV4OptionTimeOfDay other)
{
return MillisecondsSinceMidnightUniversalTime == other.MillisecondsSinceMidnightUniversalTime;
}
/// <summary>
/// Two times are equal if the have the exact same value.
/// </summary>
public override bool Equals(object obj)
{
return (obj is IpV4OptionTimeOfDay &&
Equals((IpV4OptionTimeOfDay)obj));
}
/// <summary>
/// Two times are equal if the have the exact same value.
/// </summary>
public static bool operator ==(IpV4OptionTimeOfDay value1, IpV4OptionTimeOfDay value2)
{
return value1.Equals(value2);
}
/// <summary>
/// Two times are different if the have different values.
/// </summary>
public static bool operator !=(IpV4OptionTimeOfDay value1, IpV4OptionTimeOfDay value2)
{
return !(value1 == value2);
}
/// <summary>
/// The hash code of a time is the hash code of the milliseconds since midnight UT value.
/// </summary>
public override int GetHashCode()
{
return MillisecondsSinceMidnightUniversalTime.GetHashCode();
}
private readonly uint _millisecondsSinceMidnightUniversalTime;
}
}
\ No newline at end of file
...@@ -2,58 +2,82 @@ using System; ...@@ -2,58 +2,82 @@ using System;
namespace PcapDotNet.Packets.IpV4 namespace PcapDotNet.Packets.IpV4
{ {
/// <summary>
/// A pair of address and its time in the day.
/// </summary>
public struct IpV4OptionTimedAddress : IEquatable<IpV4OptionTimedAddress> public struct IpV4OptionTimedAddress : IEquatable<IpV4OptionTimedAddress>
{ {
public IpV4OptionTimedAddress(IpV4Address address, uint timestamp) /// <summary>
/// Create a timed address accroding to the given values.
/// </summary>
/// <param name="address">The address in the pair.</param>
/// <param name="timeOfDay">The time passed since midnight UT.</param>
public IpV4OptionTimedAddress(IpV4Address address, IpV4OptionTimeOfDay timeOfDay)
{ {
_address = address; _address = address;
_millisecondsSinceMidnightUt = timestamp; _timeOfDay = timeOfDay;
} }
/// <summary>
/// The address.
/// </summary>
public IpV4Address Address public IpV4Address Address
{ {
get { return _address; } get { return _address; }
} }
public uint MillisecondsSinceMidnight /// <summary>
/// The time passed since midnight UT.
/// </summary>
public IpV4OptionTimeOfDay TimeOfDay
{ {
get { return _millisecondsSinceMidnightUt; } get { return _timeOfDay; }
}
public TimeSpan TimeOfDay
{
get { return TimeSpan.FromMilliseconds(MillisecondsSinceMidnight); }
} }
/// <summary>
/// Two options are equal if they have the same address and time passed since midnight UT.
/// </summary>
public bool Equals(IpV4OptionTimedAddress other) public bool Equals(IpV4OptionTimedAddress other)
{ {
return Address == other.Address && return Address.Equals(other.Address) &&
MillisecondsSinceMidnight == other.MillisecondsSinceMidnight; TimeOfDay.Equals(other.TimeOfDay);
} }
/// <summary>
/// Two options are equal if they have the same address and time passed since midnight UT.
/// </summary>
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
return (obj is IpV4OptionTimedAddress) && return (obj is IpV4OptionTimedAddress) &&
Equals((IpV4OptionTimedAddress)obj); Equals((IpV4OptionTimedAddress)obj);
} }
/// <summary>
/// Two options are equal if they have the same address and time passed since midnight UT.
/// </summary>
public static bool operator ==(IpV4OptionTimedAddress value1, IpV4OptionTimedAddress value2) public static bool operator ==(IpV4OptionTimedAddress value1, IpV4OptionTimedAddress value2)
{ {
return value1.Equals(value2); return value1.Equals(value2);
} }
/// <summary>
/// Two options are different if they have different addresses or time passed since midnight UT.
/// </summary>
public static bool operator !=(IpV4OptionTimedAddress value1, IpV4OptionTimedAddress value2) public static bool operator !=(IpV4OptionTimedAddress value1, IpV4OptionTimedAddress value2)
{ {
return !(value1 == value2); return !(value1 == value2);
} }
/// <summary>
/// Returns the xor of the address hash code and the time in the day hash code.
/// </summary>
public override int GetHashCode() public override int GetHashCode()
{ {
return _address.GetHashCode() ^ return _address.GetHashCode() ^
(int)_millisecondsSinceMidnightUt; _timeOfDay.GetHashCode();
} }
private readonly IpV4Address _address; private readonly IpV4Address _address;
private readonly uint _millisecondsSinceMidnightUt; private readonly IpV4OptionTimeOfDay _timeOfDay;
} }
} }
\ No newline at end of file
...@@ -52,26 +52,54 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -52,26 +52,54 @@ namespace PcapDotNet.Packets.IpV4
/// </summary> /// </summary>
public abstract class IpV4OptionTimestamp : IpV4OptionComplex, IEquatable<IpV4OptionTimestamp> public abstract class IpV4OptionTimestamp : IpV4OptionComplex, IEquatable<IpV4OptionTimestamp>
{ {
/// <summary>
/// The minimum length in bytes for the option (type, length, pointer, overflow and flags).
/// </summary>
public const int OptionMinimumLength = 4; public const int OptionMinimumLength = 4;
/// <summary>
/// The minimum length in bytes of the option value.
/// </summary>
public const int OptionValueMinimumLength = OptionMinimumLength - OptionHeaderLength; public const int OptionValueMinimumLength = OptionMinimumLength - OptionHeaderLength;
/// <summary>
/// The maximum value for the overflow field.
/// </summary>
public const int OverflowMaxValue = 15; public const int OverflowMaxValue = 15;
/// <summary>
/// The maximum value for the pointed index field.
/// </summary>
public const int PointedIndexMaxValue = byte.MaxValue / 4 - 1; public const int PointedIndexMaxValue = byte.MaxValue / 4 - 1;
/// <summary>
/// The timestamp option type.
/// </summary>
public IpV4OptionTimestampType TimestampType public IpV4OptionTimestampType TimestampType
{ {
get { return _timestampType; } get { return _timestampType; }
} }
/// <summary>
/// The number of IP modules that cannot register timestamps due to lack of space.
/// </summary>
public byte Overflow public byte Overflow
{ {
get { return _overflow; } get { return _overflow; }
} }
/// <summary>
/// The index in the timestamp that points to the for next timestamp.
/// The timestamp area is considered full when the index points beyond the timestamps.
/// </summary>
public byte PointedIndex public byte PointedIndex
{ {
get { return _pointedIndex; } get { return _pointedIndex; }
} }
/// <summary>
/// The number of bytes this option will take.
/// </summary>
public override int Length public override int Length
{ {
get get
...@@ -81,12 +109,17 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -81,12 +109,17 @@ namespace PcapDotNet.Packets.IpV4
} }
} }
/// <summary>
/// True iff this option may appear at most once in a datagram.
/// </summary>
public override bool IsAppearsAtMostOnce public override bool IsAppearsAtMostOnce
{ {
get { return true; } get { return true; }
} }
/// <summary>
/// Two options are equal if they have the same value (timestamp, overflow, pointed equals, addresses and timestamps).
/// </summary>
public bool Equals(IpV4OptionTimestamp other) public bool Equals(IpV4OptionTimestamp other)
{ {
if (other == null) if (other == null)
...@@ -98,17 +131,22 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -98,17 +131,22 @@ namespace PcapDotNet.Packets.IpV4
EqualValues(other); EqualValues(other);
} }
/// <summary>
/// Two options are equal if they have the same value (timestamp, overflow, pointed equals and addresses).
/// </summary>
public override bool Equals(IpV4Option other) public override bool Equals(IpV4Option other)
{ {
return Equals(other as IpV4OptionTimestamp); return Equals(other as IpV4OptionTimestamp);
} }
/// <summary>
/// The hash code is the xor of the base class hash code, the timestamp and overflow hash code and the pointed index hash code.
/// </summary>
public override int GetHashCode() public override int GetHashCode()
{ {
return base.GetHashCode() ^ return base.GetHashCode() ^
((byte)TimestampType << 16) ^ (((byte)TimestampType << 16) | (Overflow << 8)).GetHashCode() ^
(Overflow << 8) ^ PointedIndex.GetHashCode();
PointedIndex;
} }
internal static IpV4OptionTimestamp ReadOptionTimestamp(byte[] buffer, ref int offset, int valueLength) internal static IpV4OptionTimestamp ReadOptionTimestamp(byte[] buffer, ref int offset, int valueLength)
...@@ -151,6 +189,12 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -151,6 +189,12 @@ namespace PcapDotNet.Packets.IpV4
WriteValues(buffer, ref offset); WriteValues(buffer, ref offset);
} }
/// <summary>
/// Create the option by giving it all the data.
/// </summary>
/// <param name="timestampType">The timestamp option type.</param>
/// <param name="overflow">The number of IP modules that cannot register timestamps due to lack of space. Maximum value is 15.</param>
/// <param name="pointedIndex">The index in the timestamp to points to the octet beginning the space for next timestamp. The timestamp area is considered full when the index points beyond the timestamps.</param>
protected IpV4OptionTimestamp(IpV4OptionTimestampType timestampType, byte overflow, byte pointedIndex) protected IpV4OptionTimestamp(IpV4OptionTimestampType timestampType, byte overflow, byte pointedIndex)
: base(IpV4OptionType.InternetTimestamp) : base(IpV4OptionType.InternetTimestamp)
{ {
...@@ -165,10 +209,19 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -165,10 +209,19 @@ namespace PcapDotNet.Packets.IpV4
_pointedIndex = pointedIndex; _pointedIndex = pointedIndex;
} }
/// <summary>
/// The number of bytes the value of the option take.
/// </summary>
protected abstract int ValuesLength { get; } protected abstract int ValuesLength { get; }
/// <summary>
/// True iff the options values is equal.
/// </summary>
protected abstract bool EqualValues(IpV4OptionTimestamp other); protected abstract bool EqualValues(IpV4OptionTimestamp other);
/// <summary>
/// Writes the value of the option to the buffer.
/// </summary>
protected abstract void WriteValues(byte[] buffer, ref int offset); protected abstract void WriteValues(byte[] buffer, ref int offset);
private readonly IpV4OptionTimestampType _timestampType; private readonly IpV4OptionTimestampType _timestampType;
......
...@@ -6,9 +6,19 @@ using PcapDotNet.Base; ...@@ -6,9 +6,19 @@ using PcapDotNet.Base;
namespace PcapDotNet.Packets.IpV4 namespace PcapDotNet.Packets.IpV4
{ {
///<summary>
/// Represents a timestamp IPv4 option with each timestamp preceded with internet address of the registering entity or the internet address fields are prespecified.
///</summary>
public class IpV4OptionTimestampAndAddress : IpV4OptionTimestamp public class IpV4OptionTimestampAndAddress : IpV4OptionTimestamp
{ {
public IpV4OptionTimestampAndAddress(IpV4OptionTimestampType timestampType, byte overflow, byte pointedIndex, IList<IpV4OptionTimedAddress> addressesAndTimestamps) /// <summary>
/// Create the option by giving it all the data.
/// </summary>
/// <param name="timestampType">The timestamp option type.</param>
/// <param name="overflow">The number of IP modules that cannot register timestamps due to lack of space. Maximum value is 15.</param>
/// <param name="pointedIndex">The index in the timestamp that points to the for next timestamp.</param>
/// <param name="timedRoute">The pairs of addresses and timestamps where each timestamp time passed since midnight UT.</param>
public IpV4OptionTimestampAndAddress(IpV4OptionTimestampType timestampType, byte overflow, byte pointedIndex, IList<IpV4OptionTimedAddress> timedRoute)
: base(timestampType, overflow, pointedIndex) : base(timestampType, overflow, pointedIndex)
{ {
if (timestampType != IpV4OptionTimestampType.AddressAndTimestamp && if (timestampType != IpV4OptionTimestampType.AddressAndTimestamp &&
...@@ -17,14 +27,32 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -17,14 +27,32 @@ namespace PcapDotNet.Packets.IpV4
throw new ArgumentException("Illegal timestamp type " + timestampType, "timestampType"); throw new ArgumentException("Illegal timestamp type " + timestampType, "timestampType");
} }
_addressesAndTimestamps = addressesAndTimestamps.AsReadOnly(); _addressesAndTimestamps = timedRoute.AsReadOnly();
} }
/// <summary>
/// Create the option by giving it all the data.
/// </summary>
/// <param name="timestampType">The timestamp option type.</param>
/// <param name="overflow">The number of IP modules that cannot register timestamps due to lack of space. Maximum value is 15.</param>
/// <param name="pointedIndex">The index in the timestamp that points to the for next timestamp.</param>
/// <param name="timedRoute">The pairs of addresses and timestamps where each timestamp time passed since midnight UT.</param>
public IpV4OptionTimestampAndAddress(IpV4OptionTimestampType timestampType, byte overflow, byte pointedIndex, params IpV4OptionTimedAddress[] timedRoute)
: this(timestampType, overflow, pointedIndex, (IList<IpV4OptionTimedAddress>)timedRoute)
{
}
/// <summary>
/// The pairs of addresses and timestamps where each timestamp time passed since midnight UT.
/// </summary>
public ReadOnlyCollection<IpV4OptionTimedAddress> TimedRoute public ReadOnlyCollection<IpV4OptionTimedAddress> TimedRoute
{ {
get { return _addressesAndTimestamps; } get { return _addressesAndTimestamps; }
} }
/// <summary>
/// The hash of this option is the base class hash xored with the hash of each timestamp.
/// </summary>
public override int GetHashCode() public override int GetHashCode()
{ {
return base.GetHashCode() ^ TimedRoute.SequenceGetHashCode(); return base.GetHashCode() ^ TimedRoute.SequenceGetHashCode();
...@@ -39,28 +67,37 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -39,28 +67,37 @@ namespace PcapDotNet.Packets.IpV4
for (int i = 0; i != numValues / 2; ++i) for (int i = 0; i != numValues / 2; ++i)
{ {
addressesAndTimestamps[i] = new IpV4OptionTimedAddress(buffer.ReadIpV4Address(ref offset, Endianity.Big), addressesAndTimestamps[i] = new IpV4OptionTimedAddress(buffer.ReadIpV4Address(ref offset, Endianity.Big),
buffer.ReadUInt(ref offset, Endianity.Big)); buffer.ReadIpV4OptionTimeOfDay(ref offset, Endianity.Big));
} }
return new IpV4OptionTimestampAndAddress(timestampType, overflow, pointedIndex, addressesAndTimestamps); return new IpV4OptionTimestampAndAddress(timestampType, overflow, pointedIndex, addressesAndTimestamps);
} }
/// <summary>
/// The number of bytes the value of the option take.
/// </summary>
protected override int ValuesLength protected override int ValuesLength
{ {
get { return TimedRoute.Count * (IpV4Address.SizeOf + sizeof(uint)); } get { return TimedRoute.Count * (IpV4Address.SizeOf + sizeof(uint)); }
} }
/// <summary>
/// True iff the options values is equal.
/// </summary>
protected override bool EqualValues(IpV4OptionTimestamp other) protected override bool EqualValues(IpV4OptionTimestamp other)
{ {
return TimedRoute.SequenceEqual(((IpV4OptionTimestampAndAddress)other).TimedRoute); return TimedRoute.SequenceEqual(((IpV4OptionTimestampAndAddress)other).TimedRoute);
} }
/// <summary>
/// Writes the value of the option to the buffer.
/// </summary>
protected override void WriteValues(byte[] buffer, ref int offset) protected override void WriteValues(byte[] buffer, ref int offset)
{ {
foreach (IpV4OptionTimedAddress addressAndTimestamp in TimedRoute) foreach (IpV4OptionTimedAddress addressAndTimestamp in TimedRoute)
{ {
buffer.Write(ref offset, addressAndTimestamp.Address, Endianity.Big); buffer.Write(ref offset, addressAndTimestamp.Address, Endianity.Big);
buffer.Write(ref offset, addressAndTimestamp.MillisecondsSinceMidnight, Endianity.Big); buffer.Write(ref offset, addressAndTimestamp.TimeOfDay, Endianity.Big);
} }
} }
......
...@@ -6,24 +6,45 @@ using PcapDotNet.Base; ...@@ -6,24 +6,45 @@ using PcapDotNet.Base;
namespace PcapDotNet.Packets.IpV4 namespace PcapDotNet.Packets.IpV4
{ {
/// <summary>
/// Represents a timestamp IPv4 option with only the timestamps.
/// </summary>
public class IpV4OptionTimestampOnly : IpV4OptionTimestamp public class IpV4OptionTimestampOnly : IpV4OptionTimestamp
{ {
public IpV4OptionTimestampOnly(byte overflow, byte pointedIndex, IList<uint> timestamps) /// <summary>
/// Create the option by giving it all the data.
/// </summary>
/// <param name="overflow">The number of IP modules that cannot register timestamps due to lack of space. Maximum value is 15.</param>
/// <param name="pointedIndex">The index in the timestamp that points to the for next timestamp.</param>
/// <param name="timestamps">The timestamps as time passed since midnight UT.</param>
public IpV4OptionTimestampOnly(byte overflow, byte pointedIndex, IList<IpV4OptionTimeOfDay> timestamps)
: base(IpV4OptionTimestampType.TimestampOnly, overflow, pointedIndex) : base(IpV4OptionTimestampType.TimestampOnly, overflow, pointedIndex)
{ {
_timestamps = timestamps.AsReadOnly(); _timestamps = timestamps.AsReadOnly();
} }
public IpV4OptionTimestampOnly(byte overflow, byte pointedIndex, params uint[] timestamps) /// <summary>
: this(overflow, pointedIndex, (IList<uint>)timestamps) /// Create the option by giving it all the data.
/// </summary>
/// <param name="overflow">The number of IP modules that cannot register timestamps due to lack of space. Maximum value is 15.</param>
/// <param name="pointedIndex">The index in the timestamp that points to the for next timestamp.</param>
/// <param name="timestamps">The timestamps as time passed since midnight UT.</param>
public IpV4OptionTimestampOnly(byte overflow, byte pointedIndex, params IpV4OptionTimeOfDay[] timestamps)
: this(overflow, pointedIndex, (IList<IpV4OptionTimeOfDay>)timestamps)
{ {
} }
public ReadOnlyCollection<uint> Timestamps /// <summary>
/// The timestamps as time passed since midnight UT.
/// </summary>
public ReadOnlyCollection<IpV4OptionTimeOfDay> Timestamps
{ {
get { return _timestamps; } get { return _timestamps; }
} }
/// <summary>
/// The hash code of this options is the hash code of the base class xored with the hash code of the timestamps.
/// </summary>
public override int GetHashCode() public override int GetHashCode()
{ {
return base.GetHashCode() ^ Timestamps.SequenceGetHashCode(); return base.GetHashCode() ^ Timestamps.SequenceGetHashCode();
...@@ -31,29 +52,38 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -31,29 +52,38 @@ namespace PcapDotNet.Packets.IpV4
internal static IpV4OptionTimestampOnly Read(byte overflow, byte pointedIndex, byte[] buffer, ref int offset, int numValues) internal static IpV4OptionTimestampOnly Read(byte overflow, byte pointedIndex, byte[] buffer, ref int offset, int numValues)
{ {
uint[] timestamps = new uint[numValues]; IpV4OptionTimeOfDay[] timestamps = new IpV4OptionTimeOfDay[numValues];
for (int i = 0; i != numValues; ++i) for (int i = 0; i != numValues; ++i)
timestamps[i] = buffer.ReadUInt(ref offset, Endianity.Big); timestamps[i] = buffer.ReadIpV4OptionTimeOfDay(ref offset, Endianity.Big);
return new IpV4OptionTimestampOnly(overflow, pointedIndex, timestamps); return new IpV4OptionTimestampOnly(overflow, pointedIndex, timestamps);
} }
/// <summary>
/// The number of bytes the value of the option take.
/// </summary>
protected override int ValuesLength protected override int ValuesLength
{ {
get { return Timestamps.Count * sizeof(uint); } get { return Timestamps.Count * sizeof(uint); }
} }
/// <summary>
/// Compares the values of the options.
/// </summary>
protected override bool EqualValues(IpV4OptionTimestamp other) protected override bool EqualValues(IpV4OptionTimestamp other)
{ {
return Timestamps.SequenceEqual(((IpV4OptionTimestampOnly)other).Timestamps); return Timestamps.SequenceEqual(((IpV4OptionTimestampOnly)other).Timestamps);
} }
/// <summary>
/// Writes the value of the option to the buffer.
/// </summary>
protected override void WriteValues(byte[] buffer, ref int offset) protected override void WriteValues(byte[] buffer, ref int offset)
{ {
foreach (uint timestamp in Timestamps) foreach (IpV4OptionTimeOfDay timestamp in Timestamps)
buffer.Write(ref offset, timestamp, Endianity.Big); buffer.Write(ref offset, timestamp.MillisecondsSinceMidnightUniversalTime, Endianity.Big);
} }
private readonly ReadOnlyCollection<uint> _timestamps; private readonly ReadOnlyCollection<IpV4OptionTimeOfDay> _timestamps;
} }
} }
\ No newline at end of file
...@@ -2,10 +2,25 @@ using System; ...@@ -2,10 +2,25 @@ using System;
namespace PcapDotNet.Packets.IpV4 namespace PcapDotNet.Packets.IpV4
{ {
/// <summary>
/// The type of the timestamp ip option.
/// </summary>
public enum IpV4OptionTimestampType : byte public enum IpV4OptionTimestampType : byte
{ {
/// <summary>
/// Time stamps only, stored in consecutive 32-bit words.
/// </summary>
TimestampOnly = 0, TimestampOnly = 0,
/// <summary>
/// Each timestamp is preceded with internet address of the registering entity.
/// </summary>
AddressAndTimestamp = 1, AddressAndTimestamp = 1,
/// <summary>
/// The internet address fields are prespecified.
/// An IP module only registers its timestamp if it matches its own address with the next specified internet address.
/// </summary>
AddressPrespecified = 3 AddressPrespecified = 3
} }
} }
\ No newline at end of file
...@@ -23,36 +23,43 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -23,36 +23,43 @@ namespace PcapDotNet.Packets.IpV4
/// This option occupies only 1 octet; it has no length octet. /// This option occupies only 1 octet; it has no length octet.
/// </summary> /// </summary>
EndOfOptionList = 0, EndOfOptionList = 0,
/// <summary> /// <summary>
/// No Operation. /// No Operation.
/// This option occupies only 1 octet; it has no length octet. /// This option occupies only 1 octet; it has no length octet.
/// </summary> /// </summary>
NoOperation = 1, NoOperation = 1,
/// <summary> /// <summary>
/// Security. /// Security.
/// Used to carry Security, Compartmentation, User Group (TCC), and Handling Restriction Codes compatible with DOD requirements. /// Used to carry Security, Compartmentation, User Group (TCC), and Handling Restriction Codes compatible with DOD requirements.
/// </summary> /// </summary>
Security = 130, Security = 130,
/// <summary> /// <summary>
/// Loose Source Routing. /// Loose Source Routing.
/// Used to route the internet datagram based on information supplied by the source. /// Used to route the internet datagram based on information supplied by the source.
/// </summary> /// </summary>
LooseSourceRouting = 131, LooseSourceRouting = 131,
/// <summary> /// <summary>
/// Strict Source Routing. /// Strict Source Routing.
/// Used to route the internet datagram based on information supplied by the source. /// Used to route the internet datagram based on information supplied by the source.
/// </summary> /// </summary>
StrictSourceRouting = 137, StrictSourceRouting = 137,
/// <summary> /// <summary>
/// Record Route. /// Record Route.
/// Used to trace the route an internet datagram takes. /// Used to trace the route an internet datagram takes.
/// </summary> /// </summary>
RecordRoute = 7, RecordRoute = 7,
/// <summary> /// <summary>
/// Stream ID. /// Stream ID.
/// Used to carry the stream identifier. /// Used to carry the stream identifier.
/// </summary> /// </summary>
StreamIdentifier = 136, StreamIdentifier = 136,
/// <summary> /// <summary>
/// Internet Timestamp. /// Internet Timestamp.
/// </summary> /// </summary>
......
...@@ -6,15 +6,31 @@ using PcapDotNet.Base; ...@@ -6,15 +6,31 @@ using PcapDotNet.Base;
namespace PcapDotNet.Packets.IpV4 namespace PcapDotNet.Packets.IpV4
{ {
/// <summary>
/// Represents IPv4 Options.
/// The options may appear or not in datagrams.
/// They must be implemented by all IP modules (host and gateways).
/// What is optional is their transmission in any particular datagram, not their implementation.
/// </summary>
public class IpV4Options : ReadOnlyCollection<IpV4Option>, IEquatable<IpV4Options> public class IpV4Options : ReadOnlyCollection<IpV4Option>, IEquatable<IpV4Options>
{ {
/// <summary>
/// The maximum number of bytes the options may take.
/// </summary>
public const int MaximumBytesLength = IpV4Datagram.HeaderMaximumLength - IpV4Datagram.HeaderMinimumLength; public const int MaximumBytesLength = IpV4Datagram.HeaderMaximumLength - IpV4Datagram.HeaderMinimumLength;
/// <summary>
/// No options instance.
/// </summary>
public static IpV4Options None public static IpV4Options None
{ {
get { return _none; } get { return _none; }
} }
/// <summary>
/// Creates options from a list of options.
/// </summary>
/// <param name="options">The list of options.</param>
public IpV4Options(IList<IpV4Option> options) public IpV4Options(IList<IpV4Option> options)
: this(EndOptions(options), true) : this(EndOptions(options), true)
{ {
...@@ -22,21 +38,34 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -22,21 +38,34 @@ namespace PcapDotNet.Packets.IpV4
throw new ArgumentException("given options take " + BytesLength + " bytes and maximum number of bytes for options is " + MaximumBytesLength, "options"); throw new ArgumentException("given options take " + BytesLength + " bytes and maximum number of bytes for options is " + MaximumBytesLength, "options");
} }
/// <summary>
/// Creates options from a list of options.
/// </summary>
/// <param name="options">The list of options.</param>
public IpV4Options(params IpV4Option[] options) public IpV4Options(params IpV4Option[] options)
: this((IList<IpV4Option>)options) : this((IList<IpV4Option>)options)
{ {
} }
/// <summary>
/// The number of bytes the options take.
/// </summary>
public int BytesLength public int BytesLength
{ {
get { return _bytesLength; } get { return _bytesLength; }
} }
/// <summary>
/// Whether or not the options parsed ok.
/// </summary>
public bool IsValid public bool IsValid
{ {
get { return _isValid; } get { return _isValid; }
} }
/// <summary>
/// Two options are equal iff they have the exact same options.
/// </summary>
public bool Equals(IpV4Options other) public bool Equals(IpV4Options other)
{ {
if (other == null) if (other == null)
...@@ -48,17 +77,28 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -48,17 +77,28 @@ namespace PcapDotNet.Packets.IpV4
return this.SequenceEqual(other); return this.SequenceEqual(other);
} }
/// <summary>
/// Two options are equal iff they have the exact same options.
/// </summary>
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
return Equals(obj as IpV4Options); return Equals(obj as IpV4Options);
} }
/// <summary>
/// The hash code is the xor of the following hash codes: number of bytes the options take and all the options.
/// </summary>
/// <returns></returns>
public override int GetHashCode() public override int GetHashCode()
{ {
return BytesLength.GetHashCode() ^ return BytesLength.GetHashCode() ^
this.SequenceGetHashCode(); this.SequenceGetHashCode();
} }
/// <summary>
/// A string of all the option type names.
/// </summary>
/// <returns></returns>
public override string ToString() public override string ToString()
{ {
return this.SequenceToString(", ", typeof(IpV4Options).Name + " {", "}"); return this.SequenceToString(", ", typeof(IpV4Options).Name + " {", "}");
...@@ -70,6 +110,17 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -70,6 +110,17 @@ namespace PcapDotNet.Packets.IpV4
_bytesLength = length; _bytesLength = length;
} }
internal void Write(byte[] buffer, int offset)
{
int offsetEnd = offset + BytesLength;
foreach (IpV4Option option in this)
option.Write(buffer, ref offset);
// Padding
while (offset < offsetEnd)
buffer[offset++] = 0;
}
private IpV4Options(IList<IpV4Option> options, bool isValid) private IpV4Options(IList<IpV4Option> options, bool isValid)
: base(options) : base(options)
{ {
...@@ -122,17 +173,6 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -122,17 +173,6 @@ namespace PcapDotNet.Packets.IpV4
return new Tuple<IList<IpV4Option>, bool>(options, true); return new Tuple<IList<IpV4Option>, bool>(options, true);
} }
internal void Write(byte[] buffer, int offset)
{
int offsetEnd = offset + BytesLength;
foreach (IpV4Option option in this)
option.Write(buffer, ref offset);
// Padding
while (offset < offsetEnd)
buffer[offset++] = 0;
}
private readonly int _bytesLength; private readonly int _bytesLength;
private readonly bool _isValid; private readonly bool _isValid;
private static readonly IpV4Options _none = new IpV4Options(); private static readonly IpV4Options _none = new IpV4Options();
......
namespace PcapDotNet.Packets.IpV4 namespace PcapDotNet.Packets.IpV4
{ {
/// <summary>
/// Indicates the next level IPv4 protocol used in the pyaload of the IPv4 datagram.
/// </summary>
public enum IpV4Protocol : byte public enum IpV4Protocol : byte
{ {
/// <summary> /// <summary>
......
using System; using System;
using System.Linq;
using System.Net; using System.Net;
using PcapDotNet.Base; using PcapDotNet.Base;
using PcapDotNet.Packets.Ethernet; using PcapDotNet.Packets.Ethernet;
...@@ -6,13 +7,31 @@ using PcapDotNet.Packets.IpV4; ...@@ -6,13 +7,31 @@ using PcapDotNet.Packets.IpV4;
namespace PcapDotNet.Packets namespace PcapDotNet.Packets
{ {
/// <summary>
/// Extension methods for byte[].
/// </summary>
public static class MoreByteArray public static class MoreByteArray
{ {
/// <summary>
/// Copies a specified number of bytes from a source array starting at a particular offset to a destination array starting at a particular offset.
/// </summary>
/// <param name="source">The source buffer.</param>
/// <param name="sourceOffset">The byte offset into source.</param>
/// <param name="destination">The destination buffer.</param>
/// <param name="destinationOffset">The byte offset into destination.</param>
/// <param name="count">The number of bytes to copy.</param>
public static void BlockCopy(this byte[] source, int sourceOffset, byte[] destination, int destinationOffset, int count) public static void BlockCopy(this byte[] source, int sourceOffset, byte[] destination, int destinationOffset, int count)
{ {
Buffer.BlockCopy(source, sourceOffset, destination, destinationOffset, count); Buffer.BlockCopy(source, sourceOffset, destination, destinationOffset, count);
} }
/// <summary>
/// Reads 2 bytes from a specific offset as a short with a given endianity.
/// </summary>
/// <param name="buffer">The buffer to read the bytes from.</param>
/// <param name="offset">The offset in the buffer to start reading.</param>
/// <param name="endianity">The endianity to use to translate the bytes to the value.</param>
/// <returns>The value converted from the read bytes according to the endianity.</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "short")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "short")]
public static short ReadShort(this byte[] buffer, int offset, Endianity endianity) public static short ReadShort(this byte[] buffer, int offset, Endianity endianity)
{ {
...@@ -22,12 +41,26 @@ namespace PcapDotNet.Packets ...@@ -22,12 +41,26 @@ namespace PcapDotNet.Packets
return value; return value;
} }
/// <summary>
/// Reads 2 bytes from a specific offset as a ushort with a given endianity.
/// </summary>
/// <param name="buffer">The buffer to read the bytes from.</param>
/// <param name="offset">The offset in the buffer to start reading.</param>
/// <param name="endianity">The endianity to use to translate the bytes to the value.</param>
/// <returns>The value converted from the read bytes according to the endianity.</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "ushort")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "ushort")]
public static ushort ReadUShort(this byte[] buffer, int offset, Endianity endianity) public static ushort ReadUShort(this byte[] buffer, int offset, Endianity endianity)
{ {
return (ushort)ReadShort(buffer, offset, endianity); return (ushort)ReadShort(buffer, offset, endianity);
} }
/// <summary>
/// Reads 2 bytes from a specific offset as a ushort with a given endianity and increments the offset by the number of bytes read.
/// </summary>
/// <param name="buffer">The buffer to read the bytes from.</param>
/// <param name="offset">The offset in the buffer to start reading.</param>
/// <param name="endianity">The endianity to use to translate the bytes to the value.</param>
/// <returns>The value converted from the read bytes according to the endianity.</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "ushort")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "ushort")]
public static ushort ReadUShort(this byte[] buffer, ref int offset, Endianity endianity) public static ushort ReadUShort(this byte[] buffer, ref int offset, Endianity endianity)
{ {
...@@ -36,6 +69,13 @@ namespace PcapDotNet.Packets ...@@ -36,6 +69,13 @@ namespace PcapDotNet.Packets
return result; return result;
} }
/// <summary>
/// Reads 3 bytes from a specific offset as a UInt24 with a given endianity.
/// </summary>
/// <param name="buffer">The buffer to read the bytes from.</param>
/// <param name="offset">The offset in the buffer to start reading.</param>
/// <param name="endianity">The endianity to use to translate the bytes to the value.</param>
/// <returns>The value converted from the read bytes according to the endianity.</returns>
public static UInt24 ReadUInt24(this byte[] buffer, int offset, Endianity endianity) public static UInt24 ReadUInt24(this byte[] buffer, int offset, Endianity endianity)
{ {
UInt24 value = ReadUInt24(buffer, offset); UInt24 value = ReadUInt24(buffer, offset);
...@@ -44,6 +84,13 @@ namespace PcapDotNet.Packets ...@@ -44,6 +84,13 @@ namespace PcapDotNet.Packets
return value; return value;
} }
/// <summary>
/// Reads 3 bytes from a specific offset as a UInt24 with a given endianity and increments the offset by the number of bytes read.
/// </summary>
/// <param name="buffer">The buffer to read the bytes from.</param>
/// <param name="offset">The offset in the buffer to start reading.</param>
/// <param name="endianity">The endianity to use to translate the bytes to the value.</param>
/// <returns>The value converted from the read bytes according to the endianity.</returns>
public static UInt24 ReadUInt24(this byte[] buffer, ref int offset, Endianity endianity) public static UInt24 ReadUInt24(this byte[] buffer, ref int offset, Endianity endianity)
{ {
UInt24 result = ReadUInt24(buffer, offset, endianity); UInt24 result = ReadUInt24(buffer, offset, endianity);
...@@ -51,6 +98,13 @@ namespace PcapDotNet.Packets ...@@ -51,6 +98,13 @@ namespace PcapDotNet.Packets
return result; return result;
} }
/// <summary>
/// Reads 4 bytes from a specific offset as an int with a given endianity.
/// </summary>
/// <param name="buffer">The buffer to read the bytes from.</param>
/// <param name="offset">The offset in the buffer to start reading.</param>
/// <param name="endianity">The endianity to use to translate the bytes to the value.</param>
/// <returns>The value converted from the read bytes according to the endianity.</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "int")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "int")]
public static int ReadInt(this byte[] buffer, int offset, Endianity endianity) public static int ReadInt(this byte[] buffer, int offset, Endianity endianity)
{ {
...@@ -60,12 +114,26 @@ namespace PcapDotNet.Packets ...@@ -60,12 +114,26 @@ namespace PcapDotNet.Packets
return value; return value;
} }
/// <summary>
/// Reads 4 bytes from a specific offset as a uint with a given endianity.
/// </summary>
/// <param name="buffer">The buffer to read the bytes from.</param>
/// <param name="offset">The offset in the buffer to start reading.</param>
/// <param name="endianity">The endianity to use to translate the bytes to the value.</param>
/// <returns>The value converted from the read bytes according to the endianity.</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "uint")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "uint")]
public static uint ReadUInt(this byte[] buffer, int offset, Endianity endianity) public static uint ReadUInt(this byte[] buffer, int offset, Endianity endianity)
{ {
return (uint)ReadInt(buffer, offset, endianity); return (uint)ReadInt(buffer, offset, endianity);
} }
/// <summary>
/// Reads 4 bytes from a specific offset as a uint with a given endianity and increments the offset by the number of bytes read.
/// </summary>
/// <param name="buffer">The buffer to read the bytes from.</param>
/// <param name="offset">The offset in the buffer to start reading.</param>
/// <param name="endianity">The endianity to use to translate the bytes to the value.</param>
/// <returns>The value converted from the read bytes according to the endianity.</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "uint")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "uint")]
public static uint ReadUInt(this byte[] buffer, ref int offset, Endianity endianity) public static uint ReadUInt(this byte[] buffer, ref int offset, Endianity endianity)
{ {
...@@ -74,6 +142,13 @@ namespace PcapDotNet.Packets ...@@ -74,6 +142,13 @@ namespace PcapDotNet.Packets
return result; return result;
} }
/// <summary>
/// Reads 6 bytes from a specific offset as a UInt48 with a given endianity.
/// </summary>
/// <param name="buffer">The buffer to read the bytes from.</param>
/// <param name="offset">The offset in the buffer to start reading.</param>
/// <param name="endianity">The endianity to use to translate the bytes to the value.</param>
/// <returns>The value converted from the read bytes according to the endianity.</returns>
public static UInt48 ReadUInt48(this byte[] buffer, int offset, Endianity endianity) public static UInt48 ReadUInt48(this byte[] buffer, int offset, Endianity endianity)
{ {
UInt48 value = ReadUInt48(buffer, offset); UInt48 value = ReadUInt48(buffer, offset);
...@@ -82,6 +157,13 @@ namespace PcapDotNet.Packets ...@@ -82,6 +157,13 @@ namespace PcapDotNet.Packets
return value; return value;
} }
/// <summary>
/// Reads 6 bytes from a specific offset as a UInt48 with a given endianity and increments the offset by the number of bytes read.
/// </summary>
/// <param name="buffer">The buffer to read the bytes from.</param>
/// <param name="offset">The offset in the buffer to start reading.</param>
/// <param name="endianity">The endianity to use to translate the bytes to the value.</param>
/// <returns>The value converted from the read bytes according to the endianity.</returns>
public static UInt48 ReadUInt48(this byte[] buffer, ref int offset, Endianity endianity) public static UInt48 ReadUInt48(this byte[] buffer, ref int offset, Endianity endianity)
{ {
UInt48 result = buffer.ReadUInt48(offset, endianity); UInt48 result = buffer.ReadUInt48(offset, endianity);
...@@ -89,26 +171,85 @@ namespace PcapDotNet.Packets ...@@ -89,26 +171,85 @@ namespace PcapDotNet.Packets
return result; return result;
} }
/// <summary>
/// Reads 6 bytes from a specific offset as a MacAddress with a given endianity.
/// </summary>
/// <param name="buffer">The buffer to read the bytes from.</param>
/// <param name="offset">The offset in the buffer to start reading.</param>
/// <param name="endianity">The endianity to use to translate the bytes to the value.</param>
/// <returns>The value converted from the read bytes according to the endianity.</returns>
public static MacAddress ReadMacAddress(this byte[] buffer, int offset, Endianity endianity) public static MacAddress ReadMacAddress(this byte[] buffer, int offset, Endianity endianity)
{ {
return new MacAddress(buffer.ReadUInt48(offset, endianity)); return new MacAddress(buffer.ReadUInt48(offset, endianity));
} }
/// <summary>
/// Reads 6 bytes from a specific offset as a MacAddress with a given endianity and increments the offset by the number of bytes read.
/// </summary>
/// <param name="buffer">The buffer to read the bytes from.</param>
/// <param name="offset">The offset in the buffer to start reading.</param>
/// <param name="endianity">The endianity to use to translate the bytes to the value.</param>
/// <returns>The value converted from the read bytes according to the endianity.</returns>
public static MacAddress ReadMacAddress(this byte[] buffer, ref int offset, Endianity endianity) public static MacAddress ReadMacAddress(this byte[] buffer, ref int offset, Endianity endianity)
{ {
return new MacAddress(buffer.ReadUInt48(ref offset, endianity)); return new MacAddress(buffer.ReadUInt48(ref offset, endianity));
} }
/// <summary>
/// Reads 4 bytes from a specific offset as an IPv4 address with a given endianity.
/// </summary>
/// <param name="buffer">The buffer to read the bytes from.</param>
/// <param name="offset">The offset in the buffer to start reading.</param>
/// <param name="endianity">The endianity to use to translate the bytes to the value.</param>
/// <returns>The value converted from the read bytes according to the endianity.</returns>
public static IpV4Address ReadIpV4Address(this byte[] buffer, int offset, Endianity endianity) public static IpV4Address ReadIpV4Address(this byte[] buffer, int offset, Endianity endianity)
{ {
return new IpV4Address(buffer.ReadUInt(offset, endianity)); return new IpV4Address(buffer.ReadUInt(offset, endianity));
} }
/// <summary>
/// Reads 4 bytes from a specific offset as an IPv4 address with a given endianity and increments the offset by the number of bytes read.
/// </summary>
/// <param name="buffer">The buffer to read the bytes from.</param>
/// <param name="offset">The offset in the buffer to start reading.</param>
/// <param name="endianity">The endianity to use to translate the bytes to the value.</param>
/// <returns>The value converted from the read bytes according to the endianity.</returns>
public static IpV4Address ReadIpV4Address(this byte[] buffer, ref int offset, Endianity endianity) public static IpV4Address ReadIpV4Address(this byte[] buffer, ref int offset, Endianity endianity)
{ {
return new IpV4Address(buffer.ReadUInt(ref offset, endianity)); return new IpV4Address(buffer.ReadUInt(ref offset, endianity));
} }
/// <summary>
/// Reads 4 bytes from a specific offset as an IPv4 time of day with a given endianity.
/// </summary>
/// <param name="buffer">The buffer to read the bytes from.</param>
/// <param name="offset">The offset in the buffer to start reading.</param>
/// <param name="endianity">The endianity to use to translate the bytes to the value.</param>
/// <returns>The value converted from the read bytes according to the endianity.</returns>
public static IpV4OptionTimeOfDay ReadIpV4OptionTimeOfDay(this byte[] buffer, int offset, Endianity endianity)
{
return new IpV4OptionTimeOfDay(buffer.ReadUInt(offset, endianity));
}
/// <summary>
/// Reads 4 bytes from a specific offset as an IPv4 time of day with a given endianity and increments the offset by the number of bytes read.
/// </summary>
/// <param name="buffer">The buffer to read the bytes from.</param>
/// <param name="offset">The offset in the buffer to start reading.</param>
/// <param name="endianity">The endianity to use to translate the bytes to the value.</param>
/// <returns>The value converted from the read bytes according to the endianity.</returns>
public static IpV4OptionTimeOfDay ReadIpV4OptionTimeOfDay(this byte[] buffer, ref int offset, Endianity endianity)
{
return new IpV4OptionTimeOfDay(buffer.ReadUInt(ref offset, 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, short value, Endianity endianity) public static void Write(this byte[] buffer, int offset, short value, Endianity endianity)
{ {
if (IsWrongEndianity(endianity)) if (IsWrongEndianity(endianity))
...@@ -116,17 +257,38 @@ namespace PcapDotNet.Packets ...@@ -116,17 +257,38 @@ namespace PcapDotNet.Packets
Write(buffer, offset, value); Write(buffer, offset, value);
} }
/// <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, ushort value, Endianity endianity) public static void Write(this byte[] buffer, int offset, ushort value, Endianity endianity)
{ {
Write(buffer, offset, (short)value, endianity); Write(buffer, offset, (short)value, endianity);
} }
/// <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, ushort value, Endianity endianity) public static void Write(this byte[] buffer, ref int offset, ushort value, Endianity endianity)
{ {
Write(buffer, offset, value, endianity); Write(buffer, offset, value, endianity);
offset += sizeof(ushort); offset += sizeof(ushort);
} }
/// <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, UInt24 value, Endianity endianity) public static void Write(this byte[] buffer, int offset, UInt24 value, Endianity endianity)
{ {
if (IsWrongEndianity(endianity)) if (IsWrongEndianity(endianity))
...@@ -134,12 +296,26 @@ namespace PcapDotNet.Packets ...@@ -134,12 +296,26 @@ 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, UInt24 value, Endianity endianity) public static void Write(this byte[] buffer, ref int offset, UInt24 value, Endianity endianity)
{ {
Write(buffer, offset, value, endianity); Write(buffer, offset, value, endianity);
offset += UInt24.SizeOf; offset += UInt24.SizeOf;
} }
/// <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, int value, Endianity endianity) public static void Write(this byte[] buffer, int offset, int value, Endianity endianity)
{ {
if (IsWrongEndianity(endianity)) if (IsWrongEndianity(endianity))
...@@ -147,17 +323,38 @@ namespace PcapDotNet.Packets ...@@ -147,17 +323,38 @@ namespace PcapDotNet.Packets
Write(buffer, offset, value); Write(buffer, offset, value);
} }
/// <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, uint value, Endianity endianity) public static void Write(this byte[] buffer, int offset, uint value, Endianity endianity)
{ {
Write(buffer, offset, (int)value, endianity); Write(buffer, offset, (int)value, endianity);
} }
/// <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, uint value, Endianity endianity) public static void Write(this byte[] buffer, ref int offset, uint value, Endianity endianity)
{ {
Write(buffer, offset, value, endianity); Write(buffer, offset, value, endianity);
offset += sizeof(uint); offset += sizeof(uint);
} }
/// <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, UInt48 value, Endianity endianity) public static void Write(this byte[] buffer, int offset, UInt48 value, Endianity endianity)
{ {
if (IsWrongEndianity(endianity)) if (IsWrongEndianity(endianity))
...@@ -165,32 +362,91 @@ namespace PcapDotNet.Packets ...@@ -165,32 +362,91 @@ 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, UInt48 value, Endianity endianity) public static void Write(this byte[] buffer, ref int offset, UInt48 value, Endianity endianity)
{ {
Write(buffer, offset, value, endianity); Write(buffer, offset, value, endianity);
offset += UInt48.SizeOf; offset += UInt48.SizeOf;
} }
/// <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, MacAddress value, Endianity endianity) public static void Write(this byte[] buffer, int offset, MacAddress value, Endianity endianity)
{ {
buffer.Write(offset, value.ToValue(), endianity); buffer.Write(offset, value.ToValue(), endianity);
} }
/// <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, MacAddress value, Endianity endianity) public static void Write(this byte[] buffer, ref int offset, MacAddress value, Endianity endianity)
{ {
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, IpV4Address value, Endianity endianity) public static void Write(this byte[] buffer, int offset, IpV4Address value, Endianity endianity)
{ {
buffer.Write(offset, value.ToValue(), endianity); buffer.Write(offset, value.ToValue(), endianity);
} }
/// <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, IpV4Address value, Endianity endianity) public static void Write(this byte[] buffer, ref int offset, IpV4Address value, Endianity endianity)
{ {
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, IpV4OptionTimeOfDay value, Endianity endianity)
{
buffer.Write(offset, value.MillisecondsSinceMidnightUniversalTime, endianity);
}
/// <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, IpV4OptionTimeOfDay value, Endianity endianity)
{
buffer.Write(ref offset, value.MillisecondsSinceMidnightUniversalTime, endianity);
}
private static bool IsWrongEndianity(Endianity endianity) private static bool IsWrongEndianity(Endianity endianity)
{ {
return (BitConverter.IsLittleEndian == (endianity == Endianity.Big)); return (BitConverter.IsLittleEndian == (endianity == Endianity.Big));
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using PcapDotNet.Base;
using PcapDotNet.Packets.Ethernet; using PcapDotNet.Packets.Ethernet;
namespace PcapDotNet.Packets namespace PcapDotNet.Packets
...@@ -92,68 +93,37 @@ namespace PcapDotNet.Packets ...@@ -92,68 +93,37 @@ namespace PcapDotNet.Packets
} }
/// <summary> /// <summary>
/// Serves as a hash function for a particular type. /// The hash code of a packet is the xor of all its bytes. Each byte is xored with the next 8 bits of the integer.
/// </summary> /// </summary>
/// <returns>
/// A hash code for the current <see cref="T:System.Object"/>.
/// </returns>
/// <filterpriority>2</filterpriority>
public override int GetHashCode() public override int GetHashCode()
{ {
int hashCode = 0; return this.BytesSequenceGetHashCode();
int offset = 0;
for (; offset < _data.Length - 3; offset += 4)
hashCode ^= _data.ReadInt(offset, Endianity.Small);
if (offset < _data.Length - 1)
hashCode ^= _data.ReadShort(offset, Endianity.Small);
if (offset < _data.Length)
hashCode ^= _data[offset] >> 2;
return hashCode;
} }
/// <summary> /// <summary>
/// Returns a <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>. /// The Packet string contains the datalink and the length.
/// </summary> /// </summary>
/// <returns>
/// A <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
/// </returns>
/// <filterpriority>2</filterpriority>
public override string ToString() public override string ToString()
{ {
return typeof(Packet).Name + " <" + DataLink + ", " + Length + ">"; return typeof(Packet).Name + " <" + DataLink + ", " + Length + ">";
} }
/// <summary> /// <summary>
/// Returns an enumerator that iterates through the collection. /// Returns an enumerator that iterates through the bytes of the packet.
/// </summary> /// </summary>
/// <returns>
/// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
/// </returns>
/// <filterpriority>1</filterpriority>
public IEnumerator<byte> GetEnumerator() public IEnumerator<byte> GetEnumerator()
{ {
return ((IEnumerable<byte>)Buffer).GetEnumerator(); return ((IEnumerable<byte>)Buffer).GetEnumerator();
} }
/// <summary>
/// Returns an enumerator that iterates through a collection.
/// </summary>
/// <returns>
/// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
/// </returns>
/// <filterpriority>2</filterpriority>
IEnumerator IEnumerable.GetEnumerator() IEnumerator IEnumerable.GetEnumerator()
{ {
return GetEnumerator(); return GetEnumerator();
} }
/// <summary> /// <summary>
/// Determines the index of a specific item in the <see cref="T:System.Collections.Generic.IList`1"/>. /// Returns the first offset in the packet that contains the given byte.
/// </summary> /// </summary>
/// <returns>
/// The index of <paramref name="item"/> if found in the list; otherwise, -1.
/// </returns>
/// <param name="item">The object to locate in the <see cref="T:System.Collections.Generic.IList`1"/>.</param>
public int IndexOf(byte item) public int IndexOf(byte item)
{ {
return ((IList<byte>)Buffer).IndexOf(item); return ((IList<byte>)Buffer).IndexOf(item);
...@@ -176,15 +146,9 @@ namespace PcapDotNet.Packets ...@@ -176,15 +146,9 @@ namespace PcapDotNet.Packets
} }
/// <summary> /// <summary>
/// Gets the element at the specified index. /// Returns the value of the byte in the given offset.
/// Set operation is invalid because the object is immutable. /// Set operation is invalid because the object is immutable.
/// </summary> /// </summary>
/// <returns>
/// The element at the specified index.
/// </returns>
/// <param name="index">The zero-based index of the element to get.</param>
/// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="index"/> is not a valid index in the <see cref="T:System.Collections.Generic.IList`1"/>.</exception>
/// <exception cref="T:System.NotSupportedException">The property is set.</exception>
public byte this[int index] public byte this[int index]
{ {
get { return Buffer[index]; } get { return Buffer[index]; }
...@@ -208,21 +172,16 @@ namespace PcapDotNet.Packets ...@@ -208,21 +172,16 @@ namespace PcapDotNet.Packets
} }
/// <summary> /// <summary>
/// Determines whether the <see cref="T:System.Collections.Generic.ICollection`1"/> contains a specific value. /// Determines whether the packet contains a specific byte.
/// </summary> /// </summary>
/// <returns>
/// true if <paramref name="item"/> is found in the <see cref="T:System.Collections.Generic.ICollection`1"/>; otherwise, false.
/// </returns>
/// <param name="item">The object to locate in the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param>
public bool Contains(byte item) public bool Contains(byte item)
{ {
return Buffer.Contains(item); return Buffer.Contains(item);
} }
/// <summary> /// <summary>
/// Copies the elements of the <see cref="T:System.Collections.Generic.ICollection`1"/> to an <see cref="T:System.Array"/>, starting at a particular <see cref="T:System.Array"/> index. /// Copies the bytes of the packet to a buffer, starting at a particular offset.
/// </summary> /// </summary>
/// <param name="array">The one-dimensional <see cref="T:System.Array"/> that is the destination of the elements copied from <see cref="T:System.Collections.Generic.ICollection`1"/>. The <see cref="T:System.Array"/> must have zero-based indexing.</param><param name="arrayIndex">The zero-based index in <paramref name="array"/> at which copying begins.</param><exception cref="T:System.ArgumentNullException"><paramref name="array"/> is null.</exception><exception cref="T:System.ArgumentOutOfRangeException"><paramref name="arrayIndex"/> is less than 0.</exception><exception cref="T:System.ArgumentException"><paramref name="array"/> is multidimensional.-or-<paramref name="arrayIndex"/> is equal to or greater than the length of <paramref name="array"/>.-or-The number of elements in the source <see cref="T:System.Collections.Generic.ICollection`1"/> is greater than the available space from <paramref name="arrayIndex"/> to the end of the destination <paramref name="array"/>.-or-Type <paramref name="T"/> cannot be cast automatically to the type of the destination <paramref name="array"/>.</exception>
public void CopyTo(byte[] array, int arrayIndex) public void CopyTo(byte[] array, int arrayIndex)
{ {
Buffer.BlockCopy(0, array, arrayIndex, Length); Buffer.BlockCopy(0, array, arrayIndex, Length);
...@@ -237,11 +196,8 @@ namespace PcapDotNet.Packets ...@@ -237,11 +196,8 @@ namespace PcapDotNet.Packets
} }
/// <summary> /// <summary>
/// Gets the number of elements contained in the <see cref="T:System.Collections.Generic.ICollection`1"/>. /// Returns the number of bytes in this packet.
/// </summary> /// </summary>
/// <returns>
/// The number of elements contained in the <see cref="T:System.Collections.Generic.ICollection`1"/>.
/// </returns>
public int Count public int Count
{ {
get { return Length; } get { return Length; }
...@@ -274,7 +230,7 @@ namespace PcapDotNet.Packets ...@@ -274,7 +230,7 @@ namespace PcapDotNet.Packets
} }
/// <summary> /// <summary>
/// Takes the entire packet as an ethernet datagram. /// Takes the entire packet as an Ethernet datagram.
/// </summary> /// </summary>
public EthernetDatagram Ethernet public EthernetDatagram Ethernet
{ {
......
...@@ -4,8 +4,20 @@ using PcapDotNet.Packets.IpV4; ...@@ -4,8 +4,20 @@ using PcapDotNet.Packets.IpV4;
namespace PcapDotNet.Packets namespace PcapDotNet.Packets
{ {
/// <summary>
/// The class to use to build all the packets.
/// </summary>
public static class PacketBuilder public static class PacketBuilder
{ {
/// <summary>
/// Builds an Ethernet packet.
/// </summary>
/// <param name="timestamp">The packet timestamp.</param>
/// <param name="ethernetSource">The Ethernet source mac address.</param>
/// <param name="ethernetDestination">The Ethernet destination mac address.</param>
/// <param name="ethernetType">The Ethernet type.</param>
/// <param name="ethernetPayload">The Ethernet payload.</param>
/// <returns>A packet with an Ethernet datagram.</returns>
public static Packet Ethernet(DateTime timestamp, public static Packet Ethernet(DateTime timestamp,
MacAddress ethernetSource, MacAddress ethernetDestination, EthernetType ethernetType, MacAddress ethernetSource, MacAddress ethernetDestination, EthernetType ethernetType,
Datagram ethernetPayload) Datagram ethernetPayload)
...@@ -16,8 +28,24 @@ namespace PcapDotNet.Packets ...@@ -16,8 +28,24 @@ namespace PcapDotNet.Packets
return new Packet(buffer, timestamp, new DataLink(DataLinkKind.Ethernet)); return new Packet(buffer, timestamp, new DataLink(DataLinkKind.Ethernet));
} }
/// <summary>
/// Builds an IPv4 over Ethernet packet.
/// </summary>
/// <param name="timestamp">The packet timestamp.</param>
/// <param name="ethernetSource">The ethernet source mac address.</param>
/// <param name="ethernetDestination">The ethernet destination mac address.</param>
/// <param name="ipV4TypeOfService">The IPv4 Type of Service.</param>
/// <param name="ipV4Identification">The IPv4 Identification.</param>
/// <param name="ipV4Fragmentation">The IPv4 Fragmentation.</param>
/// <param name="ipV4Ttl">The IPv4 TTL.</param>
/// <param name="ipV4Protocol">The IPv4 Protocol.</param>
/// <param name="ipV4SourceAddress">The IPv4 source address.</param>
/// <param name="ipV4DestinationAddress">The IPv4 destination address.</param>
/// <param name="ipV4Options">The IPv4 options.</param>
/// <param name="ipV4Payload">The IPv4 payload.</param>
/// <returns>A packet with an IPv4 over Ethernet datagram.</returns>
public static Packet EthernetIpV4(DateTime timestamp, public static Packet EthernetIpV4(DateTime timestamp,
MacAddress ethernetSource, MacAddress ethernetDestination, EthernetType ethernetType, MacAddress ethernetSource, MacAddress ethernetDestination,
byte ipV4TypeOfService, ushort ipV4Identification, IpV4Fragmentation ipV4Fragmentation, byte ipV4TypeOfService, ushort ipV4Identification, IpV4Fragmentation ipV4Fragmentation,
byte ipV4Ttl, IpV4Protocol ipV4Protocol, byte ipV4Ttl, IpV4Protocol ipV4Protocol,
IpV4Address ipV4SourceAddress, IpV4Address ipV4DestinationAddress, IpV4Address ipV4SourceAddress, IpV4Address ipV4DestinationAddress,
...@@ -26,7 +54,7 @@ namespace PcapDotNet.Packets ...@@ -26,7 +54,7 @@ namespace PcapDotNet.Packets
{ {
int ipHeaderLength = IpV4Datagram.HeaderMinimumLength + ipV4Options.BytesLength; int ipHeaderLength = IpV4Datagram.HeaderMinimumLength + ipV4Options.BytesLength;
byte[] buffer = new byte[EthernetDatagram.HeaderLength + ipHeaderLength + ipV4Payload.Length]; byte[] buffer = new byte[EthernetDatagram.HeaderLength + ipHeaderLength + ipV4Payload.Length];
EthernetDatagram.WriteHeader(buffer, 0, ethernetSource, ethernetDestination, ethernetType); EthernetDatagram.WriteHeader(buffer, 0, ethernetSource, ethernetDestination, EthernetType.IpV4);
IpV4Datagram.WriteHeader(buffer, EthernetDatagram.HeaderLength, IpV4Datagram.WriteHeader(buffer, EthernetDatagram.HeaderLength,
ipV4TypeOfService, ipV4Identification, ipV4Fragmentation, ipV4TypeOfService, ipV4Identification, ipV4Fragmentation,
ipV4Ttl, ipV4Protocol, ipV4Ttl, ipV4Protocol,
......
...@@ -84,6 +84,7 @@ ...@@ -84,6 +84,7 @@
<Compile Include="IpV4\IpV4OptionStreamIdentifier.cs" /> <Compile Include="IpV4\IpV4OptionStreamIdentifier.cs" />
<Compile Include="IpV4\IpV4OptionStrictSourceRouting.cs" /> <Compile Include="IpV4\IpV4OptionStrictSourceRouting.cs" />
<Compile Include="IpV4\IpV4OptionTimedAddress.cs" /> <Compile Include="IpV4\IpV4OptionTimedAddress.cs" />
<Compile Include="IpV4\IpV4OptionTimeOfDay.cs" />
<Compile Include="IpV4\IpV4OptionTimestamp.cs" /> <Compile Include="IpV4\IpV4OptionTimestamp.cs" />
<Compile Include="IpV4\IpV4OptionTimestampAndAddress.cs" /> <Compile Include="IpV4\IpV4OptionTimestampAndAddress.cs" />
<Compile Include="IpV4\IpV4OptionTimestampOnly.cs" /> <Compile Include="IpV4\IpV4OptionTimestampOnly.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