Commit 32469b4d authored by Brickner_cp's avatar Brickner_cp

IGMP

parent acbfb27f
...@@ -4,6 +4,7 @@ using System.Collections.Generic; ...@@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using PcapDotNet.Base; using PcapDotNet.Base;
using PcapDotNet.Packets.Ethernet; using PcapDotNet.Packets.Ethernet;
using PcapDotNet.Packets.IpV4;
namespace PcapDotNet.Packets namespace PcapDotNet.Packets
{ {
...@@ -198,6 +199,35 @@ namespace PcapDotNet.Packets ...@@ -198,6 +199,35 @@ namespace PcapDotNet.Packets
return Buffer.ReadMacAddress(StartOffset + offset, endianity); return Buffer.ReadMacAddress(StartOffset + offset, endianity);
} }
protected IpV4Address ReadIpV4Address(int offset, Endianity endianity)
{
return Buffer.ReadIpV4Address(StartOffset + offset, endianity);
}
protected static ushort Sum16BitsToChecksum(uint sum)
{
// Take only 16 bits out of the 32 bit sum and add up the carrier.
// if the results overflows - do it again.
while (sum > 0xFFFF)
sum = (sum & 0xFFFF) + (sum >> 16);
// one's complement the result
sum = ~sum;
return (ushort)sum;
}
protected static uint Sum16Bits(byte[] buffer, int offset, int length)
{
int endOffset = offset + length;
uint sum = 0;
while (offset < endOffset - 1)
sum += buffer.ReadUShort(ref offset, Endianity.Big);
if (offset < endOffset)
sum += (ushort)(buffer[offset] << 8);
return sum;
}
private static readonly Datagram _empty = new Datagram(new byte[0], 0, 0); private static readonly Datagram _empty = new Datagram(new byte[0], 0, 0);
private readonly byte[] _buffer; private readonly byte[] _buffer;
private readonly int _startOffset; private readonly int _startOffset;
......
This diff is collapsed.
using System;
using System.Collections.ObjectModel;
using PcapDotNet.Packets.IpV4;
namespace PcapDotNet.Packets.Igmp
{
/// <summary>
/// Each Group Record is a block of fields containing information pertaining
/// to the sender's membership in a single multicast group on the interface from which the Report is sent.
/// A Group Record has the following internal format:
/// <pre>
/// +-----+-------------+--------------+--------+--------------+
/// | Bit | 0-7 | 8-15 | 16-31 | |
/// +-----+-------------+--------------+--------+--------------+
/// | 0 | Record Type | Aux Data Len | Number of Sources (N) |
/// +-----+-------------+--------------+--------+--------------+
/// | 32 | Multicast Address |
/// +-----+----------------------------------------------------+
/// | 64 | Source Address [1] |
/// +-----+----------------------------------------------------+
/// | 96 | Source Address [2] |
/// +-----+----------------------------------------------------+
/// . . . .
/// . . . .
/// +-----+----------------------------------------------------+
/// | 32 | Source Address [N] |
/// | + | |
/// | 32N | |
/// +-----+----------------------------------------------------+
/// | 64 | Auxiliary Data |
/// . + . .
/// . 32N . .
/// . . .
/// | | |
/// +-----+----------------------------------------------------+
/// </summary>
public class IgmpGroupRecordDatagram : Datagram
{
private static class Offset
{
public const int RecordType = 0;
public const int AuxiliaryDataLength = 1;
public const int NumberOfSources = 2;
public const int MulticastAddress = 4;
public const int SourceAddresses = 8;
}
public const int HeaderMinimumLength = 8;
public IgmpRecordType RecordType
{
get { return (IgmpRecordType)this[Offset.RecordType]; }
}
/// <summary>
/// The Aux Data Len field contains the length of the Auxiliary Data field in this Group Record, in bytes (after a translation from 32 bit words length).
/// It may contain zero, to indicate the absence of any auxiliary data.
/// </summary>
public int AuxiliaryDataLength
{
get { return 4 * this[Offset.AuxiliaryDataLength]; }
}
/// <summary>
/// The Number of Sources (N) field specifies how many source addresses are present in this Group Record.
/// </summary>
public int NumberOfSources
{
get { return ReadUShort(Offset.NumberOfSources, Endianity.Big); }
}
/// <summary>
/// The Multicast Address field contains the IP multicast address to which this Group Record pertains.
/// </summary>
public IpV4Address MulticastAddress
{
get { return ReadIpV4Address(Offset.MulticastAddress, Endianity.Big); }
}
/// <summary>
/// The Source Address [i] fields are a vector of n IP unicast addresses,
/// where n is the value in this record's Number of Sources (N) field.
/// </summary>
public ReadOnlyCollection<IpV4Address> SourceAddresses
{
get
{
IpV4Address[] sourceAddresses = new IpV4Address[NumberOfSources];
for (int i = 0; i != sourceAddresses.Length; ++i)
sourceAddresses[i] = ReadIpV4Address(Offset.SourceAddresses + 4 * i, Endianity.Big);
return new ReadOnlyCollection<IpV4Address>(sourceAddresses);
}
}
/// <summary>
/// The Auxiliary Data field, if present, contains additional information pertaining to this Group Record.
/// The protocol specified in this document, IGMPv3, does not define any auxiliary data.
/// Therefore, implementations of IGMPv3 MUST NOT include any auxiliary data (i.e., MUST set the Aux Data Len field to zero) in any transmitted Group Record,
/// and MUST ignore any auxiliary data present in any received Group Record.
/// The semantics and internal encoding of the Auxiliary Data field are to be defined by any future version or extension of IGMP that uses this field.
/// </summary>
public Datagram AuxiliaryData
{
get { return new Datagram(Buffer, StartOffset + Offset.AuxiliaryDataLength, AuxiliaryDataLength); }
}
internal IgmpGroupRecordDatagram(byte[] buffer, int offset)
: base(buffer, offset,
buffer.Length - offset < HeaderMinimumLength
? buffer.Length - offset
: Math.Min(buffer.Length - offset, HeaderMinimumLength +
4 * buffer.ReadUShort(offset + Offset.NumberOfSources, Endianity.Big) +
4 * buffer.ReadByte(offset + Offset.AuxiliaryDataLength)))
{
}
protected override bool CalculateIsValid()
{
return Length >= HeaderMinimumLength &&
Length == HeaderMinimumLength + 4 * NumberOfSources + AuxiliaryDataLength;
}
}
}
\ No newline at end of file
namespace PcapDotNet.Packets.Igmp
{
public enum IgmpQueryVersion
{
None,
Version1,
Version2,
Version3,
Unknown
}
}
\ No newline at end of file
namespace PcapDotNet.Packets.Igmp
{
/// <summary>
/// Group Record Type.
/// </summary>
public enum IgmpRecordType : byte
{
/// <summary>
/// A "Current-State Record" is sent by a system in response to a Query received on an interface.
/// It reports the current reception state of that interface, with respect to a single multicast address.
/// <para>
/// MODE_IS_INCLUDE - indicates that the interface has a filter mode of INCLUDE for the specified multicast address.
/// The Source Address [i] fields in this Group Record contain the interface's source list for the specified multicast address, if it is non-empty.
/// </para>
/// </summary>
CurrentStateRecordModeIsInclude = 1,
/// <summary>
/// A "Current-State Record" is sent by a system in response to a Query received on an interface.
/// It reports the current reception state of that interface, with respect to a single multicast address.
/// <para>
/// MODE_IS_EXCLUDE - indicates that the interface has a filter mode of EXCLUDE for the specified multicast address.
/// The Source Address [i] fields in this Group Record contain the interface's source list for the specified multicast address, if it is non-empty.
/// </para>
/// </summary>
CurrentStateRecordModeIsExclude = 2,
/// <summary>
/// A "Filter-Mode-Change Record" is sent by a system whenever a local invocation of IPMulticastListen causes a change of the filter mode
/// (i.e., a change from INCLUDE to EXCLUDE, or from EXCLUDE to INCLUDE),
/// of the interface-level state entry for a particular multicast address.
/// The Record is included in a Report sent from the interface on which the change occurred.
/// <para>
/// CHANGE_TO_INCLUDE_MODE - indicates that the interface has changed to INCLUDE filter mode for the specified multicast address.
/// The Source Address [i] fields in this Group Record contain the interface's new source list for the specified multicast address, if it is non-empty.
/// </para>
/// </summary>
FilterModeChangeToInclude = 3,
/// <summary>
/// A "Filter-Mode-Change Record" is sent by a system whenever a local invocation of IPMulticastListen causes a change of the filter mode
/// (i.e., a change from INCLUDE to EXCLUDE, or from EXCLUDE to INCLUDE),
/// of the interface-level state entry for a particular multicast address.
/// The Record is included in a Report sent from the interface on which the change occurred.
/// <para>
/// CHANGE_TO_EXCLUDE_MODE - indicates that the interface has changed to EXCLUDE filter mode for the specified multicast address.
/// The Source Address [i] fields in this Group Record contain the interface's new source list for the specified multicast address, if it is non-empty.
/// </para>
/// </summary>
FilterModeChangeToExclude= 4,
/// <summary>
/// A "Source-List-Change Record" is sent by a system whenever a local invocation of IPMulticastListen causes a change of source list
/// that is *not* coincident with a change of filter mode, of the interface-level state entry for a particular multicast address.
/// The Record is included in a Report sent from the interface on which the change occurred.
/// <para>
/// ALLOW_NEW_SOURCES - indicates that the Source Address [i] fields in this Group Record contain a list of the additional sources
/// that the system wishes to hear from, for packets sent to the specified multicast address.
/// If the change was to an INCLUDE source list, these are the addresses that were added to the list; if the change was to an EXCLUDE source list,
/// these are the addresses that were deleted from the list.
/// </para>
/// <para>
/// If a change of source list results in both allowing new sources and blocking old sources,
/// then two Group Records are sent for the same multicast address, one of type ALLOW_NEW_SOURCES and one of type BLOCK_OLD_SOURCES.
/// </para>
/// </summary>
SourceListChangeAllowNewSources = 5,
/// <summary>
/// A "Source-List-Change Record" is sent by a system whenever a local invocation of IPMulticastListen causes a change of source list
/// that is *not* coincident with a change of filter mode, of the interface-level state entry for a particular multicast address.
/// The Record is included in a Report sent from the interface on which the change occurred.
/// <para>
/// BLOCK_OLD_SOURCES - indicates that the Source Address [i] fields in this Group Record contain a list of the sources
/// that the system no longer wishes to hear from, for packets sent to the specified multicast address.
/// If the change was to an INCLUDE source list, these are the addresses that were deleted from the list; if the change was to an EXCLUDE source list,
/// these are the addresses that were added to the list.
/// </para>
/// If a change of source list results in both allowing new sources and blocking old sources,
/// then two Group Records are sent for the same multicast address, one of type ALLOW_NEW_SOURCES and one of type BLOCK_OLD_SOURCES.
/// </para>
/// </summary>
SourceListChangeBlockOldSources = 6,
}
}
\ No newline at end of file
namespace PcapDotNet.Packets.Igmp
{
public enum IgmpType : byte
{
/// <summary>
/// Membership Query (RFC3376).
/// </summary>
MembershipQuery = 0x11,
/// <summary>
/// Version 3 Membership Report (RFC3376).
/// </summary>
MembershipReportVersion3 = 0x22,
/// <summary>
/// Version 1 Membership Report (RFC1112).
/// </summary>
MembershipReportVersion1 = 0x12,
/// <summary>
/// Version 2 Membership Report (RFC2236).
/// </summary>
MembershipReportVersion2 = 0x16,
/// <summary>
/// Version 2 Leave Group (RFC2236).
/// </summary>
LeaveGroupVersion2 = 0x17
}
}
\ No newline at end of file
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
using System.Collections; using System.Collections;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using PcapDotNet.Packets.Igmp;
using PcapDotNet.Packets.Transport; using PcapDotNet.Packets.Transport;
namespace PcapDotNet.Packets.IpV4 namespace PcapDotNet.Packets.IpV4
...@@ -161,7 +162,7 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -161,7 +162,7 @@ namespace PcapDotNet.Packets.IpV4
/// </summary> /// </summary>
public IpV4Address Source public IpV4Address Source
{ {
get { return new IpV4Address(ReadUInt(Offset.Source, Endianity.Big)); } get { return ReadIpV4Address(Offset.Source, Endianity.Big); }
} }
/// <summary> /// <summary>
...@@ -169,7 +170,7 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -169,7 +170,7 @@ namespace PcapDotNet.Packets.IpV4
/// </summary> /// </summary>
public IpV4Address Destination public IpV4Address Destination
{ {
get { return new IpV4Address(ReadUInt(Offset.Destination, Endianity.Big)); } get { return ReadIpV4Address(Offset.Destination, Endianity.Big); }
} }
/// <summary> /// <summary>
...@@ -212,6 +213,20 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -212,6 +213,20 @@ namespace PcapDotNet.Packets.IpV4
get { return Tcp; } get { return Tcp; }
} }
/// <summary>
/// The payload of the datagram as an IGMP datagram.
/// </summary>
public IgmpDatagram Igmp
{
get
{
if (_igmp == null && Length >= HeaderLength)
_igmp = new IgmpDatagram(Buffer, StartOffset + HeaderLength, Length - HeaderLength);
return _igmp;
}
}
/// <summary> /// <summary>
/// The payload of the datagram as a TCP datagram. /// The payload of the datagram as a TCP datagram.
/// </summary> /// </summary>
...@@ -333,6 +348,10 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -333,6 +348,10 @@ namespace PcapDotNet.Packets.IpV4
case IpV4Protocol.Udp: case IpV4Protocol.Udp:
return Transport.IsValid && (Transport.IsChecksumOptional && Transport.Checksum == 0 || return Transport.IsValid && (Transport.IsChecksumOptional && Transport.Checksum == 0 ||
IsTransportChecksumCorrect); IsTransportChecksumCorrect);
case IpV4Protocol.InternetGroupManagementProtocol:
return Igmp.IsValid;
default: default:
// Todo check more protocols // Todo check more protocols
return true; return true;
...@@ -347,33 +366,10 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -347,33 +366,10 @@ namespace PcapDotNet.Packets.IpV4
return Sum16BitsToChecksum(sum); return Sum16BitsToChecksum(sum);
} }
private static ushort Sum16BitsToChecksum(uint sum)
{
// Take only 16 bits out of the 32 bit sum and add up the carrier.
// if the results overflows - do it again.
while (sum > 0xFFFF)
sum = (sum & 0xFFFF) + (sum >> 16);
// one's complement the result
sum = ~sum;
return (ushort)sum;
}
private static uint Sum16Bits(byte[] buffer, int offset, int length)
{
int endOffset = offset + length;
uint sum = 0;
while (offset < endOffset - 1)
sum += buffer.ReadUShort(ref offset, Endianity.Big);
if (offset < endOffset)
sum += (ushort)(buffer[offset] << 8);
return sum;
}
private bool? _isHeaderChecksumCorrect; private bool? _isHeaderChecksumCorrect;
private bool? _isTransportChecksumCorrect; private bool? _isTransportChecksumCorrect;
private IpV4Options _options; private IpV4Options _options;
private IgmpDatagram _igmp;
private TcpDatagram _tcp; private TcpDatagram _tcp;
private UdpDatagram _udp; private UdpDatagram _udp;
} }
......
...@@ -71,6 +71,11 @@ ...@@ -71,6 +71,11 @@
<Compile Include="Ethernet\EthernetType.cs" /> <Compile Include="Ethernet\EthernetType.cs" />
<Compile Include="Ethernet\MacAddress.cs" /> <Compile Include="Ethernet\MacAddress.cs" />
<Compile Include="IDataLink.cs" /> <Compile Include="IDataLink.cs" />
<Compile Include="Igmp\IgmpDatagram.cs" />
<Compile Include="Igmp\IgmpGroupRecordDatagram.cs" />
<Compile Include="Igmp\IgmpQueryVersion.cs" />
<Compile Include="Igmp\IgmpRecordType.cs" />
<Compile Include="Igmp\IgmpType.cs" />
<Compile Include="IOptionUnknownFactory.cs" /> <Compile Include="IOptionUnknownFactory.cs" />
<Compile Include="IpV4\IpV4OptionUnknown.cs" /> <Compile Include="IpV4\IpV4OptionUnknown.cs" />
<Compile Include="Option.cs" /> <Compile Include="Option.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