Skip to content

Commit 35a79e6

Browse files
lxindavem330
authored andcommitted
ping: fix the dif and sdif check in ping_lookup
When 'ping' changes to use PING socket instead of RAW socket by: # sysctl -w net.ipv4.ping_group_range="0 100" There is another regression caused when matching sk_bound_dev_if and dif, RAW socket is using inet_iif() while PING socket lookup is using skb->dev->ifindex, the cmd below fails due to this: # ip link add dummy0 type dummy # ip link set dummy0 up # ip addr add 192.168.111.1/24 dev dummy0 # ping -I dummy0 192.168.111.1 -c1 The issue was also reported on: iputils/iputils#104 But fixed in iputils in a wrong way by not binding to device when destination IP is on device, and it will cause some of kselftests to fail, as Jianlin noticed. This patch is to use inet(6)_iif and inet(6)_sdif to get dif and sdif for PING socket, and keep consistent with RAW socket. Fixes: c319b4d ("net: ipv4: add IPPROTO_ICMP socket kind") Reported-by: Jianlin Shi <jishi@redhat.com> Signed-off-by: Xin Long <lucien.xin@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 21e8a96 commit 35a79e6

File tree

1 file changed

+9
-2
lines changed

1 file changed

+9
-2
lines changed

net/ipv4/ping.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,16 +172,23 @@ static struct sock *ping_lookup(struct net *net, struct sk_buff *skb, u16 ident)
172172
struct sock *sk = NULL;
173173
struct inet_sock *isk;
174174
struct hlist_nulls_node *hnode;
175-
int dif = skb->dev->ifindex;
175+
int dif, sdif;
176176

177177
if (skb->protocol == htons(ETH_P_IP)) {
178+
dif = inet_iif(skb);
179+
sdif = inet_sdif(skb);
178180
pr_debug("try to find: num = %d, daddr = %pI4, dif = %d\n",
179181
(int)ident, &ip_hdr(skb)->daddr, dif);
180182
#if IS_ENABLED(CONFIG_IPV6)
181183
} else if (skb->protocol == htons(ETH_P_IPV6)) {
184+
dif = inet6_iif(skb);
185+
sdif = inet6_sdif(skb);
182186
pr_debug("try to find: num = %d, daddr = %pI6c, dif = %d\n",
183187
(int)ident, &ipv6_hdr(skb)->daddr, dif);
184188
#endif
189+
} else {
190+
pr_err("ping: protocol(%x) is not supported\n", ntohs(skb->protocol));
191+
return NULL;
185192
}
186193

187194
read_lock_bh(&ping_table.lock);
@@ -221,7 +228,7 @@ static struct sock *ping_lookup(struct net *net, struct sk_buff *skb, u16 ident)
221228
}
222229

223230
if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif &&
224-
sk->sk_bound_dev_if != inet_sdif(skb))
231+
sk->sk_bound_dev_if != sdif)
225232
continue;
226233

227234
sock_hold(sk);

0 commit comments

Comments
 (0)