net: ipv6: add second dif to raw socket lookups
authorDavid Ahern <dsahern@gmail.com>
Mon, 7 Aug 2017 15:44:22 +0000 (08:44 -0700)
committerDavid S. Miller <davem@davemloft.net>
Mon, 7 Aug 2017 18:39:22 +0000 (11:39 -0700)
Add a second device index, sdif, to raw socket lookups. sdif is the
index for ingress devices enslaved to an l3mdev. It allows the lookups
to consider the enslaved device as well as the L3 domain when searching
for a socket.

Signed-off-by: David Ahern <dsahern@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/rawv6.h
net/ipv4/raw_diag.c
net/ipv6/raw.c

index cbe4e9de1894674ea194239fd21d6f85435d5078..4addc5c988e02b6edff192a8b039831ddc5aa47d 100644 (file)
@@ -6,7 +6,7 @@
 extern struct raw_hashinfo raw_v6_hashinfo;
 struct sock *__raw_v6_lookup(struct net *net, struct sock *sk,
                             unsigned short num, const struct in6_addr *loc_addr,
-                            const struct in6_addr *rmt_addr, int dif);
+                            const struct in6_addr *rmt_addr, int dif, int sdif);
 
 int raw_abort(struct sock *sk, int err);
 
index c600d3c71d4dab6cfadcb27c52626ad699dde969..c200065ef9a5e49b022eeb2286d59eaf822136f9 100644 (file)
@@ -52,7 +52,7 @@ static struct sock *raw_lookup(struct net *net, struct sock *from,
                sk = __raw_v6_lookup(net, from, r->sdiag_raw_protocol,
                                     (const struct in6_addr *)r->id.idiag_src,
                                     (const struct in6_addr *)r->id.idiag_dst,
-                                    r->id.idiag_if);
+                                    r->id.idiag_if, 0);
 #endif
        return sk;
 }
index 60be012fe7085cc7a199e84333cef5ee95ed1f04..e4462b0ff801b71b8ae3a48f446a0fdd93bb22c2 100644 (file)
@@ -72,7 +72,7 @@ EXPORT_SYMBOL_GPL(raw_v6_hashinfo);
 
 struct sock *__raw_v6_lookup(struct net *net, struct sock *sk,
                unsigned short num, const struct in6_addr *loc_addr,
-               const struct in6_addr *rmt_addr, int dif)
+               const struct in6_addr *rmt_addr, int dif, int sdif)
 {
        bool is_multicast = ipv6_addr_is_multicast(loc_addr);
 
@@ -86,7 +86,9 @@ struct sock *__raw_v6_lookup(struct net *net, struct sock *sk,
                            !ipv6_addr_equal(&sk->sk_v6_daddr, rmt_addr))
                                continue;
 
-                       if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif)
+                       if (sk->sk_bound_dev_if &&
+                           sk->sk_bound_dev_if != dif &&
+                           sk->sk_bound_dev_if != sdif)
                                continue;
 
                        if (!ipv6_addr_any(&sk->sk_v6_rcv_saddr)) {
@@ -178,7 +180,8 @@ static bool ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
                goto out;
 
        net = dev_net(skb->dev);
-       sk = __raw_v6_lookup(net, sk, nexthdr, daddr, saddr, inet6_iif(skb));
+       sk = __raw_v6_lookup(net, sk, nexthdr, daddr, saddr,
+                            inet6_iif(skb), inet6_sdif(skb));
 
        while (sk) {
                int filtered;
@@ -222,7 +225,7 @@ static bool ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
                        }
                }
                sk = __raw_v6_lookup(net, sk_next(sk), nexthdr, daddr, saddr,
-                                    inet6_iif(skb));
+                                    inet6_iif(skb), inet6_sdif(skb));
        }
 out:
        read_unlock(&raw_v6_hashinfo.lock);
@@ -378,7 +381,7 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr,
                net = dev_net(skb->dev);
 
                while ((sk = __raw_v6_lookup(net, sk, nexthdr, saddr, daddr,
-                                               inet6_iif(skb)))) {
+                                            inet6_iif(skb), inet6_iif(skb)))) {
                        rawv6_err(sk, skb, NULL, type, code,
                                        inner_offset, info);
                        sk = sk_next(sk);