Skip to content

Commit e1a7ac6

Browse files
NicolasDichtelkuba-moo
authored andcommitted
ping: fix address binding wrt vrf
When ping_group_range is updated, 'ping' uses the DGRAM ICMP socket, instead of an IP raw socket. In this case, 'ping' is unable to bind its socket to a local address owned by a vrflite. Before the patch: $ sysctl -w net.ipv4.ping_group_range='0 2147483647' $ ip link add blue type vrf table 10 $ ip link add foo type dummy $ ip link set foo master blue $ ip link set foo up $ ip addr add 192.168.1.1/24 dev foo $ ip addr add 2001::1/64 dev foo $ ip vrf exec blue ping -c1 -I 192.168.1.1 192.168.1.2 ping: bind: Cannot assign requested address $ ip vrf exec blue ping6 -c1 -I 2001::1 2001::2 ping6: bind icmp socket: Cannot assign requested address CC: [email protected] Fixes: 1b69c6d ("net: Introduce L3 Master device abstraction") Signed-off-by: Nicolas Dichtel <[email protected]> Reviewed-by: David Ahern <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 15f03ff commit e1a7ac6

File tree

1 file changed

+11
-1
lines changed

1 file changed

+11
-1
lines changed

net/ipv4/ping.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@ static int ping_check_bind_addr(struct sock *sk, struct inet_sock *isk,
305305
struct net *net = sock_net(sk);
306306
if (sk->sk_family == AF_INET) {
307307
struct sockaddr_in *addr = (struct sockaddr_in *) uaddr;
308+
u32 tb_id = RT_TABLE_LOCAL;
308309
int chk_addr_ret;
309310

310311
if (addr_len < sizeof(*addr))
@@ -318,7 +319,8 @@ static int ping_check_bind_addr(struct sock *sk, struct inet_sock *isk,
318319
pr_debug("ping_check_bind_addr(sk=%p,addr=%pI4,port=%d)\n",
319320
sk, &addr->sin_addr.s_addr, ntohs(addr->sin_port));
320321

321-
chk_addr_ret = inet_addr_type(net, addr->sin_addr.s_addr);
322+
tb_id = l3mdev_fib_table_by_index(net, sk->sk_bound_dev_if) ? : tb_id;
323+
chk_addr_ret = inet_addr_type_table(net, addr->sin_addr.s_addr, tb_id);
322324

323325
if (!inet_addr_valid_or_nonlocal(net, inet_sk(sk),
324326
addr->sin_addr.s_addr,
@@ -355,6 +357,14 @@ static int ping_check_bind_addr(struct sock *sk, struct inet_sock *isk,
355357
return -ENODEV;
356358
}
357359
}
360+
361+
if (!dev && sk->sk_bound_dev_if) {
362+
dev = dev_get_by_index_rcu(net, sk->sk_bound_dev_if);
363+
if (!dev) {
364+
rcu_read_unlock();
365+
return -ENODEV;
366+
}
367+
}
358368
has_addr = pingv6_ops.ipv6_chk_addr(net, &addr->sin6_addr, dev,
359369
scoped);
360370
rcu_read_unlock();

0 commit comments

Comments
 (0)