Commit 68437e53 authored by Brickner_cp's avatar Brickner_cp

Documentation. 0 documentation warnings left.

parent b7a3df08
......@@ -71,8 +71,10 @@
<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="Other" />
<PredefinedRule Inspect="True" Prefix="_" Suffix="" Style="aaBb" ElementKind="NotPublicInstanceFields" />
<PredefinedRule Inspect="True" Prefix="_" Suffix="" Style="aaBb" ElementKind="NotPublicStaticFields" />
<PredefinedRule Inspect="True" Prefix="_" Suffix="" Style="aaBb" ElementKind="PrivateInstanceFields" />
<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>
</CodeStyleSettings>
</Configuration>
\ No newline at end of file
......@@ -95,5 +95,17 @@ namespace PcapDotNet.Base
{
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
Datagram ipV4Payload = new Datagram(ipV4PayloadBuffer);
Packet packet = PacketBuilder.EthernetIpV4(DateTime.Now,
ethernetSource, ethernetDestination, ethernetType,
ethernetSource, ethernetDestination,
ipV4TypeOfService, ipV4Identification, ipV4Fragmentation, ipV4Ttl, ipV4Protocol,
ipV4Source, ipV4Destination, ipV4Options,
ipV4Payload);
......@@ -215,7 +215,13 @@ namespace PcapDotNet.Packets.Test
[ExpectedException(typeof(ArgumentException))]
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.Fail();
}
......
......@@ -70,6 +70,11 @@ namespace PcapDotNet.Packets.TestUtils
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)
{
if (maximumOptionLength == 0)
......@@ -146,9 +151,9 @@ namespace PcapDotNet.Packets.TestUtils
{
case IpV4OptionTimestampType.TimestampOnly:
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)
timestamps[i] = random.NextUInt();
timestamps[i] = random.NextIpV4OptionTimeOfDay();
return new IpV4OptionTimestampOnly(overflow, pointedIndex, timestamps);
case IpV4OptionTimestampType.AddressAndTimestamp:
......@@ -156,7 +161,7 @@ namespace PcapDotNet.Packets.TestUtils
int numPairs = random.Next((maximumOptionLength - IpV4OptionTimestamp.OptionMinimumLength) / 8 + 1);
IpV4OptionTimedAddress[] pairs = new IpV4OptionTimedAddress[numPairs];
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);
......
using System;
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
{
get { return _ethernet; }
}
/// <summary>
/// Create the DataLink from a kind.
/// </summary>
public DataLink(DataLinkKind kind)
{
_kind = kind;
}
/// <summary>
/// The kind of the DataLink.
/// </summary>
public DataLinkKind Kind
{
get { return _kind; }
}
/// <summary>
/// Two DataLinks are equal if they are of the same kind.
/// </summary>
public bool Equals(DataLink other)
{
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)
{
return (obj is DataLink &&
Equals((DataLink)obj));
}
/// <summary>
/// Two DataLinks are equal if they are of the same kind.
/// </summary>
public static bool operator ==(DataLink dataLink1, DataLink dataLink2)
{
return dataLink1.Equals(dataLink2);
}
/// <summary>
/// Two DataLinks are different if they have different kinds.
/// </summary>
public static bool operator !=(DataLink dataLink1, DataLink dataLink2)
{
return !(dataLink1 == dataLink2);
}
/// <summary>
/// The hash code of the datalink is the hash code of its kind.
/// </summary>
public override int GetHashCode()
{
return _kind.GetHashCode();
}
/// <summary>
/// The string is the kind's string.
/// </summary>
public override string ToString()
{
return Kind.ToString();
......
namespace PcapDotNet.Packets
{
/// <summary>
/// Represents the different data links kinds.
/// </summary>
public enum DataLinkKind
{
/// <summary>
/// Ethernet data link kind.
/// </summary>
Ethernet
}
}
\ No newline at end of file
......@@ -2,17 +2,33 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using PcapDotNet.Base;
using PcapDotNet.Packets.Ethernet;
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>
{
/// <summary>
/// Take all the bytes as a datagram.
/// </summary>
/// <param name="buffer">The buffer to take as a datagram.</param>
public Datagram(byte[] buffer)
: 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)
{
_buffer = buffer;
......@@ -20,21 +36,35 @@ namespace PcapDotNet.Packets
_length = length;
}
/// <summary>
/// An empty datagram.
/// Useful for empty payloads.
/// </summary>
public static Datagram Empty
{
get { return _empty; }
}
/// <summary>
/// The number of bytes in this datagram.
/// </summary>
public int 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]
{
get { return _buffer[StartOffset + offset]; }
}
/// <summary>
/// A datagram is checked for validity according to the protocol.
/// </summary>
public bool IsValid
{
get
......@@ -45,11 +75,9 @@ namespace PcapDotNet.Packets
}
}
public virtual bool CalculateIsValid()
{
return true;
}
/// <summary>
/// Iterate through all the bytes in the datagram.
/// </summary>
public IEnumerator<byte> GetEnumerator()
{
for (int i = 0; i != Length; ++i)
......@@ -61,6 +89,9 @@ namespace PcapDotNet.Packets
return GetEnumerator();
}
/// <summary>
/// Two datagrams are equal if the have the same data.
/// </summary>
public bool Equals(Datagram other)
{
if (Length != other.Length)
......@@ -75,46 +106,82 @@ namespace PcapDotNet.Packets
return true;
}
/// <summary>
/// Two datagrams are equal if the have the same data.
/// </summary>
public override bool Equals(object obj)
{
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()
{
int i = 0;
return Length.GetHashCode() ^
this.Aggregate(0, (value, b) => value ^ (b << (8 * (i++ % 4))));
return Length.GetHashCode() ^ this.BytesSequenceGetHashCode();
}
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")]
protected byte[] Buffer
{
get { return _buffer; }
}
/// <summary>
/// The offset of the first byte of the datagram in the buffer.
/// </summary>
protected int 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")]
protected ushort ReadUShort(int offset, Endianity 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")]
protected uint ReadUInt(int offset, Endianity 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)
{
return Buffer.ReadMacAddress(StartOffset + offset, endianity);
......
namespace PcapDotNet.Packets
{
/// <summary>
/// The two possible endianities.
/// </summary>
public enum Endianity : byte
{
/// <summary>
/// Small endianity - bytes are read from the high offset to the low offset.
/// </summary>
Small,
/// <summary>
/// Big endianity - bytes are read from the low offset to the high offset.
/// </summary>
Big
}
}
\ No newline at end of file
......@@ -4,6 +4,8 @@ using PcapDotNet.Packets.IpV4;
namespace PcapDotNet.Packets.Ethernet
{
/// <summary>
/// Represents an Ethernet datagram.
///
/// +------+-----------------+------------+------------------+
/// | Byte | 0-5 | 6-11 | 12-13 |
/// +------+-----------------+------------+------------------+
......@@ -21,18 +23,30 @@ namespace PcapDotNet.Packets.Ethernet
public const int EtherTypeLength = 12;
}
/// <summary>
/// Ethernet header length in bytes.
/// </summary>
public const int HeaderLength = 14;
/// <summary>
/// The Ethernet payload.
/// </summary>
public Datagram Payload
{
get { return IpV4; }
}
/// <summary>
/// The Ethernet payload length in bytes.
/// </summary>
public int PayloadLength
{
get { return Math.Max(0, Length - HeaderLength); }
}
/// <summary>
/// Ethernet source address.
/// </summary>
public MacAddress Source
{
get
......@@ -41,6 +55,9 @@ namespace PcapDotNet.Packets.Ethernet
}
}
/// <summary>
/// Ethernet destination address.
/// </summary>
public MacAddress Destination
{
get
......@@ -49,6 +66,9 @@ namespace PcapDotNet.Packets.Ethernet
}
}
/// <summary>
/// Ethernet type (next protocol).
/// </summary>
public EthernetType EtherType
{
get
......@@ -57,20 +77,9 @@ namespace PcapDotNet.Packets.Ethernet
}
}
public override bool CalculateIsValid()
{
if (Length < HeaderLength)
return false;
switch (EtherType)
{
case EthernetType.IpV4:
return IpV4.IsValid;
default:
return true;
}
}
/// <summary>
/// The Ethernet payload as an IPv4 datagram.
/// </summary>
public IpV4Datagram IpV4
{
get
......@@ -81,7 +90,6 @@ namespace PcapDotNet.Packets.Ethernet
}
}
internal EthernetDatagram(byte[] buffer, int offset, int length)
: base(buffer, offset, length)
{
......@@ -94,6 +102,23 @@ namespace PcapDotNet.Packets.Ethernet
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;
}
}
\ No newline at end of file
......@@ -4,15 +4,29 @@ using PcapDotNet.Base;
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;
/// <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)
{
_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)
{
string[] hexes = address.Split(':');
......@@ -27,37 +41,59 @@ namespace PcapDotNet.Packets.Ethernet
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()
{
return _value;
}
/// <summary>
/// Two addresses are equal if they have the exact same value.
/// </summary>
public bool Equals(MacAddress other)
{
return _value == other._value;
}
/// <summary>
/// Two addresses are equal if they have the exact same value.
/// </summary>
public override bool Equals(object obj)
{
return (obj is MacAddress &&
Equals((MacAddress)obj));
}
/// <summary>
/// Two addresses are equal if they have the exact same value.
/// </summary>
public static bool operator ==(MacAddress macAddress1, MacAddress macAddress2)
{
return macAddress1.Equals(macAddress2);
}
/// <summary>
/// Two addresses are different if they have different values.
/// </summary>
public static bool operator !=(MacAddress macAddress1, MacAddress 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()
{
return _value.GetHashCode();
}
/// <summary>
/// Converts the address to a string in the format XX:XX:XX:XX:XX:XX.
/// </summary>
public override string ToString()
{
return string.Format(CultureInfo.InvariantCulture, "{0:X2}:{1:X2}:{2:X2}:{3:X2}:{4:X2}:{5:X2}",
......
namespace PcapDotNet.Packets
{
/// <summary>
/// Represents a datalink.
/// </summary>
public interface IDataLink
{
/// <summary>
/// The kind of the datalink.
/// </summary>
DataLinkKind Kind { get; }
}
}
\ No newline at end of file
......@@ -3,15 +3,30 @@ using System.Text;
namespace PcapDotNet.Packets.IpV4
{
/// <summary>
/// Represents an IPv4 address.
/// </summary>
public struct IpV4Address
{
/// <summary>
/// The number of bytes the address take.
/// </summary>
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)
{
_value = value;
}
/// <summary>
/// Creates an address from an address string (1.2.3.4).
/// </summary>
public IpV4Address(string value)
{
string[] values = value.Split('.');
......@@ -21,42 +36,66 @@ namespace PcapDotNet.Packets.IpV4
(byte.Parse(values[3], CultureInfo.InvariantCulture)));
}
/// <summary>
/// The zero address (0.0.0.0).
/// </summary>
public static IpV4Address Zero
{
get { return _zero; }
}
/// <summary>
/// Gets the address valud as a 32 bit integer.
/// </summary>
public uint ToValue()
{
return _value;
}
/// <summary>
/// Two addresses are equal if the have the exact same value.
/// </summary>
public bool Equals(IpV4Address other)
{
return ToValue() == other.ToValue();
}
/// <summary>
/// Two addresses are equal if the have the exact same value.
/// </summary>
public override bool Equals(object obj)
{
return (obj is IpV4Address &&
Equals((IpV4Address)obj));
}
/// <summary>
/// Two addresses are equal if the have the exact same value.
/// </summary>
public static bool operator ==(IpV4Address value1, IpV4Address value2)
{
return value1.Equals(value2);
}
/// <summary>
/// Two addresses are different if the have different values.
/// </summary>
public static bool operator !=(IpV4Address value1, IpV4Address 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()
{
return _value.GetHashCode();
}
/// <summary>
/// Translates the address to a string (1.2.3.4).
/// </summary>
public override string ToString()
{
StringBuilder stringBuilder = new StringBuilder(15);
......
......@@ -5,6 +5,8 @@ using System.Text;
namespace PcapDotNet.Packets.IpV4
{
/// <summary>
/// Represents an IPv4 datagram.
///
/// +-----+---------+-----+-----------------+-------+-----------------+
/// | Bit | 0-3 | 4-7 | 8-15 | 16-18 | 19-31 |
/// +-----+---------+-----+-----------------+-------+-----------------+
......@@ -20,10 +22,21 @@ namespace PcapDotNet.Packets.IpV4
/// +-----+-----------------------------------------------------------+
/// | 160 | Options with padding |
/// +-----+-----------------------------------------------------------+
/// | 160 | Data |
/// | to | |
/// | 360 | |
/// +-----+-----------------------------------------------------------+
/// </summary>
public class IpV4Datagram : Datagram
{
/// <summary>
/// The minimum length of the header in bytes.
/// </summary>
public const int HeaderMinimumLength = 20;
/// <summary>
/// The maximum length of the header in bytes.
/// </summary>
public const int HeaderMaximumLength = 60;
private static class Offset
......@@ -41,48 +54,78 @@ namespace PcapDotNet.Packets.IpV4
public const int Options = 20;
}
/// <summary>
/// The version (4).
/// </summary>
public const int Version = 0x4;
/// <summary>
/// The header length in bytes.
/// </summary>
public int HeaderLength
{
get { return (this[Offset.VersionAndHeaderLength] & 0x0F) * 4; }
}
/// <summary>
/// Type of Service field.
/// </summary>
public byte TypeOfService
{
get { return this[Offset.TypeOfService];}
}
/// <summary>
/// The length of the entire datagram as stated in the total length field.
/// </summary>
public ushort TotalLength
{
get { return ReadUShort(Offset.TotalLength, Endianity.Big); }
}
/// <summary>
/// The value of the IPv4 ID field.
/// </summary>
public ushort Identification
{
get { return ReadUShort(Offset.Identification, Endianity.Big); }
}
/// <summary>
/// The fragmentation information field.
/// </summary>
public IpV4Fragmentation Fragmentation
{
get { return new IpV4Fragmentation(ReadUShort(Offset.Fragmentation, Endianity.Big)); }
}
/// <summary>
/// The TTL field.
/// </summary>
public byte Ttl
{
get { return this[Offset.Ttl]; }
}
/// <summary>
/// The IPv4 (next) protocol field.
/// </summary>
public IpV4Protocol Protocol
{
get { return (IpV4Protocol)this[Offset.Protocol]; }
}
/// <summary>
/// The header check sum value.
/// </summary>
public ushort HeaderChecksum
{
get { return ReadUShort(Offset.HeaderChecksum, Endianity.Big); }
}
/// <summary>
/// True iff the header checksum value is correct according to the header.
/// </summary>
public bool IsHeaderChecksumCorrect
{
get
......@@ -93,16 +136,25 @@ namespace PcapDotNet.Packets.IpV4
}
}
/// <summary>
/// The source address.
/// </summary>
public IpV4Address Source
{
get { return new IpV4Address(ReadUInt(Offset.Source, Endianity.Big)); }
}
/// <summary>
/// The destination address.
/// </summary>
public IpV4Address Destination
{
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
{
get
......@@ -113,26 +165,17 @@ namespace PcapDotNet.Packets.IpV4
}
}
/// <summary>
/// The payload of the datagram.
/// </summary>
public Datagram Payload
{
get { return Tcp; }
}
public override bool CalculateIsValid()
{
if (Length < HeaderMinimumLength || Length < HeaderLength)
return false;
switch (Protocol)
{
case IpV4Protocol.Tcp:
return Tcp.IsValid;
default:
// Todo check the protocl further
return true;
}
}
/// <summary>
/// The payload of the datagram as a TCP datagram.
/// </summary>
public Datagram Tcp
{
get
......@@ -172,6 +215,28 @@ namespace PcapDotNet.Packets.IpV4
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()
{
uint sum = Sum16Bits(Buffer, StartOffset, Offset.HeaderChecksum) +
......
......@@ -2,13 +2,24 @@ using System;
namespace PcapDotNet.Packets.IpV4
{
/// <summary>
/// Represents IPv4 Fragmentation information.
/// </summary>
public struct IpV4Fragmentation : IEquatable<IpV4Fragmentation>
{
/// <summary>
/// No fragmentation.
/// </summary>
public static IpV4Fragmentation 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)
: this((ushort)((ushort)options | (offset / 8)))
{
......@@ -19,40 +30,62 @@ namespace PcapDotNet.Packets.IpV4
throw new ArgumentException("invalid options " + options);
}
/// <summary>
/// Options for fragmentation.
/// </summary>
public IpV4FragmentationOptions Options
{
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
{
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)
{
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)
{
return (obj is IpV4Fragmentation &&
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)
{
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)
{
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()
{
return _value;
return _value.GetHashCode();
}
internal IpV4Fragmentation(ushort value)
......
......@@ -2,12 +2,27 @@ using System;
namespace PcapDotNet.Packets.IpV4
{
/// <summary>
/// Fragmentation information flags for IPv4 datagram.
/// </summary>
[Flags]
public enum IpV4FragmentationOptions : ushort
{
None = 0x0 << 13,
// Reserved = 0x4 << 13,
DoNotFragment = 0x2 << 13,
MoreFragments = 0x1 << 13
/// <summary>
/// May Fragment, Last Fragment.
/// </summary>
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
}
/// <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>
/// <returns>
/// A hash code for the current <see cref="T:System.Object"/>.
/// </returns>
/// <filterpriority>2</filterpriority>
/// <returns></returns>
public override int GetHashCode()
{
return (byte)OptionType;
return OptionType.GetHashCode();
}
/// <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>
/// <returns>
/// A <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
/// </returns>
/// <filterpriority>2</filterpriority>
public override string ToString()
{
return OptionType.ToString();
}
protected IpV4Option(IpV4OptionType type)
{
_type = type;
}
internal static IpV4Option Read(byte[] buffer, ref int offset, int length)
{
int offsetEnd = offset + length;
......@@ -139,6 +127,14 @@ namespace PcapDotNet.Packets.IpV4
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 _nop = new IpV4OptionSimple(IpV4OptionType.NoOperation);
......
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
{
/// <summary>
/// The header length in bytes for the option (type and size).
/// </summary>
public const int OptionHeaderLength = 2;
internal static IpV4OptionComplex ReadOptionComplex(IpV4OptionType optionType, byte[] buffer, ref int offset, int length)
......@@ -40,6 +47,9 @@ namespace PcapDotNet.Packets.IpV4
}
}
/// <summary>
/// Constructs the option by type.
/// </summary>
protected IpV4OptionComplex(IpV4OptionType type)
: base(type)
{
......
......@@ -44,8 +44,13 @@ namespace PcapDotNet.Packets.IpV4
/// </summary>
public class IpV4OptionLooseSourceRouting : IpV4OptionRoute
{
public IpV4OptionLooseSourceRouting(IList<IpV4Address> addresses, byte pointedAddressIndex)
: base(IpV4OptionType.LooseSourceRouting, addresses, pointedAddressIndex)
/// <summary>
/// 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
/// </summary>
public class IpV4OptionRecordRoute : IpV4OptionRoute
{
public IpV4OptionRecordRoute(byte pointedAddressIndex, IList<IpV4Address> addresses)
: base(IpV4OptionType.RecordRoute, addresses, pointedAddressIndex)
/// <summary>
/// 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)
: this(pointedAddressIndex, (IList<IpV4Address>)addresses)
/// <summary>
/// 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;
namespace PcapDotNet.Packets.IpV4
{
/// <summary>
/// The base class for route tracking options (loose, strict, record).
/// </summary>
public abstract class IpV4OptionRoute : IpV4OptionComplex, IEquatable<IpV4OptionRoute>
{
/// <summary>
/// The minimum option length in bytes (type, length, pointer).
/// </summary>
public const int OptionMinimumLength = 3;
/// <summary>
/// The minimum option value length in bytes (pointer).
/// </summary>
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;
/// <summary>
/// The pointed index in the route.
/// </summary>
public byte 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
{
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
{
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)
{
if (other == null)
......@@ -37,23 +71,24 @@ namespace PcapDotNet.Packets.IpV4
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)
{
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()
{
return base.GetHashCode() ^
PointedAddressIndex ^
PointedAddressIndex.GetHashCode() ^
Route.SequenceGetHashCode();
}
public ReadOnlyCollection<IpV4Address> Route
{
get { return _addresses; }
}
internal override void Write(byte[] buffer, ref int offset)
{
base.Write(buffer, ref offset);
......@@ -63,6 +98,15 @@ namespace PcapDotNet.Packets.IpV4
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,
byte[] buffer, ref int offset, byte valueLength)
{
......@@ -89,17 +133,20 @@ namespace PcapDotNet.Packets.IpV4
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)
{
if (pointedAddressIndex > PointedAddressIndexMaxValue)
throw new ArgumentOutOfRangeException("pointedAddressIndex", pointedAddressIndex, "Maximum value is " + PointedAddressIndexMaxValue);
_addresses = addresses.AsReadOnly();
_route = route.AsReadOnly();
_pointedAddressIndex = pointedAddressIndex;
}
private readonly ReadOnlyCollection<IpV4Address> _addresses;
private readonly ReadOnlyCollection<IpV4Address> _route;
private readonly byte _pointedAddressIndex;
}
}
\ No newline at end of file
......@@ -17,9 +17,35 @@ namespace PcapDotNet.Packets.IpV4
/// </summary>
public class IpV4OptionSecurity : IpV4OptionComplex, IEquatable<IpV4OptionSecurity>
{
/// <summary>
/// The number of bytes this option take.
/// </summary>
public const int OptionLength = 11;
/// <summary>
/// The number of bytes this option's value take.
/// </summary>
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,
ushort handlingRestrictions, UInt24 transmissionControlCode)
: base(IpV4OptionType.Security)
......@@ -68,16 +94,25 @@ namespace PcapDotNet.Packets.IpV4
get { return _transmissionControlCode; }
}
/// <summary>
/// The number of bytes this option will take.
/// </summary>
public override int Length
{
get { return OptionLength; }
}
/// <summary>
/// True iff this option may appear at most once in a datagram.
/// </summary>
public override bool IsAppearsAtMostOnce
{
get { return true; }
}
/// <summary>
/// Two security options are equal iff they have the exam same field values.
/// </summary>
public bool Equals(IpV4OptionSecurity other)
{
if (other == null)
......@@ -89,16 +124,23 @@ namespace PcapDotNet.Packets.IpV4
TransmissionControlCode == other.TransmissionControlCode;
}
/// <summary>
/// Two security options are equal iff they have the exam same field values.
/// </summary>
public override bool Equals(IpV4Option other)
{
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()
{
return base.GetHashCode() ^
(((ushort)Level << 16) | Compartments) ^
(HandlingRestrictions << 16) ^
(((ushort)Level << 16) | Compartments).GetHashCode() ^
(HandlingRestrictions << 16).GetHashCode() ^
TransmissionControlCode.GetHashCode();
}
......
......@@ -2,15 +2,27 @@ using System;
namespace PcapDotNet.Packets.IpV4
{
/// <summary>
/// A simple IPv4 option - holds only the type.
/// </summary>
public class IpV4OptionSimple : IpV4Option
{
/// <summary>
/// The number of bytes this option will take.
/// </summary>
public const int OptionLength = 1;
/// <summary>
/// The number of bytes this option will take.
/// </summary>
public override int Length
{
get { return OptionLength; }
}
/// <summary>
/// True iff this option may appear at most once in a datagram.
/// </summary>
public override bool IsAppearsAtMostOnce
{
get { return false; }
......
......@@ -3,7 +3,7 @@ using System;
namespace PcapDotNet.Packets.IpV4
{
/// <summary>
/// Stream Identifier
/// Stream Identifier option.
/// +--------+--------+--------+--------+
/// |10001000|00000010| Stream ID |
/// +--------+--------+--------+--------+
......@@ -16,30 +16,52 @@ namespace PcapDotNet.Packets.IpV4
/// </summary>
public class IpV4OptionStreamIdentifier : IpV4OptionComplex, IEquatable<IpV4OptionStreamIdentifier>
{
/// <summary>
/// The number of bytes this option take.
/// </summary>
public const int OptionLength = 4;
/// <summary>
/// The number of bytes this option's value take.
/// </summary>
public const int OptionValueLength = OptionLength - OptionHeaderLength;
/// <summary>
/// Create the option according to the given identifier.
/// </summary>
public IpV4OptionStreamIdentifier(ushort identifier)
: base(IpV4OptionType.StreamIdentifier)
{
_identifier = identifier;
}
/// <summary>
/// The identifier of the stream.
/// </summary>
public ushort Identifier
{
get { return _identifier; }
}
/// <summary>
/// The number of bytes this option will take.
/// </summary>
public override int Length
{
get { return OptionLength; }
}
/// <summary>
/// True iff this option may appear at most once in a datagram.
/// </summary>
public override bool IsAppearsAtMostOnce
{
get { return true; }
}
/// <summary>
/// Two stream identifier options are equal if they have the same identifier.
/// </summary>
public bool Equals(IpV4OptionStreamIdentifier other)
{
if (other == null)
......@@ -47,11 +69,18 @@ namespace PcapDotNet.Packets.IpV4
return Identifier == other.Identifier;
}
/// <summary>
/// Two stream identifier options are equal if they have the same identifier.
/// </summary>
public override bool Equals(IpV4Option other)
{
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()
{
return base.GetHashCode() ^
......
......@@ -45,8 +45,11 @@ namespace PcapDotNet.Packets.IpV4
/// </summary>
public class IpV4OptionStrictSourceRouting : IpV4OptionRoute
{
public IpV4OptionStrictSourceRouting(IList<IpV4Address> addresses, byte pointedAddressIndex)
: base(IpV4OptionType.StrictSourceRouting, addresses, pointedAddressIndex)
/// <summary>
/// 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;
namespace PcapDotNet.Packets.IpV4
{
/// <summary>
/// A pair of address and its time in the day.
/// </summary>
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;
_millisecondsSinceMidnightUt = timestamp;
_timeOfDay = timeOfDay;
}
/// <summary>
/// The address.
/// </summary>
public IpV4Address Address
{
get { return _address; }
}
public uint MillisecondsSinceMidnight
/// <summary>
/// The time passed since midnight UT.
/// </summary>
public IpV4OptionTimeOfDay TimeOfDay
{
get { return _millisecondsSinceMidnightUt; }
}
public TimeSpan TimeOfDay
{
get { return TimeSpan.FromMilliseconds(MillisecondsSinceMidnight); }
get { return _timeOfDay; }
}
/// <summary>
/// Two options are equal if they have the same address and time passed since midnight UT.
/// </summary>
public bool Equals(IpV4OptionTimedAddress other)
{
return Address == other.Address &&
MillisecondsSinceMidnight == other.MillisecondsSinceMidnight;
return Address.Equals(other.Address) &&
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)
{
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)
{
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)
{
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()
{
return _address.GetHashCode() ^
(int)_millisecondsSinceMidnightUt;
_timeOfDay.GetHashCode();
}
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
/// </summary>
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;
/// <summary>
/// The minimum length in bytes of the option value.
/// </summary>
public const int OptionValueMinimumLength = OptionMinimumLength - OptionHeaderLength;
/// <summary>
/// The maximum value for the overflow field.
/// </summary>
public const int OverflowMaxValue = 15;
/// <summary>
/// The maximum value for the pointed index field.
/// </summary>
public const int PointedIndexMaxValue = byte.MaxValue / 4 - 1;
/// <summary>
/// The timestamp option type.
/// </summary>
public IpV4OptionTimestampType TimestampType
{
get { return _timestampType; }
}
/// <summary>
/// The number of IP modules that cannot register timestamps due to lack of space.
/// </summary>
public byte 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
{
get { return _pointedIndex; }
}
/// <summary>
/// The number of bytes this option will take.
/// </summary>
public override int Length
{
get
......@@ -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
{
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)
{
if (other == null)
......@@ -98,17 +131,22 @@ namespace PcapDotNet.Packets.IpV4
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)
{
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()
{
return base.GetHashCode() ^
((byte)TimestampType << 16) ^
(Overflow << 8) ^
PointedIndex;
(((byte)TimestampType << 16) | (Overflow << 8)).GetHashCode() ^
PointedIndex.GetHashCode();
}
internal static IpV4OptionTimestamp ReadOptionTimestamp(byte[] buffer, ref int offset, int valueLength)
......@@ -151,6 +189,12 @@ namespace PcapDotNet.Packets.IpV4
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)
: base(IpV4OptionType.InternetTimestamp)
{
......@@ -165,10 +209,19 @@ namespace PcapDotNet.Packets.IpV4
_pointedIndex = pointedIndex;
}
/// <summary>
/// The number of bytes the value of the option take.
/// </summary>
protected abstract int ValuesLength { get; }
/// <summary>
/// True iff the options values is equal.
/// </summary>
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);
private readonly IpV4OptionTimestampType _timestampType;
......
......@@ -6,9 +6,19 @@ using PcapDotNet.Base;
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 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)
{
if (timestampType != IpV4OptionTimestampType.AddressAndTimestamp &&
......@@ -17,14 +27,32 @@ namespace PcapDotNet.Packets.IpV4
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
{
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()
{
return base.GetHashCode() ^ TimedRoute.SequenceGetHashCode();
......@@ -39,28 +67,37 @@ namespace PcapDotNet.Packets.IpV4
for (int i = 0; i != numValues / 2; ++i)
{
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);
}
/// <summary>
/// The number of bytes the value of the option take.
/// </summary>
protected override int ValuesLength
{
get { return TimedRoute.Count * (IpV4Address.SizeOf + sizeof(uint)); }
}
/// <summary>
/// True iff the options values is equal.
/// </summary>
protected override bool EqualValues(IpV4OptionTimestamp other)
{
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)
{
foreach (IpV4OptionTimedAddress addressAndTimestamp in TimedRoute)
{
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;
namespace PcapDotNet.Packets.IpV4
{
/// <summary>
/// Represents a timestamp IPv4 option with only the timestamps.
/// </summary>
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)
{
_timestamps = timestamps.AsReadOnly();
}
public IpV4OptionTimestampOnly(byte overflow, byte pointedIndex, params uint[] timestamps)
: this(overflow, 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, 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; }
}
/// <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()
{
return base.GetHashCode() ^ Timestamps.SequenceGetHashCode();
......@@ -31,29 +52,38 @@ namespace PcapDotNet.Packets.IpV4
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)
timestamps[i] = buffer.ReadUInt(ref offset, Endianity.Big);
timestamps[i] = buffer.ReadIpV4OptionTimeOfDay(ref offset, Endianity.Big);
return new IpV4OptionTimestampOnly(overflow, pointedIndex, timestamps);
}
/// <summary>
/// The number of bytes the value of the option take.
/// </summary>
protected override int ValuesLength
{
get { return Timestamps.Count * sizeof(uint); }
}
/// <summary>
/// Compares the values of the options.
/// </summary>
protected override bool EqualValues(IpV4OptionTimestamp other)
{
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)
{
foreach (uint timestamp in Timestamps)
buffer.Write(ref offset, timestamp, Endianity.Big);
foreach (IpV4OptionTimeOfDay timestamp in Timestamps)
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;
namespace PcapDotNet.Packets.IpV4
{
/// <summary>
/// The type of the timestamp ip option.
/// </summary>
public enum IpV4OptionTimestampType : byte
{
/// <summary>
/// Time stamps only, stored in consecutive 32-bit words.
/// </summary>
TimestampOnly = 0,
/// <summary>
/// Each timestamp is preceded with internet address of the registering entity.
/// </summary>
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
}
}
\ No newline at end of file
......@@ -23,36 +23,43 @@ namespace PcapDotNet.Packets.IpV4
/// This option occupies only 1 octet; it has no length octet.
/// </summary>
EndOfOptionList = 0,
/// <summary>
/// No Operation.
/// This option occupies only 1 octet; it has no length octet.
/// </summary>
NoOperation = 1,
/// <summary>
/// Security.
/// Used to carry Security, Compartmentation, User Group (TCC), and Handling Restriction Codes compatible with DOD requirements.
/// </summary>
Security = 130,
/// <summary>
/// Loose Source Routing.
/// Used to route the internet datagram based on information supplied by the source.
/// </summary>
LooseSourceRouting = 131,
/// <summary>
/// Strict Source Routing.
/// Used to route the internet datagram based on information supplied by the source.
/// </summary>
StrictSourceRouting = 137,
/// <summary>
/// Record Route.
/// Used to trace the route an internet datagram takes.
/// </summary>
RecordRoute = 7,
/// <summary>
/// Stream ID.
/// Used to carry the stream identifier.
/// </summary>
StreamIdentifier = 136,
/// <summary>
/// Internet Timestamp.
/// </summary>
......
......@@ -6,15 +6,31 @@ using PcapDotNet.Base;
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>
{
/// <summary>
/// The maximum number of bytes the options may take.
/// </summary>
public const int MaximumBytesLength = IpV4Datagram.HeaderMaximumLength - IpV4Datagram.HeaderMinimumLength;
/// <summary>
/// No options instance.
/// </summary>
public static IpV4Options 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)
: this(EndOptions(options), true)
{
......@@ -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");
}
/// <summary>
/// Creates options from a list of options.
/// </summary>
/// <param name="options">The list of options.</param>
public IpV4Options(params IpV4Option[] options)
: this((IList<IpV4Option>)options)
{
}
/// <summary>
/// The number of bytes the options take.
/// </summary>
public int BytesLength
{
get { return _bytesLength; }
}
/// <summary>
/// Whether or not the options parsed ok.
/// </summary>
public bool IsValid
{
get { return _isValid; }
}
/// <summary>
/// Two options are equal iff they have the exact same options.
/// </summary>
public bool Equals(IpV4Options other)
{
if (other == null)
......@@ -48,17 +77,28 @@ namespace PcapDotNet.Packets.IpV4
return this.SequenceEqual(other);
}
/// <summary>
/// Two options are equal iff they have the exact same options.
/// </summary>
public override bool Equals(object obj)
{
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()
{
return BytesLength.GetHashCode() ^
this.SequenceGetHashCode();
}
/// <summary>
/// A string of all the option type names.
/// </summary>
/// <returns></returns>
public override string ToString()
{
return this.SequenceToString(", ", typeof(IpV4Options).Name + " {", "}");
......@@ -70,6 +110,17 @@ namespace PcapDotNet.Packets.IpV4
_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)
: base(options)
{
......@@ -122,17 +173,6 @@ namespace PcapDotNet.Packets.IpV4
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 bool _isValid;
private static readonly IpV4Options _none = new IpV4Options();
......
namespace PcapDotNet.Packets.IpV4
{
/// <summary>
/// Indicates the next level IPv4 protocol used in the pyaload of the IPv4 datagram.
/// </summary>
public enum IpV4Protocol : byte
{
/// <summary>
......
......@@ -2,6 +2,7 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using PcapDotNet.Base;
using PcapDotNet.Packets.Ethernet;
namespace PcapDotNet.Packets
......@@ -92,68 +93,37 @@ namespace PcapDotNet.Packets
}
/// <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>
/// <returns>
/// A hash code for the current <see cref="T:System.Object"/>.
/// </returns>
/// <filterpriority>2</filterpriority>
public override int GetHashCode()
{
int hashCode = 0;
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;
return this.BytesSequenceGetHashCode();
}
/// <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>
/// <returns>
/// A <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
/// </returns>
/// <filterpriority>2</filterpriority>
public override string ToString()
{
return typeof(Packet).Name + " <" + DataLink + ", " + Length + ">";
}
/// <summary>
/// Returns an enumerator that iterates through the collection.
/// Returns an enumerator that iterates through the bytes of the packet.
/// </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()
{
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()
{
return GetEnumerator();
}
/// <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>
/// <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)
{
return ((IList<byte>)Buffer).IndexOf(item);
......@@ -176,15 +146,9 @@ namespace PcapDotNet.Packets
}
/// <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.
/// </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]
{
get { return Buffer[index]; }
......@@ -208,21 +172,16 @@ namespace PcapDotNet.Packets
}
/// <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>
/// <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)
{
return Buffer.Contains(item);
}
/// <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>
/// <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)
{
Buffer.BlockCopy(0, array, arrayIndex, Length);
......@@ -237,11 +196,8 @@ namespace PcapDotNet.Packets
}
/// <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>
/// <returns>
/// The number of elements contained in the <see cref="T:System.Collections.Generic.ICollection`1"/>.
/// </returns>
public int Count
{
get { return Length; }
......@@ -274,7 +230,7 @@ namespace PcapDotNet.Packets
}
/// <summary>
/// Takes the entire packet as an ethernet datagram.
/// Takes the entire packet as an Ethernet datagram.
/// </summary>
public EthernetDatagram Ethernet
{
......
......@@ -4,8 +4,20 @@ using PcapDotNet.Packets.IpV4;
namespace PcapDotNet.Packets
{
/// <summary>
/// The class to use to build all the packets.
/// </summary>
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,
MacAddress ethernetSource, MacAddress ethernetDestination, EthernetType ethernetType,
Datagram ethernetPayload)
......@@ -16,8 +28,24 @@ namespace PcapDotNet.Packets
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,
MacAddress ethernetSource, MacAddress ethernetDestination, EthernetType ethernetType,
MacAddress ethernetSource, MacAddress ethernetDestination,
byte ipV4TypeOfService, ushort ipV4Identification, IpV4Fragmentation ipV4Fragmentation,
byte ipV4Ttl, IpV4Protocol ipV4Protocol,
IpV4Address ipV4SourceAddress, IpV4Address ipV4DestinationAddress,
......@@ -26,7 +54,7 @@ namespace PcapDotNet.Packets
{
int ipHeaderLength = IpV4Datagram.HeaderMinimumLength + ipV4Options.BytesLength;
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,
ipV4TypeOfService, ipV4Identification, ipV4Fragmentation,
ipV4Ttl, ipV4Protocol,
......
......@@ -84,6 +84,7 @@
<Compile Include="IpV4\IpV4OptionStreamIdentifier.cs" />
<Compile Include="IpV4\IpV4OptionStrictSourceRouting.cs" />
<Compile Include="IpV4\IpV4OptionTimedAddress.cs" />
<Compile Include="IpV4\IpV4OptionTimeOfDay.cs" />
<Compile Include="IpV4\IpV4OptionTimestamp.cs" />
<Compile Include="IpV4\IpV4OptionTimestampAndAddress.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