iwpm_msg.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750
  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[IWPM_ULIBNAME_SIZE] = "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. /*
  43. * iwpm_register_pid - Send a netlink query to user space
  44. * for the iwarp port mapper pid
  45. *
  46. * nlmsg attributes:
  47. * [IWPM_NLA_REG_PID_SEQ]
  48. * [IWPM_NLA_REG_IF_NAME]
  49. * [IWPM_NLA_REG_IBDEV_NAME]
  50. * [IWPM_NLA_REG_ULIB_NAME]
  51. */
  52. int iwpm_register_pid(struct iwpm_dev_data *pm_msg, u8 nl_client)
  53. {
  54. struct sk_buff *skb = NULL;
  55. struct iwpm_nlmsg_request *nlmsg_request = NULL;
  56. struct nlmsghdr *nlh;
  57. u32 msg_seq;
  58. const char *err_str = "";
  59. int ret = -EINVAL;
  60. if (!iwpm_valid_client(nl_client)) {
  61. err_str = "Invalid port mapper client";
  62. goto pid_query_error;
  63. }
  64. if (iwpm_check_registration(nl_client, IWPM_REG_VALID) ||
  65. iwpm_user_pid == IWPM_PID_UNAVAILABLE)
  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, IFNAMSIZ,
  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. nlmsg_end(skb, nlh);
  97. pr_debug("%s: Multicasting a nlmsg (dev = %s ifname = %s iwpm = %s)\n",
  98. __func__, pm_msg->dev_name, pm_msg->if_name, iwpm_ulib_name);
  99. ret = rdma_nl_multicast(skb, RDMA_NL_GROUP_IWPM, GFP_KERNEL);
  100. if (ret) {
  101. skb = NULL; /* skb is freed in the netlink send-op handling */
  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. /*
  118. * iwpm_add_mapping - Send a netlink add mapping message
  119. * to the port mapper
  120. * nlmsg attributes:
  121. * [IWPM_NLA_MANAGE_MAPPING_SEQ]
  122. * [IWPM_NLA_MANAGE_ADDR]
  123. */
  124. int iwpm_add_mapping(struct iwpm_sa_data *pm_msg, u8 nl_client)
  125. {
  126. struct sk_buff *skb = NULL;
  127. struct iwpm_nlmsg_request *nlmsg_request = NULL;
  128. struct nlmsghdr *nlh;
  129. u32 msg_seq;
  130. const char *err_str = "";
  131. int ret = -EINVAL;
  132. if (!iwpm_valid_client(nl_client)) {
  133. err_str = "Invalid port mapper client";
  134. goto add_mapping_error;
  135. }
  136. if (!iwpm_valid_pid())
  137. return 0;
  138. if (!iwpm_check_registration(nl_client, IWPM_REG_VALID)) {
  139. err_str = "Unregistered port mapper client";
  140. goto add_mapping_error;
  141. }
  142. skb = iwpm_create_nlmsg(RDMA_NL_IWPM_ADD_MAPPING, &nlh, nl_client);
  143. if (!skb) {
  144. err_str = "Unable to create a nlmsg";
  145. goto add_mapping_error;
  146. }
  147. nlh->nlmsg_seq = iwpm_get_nlmsg_seq();
  148. nlmsg_request = iwpm_get_nlmsg_request(nlh->nlmsg_seq, nl_client, GFP_KERNEL);
  149. if (!nlmsg_request) {
  150. err_str = "Unable to allocate netlink request";
  151. goto add_mapping_error;
  152. }
  153. msg_seq = atomic_read(&echo_nlmsg_seq);
  154. /* fill in the add mapping message */
  155. err_str = "Unable to put attribute of the nlmsg";
  156. ret = ibnl_put_attr(skb, nlh, sizeof(u32), &msg_seq,
  157. IWPM_NLA_MANAGE_MAPPING_SEQ);
  158. if (ret)
  159. goto add_mapping_error;
  160. ret = ibnl_put_attr(skb, nlh, sizeof(struct sockaddr_storage),
  161. &pm_msg->loc_addr, IWPM_NLA_MANAGE_ADDR);
  162. if (ret)
  163. goto add_mapping_error;
  164. nlmsg_end(skb, nlh);
  165. nlmsg_request->req_buffer = pm_msg;
  166. ret = rdma_nl_unicast_wait(skb, 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. /*
  184. * iwpm_add_and_query_mapping - Send a netlink add and query
  185. * mapping message to the port mapper
  186. * nlmsg attributes:
  187. * [IWPM_NLA_QUERY_MAPPING_SEQ]
  188. * [IWPM_NLA_QUERY_LOCAL_ADDR]
  189. * [IWPM_NLA_QUERY_REMOTE_ADDR]
  190. */
  191. int iwpm_add_and_query_mapping(struct iwpm_sa_data *pm_msg, u8 nl_client)
  192. {
  193. struct sk_buff *skb = NULL;
  194. struct iwpm_nlmsg_request *nlmsg_request = NULL;
  195. struct nlmsghdr *nlh;
  196. u32 msg_seq;
  197. const char *err_str = "";
  198. int ret = -EINVAL;
  199. if (!iwpm_valid_client(nl_client)) {
  200. err_str = "Invalid port mapper client";
  201. goto query_mapping_error;
  202. }
  203. if (!iwpm_valid_pid())
  204. return 0;
  205. if (!iwpm_check_registration(nl_client, IWPM_REG_VALID)) {
  206. err_str = "Unregistered port mapper client";
  207. goto query_mapping_error;
  208. }
  209. ret = -ENOMEM;
  210. skb = iwpm_create_nlmsg(RDMA_NL_IWPM_QUERY_MAPPING, &nlh, nl_client);
  211. if (!skb) {
  212. err_str = "Unable to create a nlmsg";
  213. goto query_mapping_error;
  214. }
  215. nlh->nlmsg_seq = iwpm_get_nlmsg_seq();
  216. nlmsg_request = iwpm_get_nlmsg_request(nlh->nlmsg_seq,
  217. nl_client, GFP_KERNEL);
  218. if (!nlmsg_request) {
  219. err_str = "Unable to allocate netlink request";
  220. goto query_mapping_error;
  221. }
  222. msg_seq = atomic_read(&echo_nlmsg_seq);
  223. /* fill in the query message */
  224. err_str = "Unable to put attribute of the nlmsg";
  225. ret = ibnl_put_attr(skb, nlh, sizeof(u32), &msg_seq,
  226. IWPM_NLA_QUERY_MAPPING_SEQ);
  227. if (ret)
  228. goto query_mapping_error;
  229. ret = ibnl_put_attr(skb, nlh, sizeof(struct sockaddr_storage),
  230. &pm_msg->loc_addr, IWPM_NLA_QUERY_LOCAL_ADDR);
  231. if (ret)
  232. goto query_mapping_error;
  233. ret = ibnl_put_attr(skb, nlh, sizeof(struct sockaddr_storage),
  234. &pm_msg->rem_addr, IWPM_NLA_QUERY_REMOTE_ADDR);
  235. if (ret)
  236. goto query_mapping_error;
  237. nlmsg_end(skb, nlh);
  238. nlmsg_request->req_buffer = pm_msg;
  239. ret = rdma_nl_unicast_wait(skb, 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. /*
  256. * iwpm_remove_mapping - Send a netlink remove mapping message
  257. * to the port mapper
  258. * nlmsg attributes:
  259. * [IWPM_NLA_MANAGE_MAPPING_SEQ]
  260. * [IWPM_NLA_MANAGE_ADDR]
  261. */
  262. int iwpm_remove_mapping(struct sockaddr_storage *local_addr, u8 nl_client)
  263. {
  264. struct sk_buff *skb = NULL;
  265. struct nlmsghdr *nlh;
  266. u32 msg_seq;
  267. const char *err_str = "";
  268. int ret = -EINVAL;
  269. if (!iwpm_valid_client(nl_client)) {
  270. err_str = "Invalid port mapper client";
  271. goto remove_mapping_error;
  272. }
  273. if (!iwpm_valid_pid())
  274. return 0;
  275. if (iwpm_check_registration(nl_client, IWPM_REG_UNDEF)) {
  276. err_str = "Unregistered port mapper client";
  277. goto remove_mapping_error;
  278. }
  279. skb = iwpm_create_nlmsg(RDMA_NL_IWPM_REMOVE_MAPPING, &nlh, nl_client);
  280. if (!skb) {
  281. ret = -ENOMEM;
  282. err_str = "Unable to create a nlmsg";
  283. goto remove_mapping_error;
  284. }
  285. msg_seq = atomic_read(&echo_nlmsg_seq);
  286. nlh->nlmsg_seq = iwpm_get_nlmsg_seq();
  287. err_str = "Unable to put attribute of the nlmsg";
  288. ret = ibnl_put_attr(skb, nlh, sizeof(u32), &msg_seq,
  289. IWPM_NLA_MANAGE_MAPPING_SEQ);
  290. if (ret)
  291. goto remove_mapping_error;
  292. ret = ibnl_put_attr(skb, nlh, sizeof(struct sockaddr_storage),
  293. local_addr, IWPM_NLA_MANAGE_ADDR);
  294. if (ret)
  295. goto remove_mapping_error;
  296. nlmsg_end(skb, nlh);
  297. ret = rdma_nl_unicast_wait(skb, 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. /* netlink attribute policy for the received response to register pid request */
  314. static const struct nla_policy resp_reg_policy[IWPM_NLA_RREG_PID_MAX] = {
  315. [IWPM_NLA_RREG_PID_SEQ] = { .type = NLA_U32 },
  316. [IWPM_NLA_RREG_IBDEV_NAME] = { .type = NLA_STRING,
  317. .len = IWPM_DEVNAME_SIZE - 1 },
  318. [IWPM_NLA_RREG_ULIB_NAME] = { .type = NLA_STRING,
  319. .len = IWPM_ULIBNAME_SIZE - 1 },
  320. [IWPM_NLA_RREG_ULIB_VER] = { .type = NLA_U16 },
  321. [IWPM_NLA_RREG_PID_ERR] = { .type = NLA_U16 }
  322. };
  323. /*
  324. * iwpm_register_pid_cb - Process a port mapper response to
  325. * iwpm_register_pid()
  326. */
  327. int iwpm_register_pid_cb(struct sk_buff *skb, struct netlink_callback *cb)
  328. {
  329. struct iwpm_nlmsg_request *nlmsg_request = NULL;
  330. struct nlattr *nltb[IWPM_NLA_RREG_PID_MAX];
  331. struct iwpm_dev_data *pm_msg;
  332. char *dev_name, *iwpm_name;
  333. u32 msg_seq;
  334. u8 nl_client;
  335. u16 iwpm_version;
  336. const char *msg_type = "Register Pid response";
  337. if (iwpm_parse_nlmsg(cb, IWPM_NLA_RREG_PID_MAX,
  338. resp_reg_policy, nltb, msg_type))
  339. return -EINVAL;
  340. msg_seq = nla_get_u32(nltb[IWPM_NLA_RREG_PID_SEQ]);
  341. nlmsg_request = iwpm_find_nlmsg_request(msg_seq);
  342. if (!nlmsg_request) {
  343. pr_info("%s: Could not find a matching request (seq = %u)\n",
  344. __func__, msg_seq);
  345. return -EINVAL;
  346. }
  347. pm_msg = nlmsg_request->req_buffer;
  348. nl_client = nlmsg_request->nl_client;
  349. dev_name = (char *)nla_data(nltb[IWPM_NLA_RREG_IBDEV_NAME]);
  350. iwpm_name = (char *)nla_data(nltb[IWPM_NLA_RREG_ULIB_NAME]);
  351. iwpm_version = nla_get_u16(nltb[IWPM_NLA_RREG_ULIB_VER]);
  352. /* check device name, ulib name and version */
  353. if (strcmp(pm_msg->dev_name, dev_name) ||
  354. strcmp(iwpm_ulib_name, iwpm_name) ||
  355. iwpm_version != iwpm_ulib_version) {
  356. pr_info("%s: Incorrect info (dev = %s name = %s version = %d)\n",
  357. __func__, dev_name, iwpm_name, iwpm_version);
  358. nlmsg_request->err_code = IWPM_USER_LIB_INFO_ERR;
  359. goto register_pid_response_exit;
  360. }
  361. iwpm_user_pid = cb->nlh->nlmsg_pid;
  362. atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
  363. pr_debug("%s: iWarp Port Mapper (pid = %d) is available!\n",
  364. __func__, iwpm_user_pid);
  365. if (iwpm_valid_client(nl_client))
  366. iwpm_set_registration(nl_client, IWPM_REG_VALID);
  367. register_pid_response_exit:
  368. nlmsg_request->request_done = 1;
  369. /* always for found nlmsg_request */
  370. kref_put(&nlmsg_request->kref, iwpm_free_nlmsg_request);
  371. barrier();
  372. up(&nlmsg_request->sem);
  373. return 0;
  374. }
  375. /* netlink attribute policy for the received response to add mapping request */
  376. static const struct nla_policy resp_add_policy[IWPM_NLA_RMANAGE_MAPPING_MAX] = {
  377. [IWPM_NLA_MANAGE_MAPPING_SEQ] = { .type = NLA_U32 },
  378. [IWPM_NLA_MANAGE_ADDR] = { .len = sizeof(struct sockaddr_storage) },
  379. [IWPM_NLA_MANAGE_MAPPED_LOC_ADDR] = { .len = sizeof(struct sockaddr_storage) },
  380. [IWPM_NLA_RMANAGE_MAPPING_ERR] = { .type = NLA_U16 }
  381. };
  382. /*
  383. * iwpm_add_mapping_cb - Process a port mapper response to
  384. * iwpm_add_mapping()
  385. */
  386. int iwpm_add_mapping_cb(struct sk_buff *skb, struct netlink_callback *cb)
  387. {
  388. struct iwpm_sa_data *pm_msg;
  389. struct iwpm_nlmsg_request *nlmsg_request = NULL;
  390. struct nlattr *nltb[IWPM_NLA_RMANAGE_MAPPING_MAX];
  391. struct sockaddr_storage *local_sockaddr;
  392. struct sockaddr_storage *mapped_sockaddr;
  393. const char *msg_type;
  394. u32 msg_seq;
  395. msg_type = "Add Mapping response";
  396. if (iwpm_parse_nlmsg(cb, IWPM_NLA_RMANAGE_MAPPING_MAX,
  397. resp_add_policy, nltb, msg_type))
  398. return -EINVAL;
  399. atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
  400. msg_seq = nla_get_u32(nltb[IWPM_NLA_MANAGE_MAPPING_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. local_sockaddr = (struct sockaddr_storage *)
  409. nla_data(nltb[IWPM_NLA_MANAGE_ADDR]);
  410. mapped_sockaddr = (struct sockaddr_storage *)
  411. nla_data(nltb[IWPM_NLA_MANAGE_MAPPED_LOC_ADDR]);
  412. if (iwpm_compare_sockaddr(local_sockaddr, &pm_msg->loc_addr)) {
  413. nlmsg_request->err_code = IWPM_USER_LIB_INFO_ERR;
  414. goto add_mapping_response_exit;
  415. }
  416. if (mapped_sockaddr->ss_family != local_sockaddr->ss_family) {
  417. pr_info("%s: Sockaddr family doesn't match the requested one\n",
  418. __func__);
  419. nlmsg_request->err_code = IWPM_USER_LIB_INFO_ERR;
  420. goto add_mapping_response_exit;
  421. }
  422. memcpy(&pm_msg->mapped_loc_addr, mapped_sockaddr,
  423. sizeof(*mapped_sockaddr));
  424. iwpm_print_sockaddr(&pm_msg->loc_addr,
  425. "add_mapping: Local sockaddr:");
  426. iwpm_print_sockaddr(&pm_msg->mapped_loc_addr,
  427. "add_mapping: Mapped local sockaddr:");
  428. add_mapping_response_exit:
  429. nlmsg_request->request_done = 1;
  430. /* always for found request */
  431. kref_put(&nlmsg_request->kref, iwpm_free_nlmsg_request);
  432. barrier();
  433. up(&nlmsg_request->sem);
  434. return 0;
  435. }
  436. /* netlink attribute policy for the response to add and query mapping request
  437. * and response with remote address info */
  438. static const struct nla_policy resp_query_policy[IWPM_NLA_RQUERY_MAPPING_MAX] = {
  439. [IWPM_NLA_QUERY_MAPPING_SEQ] = { .type = NLA_U32 },
  440. [IWPM_NLA_QUERY_LOCAL_ADDR] = { .len = sizeof(struct sockaddr_storage) },
  441. [IWPM_NLA_QUERY_REMOTE_ADDR] = { .len = sizeof(struct sockaddr_storage) },
  442. [IWPM_NLA_RQUERY_MAPPED_LOC_ADDR] = { .len = sizeof(struct sockaddr_storage) },
  443. [IWPM_NLA_RQUERY_MAPPED_REM_ADDR] = { .len = sizeof(struct sockaddr_storage) },
  444. [IWPM_NLA_RQUERY_MAPPING_ERR] = { .type = NLA_U16 }
  445. };
  446. /*
  447. * iwpm_add_and_query_mapping_cb - Process a port mapper response to
  448. * iwpm_add_and_query_mapping()
  449. */
  450. int iwpm_add_and_query_mapping_cb(struct sk_buff *skb,
  451. struct netlink_callback *cb)
  452. {
  453. struct iwpm_sa_data *pm_msg;
  454. struct iwpm_nlmsg_request *nlmsg_request = NULL;
  455. struct nlattr *nltb[IWPM_NLA_RQUERY_MAPPING_MAX];
  456. struct sockaddr_storage *local_sockaddr, *remote_sockaddr;
  457. struct sockaddr_storage *mapped_loc_sockaddr, *mapped_rem_sockaddr;
  458. const char *msg_type;
  459. u32 msg_seq;
  460. u16 err_code;
  461. msg_type = "Query Mapping response";
  462. if (iwpm_parse_nlmsg(cb, IWPM_NLA_RQUERY_MAPPING_MAX,
  463. resp_query_policy, nltb, msg_type))
  464. return -EINVAL;
  465. atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
  466. msg_seq = nla_get_u32(nltb[IWPM_NLA_QUERY_MAPPING_SEQ]);
  467. nlmsg_request = iwpm_find_nlmsg_request(msg_seq);
  468. if (!nlmsg_request) {
  469. pr_info("%s: Could not find a matching request (seq = %u)\n",
  470. __func__, msg_seq);
  471. return -EINVAL;
  472. }
  473. pm_msg = nlmsg_request->req_buffer;
  474. local_sockaddr = (struct sockaddr_storage *)
  475. nla_data(nltb[IWPM_NLA_QUERY_LOCAL_ADDR]);
  476. remote_sockaddr = (struct sockaddr_storage *)
  477. nla_data(nltb[IWPM_NLA_QUERY_REMOTE_ADDR]);
  478. mapped_loc_sockaddr = (struct sockaddr_storage *)
  479. nla_data(nltb[IWPM_NLA_RQUERY_MAPPED_LOC_ADDR]);
  480. mapped_rem_sockaddr = (struct sockaddr_storage *)
  481. nla_data(nltb[IWPM_NLA_RQUERY_MAPPED_REM_ADDR]);
  482. err_code = nla_get_u16(nltb[IWPM_NLA_RQUERY_MAPPING_ERR]);
  483. if (err_code == IWPM_REMOTE_QUERY_REJECT) {
  484. pr_info("%s: Received a Reject (pid = %u, echo seq = %u)\n",
  485. __func__, cb->nlh->nlmsg_pid, msg_seq);
  486. nlmsg_request->err_code = IWPM_REMOTE_QUERY_REJECT;
  487. }
  488. if (iwpm_compare_sockaddr(local_sockaddr, &pm_msg->loc_addr) ||
  489. iwpm_compare_sockaddr(remote_sockaddr, &pm_msg->rem_addr)) {
  490. pr_info("%s: Incorrect local sockaddr\n", __func__);
  491. nlmsg_request->err_code = IWPM_USER_LIB_INFO_ERR;
  492. goto query_mapping_response_exit;
  493. }
  494. if (mapped_loc_sockaddr->ss_family != local_sockaddr->ss_family ||
  495. mapped_rem_sockaddr->ss_family != remote_sockaddr->ss_family) {
  496. pr_info("%s: Sockaddr family doesn't match the requested one\n",
  497. __func__);
  498. nlmsg_request->err_code = IWPM_USER_LIB_INFO_ERR;
  499. goto query_mapping_response_exit;
  500. }
  501. memcpy(&pm_msg->mapped_loc_addr, mapped_loc_sockaddr,
  502. sizeof(*mapped_loc_sockaddr));
  503. memcpy(&pm_msg->mapped_rem_addr, mapped_rem_sockaddr,
  504. sizeof(*mapped_rem_sockaddr));
  505. iwpm_print_sockaddr(&pm_msg->loc_addr,
  506. "query_mapping: Local sockaddr:");
  507. iwpm_print_sockaddr(&pm_msg->mapped_loc_addr,
  508. "query_mapping: Mapped local sockaddr:");
  509. iwpm_print_sockaddr(&pm_msg->rem_addr,
  510. "query_mapping: Remote sockaddr:");
  511. iwpm_print_sockaddr(&pm_msg->mapped_rem_addr,
  512. "query_mapping: Mapped remote sockaddr:");
  513. query_mapping_response_exit:
  514. nlmsg_request->request_done = 1;
  515. /* always for found request */
  516. kref_put(&nlmsg_request->kref, iwpm_free_nlmsg_request);
  517. barrier();
  518. up(&nlmsg_request->sem);
  519. return 0;
  520. }
  521. /*
  522. * iwpm_remote_info_cb - Process a port mapper message, containing
  523. * the remote connecting peer address info
  524. */
  525. int iwpm_remote_info_cb(struct sk_buff *skb, struct netlink_callback *cb)
  526. {
  527. struct nlattr *nltb[IWPM_NLA_RQUERY_MAPPING_MAX];
  528. struct sockaddr_storage *local_sockaddr, *remote_sockaddr;
  529. struct sockaddr_storage *mapped_loc_sockaddr, *mapped_rem_sockaddr;
  530. struct iwpm_remote_info *rem_info;
  531. const char *msg_type;
  532. u8 nl_client;
  533. int ret = -EINVAL;
  534. msg_type = "Remote Mapping info";
  535. if (iwpm_parse_nlmsg(cb, IWPM_NLA_RQUERY_MAPPING_MAX,
  536. resp_query_policy, nltb, msg_type))
  537. return ret;
  538. nl_client = RDMA_NL_GET_CLIENT(cb->nlh->nlmsg_type);
  539. if (!iwpm_valid_client(nl_client)) {
  540. pr_info("%s: Invalid port mapper client = %d\n",
  541. __func__, nl_client);
  542. return ret;
  543. }
  544. atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
  545. local_sockaddr = (struct sockaddr_storage *)
  546. nla_data(nltb[IWPM_NLA_QUERY_LOCAL_ADDR]);
  547. remote_sockaddr = (struct sockaddr_storage *)
  548. nla_data(nltb[IWPM_NLA_QUERY_REMOTE_ADDR]);
  549. mapped_loc_sockaddr = (struct sockaddr_storage *)
  550. nla_data(nltb[IWPM_NLA_RQUERY_MAPPED_LOC_ADDR]);
  551. mapped_rem_sockaddr = (struct sockaddr_storage *)
  552. nla_data(nltb[IWPM_NLA_RQUERY_MAPPED_REM_ADDR]);
  553. if (mapped_loc_sockaddr->ss_family != local_sockaddr->ss_family ||
  554. mapped_rem_sockaddr->ss_family != remote_sockaddr->ss_family) {
  555. pr_info("%s: Sockaddr family doesn't match the requested one\n",
  556. __func__);
  557. return ret;
  558. }
  559. rem_info = kzalloc(sizeof(struct iwpm_remote_info), GFP_ATOMIC);
  560. if (!rem_info) {
  561. ret = -ENOMEM;
  562. return ret;
  563. }
  564. memcpy(&rem_info->mapped_loc_sockaddr, mapped_loc_sockaddr,
  565. sizeof(struct sockaddr_storage));
  566. memcpy(&rem_info->remote_sockaddr, remote_sockaddr,
  567. sizeof(struct sockaddr_storage));
  568. memcpy(&rem_info->mapped_rem_sockaddr, mapped_rem_sockaddr,
  569. sizeof(struct sockaddr_storage));
  570. rem_info->nl_client = nl_client;
  571. iwpm_add_remote_info(rem_info);
  572. iwpm_print_sockaddr(local_sockaddr,
  573. "remote_info: Local sockaddr:");
  574. iwpm_print_sockaddr(mapped_loc_sockaddr,
  575. "remote_info: Mapped local sockaddr:");
  576. iwpm_print_sockaddr(remote_sockaddr,
  577. "remote_info: Remote sockaddr:");
  578. iwpm_print_sockaddr(mapped_rem_sockaddr,
  579. "remote_info: Mapped remote sockaddr:");
  580. return ret;
  581. }
  582. /* netlink attribute policy for the received request for mapping info */
  583. static const struct nla_policy resp_mapinfo_policy[IWPM_NLA_MAPINFO_REQ_MAX] = {
  584. [IWPM_NLA_MAPINFO_ULIB_NAME] = { .type = NLA_STRING,
  585. .len = IWPM_ULIBNAME_SIZE - 1 },
  586. [IWPM_NLA_MAPINFO_ULIB_VER] = { .type = NLA_U16 }
  587. };
  588. /*
  589. * iwpm_mapping_info_cb - Process a port mapper request for mapping info
  590. */
  591. int iwpm_mapping_info_cb(struct sk_buff *skb, struct netlink_callback *cb)
  592. {
  593. struct nlattr *nltb[IWPM_NLA_MAPINFO_REQ_MAX];
  594. const char *msg_type = "Mapping Info response";
  595. u8 nl_client;
  596. char *iwpm_name;
  597. u16 iwpm_version;
  598. int ret = -EINVAL;
  599. if (iwpm_parse_nlmsg(cb, IWPM_NLA_MAPINFO_REQ_MAX,
  600. resp_mapinfo_policy, nltb, msg_type)) {
  601. pr_info("%s: Unable to parse nlmsg\n", __func__);
  602. return ret;
  603. }
  604. iwpm_name = (char *)nla_data(nltb[IWPM_NLA_MAPINFO_ULIB_NAME]);
  605. iwpm_version = nla_get_u16(nltb[IWPM_NLA_MAPINFO_ULIB_VER]);
  606. if (strcmp(iwpm_ulib_name, iwpm_name) ||
  607. iwpm_version != iwpm_ulib_version) {
  608. pr_info("%s: Invalid port mapper name = %s version = %d\n",
  609. __func__, iwpm_name, iwpm_version);
  610. return ret;
  611. }
  612. nl_client = RDMA_NL_GET_CLIENT(cb->nlh->nlmsg_type);
  613. if (!iwpm_valid_client(nl_client)) {
  614. pr_info("%s: Invalid port mapper client = %d\n",
  615. __func__, nl_client);
  616. return ret;
  617. }
  618. iwpm_set_registration(nl_client, IWPM_REG_INCOMPL);
  619. atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
  620. iwpm_user_pid = cb->nlh->nlmsg_pid;
  621. if (!iwpm_mapinfo_available())
  622. return 0;
  623. pr_debug("%s: iWarp Port Mapper (pid = %d) is available!\n",
  624. __func__, iwpm_user_pid);
  625. ret = iwpm_send_mapinfo(nl_client, iwpm_user_pid);
  626. return ret;
  627. }
  628. /* netlink attribute policy for the received mapping info ack */
  629. static const struct nla_policy ack_mapinfo_policy[IWPM_NLA_MAPINFO_NUM_MAX] = {
  630. [IWPM_NLA_MAPINFO_SEQ] = { .type = NLA_U32 },
  631. [IWPM_NLA_MAPINFO_SEND_NUM] = { .type = NLA_U32 },
  632. [IWPM_NLA_MAPINFO_ACK_NUM] = { .type = NLA_U32 }
  633. };
  634. /*
  635. * iwpm_ack_mapping_info_cb - Process a port mapper ack for
  636. * the provided mapping info records
  637. */
  638. int iwpm_ack_mapping_info_cb(struct sk_buff *skb, struct netlink_callback *cb)
  639. {
  640. struct nlattr *nltb[IWPM_NLA_MAPINFO_NUM_MAX];
  641. u32 mapinfo_send, mapinfo_ack;
  642. const char *msg_type = "Mapping Info Ack";
  643. if (iwpm_parse_nlmsg(cb, IWPM_NLA_MAPINFO_NUM_MAX,
  644. ack_mapinfo_policy, nltb, msg_type))
  645. return -EINVAL;
  646. mapinfo_send = nla_get_u32(nltb[IWPM_NLA_MAPINFO_SEND_NUM]);
  647. mapinfo_ack = nla_get_u32(nltb[IWPM_NLA_MAPINFO_ACK_NUM]);
  648. if (mapinfo_ack != mapinfo_send)
  649. pr_info("%s: Invalid mapinfo number (sent = %u ack-ed = %u)\n",
  650. __func__, mapinfo_send, mapinfo_ack);
  651. atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
  652. return 0;
  653. }
  654. /* netlink attribute policy for the received port mapper error message */
  655. static const struct nla_policy map_error_policy[IWPM_NLA_ERR_MAX] = {
  656. [IWPM_NLA_ERR_SEQ] = { .type = NLA_U32 },
  657. [IWPM_NLA_ERR_CODE] = { .type = NLA_U16 },
  658. };
  659. /*
  660. * iwpm_mapping_error_cb - Process a port mapper error message
  661. */
  662. int iwpm_mapping_error_cb(struct sk_buff *skb, struct netlink_callback *cb)
  663. {
  664. struct iwpm_nlmsg_request *nlmsg_request = NULL;
  665. int nl_client = RDMA_NL_GET_CLIENT(cb->nlh->nlmsg_type);
  666. struct nlattr *nltb[IWPM_NLA_ERR_MAX];
  667. u32 msg_seq;
  668. u16 err_code;
  669. const char *msg_type = "Mapping Error Msg";
  670. if (iwpm_parse_nlmsg(cb, IWPM_NLA_ERR_MAX,
  671. map_error_policy, nltb, msg_type))
  672. return -EINVAL;
  673. msg_seq = nla_get_u32(nltb[IWPM_NLA_ERR_SEQ]);
  674. err_code = nla_get_u16(nltb[IWPM_NLA_ERR_CODE]);
  675. pr_info("%s: Received msg seq = %u err code = %u client = %d\n",
  676. __func__, msg_seq, err_code, nl_client);
  677. /* look for nlmsg_request */
  678. nlmsg_request = iwpm_find_nlmsg_request(msg_seq);
  679. if (!nlmsg_request) {
  680. /* not all errors have associated requests */
  681. pr_debug("Could not find matching req (seq = %u)\n", msg_seq);
  682. return 0;
  683. }
  684. atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
  685. nlmsg_request->err_code = err_code;
  686. nlmsg_request->request_done = 1;
  687. /* always for found request */
  688. kref_put(&nlmsg_request->kref, iwpm_free_nlmsg_request);
  689. barrier();
  690. up(&nlmsg_request->sem);
  691. return 0;
  692. }