Commit 5e6eba25 authored by Brickner_cp's avatar Brickner_cp

IGMP

parent 35a8a475
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace PcapDotNet.Base
{
/// <summary>
/// Extension methods for Func of type T.
/// </summary>
public static class MoreFunc
{
public static T[] GenerateArray<T>(this Func<T> generator, int size)
{
T[] array = new T[size];
for (int i = 0; i != size; ++i)
array[i] = generator.Invoke();
return array;
}
}
}
\ No newline at end of file
...@@ -59,6 +59,7 @@ ...@@ -59,6 +59,7 @@
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="MoreFunc.cs" />
<Compile Include="MoreIEnumerable.cs" /> <Compile Include="MoreIEnumerable.cs" />
<Compile Include="MoreIList.cs" /> <Compile Include="MoreIList.cs" />
<Compile Include="MorePropertyInfo.cs" /> <Compile Include="MorePropertyInfo.cs" />
......
...@@ -76,9 +76,7 @@ namespace PcapDotNet.Packets.Test ...@@ -76,9 +76,7 @@ namespace PcapDotNet.Packets.Test
byte ipV4TypeOfService = random.NextByte(); byte ipV4TypeOfService = random.NextByte();
ushort ipV4Identification = random.NextUShort(); ushort ipV4Identification = random.NextUShort();
byte ipV4Ttl = random.NextByte(); byte ipV4Ttl = random.NextByte();
IpV4FragmentationOptions ipV4FragmentationOptions = random.NextEnum<IpV4FragmentationOptions>(); IpV4Fragmentation ipV4Fragmentation = random.NextIpV4Fragmentation();
ushort ipV4FragmentationOffset = (ushort)(random.NextUShort(ushort.MaxValue / 8) * 8);
IpV4Fragmentation ipV4Fragmentation = new IpV4Fragmentation(ipV4FragmentationOptions, ipV4FragmentationOffset);
IpV4Address ipV4Source = new IpV4Address(random.NextUInt()); IpV4Address ipV4Source = new IpV4Address(random.NextUInt());
IpV4Address ipV4Destination = new IpV4Address(random.NextUInt()); IpV4Address ipV4Destination = new IpV4Address(random.NextUInt());
IpV4Options ipV4Options = random.NextIpV4Options(); IpV4Options ipV4Options = random.NextIpV4Options();
...@@ -125,9 +123,7 @@ namespace PcapDotNet.Packets.Test ...@@ -125,9 +123,7 @@ namespace PcapDotNet.Packets.Test
igmpMaxResponseTime = random.NextTimeSpan(TimeSpan.FromSeconds(0.1), igmpMaxResponseTime = random.NextTimeSpan(TimeSpan.FromSeconds(0.1),
IgmpDatagram.MaxVersion3MaxResponseTime - TimeSpan.FromTicks(1)); IgmpDatagram.MaxVersion3MaxResponseTime - TimeSpan.FromTicks(1));
igmpQueryInterval = random.NextTimeSpan(TimeSpan.Zero, IgmpDatagram.MaxVersion3QueryInterval - TimeSpan.FromTicks(1)); igmpQueryInterval = random.NextTimeSpan(TimeSpan.Zero, IgmpDatagram.MaxVersion3QueryInterval - TimeSpan.FromTicks(1));
igmpSourceAddresses = new IpV4Address[random.Next(1000)]; igmpSourceAddresses = random.NextIpV4Addresses(random.Next(1000));
for (int sourceAddressIndex = 0; sourceAddressIndex != igmpSourceAddresses.Length; ++sourceAddressIndex)
igmpSourceAddresses[sourceAddressIndex] = random.NextIpV4Address();
packet = PacketBuilder.EthernetIpV4IgmpQueryVersion3(DateTime.Now, packet = PacketBuilder.EthernetIpV4IgmpQueryVersion3(DateTime.Now,
ethernetSource, ethernetDestination, ethernetSource, ethernetDestination,
ipV4TypeOfService, ipV4Identification, ipV4Fragmentation, ipV4Ttl, ipV4TypeOfService, ipV4Identification, ipV4Fragmentation, ipV4Ttl,
...@@ -170,19 +166,12 @@ namespace PcapDotNet.Packets.Test ...@@ -170,19 +166,12 @@ namespace PcapDotNet.Packets.Test
case IgmpMessageType.MembershipReportVersion3: case IgmpMessageType.MembershipReportVersion3:
igmpMaxResponseTime = TimeSpan.Zero; igmpMaxResponseTime = TimeSpan.Zero;
igmpGroupRecords = new IgmpGroupRecord[random.Next(100)]; igmpGroupRecords = random.NextIgmpGroupRecords(random.Next(100));
for (int groupRecordIndex = 0; groupRecordIndex != igmpGroupRecords.Length; ++groupRecordIndex)
{
IpV4Address[] sourceAddresses = new IpV4Address[random.Next(100)];
for (int sourceAddressIndex = 0; sourceAddressIndex != sourceAddresses.Length; ++sourceAddressIndex)
sourceAddresses[sourceAddressIndex] = random.NextIpV4Address();
igmpGroupRecords[groupRecordIndex] = new IgmpGroupRecord(random.NextEnum<IgmpRecordType>(), random.NextIpV4Address(), sourceAddresses, random.NextDatagram(100));
}
packet = PacketBuilder.EthernetIpV4IgmpReportVersion3(DateTime.Now, packet = PacketBuilder.EthernetIpV4IgmpReportVersion3(DateTime.Now,
ethernetSource, ethernetDestination, ethernetSource, ethernetDestination,
ipV4TypeOfService, ipV4Identification, ipV4Fragmentation, ipV4Ttl, ipV4TypeOfService, ipV4Identification, ipV4Fragmentation, ipV4Ttl,
ipV4Source, ipV4Destination, ipV4Options, ipV4Source, ipV4Destination, ipV4Options,
igmpGroupRecords); igmpGroupRecords);
break; break;
default: default:
......
...@@ -2,8 +2,10 @@ using System; ...@@ -2,8 +2,10 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using PcapDotNet.Base;
using PcapDotNet.Packets; using PcapDotNet.Packets;
using PcapDotNet.Packets.Ethernet; using PcapDotNet.Packets.Ethernet;
using PcapDotNet.Packets.Igmp;
using PcapDotNet.Packets.IpV4; using PcapDotNet.Packets.IpV4;
using PcapDotNet.Packets.Transport; using PcapDotNet.Packets.Transport;
using PcapDotNet.TestUtils; using PcapDotNet.TestUtils;
...@@ -75,6 +77,11 @@ namespace PcapDotNet.Packets.TestUtils ...@@ -75,6 +77,11 @@ namespace PcapDotNet.Packets.TestUtils
return new IpV4Address(random.NextUInt()); return new IpV4Address(random.NextUInt());
} }
public static IpV4Address[] NextIpV4Addresses(this Random random, int count)
{
return ((Func<IpV4Address>)random.NextIpV4Address).GenerateArray(count);
}
public static IpV4Fragmentation NextIpV4Fragmentation(this Random random) public static IpV4Fragmentation NextIpV4Fragmentation(this Random random)
{ {
IpV4FragmentationOptions ipV4FragmentationFlags = random.NextEnum<IpV4FragmentationOptions>(); IpV4FragmentationOptions ipV4FragmentationFlags = random.NextEnum<IpV4FragmentationOptions>();
...@@ -151,9 +158,7 @@ namespace PcapDotNet.Packets.TestUtils ...@@ -151,9 +158,7 @@ namespace PcapDotNet.Packets.TestUtils
case IpV4OptionType.StrictSourceRouting: case IpV4OptionType.StrictSourceRouting:
case IpV4OptionType.RecordRoute: case IpV4OptionType.RecordRoute:
int numAddresses = random.Next((maximumOptionLength - IpV4OptionRoute.OptionMinimumLength) / 4 + 1); int numAddresses = random.Next((maximumOptionLength - IpV4OptionRoute.OptionMinimumLength) / 4 + 1);
IpV4Address[] addresses = new IpV4Address[numAddresses]; IpV4Address[] addresses = random.NextIpV4Addresses(numAddresses);
for (int addressIndex = 0; addressIndex != numAddresses; ++addressIndex)
addresses[addressIndex] = random.NextIpV4Address();
byte pointedAddressIndex; byte pointedAddressIndex;
if (random.NextBool()) if (random.NextBool())
...@@ -192,9 +197,7 @@ namespace PcapDotNet.Packets.TestUtils ...@@ -192,9 +197,7 @@ 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);
IpV4OptionTimeOfDay[] timestamps = new IpV4OptionTimeOfDay[numTimestamps]; IpV4OptionTimeOfDay[] timestamps = ((Func<IpV4OptionTimeOfDay>)random.NextIpV4OptionTimeOfDay).GenerateArray(numTimestamps);
for (int i = 0; i != numTimestamps; ++i)
timestamps[i] = random.NextIpV4OptionTimeOfDay();
return new IpV4OptionTimestampOnly(overflow, pointedIndex, timestamps); return new IpV4OptionTimestampOnly(overflow, pointedIndex, timestamps);
case IpV4OptionTimestampType.AddressAndTimestamp: case IpV4OptionTimestampType.AddressAndTimestamp:
...@@ -260,8 +263,7 @@ namespace PcapDotNet.Packets.TestUtils ...@@ -260,8 +263,7 @@ namespace PcapDotNet.Packets.TestUtils
unknownOptionType = (TcpOptionType)unknownOptionTypeValue; unknownOptionType = (TcpOptionType)unknownOptionTypeValue;
} while (unknownOptionType.ToString() != unknownOptionTypeValue.ToString()); } while (unknownOptionType.ToString() != unknownOptionTypeValue.ToString());
Byte[] unknownOptionData = new byte[random.Next(maximumOptionLength - TcpOptionUnknown.OptionMinimumLength + 1)]; byte[] unknownOptionData = random.NextBytes(maximumOptionLength - TcpOptionUnknown.OptionMinimumLength + 1);
random.NextBytes(unknownOptionData);
return new TcpOptionUnknown(unknownOptionType, unknownOptionData); return new TcpOptionUnknown(unknownOptionType, unknownOptionData);
} }
...@@ -372,6 +374,21 @@ namespace PcapDotNet.Packets.TestUtils ...@@ -372,6 +374,21 @@ namespace PcapDotNet.Packets.TestUtils
} }
} }
// IGMP
public static IgmpGroupRecord NextIgmpGroupRecord(this Random random)
{
IpV4Address[] sourceAddresses = random.NextIpV4Addresses(random.Next(10));
return new IgmpGroupRecord(random.NextEnum<IgmpRecordType>(), random.NextIpV4Address(), sourceAddresses, random.NextDatagram(random.Next(10) * 4));
}
public static IgmpGroupRecord[] NextIgmpGroupRecords(this Random random, int count)
{
return ((Func<IgmpGroupRecord>)random.NextIgmpGroupRecord).GenerateArray(count);
}
// TCP
public static TcpOptions NextTcpOptions(this Random random) public static TcpOptions NextTcpOptions(this Random random)
{ {
int optionsLength = random.Next(TcpOptions.MaximumBytesLength) / 4 * 4; int optionsLength = random.Next(TcpOptions.MaximumBytesLength) / 4 * 4;
......
...@@ -110,6 +110,13 @@ namespace PcapDotNet.Packets.Igmp ...@@ -110,6 +110,13 @@ namespace PcapDotNet.Packets.Igmp
public const int GroupRecords = 8; public const int GroupRecords = 8;
} }
public const byte MaxQueryRobustnessVariable = 0x07;
public static TimeSpan MaxMaxResponseTime
{
get { return _maxMaxResponseTime; }
}
public static TimeSpan MaxVersion3MaxResponseTime public static TimeSpan MaxVersion3MaxResponseTime
{ {
get { return _maxVersion3MaxResponseTime; } get { return _maxVersion3MaxResponseTime; }
...@@ -128,6 +135,46 @@ namespace PcapDotNet.Packets.Igmp ...@@ -128,6 +135,46 @@ namespace PcapDotNet.Packets.Igmp
get { return (IgmpMessageType)this[Offset.MessageType]; } get { return (IgmpMessageType)this[Offset.MessageType]; }
} }
public int Version
{
get
{
switch (MessageType)
{
case IgmpMessageType.MembershipQuery:
switch (QueryVersion)
{
case IgmpQueryVersion.Version1:
return 1;
case IgmpQueryVersion.Version2:
return 2;
case IgmpQueryVersion.Version3:
return 3;
default:
throw new InvalidOperationException("Invalid QueryVersion " + QueryVersion);
}
case IgmpMessageType.MembershipReportVersion1:
return 1;
case IgmpMessageType.MembershipReportVersion2:
return 2;
case IgmpMessageType.MembershipReportVersion3:
return 3;
case IgmpMessageType.LeaveGroupVersion2:
return 2;
default:
throw new InvalidOperationException("Invalid MessageType " + MessageType);
}
}
}
/// <summary> /// <summary>
/// The IGMP version of a Membership Query message is determined as follows: /// The IGMP version of a Membership Query message is determined as follows:
/// <list type="bullet"> /// <list type="bullet">
...@@ -260,7 +307,7 @@ namespace PcapDotNet.Packets.Igmp ...@@ -260,7 +307,7 @@ namespace PcapDotNet.Packets.Igmp
/// </remarks> /// </remarks>
public bool IsSuppressRouterSideProcessing public bool IsSuppressRouterSideProcessing
{ {
get { return ((this[Offset.IsSuppressRouterSideProcessing] >> 4) & 0x01) == 0x01; } get { return ((this[Offset.IsSuppressRouterSideProcessing] >> 3) & 0x01) == 0x01; }
} }
/// <summary> /// <summary>
...@@ -459,9 +506,9 @@ namespace PcapDotNet.Packets.Igmp ...@@ -459,9 +506,9 @@ namespace PcapDotNet.Packets.Igmp
buffer.Write(offset + Offset.GroupAddress, groupAddress, Endianity.Big); buffer.Write(offset + Offset.GroupAddress, groupAddress, Endianity.Big);
// IsSuppressRouterSideProcessing and QueryRobustnessVariable // IsSuppressRouterSideProcessing and QueryRobustnessVariable
if (queryRobustnessVariable > 0x07) if (queryRobustnessVariable > MaxQueryRobustnessVariable)
throw new ArgumentOutOfRangeException("queryRobustnessVariable", queryRobustnessVariable, "must be in range [0, 7]"); throw new ArgumentOutOfRangeException("queryRobustnessVariable", queryRobustnessVariable, "must be in range [0, 7]");
buffer.Write(offset + Offset.QueryRobustnessVariable, (byte)(queryRobustnessVariable | (isSuppressRouterSideProcessing ? 0x10 : 0x00))); buffer.Write(offset + Offset.QueryRobustnessVariable, (byte)(queryRobustnessVariable | (isSuppressRouterSideProcessing ? 0x08 : 0x00)));
// QueryIntervalCode // QueryIntervalCode
if (queryInterval < TimeSpan.Zero || queryInterval > MaxVersion3QueryInterval) if (queryInterval < TimeSpan.Zero || queryInterval > MaxVersion3QueryInterval)
...@@ -591,6 +638,7 @@ namespace PcapDotNet.Packets.Igmp ...@@ -591,6 +638,7 @@ namespace PcapDotNet.Packets.Igmp
return (byte)(0x80 | (exp << 4) | mant); return (byte)(0x80 | (exp << 4) | mant);
} }
private static readonly TimeSpan _maxMaxResponseTime = TimeSpan.FromSeconds(0.1 * 255) + TimeSpan.FromSeconds(0.1) - TimeSpan.FromTicks(1);
private static readonly TimeSpan _maxVersion3MaxResponseTime = TimeSpan.FromSeconds(0.1 * CodeToValue(byte.MaxValue)) + TimeSpan.FromSeconds(0.1) - TimeSpan.FromTicks(1); private static readonly TimeSpan _maxVersion3MaxResponseTime = TimeSpan.FromSeconds(0.1 * CodeToValue(byte.MaxValue)) + TimeSpan.FromSeconds(0.1) - TimeSpan.FromTicks(1);
private static readonly TimeSpan _maxVersion3QueryInterval = TimeSpan.FromSeconds(CodeToValue(byte.MaxValue)) + TimeSpan.FromSeconds(1) - TimeSpan.FromTicks(1); private static readonly TimeSpan _maxVersion3QueryInterval = TimeSpan.FromSeconds(CodeToValue(byte.MaxValue)) + TimeSpan.FromSeconds(1) - TimeSpan.FromTicks(1);
......
...@@ -329,13 +329,14 @@ namespace PcapDotNet.Packets ...@@ -329,13 +329,14 @@ namespace PcapDotNet.Packets
TimeSpan igmpQueryInterval, IEnumerable<IpV4Address> igmpSourceAddresses) TimeSpan igmpQueryInterval, IEnumerable<IpV4Address> igmpSourceAddresses)
{ {
int ipHeaderLength = IpV4Datagram.HeaderMinimumLength + ipV4Options.BytesLength; int ipHeaderLength = IpV4Datagram.HeaderMinimumLength + ipV4Options.BytesLength;
byte[] buffer = new byte[EthernetDatagram.HeaderLength + ipHeaderLength + IgmpDatagram.GetQueryVersion3Length(igmpSourceAddresses.Count())]; int igmpLength = IgmpDatagram.GetQueryVersion3Length(igmpSourceAddresses.Count());
byte[] buffer = new byte[EthernetDatagram.HeaderLength + ipHeaderLength + igmpLength];
EthernetDatagram.WriteHeader(buffer, 0, ethernetSource, ethernetDestination, EthernetType.IpV4); 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.InternetGroupManagementProtocol, ipV4Ttl, IpV4Protocol.InternetGroupManagementProtocol,
ipV4SourceAddress, ipV4DestinationAddress, ipV4SourceAddress, ipV4DestinationAddress,
ipV4Options, IgmpDatagram.HeaderLength); ipV4Options, igmpLength);
IgmpDatagram.WriteQueryVersion3(buffer, EthernetDatagram.HeaderLength + ipHeaderLength, IgmpDatagram.WriteQueryVersion3(buffer, EthernetDatagram.HeaderLength + ipHeaderLength,
igmpMaxResponseTime, igmpGroupAddress, igmpIsSuppressRouterSideProcessing, igmpQueryRobustnessVariable, igmpMaxResponseTime, igmpGroupAddress, igmpIsSuppressRouterSideProcessing, igmpQueryRobustnessVariable,
igmpQueryInterval, igmpSourceAddresses); igmpQueryInterval, igmpSourceAddresses);
...@@ -372,13 +373,14 @@ namespace PcapDotNet.Packets ...@@ -372,13 +373,14 @@ namespace PcapDotNet.Packets
IEnumerable<IgmpGroupRecord> igmpGroupRecords) IEnumerable<IgmpGroupRecord> igmpGroupRecords)
{ {
int ipHeaderLength = IpV4Datagram.HeaderMinimumLength + ipV4Options.BytesLength; int ipHeaderLength = IpV4Datagram.HeaderMinimumLength + ipV4Options.BytesLength;
byte[] buffer = new byte[EthernetDatagram.HeaderLength + ipHeaderLength + IgmpDatagram.GetReportVersion3Length(igmpGroupRecords)]; int igmpLength = IgmpDatagram.GetReportVersion3Length(igmpGroupRecords);
byte[] buffer = new byte[EthernetDatagram.HeaderLength + ipHeaderLength + igmpLength];
EthernetDatagram.WriteHeader(buffer, 0, ethernetSource, ethernetDestination, EthernetType.IpV4); 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.InternetGroupManagementProtocol, ipV4Ttl, IpV4Protocol.InternetGroupManagementProtocol,
ipV4SourceAddress, ipV4DestinationAddress, ipV4SourceAddress, ipV4DestinationAddress,
ipV4Options, IgmpDatagram.HeaderLength); ipV4Options, igmpLength);
IgmpDatagram.WriteReportVersion3(buffer, EthernetDatagram.HeaderLength + ipHeaderLength, IgmpDatagram.WriteReportVersion3(buffer, EthernetDatagram.HeaderLength + ipHeaderLength,
igmpGroupRecords); igmpGroupRecords);
return new Packet(buffer, timestamp, DataLinkKind.Ethernet); return new Packet(buffer, timestamp, DataLinkKind.Ethernet);
......
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