Message ID | 20231129113403.157953-3-max@internet.ru (mailing list archive) |
---|---|
State | Superseded, archived |
Delegated to: | Mat Martineau |
Headers | show |
Series | more sockopts for ephemeral ports | expand |
Context | Check | Description |
---|---|---|
matttbe/build | success | Build and static analysis OK |
matttbe/checkpatch | success | total: 0 errors, 0 warnings, 0 checks, 75 lines checked |
matttbe/KVM_Validation__normal__except_selftest_mptcp_join_ | success | Success! ✅ |
matttbe/KVM_Validation__normal__only_selftest_mptcp_join_ | success | Success! ✅ |
matttbe/KVM_Validation__debug__except_selftest_mptcp_join_ | success | Success! ✅ |
matttbe/KVM_Validation__debug__only_selftest_mptcp_join_ | success | Success! ✅ |
On Wed, 29 Nov 2023, Maxim Galaganov wrote: > 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> Thanks for the v2 Maxim, looks good to me: Reviewed-by: Mat Martineau <martineau@kernel.org> > --- > net/mptcp/sockopt.c | 29 ++++++++++++++++++++++++++++- > 1 file changed, 28 insertions(+), 1 deletion(-) > > diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c > index a4bf337e6f77..a164a3e21be4 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) > -- > 2.43.0 > > >
On Wed, 29 Nov 2023, Mat Martineau wrote: > On Wed, 29 Nov 2023, Maxim Galaganov wrote: > >> 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> > > Thanks for the v2 Maxim, looks good to me: > > Reviewed-by: Mat Martineau <martineau@kernel.org> > Now that I've signed off on this, I see that there's work going on to change the implementation of local_port_range: https://lore.kernel.org/netdev/a4f5b61c9cd44eada41d8f09d3848806@AcuMS.aculab.com/ I think it makes sense to do a v3 of this series if a version of David's patch gets merged soon (I expect a v2 as he got some feedback from me and some others). I'll watch for progress with his patch on netdev. - Mat >> --- >> net/mptcp/sockopt.c | 29 ++++++++++++++++++++++++++++- >> 1 file changed, 28 insertions(+), 1 deletion(-) >> >> diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c >> index a4bf337e6f77..a164a3e21be4 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) >> -- >> 2.43.0 >> >> >> >
On Fri, Dec 1, 2023 at 3:59 PM Mat Martineau <martineau@kernel.org> wrote: > > On Wed, 29 Nov 2023, Mat Martineau wrote: > > > On Wed, 29 Nov 2023, Maxim Galaganov wrote: > > > >> 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> > > > > Thanks for the v2 Maxim, looks good to me: > > > > Reviewed-by: Mat Martineau <martineau@kernel.org> > > > > Now that I've signed off on this, I see that there's work going on to > change the implementation of local_port_range: > > https://lore.kernel.org/netdev/a4f5b61c9cd44eada41d8f09d3848806@AcuMS.aculab.com/ > > I think it makes sense to do a v3 of this series if a version of David's > patch gets merged soon (I expect a v2 as he got some feedback from me and > some others). I'll watch for progress with his patch on netdev. Maxim - It looks like this patch will be merged to net-next soon: https://lore.kernel.org/netdev/4e505d4198e946a8be03fb1b4c3072b0@AcuMS.aculab.com/ Please cherry-pick that and update your IP_LOCAL_PORT_RANGE patch to fit the new implementation. Thanks! - Mat > > >> --- > >> net/mptcp/sockopt.c | 29 ++++++++++++++++++++++++++++- > >> 1 file changed, 28 insertions(+), 1 deletion(-) > >> > >> diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c > >> index a4bf337e6f77..a164a3e21be4 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) > >> -- > >> 2.43.0 > >> > >> > >> > >
On 08.12.2023 03:24, Mat Martineau wrote: > On Fri, Dec 1, 2023 at 3:59 PM Mat Martineau <martineau@kernel.org> wrote: >> >> On Wed, 29 Nov 2023, Mat Martineau wrote: >> >>> On Wed, 29 Nov 2023, Maxim Galaganov wrote: >>> >>>> 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> >>> >>> Thanks for the v2 Maxim, looks good to me: >>> >>> Reviewed-by: Mat Martineau <martineau@kernel.org> >>> >> >> Now that I've signed off on this, I see that there's work going on to >> change the implementation of local_port_range: >> >> https://lore.kernel.org/netdev/a4f5b61c9cd44eada41d8f09d3848806@AcuMS.aculab.com/ >> >> I think it makes sense to do a v3 of this series if a version of David's >> patch gets merged soon (I expect a v2 as he got some feedback from me and >> some others). I'll watch for progress with his patch on netdev. > > Maxim - > > It looks like this patch will be merged to net-next soon: > > https://lore.kernel.org/netdev/4e505d4198e946a8be03fb1b4c3072b0@AcuMS.aculab.com/ > > Please cherry-pick that and update your IP_LOCAL_PORT_RANGE patch to > fit the new implementation. Hi Mat, I'd prefer posting v3 once the mentioned patch gets to net-next and then export branch, otherwise bots will probably complain about build errors. Tell me if I should just post them now. Thank you for spotting and tracking this. Max > > Thanks! > > - Mat > > >> >>>> --- >>>> net/mptcp/sockopt.c | 29 ++++++++++++++++++++++++++++- >>>> 1 file changed, 28 insertions(+), 1 deletion(-) >>>> >>>> diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c >>>> index a4bf337e6f77..a164a3e21be4 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) >>>> -- >>>> 2.43.0 >>>> >>>> >>>> >>>
diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c index a4bf337e6f77..a164a3e21be4 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)
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> --- net/mptcp/sockopt.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-)