|
@@ -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);
|