Skip to content

Commit

Permalink
mptcp: pm nl: support IPv4 mapped in v6 addresses
Browse files Browse the repository at this point in the history
On one side, we can allow the creation of subflows between v4 mapped in
v6 and v4 addresses. For that we look for v4mapped addresses between the
local address we want to select and the remote one.

On the other side, we also properly deal with received v4mapped
addresses, either announced ones or set via Netlink.

Fixes: 01cacb0 ("mptcp: add netlink-based PM")
Closes: #122
Suggested-by: Mat Martineau <[email protected]>
Reviewed-by: Mat Martineau <[email protected]>
Co-developed-by: Geliang Tang <[email protected]>
Signed-off-by: Geliang Tang <[email protected]>
Signed-off-by: Matthieu Baerts <[email protected]>
  • Loading branch information
matttbe authored and jenkins-tessares committed Jan 21, 2021
1 parent 1098354 commit 9b9ede9
Showing 1 changed file with 24 additions and 9 deletions.
33 changes: 24 additions & 9 deletions net/mptcp/pm_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,20 @@ static bool addresses_equal(const struct mptcp_addr_info *a,
{
bool addr_equals = false;

if (a->family != b->family)
return false;

if (a->family == AF_INET)
addr_equals = a->addr.s_addr == b->addr.s_addr;
if (a->family == b->family) {
if (a->family == AF_INET)
addr_equals = a->addr.s_addr == b->addr.s_addr;
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
else
addr_equals = !ipv6_addr_cmp(&a->addr6, &b->addr6);
else
addr_equals = !ipv6_addr_cmp(&a->addr6, &b->addr6);
} else if (a->family == AF_INET) {
if (ipv6_addr_v4mapped(&b->addr6))
addr_equals = a->addr.s_addr == b->addr6.s6_addr32[3];
} else if (b->family == AF_INET) {
if (ipv6_addr_v4mapped(&a->addr6))
addr_equals = a->addr6.s6_addr32[3] == b->addr.s_addr;
#endif
}

if (!addr_equals)
return false;
Expand Down Expand Up @@ -137,18 +142,28 @@ select_local_address(const struct pm_nl_pernet *pernet,
struct mptcp_sock *msk)
{
struct mptcp_pm_addr_entry *entry, *ret = NULL;
struct sock *sk = (struct sock *)msk;

rcu_read_lock();
__mptcp_flush_join_list(msk);
list_for_each_entry_rcu(entry, &pernet->local_addr_list, list) {
if (!(entry->addr.flags & MPTCP_PM_ADDR_FLAG_SUBFLOW))
continue;

if (entry->addr.family != sk->sk_family) {
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
if ((entry->addr.family == AF_INET &&
!ipv6_addr_v4mapped(&sk->sk_v6_daddr)) ||
(sk->sk_family == AF_INET &&
!ipv6_addr_v4mapped(&entry->addr.addr6)))
#endif
continue;
}

/* avoid any address already in use by subflows and
* pending join
*/
if (entry->addr.family == ((struct sock *)msk)->sk_family &&
!lookup_subflow_by_saddr(&msk->conn_list, &entry->addr)) {
if (!lookup_subflow_by_saddr(&msk->conn_list, &entry->addr)) {
ret = entry;
break;
}
Expand Down

0 comments on commit 9b9ede9

Please sign in to comment.