ipv4: New multicast-all socket option
Nivedita Singhvi [Thu, 28 May 2009 07:00:46 +0000 (07:00 +0000)]
After some discussion offline with Christoph Lameter and David Stevens
regarding multicast behaviour in Linux, I'm submitting a slightly
modified patch from the one Christoph submitted earlier.

This patch provides a new socket option IP_MULTICAST_ALL.

In this case, default behaviour is _unchanged_ from the current
Linux standard. The socket option is set by default to provide
original behaviour. Sockets wishing to receive data only from
multicast groups they join explicitly will need to clear this
socket option.

Signed-off-by: Nivedita Singhvi <niv@us.ibm.com>
Signed-off-by: Christoph Lameter<cl@linux.com>
Acked-by: David Stevens <dlstevens@us.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

include/linux/in.h
include/net/inet_sock.h
net/ipv4/af_inet.c
net/ipv4/igmp.c
net/ipv4/ip_sockglue.c

index d60122a..cf196da 100644 (file)
@@ -107,6 +107,7 @@ struct in_addr {
 #define MCAST_JOIN_SOURCE_GROUP                46
 #define MCAST_LEAVE_SOURCE_GROUP       47
 #define MCAST_MSFILTER                 48
+#define IP_MULTICAST_ALL               49
 
 #define MCAST_EXCLUDE  0
 #define MCAST_INCLUDE  1
index de0ecc7..20a6957 100644 (file)
@@ -130,7 +130,8 @@ struct inet_sock {
                                freebind:1,
                                hdrincl:1,
                                mc_loop:1,
-                               transparent:1;
+                               transparent:1,
+                               mc_all:1;
        int                     mc_index;
        __be32                  mc_addr;
        struct ip_mc_socklist   *mc_list;
index 5abee4c..d873621 100644 (file)
@@ -375,6 +375,7 @@ lookup_protocol:
        inet->uc_ttl    = -1;
        inet->mc_loop   = 1;
        inet->mc_ttl    = 1;
+       inet->mc_all    = 1;
        inet->mc_index  = 0;
        inet->mc_list   = NULL;
 
index 9eb6219..e6058a5 100644 (file)
@@ -2196,7 +2196,7 @@ int ip_mc_sf_allow(struct sock *sk, __be32 loc_addr, __be32 rmt_addr, int dif)
                        break;
        }
        if (!pmc)
-               return 1;
+               return inet->mc_all;
        psl = pmc->sflist;
        if (!psl)
                return pmc->sfmode == MCAST_EXCLUDE;
index 21b0187..cb49936 100644 (file)
@@ -453,6 +453,7 @@ static int do_ip_setsockopt(struct sock *sk, int level,
                             (1<<IP_ROUTER_ALERT) | (1<<IP_FREEBIND) |
                             (1<<IP_PASSSEC) | (1<<IP_TRANSPARENT))) ||
            optname == IP_MULTICAST_TTL ||
+           optname == IP_MULTICAST_ALL ||
            optname == IP_MULTICAST_LOOP ||
            optname == IP_RECVORIGDSTADDR) {
                if (optlen >= sizeof(int)) {
@@ -898,6 +899,13 @@ mc_msf_out:
                kfree(gsf);
                break;
        }
+       case IP_MULTICAST_ALL:
+               if (optlen < 1)
+                       goto e_inval;
+               if (val != 0 && val != 1)
+                       goto e_inval;
+               inet->mc_all = val;
+               break;
        case IP_ROUTER_ALERT:
                err = ip_ra_control(sk, val ? 1 : 0, NULL);
                break;
@@ -1151,6 +1159,9 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname,
                release_sock(sk);
                return err;
        }
+       case IP_MULTICAST_ALL:
+               val = inet->mc_all;
+               break;
        case IP_PKTOPTIONS:
        {
                struct msghdr msg;