diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c index a4bf337e6f7710..a164a3e21be443 100644 --- a/net/mptcp/sockopt.c +++ b/net/mptcp/sockopt.c @@ -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: @@ -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); @@ -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); @@ -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); @@ -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; @@ -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)