RFC 3678

Socket Interface Extensions for Multicast Source Filters

๐Ÿ“… published January 2004, from ietf

RFC 3678 ๐ŸŽ€ Socket Interface Extensions for Multicast Source Filters

okay bestie, here's the vibe check on this one ๐Ÿ’…

  • Network Working Group ๐ŸŒ
  • RFC number: 3678
  • Category: Informational (so it's info, not a standard)
  • Date: January 2004
  • Authors: D. Thaler (Microsoft), B. Fenner (AT&T Research), and B. Quinn (Stardust.com) ๐Ÿ‘‘
  • Obsoletes / Updates: the title block doesn't list anything it obsoletes or updates

Status of This Memo ๐Ÿ“œ

ngl this part is the legal-ish bit, but the gist is: this memo is for info only ๐Ÿซถ It is not an Internet standard of any kind, and distribution is unlimited โœจ

Copyright (C) The Internet Society (2004). All Rights Reserved.

Abstract ๐ŸŒธ

okay so the Internet Group Management Protocol (IGMPv3) for IPv4 and the Multicast Listener Discovery (MLDv2) for IPv6 let apps say which sources they want multicast traffic from. ๐Ÿ˜ญ That's the source filter thing! It means receiver apps get to decide which senders they accept traffic from, and it makes one-to-many multicast apps way easier to build ๐Ÿฆ‹

This doc is the one that adds new socket options and functions to manage those source filters for IP Multicast group memberships. It also defines the socket structures that carry the input and output arguments for these new APIs. The whole goal is to give you access to the source filtering stuff while changing as little as possible in the system, and keeping existing multicast apps totally compatible. iconic behavior ๐Ÿ’–

Table of Contents ๐Ÿ“‘

   1.  Introduction . . . . . . . . . . . . . . . . . . . . . . . . .  2
   2.  Design Considerations. . . . . . . . . . . . . . . . . . . . .  3
       2.1 What Needs to be Added . . . . . . . . . . . . . . . . . .  4
       2.2 Data Types . . . . . . . . . . . . . . . . . . . . . . . .  4
       2.3 Headers. . . . . . . . . . . . . . . . . . . . . . . . . .  4
       2.4 Structures . . . . . . . . . . . . . . . . . . . . . . . .  4
   3. Overview of APIs. . . . . . . . . . . . . . . . . . . . . . . .  5
   4. IPv4 Multicast Source Filter APIs . . . . . . . . . . . . . . .  6
      4.1 Basic (Delta-based) API for IPv4. . . . . . . . . . . . . .  6
           4.1.1 IPv4 Any-Source Multicast API. . . . . . . . . . . .  7
           4.1.2 IPv4 Source-Specific Multicast API . . . . . . . . .  7
           4.1.3 Error Codes. . . . . . . . . . . . . . . . . . . . .  8
      4.2 Advanced (Full-state) API for IPv4. . . . . . . . . . . . .  8
           4.2.1 Set Source Filter. . . . . . . . . . . . . . . . . .  8
           4.2.2 Get Source Filter. . . . . . . . . . . . . . . . . .  9
   5: Protocol-Independent Multicast Source Filter APIs . . . . . . . 10
      5.1 Basic (Delta-based) API . . . . . . . . . . . . . . . . . . 10
           5.1.1 Any-Source Multicast API . . . . . . . . . . . . . . 11
           5.1.2 Source-Specific Multicast API. . . . . . . . . . . . 11
      5.2 Advanced (Full-state) API . . . . . . . . . . . . . . . . . 11
           5.2.1 Set Source Filter. . . . . . . . . . . . . . . . . . 11
           5.2.2 Get Source Filter. . . . . . . . . . . . . . . . . . 12
   6.  Security Considerations. . . . . . . . . . . . . . . . . . . . 13
   7.  Acknowledgments. . . . . . . . . . . . . . . . . . . . . . . . 13
   8.  Appendix A: Use of ioctl() for full-state operations . . . . . 14
       8.1. IPv4 Options. . . . . . . . . . . . . . . . . . . . . . . 14
       8.2. Protocol-Independent Options. . . . . . . . . . . . . . . 15
   9.  Normative References . . . . . . . . . . . . . . . . . . . . . 16
   10. Informative References . . . . . . . . . . . . . . . . . . . . 16
   11. Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . 17
   12. Full Copyright Statement . . . . . . . . . . . . . . . . . . . 18

1. Introduction ๐Ÿฆ‹

so the de facto standard for TCP/IP apps is the "sockets" interface ๐Ÿงš It was built for Unix back in the early 1980s, but it's been put on a bunch of non-Unix systems too. TCP/IP apps written with the sockets API have historically had a super high degree of portability, and we want that same portability for apps that use multicast source filters. To make that happen, the sockets API needs some changes, and this memo describes them ๐Ÿ’œ

This document specifies new socket options and functions to manage source filters for IP Multicast group memberships. It also defines the socket structures that provide input and output arguments to these new APIs. The vibe is: give you access to the source filtering features apps need, change as little as possible, and keep existing multicast apps fully compatible ๐ŸŒˆ

Furthermore, RFC 3493 [1] defines socket interface extensions for IPv6, including protocol-independent functions for most operations. ๐Ÿ“

However, while it defines join and leave functions for IPv6, it does not provide protocol-independent versions of these operations. Those functions will be described in this document โœจ

The reader should note that this document is for informational purposes only, and that the official standard specification of the sockets API is [2]. ๐Ÿซถ

2. Design Considerations ๐Ÿ’…

there are a number of important things to think about when changing this well-worn API:

  • The API changes should provide both source and binary compatibility for programs written to the original API. Basically, existing program binaries should keep working when run on a system that supports the new API. Also, existing apps that get recompiled and run on a system supporting the new API should keep working too. Simply put, the API changes for multicast receivers that specify source filters should not break existing programs ๐Ÿ˜ญ
  • The changes to the API should be as small as possible so it's easier to convert existing multicast receiver apps to use source filters ๐ŸŽ€
  • Applications should be able to detect when the new source filter APIs are unavailable (e.g., calls fail with the ENOTSUPP error) and react gracefully (e.g., revert to the old non-source-filter API or display a meaningful error message to the user). Graceful recovery is the move ๐Ÿ‘‘
  • Lack of type-safety in an API is a bad thing and should be avoided when possible. ๐Ÿ’€

Several implementations already use ioctl() for part of the functionality described here, and for historical purposes, the ioctl API is documented in Appendix A. The preferred API, though, includes new functions. The reasons for adding new functions are:

  • New functions provide type-safety, unlike ioctl, getsockopt, and setsockopt. ๐Ÿ”ฅ
  • A new function can be written as a wrapper over an ioctl, getsockopt, or setsockopt call, if necessary. So it gives more freedom in how the functionality gets implemented in an operating system. For example, a new function might be implemented as an inline function in an include file, or as a function exported from a user-mode library that internally uses some mechanism to exchange information with the kernel, or be implemented directly in the kernel. ๐Ÿงš
  • At least one operation defined here needs to both pass information to the TCP/IP stack and retrieve information from it. In some implementations, this is problematic without either changing getsockopt or using ioctl. Using new functions avoids the need to change such implementations. no extra work for them, iykyk ๐Ÿ™ˆ

2.1. What Needs to be Added

okay so the current IP Multicast APIs let a receiver app specify the group address (destination) and, optionally, the local interface. These existing APIs need not change, and they cannot change if we want to keep binary compatibility ๐Ÿ”’ So what's needed are new source filter APIs that do the same job and also let receiver multicast apps:

  • 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. โœจ

The new API design must enable this functionality for both IPv4 and IPv6. ๐ŸŒธ

2.2. Data Types

the data types of the structure elements in this memo are meant to be examples, not absolute requirements ๐Ÿ“ Whenever possible, data types from POSIX 1003.1g [2] are used, where uintN_t means an unsigned integer of exactly N bits (e.g., uint32_t) ๐Ÿ’œ

2.3. Headers

when function prototypes and structures are shown, we show the headers that must be #included to cause that item to be defined. so you know what to include ๐ŸŽ€

2.4. Structures

when structures are described, the members shown are the ones that must appear in an implementation. Additional, nonstandard members may also be defined by an implementation. As an extra precaution, nonstandard members could be verified by Feature Test Macros as described in [2]. (Such Feature Test Macros are not defined by this RFC.) ๐Ÿ™ˆ

The ordering shown for the members of a structure is the recommended ordering, given alignment considerations of multibyte members, but an implementation may order the members differently. ๐ŸŒˆ

3. Overview of APIs โœจ

okay so there are a bunch of different APIs in this doc ๐ŸŽ€ they fit different app types and different IP versions, so before we get into the deep details, let me give you the "taxonomy" (aka the family tree ๐ŸŒณ) with a quick blurb for each one bestie ๐Ÿ’…

there are two categories of source-filter APIs, and both let a multicast receiver app name the unicast address(es) of the sender(s) it wants, along with the multicast group (the destination address) it wants to receive from ๐Ÿฆ‹

  • Basic (Delta-based): some apps just want something simple ๐Ÿ“ so this API has each function call target one single source address, which gets added to or removed from the existing filter for a given multicast group address. these apps usually land in one of two groups:
    • Any-Source Multicast: by default, every source is accepted โœจ you can mute individual sources and unmute them again whenever you want. this is also called "exclude" mode, since the source filter holds a list of excluded sources ๐Ÿ™ˆ
    • Source-Specific Multicast: only the sources on a given list are allowed, and that list can change over time ๐ŸŒธ this is also called "include" mode, since the source filter holds a list of included sources.

this one would be used by "single-source" apps like audio/video broadcasting ๐Ÿ“ก it'd also work for logical multi-source sessions where each source independently allocates its own Source-Specific Multicast group address ๐Ÿงš

  • Advanced (Full-state): this API lets an app define a complete source filter made of zero or more source addresses, and then replace the old filter with the new one ๐Ÿ‘‘

apps that need to switch between filter modes without leaving the group HAVE to use a full-state API ๐Ÿ˜ญ (ok lowercase: they must use one) โ€” so, for example, flipping the filter semantics from inclusive to exclusive or the other way around ๐Ÿ’€

apps that use a large source list for a given group address should also go full-state, since filter changes can happen atomically in a single operation ๐Ÿ”ฅ

the above types of APIs exist in IPv4-specific versions AND protocol-independent versions ๐ŸŒˆ you might be like "wait, why can't the protocol-independent ones just handle IPv4 apps too?" ๐Ÿค” fair question! since any IPv4 app already needs changes to use multicast source filters anyway, it might seem like a super cute chance to make IPv6-compatible source code while we're at it ๐Ÿ’–

but the main reasons for extending an IPv4-specific API are:

  • to minimize the changes needed in existing IPv4 multicast app source code so they can add source filter support ๐Ÿซถ
  • to avoid overloading APIs just to handle the differences between IPv4 interface addresses (e.g., in the ip_mreq structure) and interface indices ๐Ÿงฉ

4. IPv4 Multicast Source Filter APIs ๐Ÿฆ‹

Version 3 of the Internet Group Management Protocol (IGMPv3) [3] and version 2 of the Multicast Listener Discovery (MLDv2) protocol [4] let you communicate source filter info to the router ๐Ÿ›œ which means you don't have to pull down data from unwanted sources onto the local link ๐Ÿ™…โ€โ™€๏ธ but source filters can be implemented by the operating system no matter whether the routers support IGMPv3 or MLDv2 ๐Ÿซ  so when the source-filter API is available, apps can ALWAYS benefit from using it ๐ŸŽ€

(lowercase again: apps can always benefit, so no caps needed here ๐Ÿ’…)

4.1. Basic (Delta-based) API for IPv4 ๐Ÿ’–

receiving multicast packets is controlled by the setsockopt() options summarized below โœจ if you try using these with getsockopt(), you get an error of EOPNOTSUPP ๐Ÿ˜ญ

the following structures are used by BOTH the Any-Source Multicast and the Source-Specific Multicast API:

#include <netinet/in.h>

struct ip_mreq {
   struct in_addr imr_multiaddr;  /* IP address of group */
   struct in_addr imr_interface;  /* IP address of interface */
};

struct ip_mreq_source {
   struct in_addr imr_multiaddr;  /* IP address of group */
   struct in_addr imr_sourceaddr; /* IP address of source */
   struct in_addr imr_interface;  /* IP address of interface */
};

4.1.1. IPv4 Any-Source Multicast API ๐Ÿซง

the following socket options are defined in <netinet/in.h> for apps in the Any-Source Multicast category:

Socket option             Argument type
IP_ADD_MEMBERSHIP         struct ip_mreq
IP_BLOCK_SOURCE           struct ip_mreq_source
IP_UNBLOCK_SOURCE         struct ip_mreq_source
IP_DROP_MEMBERSHIP        struct ip_mreq

IP_ADD_MEMBERSHIP and IP_DROP_MEMBERSHIP are already implemented on most operating systems ๐Ÿฅน they're how you join and leave an any-source group ๐Ÿšช

IP_BLOCK_SOURCE can block data from a given source to a given group (like if the user "mutes" that source ๐Ÿคซ), and IP_UNBLOCK_SOURCE undoes that (like if the user then "unmutes" the source ๐Ÿ”Š) ๐ŸŒธ

4.1.2. IPv4 Source-Specific Multicast API ๐ŸŽ€

the following socket options are available for apps in the Source-Specific category:

Socket option             Argument type
IP_ADD_SOURCE_MEMBERSHIP  struct ip_mreq_source
IP_DROP_SOURCE_MEMBERSHIP struct ip_mreq_source
IP_DROP_MEMBERSHIP        struct ip_mreq

IP_ADD_SOURCE_MEMBERSHIP and IP_DROP_SOURCE_MEMBERSHIP are used to join and leave a source-specific group ๐Ÿงš

IP_DROP_MEMBERSHIP is supported as a convenience ๐Ÿฌ it drops ALL the sources that were joined for a particular group and interface. the operations work the same as if the socket had been closed ๐Ÿซถ

4.1.3. Error Codes ๐Ÿšจ

when the option WOULD be legal on the group, but an address is invalid (like trying to block a source that the socket already blocked, or trying to drop a group you never joined) the error you get is EADDRNOTAVAIL ๐Ÿ™ƒ

when the option itself is NOT legal on the group (like trying a Source-Specific option on a group after doing IP_ADD_MEMBERSHIP, or trying an Any-Source option WITHOUT doing IP_ADD_MEMBERSHIP first) the error you get is EINVAL ๐Ÿ’€

when any of these options are used with getsockopt(), the error is EOPNOTSUPP ๐Ÿ˜ญ

last but not least ๐Ÿ’… if the implementation puts a limit on the maximum number of sources in a source filter, ENOBUFS gets generated when an operation would go over that maximum ๐Ÿซ 

4.2. Advanced (Full-state) API for IPv4 ๐Ÿ‘‘

several implementations use ioctl() for this API ๐Ÿงฐ and for historical purposes, the ioctl() API is documented in Appendix A ๐Ÿ“œ but the preferred API uses the new functions described below โœจ

4.2.1. Set Source Filter ๐ŸŒˆ

#include <netinet/in.h>

int setipv4sourcefilter(int s, struct in_addr interface,
                        struct in_addr group, uint32_t fmode,
                        uint32_t numsrc, struct in_addr *slist);

on success the value 0 is returned, and on failure the value -1 is returned and errno is set accordingly ๐Ÿ™

  • the s argument identifies the socket ๐Ÿงฆ
  • the interface argument holds the local IP address of the interface ๐Ÿ 
  • the group argument holds the IP multicast address of the group ๐Ÿซ‚
  • the fmode argument identifies the filter mode. the value of this field must be either MCAST_INCLUDE or MCAST_EXCLUDE, which are likewise defined in <netinet/in.h> ๐Ÿ’–
  • the numsrc argument holds the number of source addresses in the slist array ๐Ÿ”ข
  • the slist argument points to an array of IP addresses of sources to include or exclude, depending on the filter mode ๐Ÿงพ

if the implementation puts a limit on the maximum number of sources in a source filter, ENOBUFS is generated when the operation would exceed the maximum ๐Ÿซ 

4.2.2. Get Source Filter ๐Ÿ”

#include <netinet/in.h>

int getipv4sourcefilter(int s, struct in_addr interface,
                        struct in_addr group, uint32_t *fmode,
                        uint32_t *numsrc, struct in_addr *slist);

on success the value 0 is returned, and on failure the value -1 is returned and errno is set accordingly ๐Ÿ™

  • the s argument identifies the socket ๐Ÿงฆ
  • the interface argument holds the local IP address of the interface ๐Ÿ 
  • the group argument holds the IP multicast address of the group ๐Ÿซ‚
  • the fmode argument points to an integer that will contain the filter mode on a successful return. the value of this field will be either MCAST_INCLUDE or MCAST_EXCLUDE, which are likewise defined in <netinet/in.h> ๐Ÿ’œ
  • on input, the numsrc argument holds the number of source addresses that will fit in the slist array. on output, the numsrc argument will hold the total number of sources in the filter ๐Ÿงฎ
  • the slist argument points to a buffer into which an array of IP addresses of included or excluded (depending on the filter mode) sources will be written. if numsrc was 0 on input, a NULL pointer may be supplied ๐Ÿซง

if the app doesn't know the size of the source list beforehand, it can make a reasonable guess (e.g., 0) ๐ŸŽฒ and if, upon completion, numsrc holds a larger value, the operation can be repeated with a big enough buffer ๐Ÿ”

so basically ๐Ÿซถ on return, numsrc is ALWAYS updated to be the total number of sources in the filter, while slist holds as many source addresses as fit, up to the minimum of the array size passed in as the original numsrc value and the total number of sources in the filter ๐Ÿง 


5. Protocol-Independent Multicast Source Filter APIs ๐ŸŒธ

protocol-independent functions are provided for join and leave operations ๐ŸŽ‰ so an app can pass a sockaddr_storage structure (the kind you get from calls like getaddrinfo() [1]) as the group to join ๐Ÿ™Œ for example, an app can resolve a DNS name (like NTP.MCAST.NET) to a multicast address that could be IPv4 OR IPv6, and then easily join and leave the group ๐Ÿฆ‹

5.1. Basic (Delta-based) API ๐Ÿ’–

receiving multicast packets is controlled by the setsockopt() options summarized below โœจ using these with getsockopt() gives you an error of EOPNOTSUPP ๐Ÿ˜ญ

the following structures are used by BOTH the Any-Source Multicast and the Source-Specific Multicast API: #include <netinet/in.h>

struct group_req {
   uint32_t                gr_interface; /* interface index */
   struct sockaddr_storage gr_group;     /* group address */
};

struct group_source_req {
   uint32_t                gsr_interface; /* interface index */
   struct sockaddr_storage gsr_group;     /* group address */
   struct sockaddr_storage gsr_source;    /* source address */
};

the sockaddr_storage structure is defined in RFC 3493 [1] to be big enough to hold either IPv4 or IPv6 address info ๐Ÿ“ฆ

the rules for generating errors are the same as those given in Section 5.1.3 ๐Ÿงพ

5.1.1. Any-Source Multicast API ๐Ÿซง

Socket option               Argument type
MCAST_JOIN_GROUP            struct group_req
MCAST_BLOCK_SOURCE          struct group_source_req
MCAST_UNBLOCK_SOURCE        struct group_source_req
MCAST_LEAVE_GROUP           struct group_req

MCAST_JOIN_GROUP and MCAST_LEAVE_GROUP are used to join and leave an any-source group ๐Ÿšช

MCAST_BLOCK_SOURCE can block data from a given source to a given group (like if the user "mutes" that source ๐Ÿคซ), and MCAST_UNBLOCK_SOURCE undoes that (like if the user then "unmutes" the source ๐Ÿ”Š) ๐ŸŒธ

5.1.2. Source-Specific Multicast API โœจ

Socket option               Argument type
MCAST_JOIN_SOURCE_GROUP     struct group_source_req
MCAST_LEAVE_SOURCE_GROUP    struct group_source_req
MCAST_LEAVE_GROUP           struct group_req

Okay bestie, this is the source-specific version ๐Ÿฆ‹. MCAST_JOIN_SOURCE_GROUP and MCAST_LEAVE_SOURCE_GROUP are the ones you use to join and leave a source-specific group. Both take a struct group_source_req ๐Ÿ’–.

Then there's MCAST_LEAVE_GROUP, which takes a struct group_req and is supported as a little convenience ๐ŸŽ€. It drops every source you've joined for a particular group and interface in one go. Honestly it behaves exactly like the socket got closed, so it's giving clean-up energy ๐Ÿงนโœจ.

5.2. Advanced (Full-state) API ๐Ÿ’…

Some implementations use ioctl() for this API, and for historical reasons that ioctl() API is written up in Appendix A ๐Ÿ“œ. The preferred way is the new functions below, so that's where you should look first ๐Ÿ‘‘.

5.2.1. Set Source Filter ๐ŸŒธ

#include <netinet/in.h>

int setsourcefilter(int s, uint32_t interface,
                    struct sockaddr *group, socklen_t grouplen,
                    uint32_t fmode, uint_t numsrc,
                    struct sockaddr_storage *slist);

On success it returns 0, and on failure it returns -1 and sets errno accordingly ๐Ÿ™ˆ.

The s argument identifies the socket ๐Ÿงฆ.

The interface argument holds the interface index of the interface ๐Ÿ”Œ.

The group argument points to either a sockaddr_in structure (for IPv4) or a sockaddr_in6 structure (for IPv6), and that structure holds the IP multicast address of the group ๐ŸŒˆ.

The grouplen argument gives the length of the sockaddr_in or sockaddr_in6 structure ๐Ÿ“.

The fmode argument identifies the filter mode. Its value has to be either MCAST_INCLUDE or MCAST_EXCLUDE, and both of those are defined in <netinet/in.h> too ๐Ÿ’œ.

The numsrc argument holds the number of source addresses in the slist array ๐Ÿ”ข.

The slist argument points to an array of IP addresses of sources, which get included or excluded depending on the filter mode ๐Ÿ“.

If the implementation puts a limit on how many sources a source filter can have, then ENOBUFS gets generated whenever the operation would go over that maximum ๐Ÿšซ.

5.2.2. Get Source Filter ๐Ÿ”

#include <netinet/in.h>

int getsourcefilter(int s, uint32_t interface,
                    struct sockaddr *group, socklen_t grouplen,
                    uint32_t fmode, uint_t *numsrc,
                    struct sockaddr_storage *slist);

Same deal as before: on success it's 0, on failure it's -1 and errno gets set ๐Ÿซถ.

The s argument identifies the socket ๐Ÿงฆ.

The interface argument holds the local IP address of the interface ๐Ÿ .

The group argument points to either a sockaddr_in structure (for IPv4) or a sockaddr_in6 structure (for IPv6), and that structure holds the IP multicast address of the group ๐ŸŒˆ.

The fmode argument points to an integer that will hold the filter mode once the call succeeds. That value will be either MCAST_INCLUDE or MCAST_EXCLUDE, both defined in <netinet/in.h> ๐Ÿ’œ.

On input, the numsrc argument holds the number of source addresses that will fit in the slist array ๐Ÿ“ฆ. On output, numsrc holds the total number of sources in the filter ๐Ÿงฎ.

The slist argument points to a buffer where an array of IP addresses of the included or excluded sources (depending on the filter mode) gets written ๐Ÿ“. If numsrc was 0 on input, you're allowed to pass a NULL pointer instead ๐Ÿ™…โ€โ™€๏ธ.

If the application doesn't know how big the source list is ahead of time, it can take a reasonable guess (for example, 0). If numsrc comes back bigger than the guess, the operation can be repeated with a buffer that's large enough ๐Ÿ”.

So to sum it up: on return, numsrc is always updated to the total number of sources in the filter, and slist holds as many source addresses as fit. That's the minimum of the array size you passed in as the original numsrc value and the total number of sources in the filter ๐ŸŽฏ.


6. Security Considerations ๐Ÿ”

Source filtering can help fight denial-of-service attacks, but it isn't a full solution on its own ๐Ÿ˜ฌ. It doesn't protect you from someone spoofing a source address so that it looks like an allowed source ๐Ÿ‘€. The good news is that multicast routing protocols which use reverse-path forwarding based on the source address do give some natural protection against spoofing. If a router gets a packet on an interface other than the one leading toward the "real" source, it drops the packet ๐Ÿ›ก๏ธ. Even so, that still doesn't guarantee protection, so please don't treat it as bulletproof ๐Ÿ’€.

7. Acknowledgments ๐Ÿซถ

This document was updated based on feedback from the IETF's IDMR and MAGMA Working Groups, plus the Austin Group ๐ŸŒŸ. Wilbert de Graaf also gave lots of helpful comments, so big thanks to him ๐Ÿ’–.

8. Appendix A: Use of ioctl() for full-state operations ๐Ÿ•ฐ๏ธ

The API defined here is historic ๐Ÿ“œ. It's written down here for informational purposes, since multiple platforms implement it. The new functions defined earlier in this document are what you should use now ๐Ÿ‘‘.

Getting the source filter for a given group can't be done with getsockopt() on some existing platforms. That's because the group and interface have to be passed down to retrieve the right filter, and getsockopt() only supports an output buffer ๐Ÿ™ƒ. ioctl() can handle it, so for symmetry, both gets and sets are done with an ioctl ๐Ÿ”„.

8.1. IPv4 Options ๐ŸŒท

The following are defined in <sys/sockio.h>:

  • ioctl() SIOCGIPMSFILTER: retrieves the list of source addresses that make up the source filter, along with the current filter mode ๐Ÿ“‹.
  • ioctl() SIOCSIPMSFILTER: sets or modifies the source filter content (for example, the unicast source address list) or the mode (exclude or include) โœ๏ธ.
Ioctl option                  Argument type
SIOCGIPMSFILTER               struct ip_msfilter
SIOCSIPMSFILTER               struct ip_msfilter

struct ip_msfilter {
   struct in_addr imsf_multiaddr;  /* IP multicast address of group */
   struct in_addr imsf_interface;  /* local IP address of interface */
   uint32_t       imsf_fmode;      /* filter mode */
   uint32_t       imsf_numsrc;     /* number of sources in src_list */
   struct in_addr imsf_slist[1];   /* start of source list */
};

#define IP_MSFILTER_SIZE(numsrc) \
   (sizeof(struct ip_msfilter) - sizeof(struct in_addr) \
   + (numsrc) * sizeof(struct in_addr))

The imsf_fmode field is a 32-bit integer that identifies the filter mode. Its value has to be either MCAST_INCLUDE or MCAST_EXCLUDE, both defined in <netinet/in.h> ๐Ÿ’œ.

The structure length pointed to has to be at least IP_MSFILTER_SIZE(0) bytes long. The imsf_numsrc parameter should be set so that IP_MSFILTER_SIZE(imsf_numsrc) gives you the buffer length ๐Ÿ“.

If the implementation puts a limit on how many sources a source filter can have, then ENOBUFS gets generated when a set operation would go over that maximum ๐Ÿšง.

After a get operation (SIOCGIPMSFILTER), the imsf_multiaddr and imsf_interface fields are unchanged. The imsf_fmode, imsf_numsrc, and as many source addresses as fit get filled into the application's buffer ๐Ÿช„.

If the application doesn't know the source list size beforehand, it can take a reasonable guess (for example, 0). If imsf_numsrc comes back bigger on completion, the operation can be repeated with a large enough buffer ๐Ÿ”.

So on return from SIOCGIPMSFILTER, imsf_numsrc is always updated to the total number of sources in the filter. imsf_slist holds as many source addresses as fit, up to the minimum of the array size passed in as the original imsf_numsrc value and the total number of sources in the filter ๐ŸŽฏ.

8.2. Protocol-Independent Options ๐ŸŒผ

The following are defined in <sys/sockio.h>:

  • ioctl() SIOCGMSFILTER: retrieves the list of source addresses that make up the source filter, along with the current filter mode ๐Ÿ“‹.
  • ioctl() SIOCSMSFILTER: sets or modifies the source filter content (for example, the unicast source address list) or the mode (exclude or include) โœ๏ธ.
Ioctl option                 Argument type
SIOCGMSFILTER                struct group_filter
SIOCSMSFILTER                struct group_filter

struct group_filter {
   uint32_t                gf_interface; /* interface index */
   struct sockaddr_storage gf_group;     /* multicast address */
   uint32_t                gf_fmode;     /* filter mode */
   uint32_t                gf_numsrc;    /* number of sources */
   struct sockaddr_storage gf_slist[1];  /* source address */
};
#define GROUP_FILTER_SIZE(numsrc) \
   (sizeof(struct group_filter) - sizeof(struct sockaddr_storage) \
   + (numsrc) * sizeof(struct sockaddr_storage))

The imf_numsrc field gets used the same way as imsf_numsrc described above ๐Ÿ”—.

9. Normative References ๐Ÿ“š

[1] Gilligan, R., Thomson, S., Bound, J., McCann, J. and W. Stevens, "Basic Socket Interface Extensions for IPv6", RFC 3493, February 2003. ๐Ÿง

[2] IEEE Std. 1003.1-2001 Standard for Information Technology -- Portable Operating System Interface (POSIX). Open Group Technical Standard: Base Specifications, Issue 6, December 2001. ISO/IEC 9945:2002. http://www.opengroup.org/austin ๐ŸŒ

10. Informative References ๐Ÿง 

[3] Cain, B., Deering, S., Kouvelas, I., Fenner, B. and A. Thyagarajan, "Internet Group Management Protocol, Version 3", RFC 3376, October 2002. ๐ŸŽ€

[4] Vida, R. and L. Costa, "Multicast Listener Discovery Version 2 (MLDv2) for IPv6", Work in Progress, December 2003. ๐Ÿšง

11. Authors' Addresses ๐Ÿ–‹๏ธ

Dave Thaler
Microsoft Corporation
One Microsoft Way
Redmond, WA  98052-6399

Phone: +1 425 703 8835
EMail: dthaler@microsoft.com


Bill Fenner
75 Willow Road
Menlo Park, CA  94025

Phone: +1 650 867 6073
EMail: fenner@research.att.com


Bob Quinn
IP Multicast Initiative (IPMI)
Stardust.com
1901 S. Bascom Ave. #333
Campbell, CA 95008

Phone: +1 408 879 8080
EMail: rcq@ipmulticast.com

Copyright (C) The Internet Society (2004). All Rights Reserved.

This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to the Internet Society or other Internet organizations, except as needed for the purpose of developing Internet standards in which case the procedures for copyrights defined in the Internet Standards process must be followed, or as required to translate it into languages other than English.

The limited permissions granted above are perpetual and will not be revoked by the Internet Society or its successors or assignees.

This document and the information contained herein is provided on an "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.

Acknowledgement ๐Ÿ’œ

Funding for the RFC Editor function is currently provided by the Internet Society ๐Ÿ™โœจ.

๐Ÿ“ฆ where this page comes from