cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

iwpm_msg.c (28672B)


      1/*
      2 * Copyright (c) 2014 Intel Corporation. All rights reserved.
      3 * Copyright (c) 2014 Chelsio, Inc. All rights reserved.
      4 *
      5 * This software is available to you under a choice of one of two
      6 * licenses.  You may choose to be licensed under the terms of the GNU
      7 * General Public License (GPL) Version 2, available from the file
      8 * COPYING in the main directory of this source tree, or the
      9 * OpenIB.org BSD license below:
     10 *
     11 *     Redistribution and use in source and binary forms, with or
     12 *     without modification, are permitted provided that the following
     13 *     conditions are met:
     14 *
     15 *      - Redistributions of source code must retain the above
     16 *        copyright notice, this list of conditions and the following
     17 *        disclaimer.
     18 *
     19 *      - Redistributions in binary form must reproduce the above
     20 *        copyright notice, this list of conditions and the following
     21 *        disclaimer in the documentation and/or other materials
     22 *        provided with the distribution.
     23 *
     24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
     28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
     29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     31 * SOFTWARE.
     32 */
     33
     34#include "iwpm_util.h"
     35
     36static const char iwpm_ulib_name[IWPM_ULIBNAME_SIZE] = "iWarpPortMapperUser";
     37u16 iwpm_ulib_version = IWPM_UABI_VERSION_MIN;
     38static int iwpm_user_pid = IWPM_PID_UNDEFINED;
     39static atomic_t echo_nlmsg_seq;
     40
     41/**
     42 * iwpm_valid_pid - Check if the userspace iwarp port mapper pid is valid
     43 *
     44 * Returns true if the pid is greater than zero, otherwise returns false
     45 */
     46int iwpm_valid_pid(void)
     47{
     48	return iwpm_user_pid > 0;
     49}
     50
     51/**
     52 * iwpm_register_pid - Send a netlink query to userspace
     53 *                     to get the iwarp port mapper pid
     54 * @pm_msg: Contains driver info to send to the userspace port mapper
     55 * @nl_client: The index of the netlink client
     56 *
     57 * nlmsg attributes:
     58 *	[IWPM_NLA_REG_PID_SEQ]
     59 *	[IWPM_NLA_REG_IF_NAME]
     60 *	[IWPM_NLA_REG_IBDEV_NAME]
     61 *	[IWPM_NLA_REG_ULIB_NAME]
     62 */
     63int iwpm_register_pid(struct iwpm_dev_data *pm_msg, u8 nl_client)
     64{
     65	struct sk_buff *skb = NULL;
     66	struct iwpm_nlmsg_request *nlmsg_request = NULL;
     67	struct nlmsghdr *nlh;
     68	u32 msg_seq;
     69	const char *err_str = "";
     70	int ret = -EINVAL;
     71
     72	if (iwpm_check_registration(nl_client, IWPM_REG_VALID) ||
     73			iwpm_user_pid == IWPM_PID_UNAVAILABLE)
     74		return 0;
     75	skb = iwpm_create_nlmsg(RDMA_NL_IWPM_REG_PID, &nlh, nl_client);
     76	if (!skb) {
     77		err_str = "Unable to create a nlmsg";
     78		goto pid_query_error;
     79	}
     80	nlh->nlmsg_seq = iwpm_get_nlmsg_seq();
     81	nlmsg_request = iwpm_get_nlmsg_request(nlh->nlmsg_seq, nl_client, GFP_KERNEL);
     82	if (!nlmsg_request) {
     83		err_str = "Unable to allocate netlink request";
     84		goto pid_query_error;
     85	}
     86	msg_seq = atomic_read(&echo_nlmsg_seq);
     87
     88	/* fill in the pid request message */
     89	err_str = "Unable to put attribute of the nlmsg";
     90	ret = ibnl_put_attr(skb, nlh, sizeof(u32), &msg_seq, IWPM_NLA_REG_PID_SEQ);
     91	if (ret)
     92		goto pid_query_error;
     93	ret = ibnl_put_attr(skb, nlh, IFNAMSIZ,
     94			    pm_msg->if_name, IWPM_NLA_REG_IF_NAME);
     95	if (ret)
     96		goto pid_query_error;
     97	ret = ibnl_put_attr(skb, nlh, IWPM_DEVNAME_SIZE,
     98				pm_msg->dev_name, IWPM_NLA_REG_IBDEV_NAME);
     99	if (ret)
    100		goto pid_query_error;
    101	ret = ibnl_put_attr(skb, nlh, IWPM_ULIBNAME_SIZE,
    102				(char *)iwpm_ulib_name, IWPM_NLA_REG_ULIB_NAME);
    103	if (ret)
    104		goto pid_query_error;
    105
    106	nlmsg_end(skb, nlh);
    107
    108	pr_debug("%s: Multicasting a nlmsg (dev = %s ifname = %s iwpm = %s)\n",
    109		__func__, pm_msg->dev_name, pm_msg->if_name, iwpm_ulib_name);
    110
    111	ret = rdma_nl_multicast(&init_net, skb, RDMA_NL_GROUP_IWPM, GFP_KERNEL);
    112	if (ret) {
    113		skb = NULL; /* skb is freed in the netlink send-op handling */
    114		iwpm_user_pid = IWPM_PID_UNAVAILABLE;
    115		err_str = "Unable to send a nlmsg";
    116		goto pid_query_error;
    117	}
    118	nlmsg_request->req_buffer = pm_msg;
    119	ret = iwpm_wait_complete_req(nlmsg_request);
    120	return ret;
    121pid_query_error:
    122	pr_info("%s: %s (client = %u)\n", __func__, err_str, nl_client);
    123	dev_kfree_skb(skb);
    124	if (nlmsg_request)
    125		iwpm_free_nlmsg_request(&nlmsg_request->kref);
    126	return ret;
    127}
    128
    129/**
    130 * iwpm_add_mapping - Send a netlink add mapping request to
    131 *                    the userspace port mapper
    132 * @pm_msg: Contains the local ip/tcp address info to send
    133 * @nl_client: The index of the netlink client
    134 *
    135 * nlmsg attributes:
    136 *	[IWPM_NLA_MANAGE_MAPPING_SEQ]
    137 *	[IWPM_NLA_MANAGE_ADDR]
    138 *	[IWPM_NLA_MANAGE_FLAGS]
    139 *
    140 * If the request is successful, the pm_msg stores
    141 * the port mapper response (mapped address info)
    142 */
    143int iwpm_add_mapping(struct iwpm_sa_data *pm_msg, u8 nl_client)
    144{
    145	struct sk_buff *skb = NULL;
    146	struct iwpm_nlmsg_request *nlmsg_request = NULL;
    147	struct nlmsghdr *nlh;
    148	u32 msg_seq;
    149	const char *err_str = "";
    150	int ret = -EINVAL;
    151
    152	if (!iwpm_valid_pid())
    153		return 0;
    154	if (!iwpm_check_registration(nl_client, IWPM_REG_VALID)) {
    155		err_str = "Unregistered port mapper client";
    156		goto add_mapping_error;
    157	}
    158	skb = iwpm_create_nlmsg(RDMA_NL_IWPM_ADD_MAPPING, &nlh, nl_client);
    159	if (!skb) {
    160		err_str = "Unable to create a nlmsg";
    161		goto add_mapping_error;
    162	}
    163	nlh->nlmsg_seq = iwpm_get_nlmsg_seq();
    164	nlmsg_request = iwpm_get_nlmsg_request(nlh->nlmsg_seq, nl_client, GFP_KERNEL);
    165	if (!nlmsg_request) {
    166		err_str = "Unable to allocate netlink request";
    167		goto add_mapping_error;
    168	}
    169	msg_seq = atomic_read(&echo_nlmsg_seq);
    170	/* fill in the add mapping message */
    171	err_str = "Unable to put attribute of the nlmsg";
    172	ret = ibnl_put_attr(skb, nlh, sizeof(u32), &msg_seq,
    173				IWPM_NLA_MANAGE_MAPPING_SEQ);
    174	if (ret)
    175		goto add_mapping_error;
    176	ret = ibnl_put_attr(skb, nlh, sizeof(struct sockaddr_storage),
    177				&pm_msg->loc_addr, IWPM_NLA_MANAGE_ADDR);
    178	if (ret)
    179		goto add_mapping_error;
    180
    181	/* If flags are required and we're not V4, then return a quiet error */
    182	if (pm_msg->flags && iwpm_ulib_version == IWPM_UABI_VERSION_MIN) {
    183		ret = -EINVAL;
    184		goto add_mapping_error_nowarn;
    185	}
    186	if (iwpm_ulib_version > IWPM_UABI_VERSION_MIN) {
    187		ret = ibnl_put_attr(skb, nlh, sizeof(u32), &pm_msg->flags,
    188				IWPM_NLA_MANAGE_FLAGS);
    189		if (ret)
    190			goto add_mapping_error;
    191	}
    192
    193	nlmsg_end(skb, nlh);
    194	nlmsg_request->req_buffer = pm_msg;
    195
    196	ret = rdma_nl_unicast_wait(&init_net, skb, iwpm_user_pid);
    197	if (ret) {
    198		skb = NULL; /* skb is freed in the netlink send-op handling */
    199		iwpm_user_pid = IWPM_PID_UNDEFINED;
    200		err_str = "Unable to send a nlmsg";
    201		goto add_mapping_error;
    202	}
    203	ret = iwpm_wait_complete_req(nlmsg_request);
    204	return ret;
    205add_mapping_error:
    206	pr_info("%s: %s (client = %u)\n", __func__, err_str, nl_client);
    207add_mapping_error_nowarn:
    208	dev_kfree_skb(skb);
    209	if (nlmsg_request)
    210		iwpm_free_nlmsg_request(&nlmsg_request->kref);
    211	return ret;
    212}
    213
    214/**
    215 * iwpm_add_and_query_mapping - Process the port mapper response to
    216 *                              iwpm_add_and_query_mapping request
    217 * @pm_msg: Contains the local ip/tcp address info to send
    218 * @nl_client: The index of the netlink client
    219 *
    220 * nlmsg attributes:
    221 *	[IWPM_NLA_QUERY_MAPPING_SEQ]
    222 *	[IWPM_NLA_QUERY_LOCAL_ADDR]
    223 *	[IWPM_NLA_QUERY_REMOTE_ADDR]
    224 *	[IWPM_NLA_QUERY_FLAGS]
    225 */
    226int iwpm_add_and_query_mapping(struct iwpm_sa_data *pm_msg, u8 nl_client)
    227{
    228	struct sk_buff *skb = NULL;
    229	struct iwpm_nlmsg_request *nlmsg_request = NULL;
    230	struct nlmsghdr *nlh;
    231	u32 msg_seq;
    232	const char *err_str = "";
    233	int ret = -EINVAL;
    234
    235	if (!iwpm_valid_pid())
    236		return 0;
    237	if (!iwpm_check_registration(nl_client, IWPM_REG_VALID)) {
    238		err_str = "Unregistered port mapper client";
    239		goto query_mapping_error;
    240	}
    241	ret = -ENOMEM;
    242	skb = iwpm_create_nlmsg(RDMA_NL_IWPM_QUERY_MAPPING, &nlh, nl_client);
    243	if (!skb) {
    244		err_str = "Unable to create a nlmsg";
    245		goto query_mapping_error;
    246	}
    247	nlh->nlmsg_seq = iwpm_get_nlmsg_seq();
    248	nlmsg_request = iwpm_get_nlmsg_request(nlh->nlmsg_seq,
    249				nl_client, GFP_KERNEL);
    250	if (!nlmsg_request) {
    251		err_str = "Unable to allocate netlink request";
    252		goto query_mapping_error;
    253	}
    254	msg_seq = atomic_read(&echo_nlmsg_seq);
    255
    256	/* fill in the query message */
    257	err_str = "Unable to put attribute of the nlmsg";
    258	ret = ibnl_put_attr(skb, nlh, sizeof(u32), &msg_seq,
    259				IWPM_NLA_QUERY_MAPPING_SEQ);
    260	if (ret)
    261		goto query_mapping_error;
    262	ret = ibnl_put_attr(skb, nlh, sizeof(struct sockaddr_storage),
    263				&pm_msg->loc_addr, IWPM_NLA_QUERY_LOCAL_ADDR);
    264	if (ret)
    265		goto query_mapping_error;
    266	ret = ibnl_put_attr(skb, nlh, sizeof(struct sockaddr_storage),
    267				&pm_msg->rem_addr, IWPM_NLA_QUERY_REMOTE_ADDR);
    268	if (ret)
    269		goto query_mapping_error;
    270
    271	/* If flags are required and we're not V4, then return a quite error */
    272	if (pm_msg->flags && iwpm_ulib_version == IWPM_UABI_VERSION_MIN) {
    273		ret = -EINVAL;
    274		goto query_mapping_error_nowarn;
    275	}
    276	if (iwpm_ulib_version > IWPM_UABI_VERSION_MIN) {
    277		ret = ibnl_put_attr(skb, nlh, sizeof(u32), &pm_msg->flags,
    278				IWPM_NLA_QUERY_FLAGS);
    279		if (ret)
    280			goto query_mapping_error;
    281	}
    282
    283	nlmsg_end(skb, nlh);
    284	nlmsg_request->req_buffer = pm_msg;
    285
    286	ret = rdma_nl_unicast_wait(&init_net, skb, iwpm_user_pid);
    287	if (ret) {
    288		skb = NULL; /* skb is freed in the netlink send-op handling */
    289		err_str = "Unable to send a nlmsg";
    290		goto query_mapping_error;
    291	}
    292	ret = iwpm_wait_complete_req(nlmsg_request);
    293	return ret;
    294query_mapping_error:
    295	pr_info("%s: %s (client = %u)\n", __func__, err_str, nl_client);
    296query_mapping_error_nowarn:
    297	dev_kfree_skb(skb);
    298	if (nlmsg_request)
    299		iwpm_free_nlmsg_request(&nlmsg_request->kref);
    300	return ret;
    301}
    302
    303/**
    304 * iwpm_remove_mapping - Send a netlink remove mapping request
    305 *                       to the userspace port mapper
    306 *
    307 * @local_addr: Local ip/tcp address to remove
    308 * @nl_client: The index of the netlink client
    309 *
    310 * nlmsg attributes:
    311 *	[IWPM_NLA_MANAGE_MAPPING_SEQ]
    312 *	[IWPM_NLA_MANAGE_ADDR]
    313 */
    314int iwpm_remove_mapping(struct sockaddr_storage *local_addr, u8 nl_client)
    315{
    316	struct sk_buff *skb = NULL;
    317	struct nlmsghdr *nlh;
    318	u32 msg_seq;
    319	const char *err_str = "";
    320	int ret = -EINVAL;
    321
    322	if (!iwpm_valid_pid())
    323		return 0;
    324	if (iwpm_check_registration(nl_client, IWPM_REG_UNDEF)) {
    325		err_str = "Unregistered port mapper client";
    326		goto remove_mapping_error;
    327	}
    328	skb = iwpm_create_nlmsg(RDMA_NL_IWPM_REMOVE_MAPPING, &nlh, nl_client);
    329	if (!skb) {
    330		ret = -ENOMEM;
    331		err_str = "Unable to create a nlmsg";
    332		goto remove_mapping_error;
    333	}
    334	msg_seq = atomic_read(&echo_nlmsg_seq);
    335	nlh->nlmsg_seq = iwpm_get_nlmsg_seq();
    336	err_str = "Unable to put attribute of the nlmsg";
    337	ret = ibnl_put_attr(skb, nlh, sizeof(u32), &msg_seq,
    338				IWPM_NLA_MANAGE_MAPPING_SEQ);
    339	if (ret)
    340		goto remove_mapping_error;
    341	ret = ibnl_put_attr(skb, nlh, sizeof(struct sockaddr_storage),
    342				local_addr, IWPM_NLA_MANAGE_ADDR);
    343	if (ret)
    344		goto remove_mapping_error;
    345
    346	nlmsg_end(skb, nlh);
    347
    348	ret = rdma_nl_unicast_wait(&init_net, skb, iwpm_user_pid);
    349	if (ret) {
    350		skb = NULL; /* skb is freed in the netlink send-op handling */
    351		iwpm_user_pid = IWPM_PID_UNDEFINED;
    352		err_str = "Unable to send a nlmsg";
    353		goto remove_mapping_error;
    354	}
    355	iwpm_print_sockaddr(local_addr,
    356			"remove_mapping: Local sockaddr:");
    357	return 0;
    358remove_mapping_error:
    359	pr_info("%s: %s (client = %u)\n", __func__, err_str, nl_client);
    360	if (skb)
    361		dev_kfree_skb_any(skb);
    362	return ret;
    363}
    364
    365/* netlink attribute policy for the received response to register pid request */
    366static const struct nla_policy resp_reg_policy[IWPM_NLA_RREG_PID_MAX] = {
    367	[IWPM_NLA_RREG_PID_SEQ]     = { .type = NLA_U32 },
    368	[IWPM_NLA_RREG_IBDEV_NAME]  = { .type = NLA_STRING,
    369					.len = IWPM_DEVNAME_SIZE - 1 },
    370	[IWPM_NLA_RREG_ULIB_NAME]   = { .type = NLA_STRING,
    371					.len = IWPM_ULIBNAME_SIZE - 1 },
    372	[IWPM_NLA_RREG_ULIB_VER]    = { .type = NLA_U16 },
    373	[IWPM_NLA_RREG_PID_ERR]     = { .type = NLA_U16 }
    374};
    375
    376/**
    377 * iwpm_register_pid_cb - Process the port mapper response to
    378 *                        iwpm_register_pid query
    379 * @skb: The socket buffer
    380 * @cb: Contains the received message (payload and netlink header)
    381 *
    382 * If successful, the function receives the userspace port mapper pid
    383 * which is used in future communication with the port mapper
    384 */
    385int iwpm_register_pid_cb(struct sk_buff *skb, struct netlink_callback *cb)
    386{
    387	struct iwpm_nlmsg_request *nlmsg_request = NULL;
    388	struct nlattr *nltb[IWPM_NLA_RREG_PID_MAX];
    389	struct iwpm_dev_data *pm_msg;
    390	char *dev_name, *iwpm_name;
    391	u32 msg_seq;
    392	u8 nl_client;
    393	u16 iwpm_version;
    394	const char *msg_type = "Register Pid response";
    395
    396	if (iwpm_parse_nlmsg(cb, IWPM_NLA_RREG_PID_MAX,
    397				resp_reg_policy, nltb, msg_type))
    398		return -EINVAL;
    399
    400	msg_seq = nla_get_u32(nltb[IWPM_NLA_RREG_PID_SEQ]);
    401	nlmsg_request = iwpm_find_nlmsg_request(msg_seq);
    402	if (!nlmsg_request) {
    403		pr_info("%s: Could not find a matching request (seq = %u)\n",
    404				 __func__, msg_seq);
    405		return -EINVAL;
    406	}
    407	pm_msg = nlmsg_request->req_buffer;
    408	nl_client = nlmsg_request->nl_client;
    409	dev_name = (char *)nla_data(nltb[IWPM_NLA_RREG_IBDEV_NAME]);
    410	iwpm_name = (char *)nla_data(nltb[IWPM_NLA_RREG_ULIB_NAME]);
    411	iwpm_version = nla_get_u16(nltb[IWPM_NLA_RREG_ULIB_VER]);
    412
    413	/* check device name, ulib name and version */
    414	if (strcmp(pm_msg->dev_name, dev_name) ||
    415			strcmp(iwpm_ulib_name, iwpm_name) ||
    416			iwpm_version < IWPM_UABI_VERSION_MIN) {
    417
    418		pr_info("%s: Incorrect info (dev = %s name = %s version = %u)\n",
    419				__func__, dev_name, iwpm_name, iwpm_version);
    420		nlmsg_request->err_code = IWPM_USER_LIB_INFO_ERR;
    421		goto register_pid_response_exit;
    422	}
    423	iwpm_user_pid = cb->nlh->nlmsg_pid;
    424	iwpm_ulib_version = iwpm_version;
    425	if (iwpm_ulib_version < IWPM_UABI_VERSION)
    426		pr_warn_once("%s: Down level iwpmd/pid %d.  Continuing...",
    427			__func__, iwpm_user_pid);
    428	atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
    429	pr_debug("%s: iWarp Port Mapper (pid = %d) is available!\n",
    430			__func__, iwpm_user_pid);
    431	iwpm_set_registration(nl_client, IWPM_REG_VALID);
    432register_pid_response_exit:
    433	nlmsg_request->request_done = 1;
    434	/* always for found nlmsg_request */
    435	kref_put(&nlmsg_request->kref, iwpm_free_nlmsg_request);
    436	barrier();
    437	up(&nlmsg_request->sem);
    438	return 0;
    439}
    440
    441/* netlink attribute policy for the received response to add mapping request */
    442static const struct nla_policy resp_add_policy[IWPM_NLA_RMANAGE_MAPPING_MAX] = {
    443	[IWPM_NLA_RMANAGE_MAPPING_SEQ]     = { .type = NLA_U32 },
    444	[IWPM_NLA_RMANAGE_ADDR]            = {
    445				.len = sizeof(struct sockaddr_storage) },
    446	[IWPM_NLA_RMANAGE_MAPPED_LOC_ADDR] = {
    447				.len = sizeof(struct sockaddr_storage) },
    448	[IWPM_NLA_RMANAGE_MAPPING_ERR]	   = { .type = NLA_U16 }
    449};
    450
    451/**
    452 * iwpm_add_mapping_cb - Process the port mapper response to
    453 *                       iwpm_add_mapping request
    454 * @skb: The socket buffer
    455 * @cb: Contains the received message (payload and netlink header)
    456 */
    457int iwpm_add_mapping_cb(struct sk_buff *skb, struct netlink_callback *cb)
    458{
    459	struct iwpm_sa_data *pm_msg;
    460	struct iwpm_nlmsg_request *nlmsg_request = NULL;
    461	struct nlattr *nltb[IWPM_NLA_RMANAGE_MAPPING_MAX];
    462	struct sockaddr_storage *local_sockaddr;
    463	struct sockaddr_storage *mapped_sockaddr;
    464	const char *msg_type;
    465	u32 msg_seq;
    466
    467	msg_type = "Add Mapping response";
    468	if (iwpm_parse_nlmsg(cb, IWPM_NLA_RMANAGE_MAPPING_MAX,
    469				resp_add_policy, nltb, msg_type))
    470		return -EINVAL;
    471
    472	atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
    473
    474	msg_seq = nla_get_u32(nltb[IWPM_NLA_RMANAGE_MAPPING_SEQ]);
    475	nlmsg_request = iwpm_find_nlmsg_request(msg_seq);
    476	if (!nlmsg_request) {
    477		pr_info("%s: Could not find a matching request (seq = %u)\n",
    478				 __func__, msg_seq);
    479		return -EINVAL;
    480	}
    481	pm_msg = nlmsg_request->req_buffer;
    482	local_sockaddr = (struct sockaddr_storage *)
    483			nla_data(nltb[IWPM_NLA_RMANAGE_ADDR]);
    484	mapped_sockaddr = (struct sockaddr_storage *)
    485			nla_data(nltb[IWPM_NLA_RMANAGE_MAPPED_LOC_ADDR]);
    486
    487	if (iwpm_compare_sockaddr(local_sockaddr, &pm_msg->loc_addr)) {
    488		nlmsg_request->err_code = IWPM_USER_LIB_INFO_ERR;
    489		goto add_mapping_response_exit;
    490	}
    491	if (mapped_sockaddr->ss_family != local_sockaddr->ss_family) {
    492		pr_info("%s: Sockaddr family doesn't match the requested one\n",
    493				__func__);
    494		nlmsg_request->err_code = IWPM_USER_LIB_INFO_ERR;
    495		goto add_mapping_response_exit;
    496	}
    497	memcpy(&pm_msg->mapped_loc_addr, mapped_sockaddr,
    498			sizeof(*mapped_sockaddr));
    499	iwpm_print_sockaddr(&pm_msg->loc_addr,
    500			"add_mapping: Local sockaddr:");
    501	iwpm_print_sockaddr(&pm_msg->mapped_loc_addr,
    502			"add_mapping: Mapped local sockaddr:");
    503
    504add_mapping_response_exit:
    505	nlmsg_request->request_done = 1;
    506	/* always for found request */
    507	kref_put(&nlmsg_request->kref, iwpm_free_nlmsg_request);
    508	barrier();
    509	up(&nlmsg_request->sem);
    510	return 0;
    511}
    512
    513/* netlink attribute policy for the response to add and query mapping request
    514 * and response with remote address info
    515 */
    516static const struct nla_policy resp_query_policy[IWPM_NLA_RQUERY_MAPPING_MAX] = {
    517	[IWPM_NLA_RQUERY_MAPPING_SEQ]     = { .type = NLA_U32 },
    518	[IWPM_NLA_RQUERY_LOCAL_ADDR]      = {
    519				.len = sizeof(struct sockaddr_storage) },
    520	[IWPM_NLA_RQUERY_REMOTE_ADDR]     = {
    521				.len = sizeof(struct sockaddr_storage) },
    522	[IWPM_NLA_RQUERY_MAPPED_LOC_ADDR] = {
    523				.len = sizeof(struct sockaddr_storage) },
    524	[IWPM_NLA_RQUERY_MAPPED_REM_ADDR] = {
    525				.len = sizeof(struct sockaddr_storage) },
    526	[IWPM_NLA_RQUERY_MAPPING_ERR]	  = { .type = NLA_U16 }
    527};
    528
    529/**
    530 * iwpm_add_and_query_mapping_cb - Process the port mapper response to
    531 *                                 iwpm_add_and_query_mapping request
    532 * @skb: The socket buffer
    533 * @cb: Contains the received message (payload and netlink header)
    534 */
    535int iwpm_add_and_query_mapping_cb(struct sk_buff *skb,
    536				struct netlink_callback *cb)
    537{
    538	struct iwpm_sa_data *pm_msg;
    539	struct iwpm_nlmsg_request *nlmsg_request = NULL;
    540	struct nlattr *nltb[IWPM_NLA_RQUERY_MAPPING_MAX];
    541	struct sockaddr_storage *local_sockaddr, *remote_sockaddr;
    542	struct sockaddr_storage *mapped_loc_sockaddr, *mapped_rem_sockaddr;
    543	const char *msg_type;
    544	u32 msg_seq;
    545	u16 err_code;
    546
    547	msg_type = "Query Mapping response";
    548	if (iwpm_parse_nlmsg(cb, IWPM_NLA_RQUERY_MAPPING_MAX,
    549				resp_query_policy, nltb, msg_type))
    550		return -EINVAL;
    551	atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
    552
    553	msg_seq = nla_get_u32(nltb[IWPM_NLA_RQUERY_MAPPING_SEQ]);
    554	nlmsg_request = iwpm_find_nlmsg_request(msg_seq);
    555	if (!nlmsg_request) {
    556		pr_info("%s: Could not find a matching request (seq = %u)\n",
    557				 __func__, msg_seq);
    558		return -EINVAL;
    559	}
    560	pm_msg = nlmsg_request->req_buffer;
    561	local_sockaddr = (struct sockaddr_storage *)
    562			nla_data(nltb[IWPM_NLA_RQUERY_LOCAL_ADDR]);
    563	remote_sockaddr = (struct sockaddr_storage *)
    564			nla_data(nltb[IWPM_NLA_RQUERY_REMOTE_ADDR]);
    565	mapped_loc_sockaddr = (struct sockaddr_storage *)
    566			nla_data(nltb[IWPM_NLA_RQUERY_MAPPED_LOC_ADDR]);
    567	mapped_rem_sockaddr = (struct sockaddr_storage *)
    568			nla_data(nltb[IWPM_NLA_RQUERY_MAPPED_REM_ADDR]);
    569
    570	err_code = nla_get_u16(nltb[IWPM_NLA_RQUERY_MAPPING_ERR]);
    571	if (err_code == IWPM_REMOTE_QUERY_REJECT) {
    572		pr_info("%s: Received a Reject (pid = %u, echo seq = %u)\n",
    573			__func__, cb->nlh->nlmsg_pid, msg_seq);
    574		nlmsg_request->err_code = IWPM_REMOTE_QUERY_REJECT;
    575	}
    576	if (iwpm_compare_sockaddr(local_sockaddr, &pm_msg->loc_addr) ||
    577		iwpm_compare_sockaddr(remote_sockaddr, &pm_msg->rem_addr)) {
    578		pr_info("%s: Incorrect local sockaddr\n", __func__);
    579		nlmsg_request->err_code = IWPM_USER_LIB_INFO_ERR;
    580		goto query_mapping_response_exit;
    581	}
    582	if (mapped_loc_sockaddr->ss_family != local_sockaddr->ss_family ||
    583		mapped_rem_sockaddr->ss_family != remote_sockaddr->ss_family) {
    584		pr_info("%s: Sockaddr family doesn't match the requested one\n",
    585				__func__);
    586		nlmsg_request->err_code = IWPM_USER_LIB_INFO_ERR;
    587		goto query_mapping_response_exit;
    588	}
    589	memcpy(&pm_msg->mapped_loc_addr, mapped_loc_sockaddr,
    590			sizeof(*mapped_loc_sockaddr));
    591	memcpy(&pm_msg->mapped_rem_addr, mapped_rem_sockaddr,
    592			sizeof(*mapped_rem_sockaddr));
    593
    594	iwpm_print_sockaddr(&pm_msg->loc_addr,
    595			"query_mapping: Local sockaddr:");
    596	iwpm_print_sockaddr(&pm_msg->mapped_loc_addr,
    597			"query_mapping: Mapped local sockaddr:");
    598	iwpm_print_sockaddr(&pm_msg->rem_addr,
    599			"query_mapping: Remote sockaddr:");
    600	iwpm_print_sockaddr(&pm_msg->mapped_rem_addr,
    601			"query_mapping: Mapped remote sockaddr:");
    602query_mapping_response_exit:
    603	nlmsg_request->request_done = 1;
    604	/* always for found request */
    605	kref_put(&nlmsg_request->kref, iwpm_free_nlmsg_request);
    606	barrier();
    607	up(&nlmsg_request->sem);
    608	return 0;
    609}
    610
    611/**
    612 * iwpm_remote_info_cb - Process remote connecting peer address info, which
    613 *                       the port mapper has received from the connecting peer
    614 * @skb: The socket buffer
    615 * @cb: Contains the received message (payload and netlink header)
    616 *
    617 * Stores the IPv4/IPv6 address info in a hash table
    618 */
    619int iwpm_remote_info_cb(struct sk_buff *skb, struct netlink_callback *cb)
    620{
    621	struct nlattr *nltb[IWPM_NLA_RQUERY_MAPPING_MAX];
    622	struct sockaddr_storage *local_sockaddr, *remote_sockaddr;
    623	struct sockaddr_storage *mapped_loc_sockaddr, *mapped_rem_sockaddr;
    624	struct iwpm_remote_info *rem_info;
    625	const char *msg_type;
    626	u8 nl_client;
    627	int ret = -EINVAL;
    628
    629	msg_type = "Remote Mapping info";
    630	if (iwpm_parse_nlmsg(cb, IWPM_NLA_RQUERY_MAPPING_MAX,
    631				resp_query_policy, nltb, msg_type))
    632		return ret;
    633
    634	nl_client = RDMA_NL_GET_CLIENT(cb->nlh->nlmsg_type);
    635	atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
    636
    637	local_sockaddr = (struct sockaddr_storage *)
    638			nla_data(nltb[IWPM_NLA_RQUERY_LOCAL_ADDR]);
    639	remote_sockaddr = (struct sockaddr_storage *)
    640			nla_data(nltb[IWPM_NLA_RQUERY_REMOTE_ADDR]);
    641	mapped_loc_sockaddr = (struct sockaddr_storage *)
    642			nla_data(nltb[IWPM_NLA_RQUERY_MAPPED_LOC_ADDR]);
    643	mapped_rem_sockaddr = (struct sockaddr_storage *)
    644			nla_data(nltb[IWPM_NLA_RQUERY_MAPPED_REM_ADDR]);
    645
    646	if (mapped_loc_sockaddr->ss_family != local_sockaddr->ss_family ||
    647		mapped_rem_sockaddr->ss_family != remote_sockaddr->ss_family) {
    648		pr_info("%s: Sockaddr family doesn't match the requested one\n",
    649				__func__);
    650		return ret;
    651	}
    652	rem_info = kzalloc(sizeof(struct iwpm_remote_info), GFP_ATOMIC);
    653	if (!rem_info) {
    654		ret = -ENOMEM;
    655		return ret;
    656	}
    657	memcpy(&rem_info->mapped_loc_sockaddr, mapped_loc_sockaddr,
    658	       sizeof(struct sockaddr_storage));
    659	memcpy(&rem_info->remote_sockaddr, remote_sockaddr,
    660	       sizeof(struct sockaddr_storage));
    661	memcpy(&rem_info->mapped_rem_sockaddr, mapped_rem_sockaddr,
    662	       sizeof(struct sockaddr_storage));
    663	rem_info->nl_client = nl_client;
    664
    665	iwpm_add_remote_info(rem_info);
    666
    667	iwpm_print_sockaddr(local_sockaddr,
    668			"remote_info: Local sockaddr:");
    669	iwpm_print_sockaddr(mapped_loc_sockaddr,
    670			"remote_info: Mapped local sockaddr:");
    671	iwpm_print_sockaddr(remote_sockaddr,
    672			"remote_info: Remote sockaddr:");
    673	iwpm_print_sockaddr(mapped_rem_sockaddr,
    674			"remote_info: Mapped remote sockaddr:");
    675	return ret;
    676}
    677
    678/* netlink attribute policy for the received request for mapping info */
    679static const struct nla_policy resp_mapinfo_policy[IWPM_NLA_MAPINFO_REQ_MAX] = {
    680	[IWPM_NLA_MAPINFO_ULIB_NAME] = { .type = NLA_STRING,
    681					.len = IWPM_ULIBNAME_SIZE - 1 },
    682	[IWPM_NLA_MAPINFO_ULIB_VER]  = { .type = NLA_U16 }
    683};
    684
    685/**
    686 * iwpm_mapping_info_cb - Process a notification that the userspace
    687 *                        port mapper daemon is started
    688 * @skb: The socket buffer
    689 * @cb: Contains the received message (payload and netlink header)
    690 *
    691 * Using the received port mapper pid, send all the local mapping
    692 * info records to the userspace port mapper
    693 */
    694int iwpm_mapping_info_cb(struct sk_buff *skb, struct netlink_callback *cb)
    695{
    696	struct nlattr *nltb[IWPM_NLA_MAPINFO_REQ_MAX];
    697	const char *msg_type = "Mapping Info response";
    698	u8 nl_client;
    699	char *iwpm_name;
    700	u16 iwpm_version;
    701	int ret = -EINVAL;
    702
    703	if (iwpm_parse_nlmsg(cb, IWPM_NLA_MAPINFO_REQ_MAX,
    704				resp_mapinfo_policy, nltb, msg_type)) {
    705		pr_info("%s: Unable to parse nlmsg\n", __func__);
    706		return ret;
    707	}
    708	iwpm_name = (char *)nla_data(nltb[IWPM_NLA_MAPINFO_ULIB_NAME]);
    709	iwpm_version = nla_get_u16(nltb[IWPM_NLA_MAPINFO_ULIB_VER]);
    710	if (strcmp(iwpm_ulib_name, iwpm_name) ||
    711			iwpm_version < IWPM_UABI_VERSION_MIN) {
    712		pr_info("%s: Invalid port mapper name = %s version = %u\n",
    713				__func__, iwpm_name, iwpm_version);
    714		return ret;
    715	}
    716	nl_client = RDMA_NL_GET_CLIENT(cb->nlh->nlmsg_type);
    717	iwpm_set_registration(nl_client, IWPM_REG_INCOMPL);
    718	atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
    719	iwpm_user_pid = cb->nlh->nlmsg_pid;
    720
    721	if (iwpm_ulib_version < IWPM_UABI_VERSION)
    722		pr_warn_once("%s: Down level iwpmd/pid %d.  Continuing...",
    723			__func__, iwpm_user_pid);
    724
    725	if (!iwpm_mapinfo_available())
    726		return 0;
    727	pr_debug("%s: iWarp Port Mapper (pid = %d) is available!\n",
    728		 __func__, iwpm_user_pid);
    729	ret = iwpm_send_mapinfo(nl_client, iwpm_user_pid);
    730	return ret;
    731}
    732
    733/* netlink attribute policy for the received mapping info ack */
    734static const struct nla_policy ack_mapinfo_policy[IWPM_NLA_MAPINFO_NUM_MAX] = {
    735	[IWPM_NLA_MAPINFO_SEQ]    =   { .type = NLA_U32 },
    736	[IWPM_NLA_MAPINFO_SEND_NUM] = { .type = NLA_U32 },
    737	[IWPM_NLA_MAPINFO_ACK_NUM] =  { .type = NLA_U32 }
    738};
    739
    740/**
    741 * iwpm_ack_mapping_info_cb - Process the port mapper ack for
    742 *                            the provided local mapping info records
    743 * @skb: The socket buffer
    744 * @cb: Contains the received message (payload and netlink header)
    745 */
    746int iwpm_ack_mapping_info_cb(struct sk_buff *skb, struct netlink_callback *cb)
    747{
    748	struct nlattr *nltb[IWPM_NLA_MAPINFO_NUM_MAX];
    749	u32 mapinfo_send, mapinfo_ack;
    750	const char *msg_type = "Mapping Info Ack";
    751
    752	if (iwpm_parse_nlmsg(cb, IWPM_NLA_MAPINFO_NUM_MAX,
    753				ack_mapinfo_policy, nltb, msg_type))
    754		return -EINVAL;
    755	mapinfo_send = nla_get_u32(nltb[IWPM_NLA_MAPINFO_SEND_NUM]);
    756	mapinfo_ack = nla_get_u32(nltb[IWPM_NLA_MAPINFO_ACK_NUM]);
    757	if (mapinfo_ack != mapinfo_send)
    758		pr_info("%s: Invalid mapinfo number (sent = %u ack-ed = %u)\n",
    759			__func__, mapinfo_send, mapinfo_ack);
    760	atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
    761	return 0;
    762}
    763
    764/* netlink attribute policy for the received port mapper error message */
    765static const struct nla_policy map_error_policy[IWPM_NLA_ERR_MAX] = {
    766	[IWPM_NLA_ERR_SEQ]        = { .type = NLA_U32 },
    767	[IWPM_NLA_ERR_CODE]       = { .type = NLA_U16 },
    768};
    769
    770/**
    771 * iwpm_mapping_error_cb - Process port mapper notification for error
    772 *
    773 * @skb: The socket buffer
    774 * @cb: Contains the received message (payload and netlink header)
    775 */
    776int iwpm_mapping_error_cb(struct sk_buff *skb, struct netlink_callback *cb)
    777{
    778	struct iwpm_nlmsg_request *nlmsg_request = NULL;
    779	int nl_client = RDMA_NL_GET_CLIENT(cb->nlh->nlmsg_type);
    780	struct nlattr *nltb[IWPM_NLA_ERR_MAX];
    781	u32 msg_seq;
    782	u16 err_code;
    783	const char *msg_type = "Mapping Error Msg";
    784
    785	if (iwpm_parse_nlmsg(cb, IWPM_NLA_ERR_MAX,
    786				map_error_policy, nltb, msg_type))
    787		return -EINVAL;
    788
    789	msg_seq = nla_get_u32(nltb[IWPM_NLA_ERR_SEQ]);
    790	err_code = nla_get_u16(nltb[IWPM_NLA_ERR_CODE]);
    791	pr_info("%s: Received msg seq = %u err code = %u client = %d\n",
    792				__func__, msg_seq, err_code, nl_client);
    793	/* look for nlmsg_request */
    794	nlmsg_request = iwpm_find_nlmsg_request(msg_seq);
    795	if (!nlmsg_request) {
    796		/* not all errors have associated requests */
    797		pr_debug("Could not find matching req (seq = %u)\n", msg_seq);
    798		return 0;
    799	}
    800	atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
    801	nlmsg_request->err_code = err_code;
    802	nlmsg_request->request_done = 1;
    803	/* always for found request */
    804	kref_put(&nlmsg_request->kref, iwpm_free_nlmsg_request);
    805	barrier();
    806	up(&nlmsg_request->sem);
    807	return 0;
    808}
    809
    810/* netlink attribute policy for the received hello request */
    811static const struct nla_policy hello_policy[IWPM_NLA_HELLO_MAX] = {
    812	[IWPM_NLA_HELLO_ABI_VERSION]     = { .type = NLA_U16 }
    813};
    814
    815/**
    816 * iwpm_hello_cb - Process a hello message from iwpmd
    817 *
    818 * @skb: The socket buffer
    819 * @cb: Contains the received message (payload and netlink header)
    820 *
    821 * Using the received port mapper pid, send the kernel's abi_version
    822 * after adjusting it to support the iwpmd version.
    823 */
    824int iwpm_hello_cb(struct sk_buff *skb, struct netlink_callback *cb)
    825{
    826	struct nlattr *nltb[IWPM_NLA_HELLO_MAX];
    827	const char *msg_type = "Hello request";
    828	u8 nl_client;
    829	u16 abi_version;
    830	int ret = -EINVAL;
    831
    832	if (iwpm_parse_nlmsg(cb, IWPM_NLA_HELLO_MAX, hello_policy, nltb,
    833			     msg_type)) {
    834		pr_info("%s: Unable to parse nlmsg\n", __func__);
    835		return ret;
    836	}
    837	abi_version = nla_get_u16(nltb[IWPM_NLA_HELLO_ABI_VERSION]);
    838	nl_client = RDMA_NL_GET_CLIENT(cb->nlh->nlmsg_type);
    839	iwpm_set_registration(nl_client, IWPM_REG_INCOMPL);
    840	atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
    841	iwpm_ulib_version = min_t(u16, IWPM_UABI_VERSION, abi_version);
    842	pr_debug("Using ABI version %u\n", iwpm_ulib_version);
    843	iwpm_user_pid = cb->nlh->nlmsg_pid;
    844	ret = iwpm_send_hello(nl_client, iwpm_user_pid, iwpm_ulib_version);
    845	return ret;
    846}