2022-05-04 05:38:49 +03:00
// SPDX-License-Identifier: GPL-2.0
/* Multipath TCP
*
* Copyright ( c ) 2022 , Intel Corporation .
*/
# include "protocol.h"
2022-07-06 00:32:17 +03:00
# include "mib.h"
2024-05-14 04:13:31 +03:00
# include "mptcp_pm_gen.h"
2022-05-04 05:38:49 +03:00
void mptcp_free_local_addr_list ( struct mptcp_sock * msk )
{
struct mptcp_pm_addr_entry * entry , * tmp ;
struct sock * sk = ( struct sock * ) msk ;
LIST_HEAD ( free_list ) ;
if ( ! mptcp_pm_is_userspace ( msk ) )
return ;
spin_lock_bh ( & msk - > pm . lock ) ;
list_splice_init ( & msk - > pm . userspace_pm_local_addr_list , & free_list ) ;
spin_unlock_bh ( & msk - > pm . lock ) ;
list_for_each_entry_safe ( entry , tmp , & free_list , list ) {
sock_kfree_s ( sk , entry , sizeof ( * entry ) ) ;
}
}
2023-04-14 18:47:06 +03:00
static int mptcp_userspace_pm_append_new_local_addr ( struct mptcp_sock * msk ,
2024-02-15 21:25:28 +03:00
struct mptcp_pm_addr_entry * entry ,
bool needs_id )
2022-05-04 05:38:49 +03:00
{
DECLARE_BITMAP ( id_bitmap , MPTCP_PM_MAX_ADDR_ID + 1 ) ;
struct mptcp_pm_addr_entry * match = NULL ;
struct sock * sk = ( struct sock * ) msk ;
struct mptcp_pm_addr_entry * e ;
bool addr_match = false ;
bool id_match = false ;
int ret = - EINVAL ;
bitmap_zero ( id_bitmap , MPTCP_PM_MAX_ADDR_ID + 1 ) ;
spin_lock_bh ( & msk - > pm . lock ) ;
list_for_each_entry ( e , & msk - > pm . userspace_pm_local_addr_list , list ) {
addr_match = mptcp_addresses_equal ( & e - > addr , & entry - > addr , true ) ;
2024-02-15 21:25:28 +03:00
if ( addr_match & & entry - > addr . id = = 0 & & needs_id )
2022-05-04 05:38:49 +03:00
entry - > addr . id = e - > addr . id ;
id_match = ( e - > addr . id = = entry - > addr . id ) ;
if ( addr_match & & id_match ) {
match = e ;
break ;
} else if ( addr_match | | id_match ) {
break ;
}
__set_bit ( e - > addr . id , id_bitmap ) ;
}
if ( ! match & & ! addr_match & & ! id_match ) {
/* Memory for the entry is allocated from the
* sock option buffer .
*/
e = sock_kmalloc ( sk , sizeof ( * e ) , GFP_ATOMIC ) ;
if ( ! e ) {
2023-01-25 13:47:24 +03:00
ret = - ENOMEM ;
goto append_err ;
2022-05-04 05:38:49 +03:00
}
* e = * entry ;
2024-02-15 21:25:28 +03:00
if ( ! e - > addr . id & & needs_id )
2022-05-04 05:38:49 +03:00
e - > addr . id = find_next_zero_bit ( id_bitmap ,
MPTCP_PM_MAX_ADDR_ID + 1 ,
1 ) ;
list_add_tail_rcu ( & e - > list , & msk - > pm . userspace_pm_local_addr_list ) ;
2023-06-05 06:25:21 +03:00
msk - > pm . local_addr_used + + ;
2022-05-04 05:38:49 +03:00
ret = e - > addr . id ;
} else if ( match ) {
ret = entry - > addr . id ;
}
2023-01-25 13:47:24 +03:00
append_err :
2022-05-04 05:38:49 +03:00
spin_unlock_bh ( & msk - > pm . lock ) ;
return ret ;
}
2022-05-04 05:38:50 +03:00
2023-06-05 06:25:19 +03:00
/* If the subflow is closed from the other peer (not via a
* subflow destroy command then ) , we want to keep the entry
* not to assign the same ID to another address and to be
* able to send RM_ADDR after the removal of the subflow .
*/
static int mptcp_userspace_pm_delete_local_addr ( struct mptcp_sock * msk ,
struct mptcp_pm_addr_entry * addr )
{
struct mptcp_pm_addr_entry * entry , * tmp ;
list_for_each_entry_safe ( entry , tmp , & msk - > pm . userspace_pm_local_addr_list , list ) {
if ( mptcp_addresses_equal ( & entry - > addr , & addr - > addr , false ) ) {
/* TODO: a refcount is needed because the entry can
* be used multiple times ( e . g . fullmesh mode ) .
*/
list_del_rcu ( & entry - > list ) ;
kfree ( entry ) ;
2023-06-05 06:25:21 +03:00
msk - > pm . local_addr_used - - ;
2023-06-05 06:25:19 +03:00
return 0 ;
}
}
return - EINVAL ;
}
2024-03-01 21:18:35 +03:00
static struct mptcp_pm_addr_entry *
mptcp_userspace_pm_lookup_addr_by_id ( struct mptcp_sock * msk , unsigned int id )
{
struct mptcp_pm_addr_entry * entry ;
list_for_each_entry ( entry , & msk - > pm . userspace_pm_local_addr_list , list ) {
if ( entry - > addr . id = = id )
return entry ;
}
return NULL ;
}
2022-05-04 05:38:50 +03:00
int mptcp_userspace_pm_get_flags_and_ifindex_by_id ( struct mptcp_sock * msk ,
unsigned int id ,
u8 * flags , int * ifindex )
{
2024-03-01 21:18:35 +03:00
struct mptcp_pm_addr_entry * match ;
2022-05-04 05:38:50 +03:00
spin_lock_bh ( & msk - > pm . lock ) ;
2024-03-01 21:18:35 +03:00
match = mptcp_userspace_pm_lookup_addr_by_id ( msk , id ) ;
2022-05-04 05:38:50 +03:00
spin_unlock_bh ( & msk - > pm . lock ) ;
if ( match ) {
* flags = match - > flags ;
* ifindex = match - > ifindex ;
}
return 0 ;
}
int mptcp_userspace_pm_get_local_id ( struct mptcp_sock * msk ,
struct mptcp_addr_info * skc )
{
2024-02-08 21:03:53 +03:00
struct mptcp_pm_addr_entry * entry = NULL , * e , new_entry ;
2022-05-04 05:38:50 +03:00
__be16 msk_sport = ( ( struct inet_sock * )
inet_sk ( ( struct sock * ) msk ) ) - > inet_sport ;
2024-02-08 21:03:53 +03:00
spin_lock_bh ( & msk - > pm . lock ) ;
list_for_each_entry ( e , & msk - > pm . userspace_pm_local_addr_list , list ) {
if ( mptcp_addresses_equal ( & e - > addr , skc , false ) ) {
entry = e ;
break ;
}
}
spin_unlock_bh ( & msk - > pm . lock ) ;
if ( entry )
return entry - > addr . id ;
2022-05-04 05:38:50 +03:00
memset ( & new_entry , 0 , sizeof ( struct mptcp_pm_addr_entry ) ) ;
new_entry . addr = * skc ;
new_entry . addr . id = 0 ;
new_entry . flags = MPTCP_PM_ADDR_FLAG_IMPLICIT ;
if ( new_entry . addr . port = = msk_sport )
new_entry . addr . port = 0 ;
2024-02-15 21:25:28 +03:00
return mptcp_userspace_pm_append_new_local_addr ( msk , & new_entry , true ) ;
2022-05-04 05:38:50 +03:00
}
2022-05-04 05:38:52 +03:00
2023-10-23 21:17:10 +03:00
int mptcp_pm_nl_announce_doit ( struct sk_buff * skb , struct genl_info * info )
2022-05-04 05:38:52 +03:00
{
struct nlattr * token = info - > attrs [ MPTCP_PM_ATTR_TOKEN ] ;
struct nlattr * addr = info - > attrs [ MPTCP_PM_ATTR_ADDR ] ;
struct mptcp_pm_addr_entry addr_val ;
struct mptcp_sock * msk ;
int err = - EINVAL ;
2023-10-26 02:37:09 +03:00
struct sock * sk ;
2022-05-04 05:38:52 +03:00
u32 token_val ;
if ( ! addr | | ! token ) {
GENL_SET_ERR_MSG ( info , " missing required inputs " ) ;
return err ;
}
token_val = nla_get_u32 ( token ) ;
msk = mptcp_token_get_sock ( sock_net ( skb - > sk ) , token_val ) ;
if ( ! msk ) {
NL_SET_ERR_MSG_ATTR ( info - > extack , token , " invalid token " ) ;
return err ;
}
2023-10-26 02:37:09 +03:00
sk = ( struct sock * ) msk ;
2022-05-04 05:38:52 +03:00
if ( ! mptcp_pm_is_userspace ( msk ) ) {
GENL_SET_ERR_MSG ( info , " invalid request; userspace PM not selected " ) ;
goto announce_err ;
}
err = mptcp_pm_parse_entry ( addr , info , true , & addr_val ) ;
if ( err < 0 ) {
GENL_SET_ERR_MSG ( info , " error parsing local address " ) ;
goto announce_err ;
}
if ( addr_val . addr . id = = 0 | | ! ( addr_val . flags & MPTCP_PM_ADDR_FLAG_SIGNAL ) ) {
GENL_SET_ERR_MSG ( info , " invalid addr id or flags " ) ;
2022-12-10 03:28:07 +03:00
err = - EINVAL ;
2022-05-04 05:38:52 +03:00
goto announce_err ;
}
2024-02-15 21:25:28 +03:00
err = mptcp_userspace_pm_append_new_local_addr ( msk , & addr_val , false ) ;
2022-05-04 05:38:52 +03:00
if ( err < 0 ) {
GENL_SET_ERR_MSG ( info , " did not match address and id " ) ;
goto announce_err ;
}
2023-10-26 02:37:09 +03:00
lock_sock ( sk ) ;
2022-05-04 05:38:52 +03:00
spin_lock_bh ( & msk - > pm . lock ) ;
2023-06-20 19:30:22 +03:00
if ( mptcp_pm_alloc_anno_list ( msk , & addr_val . addr ) ) {
2023-06-05 06:25:21 +03:00
msk - > pm . add_addr_signaled + + ;
2022-05-04 05:38:52 +03:00
mptcp_pm_announce_addr ( msk , & addr_val . addr , false ) ;
mptcp_pm_nl_addr_send_ack ( msk ) ;
}
spin_unlock_bh ( & msk - > pm . lock ) ;
2023-10-26 02:37:09 +03:00
release_sock ( sk ) ;
2022-05-04 05:38:52 +03:00
err = 0 ;
announce_err :
2023-10-26 02:37:09 +03:00
sock_put ( sk ) ;
2022-05-04 05:38:52 +03:00
return err ;
}
2022-05-04 05:38:54 +03:00
2023-10-26 02:37:04 +03:00
static int mptcp_userspace_pm_remove_id_zero_address ( struct mptcp_sock * msk ,
struct genl_info * info )
{
struct mptcp_rm_list list = { . nr = 0 } ;
struct mptcp_subflow_context * subflow ;
struct sock * sk = ( struct sock * ) msk ;
bool has_id_0 = false ;
int err = - EINVAL ;
lock_sock ( sk ) ;
mptcp_for_each_subflow ( msk , subflow ) {
2024-02-15 21:25:31 +03:00
if ( READ_ONCE ( subflow - > local_id ) = = 0 ) {
2023-10-26 02:37:04 +03:00
has_id_0 = true ;
break ;
}
}
if ( ! has_id_0 ) {
GENL_SET_ERR_MSG ( info , " address with id 0 not found " ) ;
goto remove_err ;
}
list . ids [ list . nr + + ] = 0 ;
spin_lock_bh ( & msk - > pm . lock ) ;
mptcp_pm_remove_addr ( msk , & list ) ;
spin_unlock_bh ( & msk - > pm . lock ) ;
err = 0 ;
remove_err :
release_sock ( sk ) ;
return err ;
}
2023-10-23 21:17:10 +03:00
int mptcp_pm_nl_remove_doit ( struct sk_buff * skb , struct genl_info * info )
2022-05-04 05:38:54 +03:00
{
struct nlattr * token = info - > attrs [ MPTCP_PM_ATTR_TOKEN ] ;
struct nlattr * id = info - > attrs [ MPTCP_PM_ATTR_LOC_ID ] ;
2024-03-01 21:18:35 +03:00
struct mptcp_pm_addr_entry * match ;
2022-05-04 05:38:54 +03:00
struct mptcp_pm_addr_entry * entry ;
struct mptcp_sock * msk ;
LIST_HEAD ( free_list ) ;
int err = - EINVAL ;
2023-10-26 02:37:09 +03:00
struct sock * sk ;
2022-05-04 05:38:54 +03:00
u32 token_val ;
u8 id_val ;
if ( ! id | | ! token ) {
GENL_SET_ERR_MSG ( info , " missing required inputs " ) ;
return err ;
}
id_val = nla_get_u8 ( id ) ;
token_val = nla_get_u32 ( token ) ;
msk = mptcp_token_get_sock ( sock_net ( skb - > sk ) , token_val ) ;
if ( ! msk ) {
NL_SET_ERR_MSG_ATTR ( info - > extack , token , " invalid token " ) ;
return err ;
}
2023-10-26 02:37:09 +03:00
sk = ( struct sock * ) msk ;
2022-05-04 05:38:54 +03:00
if ( ! mptcp_pm_is_userspace ( msk ) ) {
GENL_SET_ERR_MSG ( info , " invalid request; userspace PM not selected " ) ;
2023-11-29 02:18:50 +03:00
goto out ;
2022-05-04 05:38:54 +03:00
}
2023-10-26 02:37:04 +03:00
if ( id_val = = 0 ) {
err = mptcp_userspace_pm_remove_id_zero_address ( msk , info ) ;
2023-11-29 02:18:50 +03:00
goto out ;
2023-10-26 02:37:04 +03:00
}
2023-10-26 02:37:09 +03:00
lock_sock ( sk ) ;
2022-05-04 05:38:54 +03:00
2024-03-01 21:18:35 +03:00
match = mptcp_userspace_pm_lookup_addr_by_id ( msk , id_val ) ;
2022-05-04 05:38:54 +03:00
if ( ! match ) {
GENL_SET_ERR_MSG ( info , " address with specified id not found " ) ;
2023-10-26 02:37:09 +03:00
release_sock ( sk ) ;
2023-11-29 02:18:50 +03:00
goto out ;
2022-05-04 05:38:54 +03:00
}
list_move ( & match - > list , & free_list ) ;
2023-06-05 06:25:17 +03:00
mptcp_pm_remove_addrs ( msk , & free_list ) ;
2022-05-04 05:38:54 +03:00
2023-10-26 02:37:09 +03:00
release_sock ( sk ) ;
2022-05-04 05:38:54 +03:00
list_for_each_entry_safe ( match , entry , & free_list , list ) {
2023-10-26 02:37:09 +03:00
sock_kfree_s ( sk , match , sizeof ( * match ) ) ;
2022-05-04 05:38:54 +03:00
}
err = 0 ;
2023-11-29 02:18:50 +03:00
out :
2023-10-26 02:37:09 +03:00
sock_put ( sk ) ;
2022-05-04 05:38:54 +03:00
return err ;
}
mptcp: netlink: allow userspace-driven subflow establishment
This allows userspace to tell kernel to add a new subflow to an existing
mptcp connection.
Userspace provides the token to identify the mptcp-level connection
that needs a change in active subflows and the local and remote
addresses of the new or the to-be-removed subflow.
MPTCP_PM_CMD_SUBFLOW_CREATE requires the following parameters:
{ token, { loc_id, family, loc_addr4 | loc_addr6 }, { family, rem_addr4 |
rem_addr6, rem_port }
MPTCP_PM_CMD_SUBFLOW_DESTROY requires the following parameters:
{ token, { family, loc_addr4 | loc_addr6, loc_port }, { family, rem_addr4 |
rem_addr6, rem_port }
Acked-by: Paolo Abeni <pabeni@redhat.com>
Co-developed-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-05-04 05:38:56 +03:00
2023-10-23 21:17:10 +03:00
int mptcp_pm_nl_subflow_create_doit ( struct sk_buff * skb , struct genl_info * info )
mptcp: netlink: allow userspace-driven subflow establishment
This allows userspace to tell kernel to add a new subflow to an existing
mptcp connection.
Userspace provides the token to identify the mptcp-level connection
that needs a change in active subflows and the local and remote
addresses of the new or the to-be-removed subflow.
MPTCP_PM_CMD_SUBFLOW_CREATE requires the following parameters:
{ token, { loc_id, family, loc_addr4 | loc_addr6 }, { family, rem_addr4 |
rem_addr6, rem_port }
MPTCP_PM_CMD_SUBFLOW_DESTROY requires the following parameters:
{ token, { family, loc_addr4 | loc_addr6, loc_port }, { family, rem_addr4 |
rem_addr6, rem_port }
Acked-by: Paolo Abeni <pabeni@redhat.com>
Co-developed-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-05-04 05:38:56 +03:00
{
struct nlattr * raddr = info - > attrs [ MPTCP_PM_ATTR_ADDR_REMOTE ] ;
struct nlattr * token = info - > attrs [ MPTCP_PM_ATTR_TOKEN ] ;
struct nlattr * laddr = info - > attrs [ MPTCP_PM_ATTR_ADDR ] ;
2023-06-05 06:25:19 +03:00
struct mptcp_pm_addr_entry local = { 0 } ;
mptcp: netlink: allow userspace-driven subflow establishment
This allows userspace to tell kernel to add a new subflow to an existing
mptcp connection.
Userspace provides the token to identify the mptcp-level connection
that needs a change in active subflows and the local and remote
addresses of the new or the to-be-removed subflow.
MPTCP_PM_CMD_SUBFLOW_CREATE requires the following parameters:
{ token, { loc_id, family, loc_addr4 | loc_addr6 }, { family, rem_addr4 |
rem_addr6, rem_port }
MPTCP_PM_CMD_SUBFLOW_DESTROY requires the following parameters:
{ token, { family, loc_addr4 | loc_addr6, loc_port }, { family, rem_addr4 |
rem_addr6, rem_port }
Acked-by: Paolo Abeni <pabeni@redhat.com>
Co-developed-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-05-04 05:38:56 +03:00
struct mptcp_addr_info addr_r ;
struct mptcp_sock * msk ;
int err = - EINVAL ;
struct sock * sk ;
u32 token_val ;
if ( ! laddr | | ! raddr | | ! token ) {
GENL_SET_ERR_MSG ( info , " missing required inputs " ) ;
return err ;
}
token_val = nla_get_u32 ( token ) ;
msk = mptcp_token_get_sock ( genl_info_net ( info ) , token_val ) ;
if ( ! msk ) {
NL_SET_ERR_MSG_ATTR ( info - > extack , token , " invalid token " ) ;
return err ;
}
2023-10-26 02:37:08 +03:00
sk = ( struct sock * ) msk ;
mptcp: netlink: allow userspace-driven subflow establishment
This allows userspace to tell kernel to add a new subflow to an existing
mptcp connection.
Userspace provides the token to identify the mptcp-level connection
that needs a change in active subflows and the local and remote
addresses of the new or the to-be-removed subflow.
MPTCP_PM_CMD_SUBFLOW_CREATE requires the following parameters:
{ token, { loc_id, family, loc_addr4 | loc_addr6 }, { family, rem_addr4 |
rem_addr6, rem_port }
MPTCP_PM_CMD_SUBFLOW_DESTROY requires the following parameters:
{ token, { family, loc_addr4 | loc_addr6, loc_port }, { family, rem_addr4 |
rem_addr6, rem_port }
Acked-by: Paolo Abeni <pabeni@redhat.com>
Co-developed-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-05-04 05:38:56 +03:00
if ( ! mptcp_pm_is_userspace ( msk ) ) {
GENL_SET_ERR_MSG ( info , " invalid request; userspace PM not selected " ) ;
goto create_err ;
}
2024-03-01 21:18:30 +03:00
err = mptcp_pm_parse_entry ( laddr , info , true , & local ) ;
mptcp: netlink: allow userspace-driven subflow establishment
This allows userspace to tell kernel to add a new subflow to an existing
mptcp connection.
Userspace provides the token to identify the mptcp-level connection
that needs a change in active subflows and the local and remote
addresses of the new or the to-be-removed subflow.
MPTCP_PM_CMD_SUBFLOW_CREATE requires the following parameters:
{ token, { loc_id, family, loc_addr4 | loc_addr6 }, { family, rem_addr4 |
rem_addr6, rem_port }
MPTCP_PM_CMD_SUBFLOW_DESTROY requires the following parameters:
{ token, { family, loc_addr4 | loc_addr6, loc_port }, { family, rem_addr4 |
rem_addr6, rem_port }
Acked-by: Paolo Abeni <pabeni@redhat.com>
Co-developed-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-05-04 05:38:56 +03:00
if ( err < 0 ) {
NL_SET_ERR_MSG_ATTR ( info - > extack , laddr , " error parsing local addr " ) ;
goto create_err ;
}
2024-03-01 21:18:30 +03:00
if ( local . flags & MPTCP_PM_ADDR_FLAG_SIGNAL ) {
GENL_SET_ERR_MSG ( info , " invalid addr flags " ) ;
err = - EINVAL ;
goto create_err ;
}
local . flags | = MPTCP_PM_ADDR_FLAG_SUBFLOW ;
mptcp: netlink: allow userspace-driven subflow establishment
This allows userspace to tell kernel to add a new subflow to an existing
mptcp connection.
Userspace provides the token to identify the mptcp-level connection
that needs a change in active subflows and the local and remote
addresses of the new or the to-be-removed subflow.
MPTCP_PM_CMD_SUBFLOW_CREATE requires the following parameters:
{ token, { loc_id, family, loc_addr4 | loc_addr6 }, { family, rem_addr4 |
rem_addr6, rem_port }
MPTCP_PM_CMD_SUBFLOW_DESTROY requires the following parameters:
{ token, { family, loc_addr4 | loc_addr6, loc_port }, { family, rem_addr4 |
rem_addr6, rem_port }
Acked-by: Paolo Abeni <pabeni@redhat.com>
Co-developed-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-05-04 05:38:56 +03:00
err = mptcp_pm_parse_addr ( raddr , info , & addr_r ) ;
if ( err < 0 ) {
NL_SET_ERR_MSG_ATTR ( info - > extack , raddr , " error parsing remote addr " ) ;
goto create_err ;
}
2024-03-01 21:18:30 +03:00
if ( ! mptcp_pm_addr_families_match ( sk , & local . addr , & addr_r ) ) {
2023-01-12 20:42:52 +03:00
GENL_SET_ERR_MSG ( info , " families mismatch " ) ;
err = - EINVAL ;
goto create_err ;
}
2024-02-15 21:25:28 +03:00
err = mptcp_userspace_pm_append_new_local_addr ( msk , & local , false ) ;
2023-06-05 06:25:19 +03:00
if ( err < 0 ) {
GENL_SET_ERR_MSG ( info , " did not match address and id " ) ;
goto create_err ;
}
mptcp: netlink: allow userspace-driven subflow establishment
This allows userspace to tell kernel to add a new subflow to an existing
mptcp connection.
Userspace provides the token to identify the mptcp-level connection
that needs a change in active subflows and the local and remote
addresses of the new or the to-be-removed subflow.
MPTCP_PM_CMD_SUBFLOW_CREATE requires the following parameters:
{ token, { loc_id, family, loc_addr4 | loc_addr6 }, { family, rem_addr4 |
rem_addr6, rem_port }
MPTCP_PM_CMD_SUBFLOW_DESTROY requires the following parameters:
{ token, { family, loc_addr4 | loc_addr6, loc_port }, { family, rem_addr4 |
rem_addr6, rem_port }
Acked-by: Paolo Abeni <pabeni@redhat.com>
Co-developed-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-05-04 05:38:56 +03:00
lock_sock ( sk ) ;
2024-03-01 21:18:30 +03:00
err = __mptcp_subflow_connect ( sk , & local . addr , & addr_r ) ;
mptcp: netlink: allow userspace-driven subflow establishment
This allows userspace to tell kernel to add a new subflow to an existing
mptcp connection.
Userspace provides the token to identify the mptcp-level connection
that needs a change in active subflows and the local and remote
addresses of the new or the to-be-removed subflow.
MPTCP_PM_CMD_SUBFLOW_CREATE requires the following parameters:
{ token, { loc_id, family, loc_addr4 | loc_addr6 }, { family, rem_addr4 |
rem_addr6, rem_port }
MPTCP_PM_CMD_SUBFLOW_DESTROY requires the following parameters:
{ token, { family, loc_addr4 | loc_addr6, loc_port }, { family, rem_addr4 |
rem_addr6, rem_port }
Acked-by: Paolo Abeni <pabeni@redhat.com>
Co-developed-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-05-04 05:38:56 +03:00
release_sock ( sk ) ;
2023-06-05 06:25:19 +03:00
spin_lock_bh ( & msk - > pm . lock ) ;
if ( err )
mptcp_userspace_pm_delete_local_addr ( msk , & local ) ;
2023-06-05 06:25:21 +03:00
else
msk - > pm . subflows + + ;
2023-06-05 06:25:19 +03:00
spin_unlock_bh ( & msk - > pm . lock ) ;
mptcp: netlink: allow userspace-driven subflow establishment
This allows userspace to tell kernel to add a new subflow to an existing
mptcp connection.
Userspace provides the token to identify the mptcp-level connection
that needs a change in active subflows and the local and remote
addresses of the new or the to-be-removed subflow.
MPTCP_PM_CMD_SUBFLOW_CREATE requires the following parameters:
{ token, { loc_id, family, loc_addr4 | loc_addr6 }, { family, rem_addr4 |
rem_addr6, rem_port }
MPTCP_PM_CMD_SUBFLOW_DESTROY requires the following parameters:
{ token, { family, loc_addr4 | loc_addr6, loc_port }, { family, rem_addr4 |
rem_addr6, rem_port }
Acked-by: Paolo Abeni <pabeni@redhat.com>
Co-developed-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-05-04 05:38:56 +03:00
create_err :
2023-10-26 02:37:08 +03:00
sock_put ( sk ) ;
mptcp: netlink: allow userspace-driven subflow establishment
This allows userspace to tell kernel to add a new subflow to an existing
mptcp connection.
Userspace provides the token to identify the mptcp-level connection
that needs a change in active subflows and the local and remote
addresses of the new or the to-be-removed subflow.
MPTCP_PM_CMD_SUBFLOW_CREATE requires the following parameters:
{ token, { loc_id, family, loc_addr4 | loc_addr6 }, { family, rem_addr4 |
rem_addr6, rem_port }
MPTCP_PM_CMD_SUBFLOW_DESTROY requires the following parameters:
{ token, { family, loc_addr4 | loc_addr6, loc_port }, { family, rem_addr4 |
rem_addr6, rem_port }
Acked-by: Paolo Abeni <pabeni@redhat.com>
Co-developed-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-05-04 05:38:56 +03:00
return err ;
}
static struct sock * mptcp_nl_find_ssk ( struct mptcp_sock * msk ,
const struct mptcp_addr_info * local ,
const struct mptcp_addr_info * remote )
{
struct mptcp_subflow_context * subflow ;
if ( local - > family ! = remote - > family )
return NULL ;
mptcp_for_each_subflow ( msk , subflow ) {
const struct inet_sock * issk ;
struct sock * ssk ;
ssk = mptcp_subflow_tcp_sock ( subflow ) ;
if ( local - > family ! = ssk - > sk_family )
continue ;
issk = inet_sk ( ssk ) ;
switch ( ssk - > sk_family ) {
case AF_INET :
if ( issk - > inet_saddr ! = local - > addr . s_addr | |
issk - > inet_daddr ! = remote - > addr . s_addr )
continue ;
break ;
# if IS_ENABLED(CONFIG_MPTCP_IPV6)
case AF_INET6 : {
const struct ipv6_pinfo * pinfo = inet6_sk ( ssk ) ;
if ( ! ipv6_addr_equal ( & local - > addr6 , & pinfo - > saddr ) | |
! ipv6_addr_equal ( & remote - > addr6 , & ssk - > sk_v6_daddr ) )
continue ;
break ;
}
# endif
default :
continue ;
}
if ( issk - > inet_sport = = local - > port & &
2022-07-06 00:32:11 +03:00
issk - > inet_dport = = remote - > port )
return ssk ;
mptcp: netlink: allow userspace-driven subflow establishment
This allows userspace to tell kernel to add a new subflow to an existing
mptcp connection.
Userspace provides the token to identify the mptcp-level connection
that needs a change in active subflows and the local and remote
addresses of the new or the to-be-removed subflow.
MPTCP_PM_CMD_SUBFLOW_CREATE requires the following parameters:
{ token, { loc_id, family, loc_addr4 | loc_addr6 }, { family, rem_addr4 |
rem_addr6, rem_port }
MPTCP_PM_CMD_SUBFLOW_DESTROY requires the following parameters:
{ token, { family, loc_addr4 | loc_addr6, loc_port }, { family, rem_addr4 |
rem_addr6, rem_port }
Acked-by: Paolo Abeni <pabeni@redhat.com>
Co-developed-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-05-04 05:38:56 +03:00
}
2022-07-06 00:32:11 +03:00
return NULL ;
mptcp: netlink: allow userspace-driven subflow establishment
This allows userspace to tell kernel to add a new subflow to an existing
mptcp connection.
Userspace provides the token to identify the mptcp-level connection
that needs a change in active subflows and the local and remote
addresses of the new or the to-be-removed subflow.
MPTCP_PM_CMD_SUBFLOW_CREATE requires the following parameters:
{ token, { loc_id, family, loc_addr4 | loc_addr6 }, { family, rem_addr4 |
rem_addr6, rem_port }
MPTCP_PM_CMD_SUBFLOW_DESTROY requires the following parameters:
{ token, { family, loc_addr4 | loc_addr6, loc_port }, { family, rem_addr4 |
rem_addr6, rem_port }
Acked-by: Paolo Abeni <pabeni@redhat.com>
Co-developed-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-05-04 05:38:56 +03:00
}
2023-10-23 21:17:10 +03:00
int mptcp_pm_nl_subflow_destroy_doit ( struct sk_buff * skb , struct genl_info * info )
mptcp: netlink: allow userspace-driven subflow establishment
This allows userspace to tell kernel to add a new subflow to an existing
mptcp connection.
Userspace provides the token to identify the mptcp-level connection
that needs a change in active subflows and the local and remote
addresses of the new or the to-be-removed subflow.
MPTCP_PM_CMD_SUBFLOW_CREATE requires the following parameters:
{ token, { loc_id, family, loc_addr4 | loc_addr6 }, { family, rem_addr4 |
rem_addr6, rem_port }
MPTCP_PM_CMD_SUBFLOW_DESTROY requires the following parameters:
{ token, { family, loc_addr4 | loc_addr6, loc_port }, { family, rem_addr4 |
rem_addr6, rem_port }
Acked-by: Paolo Abeni <pabeni@redhat.com>
Co-developed-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-05-04 05:38:56 +03:00
{
struct nlattr * raddr = info - > attrs [ MPTCP_PM_ATTR_ADDR_REMOTE ] ;
struct nlattr * token = info - > attrs [ MPTCP_PM_ATTR_TOKEN ] ;
struct nlattr * laddr = info - > attrs [ MPTCP_PM_ATTR_ADDR ] ;
struct mptcp_addr_info addr_l ;
struct mptcp_addr_info addr_r ;
struct mptcp_sock * msk ;
struct sock * sk , * ssk ;
int err = - EINVAL ;
u32 token_val ;
if ( ! laddr | | ! raddr | | ! token ) {
GENL_SET_ERR_MSG ( info , " missing required inputs " ) ;
return err ;
}
token_val = nla_get_u32 ( token ) ;
msk = mptcp_token_get_sock ( genl_info_net ( info ) , token_val ) ;
if ( ! msk ) {
NL_SET_ERR_MSG_ATTR ( info - > extack , token , " invalid token " ) ;
return err ;
}
2023-10-26 02:37:08 +03:00
sk = ( struct sock * ) msk ;
mptcp: netlink: allow userspace-driven subflow establishment
This allows userspace to tell kernel to add a new subflow to an existing
mptcp connection.
Userspace provides the token to identify the mptcp-level connection
that needs a change in active subflows and the local and remote
addresses of the new or the to-be-removed subflow.
MPTCP_PM_CMD_SUBFLOW_CREATE requires the following parameters:
{ token, { loc_id, family, loc_addr4 | loc_addr6 }, { family, rem_addr4 |
rem_addr6, rem_port }
MPTCP_PM_CMD_SUBFLOW_DESTROY requires the following parameters:
{ token, { family, loc_addr4 | loc_addr6, loc_port }, { family, rem_addr4 |
rem_addr6, rem_port }
Acked-by: Paolo Abeni <pabeni@redhat.com>
Co-developed-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-05-04 05:38:56 +03:00
if ( ! mptcp_pm_is_userspace ( msk ) ) {
GENL_SET_ERR_MSG ( info , " invalid request; userspace PM not selected " ) ;
goto destroy_err ;
}
err = mptcp_pm_parse_addr ( laddr , info , & addr_l ) ;
if ( err < 0 ) {
NL_SET_ERR_MSG_ATTR ( info - > extack , laddr , " error parsing local addr " ) ;
goto destroy_err ;
}
err = mptcp_pm_parse_addr ( raddr , info , & addr_r ) ;
if ( err < 0 ) {
NL_SET_ERR_MSG_ATTR ( info - > extack , raddr , " error parsing remote addr " ) ;
goto destroy_err ;
}
2024-02-23 19:14:11 +03:00
# if IS_ENABLED(CONFIG_MPTCP_IPV6)
if ( addr_l . family = = AF_INET & & ipv6_addr_v4mapped ( & addr_r . addr6 ) ) {
ipv6_addr_set_v4mapped ( addr_l . addr . s_addr , & addr_l . addr6 ) ;
addr_l . family = AF_INET6 ;
}
if ( addr_r . family = = AF_INET & & ipv6_addr_v4mapped ( & addr_l . addr6 ) ) {
ipv6_addr_set_v4mapped ( addr_r . addr . s_addr , & addr_r . addr6 ) ;
addr_r . family = AF_INET6 ;
}
# endif
mptcp: netlink: allow userspace-driven subflow establishment
This allows userspace to tell kernel to add a new subflow to an existing
mptcp connection.
Userspace provides the token to identify the mptcp-level connection
that needs a change in active subflows and the local and remote
addresses of the new or the to-be-removed subflow.
MPTCP_PM_CMD_SUBFLOW_CREATE requires the following parameters:
{ token, { loc_id, family, loc_addr4 | loc_addr6 }, { family, rem_addr4 |
rem_addr6, rem_port }
MPTCP_PM_CMD_SUBFLOW_DESTROY requires the following parameters:
{ token, { family, loc_addr4 | loc_addr6, loc_port }, { family, rem_addr4 |
rem_addr6, rem_port }
Acked-by: Paolo Abeni <pabeni@redhat.com>
Co-developed-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-05-04 05:38:56 +03:00
if ( addr_l . family ! = addr_r . family ) {
GENL_SET_ERR_MSG ( info , " address families do not match " ) ;
2022-12-10 03:28:07 +03:00
err = - EINVAL ;
mptcp: netlink: allow userspace-driven subflow establishment
This allows userspace to tell kernel to add a new subflow to an existing
mptcp connection.
Userspace provides the token to identify the mptcp-level connection
that needs a change in active subflows and the local and remote
addresses of the new or the to-be-removed subflow.
MPTCP_PM_CMD_SUBFLOW_CREATE requires the following parameters:
{ token, { loc_id, family, loc_addr4 | loc_addr6 }, { family, rem_addr4 |
rem_addr6, rem_port }
MPTCP_PM_CMD_SUBFLOW_DESTROY requires the following parameters:
{ token, { family, loc_addr4 | loc_addr6, loc_port }, { family, rem_addr4 |
rem_addr6, rem_port }
Acked-by: Paolo Abeni <pabeni@redhat.com>
Co-developed-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-05-04 05:38:56 +03:00
goto destroy_err ;
}
if ( ! addr_l . port | | ! addr_r . port ) {
GENL_SET_ERR_MSG ( info , " missing local or remote port " ) ;
2022-12-10 03:28:07 +03:00
err = - EINVAL ;
mptcp: netlink: allow userspace-driven subflow establishment
This allows userspace to tell kernel to add a new subflow to an existing
mptcp connection.
Userspace provides the token to identify the mptcp-level connection
that needs a change in active subflows and the local and remote
addresses of the new or the to-be-removed subflow.
MPTCP_PM_CMD_SUBFLOW_CREATE requires the following parameters:
{ token, { loc_id, family, loc_addr4 | loc_addr6 }, { family, rem_addr4 |
rem_addr6, rem_port }
MPTCP_PM_CMD_SUBFLOW_DESTROY requires the following parameters:
{ token, { family, loc_addr4 | loc_addr6, loc_port }, { family, rem_addr4 |
rem_addr6, rem_port }
Acked-by: Paolo Abeni <pabeni@redhat.com>
Co-developed-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-05-04 05:38:56 +03:00
goto destroy_err ;
}
2022-07-06 00:32:11 +03:00
lock_sock ( sk ) ;
mptcp: netlink: allow userspace-driven subflow establishment
This allows userspace to tell kernel to add a new subflow to an existing
mptcp connection.
Userspace provides the token to identify the mptcp-level connection
that needs a change in active subflows and the local and remote
addresses of the new or the to-be-removed subflow.
MPTCP_PM_CMD_SUBFLOW_CREATE requires the following parameters:
{ token, { loc_id, family, loc_addr4 | loc_addr6 }, { family, rem_addr4 |
rem_addr6, rem_port }
MPTCP_PM_CMD_SUBFLOW_DESTROY requires the following parameters:
{ token, { family, loc_addr4 | loc_addr6, loc_port }, { family, rem_addr4 |
rem_addr6, rem_port }
Acked-by: Paolo Abeni <pabeni@redhat.com>
Co-developed-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-05-04 05:38:56 +03:00
ssk = mptcp_nl_find_ssk ( msk , & addr_l , & addr_r ) ;
if ( ssk ) {
struct mptcp_subflow_context * subflow = mptcp_subflow_ctx ( ssk ) ;
2023-06-05 06:25:19 +03:00
struct mptcp_pm_addr_entry entry = { . addr = addr_l } ;
mptcp: netlink: allow userspace-driven subflow establishment
This allows userspace to tell kernel to add a new subflow to an existing
mptcp connection.
Userspace provides the token to identify the mptcp-level connection
that needs a change in active subflows and the local and remote
addresses of the new or the to-be-removed subflow.
MPTCP_PM_CMD_SUBFLOW_CREATE requires the following parameters:
{ token, { loc_id, family, loc_addr4 | loc_addr6 }, { family, rem_addr4 |
rem_addr6, rem_port }
MPTCP_PM_CMD_SUBFLOW_DESTROY requires the following parameters:
{ token, { family, loc_addr4 | loc_addr6, loc_port }, { family, rem_addr4 |
rem_addr6, rem_port }
Acked-by: Paolo Abeni <pabeni@redhat.com>
Co-developed-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-05-04 05:38:56 +03:00
2023-06-05 06:25:19 +03:00
spin_lock_bh ( & msk - > pm . lock ) ;
mptcp_userspace_pm_delete_local_addr ( msk , & entry ) ;
spin_unlock_bh ( & msk - > pm . lock ) ;
mptcp: netlink: allow userspace-driven subflow establishment
This allows userspace to tell kernel to add a new subflow to an existing
mptcp connection.
Userspace provides the token to identify the mptcp-level connection
that needs a change in active subflows and the local and remote
addresses of the new or the to-be-removed subflow.
MPTCP_PM_CMD_SUBFLOW_CREATE requires the following parameters:
{ token, { loc_id, family, loc_addr4 | loc_addr6 }, { family, rem_addr4 |
rem_addr6, rem_port }
MPTCP_PM_CMD_SUBFLOW_DESTROY requires the following parameters:
{ token, { family, loc_addr4 | loc_addr6, loc_port }, { family, rem_addr4 |
rem_addr6, rem_port }
Acked-by: Paolo Abeni <pabeni@redhat.com>
Co-developed-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-05-04 05:38:56 +03:00
mptcp_subflow_shutdown ( sk , ssk , RCV_SHUTDOWN | SEND_SHUTDOWN ) ;
mptcp_close_ssk ( sk , ssk , subflow ) ;
2022-07-06 00:32:17 +03:00
MPTCP_INC_STATS ( sock_net ( sk ) , MPTCP_MIB_RMSUBFLOW ) ;
mptcp: netlink: allow userspace-driven subflow establishment
This allows userspace to tell kernel to add a new subflow to an existing
mptcp connection.
Userspace provides the token to identify the mptcp-level connection
that needs a change in active subflows and the local and remote
addresses of the new or the to-be-removed subflow.
MPTCP_PM_CMD_SUBFLOW_CREATE requires the following parameters:
{ token, { loc_id, family, loc_addr4 | loc_addr6 }, { family, rem_addr4 |
rem_addr6, rem_port }
MPTCP_PM_CMD_SUBFLOW_DESTROY requires the following parameters:
{ token, { family, loc_addr4 | loc_addr6, loc_port }, { family, rem_addr4 |
rem_addr6, rem_port }
Acked-by: Paolo Abeni <pabeni@redhat.com>
Co-developed-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-05-04 05:38:56 +03:00
err = 0 ;
} else {
err = - ESRCH ;
}
2022-07-06 00:32:11 +03:00
release_sock ( sk ) ;
mptcp: netlink: allow userspace-driven subflow establishment
This allows userspace to tell kernel to add a new subflow to an existing
mptcp connection.
Userspace provides the token to identify the mptcp-level connection
that needs a change in active subflows and the local and remote
addresses of the new or the to-be-removed subflow.
MPTCP_PM_CMD_SUBFLOW_CREATE requires the following parameters:
{ token, { loc_id, family, loc_addr4 | loc_addr6 }, { family, rem_addr4 |
rem_addr6, rem_port }
MPTCP_PM_CMD_SUBFLOW_DESTROY requires the following parameters:
{ token, { family, loc_addr4 | loc_addr6, loc_port }, { family, rem_addr4 |
rem_addr6, rem_port }
Acked-by: Paolo Abeni <pabeni@redhat.com>
Co-developed-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-05-04 05:38:56 +03:00
2022-07-06 00:32:11 +03:00
destroy_err :
2023-10-26 02:37:08 +03:00
sock_put ( sk ) ;
mptcp: netlink: allow userspace-driven subflow establishment
This allows userspace to tell kernel to add a new subflow to an existing
mptcp connection.
Userspace provides the token to identify the mptcp-level connection
that needs a change in active subflows and the local and remote
addresses of the new or the to-be-removed subflow.
MPTCP_PM_CMD_SUBFLOW_CREATE requires the following parameters:
{ token, { loc_id, family, loc_addr4 | loc_addr6 }, { family, rem_addr4 |
rem_addr6, rem_port }
MPTCP_PM_CMD_SUBFLOW_DESTROY requires the following parameters:
{ token, { family, loc_addr4 | loc_addr6, loc_port }, { family, rem_addr4 |
rem_addr6, rem_port }
Acked-by: Paolo Abeni <pabeni@redhat.com>
Co-developed-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-05-04 05:38:56 +03:00
return err ;
}
2022-07-06 00:32:14 +03:00
2024-03-05 14:04:31 +03:00
int mptcp_userspace_pm_set_flags ( struct sk_buff * skb , struct genl_info * info )
2022-07-06 00:32:14 +03:00
{
2024-03-05 14:04:31 +03:00
struct mptcp_pm_addr_entry loc = { . addr = { . family = AF_UNSPEC } , } ;
struct mptcp_pm_addr_entry rem = { . addr = { . family = AF_UNSPEC } , } ;
struct nlattr * attr_rem = info - > attrs [ MPTCP_PM_ATTR_ADDR_REMOTE ] ;
struct nlattr * token = info - > attrs [ MPTCP_PM_ATTR_TOKEN ] ;
struct nlattr * attr = info - > attrs [ MPTCP_PM_ATTR_ADDR ] ;
struct net * net = sock_net ( skb - > sk ) ;
2022-07-06 00:32:14 +03:00
struct mptcp_sock * msk ;
int ret = - EINVAL ;
2023-10-26 02:37:09 +03:00
struct sock * sk ;
2022-07-06 00:32:14 +03:00
u32 token_val ;
2024-03-05 14:04:31 +03:00
u8 bkup = 0 ;
2022-07-06 00:32:14 +03:00
token_val = nla_get_u32 ( token ) ;
msk = mptcp_token_get_sock ( net , token_val ) ;
2024-03-05 14:04:32 +03:00
if ( ! msk ) {
NL_SET_ERR_MSG_ATTR ( info - > extack , token , " invalid token " ) ;
2022-07-06 00:32:14 +03:00
return ret ;
2024-03-05 14:04:32 +03:00
}
2022-07-06 00:32:14 +03:00
2023-10-26 02:37:09 +03:00
sk = ( struct sock * ) msk ;
2024-03-05 14:04:32 +03:00
if ( ! mptcp_pm_is_userspace ( msk ) ) {
GENL_SET_ERR_MSG ( info , " userspace PM not selected " ) ;
2022-07-06 00:32:14 +03:00
goto set_flags_err ;
2024-03-05 14:04:32 +03:00
}
2022-07-06 00:32:14 +03:00
2024-03-05 14:04:31 +03:00
ret = mptcp_pm_parse_entry ( attr , info , false , & loc ) ;
if ( ret < 0 )
2022-07-06 00:32:14 +03:00
goto set_flags_err ;
2024-03-05 14:04:31 +03:00
if ( attr_rem ) {
ret = mptcp_pm_parse_entry ( attr_rem , info , false , & rem ) ;
if ( ret < 0 )
goto set_flags_err ;
}
if ( loc . addr . family = = AF_UNSPEC | |
rem . addr . family = = AF_UNSPEC ) {
2024-03-05 14:04:32 +03:00
GENL_SET_ERR_MSG ( info , " invalid address families " ) ;
2024-03-05 14:04:31 +03:00
ret = - EINVAL ;
goto set_flags_err ;
}
if ( loc . flags & MPTCP_PM_ADDR_FLAG_BACKUP )
bkup = 1 ;
2023-10-26 02:37:09 +03:00
lock_sock ( sk ) ;
2024-03-05 14:04:31 +03:00
ret = mptcp_pm_nl_mp_prio_send_ack ( msk , & loc . addr , & rem . addr , bkup ) ;
2023-10-26 02:37:09 +03:00
release_sock ( sk ) ;
2022-07-06 00:32:14 +03:00
set_flags_err :
2023-10-26 02:37:09 +03:00
sock_put ( sk ) ;
2022-07-06 00:32:14 +03:00
return ret ;
}
2024-03-01 21:18:27 +03:00
int mptcp_userspace_pm_dump_addr ( struct sk_buff * msg ,
struct netlink_callback * cb )
{
struct id_bitmap {
DECLARE_BITMAP ( map , MPTCP_PM_MAX_ADDR_ID + 1 ) ;
} * bitmap ;
const struct genl_info * info = genl_info_dump ( cb ) ;
struct net * net = sock_net ( msg - > sk ) ;
struct mptcp_pm_addr_entry * entry ;
struct mptcp_sock * msk ;
struct nlattr * token ;
int ret = - EINVAL ;
struct sock * sk ;
void * hdr ;
bitmap = ( struct id_bitmap * ) cb - > ctx ;
token = info - > attrs [ MPTCP_PM_ATTR_TOKEN ] ;
msk = mptcp_token_get_sock ( net , nla_get_u32 ( token ) ) ;
if ( ! msk ) {
NL_SET_ERR_MSG_ATTR ( info - > extack , token , " invalid token " ) ;
return ret ;
}
sk = ( struct sock * ) msk ;
if ( ! mptcp_pm_is_userspace ( msk ) ) {
GENL_SET_ERR_MSG ( info , " invalid request; userspace PM not selected " ) ;
goto out ;
}
lock_sock ( sk ) ;
spin_lock_bh ( & msk - > pm . lock ) ;
list_for_each_entry ( entry , & msk - > pm . userspace_pm_local_addr_list , list ) {
if ( test_bit ( entry - > addr . id , bitmap - > map ) )
continue ;
hdr = genlmsg_put ( msg , NETLINK_CB ( cb - > skb ) . portid ,
cb - > nlh - > nlmsg_seq , & mptcp_genl_family ,
NLM_F_MULTI , MPTCP_PM_CMD_GET_ADDR ) ;
if ( ! hdr )
break ;
if ( mptcp_nl_fill_addr ( msg , entry ) < 0 ) {
genlmsg_cancel ( msg , hdr ) ;
break ;
}
__set_bit ( entry - > addr . id , bitmap - > map ) ;
genlmsg_end ( msg , hdr ) ;
}
spin_unlock_bh ( & msk - > pm . lock ) ;
release_sock ( sk ) ;
ret = msg - > len ;
out :
sock_put ( sk ) ;
return ret ;
}
2024-03-01 21:18:36 +03:00
int mptcp_userspace_pm_get_addr ( struct sk_buff * skb ,
struct genl_info * info )
{
struct nlattr * attr = info - > attrs [ MPTCP_PM_ENDPOINT_ADDR ] ;
struct nlattr * token = info - > attrs [ MPTCP_PM_ATTR_TOKEN ] ;
struct mptcp_pm_addr_entry addr , * entry ;
struct net * net = sock_net ( skb - > sk ) ;
struct mptcp_sock * msk ;
struct sk_buff * msg ;
int ret = - EINVAL ;
struct sock * sk ;
void * reply ;
msk = mptcp_token_get_sock ( net , nla_get_u32 ( token ) ) ;
if ( ! msk ) {
NL_SET_ERR_MSG_ATTR ( info - > extack , token , " invalid token " ) ;
return ret ;
}
sk = ( struct sock * ) msk ;
if ( ! mptcp_pm_is_userspace ( msk ) ) {
GENL_SET_ERR_MSG ( info , " invalid request; userspace PM not selected " ) ;
goto out ;
}
ret = mptcp_pm_parse_entry ( attr , info , false , & addr ) ;
if ( ret < 0 )
goto out ;
msg = nlmsg_new ( NLMSG_DEFAULT_SIZE , GFP_KERNEL ) ;
if ( ! msg ) {
ret = - ENOMEM ;
goto out ;
}
reply = genlmsg_put_reply ( msg , info , & mptcp_genl_family , 0 ,
info - > genlhdr - > cmd ) ;
if ( ! reply ) {
GENL_SET_ERR_MSG ( info , " not enough space in Netlink message " ) ;
ret = - EMSGSIZE ;
goto fail ;
}
lock_sock ( sk ) ;
spin_lock_bh ( & msk - > pm . lock ) ;
entry = mptcp_userspace_pm_lookup_addr_by_id ( msk , addr . addr . id ) ;
if ( ! entry ) {
GENL_SET_ERR_MSG ( info , " address not found " ) ;
ret = - EINVAL ;
goto unlock_fail ;
}
ret = mptcp_nl_fill_addr ( msg , entry ) ;
if ( ret )
goto unlock_fail ;
genlmsg_end ( msg , reply ) ;
ret = genlmsg_reply ( msg , info ) ;
spin_unlock_bh ( & msk - > pm . lock ) ;
release_sock ( sk ) ;
sock_put ( sk ) ;
return ret ;
unlock_fail :
spin_unlock_bh ( & msk - > pm . lock ) ;
release_sock ( sk ) ;
fail :
nlmsg_free ( msg ) ;
out :
sock_put ( sk ) ;
return ret ;
}