op-msg.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Linux WiMAX
  4. * Generic messaging interface between userspace and driver/device
  5. *
  6. * Copyright (C) 2007-2008 Intel Corporation <linux-wimax@intel.com>
  7. * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
  8. *
  9. * This implements a direct communication channel between user space and
  10. * the driver/device, by which free form messages can be sent back and
  11. * forth.
  12. *
  13. * This is intended for device-specific features, vendor quirks, etc.
  14. *
  15. * See include/net/wimax.h
  16. *
  17. * GENERIC NETLINK ENCODING AND CAPACITY
  18. *
  19. * A destination "pipe name" is added to each message; it is up to the
  20. * drivers to assign or use those names (if using them at all).
  21. *
  22. * Messages are encoded as a binary netlink attribute using nla_put()
  23. * using type NLA_UNSPEC (as some versions of libnl still in
  24. * deployment don't yet understand NLA_BINARY).
  25. *
  26. * The maximum capacity of this transport is PAGESIZE per message (so
  27. * the actual payload will be bit smaller depending on the
  28. * netlink/generic netlink attributes and headers).
  29. *
  30. * RECEPTION OF MESSAGES
  31. *
  32. * When a message is received from user space, it is passed verbatim
  33. * to the driver calling wimax_dev->op_msg_from_user(). The return
  34. * value from this function is passed back to user space as an ack
  35. * over the generic netlink protocol.
  36. *
  37. * The stack doesn't do any processing or interpretation of these
  38. * messages.
  39. *
  40. * SENDING MESSAGES
  41. *
  42. * Messages can be sent with wimax_msg().
  43. *
  44. * If the message delivery needs to happen on a different context to
  45. * that of its creation, wimax_msg_alloc() can be used to get a
  46. * pointer to the message that can be delivered later on with
  47. * wimax_msg_send().
  48. *
  49. * ROADMAP
  50. *
  51. * wimax_gnl_doit_msg_from_user() Process a message from user space
  52. * wimax_dev_get_by_genl_info()
  53. * wimax_dev->op_msg_from_user() Delivery of message to the driver
  54. *
  55. * wimax_msg() Send a message to user space
  56. * wimax_msg_alloc()
  57. * wimax_msg_send()
  58. */
  59. #include <linux/device.h>
  60. #include <linux/slab.h>
  61. #include <net/genetlink.h>
  62. #include <linux/netdevice.h>
  63. #include <linux/wimax.h>
  64. #include <linux/security.h>
  65. #include <linux/export.h>
  66. #include "wimax-internal.h"
  67. #define D_SUBMODULE op_msg
  68. #include "debug-levels.h"
  69. /**
  70. * wimax_msg_alloc - Create a new skb for sending a message to userspace
  71. *
  72. * @wimax_dev: WiMAX device descriptor
  73. * @pipe_name: "named pipe" the message will be sent to
  74. * @msg: pointer to the message data to send
  75. * @size: size of the message to send (in bytes), including the header.
  76. * @gfp_flags: flags for memory allocation.
  77. *
  78. * Returns: %0 if ok, negative errno code on error
  79. *
  80. * Description:
  81. *
  82. * Allocates an skb that will contain the message to send to user
  83. * space over the messaging pipe and initializes it, copying the
  84. * payload.
  85. *
  86. * Once this call is done, you can deliver it with
  87. * wimax_msg_send().
  88. *
  89. * IMPORTANT:
  90. *
  91. * Don't use skb_push()/skb_pull()/skb_reserve() on the skb, as
  92. * wimax_msg_send() depends on skb->data being placed at the
  93. * beginning of the user message.
  94. *
  95. * Unlike other WiMAX stack calls, this call can be used way early,
  96. * even before wimax_dev_add() is called, as long as the
  97. * wimax_dev->net_dev pointer is set to point to a proper
  98. * net_dev. This is so that drivers can use it early in case they need
  99. * to send stuff around or communicate with user space.
  100. */
  101. struct sk_buff *wimax_msg_alloc(struct wimax_dev *wimax_dev,
  102. const char *pipe_name,
  103. const void *msg, size_t size,
  104. gfp_t gfp_flags)
  105. {
  106. int result;
  107. struct device *dev = wimax_dev_to_dev(wimax_dev);
  108. size_t msg_size;
  109. void *genl_msg;
  110. struct sk_buff *skb;
  111. msg_size = nla_total_size(size)
  112. + nla_total_size(sizeof(u32))
  113. + (pipe_name ? nla_total_size(strlen(pipe_name)) : 0);
  114. result = -ENOMEM;
  115. skb = genlmsg_new(msg_size, gfp_flags);
  116. if (skb == NULL)
  117. goto error_new;
  118. genl_msg = genlmsg_put(skb, 0, 0, &wimax_gnl_family,
  119. 0, WIMAX_GNL_OP_MSG_TO_USER);
  120. if (genl_msg == NULL) {
  121. dev_err(dev, "no memory to create generic netlink message\n");
  122. goto error_genlmsg_put;
  123. }
  124. result = nla_put_u32(skb, WIMAX_GNL_MSG_IFIDX,
  125. wimax_dev->net_dev->ifindex);
  126. if (result < 0) {
  127. dev_err(dev, "no memory to add ifindex attribute\n");
  128. goto error_nla_put;
  129. }
  130. if (pipe_name) {
  131. result = nla_put_string(skb, WIMAX_GNL_MSG_PIPE_NAME,
  132. pipe_name);
  133. if (result < 0) {
  134. dev_err(dev, "no memory to add pipe_name attribute\n");
  135. goto error_nla_put;
  136. }
  137. }
  138. result = nla_put(skb, WIMAX_GNL_MSG_DATA, size, msg);
  139. if (result < 0) {
  140. dev_err(dev, "no memory to add payload (msg %p size %zu) in "
  141. "attribute: %d\n", msg, size, result);
  142. goto error_nla_put;
  143. }
  144. genlmsg_end(skb, genl_msg);
  145. return skb;
  146. error_nla_put:
  147. error_genlmsg_put:
  148. error_new:
  149. nlmsg_free(skb);
  150. return ERR_PTR(result);
  151. }
  152. EXPORT_SYMBOL_GPL(wimax_msg_alloc);
  153. /**
  154. * wimax_msg_data_len - Return a pointer and size of a message's payload
  155. *
  156. * @msg: Pointer to a message created with wimax_msg_alloc()
  157. * @size: Pointer to where to store the message's size
  158. *
  159. * Returns the pointer to the message data.
  160. */
  161. const void *wimax_msg_data_len(struct sk_buff *msg, size_t *size)
  162. {
  163. struct nlmsghdr *nlh = (void *) msg->head;
  164. struct nlattr *nla;
  165. nla = nlmsg_find_attr(nlh, sizeof(struct genlmsghdr),
  166. WIMAX_GNL_MSG_DATA);
  167. if (nla == NULL) {
  168. pr_err("Cannot find attribute WIMAX_GNL_MSG_DATA\n");
  169. return NULL;
  170. }
  171. *size = nla_len(nla);
  172. return nla_data(nla);
  173. }
  174. EXPORT_SYMBOL_GPL(wimax_msg_data_len);
  175. /**
  176. * wimax_msg_data - Return a pointer to a message's payload
  177. *
  178. * @msg: Pointer to a message created with wimax_msg_alloc()
  179. */
  180. const void *wimax_msg_data(struct sk_buff *msg)
  181. {
  182. struct nlmsghdr *nlh = (void *) msg->head;
  183. struct nlattr *nla;
  184. nla = nlmsg_find_attr(nlh, sizeof(struct genlmsghdr),
  185. WIMAX_GNL_MSG_DATA);
  186. if (nla == NULL) {
  187. pr_err("Cannot find attribute WIMAX_GNL_MSG_DATA\n");
  188. return NULL;
  189. }
  190. return nla_data(nla);
  191. }
  192. EXPORT_SYMBOL_GPL(wimax_msg_data);
  193. /**
  194. * wimax_msg_len - Return a message's payload length
  195. *
  196. * @msg: Pointer to a message created with wimax_msg_alloc()
  197. */
  198. ssize_t wimax_msg_len(struct sk_buff *msg)
  199. {
  200. struct nlmsghdr *nlh = (void *) msg->head;
  201. struct nlattr *nla;
  202. nla = nlmsg_find_attr(nlh, sizeof(struct genlmsghdr),
  203. WIMAX_GNL_MSG_DATA);
  204. if (nla == NULL) {
  205. pr_err("Cannot find attribute WIMAX_GNL_MSG_DATA\n");
  206. return -EINVAL;
  207. }
  208. return nla_len(nla);
  209. }
  210. EXPORT_SYMBOL_GPL(wimax_msg_len);
  211. /**
  212. * wimax_msg_send - Send a pre-allocated message to user space
  213. *
  214. * @wimax_dev: WiMAX device descriptor
  215. *
  216. * @skb: &struct sk_buff returned by wimax_msg_alloc(). Note the
  217. * ownership of @skb is transferred to this function.
  218. *
  219. * Returns: 0 if ok, < 0 errno code on error
  220. *
  221. * Description:
  222. *
  223. * Sends a free-form message that was preallocated with
  224. * wimax_msg_alloc() and filled up.
  225. *
  226. * Assumes that once you pass an skb to this function for sending, it
  227. * owns it and will release it when done (on success).
  228. *
  229. * IMPORTANT:
  230. *
  231. * Don't use skb_push()/skb_pull()/skb_reserve() on the skb, as
  232. * wimax_msg_send() depends on skb->data being placed at the
  233. * beginning of the user message.
  234. *
  235. * Unlike other WiMAX stack calls, this call can be used way early,
  236. * even before wimax_dev_add() is called, as long as the
  237. * wimax_dev->net_dev pointer is set to point to a proper
  238. * net_dev. This is so that drivers can use it early in case they need
  239. * to send stuff around or communicate with user space.
  240. */
  241. int wimax_msg_send(struct wimax_dev *wimax_dev, struct sk_buff *skb)
  242. {
  243. struct device *dev = wimax_dev_to_dev(wimax_dev);
  244. void *msg = skb->data;
  245. size_t size = skb->len;
  246. might_sleep();
  247. d_printf(1, dev, "CTX: wimax msg, %zu bytes\n", size);
  248. d_dump(2, dev, msg, size);
  249. genlmsg_multicast(&wimax_gnl_family, skb, 0, 0, GFP_KERNEL);
  250. d_printf(1, dev, "CTX: genl multicast done\n");
  251. return 0;
  252. }
  253. EXPORT_SYMBOL_GPL(wimax_msg_send);
  254. /**
  255. * wimax_msg - Send a message to user space
  256. *
  257. * @wimax_dev: WiMAX device descriptor (properly referenced)
  258. * @pipe_name: "named pipe" the message will be sent to
  259. * @buf: pointer to the message to send.
  260. * @size: size of the buffer pointed to by @buf (in bytes).
  261. * @gfp_flags: flags for memory allocation.
  262. *
  263. * Returns: %0 if ok, negative errno code on error.
  264. *
  265. * Description:
  266. *
  267. * Sends a free-form message to user space on the device @wimax_dev.
  268. *
  269. * NOTES:
  270. *
  271. * Once the @skb is given to this function, who will own it and will
  272. * release it when done (unless it returns error).
  273. */
  274. int wimax_msg(struct wimax_dev *wimax_dev, const char *pipe_name,
  275. const void *buf, size_t size, gfp_t gfp_flags)
  276. {
  277. int result = -ENOMEM;
  278. struct sk_buff *skb;
  279. skb = wimax_msg_alloc(wimax_dev, pipe_name, buf, size, gfp_flags);
  280. if (IS_ERR(skb))
  281. result = PTR_ERR(skb);
  282. else
  283. result = wimax_msg_send(wimax_dev, skb);
  284. return result;
  285. }
  286. EXPORT_SYMBOL_GPL(wimax_msg);
  287. /*
  288. * Relays a message from user space to the driver
  289. *
  290. * The skb is passed to the driver-specific function with the netlink
  291. * and generic netlink headers already stripped.
  292. *
  293. * This call will block while handling/relaying the message.
  294. */
  295. int wimax_gnl_doit_msg_from_user(struct sk_buff *skb, struct genl_info *info)
  296. {
  297. int result, ifindex;
  298. struct wimax_dev *wimax_dev;
  299. struct device *dev;
  300. struct nlmsghdr *nlh = info->nlhdr;
  301. char *pipe_name;
  302. void *msg_buf;
  303. size_t msg_len;
  304. might_sleep();
  305. d_fnstart(3, NULL, "(skb %p info %p)\n", skb, info);
  306. result = -ENODEV;
  307. if (info->attrs[WIMAX_GNL_MSG_IFIDX] == NULL) {
  308. pr_err("WIMAX_GNL_MSG_FROM_USER: can't find IFIDX attribute\n");
  309. goto error_no_wimax_dev;
  310. }
  311. ifindex = nla_get_u32(info->attrs[WIMAX_GNL_MSG_IFIDX]);
  312. wimax_dev = wimax_dev_get_by_genl_info(info, ifindex);
  313. if (wimax_dev == NULL)
  314. goto error_no_wimax_dev;
  315. dev = wimax_dev_to_dev(wimax_dev);
  316. /* Unpack arguments */
  317. result = -EINVAL;
  318. if (info->attrs[WIMAX_GNL_MSG_DATA] == NULL) {
  319. dev_err(dev, "WIMAX_GNL_MSG_FROM_USER: can't find MSG_DATA "
  320. "attribute\n");
  321. goto error_no_data;
  322. }
  323. msg_buf = nla_data(info->attrs[WIMAX_GNL_MSG_DATA]);
  324. msg_len = nla_len(info->attrs[WIMAX_GNL_MSG_DATA]);
  325. if (info->attrs[WIMAX_GNL_MSG_PIPE_NAME] == NULL)
  326. pipe_name = NULL;
  327. else {
  328. struct nlattr *attr = info->attrs[WIMAX_GNL_MSG_PIPE_NAME];
  329. size_t attr_len = nla_len(attr);
  330. /* libnl-1.1 does not yet support NLA_NUL_STRING */
  331. result = -ENOMEM;
  332. pipe_name = kstrndup(nla_data(attr), attr_len + 1, GFP_KERNEL);
  333. if (pipe_name == NULL)
  334. goto error_alloc;
  335. pipe_name[attr_len] = 0;
  336. }
  337. mutex_lock(&wimax_dev->mutex);
  338. result = wimax_dev_is_ready(wimax_dev);
  339. if (result == -ENOMEDIUM)
  340. result = 0;
  341. if (result < 0)
  342. goto error_not_ready;
  343. result = -ENOSYS;
  344. if (wimax_dev->op_msg_from_user == NULL)
  345. goto error_noop;
  346. d_printf(1, dev,
  347. "CRX: nlmsghdr len %u type %u flags 0x%04x seq 0x%x pid %u\n",
  348. nlh->nlmsg_len, nlh->nlmsg_type, nlh->nlmsg_flags,
  349. nlh->nlmsg_seq, nlh->nlmsg_pid);
  350. d_printf(1, dev, "CRX: wimax message %zu bytes\n", msg_len);
  351. d_dump(2, dev, msg_buf, msg_len);
  352. result = wimax_dev->op_msg_from_user(wimax_dev, pipe_name,
  353. msg_buf, msg_len, info);
  354. error_noop:
  355. error_not_ready:
  356. mutex_unlock(&wimax_dev->mutex);
  357. error_alloc:
  358. kfree(pipe_name);
  359. error_no_data:
  360. dev_put(wimax_dev->net_dev);
  361. error_no_wimax_dev:
  362. d_fnend(3, NULL, "(skb %p info %p) = %d\n", skb, info, result);
  363. return result;
  364. }