mptcp: sockopt: support IP_LOCAL_PORT_RANGE and IP_BIND_ADDRESS_NO_PORT
authorMaxim Galaganov <max@internet.ru>
Tue, 19 Dec 2023 21:31:06 +0000 (22:31 +0100)
committerDavid S. Miller <davem@davemloft.net>
Tue, 26 Dec 2023 22:33:21 +0000 (22:33 +0000)
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 90c337da1524 ("inet: add IP_BIND_ADDRESS_NO_PORT to overcome
bind(0) limitations")
[2] commit ca571e2eb7eb ("inet: move inet->bind_address_no_port to
inet->inet_flags")
[3] commit 91d0b78c5177 ("inet: Add IP_LOCAL_PORT_RANGE socket option")
[4] commit ae5439658cce ("selftests/net: Cover the IP_LOCAL_PORT_RANGE
socket option")

Signed-off-by: Maxim Galaganov <max@internet.ru>
Reviewed-by: Mat Martineau <martineau@kernel.org>
Signed-off-by: Matthieu Baerts <matttbe@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/mptcp/sockopt.c

index a4bf337e6f771095c62313150a90d43f21bb574c..c40f1428e6020236db6e13317cde86d7627bce9e 100644 (file)
@@ -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:
@@ -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:
 
@@ -710,6 +711,14 @@ 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:
+               WRITE_ONCE(inet_sk(ssk)->local_port_range,
+                          READ_ONCE(inet_sk(sk)->local_port_range));
+               break;
        default:
                release_sock(sk);
                WARN_ON_ONCE(1);
@@ -755,6 +764,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);
@@ -1350,6 +1361,12 @@ static int mptcp_getsockopt_v4(struct mptcp_sock *msk, int optname,
        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:
+               return mptcp_put_int_option(msk, optval, optlen,
+                               READ_ONCE(inet_sk(sk)->local_port_range));
        }
 
        return -EOPNOTSUPP;
@@ -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(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)