Skip to content

Commit

Permalink
mptcp: sockopt: support IP_LOCAL_PORT_RANGE and IP_BIND_ADDRESS_NO_PORT
Browse files Browse the repository at this point in the history
Support for IP_BIND_ADDRESS_NO_PORT sockopt was introduced in [1].
Recently [2] allowed its value to be accessed without locking the
socket.

Support for (newer) IP_LOCAL_PORT_RANGE sockopt was introduced in [3].
In the same series a selftest was added in [4]. This selftest also
covers the IP_BIND_ADDRESS_NO_PORT sockopt.

This patch enables getsockopt()/setsockopt() on MPTCP sockets for these
socket options, syncing set values to subflows in sync_socket_options().
Ephemeral port range is synced to subflows, enabling NAT usecase
described in [3].

[1] commit 90c337d ("inet: add IP_BIND_ADDRESS_NO_PORT to overcome
bind(0) limitations")
[2] commit ca571e2 ("inet: move inet->bind_address_no_port to
inet->inet_flags")
[3] commit 91d0b78 ("inet: Add IP_LOCAL_PORT_RANGE socket option")
[4] commit ae54396 ("selftests/net: Cover the IP_LOCAL_PORT_RANGE
socket option")

Signed-off-by: Maxim Galaganov <[email protected]>
  • Loading branch information
darkwrat authored and intel-lab-lkp committed Nov 29, 2023
1 parent 6d9b3ca commit 845cbb6
Showing 1 changed file with 28 additions and 1 deletion.
29 changes: 28 additions & 1 deletion net/mptcp/sockopt.c
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,8 @@ static bool mptcp_supported_sockopt(int level, int optname)
/* should work fine */
case IP_FREEBIND:
case IP_TRANSPARENT:
case IP_BIND_ADDRESS_NO_PORT:
case IP_LOCAL_PORT_RANGE:

/* the following are control cmsg related */
case IP_PKTINFO:
Expand All @@ -455,7 +457,6 @@ static bool mptcp_supported_sockopt(int level, int optname)
/* common stuff that need some love */
case IP_TOS:
case IP_TTL:
case IP_BIND_ADDRESS_NO_PORT:
case IP_MTU_DISCOVER:
case IP_RECVERR:

Expand Down Expand Up @@ -688,6 +689,7 @@ static int mptcp_setsockopt_sol_ip_set(struct mptcp_sock *msk, int optname,
{
struct sock *sk = (struct sock *)msk;
struct sock *ssk;
bool slow;
int err;

err = ip_setsockopt(sk, SOL_IP, optname, optval, optlen);
Expand All @@ -710,6 +712,16 @@ static int mptcp_setsockopt_sol_ip_set(struct mptcp_sock *msk, int optname,
inet_assign_bit(TRANSPARENT, ssk,
inet_test_bit(TRANSPARENT, sk));
break;
case IP_BIND_ADDRESS_NO_PORT:
inet_assign_bit(BIND_ADDRESS_NO_PORT, ssk,
inet_test_bit(BIND_ADDRESS_NO_PORT, sk));
break;
case IP_LOCAL_PORT_RANGE:
slow = lock_sock_fast(ssk);
inet_sk(ssk)->local_port_range.lo = inet_sk(sk)->local_port_range.lo;
inet_sk(ssk)->local_port_range.hi = inet_sk(sk)->local_port_range.hi;
unlock_sock_fast(ssk, slow);
break;
default:
release_sock(sk);
WARN_ON_ONCE(1);
Expand Down Expand Up @@ -755,6 +767,8 @@ static int mptcp_setsockopt_v4(struct mptcp_sock *msk, int optname,
switch (optname) {
case IP_FREEBIND:
case IP_TRANSPARENT:
case IP_BIND_ADDRESS_NO_PORT:
case IP_LOCAL_PORT_RANGE:
return mptcp_setsockopt_sol_ip_set(msk, optname, optval, optlen);
case IP_TOS:
return mptcp_setsockopt_v4_set_tos(msk, optname, optval, optlen);
Expand Down Expand Up @@ -1346,10 +1360,20 @@ static int mptcp_getsockopt_v4(struct mptcp_sock *msk, int optname,
char __user *optval, int __user *optlen)
{
struct sock *sk = (void *)msk;
bool slow;
int val;

switch (optname) {
case IP_TOS:
return mptcp_put_int_option(msk, optval, optlen, READ_ONCE(inet_sk(sk)->tos));
case IP_BIND_ADDRESS_NO_PORT:
return mptcp_put_int_option(msk, optval, optlen,
inet_test_bit(BIND_ADDRESS_NO_PORT, sk));
case IP_LOCAL_PORT_RANGE:
slow = lock_sock_fast(sk);
val = inet_sk(sk)->local_port_range.hi << 16 | inet_sk(sk)->local_port_range.lo;
unlock_sock_fast(sk, slow);
return mptcp_put_int_option(msk, optval, optlen, val);
}

return -EOPNOTSUPP;
Expand Down Expand Up @@ -1450,6 +1474,9 @@ static void sync_socket_options(struct mptcp_sock *msk, struct sock *ssk)

inet_assign_bit(TRANSPARENT, ssk, inet_test_bit(TRANSPARENT, sk));
inet_assign_bit(FREEBIND, ssk, inet_test_bit(FREEBIND, sk));
inet_assign_bit(BIND_ADDRESS_NO_PORT, ssk, inet_test_bit(BIND_ADDRESS_NO_PORT, sk));
inet_sk(ssk)->local_port_range.lo = inet_sk(sk)->local_port_range.lo;
inet_sk(ssk)->local_port_range.hi = inet_sk(sk)->local_port_range.hi;
}

void mptcp_sockopt_sync_locked(struct mptcp_sock *msk, struct sock *ssk)
Expand Down

0 comments on commit 845cbb6

Please sign in to comment.