Commit 67359930 authored by David Ahern's avatar David Ahern Committed by David S. Miller

net: ipv4: add second dif to raw socket lookups

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: default avatarDavid Ahern <dsahern@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3fa6f616
...@@ -26,7 +26,7 @@ extern struct proto raw_prot; ...@@ -26,7 +26,7 @@ extern struct proto raw_prot;
extern struct raw_hashinfo raw_v4_hashinfo; extern struct raw_hashinfo raw_v4_hashinfo;
struct sock *__raw_v4_lookup(struct net *net, struct sock *sk, struct sock *__raw_v4_lookup(struct net *net, struct sock *sk,
unsigned short num, __be32 raddr, unsigned short num, __be32 raddr,
__be32 laddr, int dif); __be32 laddr, int dif, int sdif);
int raw_abort(struct sock *sk, int err); int raw_abort(struct sock *sk, int err);
void raw_icmp_error(struct sk_buff *, int, u32); void raw_icmp_error(struct sk_buff *, int, u32);
......
...@@ -122,7 +122,8 @@ void raw_unhash_sk(struct sock *sk) ...@@ -122,7 +122,8 @@ void raw_unhash_sk(struct sock *sk)
EXPORT_SYMBOL_GPL(raw_unhash_sk); EXPORT_SYMBOL_GPL(raw_unhash_sk);
struct sock *__raw_v4_lookup(struct net *net, struct sock *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) { sk_for_each_from(sk) {
struct inet_sock *inet = inet_sk(sk); struct inet_sock *inet = inet_sk(sk);
...@@ -130,7 +131,8 @@ struct sock *__raw_v4_lookup(struct net *net, struct sock *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 && if (net_eq(sock_net(sk), net) && inet->inet_num == num &&
!(inet->inet_daddr && inet->inet_daddr != raddr) && !(inet->inet_daddr && inet->inet_daddr != raddr) &&
!(inet->inet_rcv_saddr && inet->inet_rcv_saddr != laddr) && !(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 */ goto found; /* gotcha */
} }
sk = NULL; sk = NULL;
...@@ -171,6 +173,7 @@ static int icmp_filter(const struct sock *sk, const struct sk_buff *skb) ...@@ -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) static int raw_v4_input(struct sk_buff *skb, const struct iphdr *iph, int hash)
{ {
int sdif = inet_sdif(skb);
struct sock *sk; struct sock *sk;
struct hlist_head *head; struct hlist_head *head;
int delivered = 0; int delivered = 0;
...@@ -184,7 +187,7 @@ static int raw_v4_input(struct sk_buff *skb, const struct iphdr *iph, int hash) ...@@ -184,7 +187,7 @@ static int raw_v4_input(struct sk_buff *skb, const struct iphdr *iph, int hash)
net = dev_net(skb->dev); net = dev_net(skb->dev);
sk = __raw_v4_lookup(net, __sk_head(head), iph->protocol, sk = __raw_v4_lookup(net, __sk_head(head), iph->protocol,
iph->saddr, iph->daddr, iph->saddr, iph->daddr,
skb->dev->ifindex); skb->dev->ifindex, sdif);
while (sk) { while (sk) {
delivered = 1; delivered = 1;
...@@ -199,7 +202,7 @@ static int raw_v4_input(struct sk_buff *skb, const struct iphdr *iph, int hash) ...@@ -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, sk = __raw_v4_lookup(net, sk_next(sk), iph->protocol,
iph->saddr, iph->daddr, iph->saddr, iph->daddr,
skb->dev->ifindex); skb->dev->ifindex, sdif);
} }
out: out:
read_unlock(&raw_v4_hashinfo.lock); read_unlock(&raw_v4_hashinfo.lock);
...@@ -297,12 +300,15 @@ void raw_icmp_error(struct sk_buff *skb, int protocol, u32 info) ...@@ -297,12 +300,15 @@ void raw_icmp_error(struct sk_buff *skb, int protocol, u32 info)
read_lock(&raw_v4_hashinfo.lock); read_lock(&raw_v4_hashinfo.lock);
raw_sk = sk_head(&raw_v4_hashinfo.ht[hash]); raw_sk = sk_head(&raw_v4_hashinfo.ht[hash]);
if (raw_sk) { if (raw_sk) {
int dif = skb->dev->ifindex;
int sdif = inet_sdif(skb);
iph = (const struct iphdr *)skb->data; iph = (const struct iphdr *)skb->data;
net = dev_net(skb->dev); net = dev_net(skb->dev);
while ((raw_sk = __raw_v4_lookup(net, raw_sk, protocol, while ((raw_sk = __raw_v4_lookup(net, raw_sk, protocol,
iph->daddr, iph->saddr, iph->daddr, iph->saddr,
skb->dev->ifindex)) != NULL) { dif, sdif)) != NULL) {
raw_err(raw_sk, skb, info); raw_err(raw_sk, skb, info);
raw_sk = sk_next(raw_sk); raw_sk = sk_next(raw_sk);
iph = (const struct iphdr *)skb->data; iph = (const struct iphdr *)skb->data;
......
...@@ -46,7 +46,7 @@ static struct sock *raw_lookup(struct net *net, struct sock *from, ...@@ -46,7 +46,7 @@ static struct sock *raw_lookup(struct net *net, struct sock *from,
sk = __raw_v4_lookup(net, from, r->sdiag_raw_protocol, sk = __raw_v4_lookup(net, from, r->sdiag_raw_protocol,
r->id.idiag_dst[0], r->id.idiag_dst[0],
r->id.idiag_src[0], r->id.idiag_src[0],
r->id.idiag_if); r->id.idiag_if, 0);
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
else else
sk = __raw_v6_lookup(net, from, r->sdiag_raw_protocol, sk = __raw_v6_lookup(net, from, r->sdiag_raw_protocol,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment