IGMPv3
Table of Contents >> Optional Protocols
Contents
- 1 Introduction
- 2 Implementation Notes
- 3 System-wide Macros
- 4 tfInitTreckOptions() / tfSetTreckOptions() Parameters
- 5 tfInterfaceSetOptions()
- 6 tfInterfaceGetOptions()
- 7 setsockopt()
- 8 ip_mreq Parameters
- 9 ip_mreq_source Parameters
- 10 group_req Parameters
- 11 group_source_req Parameters
- 12 getsockopt()
- 13 Advanced APIs
Introduction
IGMPv3 for IPv4 allows receiver applications to specify source filters on multicast group memberships, so that applications only receive multicast packets from specified sources. The source filters can exclude or include source addresses. This capability is desired in the case of one-to-many type multicast applications.
To support source filtering of multicast packets new socket APIs have been added.
The current IP Multicast APIs allow a receiver application to specify the multicast group address (destination) and (optionally) the local interface.
The new source filter socket APIs provide the same functionality but also allow receiver multicast applications to:
- Specify zero or more unicast (source) address(es) in a source filter.
- Determine whether the source filter describes an inclusive or exclusive list of sources.
Two modes of setting source filters are provided: "include", and "exclude" modes. The user cannot mix include and exclude modes. At any given time, the source filter list for a given socket, interface, and multicast group address is either inclusive, or exclusive.
| Source Filter Mode | Comments |
|---|---|
| include | For a given multicast group address, and interface, the user accepts multicasts on the socket from sources addresses on the list. |
| exclude | For a given multicast group address, and interface, the user accepts multicasts on the socket from all source addresses except the ones on the list. |
Two sets of APIs are provided as specified in RFC 3678:
- Basic (Delta-Based) APIs using the setsockopt() BSD socket API.
- Advanced (Full-State) APIs which allow the user to define a complete source-filter comprised of zero or more source-addresses, and replace the previous filter with a new one.
| API | Type of API | Comments |
|---|---|---|
| setsockopt() | Basic | Cannot do getsockopt. Add filter addresses one at a time. Can use exclusive or inclusive mode. Must leave the group to switch between inclusive and exclusive mode. |
| setipv4sourcefilter(), setsourcefilter() |
Advanced | Can specify complete source filter list with one call. Can replace a source filter list with a new one. Can switch between inclusive and exclusive mode without leaving the group. setsourcefilter() supports IPv4 and IPv6 addresses. |
| getipv4sourcefilter(), getsourcefilter() |
Advanced | Application can retrieve source filter list. getsourcefilter() supports IPv4 and IPv6 addresses. |
| tfIoctl() | Advanced | Obsoleted by setipv4sourcefilter(), getipv4sourcefilter(), setsourcefilter() and getsourcefilter() which provide the same functionality. tfIoctl() is provided for backward compatibility. |
Implementation Notes
- The host (but not the router) side of IGMPv3 is implemented.
- When TM_USE_IGMPV3 is defined, the IGMPv3 protocol is supported along with IGMPv2 and IGMPv1 for backward compatibility.
System-wide Macros
| Macro Name | Default Value | Comments |
|---|---|---|
| TM_USE_IGMPV3 | Not defined | Add '#define TM_USE_IGMPV3' to <trsystem.h>. |
| TM_IP_MAX_SOURCE_FILTER | 128 | Maximum number of source addresses in the filter per multicast group. The user can redefine this macro with another value in <trsystem.h>. |
| TM_SO_MAX_SOURCE_FILTER | 64 | Maximum number of source addresses in the filter per socket for a given multicast group. The user can redefine this macro with another value in <trsystem.h>. |
tfInitTreckOptions() / tfSetTreckOptions() Parameters
The user can change the per context default values for the maximum source filter per group and/or per socket at run time using either the tfSetTreckOptions() or tfInitTreckOptions() APIs.
| Option Name | Comments |
|---|---|
| TM_OPTION_IGMP_SO_MAX_SRC_FILTER | Maximum Source Filter per socket. |
| TM_OPTION_IGMP_IP_MAX_SRC_FILTER | Maximum Source Filter per multicast group. |
tfInterfaceSetOptions()
To prevent DOS attacks, RFC 3376 states:
Hosts SHOULD ignore v2 or v3 Queries without the Router-Alert option.
Unfortunately some routers do send IGMPv2 Queries without the router alert option. The stack follows the RFC, but allows the user to set an interface option to alter the behavior so that the stack can process IGMPv2 queries even when the local routers do not set the router alert option in the IGMPv2 queries.
A new option TM_DEV_OPTIONS_NO_IGMPV2_RA has been added to tfInterfaceSetOptions().
| Option Name | Data Type | Comments | |
|---|---|---|---|
| TM_DEV_OPTIONS_NO_IGMPV2_RA | unsigned char | 0 | Drop incoming IGMPv2 queries that do not carry the router alert option.
(Default per RFC 3376.) |
| 1 | Accept IGMPv2 queries that do not carry the router alert option. | ||
Example
To prevent the stack from dropping IGMPv2 queries that do not carry the router alert option, call tfInterfaceSetOptions() as follows:
unsigned char optionValue; optionValue = 1; errorCode = tfInterfaceSetOptions(interfaceHandle, TM_DEV_OPTIONS_NO_IGMPV2_RA, &optionValue, sizeof(unsigned char));
tfInterfaceGetOptions()
The user can check whether the TM_DEV_OPTIONS_NO_IGMPV2_RA is on or off, by calling tfInterfaceGetOptions().
Example
unsigned char optionValue; errorCode = tfInterfaceGetOptions(interfaceHandle, TM_DEV_OPTIONS_NO_IGMPV2_RA, &optionValue, sizeof(unsigned char));
setsockopt()
New options have been added to setsockopt() at the SOL_SOCKET level to allow the user to specify source filters.
IPv4-Specific Data Structures
Two data structures are used by setsockopt with the IPv4-specific IGMP multicast options; struct ip_mreq is an existing structure; struct ip_mreq_source has been added to support source filtering.
| Data Structure | Usage |
|---|---|
| struct ip_mreq | Currently used by the user to specify the multicast group address (destination) and optionally the local interface. It allows any source address. |
| struct ip_mreq_source | This new data structure allows the user to specify a source address in addition to the multicast group address (destination) and local interface. |
#include <trsocket.h> /* Structure used for joining or leaving a group multicast IP address */ struct ip_mreq { struct in_addr imr_multiaddr; /* IPv4 Class D multicast address */ struct in_addr imr_interface; /* IPv4 address of local interface */ };
ip_mreq Parameters
- imr_multiaddr
- IP host group address that the user wants to join/leave.
- imr_interface
- IP address of the local interface that the host group address is to be joined on, or is to leave from. If zero, then the default local interface selected with tfSetMcastInterface() will be used instead.
#include <trsocket.h> /* Structure used for Source-Specific Multicast (RFC 3678) */ struct ip_mreq_source { struct in_addr imr_multiaddr; /* IPv4 Class D multicast address */ struct in_addr imr_sourceaddr; /* IPv4 address of peer's source */ struct in_addr imr_interface; /* IPv4 address of local interface */ };
ip_mreq_source Parameters
- imr_multiaddr
- IP host group address that the user wants to join/leave.
- imr_sourceaddr
- IP address of the peer's source.
- imr_interface
- IP address of the local interface that the host group address is to be joined on, or is to leave from. If 0, then the default local interface selected with tfSetMcastInterface() will be used instead.
| An imr_interface IP address of zero is valid if the user has either designated a default multicast interface for the socket via the IP_MULTICAST_IF socket option, or designated a default multicast interface for the system via tfSetMcastInterface(). |
Protocol-Independent Data Structures
Two data structures are used by setsockopt with the protocol-independent IGMP multicast options:
| Data Structure | Usage |
|---|---|
| struct group_req | Used with MCAST_JOIN_GROUP and MCAST_LEAVE_GROUP socket options to specify the multicast group address (destination) and, optionally, the local interface. It allows any source address. |
| struct group_source_req | Used with MCAST_BLOCK_SOURCE, MCAST_UNBLOCK_SOURCE, MCAST_JOIN_SOURCE_GROUP and MCAST_LEAVE_SOURCE_GROUP socket options to specify the multicast group address (destination), source address and, optionally, the local interface. |
#include <trsocket.h> /* * Structure used by setsockopt() options MCAST_JOIN_GROUP and * MCAST_LEAVE_GROUP to join or leave an IP multicast group * address (see RFC 3678 section 5.1). * Supports IPv4 (IGMP) and IPv6 (MLD). */ struct group_req { ttUser32Bit gr_interface; /* interface index */ struct sockaddr_storage gr_group; /* group address */ };
group_req Parameters
- gr_interface
- Index of the corresponding configured interface as returned by if_nametoindex(). Note that a zero index is valid if the user has either designated a default multicast interface for the socket via the IP_MULTICAST_IF or IPV6_MULTICAST_IF socket options, or designated a default multicast interface for the system via tfSetMcastInterface() or tf6SetMcastInterface().
- gr_group
- Destination multicast group address (IPv4 or IPv6).
#include <trsocket.h> /* * Structure used for source-specific IP multicast setsockopt() options * MCAST_BLOCK_SOURCE, MCAST_UNBLOCK_SOURCE, MCAST_JOIN_SOURCE_GROUP and * MCAST_LEAVE_SOURCE_GROUP (see RFC 3678 section 5.1). * Supports IPv4 (IGMPv3) and IPv6 (MLDv2). */ struct group_source_req { ttUser32Bit gsr_interface; /* interface index */ struct sockaddr_storage gsr_group; /* group address */ struct sockaddr_storage gsr_source; /* source address */ };
group_source_req Parameters
- gsr_interface
- Index of the corresponding configured interface as returned by if_nametoindex(). Note that a zero index is valid if the user has either designated a default multicast interface for the socket via the IP_MULTICAST_IF or IPV6_MULTICAST_IF socket options, or designated a default multicast interface for the system via tfSetMcastInterface() or tf6SetMcastInterface().
- gsr_group
- Destination multicast group address (IPv4 or IPv6).
- gsr_source
- Peer's IPv4 or IPv6 address to be added or removed from the source filter. Note: the address families of gsr_group and gsr_source must match.
| An interface index of zero is valid if the user has either designated a default multicast interface for the socket via the IP_MULTICAST_IF socket option, or designated a default multicast interface for the system via tfSetMcastInterface(). |
Options
IP_ADD_MEMBERSHIP and IP_DROP_MEMBERSHIP are existing options. All other options have been added to support source filtering.
IPv4 Any Source Multicast API (Exclude Mode)
By default, all sources are accepted. Individual sources may be turned off and back on as needed over time. This is also known as "exclude" mode, since the source filter contains a list of excluded sources.
| Option | Associated Structure | Comment |
|---|---|---|
| IP_ADD_MEMBERSHIP | struct ip_mreq | Join the specified multicast group, regardless of the source address. |
| IP_DROP_MEMBERSHIP | struct ip_mreq | Leave the specified multicast group, regardless of the source address. |
| IP_BLOCK_SOURCE | struct ip_mreq_source | Block data from a given source to a given multicast group (mute). |
| IP_UNBLOCK_SOURCE | struct ip_mreq_source | Unblock data from a given source to a given multicast group (un-mute). |
IPv4 Source Specific Multicast API (Include Mode)
Only sources in a given list are allowed. The list may change over time. This is also known as "include" mode, since the source filter contains a list of included sources. IPv4 Source Specific Multicast API would be used, for example, by "single-source" applications such as audio/video broadcasting. It would also be used for logical multi-source sessions where each source independently allocates its own Source-Specific Multicast group address.
| Option | Associated Structure | Comment |
|---|---|---|
| IP_ADD_SOURCE_MEMBERSHIP | struct ip_mreq_source | Join a source-specific group. |
| IP_DROP_SOURCE_MEMBERSHIP | struct ip_mreq_source | Leave a source-specific group. |
| IP_DROP_MEMBERSHIP | struct ip_mreq | Provided as a convenience. Drop all sources which have been joined for a particular group and interface. |
Protocol-Independent Any Source Multicast API (Exclude Mode)
By default, all sources are accepted. Individual sources may be turned off and back on as needed over time. This is also known as "exclude" mode, since the source filter contains a list of excluded sources.
| Option | Associated Structure | Comment |
|---|---|---|
| MCAST_JOIN_GROUP | struct group_req | Join the specified multicast group, regardless of the source address. |
| MCAST_LEAVE_GROUP | struct group_req | Leave the specified multicast group, regardless of the source address. |
| MCAST_BLOCK_SOURCE | struct group_source_req | Block data from a given source to a given multicast group (mute). |
| MCAST_UNBLOCK_SOURCE | struct group_source_req | Unblock data from a given source to a given multicast group (un-mute). |
Protocol-Independent Source Specific Multicast API (Include Mode)
Only sources in a given list are allowed. The list may change over time. This is also known as "include" mode, since the source filter contains a list of included sources. Protocol-independent Source Specific Multicast API would be used, for example, by "single-source" applications such as audio/video broadcasting. It would also be used for logical multi-source sessions where each source independently allocates its own Source-Specific Multicast group address.
| Option | Associated Structure | Comment |
|---|---|---|
| MCAST_JOIN_SOURCE_GROUP | struct group_source_req | Join a source-specific group. |
| MCAST_LEAVE_SOURCE_GROUP | struct group_source_req | Leave a source-specific group. |
| MCAST_LEAVE_GROUP | struct group_req | Provided as a convenience. Drop all sources which have been joined for a particular group and interface. |
Return Codes
Upon success, setsockopt() returns TM_ENOERROR. Upon failure, setsockopt() returns TM_SOCKET_ERROR, and sets the error code on the socket. To retrieve the socket error the user must call tfGetSocketError().
| Socket Error | Meaning |
|---|---|
| TM_EBADF | Invalid socket descriptor. |
| TM_EPROTOTYPE | The socket is not of type SOCK_DGRAM or SOCK_RAW |
| TM_EINVAL | Operation is not legal on the multicast group. (i.e., when trying a Source-Specific option on a group after doing IP_ADD_MEMBERSHIP, or when trying an Any-Source option without doing IP_ADD_MEMBERSHIP). Please see table below.
The option length is not valid. For example, when trying to use struct ip_mreq_source instead of struct ip_mreq with IP_DROP_MEMBERSHIP or IP_ADD_MEMBERSHIP. |
| TM_EADDRNOTAVAIL | Address is invalid. For example, when the interface address is not a valid configured address, or when the group address is not multicast, or when the source address is invalid, or when trying to add a source on a multicast local group, or when trying to block a source that is already blocked on the socket, or when trying to drop an un-joined multicast group. Please see table below. |
| TM_EADDRINUSE | Address already in use. Please see table below. |
| TM_ENOBUFS | No memory for operation, most probably because the maximum number of filters has been reached. |
The following table shows what sequence of requests are allowed or disallowed, and if disallowed what the error code is.
| Previous Request | Next Request | Socket Error |
|---|---|---|
| IP_ADD_MEMBERSHIP | IP_ADD_MEMBERSHIP | TM_EADDRINUSE |
| IP_ADD_MEMBERSHIP | IP_DROP_MEMBERSHIP | TM_ENOERROR |
| IP_ADD_MEMBERSHIP | IP_ADD_SOURCE_MEMBERSHIP | TM_EINVAL |
| IP_ADD_MEMBERSHIP | IP_DROP_SOURCE_MEMBERSHIP | TM_EINVAL |
| IP_ADD_MEMBERSHIP | IP_BLOCK_SOURCE | TM_ENOERROR |
| IP_ADD_SOURCE_MEMBERSHIP | IP_ADD_MEMBERSHIP | TM_EADDRINUSE |
| IP_ADD_SOURCE_MEMBERSHIP | IP_DROP_MEMBERSHIP | TM_ENOERROR |
| IP_ADD_SOURCE_MEMBERSHIP | IP_ADD_SOURCE_MEMBERSHIP | TM_EADDRNOTAVAIL if source address is same |
| TM_ENOERROR otherwise | ||
| IP_ADD_SOURCE_MEMBERSHIP | IP_DROP_SOURCE_MEMBERSHIP | TM_ENOERROR if source address is same |
| TM_EADDRNOTAVAIL otherwise | ||
| IP_ADD_SOURCE_MEMBERSHIP | IP_BLOCK_SOURCE | TM_EINVAL |
| IP_ADD_SOURCE_MEMBERSHIP | IP_UNBLOCK_SOURCE | TM_EINVAL |
| IP_BLOCK_SOURCE | IP_ADD_MEMBERSHIP | TM_EADDRINUSE |
| IP_BLOCK_SOURCE | IP_DROP_MEMBERSHIP | TM_ENOERROR |
| IP_BLOCK_SOURCE | IP_ADD_SOURCE_MEMBERSHIP | TM_EINVAL |
| IP_BLOCK_SOURCE | IP_DROP_SOURCE_MEMBERSHIP | TM_EINVAL |
| IP_BLOCK_SOURCE | IP_BLOCK_SOURCE | TM_EADDRNOTAVAIL if source address is same |
| TM_ENOERROR otherwise | ||
| IP_BLOCK_SOURCE | IP_UNBLOCK_SOURCE | TM_ENOERROR if source address is same |
| TM_EADDRNOTAVAIL otherwise |
getsockopt()
None of the above options are supported in the getsockopt() socket API; therefore, it will always return TM_SOCKET_ERROR and set the error code on the socket to TM_EOPNOTSUPP.