Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ipv6: Add sockopt IPV6_MULTICAST_ALL analogue to IP_MULTICAST_ALL

The socket option will be enabled by default to ensure current behaviour
is not changed. This is the same for the IPv4 version.

A socket bound to in6addr_any and a specific port will receive all traffic
on that port. Analogue to IP_MULTICAST_ALL, disable this behaviour, if
one or more multicast groups were joined (using said socket) and only
pass on multicast traffic from groups, which were explicitly joined via
this socket.

Without this option disabled a socket (system even) joined to multiple
multicast groups is very hard to get right. Filtering by destination
address has to take place in user space to avoid receiving multicast
traffic from other multicast groups, which might have traffic on the same
port.

The extension of the IP_MULTICAST_ALL socketoption to just apply to ipv6,
too, is not done to avoid changing the behaviour of current applications.

Signed-off-by: Andre Naujoks <nautsch2@gmail.com>
Acked-By: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Andre Naujoks and committed by
David S. Miller
15033f04 d03790f5

+16 -2
+2 -1
include/linux/ipv6.h
··· 274 274 */ 275 275 dontfrag:1, 276 276 autoflowlabel:1, 277 - autoflowlabel_set:1; 277 + autoflowlabel_set:1, 278 + mc_all:1; 278 279 __u8 min_hopcount; 279 280 __u8 tclass; 280 281 __be32 rcv_flowinfo;
+1
include/uapi/linux/in6.h
··· 177 177 #define IPV6_V6ONLY 26 178 178 #define IPV6_JOIN_ANYCAST 27 179 179 #define IPV6_LEAVE_ANYCAST 28 180 + #define IPV6_MULTICAST_ALL 29 180 181 181 182 /* IPV6_MTU_DISCOVER values */ 182 183 #define IPV6_PMTUDISC_DONT 0
+1
net/ipv6/af_inet6.c
··· 209 209 np->hop_limit = -1; 210 210 np->mcast_hops = IPV6_DEFAULT_MCASTHOPS; 211 211 np->mc_loop = 1; 212 + np->mc_all = 1; 212 213 np->pmtudisc = IPV6_PMTUDISC_WANT; 213 214 np->repflow = net->ipv6.sysctl.flowlabel_reflect; 214 215 sk->sk_ipv6only = net->ipv6.sysctl.bindv6only;
+11
net/ipv6/ipv6_sockglue.c
··· 674 674 retv = ipv6_sock_ac_drop(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_acaddr); 675 675 break; 676 676 } 677 + case IPV6_MULTICAST_ALL: 678 + if (optlen < sizeof(int)) 679 + goto e_inval; 680 + np->mc_all = valbool; 681 + retv = 0; 682 + break; 683 + 677 684 case MCAST_JOIN_GROUP: 678 685 case MCAST_LEAVE_GROUP: 679 686 { ··· 1271 1264 1272 1265 case IPV6_MULTICAST_IF: 1273 1266 val = np->mcast_oif; 1267 + break; 1268 + 1269 + case IPV6_MULTICAST_ALL: 1270 + val = np->mc_all; 1274 1271 break; 1275 1272 1276 1273 case IPV6_UNICAST_IF:
+1 -1
net/ipv6/mcast.c
··· 636 636 } 637 637 if (!mc) { 638 638 rcu_read_unlock(); 639 - return true; 639 + return np->mc_all; 640 640 } 641 641 read_lock(&mc->sflock); 642 642 psl = mc->sflist;