On 11.04.2018 13:02, Andre Naujoks wrote:
> Hi.

Hi again.

Since it has been a month now, I'd like to send a little "ping" on this subject.

Is anything wrong with this? Or was it just bad timing?

Regards
  Andre

> 
> I was running into a problem, when trying to join multiple multicast groups
> on a single socket and thus binding to the any-address on said socket. I
> received traffic from multicast groups, I did not join on that socket and
> was at first surprised by that. After reading some old e-mails/threads,
> which came to the conclusion "It is, as it is."
> (e.g https://marc.info/?l=linux-kernel&m=115815686626791&w=2), I discovered
> the IPv4 socketoption IP_MULTICAST_ALL, which, when disabled, does exactly
> what I would expect from a socket by default.
> 
> I propose a socket option for IPv6, which does the same and has the same
> default as the IPv4 version. My first thought was, to just apply
> IP_MULTICAST_ALL to a ipv6 socket, but that would change the behavior of
> current applications and would probably be a big no-no.
> 
> Regards
>   Andre
> 
> 
> From 473653086c05a3de839c3504885053f6254c7bc5 Mon Sep 17 00:00:00 2001
> From: Andre Naujoks <nauts...@gmail.com>
> Date: Wed, 11 Apr 2018 12:38:28 +0200
> Subject: [PATCH] Add a socketoption IPV6_MULTICAST_ALL analogue to the IPV4
>  version
> 
> 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 <nauts...@gmail.com>
> ---
>  include/linux/ipv6.h     |  3 ++-
>  include/uapi/linux/in6.h |  1 +
>  net/ipv6/af_inet6.c      |  1 +
>  net/ipv6/ipv6_sockglue.c | 11 +++++++++++
>  net/ipv6/mcast.c         |  2 +-
>  5 files changed, 16 insertions(+), 2 deletions(-)
> 
> diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
> index 8415bf1a9776..495e834c1367 100644
> --- a/include/linux/ipv6.h
> +++ b/include/linux/ipv6.h
> @@ -274,7 +274,8 @@ struct ipv6_pinfo {
>                                                */
>                               dontfrag:1,
>                               autoflowlabel:1,
> -                             autoflowlabel_set:1;
> +                             autoflowlabel_set:1,
> +                             mc_all:1;
>       __u8                    min_hopcount;
>       __u8                    tclass;
>       __be32                  rcv_flowinfo;
> diff --git a/include/uapi/linux/in6.h b/include/uapi/linux/in6.h
> index ed291e55f024..71d82fe15b03 100644
> --- a/include/uapi/linux/in6.h
> +++ b/include/uapi/linux/in6.h
> @@ -177,6 +177,7 @@ struct in6_flowlabel_req {
>  #define IPV6_V6ONLY          26
>  #define IPV6_JOIN_ANYCAST    27
>  #define IPV6_LEAVE_ANYCAST   28
> +#define IPV6_MULTICAST_ALL   29
>  
>  /* IPV6_MTU_DISCOVER values */
>  #define IPV6_PMTUDISC_DONT           0
> diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
> index 8da0b513f188..7844cd9d2f10 100644
> --- a/net/ipv6/af_inet6.c
> +++ b/net/ipv6/af_inet6.c
> @@ -209,6 +209,7 @@ static int inet6_create(struct net *net, struct socket 
> *sock, int protocol,
>       np->hop_limit   = -1;
>       np->mcast_hops  = IPV6_DEFAULT_MCASTHOPS;
>       np->mc_loop     = 1;
> +     np->mc_all      = 1;
>       np->pmtudisc    = IPV6_PMTUDISC_WANT;
>       np->repflow     = net->ipv6.sysctl.flowlabel_reflect;
>       sk->sk_ipv6only = net->ipv6.sysctl.bindv6only;
> diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
> index 4d780c7f0130..b2bc1942a2ee 100644
> --- a/net/ipv6/ipv6_sockglue.c
> +++ b/net/ipv6/ipv6_sockglue.c
> @@ -664,6 +664,13 @@ static int do_ipv6_setsockopt(struct sock *sk, int 
> level, int optname,
>                       retv = ipv6_sock_ac_drop(sk, mreq.ipv6mr_ifindex, 
> &mreq.ipv6mr_acaddr);
>               break;
>       }
> +     case IPV6_MULTICAST_ALL:
> +             if (optlen < sizeof(int))
> +                     goto e_inval;
> +             np->mc_all = valbool;
> +             retv = 0;
> +             break;
> +
>       case MCAST_JOIN_GROUP:
>       case MCAST_LEAVE_GROUP:
>       {
> @@ -1255,6 +1262,10 @@ static int do_ipv6_getsockopt(struct sock *sk, int 
> level, int optname,
>               val = np->mcast_oif;
>               break;
>  
> +     case IPV6_MULTICAST_ALL:
> +             val = np->mc_all;
> +             break;
> +
>       case IPV6_UNICAST_IF:
>               val = (__force int)htonl((__u32) np->ucast_oif);
>               break;
> diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
> index 793159d77d8a..623ad00eb3c2 100644
> --- a/net/ipv6/mcast.c
> +++ b/net/ipv6/mcast.c
> @@ -622,7 +622,7 @@ bool inet6_mc_check(struct sock *sk, const struct 
> in6_addr *mc_addr,
>       }
>       if (!mc) {
>               rcu_read_unlock();
> -             return true;
> +             return np->mc_all;
>       }
>       read_lock(&mc->sflock);
>       psl = mc->sflist;
> 

Reply via email to