netlink.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /*
  2. * Netlink inteface for IEEE 802.15.4 stack
  3. *
  4. * Copyright 2007, 2008 Siemens AG
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2
  8. * as published by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program; if not, write to the Free Software Foundation, Inc.,
  17. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18. *
  19. * Written by:
  20. * Sergey Lapin <slapin@ossfans.org>
  21. * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
  22. * Maxim Osipov <maxim.osipov@siemens.com>
  23. */
  24. #include <linux/kernel.h>
  25. #include <linux/gfp.h>
  26. #include <net/genetlink.h>
  27. #include <linux/nl802154.h>
  28. #include "ieee802154.h"
  29. static unsigned int ieee802154_seq_num;
  30. static DEFINE_SPINLOCK(ieee802154_seq_lock);
  31. struct genl_family nl802154_family = {
  32. .id = GENL_ID_GENERATE,
  33. .hdrsize = 0,
  34. .name = IEEE802154_NL_NAME,
  35. .version = 1,
  36. .maxattr = IEEE802154_ATTR_MAX,
  37. };
  38. /* Requests to userspace */
  39. struct sk_buff *ieee802154_nl_create(int flags, u8 req)
  40. {
  41. void *hdr;
  42. struct sk_buff *msg = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC);
  43. unsigned long f;
  44. if (!msg)
  45. return NULL;
  46. spin_lock_irqsave(&ieee802154_seq_lock, f);
  47. hdr = genlmsg_put(msg, 0, ieee802154_seq_num++,
  48. &nl802154_family, flags, req);
  49. spin_unlock_irqrestore(&ieee802154_seq_lock, f);
  50. if (!hdr) {
  51. nlmsg_free(msg);
  52. return NULL;
  53. }
  54. return msg;
  55. }
  56. int ieee802154_nl_mcast(struct sk_buff *msg, unsigned int group)
  57. {
  58. /* XXX: nlh is right at the start of msg */
  59. void *hdr = genlmsg_data(NLMSG_DATA(msg->data));
  60. if (genlmsg_end(msg, hdr) < 0)
  61. goto out;
  62. return genlmsg_multicast(msg, 0, group, GFP_ATOMIC);
  63. out:
  64. nlmsg_free(msg);
  65. return -ENOBUFS;
  66. }
  67. struct sk_buff *ieee802154_nl_new_reply(struct genl_info *info,
  68. int flags, u8 req)
  69. {
  70. void *hdr;
  71. struct sk_buff *msg = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC);
  72. if (!msg)
  73. return NULL;
  74. hdr = genlmsg_put_reply(msg, info,
  75. &nl802154_family, flags, req);
  76. if (!hdr) {
  77. nlmsg_free(msg);
  78. return NULL;
  79. }
  80. return msg;
  81. }
  82. int ieee802154_nl_reply(struct sk_buff *msg, struct genl_info *info)
  83. {
  84. /* XXX: nlh is right at the start of msg */
  85. void *hdr = genlmsg_data(NLMSG_DATA(msg->data));
  86. if (genlmsg_end(msg, hdr) < 0)
  87. goto out;
  88. return genlmsg_reply(msg, info);
  89. out:
  90. nlmsg_free(msg);
  91. return -ENOBUFS;
  92. }
  93. int __init ieee802154_nl_init(void)
  94. {
  95. int rc;
  96. rc = genl_register_family(&nl802154_family);
  97. if (rc)
  98. goto fail;
  99. rc = nl802154_mac_register();
  100. if (rc)
  101. goto fail;
  102. rc = nl802154_phy_register();
  103. if (rc)
  104. goto fail;
  105. return 0;
  106. fail:
  107. genl_unregister_family(&nl802154_family);
  108. return rc;
  109. }
  110. void __exit ieee802154_nl_exit(void)
  111. {
  112. genl_unregister_family(&nl802154_family);
  113. }