netlink.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  1. /*
  2. * Copyright (C) 2011 Instituto Nokia de Tecnologia
  3. *
  4. * Authors:
  5. * Lauro Ramos Venancio <lauro.venancio@openbossa.org>
  6. * Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the
  20. * Free Software Foundation, Inc.,
  21. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  22. */
  23. #include <net/genetlink.h>
  24. #include <linux/nfc.h>
  25. #include <linux/slab.h>
  26. #include "nfc.h"
  27. static struct genl_multicast_group nfc_genl_event_mcgrp = {
  28. .name = NFC_GENL_MCAST_EVENT_NAME,
  29. };
  30. struct genl_family nfc_genl_family = {
  31. .id = GENL_ID_GENERATE,
  32. .hdrsize = 0,
  33. .name = NFC_GENL_NAME,
  34. .version = NFC_GENL_VERSION,
  35. .maxattr = NFC_ATTR_MAX,
  36. };
  37. static const struct nla_policy nfc_genl_policy[NFC_ATTR_MAX + 1] = {
  38. [NFC_ATTR_DEVICE_INDEX] = { .type = NLA_U32 },
  39. [NFC_ATTR_DEVICE_NAME] = { .type = NLA_STRING,
  40. .len = NFC_DEVICE_NAME_MAXSIZE },
  41. [NFC_ATTR_PROTOCOLS] = { .type = NLA_U32 },
  42. };
  43. static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target,
  44. struct netlink_callback *cb, int flags)
  45. {
  46. void *hdr;
  47. nfc_dbg("entry");
  48. hdr = genlmsg_put(msg, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq,
  49. &nfc_genl_family, flags, NFC_CMD_GET_TARGET);
  50. if (!hdr)
  51. return -EMSGSIZE;
  52. genl_dump_check_consistent(cb, hdr, &nfc_genl_family);
  53. NLA_PUT_U32(msg, NFC_ATTR_TARGET_INDEX, target->idx);
  54. NLA_PUT_U32(msg, NFC_ATTR_PROTOCOLS,
  55. target->supported_protocols);
  56. NLA_PUT_U16(msg, NFC_ATTR_TARGET_SENS_RES, target->sens_res);
  57. NLA_PUT_U8(msg, NFC_ATTR_TARGET_SEL_RES, target->sel_res);
  58. return genlmsg_end(msg, hdr);
  59. nla_put_failure:
  60. genlmsg_cancel(msg, hdr);
  61. return -EMSGSIZE;
  62. }
  63. static struct nfc_dev *__get_device_from_cb(struct netlink_callback *cb)
  64. {
  65. struct nfc_dev *dev;
  66. int rc;
  67. u32 idx;
  68. rc = nlmsg_parse(cb->nlh, GENL_HDRLEN + nfc_genl_family.hdrsize,
  69. nfc_genl_family.attrbuf,
  70. nfc_genl_family.maxattr,
  71. nfc_genl_policy);
  72. if (rc < 0)
  73. return ERR_PTR(rc);
  74. if (!nfc_genl_family.attrbuf[NFC_ATTR_DEVICE_INDEX])
  75. return ERR_PTR(-EINVAL);
  76. idx = nla_get_u32(nfc_genl_family.attrbuf[NFC_ATTR_DEVICE_INDEX]);
  77. dev = nfc_get_device(idx);
  78. if (!dev)
  79. return ERR_PTR(-ENODEV);
  80. return dev;
  81. }
  82. static int nfc_genl_dump_targets(struct sk_buff *skb,
  83. struct netlink_callback *cb)
  84. {
  85. int i = cb->args[0];
  86. struct nfc_dev *dev = (struct nfc_dev *) cb->args[1];
  87. int rc;
  88. nfc_dbg("entry");
  89. if (!dev) {
  90. dev = __get_device_from_cb(cb);
  91. if (IS_ERR(dev))
  92. return PTR_ERR(dev);
  93. cb->args[1] = (long) dev;
  94. }
  95. spin_lock_bh(&dev->targets_lock);
  96. cb->seq = dev->targets_generation;
  97. while (i < dev->n_targets) {
  98. rc = nfc_genl_send_target(skb, &dev->targets[i], cb,
  99. NLM_F_MULTI);
  100. if (rc < 0)
  101. break;
  102. i++;
  103. }
  104. spin_unlock_bh(&dev->targets_lock);
  105. cb->args[0] = i;
  106. return skb->len;
  107. }
  108. static int nfc_genl_dump_targets_done(struct netlink_callback *cb)
  109. {
  110. struct nfc_dev *dev = (struct nfc_dev *) cb->args[1];
  111. nfc_dbg("entry");
  112. if (dev)
  113. nfc_put_device(dev);
  114. return 0;
  115. }
  116. int nfc_genl_targets_found(struct nfc_dev *dev)
  117. {
  118. struct sk_buff *msg;
  119. void *hdr;
  120. nfc_dbg("entry");
  121. dev->genl_data.poll_req_pid = 0;
  122. msg = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC);
  123. if (!msg)
  124. return -ENOMEM;
  125. hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0,
  126. NFC_EVENT_TARGETS_FOUND);
  127. if (!hdr)
  128. goto free_msg;
  129. NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx);
  130. genlmsg_end(msg, hdr);
  131. return genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_ATOMIC);
  132. nla_put_failure:
  133. genlmsg_cancel(msg, hdr);
  134. free_msg:
  135. nlmsg_free(msg);
  136. return -EMSGSIZE;
  137. }
  138. int nfc_genl_device_added(struct nfc_dev *dev)
  139. {
  140. struct sk_buff *msg;
  141. void *hdr;
  142. nfc_dbg("entry");
  143. msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
  144. if (!msg)
  145. return -ENOMEM;
  146. hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0,
  147. NFC_EVENT_DEVICE_ADDED);
  148. if (!hdr)
  149. goto free_msg;
  150. NLA_PUT_STRING(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev));
  151. NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx);
  152. NLA_PUT_U32(msg, NFC_ATTR_PROTOCOLS, dev->supported_protocols);
  153. genlmsg_end(msg, hdr);
  154. genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL);
  155. return 0;
  156. nla_put_failure:
  157. genlmsg_cancel(msg, hdr);
  158. free_msg:
  159. nlmsg_free(msg);
  160. return -EMSGSIZE;
  161. }
  162. int nfc_genl_device_removed(struct nfc_dev *dev)
  163. {
  164. struct sk_buff *msg;
  165. void *hdr;
  166. nfc_dbg("entry");
  167. msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
  168. if (!msg)
  169. return -ENOMEM;
  170. hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0,
  171. NFC_EVENT_DEVICE_REMOVED);
  172. if (!hdr)
  173. goto free_msg;
  174. NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx);
  175. genlmsg_end(msg, hdr);
  176. genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL);
  177. return 0;
  178. nla_put_failure:
  179. genlmsg_cancel(msg, hdr);
  180. free_msg:
  181. nlmsg_free(msg);
  182. return -EMSGSIZE;
  183. }
  184. static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev,
  185. u32 pid, u32 seq,
  186. struct netlink_callback *cb,
  187. int flags)
  188. {
  189. void *hdr;
  190. nfc_dbg("entry");
  191. hdr = genlmsg_put(msg, pid, seq, &nfc_genl_family, flags,
  192. NFC_CMD_GET_DEVICE);
  193. if (!hdr)
  194. return -EMSGSIZE;
  195. if (cb)
  196. genl_dump_check_consistent(cb, hdr, &nfc_genl_family);
  197. NLA_PUT_STRING(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev));
  198. NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx);
  199. NLA_PUT_U32(msg, NFC_ATTR_PROTOCOLS, dev->supported_protocols);
  200. return genlmsg_end(msg, hdr);
  201. nla_put_failure:
  202. genlmsg_cancel(msg, hdr);
  203. return -EMSGSIZE;
  204. }
  205. static int nfc_genl_dump_devices(struct sk_buff *skb,
  206. struct netlink_callback *cb)
  207. {
  208. struct class_dev_iter *iter = (struct class_dev_iter *) cb->args[0];
  209. struct nfc_dev *dev = (struct nfc_dev *) cb->args[1];
  210. bool first_call = false;
  211. nfc_dbg("entry");
  212. if (!iter) {
  213. first_call = true;
  214. iter = kmalloc(sizeof(struct class_dev_iter), GFP_KERNEL);
  215. if (!iter)
  216. return -ENOMEM;
  217. cb->args[0] = (long) iter;
  218. }
  219. mutex_lock(&nfc_devlist_mutex);
  220. cb->seq = nfc_devlist_generation;
  221. if (first_call) {
  222. nfc_device_iter_init(iter);
  223. dev = nfc_device_iter_next(iter);
  224. }
  225. while (dev) {
  226. int rc;
  227. rc = nfc_genl_send_device(skb, dev, NETLINK_CB(cb->skb).pid,
  228. cb->nlh->nlmsg_seq,
  229. cb, NLM_F_MULTI);
  230. if (rc < 0)
  231. break;
  232. dev = nfc_device_iter_next(iter);
  233. }
  234. mutex_unlock(&nfc_devlist_mutex);
  235. cb->args[1] = (long) dev;
  236. return skb->len;
  237. }
  238. static int nfc_genl_dump_devices_done(struct netlink_callback *cb)
  239. {
  240. struct class_dev_iter *iter = (struct class_dev_iter *) cb->args[0];
  241. nfc_dbg("entry");
  242. nfc_device_iter_exit(iter);
  243. kfree(iter);
  244. return 0;
  245. }
  246. static int nfc_genl_get_device(struct sk_buff *skb, struct genl_info *info)
  247. {
  248. struct sk_buff *msg;
  249. struct nfc_dev *dev;
  250. u32 idx;
  251. int rc = -ENOBUFS;
  252. nfc_dbg("entry");
  253. if (!info->attrs[NFC_ATTR_DEVICE_INDEX])
  254. return -EINVAL;
  255. idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
  256. dev = nfc_get_device(idx);
  257. if (!dev)
  258. return -ENODEV;
  259. msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
  260. if (!msg) {
  261. rc = -ENOMEM;
  262. goto out_putdev;
  263. }
  264. rc = nfc_genl_send_device(msg, dev, info->snd_pid, info->snd_seq,
  265. NULL, 0);
  266. if (rc < 0)
  267. goto out_free;
  268. nfc_put_device(dev);
  269. return genlmsg_reply(msg, info);
  270. out_free:
  271. nlmsg_free(msg);
  272. out_putdev:
  273. nfc_put_device(dev);
  274. return rc;
  275. }
  276. static int nfc_genl_start_poll(struct sk_buff *skb, struct genl_info *info)
  277. {
  278. struct nfc_dev *dev;
  279. int rc;
  280. u32 idx;
  281. u32 protocols;
  282. nfc_dbg("entry");
  283. if (!info->attrs[NFC_ATTR_DEVICE_INDEX] ||
  284. !info->attrs[NFC_ATTR_PROTOCOLS])
  285. return -EINVAL;
  286. idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
  287. protocols = nla_get_u32(info->attrs[NFC_ATTR_PROTOCOLS]);
  288. dev = nfc_get_device(idx);
  289. if (!dev)
  290. return -ENODEV;
  291. mutex_lock(&dev->genl_data.genl_data_mutex);
  292. rc = nfc_start_poll(dev, protocols);
  293. if (!rc)
  294. dev->genl_data.poll_req_pid = info->snd_pid;
  295. mutex_unlock(&dev->genl_data.genl_data_mutex);
  296. nfc_put_device(dev);
  297. return rc;
  298. }
  299. static int nfc_genl_stop_poll(struct sk_buff *skb, struct genl_info *info)
  300. {
  301. struct nfc_dev *dev;
  302. int rc;
  303. u32 idx;
  304. nfc_dbg("entry");
  305. if (!info->attrs[NFC_ATTR_DEVICE_INDEX])
  306. return -EINVAL;
  307. idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
  308. dev = nfc_get_device(idx);
  309. if (!dev)
  310. return -ENODEV;
  311. mutex_lock(&dev->genl_data.genl_data_mutex);
  312. if (dev->genl_data.poll_req_pid != info->snd_pid) {
  313. rc = -EBUSY;
  314. goto out;
  315. }
  316. rc = nfc_stop_poll(dev);
  317. dev->genl_data.poll_req_pid = 0;
  318. out:
  319. mutex_unlock(&dev->genl_data.genl_data_mutex);
  320. nfc_put_device(dev);
  321. return rc;
  322. }
  323. static struct genl_ops nfc_genl_ops[] = {
  324. {
  325. .cmd = NFC_CMD_GET_DEVICE,
  326. .doit = nfc_genl_get_device,
  327. .dumpit = nfc_genl_dump_devices,
  328. .done = nfc_genl_dump_devices_done,
  329. .policy = nfc_genl_policy,
  330. },
  331. {
  332. .cmd = NFC_CMD_START_POLL,
  333. .doit = nfc_genl_start_poll,
  334. .policy = nfc_genl_policy,
  335. },
  336. {
  337. .cmd = NFC_CMD_STOP_POLL,
  338. .doit = nfc_genl_stop_poll,
  339. .policy = nfc_genl_policy,
  340. },
  341. {
  342. .cmd = NFC_CMD_GET_TARGET,
  343. .dumpit = nfc_genl_dump_targets,
  344. .done = nfc_genl_dump_targets_done,
  345. .policy = nfc_genl_policy,
  346. },
  347. };
  348. static int nfc_genl_rcv_nl_event(struct notifier_block *this,
  349. unsigned long event, void *ptr)
  350. {
  351. struct netlink_notify *n = ptr;
  352. struct class_dev_iter iter;
  353. struct nfc_dev *dev;
  354. if (event != NETLINK_URELEASE || n->protocol != NETLINK_GENERIC)
  355. goto out;
  356. nfc_dbg("NETLINK_URELEASE event from id %d", n->pid);
  357. nfc_device_iter_init(&iter);
  358. dev = nfc_device_iter_next(&iter);
  359. while (dev) {
  360. mutex_lock(&dev->genl_data.genl_data_mutex);
  361. if (dev->genl_data.poll_req_pid == n->pid) {
  362. nfc_stop_poll(dev);
  363. dev->genl_data.poll_req_pid = 0;
  364. }
  365. mutex_unlock(&dev->genl_data.genl_data_mutex);
  366. dev = nfc_device_iter_next(&iter);
  367. }
  368. nfc_device_iter_exit(&iter);
  369. out:
  370. return NOTIFY_DONE;
  371. }
  372. void nfc_genl_data_init(struct nfc_genl_data *genl_data)
  373. {
  374. genl_data->poll_req_pid = 0;
  375. mutex_init(&genl_data->genl_data_mutex);
  376. }
  377. void nfc_genl_data_exit(struct nfc_genl_data *genl_data)
  378. {
  379. mutex_destroy(&genl_data->genl_data_mutex);
  380. }
  381. static struct notifier_block nl_notifier = {
  382. .notifier_call = nfc_genl_rcv_nl_event,
  383. };
  384. /**
  385. * nfc_genl_init() - Initialize netlink interface
  386. *
  387. * This initialization function registers the nfc netlink family.
  388. */
  389. int __init nfc_genl_init(void)
  390. {
  391. int rc;
  392. rc = genl_register_family_with_ops(&nfc_genl_family, nfc_genl_ops,
  393. ARRAY_SIZE(nfc_genl_ops));
  394. if (rc)
  395. return rc;
  396. rc = genl_register_mc_group(&nfc_genl_family, &nfc_genl_event_mcgrp);
  397. netlink_register_notifier(&nl_notifier);
  398. return rc;
  399. }
  400. /**
  401. * nfc_genl_exit() - Deinitialize netlink interface
  402. *
  403. * This exit function unregisters the nfc netlink family.
  404. */
  405. void nfc_genl_exit(void)
  406. {
  407. netlink_unregister_notifier(&nl_notifier);
  408. genl_unregister_family(&nfc_genl_family);
  409. }