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 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="MoreFunc.cs" />
<Compile Include="MoreIEnumerable.cs" />
<Compile Include="MoreIList.cs" />
<Compile Include="MorePropertyInfo.cs" />
......
......@@ -76,9 +76,7 @@ namespace PcapDotNet.Packets.Test
byte ipV4TypeOfService = random.NextByte();
ushort ipV4Identification = random.NextUShort();
byte ipV4Ttl = random.NextByte();
IpV4FragmentationOptions ipV4FragmentationOptions = random.NextEnum<IpV4FragmentationOptions>();
ushort ipV4FragmentationOffset = (ushort)(random.NextUShort(ushort.MaxValue / 8) * 8);
IpV4Fragmentation ipV4Fragmentation = new IpV4Fragmentation(ipV4FragmentationOptions, ipV4FragmentationOffset);
IpV4Fragmentation ipV4Fragmentation = random.NextIpV4Fragmentation();
IpV4Address ipV4Source = new IpV4Address(random.NextUInt());
IpV4Address ipV4Destination = new IpV4Address(random.NextUInt());
IpV4Options ipV4Options = random.NextIpV4Options();
......@@ -125,9 +123,7 @@ namespace PcapDotNet.Packets.Test
igmpMaxResponseTime = random.NextTimeSpan(TimeSpan.FromSeconds(0.1),
IgmpDatagram.MaxVersion3MaxResponseTime - TimeSpan.FromTicks(1));
igmpQueryInterval = random.NextTimeSpan(TimeSpan.Zero, IgmpDatagram.MaxVersion3QueryInterval - TimeSpan.FromTicks(1));
igmpSourceAddresses = new IpV4Address[random.Next(1000)];
for (int sourceAddressIndex = 0; sourceAddressIndex != igmpSourceAddresses.Length; ++sourceAddressIndex)
igmpSourceAddresses[sourceAddressIndex] = random.NextIpV4Address();
igmpSourceAddresses = random.NextIpV4Addresses(random.Next(1000));
packet = PacketBuilder.EthernetIpV4IgmpQueryVersion3(DateTime.Now,
ethernetSource, ethernetDestination,
ipV4TypeOfService, ipV4Identification, ipV4Fragmentation, ipV4Ttl,
......@@ -170,14 +166,7 @@ namespace PcapDotNet.Packets.Test
case IgmpMessageType.MembershipReportVersion3:
igmpMaxResponseTime = TimeSpan.Zero;
igmpGroupRecords = new IgmpGroupRecord[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));
}
igmpGroupRecords = random.NextIgmpGroupRecords(random.Next(100));
packet = PacketBuilder.EthernetIpV4IgmpReportVersion3(DateTime.Now,
ethernetSource, ethernetDestination,
ipV4TypeOfService, ipV4Identification, ipV4Fragmentation, ipV4Ttl,
......
......@@ -2,8 +2,10 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PcapDotNet.Base;
using PcapDotNet.Packets;
using PcapDotNet.Packets.Ethernet;
using PcapDotNet.Packets.Igmp;
using PcapDotNet.Packets.IpV4;
using PcapDotNet.Packets.Transport;
using PcapDotNet.TestUtils;
......@@ -75,6 +77,11 @@ namespace PcapDotNet.Packets.TestUtils
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)
{
IpV4FragmentationOptions ipV4FragmentationFlags = random.NextEnum<IpV4FragmentationOptions>();
......@@ -151,9 +158,7 @@ namespace PcapDotNet.Packets.TestUtils
case IpV4OptionType.StrictSourceRouting:
case IpV4OptionType.RecordRoute:
int numAddresses = random.Next((maximumOptionLength - IpV4OptionRoute.OptionMinimumLength) / 4 + 1);
IpV4Address[] addresses = new IpV4Address[numAddresses];
for (int addressIndex = 0; addressIndex != numAddresses; ++addressIndex)
addresses[addressIndex] = random.NextIpV4Address();
IpV4Address[] addresses = random.NextIpV4Addresses(numAddresses);
byte pointedAddressIndex;
if (random.NextBool())
......@@ -192,9 +197,7 @@ namespace PcapDotNet.Packets.TestUtils
{
case IpV4OptionTimestampType.TimestampOnly:
int numTimestamps = random.Next((maximumOptionLength - IpV4OptionTimestamp.OptionMinimumLength) / 4 + 1);
IpV4OptionTimeOfDay[] timestamps = new IpV4OptionTimeOfDay[numTimestamps];
for (int i = 0; i != numTimestamps; ++i)
timestamps[i] = random.NextIpV4OptionTimeOfDay();
IpV4OptionTimeOfDay[] timestamps = ((Func<IpV4OptionTimeOfDay>)random.NextIpV4OptionTimeOfDay).GenerateArray(numTimestamps);
return new IpV4OptionTimestampOnly(overflow, pointedIndex, timestamps);
case IpV4OptionTimestampType.AddressAndTimestamp:
......@@ -260,8 +263,7 @@ namespace PcapDotNet.Packets.TestUtils
unknownOptionType = (TcpOptionType)unknownOptionTypeValue;
} while (unknownOptionType.ToString() != unknownOptionTypeValue.ToString());
Byte[] unknownOptionData = new byte[random.Next(maximumOptionLength - TcpOptionUnknown.OptionMinimumLength + 1)];
random.NextBytes(unknownOptionData);
byte[] unknownOptionData = random.NextBytes(maximumOptionLength - TcpOptionUnknown.OptionMinimumLength + 1);
return new TcpOptionUnknown(unknownOptionType, unknownOptionData);
}
......@@ -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)
{
int optionsLength = random.Next(TcpOptions.MaximumBytesLength) / 4 * 4;
......
......@@ -110,6 +110,13 @@ namespace PcapDotNet.Packets.Igmp
public const int GroupRecords = 8;
}
public const byte MaxQueryRobustnessVariable = 0x07;
public static TimeSpan MaxMaxResponseTime
{
get { return _maxMaxResponseTime; }
}
public static TimeSpan MaxVersion3MaxResponseTime
{
get { return _maxVersion3MaxResponseTime; }
......@@ -128,6 +135,46 @@ namespace PcapDotNet.Packets.Igmp
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>
/// The IGMP version of a Membership Query message is determined as follows:
/// <list type="bullet">
......@@ -260,7 +307,7 @@ namespace PcapDotNet.Packets.Igmp
/// </remarks>
public bool IsSuppressRouterSideProcessing
{
get { return ((this[Offset.IsSuppressRouterSideProcessing] >> 4) & 0x01) == 0x01; }
get { return ((this[Offset.IsSuppressRouterSideProcessing] >> 3) & 0x01) == 0x01; }
}
/// <summary>
......@@ -459,9 +506,9 @@ namespace PcapDotNet.Packets.Igmp
buffer.Write(offset + Offset.GroupAddress, groupAddress, Endianity.Big);
// IsSuppressRouterSideProcessing and QueryRobustnessVariable
if (queryRobustnessVariable > 0x07)
if (queryRobustnessVariable > MaxQueryRobustnessVariable)
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
if (queryInterval < TimeSpan.Zero || queryInterval > MaxVersion3QueryInterval)
......@@ -591,6 +638,7 @@ namespace PcapDotNet.Packets.Igmp
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 _maxVersion3QueryInterval = TimeSpan.FromSeconds(CodeToValue(byte.MaxValue)) + TimeSpan.FromSeconds(1) - TimeSpan.FromTicks(1);
......
......@@ -329,13 +329,14 @@ namespace PcapDotNet.Packets
TimeSpan igmpQueryInterval, IEnumerable<IpV4Address> igmpSourceAddresses)
{
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);
IpV4Datagram.WriteHeader(buffer, EthernetDatagram.HeaderLength,
ipV4TypeOfService, ipV4Identification, ipV4Fragmentation,
ipV4Ttl, IpV4Protocol.InternetGroupManagementProtocol,
ipV4SourceAddress, ipV4DestinationAddress,
ipV4Options, IgmpDatagram.HeaderLength);
ipV4Options, igmpLength);
IgmpDatagram.WriteQueryVersion3(buffer, EthernetDatagram.HeaderLength + ipHeaderLength,
igmpMaxResponseTime, igmpGroupAddress, igmpIsSuppressRouterSideProcessing, igmpQueryRobustnessVariable,
igmpQueryInterval, igmpSourceAddresses);
......@@ -372,13 +373,14 @@ namespace PcapDotNet.Packets
IEnumerable<IgmpGroupRecord> igmpGroupRecords)
{
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);
IpV4Datagram.WriteHeader(buffer, EthernetDatagram.HeaderLength,
ipV4TypeOfService, ipV4Identification, ipV4Fragmentation,
ipV4Ttl, IpV4Protocol.InternetGroupManagementProtocol,
ipV4SourceAddress, ipV4DestinationAddress,
ipV4Options, IgmpDatagram.HeaderLength);
ipV4Options, igmpLength);
IgmpDatagram.WriteReportVersion3(buffer, EthernetDatagram.HeaderLength + ipHeaderLength,
igmpGroupRecords);
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