On 9/24/18 10:13 AM, Mike Manning wrote:
> From: Dewi Morgan <morg...@vyatta.att-mail.com>
> 
> For bound udp sockets in a vrf, also check the sdif to get the index
> for ingress devices enslaved to an l3mdev. Verify the multicast address
> against the enslaved rather than the l3mdev device.
> 
> Signed-off-by: Dewi Morgan <morg...@vyatta.att-mail.com>
> Signed-off-by: Mike Manning <mmann...@vyatta.att-mail.com>
> ---
>  net/ipv6/ip6_input.c | 24 ++++++++++++++++++++----
>  net/ipv6/udp.c       |  8 +++++---
>  2 files changed, 25 insertions(+), 7 deletions(-)
> 

This should be 2 patches -- 1 that modifies the socket lookup to
consider and 1 that alters in the input path. They are completely
separate changes.


> diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
> index 108f5f88ec98..82ffb5cdd2ab 100644
> --- a/net/ipv6/ip6_input.c
> +++ b/net/ipv6/ip6_input.c
> @@ -324,11 +324,14 @@ void ipv6_list_rcv(struct list_head *head, struct 
> packet_type *pt,
>  static int ip6_input_finish(struct net *net, struct sock *sk, struct sk_buff 
> *skb)
>  {
>       const struct inet6_protocol *ipprot;
> +     int sdif = inet6_sdif(skb);
> +     bool have_final = false;
>       struct inet6_dev *idev;
> +     struct net_device *dev;

make sdif and dev declarations local to where they are needed.


>       unsigned int nhoff;
> +     bool deliver;

deliver is not needed.

>       int nexthdr;
>       bool raw;
> -     bool have_final = false;

so no need to move this one.

>  
>       /*
>        *      Parse extension headers
> @@ -371,9 +374,22 @@ static int ip6_input_finish(struct net *net, struct sock 
> *sk, struct sk_buff *sk
>                       skb_postpull_rcsum(skb, skb_network_header(skb),
>                                          skb_network_header_len(skb));
>                       hdr = ipv6_hdr(skb);
> -                     if (ipv6_addr_is_multicast(&hdr->daddr) &&
> -                         !ipv6_chk_mcast_addr(skb->dev, &hdr->daddr,
> -                         &hdr->saddr) &&
> +
> +                     /* skb->dev passed may be master dev for vrfs. */
> +                     if (sdif) {
> +                             dev = dev_get_by_index_rcu(dev_net(skb->dev),

net is a passed in argument. Why not use it?

> +                                                        sdif);
> +                             if (!dev) {
> +                                     kfree_skb(skb);
> +                                     return -ENODEV;

The rcu_read_lock() is held. I believe 'goto discard' is sufficient if
the enslaved device disappeared.

> +                             }
> +                     } else {
> +                             dev = skb->dev;
> +                     }
> +
> +                     deliver = ipv6_chk_mcast_addr(dev, &hdr->daddr,
> +                                                   &hdr->saddr);
> +                     if (ipv6_addr_is_multicast(&hdr->daddr) && !deliver &&
>                           !ipv6_is_mld(skb, nexthdr, 
> skb_network_header_len(skb)))
>                               goto discard;
>               }

I think the original code only needs skb->dev changed to dev making this
a much smaller patch.

Reply via email to