ipv4: New multicast-all socket option
authorNivedita Singhvi <niv@us.ibm.com>
Thu, 28 May 2009 07:00:46 +0000 (07:00 +0000)
committerDavid S. Miller <davem@davemloft.net>
Tue, 2 Jun 2009 07:45:24 +0000 (00:45 -0700)
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 d60122a3a0886310e9221405ad1c022f9d3d2fa7..cf196da04ec92434ded51b599a7ae837f030c528 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 de0ecc71cf0388d944ec0a032b7ffe8453324a95..20a6957af870a0b12973a4b3cb937d5e0aeac011 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 5abee4c9744948230bf0fa50277086a2cf1a8316..d873621785884507a270ed7e4e7d6345935d0c48 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 9eb6219af615af2327daef1ec461e3b1fdb16500..e6058a503796763ba023f11227a3487d3630e660 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 21b0187123d6c4118ed13ad2160aa1a7452f2140..cb49936856e051c8a6db210ec004f5d78e85ba73 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;