IGMP - Internet Group Management Protocol

pcapkit.protocols.internet.igmp contains IGMP, the abstract base of the Internet Group Management Protocol (IGMP) [*] versions 1, 2 and 3. IGMPv1 and IGMPv2 share the 8-octet structure below. IGMPv1 and IGMPv2 set version and reuse this schema and data model as-is; IGMPv3’s wire format differs materially by message, so IGMPv3 carries its own instead – see IGMPv3 - Internet Group Management Protocol Version 3. alias names the protocol each message is read as: 'IGMP' for IGMPv1, the name RFC 1112 gives it, and 'IGMPv2' or 'IGMPv3' for the others. Constructing the base gives the version class its version keyword names; without it, octets give the class the message classifies as, and fields are refused. Its from_data() gives the class the version of its data names: every IGMP data model carries one, 1, 2 or 3, set by the class that read or built the message and on no octet, so an IGMPv1 and an IGMPv2 message read alike apart from it (#2574).

The structure is keyed as for IGMPv1; an IGMPv2 message’s keys start igmpv2 instead:

Octets

Bits

Name

Description

0

0

igmpv1.type

Type

1

8

igmpv1.max_resp_time

Max Response Time

2

16

igmpv1.checksum

Checksum

4

32

igmpv1.group

Group Address

class pcapkit.protocols.internet.igmp.IGMP[_PT: Data, _ST: Schema](file=None, length=None, **kwargs)[source]

Bases: Internet[_PT, _ST], Generic[_PT, _ST]

This class implements Internet Group Management Protocol.

The class is abstract: version is set by the concrete IGMPv1, IGMPv2 and IGMPv3 classes. read() refuses a message that _classify() does not place in version.

It dispatches on both paths, never giving an instance of this class (#2574). version names the version class; without it, octets give the one _dispatch() picks, and fields are refused, since no field picks a class. from_data() reads the version of its data. See __new__().

The checksum of every version is verified on read under CHECKSUM_VERIFY, unless the enclosing IP layer is a fragment, see _verify_checksum(); make() computes one it is not given.

property name: Literal['Internet Group Management Protocol']

Name of corresponding protocol.

abstract property version: Literal[1, 2, 3]

IGMP version this class reads, 1, 2 or 3.

property alias: str

Acronym of corresponding protocol, 'IGMP', 'IGMPv2' or 'IGMPv3'.

IGMPv1 reports 'IGMP', the name RFC 1112 gives it.

property length: Literal[8]

Header length of current protocol.

classmethod id()[source]

Index ID of the protocol.

RFC 1112 names the protocol IGMP, without a version, the same shape ICMP takes for RFC 792 – so the family base’s own name doubles as IGMPv1’s canonical name. RFC 2236 and RFC 3376 name IGMPv2 and IGMPv3 with their own versions.

Return type:

tuple[Literal['IGMP'], Literal['IGMPv2'], Literal['IGMPv3']]

Returns:

Index ID of the protocol, the family name and the IGMPv2 and IGMPv3 names; the concrete IGMPv1, IGMPv2 and IGMPv3 classes narrow it to their own canonical name.

read(length=None, **kwargs)[source]

Read Internet Group Management Protocol.

Parameters:
  • length (int | None) – Length of packet data.

  • **kwargs (Any) – Arbitrary keyword arguments.

Raises:

ProtocolError – If _classify() does not place the message in version.

Return type:

_PT

Returns:

Parsed packet data.

make(type=Type.IGMP_Membership_Query, max_resp_time=0, checksum=None, group='0.0.0.0', payload=b'', **kwargs)[source]

Make (construct) packet data.

The version of a constructed message is decided by its type, max_resp_time and length (see _classify()), not by the class that built it.

Parameters:
  • type (Type | int) – Message type.

  • max_resp_time (int) – Max response time, in tenths of a second; zero for an IGMPv1 message.

  • checksum (bytes | None) – Checksum over the message with this field zeroed, no pseudo-header (RFC 2236 Section 2.3); if None, computed over the message, payload included, when CHECKSUM_COMPUTE is on, zero when it is off.

  • group (IPv4Address | str | bytes | int) – Group address; 0.0.0.0 for a General Query.

  • payload (bytes | ProtocolBase | Schema) – Payload of current instance.

  • **kwargs (Any) – Arbitrary keyword arguments.

Return type:

_ST

Returns:

Constructed packet data.

Raises:

ProtocolError – If type is a name, a bool, or a member or code outside 0 to 255, max_resp_time is not a non-bool integer from 0 to 255, or checksum is not two octets.

classmethod from_data(data, **kwargs)[source]

Create protocol instance from data.

Parameters:
Return type:

Self

Returns:

Protocol instance; on this class, an instance of the version class the version of data names, which every IGMP data model carries (#2574).

Raises:

ProtocolError – If data carries no version, or one that names no version class, on this class.

classmethod __index__()[source]

Numeral registry index of the protocol.

Return type:

TransType

Returns:

Numeral registry index of the protocol in IANA.

__init__(file=None, length=None, *, version=None, **kwargs)[source]

Initialisation.

Parameters:
  • file (IO[bytes] | bytes | None) – Source packet stream.

  • length (int | None) – Length of packet data.

  • version (Literal[1, 2, 3] | None) – Version of IGMP, 1, 2 or 3: the class __new__() picks. Building from fields, it must be this class’s version. Parsing, it is handed on unread, as the enclosing IP layer passes its own version under this name to the layer it carries.

  • **kwargs (Any) – As Protocol.__init__.

Raises:

ProtocolError – If, building from fields, version names no version class, or is not this class’s own version, which every IGMP class states, a subclass outside the members included.

static __new__(cls, file=None, length=None, **kwargs)[source]

Create the version class a construction of this class describes.

The version keyword names the class, on either path. Without it, parsing octets gives the class _dispatch() picks, and building from fields is refused, since no field picks a class. That class’s __init__ then runs with the same arguments. A subclass of this class is created as itself.

Parameters:
  • file (IO[bytes] | bytes | None) – Source packet stream, read here without being consumed.

  • length (int | None) – Length of packet data.

  • **kwargs (Any) – Arbitrary keyword arguments.

Return type:

IGMP

Returns:

An uninitialised instance of the version class.

Raises:

ProtocolError – If version names no version class; or, without it, if building from fields, or if the octets are no version’s message.

classmethod _make_data(data)[source]

Create key-value pairs from data for protocol construction.

Parameters:

data (IGMP) – protocol data

Return type:

dict[str, Any]

Returns:

Key-value pairs for protocol construction.

classmethod _classify(type, max_resp_time, length)[source]

Classify a parsed IGMP header as IGMPv1, IGMPv2 or IGMPv3.

A Membership Query is IGMPv1/v2 only at exactly 8 octets: IGMPv1 if max_resp_time is zero, IGMPv2 otherwise. A Membership Query of 12 or more octets is IGMPv3’s Query, carrying the source-list extension (RFC 3376 Section 7.1); one of 9 to 11 octets is neither and is ignored. The IGMPv3 Membership Report (0x22) is always IGMPv3, whatever its length.

Parameters:
  • type (Type | int) – The header’s message type.

  • max_resp_time (int) – The header’s max response time (the raw Max Resp Code octet; unused for a type whose version does not depend on it).

  • length (int) – The whole IGMP message’s length, in octets.

Return type:

Literal[0, 1, 2, 3]

Returns:

1, 2 or 3 for that version, 0 for none of them.

_verify_checksum(igmp, checksum, length)[source]

Record on igmp the outcome of verifying the message’s checksum.

Only under CHECKSUM_VERIFY, as checksum_status. Every version’s checksum covers the whole message, the entire IP payload, with no pseudo-header (RFC 2236 Section 2.3, RFC 3376 Section 4.1.2, RFC 3376 Section 4.2.2). That holds for IGMPv1 as well: RFC 1112 defines an 8-octet message, and RFC 2236, which updates it, sums a longer one whole (RFC 2236 Section 2.5). See verify_message(). A message the data ends inside, as its header’s __short_read__ records, is TRUNCATED (#2689).

Parameters:
  • igmp (_PT) – Parsed message data.

  • checksum (bytes) – The checksum field, as on the wire.

  • length (int) – The whole message’s length, in octets.

classmethod _dispatch(data, length)[source]

Pick the class that parses the IGMP message at the start of data.

The type and max response time are the first two octets, read here before any class is built, and _classify() decides the version.

Parameters:
  • data (bytes) – Payload of the IP layer, starting at the IGMP message.

  • length (int) – The IGMP message’s length, in octets.

Return type:

Type[ProtocolBase] | Type[Raw]

Returns:

IGMPv1, IGMPv2 or IGMPv3 for the version the message classifies as; Raw for any other message, which then keeps its octets undissected.

static _member_of_version(version)[source]

The version class a version of 1, 2 or 3 names.

Parameters:

version (Any) – Version of IGMP, as _classify() returns it or the version keyword gives it.

Return type:

Type[IGMP]

Returns:

IGMPv1, IGMPv2 or IGMPv3.

Raises:

ProtocolError – If version names none of them, or is no int: a bool or a float is refused even where it equals one.

Header Schemas

class pcapkit.protocols.schema.internet.igmp.IGMP(type=NO_VALUE, max_resp_time=NO_VALUE, checksum=NO_VALUE, group=NO_VALUE, payload=NO_VALUE, *, __packet__=None, **kwargs)[source]

Bases: Schema

Header schema for IGMP packet.

The same 8-octet layout serves IGMPv1 (RFC 1112 Page 11) and IGMPv2 (RFC 2236 Section 2): v1 leaves max_resp_time reserved at zero rather than omitting the octet (#2439).

type: Type = <EnumField type>

Message type.

max_resp_time: int = <UInt8Field max_resp_time>

Max response time, in units of 1/10 second (zero/reserved outside an IGMPv2 Membership Query).

checksum: bytes = <BytesField checksum>

Checksum. The 16-bit one’s complement of the one’s complement sum of the message, with the checksum field itself taken as zero and no pseudo-header involved – the 8-octet message itself for IGMPv1 (RFC 1112 Page 11), or the whole IP payload for IGMPv2 (RFC 2236 Section 2.3).

group: IPv4Address = <IPv4AddressField group>

Group address.

payload: bytes = <PayloadField payload>

Payload, empty for a standards-conformant IGMPv1/v2 message, since the 8-octet header is the whole message. It is the rest of the IP payload, which the checksum covers too, so a cut inside it is recorded (#2711).

Data Models

class pcapkit.protocols.data.internet.igmp.IGMP(version, type, max_resp_time, checksum, group)[source]

Bases: Protocol

Data model for Internet Group Management Protocol.

This single schema covers both IGMPv1 (RFC 1112 Page 11) and IGMPv2 (RFC 2236 Section 2) messages: v1’s 8-octet header is the same shape as v2’s, with max_resp_time reserved at zero and fewer type values defined (#2439). IGMPv3 (RFC 3376) adds a group-record-list body of a materially different shape and is out of scope here – see pcapkit.protocols.data.internet.igmpv3.

version: Literal[1, 2]

Version of IGMP the message was read as, 1 or 2 – the version of the class that read or built it. It is on no octet, since the versions share this layout, and IGMP.from_data dispatches on it (#2574).

type: Type

Message type.

max_resp_time: int

Max response time, in units of 1/10 second. Meaningful only for a Membership Query under IGMPv2 (RFC 2236 Section 2.2); reserved and zero on every other message, including every IGMPv1 one (RFC 1112 Page 11).

checksum: bytes

Checksum.

group: IPv4Address

Group address – the IPv4 multicast group being queried, reported or left, or 0.0.0.0 on a General Query.

checksum_status: ChecksumStatus

Outcome of verifying checksum, present only when CHECKSUM_VERIFY is on.

Footnotes