• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
36 static const char iwpm_ulib_name[IWPM_ULIBNAME_SIZE] = "iWarpPortMapperUser";
37 u16 iwpm_ulib_version = IWPM_UABI_VERSION_MIN;
38 static int iwpm_user_pid = IWPM_PID_UNDEFINED;
39 static 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  */
iwpm_valid_pid(void)46 int 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  */
iwpm_register_pid(struct iwpm_dev_data * pm_msg,u8 nl_client)63 int 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;
121 pid_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  */
iwpm_add_mapping(struct iwpm_sa_data * pm_msg,u8 nl_client)143 int 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;
205 add_mapping_error:
206 	pr_info("%s: %s (client = %u)\n", __func__, err_str, nl_client);
207 add_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  */
iwpm_add_and_query_mapping(struct iwpm_sa_data * pm_msg,u8 nl_client)226 int 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;
294 query_mapping_error:
295 	pr_info("%s: %s (client = %u)\n", __func__, err_str, nl_client);
296 query_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  */
iwpm_remove_mapping(struct sockaddr_storage * local_addr,u8 nl_client)314 int 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;
358 remove_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 */
366 static 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  */
iwpm_register_pid_cb(struct sk_buff * skb,struct netlink_callback * cb)385 int 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);
432 register_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 */
442 static 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  */
iwpm_add_mapping_cb(struct sk_buff * skb,struct netlink_callback * cb)457 int 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 
504 add_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  */
516 static 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  */
iwpm_add_and_query_mapping_cb(struct sk_buff * skb,struct netlink_callback * cb)535 int 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:");
602 query_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  */
iwpm_remote_info_cb(struct sk_buff * skb,struct netlink_callback * cb)619 int 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 */
679 static 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  */
iwpm_mapping_info_cb(struct sk_buff * skb,struct netlink_callback * cb)694 int 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 */
734 static 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  */
iwpm_ack_mapping_info_cb(struct sk_buff * skb,struct netlink_callback * cb)746 int 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 */
765 static 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  */
iwpm_mapping_error_cb(struct sk_buff * skb,struct netlink_callback * cb)776 int 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 */
811 static 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  */
iwpm_hello_cb(struct sk_buff * skb,struct netlink_callback * cb)824 int 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 }
847