mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-24 09:40:58 +07:00
net: ipv6: Allow connect to linklocal address from socket bound to vrf
Allow a process bound to a VRF to connect to a linklocal address. Currently, this fails because of a mismatch between the scope of the linklocal address and the sk_bound_dev_if inherited by the VRF binding: $ ssh -6 fe80::70b8:cff:fedd:ead8%eth1 ssh: connect to host fe80::70b8:cff:fedd:ead8%eth1 port 22: Invalid argument Relax the scope check to allow the socket to be bound to the same L3 device as the scope id. This makes ipv6 linklocal consistent with other relaxed checks enabled by commits1ff23beebd
("net: l3mdev: Allow send on enslaved interface") and7bb387c5ab
("net: Allow IP_MULTICAST_IF to set index to L3 slave"). Signed-off-by: David Ahern <dsahern@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
e3e49ca9b0
commit
54dc3e3324
@ -72,6 +72,7 @@
|
||||
#include <net/tcp_states.h>
|
||||
#include <linux/net_tstamp.h>
|
||||
#include <net/smc.h>
|
||||
#include <net/l3mdev.h>
|
||||
|
||||
/*
|
||||
* This structure really needs to be cleaned up.
|
||||
@ -2399,4 +2400,23 @@ static inline void sk_pacing_shift_update(struct sock *sk, int val)
|
||||
sk->sk_pacing_shift = val;
|
||||
}
|
||||
|
||||
/* if a socket is bound to a device, check that the given device
|
||||
* index is either the same or that the socket is bound to an L3
|
||||
* master device and the given device index is also enslaved to
|
||||
* that L3 master
|
||||
*/
|
||||
static inline bool sk_dev_equal_l3scope(struct sock *sk, int dif)
|
||||
{
|
||||
int mdif;
|
||||
|
||||
if (!sk->sk_bound_dev_if || sk->sk_bound_dev_if == dif)
|
||||
return true;
|
||||
|
||||
mdif = l3mdev_master_ifindex_by_index(sock_net(sk), dif);
|
||||
if (mdif && mdif == sk->sk_bound_dev_if)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif /* _SOCK_H */
|
||||
|
@ -221,8 +221,7 @@ int __ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr,
|
||||
if (__ipv6_addr_needs_scope_id(addr_type)) {
|
||||
if (addr_len >= sizeof(struct sockaddr_in6) &&
|
||||
usin->sin6_scope_id) {
|
||||
if (sk->sk_bound_dev_if &&
|
||||
sk->sk_bound_dev_if != usin->sin6_scope_id) {
|
||||
if (!sk_dev_equal_l3scope(sk, usin->sin6_scope_id)) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
@ -176,8 +176,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
|
||||
/* If interface is set while binding, indices
|
||||
* must coincide.
|
||||
*/
|
||||
if (sk->sk_bound_dev_if &&
|
||||
sk->sk_bound_dev_if != usin->sin6_scope_id)
|
||||
if (!sk_dev_equal_l3scope(sk, usin->sin6_scope_id))
|
||||
return -EINVAL;
|
||||
|
||||
sk->sk_bound_dev_if = usin->sin6_scope_id;
|
||||
|
Loading…
Reference in New Issue
Block a user