Skip to content
Permalink
Browse files
net: Allow all multicast packets to be received on a interface.
To receive IGMP or MLD packets on a IP socket on any interface the
multicast group needs to be explicitly joined. This works well for when
the multicast group the user is interested in is known, but does not
provide an easy way to snoop all packets in the 224.0.0.0/8 or the
FF00::/8 range.

Define a new sysctl to allow a given interface to become a IGMP or MLD
snooper. When set the interface will allow any IGMP or MLD packet to be
received on sockets bound to these devices.
  • Loading branch information
Callum Sinclair authored and intel-lab-lkp committed Jun 17, 2021
1 parent 7058521 commit 4220b6837f4315ff557bd44f7aada23b69e181b6
Show file tree
Hide file tree
Showing 11 changed files with 45 additions and 0 deletions.
@@ -1328,6 +1328,14 @@ mc_forwarding - BOOLEAN
conf/all/mc_forwarding must also be set to TRUE to enable multicast
routing for the interface

mc_snooping - BOOLEAN
Enable multicast snooping on the interface. This allows any given
multicast group to be received without explicitly being joined.
The kernel needs to be compiled with CONFIG_MROUTE and/or
CONFIG_IPV6_MROUTE.
conf/all/mc_snooping must also be set to TRUE to enable multicast
snooping for the interface.

medium_id - INTEGER
Integer value used to differentiate the devices by the medium they
are attached to. Two devices can have different id values when
@@ -95,6 +95,7 @@ static inline void ipv4_devconf_setall(struct in_device *in_dev)

#define IN_DEV_FORWARD(in_dev) IN_DEV_CONF_GET((in_dev), FORWARDING)
#define IN_DEV_MFORWARD(in_dev) IN_DEV_ANDCONF((in_dev), MC_FORWARDING)
#define IN_DEV_MSNOOPING(in_dev) IN_DEV_ANDCONF((in_dev), MC_SNOOPING)
#define IN_DEV_BFORWARD(in_dev) IN_DEV_ANDCONF((in_dev), BC_FORWARDING)
#define IN_DEV_RPFILTER(in_dev) IN_DEV_MAXCONF((in_dev), RP_FILTER)
#define IN_DEV_SRC_VMARK(in_dev) IN_DEV_ORCONF((in_dev), SRC_VMARK)
@@ -52,6 +52,7 @@ struct ipv6_devconf {
#endif
#ifdef CONFIG_IPV6_MROUTE
__s32 mc_forwarding;
__s32 mc_snooping;
#endif
__s32 disable_ipv6;
__s32 drop_unicast_in_l2_multicast;
@@ -169,6 +169,7 @@ enum
IPV4_DEVCONF_DROP_UNICAST_IN_L2_MULTICAST,
IPV4_DEVCONF_DROP_GRATUITOUS_ARP,
IPV4_DEVCONF_BC_FORWARDING,
IPV4_DEVCONF_MC_SNOOPING,
__IPV4_DEVCONF_MAX
};

@@ -190,6 +190,7 @@ enum {
DEVCONF_NDISC_TCLASS,
DEVCONF_RPL_SEG_ENABLED,
DEVCONF_RA_DEFRTR_METRIC,
DEVCONF_MC_SNOOPING,
DEVCONF_MAX
};

@@ -19,6 +19,7 @@ enum {
NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN,
NETCONFA_INPUT,
NETCONFA_BC_FORWARDING,
NETCONFA_MC_SNOOPING,
__NETCONFA_MAX
};
#define NETCONFA_MAX (__NETCONFA_MAX - 1)
@@ -482,6 +482,7 @@ enum
NET_IPV4_CONF_PROMOTE_SECONDARIES=20,
NET_IPV4_CONF_ARP_ACCEPT=21,
NET_IPV4_CONF_ARP_NOTIFY=22,
NET_IPV4_CONF_MC_SNOOPING=23,
};

/* /proc/sys/net/ipv4/netfilter */
@@ -2014,6 +2014,8 @@ static int inet_netconf_msgsize_devconf(int type)
size += nla_total_size(4);
if (all || type == NETCONFA_MC_FORWARDING)
size += nla_total_size(4);
if (all || type == NETCONFA_MC_SNOOPING)
size += nla_total_size(4);
if (all || type == NETCONFA_BC_FORWARDING)
size += nla_total_size(4);
if (all || type == NETCONFA_PROXY_NEIGH)
@@ -2062,6 +2064,10 @@ static int inet_netconf_fill_devconf(struct sk_buff *skb, int ifindex,
nla_put_s32(skb, NETCONFA_MC_FORWARDING,
IPV4_DEVCONF(*devconf, MC_FORWARDING)) < 0)
goto nla_put_failure;
if ((all || type == NETCONFA_MC_SNOOPING) &&
nla_put_s32(skb, NETCONFA_MC_SNOOPING,
IPV4_DEVCONF(*devconf, NETCONFA_MC_SNOOPING)) < 0)
goto nla_put_failure;
if ((all || type == NETCONFA_BC_FORWARDING) &&
nla_put_s32(skb, NETCONFA_BC_FORWARDING,
IPV4_DEVCONF(*devconf, BC_FORWARDING)) < 0)
@@ -2506,6 +2512,7 @@ static struct devinet_sysctl_table {
DEVINET_SYSCTL_COMPLEX_ENTRY(FORWARDING, "forwarding",
devinet_sysctl_forward),
DEVINET_SYSCTL_RO_ENTRY(MC_FORWARDING, "mc_forwarding"),
DEVINET_SYSCTL_RW_ENTRY(MC_SNOOPING, "mc_snooping"),
DEVINET_SYSCTL_RW_ENTRY(BC_FORWARDING, "bc_forwarding"),

DEVINET_SYSCTL_RW_ENTRY(ACCEPT_REDIRECTS, "accept_redirects"),
@@ -2692,6 +2692,11 @@ int ip_check_mc_rcu(struct in_device *in_dev, __be32 mc_addr, __be32 src_addr, u
struct ip_sf_list *psf;
int rv = 0;

#ifdef CONFIG_IP_MROUTE
if (IN_DEV_MSNOOPING(in_dev))
return 1;
#endif /* CONFIG_IP_MROUTE */

mc_hash = rcu_dereference(in_dev->mc_hash);
if (mc_hash) {
u32 hash = hash_32((__force u32)mc_addr, MC_HASH_SZ_LOG);
@@ -502,6 +502,8 @@ static int inet6_netconf_msgsize_devconf(int type)
#ifdef CONFIG_IPV6_MROUTE
if (all || type == NETCONFA_MC_FORWARDING)
size += nla_total_size(4);
if (all || type == NETCONFA_MC_SNOOPING)
size += nla_total_size(4);
#endif
if (all || type == NETCONFA_PROXY_NEIGH)
size += nla_total_size(4);
@@ -546,6 +548,10 @@ static int inet6_netconf_fill_devconf(struct sk_buff *skb, int ifindex,
nla_put_s32(skb, NETCONFA_MC_FORWARDING,
devconf->mc_forwarding) < 0)
goto nla_put_failure;
if ((all || type == NETCONFA_MC_SNOOPING) &&
nla_put_s32(skb, NETCONFA_MC_SNOOPING,
devconf->mc_snooping) < 0)
goto nla_put_failure;
#endif
if ((all || type == NETCONFA_PROXY_NEIGH) &&
nla_put_s32(skb, NETCONFA_PROXY_NEIGH, devconf->proxy_ndp) < 0)
@@ -5503,6 +5509,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
#endif
#ifdef CONFIG_IPV6_MROUTE
array[DEVCONF_MC_FORWARDING] = cnf->mc_forwarding;
array[DEVCONF_MC_SNOOPING] = cnf->mc_snooping;
#endif
array[DEVCONF_DISABLE_IPV6] = cnf->disable_ipv6;
array[DEVCONF_ACCEPT_DAD] = cnf->accept_dad;
@@ -6786,6 +6793,13 @@ static const struct ctl_table addrconf_sysctl[] = {
.mode = 0444,
.proc_handler = proc_dointvec,
},
{
.procname = "mc_snooping",
.data = &ipv6_devconf.mc_snooping,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec,
},
#endif
{
.procname = "disable_ipv6",
@@ -1013,6 +1013,11 @@ bool ipv6_chk_mcast_addr(struct net_device *dev, const struct in6_addr *group,
struct ifmcaddr6 *mc;
bool rv = false;

#ifdef CONFIG_IPV6_MROUTE
if (dev_net(dev)->ipv6.devconf_all->mc_snooping)
return true;
#endif

rcu_read_lock();
idev = __in6_dev_get(dev);
if (idev) {

0 comments on commit 4220b68

Please sign in to comment.