Commit c85636a2 authored by Maxim Galaganov's avatar Maxim Galaganov Committed by David S. Miller

mptcp: sockopt: support IP_LOCAL_PORT_RANGE and IP_BIND_ADDRESS_NO_PORT

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 90c337da ("inet: add IP_BIND_ADDRESS_NO_PORT to overcome
bind(0) limitations")
[2] commit ca571e2e ("inet: move inet->bind_address_no_port to
inet->inet_flags")
[3] commit 91d0b78c ("inet: Add IP_LOCAL_PORT_RANGE socket option")
[4] commit ae543965 ("selftests/net: Cover the IP_LOCAL_PORT_RANGE
socket option")
Signed-off-by: default avatarMaxim Galaganov <max@internet.ru>
Reviewed-by: default avatarMat Martineau <martineau@kernel.org>
Signed-off-by: default avatarMatthieu Baerts <matttbe@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 57d3117c
...@@ -440,6 +440,8 @@ static bool mptcp_supported_sockopt(int level, int optname) ...@@ -440,6 +440,8 @@ static bool mptcp_supported_sockopt(int level, int optname)
/* should work fine */ /* should work fine */
case IP_FREEBIND: case IP_FREEBIND:
case IP_TRANSPARENT: case IP_TRANSPARENT:
case IP_BIND_ADDRESS_NO_PORT:
case IP_LOCAL_PORT_RANGE:
/* the following are control cmsg related */ /* the following are control cmsg related */
case IP_PKTINFO: case IP_PKTINFO:
...@@ -455,7 +457,6 @@ static bool mptcp_supported_sockopt(int level, int optname) ...@@ -455,7 +457,6 @@ static bool mptcp_supported_sockopt(int level, int optname)
/* common stuff that need some love */ /* common stuff that need some love */
case IP_TOS: case IP_TOS:
case IP_TTL: case IP_TTL:
case IP_BIND_ADDRESS_NO_PORT:
case IP_MTU_DISCOVER: case IP_MTU_DISCOVER:
case IP_RECVERR: case IP_RECVERR:
...@@ -710,6 +711,14 @@ static int mptcp_setsockopt_sol_ip_set(struct mptcp_sock *msk, int optname, ...@@ -710,6 +711,14 @@ static int mptcp_setsockopt_sol_ip_set(struct mptcp_sock *msk, int optname,
inet_assign_bit(TRANSPARENT, ssk, inet_assign_bit(TRANSPARENT, ssk,
inet_test_bit(TRANSPARENT, sk)); inet_test_bit(TRANSPARENT, sk));
break; 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:
WRITE_ONCE(inet_sk(ssk)->local_port_range,
READ_ONCE(inet_sk(sk)->local_port_range));
break;
default: default:
release_sock(sk); release_sock(sk);
WARN_ON_ONCE(1); WARN_ON_ONCE(1);
...@@ -755,6 +764,8 @@ static int mptcp_setsockopt_v4(struct mptcp_sock *msk, int optname, ...@@ -755,6 +764,8 @@ static int mptcp_setsockopt_v4(struct mptcp_sock *msk, int optname,
switch (optname) { switch (optname) {
case IP_FREEBIND: case IP_FREEBIND:
case IP_TRANSPARENT: case IP_TRANSPARENT:
case IP_BIND_ADDRESS_NO_PORT:
case IP_LOCAL_PORT_RANGE:
return mptcp_setsockopt_sol_ip_set(msk, optname, optval, optlen); return mptcp_setsockopt_sol_ip_set(msk, optname, optval, optlen);
case IP_TOS: case IP_TOS:
return mptcp_setsockopt_v4_set_tos(msk, optname, optval, optlen); return mptcp_setsockopt_v4_set_tos(msk, optname, optval, optlen);
...@@ -1350,6 +1361,12 @@ static int mptcp_getsockopt_v4(struct mptcp_sock *msk, int optname, ...@@ -1350,6 +1361,12 @@ static int mptcp_getsockopt_v4(struct mptcp_sock *msk, int optname,
switch (optname) { switch (optname) {
case IP_TOS: case IP_TOS:
return mptcp_put_int_option(msk, optval, optlen, READ_ONCE(inet_sk(sk)->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:
return mptcp_put_int_option(msk, optval, optlen,
READ_ONCE(inet_sk(sk)->local_port_range));
} }
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -1450,6 +1467,8 @@ static void sync_socket_options(struct mptcp_sock *msk, struct sock *ssk) ...@@ -1450,6 +1467,8 @@ 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(TRANSPARENT, ssk, inet_test_bit(TRANSPARENT, sk));
inet_assign_bit(FREEBIND, ssk, inet_test_bit(FREEBIND, 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));
WRITE_ONCE(inet_sk(ssk)->local_port_range, READ_ONCE(inet_sk(sk)->local_port_range));
} }
void mptcp_sockopt_sync_locked(struct mptcp_sock *msk, struct sock *ssk) void mptcp_sockopt_sync_locked(struct mptcp_sock *msk, struct sock *ssk)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment