summaryrefslogtreecommitdiff
path: root/net/ipv6/raw.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/raw.c')
-rw-r--r--net/ipv6/raw.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 70fa81449997..e2405853ff40 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -71,10 +71,9 @@ static 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)
{
- struct hlist_node *node;
bool is_multicast = ipv6_addr_is_multicast(loc_addr);
- sk_for_each_from(sk, node)
+ sk_for_each_from(sk)
if (inet_sk(sk)->inet_num == num) {
struct ipv6_pinfo *np = inet6_sk(sk);
@@ -98,6 +97,24 @@ static struct sock *__raw_v6_lookup(struct net *net, struct sock *sk,
}
goto found;
}
+ sk_for_each_from (sk)
+ if (inet_sk(sk)->inet_num == num) {
+ struct ipv6_pinfo *np=inet6_sk(sk);
+ if (!net_eq(sock_net(sk), net))
+ continue;
+ if (!ipv6_addr_any(&np->daddr) && !ipv6_addr_equal(&np->daddr, rmt_addr))
+ continue;
+ if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif)
+ continue;
+ if (!ipv6_addr_any(&np->rcv_saddr)) {
+ if (ipv6_addr_equal(&np->rcv_saddr, loc_addr))
+ goto found;
+ if (is_multicast && inet6_mc_check(sk, loc_addr, rmt_addr))
+ goto found;
+ continue;
+ }
+ goto found;
+ }
sk = NULL;
found:
return sk;