different multicast group.

Signed-off-by: Christoph Lameter <cl@linux.com>

---
 Documentation/networking/ip-sysctl.txt |   10 ++++++++++
 include/linux/igmp.h                   |    1 +
 include/linux/sysctl.h                 |    1 +
 net/ipv4/igmp.c                        |    6 +++---
 net/ipv4/sysctl_net_ipv4.c             |    8 ++++++++
 5 files changed, 23 insertions(+), 3 deletions(-)

Index: linux-2.6/net/ipv4/igmp.c
===================================================================
--- linux-2.6.orig/net/ipv4/igmp.c	2009-04-14 13:03:14.000000000 -0500
+++ linux-2.6/net/ipv4/igmp.c	2009-04-14 13:11:38.000000000 -0500
@@ -1419,7 +1419,7 @@ static struct in_device *ip_mc_find_dev(
  */
 int sysctl_igmp_max_memberships __read_mostly = IP_MAX_MEMBERSHIPS;
 int sysctl_igmp_max_msf __read_mostly = IP_MAX_MSF;
-
+int sysctl_igmp_mc_socket_based_filtering = 0;

 static int ip_mc_del1_src(struct ip_mc_list *pmc, int sfmode,
 	__be32 *psfsrc)
@@ -2187,7 +2187,7 @@ int ip_mc_sf_allow(struct sock *sk, __be
 	struct ip_sf_socklist *psl;
 	int i;

-	if (!ipv4_is_multicast(loc_addr))
+	if (ipv4_is_lbcast(loc_addr) || !ipv4_is_multicast(loc_addr))
 		return 1;

 	for (pmc=inet->mc_list; pmc; pmc=pmc->next) {
@@ -2196,7 +2196,7 @@ int ip_mc_sf_allow(struct sock *sk, __be
 			break;
 	}
 	if (!pmc)
-		return 1;
+		return !sysctl_igmp_mc_socket_based_filtering;
 	psl = pmc->sflist;
 	if (!psl)
 		return pmc->sfmode == MCAST_EXCLUDE;
Index: linux-2.6/include/linux/igmp.h
===================================================================
--- linux-2.6.orig/include/linux/igmp.h	2009-04-14 13:13:14.000000000 -0500
+++ linux-2.6/include/linux/igmp.h	2009-04-14 13:41:14.000000000 -0500
@@ -150,6 +150,7 @@ static inline struct igmpv3_query *

 extern int sysctl_igmp_max_memberships;
 extern int sysctl_igmp_max_msf;
+extern int sysctl_igmp_mc_socket_based_filtering;

 struct ip_sf_socklist
 {
Index: linux-2.6/include/linux/sysctl.h
===================================================================
--- linux-2.6.orig/include/linux/sysctl.h	2009-04-14 13:15:57.000000000 -0500
+++ linux-2.6/include/linux/sysctl.h	2009-04-14 13:16:49.000000000 -0500
@@ -435,6 +435,7 @@ enum
 	NET_TCP_ALLOWED_CONG_CONTROL=123,
 	NET_TCP_MAX_SSTHRESH=124,
 	NET_TCP_FRTO_RESPONSE=125,
+	NET_IPV4_IGMP_MC_SOCKET_BASED_FILTERING=126,
 };

 enum {
Index: linux-2.6/net/ipv4/sysctl_net_ipv4.c
===================================================================
--- linux-2.6.orig/net/ipv4/sysctl_net_ipv4.c	2009-04-14 13:13:53.000000000 -0500
+++ linux-2.6/net/ipv4/sysctl_net_ipv4.c	2009-04-14 13:15:44.000000000 -0500
@@ -408,6 +408,14 @@ static struct ctl_table ipv4_table[] = {
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec
 	},
+	{
+		.ctl_name	= NET_IPV4_IGMP_MC_SOCKET_BASED_FILTERING,
+		.procname	= "igmp_mc_socked_based_filtering",
+		.data		= &sysctl_igmp_mc_socket_based_filtering,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec
+	},

 #endif
 	{
Index: linux-2.6/Documentation/networking/ip-sysctl.txt
===================================================================
--- linux-2.6.orig/Documentation/networking/ip-sysctl.txt	2009-04-14 13:48:09.000000000 -0500
+++ linux-2.6/Documentation/networking/ip-sysctl.txt	2009-04-14 13:53:10.000000000 -0500
@@ -611,6 +611,16 @@ igmp_max_memberships - INTEGER
 	Change the maximum number of multicast groups we can subscribe to.
 	Default: 20

+igmp_mc_socket_based_filtering - INTEGER
+	Use the list of subscribed multicast addresses to filter the traffic
+	going to a multicast socket. If set to zero then multicast traffic
+        is forwarded to any socket subscribed to a port number ignoring the
+        list of multicast groups that a socket has been subscribed to. This mode
+        is the default since it has been done that way in the past.
+	If set to one then only multicast traffic of the multicast groups
+        that a socket has joined are forwarded to the socket.
+	Default: 0
+
 conf/interface/*  changes special settings per interface (where "interface" is
 		  the name of your network interface)
 conf/all/*	  is special, changes the settings for all interfaces
