iwpm_msg.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685
  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. #include "iwpm_util.h"
  34. static const char iwpm_ulib_name[] = "iWarpPortMapperUser";
  35. static int iwpm_ulib_version = 3;
  36. static int iwpm_user_pid = IWPM_PID_UNDEFINED;
  37. static atomic_t echo_nlmsg_seq;
  38. int iwpm_valid_pid(void)
  39. {
  40. return iwpm_user_pid > 0;
  41. }
  42. EXPORT_SYMBOL(iwpm_valid_pid);
  43. /*
  44. * iwpm_register_pid - Send a netlink query to user space
  45. * for the iwarp port mapper pid
  46. *
  47. * nlmsg attributes:
  48. * [IWPM_NLA_REG_PID_SEQ]
  49. * [IWPM_NLA_REG_IF_NAME]
  50. * [IWPM_NLA_REG_IBDEV_NAME]
  51. * [IWPM_NLA_REG_ULIB_NAME]
  52. */
  53. int iwpm_register_pid(struct iwpm_dev_data *pm_msg, u8 nl_client)
  54. {
  55. struct sk_buff *skb = NULL;
  56. struct iwpm_nlmsg_request *nlmsg_request = NULL;
  57. struct nlmsghdr *nlh;
  58. u32 msg_seq;
  59. const char *err_str = "";
  60. int ret = -EINVAL;
  61. if (!iwpm_valid_client(nl_client)) {
  62. err_str = "Invalid port mapper client";
  63. goto pid_query_error;
  64. }
  65. if (iwpm_registered_client(nl_client))
  66. return 0;
  67. skb = iwpm_create_nlmsg(RDMA_NL_IWPM_REG_PID, &nlh, nl_client);
  68. if (!skb) {
  69. err_str = "Unable to create a nlmsg";
  70. goto pid_query_error;
  71. }
  72. nlh->nlmsg_seq = iwpm_get_nlmsg_seq();
  73. nlmsg_request = iwpm_get_nlmsg_request(nlh->nlmsg_seq, nl_client, GFP_KERNEL);
  74. if (!nlmsg_request) {
  75. err_str = "Unable to allocate netlink request";
  76. goto pid_query_error;
  77. }
  78. msg_seq = atomic_read(&echo_nlmsg_seq);
  79. /* fill in the pid request message */
  80. err_str = "Unable to put attribute of the nlmsg";
  81. ret = ibnl_put_attr(skb, nlh, sizeof(u32), &msg_seq, IWPM_NLA_REG_PID_SEQ);
  82. if (ret)
  83. goto pid_query_error;
  84. ret = ibnl_put_attr(skb, nlh, IWPM_IFNAME_SIZE,
  85. pm_msg->if_name, IWPM_NLA_REG_IF_NAME);
  86. if (ret)
  87. goto pid_query_error;
  88. ret = ibnl_put_attr(skb, nlh, IWPM_DEVNAME_SIZE,
  89. pm_msg->dev_name, IWPM_NLA_REG_IBDEV_NAME);
  90. if (ret)
  91. goto pid_query_error;
  92. ret = ibnl_put_attr(skb, nlh, IWPM_ULIBNAME_SIZE,
  93. (char *)iwpm_ulib_name, IWPM_NLA_REG_ULIB_NAME);
  94. if (ret)
  95. goto pid_query_error;
  96. pr_debug("%s: Multicasting a nlmsg (dev = %s ifname = %s iwpm = %s)\n",
  97. __func__, pm_msg->dev_name, pm_msg->if_name, iwpm_ulib_name);
  98. ret = ibnl_multicast(skb, nlh, RDMA_NL_GROUP_IWPM, GFP_KERNEL);
  99. if (ret) {
  100. skb = NULL; /* skb is freed in the netlink send-op handling */
  101. iwpm_set_registered(nl_client, 1);
  102. iwpm_user_pid = IWPM_PID_UNAVAILABLE;
  103. err_str = "Unable to send a nlmsg";
  104. goto pid_query_error;
  105. }
  106. nlmsg_request->req_buffer = pm_msg;
  107. ret = iwpm_wait_complete_req(nlmsg_request);
  108. return ret;
  109. pid_query_error:
  110. pr_info("%s: %s (client = %d)\n", __func__, err_str, nl_client);
  111. if (skb)
  112. dev_kfree_skb(skb);
  113. if (nlmsg_request)
  114. iwpm_free_nlmsg_request(&nlmsg_request->kref);
  115. return ret;
  116. }
  117. EXPORT_SYMBOL(iwpm_register_pid);
  118. /*
  119. * iwpm_add_mapping - Send a netlink add mapping message
  120. * to the port mapper
  121. * nlmsg attributes:
  122. * [IWPM_NLA_MANAGE_MAPPING_SEQ]
  123. * [IWPM_NLA_MANAGE_ADDR]
  124. */
  125. int iwpm_add_mapping(struct iwpm_sa_data *pm_msg, u8 nl_client)
  126. {
  127. struct sk_buff *skb = NULL;
  128. struct iwpm_nlmsg_request *nlmsg_request = NULL;
  129. struct nlmsghdr *nlh;
  130. u32 msg_seq;
  131. const char *err_str = "";
  132. int ret = -EINVAL;
  133. if (!iwpm_valid_client(nl_client)) {
  134. err_str = "Invalid port mapper client";
  135. goto add_mapping_error;
  136. }
  137. if (!iwpm_registered_client(nl_client)) {
  138. err_str = "Unregistered port mapper client";
  139. goto add_mapping_error;
  140. }
  141. if (!iwpm_valid_pid())
  142. return 0;
  143. skb = iwpm_create_nlmsg(RDMA_NL_IWPM_ADD_MAPPING, &nlh, nl_client);
  144. if (!skb) {
  145. err_str = "Unable to create a nlmsg";
  146. goto add_mapping_error;
  147. }
  148. nlh->nlmsg_seq = iwpm_get_nlmsg_seq();
  149. nlmsg_request = iwpm_get_nlmsg_request(nlh->nlmsg_seq, nl_client, GFP_KERNEL);
  150. if (!nlmsg_request) {
  151. err_str = "Unable to allocate netlink request";
  152. goto add_mapping_error;
  153. }
  154. msg_seq = atomic_read(&echo_nlmsg_seq);
  155. /* fill in the add mapping message */
  156. err_str = "Unable to put attribute of the nlmsg";
  157. ret = ibnl_put_attr(skb, nlh, sizeof(u32), &msg_seq,
  158. IWPM_NLA_MANAGE_MAPPING_SEQ);
  159. if (ret)
  160. goto add_mapping_error;
  161. ret = ibnl_put_attr(skb, nlh, sizeof(struct sockaddr_storage),
  162. &pm_msg->loc_addr, IWPM_NLA_MANAGE_ADDR);
  163. if (ret)
  164. goto add_mapping_error;
  165. nlmsg_request->req_buffer = pm_msg;
  166. ret = ibnl_unicast(skb, nlh, iwpm_user_pid);
  167. if (ret) {
  168. skb = NULL; /* skb is freed in the netlink send-op handling */
  169. iwpm_user_pid = IWPM_PID_UNDEFINED;
  170. err_str = "Unable to send a nlmsg";
  171. goto add_mapping_error;
  172. }
  173. ret = iwpm_wait_complete_req(nlmsg_request);
  174. return ret;
  175. add_mapping_error:
  176. pr_info("%s: %s (client = %d)\n", __func__, err_str, nl_client);
  177. if (skb)
  178. dev_kfree_skb(skb);
  179. if (nlmsg_request)
  180. iwpm_free_nlmsg_request(&nlmsg_request->kref);
  181. return ret;
  182. }
  183. EXPORT_SYMBOL(iwpm_add_mapping);
  184. /*
  185. * iwpm_add_and_query_mapping - Send a netlink add and query
  186. * mapping message to the port mapper
  187. * nlmsg attributes:
  188. * [IWPM_NLA_QUERY_MAPPING_SEQ]
  189. * [IWPM_NLA_QUERY_LOCAL_ADDR]
  190. * [IWPM_NLA_QUERY_REMOTE_ADDR]
  191. */
  192. int iwpm_add_and_query_mapping(struct iwpm_sa_data *pm_msg, u8 nl_client)
  193. {
  194. struct sk_buff *skb = NULL;
  195. struct iwpm_nlmsg_request *nlmsg_request = NULL;
  196. struct nlmsghdr *nlh;
  197. u32 msg_seq;
  198. const char *err_str = "";
  199. int ret = -EINVAL;
  200. if (!iwpm_valid_client(nl_client)) {
  201. err_str = "Invalid port mapper client";
  202. goto query_mapping_error;
  203. }
  204. if (!iwpm_registered_client(nl_client)) {
  205. err_str = "Unregistered port mapper client";
  206. goto query_mapping_error;
  207. }
  208. if (!iwpm_valid_pid())
  209. return 0;
  210. ret = -ENOMEM;
  211. skb = iwpm_create_nlmsg(RDMA_NL_IWPM_QUERY_MAPPING, &nlh, nl_client);
  212. if (!skb) {
  213. err_str = "Unable to create a nlmsg";
  214. goto query_mapping_error;
  215. }
  216. nlh->nlmsg_seq = iwpm_get_nlmsg_seq();
  217. nlmsg_request = iwpm_get_nlmsg_request(nlh->nlmsg_seq,
  218. nl_client, GFP_KERNEL);
  219. if (!nlmsg_request) {
  220. err_str = "Unable to allocate netlink request";
  221. goto query_mapping_error;
  222. }
  223. msg_seq = atomic_read(&echo_nlmsg_seq);
  224. /* fill in the query message */
  225. err_str = "Unable to put attribute of the nlmsg";
  226. ret = ibnl_put_attr(skb, nlh, sizeof(u32), &msg_seq,
  227. IWPM_NLA_QUERY_MAPPING_SEQ);
  228. if (ret)
  229. goto query_mapping_error;
  230. ret = ibnl_put_attr(skb, nlh, sizeof(struct sockaddr_storage),
  231. &pm_msg->loc_addr, IWPM_NLA_QUERY_LOCAL_ADDR);
  232. if (ret)
  233. goto query_mapping_error;
  234. ret = ibnl_put_attr(skb, nlh, sizeof(struct sockaddr_storage),
  235. &pm_msg->rem_addr, IWPM_NLA_QUERY_REMOTE_ADDR);
  236. if (ret)
  237. goto query_mapping_error;
  238. nlmsg_request->req_buffer = pm_msg;
  239. ret = ibnl_unicast(skb, nlh, iwpm_user_pid);
  240. if (ret) {
  241. skb = NULL; /* skb is freed in the netlink send-op handling */
  242. err_str = "Unable to send a nlmsg";
  243. goto query_mapping_error;
  244. }
  245. ret = iwpm_wait_complete_req(nlmsg_request);
  246. return ret;
  247. query_mapping_error:
  248. pr_info("%s: %s (client = %d)\n", __func__, err_str, nl_client);
  249. if (skb)
  250. dev_kfree_skb(skb);
  251. if (nlmsg_request)
  252. iwpm_free_nlmsg_request(&nlmsg_request->kref);
  253. return ret;
  254. }
  255. EXPORT_SYMBOL(iwpm_add_and_query_mapping);
  256. /*
  257. * iwpm_remove_mapping - Send a netlink remove mapping message
  258. * to the port mapper
  259. * nlmsg attributes:
  260. * [IWPM_NLA_MANAGE_MAPPING_SEQ]
  261. * [IWPM_NLA_MANAGE_ADDR]
  262. */
  263. int iwpm_remove_mapping(struct sockaddr_storage *local_addr, u8 nl_client)
  264. {
  265. struct sk_buff *skb = NULL;
  266. struct nlmsghdr *nlh;
  267. u32 msg_seq;
  268. const char *err_str = "";
  269. int ret = -EINVAL;
  270. if (!iwpm_valid_client(nl_client)) {
  271. err_str = "Invalid port mapper client";
  272. goto remove_mapping_error;
  273. }
  274. if (!iwpm_registered_client(nl_client)) {
  275. err_str = "Unregistered port mapper client";
  276. goto remove_mapping_error;
  277. }
  278. if (!iwpm_valid_pid())
  279. return 0;
  280. skb = iwpm_create_nlmsg(RDMA_NL_IWPM_REMOVE_MAPPING, &nlh, nl_client);
  281. if (!skb) {
  282. ret = -ENOMEM;
  283. err_str = "Unable to create a nlmsg";
  284. goto remove_mapping_error;
  285. }
  286. msg_seq = atomic_read(&echo_nlmsg_seq);
  287. nlh->nlmsg_seq = iwpm_get_nlmsg_seq();
  288. err_str = "Unable to put attribute of the nlmsg";
  289. ret = ibnl_put_attr(skb, nlh, sizeof(u32), &msg_seq,
  290. IWPM_NLA_MANAGE_MAPPING_SEQ);
  291. if (ret)
  292. goto remove_mapping_error;
  293. ret = ibnl_put_attr(skb, nlh, sizeof(struct sockaddr_storage),
  294. local_addr, IWPM_NLA_MANAGE_ADDR);
  295. if (ret)
  296. goto remove_mapping_error;
  297. ret = ibnl_unicast(skb, nlh, iwpm_user_pid);
  298. if (ret) {
  299. skb = NULL; /* skb is freed in the netlink send-op handling */
  300. iwpm_user_pid = IWPM_PID_UNDEFINED;
  301. err_str = "Unable to send a nlmsg";
  302. goto remove_mapping_error;
  303. }
  304. iwpm_print_sockaddr(local_addr,
  305. "remove_mapping: Local sockaddr:");
  306. return 0;
  307. remove_mapping_error:
  308. pr_info("%s: %s (client = %d)\n", __func__, err_str, nl_client);
  309. if (skb)
  310. dev_kfree_skb_any(skb);
  311. return ret;
  312. }
  313. EXPORT_SYMBOL(iwpm_remove_mapping);
  314. /* netlink attribute policy for the received response to register pid request */
  315. static const struct nla_policy resp_reg_policy[IWPM_NLA_RREG_PID_MAX] = {
  316. [IWPM_NLA_RREG_PID_SEQ] = { .type = NLA_U32 },
  317. [IWPM_NLA_RREG_IBDEV_NAME] = { .type = NLA_STRING,
  318. .len = IWPM_DEVNAME_SIZE - 1 },
  319. [IWPM_NLA_RREG_ULIB_NAME] = { .type = NLA_STRING,
  320. .len = IWPM_ULIBNAME_SIZE - 1 },
  321. [IWPM_NLA_RREG_ULIB_VER] = { .type = NLA_U16 },
  322. [IWPM_NLA_RREG_PID_ERR] = { .type = NLA_U16 }
  323. };
  324. /*
  325. * iwpm_register_pid_cb - Process a port mapper response to
  326. * iwpm_register_pid()
  327. */
  328. int iwpm_register_pid_cb(struct sk_buff *skb, struct netlink_callback *cb)
  329. {
  330. struct iwpm_nlmsg_request *nlmsg_request = NULL;
  331. struct nlattr *nltb[IWPM_NLA_RREG_PID_MAX];
  332. struct iwpm_dev_data *pm_msg;
  333. char *dev_name, *iwpm_name;
  334. u32 msg_seq;
  335. u8 nl_client;
  336. u16 iwpm_version;
  337. const char *msg_type = "Register Pid response";
  338. if (iwpm_parse_nlmsg(cb, IWPM_NLA_RREG_PID_MAX,
  339. resp_reg_policy, nltb, msg_type))
  340. return -EINVAL;
  341. msg_seq = nla_get_u32(nltb[IWPM_NLA_RREG_PID_SEQ]);
  342. nlmsg_request = iwpm_find_nlmsg_request(msg_seq);
  343. if (!nlmsg_request) {
  344. pr_info("%s: Could not find a matching request (seq = %u)\n",
  345. __func__, msg_seq);
  346. return -EINVAL;
  347. }
  348. pm_msg = nlmsg_request->req_buffer;
  349. nl_client = nlmsg_request->nl_client;
  350. dev_name = (char *)nla_data(nltb[IWPM_NLA_RREG_IBDEV_NAME]);
  351. iwpm_name = (char *)nla_data(nltb[IWPM_NLA_RREG_ULIB_NAME]);
  352. iwpm_version = nla_get_u16(nltb[IWPM_NLA_RREG_ULIB_VER]);
  353. /* check device name, ulib name and version */
  354. if (strcmp(pm_msg->dev_name, dev_name) ||
  355. strcmp(iwpm_ulib_name, iwpm_name) ||
  356. iwpm_version != iwpm_ulib_version) {
  357. pr_info("%s: Incorrect info (dev = %s name = %s version = %d)\n",
  358. __func__, dev_name, iwpm_name, iwpm_version);
  359. nlmsg_request->err_code = IWPM_USER_LIB_INFO_ERR;
  360. goto register_pid_response_exit;
  361. }
  362. iwpm_user_pid = cb->nlh->nlmsg_pid;
  363. atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
  364. pr_debug("%s: iWarp Port Mapper (pid = %d) is available!\n",
  365. __func__, iwpm_user_pid);
  366. if (iwpm_valid_client(nl_client))
  367. iwpm_set_registered(nl_client, 1);
  368. register_pid_response_exit:
  369. nlmsg_request->request_done = 1;
  370. /* always for found nlmsg_request */
  371. kref_put(&nlmsg_request->kref, iwpm_free_nlmsg_request);
  372. barrier();
  373. wake_up(&nlmsg_request->waitq);
  374. return 0;
  375. }
  376. EXPORT_SYMBOL(iwpm_register_pid_cb);
  377. /* netlink attribute policy for the received response to add mapping request */
  378. static const struct nla_policy resp_add_policy[IWPM_NLA_RMANAGE_MAPPING_MAX] = {
  379. [IWPM_NLA_MANAGE_MAPPING_SEQ] = { .type = NLA_U32 },
  380. [IWPM_NLA_MANAGE_ADDR] = { .len = sizeof(struct sockaddr_storage) },
  381. [IWPM_NLA_MANAGE_MAPPED_LOC_ADDR] = { .len = sizeof(struct sockaddr_storage) },
  382. [IWPM_NLA_RMANAGE_MAPPING_ERR] = { .type = NLA_U16 }
  383. };
  384. /*
  385. * iwpm_add_mapping_cb - Process a port mapper response to
  386. * iwpm_add_mapping()
  387. */
  388. int iwpm_add_mapping_cb(struct sk_buff *skb, struct netlink_callback *cb)
  389. {
  390. struct iwpm_sa_data *pm_msg;
  391. struct iwpm_nlmsg_request *nlmsg_request = NULL;
  392. struct nlattr *nltb[IWPM_NLA_RMANAGE_MAPPING_MAX];
  393. struct sockaddr_storage *local_sockaddr;
  394. struct sockaddr_storage *mapped_sockaddr;
  395. const char *msg_type;
  396. u32 msg_seq;
  397. msg_type = "Add Mapping response";
  398. if (iwpm_parse_nlmsg(cb, IWPM_NLA_RMANAGE_MAPPING_MAX,
  399. resp_add_policy, nltb, msg_type))
  400. return -EINVAL;
  401. atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
  402. msg_seq = nla_get_u32(nltb[IWPM_NLA_MANAGE_MAPPING_SEQ]);
  403. nlmsg_request = iwpm_find_nlmsg_request(msg_seq);
  404. if (!nlmsg_request) {
  405. pr_info("%s: Could not find a matching request (seq = %u)\n",
  406. __func__, msg_seq);
  407. return -EINVAL;
  408. }
  409. pm_msg = nlmsg_request->req_buffer;
  410. local_sockaddr = (struct sockaddr_storage *)
  411. nla_data(nltb[IWPM_NLA_MANAGE_ADDR]);
  412. mapped_sockaddr = (struct sockaddr_storage *)
  413. nla_data(nltb[IWPM_NLA_MANAGE_MAPPED_LOC_ADDR]);
  414. if (iwpm_compare_sockaddr(local_sockaddr, &pm_msg->loc_addr)) {
  415. nlmsg_request->err_code = IWPM_USER_LIB_INFO_ERR;
  416. goto add_mapping_response_exit;
  417. }
  418. if (mapped_sockaddr->ss_family != local_sockaddr->ss_family) {
  419. pr_info("%s: Sockaddr family doesn't match the requested one\n",
  420. __func__);
  421. nlmsg_request->err_code = IWPM_USER_LIB_INFO_ERR;
  422. goto add_mapping_response_exit;
  423. }
  424. memcpy(&pm_msg->mapped_loc_addr, mapped_sockaddr,
  425. sizeof(*mapped_sockaddr));
  426. iwpm_print_sockaddr(&pm_msg->loc_addr,
  427. "add_mapping: Local sockaddr:");
  428. iwpm_print_sockaddr(&pm_msg->mapped_loc_addr,
  429. "add_mapping: Mapped local sockaddr:");
  430. add_mapping_response_exit:
  431. nlmsg_request->request_done = 1;
  432. /* always for found request */
  433. kref_put(&nlmsg_request->kref, iwpm_free_nlmsg_request);
  434. barrier();
  435. wake_up(&nlmsg_request->waitq);
  436. return 0;
  437. }
  438. EXPORT_SYMBOL(iwpm_add_mapping_cb);
  439. /* netlink attribute policy for the response to add and query mapping request */
  440. static const struct nla_policy resp_query_policy[IWPM_NLA_RQUERY_MAPPING_MAX] = {
  441. [IWPM_NLA_QUERY_MAPPING_SEQ] = { .type = NLA_U32 },
  442. [IWPM_NLA_QUERY_LOCAL_ADDR] = { .len = sizeof(struct sockaddr_storage) },
  443. [IWPM_NLA_QUERY_REMOTE_ADDR] = { .len = sizeof(struct sockaddr_storage) },
  444. [IWPM_NLA_RQUERY_MAPPED_LOC_ADDR] = { .len = sizeof(struct sockaddr_storage) },
  445. [IWPM_NLA_RQUERY_MAPPED_REM_ADDR] = { .len = sizeof(struct sockaddr_storage) },
  446. [IWPM_NLA_RQUERY_MAPPING_ERR] = { .type = NLA_U16 }
  447. };
  448. /*
  449. * iwpm_add_and_query_mapping_cb - Process a port mapper response to
  450. * iwpm_add_and_query_mapping()
  451. */
  452. int iwpm_add_and_query_mapping_cb(struct sk_buff *skb,
  453. struct netlink_callback *cb)
  454. {
  455. struct iwpm_sa_data *pm_msg;
  456. struct iwpm_nlmsg_request *nlmsg_request = NULL;
  457. struct nlattr *nltb[IWPM_NLA_RQUERY_MAPPING_MAX];
  458. struct sockaddr_storage *local_sockaddr, *remote_sockaddr;
  459. struct sockaddr_storage *mapped_loc_sockaddr, *mapped_rem_sockaddr;
  460. const char *msg_type;
  461. u32 msg_seq;
  462. u16 err_code;
  463. msg_type = "Query Mapping response";
  464. if (iwpm_parse_nlmsg(cb, IWPM_NLA_RQUERY_MAPPING_MAX,
  465. resp_query_policy, nltb, msg_type))
  466. return -EINVAL;
  467. atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
  468. msg_seq = nla_get_u32(nltb[IWPM_NLA_QUERY_MAPPING_SEQ]);
  469. nlmsg_request = iwpm_find_nlmsg_request(msg_seq);
  470. if (!nlmsg_request) {
  471. pr_info("%s: Could not find a matching request (seq = %u)\n",
  472. __func__, msg_seq);
  473. return -EINVAL;
  474. }
  475. pm_msg = nlmsg_request->req_buffer;
  476. local_sockaddr = (struct sockaddr_storage *)
  477. nla_data(nltb[IWPM_NLA_QUERY_LOCAL_ADDR]);
  478. remote_sockaddr = (struct sockaddr_storage *)
  479. nla_data(nltb[IWPM_NLA_QUERY_REMOTE_ADDR]);
  480. mapped_loc_sockaddr = (struct sockaddr_storage *)
  481. nla_data(nltb[IWPM_NLA_RQUERY_MAPPED_LOC_ADDR]);
  482. mapped_rem_sockaddr = (struct sockaddr_storage *)
  483. nla_data(nltb[IWPM_NLA_RQUERY_MAPPED_REM_ADDR]);
  484. err_code = nla_get_u16(nltb[IWPM_NLA_RQUERY_MAPPING_ERR]);
  485. if (err_code == IWPM_REMOTE_QUERY_REJECT) {
  486. pr_info("%s: Received a Reject (pid = %u, echo seq = %u)\n",
  487. __func__, cb->nlh->nlmsg_pid, msg_seq);
  488. nlmsg_request->err_code = IWPM_REMOTE_QUERY_REJECT;
  489. }
  490. if (iwpm_compare_sockaddr(local_sockaddr, &pm_msg->loc_addr) ||
  491. iwpm_compare_sockaddr(remote_sockaddr, &pm_msg->rem_addr)) {
  492. pr_info("%s: Incorrect local sockaddr\n", __func__);
  493. nlmsg_request->err_code = IWPM_USER_LIB_INFO_ERR;
  494. goto query_mapping_response_exit;
  495. }
  496. if (mapped_loc_sockaddr->ss_family != local_sockaddr->ss_family ||
  497. mapped_rem_sockaddr->ss_family != remote_sockaddr->ss_family) {
  498. pr_info("%s: Sockaddr family doesn't match the requested one\n",
  499. __func__);
  500. nlmsg_request->err_code = IWPM_USER_LIB_INFO_ERR;
  501. goto query_mapping_response_exit;
  502. }
  503. memcpy(&pm_msg->mapped_loc_addr, mapped_loc_sockaddr,
  504. sizeof(*mapped_loc_sockaddr));
  505. memcpy(&pm_msg->mapped_rem_addr, mapped_rem_sockaddr,
  506. sizeof(*mapped_rem_sockaddr));
  507. iwpm_print_sockaddr(&pm_msg->loc_addr,
  508. "query_mapping: Local sockaddr:");
  509. iwpm_print_sockaddr(&pm_msg->mapped_loc_addr,
  510. "query_mapping: Mapped local sockaddr:");
  511. iwpm_print_sockaddr(&pm_msg->rem_addr,
  512. "query_mapping: Remote sockaddr:");
  513. iwpm_print_sockaddr(&pm_msg->mapped_rem_addr,
  514. "query_mapping: Mapped remote sockaddr:");
  515. query_mapping_response_exit:
  516. nlmsg_request->request_done = 1;
  517. /* always for found request */
  518. kref_put(&nlmsg_request->kref, iwpm_free_nlmsg_request);
  519. barrier();
  520. wake_up(&nlmsg_request->waitq);
  521. return 0;
  522. }
  523. EXPORT_SYMBOL(iwpm_add_and_query_mapping_cb);
  524. /* netlink attribute policy for the received request for mapping info */
  525. static const struct nla_policy resp_mapinfo_policy[IWPM_NLA_MAPINFO_REQ_MAX] = {
  526. [IWPM_NLA_MAPINFO_ULIB_NAME] = { .type = NLA_STRING,
  527. .len = IWPM_ULIBNAME_SIZE - 1 },
  528. [IWPM_NLA_MAPINFO_ULIB_VER] = { .type = NLA_U16 }
  529. };
  530. /*
  531. * iwpm_mapping_info_cb - Process a port mapper request for mapping info
  532. */
  533. int iwpm_mapping_info_cb(struct sk_buff *skb, struct netlink_callback *cb)
  534. {
  535. struct nlattr *nltb[IWPM_NLA_MAPINFO_REQ_MAX];
  536. const char *msg_type = "Mapping Info response";
  537. int iwpm_pid;
  538. u8 nl_client;
  539. char *iwpm_name;
  540. u16 iwpm_version;
  541. int ret = -EINVAL;
  542. if (iwpm_parse_nlmsg(cb, IWPM_NLA_MAPINFO_REQ_MAX,
  543. resp_mapinfo_policy, nltb, msg_type)) {
  544. pr_info("%s: Unable to parse nlmsg\n", __func__);
  545. return ret;
  546. }
  547. iwpm_name = (char *)nla_data(nltb[IWPM_NLA_MAPINFO_ULIB_NAME]);
  548. iwpm_version = nla_get_u16(nltb[IWPM_NLA_MAPINFO_ULIB_VER]);
  549. if (strcmp(iwpm_ulib_name, iwpm_name) ||
  550. iwpm_version != iwpm_ulib_version) {
  551. pr_info("%s: Invalid port mapper name = %s version = %d\n",
  552. __func__, iwpm_name, iwpm_version);
  553. return ret;
  554. }
  555. nl_client = RDMA_NL_GET_CLIENT(cb->nlh->nlmsg_type);
  556. if (!iwpm_valid_client(nl_client)) {
  557. pr_info("%s: Invalid port mapper client = %d\n",
  558. __func__, nl_client);
  559. return ret;
  560. }
  561. iwpm_set_registered(nl_client, 0);
  562. atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
  563. if (!iwpm_mapinfo_available())
  564. return 0;
  565. iwpm_pid = cb->nlh->nlmsg_pid;
  566. pr_debug("%s: iWarp Port Mapper (pid = %d) is available!\n",
  567. __func__, iwpm_pid);
  568. ret = iwpm_send_mapinfo(nl_client, iwpm_pid);
  569. return ret;
  570. }
  571. EXPORT_SYMBOL(iwpm_mapping_info_cb);
  572. /* netlink attribute policy for the received mapping info ack */
  573. static const struct nla_policy ack_mapinfo_policy[IWPM_NLA_MAPINFO_NUM_MAX] = {
  574. [IWPM_NLA_MAPINFO_SEQ] = { .type = NLA_U32 },
  575. [IWPM_NLA_MAPINFO_SEND_NUM] = { .type = NLA_U32 },
  576. [IWPM_NLA_MAPINFO_ACK_NUM] = { .type = NLA_U32 }
  577. };
  578. /*
  579. * iwpm_ack_mapping_info_cb - Process a port mapper ack for
  580. * the provided mapping info records
  581. */
  582. int iwpm_ack_mapping_info_cb(struct sk_buff *skb, struct netlink_callback *cb)
  583. {
  584. struct nlattr *nltb[IWPM_NLA_MAPINFO_NUM_MAX];
  585. u32 mapinfo_send, mapinfo_ack;
  586. const char *msg_type = "Mapping Info Ack";
  587. if (iwpm_parse_nlmsg(cb, IWPM_NLA_MAPINFO_NUM_MAX,
  588. ack_mapinfo_policy, nltb, msg_type))
  589. return -EINVAL;
  590. mapinfo_send = nla_get_u32(nltb[IWPM_NLA_MAPINFO_SEND_NUM]);
  591. mapinfo_ack = nla_get_u32(nltb[IWPM_NLA_MAPINFO_ACK_NUM]);
  592. if (mapinfo_ack != mapinfo_send)
  593. pr_info("%s: Invalid mapinfo number (sent = %u ack-ed = %u)\n",
  594. __func__, mapinfo_send, mapinfo_ack);
  595. atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
  596. return 0;
  597. }
  598. EXPORT_SYMBOL(iwpm_ack_mapping_info_cb);
  599. /* netlink attribute policy for the received port mapper error message */
  600. static const struct nla_policy map_error_policy[IWPM_NLA_ERR_MAX] = {
  601. [IWPM_NLA_ERR_SEQ] = { .type = NLA_U32 },
  602. [IWPM_NLA_ERR_CODE] = { .type = NLA_U16 },
  603. };
  604. /*
  605. * iwpm_mapping_error_cb - Process a port mapper error message
  606. */
  607. int iwpm_mapping_error_cb(struct sk_buff *skb, struct netlink_callback *cb)
  608. {
  609. struct iwpm_nlmsg_request *nlmsg_request = NULL;
  610. int nl_client = RDMA_NL_GET_CLIENT(cb->nlh->nlmsg_type);
  611. struct nlattr *nltb[IWPM_NLA_ERR_MAX];
  612. u32 msg_seq;
  613. u16 err_code;
  614. const char *msg_type = "Mapping Error Msg";
  615. if (iwpm_parse_nlmsg(cb, IWPM_NLA_ERR_MAX,
  616. map_error_policy, nltb, msg_type))
  617. return -EINVAL;
  618. msg_seq = nla_get_u32(nltb[IWPM_NLA_ERR_SEQ]);
  619. err_code = nla_get_u16(nltb[IWPM_NLA_ERR_CODE]);
  620. pr_info("%s: Received msg seq = %u err code = %u client = %d\n",
  621. __func__, msg_seq, err_code, nl_client);
  622. /* look for nlmsg_request */
  623. nlmsg_request = iwpm_find_nlmsg_request(msg_seq);
  624. if (!nlmsg_request) {
  625. /* not all errors have associated requests */
  626. pr_debug("Could not find matching req (seq = %u)\n", msg_seq);
  627. return 0;
  628. }
  629. atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
  630. nlmsg_request->err_code = err_code;
  631. nlmsg_request->request_done = 1;
  632. /* always for found request */
  633. kref_put(&nlmsg_request->kref, iwpm_free_nlmsg_request);
  634. barrier();
  635. wake_up(&nlmsg_request->waitq);
  636. return 0;
  637. }
  638. EXPORT_SYMBOL(iwpm_mapping_error_cb);