|
@@ -122,7 +122,8 @@ void raw_unhash_sk(struct sock *sk)
|
|
|
EXPORT_SYMBOL_GPL(raw_unhash_sk);
|
|
|
|
|
|
struct sock *__raw_v4_lookup(struct net *net, struct sock *sk,
|
|
|
- unsigned short num, __be32 raddr, __be32 laddr, int dif)
|
|
|
+ unsigned short num, __be32 raddr, __be32 laddr,
|
|
|
+ int dif, int sdif)
|
|
|
{
|
|
|
sk_for_each_from(sk) {
|
|
|
struct inet_sock *inet = inet_sk(sk);
|
|
@@ -130,7 +131,8 @@ struct sock *__raw_v4_lookup(struct net *net, struct sock *sk,
|
|
|
if (net_eq(sock_net(sk), net) && inet->inet_num == num &&
|
|
|
!(inet->inet_daddr && inet->inet_daddr != raddr) &&
|
|
|
!(inet->inet_rcv_saddr && inet->inet_rcv_saddr != laddr) &&
|
|
|
- !(sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif))
|
|
|
+ !(sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif &&
|
|
|
+ sk->sk_bound_dev_if != sdif))
|
|
|
goto found; /* gotcha */
|
|
|
}
|
|
|
sk = NULL;
|
|
@@ -171,6 +173,7 @@ static int icmp_filter(const struct sock *sk, const struct sk_buff *skb)
|
|
|
*/
|
|
|
static int raw_v4_input(struct sk_buff *skb, const struct iphdr *iph, int hash)
|
|
|
{
|
|
|
+ int sdif = inet_sdif(skb);
|
|
|
struct sock *sk;
|
|
|
struct hlist_head *head;
|
|
|
int delivered = 0;
|
|
@@ -184,7 +187,7 @@ static int raw_v4_input(struct sk_buff *skb, const struct iphdr *iph, int hash)
|
|
|
net = dev_net(skb->dev);
|
|
|
sk = __raw_v4_lookup(net, __sk_head(head), iph->protocol,
|
|
|
iph->saddr, iph->daddr,
|
|
|
- skb->dev->ifindex);
|
|
|
+ skb->dev->ifindex, sdif);
|
|
|
|
|
|
while (sk) {
|
|
|
delivered = 1;
|
|
@@ -199,7 +202,7 @@ static int raw_v4_input(struct sk_buff *skb, const struct iphdr *iph, int hash)
|
|
|
}
|
|
|
sk = __raw_v4_lookup(net, sk_next(sk), iph->protocol,
|
|
|
iph->saddr, iph->daddr,
|
|
|
- skb->dev->ifindex);
|
|
|
+ skb->dev->ifindex, sdif);
|
|
|
}
|
|
|
out:
|
|
|
read_unlock(&raw_v4_hashinfo.lock);
|
|
@@ -297,12 +300,15 @@ void raw_icmp_error(struct sk_buff *skb, int protocol, u32 info)
|
|
|
read_lock(&raw_v4_hashinfo.lock);
|
|
|
raw_sk = sk_head(&raw_v4_hashinfo.ht[hash]);
|
|
|
if (raw_sk) {
|
|
|
+ int dif = skb->dev->ifindex;
|
|
|
+ int sdif = inet_sdif(skb);
|
|
|
+
|
|
|
iph = (const struct iphdr *)skb->data;
|
|
|
net = dev_net(skb->dev);
|
|
|
|
|
|
while ((raw_sk = __raw_v4_lookup(net, raw_sk, protocol,
|
|
|
iph->daddr, iph->saddr,
|
|
|
- skb->dev->ifindex)) != NULL) {
|
|
|
+ dif, sdif)) != NULL) {
|
|
|
raw_err(raw_sk, skb, info);
|
|
|
raw_sk = sk_next(raw_sk);
|
|
|
iph = (const struct iphdr *)skb->data;
|