2014-03-26 17:07:35 -05:00
/*
* Copyright ( c ) 2014 Intel Corporation . All rights reserved .
* Copyright ( c ) 2014 Chelsio , Inc . All rights reserved .
*
* This software is available to you under a choice of one of two
* licenses . You may choose to be licensed under the terms of the GNU
* General Public License ( GPL ) Version 2 , available from the file
* COPYING in the main directory of this source tree , or the
* OpenIB . org BSD license below :
*
* Redistribution and use in source and binary forms , with or
* without modification , are permitted provided that the following
* conditions are met :
*
* - Redistributions of source code must retain the above
* copyright notice , this list of conditions and the following
* disclaimer .
*
* - Redistributions in binary form must reproduce the above
* copyright notice , this list of conditions and the following
* disclaimer in the documentation and / or other materials
* provided with the distribution .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND ,
* EXPRESS OR IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY , FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT . IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER LIABILITY , WHETHER IN AN
* ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM , OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE .
*/
# include "iwpm_util.h"
2015-05-08 16:36:33 -05:00
static const char iwpm_ulib_name [ IWPM_ULIBNAME_SIZE ] = " iWarpPortMapperUser " ;
2019-01-29 13:33:16 -08:00
u16 iwpm_ulib_version = IWPM_UABI_VERSION_MIN ;
2014-03-26 17:07:35 -05:00
static int iwpm_user_pid = IWPM_PID_UNDEFINED ;
static atomic_t echo_nlmsg_seq ;
2019-02-05 11:33:22 -08:00
/**
* iwpm_valid_pid - Check if the userspace iwarp port mapper pid is valid
*
* Returns true if the pid is greater than zero , otherwise returns false
*/
2014-03-26 17:07:35 -05:00
int iwpm_valid_pid ( void )
{
return iwpm_user_pid > 0 ;
}
2019-02-05 11:33:22 -08:00
/**
* iwpm_register_pid - Send a netlink query to userspace
* to get the iwarp port mapper pid
* @ pm_msg : Contains driver info to send to the userspace port mapper
* @ nl_client : The index of the netlink client
2014-03-26 17:07:35 -05:00
*
* nlmsg attributes :
* [ IWPM_NLA_REG_PID_SEQ ]
* [ IWPM_NLA_REG_IF_NAME ]
* [ IWPM_NLA_REG_IBDEV_NAME ]
* [ IWPM_NLA_REG_ULIB_NAME ]
*/
int iwpm_register_pid ( struct iwpm_dev_data * pm_msg , u8 nl_client )
{
struct sk_buff * skb = NULL ;
struct iwpm_nlmsg_request * nlmsg_request = NULL ;
struct nlmsghdr * nlh ;
u32 msg_seq ;
const char * err_str = " " ;
int ret = - EINVAL ;
2015-07-02 12:47:44 -05:00
if ( iwpm_check_registration ( nl_client , IWPM_REG_VALID ) | |
iwpm_user_pid = = IWPM_PID_UNAVAILABLE )
2014-03-26 17:07:35 -05:00
return 0 ;
skb = iwpm_create_nlmsg ( RDMA_NL_IWPM_REG_PID , & nlh , nl_client ) ;
if ( ! skb ) {
err_str = " Unable to create a nlmsg " ;
goto pid_query_error ;
}
nlh - > nlmsg_seq = iwpm_get_nlmsg_seq ( ) ;
nlmsg_request = iwpm_get_nlmsg_request ( nlh - > nlmsg_seq , nl_client , GFP_KERNEL ) ;
if ( ! nlmsg_request ) {
err_str = " Unable to allocate netlink request " ;
goto pid_query_error ;
}
msg_seq = atomic_read ( & echo_nlmsg_seq ) ;
/* fill in the pid request message */
err_str = " Unable to put attribute of the nlmsg " ;
ret = ibnl_put_attr ( skb , nlh , sizeof ( u32 ) , & msg_seq , IWPM_NLA_REG_PID_SEQ ) ;
if ( ret )
goto pid_query_error ;
2016-02-26 09:18:00 -06:00
ret = ibnl_put_attr ( skb , nlh , IFNAMSIZ ,
2016-02-26 09:18:05 -06:00
pm_msg - > if_name , IWPM_NLA_REG_IF_NAME ) ;
2014-03-26 17:07:35 -05:00
if ( ret )
goto pid_query_error ;
ret = ibnl_put_attr ( skb , nlh , IWPM_DEVNAME_SIZE ,
pm_msg - > dev_name , IWPM_NLA_REG_IBDEV_NAME ) ;
if ( ret )
goto pid_query_error ;
ret = ibnl_put_attr ( skb , nlh , IWPM_ULIBNAME_SIZE ,
( char * ) iwpm_ulib_name , IWPM_NLA_REG_ULIB_NAME ) ;
if ( ret )
goto pid_query_error ;
2017-09-29 08:25:01 -05:00
nlmsg_end ( skb , nlh ) ;
2014-03-26 17:07:35 -05:00
pr_debug ( " %s: Multicasting a nlmsg (dev = %s ifname = %s iwpm = %s) \n " ,
__func__ , pm_msg - > dev_name , pm_msg - > if_name , iwpm_ulib_name ) ;
2019-07-23 10:02:05 +03:00
ret = rdma_nl_multicast ( & init_net , skb , RDMA_NL_GROUP_IWPM , GFP_KERNEL ) ;
2014-03-26 17:07:35 -05:00
if ( ret ) {
skb = NULL ; /* skb is freed in the netlink send-op handling */
iwpm_user_pid = IWPM_PID_UNAVAILABLE ;
err_str = " Unable to send a nlmsg " ;
goto pid_query_error ;
}
nlmsg_request - > req_buffer = pm_msg ;
ret = iwpm_wait_complete_req ( nlmsg_request ) ;
return ret ;
pid_query_error :
2021-06-10 19:40:32 +08:00
pr_info ( " %s: %s (client = %u) \n " , __func__ , err_str , nl_client ) ;
2019-08-21 19:30:09 +02:00
dev_kfree_skb ( skb ) ;
2014-03-26 17:07:35 -05:00
if ( nlmsg_request )
iwpm_free_nlmsg_request ( & nlmsg_request - > kref ) ;
return ret ;
}
2019-02-05 11:33:22 -08:00
/**
* iwpm_add_mapping - Send a netlink add mapping request to
* the userspace port mapper
* @ pm_msg : Contains the local ip / tcp address info to send
* @ nl_client : The index of the netlink client
*
2014-03-26 17:07:35 -05:00
* nlmsg attributes :
* [ IWPM_NLA_MANAGE_MAPPING_SEQ ]
* [ IWPM_NLA_MANAGE_ADDR ]
2019-01-29 13:33:16 -08:00
* [ IWPM_NLA_MANAGE_FLAGS ]
2019-02-05 11:33:22 -08:00
*
* If the request is successful , the pm_msg stores
* the port mapper response ( mapped address info )
2014-03-26 17:07:35 -05:00
*/
int iwpm_add_mapping ( struct iwpm_sa_data * pm_msg , u8 nl_client )
{
struct sk_buff * skb = NULL ;
struct iwpm_nlmsg_request * nlmsg_request = NULL ;
struct nlmsghdr * nlh ;
u32 msg_seq ;
const char * err_str = " " ;
int ret = - EINVAL ;
2015-07-02 12:47:44 -05:00
if ( ! iwpm_valid_pid ( ) )
return 0 ;
if ( ! iwpm_check_registration ( nl_client , IWPM_REG_VALID ) ) {
2014-03-26 17:07:35 -05:00
err_str = " Unregistered port mapper client " ;
goto add_mapping_error ;
}
skb = iwpm_create_nlmsg ( RDMA_NL_IWPM_ADD_MAPPING , & nlh , nl_client ) ;
if ( ! skb ) {
err_str = " Unable to create a nlmsg " ;
goto add_mapping_error ;
}
nlh - > nlmsg_seq = iwpm_get_nlmsg_seq ( ) ;
nlmsg_request = iwpm_get_nlmsg_request ( nlh - > nlmsg_seq , nl_client , GFP_KERNEL ) ;
if ( ! nlmsg_request ) {
err_str = " Unable to allocate netlink request " ;
goto add_mapping_error ;
}
msg_seq = atomic_read ( & echo_nlmsg_seq ) ;
/* fill in the add mapping message */
err_str = " Unable to put attribute of the nlmsg " ;
ret = ibnl_put_attr ( skb , nlh , sizeof ( u32 ) , & msg_seq ,
IWPM_NLA_MANAGE_MAPPING_SEQ ) ;
if ( ret )
goto add_mapping_error ;
ret = ibnl_put_attr ( skb , nlh , sizeof ( struct sockaddr_storage ) ,
& pm_msg - > loc_addr , IWPM_NLA_MANAGE_ADDR ) ;
if ( ret )
goto add_mapping_error ;
2017-09-29 08:25:01 -05:00
2019-01-29 13:33:16 -08:00
/* If flags are required and we're not V4, then return a quiet error */
if ( pm_msg - > flags & & iwpm_ulib_version = = IWPM_UABI_VERSION_MIN ) {
ret = - EINVAL ;
goto add_mapping_error_nowarn ;
}
if ( iwpm_ulib_version > IWPM_UABI_VERSION_MIN ) {
ret = ibnl_put_attr ( skb , nlh , sizeof ( u32 ) , & pm_msg - > flags ,
IWPM_NLA_MANAGE_FLAGS ) ;
if ( ret )
goto add_mapping_error ;
}
2017-09-29 08:25:01 -05:00
nlmsg_end ( skb , nlh ) ;
2014-03-26 17:07:35 -05:00
nlmsg_request - > req_buffer = pm_msg ;
2019-07-23 10:02:05 +03:00
ret = rdma_nl_unicast_wait ( & init_net , skb , iwpm_user_pid ) ;
2014-03-26 17:07:35 -05:00
if ( ret ) {
skb = NULL ; /* skb is freed in the netlink send-op handling */
iwpm_user_pid = IWPM_PID_UNDEFINED ;
err_str = " Unable to send a nlmsg " ;
goto add_mapping_error ;
}
ret = iwpm_wait_complete_req ( nlmsg_request ) ;
return ret ;
add_mapping_error :
2021-06-10 19:40:32 +08:00
pr_info ( " %s: %s (client = %u) \n " , __func__ , err_str , nl_client ) ;
2019-01-29 13:33:16 -08:00
add_mapping_error_nowarn :
2019-08-21 19:30:09 +02:00
dev_kfree_skb ( skb ) ;
2014-03-26 17:07:35 -05:00
if ( nlmsg_request )
iwpm_free_nlmsg_request ( & nlmsg_request - > kref ) ;
return ret ;
}
2019-02-05 11:33:22 -08:00
/**
* iwpm_add_and_query_mapping - Process the port mapper response to
* iwpm_add_and_query_mapping request
* @ pm_msg : Contains the local ip / tcp address info to send
* @ nl_client : The index of the netlink client
*
2014-03-26 17:07:35 -05:00
* nlmsg attributes :
* [ IWPM_NLA_QUERY_MAPPING_SEQ ]
* [ IWPM_NLA_QUERY_LOCAL_ADDR ]
* [ IWPM_NLA_QUERY_REMOTE_ADDR ]
2019-01-29 13:33:16 -08:00
* [ IWPM_NLA_QUERY_FLAGS ]
2014-03-26 17:07:35 -05:00
*/
int iwpm_add_and_query_mapping ( struct iwpm_sa_data * pm_msg , u8 nl_client )
{
struct sk_buff * skb = NULL ;
struct iwpm_nlmsg_request * nlmsg_request = NULL ;
struct nlmsghdr * nlh ;
u32 msg_seq ;
const char * err_str = " " ;
int ret = - EINVAL ;
2015-07-02 12:47:44 -05:00
if ( ! iwpm_valid_pid ( ) )
return 0 ;
if ( ! iwpm_check_registration ( nl_client , IWPM_REG_VALID ) ) {
2014-03-26 17:07:35 -05:00
err_str = " Unregistered port mapper client " ;
goto query_mapping_error ;
}
ret = - ENOMEM ;
skb = iwpm_create_nlmsg ( RDMA_NL_IWPM_QUERY_MAPPING , & nlh , nl_client ) ;
if ( ! skb ) {
err_str = " Unable to create a nlmsg " ;
goto query_mapping_error ;
}
nlh - > nlmsg_seq = iwpm_get_nlmsg_seq ( ) ;
nlmsg_request = iwpm_get_nlmsg_request ( nlh - > nlmsg_seq ,
nl_client , GFP_KERNEL ) ;
if ( ! nlmsg_request ) {
err_str = " Unable to allocate netlink request " ;
goto query_mapping_error ;
}
msg_seq = atomic_read ( & echo_nlmsg_seq ) ;
/* fill in the query message */
err_str = " Unable to put attribute of the nlmsg " ;
ret = ibnl_put_attr ( skb , nlh , sizeof ( u32 ) , & msg_seq ,
IWPM_NLA_QUERY_MAPPING_SEQ ) ;
if ( ret )
goto query_mapping_error ;
ret = ibnl_put_attr ( skb , nlh , sizeof ( struct sockaddr_storage ) ,
& pm_msg - > loc_addr , IWPM_NLA_QUERY_LOCAL_ADDR ) ;
if ( ret )
goto query_mapping_error ;
ret = ibnl_put_attr ( skb , nlh , sizeof ( struct sockaddr_storage ) ,
& pm_msg - > rem_addr , IWPM_NLA_QUERY_REMOTE_ADDR ) ;
if ( ret )
goto query_mapping_error ;
2017-09-29 08:25:01 -05:00
2019-01-29 13:33:16 -08:00
/* If flags are required and we're not V4, then return a quite error */
if ( pm_msg - > flags & & iwpm_ulib_version = = IWPM_UABI_VERSION_MIN ) {
ret = - EINVAL ;
goto query_mapping_error_nowarn ;
}
if ( iwpm_ulib_version > IWPM_UABI_VERSION_MIN ) {
ret = ibnl_put_attr ( skb , nlh , sizeof ( u32 ) , & pm_msg - > flags ,
IWPM_NLA_QUERY_FLAGS ) ;
if ( ret )
goto query_mapping_error ;
}
2017-09-29 08:25:01 -05:00
nlmsg_end ( skb , nlh ) ;
2014-03-26 17:07:35 -05:00
nlmsg_request - > req_buffer = pm_msg ;
2019-07-23 10:02:05 +03:00
ret = rdma_nl_unicast_wait ( & init_net , skb , iwpm_user_pid ) ;
2014-03-26 17:07:35 -05:00
if ( ret ) {
skb = NULL ; /* skb is freed in the netlink send-op handling */
err_str = " Unable to send a nlmsg " ;
goto query_mapping_error ;
}
ret = iwpm_wait_complete_req ( nlmsg_request ) ;
return ret ;
query_mapping_error :
2021-06-10 19:40:32 +08:00
pr_info ( " %s: %s (client = %u) \n " , __func__ , err_str , nl_client ) ;
2019-01-29 13:33:16 -08:00
query_mapping_error_nowarn :
2019-08-21 19:30:09 +02:00
dev_kfree_skb ( skb ) ;
2014-03-26 17:07:35 -05:00
if ( nlmsg_request )
iwpm_free_nlmsg_request ( & nlmsg_request - > kref ) ;
return ret ;
}
2019-02-05 11:33:22 -08:00
/**
* iwpm_remove_mapping - Send a netlink remove mapping request
* to the userspace port mapper
*
* @ local_addr : Local ip / tcp address to remove
* @ nl_client : The index of the netlink client
*
2014-03-26 17:07:35 -05:00
* nlmsg attributes :
* [ IWPM_NLA_MANAGE_MAPPING_SEQ ]
* [ IWPM_NLA_MANAGE_ADDR ]
*/
int iwpm_remove_mapping ( struct sockaddr_storage * local_addr , u8 nl_client )
{
struct sk_buff * skb = NULL ;
struct nlmsghdr * nlh ;
u32 msg_seq ;
const char * err_str = " " ;
int ret = - EINVAL ;
2015-07-02 12:47:44 -05:00
if ( ! iwpm_valid_pid ( ) )
return 0 ;
if ( iwpm_check_registration ( nl_client , IWPM_REG_UNDEF ) ) {
2014-03-26 17:07:35 -05:00
err_str = " Unregistered port mapper client " ;
goto remove_mapping_error ;
}
skb = iwpm_create_nlmsg ( RDMA_NL_IWPM_REMOVE_MAPPING , & nlh , nl_client ) ;
if ( ! skb ) {
ret = - ENOMEM ;
err_str = " Unable to create a nlmsg " ;
goto remove_mapping_error ;
}
msg_seq = atomic_read ( & echo_nlmsg_seq ) ;
nlh - > nlmsg_seq = iwpm_get_nlmsg_seq ( ) ;
err_str = " Unable to put attribute of the nlmsg " ;
ret = ibnl_put_attr ( skb , nlh , sizeof ( u32 ) , & msg_seq ,
IWPM_NLA_MANAGE_MAPPING_SEQ ) ;
if ( ret )
goto remove_mapping_error ;
ret = ibnl_put_attr ( skb , nlh , sizeof ( struct sockaddr_storage ) ,
local_addr , IWPM_NLA_MANAGE_ADDR ) ;
if ( ret )
goto remove_mapping_error ;
2017-09-29 08:25:01 -05:00
nlmsg_end ( skb , nlh ) ;
2019-07-23 10:02:05 +03:00
ret = rdma_nl_unicast_wait ( & init_net , skb , iwpm_user_pid ) ;
2014-03-26 17:07:35 -05:00
if ( ret ) {
skb = NULL ; /* skb is freed in the netlink send-op handling */
iwpm_user_pid = IWPM_PID_UNDEFINED ;
err_str = " Unable to send a nlmsg " ;
goto remove_mapping_error ;
}
iwpm_print_sockaddr ( local_addr ,
" remove_mapping: Local sockaddr: " ) ;
return 0 ;
remove_mapping_error :
2021-06-10 19:40:32 +08:00
pr_info ( " %s: %s (client = %u) \n " , __func__ , err_str , nl_client ) ;
2014-03-26 17:07:35 -05:00
if ( skb )
dev_kfree_skb_any ( skb ) ;
return ret ;
}
/* netlink attribute policy for the received response to register pid request */
static const struct nla_policy resp_reg_policy [ IWPM_NLA_RREG_PID_MAX ] = {
[ IWPM_NLA_RREG_PID_SEQ ] = { . type = NLA_U32 } ,
[ IWPM_NLA_RREG_IBDEV_NAME ] = { . type = NLA_STRING ,
. len = IWPM_DEVNAME_SIZE - 1 } ,
[ IWPM_NLA_RREG_ULIB_NAME ] = { . type = NLA_STRING ,
. len = IWPM_ULIBNAME_SIZE - 1 } ,
[ IWPM_NLA_RREG_ULIB_VER ] = { . type = NLA_U16 } ,
[ IWPM_NLA_RREG_PID_ERR ] = { . type = NLA_U16 }
} ;
2019-02-05 11:33:22 -08:00
/**
* iwpm_register_pid_cb - Process the port mapper response to
* iwpm_register_pid query
2021-01-18 22:39:29 +00:00
* @ skb : The socket buffer
2019-02-05 11:33:22 -08:00
* @ cb : Contains the received message ( payload and netlink header )
*
* If successful , the function receives the userspace port mapper pid
* which is used in future communication with the port mapper
2014-03-26 17:07:35 -05:00
*/
int iwpm_register_pid_cb ( struct sk_buff * skb , struct netlink_callback * cb )
{
struct iwpm_nlmsg_request * nlmsg_request = NULL ;
struct nlattr * nltb [ IWPM_NLA_RREG_PID_MAX ] ;
struct iwpm_dev_data * pm_msg ;
char * dev_name , * iwpm_name ;
u32 msg_seq ;
u8 nl_client ;
u16 iwpm_version ;
const char * msg_type = " Register Pid response " ;
if ( iwpm_parse_nlmsg ( cb , IWPM_NLA_RREG_PID_MAX ,
resp_reg_policy , nltb , msg_type ) )
return - EINVAL ;
msg_seq = nla_get_u32 ( nltb [ IWPM_NLA_RREG_PID_SEQ ] ) ;
nlmsg_request = iwpm_find_nlmsg_request ( msg_seq ) ;
if ( ! nlmsg_request ) {
pr_info ( " %s: Could not find a matching request (seq = %u) \n " ,
__func__ , msg_seq ) ;
return - EINVAL ;
}
pm_msg = nlmsg_request - > req_buffer ;
nl_client = nlmsg_request - > nl_client ;
dev_name = ( char * ) nla_data ( nltb [ IWPM_NLA_RREG_IBDEV_NAME ] ) ;
iwpm_name = ( char * ) nla_data ( nltb [ IWPM_NLA_RREG_ULIB_NAME ] ) ;
iwpm_version = nla_get_u16 ( nltb [ IWPM_NLA_RREG_ULIB_VER ] ) ;
/* check device name, ulib name and version */
if ( strcmp ( pm_msg - > dev_name , dev_name ) | |
strcmp ( iwpm_ulib_name , iwpm_name ) | |
2019-01-29 13:33:16 -08:00
iwpm_version < IWPM_UABI_VERSION_MIN ) {
2014-03-26 17:07:35 -05:00
2021-06-10 19:40:32 +08:00
pr_info ( " %s: Incorrect info (dev = %s name = %s version = %u) \n " ,
2014-03-26 17:07:35 -05:00
__func__ , dev_name , iwpm_name , iwpm_version ) ;
nlmsg_request - > err_code = IWPM_USER_LIB_INFO_ERR ;
goto register_pid_response_exit ;
}
iwpm_user_pid = cb - > nlh - > nlmsg_pid ;
2019-01-29 13:33:16 -08:00
iwpm_ulib_version = iwpm_version ;
if ( iwpm_ulib_version < IWPM_UABI_VERSION )
2021-06-10 19:40:32 +08:00
pr_warn_once ( " %s: Down level iwpmd/pid %d. Continuing... " ,
2019-01-29 13:33:16 -08:00
__func__ , iwpm_user_pid ) ;
2014-03-26 17:07:35 -05:00
atomic_set ( & echo_nlmsg_seq , cb - > nlh - > nlmsg_seq ) ;
pr_debug ( " %s: iWarp Port Mapper (pid = %d) is available! \n " ,
__func__ , iwpm_user_pid ) ;
2021-07-23 17:08:57 +03:00
iwpm_set_registration ( nl_client , IWPM_REG_VALID ) ;
2014-03-26 17:07:35 -05:00
register_pid_response_exit :
nlmsg_request - > request_done = 1 ;
/* always for found nlmsg_request */
kref_put ( & nlmsg_request - > kref , iwpm_free_nlmsg_request ) ;
barrier ( ) ;
2016-02-26 09:18:05 -06:00
up ( & nlmsg_request - > sem ) ;
2014-03-26 17:07:35 -05:00
return 0 ;
}
/* netlink attribute policy for the received response to add mapping request */
static const struct nla_policy resp_add_policy [ IWPM_NLA_RMANAGE_MAPPING_MAX ] = {
2019-01-29 13:33:11 -08:00
[ IWPM_NLA_RMANAGE_MAPPING_SEQ ] = { . type = NLA_U32 } ,
[ IWPM_NLA_RMANAGE_ADDR ] = {
. len = sizeof ( struct sockaddr_storage ) } ,
[ IWPM_NLA_RMANAGE_MAPPED_LOC_ADDR ] = {
. len = sizeof ( struct sockaddr_storage ) } ,
[ IWPM_NLA_RMANAGE_MAPPING_ERR ] = { . type = NLA_U16 }
2014-03-26 17:07:35 -05:00
} ;
2019-02-05 11:33:22 -08:00
/**
* iwpm_add_mapping_cb - Process the port mapper response to
* iwpm_add_mapping request
2021-01-18 22:39:29 +00:00
* @ skb : The socket buffer
2019-02-05 11:33:22 -08:00
* @ cb : Contains the received message ( payload and netlink header )
2014-03-26 17:07:35 -05:00
*/
int iwpm_add_mapping_cb ( struct sk_buff * skb , struct netlink_callback * cb )
{
struct iwpm_sa_data * pm_msg ;
struct iwpm_nlmsg_request * nlmsg_request = NULL ;
struct nlattr * nltb [ IWPM_NLA_RMANAGE_MAPPING_MAX ] ;
struct sockaddr_storage * local_sockaddr ;
struct sockaddr_storage * mapped_sockaddr ;
const char * msg_type ;
u32 msg_seq ;
msg_type = " Add Mapping response " ;
if ( iwpm_parse_nlmsg ( cb , IWPM_NLA_RMANAGE_MAPPING_MAX ,
resp_add_policy , nltb , msg_type ) )
return - EINVAL ;
atomic_set ( & echo_nlmsg_seq , cb - > nlh - > nlmsg_seq ) ;
2019-01-29 13:33:11 -08:00
msg_seq = nla_get_u32 ( nltb [ IWPM_NLA_RMANAGE_MAPPING_SEQ ] ) ;
2014-03-26 17:07:35 -05:00
nlmsg_request = iwpm_find_nlmsg_request ( msg_seq ) ;
if ( ! nlmsg_request ) {
pr_info ( " %s: Could not find a matching request (seq = %u) \n " ,
__func__ , msg_seq ) ;
return - EINVAL ;
}
pm_msg = nlmsg_request - > req_buffer ;
local_sockaddr = ( struct sockaddr_storage * )
2019-01-29 13:33:11 -08:00
nla_data ( nltb [ IWPM_NLA_RMANAGE_ADDR ] ) ;
2014-03-26 17:07:35 -05:00
mapped_sockaddr = ( struct sockaddr_storage * )
2019-01-29 13:33:11 -08:00
nla_data ( nltb [ IWPM_NLA_RMANAGE_MAPPED_LOC_ADDR ] ) ;
2014-03-26 17:07:35 -05:00
if ( iwpm_compare_sockaddr ( local_sockaddr , & pm_msg - > loc_addr ) ) {
nlmsg_request - > err_code = IWPM_USER_LIB_INFO_ERR ;
goto add_mapping_response_exit ;
}
if ( mapped_sockaddr - > ss_family ! = local_sockaddr - > ss_family ) {
pr_info ( " %s: Sockaddr family doesn't match the requested one \n " ,
__func__ ) ;
nlmsg_request - > err_code = IWPM_USER_LIB_INFO_ERR ;
goto add_mapping_response_exit ;
}
memcpy ( & pm_msg - > mapped_loc_addr , mapped_sockaddr ,
sizeof ( * mapped_sockaddr ) ) ;
iwpm_print_sockaddr ( & pm_msg - > loc_addr ,
" add_mapping: Local sockaddr: " ) ;
iwpm_print_sockaddr ( & pm_msg - > mapped_loc_addr ,
" add_mapping: Mapped local sockaddr: " ) ;
add_mapping_response_exit :
nlmsg_request - > request_done = 1 ;
/* always for found request */
kref_put ( & nlmsg_request - > kref , iwpm_free_nlmsg_request ) ;
barrier ( ) ;
2016-02-26 09:18:05 -06:00
up ( & nlmsg_request - > sem ) ;
2014-03-26 17:07:35 -05:00
return 0 ;
}
2015-04-21 16:28:10 -04:00
/* netlink attribute policy for the response to add and query mapping request
2021-04-07 16:15:52 +08:00
* and response with remote address info
*/
2014-03-26 17:07:35 -05:00
static const struct nla_policy resp_query_policy [ IWPM_NLA_RQUERY_MAPPING_MAX ] = {
2019-01-29 13:33:11 -08:00
[ IWPM_NLA_RQUERY_MAPPING_SEQ ] = { . type = NLA_U32 } ,
[ IWPM_NLA_RQUERY_LOCAL_ADDR ] = {
. len = sizeof ( struct sockaddr_storage ) } ,
[ IWPM_NLA_RQUERY_REMOTE_ADDR ] = {
. len = sizeof ( struct sockaddr_storage ) } ,
[ IWPM_NLA_RQUERY_MAPPED_LOC_ADDR ] = {
. len = sizeof ( struct sockaddr_storage ) } ,
[ IWPM_NLA_RQUERY_MAPPED_REM_ADDR ] = {
. len = sizeof ( struct sockaddr_storage ) } ,
2014-03-26 17:07:35 -05:00
[ IWPM_NLA_RQUERY_MAPPING_ERR ] = { . type = NLA_U16 }
} ;
2019-02-05 11:33:22 -08:00
/**
* iwpm_add_and_query_mapping_cb - Process the port mapper response to
* iwpm_add_and_query_mapping request
2021-01-18 22:39:29 +00:00
* @ skb : The socket buffer
2019-02-05 11:33:22 -08:00
* @ cb : Contains the received message ( payload and netlink header )
2014-03-26 17:07:35 -05:00
*/
int iwpm_add_and_query_mapping_cb ( struct sk_buff * skb ,
struct netlink_callback * cb )
{
struct iwpm_sa_data * pm_msg ;
struct iwpm_nlmsg_request * nlmsg_request = NULL ;
struct nlattr * nltb [ IWPM_NLA_RQUERY_MAPPING_MAX ] ;
struct sockaddr_storage * local_sockaddr , * remote_sockaddr ;
struct sockaddr_storage * mapped_loc_sockaddr , * mapped_rem_sockaddr ;
const char * msg_type ;
u32 msg_seq ;
u16 err_code ;
msg_type = " Query Mapping response " ;
if ( iwpm_parse_nlmsg ( cb , IWPM_NLA_RQUERY_MAPPING_MAX ,
resp_query_policy , nltb , msg_type ) )
return - EINVAL ;
atomic_set ( & echo_nlmsg_seq , cb - > nlh - > nlmsg_seq ) ;
2019-01-29 13:33:11 -08:00
msg_seq = nla_get_u32 ( nltb [ IWPM_NLA_RQUERY_MAPPING_SEQ ] ) ;
2014-03-26 17:07:35 -05:00
nlmsg_request = iwpm_find_nlmsg_request ( msg_seq ) ;
if ( ! nlmsg_request ) {
pr_info ( " %s: Could not find a matching request (seq = %u) \n " ,
__func__ , msg_seq ) ;
2016-06-03 12:08:00 -07:00
return - EINVAL ;
2014-03-26 17:07:35 -05:00
}
pm_msg = nlmsg_request - > req_buffer ;
local_sockaddr = ( struct sockaddr_storage * )
2019-01-29 13:33:11 -08:00
nla_data ( nltb [ IWPM_NLA_RQUERY_LOCAL_ADDR ] ) ;
2014-03-26 17:07:35 -05:00
remote_sockaddr = ( struct sockaddr_storage * )
2019-01-29 13:33:11 -08:00
nla_data ( nltb [ IWPM_NLA_RQUERY_REMOTE_ADDR ] ) ;
2014-03-26 17:07:35 -05:00
mapped_loc_sockaddr = ( struct sockaddr_storage * )
nla_data ( nltb [ IWPM_NLA_RQUERY_MAPPED_LOC_ADDR ] ) ;
mapped_rem_sockaddr = ( struct sockaddr_storage * )
nla_data ( nltb [ IWPM_NLA_RQUERY_MAPPED_REM_ADDR ] ) ;
err_code = nla_get_u16 ( nltb [ IWPM_NLA_RQUERY_MAPPING_ERR ] ) ;
if ( err_code = = IWPM_REMOTE_QUERY_REJECT ) {
pr_info ( " %s: Received a Reject (pid = %u, echo seq = %u) \n " ,
__func__ , cb - > nlh - > nlmsg_pid , msg_seq ) ;
nlmsg_request - > err_code = IWPM_REMOTE_QUERY_REJECT ;
}
if ( iwpm_compare_sockaddr ( local_sockaddr , & pm_msg - > loc_addr ) | |
iwpm_compare_sockaddr ( remote_sockaddr , & pm_msg - > rem_addr ) ) {
pr_info ( " %s: Incorrect local sockaddr \n " , __func__ ) ;
nlmsg_request - > err_code = IWPM_USER_LIB_INFO_ERR ;
goto query_mapping_response_exit ;
}
if ( mapped_loc_sockaddr - > ss_family ! = local_sockaddr - > ss_family | |
mapped_rem_sockaddr - > ss_family ! = remote_sockaddr - > ss_family ) {
pr_info ( " %s: Sockaddr family doesn't match the requested one \n " ,
__func__ ) ;
nlmsg_request - > err_code = IWPM_USER_LIB_INFO_ERR ;
goto query_mapping_response_exit ;
}
memcpy ( & pm_msg - > mapped_loc_addr , mapped_loc_sockaddr ,
sizeof ( * mapped_loc_sockaddr ) ) ;
memcpy ( & pm_msg - > mapped_rem_addr , mapped_rem_sockaddr ,
sizeof ( * mapped_rem_sockaddr ) ) ;
iwpm_print_sockaddr ( & pm_msg - > loc_addr ,
" query_mapping: Local sockaddr: " ) ;
iwpm_print_sockaddr ( & pm_msg - > mapped_loc_addr ,
" query_mapping: Mapped local sockaddr: " ) ;
iwpm_print_sockaddr ( & pm_msg - > rem_addr ,
" query_mapping: Remote sockaddr: " ) ;
iwpm_print_sockaddr ( & pm_msg - > mapped_rem_addr ,
" query_mapping: Mapped remote sockaddr: " ) ;
query_mapping_response_exit :
nlmsg_request - > request_done = 1 ;
/* always for found request */
kref_put ( & nlmsg_request - > kref , iwpm_free_nlmsg_request ) ;
barrier ( ) ;
2016-02-26 09:18:05 -06:00
up ( & nlmsg_request - > sem ) ;
2014-03-26 17:07:35 -05:00
return 0 ;
}
2019-02-05 11:33:22 -08:00
/**
* iwpm_remote_info_cb - Process remote connecting peer address info , which
* the port mapper has received from the connecting peer
2021-01-18 22:39:29 +00:00
* @ skb : The socket buffer
2019-02-05 11:33:22 -08:00
* @ cb : Contains the received message ( payload and netlink header )
*
* Stores the IPv4 / IPv6 address info in a hash table
2015-04-21 16:28:10 -04:00
*/
int iwpm_remote_info_cb ( struct sk_buff * skb , struct netlink_callback * cb )
{
struct nlattr * nltb [ IWPM_NLA_RQUERY_MAPPING_MAX ] ;
struct sockaddr_storage * local_sockaddr , * remote_sockaddr ;
struct sockaddr_storage * mapped_loc_sockaddr , * mapped_rem_sockaddr ;
struct iwpm_remote_info * rem_info ;
const char * msg_type ;
u8 nl_client ;
int ret = - EINVAL ;
msg_type = " Remote Mapping info " ;
if ( iwpm_parse_nlmsg ( cb , IWPM_NLA_RQUERY_MAPPING_MAX ,
resp_query_policy , nltb , msg_type ) )
return ret ;
nl_client = RDMA_NL_GET_CLIENT ( cb - > nlh - > nlmsg_type ) ;
atomic_set ( & echo_nlmsg_seq , cb - > nlh - > nlmsg_seq ) ;
local_sockaddr = ( struct sockaddr_storage * )
2019-01-29 13:33:11 -08:00
nla_data ( nltb [ IWPM_NLA_RQUERY_LOCAL_ADDR ] ) ;
2015-04-21 16:28:10 -04:00
remote_sockaddr = ( struct sockaddr_storage * )
2019-01-29 13:33:11 -08:00
nla_data ( nltb [ IWPM_NLA_RQUERY_REMOTE_ADDR ] ) ;
2015-04-21 16:28:10 -04:00
mapped_loc_sockaddr = ( struct sockaddr_storage * )
nla_data ( nltb [ IWPM_NLA_RQUERY_MAPPED_LOC_ADDR ] ) ;
mapped_rem_sockaddr = ( struct sockaddr_storage * )
nla_data ( nltb [ IWPM_NLA_RQUERY_MAPPED_REM_ADDR ] ) ;
if ( mapped_loc_sockaddr - > ss_family ! = local_sockaddr - > ss_family | |
mapped_rem_sockaddr - > ss_family ! = remote_sockaddr - > ss_family ) {
pr_info ( " %s: Sockaddr family doesn't match the requested one \n " ,
__func__ ) ;
return ret ;
}
rem_info = kzalloc ( sizeof ( struct iwpm_remote_info ) , GFP_ATOMIC ) ;
if ( ! rem_info ) {
ret = - ENOMEM ;
return ret ;
}
memcpy ( & rem_info - > mapped_loc_sockaddr , mapped_loc_sockaddr ,
sizeof ( struct sockaddr_storage ) ) ;
memcpy ( & rem_info - > remote_sockaddr , remote_sockaddr ,
sizeof ( struct sockaddr_storage ) ) ;
memcpy ( & rem_info - > mapped_rem_sockaddr , mapped_rem_sockaddr ,
sizeof ( struct sockaddr_storage ) ) ;
rem_info - > nl_client = nl_client ;
iwpm_add_remote_info ( rem_info ) ;
iwpm_print_sockaddr ( local_sockaddr ,
" remote_info: Local sockaddr: " ) ;
iwpm_print_sockaddr ( mapped_loc_sockaddr ,
" remote_info: Mapped local sockaddr: " ) ;
iwpm_print_sockaddr ( remote_sockaddr ,
" remote_info: Remote sockaddr: " ) ;
iwpm_print_sockaddr ( mapped_rem_sockaddr ,
" remote_info: Mapped remote sockaddr: " ) ;
return ret ;
}
2014-03-26 17:07:35 -05:00
/* netlink attribute policy for the received request for mapping info */
static const struct nla_policy resp_mapinfo_policy [ IWPM_NLA_MAPINFO_REQ_MAX ] = {
[ IWPM_NLA_MAPINFO_ULIB_NAME ] = { . type = NLA_STRING ,
. len = IWPM_ULIBNAME_SIZE - 1 } ,
[ IWPM_NLA_MAPINFO_ULIB_VER ] = { . type = NLA_U16 }
} ;
2019-02-05 11:33:22 -08:00
/**
* iwpm_mapping_info_cb - Process a notification that the userspace
* port mapper daemon is started
2021-01-18 22:39:29 +00:00
* @ skb : The socket buffer
2019-02-05 11:33:22 -08:00
* @ cb : Contains the received message ( payload and netlink header )
*
* Using the received port mapper pid , send all the local mapping
* info records to the userspace port mapper
2014-03-26 17:07:35 -05:00
*/
int iwpm_mapping_info_cb ( struct sk_buff * skb , struct netlink_callback * cb )
{
struct nlattr * nltb [ IWPM_NLA_MAPINFO_REQ_MAX ] ;
const char * msg_type = " Mapping Info response " ;
u8 nl_client ;
char * iwpm_name ;
u16 iwpm_version ;
int ret = - EINVAL ;
if ( iwpm_parse_nlmsg ( cb , IWPM_NLA_MAPINFO_REQ_MAX ,
resp_mapinfo_policy , nltb , msg_type ) ) {
pr_info ( " %s: Unable to parse nlmsg \n " , __func__ ) ;
return ret ;
}
iwpm_name = ( char * ) nla_data ( nltb [ IWPM_NLA_MAPINFO_ULIB_NAME ] ) ;
iwpm_version = nla_get_u16 ( nltb [ IWPM_NLA_MAPINFO_ULIB_VER ] ) ;
if ( strcmp ( iwpm_ulib_name , iwpm_name ) | |
2019-01-29 13:33:16 -08:00
iwpm_version < IWPM_UABI_VERSION_MIN ) {
2021-06-10 19:40:32 +08:00
pr_info ( " %s: Invalid port mapper name = %s version = %u \n " ,
2014-03-26 17:07:35 -05:00
__func__ , iwpm_name , iwpm_version ) ;
return ret ;
}
nl_client = RDMA_NL_GET_CLIENT ( cb - > nlh - > nlmsg_type ) ;
2015-07-02 12:47:44 -05:00
iwpm_set_registration ( nl_client , IWPM_REG_INCOMPL ) ;
2014-03-26 17:07:35 -05:00
atomic_set ( & echo_nlmsg_seq , cb - > nlh - > nlmsg_seq ) ;
2015-07-02 12:47:44 -05:00
iwpm_user_pid = cb - > nlh - > nlmsg_pid ;
2019-01-29 13:33:16 -08:00
if ( iwpm_ulib_version < IWPM_UABI_VERSION )
2021-06-10 19:40:32 +08:00
pr_warn_once ( " %s: Down level iwpmd/pid %d. Continuing... " ,
2019-01-29 13:33:16 -08:00
__func__ , iwpm_user_pid ) ;
2014-03-26 17:07:35 -05:00
if ( ! iwpm_mapinfo_available ( ) )
return 0 ;
pr_debug ( " %s: iWarp Port Mapper (pid = %d) is available! \n " ,
2015-07-02 12:47:44 -05:00
__func__ , iwpm_user_pid ) ;
ret = iwpm_send_mapinfo ( nl_client , iwpm_user_pid ) ;
2014-03-26 17:07:35 -05:00
return ret ;
}
/* netlink attribute policy for the received mapping info ack */
static const struct nla_policy ack_mapinfo_policy [ IWPM_NLA_MAPINFO_NUM_MAX ] = {
[ IWPM_NLA_MAPINFO_SEQ ] = { . type = NLA_U32 } ,
[ IWPM_NLA_MAPINFO_SEND_NUM ] = { . type = NLA_U32 } ,
[ IWPM_NLA_MAPINFO_ACK_NUM ] = { . type = NLA_U32 }
} ;
2019-02-05 11:33:22 -08:00
/**
* iwpm_ack_mapping_info_cb - Process the port mapper ack for
* the provided local mapping info records
2021-01-18 22:39:29 +00:00
* @ skb : The socket buffer
2019-02-05 11:33:22 -08:00
* @ cb : Contains the received message ( payload and netlink header )
2014-03-26 17:07:35 -05:00
*/
int iwpm_ack_mapping_info_cb ( struct sk_buff * skb , struct netlink_callback * cb )
{
struct nlattr * nltb [ IWPM_NLA_MAPINFO_NUM_MAX ] ;
u32 mapinfo_send , mapinfo_ack ;
const char * msg_type = " Mapping Info Ack " ;
if ( iwpm_parse_nlmsg ( cb , IWPM_NLA_MAPINFO_NUM_MAX ,
ack_mapinfo_policy , nltb , msg_type ) )
return - EINVAL ;
mapinfo_send = nla_get_u32 ( nltb [ IWPM_NLA_MAPINFO_SEND_NUM ] ) ;
mapinfo_ack = nla_get_u32 ( nltb [ IWPM_NLA_MAPINFO_ACK_NUM ] ) ;
if ( mapinfo_ack ! = mapinfo_send )
pr_info ( " %s: Invalid mapinfo number (sent = %u ack-ed = %u) \n " ,
__func__ , mapinfo_send , mapinfo_ack ) ;
atomic_set ( & echo_nlmsg_seq , cb - > nlh - > nlmsg_seq ) ;
return 0 ;
}
/* netlink attribute policy for the received port mapper error message */
static const struct nla_policy map_error_policy [ IWPM_NLA_ERR_MAX ] = {
[ IWPM_NLA_ERR_SEQ ] = { . type = NLA_U32 } ,
[ IWPM_NLA_ERR_CODE ] = { . type = NLA_U16 } ,
} ;
2019-02-05 11:33:22 -08:00
/**
* iwpm_mapping_error_cb - Process port mapper notification for error
*
2021-01-18 22:39:29 +00:00
* @ skb : The socket buffer
2019-02-05 11:33:22 -08:00
* @ cb : Contains the received message ( payload and netlink header )
2014-03-26 17:07:35 -05:00
*/
int iwpm_mapping_error_cb ( struct sk_buff * skb , struct netlink_callback * cb )
{
struct iwpm_nlmsg_request * nlmsg_request = NULL ;
int nl_client = RDMA_NL_GET_CLIENT ( cb - > nlh - > nlmsg_type ) ;
struct nlattr * nltb [ IWPM_NLA_ERR_MAX ] ;
u32 msg_seq ;
u16 err_code ;
const char * msg_type = " Mapping Error Msg " ;
if ( iwpm_parse_nlmsg ( cb , IWPM_NLA_ERR_MAX ,
map_error_policy , nltb , msg_type ) )
return - EINVAL ;
msg_seq = nla_get_u32 ( nltb [ IWPM_NLA_ERR_SEQ ] ) ;
err_code = nla_get_u16 ( nltb [ IWPM_NLA_ERR_CODE ] ) ;
pr_info ( " %s: Received msg seq = %u err code = %u client = %d \n " ,
__func__ , msg_seq , err_code , nl_client ) ;
/* look for nlmsg_request */
nlmsg_request = iwpm_find_nlmsg_request ( msg_seq ) ;
if ( ! nlmsg_request ) {
/* not all errors have associated requests */
pr_debug ( " Could not find matching req (seq = %u) \n " , msg_seq ) ;
return 0 ;
}
atomic_set ( & echo_nlmsg_seq , cb - > nlh - > nlmsg_seq ) ;
nlmsg_request - > err_code = err_code ;
nlmsg_request - > request_done = 1 ;
/* always for found request */
kref_put ( & nlmsg_request - > kref , iwpm_free_nlmsg_request ) ;
barrier ( ) ;
2016-02-26 09:18:05 -06:00
up ( & nlmsg_request - > sem ) ;
2014-03-26 17:07:35 -05:00
return 0 ;
}
2019-01-29 13:33:16 -08:00
/* netlink attribute policy for the received hello request */
static const struct nla_policy hello_policy [ IWPM_NLA_HELLO_MAX ] = {
[ IWPM_NLA_HELLO_ABI_VERSION ] = { . type = NLA_U16 }
} ;
2019-02-05 11:33:22 -08:00
/**
* iwpm_hello_cb - Process a hello message from iwpmd
*
2021-01-18 22:39:29 +00:00
* @ skb : The socket buffer
2019-02-05 11:33:22 -08:00
* @ cb : Contains the received message ( payload and netlink header )
*
* Using the received port mapper pid , send the kernel ' s abi_version
* after adjusting it to support the iwpmd version .
2019-01-29 13:33:16 -08:00
*/
int iwpm_hello_cb ( struct sk_buff * skb , struct netlink_callback * cb )
{
struct nlattr * nltb [ IWPM_NLA_HELLO_MAX ] ;
const char * msg_type = " Hello request " ;
u8 nl_client ;
u16 abi_version ;
int ret = - EINVAL ;
if ( iwpm_parse_nlmsg ( cb , IWPM_NLA_HELLO_MAX , hello_policy , nltb ,
msg_type ) ) {
pr_info ( " %s: Unable to parse nlmsg \n " , __func__ ) ;
return ret ;
}
abi_version = nla_get_u16 ( nltb [ IWPM_NLA_HELLO_ABI_VERSION ] ) ;
nl_client = RDMA_NL_GET_CLIENT ( cb - > nlh - > nlmsg_type ) ;
iwpm_set_registration ( nl_client , IWPM_REG_INCOMPL ) ;
atomic_set ( & echo_nlmsg_seq , cb - > nlh - > nlmsg_seq ) ;
iwpm_ulib_version = min_t ( u16 , IWPM_UABI_VERSION , abi_version ) ;
pr_debug ( " Using ABI version %u \n " , iwpm_ulib_version ) ;
iwpm_user_pid = cb - > nlh - > nlmsg_pid ;
ret = iwpm_send_hello ( nl_client , iwpm_user_pid , iwpm_ulib_version ) ;
return ret ;
}